changeset 371:1b463ef9bcc2

More work from Frank.
author Ryan C. Gordon <icculus@icculus.org>
date Tue, 25 Jun 2002 17:15:03 +0000
parents 12023d47b716
children ee0678efd4a3
files alt_audio_convert.c alt_audio_convert.h filter_templates.h
diffstat 3 files changed, 159 insertions(+), 107 deletions(-) [+]
line wrap: on
line diff
--- a/alt_audio_convert.c	Mon Jun 24 23:13:04 2002 +0000
+++ b/alt_audio_convert.c	Tue Jun 25 17:15:03 2002 +0000
@@ -139,14 +139,16 @@
     for( i = 0; Data->adapter[i] != NULL; i++ )
 	length = (*Data->adapter[i])( Temp, length);
 
-    Data->len_cvt = length;
     return length;
 }
 
 int Sound_ConvertAudio( Sound_AudioCVT *Data )
 {
+    int length;
     /* !!! FIXME: Try the looping stuff under certain circumstances? --ryan. */
-    return ConvertAudio( Data, Data->buf, Data->len, 0 );
+    length = ConvertAudio( Data, Data->buf, Data->len, 0 );
+    Data->len_cvt = length;
+    return length;
 }
 
 
@@ -280,8 +282,8 @@
     Sint16* buffer = (Sint16*) Data.buffer;
     Sint16* src = (Sint16*) Data.buffer;
     length >>= 2;
-    for( i = 0; i < length;  i++ )
-         buffer[i] = ((int) *(src++) + *(src++) ) >> 1;
+    for( i = 0; i < length;  i++, src+=2 )
+         buffer[i] = ((int) src[0] + src[1] ) >> 1;
     return 2*length;
 }
 
@@ -291,8 +293,8 @@
     Uint16* buffer = (Uint16*) Data.buffer;
     Uint16* src = (Uint16*) Data.buffer;
     length >>= 2;
-    for( i = 0; i < length;  i++ )
-         buffer[i] = ((int) *(src++) + *(src++) ) >> 1;
+    for( i = 0; i < length;  i++, src+=2 )
+         buffer[i] = ((int) src[0] + src[1] ) >> 1;
     return 2*length;
 }
 
@@ -302,8 +304,8 @@
     Sint8* buffer = (Sint8*) Data.buffer;
     Sint8* src = (Sint8*) Data.buffer;
     length >>= 1;
-    for( i = 0; i < length;  i++ )
-         buffer[i] = ((int) *(src++) + *(src++) ) >> 1;
+    for( i = 0; i < length;  i++, src+=2 )
+         buffer[i] = ((int) src[0] + src[1] ) >> 1;
     return length;
 }
 
@@ -313,8 +315,8 @@
     Uint8* buffer = (Uint8*) Data.buffer;
     Uint8* src = (Uint8*) Data.buffer;
     length >>= 1;
-    for( i = 0; i < length;  i++ )
-         buffer[i] = ((int) *(src++) + *(src++) ) >> 1;
+    for( i = 0; i < length;  i++, src+=2 )
+         buffer[i] = ((int) src[0] + src[1] ) >> 1;
     return length;
 }
 
@@ -324,8 +326,8 @@
     int i;
     Uint16* buffer = (Uint16*) Data.buffer;
     Uint16* dst = (Uint16*)Data.buffer + length;
-    for( i = length>>1; i--; )
-         *(--dst) = *(--dst) = buffer[i];
+    for( i = length>>1; i--; dst-=2 )
+         dst[-1] = dst[-2] = buffer[i];
     return 2*length;
 }
 
@@ -334,8 +336,8 @@
     int i;
     Uint8* buffer = Data.buffer;
     Uint8* dst = Data.buffer + 2*length;
-    for( i = length; i--; )
-         *(--dst) = *(--dst) = buffer[i];
+    for( i = length; i--; dst-=2 )
+         dst[-1] = dst[-2] = buffer[i];
     return 2*length;
 }
 
@@ -350,21 +352,28 @@
 }
 
 /*-------------------------------------------------------------------------*/
