📄 adamslpr.m
字号:
function [h,L2E,mL2,it,cs] = adamslpr(n,up,lo,wp,ws,K,L) % [h,L2E,mL2,it,cs] = adamslpr(n,up,lo,wp,ws,K,L)% An implementation of Adams' approach to constrained weighted % L2 Low Pass FIR filter design % (constraint frequncies are refined with Newton's Method)% see John Adams' paper: FIR Digital Filters with% Least-Squares Stopbands Subject to Peak-Gain Constraints,% in IEEE Trans on Circuits and Systems,% vol 39, no 4, April 1991%% input: % n : filter length% up : [upper bound in pass band, upper bound in stop band]% lo : [lower bound in pass band, lower bound in stop band]% wp : passband edge of L2 weight function% ws : stopband edge of L2 weight function% K : stopband L2 weight / passband L2 weight% L : grid size (optional)% output:% h : filter of length n% L2E : _unweighted_ L2 error% mL2 : minimum _unweighted_ L2 error achievable % (L2 error of best unweighted L2 filter)% it : number of iterations% cs : constraint set at convergence%% subprograms called:% frefine : refines the extremal frequencies of an FIR filter% local_max : finds local maxima%% EXAMPLE% wp = 0.27*pi; ws = 0.333*pi; n = 55; K = 3;% dp = 0.03; ds = 0.01; up = [1+dp, ds]; lo = [1-dp, -ds];% [h,L2E,mL2,it,cs] = adamslpr(n,up,lo,wp,ws,K);%% % example from Adams' paper% wp = 0.0625*2*pi; ws = 0.0804*2*pi; n = 95;% ds = 10^(-45/20); % up = [1 ds];% lo = [10^(-1/20) -ds];% K = 1000;% [h,L2E,mL2,it,cs] = adamslpr(n,up,lo,wp,ws,K);% this program was coded by: Ivan Selesnick, October 95, Rice UniversityPF = 1; % flag : Plot Figures (1:plot figs, 0:don't)if nargin < 8 L = 2^ceil(log2(3*n));endr = sqrt(2);w = [0:L]*pi/L; % w includes both 0 and pikp = round(L*wp/pi+1);ks = round(L*ws/pi+1);wo = (wp+ws)/2;q = round(wo*L/pi);u = [up(1)*ones(q,1); up(2)*ones(L+1-q,1)];l = [lo(1)*ones(q,1); lo(2)*ones(L+1-q,1)];if rem(n,2) == 1 parity = 1; m = (n-1)/2; % c = 2*[wo/r; [sin(wo*[1:m])./[1:m]]']/pi; c = 2*[wp/r; [sin(wp*[1:m])./[1:m]]']/pi; Z = zeros(2*L-n,1); v = [0:m]; tt = 1 - 1/r;else parity = 0; m = n/2; Z = zeros(4*L,1); v = [1:m]-1/2; c = [2*sin(wp*v)./(v*pi)]'; tt = 0;end% ----- construct R matrix --------------------if rem(n,2) == 1 % odd length symmetric filter v1 = 1:m; v2 = m:2*m; tp = [wp+K*(pi-ws), (sin(v1*wp)-K*sin(v1*ws))./v1]/pi; hk = ((sin(v2*wp)-K*sin(v2*ws))./v2)/pi; R = toeplitz(tp,tp) + hankel(tp,hk); R(1,:) = R(1,:)/r; R(:,1) = R(:,1)/r; Ri = inv(R); else % even length symmetric filter v1 = 1:(m-1); v2 = (m-1):2*(m-1); tp = [(wp+K*(pi-ws)), (sin(v1*wp)-K*sin(v1*ws))./v1]/pi; v1 = 1:m; v2 = m:2*m-1; tp2 = ((sin(v1*wp)-K*sin(v1*ws))./v1)/pi; hk2 = ((sin(v2*wp)-K*sin(v2*ws))./v2)/pi; R = toeplitz(tp,tp) + hankel(tp2,hk2); Ri = inv(R);endmL2 = wo/pi - c'*c/2;L2E = mL2;a = Ri*c; % best L2 cosine coefficientsmu = []; % Lagrange multipliersSN = 1e-7; % Small Numberit = 0;% BEGIN LOOPINGwhile 1 % calculate A (filter response amplitude) if parity == 1 A = fft([a(1)*r; a(2:m+1); Z; a(m+1:-1:2)]); A = real(A(1:L+1)/2); else Z(2:2:2*m) = a; Z(4*L-2*m+2:2:4*L) = a(m:-1:1); A = fft(Z); A = real(A(1:L+1)/2); end % find local maxima and minima kmax = local_max(A); kmin = local_max(-A); if parity == 0 n1 = length(kmax); if kmax(n1) == L+1 kmax(n1) = []; n1 = n1 - 1; end n2 = length(kmin); if kmin(n2) == L+1 kmin(n2) = []; n2 = n2 - 1; end end % refine frequencies cmax = (kmax-1)*pi/L; cmin = (kmin-1)*pi/L; cmax = frefine(a,v,cmax); cmin = frefine(a,v,cmin); % append band edges to constraint set kmax = [kmax; ks]; kmin = [kmin; kp]; cmax = [cmax; ws]; cmin = [cmin; wp]; % evaluate A at refined frequencies Amax = cos(cmax*v)*a - tt*a(1); Amin = cos(cmin*v)*a - tt*a(1); % determine new constraint set v1 = Amax > u(kmax)-10*SN; v2 = Amin < l(kmin)+10*SN; kmax = kmax(v1); kmin = kmin(v2); cmax = cmax(v1); cmin = cmin(v2); Amax = Amax(v1); Amin = Amin(v2); n1 = length(kmax); n2 = length(kmin); % if constraint set is too big, then trim it down % to its maximum size (m+1). % identify w=0 and w=pi as local max or min if (n1+n2) > m+1 [tmp1,i1] = min(kmin); [tmp2,i2] = min(kmax); if tmp1 == 1 zext_type = -1; zi = i1; % (w=0 is a local minimum) else zext_type = 1; zi = i2; % (w=0 is a local maximum) end [tmp1,i1] = max(kmin); [tmp2,i2] = max(kmax); if tmp1 == L+1 piext_type = -1; pii = i1; % (w=pi is a local minimum) else piext_type = 1; pii = i2; % (w=pi is a local maximum) end end if (n1+n2) == m+2 % remove either w=0 or w=pi from % constraint set, not both. % decide which one to remove: if zext_type == 1 E0 = A(1) - up(1); else E0 = lo(1) - A(1); end if piext_type == 1 Epi = A(L+1) - up(2); else Epi = lo(2) - A(L+1); end if E0 > Epi % remove w = 0 from constraint set if zext_type == -1 kmin(zi) = []; n2 = n2 - 1; cmin(zi) = []; Amin(zi) = []; else kmax(zi) = []; n1 = n1 - 1; cmax(zi) = []; Amax(zi) = []; end else % (E0 >= Epi) % remove w = pi from constraint set if piext_type == -1 kmin(pii) = []; n2 = n2 - 1; cmin(pii) = []; Amin(pii) = []; else kmax(pii) = []; n1 = n1 - 1; cmax(pii) = []; Amax(pii) = []; end end elseif (n1+n2) == m+3 % remove both w=0 and w=pi from constraint set if zext_type == -1 kmin(zi) = []; n2 = n2 - 1; cmin(zi) = []; Amin(zi) = []; % update pii if nec. if (piext_type == -1) & (zi < pii) pii = pii-1; end else kmax(zi) = []; n1 = n1 - 1; cmax(zi) = []; Amax(zi) = []; % update pii if nec. if (piext_type == 1) & (zi < pii) pii = pii-1; end end % remove w = pi from constraint set if piext_type == -1 kmin(pii) = []; n2 = n2 - 1; cmin(pii) = []; Amin(pii) = []; else kmax(pii) = []; n1 = n1 - 1; cmax(pii) = []; Amax(pii) = []; end end % plot figures if PF wv = [cmax; cmin]; Av = [Amax; Amin]; figure(1), plot(w/pi,A), axis([0 1 -.2 1.2]) hold on, plot(wv/pi,Av,'o'), hold off figure(2) subplot(211) plot(w/pi,A-1), hold on, plot(wv/pi,Av-1,'o'), hold off axis([0 wo/pi 2*(lo(1)-1) 2*(up(1)-1)]) subplot(212) plot(w/pi,A), hold on, plot(wv/pi,Av,'o'), hold off axis([wo/pi 1 2*lo(2) 2*up(2)]) pause(.5) end % check stopping criterion E = max([Amax-u(kmax); l(kmin)-Amin; 0]); fprintf(1,' Bound Violation = %15.13f L2E = %18.15f\n',E,L2E); if E < SN fprintf(1,' I converged in %d iterations\n',it) break end if E > 20 fprintf(1,'\nI think your specifications are unrealizable.\n\n') end % calculate new Lagrange multipliers if parity == 1 G = [ones(n1,m+1); -ones(n2,m+1)].*cos([cmax; cmin]*[0:m]); G(:,1) = G(:,1)/r; else G = [ones(n1,m); -ones(n2,m)].*cos([cmax; cmin]*([1:m]-1/2)); end d = [u(kmax); -l(kmin)]; mu = (G*Ri*G')\(G*Ri*c-d); % iteratively remove negative multiplier [min_mu,K] = min(mu); while min_mu < 0 G(K,:) = []; d(K) = []; mu = (G*Ri*G')\(G*Ri*c-d); [min_mu,K] = min(mu); end % determine new cosine coefficients vv = G'*mu; L2E = vv'*vv/2 + mL2; a = Ri*(c-vv); it = it + 1;endif parity == 1 h = [a(m+1:-1:2)/2; a(1)/r; a(2:m+1)/2];else h = [a(m:-1:1); a]/2;endcs = [cmax; cmin];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -