Странная проблема с фильтрацией звука в MATLAB

#matlab #audio

#matlab #Аудио

Вопрос:

Я фильтрую аудиофайл с помощью matlab внутри функционального скрипта, в котором есть функция с именем «filtro_pf», созданная мной, которая является полосовым фильтром, а ее выходные данные представляют собой соответствующие коэффициенты IIR:

 [b,a] = filtro_pf(Ap,As,fp1,fs1,fp2,fs2,1); //BAND PASS FILTER
b2 = [0.0039,0,-0.0156,0,0.0234,0,-0.0156,0,0.0039];
a2 =[1.0000,-6.2682,17.2660,-27.3421,27.2582,-17.5284,7.0998,-1.6555,0.1701];
wfpf = filter(b,a,audio_stream);
wavplay(wfpf,fs);
 

Обратите внимание, что вторая и третья строки (b2 и a2) — это значения, которые функция filtro_pb () выдает мне для этих входных данных. Я запустил один раз, а затем скопировал их в эти переменные. Теперь, после запуска этого скрипта, если я запрошу «a» и «a2» в консоли, у меня будет:

 a =

1.0000   -6.2682   17.2660  -27.3421   27.2582  -17.5284    7.0998   -1.6555    0.1701


a2 =

1.0000   -6.2682   17.2660  -27.3421   27.2582  -17.5284    7.0998   -1.6555    0.1701
 

Они практически одинаковы. Но если я использую ‘a2’ вместо ‘a’ в функции filter (), это не сработает. Я слышу какой-то тикающий звук, и все. С помощью ‘a’ я слышу, как звук правильно фильтруется. Этот же код использовался ранее, и он работает:

 %[b,a] = filtro_pa(Ap,As,fp,fs,1); //HIGH PASS FILTER
b = [0.5411   -1.6232    1.6232   -0.5411];
a = [1.0000   -1.8062    1.2298   -0.2925];
wfpa = filter(b2, a2, audio_stream);
wavplay(wfpa,fs);
 

Опять же, я использовал этот скрипт ранее и увидел, что эти значения (из a2 и b2) были выводом на эти входы. Теперь вместо повторного вызова функции (что, кстати, прокомментировано) Я использую векторы ‘a’ и ‘b’ напрямую. Он работает для фильтра нижних частот и для фильтра верхних частот.

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

Я просто хочу знать, как функция может не работать со второй переменной, если они практически одинаковы?

Ответ №1:

В переменных присутствует больше точности, чем отображается, что означает, что ваши a2 b2 векторы and не совпадают с a and b . Может показаться удивительным, что ошибки в этом порядке сделают фильтр нестабильным, но, похоже, именно это и происходит. Вы должны быть в состоянии изучить это, посмотрев на ответ фильтра с freqz помощью и построив результирующий звуковой вектор, а не просто прослушивая его.

Вы можете использовать format long для печати большей точности, но у них все равно будет некоторая ошибка округления. Чтобы избежать этого, сохраните векторы в файле .mat и перезагрузите его. Файл .mat будет использовать двоичный формат и хранить полную точность ваших векторов.

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

Вот пример сравнения частотной характеристики:

 [H W] = freqz(b2, a2);  % your filter (with error)
a_error = zeros(size(a2));
a_error(9) = a_error(9) .001;  % a little bit of error in a single coefficient
[HE WE] = freqz(b2, a2   a_error);   % frequency response of THAT filter
plot(log10(abs([H HE])))
 

Как вы можете видеть, небольшое изменение имеет большое значение.

Фактический анализ нестабильности происходит при рассмотрении полюсов и нулей фильтра:

 [z p k] = tf2zp(b2, a2);
abs(p)
 

Если какие-либо полюса имеют величину, превышающую 1 (это так), фильтр будет нестабильным. Попробуйте реальные значения, затем ваши «приблизительные» значения и посмотрите, что произойдет.

Комментарии:

1. Я только что использовал vpa (a) для отображения ‘a’ с 20 цифрами, и вот мы идем. Теперь это работает. Невероятно … однажды мне сказали, что эти фильтры могут быть нестабильными с очень небольшими различиями, но я бы никогда не подумал, что это так нестабильно! Спасибо!