Многополосное сжатие динамического диапазона

В этом примере показано, как симулировать цифровое аудио многополосная система сжатия динамического диапазона.

Введение

Сжатие динамического диапазона уменьшает динамический диапазон сигнала путем ослабления уровня сильного peaks при оставлении более слабого peaks без изменений. Сжатие имеет приложения в аудиозаписи, смешивании, и в широковещательной передаче.

Многополосное сжатие сжимает различные полосы звуковой частоты отдельно первым разделением звукового сигнала в несколько полос и затем передачи каждой полосы через ее собственный независимо корректируемый компрессор. Многополосное сжатие широко используется в аудио мастеринге и часто включается в аудио рабочие станции.

Многополосный компрессор в этом примере сначала разделяет звуковой сигнал в различные полосы, использующие многополосный перекрестный фильтр. Linkwitz-раздраженные перекрестные фильтры используются, чтобы получить полную allpass частотную характеристику. Каждая полоса затем сжата с помощью отдельного компрессора динамического диапазона. Ключевые характеристики компрессора, такие как коэффициент сжатия, время нападения и релиза, порог и ширина колена, являются независимо настраиваемыми для каждой полосы. Эффект сжатия на динамическом диапазоне сигнала продемонстрирован.

Linkwitz-раздраженные перекрестные фильтры

Linkwitz-раздраженный перекрестный фильтр состоит из комбинации lowpass и фильтра highpass, каждый сформированный путем расположения каскадом двух lowpass или highpass Фильтров Баттерворта. Подведение итогов ответа двух фильтров дает к усилению 0 дБ в частоте среза, так, чтобы перекрестное соединение действовало как фильтр allpass (и поэтому вводящий искажение в звуковом сигнале).

crossoverFilter может использоваться, чтобы реализовать Linkwitz-раздраженный Системный объект. Поскольку Linkwitz-раздраженный перекрестный фильтр формируется путем расположения каскадом двух Фильтров Баттерворта, его порядок всегда ровен. Наклон Фильтра Баттерворта равен 6*N дБ/октава, где N является порядком фильтра. Когда свойство CrossoverSlopes crossoverFilter является делимым 12 (т.е. фильтр даже упорядочен), объект реализует Linkwitz-раздраженное перекрестное соединение. В противном случае объект реализует перекрестное соединение Баттерворта, где lowpass и разделы highpass каждый реализованы с помощью одного Фильтра Баттерворта или порядка CrossoverSlopes/6, соответственно.

Вот пример, где четвертый порядок Linkwitz-раздраженное перекрестное соединение используется, чтобы отфильтровать сигнал. Заметьте, что lowpass и highpass разделяют, у каждого есть-6 усилений дБ в частоте среза. Сумма lowpass и разделов highpass является allpass.

Fs = 44100;
% Linkwitz-Riley filter
crossover = crossoverFilter(1,5000,4*6,Fs);
% Transfer function estimator
transferFuncEstimator = dsp.TransferFunctionEstimator( ...
    'FrequencyRange','onesided','SpectralAverages',20);
frameLength = 1024;
scope = dsp.ArrayPlot( ...
    'PlotType','Line', ...
    'YLimits',[-40 1], ...
    'YLabel','Magnitude (dB)', ...
    'XScale','log', ...
    'SampleIncrement',(Fs/2)/(frameLength/2+1), ...
    'XLabel','Frequency (Hz)', ...
    'Title','Eighth order Linkwitz-Riley Crossover Filter', ...
    'ShowLegend',true, ...
    'ChannelNames',{'Band 1','Band 2','Sum'});
tic;
while toc < 10
    in = randn(1024,1);
    % Return lowpass and highpass responses of the crossover filter
    [ylp,yhp] = crossover(in);
    % sum the responses
    y = ylp + yhp;
    v = transferFuncEstimator(repmat(in,1,3),[ylp yhp y]);
    scope(20*log10(abs(v)));
end

Многополосные перекрестные фильтры

crossoverFilter может также использоваться, чтобы реализовать многополосный перекрестный фильтр путем объединения фильтров перекрестного соединения 2D полосы, и allpass просачивается древовидная структура. Фильтр делит спектр на несколько полос, таким образом, что их сумма является совершенным фильтром allpass.

Пример ниже показов перекрестный фильтр с четырьмя полосами, сформированный из четвертого порядка Linkwitz-раздраженные перекрестные фильтры. Заметьте allpass ответ суммы этих четырех полос.

Fs = 44100;
crossover = crossoverFilter(3,[2e3 5e3 10e3],[24 24 24],44100);
transferFuncEstimator = dsp.TransferFunctionEstimator...
                                 ('FrequencyRange','onesided',...
                                  'SpectralAverages',20);
L = 2^14;
scope = dsp.ArrayPlot( ...
    'PlotType','Line', ...
    'XOffset',0, ...
    'YLimits',[-120 5], ...
    'XScale','log', ...
    'SampleIncrement', .5 * Fs/(L/2 + 1 ), ...
    'YLabel','Frequency Response (dB)', ...
    'XLabel','Frequency (Hz)', ...
    'Title','Four-Band Crossover Filter', ...
    'ShowLegend',true, ...
    'ChannelNames',{'Band 1','Band 2','Band 3','Band 4','Sum'});
tic;
while toc < 10
   in = randn(L,1);
   % Split the signal into four bands
   [ylp,ybp1,ybp2,yhp] = crossover(in);
   y = ylp + ybp1 + ybp2 + yhp;
   z  = transferFuncEstimator(repmat(in,1,5),[ylp,ybp1,ybp2,yhp,y]);
   scope(20*log10(abs(z)))
end

Сжатие динамического диапазона

компрессором является Системный объект компрессора динамического диапазона. Входной сигнал сжат, когда он превышает заданный порог. Объемом сжатия управляет заданный коэффициент сжатия. Времена нападения и релиза определяют, как быстро компрессор запускает или прекращает сжиматься. Ширина колена обеспечивает плавный переход для усиления компрессора вокруг порога. Наконец, усиление состава может быть применено при выходе компрессора. Это усиление состава усиливает и сильный и слабый peaks одинаково.

Статическая характеристика сжатия компрессора зависит от коэффициента сжатия, порога и ширины колена. Пример ниже иллюстрирует статическую характеристику сжатия для твердого колена:

drc = compressor(-15,5);
visualize(drc);

Для того, чтобы просмотреть эффект порога, отношения и ширины колена на статической характеристике компрессора, измените значения Порога, свойств Ratio и KneeWidth. График статической характеристики должен измениться соответственно.

Время атаки компрессора задано как время (в msec), это берет для усиления компрессора, чтобы повыситься с 10% до 90% его окончательного значения, когда уровень сигнала превышает порог. Время релиза компрессора задано как время (в секундах), это берет усиление компрессора, чтобы понизиться с 90% до 10% его значения, когда уровень сигнала опускается ниже порога. Пример ниже иллюстрирует огибающую сигнала для различного релиза и время атаки:

Fs = 44100; % Sample rate
drc = compressor(-10,5, ...
    'SampleRate',Fs, ...
    'AttackTime',0.050, ...
    'ReleaseTime',0.200, ...
    'MakeUpGainMode','Property');
x = [ones(Fs,1);0.1*ones(Fs,1)];
[y,g] = drc(x);
t = (1/Fs) * (0: 2*Fs - 1);
figure
subplot(211)
plot(t,x);
hold on; grid on;
plot(t,y,'r')
ylabel('Amplitude')
legend('Input','Compressed Output')
subplot(212)
plot(t,g)
grid on
legend('Compressor gain (dB)')
xlabel('Time (sec)')
ylabel('Gain (dB)')

Входной максимальный уровень составляет 0 дБ, который является выше заданного порога на-10 дБ. Установившийся компрессор выход для входа на 0 дБ-10 + 10/5 =-8 дБ. Усиление - поэтому-8 дБ. Время атаки задано как время, это берет усиление компрессора, чтобы повыситься с 10% до 90% его окончательного значения, когда уровень на входе выходит за предел порога, или в этом случае, от-0.8 дБ до-7.2 дБ. Давайте найдем времена, в которые усиления на этапе сжатия равны-0.8 дБ и-7.2 дБ, соответственно:

[~,t1] = min(abs(g(1:Fs) + 0.1 * 8));
[~,t2] = min(abs(g(1:Fs) + 0.9 * 8));
tAttack = (t2 - t1) / Fs;
fprintf('Attack time is %d s\n',tAttack)
Attack time is 5.000000e-02 s

Входной сигнал затем роняет вниз к 0, где нет никакого сжатия. Время релиза задано как время, которое оно берет усиление, чтобы пропустить с 90% до 10% его абсолютного значения, когда вход понижается порог, или в этом случае,-7.2 дБ к-0.8 дБ. Давайте найдем времена, в которые усиления на этапе без сжатий равны-7.2 дБ и-0.8 дБ, соответственно:

[~,t1] = min(abs(g(Fs:end) + 0.9 * 8));
[~,t2] = min(abs(g(Fs:end) + 0.1 * 8));
tRelease = (t2 - t1) / Fs;
fprintf('Release time is %d s\n',tRelease)
Release time is 2.000000e-01 s

