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

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

Введение

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

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

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

Фильтры кроссовера Linkwitz-Riley

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

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

Вот пример, где для фильтрации сигнала используется кроссовер Linkwitz-Riley четвертого порядка. Заметьте, что 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(frameLength,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 может также использоваться для реализации многополосного перекрестного фильтра путем объединения двухполосных перекрестных фильтров и allpass-фильтров в древовидной структуре. Фильтр делит спектр на несколько полос, так что их сумма является идеальным фильтром allpass.

В приведенном ниже примере показан четырехполосный перекрестный фильтр, образованный перекрестными фильтрами Linkwitz-Riley четвертого порядка. Заметьте 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

Динамическое сжатие области значений

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

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

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

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

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

Fs = 44100;

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)')

Figure contains 2 axes. Axes 1 contains 2 objects of type line. These objects represent Input, Compressed Output. Axes 2 contains an object of type line. This object represents Compressor 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 = timescope('SampleRate',reader.SampleRate, ...
    'TimeSpanSource','property',...
    'TimeSpan',1,'BufferLength',Fs*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), предназначенный для взаимодействия с симуляцией. UI позволяет вам настройкам параметров, и результаты отражаются в симуляции мгновенно. Чтобы запустить пользовательский интерфейс, который управляет симуляцией, щелкните ссылку 'Launch Parameter Tuning UI' на модели.

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

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

bdclose(model)

MATLAB Version примера мультидиапазонной динамической Области значений сжатия

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

Функция multibandAudioCompressionExampleApp оборачивается вокруг HelperMultibandCompressionSim и итеративно вызывает его. Он также строит графики несжатых и сжатых аудиосигналов. Графическое изображение происходит, когда plotResults вход в функцию равен 'true'.

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

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

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

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

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