/* * ifgcore.c * Filtered Gaussian source with interpolation (core C-code). * Shared by MATLAB C-MEX function, SIMULINK C-MEX S-Function, and TLC. * * Copyright 1996-2005 The MathWorks, Inc. * $Revision: 1.1.6.2 $ $Date: 2004/12/18 07:33:36 $ */ /* The interpfilter is currently hard-wired to use a filtgaussian source. */ #include #include "fgcore.h" #include "ifgcore.h" void polyphasefilter( cArray y, /* Interpolating filter output */ int_T yStartIdx, /* Index of first sample in output */ int_T Nout, /* Number of samples to output per channel */ cArray x, /* Filtered Gaussian source output */ int_T *numSourceSamples, /* Number of source samples generated */ int_T NS, /* Number of samples alloc. to y (per channel) */ int_T NC, /* Number of channels */ int_T ppInterpFactor, int_T ppSubfilterLength, real_T *ppFilterBank, cArray ppFilterInputState, int_T *ppFilterPhase, cArray ppLastFilterOutputs, real_T *fgImpulseResponse, /* Filter impulse response */ int_T fgLengthIR, /* Length of impulse response */ cArray fgState, /* State matrix */ real_T *fgWGNState, /* WGN generator state */ cArray fgLastOutputs, /* Last two outputs */ cArray fgWGN, /* WGN (allocated storage) */ real64_T *fgWGN2 /* WGN (temporary allocated storage) */ ) { int_T m, n, i, /* Loop indices */ N, startPhase; int_T R = ppInterpFactor, M = ppSubfilterLength; real_T *g = ppFilterBank; cArray u = ppFilterInputState; /* Not transposed (unlike M-code) */ /* Return if no output samples requested; no source samples required. */ if (Nout==0) { *numSourceSamples = 0; return; } /* Increment polyphase filter phase by 1. The additional -1 and +1 are because phase is 1-based, but % is 0-based. */ startPhase = (*ppFilterPhase+1 - 1)%R + 1; if (R==1) { /* No polyphase interpolation. */ /* Number of source samples equals number of output samples */ N = Nout; /* Generate source samples. */ corefiltgaussian( x, N, fgImpulseResponse, fgState, fgWGNState, fgLastOutputs, fgWGN, fgWGN2, Nout, NC, fgLengthIR ); /* Output samples are exactly equal to source samples. */ for (m=0; mNout)? Nout : m0; /* Flush polyphase filter if needed. */ if (m0>0) { /* Equivalent M-code: y(:, 1:m0) = (g((1:m0)+startPhase-1, :)*u).'; */ int_T k, iy, ig, iu; for (m=0; m0) { /* Generate source samples. */ corefiltgaussian( x, N, fgImpulseResponse, fgState, fgWGNState, fgLastOutputs, fgWGN, fgWGN2, NS, NC, fgLengthIR ); /* Compute outputs and update state matrix. */ for (m=0; m=0; i1--) { int_T iu1 = NC*i1 + m; int_T iu2 = iu1 + NC; Re(u, iu2) = Re(u, iu1); Im(u, iu2) = Im(u, iu1); } /* Set first element of filter input state (for each channel). */ { int_T iu = m; int_T ix = NS*m + n; Re(u, iu) = Re(x, ix); Im(u, iu) = Im(x, ix); } /* Compute outputs and update state matrix. Note that these are zero-based indices, unlike M-code. */ { int_T m1 = m0 + n*R, /* Start index for output */ m2 = m1 + R - 1, /* End index for output */ nn, ig0; /* Loop index */ /* Modify indices if needed. */ if (n==N-1 && m2>Nout-1) { m2 = Nout-1; } /* Equivalent M-code: y(:,m1:m2) = (g(1:Lm,:)*u).'; */ ig0 = 0; for (nn=m1; nn<=m2; nn++) { int_T k, iy; iy = NS*m + nn + yStartIdx; Re(y, iy) = 0.0; Im(y, iy) = 0.0; for (k=0; k0) */ } /* if (R==1) */ /* Update polyphase filter phase. The additional -1 and +1 are because phase is 1-based, but % is 0-based. */ *ppFilterPhase = (startPhase+(Nout-1) - 1)%R + 1; /* Store last *two* outputs for each path. Needed for linear interpolation. */ if (Nout==1) { /* Equivalent M-code: ppLastFilterOutputs = [ppLastFilterOutputs(:, end) y]; */ for (m=0; m numSamples = 1 (no interpolation) startIdx==1 and Nout<=KI+1 OR startIdx==2 and Nout<=KI ==> numSamples = 2 (2-pt interpolation) */ numSamples = (int_T) ceil((real_T)(endIdx-1) / (real_T)KI) + 1; /* Determine *previous* polyphase filter outputs. If startIdx of linear interpolation is 1 or 2, use only last filter output. Otherwise, use last *two* outputs. */ numPrevOutputs = (startIdx>2)? 2 : 1; for (m=0; m