8

I am trying to decipher a message hidden within a very noisy audio file(.wav)(I think it is white noise with an additional low drone). The message is a six digit number. I have not have any further details about 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

Plot of the signal spectrum: picture

penelope
  • 3,676
  • 1
  • 26
  • 63
  • can you provide us with a sample you're working with? and maybe your result? – penelope Dec 04 '12 at 08:56
  • I cannot upload the plot images( not enough points) and have no way to link you to the file – user1825494 Dec 04 '12 at 09:04
  • 1
    if you put links in the comments, somebody will gladly edit them in. And if you find a way to upload the files somewhere and provide link, get back with that as well. – penelope Dec 04 '12 at 09:06
  • 2
    The graph would be much more informative if it were plotted log-log. As it is, it looks like you have wideband noise from about 1.5 kHz to 22.5 kHz, with a narrowband tone at about 2 kHz. What I presume is the "voice" signal, along with what appears to be a significant DC offset, sits in a fairly quiet "hole". It really shouldn't be all that hard to isolate with a suitable bandpass filter. – Dave Tweed Dec 04 '12 at 20:23

3 Answers3

1

A few points:

  1. Filtering in the frequency domain is complicated and needs a real algorithm like overlap add to avoid time domain aliasing. It's much easier to filter directly in the time domain: [b,a] = butter(1,100/(SampleRate/2); y_filtered = filter(b,a,y); is much better
  2. You probably want to put notch filter on the drone frequency
  3. For broad-band stationary noise a good method is Wiener filtering or spectral subtraction. Many papers have been published on this.
Hilmar
  • 44,604
  • 1
  • 32
  • 63
0

The human voice has some peculiarities that might help. For one, female voice starts at about 200Hz, male lower, so doing a high-pass filter here would help a bit. See also acoustic-features-distinguishing-the-male-and-female-voice.

Additionally, identify the drone frequencies via a histogram.

Doing all of this in code is a bit cumbersome. Have you considered some audio program like Audacity?

serv-inc
  • 95
  • 10
0

You mention using a low pass filter, but as one of the commenters mentioned you would probably do better with a band-pass filter to also filter out the low frequency noise. There also exists noise reduction filters in third-party libraries if you are interested in pre-existing solutions.

Ethereal
  • 167
  • 1
  • 4