annotate aim-mat/modules/bmm/pzfc/PZBankStep2.m @ 0:74dedb26614d

Initial checkin of AIM-MAT version 1.5 (6.4.2011).
author tomwalters
date Fri, 20 May 2011 12:32:31 +0100
parents
children
rev   line source
tomwalters@0 1 function [outputs, state1, state2] = PZBankStep2(inputs, pfreqs, pdamps, ...
tomwalters@0 2 mindamp, maxdamp, xmin, xmax, rmin, rmax, za0, za1, za2, state1, state2, ...
tomwalters@0 3 showconstellation, showtransfuns)
tomwalters@0 4 % function [outputs, state1, state2] = PZBankStep2(inputs, pfreqs, pdamps, ...
tomwalters@0 5 % mindamp, maxdamp, xmin, xmax, rmin, rmax, za0, za1, za2, state1, state2, ...
tomwalters@0 6 % showconstellation, showtransfuns)
tomwalters@0 7 % one time step of Pole-Zero-FilterBank, using row vectors of parameters
tomwalters@0 8 % inputs should contain shifted outputs from last time with new scalar
tomwalters@0 9 % waveform input on the front: inputs = [newin, outputs(1:N-1)];
tomwalters@0 10 % version 2 uses pole x and radius interpolation to adjust dampling
tomwalters@0 11 % the min and max are interpolation reference points, not limits to enforce
tomwalters@0 12 % and it should all work for multiple channels in parallel if the
tomwalters@0 13 % parameter vectors are all appropriately duplicated as well
tomwalters@0 14
tomwalters@0 15 if nargin < 15
tomwalters@0 16 showconstellation = 0; % don't by default; value is used as fig num.
tomwalters@0 17 end
tomwalters@0 18
tomwalters@0 19 if nargin < 16
tomwalters@0 20 showtransfuns = 0; % don't by default; value is used as fig num.
tomwalters@0 21 end
tomwalters@0 22
tomwalters@0 23 [nstages, nchans] = size(pfreqs); % number of filter channels and stereo channels
tomwalters@0 24
tomwalters@0 25 damprate = 1/(maxdamp - mindamp); % to save a bunch of divides
tomwalters@0 26
tomwalters@0 27 % limit to keep the poles reasonably stable:
tomwalters@0 28 interpfactor = (pdamps - mindamp)*damprate;
tomwalters@0 29 % interpfactor = min(1.5, interpfactor); % seems to keep it stable
tomwalters@0 30
tomwalters@0 31 x = xmin + (xmax - xmin).*interpfactor;
tomwalters@0 32 r = rmin + (rmax - rmin).*interpfactor;
tomwalters@0 33
tomwalters@0 34 %optional improvement to constellation adds a bit to r:
tomwalters@0 35 fd = pfreqs.*pdamps;
tomwalters@0 36 r = r + 0.25*fd.*min(0.05, fd); % quadratic for small values, then linear
tomwalters@0 37
tomwalters@0 38 zb1 = -2*x;
tomwalters@0 39 zb2 = r.*r;
tomwalters@0 40
tomwalters@0 41 bExtraDelay = 1; % boolean to control whether to do allow extra sample of filter delay
tomwalters@0 42
tomwalters@0 43 if bExtraDelay
tomwalters@0 44 % canonic poles but with input provided where unity DC gain is assured
tomwalters@0 45 % (mean value of state is always equal to mean value of input)
tomwalters@0 46 newstate = inputs - (state1 - inputs).*zb1 - (state2 - inputs).*zb2;
tomwalters@0 47
tomwalters@0 48 % canonic zeros part as before:
tomwalters@0 49
tomwalters@0 50 outputs = za0 .* newstate + za1 .* state1 + za2 .* state2 ;
tomwalters@0 51 outputs = outputs - 0.0001*outputs.^3; % cubic compression nonlinearity
tomwalters@0 52
tomwalters@0 53 state2 = state1;
tomwalters@0 54 state1 = newstate;
tomwalters@0 55 else
tomwalters@0 56 input = inputs(1,:); % first stage input is top input; ignore the rest
tomwalters@0 57 for stage = 1:nstages
tomwalters@0 58 newstate = input - (state1(stage,:) - input).*zb1(stage) - (state2(stage,:) - input).*zb2(stage);
tomwalters@0 59 % output of stage immediately becomes input for next stage, if needed:
tomwalters@0 60 input = za0(stage) .* newstate + za1(stage) .* state1(stage,:) + za2(stage) .* state2(stage,:) ;
tomwalters@0 61 input = input - 0.0001*input.^3; % cubic compression nonlinearity
tomwalters@0 62 outputs(stage,:) = input;
tomwalters@0 63 state2(stage,:) = state1(stage,:);
tomwalters@0 64 state1(stage,:) = newstate;
tomwalters@0 65 end
tomwalters@0 66 end
tomwalters@0 67
tomwalters@0 68
tomwalters@0 69 if showconstellation
tomwalters@0 70 figure(showconstellation);
tomwalters@0 71 % keyboard
tomwalters@0 72 hold off
tomwalters@0 73 % I have exact x and r, just need y
tomwalters@0 74 py = (r.*r - x.*x).^0.5;
tomwalters@0 75 % let it error out if we get a complex y.
tomwalters@0 76 plot(x,py,'x');
tomwalters@0 77 hold on
tomwalters@0 78 zr = (za2./za0).^0.5;
tomwalters@0 79 zx = -0.5*(za1./za0);
tomwalters@0 80 zy = (zr.*zr - zx.*zx).^0.5;
tomwalters@0 81 % zy(zy<0) = 0;
tomwalters@0 82 % zy = zy.^0.5;
tomwalters@0 83 plot(zx, zy, 'o');
tomwalters@0 84
tomwalters@0 85 drawnow
tomwalters@0 86 end
tomwalters@0 87
tomwalters@0 88 if showtransfuns % 1D indexing does only 1 channel for now
tomwalters@0 89 fbasis = pi*2.^((-129:0)' /12); %% 120 semitones, 10 octaves, leading up to pi rad/samp
tomwalters@0 90 z = exp(i*fbasis);
tomwalters@0 91 z2 = z.*z;
tomwalters@0 92 nch = size(pfreqs,1);
tomwalters@0 93 nf = length(fbasis);
tomwalters@0 94 chanxfns = zeros(nf, nch);
tomwalters@0 95 cascxfns = ones(nf, nch);
tomwalters@0 96 for ch = 1:length(pfreqs)
tomwalters@0 97 chanxfns(:,ch) = abs((1+zb1(ch)+zb2(ch)).*(za0(ch)+za1(ch).*z+za2(ch).*z2)./(1+zb1(ch).*z+zb2(ch).*z2));
tomwalters@0 98 cascxfns(:,ch) = cascxfns(:,max(1,ch-1)) .* chanxfns(:,ch);
tomwalters@0 99 end
tomwalters@0 100
tomwalters@0 101 figure(showtransfuns)
tomwalters@0 102 hold off
tomwalters@0 103 loglog(fbasis, chanxfns);
tomwalters@0 104 axis([min(fbasis), max(fbasis), 0.1, 10]);
tomwalters@0 105
tomwalters@0 106 figure(showtransfuns+1)
tomwalters@0 107 hold off
tomwalters@0 108 loglog(fbasis, cascxfns);
tomwalters@0 109 axis([min(fbasis), max(fbasis), 0.02, 20000]);
tomwalters@0 110 end
tomwalters@0 111
tomwalters@0 112
tomwalters@0 113 return;
tomwalters@0 114