📄 butter.m
字号:
function [num, den, z, p] = butter(n, Wn, varargin)%BUTTER Butterworth digital and analog filter design.% [B,A] = BUTTER(N,Wn) designs an Nth order lowpass digital% Butterworth filter and returns the filter coefficients in length % N+1 vectors B (numerator) and A (denominator). The coefficients % are listed in descending powers of z. The cut-off frequency % Wn must be 0.0 < Wn < 1.0, with 1.0 corresponding to % half the sample rate.%% If Wn is a two-element vector, Wn = [W1 W2], BUTTER returns an % order 2N bandpass filter with passband W1 < W < W2.% [B,A] = BUTTER(N,Wn,'high') designs a highpass filter.% [B,A] = BUTTER(N,Wn,'stop') is a bandstop filter if Wn = [W1 W2].% % When used with three left-hand arguments, as in% [Z,P,K] = BUTTER(...), the zeros and poles are returned in% length N column vectors Z and P, and the gain in scalar K. %% When used with four left-hand arguments, as in% [A,B,C,D] = BUTTER(...), state-space matrices are returned.%% BUTTER(N,Wn,'s'), BUTTER(N,Wn,'high','s') and BUTTER(N,Wn,'stop','s')% design analog Butterworth filters. In this case, Wn can be bigger% than 1.0.%% See also BUTTORD, BESSELF, CHEBY1, CHEBY2, ELLIP, FREQZ, FILTER.% Author(s): J.N. Little, 1-14-87% J.N. Little, 1-14-88, revised% L. Shure, 4-29-88, revised% T. Krauss, 3-24-93, revised% References:% [1] T. W. Parks and C. S. Burrus, Digital Filter Design,% John Wiley & Sons, 1987, chapter 7, section 7.3.3.[btype,analog,errStr] = iirchk(Wn,varargin{:});error(errStr)if n>500 error('Filter order too large.')end% step 1: get analog, pre-warped frequenciesif ~analog, fs = 2; u = 2*fs*tan(pi*Wn/fs);else u = Wn;endBw=[];% step 2: convert to low-pass prototype estimateif btype == 1 % lowpass Wn = u;elseif btype == 2 % bandpass Bw = u(2) - u(1); Wn = sqrt(u(1)*u(2)); % center frequencyelseif btype == 3 % highpass Wn = u;elseif btype == 4 % bandstop Bw = u(2) - u(1); Wn = sqrt(u(1)*u(2)); % center frequencyend% step 3: Get N-th order Butterworth analog lowpass prototype[z,p,k] = buttap(n);% Transform to state-space[a,b,c,d] = zp2ss(z,p,k);% step 4: Transform to lowpass, bandpass, highpass, or bandstop of desired Wnif btype == 1 % Lowpass [a,b,c,d] = lp2lp(a,b,c,d,Wn);elseif btype == 2 % Bandpass [a,b,c,d] = lp2bp(a,b,c,d,Wn,Bw);elseif btype == 3 % Highpass [a,b,c,d] = lp2hp(a,b,c,d,Wn);elseif btype == 4 % Bandstop [a,b,c,d] = lp2bs(a,b,c,d,Wn,Bw);end% step 5: Use Bilinear transformation to find discrete equivalent:if ~analog, [a,b,c,d] = bilinear(a,b,c,d,fs);endif nargout == 4 num = a; den = b; z = c; p = d;else % nargout <= 3% Transform to zero-pole-gain and polynomial forms: if nargout == 3 [z,p,k] = ss2zp(a,b,c,d,1); z = buttzeros(btype,n,Wn,Bw,analog); num = z; den = p; z = k; else % nargout <= 2 den = poly(a); num = buttnum(btype,n,Wn,Bw,analog,den); % num = poly(a-b*c)+(d-1)*den; endend%---------------------------------function b = buttnum(btype,n,Wn,Bw,analog,den)% This internal function returns more exact numerator vectors% for the num/den case.% Wn input is two element band edge vectorif analog switch btype case 1 % lowpass b = [zeros(1,n) n^(-n)]; b = real( b*polyval(den,-j*0)/polyval(b,-j*0) ); case 2 % bandpass b = [zeros(1,n) Bw^n zeros(1,n)]; b = real( b*polyval(den,-j*Wn)/polyval(b,-j*Wn) ); case 3 % highpass b = [1 zeros(1,n)]; b = real( b*den(1)/b(1) ); case 4 % bandstop r = j*Wn*((-1).^(0:2*n-1)'); b = poly(r); b = real( b*polyval(den,-j*0)/polyval(b,-j*0) ); endelse Wn = 2*atan2(Wn,4); switch btype case 1 % lowpass r = -ones(n,1); w = 0; case 2 % bandpass r = [ones(n,1); -ones(n,1)]; w = Wn; case 3 % highpass r = ones(n,1); w = pi; case 4 % bandstop r = exp(j*Wn*( (-1).^(0:2*n-1)' )); w = 0; end b = poly(r); % now normalize so |H(w)| == 1: kern = exp(-j*w*(0:length(b)-1)); b = real(b*(kern*den(:))/(kern*b(:)));endfunction z = buttzeros(btype,n,Wn,Bw,analog)% This internal function returns more exact zeros.% Wn input is two element band edge vectorif analog % for lowpass and bandpass, don't include zeros at +Inf or -Inf switch btype case 1 % lowpass z = zeros(0,1); case 2 % bandpass z = zeros(n,1); case 3 % highpass z = zeros(n,1); case 4 % bandstop z = j*Wn*((-1).^(0:2*n-1)'); endelse Wn = 2*atan2(Wn,4); switch btype case 1 % lowpass z = -ones(n,1); case 2 % bandpass z = [ones(n,1); -ones(n,1)]; case 3 % highpass z = ones(n,1); case 4 % bandstop z = exp(j*Wn*( (-1).^(0:2*n-1)' )); endend% FUNCTIONSfunction [at,bt,ct,dt] = lp2lp(a,b,c,d,wo)%LP2LP Lowpass to lowpass analog filter transformation.% [NUMT,DENT] = LP2LP(NUM,DEN,Wo) transforms the lowpass filter% prototype NUM(s)/DEN(s) with unity cutoff frequency of 1 rad/sec % to a lowpass filter with cutoff frequency Wo (rad/sec).% [AT,BT,CT,DT] = LP2LP(A,B,C,D,Wo) does the same when the% filter is described in state-space form.%% See also BILINEAR, IMPINVAR, LP2BP, LP2BS and LP2HP% Author(s): J.N. Little and G.F. Franklin, 8-4-87if nargin == 3 % Transfer function case % handle column vector inputs: convert to rows if size(a,2) == 1 a = a(:).'; end if size(b,2) == 1 b = b(:).'; end % Transform to state-space wo = c; [a,b,c,d] = tf2ss(a,b);enderror(abcdchk(a,b,c,d));[ma,nb] = size(b);[mc,ma] = size(c);% Transform lowpass to lowpassat = wo*a;bt = wo*b;ct = c;dt = d;if nargin == 3 % Transfer function case % Transform back to transfer function [z,k] = tzero(at,bt,ct,dt); num = k * poly(z); den = poly(at); at = num; bt = den;endfunction [at,bt,ct,dt] = lp2bp(a,b,c,d,wo,bw)%LP2BP Lowpass to bandpass analog filter transformation.% [NUMT,DENT] = LP2BP(NUM,DEN,Wo,Bw) transforms the lowpass filter% prototype NUM(s)/DEN(s) with unity cutoff frequency to a% bandpass filter with center frequency Wo and bandwidth Bw.% [AT,BT,CT,DT] = LP2BP(A,B,C,D,Wo,Bw) does the same when the% filter is described in state-space form.if nargin == 4 % Transfer function case % Transform to state-space wo = c; bw = d; [a,b,c,d] = tf2ss(a,b);enderror(abcdchk(a,b,c,d));[ma,nb] = size(b);[mc,ma] = size(c);% Transform lowpass to bandpassq = wo/bw;at = wo*[a/q eye(ma); -eye(ma) zeros(ma)];bt = wo*[b/q; zeros(ma,nb)];ct = [c zeros(mc,ma)];dt = d;if nargin == 4 % Transfer function case % Transform back to transfer function b = poly(at); at = poly(at-bt*ct)+(dt-1)*b; bt = b;endfunction [at,bt,ct,dt] = lp2hp(a,b,c,d,wo)%LP2HP Lowpass to highpass analog filter transformation.% [NUMT,DENT] = LP2HP(NUM,DEN,Wo) transforms the lowpass filter% prototype NUM(s)/DEN(s) with unity cutoff frequency to a% highpass filter with cutoff frequency Wo.% [AT,BT,CT,DT] = LP2HP(A,B,C,D,Wo) does the same when the% filter is described in state-space form.if nargin == 3 % Transfer function case % Transform to state-space wo = c; [a,b,c,d] = tf2ss(a,b);enderror(abcdchk(a,b,c,d));[ma,nb] = size(b);[mc,ma] = size(c);% Transform lowpass to highpassat = wo*inv(a);bt = -wo*(a\b);ct = c/a;dt = d - c/a*b;if nargin == 3 % Transfer function case % Transform back to transfer function b = poly(at); at = poly(at-bt*ct)+(dt-1)*b; bt = b;endfunction [at,bt,ct,dt] = lp2bs(a,b,c,d,wo,bw)%LP2BS Lowpass to bandstop analog filter transformation.% [NUMT,DENT] = LP2BS(NUM,DEN,Wo,Bw) transforms the lowpass filter% prototype NUM(s)/DEN(s) with unity cutoff frequency to a% bandstop filter with center frequency Wo and bandwidth Bw.% [AT,BT,CT,DT] = LP2BS(A,B,C,D,Wo,Bw) does the same when the% filter is described in state-space form.if nargin == 4 % Transfer function case % Transform to state-space wo = c; bw = d; [a,b,c,d] = tf2ss(a,b);enderror(abcdchk(a,b,c,d));[ma,nb] = size(b);[mc,ma] = size(c);% Transform lowpass to bandstopq = wo/bw;at = [wo/q*inv(a) wo*eye(ma); -wo*eye(ma) zeros(ma)];bt = -[wo/q*(a\b); zeros(ma,nb)];ct = [c/a zeros(mc,ma)];dt = d - c/a*b;if nargin == 4 % Transfer function case % Transform back to transfer function b = poly(at); at = poly(at-bt*ct)+(dt-1)*b; bt = b;endfunction [zd, pd, kd, dd] = bilinear(z, p, k, fs, fp, fp1)%BILINEAR Bilinear transformation with optional frequency prewarping.% [Zd,Pd,Kd] = BILINEAR(Z,P,K,Fs) converts the s-domain transfer% function specified by Z, P, and K to a z-transform discrete% equivalent obtained from the bilinear transformation:%% H(z) = H(s) |% | s = 2*Fs*(z-1)/(z+1)%% where column vectors Z and P specify the zeros and poles, scalar% K specifies the gain, and Fs is the sample frequency in Hz.% [NUMd,DENd] = BILINEAR(NUM,DEN,Fs), where NUM and DEN are % row vectors containing numerator and denominator transfer% function coefficients, NUM(s)/DEN(s), in descending powers of% s, transforms to z-transform coefficients NUMd(z)/DENd(z).% [Ad,Bd,Cd,Dd] = BILINEAR(A,B,C,D,Fs) is a state-space version.% Each of the above three forms of BILINEAR accepts an optional% additional input argument that specifies prewarping. For example,% [Zd,Pd,Kd] = BILINEAR(Z,P,K,Fs,Fp) applies prewarping before% the bilinear transformation so that the frequency responses% before and after mapping match exactly at frequency point Fp% (match point Fp is specified in Hz).%% See also IMPINVAR.% Author(s): J.N. Little, 4-28-87 % J.N. Little, 5-5-87, revised% Gene Franklin, Stanford Univ., motivated the state-space% approach to the bilinear transformation.[mn,nn] = size(z);[md,nd] = size(p);if (nd == 1 & nn < 2) & nargout ~= 4 % In zero-pole-gain form if mn > md error('Numerator cannot be higher order than denominator.') end if nargin == 5 % Prewarp fp = 2*pi*fp; fs = fp/tan(fp/fs/2); else fs = 2*fs; end z = z(finite(z)); % Strip infinities from zeros pd = (1+p/fs)./(1-p/fs); % Do bilinear transformation zd = (1+z/fs)./(1-z/fs);% real(kd) or just kd? kd = (k*prod(fs-z)./prod(fs-p)); zd = [zd;-ones(length(pd)-length(zd),1)]; % Add extra zeros at -1elseif (md == 1 & mn == 1) | nargout == 4 % if nargout == 4 % State-space case a = z; b = p; c = k; d = fs; fs = fp; error(abcdchk(a,b,c,d)); if nargin == 6 % Prewarp fp = fp1; % Decode arguments fp = 2*pi*fp; fs = fp/tan(fp/fs/2)/2; end else % Transfer function case if nn > nd error('Numerator cannot be higher order than denominator.') end num = z; den = p; % Decode arguments if nargin == 4 % Prewarp fp = fs; fs = k; % Decode arguments fp = 2*pi*fp; fs = fp/tan(fp/fs/2)/2; else fs = k; % Decode arguments end % Put num(s)/den(s) in state-space canonical form. [a,b,c,d] = tf2ss(num,den); end % Now do state-space version of bilinear transformation: t = 1/fs; r = sqrt(t); t1 = eye(size(a)) + a*t/2; t2 = eye(size(a)) - a*t/2; ad = t2\t1; bd = t/r*(t2\b); cd = r*c/t2; dd = c/t2*b*t/2 + d; if nargout == 4 zd = ad; pd = bd; kd = cd; else % Convert back to transfer function form: p = poly(ad); zd = poly(ad-bd*cd)+(dd-1)*p; pd = p; endelse error('First two arguments must have the same orientation.')end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -