PageRenderTime 55ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/cvs_final/octave-forge/main/signal/inst/zp2sos.m

#
MATLAB | 136 lines | 47 code | 17 blank | 72 comment | 11 complexity | f88edd3388026bce82dd786d607f0fd9 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, LGPL-2.1, GPL-3.0, LGPL-3.0
  1. %% Copyright (C) 2005 Julius O. Smith III
  2. %%
  3. %% This program is free software; you can redistribute it and/or modify
  4. %% it under the terms of the GNU General Public License as published by
  5. %% the Free Software Foundation; either version 2 of the License, or
  6. %% (at your option) any later version.
  7. %%
  8. %% This program is distributed in the hope that it will be useful,
  9. %% but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. %% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. %% GNU General Public License for more details.
  12. %%
  13. %% You should have received a copy of the GNU General Public License
  14. %% along with this program; if not, write to the Free Software
  15. %% Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  16. %% -*- texinfo -*-
  17. %% @deftypefn {Function File} {[@var{sos}, @var{g}] =} zp2sos (@var{z}, @var{p})
  18. %% Convert filter poles and zeros to second-order sections.
  19. %%
  20. %% INPUTS:@*
  21. %% @itemize
  22. %% @item
  23. %% @var{z} = column-vector containing the filter zeros@*
  24. %% @item
  25. %% @var{p} = column-vector containing the filter poles@*
  26. %% @item
  27. %% @var{g} = overall filter gain factor
  28. %% @end itemize
  29. %%
  30. %% RETURNED:
  31. %% @itemize
  32. %% @item
  33. %% @var{sos} = matrix of series second-order sections, one per row:@*
  34. %% @var{sos} = [@var{B1}.' @var{A1}.'; ...; @var{BN}.' @var{AN}.'], where@*
  35. %% @code{@var{B1}.'==[b0 b1 b2] and @var{A1}.'==[1 a1 a2]} for
  36. %% section 1, etc.@*
  37. %% b0 must be nonzero for each section.@*
  38. %% See @code{filter()} for documentation of the
  39. %% second-order direct-form filter coefficients @var{B}i and
  40. %% %@var{A}i, i=1:N.
  41. %%
  42. %% @item
  43. %% @var{Bscale} is an overall gain factor that effectively scales
  44. %% any one of the @var{B}i vectors.
  45. %% @end itemize
  46. %%
  47. %% EXAMPLE:
  48. %% @example
  49. %% [z,p,g] = tf2zp([1 0 0 0 0 1],[1 0 0 0 0 .9]);
  50. %% [sos,g] = zp2sos(z,p,g)
  51. %%
  52. %% sos =
  53. %% 1.0000 0.6180 1.0000 1.0000 0.6051 0.9587
  54. %% 1.0000 -1.6180 1.0000 1.0000 -1.5843 0.9587
  55. %% 1.0000 1.0000 0 1.0000 0.9791 0
  56. %%
  57. %% g =
  58. %% 1
  59. %% @end example
  60. %%
  61. %% @seealso{sos2pz sos2tf tf2sos zp2tf tf2zp}
  62. %% @end deftypefn
  63. function [sos,g] = zp2sos(z,p,g)
  64. if nargin<3, g=1; end
  65. if nargin<2, p=[]; end
  66. [zc,zr] = cplxreal(z);
  67. [pc,pr] = cplxreal(p);
  68. % zc,zr,pc,pr
  69. nzc=length(zc);
  70. npc=length(pc);
  71. nzr=length(zr);
  72. npr=length(pr);
  73. % Pair up real zeros:
  74. if nzr
  75. if mod(nzr,2)==1, zr=[zr;0]; nzr=nzr+1; end
  76. nzrsec = nzr/2;
  77. zrms = -zr(1:2:nzr-1)-zr(2:2:nzr);
  78. zrp = zr(1:2:nzr-1).*zr(2:2:nzr);
  79. else
  80. nzrsec = 0;
  81. end
  82. % Pair up real poles:
  83. if npr
  84. if mod(npr,2)==1, pr=[pr;0]; npr=npr+1; end
  85. nprsec = npr/2;
  86. prms = -pr(1:2:npr-1)-pr(2:2:npr);
  87. prp = pr(1:2:npr-1).*pr(2:2:npr);
  88. else
  89. nprsec = 0;
  90. end
  91. nsecs = max(nzc+nzrsec,npc+nprsec);
  92. % Convert complex zeros and poles to real 2nd-order section form:
  93. zcm2r = -2*real(zc);
  94. zca2 = abs(zc).^2;
  95. pcm2r = -2*real(pc);
  96. pca2 = abs(pc).^2;
  97. sos = zeros(nsecs,6);
  98. sos(:,1) = ones(nsecs,1); % all 2nd-order polynomials are monic
  99. sos(:,4) = ones(nsecs,1);
  100. nzrl=nzc+nzrsec; % index of last real zero section
  101. nprl=npc+nprsec; % index of last real pole section
  102. for i=1:nsecs
  103. if i<=nzc % lay down a complex zero pair:
  104. sos(i,2:3) = [zcm2r(i) zca2(i)];
  105. elseif i<=nzrl % lay down a pair of real zeros:
  106. sos(i,2:3) = [zrms(i-nzc) zrp(i-nzc)];
  107. end
  108. if i<=npc % lay down a complex pole pair:
  109. sos(i,5:6) = [pcm2r(i) pca2(i)];
  110. elseif i<=nprl % lay down a pair of real poles:
  111. sos(i,5:6) = [prms(i-npc) prp(i-npc)];
  112. end
  113. end
  114. %!test
  115. %! B=[1 0 0 0 0 1]; A=[1 0 0 0 0 .9];
  116. %! [z,p,g] = tf2zp(B,A);
  117. %! [sos,g] = zp2sos(z,p,g);
  118. %! [Bh,Ah] = sos2tf(sos,g);
  119. %! assert({Bh,Ah},{B,A},100*eps);