Matlab – How to create 1/3-Octave-Band Filters in MatLAB/Octave

MATLABsignal processing

I have to design 1/3-Octave-Band filters in MatLAB (or alternatively in Octave). I've read this doc article and I've tried using the fdesign.octavedesign duo, but this method allows creation of band filters for mid-band frequencies starting at around 25Hz. I need to create filters for frequency range from 0.5Hz to 100Hz.

I know how to calculate midband frequencies (fm) for those filters and corresponding upper and lower frequency bounds, so I've tried creating them myself using butter or cheby1 functions or using the fdatool. While filters created/displayed in fdatool look good, when I use them to filter chirp signal using the filer function, I can see something like in the image below: filtered chirp

Top plot is chirp filtered with my custom filter, bottom plot shows the same chirp filtered with the filter of the same order, type and mid-band frequency, but created using fdesign.octavedesign duo. I don't know how to get rid of that signal gain at the beginning and this one is actually one of the lowest signal gain, which shows for 100hZ mid-band frequency. The lower the mid-band frequency is, the worse my filter is (actually, below 2 or 3 Hz my filters filter out everything).

Hers is the code, that I am using to build my filter:

Wn = [Fl(i) Fh(i)] / (Fs/2);
[ z, p, k ] = butter( N, Wn, 'bandpass' );
% [z,p,k] = cheby1( N, Rp, Wn, 'bandpass' );
[ sos, g ]=zp2sos( z, p, k );
f = dfilt.df2sos( sos, g );

Can anyone help me with designing proper 1/3-Octave-Band filters for that frequency range (0.5รท100)Hz?


EDIT:
I've found another way to do what I want using the standardized fdesign.octave method. Read my answer below.

Best Answer

Just do it manually by working out the centre frequencies you want and then calculating upper and lower bounds. The following demo uses simple butterworth filters, but you can swap that out with any prototype you like.

fs = 250;
bw = 1/3;

fMin = 0.5;
fMax = 100;

octs = log2(fMax/fMin);
bmax = ceil(octs/bw);

fc = fMin*2.^( (0:bmax) * bw ); % centre frequencies
fl = fc*2^(-bw/2); % lower cutoffs
fu = fc*2^(+bw/2); % upper cutoffs

numBands = length(fc);

b = cell(numBands,1);
a = cell(numBands,1);

figure
for nn = 1:length(fc)

    [b{nn},a{nn}] = butter(2, [fl(nn) fu(nn)]/(fs/2), 'bandpass');
    [h,f]=freqz(b{nn},a{nn},1024,fs);

    hold on;
    plot(f, 20*log10(abs(h)) );

end
set(gca, 'XScale', 'log')
ylim([-50 0])

Which gives . . .

enter image description here

You can then use tf2sos if you want stability from higher order filters as a cascade of 2nd order sections.

You can use the following code to test a chirp to see that nothing weird is going on . .

dt=1/fs;
t = 0:dt:2000;      % 2 seconds
fo = 0.5; f1 = 120; 
x = chirp(t,fo,numel(t)*dt,f1,'logarithmic')';
y = zeros(numel(x), length(fc));
for nn = 1:length(fc)
    y(:,nn) = filter(b{nn},a{nn},x);
end

figure; plot(y)

enter image description here

Related Topic