Filtering noise from an audio file
Mostrar comentarios más antiguos
I have a corrupted audio file which contains a message with very loud noise, and I should filter the noise as much as possible. I tried couple of filters, and I could eliminate some of the noises but it's not enough. P.S. The expected audio file is also there, which I plotted it to compare the filtered one with it. Both audio files and the code are provided in the zip file.

clc;
close all;
clear;
[Clean, Fs2] = audioread('expected.m4a');
[sample_data, sample_rate] = audioread('corrupted.m4a');
signal = medfilt1(sample_data,90); % Applying median filter
%_______________________________________________________________________________%
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
filtered_sound2 = filtfilt(soslp, glp, signal);
%_______________________________________________________________________________%
fs2_d = [filtered_sound2,filtered_sound2];
sound(fs2_d, sample_rate)
subplot(4,1,1);
plot(sample_data); % Original Signal
title('Original Signal');
xlabel('Time (s)'); ylabel ('Amplitude');
subplot(4,1,2);
plot(filtered_sound2); % Filtered output
title('Filtered Signal Double');
xlabel('Time (s)'); ylabel ('Amplitude');
subplot(4,1,3);
plot(fs2_d); % Filtered output
title('Filtered Signal Double');
xlabel('Time (s)'); ylabel ('Amplitude');
subplot(4,1,4);
plot(Clean); % Expected output
title('Expected Signal');
xlabel('Time (s)'); ylabel ('Amplitude');
12 comentarios
Just some comments: In R2016b I get the warning
Warning: The first two inputs are interpreted as an SOS matrix
and G vector. Use column vectors if you meant to specify a
transfer function.
in the line: filtered_sound2 = filtfilt(soslp, glp, signal);
Producing a stereo sound by fs2_d = [filtered_sound2,filtered_sound2] is not needed. Stay at mono.
Naser Je
el 12 de Mayo de 2018
Jan
el 12 de Mayo de 2018
If you mention that you took an idea from another thread, add a link also. This helps the readers. It would be useful to know, why you have chosen these filter parameters 1000, 1010, 1, 150.
Naser Je
el 12 de Mayo de 2018
Jan
el 12 de Mayo de 2018
I'd scale the filtered signal and the expected signal to be in the range [-1, 1] and subtract both from each other. Then you have the pure noise - approximately. Now use FFT to analyze its spectrum. Maybe this allows to improve the filter parameters. I'm not familiar enough with signal processing to help you further.
Star Strider
el 12 de Mayo de 2018
Note that the person who asked that question ended up using wavelets to eliminate the noise, as I originally suggested in my Answer. It is not possible to eliminate broadband noise with only a frequency-selective filter.
The first step of course is to use the fft (link) to see what the frequency content is. That allows you to design your filter effectively.
Abdulaziz Al-Hasani
el 15 de Abr. de 2019
Dear all ,
i would like anyone to have exprience for use the matlab , i need to 3- Design a filter to reduce the noise of a received audio signal
please as you can help me ,
i am looking forward
please contact me in 1502208@mtc.edu.om
Jan
el 15 de Abr. de 2019
@Abdulaziz Al-Hasani: Please open a new question and post the details there. Avoid to hijack another thread by posting a new problem in the section for comments.
mohamed mostafa
el 26 de Mayo de 2020
please, how i can design a filter to sperate two voices, my voice and audio of phone.
zina shalchi
el 27 de Oct. de 2020
Hello, I faced the following errors
Error using sound (line 76)
Only one- and two-channel audio supported.
Error in dsp (line 26)
sound(fs2_d, sample_rate)
while trying to implement your code
@Naser Je
would you help
Lochan Chitnis
el 21 de Sept. de 2021
can someone please explain the above code
Mathieu NOE
el 21 de Sept. de 2021
hi
just for the spectral analysis , I used this code. Seems the signal is burried in heavy broadband (white) noise plus two strong tones at 1000 and 2000 Hz
clc
clearvars
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% load signal
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% data
[signal,Fs] = audioread('corrupted.m4a');
% [signal,Fs] = audioread('expected.m4a');
[samples,channels] = size(signal);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
NFFT = 256; %
OVERLAP = 0.75;
% spectrogram dB scale
spectrogram_dB_scale = 60; % dB range scale (means , the lowest displayed level is XX dB below the max level)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% options
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% if you are dealing with acoustics, you may wish to have A weighted
% spectrums
% option_w = 0 : linear spectrum (no weighting dB (L) )
% option_w = 1 : A weighted spectrum (dB (A) )
option_w = 0;
%% decimate (if needed)
% NB : decim = 1 will do nothing (output = input)
decim = 1;
if decim>1
for ck = 1:channels
newsignal(:,ck) = decimate(signal(:,ck),decim);
Fs = Fs/decim;
end
signal = newsignal;
end
samples = length(signal);
time = (0:samples-1)*1/Fs;
%%%%%% legend structure %%%%%%%%
for ck = 1:channels
leg_str{ck} = ['Channel ' num2str(ck) ];
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 1 : time domain plot
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
figure(1),plot(time,signal);grid on
title(['Time plot / Fs = ' num2str(Fs) ' Hz ']);
xlabel('Time (s)');ylabel('Amplitude');
legend(leg_str);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 2 : averaged FFT spectrum
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[freq, sensor_spectrum] = myfft_peak(signal,Fs,NFFT,OVERLAP);
% convert to dB scale (ref = 1)
sensor_spectrum_dB = 20*log10(sensor_spectrum);
% apply A weigthing if needed
if option_w == 1
pondA_dB = pondA_function(freq);
sensor_spectrum_dB = sensor_spectrum_dB+pondA_dB;
my_ylabel = ('Amplitude (dB (A))');
else
my_ylabel = ('Amplitude (dB (L))');
end
figure(2),plot(freq,sensor_spectrum_dB);grid on
df = freq(2)-freq(1); % frequency resolution
title(['Averaged FFT Spectrum / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(df,3) ' Hz ']);
xlabel('Frequency (Hz)');ylabel(my_ylabel);
legend(leg_str);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 3 : time / frequency analysis : spectrogram demo
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for ck = 1:channels
[sg,fsg,tsg] = specgram(signal(:,ck),NFFT,Fs,hanning(NFFT),floor(NFFT*OVERLAP));
% FFT normalisation and conversion amplitude from linear to dB (peak)
sg_dBpeak = 20*log10(abs(sg))+20*log10(2/length(fsg)); % NB : X=fft(x.*hanning(N))*4/N; % hanning only
% apply A weigthing if needed
if option_w == 1
pondA_dB = pondA_function(fsg);
sg_dBpeak = sg_dBpeak+(pondA_dB*ones(1,size(sg_dBpeak,2)));
my_title = ('Spectrogram (dB (A))');
else
my_title = ('Spectrogram (dB (L))');
end
% saturation of the dB range :
% saturation_dB = 60; % dB range scale (means , the lowest displayed level is XX dB below the max level)
min_disp_dB = round(max(max(sg_dBpeak))) - spectrogram_dB_scale;
sg_dBpeak(sg_dBpeak<min_disp_dB) = min_disp_dB;
% plots spectrogram
figure(2+ck);
imagesc(tsg,fsg,sg_dBpeak);colormap('jet');
axis('xy');colorbar('vert');grid on
df = fsg(2)-fsg(1); % freq resolution
title([my_title ' / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(df,3) ' Hz / Channel : ' num2str(ck)]);
xlabel('Time (s)');ylabel('Frequency (Hz)');
end
function pondA_dB = pondA_function(f)
% dB (A) weighting curve
n = ((12200^2*f.^4)./((f.^2+20.6^2).*(f.^2+12200^2).*sqrt(f.^2+107.7^2).*sqrt(f.^2+737.9^2)));
r = ((12200^2*1000.^4)./((1000.^2+20.6^2).*(1000.^2+12200^2).*sqrt(1000.^2+107.7^2).*sqrt(1000.^2+737.9^2))) * ones(size(f));
pondA = n./r;
pondA_dB = 20*log10(pondA(:));
end
function [freq_vector,fft_spectrum] = myfft_peak(signal, Fs, nfft, Overlap)
% FFT peak spectrum of signal (example sinus amplitude 1 = 0 dB after fft).
% Linear averaging
% signal - input signal,
% Fs - Sampling frequency (Hz).
% nfft - FFT window size
% Overlap - buffer percentage of overlap % (between 0 and 0.95)
[samples,channels] = size(signal);
% fill signal with zeros if its length is lower than nfft
if samples<nfft
s_tmp = zeros(nfft,channels);
s_tmp((1:samples),:) = signal;
signal = s_tmp;
samples = nfft;
end
% window : hanning
window = hanning(nfft);
window = window(:);
% compute fft with overlap
offset = fix((1-Overlap)*nfft);
spectnum = 1+ fix((samples-nfft)/offset); % Number of windows
% % for info is equivalent to :
% noverlap = Overlap*nfft;
% spectnum = fix((samples-noverlap)/(nfft-noverlap)); % Number of windows
% main loop
fft_spectrum = 0;
for i=1:spectnum
start = (i-1)*offset;
sw = signal((1+start):(start+nfft),:).*(window*ones(1,channels));
fft_spectrum = fft_spectrum + (abs(fft(sw))*4/nfft); % X=fft(x.*hanning(N))*4/N; % hanning only
end
fft_spectrum = fft_spectrum/spectnum; % to do linear averaging scaling
% one sidded fft spectrum % Select first half
if rem(nfft,2) % nfft odd
select = (1:(nfft+1)/2)';
else
select = (1:nfft/2+1)';
end
fft_spectrum = fft_spectrum(select,:);
freq_vector = (select - 1)*Fs/nfft;
end
Respuestas (1)
matt
el 1 de Dic. de 2022
Limit bandwidth to region of highest signal strength in clean audio.
[Clean, Fs2] = audioread('expected.m4a');
[sample_data, sample_rate] = audioread('corrupted.m4a');
Fs = sample_rate;
d1 = designfilt('bandpassiir','FilterOrder',20, ...
'HalfPowerFrequency1',100,'HalfPowerFrequency2',600, ...
'SampleRate',Fs);
N = length(sample_data);
y1 = filtfilt(d1,sample_data);
%
Audio2 = audioplayer(y1,Fs);
play(Audio2);
f = linspace(0,Fs,N);
figure;
plot(f,abs(fft(sample_data)))
hold on
plot(f,abs(fft(Clean)))
plot(f,abs(fft(y1)))
Categorías
Más información sobre Multirate and Multistage Filters en Centro de ayuda y File Exchange.
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!