Can you help remove the noise from this audio file?

I'm having trouble removing the noise heard from this audio file audio_sample.wav.
I've attempted to use the "butter" function to experiment with removing certain frequencies in an effort to reduce the noise as much as possible.
You will need to have the audio file in the search path your MATLAB is using.
The code will play my "current solution".
Thanks for any help.
%%1) Load the 'audio_sample.wav' file in MATLAB
[sample_data, sample_rate] = audioread('audio_sample.wav');
% a. Plot the signal in time and the amplitude of its frequency
% components using the FFT.
sample_period = 1/sample_rate;
t = (0:sample_period:(length(sample_data)-1)/sample_rate);
subplot(2,2,1)
plot(t,sample_data)
title('Time Domain Representation - Unfiltered Sound')
xlabel('Time (seconds)')
ylabel('Amplitude')
xlim([0 t(end)])
m = length(sample_data); % Original sample length.
n = pow2(nextpow2(m)); % Transforming the length so that the number of
% samples is a power of 2. This can make the transform computation
% significantly faster,particularly for sample sizes with large prime
% factors.
y = fft(sample_data, n);
f = (0:n-1)*(sample_rate/n);
amplitude = abs(y)/n;
subplot(2,2,2)
plot(f(1:floor(n/2)),amplitude(1:floor(n/2)))
title('Frequency Domain Representation - Unfiltered Sound')
xlabel('Frequency')
ylabel('Amplitude')
% b. Listen to the audio file.
% sound(sample_data, sample_rate)
%%2) Filter the audio sample data to remove noise from the signal.
order = 7;
[b,a] = butter(order,1000/(sample_rate/2),'low');
filtered_sound = filter(b,a,sample_data);
sound(filtered_sound, sample_rate)
t1 = (0:sample_period:(length(filtered_sound)-1)/sample_rate);
subplot(2,2,3)
plot(t1,filtered_sound)
title('Time Domain Representation - Filtered Sound')
xlabel('Time (seconds)')
ylabel('Amplitude')
xlim([0 t1(end)])
m1 = length(sample_data); % Original sample length.
n1 = pow2(nextpow2(m1)); % Transforming the length so that the number of
% samples is a power of 2. This can make the transform computation
% significantly faster,particularly for sample sizes with large prime
% factors.
y1 = fft(filtered_sound, n1);
f = (0:n1-1)*(sample_rate/n1);
amplitude = abs(y1)/n1;
subplot(2,2,4)
plot(f(1:floor(n1/2)),amplitude(1:floor(n1/2)))
title('Frequency Domain Representation - Filtered Sound')
xlabel('Frequency')
ylabel('Amplitude')

2 Comments

can u help to remove instrumental part to give just the audio?
I am doing an experiment recently. Your code and files may be helpful to me. Could you please send them to me?

Sign in to comment.

 Accepted Answer

It is not possible to eliminate broadband noise with a frequency-selective filter. You have to use wavelets to effectively de-noise it.
I got reasonable results with this filter, and using the filtfilt function:
Fs = sample_rate; % Sampling Frequency (Hz)
Fn = Fs/2; % Nyquist Frequency (Hz)
Wp = 1000/Fn; % Passband Frequency (Normalised)
Ws = 1010/Fn; % Stopband Frequency (Normalised)
Rp = 1; % Passband Ripple (dB)
Rs = 150; % Stopband Ripple (dB)
[n,Ws] = cheb2ord(Wp,Ws,Rp,Rs); % Filter Order
[z,p,k] = cheby2(n,Rs,Ws,'low'); % Filter Design
[soslp,glp] = zp2sos(z,p,k); % Convert To Second-Order-Section For Stability
figure(3)
freqz(soslp, 2^16, Fs) % Filter Bode Plot
filtered_sound = filtfilt(soslp, glp, sample_data);
sound(filtered_sound, sample_rate)
Experiment to get the results you want.

11 Comments

