8
$\begingroup$

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

$\endgroup$
4
  • $\begingroup$ can you provide us with a sample you're working with? and maybe your result? $\endgroup$
    – penelope
    Commented Dec 4, 2012 at 8:56
  • $\begingroup$ I cannot upload the plot images( not enough points) and have no way to link you to the file $\endgroup$ Commented Dec 4, 2012 at 9:04
  • 1
    $\begingroup$ 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. $\endgroup$
    – penelope
    Commented Dec 4, 2012 at 9:06
  • 2
    $\begingroup$ 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. $\endgroup$
    – Dave Tweed
    Commented Dec 4, 2012 at 20:23

3 Answers 3

1
$\begingroup$

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.
$\endgroup$
0
$\begingroup$

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.

$\endgroup$
0
$\begingroup$

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?

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.