Why are my filters designed with fdesign so bad?

2 views (last 30 days)
I am getting very poor bandpass and bandstop IIR filters designed using fdesign.bandpass and fdesign.bandstop, using any of the following design methods:
'butter', 'ellip', 'cheby1', 'cheby2'
However, if I call the simple design functions directly (e.g. buttord, followed by butter) then the results are very good.
Just to be clear, I get good results from both methods if the passband/stopband is relatively wide:
However, for very narrow passbands/stopbands, the fdesign filters are garbage. I don't get any error or warning telling me that anything bad happened:
What are the differences between how the design methods are implemented in these two cases? And when should I choose which?
In general, I find the multiple MATLAB/toolbox implementations of the same filter design methods rather convoluted. I have spent many hours reading through all the different incarnations of the documentation and I'm not really any the wiser. In particular, the system objects, dfilt filter objects and designfilt digital filters all seem very inconvenient to use (and all hide subtle differences).
To reproduce my results above, you can run this script:
close all; clear all; clc;
% Filter parameters
Type = 'bandpass'; % Filter type
Fsamp = 1e6; % Sample rate (Hz)
Fp = [9,11]; % Passband edges (Hz)
Fst = [5,20]; % Stopband edges (Hz)
Ap = 0.1; % Passband ripple (dB)
Ast = 60; % Stopband attenuation (dB)
Method = 'butter'; % Filter design method
% Plot parameters
Fplot = logspace(-2, log10(0.5*Fsamp), 32768);
% Design filters and calculate responses
Hsimp = SimpleResponse(Method, Type, Fp, Fst, Ap, Ast, Fsamp, Fplot);
Htbox = FdesignResponse(Method, Type, Fp, Fst, Ap, Ast, Fsamp, Fplot);
% Plot
semilogx(Fplot, 20*log10(abs(Hsimp)), 'LineWidth', 1.5);
hold on; grid on;
semilogx(Fplot, 20*log10(abs(Htbox)), '--r', 'LineWidth', 1.5);
legend('simple', 'fdesign');
ylim([-200,5]);
xlim([0.1*Fp(1), 10*Fp(2)]);
xlabel('Frequency (Hz)');
ylabel('Magnitude (dB)');
which calls SimpleResponse.m:
function H = SimpleResponse(Method, Type, Fp, Fst, Ap, Ast, Fsamp, Fplot)
switch Method
case 'butter'
[n,Wn] = buttord(Fp/(0.5*Fsamp), Fst/(0.5*Fsamp), Ap, Ast);
[z,p,k] = butter(n, Wn, Type);
case 'ellip'
[n,Wn] = ellipord(Fp/(0.5*Fsamp), Fst/(0.5*Fsamp), Ap, Ast);
[z,p,k] = ellip(n, Ap, Ast, Wn, Type);
case 'cheby1'
[n,Wn] = cheb1ord(Fp/(0.5*Fsamp), Fst/(0.5*Fsamp), Ap, Ast);
[z,p,k] = cheby1(n, Ap, Wn, Type);
case 'cheby2'
[n,Wn] = cheb2ord(Fp/(0.5*Fsamp), Fst/(0.5*Fsamp), Ap, Ast);
[z,p,k] = cheby2(n, Ast, Wn, Type);
otherwise
error(['Unsupported method: ' Method]);
end
% Calculate response
SOS = zp2sos(z,p,k);
H = freqz(SOS, 2*pi*Fplot/Fsamp);
and FdesignResponse.m:
function H = FdesignResponse(Method, Type, Fp, Fst, Ap, Ast, Fsamp, Fplot)
if isequal(Type, 'bandpass')
fd = fdesign.bandpass('Fst1,Fp1,Fp2,Fst2,Ast1,Ap,Ast2', Fst(1), Fp(1), Fp(2), Fst(2), Ast, Ap, Ast, Fsamp);
elseif isequal(Type, 'stop')
fd = fdesign.bandstop('Fp1,Fst1,Fst2,Fp2,Ap1,Ast,Ap2', Fp(1), Fst(1), Fst(2), Fp(2), Ap, Ast, Ap, Fsamp);
else
error(['Unsupported filter type: ' Type]);
end
d = design(fd, Method);
% Compute response
H = freqz(d, 2*pi*Fplot/Fsamp);

Answers (0)

Community Treasure Hunt

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

Start Hunting!