home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2004 March / PCWELT_3_2004.ISO / pcwsoft / flaskmpeg_078_39_src.z.exe / flaskmpeg / Audio / Resampler / Resampler.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-28  |  19.9 KB  |  604 lines

  1. /* 
  2.  *  Resampler.cpp 
  3.  * 
  4.  *  Original code from Julius O. Smith III< jos@ccrma.stanford.edu>
  5.  *
  6.  *    Copyright (C) Alberto Vigata - January 2000
  7.  *
  8.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  9.  *    
  10.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2, or (at your option)
  13.  *  any later version.
  14.  *   
  15.  *  FlasKMPEG is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *   
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with GNU Make; see the file COPYING.  If not, write to
  22.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  23.  *
  24.  */
  25.  
  26. // Resampler.cpp: implementation of the CResampler class.
  27. //
  28. //////////////////////////////////////////////////////////////////////
  29. #include <windows.h>
  30. #include <stdlib.h> 
  31. #include <stdio.h>
  32. #include <math.h>
  33. #include <string.h>
  34.  
  35. #include "Resampler.h"
  36. //////////////////////////////////////////////////////////////////////
  37. // Construction/Destruction
  38. //////////////////////////////////////////////////////////////////////
  39.  
  40. CResampler::CResampler()
  41. {
  42.  
  43. }
  44.  
  45. CResampler::~CResampler()
  46. {
  47.  
  48. }
  49.  
  50. CResampler::CResampler(                       
  51.     double factor,            /* factor = Sndout/Sndin */
  52.     int nChans,                /* number of sound channels (1 or 2) */
  53.     CAsyncBuffer *ABuffer    /* Buffer to read data from */  
  54. )
  55. {
  56. CResampler::factor        =factor;
  57. CResampler::ABuffer        =ABuffer;
  58. CResampler::nChans        =nChans;
  59. }
  60.  
  61. int CResampler::read(char *buffer){
  62.     
  63.     ResampleFast((short *)buffer);
  64.     
  65.     return eosFlag ? ((nChans==1)? Nout*2 : Nout*4) : 0;
  66. }
  67.  
  68.  
  69. int CResampler::Resample(            /* number of output samples returned */
  70.     BOOL interpFilt,        /* TRUE means interpolate filter coeffs */
  71.     int fastMode,        /* 0 = highest quality, slowest speed */
  72.     BOOL largeFilter        /* TRUE means use 65-tap FIR filter */
  73.  
  74. )
  75. {
  76.     UHRWORD LpScl;        /* Unity-gain scale factor */
  77.     UHRWORD Nwing;        /* Filter table size */
  78.     UHRWORD Nmult;        /* Filter length for up-conversions */
  79.     HRWORD *Imp=0;        /* Filter coefficients */
  80.     HRWORD *ImpD=0;        /* ImpD[n] = Imp[n+1]-Imp[n] */
  81.     
  82.    // if (fastMode)
  83.      // return ResampleFast();
  84.  
  85. #ifdef DEBUG
  86.     /* Check for illegal constants */
  87.     if (Np >= 16)
  88.       return err_ret("Error: Np>=16");
  89.     if (Nb+Nhg+NLpScl >= 32)
  90.       return err_ret("Error: Nb+Nhg+NLpScl>=32");
  91.     if (Nh+Nb > 32)
  92.       return err_ret("Error: Nh+Nb>32");
  93. #endif
  94.     
  95.     /* Set defaults */
  96.  
  97. /*    if (filterFile != NULL && *filterFile != '\0') {
  98.     if (readFilter(filterFile, &Imp, &ImpD, &LpScl, &Nmult, &Nwing))
  99.       return err_ret("could not find filter file, "
  100.            "or syntax error in contents of filter file");
  101.     } else*/ if (largeFilter) {
  102.     Nmult = LARGE_FILTER_NMULT;
  103.     Imp = LARGE_FILTER_IMP;    /* Impulse response */
  104.     ImpD = LARGE_FILTER_IMPD;    /* Impulse response deltas */
  105.     LpScl = LARGE_FILTER_SCALE;    /* Unity-gain scale factor */
  106.     Nwing = LARGE_FILTER_NWING;    /* Filter table length */
  107.     } else {
  108.     Nmult = SMALL_FILTER_NMULT;
  109.     Imp = SMALL_FILTER_IMP;    /* Impulse response */
  110.     ImpD = SMALL_FILTER_IMPD;    /* Impulse response deltas */
  111.     LpScl = SMALL_FILTER_SCALE;    /* Unity-gain scale factor */
  112.     Nwing = SMALL_FILTER_NWING;    /* Filter table length */
  113.     }
  114. #if DEBUG
  115.     fprintf(stderr,"Attenuating resampler scale factor by 0.95 "
  116.         "to reduce probability of clipping\n");
  117. #endif
  118.     LpScl *= 0.95;
  119.     return ResampleWithFilter(interpFilt, Imp, ImpD, LpScl, Nmult, Nwing);
  120. }
  121.  
  122. int CResampler::ResampleWithFilter(  /* number of output samples returned */
  123.     BOOL interpFilt,        /* TRUE means interpolate filter coeffs */
  124.     HRWORD Imp[], HRWORD ImpD[],
  125.     UHRWORD LpScl, UHRWORD Nmult, UHRWORD Nwing)
  126. {
  127.     URWORD Time, Time2;        /* Current time/pos in input sample */
  128.     UHRWORD Xp, Ncreep, Xoff, Xread;
  129.     int OBUFFSIZE = (int)(((double)IBUFFSIZE)*factor+2.0);
  130.     HRWORD X1[IBUFFSIZE]; /* I/O buffers */
  131.     HRWORD X2[IBUFFSIZE]; /* I/O buffers */
  132.     HRWORD *Y1=(HRWORD *)malloc(OBUFFSIZE*sizeof(HRWORD));
  133.     HRWORD *Y2=(HRWORD *)malloc(OBUFFSIZE*sizeof(HRWORD));
  134.  
  135.     UHRWORD Nout, Nx;
  136.     int i, Ycount, last;
  137.     
  138.     int **obufs ;//= sndlib_allocate_buffers(nChans, OBUFFSIZE);
  139.     //if (obufs == NULL)
  140.     //return err_ret("Can't allocate output buffers");
  141.  
  142.     /* Account for increased filter gain when using factors less than 1 */
  143.     if (factor < 1)
  144.       LpScl = LpScl*factor + 0.5;
  145.  
  146.     /* Calc reach of LP filter wing & give some creeping room */
  147.     Xoff = ((Nmult+1)/2.0) * MAX(1.0,1.0/factor) + 10;
  148.  
  149.     if (IBUFFSIZE < 2*Xoff)      /* Check input buffer size */
  150.       return err_ret("IBUFFSIZE (or factor) is too small");
  151.  
  152.     Nx = IBUFFSIZE - 2*Xoff;     /* # of samples to process each iteration */
  153.     
  154.     last = 0;            /* Have not read last input sample yet */
  155.     Ycount = 0;            /* Current sample and length of output file */
  156.     Xp = Xoff;            /* Current "now"-sample pointer for input */
  157.     Xread = Xoff;        /* Position in input array to read into */
  158.     Time = (Xoff<<Np);        /* Current-time pointer for converter */
  159.     
  160.     for (i=0; i<Xoff; X1[i++]=0); /* Need Xoff zeros at begining of sample */
  161.     for (i=0; i<Xoff; X2[i++]=0); /* Need Xoff zeros at begining of sample */
  162.         
  163.     do {
  164.     if (!last)        /* If haven't read last sample yet */
  165.     {
  166.         last = readData(X1, X2, IBUFFSIZE,(int)Xread);
  167.         if (last && (last-Xoff<Nx)) { /* If last sample has been read... */
  168.         Nx = last-Xoff;    /* ...calc last sample affected by filter */
  169.         if (Nx <= 0)
  170.           break;
  171.         }
  172.     }
  173.     /* Resample stuff in input buffer */
  174.     Time2 = Time;
  175.     if (factor >= 1) {    /* SrcUp() is faster if we can use it */
  176.         Nout=SrcUp(X1,Y1,factor,&Time,Nx,Nwing,LpScl,Imp,ImpD,interpFilt);
  177.         if (nChans==2)
  178.           Nout=SrcUp(X2,Y2,factor,&Time2,Nx,Nwing,LpScl,Imp,ImpD,
  179.              interpFilt);
  180.     }
  181.     else {
  182.         Nout=SrcUD(X1,Y1,factor,&Time,Nx,Nwing,LpScl,Imp,ImpD,interpFilt);
  183.         if (nChans==2)
  184.           Nout=SrcUD(X2,Y2,factor,&Time2,Nx,Nwing,LpScl,Imp,ImpD,
  185.              interpFilt);
  186.     }
  187.  
  188.     Time -= (Nx<<Np);    /* Move converter Nx samples back in time */
  189.     Xp += Nx;        /* Advance by number of samples processed */
  190.     Ncreep = (Time>>Np) - Xoff; /* Calc time accumulation in Time */
  191.     if (Ncreep) {
  192.         Time -= (Ncreep<<Np);    /* Remove time accumulation */
  193.         Xp += Ncreep;            /* and add it to read pointer */
  194.     }
  195.     for (i=0; i<IBUFFSIZE-Xp+Xoff; i++) { /* Copy part of input signal */
  196.         X1[i] = X1[i+Xp-Xoff]; /* that must be re-used */
  197.         if (nChans==2)
  198.           X2[i] = X2[i+Xp-Xoff]; /* that must be re-used */
  199.     }
  200.     if (last) {        /* If near end of sample... */
  201.         last -= Xp;        /* ...keep track were it ends */
  202.         if (!last)        /* Lengthen input by 1 sample if... */
  203.           last++;        /* ...needed to keep flag TRUE */
  204.     }
  205.     Xread = i;        /* Pos in input buff to read new data into */
  206.     Xp = Xoff;
  207.     
  208.     Ycount += Nout;
  209.     if (Ycount>outCount) {
  210.         Nout -= (Ycount-outCount);
  211.         Ycount = outCount;
  212.     }
  213.  
  214.     if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */
  215.       return err_ret("Output array overflow");
  216.     
  217.     write(Nout, Y1, Y2);
  218.  
  219.     printf(".");  fflush(stdout);
  220.  
  221.     } while (Ycount<outCount); /* Continue until done */
  222.     free(Y1);
  223.     free(Y2);
  224.     return(Ycount);        /* Return # of samples in output file */
  225. }
  226. void CResampler::ResampleFastStart(){
  227.     int OBUFFSIZE = (int)(((double)IBUFFSIZE)*factor+2.0);
  228.     Y1=(HRWORD *)malloc(OBUFFSIZE*sizeof(HRWORD));
  229.     Y2=(HRWORD *)malloc(OBUFFSIZE*sizeof(HRWORD));
  230.  
  231.     Xoff = 10;
  232.  
  233.     Nx = IBUFFSIZE - 2*Xoff;     /* # of samples to process each iteration */
  234.     last = 0;            /* Have not read last input sample yet */
  235.     Ycount = 0;            /* Current sample and length of output file */
  236.  
  237.     Xp = Xoff;            /* Current "now"-sample pointer for input */
  238.     Xread = Xoff;        /* Position in input array to read into */
  239.     Time = (Xoff<<Np);        /* Current-time pointer for converter */
  240.     
  241.     for (i=0; i<Xoff; X1[i++]=0); /* Need Xoff zeros at begining of sample */
  242.     for (i=0; i<Xoff; X2[i++]=0); /* Need Xoff zeros at begining of sample */
  243.  
  244. }
  245. void CResampler::ResampleFastStop(){
  246.     free(Y1);
  247.     free(Y2);
  248. }
  249. int CResampler::ResampleFast( short *oData /* number of output samples returned */
  250. )
  251. {
  252.  
  253.     readData(X1, X2, IBUFFSIZE,(int)Xread);
  254.  
  255.  
  256.     /* Resample stuff in input buffer */
  257.     Time2 = Time;
  258.     Nout=SrcLinear(X1,Y1,factor,&Time,Nx);
  259.     if (nChans==2)
  260.       Nout=SrcLinear(X2,Y2,factor,&Time2,Nx);
  261.  
  262.     Time -= (Nx<<Np);    /* Move converter Nx samples back in time */
  263.     Xp += Nx;        /* Advance by number of samples processed */
  264.     Ncreep = (Time>>Np) - Xoff; /* Calc time accumulation in Time */
  265.     if (Ncreep) {
  266.         Time -= (Ncreep<<Np);    /* Remove time accumulation */
  267.         Xp += Ncreep;            /* and add it to read pointer */
  268.     }
  269.     for (i=0; i<IBUFFSIZE-Xp+Xoff; i++) { /* Copy part of input signal */
  270.         X1[i] = X1[i+Xp-Xoff]; /* that must be re-used */
  271.         if (nChans==2)
  272.           X2[i] = X2[i+Xp-Xoff]; /* that must be re-used */
  273.     }
  274.     if (last) {        /* If near end of sample... */
  275.         last -= Xp;        /* ...keep track were it ends */
  276.         if (!last)        /* Lengthen input by 1 sample if... */
  277.           last++;        /* ...needed to keep flag TRUE */
  278.     }
  279.     Xread = i;        /* Pos in input buff to read new data into */
  280.     Xp = Xoff;
  281.     
  282.     //Ycount += Nout;
  283.     //if (Ycount>outCount) {
  284.     //    Nout -= (Ycount-outCount);
  285.     //    Ycount = outCount;
  286.     //}
  287.  
  288.     //if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */
  289.      // return err_ret("Output array overflow");
  290.     
  291.     write(Nout,Y1,Y2,oData);
  292.     
  293.     return 0;        /* Return # of samples in output file */
  294. }
  295. /* Sampling rate conversion subroutine */
  296.  
  297. int CResampler::SrcUD(HRWORD X[], HRWORD Y[], double factor, URWORD *Time,
  298.          UHRWORD Nx, UHRWORD Nwing, UHRWORD LpScl,
  299.          HRWORD Imp[], HRWORD ImpD[], BOOL Interp)
  300. {
  301.     HRWORD *Xp, *Ystart;
  302.     RWORD v;
  303.     
  304.     double dh;                  /* Step through filter impulse response */
  305.     double dt;                  /* Step through input signal */
  306.     URWORD endTime;              /* When Time reaches EndTime, return to user */
  307.     URWORD dhb, dtb;             /* Fixed-point versions of Dh,Dt */
  308.     
  309.     dt = 1.0/factor;            /* Output sampling period */
  310.     dtb = dt*(1<<Np) + 0.5;     /* Fixed-point representation */
  311.     
  312.     dh = MIN(Npc, factor*Npc);  /* Filter sampling period */
  313.     dhb = dh*(1<<Na) + 0.5;     /* Fixed-point representation */
  314.     
  315.     Ystart = Y;
  316.     endTime = *Time + (1<<Np)*(RWORD)Nx;
  317.     while (*Time < endTime)
  318.     {
  319.     Xp = &X[*Time>>Np];    /* Ptr to current input sample */
  320.     v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (HRWORD)(*Time&Pmask),
  321.              -1, dhb);    /* Perform left-wing inner product */
  322.     v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (HRWORD)((-*Time)&Pmask),
  323.               1, dhb);    /* Perform right-wing inner product */
  324.     v >>= Nhg;        /* Make guard bits */
  325.     v *= LpScl;        /* Normalize for unity filter gain */
  326.     *Y++ = RWORDToHRWORD(v,NLpScl);   /* strip guard bits, deposit output */
  327.     *Time += dtb;        /* Move to next sample by time increment */
  328.     }
  329.     return (Y - Ystart);        /* Return the number of output samples */
  330. }
  331.  
  332.  
  333. /* Sampling rate up-conversion only subroutine;
  334.  * Slightly faster than down-conversion;
  335.  */
  336. int CResampler::SrcUp(HRWORD X[], HRWORD Y[], double factor, URWORD *Time,
  337.          UHRWORD Nx, UHRWORD Nwing, UHRWORD LpScl,
  338.          HRWORD Imp[], HRWORD ImpD[], BOOL Interp)
  339. {
  340.     HRWORD *Xp, *Ystart;
  341.     RWORD v;
  342.     
  343.     double dt;                  /* Step through input signal */ 
  344.     URWORD dtb;                  /* Fixed-point version of Dt */
  345.     URWORD endTime;              /* When Time reaches EndTime, return to user */
  346.     
  347.     dt = 1.0/factor;            /* Output sampling period */
  348.     dtb = dt*(1<<Np) + 0.5;     /* Fixed-point representation */
  349.     
  350.     Ystart = Y;
  351.     endTime = *Time + (1<<Np)*(RWORD)Nx;
  352.     while (*Time < endTime)
  353.     {
  354.     Xp = &X[*Time>>Np];      /* Ptr to current input sample */
  355.     /* Perform left-wing inner product */
  356.     v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, (HRWORD)(*Time&Pmask),-1);
  357.     /* Perform right-wing inner product */
  358.     v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, 
  359.               (HRWORD)((-*Time)&Pmask),1);
  360.     v >>= Nhg;        /* Make guard bits */
  361.     v *= LpScl;        /* Normalize for unity filter gain */
  362.     *Y++ = RWORDToHRWORD(v,NLpScl);   /* strip guard bits, deposit output */
  363.     *Time += dtb;        /* Move to next sample by time increment */
  364.     }
  365.     return (Y - Ystart);        /* Return the number of output samples */
  366. }
  367.  
  368. /* Sampling rate conversion using linear interpolation for maximum speed.
  369.  */
  370. int 
  371.   CResampler::SrcLinear(HRWORD X[], HRWORD Y[], double factor, URWORD *Time, UHRWORD Nx)
  372. {
  373.     HRWORD iconst;
  374.     HRWORD *Xp, *Ystart;
  375.     RWORD v,x1,x2;
  376.     
  377.     double dt;                  /* Step through input signal */ 
  378.     URWORD dtb;                  /* Fixed-point version of Dt */
  379.     URWORD endTime;              /* When Time reaches EndTime, return to user */
  380.     
  381.     dt = 1.0/factor;            /* Output sampling period */
  382.     dtb = dt*(1<<Np) + 0.5;     /* Fixed-point representation */
  383.     
  384.     Ystart = Y;
  385.     endTime = *Time + (1<<Np)*(RWORD)Nx;
  386.     while (*Time < endTime)
  387.     {
  388.     iconst = (*Time) & Pmask;
  389.     Xp = &X[(*Time)>>Np];      /* Ptr to current input sample */
  390.     x1 = *Xp++;
  391.     x2 = *Xp;
  392.     x1 *= ((1<<Np)-iconst);
  393.     x2 *= iconst;
  394.     v = x1 + x2;
  395.     *Y++ = RWORDToHRWORD(v,Np);   /* Deposit output */
  396.     *Time += dtb;            /* Move to next sample by time increment */
  397.     }
  398.     return (Y - Ystart);            /* Return number of output samples */
  399. }
  400.  
  401. #ifdef DEBUG
  402. static int pof = 0;        /* positive overflow count */
  403. static int nof = 0;        /* negative overflow count */
  404. #endif
  405.  
  406. INLINE HRWORD CResampler::RWORDToHRWORD(RWORD v, int scl)
  407. {
  408.     HRWORD out;
  409.     RWORD llsb = (1<<(scl-1));
  410.     v += llsb;        /* round */
  411.     v >>= scl;
  412.     if (v>MAX_HRWORD) {
  413. #ifdef DEBUG
  414.     if (pof == 0)
  415.       fprintf(stderr, "*** resample: sound sample overflow\n");
  416.     else if ((pof % 10000) == 0)
  417.       fprintf(stderr, "*** resample: another ten thousand overflows\n");
  418.     pof++;
  419. #endif
  420.     v = MAX_HRWORD;
  421.     } else if (v < MIN_HRWORD) {
  422. #ifdef DEBUG
  423.     if (nof == 0)
  424.       fprintf(stderr, "*** resample: sound sample (-) overflow\n");
  425.     else if ((nof % 1000) == 0)
  426.       fprintf(stderr, "*** resample: another thousand (-) overflows\n");
  427.     nof++;
  428. #endif
  429.     v = MIN_HRWORD;
  430.     }    
  431.     out = (HRWORD) v;
  432.     return out;
  433. }
  434.  
  435. /* CAUTION: Assumes we call this for only one resample job per program run! */
  436. /* return: 0 - notDone */
  437. /*        >0 - index of last sample */
  438. int INLINE CResampler::readData(
  439.          HRWORD *outPtr1,      /* array receiving left chan samps */
  440.          HRWORD *outPtr2,      /* array receiving right chan samps */
  441.          int   dataArraySize, /* size of these arrays */
  442.          int   Xoff)          /* read into input array starting at this index */
  443.    int    i, Nsamps,Top,val;
  444.    short  *iData;
  445.  
  446.    Nsamps = dataArraySize - Xoff;   /* Calculate number of samples to get */
  447.    outPtr1 += Xoff;                 /* Start at designated sample number */
  448.    outPtr2 += Xoff;
  449.  
  450.    /* NOTE: doesn't return an error code! */
  451.    if(nChans==1)
  452.      eosFlag=ABuffer->ReadBuffer((char **)&iData, Nsamps*2);
  453.    else if(nChans==2)
  454.      eosFlag=ABuffer->ReadBuffer((char **)&iData, Nsamps*4);
  455.  
  456. //   if( (framecount+Nsamps)> inCount) /* if this is the last iteration */
  457. //       Top= inCount - framecount;
  458. //   else
  459.        Top= Nsamps;
  460.  
  461.    if (nChans == 1) { 
  462.       for (i = 0; i < Top; i++)
  463.          *outPtr1++ = (HRWORD) iData[i];
  464.    }
  465.    else {
  466.       for (i = 0; i < Top; i++) {
  467.          *outPtr1++ = (HRWORD) iData[(2*i)];
  468.          *outPtr2++ = (HRWORD) iData[(2*i)+1];
  469.       }
  470.    }
  471.  
  472.  
  473.    //framecount += Nsamps;
  474.  
  475.    //if (framecount >= inCount)            /* return index of last samp */
  476.      // return (((Nsamps - (framecount - inCount)) - 1) + Xoff);
  477.    //else
  478.       return 0;
  479. }
  480.  
  481.  
  482. int CResampler::err_ret(char *s)
  483. {
  484.     fprintf(stderr,"resample: %s \n\n",s); /* Display error message  */
  485.     return -1;
  486. };
  487.  
  488. RWORD CResampler::FilterUD( HRWORD Imp[], HRWORD ImpD[],
  489.              UHRWORD Nwing, BOOL Interp,
  490.              HRWORD *Xp, HRWORD Ph, HRWORD Inc, UHRWORD dhb)
  491. {
  492.     HRWORD a;
  493.     HRWORD *Hp, *Hdp, *End;
  494.     RWORD v, t;
  495.     URWORD Ho;
  496.     
  497.     v=0;
  498.     Ho = (Ph*(URWORD)dhb)>>Np;
  499.     End = &Imp[Nwing];
  500.     if (Inc == 1)        /* If doing right wing...              */
  501.     {                /* ...drop extra coeff, so when Ph is  */
  502.       End--;            /*    0.5, we don't do too many mult's */
  503.       if (Ph == 0)        /* If the phase is zero...           */
  504.         Ho += dhb;        /* ...then we've already skipped the */
  505.     }                /*    first sample, so we must also  */
  506.                 /*    skip ahead in Imp[] and ImpD[] */
  507.     if (Interp)
  508.       while ((Hp = &Imp[Ho>>Na]) < End) {
  509.         t = *Hp;        /* Get IR sample */
  510.         Hdp = &ImpD[Ho>>Na];  /* get interp (lower Na) bits from diff table*/
  511.         a = Ho & Amask;    /* a is logically between 0 and 1 */
  512.         t += (((RWORD)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */
  513.         t *= *Xp;        /* Mult coeff by input sample */
  514.         if (t & 1<<(Nhxn-1))    /* Round, if needed */
  515.           t += 1<<(Nhxn-1);
  516.         t >>= Nhxn;        /* Leave some guard bits, but come back some */
  517.         v += t;            /* The filter output */
  518.         Ho += dhb;        /* IR step */
  519.         Xp += Inc;        /* Input signal step. NO CHECK ON BOUNDS */
  520.       }
  521.       else 
  522.         while ((Hp = &Imp[Ho>>Na]) < End) {
  523.           t = *Hp;        /* Get IR sample */
  524.           t *= *Xp;        /* Mult coeff by input sample */
  525.           if (t & 1<<(Nhxn-1))    /* Round, if needed */
  526.             t += 1<<(Nhxn-1);
  527.           t >>= Nhxn;        /* Leave some guard bits, but come back some */
  528.           v += t;            /* The filter output */
  529.           Ho += dhb;        /* IR step */
  530.           Xp += Inc;        /* Input signal step. NO CHECK ON BOUNDS */
  531.         }
  532.         return(v);
  533. }
  534.  
  535.  
  536. RWORD CResampler::FilterUp(HRWORD Imp[], HRWORD ImpD[], 
  537.                          UHRWORD Nwing, BOOL Interp,
  538.                          HRWORD *Xp, HRWORD Ph, HRWORD Inc)
  539. {
  540.     HRWORD *Hp, *Hdp = NULL, *End;
  541.     HRWORD a = 0;
  542.     RWORD v, t;
  543.     
  544.     v=0;
  545.     Hp = &Imp[Ph>>Na];
  546.     End = &Imp[Nwing];
  547.     if (Interp) {
  548.     Hdp = &ImpD[Ph>>Na];
  549.     a = Ph & Amask;
  550.     }
  551.     if (Inc == 1)        /* If doing right wing...              */
  552.     {                /* ...drop extra coeff, so when Ph is  */
  553.     End--;            /*    0.5, we don't do too many mult's */
  554.     if (Ph == 0)        /* If the phase is zero...           */
  555.     {            /* ...then we've already skipped the */
  556.         Hp += Npc;        /*    first sample, so we must also  */
  557.         Hdp += Npc;        /*    skip ahead in Imp[] and ImpD[] */
  558.     }
  559.     }
  560.     if (Interp)
  561.       while (Hp < End) {
  562.       t = *Hp;        /* Get filter coeff */
  563.       t += (((RWORD)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */
  564.       Hdp += Npc;        /* Filter coeff differences step */
  565.       t *= *Xp;        /* Mult coeff by input sample */
  566.       if (t & (1<<(Nhxn-1)))  /* Round, if needed */
  567.         t += (1<<(Nhxn-1));
  568.       t >>= Nhxn;        /* Leave some guard bits, but come back some */
  569.       v += t;            /* The filter output */
  570.       Hp += Npc;        /* Filter coeff step */
  571.       Xp += Inc;        /* Input signal step. NO CHECK ON BOUNDS */
  572.       } 
  573.     else 
  574.       while (Hp < End) {
  575.       t = *Hp;        /* Get filter coeff */
  576.       t *= *Xp;        /* Mult coeff by input sample */
  577.       if (t & (1<<(Nhxn-1)))  /* Round, if needed */
  578.         t += (1<<(Nhxn-1));
  579.       t >>= Nhxn;        /* Leave some guard bits, but come back some */
  580.       v += t;            /* The filter output */
  581.       Hp += Npc;        /* Filter coeff step */
  582.       Xp += Inc;        /* Input signal step. NO CHECK ON BOUNDS */
  583.       }
  584.     return(v);
  585. }
  586. void INLINE CResampler::write(int samples, HRWORD *Y1, HRWORD *Y2, short *oData){
  587.     //writes interleaved audio
  588.     int i;
  589.     if (nChans==1) {
  590.         for (i = 0; i < samples; i++)
  591.             oData[i] = Y1[i];
  592.     } else {
  593.         for (i = 0; i < samples; i++) {
  594.         oData[2*i] =  Y1[i];
  595.         oData[(2*i)+1] =  Y2[i];
  596.         }
  597.     }
  598. }
  599.  
  600. void INLINE CResampler::write(int samples, HRWORD *Y1, HRWORD *Y2)
  601. {
  602. }
  603.