www.gusucode.com > signal 工具箱matlab源码程序 > signal/firpmord.m

    function [N, ff, aa, wts] = firpmord(fcuts, mags, devs, fsamp, cellflag) %#ok
%FIRPMORD  Parks-McClellan optimal equiripple FIR order estimator.
%   [N,Fo,Ao,W] = FIRPMORD(F,A,DEV,Fs) finds the approximate order N, 
%   normalized frequency band edges Fo, frequency band magnitudes Ao and 
%   weights W to be used by the FIRPM function as follows:
%       B = FIRPM(N,Fo,Ao,W)
%   The resulting filter will approximately meet the specifications given
%   by the input parameters F, A, and DEV.  F is a vector of cutoff
%   frequencies in Hz, in ascending order between 0 and half the sampling
%   frequency Fs. If you do not specify Fs, it defaults to 2.  A is a
%   vector specifying the desired function's amplitude on the bands defined
%   by F. The length of F is twice the length of A, minus 2 (it must
%   therefore be even).  The first frequency band always starts at zero,
%   and the last always ends at Fs/2.  It is not necessary to add these
%   elements to the  F vector.  DEV is a vector of maximum deviations or
%   ripples (in linear units) allowable for each band.  DEV must have the
%   same length as A.
%
%   C = FIRPMORD(F,A,DEV,FS,'cell') is a cell-array whose elements are the 
%   parameters to FIRPM.
%
% %  EXAMPLE
% %    Design a lowpass filter with a passband-edge frequency of 1500Hz, a 
% %    stopband-edge of 2000Hz, passband ripple of 0.01, stopband ripple 
% %    of 0.1, and a sampling frequency of 8000Hz:
%
%         [n,fo,mo,w] = firpmord( [1500 2000], [1 0], [0.01 0.1], 8000 );
%         b = firpm(n,fo,mo,w);
%
% %    This is equivalent to
%         c = firpmord( [1500 2000], [1 0], [0.01 0.1], 8000, 'cell');
%         b = firpm(c{:});
%
% % CAUTION 1: The order N is often underestimated. If the filter does not
% % meet the original specifications, a higher order such as N+1 or N+2 will.
% % CAUTION 2: Results are inaccurate if cutoff frequencies are near zero
% % frequency or the Nyquist frequency.
%
%   See also FIRPM, KAISERORD, DESIGNFILT.

%   Author(s): J. H. McClellan, 10-28-91
%   Copyright 1988-2013 The MathWorks, Inc.
%     

%   References:
%     [1] Rabiner & Gold, Theory and Applications of DSP, pp. 156-7.     

narginchk(3,5)
if nargin == 3,
    fsamp = 2;
end
% Cast to enforce precision rules
fcuts = signal.internal.sigcasttofloat(fcuts,'double','firpmord','F',...
  'allownumeric');
mags = signal.internal.sigcasttofloat(mags,'double','firpmord','A',...
  'allownumeric');
devs = signal.internal.sigcasttofloat(devs,'double','firpmord','DEV',...
  'allownumeric');
fsamp = signal.internal.sigcasttofloat(fsamp,'double','firpmord','Fs',...
  'allownumeric');

fcuts = fcuts/fsamp;       %  NORMALIZE to sampling frequency
if any(fcuts > 1/2),
    error(message('signal:firpmord:InvalidRange'));
end
if any(fcuts < 0),
    error(message('signal:firpmord:MustBePositive'));
end

% Turn vectors into column vectors
fcuts = fcuts(:);
mags = mags(:);
devs = devs(:);

mf = size(fcuts, 1);
mm = size(mags, 1);
nbands = mm;

if length(mags) ~= length(devs)
    error(message('signal:firpmord:MismatchedVectorLength', 'A', 'DEV'))
end

if mf ~= 2*(nbands-1)
    error(message('signal:firpmord:InvalidLength', 'F', '2*length(A)-2'))
end

zz = mags==0;             % find stopbands
devs = devs./(zz+mags);   % divide delta by mag to get relative deviation

% Determine the smallest width transition zone
% Separate the passband and stopband edges
%
f1 = fcuts(1:2:(mf-1));
f2 = fcuts(2:2:mf);
[df,n] = min(f2-f1); %#ok

%=== LOWPASS case: Use formula (ref: Herrmann, Rabiner, Chan)
%
if( nbands==2 )
     L = remlpord( f1(n), f2(n), devs(1), devs(2));

%=== BANDPASS case:
%    - try different lowpasses and take the WORST one that
%        goes through the BP specs; try both transition widths
%    - will also do the bandreject case
%    - does the multi-band case, one bandpass at a time.
%    
else
  L = 0;
  for i=2:nbands-1,
    L1 = remlpord( f1(i-1), f2(i-1), devs(i),   devs(i-1) );
    L2 = remlpord( f1(i),   f2(i),   devs(i),   devs(i+1) );
    L = max( [L; L1; L2] );
  end
end

N = ceil( L ) - 1;   % need order, not length, for firpm

%=== Make the MATLAB compatible specs for firpm
%
ff = [0;2*fcuts;1];
am(1:2:2*nbands-1) = mags;	
aa = [am';0] + [0;am'];
wts = ones(size(devs))*max(devs)./devs;

% If gain is not zero at nyquist, the order must be even.
% If the order is odd, we bump up the order by one.
if (aa(end) ~= 0) && rem(N,2),
    N = N+1;
end

if nargout == 1 && nargin == 5
   N = {N, ff, aa, wts};
end

%----------------------------------------------------------------------------
function L = remlpord(freq1, freq2, delta1, delta2 )
%REMLPORD FIR lowpass filter Length estimator
%
%   L = remlpord(freq1, freq2, dev1, dev2)
%
%   input:
%     freq1: passband cutoff freq (NORMALIZED)
%     freq2: stopband cutoff freq (NORMALIZED)
%     dev1:  passband ripple (DESIRED)
%     dev2:  stopband attenuation (not in dB)
%
%   output:
%     L = filter Length (# of samples)
%         NOT the order N, which is N = L-1
%
%   NOTE: Will also work for highpass filters (i.e., f1 > f2)
%         Will not work well if transition zone is near f = 0, or
%         near f = fs/2

% 	Author(s): J. H. McClellan, 10-28-91
%       Was Revision: 1.4, Date: 1994/01/25 17:59:46
	
%   References:
%     [1] Rabiner & Gold, Theory and Appications of DSP, pp. 156-7.     

AA = [-4.278e-01  -4.761e-01  0;
      -5.941e-01   7.114e-02  0;
      -2.660e-03   5.309e-03  0 ];
d1 = log10(delta1);
d2 = log10(delta2);
D = [1 d1 d1*d1] * AA * [1; d2; d2*d2];
%
bb = [11.01217; 0.51244];
fK =  [1.0  (d1-d2)] * bb;
%
df = abs(freq2 - freq1);
%
L = D/df - fK*df + 1;

% [EOF] - FIRPMORD.M