updated imported aflib sources to OSALP 7.3

This commit is contained in:
darkeye 2002-08-03 10:28:56 +00:00
parent e4da2d70b8
commit 374763d680
7 changed files with 895 additions and 484 deletions

View File

@ -29,6 +29,8 @@ darkice_SOURCES = AudioEncoder.h\
LameLibEncoder.h\ LameLibEncoder.h\
VorbisLibEncoder.cpp\ VorbisLibEncoder.cpp\
VorbisLibEncoder.h\ VorbisLibEncoder.h\
aflibDebug.h\
aflibDebug.cc\
aflibConverter.h\ aflibConverter.h\
aflibConverter.cc\ aflibConverter.cc\
aflibConverterLargeFilter.h\ aflibConverterLargeFilter.h\

View File

@ -18,10 +18,13 @@
* Julius O. Smith jos@ccrma.stanford.edu * 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 into a C++ class
*/ */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -32,6 +35,7 @@
#include "aflibConverterLargeFilter.h" #include "aflibConverterLargeFilter.h"
#include "aflibConverterSmallFilter.h" #include "aflibConverterSmallFilter.h"
#include "aflibDebug.h"
#if (!defined(TRUE) || !defined(FALSE)) #if (!defined(TRUE) || !defined(FALSE))
# define TRUE 1 # define TRUE 1
@ -112,12 +116,16 @@ aflibConverter::aflibConverter(
bool linear_interpolation, bool linear_interpolation,
bool filter_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; interpFilt = filter_interpolation;
largeFilter = high_quality; largeFilter = high_quality;
linearInterp = linear_interpolation; linearInterp = linear_interpolation;
X = NULL; _X = NULL;
Y = NULL; _Y = NULL;
_vol = 1.0;
} }
aflibConverter::~aflibConverter() aflibConverter::~aflibConverter()
@ -131,65 +139,65 @@ aflibConverter::deleteMemory()
{ {
int i; int i;
// Delete memory for the input and output arrays // 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]; delete [] _X[i];
X[i] = NULL; _X[i] = NULL;
delete [] Y[i]; delete [] _Y[i];
Y[i] = NULL; _Y[i] = NULL;
} }
delete [] X; delete [] _X;
X = NULL; _X = NULL;
delete [] Y; delete [] _Y;
Y = NULL; _Y = NULL;
} }
} }
void void
aflibConverter::initialize( aflibConverter::initialize(
double fac, double fac,
int channels) int channels,
double volume)
{ {
// This function will allow one to stream data. When a new data stream is to // 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 // 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 // of channels don't change. Otherwise each new data block sent to resample
// will be considered part of the previous data block. // 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; int i;
// Delete all previous allocated input and output buffer memory // Delete all previous allocated input and output buffer memory
deleteMemory(); deleteMemory();
factor = fac; _factor = fac;
nChans = channels; _nChans = channels;
initial = TRUE; _initial = TRUE;
_vol = volume;
// Allocate all new memory // Allocate all new memory
X = new HWORD * [nChans]; _X = new short * [_nChans];
Y = new HWORD * [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) // Add extra to allow of offset of input data (Xoff in main routine)
X[i] = new HWORD[IBUFFSIZE + 256]; _X[i] = new short[IBUFFSIZE + 256];
Y[i] = new HWORD[(int)(((double)IBUFFSIZE)*factor)]; _Y[i] = new short[(int)(((double)IBUFFSIZE)*_factor)];
memset(X[i], 0, sizeof(HWORD) * (IBUFFSIZE + 256)); memset(_X[i], 0, sizeof(short) * (IBUFFSIZE + 256));
} }
} }
int int
aflibConverter::resample( /* number of output samples returned */ aflibConverter::resample( /* number of output samples returned */
int& inCount, /* number of input samples to convert */ int& inCount, /* number of input samples to convert */
int outCount, /* number of output samples to compute */ int outCount, /* number of output samples to compute */
HWORD inArray[], /* input data */ short inArray[], /* input data */
HWORD outArray[]) /* output data */ short outArray[]) /* output data */
{ {
int Ycount; int Ycount;
@ -200,40 +208,42 @@ aflibConverter::resample( /* number of output samples returned */
// Use small filtering. Good qulaity // Use small filtering. Good qulaity
else if (largeFilter == FALSE) else if (largeFilter == FALSE)
Ycount = resampleWithFilter(inCount,outCount,inArray,outArray, 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); SMALL_FILTER_NMULT, SMALL_FILTER_NWING);
// Use large filtering Great quality // Use large filtering Great quality
else else
Ycount = resampleWithFilter(inCount,outCount,inArray,outArray, 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); LARGE_FILTER_NMULT, LARGE_FILTER_NWING);
initial = FALSE; _initial = FALSE;
return (Ycount); return (Ycount);
} }
int int
aflibConverter::err_ret(char *s) 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; return -1;
} }
int int
aflibConverter::readData( aflibConverter::readData(
int inCount, /* _total_ number of frames in input file */ int inCount, /* _total_ number of frames in input file */
HWORD inArray[], /* input data */ short inArray[], /* input data */
HWORD *outPtr[], /* array receiving chan samps */ short *outPtr[], /* array receiving chan samps */
int dataArraySize, /* size of these arrays */ int dataArraySize, /* size of these arrays */
int Xoff, /* read into input array starting at this index */ int Xoff, /* read into input array starting at this index */
bool init_count) bool init_count)
{ {
int i, Nsamps, c; int i, Nsamps, c;
static unsigned int framecount; /* frames previously read */ static unsigned int framecount; /* frames previously read */
HWORD *ptr; short *ptr;
if (init_count == TRUE) if (init_count == TRUE)
framecount = 0; /* init this too */ framecount = 0; /* init this too */
@ -246,13 +256,13 @@ aflibConverter::readData(
Nsamps = inCount - framecount; Nsamps = inCount - framecount;
} }
for (c = 0; c < nChans; c++) for (c = 0; c < _nChans; c++)
{ {
ptr = outPtr[c]; ptr = outPtr[c];
ptr += Xoff; /* Start at designated sample number */ ptr += Xoff; /* Start at designated sample number */
for (i = 0; i < Nsamps; i++) for (i = 0; i < Nsamps; i++)
*ptr++ = (HWORD) inArray[c * inCount + i + framecount]; *ptr++ = (short) inArray[c * inCount + i + framecount];
} }
framecount += Nsamps; framecount += Nsamps;
@ -263,32 +273,37 @@ aflibConverter::readData(
return 0; return 0;
} }
int int
aflibConverter::SrcLinear( aflibConverter::SrcLinear(
HWORD X[], short X[],
HWORD Y[], short Y[],
double factor, double factor,
UWORD *Time, unsigned int *Time,
UHWORD& Nx, unsigned short& Nx,
UHWORD Nout) unsigned short Nout)
{ {
HWORD iconst; short iconst;
HWORD *Xp, *Ystart; short *Xp, *Ystart;
WORD v,x1,x2; int v,x1,x2;
double dt; /* Step through input signal */ double dt; /* Step through input signal */
UWORD dtb; /* Fixed-point version of Dt */ unsigned int dtb; /* Fixed-point version of Dt */
UWORD endTime; /* When Time reaches EndTime, return to user */ // unsigned int endTime; /* When Time reaches EndTime, return to user */
UWORD start_sample, end_sample; unsigned int start_sample, end_sample;
dt = 1.0/factor; /* Output sampling period */ dt = 1.0/factor; /* Output sampling period */
dtb = (UWORD)(dt*(1<<Np) + 0.5); /* Fixed-point representation */ dtb = (unsigned int)(dt*(1<<Np) + 0.5); /* Fixed-point representation */
start_sample = (*Time)>>Np; start_sample = (*Time)>>Np;
Ystart = Y; Ystart = Y;
endTime = *Time + (1<<Np)*(WORD)Nx; // endTime = *Time + (1<<Np)*(int)Nx;
/*
* TODO
* DAS: not sure why this was changed from *Time < endTime
* update: *Time < endTime causes seg fault. Also adds a clicking sound.
*/
while (Y - Ystart != Nout) while (Y - Ystart != Nout)
// while (*Time < endTime)
{ {
iconst = (*Time) & Pmask; iconst = (*Time) & Pmask;
Xp = &X[(*Time)>>Np]; /* Ptr to current input sample */ Xp = &X[(*Time)>>Np]; /* Ptr to current input sample */
@ -308,40 +323,46 @@ aflibConverter::SrcLinear(
int int
aflibConverter::SrcUp( aflibConverter::SrcUp(
HWORD X[], short X[],
HWORD Y[], short Y[],
double factor, double factor,
UWORD *Time, unsigned int *Time,
UHWORD& Nx, unsigned short& Nx,
UHWORD Nout, unsigned short Nout,
UHWORD Nwing, unsigned short Nwing,
UHWORD LpScl, unsigned short LpScl,
HWORD Imp[], short Imp[],
HWORD ImpD[], short ImpD[],
BOOL Interp) bool Interp)
{ {
HWORD *Xp, *Ystart; short *Xp, *Ystart;
WORD v; int v;
double dt; /* Step through input signal */ double dt; /* Step through input signal */
UWORD dtb; /* Fixed-point version of Dt */ unsigned int dtb; /* Fixed-point version of Dt */
UWORD endTime; /* When Time reaches EndTime, return to user */ // unsigned int endTime; /* When Time reaches EndTime, return to user */
UWORD start_sample, end_sample; unsigned int start_sample, end_sample;
dt = 1.0/factor; /* Output sampling period */ dt = 1.0/factor; /* Output sampling period */
dtb = (UWORD)(dt*(1<<Np) + 0.5); /* Fixed-point representation */ dtb = (unsigned int)(dt*(1<<Np) + 0.5); /* Fixed-point representation */
start_sample = (*Time)>>Np; start_sample = (*Time)>>Np;
Ystart = Y; Ystart = Y;
endTime = *Time + (1<<Np)*(WORD)Nx; // endTime = *Time + (1<<Np)*(int)Nx;
/*
* TODO
* DAS: not sure why this was changed from *Time < endTime
* update: *Time < endTime causes seg fault. Also adds a clicking sound.
*/
while (Y - Ystart != Nout) while (Y - Ystart != Nout)
// while (*Time < endTime)
{ {
Xp = &X[*Time>>Np]; /* Ptr to current input sample */ Xp = &X[*Time>>Np]; /* Ptr to current input sample */
/* Perform left-wing inner product */ /* Perform left-wing inner product */
v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, (HWORD)(*Time&Pmask),-1); v = FilterUp(Imp, ImpD, Nwing, Interp, Xp, (short)(*Time&Pmask),-1);
/* Perform right-wing inner product */ /* Perform right-wing inner product */
v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1, v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1,
(HWORD)((-*Time)&Pmask),1); (short)((((*Time)^Pmask)+1)&Pmask), 1);
v >>= Nhg; /* Make guard bits */ v >>= Nhg; /* Make guard bits */
v *= LpScl; /* Normalize for unity filter gain */ v *= LpScl; /* Normalize for unity filter gain */
*Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */
@ -356,48 +377,55 @@ aflibConverter::SrcUp(
int int
aflibConverter::SrcUD( aflibConverter::SrcUD(
HWORD X[], short X[],
HWORD Y[], short Y[],
double factor, double factor,
UWORD *Time, unsigned int *Time,
UHWORD& Nx, unsigned short& Nx,
UHWORD Nout, unsigned short Nout,
UHWORD Nwing, unsigned short Nwing,
UHWORD LpScl, unsigned short LpScl,
HWORD Imp[], short Imp[],
HWORD ImpD[], short ImpD[],
BOOL Interp) bool Interp)
{ {
HWORD *Xp, *Ystart; short *Xp, *Ystart;
WORD v; int v;
double dh; /* Step through filter impulse response */ double dh; /* Step through filter impulse response */
double dt; /* Step through input signal */ double dt; /* Step through input signal */
UWORD endTime; /* When Time reaches EndTime, return to user */ // unsigned int endTime; /* When Time reaches EndTime, return to user */
UWORD dhb, dtb; /* Fixed-point versions of Dh,Dt */ unsigned int dhb, dtb; /* Fixed-point versions of Dh,Dt */
UWORD start_sample, end_sample; unsigned int start_sample, end_sample;
dt = 1.0/factor; /* Output sampling period */ dt = 1.0/factor; /* Output sampling period */
dtb = (UWORD)(dt*(1<<Np) + 0.5); /* Fixed-point representation */ dtb = (unsigned int)(dt*(1<<Np) + 0.5); /* Fixed-point representation */
dh = MIN(Npc, factor*Npc); /* Filter sampling period */ dh = MIN(Npc, factor*Npc); /* Filter sampling period */
dhb = (UWORD)(dh*(1<<Na) + 0.5); /* Fixed-point representation */ dhb = (unsigned int)(dh*(1<<Na) + 0.5); /* Fixed-point representation */
start_sample = (*Time)>>Np; start_sample = (*Time)>>Np;
Ystart = Y; Ystart = Y;
endTime = *Time + (1<<Np)*(WORD)Nx; // endTime = *Time + (1<<Np)*(int)Nx;
/*
* TODO
* DAS: not sure why this was changed from *Time < endTime
* update: *Time < endTime causes seg fault. Also adds a clicking sound.
*/
while (Y - Ystart != Nout) while (Y - Ystart != Nout)
// while (*Time < endTime)
{ {
Xp = &X[*Time>>Np]; /* Ptr to current input sample */ Xp = &X[*Time>>Np]; /* Ptr to current input sample */
v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (HWORD)(*Time&Pmask), v = FilterUD(Imp, ImpD, Nwing, Interp, Xp, (short)(*Time&Pmask),
-1, dhb); /* Perform left-wing inner product */ -1, dhb); /* Perform left-wing inner product */
v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (HWORD)((-*Time)&Pmask), v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1,
1, dhb); /* Perform right-wing inner product */ (short)((((*Time)^Pmask)+1)&Pmask), 1, dhb); /* Perform right-wing inner product */
v >>= Nhg; /* Make guard bits */ v >>= Nhg; /* Make guard bits */
v *= LpScl; /* Normalize for unity filter gain */ v *= LpScl; /* Normalize for unity filter gain */
*Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */ *Y++ = WordToHword(v,NLpScl); /* strip guard bits, deposit output */
*Time += dtb; /* Move to next sample by time increment */ *Time += dtb; /* Move to next sample by time increment */
} }
end_sample = (*Time)>>Np; end_sample = (*Time)>>Np;
Nx = end_sample - start_sample; Nx = end_sample - start_sample;
return (Y - Ystart); /* Return the number of output samples */ return (Y - Ystart); /* Return the number of output samples */
@ -408,17 +436,17 @@ int
aflibConverter::resampleFast( /* number of output samples returned */ aflibConverter::resampleFast( /* number of output samples returned */
int& inCount, /* number of input samples to convert */ int& inCount, /* number of input samples to convert */
int outCount, /* number of output samples to compute */ int outCount, /* number of output samples to compute */
HWORD inArray[], /* input data */ short inArray[], /* input data */
HWORD outArray[]) /* output data */ short outArray[]) /* output data */
{ {
UWORD Time2; /* Current time/pos in input sample */ unsigned int Time2; /* Current time/pos in input sample */
#if 0 #if 0
UHWORD Ncreep; unsigned short Ncreep;
#endif #endif
UHWORD Xp, Xoff, Xread; unsigned short Xp, Xoff, Xread;
int OBUFFSIZE = (int)(((double)IBUFFSIZE)*factor); int OBUFFSIZE = (int)(((double)IBUFFSIZE)*_factor);
UHWORD Nout = 0, Nx; unsigned short Nout = 0, Nx, orig_Nx;
UHWORD maxOutput; unsigned short maxOutput;
int total_inCount = 0; int total_inCount = 0;
int c, i, Ycount, last; int c, i, Ycount, last;
bool first_pass = TRUE; bool first_pass = TRUE;
@ -433,13 +461,14 @@ aflibConverter::resampleFast( /* number of output samples returned */
Xp = Xoff; /* Current "now"-sample pointer for input */ Xp = Xoff; /* Current "now"-sample pointer for input */
Xread = Xoff; /* Position in input array to read into */ Xread = Xoff; /* Position in input array to read into */
if (initial == TRUE) if (_initial == TRUE)
Time = (Xoff<<Np); /* Current-time pointer for converter */ _Time = (Xoff<<Np); /* Current-time pointer for converter */
do { do {
if (!last) /* If haven't read last sample yet */ if (!last) /* If haven't read last sample yet */
{ {
last = readData(inCount, inArray, X, IBUFFSIZE, (int)Xread,first_pass); last = readData(inCount, inArray, _X,
IBUFFSIZE, (int)Xread,first_pass);
first_pass = FALSE; first_pass = FALSE;
if (last && (last-Xoff<Nx)) { /* If last sample has been read... */ if (last && (last-Xoff<Nx)) { /* If last sample has been read... */
Nx = last-Xoff; /* ...calc last sample affected by filter */ Nx = last-Xoff; /* ...calc last sample affected by filter */
@ -448,20 +477,22 @@ aflibConverter::resampleFast( /* number of output samples returned */
} }
} }
if ((outCount-Ycount) > (OBUFFSIZE - (2*Xoff*factor)) ) if ((outCount-Ycount) > (OBUFFSIZE - (2*Xoff*_factor)) )
maxOutput = OBUFFSIZE - (UHWORD)(2*Xoff*factor); maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor);
else else
maxOutput = outCount-Ycount; maxOutput = outCount-Ycount;
for (c = 0; c < nChans; c++) for (c = 0; c < _nChans; c++)
{ {
Time2 = Time; orig_Nx = Nx;
Time2 = _Time;
/* Resample stuff in input buffer */ /* Resample stuff in input buffer */
Nout=SrcLinear(X[c],Y[c],factor,&Time2,Nx,maxOutput); Nout=SrcLinear(_X[c],_Y[c],_factor,&Time2,orig_Nx,maxOutput);
} }
Time = Time2; Nx = orig_Nx;
_Time = Time2;
Time -= (Nx<<Np); /* Move converter Nx samples back in time */ _Time -= (Nx<<Np); /* Move converter Nx samples back in time */
Xp += Nx; /* Advance by number of samples processed */ Xp += Nx; /* Advance by number of samples processed */
#if 0 #if 0
Ncreep = (Time>>Np) - Xoff; /* Calc time accumulation in Time */ Ncreep = (Time>>Np) - Xoff; /* Calc time accumulation in Time */
@ -470,10 +501,10 @@ aflibConverter::resampleFast( /* number of output samples returned */
Xp += Ncreep; /* and add it to read pointer */ Xp += Ncreep; /* and add it to read pointer */
} }
#endif #endif
for (c = 0; c < nChans; c++) for (c = 0; c < _nChans; c++)
{ {
for (i=0; i<IBUFFSIZE-Xp+Xoff; i++) { /* Copy part of input signal */ for (i=0; i<IBUFFSIZE-Xp+Xoff; i++) { /* Copy part of input signal */
X[c][i] = X[c][i+Xp-Xoff]; /* that must be re-used */ _X[c][i] = _X[c][i+Xp-Xoff]; /* that must be re-used */
} }
} }
if (last) { /* If near end of sample... */ if (last) { /* If near end of sample... */
@ -493,13 +524,13 @@ aflibConverter::resampleFast( /* number of output samples returned */
if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */ if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */
return err_ret("Output array overflow"); return err_ret("Output array overflow");
for (c = 0; c < nChans; c++) for (c = 0; c < _nChans; c++)
for (i = 0; i < Nout; i++) for (i = 0; i < Nout; i++)
outArray[c * outCount + i + Ycount - Nout] = Y[c][i]; outArray[c * outCount + i + Ycount - Nout] = _Y[c][i];
total_inCount += Nx; total_inCount += Nx;
} while (Ycount<outCount); /* Continue until done */ } while (Ycount < outCount); /* Continue until done */
inCount = total_inCount; inCount = total_inCount;
@ -511,30 +542,30 @@ int
aflibConverter::resampleWithFilter( /* number of output samples returned */ aflibConverter::resampleWithFilter( /* number of output samples returned */
int& inCount, /* number of input samples to convert */ int& inCount, /* number of input samples to convert */
int outCount, /* number of output samples to compute */ int outCount, /* number of output samples to compute */
HWORD inArray[], /* input data */ short inArray[], /* input data */
HWORD outArray[], /* output data */ short outArray[], /* output data */
HWORD Imp[], HWORD ImpD[], short Imp[], short ImpD[],
UHWORD LpScl, UHWORD Nmult, UHWORD Nwing) unsigned short LpScl, unsigned short Nmult, unsigned short Nwing)
{ {
UWORD Time2; /* Current time/pos in input sample */ unsigned int Time2; /* Current time/pos in input sample */
#if 0 #if 0
UHWORD Ncreep; unsigned short Ncreep;
#endif #endif
UHWORD Xp, Xoff, Xread; unsigned short Xp, Xoff, Xread;
int OBUFFSIZE = (int)(((double)IBUFFSIZE)*factor); int OBUFFSIZE = (int)(((double)IBUFFSIZE)*_factor);
UHWORD Nout = 0, Nx; unsigned short Nout = 0, Nx, orig_Nx;
UHWORD maxOutput; unsigned short maxOutput;
int total_inCount = 0; int total_inCount = 0;
int c, i, Ycount, last; int c, i, Ycount, last;
bool first_pass = TRUE; bool first_pass = TRUE;
/* Account for increased filter gain when using factors less than 1 */ /* Account for increased filter gain when using factors less than 1 */
if (factor < 1) if (_factor < 1)
LpScl = (UHWORD)(LpScl*factor + 0.5); LpScl = (unsigned short)(LpScl*_factor + 0.5);
/* Calc reach of LP filter wing & give some creeping room */ /* Calc reach of LP filter wing & give some creeping room */
Xoff = (UHWORD)(((Nmult+1)/2.0) * MAX(1.0,1.0/factor) + 10); Xoff = (unsigned short)(((Nmult+1)/2.0) * MAX(1.0,1.0/_factor) + 10);
if (IBUFFSIZE < 2*Xoff) /* Check input buffer size */ if (IBUFFSIZE < 2*Xoff) /* Check input buffer size */
return err_ret("IBUFFSIZE (or factor) is too small"); return err_ret("IBUFFSIZE (or factor) is too small");
@ -546,13 +577,14 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */
Xp = Xoff; /* Current "now"-sample pointer for input */ Xp = Xoff; /* Current "now"-sample pointer for input */
Xread = Xoff; /* Position in input array to read into */ Xread = Xoff; /* Position in input array to read into */
if (initial == TRUE) if (_initial == TRUE)
Time = (Xoff<<Np); /* Current-time pointer for converter */ _Time = (Xoff<<Np); /* Current-time pointer for converter */
do { do {
if (!last) /* If haven't read last sample yet */ if (!last) /* If haven't read last sample yet */
{ {
last = readData(inCount, inArray, X, IBUFFSIZE, (int)Xread,first_pass); last = readData(inCount, inArray, _X,
IBUFFSIZE, (int)Xread,first_pass);
first_pass = FALSE; first_pass = FALSE;
if (last && (last-Xoff<Nx)) { /* If last sample has been read... */ if (last && (last-Xoff<Nx)) { /* If last sample has been read... */
Nx = last-Xoff; /* ...calc last sample affected by filter */ Nx = last-Xoff; /* ...calc last sample affected by filter */
@ -561,25 +593,28 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */
} }
} }
if ( (outCount-Ycount) > (OBUFFSIZE - (2*Xoff*factor)) ) if ( (outCount-Ycount) > (OBUFFSIZE - (2*Xoff*_factor)) )
maxOutput = OBUFFSIZE - (UHWORD)(2*Xoff*factor); maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor);
else else
maxOutput = outCount-Ycount; maxOutput = outCount-Ycount;
for (c = 0; c < nChans; c++) for (c = 0; c < _nChans; c++)
{ {
Time2 = Time; orig_Nx = Nx;
Time2 = _Time;
/* Resample stuff in input buffer */ /* Resample stuff in input buffer */
if (factor >= 1) { /* SrcUp() is faster if we can use it */ 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); Nout=SrcUp(_X[c],_Y[c],_factor,
&Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt);
} }
else { else {
Nout=SrcUD(X[c],Y[c],factor,&Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt); Nout=SrcUD(_X[c],_Y[c],_factor,
&Time2,Nx,maxOutput,Nwing,LpScl,Imp,ImpD,interpFilt);
} }
} }
Time = Time2; _Time = Time2;
Time -= (Nx<<Np); /* Move converter Nx samples back in time */ _Time -= (Nx<<Np); /* Move converter Nx samples back in time */
Xp += Nx; /* Advance by number of samples processed */ Xp += Nx; /* Advance by number of samples processed */
#if 0 #if 0
Ncreep = (Time>>Np) - Xoff; /* Calc time accumulation in Time */ Ncreep = (Time>>Np) - Xoff; /* Calc time accumulation in Time */
@ -595,28 +630,28 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */
} }
Ycount += Nout; Ycount += Nout;
if (Ycount>outCount) { if (Ycount > outCount) {
Nout -= (Ycount-outCount); Nout -= (Ycount - outCount);
Ycount = outCount; Ycount = outCount;
} }
if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */ if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */
return err_ret("Output array overflow"); return err_ret("Output array overflow");
for (c = 0; c < nChans; c++) for (c = 0; c < _nChans; c++)
{ {
for (i = 0; i < Nout; i++) for (i = 0; i < Nout; i++)
{ {
outArray[c * outCount + i + Ycount - Nout] = Y[c][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 (c = 0; c < _nChans; c++)
{ {
for (i=0; i<IBUFFSIZE-act_incount+Xoff; i++) { /* Copy part of input signal */ for (i=0; i<IBUFFSIZE-act_incount+Xoff; i++) { /* Copy part of input signal */
X[c][i] = X[c][i+act_incount]; /* that must be re-used */ _X[c][i] = _X[c][i+act_incount]; /* that must be re-used */
} }
} }
Xread = IBUFFSIZE - Nx; /* Pos in input buff to read new data into */ Xread = IBUFFSIZE - Nx; /* Pos in input buff to read new data into */
@ -624,30 +659,37 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */
total_inCount += Nx; total_inCount += Nx;
} while (Ycount<outCount); /* Continue until done */ } while (Ycount < outCount); /* Continue until done */
inCount = total_inCount; inCount = total_inCount;
return(Ycount); /* Return # of samples in output file */ return(Ycount); /* Return # of samples in output file */
} }
int
WORD aflibConverter::FilterUp(
aflibConverter::FilterUp(HWORD Imp[], HWORD ImpD[], short Imp[],
UHWORD Nwing, BOOL Interp, short ImpD[],
HWORD *Xp, HWORD Ph, HWORD Inc) unsigned short Nwing,
bool Interp,
short *Xp,
short Ph,
short Inc)
{ {
HWORD *Hp, *Hdp = NULL, *End; short *Hp, *Hdp = NULL, *End;
HWORD a = 0; short a = 0;
WORD v, t; int v, t;
v=0; v=0;
Hp = &Imp[Ph>>Na]; Hp = &Imp[Ph>>Na];
End = &Imp[Nwing]; End = &Imp[Nwing];
if (Interp) {
if (Interp)
{
Hdp = &ImpD[Ph>>Na]; Hdp = &ImpD[Ph>>Na];
a = Ph & Amask; a = Ph & Amask;
} }
if (Inc == 1) /* If doing right wing... */ if (Inc == 1) /* If doing right wing... */
{ /* ...drop extra coeff, so when Ph is */ { /* ...drop extra coeff, so when Ph is */
End--; /* 0.5, we don't do too many mult's */ End--; /* 0.5, we don't do too many mult's */
@ -657,10 +699,13 @@ aflibConverter::FilterUp(HWORD Imp[], HWORD ImpD[],
Hdp += Npc; /* skip ahead in Imp[] and ImpD[] */ Hdp += Npc; /* skip ahead in Imp[] and ImpD[] */
} }
} }
if (Interp) if (Interp)
while (Hp < End) { {
while (Hp < End)
{
t = *Hp; /* Get filter coeff */ t = *Hp; /* Get filter coeff */
t += (((WORD)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */ t += (((int)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */
Hdp += Npc; /* Filter coeff differences step */ Hdp += Npc; /* Filter coeff differences step */
t *= *Xp; /* Mult coeff by input sample */ t *= *Xp; /* Mult coeff by input sample */
if (t & (1<<(Nhxn-1))) /* Round, if needed */ if (t & (1<<(Nhxn-1))) /* Round, if needed */
@ -670,8 +715,11 @@ aflibConverter::FilterUp(HWORD Imp[], HWORD ImpD[],
Hp += Npc; /* Filter coeff step */ Hp += Npc; /* Filter coeff step */
Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */
} }
}
else else
while (Hp < End) { {
while (Hp < End)
{
t = *Hp; /* Get filter coeff */ t = *Hp; /* Get filter coeff */
t *= *Xp; /* Mult coeff by input sample */ t *= *Xp; /* Mult coeff by input sample */
if (t & (1<<(Nhxn-1))) /* Round, if needed */ if (t & (1<<(Nhxn-1))) /* Round, if needed */
@ -681,22 +729,29 @@ aflibConverter::FilterUp(HWORD Imp[], HWORD ImpD[],
Hp += Npc; /* Filter coeff step */ Hp += Npc; /* Filter coeff step */
Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */
} }
}
return(v); return(v);
} }
WORD int
aflibConverter::FilterUD( HWORD Imp[], HWORD ImpD[], aflibConverter::FilterUD(
UHWORD Nwing, BOOL Interp, short Imp[],
HWORD *Xp, HWORD Ph, HWORD Inc, UHWORD dhb) short ImpD[],
unsigned short Nwing,
bool Interp,
short *Xp,
short Ph,
short Inc,
unsigned short dhb)
{ {
HWORD a; short a;
HWORD *Hp, *Hdp, *End; short *Hp, *Hdp, *End;
WORD v, t; int v, t;
UWORD Ho; unsigned int Ho;
v=0; v=0;
Ho = (Ph*(UWORD)dhb)>>Np; Ho = (Ph*(unsigned int)dhb)>>Np;
End = &Imp[Nwing]; End = &Imp[Nwing];
if (Inc == 1) /* If doing right wing... */ if (Inc == 1) /* If doing right wing... */
{ /* ...drop extra coeff, so when Ph is */ { /* ...drop extra coeff, so when Ph is */
@ -705,12 +760,15 @@ aflibConverter::FilterUD( HWORD Imp[], HWORD ImpD[],
Ho += dhb; /* ...then we've already skipped the */ Ho += dhb; /* ...then we've already skipped the */
} /* first sample, so we must also */ } /* first sample, so we must also */
/* skip ahead in Imp[] and ImpD[] */ /* skip ahead in Imp[] and ImpD[] */
if (Interp) if (Interp)
while ((Hp = &Imp[Ho>>Na]) < End) { {
while ((Hp = &Imp[Ho>>Na]) < End)
{
t = *Hp; /* Get IR sample */ t = *Hp; /* Get IR sample */
Hdp = &ImpD[Ho>>Na]; /* get interp (lower Na) bits from diff table*/ Hdp = &ImpD[Ho>>Na]; /* get interp (lower Na) bits from diff table*/
a = Ho & Amask; /* a is logically between 0 and 1 */ a = Ho & Amask; /* a is logically between 0 and 1 */
t += (((WORD)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */ t += (((int)*Hdp)*a)>>Na; /* t is now interp'd filter coeff */
t *= *Xp; /* Mult coeff by input sample */ t *= *Xp; /* Mult coeff by input sample */
if (t & 1<<(Nhxn-1)) /* Round, if needed */ if (t & 1<<(Nhxn-1)) /* Round, if needed */
t += 1<<(Nhxn-1); t += 1<<(Nhxn-1);
@ -719,8 +777,11 @@ aflibConverter::FilterUD( HWORD Imp[], HWORD ImpD[],
Ho += dhb; /* IR step */ Ho += dhb; /* IR step */
Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */
} }
}
else else
while ((Hp = &Imp[Ho>>Na]) < End) { {
while ((Hp = &Imp[Ho>>Na]) < End)
{
t = *Hp; /* Get IR sample */ t = *Hp; /* Get IR sample */
t *= *Xp; /* Mult coeff by input sample */ t *= *Xp; /* Mult coeff by input sample */
if (t & 1<<(Nhxn-1)) /* Round, if needed */ if (t & 1<<(Nhxn-1)) /* Round, if needed */
@ -730,6 +791,7 @@ aflibConverter::FilterUD( HWORD Imp[], HWORD ImpD[],
Ho += dhb; /* IR step */ Ho += dhb; /* IR step */
Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */ Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */
} }
}
return(v); return(v);
} }

View File

@ -18,7 +18,7 @@
* Julius O. Smith jos@ccrma.stanford.edu * 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 into a C++ class
*/ */
@ -26,6 +26,10 @@
#ifndef _AFLIBCONVERTER_H_ #ifndef _AFLIBCONVERTER_H_
#define _AFLIBCONVERTER_H_ #define _AFLIBCONVERTER_H_
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifndef MAX #ifndef MAX
#define MAX(x,y) ((x)>(y) ?(x):(y)) #define MAX(x,y) ((x)>(y) ?(x):(y))
#endif #endif
@ -36,11 +40,6 @@
#define MAX_HWORD (32767) #define MAX_HWORD (32767)
#define MIN_HWORD (-32768) #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 */ #define IBUFFSIZE 4096 /* Input buffer size */
/*! \class aflibConverter /*! \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. 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 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 initialize should be called to initialize everything. This initialize function will set
number of channels. Once everything is specified then resample should be called as many the conversion factor as well as a multiplecation factor for volume. The volume only
times as is necessary to process all the data. The value inCount will be returned applies to the small and large filter. Since this filter uses a history of the audio data
indicating how many inArray samples were actually used to produce the output. This it is possible for it to vary in amplitude. This allows users to scale the data. This
value can be used to indicate where the next block of inArray data should start. The class will work on any number of channels. Once everything is specified then resample
resample function is driven by the outCount value specified. The inArray should should be called as many times as is necessary to process all the data. The value
contain at least: 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. outCount / factor + extra_samples.
extra_samples depends on the type of filtering done. As a rule of thumb 50 should be extra_samples depends on the type of filtering done. As a rule of thumb 50 should be
adequate for any type of filter. adequate for any type of filter.
*/ */
class aflibData;
class aflibConverter { class aflibConverter {
@ -86,14 +89,15 @@ public:
void void
initialize( initialize(
double factor, /* factor = Sndout/Sndin */ 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 int
resample( /* number of output samples returned */ resample( /* number of output samples returned */
int& inCount, /* number of input samples to convert */ int& inCount, /* number of input samples to convert */
int outCount, /* number of output samples to compute */ int outCount, /* number of output samples to compute */
HWORD inArray[], /* input array data (length inCount * nChans) */ short inArray[], /* input array data (length inCount * nChans) */
HWORD outArray[]);/* output array data (length outCount * nChans) */ short outArray[]);/* output array data (length outCount * nChans) */
private: private:
@ -114,130 +118,117 @@ private:
int int
readData( readData(
int inCount, /* _total_ number of frames in input file */ int inCount, /* _total_ number of frames in input file */
HWORD inArray[], /* input data */ short inArray[], /* input data */
HWORD *outPtr[], /* array receiving chan samps */ short *outPtr[], /* array receiving chan samps */
int dataArraySize, /* size of these arrays */ int dataArraySize, /* size of these arrays */
int Xoff, /* read into input array starting at this index */ int Xoff, /* read into input array starting at this index */
bool init_count); bool init_count);
inline HWORD inline short
WordToHword(WORD v, int scl) WordToHword(int v, int scl)
{ {
HWORD out; short out;
WORD llsb = (1<<(scl-1)); int llsb = (1<<(scl-1));
v += llsb; /* round */ v += llsb; /* round */
v >>= scl; v >>= scl;
if (v>MAX_HWORD) { 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; v = MAX_HWORD;
} else if (v < MIN_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; v = MIN_HWORD;
} }
out = (HWORD) v; out = (short) v;
return out; return out;
}; };
int int
SrcLinear( SrcLinear(
HWORD X[], short X[],
HWORD Y[], short Y[],
double factor, double factor,
UWORD *Time, unsigned int *Time,
UHWORD& Nx, unsigned short& Nx,
UHWORD Nout); unsigned short Nout);
int int
SrcUp( SrcUp(
HWORD X[], short X[],
HWORD Y[], short Y[],
double factor, double factor,
UWORD *Time, unsigned int *Time,
UHWORD& Nx, unsigned short& Nx,
UHWORD Nout, unsigned short Nout,
UHWORD Nwing, unsigned short Nwing,
UHWORD LpScl, unsigned short LpScl,
HWORD Imp[], short Imp[],
HWORD ImpD[], short ImpD[],
BOOL Interp); bool Interp);
int int
SrcUD( SrcUD(
HWORD X[], short X[],
HWORD Y[], short Y[],
double factor, double factor,
UWORD *Time, unsigned int *Time,
UHWORD& Nx, unsigned short& Nx,
UHWORD Nout, unsigned short Nout,
UHWORD Nwing, unsigned short Nwing,
UHWORD LpScl, unsigned short LpScl,
HWORD Imp[], short Imp[],
HWORD ImpD[], short ImpD[],
BOOL Interp); bool Interp);
WORD int
FilterUp( FilterUp(
HWORD Imp[], short Imp[],
HWORD ImpD[], short ImpD[],
UHWORD Nwing, unsigned short Nwing,
BOOL Interp, bool Interp,
HWORD *Xp, short *Xp,
HWORD Ph, short Ph,
HWORD Inc); short Inc);
WORD int
FilterUD( FilterUD(
HWORD Imp[], short Imp[],
HWORD ImpD[], short ImpD[],
UHWORD Nwing, unsigned short Nwing,
BOOL Interp, bool Interp,
HWORD *Xp, short *Xp,
HWORD Ph, short Ph,
HWORD Inc, short Inc,
UHWORD dhb); unsigned short dhb);
int int
resampleFast( /* number of output samples returned */ resampleFast( /* number of output samples returned */
int& inCount, /* number of input samples to convert */ int& inCount, /* number of input samples to convert */
int outCount, /* number of output samples to compute */ int outCount, /* number of output samples to compute */
HWORD inArray[], /* input array data (length inCount * nChans) */ short inArray[], /* input array data (length inCount * nChans) */
HWORD outArray[]);/* output array data (length outCount * nChans) */ short outArray[]);/* output array data (length outCount * nChans) */
int int
resampleWithFilter( /* number of output samples returned */ resampleWithFilter( /* number of output samples returned */
int& inCount, /* number of input samples to convert */ int& inCount, /* number of input samples to convert */
int outCount, /* number of output samples to compute */ int outCount, /* number of output samples to compute */
HWORD inArray[], /* input array data (length inCount * nChans) */ short inArray[], /* input array data (length inCount * nChans) */
HWORD outArray[], /* output array data (length outCount * nChans) */ short outArray[], /* output array data (length outCount * nChans) */
HWORD Imp[], HWORD ImpD[], short Imp[], short ImpD[],
UHWORD LpScl, UHWORD Nmult, UHWORD Nwing); unsigned short LpScl, unsigned short Nmult, unsigned short Nwing);
static HWORD SMALL_FILTER_IMP[]; static short SMALL_FILTER_IMP[];
static HWORD LARGE_FILTER_IMP[]; static short LARGE_FILTER_IMP[];
bool interpFilt; bool interpFilt;
bool largeFilter; bool largeFilter;
bool linearInterp; bool linearInterp;
HWORD ** X; short ** _X;
HWORD ** Y; short ** _Y;
UWORD Time; unsigned int _Time;
double factor; double _factor;
int nChans; int _nChans;
bool initial; bool _initial;
double _vol;
}; };

View File

@ -34,11 +34,16 @@ well for its level of computational expense.
*/ */
#define LARGE_FILTER_NMULT ((HWORD)65) #ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define LARGE_FILTER_NMULT ((short)65)
#define LARGE_FILTER_SCALE 14746 /* Unity-gain scale factor */ #define LARGE_FILTER_SCALE 14746 /* Unity-gain scale factor */
#define LARGE_FILTER_NWING 8192 /* Filter table length */ #define LARGE_FILTER_NWING 8192 /* Filter table length */
HWORD aflibConverter::LARGE_FILTER_IMP[] /* Impulse response */ = { short aflibConverter::LARGE_FILTER_IMP[] /* Impulse response */ = {
32767, 32767,
32766, 32766,
32764, 32764,
@ -8232,7 +8237,7 @@ HWORD aflibConverter::LARGE_FILTER_IMP[] /* Impulse response */ = {
0, 0,
0}; 0};
static HWORD LARGE_FILTER_IMPD[] /* Impulse response differences */ = { static short LARGE_FILTER_IMPD[] /* Impulse response differences */ = {
-1, -1,
-2, -2,
-3, -3,

View File

@ -19,11 +19,16 @@
* *
*/ */
#define SMALL_FILTER_NMULT ((HWORD)13)
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#define SMALL_FILTER_NMULT ((short)13)
#define SMALL_FILTER_SCALE 13128 /* Unity-gain scale factor */ #define SMALL_FILTER_SCALE 13128 /* Unity-gain scale factor */
#define SMALL_FILTER_NWING 1536 /* Filter table length */ #define SMALL_FILTER_NWING 1536 /* Filter table length */
HWORD aflibConverter::SMALL_FILTER_IMP[] /* Impulse response */ = { short aflibConverter::SMALL_FILTER_IMP[] /* Impulse response */ = {
32767, 32767,
32766, 32766,
32764, 32764,
@ -1562,7 +1567,7 @@ HWORD aflibConverter::SMALL_FILTER_IMP[] /* Impulse response */ = {
-1 -1
}; };
static HWORD SMALL_FILTER_IMPD[] = { static short SMALL_FILTER_IMPD[] = {
-1, -1,
-2, -2,
-4, -4,

View File

@ -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 <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
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);
}

View File

@ -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