/* * Copyright: (C) 2000 Julius O. Smith * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Julius O. Smith jos@ccrma.stanford.edu * */ /* This code was modified by Bruce Forsberg (forsberg@tns.net) to make it into a C++ class */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include "aflibConverter.h" #include "aflibConverterLargeFilter.h" #include "aflibConverterSmallFilter.h" #include "aflibDebug.h" #if (!defined(TRUE) || !defined(FALSE)) # define TRUE 1 # define FALSE 0 #endif /* * The configuration constants below govern * the number of bits in the input sample and filter coefficients, the * number of bits to the right of the binary-point for fixed-point math, etc. */ /* Conversion constants */ #define Nhc 8 #define Na 7 #define Np (Nhc+Na) #define Npc (1< (inCount - (int)framecount)) { Nsamps = inCount - framecount; } for (c = 0; c < _nChans; c++) { ptr = outPtr[c]; ptr += Xoff; /* Start at designated sample number */ for (i = 0; i < Nsamps; i++) *ptr++ = (short) inArray[c * inCount + i + framecount]; } framecount += Nsamps; if ((int)framecount >= inCount) /* return index of last samp */ return (((Nsamps - (framecount - inCount)) - 1) + Xoff); else return 0; } int aflibConverter::SrcLinear( short X[], short Y[], double factor, unsigned int *Time, unsigned short& Nx, unsigned short Nout) { short iconst; short *Xp, *Ystart; int v,x1,x2; double dt; /* Step through input signal */ unsigned int dtb; /* Fixed-point version of Dt */ // unsigned int endTime; /* When Time reaches EndTime, return to user */ unsigned int start_sample, end_sample; dt = 1.0/factor; /* Output sampling period */ dtb = (unsigned int)(dt*(1<>Np; Ystart = Y; // endTime = *Time + (1<>Np]; /* Ptr to current input sample */ x1 = *Xp++; x2 = *Xp; x1 *= ((1<>Np; Nx = end_sample - start_sample; return (Y - Ystart); /* Return number of output samples */ } int aflibConverter::SrcUp( short X[], short Y[], double factor, unsigned int *Time, unsigned short& Nx, unsigned short Nout, unsigned short Nwing, unsigned short LpScl, short Imp[], short ImpD[], bool Interp) { short *Xp, *Ystart; int v; double dt; /* Step through input signal */ unsigned int dtb; /* Fixed-point version of Dt */ // unsigned int endTime; /* When Time reaches EndTime, return to user */ unsigned int start_sample, end_sample; dt = 1.0/factor; /* Output sampling period */ dtb = (unsigned int)(dt*(1<>Np; Ystart = Y; // endTime = *Time + (1<>Np]; /* Ptr to current input sample */ /* Perform left-wing inner product */ v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, (short)(*Time&Pmask),-1); /* Perform right-wing inner product */ v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, (short)((((*Time)^Pmask)+1)&Pmask), 1); v >>= Nhg; /* Make guard bits */ v *= LpScl; /* Normalize for unity filter gain */ *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ *Time += dtb; /* Move to next sample by time increment */ } end_sample = (*Time)>>Np; Nx = end_sample - start_sample; return (Y - Ystart); /* Return the number of output samples */ } int aflibConverter::SrcUD( short X[], short Y[], double factor, unsigned int *Time, unsigned short& Nx, unsigned short Nout, unsigned short Nwing, unsigned short LpScl, short Imp[], short ImpD[], bool Interp) { short *Xp, *Ystart; int v; double dh; /* Step through filter impulse response */ double dt; /* Step through input signal */ // unsigned int endTime; /* When Time reaches EndTime, return to user */ unsigned int dhb, dtb; /* Fixed-point versions of Dh,Dt */ unsigned int start_sample, end_sample; dt = 1.0/factor; /* Output sampling period */ dtb = (unsigned int)(dt*(1<>Np; Ystart = Y; // endTime = *Time + (1<>Np]; /* Ptr to current input sample */ v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (short)(*Time&Pmask), -1, dhb); /* Perform left-wing inner product */ v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (short)((((*Time)^Pmask)+1)&Pmask), 1, dhb); /* Perform right-wing inner product */ v >>= Nhg; /* Make guard bits */ v *= LpScl; /* Normalize for unity filter gain */ *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ *Time += dtb; /* Move to next sample by time increment */ } end_sample = (*Time)>>Np; Nx = end_sample - start_sample; return (Y - Ystart); /* Return the number of output samples */ } int aflibConverter::resampleFast( /* number of output samples returned */ int& inCount, /* number of input samples to convert */ int outCount, /* number of output samples to compute */ short inArray[], /* input data */ short outArray[]) /* output data */ { unsigned int Time2; /* Current time/pos in input sample */ #if 0 unsigned short Ncreep; #endif unsigned short Xp, Xoff, Xread; int OBUFFSIZE = (int)(((double)IBUFFSIZE)*_factor); unsigned short Nout = 0, Nx, orig_Nx; unsigned short maxOutput; int total_inCount = 0; int c, i, Ycount, last; bool first_pass = TRUE; Xoff = 10; Nx = IBUFFSIZE - 2*Xoff; /* # of samples to process each iteration */ last = 0; /* Have not read last input sample yet */ Ycount = 0; /* Current sample and length of output file */ Xp = Xoff; /* Current "now"-sample pointer for input */ Xread = Xoff; /* Position in input array to read into */ if (_initial == TRUE) _Time = (Xoff< (OBUFFSIZE - (2*Xoff*_factor)) ) maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor); else maxOutput = outCount-Ycount; for (c = 0; c < _nChans; c++) { orig_Nx = Nx; Time2 = _Time; /* Resample stuff in input buffer */ Nout=SrcLinear(_II[c],_JJ[c],_factor,&Time2,orig_Nx,maxOutput); } Nx = orig_Nx; _Time = Time2; _Time -= (Nx<>Np) - Xoff; /* Calc time accumulation in Time */ if (Ncreep) { Time -= (Ncreep<outCount) { Nout -= (Ycount-outCount); Ycount = outCount; } if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */ return err_ret("Output array overflow"); for (c = 0; c < _nChans; c++) for (i = 0; i < Nout; i++) outArray[c * outCount + i + Ycount - Nout] = _JJ[c][i]; total_inCount += Nx; } while (Ycount < outCount); /* Continue until done */ inCount = total_inCount; return(Ycount); /* Return # of samples in output file */ } int aflibConverter::resampleWithFilter( /* number of output samples returned */ int& inCount, /* number of input samples to convert */ int outCount, /* number of output samples to compute */ short inArray[], /* input data */ short outArray[], /* output data */ short Imp[], short ImpD[], unsigned short LpScl, unsigned short Nmult, unsigned short Nwing) { unsigned int Time2; /* Current time/pos in input sample */ #if 0 unsigned short Ncreep; #endif unsigned short Xp, Xoff, Xread; int OBUFFSIZE = (int)(((double)IBUFFSIZE)*_factor); unsigned short Nout = 0, Nx, orig_Nx; unsigned short maxOutput; int total_inCount = 0; int c, i, Ycount, last; bool first_pass = TRUE; /* Account for increased filter gain when using factors less than 1 */ if (_factor < 1) LpScl = (unsigned short)(LpScl*_factor + 0.5); /* Calc reach of LP filter wing & give some creeping room */ Xoff = (unsigned short)(((Nmult+1)/2.0) * MAX(1.0,1.0/_factor) + 10); if (IBUFFSIZE < 2*Xoff) /* Check input buffer size */ return err_ret("IBUFFSIZE (or factor) is too small"); Nx = IBUFFSIZE - 2*Xoff; /* # of samples to process each iteration */ last = 0; /* Have not read last input sample yet */ Ycount = 0; /* Current sample and length of output file */ Xp = Xoff; /* Current "now"-sample pointer for input */ Xread = Xoff; /* Position in input array to read into */ if (_initial == TRUE) _Time = (Xoff< (OBUFFSIZE - (2*Xoff*_factor)) ) maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor); else maxOutput = outCount-Ycount; for (c = 0; c < _nChans; c++) { orig_Nx = Nx; Time2 = _Time; /* Resample stuff in input buffer */ if (_factor >= 1) { /* SrcUp() is faster if we can use it */ Nout=SrcUp(_II[c],_JJ[c],_factor, &Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); } else { Nout=SrcUD(_II[c],_JJ[c],_factor, &Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); } } _Time = Time2; _Time -= (Nx<>Np) - Xoff; /* Calc time accumulation in Time */ if (Ncreep) { Time -= (Ncreep< outCount) { Nout -= (Ycount - outCount); Ycount = outCount; } if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */ return err_ret("Output array overflow"); for (c = 0; c < _nChans; c++) { for (i = 0; i < Nout; i++) { outArray[c * outCount + i + Ycount - Nout] = _JJ[c][i]; } } int act_incount = (int)Nx; for (c = 0; c < _nChans; c++) { for (i=0; i>Na]; End = &Imp[Nwing]; if (Interp) { Hdp = &ImpD[Ph>>Na]; a = Ph & Amask; } if (Inc == 1) /* If doing right wing... */ { /* ...drop extra coeff, so when Ph is */ End--; /* 0.5, we don't do too many mult's */ if (Ph == 0) /* If the phase is zero... */ { /* ...then we've already skipped the */ Hp += Npc; /* first sample, so we must also */ Hdp += Npc; /* skip ahead in Imp[] and ImpD[] */ } } if (Interp) { while (Hp < End) { t = *Hp; /* Get filter coeff */ t += (((int)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */ Hdp += Npc; /* Filter coeff differences step */ t *= *Xp; /* Mult coeff by input sample */ if (t & (1<<(Nhxn-1))) /* Round, if needed */ t += (1<<(Nhxn-1)); t >>= Nhxn; /* Leave some guard bits, but come back some */ v += t; /* The filter output */ Hp += Npc; /* Filter coeff step */ Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ } } else { while (Hp < End) { t = *Hp; /* Get filter coeff */ t *= *Xp; /* Mult coeff by input sample */ if (t & (1<<(Nhxn-1))) /* Round, if needed */ t += (1<<(Nhxn-1)); t >>= Nhxn; /* Leave some guard bits, but come back some */ v += t; /* The filter output */ Hp += Npc; /* Filter coeff step */ Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ } } return(v); } int aflibConverter::FilterUD( short Imp[], short ImpD[], unsigned short Nwing, bool Interp, short *Xp, short Ph, short Inc, unsigned short dhb) { short a; short *Hp, *Hdp, *End; int v, t; unsigned int Ho; v=0; Ho = (Ph*(unsigned int)dhb)>>Np; End = &Imp[Nwing]; if (Inc == 1) /* If doing right wing... */ { /* ...drop extra coeff, so when Ph is */ End--; /* 0.5, we don't do too many mult's */ if (Ph == 0) /* If the phase is zero... */ Ho += dhb; /* ...then we've already skipped the */ } /* first sample, so we must also */ /* skip ahead in Imp[] and ImpD[] */ if (Interp) { while ((Hp = &Imp[Ho>>Na]) < End) { t = *Hp; /* Get IR sample */ Hdp = &ImpD[Ho>>Na]; /* get interp (lower Na) bits from diff table*/ a = Ho & Amask; /* a is logically between 0 and 1 */ t += (((int)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */ t *= *Xp; /* Mult coeff by input sample */ if (t & 1<<(Nhxn-1)) /* Round, if needed */ t += 1<<(Nhxn-1); t >>= Nhxn; /* Leave some guard bits, but come back some */ v += t; /* The filter output */ Ho += dhb; /* IR step */ Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ } } else { while ((Hp = &Imp[Ho>>Na]) < End) { t = *Hp; /* Get IR sample */ t *= *Xp; /* Mult coeff by input sample */ if (t & 1<<(Nhxn-1)) /* Round, if needed */ t += 1<<(Nhxn-1); t >>= Nhxn; /* Leave some guard bits, but come back some */ v += t; /* The filter output */ Ho += dhb; /* IR step */ Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ } } return(v); }