diff --git a/darkice/trunk/src/Makefile.am b/darkice/trunk/src/Makefile.am index fa8e0b4..35660da 100644 --- a/darkice/trunk/src/Makefile.am +++ b/darkice/trunk/src/Makefile.am @@ -29,6 +29,8 @@ darkice_SOURCES = AudioEncoder.h\ LameLibEncoder.h\ VorbisLibEncoder.cpp\ VorbisLibEncoder.h\ + aflibDebug.h\ + aflibDebug.cc\ aflibConverter.h\ aflibConverter.cc\ aflibConverterLargeFilter.h\ diff --git a/darkice/trunk/src/aflibConverter.cc b/darkice/trunk/src/aflibConverter.cc index 5a2272e..5a2eb12 100644 --- a/darkice/trunk/src/aflibConverter.cc +++ b/darkice/trunk/src/aflibConverter.cc @@ -18,10 +18,13 @@ * Julius O. Smith jos@ccrma.stanford.edu * */ -/* This code was modified by Bruce Forsberg (forsberg@adnc.com) to make it +/* 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 @@ -32,6 +35,7 @@ #include "aflibConverterLargeFilter.h" #include "aflibConverterSmallFilter.h" +#include "aflibDebug.h" #if (!defined(TRUE) || !defined(FALSE)) # define TRUE 1 @@ -112,12 +116,16 @@ aflibConverter::aflibConverter( bool linear_interpolation, bool filter_interpolation) { + /* TODO put all these into an enum as it only makes sense to have + * one true at a time. - DAS + */ interpFilt = filter_interpolation; largeFilter = high_quality; linearInterp = linear_interpolation; - X = NULL; - Y = NULL; + _X = NULL; + _Y = NULL; + _vol = 1.0; } aflibConverter::~aflibConverter() @@ -131,65 +139,65 @@ aflibConverter::deleteMemory() { int i; - // Delete memory for the input and output arrays - if (X != NULL) + if (_X != NULL) { - for (i = 0; i < nChans; i++) + for (i = 0; i < _nChans; i++) { - delete [] X[i]; - X[i] = NULL; - delete [] Y[i]; - Y[i] = NULL; + delete [] _X[i]; + _X[i] = NULL; + delete [] _Y[i]; + _Y[i] = NULL; } - delete [] X; - X = NULL; - delete [] Y; - Y = NULL; + delete [] _X; + _X = NULL; + delete [] _Y; + _Y = NULL; } } - void aflibConverter::initialize( double fac, - int channels) + int channels, + double volume) { - // This function will allow one to stream data. When a new data stream is to - // be input then this function should be called. Even if the factor and number - // of channels don't change. Otherwise each new data block sent to resample - // will be considered part of the previous data block. +// This function will allow one to stream data. When a new data stream is to +// be input then this function should be called. Even if the factor and number +// of channels don't change. Otherwise each new data block sent to resample +// will be considered part of the previous data block. This function also allows +// one to specified a multiplication factor to adjust the final output. This +// applies to the small and large filter. int i; - // Delete all previous allocated input and output buffer memory deleteMemory(); - factor = fac; - nChans = channels; - initial = TRUE; + _factor = fac; + _nChans = channels; + _initial = TRUE; + _vol = volume; // Allocate all new memory - X = new HWORD * [nChans]; - Y = new HWORD * [nChans]; + _X = new short * [_nChans]; + _Y = new short * [_nChans]; - for (i = 0; i < nChans; i++) + for (i = 0; i < _nChans; i++) { // Add extra to allow of offset of input data (Xoff in main routine) - X[i] = new HWORD[IBUFFSIZE + 256]; - Y[i] = new HWORD[(int)(((double)IBUFFSIZE)*factor)]; - memset(X[i], 0, sizeof(HWORD) * (IBUFFSIZE + 256)); + _X[i] = new short[IBUFFSIZE + 256]; + _Y[i] = new short[(int)(((double)IBUFFSIZE)*_factor)]; + memset(_X[i], 0, sizeof(short) * (IBUFFSIZE + 256)); } } - int aflibConverter::resample( /* number of output samples returned */ int& inCount, /* number of input samples to convert */ int outCount, /* number of output samples to compute */ - HWORD inArray[], /* input data */ - HWORD outArray[]) /* output data */ + short inArray[], /* input data */ + short outArray[]) /* output data */ { int Ycount; @@ -200,40 +208,42 @@ aflibConverter::resample( /* number of output samples returned */ // Use small filtering. Good qulaity else if (largeFilter == FALSE) Ycount = resampleWithFilter(inCount,outCount,inArray,outArray, - SMALL_FILTER_IMP, SMALL_FILTER_IMPD, (UHWORD)(SMALL_FILTER_SCALE * 0.95), + SMALL_FILTER_IMP, SMALL_FILTER_IMPD, + (unsigned short)(SMALL_FILTER_SCALE * _vol), SMALL_FILTER_NMULT, SMALL_FILTER_NWING); // Use large filtering Great quality else Ycount = resampleWithFilter(inCount,outCount,inArray,outArray, - LARGE_FILTER_IMP, LARGE_FILTER_IMPD, (UHWORD)(LARGE_FILTER_SCALE * 0.95), + LARGE_FILTER_IMP, LARGE_FILTER_IMPD, + (unsigned short)(LARGE_FILTER_SCALE * _vol), LARGE_FILTER_NMULT, LARGE_FILTER_NWING); - initial = FALSE; + _initial = FALSE; return (Ycount); } + int aflibConverter::err_ret(char *s) { - fprintf(stderr,"resample: %s \n\n",s); /* Display error message */ + aflib_debug("resample: %s \n\n",s); /* Display error message */ return -1; } - int aflibConverter::readData( int inCount, /* _total_ number of frames in input file */ - HWORD inArray[], /* input data */ - HWORD *outPtr[], /* array receiving chan samps */ + short inArray[], /* input data */ + short *outPtr[], /* array receiving chan samps */ int dataArraySize, /* size of these arrays */ int Xoff, /* read into input array starting at this index */ bool init_count) { int i, Nsamps, c; static unsigned int framecount; /* frames previously read */ - HWORD *ptr; + short *ptr; if (init_count == TRUE) framecount = 0; /* init this too */ @@ -246,13 +256,13 @@ aflibConverter::readData( Nsamps = inCount - framecount; } - for (c = 0; c < nChans; c++) + for (c = 0; c < _nChans; c++) { ptr = outPtr[c]; ptr += Xoff; /* Start at designated sample number */ for (i = 0; i < Nsamps; i++) - *ptr++ = (HWORD) inArray[c * inCount + i + framecount]; + *ptr++ = (short) inArray[c * inCount + i + framecount]; } framecount += Nsamps; @@ -263,144 +273,162 @@ aflibConverter::readData( return 0; } - -int +int aflibConverter::SrcLinear( - HWORD X[], - HWORD Y[], + short X[], + short Y[], double factor, - UWORD *Time, - UHWORD& Nx, - UHWORD Nout) + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout) { - HWORD iconst; - HWORD *Xp, *Ystart; - WORD v,x1,x2; - - double dt; /* Step through input signal */ - UWORD dtb; /* Fixed-point version of Dt */ - UWORD endTime; /* When Time reaches EndTime, return to user */ - UWORD start_sample, end_sample; - - dt = 1.0/factor; /* Output sampling period */ - dtb = (UWORD)(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 */ + 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( - HWORD X[], - HWORD Y[], + short X[], + short Y[], double factor, - UWORD *Time, - UHWORD& Nx, - UHWORD Nout, - UHWORD Nwing, - UHWORD LpScl, - HWORD Imp[], - HWORD ImpD[], - BOOL Interp) + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout, + unsigned short Nwing, + unsigned short LpScl, + short Imp[], + short ImpD[], + bool Interp) { - HWORD *Xp, *Ystart; - WORD v; - - double dt; /* Step through input signal */ - UWORD dtb; /* Fixed-point version of Dt */ - UWORD endTime; /* When Time reaches EndTime, return to user */ - UWORD start_sample, end_sample; + short *Xp, *Ystart; + int v; - dt = 1.0/factor; /* Output sampling period */ - dtb = (UWORD)(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, (HWORD)(*Time&Pmask),-1); - /* Perform right-wing inner product */ - v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, - (HWORD)((-*Time)&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 */ + 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( - HWORD X[], - HWORD Y[], + short X[], + short Y[], double factor, - UWORD *Time, - UHWORD& Nx, - UHWORD Nout, - UHWORD Nwing, - UHWORD LpScl, - HWORD Imp[], - HWORD ImpD[], - BOOL Interp) + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout, + unsigned short Nwing, + unsigned short LpScl, + short Imp[], + short ImpD[], + bool Interp) { - HWORD *Xp, *Ystart; - WORD v; - - double dh; /* Step through filter impulse response */ - double dt; /* Step through input signal */ - UWORD endTime; /* When Time reaches EndTime, return to user */ - UWORD dhb, dtb; /* Fixed-point versions of Dh,Dt */ - UWORD start_sample, end_sample; + short *Xp, *Ystart; + int v; - dt = 1.0/factor; /* Output sampling period */ - dtb = (UWORD)(dt*(1<>Np; - Ystart = Y; - endTime = *Time + (1<>Np]; /* Ptr to current input sample */ - v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (HWORD)(*Time&Pmask), - -1, dhb); /* Perform left-wing inner product */ - v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (HWORD)((-*Time)&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 */ + 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 */ } @@ -408,17 +436,17 @@ int aflibConverter::resampleFast( /* number of output samples returned */ int& inCount, /* number of input samples to convert */ int outCount, /* number of output samples to compute */ - HWORD inArray[], /* input data */ - HWORD outArray[]) /* output data */ + short inArray[], /* input data */ + short outArray[]) /* output data */ { - UWORD Time2; /* Current time/pos in input sample */ + unsigned int Time2; /* Current time/pos in input sample */ #if 0 - UHWORD Ncreep; + unsigned short Ncreep; #endif - UHWORD Xp, Xoff, Xread; - int OBUFFSIZE = (int)(((double)IBUFFSIZE)*factor); - UHWORD Nout = 0, Nx; - UHWORD maxOutput; + 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; @@ -433,36 +461,39 @@ aflibConverter::resampleFast( /* number of output samples returned */ 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 - (UHWORD)(2*Xoff*factor); - else - maxOutput = outCount-Ycount; + if ((outCount-Ycount) > (OBUFFSIZE - (2*Xoff*_factor)) ) + maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor); + else + maxOutput = outCount-Ycount; - for (c = 0; c < nChans; c++) - { - Time2 = Time; + for (c = 0; c < _nChans; c++) + { + orig_Nx = Nx; + Time2 = _Time; /* Resample stuff in input buffer */ - Nout=SrcLinear(X[c],Y[c],factor,&Time2,Nx,maxOutput); - } - Time = Time2; + Nout=SrcLinear(_X[c],_Y[c],_factor,&Time2,orig_Nx,maxOutput); + } + Nx = orig_Nx; + _Time = Time2; - Time -= (Nx<>Np) - Xoff; /* Calc time accumulation in Time */ if (Ncreep) { @@ -470,36 +501,36 @@ aflibConverter::resampleFast( /* number of output samples returned */ Xp += Ncreep; /* and add it to read pointer */ } #endif - for (c = 0; c < nChans; c++) - { - for (i=0; ioutCount) { - Nout -= (Ycount-outCount); - Ycount = outCount; - } + Ycount += Nout; + if (Ycount>outCount) { + Nout -= (Ycount-outCount); + Ycount = outCount; + } - if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */ - return err_ret("Output array overflow"); + 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] = Y[c][i]; + for (c = 0; c < _nChans; c++) + for (i = 0; i < Nout; i++) + outArray[c * outCount + i + Ycount - Nout] = _Y[c][i]; - total_inCount += Nx; + total_inCount += Nx; - } while (Ycount (OBUFFSIZE - (2*Xoff*factor)) ) - maxOutput = OBUFFSIZE - (UHWORD)(2*Xoff*factor); - else - maxOutput = outCount-Ycount; + if ( (outCount-Ycount) > (OBUFFSIZE - (2*Xoff*_factor)) ) + maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor); + else + maxOutput = outCount-Ycount; - for (c = 0; c < nChans; c++) - { - Time2 = Time; + 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(X[c],Y[c],factor,&Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); - } - else { - Nout=SrcUD(X[c],Y[c],factor,&Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); - } - } - Time = Time2; + if (_factor >= 1) { /* SrcUp() is faster if we can use it */ + Nout=SrcUp(_X[c],_Y[c],_factor, + &Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); + } + else { + Nout=SrcUD(_X[c],_Y[c],_factor, + &Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); + } + } + _Time = Time2; - Time -= (Nx<>Np) - Xoff; /* Calc time accumulation in Time */ if (Ncreep) { @@ -588,148 +623,175 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */ Xp += Ncreep; /* and add it to read pointer */ } #endif - if (last) { /* If near end of sample... */ - last -= Xp; /* ...keep track were it ends */ - if (!last) /* Lengthen input by 1 sample if... */ - last++; /* ...needed to keep flag TRUE */ - } - - Ycount += Nout; - if (Ycount>outCount) { - Nout -= (Ycount-outCount); - Ycount = outCount; - } + if (last) { /* If near end of sample... */ + last -= Xp; /* ...keep track were it ends */ + if (!last) /* Lengthen input by 1 sample if... */ + last++; /* ...needed to keep flag TRUE */ + } + + Ycount += Nout; + if (Ycount > 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] = Y[c][i]; - } - } + 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] = _Y[c][i]; + } + } - int act_incount = (int)Nx; + 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[] */ + short *Hp, *Hdp = NULL, *End; + short a = 0; + int v, t; + + v=0; + Hp = &Imp[Ph>>Na]; + End = &Imp[Nwing]; + + if (Interp) + { + Hdp = &ImpD[Ph>>Na]; + a = Ph & Amask; } - } - if (Interp) - while (Hp < End) { - t = *Hp; /* Get filter coeff */ - t += (((WORD)*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); + + 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); } -WORD -aflibConverter::FilterUD( HWORD Imp[], HWORD ImpD[], - UHWORD Nwing, BOOL Interp, - HWORD *Xp, HWORD Ph, HWORD Inc, UHWORD dhb) +int +aflibConverter::FilterUD( + short Imp[], + short ImpD[], + unsigned short Nwing, + bool Interp, + short *Xp, + short Ph, + short Inc, + unsigned short dhb) { - HWORD a; - HWORD *Hp, *Hdp, *End; - WORD v, t; - UWORD Ho; - - v=0; - Ho = (Ph*(UWORD)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 += (((WORD)*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); + 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); } diff --git a/darkice/trunk/src/aflibConverter.h b/darkice/trunk/src/aflibConverter.h index e8d9500..3ab92f6 100644 --- a/darkice/trunk/src/aflibConverter.h +++ b/darkice/trunk/src/aflibConverter.h @@ -18,7 +18,7 @@ * Julius O. Smith jos@ccrma.stanford.edu * */ -/* This code was modified by Bruce Forsberg (forsberg@adnc.com) to make it +/* This code was modified by Bruce Forsberg (forsberg@tns.net) to make it into a C++ class */ @@ -26,6 +26,10 @@ #ifndef _AFLIBCONVERTER_H_ #define _AFLIBCONVERTER_H_ +#ifdef HAVE_CONFIG_H +#include +#endif + #ifndef MAX #define MAX(x,y) ((x)>(y) ?(x):(y)) #endif @@ -36,11 +40,6 @@ #define MAX_HWORD (32767) #define MIN_HWORD (-32768) -typedef char BOOL; -typedef short HWORD; -typedef unsigned short UHWORD; -typedef int WORD; -typedef unsigned int UWORD; #define IBUFFSIZE 4096 /* Input buffer size */ /*! \class aflibConverter @@ -58,18 +57,22 @@ typedef unsigned int UWORD; This class was designed to stream audio data. It also expects audio data as 16 bit values. Each time a new stream is started some initialization needs to be done. Thus the function - initialize should be called to initialize everything. This class will work on any - number of channels. Once everything is specified then resample should be called as many - times as is necessary to process all the data. The value inCount will be returned - indicating how many inArray samples were actually used to produce the output. This - value can be used to indicate where the next block of inArray data should start. The - resample function is driven by the outCount value specified. The inArray should - contain at least: + initialize should be called to initialize everything. This initialize function will set + the conversion factor as well as a multiplecation factor for volume. The volume only + applies to the small and large filter. Since this filter uses a history of the audio data + it is possible for it to vary in amplitude. This allows users to scale the data. This + class will work on any number of channels. Once everything is specified then resample + should be called as many times as is necessary to process all the data. The value + inCount will be returned indicating how many inArray samples were actually used to + produce the output. This value can be used to indicate where the next block of + inArray data should start. The resample function is driven by the outCount value + specified. The inArray should contain at least: outCount / factor + extra_samples. extra_samples depends on the type of filtering done. As a rule of thumb 50 should be adequate for any type of filter. */ +class aflibData; class aflibConverter { @@ -86,14 +89,15 @@ public: void initialize( double factor, /* factor = Sndout/Sndin */ - int channels);/* number of sound channels */ + int channels, /* number of sound channels */ + double volume = 1.0); /* factor to multiply amplitude */ int resample( /* number of output samples returned */ int& inCount, /* number of input samples to convert */ - int outCount, /* number of output samples to compute */ - HWORD inArray[], /* input array data (length inCount * nChans) */ - HWORD outArray[]);/* output array data (length outCount * nChans) */ + int outCount, /* number of output samples to compute */ + short inArray[], /* input array data (length inCount * nChans) */ + short outArray[]);/* output array data (length outCount * nChans) */ private: @@ -114,130 +118,117 @@ private: int readData( int inCount, /* _total_ number of frames in input file */ - HWORD inArray[], /* input data */ - HWORD *outPtr[], /* array receiving chan samps */ + short inArray[], /* input data */ + short *outPtr[], /* array receiving chan samps */ int dataArraySize, /* size of these arrays */ int Xoff, /* read into input array starting at this index */ bool init_count); - inline HWORD - WordToHword(WORD v, int scl) + inline short + WordToHword(int v, int scl) { - HWORD out; - WORD llsb = (1<<(scl-1)); + short out; + int llsb = (1<<(scl-1)); v += llsb; /* round */ v >>= scl; if (v>MAX_HWORD) { -#ifdef DEBUG - if (pof == 0) - fprintf(stderr, "*** resample: sound sample overflow\n"); - else if ((pof % 10000) == 0) - fprintf(stderr, "*** resample: another ten thousand overflows\n"); - pof++; -#endif v = MAX_HWORD; } else if (v < MIN_HWORD) { -#ifdef DEBUG - if (nof == 0) - fprintf(stderr, "*** resample: sound sample (-) overflow\n"); - else if ((nof % 1000) == 0) - fprintf(stderr, "*** resample: another thousand (-) overflows\n"); - nof++; -#endif v = MIN_HWORD; } - out = (HWORD) v; + out = (short) v; return out; }; int SrcLinear( - HWORD X[], - HWORD Y[], + short X[], + short Y[], double factor, - UWORD *Time, - UHWORD& Nx, - UHWORD Nout); + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout); int SrcUp( - HWORD X[], - HWORD Y[], + short X[], + short Y[], double factor, - UWORD *Time, - UHWORD& Nx, - UHWORD Nout, - UHWORD Nwing, - UHWORD LpScl, - HWORD Imp[], - HWORD ImpD[], - BOOL Interp); + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout, + unsigned short Nwing, + unsigned short LpScl, + short Imp[], + short ImpD[], + bool Interp); int SrcUD( - HWORD X[], - HWORD Y[], + short X[], + short Y[], double factor, - UWORD *Time, - UHWORD& Nx, - UHWORD Nout, - UHWORD Nwing, - UHWORD LpScl, - HWORD Imp[], - HWORD ImpD[], - BOOL Interp); + unsigned int *Time, + unsigned short& Nx, + unsigned short Nout, + unsigned short Nwing, + unsigned short LpScl, + short Imp[], + short ImpD[], + bool Interp); - WORD + int FilterUp( - HWORD Imp[], - HWORD ImpD[], - UHWORD Nwing, - BOOL Interp, - HWORD *Xp, - HWORD Ph, - HWORD Inc); + short Imp[], + short ImpD[], + unsigned short Nwing, + bool Interp, + short *Xp, + short Ph, + short Inc); - WORD + int FilterUD( - HWORD Imp[], - HWORD ImpD[], - UHWORD Nwing, - BOOL Interp, - HWORD *Xp, - HWORD Ph, - HWORD Inc, - UHWORD dhb); + short Imp[], + short ImpD[], + unsigned short Nwing, + bool Interp, + short *Xp, + short Ph, + short Inc, + unsigned short dhb); int resampleFast( /* number of output samples returned */ int& inCount, /* number of input samples to convert */ int outCount, /* number of output samples to compute */ - HWORD inArray[], /* input array data (length inCount * nChans) */ - HWORD outArray[]);/* output array data (length outCount * nChans) */ + short inArray[], /* input array data (length inCount * nChans) */ + short outArray[]);/* output array data (length outCount * nChans) */ int resampleWithFilter( /* number of output samples returned */ int& inCount, /* number of input samples to convert */ int outCount, /* number of output samples to compute */ - HWORD inArray[], /* input array data (length inCount * nChans) */ - HWORD outArray[], /* output array data (length outCount * nChans) */ - HWORD Imp[], HWORD ImpD[], - UHWORD LpScl, UHWORD Nmult, UHWORD Nwing); + short inArray[], /* input array data (length inCount * nChans) */ + short outArray[], /* output array data (length outCount * nChans) */ + short Imp[], short ImpD[], + unsigned short LpScl, unsigned short Nmult, unsigned short Nwing); -static HWORD SMALL_FILTER_IMP[]; -static HWORD LARGE_FILTER_IMP[]; +static short SMALL_FILTER_IMP[]; +static short LARGE_FILTER_IMP[]; bool interpFilt; bool largeFilter; bool linearInterp; -HWORD ** X; -HWORD ** Y; -UWORD Time; -double factor; -int nChans; -bool initial; +short ** _X; +short ** _Y; +unsigned int _Time; +double _factor; +int _nChans; +bool _initial; +double _vol; }; diff --git a/darkice/trunk/src/aflibConverterLargeFilter.h b/darkice/trunk/src/aflibConverterLargeFilter.h index 61f4642..5d5b05b 100644 --- a/darkice/trunk/src/aflibConverterLargeFilter.h +++ b/darkice/trunk/src/aflibConverterLargeFilter.h @@ -34,11 +34,16 @@ well for its level of computational expense. */ -#define LARGE_FILTER_NMULT ((HWORD)65) +#ifdef HAVE_CONFIG_H +#include +#endif + + +#define LARGE_FILTER_NMULT ((short)65) #define LARGE_FILTER_SCALE 14746 /* Unity-gain scale factor */ #define LARGE_FILTER_NWING 8192 /* Filter table length */ -HWORD aflibConverter::LARGE_FILTER_IMP[] /* Impulse response */ = { +short aflibConverter::LARGE_FILTER_IMP[] /* Impulse response */ = { 32767, 32766, 32764, @@ -8232,7 +8237,7 @@ HWORD aflibConverter::LARGE_FILTER_IMP[] /* Impulse response */ = { 0, 0}; -static HWORD LARGE_FILTER_IMPD[] /* Impulse response differences */ = { +static short LARGE_FILTER_IMPD[] /* Impulse response differences */ = { -1, -2, -3, diff --git a/darkice/trunk/src/aflibConverterSmallFilter.h b/darkice/trunk/src/aflibConverterSmallFilter.h index d1084d7..d7d6b71 100644 --- a/darkice/trunk/src/aflibConverterSmallFilter.h +++ b/darkice/trunk/src/aflibConverterSmallFilter.h @@ -19,11 +19,16 @@ * */ -#define SMALL_FILTER_NMULT ((HWORD)13) + +#ifdef HAVE_CONFIG_H +#include +#endif + +#define SMALL_FILTER_NMULT ((short)13) #define SMALL_FILTER_SCALE 13128 /* Unity-gain scale factor */ #define SMALL_FILTER_NWING 1536 /* Filter table length */ -HWORD aflibConverter::SMALL_FILTER_IMP[] /* Impulse response */ = { +short aflibConverter::SMALL_FILTER_IMP[] /* Impulse response */ = { 32767, 32766, 32764, @@ -1562,7 +1567,7 @@ HWORD aflibConverter::SMALL_FILTER_IMP[] /* Impulse response */ = { -1 }; -static HWORD SMALL_FILTER_IMPD[] = { +static short SMALL_FILTER_IMPD[] = { -1, -2, -4, diff --git a/darkice/trunk/src/aflibDebug.cc b/darkice/trunk/src/aflibDebug.cc new file mode 100644 index 0000000..d78aa01 --- /dev/null +++ b/darkice/trunk/src/aflibDebug.cc @@ -0,0 +1,228 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "aflibDebug.h" +#include +#include +#include +#include + +static int aflib_debug_level = ::aflibDebug::lInfo; +static bool aflib_debug_abort = false; +static const char *aflib_debug_prefix = ""; +static char *messageAppName = 0; + + +/* +static char* status_strs[] = +{ + "Success", + "Error Open", + "Unsupported", + "AFLIB_ERROR_INITIALIZATION_FAILURE", + "AFLIB_NOT_FOUND", + "AFLIB_END_OF_FILE", + "AFLIB_NO_DATA", + 0 +}; + + +static char* data_size_strs[] = +{ + "UNDEFINED", + "8 bit signed", + "8 bit unsigned", + "16 bit signed", + "16 bit unsigned", + "32 bit signed", + "32 bit unsigned", + 0 +}; + +static char* data_endian_strs[] = +{ + "UNDEFINED", + "ENDIAN_LITTLE", + "ENDIAN_BIG", + 0 +}; +*/ + +/* + * Call the graphical application to display a message, if + * defined. Otherwise, send to standard error. Debug messages are + * always sent to standard error because they tend to be very verbose. + * Note that the external application is run in the background to + * avoid blocking the sound server. + */ +void output_message(::aflibDebug::Level level, const char *msg) { + char buff[1024]; + + /* default to text output if no message app is defined or if it is a debug message. */ + if (messageAppName == 0 || !strcmp(messageAppName, "") || (level == ::aflibDebug::lDebug)) + { + fprintf(stderr, "%s\n", msg); + return; + } + + switch (level) { + case ::aflibDebug::lFatal: + sprintf(buff, "%s -e \"aflib fatal error:\n\n%s\" &", messageAppName, msg); + break; + case ::aflibDebug::lWarning: + sprintf(buff, "%s -w \"aflib warning message:\n\n%s\" &", messageAppName, msg); + break; + case ::aflibDebug::lInfo: + sprintf(buff, "%s -i \"aflib informational message:\n\n%s\" &", messageAppName, msg); + break; + default: + break; // avoid compile warning + } + system(buff); +} + +/* + * Display a message using output_message. If the message is the same + * as the previous one, just increment a count but don't display + * it. This prevents flooding the user with duplicate warnings. If the + * message is not the same as the previous one, then we report the + * previously repeated message (if any) and reset the last message and + * count. + */ +void display_message(::aflibDebug::Level level, const char *msg) { + static char lastMsg[1024]; + static ::aflibDebug::Level lastLevel; + static int msgCount = 0; + + if (!strncmp(msg, lastMsg, 1024)) + { + msgCount++; + } else { + if (msgCount > 0) + { + char buff[1024]; + sprintf(buff, "%s\n(The previous message was repeated %d times.)", lastMsg, msgCount); + output_message(lastLevel, buff); + } + + strncpy(lastMsg, msg, 1024); + lastLevel = level; + msgCount = 0; + output_message(level, msg); + } + +} + +static class DebugInitFromEnv { + + public: + DebugInitFromEnv() { + const char *env = getenv("AFLIB_DEBUG"); + if(env) + { + if(strcmp(env,"debug") == 0) + aflib_debug_level = ::aflibDebug::lDebug; + else if(strcmp(env,"info") == 0) + aflib_debug_level = ::aflibDebug::lInfo; + else if(strcmp(env,"warning") == 0) + aflib_debug_level = ::aflibDebug::lWarning; + else if(strcmp(env,"quiet") == 0) + aflib_debug_level = ::aflibDebug::lFatal; + else + { + fprintf(stderr, + "AFLIB_DEBUG must be one of debug,info,warning,quiet\n"); + } + } + + env = getenv("AFLIB_DEBUG_ABORT"); + if(env) + aflib_debug_abort = true; + } +} + +debugInitFromEnv; + + +void aflibDebug::init(const char *prefix, Level level) +{ + aflib_debug_level = level; + aflib_debug_prefix = prefix; +} + +void aflibDebug::fatal(const char *fmt, ...) +{ + char buff[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + display_message(::aflibDebug::lFatal, buff); + + if(aflib_debug_abort) abort(); + exit(1); +} + +void aflibDebug::warning(const char *fmt, ...) +{ + if(lWarning >= aflib_debug_level) + { + char buff[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + display_message(::aflibDebug::lWarning, buff); + } +} + +void aflibDebug::info(const char *fmt, ...) +{ + if(lInfo >= aflib_debug_level) + { + char buff[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + display_message(::aflibDebug::lInfo, buff); + } +} + +void aflibDebug::debug(const char *fmt, ...) +{ + if(lDebug >= aflib_debug_level) + { + char buff[1024]; + va_list ap; + va_start(ap, fmt); + vsprintf(buff, fmt, ap); + va_end(ap); + display_message(::aflibDebug::lDebug, buff); + } +} + +void aflibDebug::messageApp(const char *appName) +{ + messageAppName = (char*) realloc(messageAppName, strlen(appName)+1); + strcpy(messageAppName, appName); +} diff --git a/darkice/trunk/src/aflibDebug.h b/darkice/trunk/src/aflibDebug.h new file mode 100644 index 0000000..ea7dd99 --- /dev/null +++ b/darkice/trunk/src/aflibDebug.h @@ -0,0 +1,118 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + + Some inspiration taken from glib. + Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + Modified by the GLib Team and others 1997-1999. + + */ + +#ifndef _AFLIBDEBUG_H_ +#define _AFLIBDEBUG_H_ + +/* + * BC - Status (2000-09-30): Debug. + * + * Collection class, no instance, no members. Thus binary compatible (will + * be kept). + */ + +#define aflib_fatal ::aflibDebug::fatal +#define aflib_warning ::aflibDebug::warning +#define aflib_info ::aflibDebug::info +#define aflib_debug ::aflibDebug::debug + +/* source compatibility with older sources */ +#define aflibdebug ::aflibDebug::debug +#define setaflibdebug(x) aflib_warning("setaflibdebug is obsolete") + +#ifdef __GNUC__ + +#define aflib_return_if_fail(expr) \ + if (!(expr)) \ + { \ + aflib_warning ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + return; \ + } + +#define aflib_return_val_if_fail(expr,val) \ + if (!(expr)) \ + { \ + aflib_warning ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + return (val); \ + } + +#define aflib_assert(expr) \ + if (!(expr)) \ + aflib_fatal ("file %s: line %d (%s): assertion failed: (%s)", \ + __FILE__, __LINE__, __PRETTY_FUNCTION__, #expr); \ + +#else + +#define aflib_return_if_fail(expr) \ + if (!(expr)) \ + { \ + aflib_warning ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + return; \ + } + +#define aflib_return_val_if_fail(expr,val) \ + if (!(expr)) \ + { \ + aflib_warning ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + return (val); \ + } + +#define aflib_assert(expr) \ + if (!(expr)) \ + aflib_fatal ("file %s: line %d: assertion failed: (%s)", \ + __FILE__, __LINE__, #expr); \ + +#endif + +class aflibDebug { + public: + enum Level { lFatal = 3, lWarning = 2, lInfo = 1, lDebug = 0 }; + + /** + * Initializes at which is the minimum level to react to. If you + * call this, call this before creating the Arts::Dispatcher object. + */ + static void init(const char *prefix, Level level); + + static void fatal(const char *fmt,...); // print on stderr & abort + static void warning(const char *fmt,...); // print on stderr + static void info(const char *fmt,...); // print on stdout + static void debug(const char *fmt,...); // print on stdout + + /** + * This method sets the name of an external application to + * display messages graphically. + */ + static void messageApp(const char *appName); + + }; + +#endif