-enum RateConverterType { varRate = 0, hlfRate = 1, dblRate = 2 };
+enum RateConverterType{
+    dcrsRate = 0,
+    incrsRate = 1,
+    hlfRate = 2,
+    dblRate = 3
+};
+
 static void initRateConverterBuffer( RateConverterBuffer *rcb,
-    AdapterC* Data, int length, enum RateConverterType r, int rel_size )
+    AdapterC* Data, int length, enum RateConverterType typ )
 {
-    int size, dir;
-    int den[] = { 0, 1, 2};
-    int num[] = { 0, 2, 1};
+    int size, minsize, dir;
+    int den[] = { 0, 0, 1, 2};
+    int num[] = { 0, 0, 2, 1};
     int i;
 
-    den[0] = Data->filter->denominator;
-    num[0] = Data->filter->numerator;
+    den[incrsRate] = Data->filter->denominator;
+    num[incrsRate] = Data->filter->numerator;
 
-    size = 2 * _fsize * abs(rel_size);
-    dir = rel_size > 0 ? 1 : 0;
+    size = 8 * _fsize;
+    dir = typ&1;
     length >>= 1;
+    minsize = min( length, size );
 
     rcb->buffer = (Sint16*)( Data->buffer );
 
@@ -379,28 +388,31 @@
         }
         rcb->finp = rcb->linp = rcb->inbuffer + size;
         if( size < 0 )
-            rcb->buffer += num[r] * ( length + 2 * size ) / den[r];
+            rcb->buffer += num[typ] * ( length + 2 * size ) / den[typ];
     }
     else
     {
+        for( i = 0; i < minsize; i++ )
+        {
+            rcb->inbuffer[i] = rcb->buffer[length-size+i];
+            rcb->inbuffer[i+size] = 0;
+            rcb->inbuffer[i+2*size] = rcb->buffer[i];
+        }
         for( i = 0; i < size; i++ )
         {
-            int k;
-            k = length-size+i;
-            rcb->inbuffer[i] = k < 0 ? 0 : rcb->buffer[k];
+            rcb->inbuffer[i] = 0;
             rcb->inbuffer[i+size] = 0;
-            rcb->inbuffer[i+2*size] = i < length ? rcb->buffer[i] : 0;
+            rcb->inbuffer[i+2*size] = 0;
         }
-        // !!!FIXME: take lenght < size into account
-        rcb->flength = rcb->llength = size;
-        rcb->clength = length - size;
+        rcb->flength = rcb->llength = size/2 + minsize/2;
+        rcb->clength = length - minsize;
 
         if( dir )
         {
-            rcb->finp = rcb->inbuffer + 5*size/2;
-            rcb->cinp = rcb->buffer + length - size/2;
-            rcb->linp = rcb->inbuffer + 3*size/2;
-            rcb->buffer += den[r] * ( length + size ) / num[r];
+            rcb->finp = rcb->inbuffer + 2 * size + minsize/2;
+            rcb->cinp = rcb->buffer + length - minsize/2;
+            rcb->linp = rcb->inbuffer + size + minsize/2;
+            rcb->buffer += den[typ] * ( length + minsize ) / num[typ];
         }
         else
         {
@@ -435,17 +447,24 @@
 
 
 /*-------------------------------------------------------------------------*/
+   /*
+    * !!! FIXME !!!
+    *
+    * The doubleRate filter is half as large as the halfRate one!  Frank
+    */
+
+
 static int doubleRateMono( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, dblRate, 1 );
+    initRateConverterBuffer( &rcb, &Data, length, dblRate );
     return doRateConversion( &rcb, doubleRate1, NULL );
 }
 
 static int doubleRateStereo( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, dblRate, 2 );
+    initRateConverterBuffer( &rcb, &Data, length, dblRate );
     doRateConversion( &rcb, doubleRate2, NULL );
     nextRateConverterBuffer( &rcb );
     return 2 + doRateConversion( &rcb, doubleRate2, NULL );
@@ -455,14 +474,14 @@
 static int halfRateMono( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, hlfRate, -1 );
+    initRateConverterBuffer( &rcb, &Data, length, hlfRate );
     return doRateConversion( &rcb, halfRate1, NULL );
 }
 
 static int halfRateStereo( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, hlfRate, -2 );
+    initRateConverterBuffer( &rcb, &Data, length, hlfRate );
     doRateConversion( &rcb, halfRate2, NULL );
     nextRateConverterBuffer( &rcb );
     return 2 + doRateConversion( &rcb, halfRate2, NULL );
@@ -472,14 +491,14 @@
 static int increaseRateMono( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, varRate, 2 );
+    initRateConverterBuffer( &rcb, &Data, length, incrsRate );
     return doRateConversion( &rcb, increaseRate1, Data.filter );
 }
 
 static int increaseRateStereo( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, varRate, 4 );
