简体   繁体   中英

Filter message from noisy voice signal

I am trying to decipher a message hidden within a very noisy(sounds like white noise with an additional low drone) audio file(.wav). The message is a six digit number. I have not been informed of any of the details of the noise. I attempted to use a low-pass filter in the hopes that eliminating most of the higher frequencies would allow me to hear the numbers but, I seem to be unable to also get rid of enough of the low drone to hear the voice well enough. My attempt was as follows(the employed function 'freq_space_low_pass_filter' is included at the end):

[data, SampleRate, NbitsPerSample]=wavread('noisy_msg6.wav');

y=data(:,1); % we will work only with one channel in this demo 
N=length(y); %number of sample points
t=( (1:N)*1/SampleRate ).'; % time spacing is 1/SampleRate and we want column vector

Y=fft(y);

spectrum_freq=fourier_frequencies(SampleRate, N);

Freq3db=100;
[spectrum_filtered,g_vs_freq]=freq_space_low_pass_filter(Y, SampleRate, Freq3db);


y_filtered=ifft(spectrum_filtered);

y_filtered=real(y_filtered);



wavwrite(y_filtered/(0.1+max(y_filtered)), SampleRate, NbitsPerSample,        'noisy_msg6_filtered.wav');

%%%%%%%%down sampling%%%%%%%%

indexes=(abs(spectrum_freq) < 10*Freq3db);
spectrum_freq_down_sampled = spectrum_freq(indexes);
spectrum_down_sampled = spectrum_filtered(indexes);
N_down_sampled = length(spectrum_down_sampled);

spectrum_down_sampled=spectrum_down_sampled*N_down_sampled/N;

SampleRate_down_sampled=SampleRate*N_down_sampled/N;

y_down_sampled=real(ifft(spectrum_down_sampled));
t_down_sampled = ( (1:N_down_sampled)*1/SampleRate_down_sampled ).';

sound(y_down_sampled, SampleRate_down_sampled)

function [spectrum_filtered,g]=freq_space_low_pass_filter(spectrum, SampleRate, Freq3db)
%% applies low pass filter in the frequency domain
% spectrum - result of fft on time series data (column vector is expected)
% SampleRate - measured in Hz, 1/dt where dt spacing of the points in time domain
% Freq3db - desired 3db roll off point in Hz

N=length(spectrum);

function G=filter_gain(freq, Freq3db)
    G=1./(1+1i*freq/Freq3db); % this corresponds to low pass RC filter
end

spectrum_freq=fourier_frequencies(SampleRate, N);

% calculate filter gain for each spectrum frequency
g=filter_gain(spectrum_freq, Freq3db);
spectrum_filtered=spectrum.*g;

end

Any and all assistance will be greatly appreciated. Thanks!

我过滤后的原始信号的图

If you have no prior information on the noise, then filtering would not generally be a good idea. Your concept would work fine if you know that your noise energy is concentrated above a certain frequency. Lowpass filtering may then give you an appreciable SNR benefit at the expense of losing the higher frequncy speech information. But again, this is only useful if you know the average spectral profile of your noise.

You need to leverage any information you can about what makes the noise different to the speech signal. A spectral subtraction technique might give you more benefit. If you have some noise that preceedes the speech in your samples, you can make a compensating filter based on that information.

What does the noise look like in terms of time frequency response? If it is relatively stationary, you could use the fact that speech is highly modulated (approx 4Hz) to estimate SNR in different frequency bands, then attenuate the bands with the worst SNR estimates.

How many channels of audio are in the recording? If it is more than 1, and the spatial position of your target audio sorce does not change, you can use cross correlation techniques to improve SNR.

If it's a human voice saying the numbers, then you can safely completely filter out all frequencies below 500 Hz and above, say, 8 kHz. From there, you can more safely work out which frequencies mask out the voice.

If you want to cheat a bit, you could give the audio sample a shot with a parametric EQ with a narrow band bell filter and sweep through the 500 - 8000 Hz range until you get something :) Although the problem sounds more like homework in a Matlab course.

My Matlab is too rusty for code, but here's some things to try:

  1. Add a highpass filter at 500 Hz
  2. Add a lowpass filter at 8 kHz
  3. Add a narrow bell filter at, say 4 kHz, where the human ear is the most sensitive. Boost it by 6 dB to clear out the masking effect of the other frequencies.
  4. For added effect, boost the lower and higher harmonics too (2 kHz and 8 kHz), but by less dB

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM