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\
VorbisLibEncoder.cpp\
VorbisLibEncoder.h\
aflibDebug.h\
aflibDebug.cc\
aflibConverter.h\
aflibConverter.cc\
aflibConverterLargeFilter.h\

View File

@ -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 <config.h>
#endif
#include <stdlib.h>
#include <stdio.h>
@ -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.
// 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,32 +273,37 @@ aflibConverter::readData(
return 0;
}
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;
short iconst;
short *Xp, *Ystart;
int 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;
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 = (UWORD)(dt*(1<<Np) + 0.5); /* Fixed-point representation */
dtb = (unsigned int)(dt*(1<<Np) + 0.5); /* Fixed-point representation */
start_sample = (*Time)>>Np;
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 (*Time < endTime)
{
iconst = (*Time) & Pmask;
Xp = &X[(*Time)>>Np]; /* Ptr to current input sample */
@ -308,40 +323,46 @@ aflibConverter::SrcLinear(
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;
short *Xp, *Ystart;
int 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;
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 = (UWORD)(dt*(1<<Np) + 0.5); /* Fixed-point representation */
dtb = (unsigned int)(dt*(1<<Np) + 0.5); /* Fixed-point representation */
start_sample = (*Time)>>Np;
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 (*Time < endTime)
{
Xp = &X[*Time>>Np]; /* Ptr to current input sample */
/* 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 */
v += FilterUp(Imp, ImpD, Nwing, Interp, Xp+1,
(HWORD)((-*Time)&Pmask),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 */
@ -356,48 +377,55 @@ aflibConverter::SrcUp(
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;
short *Xp, *Ystart;
int 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;
// 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 = (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 */
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;
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 (*Time < endTime)
{
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 */
v += FilterUD(Imp, ImpD, Nwing, Interp, Xp+1, (HWORD)((-*Time)&Pmask),
1, dhb); /* Perform right-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,13 +461,14 @@ 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<<Np); /* Current-time pointer for converter */
if (_initial == TRUE)
_Time = (Xoff<<Np); /* Current-time pointer for converter */
do {
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;
if (last && (last-Xoff<Nx)) { /* If last sample has been read... */
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)) )
maxOutput = OBUFFSIZE - (UHWORD)(2*Xoff*factor);
if ((outCount-Ycount) > (OBUFFSIZE - (2*Xoff*_factor)) )
maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor);
else
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 */
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 */
#if 0
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 */
}
#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 */
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... */
@ -493,9 +524,9 @@ aflibConverter::resampleFast( /* number of output samples returned */
if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */
return err_ret("Output array overflow");
for (c = 0; c < nChans; c++)
for (c = 0; c < _nChans; c++)
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;
@ -511,30 +542,30 @@ int
aflibConverter::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 data */
HWORD outArray[], /* output data */
HWORD Imp[], HWORD ImpD[],
UHWORD LpScl, UHWORD Nmult, UHWORD Nwing)
short inArray[], /* input data */
short outArray[], /* output data */
short Imp[], short ImpD[],
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
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;
/* Account for increased filter gain when using factors less than 1 */
if (factor < 1)
LpScl = (UHWORD)(LpScl*factor + 0.5);
if (_factor < 1)
LpScl = (unsigned short)(LpScl*_factor + 0.5);
/* 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 */
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 */
Xread = Xoff; /* Position in input array to read into */
if (initial == TRUE)
Time = (Xoff<<Np); /* Current-time pointer for converter */
if (_initial == TRUE)
_Time = (Xoff<<Np); /* Current-time pointer for converter */
do {
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;
if (last && (last-Xoff<Nx)) { /* If last sample has been read... */
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)) )
maxOutput = OBUFFSIZE - (UHWORD)(2*Xoff*factor);
if ( (outCount-Ycount) > (OBUFFSIZE - (2*Xoff*_factor)) )
maxOutput = OBUFFSIZE - (unsigned short)(2*Xoff*_factor);
else
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 */
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);
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);
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 */
#if 0
Ncreep = (Time>>Np) - Xoff; /* Calc time accumulation in Time */
@ -603,20 +638,20 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */
if (Nout > OBUFFSIZE) /* Check to see if output buff overflowed */
return err_ret("Output array overflow");
for (c = 0; c < nChans; c++)
for (c = 0; c < _nChans; c++)
{
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;
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 */
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 */
@ -631,23 +666,30 @@ aflibConverter::resampleWithFilter( /* number of output samples returned */
return(Ycount); /* Return # of samples in output file */
}
WORD
aflibConverter::FilterUp(HWORD Imp[], HWORD ImpD[],
UHWORD Nwing, BOOL Interp,
HWORD *Xp, HWORD Ph, HWORD Inc)
int
aflibConverter::FilterUp(
short Imp[],
short ImpD[],
unsigned short Nwing,
bool Interp,
short *Xp,
short Ph,
short Inc)
{
HWORD *Hp, *Hdp = NULL, *End;
HWORD a = 0;
WORD v, t;
short *Hp, *Hdp = NULL, *End;
short a = 0;
int v, t;
v=0;
Hp = &Imp[Ph>>Na];
End = &Imp[Nwing];
if (Interp) {
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 */
@ -657,10 +699,13 @@ aflibConverter::FilterUp(HWORD Imp[], HWORD ImpD[],
Hdp += Npc; /* skip ahead in Imp[] and ImpD[] */
}
}
if (Interp)
while (Hp < End) {
{
while (Hp < End)
{
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 */
t *= *Xp; /* Mult coeff by input sample */
if (t & (1<<(Nhxn-1))) /* Round, if needed */
@ -670,8 +715,11 @@ aflibConverter::FilterUp(HWORD Imp[], HWORD ImpD[],
Hp += Npc; /* Filter coeff step */
Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */
}
}
else
while (Hp < End) {
{
while (Hp < End)
{
t = *Hp; /* Get filter coeff */
t *= *Xp; /* Mult coeff by input sample */
if (t & (1<<(Nhxn-1))) /* Round, if needed */
@ -681,22 +729,29 @@ aflibConverter::FilterUp(HWORD Imp[], HWORD ImpD[],
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;
short a;
short *Hp, *Hdp, *End;
int v, t;
unsigned int Ho;
v=0;
Ho = (Ph*(UWORD)dhb)>>Np;
Ho = (Ph*(unsigned int)dhb)>>Np;
End = &Imp[Nwing];
if (Inc == 1) /* If doing right wing... */
{ /* ...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 */
} /* first sample, so we must also */
/* skip ahead in Imp[] and ImpD[] */
if (Interp)
while ((Hp = &Imp[Ho>>Na]) < End) {
{
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 += (((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);
@ -719,8 +777,11 @@ aflibConverter::FilterUD( HWORD Imp[], HWORD ImpD[],
Ho += dhb; /* IR step */
Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */
}
}
else
while ((Hp = &Imp[Ho>>Na]) < End) {
{
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 */
@ -730,6 +791,7 @@ aflibConverter::FilterUD( HWORD Imp[], HWORD ImpD[],
Ho += dhb; /* IR step */
Xp += Inc; /* Input signal step. NO CHECK ON BOUNDS */
}
}
return(v);
}

View File

@ -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 <config.h>
#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) */
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;
};

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_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,

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_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,

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