⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adamslpr.m

📁 数值计算
💻 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 + -