function [h,h2,rs] = chebbp(N,L,wp,us,ls)
% h = chebbp(N,L,wp,us,ls,g)
% A program for the design of symmetric bandpass FIR filters with 
% flat monotonically decreasing passbands (on either side of wp)
% and equiripple stopbands.
%
% output
%  h  : filter
% input
%  N  : length of total filter
%  L  : degree of flatness
%  wp : passband frequency of flatness
%  us : upper bound in stop band
%  ls : lower boudn in stop band
%
% Author: Ivan W. Selesnick, Rice University
%
% % EXAMPLE
%    N  =  25;
%    L  =  8;
%    wp  = .4*pi;
%    us =  0.01;
%    ls = -us;
%    [h,h2,rs] = chebbp(N,L,wp,us,ls);
% or
%    N = 31; L = 16; 
%    chebbp(N,L,wp,us,ls);

% Reference:
% "Exchange Algorithms for the Design of Linear Phase FIR Filters 
% and Differentiators Having Flat Monotonic Passbands and Equiripple 
% Stopbands" by I. W. Selesnick and C. S. Burrus, 
% IEEE Trans. on Cicuits and Systems II, 43(9):671-675, Sept 1996



if (rem(N,2) == 0) | (rem(L,4) ~= 0)
   disp('N must be odd and L must be divisible by 4')
   return
else
   g = 2^ceil(log2(4*N));		% number of grid points
   SN = 1e-9;                           % SN : SMALL NUMBER
   q  = (N-L+1)/2;
   w  = [0:g]'*pi/g;
   ws1 = wp*0.8;
   a = 5; b = 1;
   ws2 = (a*wp+b*pi)/(a+b);

   d = ws1/(pi-ws2);    	% q1 : number of ref. set freq. in 1st stopband
   q1 = round(q/(1+1/d));   	% q2 : number of ref. set freq. in 2nd stopband
   if q1 == 0
      q1 = 1;
   elseif q1 == q
      q1 = q - 1;
   end
   q2 = q - q1;

   if q1 == 1;
        rs1 = ws1;
   else
        rs1 = [0:q1-1]'*(ws1/(q1-1));
   end
   if q2 == 1
        rs2 = ws2;
   else
        rs2 = [0:q2-1]'*(pi-ws2)/(q2-1)+ws2;
   end
   rs = [rs1; rs2];

   Y1 = [ls*(1-(-1).^(q1:-1:1))/2 + us*((-1).^(q1:-1:1)+1)/2]';
   Y2 = [ls*(1-(-1).^(1:q2))/2 + us*((-1).^(1:q2)+1)/2]';
   Y = [Y1; Y2];

   n  = 0:q-1;
   Z   = zeros(2*(g-q)+1,1);
   % A1  = (-1)^(L/2) * (sin(w/2-wp/2).*sin(w/2+wp/2)).^(L/2);
   % A1r = (-1)^(L/2) * (sin(rs/2-wp/2).*sin(rs/2+wp/2)).^(L/2);
   A1  = (-1)^(L/2) * ((cos(wp)-cos(w))/2).^(L/2);
   A1r = (-1)^(L/2) * ((cos(wp)-cos(rs))/2).^(L/2);
   it = 0;
while 1 & (it < 20)
	if length(rs) ~= length(n)
		keyboard
	end
   a2 = cos(rs*n)\[(Y-1)./A1r];
   A2 = real(fft([a2(1);a2(2:q)/2;Z;a2(q:-1:2)/2])); A2 = A2(1:g+1);
   A  = 1 + A1.*A2;
   figure(1), plot(w/pi,A),
        hold on, plot(rs/pi,Y,'o'), hold off, % pause(.1)
   figure(2), plot(w/pi,20*log10(abs(A))),
        hold on, plot(rs/pi,20*log10(abs(Y)),'o'), hold off, % pause(.1)
	pause(.5)
   ri = sort([localmax(A); localmax(-A)]);
   lri = length(ri);
   % ri(1:length(ri)-q) = [];
        if lri ~= q+1
		if abs(A(ri(lri))-A(ri(lri-1))) < abs(A(ri(1))-A(ri(2)))
			ri(lri) = [];
		else
			ri(1) = [];
		end
        end
   rs = (ri-1)*pi/g;
   [temp, k] = min(abs(rs - wp)); rs(k) = [];
   q1 = sum(rs < wp);
   q2 = sum(rs > wp);

   Y1 = [ls*(1-(-1).^(q1:-1:1))/2 + us*((-1).^(q1:-1:1)+1)/2]';
   Y2 = [ls*(1-(-1).^(1:q2))/2 + us*((-1).^(1:q2)+1)/2]';
   Y = [Y1; Y2];

   % rs = refine2(a2,L/2,rs);
   % A1r = (-1)^(L/2) * (sin(rs/2-wp/2).*sin(rs/2+wp/2)).^(L/2);
   A1r = (-1)^(L/2) * ((cos(wp)-cos(rs))/2).^(L/2);
   Ar = 1 + (cos(rs*n)*a2) .* A1r;
   Err = max([max(Ar)-us, ls-min(Ar)]);
   fprintf(1,'    Err = %18.15f\n',Err);
   if Err < SN, fprintf(1,'\n    I have converged \n'), break, end
   it = it + 1;
end

h2 = [a2(q:-1:2)/2; a2(1); a2(2:q)/2];
h = h2;
for k = 1:L/2
   h = conv(h,[1 -2*cos(wp) 1]')/4;
end
h((N+1)/2) = h((N+1)/2) + 1;

end

