function  [y, h] = resample( x, p, q, N, beta )
%RESAMPLE  Change the sampling rate of a signal
%	Y = RESAMPLE(X,P,Q) resamples the sequence in vector X at P/Q times
%	the original sample rate using a polyphase implementation. 
%	The resulting vector is P/Q times the length of X.  P and Q must be 
%	positive integers.
%
%	RESAMPLE applies an anti-aliasing (lowpass) FIR filter to X during the 
%	resampling process.  The filter is designed using FIR1 with a Kaiser 
%	window.
%
%	Y = RESAMPLE(X,P,Q,N) uses N terms on either side of X[n] to perform
%	the resampling.  The length of the FIR filter RESAMPLE uses is 
%	proportional to N; by increasing N you get better accuracy at the 
%	expense of more computation time.  If you don't specify N, RESAMPLE uses
%	N = 10 by default.  If you let N = 0, RESAMPLE uses a zero-order hold.
%
%	Y = RESAMPLE(X,P,Q,N,BETA) uses BETA as the design parameter for the 
%	Kaiser window used to design the filter.  RESAMPLE uses BETA = 5 if
%	you don't include it.
%
%	Y = RESAMPLE(X,P,Q,B) uses B to filter X if B is a vector of filter 
%	coefficients. 
%
%	[Y,B] = RESAMPLE(X,P,Q,...) returns in B the coefficients of the filter
%	applied to X during the resampling process.  
%
%	See also: INTERP, DECIMATE, FIR1, KAISER, INTFILT

%	NOTE-1: uses a polyphase implementation to conserve memory.
%	NOTE-2: digital anti-alias filter is desiged via windowing

%	Author(s): James McClellan, 6-11-93
%	Copyright (c) 1984-94 by The MathWorks, Inc.
%	$Revision: 1.10 $  $Date: 1994/01/25 17:59:47 $

if nargin < 5,  beta = 5;  end   %--- design parameter for Kaiser window LPF
if nargin < 4,   N = 10;   end
if abs(round(p))~=p | p==0, error('P must be a positive integer.'), end
if abs(round(q))~=q | q==0, error('Q must be a positive integer.'), end
[row,col]=size(x);
if (min(row,col)>1) | (row*col<1), error('Input X must be a vector.'), end

[p,q] = rat( p/q, 1e-12 );  %--- reduce to lowest terms 
   % (usually exact, sometimes not; loses at most 1 second every 10^12 seconds)
if (p==1)&(q==1)
    y = x; 
    h = 1;
    return
end
pqmax = max(p,q);
if length(N)>1      % use input filter
   L = length(N);
   h = N;
   zoh = 0;  % zero order hold flag
else                % design filter
   fc = 1/2/pqmax;
   L = 2*N*pqmax + 1;
   if( N>0 )
      h = p*fir1( L-1, 2*fc, kaiser(L,beta) );
      zoh = 0;  % zero order hold flag
   else
      h = ones(p,1);
      L = p;
      zoh = 1;  % zero order hold flag
   end
end

Lhalf = (L-1)/2;
Lx = length(x);
Ly = ceil( Lx*p/q );
y(Ly) = 0;          %<--- creates a row
for r=1:p
   ref = r-1;
   if( ~zoh )
      jkl = (ref-p):-p:-Lhalf;
      center = length(jkl);
      jkl = (Lhalf+1) + [ fliplr(jkl) (ref:p:Lhalf) ];
      yt = conv( h(jkl), x );
      yt(1:center) = [];
   else
      yt = x;      %<--- zero-order hold
   end
   ind = ref:p:(p*q);
   ii = find(rem(ind,q)==0);
   jj = ind(ii(1))/q + 1;
   y(jj:p:Ly) = yt(ii(1):q:Lx);
end

if row>1, y=y(:); end

