/tags/R2008-04-29/main/signal/inst/resample.m

# · Objective C · 194 lines · 161 code · 33 blank · 0 comment · 17 complexity · 252fd8995b9872c38978322567e674be MD5 · raw file

  1. function [y, h] = resample( x, p, q, h )
  2. ## -*- texinfo -*-
  3. ## @deftypefn {Function File} {[@var{y} @var{h}]=} resample(@var{x},@var{p},@var{q})
  4. ## @deftypefnx {Function File} {@var{y} =} resample(@var{x},@var{p},@var{q},@var{h})
  5. ## Change the sample rate of @var{x} by a factor of @var{p}/@var{q}. This is
  6. ## performed using a polyphase algorithm. The impulse response @var{h} of the antialiasing
  7. ## filter is either specified or either designed with a Kaiser-windowed sinecard.
  8. ## @end deftypefn
  9. ## Ref [1] J. G. Proakis and D. G. Manolakis,
  10. ## Digital Signal Processing: Principles, Algorithms, and Applications,
  11. ## 4th ed., Prentice Hall, 2007. Chap. 6
  12. ##
  13. ## Ref [2] A. V. Oppenheim, R. W. Schafer and J. R. Buck,
  14. ## Discrete-time signal processing, Signal processing series,
  15. ## Prentice-Hall, 1999
  16. ## Copyright (C) 2008 Eric Chassande-Mottin, CNRS (France)
  17. ## This program is free software; you can redistribute it and/or modify
  18. ## it under the terms of the GNU General Public License as published by
  19. ## the Free Software Foundation; either version 3 of the License, or
  20. ## (at your option) any later version.
  21. ##
  22. ## This program is distributed in the hope that it will be useful,
  23. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  24. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25. ## GNU General Public License for more details.
  26. ##
  27. ## You should have received a copy of the GNU General Public License
  28. ## along with this program; if not, see .
  29. if nargchk(3,4,nargin)
  30. usage("resample.m: [y, h] = resample( x, p, q[, h] )");
  31. end;
  32. if any([p q]<=0)|any([p q]~=floor([p q])),
  33. error("resample.m: p and q must be positive integers");
  34. endif
  35. ## simplify decimation and interpolation factors
  36. great_common_divisor=gcd(p,q);
  37. if (great_common_divisor>1)
  38. p=p/great_common_divisor;
  39. q=q/great_common_divisor;
  40. endif
  41. ## filter design if required
  42. if (nargin < 4)
  43. ## properties of the antialiasing filter
  44. log10_rejection = -3.0;
  45. stopband_cutoff_f = 1.0/(2.0 * max(p,q));
  46. roll_off_width = stopband_cutoff_f / 10.0;
  47. ## determine filter length
  48. ## use empirical formula from [2] Chap 7, Eq. (7.63) p 476
  49. rejection_dB = -20.0*log10_rejection;
  50. L = ceil((rejection_dB-8.0) / (28.714 * roll_off_width));
  51. ## ideal sinc filter
  52. t=(-L:L)';
  53. ideal_filter=2*p*stopband_cutoff_f*sinc(2*stopband_cutoff_f*t);
  54. ## determine parameter of Kaiser window
  55. ## use empirical formula from [2] Chap 7, Eq. (7.62) p 474
  56. if ((rejection_dB>=21)&(rejection_dB<=50))
  57. beta = 0.5842 * (rejection_dB-21.0)^0.4 + 0.07886 * (rejection_dB-21.0);
  58. elseif (rejection_dB>50)
  59. beta = 0.1102 * (rejection_dB-8.7);
  60. else
  61. beta = 0.0;
  62. endif
  63. ## apodize ideal filter response
  64. h=kaiser(2*L+1,beta).*ideal_filter;
  65. endif
  66. ## check if input is a row vector
  67. isrowvector=false;
  68. if ((rows(x)==1)&(columns(x)>1))
  69. x=x(:);
  70. isrowvector=true;
  71. endif
  72. ## check if filter is a vector
  73. if ~isvector(h)
  74. error("resample.m: the filter h should be a vector");
  75. endif
  76. Lx = length(x);
  77. Lh = length(h);
  78. L = ( Lh - 1 )/2.0;
  79. Ly = ceil(Lx*p/q);
  80. ## pre and postpad filter response
  81. nz_pre = floor(q-mod(L,q));
  82. hpad = prepad(h,Lh+nz_pre);
  83. offset = floor((L+nz_pre)/q);
  84. nz_post = 0;
  85. while ceil( ( (Lx-1)*p + nz_pre + Lh + nz_post )/q ) - offset < Ly
  86. nz_post++;
  87. endwhile
  88. hpad = postpad(hpad,Lh + nz_pre + nz_post);
  89. ## filtering
  90. xfilt = upfirdn(x,hpad,p,q);
  91. y = xfilt(offset+1:offset+Ly,:);
  92. if isrowvector,
  93. y=y.';
  94. endif
  95. endfunction
  96. %!test
  97. %! N=512;
  98. %! p=3; q=5;
  99. %! r=p/q;
  100. %! NN=ceil(r*N);
  101. %! t=0:N-1;
  102. %! tt=0:NN-1;
  103. %! err=zeros(N/2,1);
  104. %! for n = 0:N/2-1,
  105. %! phi0=2*pi*rand;
  106. %! f0=n/N;
  107. %! x=sin(2*pi*f0*t' + phi0);
  108. %! [y,h]=resample(x,p,q);
  109. %! xx=sin(2*pi*f0/r*tt' + phi0);
  110. %! t0=ceil((length(h)-1)/2/q);
  111. %! idx=t0+1:NN-t0;
  112. %! err(n+1)=max(abs(y(idx)-xx(idx)));
  113. %! endfor;
  114. %! rolloff=.1;
  115. %! rejection=10^-3;
  116. %! idx_inband=1:ceil((1-rolloff/2)*r*N/2)-1;
  117. %! assert(max(err(idx_inband))<rejection);
  118. %!test
  119. %! N=512;
  120. %! p=3; q=5;
  121. %! r=p/q;
  122. %! NN=ceil(r*N);
  123. %! t=0:N-1;
  124. %! tt=0:NN-1;
  125. %! reject=zeros(N/2,1);
  126. %! for n = 0:N/2-1,
  127. %! phi0=2*pi*rand;
  128. %! f0=n/N;
  129. %! x=sin(2*pi*f0*t' + phi0);
  130. %! [y,h]=resample(x,p,q);
  131. %! xx=sin(2*pi*f0/r*tt' + phi0);
  132. %! t0=ceil((length(h)-1)/2/q);
  133. %! idx=t0+1:NN-t0;
  134. %! reject(n+1)=max(abs(y(idx)));
  135. %! endfor;
  136. %! rolloff=.1;
  137. %! rejection=10^-3;
  138. %! idx_stopband=ceil((1+rolloff/2)*r*N/2)+1:N/2;
  139. %! assert(max(reject(idx_stopband))<=rejection);
  140. %!test
  141. %! N=1024;
  142. %! p=2; q=7;
  143. %! r=p/q;
  144. %! NN=ceil(r*N);
  145. %! t=0:N-1;
  146. %! tt=0:NN-1;
  147. %! err=zeros(N/2,1);
  148. %! for n = 0:N/2-1,
  149. %! phi0=2*pi*rand;
  150. %! f0=n/N;
  151. %! x=sin(2*pi*f0*t' + phi0);
  152. %! [y,h]=resample(x,p,q);
  153. %! xx=sin(2*pi*f0/r*tt' + phi0);
  154. %! t0=ceil((length(h)-1)/2/q);
  155. %! idx=t0+1:NN-t0;
  156. %! err(n+1)=max(abs(y(idx)-xx(idx)));
  157. %! endfor;
  158. %! rolloff=.1;
  159. %! rejection=10^-3;
  160. %! idx_inband=1:ceil((1-rolloff/2)*r*N/2)-1;
  161. %! assert(max(err(idx_inband))<rejection);