exponenta event banner

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

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

Введение

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

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

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

Кроссоверные фильтры Linkwitz-Riley

Кроссоверный фильтр Линквица-Райли состоит из комбинации фильтра нижних и верхних частот, каждый из которых образован каскадированием двух фильтров Баттерворта нижних или верхних частот. Суммирование отклика двух фильтров дает коэффициент усиления 0 дБ на частоте пересечения, так что пересечение действует как фильтр allpass (и, следовательно, не вносит искажений в аудиосигнал).

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

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

В приведенном ниже примере показан четырехполосный перекрестный фильтр, образованный перекрестными фильтрами Линквитца-Райли четвертого порядка. Обратите внимание на отклик 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 является объектом системы компрессора динамического диапазона. Входной сигнал сжимается, когда он превышает заданное пороговое значение. Величина сжатия регулируется заданной степенью сжатия. Время атаки и отпускания определяет скорость запуска или прекращения сжатия компрессора. Ширина колена обеспечивает плавный переход для усиления компрессора вокруг порога. Наконец, на выходе компрессора может быть применено усиление подпитки. Этот коэффициент усиления усиливает как сильные, так и слабые пики одинаково.

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

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). Чтобы услышать разницу между исходным и сжатым звуковыми сигналами, включите переключатель на верхнем уровне.

Модель объединяет пользовательский интерфейс, предназначенный для взаимодействия с моделированием. Пользовательский интерфейс позволяет настраивать параметры, и результаты мгновенно отражаются в моделировании. Чтобы запустить пользовательский интерфейс, управляющий моделированием, щелкните ссылку «Запуск настройки параметров» на модели.

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

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

bdclose(model)

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

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

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

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

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

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

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

Звонить multibandAudioCompressionExampleApp(true) для использования MEX-файла для моделирования. Моделирование также выполняется до тех пор, пока пользователь явно не остановит его из пользовательского интерфейса.