Пример ниже иллюстрирует эффект сжатия динамического диапазона на звуковом сигнале. Порог сжатия устанавливается к-15 дБ, и коэффициент сжатия равняется 7.

frameLength = 1024;
reader = dsp.AudioFileReader('Filename', ...
    'RockGuitar-16-44p1-stereo-72secs.wav', ...
    'SamplesPerFrame',frameLength);
% Compressor. Threshold = -15 dB, ratio = 7
drc = compressor(-15,7, ...
    'SampleRate',reader.SampleRate, ...
    'MakeUpGainMode','Property', ...
    'KneeWidth',5);
scope = dsp.TimeScope('SampleRate',reader.SampleRate, ...
    'TimeSpan',1,'BufferLength',44100*4, ...
    'ShowGrid',true, ...
    'LayoutDimensions',[2 1], ...
    'NumInputPorts',2, ...
    'TimeSpanOverrunAction','Scroll');
scope.ActiveDisplay = 1;
scope.YLimits = [-1 1];
scope.ShowLegend = true;
scope.ChannelNames = {'Original versus compressed audio'};
scope.ActiveDisplay = 2;
scope.YLimits = [-6 0];
scope.YLabel  = 'Gain (dB)';
scope.ShowLegend = true;
scope.ChannelNames = {'compressor gain in dB'};

while ~isDone(reader)
   x = reader();
   [y,g] = drc(x);
   x1 = x(:,1);
   y1 = y(:,1);
   scope([x1,y1],g(:,1))
end

Версия Simulink многополосного примера сжатия динамического диапазона

Следующая модель реализует многополосный пример сжатия динамического диапазона:

model = 'audiomultibanddynamiccompression';
open_system(model)

В этом примере звуковой сигнал сначала разделен на четыре полосы, использующие многополосный перекрестный фильтр. Каждая полоса сжата с помощью отдельного компрессора. Эти четыре полосы затем повторно объединены, чтобы сформировать аудиовыход. Динамический диапазон несжатых и сжатых сигналов (заданный как отношение самого большого абсолютного значения сигнала к RMS сигнала) вычисляется. Чтобы услышать различие между исходными и сжатыми звуковыми сигналами, переключите переключатель на верхнем уровне.

Модель интегрирует Пользовательский интерфейс (UI), спроектированный, чтобы взаимодействовать с симуляцией. Пользовательский интерфейс позволяет вам настройкам параметров, и результаты отражаются в симуляции немедленно. Чтобы запустить пользовательский интерфейс, который управляет симуляцией, щелкните по ссылке 'Launch Parameter Tuning UI' на модель.

set_param(model,'StopTime','(1/44100) * 8192 * 20');
sim(model);

Закройте модель:

bdclose(model)

MATLAB Version многополосного примера сжатия динамического диапазона

HelperMultibandCompressionSim функция MATLAB, содержащая многополосную реализацию примера сжатия динамического диапазона. Это инстанцирует, инициализирует и продвигается через объекты, формирующие алгоритм.

Функциональный multibandAudioCompressionExampleApp переносит HelperMultibandCompressionSim и итеративно вызовы это. Это также строит несжатое по сравнению со сжатыми звуковыми сигналами. Графический вывод происходит когда plotResults вход к функции 'верен'.

Выполните multibandAudioCompressionExampleApp запускать симуляцию и строить результаты на осциллографах. Обратите внимание на то, что симуляция запускается столько, сколько пользователь явным образом не останавливает ее.

multibandAudioCompressionExampleApp запускает пользовательский интерфейс, спроектированный, чтобы взаимодействовать с симуляцией. Пользовательский интерфейс позволяет вам настройкам параметров, и результаты отражаются в симуляции немедленно. Для получения дополнительной информации о пользовательском интерфейсе обратитесь к HelperCreateParamTuningUI.

MATLAB Coder может использоваться, чтобы сгенерировать код С для функционального HelperMultibandCompressionSim. Для того, чтобы сгенерировать файл MEX для вашей платформы, выполните HelperMultibandCompressionCodeGeneration.

Путем вызова обертки функционируют multibandAudioCompressionExampleApp с 'true' в качестве аргумента сгенерированный файл MEX может использоваться вместо HelperMultibandCompressionSim для симуляции. В этом сценарии пользовательский интерфейс все еще запускается в среде MATLAB, но основной алгоритм обработки выполняется файлом MEX. Производительность улучшается в этом режиме, не ставя под угрозу способность к настройкам параметров.

Вызовите multibandAudioCompressionExampleApp(true) использовать файл MEX в симуляции. Снова, запуски симуляции, пока пользователь явным образом не останавливает его от пользовательского интерфейса.