Mercurial > SDL_sound_CoreAudio
diff alt_audio_convert.c @ 373:24a610dfbbfd
More altcvt updates from Frank.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 29 Jun 2002 04:08:17 +0000 |
parents | 1b463ef9bcc2 |
children | 44ed8bdeba74 |
line wrap: on
line diff
--- a/alt_audio_convert.c Tue Jun 25 17:15:29 2002 +0000 +++ b/alt_audio_convert.c Sat Jun 29 04:08:17 2002 +0000 @@ -34,6 +34,10 @@ #define min(x, y) ( ((x) < (y)) ? (x) : (y) ) #endif +#ifndef max +#define max(x, y) ( ((x) > (y)) ? (x) : (y) ) +#endif + #ifndef abs #define abs(x) ( ((x) > (0)) ? (x) : -(x) ) #endif @@ -146,7 +150,7 @@ { int length; /* !!! FIXME: Try the looping stuff under certain circumstances? --ryan. */ - length = ConvertAudio( Data, Data->buf, Data->len, 0 ); + length = ConvertAudio( Data, Data->buf, Data->len, 12 ); Data->len_cvt = length; return length; } @@ -249,7 +253,8 @@ } /*-------------------------------------------------------------------------*/ -static int changeSigned( AdapterC Data, int length, int XOR ) +/* poor mans mmx :-) */ +static int changeSigned( AdapterC Data, int length, Uint32 XOR ) { int i; Uint32* buffer = (Uint32*) Data.buffer; @@ -325,9 +330,9 @@ { int i; Uint16* buffer = (Uint16*) Data.buffer; - Uint16* dst = (Uint16*)Data.buffer + length; + Uint16* dst = (Uint16*)Data.buffer + length - 2; for( i = length>>1; i--; dst-=2 ) - dst[-1] = dst[-2] = buffer[i]; + dst[0] = dst[1] = buffer[i]; return 2*length; } @@ -335,9 +340,9 @@ { int i; Uint8* buffer = Data.buffer; - Uint8* dst = Data.buffer + 2*length; - for( i = length; i--; dst-=2 ) - dst[-1] = dst[-2] = buffer[i]; + Uint8* buffer1 = Data.buffer + 1; + for( i = length-1; i >= 0; i-- ) + buffer[2*i] = buffer1[2*i] = buffer[i]; return 2*length; } @@ -347,37 +352,37 @@ int i; Sint16* buffer = (Sint16*) Data.buffer; for(i = length>>1; i--; ) - buffer[i]= 38084 * buffer[i] >> 16; + buffer[i]= (38084 * (int)buffer[i]) >> 16; return length; } /*-------------------------------------------------------------------------*/ enum RateConverterType{ - dcrsRate = 0, - incrsRate = 1, - hlfRate = 2, - dblRate = 3 + dcrsRate = -1, + incrsRate = 0, + hlfRate = 1, + dblRate = 2 }; static void initRateConverterBuffer( RateConverterBuffer *rcb, AdapterC* Data, int length, enum RateConverterType typ ) { int size, minsize, dir; - int den[] = { 0, 0, 1, 2}; - int num[] = { 0, 0, 2, 1}; + int den[] = { 0, 1, 2}; + int num[] = { 0, 2, 1}; int i; den[incrsRate] = Data->filter->denominator; num[incrsRate] = Data->filter->numerator; size = 8 * _fsize; - dir = typ&1; + dir = ~typ&1; length >>= 1; minsize = min( length, size ); rcb->buffer = (Sint16*)( Data->buffer ); - if( Data->mode & SDL_AI_Loop ) + if( Data->mode & SDL_SOUND_Loop ) { // !!!FIXME: modulo length, take scale into account, // check against the 'else' part @@ -398,7 +403,7 @@ rcb->inbuffer[i+size] = 0; rcb->inbuffer[i+2*size] = rcb->buffer[i]; } - for( i = 0; i < size; i++ ) + for( ; i < size; i++ ) { rcb->inbuffer[i] = 0; rcb->inbuffer[i+size] = 0; @@ -521,13 +526,35 @@ return doRateConversion( &rcb, decreaseRate2, Data.filter ); } +/*-------------------------------------------------------------------------*/ +static int padSilence( AdapterC Data, int length ) +{ + Uint32 zero, *buffer; + int i, mask = 0; + + buffer = (Uint32*) ( Data.buffer + length ); + if( Data.mode != SDL_SOUND_Loop ) + mask = Data.filter->mask; + length = mask - ( ( length - 1 ) & mask ); + zero = Data.filter->zero; + + for( i = length>>2; i--; ) + buffer[i] = zero; + for( i = 4*(length>>2); i < length; i++) + ((Uint8*)buffer)[i] ^= ((Uint8*)&zero)[i&3]; + + return length + ((Uint8*)buffer - Data.buffer); +} /*-------------------------------------------------------------------------*/ typedef struct{ + Sint16 numerator; Sint16 denominator; - Sint16 numerator; } Fraction; +const Fraction Half = {1, 2}; +const Fraction Double = {2, 1}; + /* gives a maximal error of 3% and typical less than 0.2% */ static Fraction findFraction( float Value ) { @@ -579,8 +606,8 @@ else return sin(x)/x; } -static void calculateVarFilter( Sint16* dst, - float Ratio, float phase, float scale ) +static float calculateVarFilter( Sint16* dst, + float Ratio, float phase, float scale ) { const Uint16 KaiserWindow7[]= { 22930, 16292, 14648, 14288, 14470, 14945, 15608, 16404, @@ -595,6 +622,7 @@ float w; const float fg = -.018 + .5 * Ratio; const float omega = 2 * M_PI * fg; + fprintf( stderr, " phase: %6g \n", phase ); phase -= 63; for( i = 0; i < 64; i++) { @@ -602,17 +630,19 @@ dst[i] = w * sinc( omega * (i+phase) ); dst[127-i] = w * sinc( omega * (127-i+phase) ); } + return fg; } -static void setupVarFilter( VarFilter* filter, float Ratio ) +static Fraction setupVarFilter( VarFilter* filter, float Ratio ) { - int i,n,d, incr, phase = 0; - float Scale, rd; + int pos,n,d, incr, phase = 0; + float Scale, rd, fg; Fraction IRatio; IRatio = findFraction( Ratio ); - Scale = Ratio < 1. ? 0.0364733 : 0.0211952; - Ratio = min( Ratio, 1/Ratio ); +// Scale = Ratio < 1. ? 0.0364733 : 0.0211952; + Scale = 0.0084778; + Ratio = min( Ratio, 0.97 ); n = IRatio.numerator; d = IRatio.denominator; @@ -620,21 +650,46 @@ filter->numerator = n; rd = 1. / d; - for( i = 0; i < d; i++ ) + fprintf( stderr, "Filter:\n" ); + + for( pos = 0; pos < d; pos++ ) { - calculateVarFilter( filter->c[i], Ratio, phase*rd, Scale ); + fg = calculateVarFilter( filter->c[pos], Ratio, phase*rd, Scale ); phase += n; - filter->incr[i] = phase / d; + filter->incr[pos] = phase / d; phase %= d; } + fprintf( stderr, " fg: %6g\n\n", fg ); +/* !!!FIXME: get rid of the inversion -Frank*/ + IRatio.numerator = d; + IRatio.denominator = n; + return IRatio; +} +/*-------------------------------------------------------------------------*/ +static void adjustSize( Sound_AudioCVT *Data, int add, Fraction f ) +{ + + double ratio = f.numerator / (double) f.denominator; + Data->len_ratio *= ratio; + Data->len_mult = max( Data->len_mult, ceil(Data->len_ratio) ); + Data->add = ratio * (Data->add + add); + Data->len_add = max( Data->len_add, ceil(Data->add) ); +} + +static void initSize( Sound_AudioCVT *Data ) +{ + Data->len_ratio = 1.; + Data->len_mult = 1; + Data->add = 0; + Data->len_add = 0; } /*-------------------------------------------------------------------------*/ static void createRateConverter( Sound_AudioCVT *Data, int* fip, int SrcRate, int DestRate, int Channel ) { + Fraction f; int filter_index = *fip; - int VarPos = 0; int Mono = 2 - Channel; float Ratio = DestRate; @@ -655,9 +710,7 @@ Data->adapter[filter_index++] = Mono ? doubleRateMono : doubleRateStereo; Ratio /= 2.; - Data->mult *= 2; - Data->add *= 2; - Data->add += _fsize; + adjustSize( Data, _fsize, Double ); } while( Ratio < 31./64. ) @@ -665,22 +718,22 @@ Data->adapter[filter_index++] = Mono ? halfRateMono : halfRateStereo; Ratio *= 2; + adjustSize( Data, _fsize, Half ); } if( Ratio > 1. ) { - setupVarFilter( &Data->filter, Ratio ); + f = setupVarFilter( &Data->filter, Ratio ); Data->adapter[VarPos] = Mono ? increaseRateMono : increaseRateStereo; - Data->mult *= 2; - Data->add *= 2; - Data->add += _fsize; + adjustSize( Data, _fsize, f ); } else { - setupVarFilter( &Data->filter, Ratio ); + f = setupVarFilter( &Data->filter, Ratio ); Data->adapter[filter_index++] = Mono ? decreaseRateMono : decreaseRateStereo; + adjustSize( Data, _fsize, f ); } *fip = filter_index; } @@ -693,8 +746,7 @@ if( src.channels == 2 && dst.channels == 1 ) { - Data->add /= 2; - Data->mult /= 2; + adjustSize( Data, 0, Half ); if( !IS_SYSENDIAN(src) ) Data->adapter[filter_index++] = swapBytes; @@ -720,8 +772,7 @@ if( src.channels == 1 && dst.channels == 2 ) { - Data->add *= 2; - Data->mult *= 2; + adjustSize( Data, 0, Double ); Data->adapter[filter_index++] = convertMonoToStereo16Bit; } @@ -735,8 +786,7 @@ int filter_index = *fip; if( IS_16BIT(src) ) { - Data->add /= 2; - Data->mult /= 2; + adjustSize( Data, 0, Half ); if( IS_SYSENDIAN(src) ) Data->adapter[filter_index++] = cut16BitSysTo8Bit; @@ -746,8 +796,7 @@ if( src.channels == 2 && dst.channels == 1 ) { - Data->add /= 2; - Data->mult /= 2; + adjustSize( Data, 0, Half ); if( IS_SIGNED(src) ) Data->adapter[filter_index++] = convertStereoToMonoS8Bit; @@ -760,15 +809,13 @@ if( src.channels == 1 && dst.channels == 2 ) { - Data->add *= 2; - Data->mult *= 2; + adjustSize( Data, 0, Double ); Data->adapter[filter_index++] = convertMonoToStereo8Bit; } if( !IS_8BIT(dst) ) { - Data->add *= 2; - Data->mult *= 2; + adjustSize( Data, 0, Double ); if( IS_SYSENDIAN(dst) ) Data->adapter[filter_index++] = expand8BitTo16BitSys; else @@ -787,8 +834,7 @@ if( IS_FLOAT(src) ) { Data->adapter[filter_index++] = cutFloatTo16Bit; - Data->mult /= 2; - Data->add /= 2; + adjustSize( Data, 0, Half ); } if( IS_8BIT(src) || IS_8BIT(dst) ) @@ -799,13 +845,23 @@ if( IS_FLOAT(dst) ) { Data->adapter[filter_index++] = expand16BitToFloat; - Data->mult *= 2; - Data->add *= 2; + adjustSize( Data, 0, Double ); } *fip = filter_index; } +/*-------------------------------------------------------------------------*/ +Uint32 getSilenceValue( Uint16 format ) +{ + const static float fzero[] = {0.0000001}; + switch( format ) + { + case 0x0020: return *(Uint32*) fzero; + default: ; + } + return 0; +} /*-------------------------------------------------------------------------*/ int BuildAudioCVT( Sound_AudioCVT *Data, @@ -815,9 +871,10 @@ int filter_index = 0; if( Data == NULL ) return -1; - Data->mult = 1.; - Data->add = 0; + initSize( Data ); Data->filter.denominator = 0; + Data->filter.zero = getSilenceValue( dst.format ); + Data->filter.mask = dst.size - 1; /* Check channels */ if( src.channels < 1 || src.channels > 2 || @@ -848,17 +905,16 @@ /* Set up the filter information */ sucess_exit: + Data->adapter[filter_index++] = padSilence; + Data->adapter[filter_index] = NULL; /* !!! FIXME: Is it okay to assign NULL to a function pointer? Borland says no. -frank */ - Data->adapter[filter_index] = NULL; - Data->needed = filter_index > 0 ? 1 : 0; return 0; error_exit: /* !!! FIXME: Is it okay to assign NULL to a function pointer? Borland says no. -frank */ Data->adapter[0] = NULL; - Data->needed = 0; return -1; } @@ -909,17 +965,27 @@ AdapterDesc(increaseRateStereo), AdapterDesc(decreaseRateMono), AdapterDesc(decreaseRateStereo), - { NULL, "----------NULL-----------" } + AdapterDesc(padSilence), + { NULL, "----------NULL-----------\n" } }; - fprintf( stderr, "\nAdapter List: \n" ); + fprintf( stderr, "Sound_AudioCVT:\n" ); + fprintf( stderr, " needed: %8d\n", Data->needed ); + fprintf( stderr, " add: %8g\n", Data->add ); + fprintf( stderr, " len_add: %8d\n", Data->len_add ); + fprintf( stderr, " len_ratio: %8g\n", Data->len_ratio ); + fprintf( stderr, " len_mult: %8d\n", Data->len_mult ); + fprintf( stderr, " filter->mask: %#7x\n", Data->filter.mask ); + fprintf( stderr, "\n" ); + + fprintf( stderr, "Adapter List: \n" ); for( i = 0; i < 32; i++ ) { for( j = 0; j < SDL_TABLESIZE(AdapterDescription); j++ ) { if( Data->adapter[i] == AdapterDescription[j].adapter ) { - fprintf( stderr, " %s\n", AdapterDescription[j].name ); + fprintf( stderr, " %s \n", AdapterDescription[j].name ); if( Data->adapter[i] == NULL ) goto sucess_exit; goto cont; } @@ -933,12 +999,14 @@ if( Data->filter.denominator ) { fprintf( stderr, "Variable Rate Converter:\n" - "numerator: %3d, denominator: %3d\n", + " numerator: %3d\n" + " denominator: %3d\n", Data->filter.denominator, Data->filter.numerator ); - fprintf( stderr, "increment sequence: " ); + fprintf( stderr, " increment sequence:\n" + " " ); for( i = 0; i < Data->filter.denominator; i++ ) - fprintf( stderr, "%3d ", Data->filter.incr[i] ); + fprintf( stderr, "%1d ", Data->filter.incr[i] ); fprintf( stderr, "\n" ); } @@ -951,20 +1019,22 @@ 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 dst_format, Uint8 dst_channels, int dst_rate, Uint32 dst_size ) { SDL_AudioSpec src, dst; int ret; fprintf (stderr, - "Sound_BuildAudioCVT() :\n" - "-----------------------\n" - "format: %s -> %s\n" - "channels: %6d -> %6d\n" - "rate: %6d -> %6d\n", + "Sound_BuildAudioCVT():\n" + "-----------------------------\n" + "format: %s -> %s\n" + "channels: %6d -> %6d\n" + "rate: %6d -> %6d\n" + "size: don't care -> %#7x\n\n", fmt_to_str (src_format), fmt_to_str (dst_format), - src_channels, dst_channels, - src_rate, dst_rate); + src_channels, dst_channels, + src_rate, dst_rate, + dst_size ); src.format = src_format; src.channels = src_channels; @@ -973,14 +1043,14 @@ dst.format = dst_format; dst.channels = dst_channels; dst.freq = dst_rate; + dst.size = dst_size; ret = BuildAudioCVT( Data, src, dst ); - Data->len_mult = Data->mult > 1 ? ceil(Data->mult) : 1; - Data->len_ratio = Data->mult; + Data->needed = 1; show_AudioCVT( Data ); fprintf (stderr, "\n" - "return value: %d \n", ret ); + "return value: %d \n\n\n", ret ); return ret; }