home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 10 / 10.iso / l / l455 / 8.ddi / SIGNAL.DI$ / REMEZ.M < prev    next >
Encoding:
Text File  |  1993-03-11  |  15.0 KB  |  588 lines

  1. function [h,ha] = remez(nfilt, ff, aa, wtx, ftype)
  2. %REMEZ    Parks-McClellan optimal equiripple FIR filter design.
  3. %       B = REMEZ(N,F,M) designs an N'th order FIR digital filter,
  4. %    with the frequency response specified by vectors F and M, 
  5. %    and returns the    filter coefficients in length N+1 vector B.
  6. %    Vectors F and M specify the frequency and magnitude
  7. %    breakpoints for the filter such that PLOT(F,M) would show a
  8. %    plot of the desired frequency response. The elements of M must
  9. %    appear in equal-valued pairs.  The frequencies in F must be
  10. %    between 0.0 < F < 1.0, with 1.0 corresponding to half the
  11. %    sample rate. They must be in increasing order, start with 0.0,
  12. %    and end with 1.0.
  13. %       B = REMEZ(N,F,M,W) uses vector W to specify weighting in each
  14. %    of the pass or stop bands in vectors F and M.
  15. %    B = REMEZ(N,F,M,FTYPE) or B = REMEZ(N,F,M,W,FTYPE), where FTYPE
  16. %    is the string 'Hilbert' or 'differentiator', designs Hilbert
  17. %    transformers or differentiators, respectively.  For the Hilbert
  18. %    case, the lowest frequency should not be 0.
  19. %    
  20. %    See also FIR1, FIR2, BUTTER, CHEBY1, CHEBY2, YULEWALK, FREQZ
  21. %    and FILTER.
  22.  
  23. %    Author: L. Shure 3-27-87
  24. %    Revised 6-8-88 LS
  25. %    (c) Copyright 1987-88, by The MathWorks, Inc.
  26.  
  27. %    References:
  28. %      [1] "Programs for Digital Signal Processing", IEEE Press
  29. %           John Wiley & Sons, 1979, pg. 5.1-1.
  30. %      [2] "Selected Papers in Digital Signal Processing, II",
  31. %           IEEE Press, 1976, pg. 97.
  32.  
  33. %    Note: Frequency transitions much faster than 0.1 can cause large
  34. %    amounts of ripple in the response.  By default, if two 
  35. %    coincident frequency points are specified, they will be 
  36. %    separated by 0.1.  See the parameter SMALL below.
  37.  
  38. lgrid = 16;    % Grid density (should be greater than 16)
  39. nfilt = nfilt + 1;
  40.  
  41. if (nargin < 3 | nargin > 5)
  42.     error('Incorrect number of input arguments.')
  43. end
  44. if nfilt < 4
  45.     error('Filter order must be 3 or more.')
  46. end
  47. if nargin == 4
  48.     if isstr(wtx)
  49.         ftype = wtx(1); 
  50.         wtx = ones(fix((1+max(size(aa)))/2),1);
  51.     else
  52.         ftype = 'f';
  53.     end
  54. end
  55. if nargin < 4
  56.     ftype = 'f';
  57.     wtx = ones(fix((1+max(size(aa)))/2),1);
  58. end
  59. if rem(length(ff),2)
  60.     error('Frequencies must be specified in bands.');
  61. end
  62. daa = diff(aa);
  63. if abs(any(daa(1:2:length(daa)))) > eps
  64.     error('Bands must be specified with constant magnitudes.')
  65. end
  66. clear daa;
  67.         
  68. if ftype(1) == 'h' | ftype(1) == 'H'
  69.     jtype = 3;    % Hilbert transformer
  70. elseif ftype(1) == 'd' | ftype(1) == 'D'
  71.     jtype = 2;    % Differentiator
  72. else
  73.     jtype = 1;    % Regular filter
  74. end
  75. if nargin > 3 & (max(size(wtx)) ~= fix((1+max(size(aa)))/2))
  76.     error('There should be one weight per band.')
  77. end
  78. ha = 1;
  79.  
  80. ff = ff(:)';
  81. aa = aa(:)';
  82. wtx = wtx(:)';
  83. [mf,nf] = size(ff);
  84. [ma,na] = size(aa);
  85. if na ~= nf
  86.     error('Frequency and amplitude vectors must be the same length.')
  87. end
  88.  
  89. nbands = nf/2;
  90. jb = 2*nbands;
  91. if jb ~= nf
  92.     error('The number of frequency points must be even.')
  93. end
  94.  
  95. % The following constraint is not necessary:
  96. % if jtype ~= 3 & (abs(ff(1)) > eps | abs(ff(jb) - 1) > eps)
  97. %    error('The first frequency must be 0 and the last 1.')
  98. % end
  99.  
  100. if jtype == 3 & ff(1) == 0
  101.     error('The first frequency for a Hilbert transformer must not be 0.')
  102. end
  103.  
  104. % interpolate breakpoints onto large grid
  105. edge = ff;
  106. fx = aa(2:2:jb);
  107.  
  108. df = diff(ff);
  109. if (any(df < 0))
  110.     error('Frequencies must be non-decreasing.')
  111. end
  112. small = 0.05;        % Default minimum frequency transition
  113. for k=2:2:jb-2;
  114.     if edge(k) == edge(k+1)
  115.         edge(k) = edge(k) - small;
  116.         edge(k+1) = edge(k+1) + small;
  117.     end
  118. end
  119. edge = edge/2;
  120. cmptr = computer;
  121. if (exist('remezf') == 3) & (nfilt < 128)
  122.     % Use MEX-file
  123.     h = eval('remezf(nfilt,edge,fx,wtx,jtype)');
  124.     h = [h; sign(.5-(jtype ~= 1))*h(max(size(h))-rem(nfilt,2):-1:1)].';
  125.     h = h(max(size(h)):-1:1);
  126.     return
  127. end
  128. neg = 1 - (jtype == 1);
  129. nodd = rem(nfilt,2);
  130. nfcns = fix(nfilt/2);
  131. if nodd == 1 & neg == 0
  132.     nfcns = nfcns + 1;
  133. end
  134. grid(1) = edge(1);
  135. delf = .5/(lgrid*nfcns);
  136. if neg ~= 0 & edge(1) < delf
  137.     grid(1) = delf;
  138. end
  139. j = 1;
  140. l = 1;
  141. lband = 1;
  142. while lband <= nbands
  143.     fup = edge(l+1);
  144.     grid = [grid (grid(j)+delf):delf:(fup+delf)];
  145.     jend = max(size(grid));
  146.     grid(jend-1) = fup;
  147.     sel = j:jend-1;
  148.     des(sel) = fx(lband)*((grid(sel)-1)*(jtype == 2) + 1);
  149.           wt(sel) = wtx(lband)./(1 +((jtype == 2) & fx(lband) >= .0001)*(grid(sel) - 1));
  150.     j = jend;
  151.     lband = lband + 1;
  152.     l = l + 2;
  153.     if lband <= nbands
  154.         grid(j) = edge(l);
  155.     end
  156. end
  157. ngrid = j - 1;
  158. if neg == nodd & grid(ngrid) > .5-delf
  159.     ngrid = ngrid - 1;
  160. end
  161. if neg <= 0
  162.     if nodd ~= 1
  163.         des = des(1:ngrid)./cos(pi*grid(1:ngrid));
  164.         wt = wt(1:ngrid).*cos(pi*grid(1:ngrid));
  165.     end
  166. elseif nodd ~= 1
  167.     des = des(1:ngrid)./sin(pi*grid(1:ngrid));
  168.     wt = wt(1:ngrid).*sin(pi*grid(1:ngrid));
  169. else
  170.     des = des(1:ngrid)./sin(2*pi*grid(1:ngrid));
  171.     wt = wt(1:ngrid).*sin(2*pi*grid(1:ngrid));
  172. end
  173. temp = (ngrid-1)/nfcns;
  174. j=1:nfcns;
  175. iext = fix([temp*(j-1)+1 ngrid])';
  176. nm1 = nfcns - 1;
  177. nz = nfcns + 1;
  178.  
  179. % Remez exchange loop
  180. comp = [];
  181. itrmax = 25;
  182. devl = -1;
  183. nzz = nz + 1;
  184. niter = 0;
  185. jchnge = 1;
  186. jet = fix((nfcns - 1)/15) + 1;
  187. while jchnge > 0
  188.    iext(nzz) = ngrid + 1;
  189.    niter = niter + 1;
  190.    if niter > itrmax
  191.       break;
  192.    end
  193.    l = iext(1:nz)';
  194.    x = cos(2*pi*grid(l));
  195.    for nn = 1:nz
  196.     ad(nn) = remezdd(nn, nz, jet, x);
  197.    end
  198.    add = ones(size(ad));
  199.    add(2:2:nz) = -add(2:2:nz);
  200.    dnum = ad*des(l)';
  201.    dden = add*(ad./wt(l))';
  202.    dev = dnum/dden;
  203.    nu = 1;
  204.    if dev > 0
  205.       nu = -1;
  206.    end
  207.    dev = -nu*dev;
  208.    y = des(l) + nu*dev*add./wt(l);
  209.    if dev <= devl
  210.       disp('-- Failure to Converge --')
  211.       disp('Probable cause is machine rounding error.')
  212.       if niter > 3
  213. disp('The number of iterations exceeds 3 but the design may be correct.')
  214. disp('The design may be verified by looking at the frequency response.')
  215.       end
  216.       break;
  217.    end
  218.    devl = dev;
  219.    jchnge = 0;
  220.    k1 = iext(1);
  221.    knz = iext(nz);
  222.    klow = 0;
  223.    nut = -nu;
  224.    j = 1;
  225.    flag34 = 1;
  226.    while j < nzz
  227.       kup = iext(j+1);
  228.       l = iext(j) + 1;
  229.       nut = -nut;
  230.       if j == 2
  231.          y1 = comp;
  232.       end
  233.       comp = dev;
  234.       flag = 1;
  235.       if l < kup
  236.     % gee
  237.     c = ad./(cos(2*pi*grid(l))-x);  
  238.     err = (c*y'/sum(c) - des(l))*wt(l);
  239.     dtemp = nut*err - comp;
  240.     if dtemp > 0
  241.         comp = nut*err;
  242.         l = l + 1;
  243.             while l < kup
  244.             % gee
  245.            c = ad./(cos(2*pi*grid(l))-x);  
  246.                err = (c*y'/sum(c) - des(l))*wt(l);
  247.                dtemp = nut*err - comp;
  248.                if dtemp > 0
  249.                   comp = nut*err;
  250.                   l = l + 1;
  251.                else
  252.                   break;
  253.                end
  254.             end    
  255.         iext(j) = l - 1;
  256.         j = j + 1;
  257.         klow = l - 1;
  258.         jchnge = jchnge + 1;
  259.         flag = 0;
  260.     end
  261.       end
  262.       if flag
  263.          l = l - 2;
  264.          while l > klow
  265.         % gee
  266.         c = ad./(cos(2*pi*grid(l))-x);  
  267.             err = (c*y'/sum(c) - des(l))*wt(l);
  268.             dtemp = nut*err - comp;
  269.             if dtemp > 0 | jchnge > 0
  270.                break;
  271.             end
  272.             l = l - 1;
  273.          end
  274.          if l <= klow
  275.             l = iext(j) + 1;
  276.             if jchnge > 0
  277.                iext(j) = l - 1;
  278.                j = j + 1;
  279.                klow = l - 1;
  280.                jchnge = jchnge + 1;
  281.             else
  282.                l = l + 1;
  283.                while l < kup
  284.            % gee
  285.            c = ad./(cos(2*pi*grid(l))-x);  
  286.                err = (c*y'/sum(c) - des(l))*wt(l);
  287.                   dtemp = nut*err - comp;
  288.               if dtemp > 0
  289.                      break;
  290.                   end
  291.                   l = l + 1;
  292.                end
  293.                if l < kup & dtemp > 0
  294.                   comp = nut*err;
  295.                   l = l + 1;
  296.                   while l < kup
  297.               % gee
  298.               c = ad./(cos(2*pi*grid(l))-x);  
  299.                   err = (c*y'/sum(c) - des(l))*wt(l);
  300.                      dtemp = nut*err - comp;
  301.                      if dtemp > 0
  302.                         comp = nut*err;
  303.                         l = l + 1;
  304.                      else
  305.                         break;
  306.                      end
  307.                   end    
  308.                   iext(j) = l - 1;
  309.               j = j + 1;    
  310.                   klow = l - 1;
  311.                   jchnge = jchnge + 1;
  312.                else
  313.                   klow = iext(j);
  314.                   j = j + 1;
  315.                end
  316.             end
  317.          elseif dtemp > 0
  318.             comp = nut*err;
  319.             l = l - 1;
  320.             while l > klow
  321.            % gee
  322.            c = ad./(cos(2*pi*grid(l))-x);  
  323.                err = (c*y'/sum(c) - des(l))*wt(l);
  324.                dtemp = nut*err - comp;
  325.                if dtemp > 0
  326.                   comp = nut*err;
  327.                   l = l - 1;
  328.                else
  329.                   break;
  330.                end
  331.             end
  332.             klow = iext(j);
  333.             iext(j) = l + 1;
  334.             j = j + 1;
  335.             jchnge = jchnge + 1;
  336.          else
  337.             klow = iext(j);
  338.             j = j + 1;
  339.          end
  340.       end
  341.    end
  342.    while j == nzz
  343.       ynz = comp;
  344.       k1 = min([k1 iext(1)]);
  345.       knz = max([knz iext(nz)]);
  346.       nut1 = nut;
  347.       nut = -nu;
  348.       l = 0;
  349.       kup = k1;
  350.       comp = ynz*1.00001;
  351.       luck = 1;
  352.       flag = 1;
  353.       l = l + 1;
  354.       while l < kup
  355.      % gee
  356.      c = ad./(cos(2*pi*grid(l))-x);  
  357.          err = (c*y'/sum(c) - des(l))*wt(l);
  358.          dtemp = err*nut - comp;
  359.          if dtemp > 0
  360.             comp = nut*err;
  361.             j = nzz;
  362.             l = l + 1;
  363.             while l < kup
  364.            % gee
  365.            c = ad./(cos(2*pi*grid(l))-x);  
  366.                err = (c*y'/sum(c) - des(l))*wt(l);
  367.                dtemp = nut*err - comp;
  368.                if dtemp > 0
  369.                   comp = nut*err;
  370.                   l = l + 1;
  371.                else
  372.                   break;
  373.                end
  374.             end    
  375.             iext(j) = l - 1;
  376.             j = j + 1;
  377.             klow = l - 1;
  378.             jchnge = jchnge + 1;
  379.             flag = 0;
  380.             break;
  381.          end
  382.          l = l + 1;
  383.       end
  384.       if flag
  385.          luck = 6;
  386.          l = ngrid + 1;
  387.          klow = knz;
  388.          nut = -nut1;
  389.          comp = y1*1.00001;
  390.          l = l - 1;
  391.          while l > klow
  392.         % gee
  393.         c = ad./(cos(2*pi*grid(l))-x);  
  394.             err = (c*y'/sum(c) - des(l))*wt(l);
  395.             dtemp = err*nut - comp;
  396.             if dtemp > 0
  397.                j = nzz;
  398.                comp = nut*err;
  399.                luck = luck + 10;
  400.                l = l - 1;
  401.                while l > klow
  402.            % gee
  403.            c = ad./(cos(2*pi*grid(l))-x);  
  404.                err = (c*y'/sum(c) - des(l))*wt(l);
  405.                   dtemp = nut*err - comp;
  406.                   if dtemp > 0
  407.                      comp = nut*err;
  408.                      l = l - 1;
  409.                   else
  410.                      break;
  411.                   end
  412.                end
  413.                klow = iext(j);
  414.                iext(j) = l + 1;
  415.                j = j + 1;
  416.                jchnge = jchnge + 1;
  417.            flag = 0;
  418.                break;
  419.             end
  420.             l = l - 1;
  421.          end
  422.          if flag
  423.             flag34 = 0;
  424.             if luck ~= 6
  425.                iext = [k1 iext(2:nz-nfcns)' iext(nz-nfcns:nz-1)']';
  426.                jchnge = jchnge + 1;
  427.             end
  428.             break;
  429.          end
  430.       end
  431.    end
  432.    if flag34 & j > nzz 
  433.       if luck > 9
  434.          iext = [iext(2:nfcns+1)' iext(nfcns+1:nz-1)' iext(nzz) iext(nzz)]';
  435.          jchnge = jchnge + 1;
  436.       else
  437.          y1 = max([y1 comp]);
  438.          k1 = iext(nzz);
  439.          l = ngrid + 1;
  440.          klow = knz;
  441.          nut = -nut1;
  442.          comp = y1*1.00001;
  443.          l = l - 1;
  444.          while l > klow
  445.         % gee
  446.         c = ad./(cos(2*pi*grid(l))-x);  
  447.             err = (c*y'/sum(c) - des(l))*wt(l);
  448.             dtemp = err*nut - comp;
  449.             if dtemp > 0
  450.                j = nzz;
  451.                comp = nut*err;
  452.                luck = luck + 10;
  453.                l = l - 1;
  454.                while l > klow
  455.            % gee
  456.            c = ad./(cos(2*pi*grid(l))-x);  
  457.                err = (c*y'/sum(c) - des(l))*wt(l);
  458.                   dtemp = nut*err - comp;
  459.                   if dtemp > 0
  460.                      comp = nut*err;
  461.                      l = l - 1;
  462.                   else
  463.                      break;
  464.                   end
  465.                end
  466.                klow = iext(j);
  467.                iext(j) = l + 1;
  468.                j = j + 1;
  469.                jchnge = jchnge + 1;
  470.                iext = [iext(2:nfcns+1)' iext(nfcns+1:nz-1)' iext(nzz) iext(nzz)]';
  471.                break;
  472.             end
  473.             l = l - 1;
  474.          end
  475.          if luck ~= 6
  476.             iext = [k1 iext(2:nz-nfcns)' iext(nz-nfcns:nz-1)']';
  477.             jchnge = jchnge + 1;
  478.          end
  479.       end  
  480.    end
  481. end
  482.  
  483. % Inverse Fourier transformation
  484. nm1 = nfcns - 1;
  485. fsh = 1.0e-6;
  486. gtemp = grid(1);
  487. x(nzz) = -2;
  488. cn = 2*nfcns - 1;
  489. delf = 1/cn;
  490. l = 1;
  491. kkk = 0;
  492. if (edge(1) == 0 & edge(jb) == .5) | nfcns <= 3
  493.    kkk = 1;
  494. end
  495. if kkk ~= 1
  496.    dtemp = cos(2*pi*grid(1));
  497.    dnum = cos(2*pi*grid(ngrid));
  498.    aa = 2/(dtemp - dnum);
  499.    bb = -(dtemp+dnum)/(dtemp - dnum);
  500. end
  501. for j = 1:nfcns
  502.    ft = (j-1)*delf;
  503.    xt = cos(2*pi*ft);
  504.    if kkk ~= 1
  505.       xt = (xt-bb)/aa;
  506.       ft = acos(xt)/(2*pi);
  507.    end
  508.    xe = x(l);
  509.    while xt <= xe & xe-xt >= fsh
  510.       l = l + 1;
  511.       xe = x(l);
  512.    end
  513.    if abs(xt-xe) < fsh
  514.       a(j) = y(l);
  515.    else
  516.       grid(1) = ft;
  517.       % gee
  518.       c = ad./(cos(2*pi*ft)-x(1:nz));  
  519.       a(j) = c*y'/sum(c);
  520.    end
  521.    l = max([1, l-1]);
  522. end
  523. grid(1) = gtemp;
  524. dden = 2*pi/cn;
  525. for j = 1:nfcns
  526.    dnum = (j-1)*dden;
  527.    if nm1 < 1
  528.       alpha(j) = a(1);
  529.    else
  530.       alpha(j) = a(1) + 2*cos(dnum*(1:nm1))*a(2:nfcns)';
  531.    end
  532. end
  533. alpha = [alpha(1) 2*alpha(2:nfcns)]'/cn;
  534. if kkk ~= 1
  535.    p(1) = 2*alpha(nfcns)*bb + alpha(nm1);
  536.    p(2) = 2*aa*alpha(nfcns);
  537.    q(1) = alpha(nfcns-2) - alpha(nfcns);
  538.    for j = 2:nm1
  539.       if j == nm1
  540.          aa = aa/2;
  541.          bb = bb/2;
  542.       end
  543.       p(j+1) = 0;
  544.       sel = 1:j;
  545.       a(sel) = p(sel);
  546.       p(sel) = 2*bb*a(sel);
  547.       p(2) = p(2) + 2*a(1)*aa;
  548.       jm1 = j - 1;
  549.       sel = 1:jm1;
  550.       p(sel) = p(sel) + q(sel) + aa*a(sel+1);
  551.       jp1 = j + 1;
  552.       sel = 3:jp1;
  553.       p(sel) = p(sel) + aa*a(sel-1);
  554.       if j ~= nm1
  555.          sel = 1:j;
  556.          q(sel) = -a(sel);
  557.          q(1) = q(1) + alpha(nfcns - 1 - j);
  558.       end
  559.    end
  560.    alpha(1:nfcns) = p(1:nfcns);
  561. end
  562. if nfcns <= 3
  563.    alpha(nfcns + 1) = 0;
  564.    alpha(nfcns + 2) = 0;
  565. end
  566.  
  567. alpha=alpha';
  568.  
  569. % now that's done!
  570.  
  571. if neg <= 0
  572.    if nodd ~= 0
  573.       h = [.5*alpha(nz-1:-1:nz-nm1) alpha(1)];
  574.    else
  575.       h = .25*[alpha(nfcns) alpha(nz-2:-1:nz-nm1)+alpha(nfcns:-1:nfcns-nm1+2) ...
  576.            2*alpha(1)+alpha(2)];
  577.    end
  578. elseif nodd ~= 0
  579.    h = .25*[alpha(nfcns) alpha(nm1)];
  580.    h(nfcns:fix(nfilt/2)+nodd) = .25*[alpha(nz-3:-1:nz-nm1)-alpha(nfcns:-1:nfcns-nm1+3) 2*alpha(1)-alpha(3) 0];
  581. else
  582.    h = .25*[alpha(nfcns) alpha(nz-2:-1:nz-nm1)-alpha(nfcns:-1:nfcns-nm1+2) ...
  583.         2*alpha(1)-alpha(2)];
  584. end
  585. lenh=max(size(h));
  586. h = [sign(.5-neg)*h(1:lenh-nodd) h(lenh:-1:1)];
  587.  
  588.