# HG changeset patch # User Ryan C. Gordon # Date 1024436984 0 # Node ID f61eadea1f44d7580a99c2d48a044c198b64f280 # Parent 4bcbc442d145aabd751d677c64a9588308b8ffc0 More revisions from Frank. diff -r 4bcbc442d145 -r f61eadea1f44 alt_audio_convert.c --- a/alt_audio_convert.c Thu Jun 13 23:15:37 2002 +0000 +++ b/alt_audio_convert.c Tue Jun 18 21:49:44 2002 +0000 @@ -1,50 +1,117 @@ /* - Extended Audio Converter for SDL (Simple DirectMedia Layer) - Copyright (C) 2002 Frank Ranostaj - Institute of Applied Physik - Johann Wolfgang Goethe-Universität - Frankfurt am Main, Germany - - 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. + * Extended Audio Converter for SDL (Simple DirectMedia Layer) + * Copyright (C) 2002 Frank Ranostaj + * Institute of Applied Physik + * Johann Wolfgang Goethe-Universität + * Frankfurt am Main, Germany + * + * 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; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Frank Ranostaj + * ranostaj@stud.uni-frankfurt.de + * + * (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.) + */ - 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; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Frank Ranostaj - ranostaj@stud.uni-frankfurt.de - -(This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.) - -*/ #include "alt_audio_convert.h" #include #include +/* just to make sure this is defined... */ + +#ifndef min +#define min(x, y) ( ((x) < (y)) ? (x) : (y) ) +#endif + +#ifndef max +#define max(x, y) ( ((x) > (y)) ? (x) : (y) ) +#endif + + /* some macros for "parsing" format */ #define IS_8BIT(x) ((x).format & 0x0008) #define IS_16BIT(x) ((x).format & 0x0010) -#define IS_FLOAT(x) ((x).format & 0x0020) /* !!! FIXME: is this ok? */ +#define IS_FLOAT(x) ((x).format & 0x0020) #define IS_SIGNED(x) ((x).format & 0x8000) -#define IS_SYSENDIAN(x) ((AUDIO_U16SYS ^ (x).format) & 0x1000) +#define IS_SYSENDIAN(x) ((~AUDIO_U16SYS ^ (x).format) & 0x1000) /*-------------------------------------------------------------------------*/ /* this filter (Kaiser-window beta=6.8) gives a decent -80dB attentuation */ -static const int filter[_fsize/2] = { +static const int filter[_fsize / 2] = +{ 0, 20798, 0, -6764, 0, 3863, 0, -2560, 0, 1800, 0, -1295, 0, 936, 0, -671, 0, 474, 0, -326, 0, 217, 0, -138, - 0, 83, 0, -46, 0, 23, 0, -9 }; + 0, 83, 0, -46, 0, 23, 0, -9 +}; + + +/*-------------------------------------------------------------------------*/ +/* the purpose of the RateConverterBuffer is to provide a continous storage + for head and tail of the (sample)-buffer. This allows a simple and + perfomant implemantation of the sample rate converters. Depending of the + operation mode, two layouts for the RateConverterBuffer.inbuffer are + possible: + + in the Loop Mode: + ... T-4 T-3 T-2 T-1 H+0 H+1 H+2 H+3 H+4 ... + | + linp, finp + + in the Single Mode (non Loop): + ... T-4 T-3 T-2 T-1 0 0 0 ... 0 0 0 H+0 H+1 H+2 H+3 H+4 ... + | | + linp finp + + The RateConverterBuffer allows an accurate attack and decay of the + filters in the rate Converters. + + The pointer finp are actually shifted against the depicted position so + that on the first invocation of the rate converter the input of the + filter is nearly complete in the zero region, only one input value is + used. After the calculation of the first output value, the pointer are + incremented or decremented depending on down or up conversion and the + first two input value are taken into account. This procedure repeats + until the filter has processed all zeroes. The distance of the pointer + movement is stored in flength. + + Further a pointer cinp to the sample buffer itself is stored. The pointer + to the sample buffer is shifted too, so that on the first use of this + pointer the filter is complete in the sample buffer. The pointer moves + over the sample buffer until it reaches the other end. The distance of + the movement is stored in clength. + + Finally the decay of the filter is done by linp, llength like finp, + flength, but in reverse order. + + buffer denotes the start or the end of the output buffer, depending + on direction of the rate conversion. + + All pointer and length referring the buffer as Sint16. All length + are refering to the input buffer */ + +typedef struct +{ + Sint16 inbuffer[6*_fsize]; + Sint16 *finp, *cinp, *linp; + Sint16 *buffer; + int flength, clength, llength; +} RateConverterBuffer; + /* Mono (1 channel ) */ #define Suffix(x) x##1 @@ -56,9 +123,10 @@ #include "filter_templates.h" #undef Suffix + /*-------------------------------------------------------------------------*/ static int ConvertAudio( Sound_AudioCVT *Data, - Uint8* buffer, int length, int mode ) + Uint8* buffer, int length, int mode ) { AdapterC Temp; int i; @@ -293,71 +361,157 @@ } /*-------------------------------------------------------------------------*/ -static int doubleRateStereo( AdapterC Data, int length ) +static void initRateConverterBuffer( RateConverterBuffer *rcb, + AdapterC* Data, int length, int rel_size ) { - length >>= 2; - _doubleRate2( (Sint16*)Data.buffer, Data.mode, length ); - return 4*_doubleRate2( (Sint16*)Data.buffer+1, Data.mode, length ); -} + int size, slength; + int den, num; + int i; + + den = Data->filter->denominator; + num = Data->filter->numerator; + size = _fsize * rel_size; + length >>= 1; + slength = rel_size > 0 ? length : -length; + + rcb->buffer = (Sint16*)( Data->buffer ); -static int doubleRateMono( AdapterC Data, int length ) -{ - return 2*_doubleRate1( (Sint16*)Data.buffer, Data.mode, length>>1 ); + if( Data->mode & SDL_AI_Loop ) + { + // !!!FIXME: modulo length, take scale into account + for( i = 0; i < size; i++ ) + { + rcb->inbuffer[i] = rcb->buffer[length-size+i]; + rcb->inbuffer[i+size] = rcb->buffer[i]; + } + rcb->finp = rcb->linp = rcb->inbuffer + size; + if( size < 0 ) + rcb->buffer += num * ( length + 2 * size ) / den; + } + else + { + for( i = 0; i < size; i++ ) + { + int j; + j = length-size+i; + rcb->inbuffer[i] = j < 0 ? 0 : rcb->buffer[j]; + rcb->inbuffer[i+size] = 0; + rcb->inbuffer[i+2*size] = i < length ? rcb->buffer[i] : 0; + } + // !!!FIXME: take lenght < size into account + rcb->finp = rcb->inbuffer + abs( 3*size/2 ) + size/2; + rcb->linp = rcb->inbuffer + abs( 3*size/2 ) - size/2; + rcb->flength = rcb->llength = 2*size; + rcb->clength = slength - 2*size; + + if( size < 0 ) + rcb->buffer += num * ( length + 2 * size ) / den; + } } -/*-------------------------------------------------------------------------*/ -static int halfRateStereo( AdapterC Data, int length ) +static void nextRateConverterBuffer( RateConverterBuffer *rcb ) { - length >>= 2; - _halfRate2( (Sint16*)Data.buffer, Data.mode, length ); - return 4*_halfRate2( (Sint16*)Data.buffer+1, Data.mode, length ); + rcb->buffer++; + rcb->finp++; + rcb->cinp++; + rcb->linp++; } -static int halfRateMono( AdapterC Data, int length ) +typedef Sint16* (*RateConverter)( Sint16*, Sint16*, int, VarFilter*, int*); +static int doRateConversion( RateConverterBuffer* rcb, + RateConverter ffp, VarFilter* filter ) { - return 2*_halfRate2( (Sint16*)Data.buffer, Data.mode, length>>1 ); + int pos = 0; + Sint16 *outp; + outp = rcb->buffer; + + outp = (*ffp)( outp, rcb->finp, rcb->flength, filter, &pos ); + outp = (*ffp)( outp, rcb->cinp, rcb->clength, filter, &pos ); + outp = (*ffp)( outp, rcb->linp, rcb->llength, filter, &pos ); + return 2 * abs( rcb->buffer - outp ); +} + + +/*-------------------------------------------------------------------------*/ +static int doubleRateMono( AdapterC Data, int length ) +{ + RateConverterBuffer rcb; + initRateConverterBuffer( &rcb, &Data, length, 1 ); + return doRateConversion( &rcb, doubleRate1, NULL ); +} + +static int doubleRateStereo( AdapterC Data, int length ) +{ + RateConverterBuffer rcb; + initRateConverterBuffer( &rcb, &Data, length, 2 ); + doRateConversion( &rcb, doubleRate2, NULL ); + nextRateConverterBuffer( &rcb ); + return 2 + doRateConversion( &rcb, doubleRate2, NULL ); } /*-------------------------------------------------------------------------*/ -static int varRateUpStereo( AdapterC Data, int length ) +static int halfRateMono( AdapterC Data, int length ) { - length >>= 2; - _varRateUp2( (Sint16*)Data.buffer, Data.mode, Data.filter, length ); - return 4 * _varRateUp2( (Sint16*)Data.buffer+1, - Data.mode, Data.filter, length ); + RateConverterBuffer rcb; + initRateConverterBuffer( &rcb, &Data, length, -1 ); + return doRateConversion( &rcb, halfRate1, NULL ); } -static int varRateUpMono( AdapterC Data, int length ) +static int halfRateStereo( AdapterC Data, int length ) { - return 2 * _varRateUp1( (Sint16*)Data.buffer, - Data.mode, Data.filter, length>>1 ); + RateConverterBuffer rcb; + initRateConverterBuffer( &rcb, &Data, length, -2 ); + doRateConversion( &rcb, halfRate2, NULL ); + nextRateConverterBuffer( &rcb ); + return 2 + doRateConversion( &rcb, halfRate2, NULL ); +} + +/*-------------------------------------------------------------------------*/ +static int increaseRateMono( AdapterC Data, int length ) +{ + RateConverterBuffer rcb; + initRateConverterBuffer( &rcb, &Data, length, 2 ); + return doRateConversion( &rcb, increaseRate1, Data.filter ); } -static int varRateDownStereo( AdapterC Data, int length ) +static int increaseRateStereo( AdapterC Data, int length ) { - length >>= 2; - _varRateDown2( (Sint16*)Data.buffer, Data.mode, Data.filter, length ); - return 2 * _varRateDown2( (Sint16*)Data.buffer+1, - Data.mode, Data.filter, length ); + RateConverterBuffer rcb; + initRateConverterBuffer( &rcb, &Data, length, 4 ); + doRateConversion( &rcb, increaseRate2, Data.filter ); + nextRateConverterBuffer( &rcb ); + return 2 + doRateConversion( &rcb, increaseRate2, Data.filter ); } -static int varRateDownMono( AdapterC Data, int length ) +/*-------------------------------------------------------------------------*/ +static int decreaseRateMono( AdapterC Data, int length ) { - return _varRateDown1( (Sint16*)Data.buffer, - Data.mode, Data.filter, length>>1 ); + RateConverterBuffer rcb; + initRateConverterBuffer( &rcb, &Data, length, -2 ); + return doRateConversion( &rcb, decreaseRate1, Data.filter ); } +static int decreaseRateStereo( AdapterC Data, int length ) +{ + RateConverterBuffer rcb; + initRateConverterBuffer( &rcb, &Data, length, -4 ); + doRateConversion( &rcb, decreaseRate2, Data.filter ); + nextRateConverterBuffer( &rcb ); + return doRateConversion( &rcb, decreaseRate2, Data.filter ); +} + + /*-------------------------------------------------------------------------*/ typedef struct{ Sint16 denominator; Sint16 numerator; } Fraction; +/* gives a maximal error of 3% and typical less than 0.2% */ static Fraction findFraction( float Value ) { -/* gives a maximal error of 3% and typical less than 0.2% */ - const Uint8 frac[96]={ - 1, 2, -1, /* /1 */ + const Sint8 frac[95]={ + 2, -1, /* /1 */ 1, 3, -1, /* /2 */ 2, 4, 5, -1, /* /3 */ 3, 5, 7, -1, /* /4 */ @@ -376,12 +530,12 @@ Fraction Result = {0,0}; - int n,num,den=1; + int n,num=1,den=1; float RelErr, BestErr = 0; if( Value < 31/64. || Value > 64/31. ) return Result; - for( n = 0; n < sizeof(frac); num=frac[++n] ) + for( n = 0; n < sizeof(frac); num=frac[n++] ) { if( num < 0 ) den++; RelErr = Value * num / den; @@ -403,7 +557,8 @@ else return sin(x)/x; } -static void calculateVarFilter( Sint16* dst, float Ratio, float phase, float scale ) +static void calculateVarFilter( Sint16* dst, + float Ratio, float phase, float scale ) { const Uint16 KaiserWindow7[]= { 22930, 16292, 14648, 14288, 14470, 14945, 15608, 16404, @@ -440,13 +595,14 @@ { int i,n,d; Fraction IRatio; - float phase; + float phase = 0.; IRatio = findFraction( Ratio ); Ratio = min( Ratio, 1/Ratio ); n = IRatio.numerator; d = IRatio.denominator; - filter->pos_mod = d; + filter->denominator = d; + filter->numerator = n; for( i = 0; i < d; i++ ) { @@ -466,7 +622,7 @@ /*-------------------------------------------------------------------------*/ static void createRateConverter( Sound_AudioCVT *Data, int* fip, - int SrcRate, int DestRate, int Channel ) + int SrcRate, int DestRate, int Channel ) { int filter_index = *fip; @@ -506,7 +662,7 @@ { setupVarFilter( &Data->filter, Ratio, Up ); Data->adapter[VarPos] = - Mono ? varRateUpMono : varRateUpStereo; + Mono ? increaseRateMono : increaseRateStereo; Data->len_mult *= 2; Data->add *= 2; Data->add += _fsize; @@ -515,7 +671,7 @@ { setupVarFilter( &Data->filter, Ratio, Down ); Data->adapter[filter_index++] = - Mono ? varRateDownMono : varRateDownStereo; + Mono ? decreaseRateMono : decreaseRateStereo; } *fip = filter_index; } @@ -643,8 +799,8 @@ /*-------------------------------------------------------------------------*/ -DECLSPEC int BuildAudioCVT(Sound_AudioCVT *Data, - SDL_AudioSpec src, SDL_AudioSpec dst ) +int BuildAudioCVT( Sound_AudioCVT *Data, + SDL_AudioSpec src, SDL_AudioSpec dst ) { SDL_AudioSpec intrm; int filter_index = 0; @@ -733,14 +889,14 @@ AdapterDesc(convertMonoToStereo16Bit), AdapterDesc(convertMonoToStereo8Bit), AdapterDesc(minus5dB), + AdapterDesc(doubleRateMono), AdapterDesc(doubleRateStereo), - AdapterDesc(doubleRateMono), - AdapterDesc(halfRateStereo), AdapterDesc(halfRateMono), - AdapterDesc(varRateUpStereo), - AdapterDesc(varRateUpMono), - AdapterDesc(varRateDownStereo), - AdapterDesc(varRateDownMono), + AdapterDesc(halfRateStereo), + AdapterDesc(increaseRateMono), + AdapterDesc(increaseRateStereo), + AdapterDesc(decreaseRateMono), + AdapterDesc(decreaseRateStereo), { NULL, "----------NULL-----------" } }; const int AdapterDescMax = sizeof(AdapterDescription) @@ -766,8 +922,8 @@ int Sound_BuildAudioCVT(Sound_AudioCVT *Data, - Uint16 src_format, Uint8 src_channels, int src_rate, - Uint16 dst_format, Uint8 dst_channels, int dst_rate) + Uint16 src_format, Uint8 src_channels, int src_rate, + Uint16 dst_format, Uint8 dst_channels, int dst_rate) { SDL_AudioSpec src, dst; int ret; diff -r 4bcbc442d145 -r f61eadea1f44 alt_audio_convert.h --- a/alt_audio_convert.h Thu Jun 13 23:15:37 2002 +0000 +++ b/alt_audio_convert.h Tue Jun 18 21:49:44 2002 +0000 @@ -1,33 +1,32 @@ /* - Extended Audio Converter for SDL (Simple DirectMedia Layer) - Copyright (C) 2002 Frank Ranostaj - Institute of Applied Physik - Johann Wolfgang Goethe-Universität - Frankfurt am Main, Germany - - 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. + * Extended Audio Converter for SDL (Simple DirectMedia Layer) + * Copyright (C) 2002 Frank Ranostaj + * Institute of Applied Physik + * Johann Wolfgang Goethe-Universität + * Frankfurt am Main, Germany + * + * 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; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Frank Ranostaj + * ranostaj@stud.uni-frankfurt.de + * + * (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.) + */ - 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; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Frank Ranostaj - ranostaj@stud.uni-frankfurt.de - -(This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.) - -*/ - -#ifndef _INCLUDE_AUDIO_CONVERT_H_ -#define _INCLUDE_AUDIO_CONVERT_H_ +#ifndef _INCLUDE_ALT_AUDIO_CONVERT_H_ +#define _INCLUDE_ALT_AUDIO_CONVERT_H_ #include "SDL_audio.h" #define Sound_AI_Loop 0x2 @@ -37,7 +36,8 @@ typedef struct{ Sint16 c[16][2*_fsize]; char incr[16]; - int pos_mod; + int denominator; + int numerator; } VarFilter; typedef struct{ @@ -74,5 +74,5 @@ Uint16 src_format, Uint8 src_channels, int src_rate, Uint16 dst_format, Uint8 dst_channels, int dst_rate ); -#endif /* _INCLUDE_AUDIO_CONVERT_H_ */ +#endif /* _INCLUDE_ALT_AUDIO_CONVERT_H_ */ diff -r 4bcbc442d145 -r f61eadea1f44 filter_templates.h --- a/filter_templates.h Thu Jun 13 23:15:37 2002 +0000 +++ b/filter_templates.h Tue Jun 18 21:49:44 2002 +0000 @@ -1,259 +1,149 @@ -/* - Extended Audio Converter for SDL (Simple DirectMedia Layer) - Copyright (C) 2002 Frank Ranostaj - Institute of Applied Physik - Johann Wolfgang Goethe-Universität - Frankfurt am Main, Germany - - 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; if not, write to the Free - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Frank Ranostaj - ranostaj@stud.uni-frankfurt.de -*/ - -#ifndef Suffix -#error include filter_template.h with defined Suffix macro! -#else -#define CH(x) (Suffix((x)*)) -//--------------------------------------------------------------------------- -int Suffix(_doubleRate)( short *buffer, int mode, int length ) -{ - const fsize = _fsize/2; - int i,di,border; - short inbuffer[_fsize]; +/* + * Extended Audio Converter for SDL (Simple DirectMedia Layer) + * Copyright (C) 2002 Frank Ranostaj + * Institute of Applied Physik + * Johann Wolfgang Goethe-Universität + * Frankfurt am Main, Germany + * + * 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; if not, write to the Free + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Frank Ranostaj + * ranostaj@stud.uni-frankfurt.de + * + * (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.) + */ - if( mode & SDL_AI_Loop ) - { - for( i = 0; i < fsize; i++ ) - { - inbuffer[CH(i+fsize)] = buffer[CH(length+i)] = buffer[CH(i)]; - inbuffer[CH(i)] = buffer[CH(length-fsize+i)]; - } - border = 0; - } - else - { - for( i = 0; i < fsize; i++ ) - { - inbuffer[CH(i)] = buffer[CH(length+i)] = 0; - inbuffer[CH(i+fsize)] = buffer[CH(i)]; - } - border = fsize/2; - } +#ifndef Suffix +#error include filter_template.h with defined Suffix macro! +#else +#define CH(x) (Suffix((x)*)) +/*-------------------------------------------------------------------------*/ + /* + * !!! FIXME !!! + * + * + * Tune doubleRate(), halfRate() and varRate() for speed + * - Frank + */ - for(i = length + border - 1; i >= -border; i--) - { - const short* const inp = i < fsize/2 ? - &inbuffer[CH(i+fsize)] : &buffer[CH(i)]; - short* const outp = &buffer[CH(2*(i+border))]; - int out = 0; - - for( di = 1; di < 1+fsize; di+=2 ) - out+= filter[di]*( inp[CH(di)/2] + inp[CH(1-di)/2] ); - outp[CH(1)] = ( 32770*inp[CH(1)] + out) >> 16; - outp[CH(0)] = ( 32770*inp[CH(0)] + out) >> 16; - } - return 2*length + 4*border; -} - -//--------------------------------------------------------------------------- -short Suffix(filterHalfBand)( short* inp ) -{ - static const int fsize = _fsize; - int out = 32770*inp[0]; - int di; - for( di = 1; di < fsize/2; di+=2 ) - out+= filter[di]*( inp[CH(di)] + inp[CH(-di)] ); - return out >> 16; -} - -int Suffix(_halfRate)( short *buffer, int mode, int length ) +/*-------------------------------------------------------------------------*/ +static Sint16* Suffix(doubleRate)( Sint16 *outp, Sint16 *inp, int length, + VarFilter* filt, int* cpos ) { static const int fsize = _fsize; - - int i,border; - - short inbuffer[3*_fsize]; - short *finp, *linp; + int i, out; + Sint16* to; - if( mode & SDL_AI_Loop ) - { - if( length & 1 ) - { - // do something meaningful - } - for( i = 0; i < fsize; i++ ) - { - inbuffer[CH(i)] = buffer[CH(length-fsize+i)]; - inbuffer[CH(i+fsize)] = buffer[CH(i)]; - } - border = 0; - finp = inbuffer + CH( fsize ); - linp = inbuffer + CH( fsize-length ); - } - else + inp += fsize; + to = inp + length; + + for(; inp > to; inp -= CH(1) ) { - for( i = 0; i < fsize; i++ ) - { - inbuffer[CH(i)] = buffer[CH(length-fsize+i)]; - inbuffer[CH(i+fsize)] = 0; - inbuffer[CH(i+2*fsize)] = buffer[CH(i)]; - } - border = fsize; - finp = inbuffer + CH( (3*fsize)/2 + 2*border ); - linp = inbuffer + CH( fsize/2 - length ); - } - - length = ( length + 1 ) / 2; + out = 0; + for( i = 1; i < 1+fsize; i++ ) + out+= filter[2*i] * ( inp[CH(i)] + inp[CH(1-i)] ); - for(i = -border; i < fsize; i++) - { - buffer[CH(i+border)] = Suffix(filterHalfBand)( finp+CH(2*i) ); + outp[CH(1)] = ( 32770 * inp[CH(1)] + out) >> 16; + outp[CH(0)] = ( 32770 * inp[CH(0)] + out) >> 16; + outp -= CH(2); } - for(; i < length-fsize; i++) - { - buffer[CH(i+border)] = Suffix(filterHalfBand)( buffer+CH(2*i) ); - } - for(; i < length+border; i++) - { - buffer[CH(i+border)] = Suffix(filterHalfBand)( linp+CH(2*i) ); - } - return length + 2*border; + return outp; } -//--------------------------------------------------------------------------- -short Suffix(filterVarBand)( VarFilter* filt, short** inpp, char* cpos ) +/*-------------------------------------------------------------------------*/ +static Sint16* Suffix(halfRate)( Sint16 *outp, Sint16 *inp, int length, + VarFilter* filt, int* cpos ) { - int di; - int out = 0; - short *inp = *inpp; - int pos = *cpos; - short *filter = filt->c[pos]; + static const int fsize = CH(_fsize/2); + int i, out; + Sint16* to; + + inp -= fsize; + to = inp + length; - for( di = 0; di < 2*_fsize; di++ ) - out+= filter[di] * (int)inp[CH(di)]; + for(; inp < to; inp+= CH(2) ) + { + out = 32770 * inp[0]; + for( i = 1; i < fsize/2; i+=2 ) + out+= filter[i]*( (int)inp[CH(i)] + inp[CH(-i)] ); + outp[0] = out >> 16; - *inpp += CH(filt->incr[pos]); - *cpos = ( pos + 1 ) % filt->pos_mod; - return out >> 16; + outp += CH(1); + } + return outp; } -int Suffix(_varRateDown)( short* buffer, int mode, VarFilter* filter, int length ) +/*-------------------------------------------------------------------------*/ +static Sint16* Suffix(increaseRate)( Sint16 *outp, Sint16 *inp, int length, + VarFilter* filt, int* cpos ) { - static const int fsize = _fsize; - int i,border; - short inbuffer[CH(3*_fsize)]; - short *finp, *linp, *bufp, *outbuf; - char pos = 0; - VarFilter* filterp = filter; + const static int fsize = 2*_fsize; + Sint16 *filter; + int out; + int i, pos; + Sint16* to; - if( mode & SDL_AI_Loop ) - { - for( i = 0; i < fsize; i++ ) - { - inbuffer[CH(i)] = buffer[CH(length-fsize+i)]; - inbuffer[CH(i+fsize)] = buffer[CH(i)]; - } - border = 0; - finp = inbuffer+CH(fsize); - linp = inbuffer+CH(fsize-length); - } - else + inp += fsize; + to = inp + length; + + while( inp > to ) { - for( i = 0; i < fsize; i++ ) - { - inbuffer[CH(i)] = buffer[CH(length-fsize+i)]; - inbuffer[CH(i+fsize)] = 0; - inbuffer[CH(i+2*fsize)] = buffer[CH(i)]; - } - border = fsize; - finp = inbuffer + CH( 3*fsize/2 ); - linp = inbuffer + CH( fsize/2 ); - } + pos = *cpos; + out = 0; + filter = filt->c[pos]; + for( i = 0; i < 2*_fsize; i++ ) + out+= filter[i] * (int)inp[CH(i)]; + outp[0] = out >> 16; - length = ( length + 1 ) / 2; - bufp = buffer; - outbuf = buffer+CH(border); - - for(i = -border; i < fsize; i++) - { - outbuf[CH(i)] = Suffix(filterVarBand)( filterp, &finp, &pos ); + inp -= CH(filt->incr[pos]); + outp -= CH(1); + *cpos = ( pos + 1 ) % filt->denominator; } - for(; i < length-fsize; i++) - { - outbuf[CH(i)] = Suffix(filterVarBand)( filterp, &bufp, &pos ); - } - for(; i < length+border; i++) - { - outbuf[CH(i)] = Suffix(filterVarBand)( filterp, &linp, &pos ); - } - return length + 2*border; + return outp; } -int Suffix(_varRateUp)( short* buffer, int mode, VarFilter* filter, int length ) +/*-------------------------------------------------------------------------*/ +static Sint16* Suffix(decreaseRate)( Sint16 *outp, Sint16 *inp, int length, + VarFilter* filt, int* cpos ) { - static const int fsize = _fsize; - int i,border; - short inbuffer[CH(3*_fsize)]; - short *finp, *linp, *bufp, *outbuf; - char pos = 0; - VarFilter* filterp = filter; + const static int fsize = 2*_fsize; + Sint16 *filter; + int out; + int i, pos; + Sint16 *to; - if( mode & SDL_AI_Loop ) - { - for( i = 0; i < fsize; i++ ) - { - inbuffer[CH(i)] = buffer[CH(length-fsize+i)]; - inbuffer[CH(i+fsize)] = buffer[CH(i)]; - } - border = 0; - finp = inbuffer+CH(fsize); - linp = inbuffer+CH(fsize-length); - } - else + inp -= fsize; + to = inp + length; + + while( inp < to ) { - for( i = 0; i < fsize; i++ ) - { - inbuffer[CH(i)] = buffer[CH(length-fsize+i)]; - inbuffer[CH(i+fsize)] = 0; - inbuffer[CH(i+2*fsize)] = buffer[CH(i)]; - } - border = fsize; - finp = inbuffer + CH( 3*fsize/2 ); - linp = inbuffer + CH( fsize/2 ); - } - - length = 2 * length; - bufp = buffer+length; - outbuf = buffer+CH(border); + pos = *cpos; + out = 0; + filter = filt->c[pos]; + for( i = 0; i < 2*_fsize; i++ ) + out+= filter[i] * (int)inp[CH(i)]; + outp[0] = out >> 16; - for(i = length+border-1; i > length-fsize-1; i--) - { - outbuf[CH(i)] = Suffix(filterVarBand)( filterp, &linp, &pos ); - } - for(; i > fsize-1 ; i--) - { - outbuf[CH(i)] = Suffix(filterVarBand)( filterp, &bufp, &pos ); + inp += CH(filt->incr[pos]); + outp += CH(1); + *cpos = ( pos + 1 ) % filt->denominator; } - for(; i > -border-1; i--) - { - outbuf[CH(i)] = Suffix(filterVarBand)( filterp, &finp, &pos ); - } - return length + 2*border; + return outp; } -//--------------------------------------------------------------------------- + +/*-------------------------------------------------------------------------*/ #undef CH #endif /* Suffix */ - +