Thanks for your help.
Having worked on it a little more, I realized that the noise plays in isolation from approximately 0s to 3.44s.
Therefore I analyzed the first 3.44s of audio_sample.wav and displayed its frequency components using the FFT.
Given that I have the frequency components of the:
  • Unfiltered Audio, and
  • Unfiltered Noise of the Audio
What is the method of subtracting the frequency components of the noise from the entire frequency spectrum of audio_sample.wav?
close all; clear all; clc;
%%Analyse the audio
[y, Fs] = audioread('audio_sample.wav');
% Plot the Time Domain Representation
t = (0:1/Fs:(length(y)-1)/Fs);
subplot(2,2,1)
plot(t,y)
title('Time Domain - Unfiltered Audio')
xlabel('Time (seconds)')
ylabel('Amplitude')
xlim([0 t(end)])
% By visual inspection, the noise plays from 0 sec to approximately 3.44
% sec
% Plot the Frequency Domain Representation
m = length(y);
x = fft(y, m);
f = (0:m-1)*(Fs/m);
amplitude = abs(x)/m;
subplot(2,2,2)
plot(f(1:(m/2)),amplitude(1:(m/2)))
title('Frequency Domain - Unfiltered Audio')
xlabel('Frequency')
ylabel('Amplitude')
xlim([0 2000])
%%Analyse the noise audio
noise_Fs = [1, 3.44*Fs]; % Collect the first 3.44 sec
[y_n, Fs_n] = audioread('audio_sample.wav', noise_Fs);
% Plot the Time Domain Representation
t_n = (0:1/Fs_n:(length(y_n)-1)/Fs_n);
subplot(2,2,3)
plot(t_n,y_n)
title('Time Domain - Unfiltered Noise of the Audio')
xlabel('Time (seconds)')
ylabel('Amplitude')
xlim([0 t(end)])
% Plot the Frequency Domain Representation
a = length(y_n);
v = fft(y_n, a);
f_n = (0:a-1)*(Fs/a);
amplitude = abs(v)/a;
subplot(2,2,4)
plot(f_n(1:(a/2)),amplitude(1:(a/2)))
title('Frequency Domain - Unfiltered Noise of the Audio')
xlabel('Frequency')
ylabel('Amplitude')
xlim([0 2000])
ylim([0 0.02])
If you have the unfiltered noise, just subtract it from the signal+noise in the time domain. That should produce a clean signal.
The noise spectrum you plotted seems to be correlated to the frequency content of your signal. That is going to complicate any frequency-based filtering approach.
You could theoretically design a bandstop filter that simulates the inverse of the noise signal. The easiest way to do that would be to ‘smooth’ it in the frequency domain with a Savitzsky-Golay filter (the sgolayfilt function), and the use the inverse of that (subtract it from the maximum) and the firls function (or related functions) to produce a filter that approximates and specifically filters that noise. You will have to experiment with that to get the result you want.
The best option to remove broadband noise (that is not frequency-limited) is to use wavelets.
Thanks Star Strider. I ended up taking a low filter to the signal and then using your recommended method of wavelets to try and reduce as much of the noise as possible whilst preserving as much of the music.
As always, my pleasure.
star strider can you provide me code of denoising with weiver filter also
Christopher Vergara can you please give the code for adding and removing the noise from the signal
Star Strider can you please give a full working code of removing broadband noise from an audio signal.
Broadband noise removal requires either wavelet denoising or using the Savitzky-Golay filter.
By definition, a frequency-selective filter cannot do it.
Hi can you show the code on how you implemented this in order to remove the noise? I know i'm a little late to the party here.
Andrew Selley —
I did in my original Answer. (I would now use an elliptic filter. The code is essentially the same, switching to the elliptic filter functions.) Frequency-selective filters are onoly useful for band-limited noise, and that can be determined by using the fft function. Christopher Vergara’s initial Comment nicely describes that entire process.
For broadband noise, use the Savitzky-Golay filter (sgolayfilt) function. I usually use a degree 3 polynomial and vary the other parameters to get the result I want. Another option is wavelet denoising, however that requires the Wavelet Toolbox.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!