+    initRateConverterBuffer( &rcb, &Data, length, incrsRate );
     doRateConversion( &rcb, increaseRate2, Data.filter );
     nextRateConverterBuffer( &rcb );
     return 2 + doRateConversion( &rcb, increaseRate2, Data.filter );
@@ -489,14 +508,14 @@
 static int decreaseRateMono( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, varRate, -2 );
+    initRateConverterBuffer( &rcb, &Data, length, dcrsRate );
     return doRateConversion( &rcb, decreaseRate1, Data.filter );
 }
 
 static int decreaseRateStereo( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, varRate, -4 );
+    initRateConverterBuffer( &rcb, &Data, length, dcrsRate );
     doRateConversion( &rcb, decreaseRate2, Data.filter );
     nextRateConverterBuffer( &rcb );
     return doRateConversion( &rcb, decreaseRate2, Data.filter );
@@ -532,13 +551,14 @@
 
 
     Fraction Result = {0,0};
-    int n,num=1,den=1;
+    int i,num,den=1;
 
     float RelErr, BestErr = 0;
     if( Value < 31/64. || Value > 64/31. ) return Result;
 
-    for( n = 0; n < SDL_TABLESIZE(frac); num=frac[n++] )
+    for( i = 0; i < SDL_TABLESIZE(frac); i++ )
     {
+         num = frac[i];
          if( num < 0 ) den++;
          RelErr = Value * num / den;
          RelErr = min( RelErr, 1/RelErr );
@@ -584,41 +604,28 @@
     }
 }
 
-typedef struct{
-    float scale;
-    int incr;
-} VarFilterMode;
-
-const VarFilterMode Up = { 0.0211952, -1 };
-const VarFilterMode Down = { 0.0364733, 1 };
+static void setupVarFilter( VarFilter* filter, float Ratio )
+{
+    int i,n,d, incr, phase = 0;
+    float Scale, rd;
+    Fraction IRatio;
 
-static void setupVarFilter( VarFilter* filter,
-                     float Ratio, VarFilterMode Direction )
-{
-    int i,n,d;
-    Fraction IRatio;
-    float phase = 0.;
     IRatio = findFraction( Ratio );
+    Scale = Ratio < 1. ? 0.0364733 : 0.0211952;
     Ratio = min( Ratio, 1/Ratio );
 
     n = IRatio.numerator;
     d = IRatio.denominator;
     filter->denominator = d;
     filter->numerator = n;
+    rd = 1. / d;
 
     for( i = 0; i < d; i++ )
     {
-        if( phase >= n )
-        {
-            phase -= d;
-            filter->incr[i] = abs(Direction.incr);
-        }
-        else
-            filter->incr[i] = abs(1+Direction.incr);
-
-        calculateVarFilter( filter->c[i], Ratio, phase/(float)n,
-                            Direction.scale );
-        phase += d;
+        calculateVarFilter( filter->c[i], Ratio, phase*rd, Scale );
+        phase += n;
+        filter->incr[i] = phase / d;
+        phase %= d;
     }
 }
 
@@ -648,7 +655,7 @@
         Data->adapter[filter_index++] =
             Mono ? doubleRateMono : doubleRateStereo;
         Ratio /= 2.;
-        Data->len_mult *= 2;
+        Data->mult *= 2;
         Data->add *= 2;
         Data->add += _fsize;
     }
@@ -662,16 +669,16 @@
 
     if( Ratio > 1. )
     {
-        setupVarFilter( &Data->filter, Ratio, Up );
+        setupVarFilter( &Data->filter, Ratio );
         Data->adapter[VarPos] =
             Mono ? increaseRateMono : increaseRateStereo;
-        Data->len_mult *= 2;
+        Data->mult *= 2;
         Data->add *= 2;
         Data->add += _fsize;
     }
     else
     {
-        setupVarFilter( &Data->filter, Ratio, Down );
+        setupVarFilter( &Data->filter, Ratio );
         Data->adapter[filter_index++] =
             Mono ? decreaseRateMono : decreaseRateStereo;
     }
