How to make Narrow Bandpass filter?
14 views (last 30 days)
Show older comments
I have a signal, that has a bunch of noise and sine signals in it, 4 sine signals too be exact, and 4 noise signals.
i have pin pointed the frequencies of these sine signals to be 159.0574, 359.3519, 459.4992, 709.8674.
The signal and its spektrum looks like this:

I need to filter out all the noise, so i tried too use bandpass, using each sine frequency :
f1 = bandpass(signalas, [floor(virsunes(1)) ceil(virsunes(1))], Fd);
f2 = bandpass(signalas, [floor(virsunes(2)) ceil(virsunes(2))], Fd);
f3 = bandpass(signalas, [floor(virsunes(3)) ceil(virsunes(3))], Fd);
f4 = bandpass(signalas, [floor(virsunes(4)) ceil(virsunes(4))], Fd);
virsunes is just an array of those frequencies.
When i combined the filtered signals, i got this:

A lot of the noise has stuck around because it's too close too the sine signal. How to make a bandpass filter more narrow, for it too filter all the noise?
I attached the signal file "G4_12.dot".
0 Comments
Accepted Answer
Mathieu NOE
on 9 Dec 2020
hello
seems I have already seen similar post somewhere... a buddy of yours ?
you did not mentionned the sampling frequency , but 24 kHz seemed correct
here my little contribution :
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% options
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% spectrogram dB scale
spectrogram_dB_scale = 60; % dB range scale (means , the lowest displayed level is XX dB below the max level)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% load signal
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% test data
Fs = 24000;
% t = 0:1/Fs:10-1/Fs;
fid = fopen('G4_12.dat','r')
[signal,samples] = fscanf(fid, '%12f');
fclose(fid);
% decimate
decim = 12;
signal = decimate(signal,decim);
Fs = Fs/decim;
samples = length(signal);
time =(1:samples)/Fs;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% FFT parameters
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
n_max = fix(log2(samples));
NFFT = 2^(n_max-1); % 2^n with n chosen so that NFFT is below length of signal (even after decimation) by factor > 2 so some averaging is doable
% NFFT = 2048/4; % 2^n with n chosen so that NFFT is below length of signal (even after decimation) by factor > 2 so some averaging is doable
NOVERLAP = round(0.95*NFFT);
w = hanning(NFFT); % Hanning window / Use the HANN function to get a Hanning window which has the first and last zero-weighted samples.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display : averaged FFT spectrum before filter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[sensor_spectrum, freq] = pwelch(signal,w,NOVERLAP,NFFT,Fs,'power');
sensor_spectrum_dB = 10*log10(sensor_spectrum);% convert to dB scale (ref = 1)
% sensor_spectrum_dB = sensor_spectrum_dB-min(sensor_spectrum_dB); % y axis shift so dB values are positive (min value = 0)
%% findpeaks
% df = Fs/NFFT;
% MAXW = 10*df;
% MPD = 20;
% MPP = 20;
% [peaks,loc,W,P] = findpeaks(sensor_spectrum_dB,'MinPeakDistance',MPD,'MaxPeakWidth',MAXW,'MinPeakProminence',MPP);
% freq_peaks = freq(loc);
freq_peaks = [159.0574, 359.3519, 459.4992, 709.8674];
peaks = interp1(freq,sensor_spectrum_dB,freq_peaks,'linear');
figure(1),plot(freq,sensor_spectrum_dB,'b',freq_peaks,peaks,'*r');grid
title(['Averaged FFT Spectrum / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(freq(2)-freq(1)) ' Hz ']);
xlabel('Frequency (Hz)');ylabel(' dB')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display 2 : time / frequency analysis : spectrogram demo
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[sg,fsg,tsg] = specgram(signal,NFFT,Fs,hanning(NFFT),NOVERLAP);
% 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
% scalingf the dB range :
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);
imagesc(tsg,fsg,sg_dBpeak);colormap('jet');
axis('xy');colorbar('vert');grid
title(['Spectrogram / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(fsg(2)-fsg(1)) ' Hz ']);
xlabel('Time (s)');ylabel('Frequency (Hz)');
% keep only signal content extracted by bandpass filters
fc = freq_peaks; % Hz
bandwith = 8; % Hz
f_low = fc-0.5*bandwith;
f_high = fc+0.5*bandwith;
N = 4;
signal_filtered = zeros(size(signal));
for ci = 1:length(fc)
[b,a] = butter(N,2/Fs*[f_low(ci) f_high(ci)]);
% add filtered signal to total final signal
tmp = filtfilt(b,a,signal);
signal_filtered = signal_filtered + tmp;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% display : averaged FFT spectrum before / after notch filter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[sensor_spectrum_filtered, freq] = pwelch(signal_filtered,w,NOVERLAP,NFFT,Fs,'power');
sensor_spectrum_filtered_dB = 10*log10(sensor_spectrum_filtered);% convert to dB scale (ref = 1)
figure(4),plot(freq,sensor_spectrum_dB,'b',freq,sensor_spectrum_filtered_dB,'r');grid
title(['Averaged FFT Spectrum / Fs = ' num2str(Fs) ' Hz / Delta f = ' num2str(freq(2)-freq(1)) ' Hz ']);
legend('before filter','after filter');
xlabel('Frequency (Hz)');ylabel(' dB')
figure(5),plot(time,signal_filtered,'b');grid
title('Filtered signal');
xlabel('Time (s)');ylabel(' amplitude')
2 Comments
Mathieu NOE
on 10 Dec 2020
With STFT (short time fourier transform) , which is the basement of spectrogram, it may be difficult to obtain a good compromise between frequency resolution and time resolution.
i found in this specific case that to separate the sinus from the noise bands we needed a refined frequency resolution (df< 2 Hz) , but that does not give a very attractive time resolution
so my suggestion (to your colleague) was to look at each of the bandpass filtered signal, to rectify it, to make an enveloppe of that and to detect when that enveloppe goes above a certain (positive) threshold :
- when it crosses the enveloppe with a positive slope it's the beginning of the signal
- when it crosses the enveloppe with a negative slope it's the end of the signal
IMHO, it's much better than to rely on readings from the spectrogram
More Answers (0)
See Also
Categories
Find more on Time-Frequency Analysis in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
