MATLAB: удаление высокочастотного шума из файла WAV - PullRequest
0 голосов
/ 15 ноября 2018

Я пытаюсь удалить высокочастотный шум из следующего файла .

Это файл женщины, читающей новости, с громким шумом, звучащим над ним.В конце файла кто-то еще начинает говорить, но на другом языке.

Я хочу отфильтровать этот высокий шум и быть в состоянии четко слышать женщину, читающую новости.Глядя на частотную область:

Unfiltered

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

Есть ли какой-нибудь умный способ восстановить гармоники речи, чтобы услышать то, что говоритсяпонятнее?Или есть ли у меня умный способ отфильтровать сигнал, не теряя при этом четкости звука?

Я могу включить любой код, который использовал в matlab, если это необходимо.

Примечание:

  • Я сместил сигнал до 0 в изображении, которое я связал

  • Я использовал filtfilt() вместо filter()

  • Я использовал butter() для фильтров

1 Ответ

0 голосов
/ 23 ноября 2018

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

К счастью, в этом случае помехи довольно сильные и имеют довольно регулярный характер, что облегчает оценку.Это видно из сигнала spectrogram.Для следующих выводов мы будем предполагать, что выборки wavfile были сохранены в массиве x и что частота дискретизации составляет fs (что составляет 8000 Гц в предоставленной выборке).

[Sx,f,t] = spectrogram(x, triang(1024), 1023, [], fs, 'onesided');

enter image description here

Учитывая, что помехи сильны, получение частоты помехи может быть выполнено путем определения максимальной частоты в каждом временном интервале:

frequency = zeros(size(Sx,2),1);
for k = 1:size(Sx,2)
    [pks,loc] = findpeaks(Sx(:,k));
    frequency(k) = fs * (loc(1)-1);
end

Видя, что помехи являются периодическими, мы можем использовать дискретное преобразование Фурье для разложения этого сигнала:

M = 32*fs;
Ff = fft(frequency, M);
plot(fs*[0:M-1]/M, 20*log10(abs(Ff));
axis(0, 2);
xlabel('frequency (Hz)');
ylabel('amplitude (dB)');

enter image description here

Использование первых двух гармоник в качестве приближениямы можем смоделировать частоту интерференционного сигнала как:

T = 1.0/fs
t = [0:length(x)-1]*T
freq = 750.0127340203496
       + 249.99913423501602*cos(2*pi*0.25*t - 1.5702946346796276)
       + 250.23974282864816*cos(2*pi*0.5 *t - 1.5701043282285363);

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

% Compute the phase of the sine/cosine to correlate the signal with
delta_phi = 2*pi*freq/fs;
phi = cumsum(delta_phi);

% We scale the phase adjustments with a triangular window to try to reduce
% phase discontinuities. I've chosen a window of ~200 samples somewhat arbitrarily,
% but it is large enough to cover 8 cycles of the interference around its lowest
% frequency sections (so we can get a better estimate by averaging out other signal
% contributions over multiple interference cycles), and is small enough to capture
% local phase variations.
step = 50;
L    = 200;
win  = triang(L);
win  = win/sum(win);

for i = 0:floor((length(x)-(L-step))/step)
    % The phase tweak to align the sine/cosine isn't linear, so we run a few
    % iterations to let it converge to a phase locked to the original signal
    for iter = 0:1
        xseg   = x[(i*step+1):(i*step+L+1)];
        phiseg = phi[(i*step+1):(i*step+L+1)];
        r1 = sum(xseg .* cos(phiseg));
        r2 = sum(xseg .* sin(phiseg));
        theta = atan2(r2, r1);

        delta_phi[(i*step+1):(i*step+L+1)] = delta_phi[(i*step+1):(i*step+L+1)] - theta*win;
        phi = cumsum(delta_phi);
    end
end

Наконец, нам нужно оценить амплитуду помехи.Здесь мы выбираем выполнение оценки в течение начальных 0,15 секунд, когда перед началом речи есть небольшая пауза, чтобы оценка не была смещена по амплитуде речи:

tmax = 0.15;
nmax = floor(tmax * fs);
amp  = sqrt(2*mean(x[1:nmax].^2));
% this should give us amp ~ 0.250996990794946

Эти параметры затем позволяют нам достаточноточно восстановить помехи и, соответственно, устранить помехи из исходного сигнала путем прямого вычитания:

y = amp * cos(phi)
x = x-y

enter image description here

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

Примечание : скрипт Python, используемый для этой обработки (и соответствующий вывод файла .wav), можно найти здесь .

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