@@ -687,7 +694,7 @@
     if( src.channels == 2 && dst.channels == 1 )
     {
         Data->add /= 2;
-        Data->len_mult /= 2;
+        Data->mult /= 2;
 
         if( !IS_SYSENDIAN(src) )
             Data->adapter[filter_index++] = swapBytes;
@@ -714,7 +721,7 @@
     if( src.channels == 1 && dst.channels == 2 )
     {
         Data->add *= 2;
-        Data->len_mult *= 2;
+        Data->mult *= 2;
         Data->adapter[filter_index++] = convertMonoToStereo16Bit;
     }
 
@@ -729,7 +736,7 @@
     if( IS_16BIT(src) )
     {
         Data->add /= 2;
-        Data->len_mult /= 2;
+        Data->mult /= 2;
 
         if( IS_SYSENDIAN(src) )
             Data->adapter[filter_index++] = cut16BitSysTo8Bit;
@@ -740,7 +747,7 @@
     if( src.channels == 2 && dst.channels == 1 )
     {
         Data->add /= 2;
-        Data->len_mult /= 2;
+        Data->mult /= 2;
 
         if( IS_SIGNED(src) )
             Data->adapter[filter_index++] = convertStereoToMonoS8Bit;
@@ -754,14 +761,14 @@
     if( src.channels == 1 && dst.channels == 2  )
     {
         Data->add *= 2;
-        Data->len_mult *= 2;
+        Data->mult *= 2;
         Data->adapter[filter_index++] = convertMonoToStereo8Bit;
     }
 
     if( !IS_8BIT(dst) )
     {
         Data->add *= 2;
-        Data->len_mult *= 2;
+        Data->mult *= 2;
         if( IS_SYSENDIAN(dst) )
             Data->adapter[filter_index++] = expand8BitTo16BitSys;
         else
@@ -780,7 +787,7 @@
     if( IS_FLOAT(src) )
     {
         Data->adapter[filter_index++] = cutFloatTo16Bit;
-        Data->len_mult /= 2;
+        Data->mult /= 2;
         Data->add /= 2;
     }
 
@@ -792,7 +799,7 @@
     if( IS_FLOAT(dst) )
     {
         Data->adapter[filter_index++] = expand16BitToFloat;
-        Data->len_mult *= 2;
+        Data->mult *= 2;
         Data->add *= 2;
     }
 
@@ -808,8 +815,9 @@
     int filter_index = 0;
 
     if( Data == NULL ) return -1;
-    Data->len_mult = 1.;
+    Data->mult = 1.;
     Data->add = 0;
+    Data->filter.denominator = 0;
 
     /* Check channels */
     if( src.channels < 1 || src.channels > 2 ||
@@ -840,17 +848,17 @@
 
     /* Set up the filter information */
 sucess_exit:
-    if( filter_index > 0 )
-        Data->needed = 1;
 /* !!! 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;
 }
 
@@ -912,14 +920,32 @@
             if( Data->adapter[i] == AdapterDescription[j].adapter )
             {
                 fprintf( stderr, "    %s\n", AdapterDescription[j].name );
-                if( Data->adapter[i] == NULL ) return;
+                if( Data->adapter[i] == NULL ) goto sucess_exit;
                 goto cont;
             }
         }
         fprintf( stderr, "    Error: unknown adapter\n" );
+
         cont:
     }
     fprintf( stderr, "    Error: NULL adapter missing\n" );
+    sucess_exit:
+    if( Data->filter.denominator )
+    {
+        fprintf( stderr, "Variable Rate Converter:\n"
+                         "numerator: %3d, denominator: %3d\n",
+                         Data->filter.denominator, Data->filter.numerator );
+
+        fprintf( stderr, "increment sequence: " );
+        for( i = 0; i < Data->filter.denominator; i++ )
+             fprintf( stderr, "%3d ", Data->filter.incr[i] );
+
+        fprintf( stderr, "\n" );
+    }
+    else
+    {
+        fprintf( stderr, "No Variable Rate Converter\n" );
+    }
 }
 
 
@@ -949,6 +975,8 @@
     dst.freq = dst_rate;
 
     ret = BuildAudioCVT( Data, src, dst );
+	Data->len_mult = Data->mult > 1 ? ceil(Data->mult) : 1;
+	Data->len_ratio = Data->mult;
 
     show_AudioCVT( Data );
     fprintf (stderr, "\n"
--- a/alt_audio_convert.h	Mon Jun 24 23:13:04 2002 +0000
+++ b/alt_audio_convert.h	Tue Jun 25 17:15:03 2002 +0000
@@ -35,7 +35,7 @@
 
 typedef struct{
    Sint16 c[16][4*_fsize];
-   char incr[16];
+   Uint8 incr[16];
    int denominator;
    int numerator;
 } VarFilter;
@@ -53,16 +53,23 @@
     int    add;
     int (*adapter[32]) ( AdapterC Data, int length );
 } SDL_AudioC;
-
*/
+
+*/
+
+/* the len_* variables and the needed variable are not used internally, 
+they are provided for compatibility */
 
 typedef struct{
    int needed;
    VarFilter filter;
-   double len_mult;           /* buffer must be len*len_mult big*/
    Uint8* buf;
-   int len;
-   int len_cvt;                 /* Length of converted audio buffer */
-   int add;
+   int len;                /* Length of original audio buffer  */ 
+   int len_cvt;            /* Length of converted audio buffer */
+   int len_mult;           /* buffer must be len*len_mult big */
+   double len_ratio;       /* Given len, final size is len*len_ratio */
+        
+   double add;
+   double mult;        
    int (*adapter[32]) ( AdapterC Data, int length );
 } Sound_AudioCVT;
 
--- a/filter_templates.h	Mon Jun 24 23:13:04 2002 +0000
+++ b/filter_templates.h	Tue Jun 25 17:15:03 2002 +0000
@@ -98,6 +98,7 @@
         out+=  1800 * sum_h( inp,  9);
         out-=  2560 * sum_h( inp,  7);
         out+=  3863 * sum_h( inp,  5);
+        out-=  6764 * sum_h( inp,  3);
         out+= 20798 * sum_h( inp,  1);
         out+= 32770 * (int)inp[0];
 
@@ -111,59 +112,75 @@
 
 /*-------------------------------------------------------------------------*/
 static Sint16* Suffix(increaseRate)( Sint16 *outp, Sint16 *inp, int length,
-                                     VarFilter* filt, int* cpos )
+                                     VarFilter* filter, int* cpos )
 {
     const static int fsize = CH(2*_fsize);
-    Sint16 *filter;
+    Sint16 *f;
     int out;
     int i, pos;
     Sint16* to;
 
     inp -= fsize;
     to = inp - length;
+    pos = *cpos;
 
     while( inp > to )
     {
-        pos = *cpos;
         out = 0;
-        filter = filt->c[pos];
-        for( i = 0; i < 4*_fsize; i++ )
-    	    out+= filter[i] * (int)inp[CH(i)];
+        f = filter->c[pos];
+        for( i = _fsize + 1; --i; inp+=CH(4), f+=4 )
+        {
+    	    out+= f[0] * (int)inp[CH(0)];
+    	    out+= f[1] * (int)inp[CH(1)];
+    	    out+= f[2] * (int)inp[CH(2)];
+    	    out+= f[3] * (int)inp[CH(3)];
+        }
         outp[0] = out >> 16;
 
-        inp -= CH(filt->incr[pos]);
+        pos = ( pos + filter->denominator - 1 ) % filter->denominator;
+        inp -= CH( 4 * _fsize );
+        inp -= CH( filter->incr[pos] );
         outp -= CH(1);
-        *cpos = ( pos + 1 ) % filt->denominator;
     }
+
+    *cpos = pos;
     return outp;
 }
 
 /*-------------------------------------------------------------------------*/
 static Sint16* Suffix(decreaseRate)( Sint16 *outp, Sint16 *inp, int length,
-                                     VarFilter* filt, int* cpos )
+                                     VarFilter* filter, int* cpos )
 {
     const static int fsize = CH(2*_fsize);
-    Sint16 *filter;
+    Sint16 *f;
     int out;
     int i, pos;
     Sint16 *to;
 
     inp -= fsize;
     to = inp + length;
+    pos = *cpos;
 
     while( inp < to )
     {
-        pos = *cpos;
         out = 0;
-        filter = filt->c[pos];
-        for( i = 0; i < 4*_fsize; i++ )
-    	    out+= filter[i] * inp[CH(i)];
+        f = filter->c[pos];
+        for( i = _fsize + 1; --i; inp+=CH(4), f+=4 )
+        {
+    	    out+= f[0] * (int)inp[CH(0)];
+    	    out+= f[1] * (int)inp[CH(1)];
+    	    out+= f[2] * (int)inp[CH(2)];
+    	    out+= f[3] * (int)inp[CH(3)];
+        }
         outp[0] = out >> 16;
 
-        inp += CH(filt->incr[pos]);
+        inp -= CH( 4 * _fsize );
+        inp += CH( filter->incr[pos] );
         outp += CH(1);
-        *cpos = ( pos + 1 ) % filt->denominator;
+        pos = ( pos + 1 ) % filter->denominator;
     }
+
+    *cpos = pos;
     return outp;
 }