changeset 366:eda146d666d1

More patches from Frank.
author Ryan C. Gordon <icculus@icculus.org>
date Fri, 21 Jun 2002 20:03:46 +0000
parents f61eadea1f44
children ae8d3fb4ae0b
files alt_audio_convert.c alt_audio_convert.h filter_templates.h
diffstat 3 files changed, 111 insertions(+), 86 deletions(-) [+]
line wrap: on
line diff
--- a/alt_audio_convert.c	Tue Jun 18 21:49:44 2002 +0000
+++ b/alt_audio_convert.c	Fri Jun 21 20:03:46 2002 +0000
@@ -26,7 +26,6 @@
  */
 
 #include "alt_audio_convert.h"
-#include <stdlib.h>
 #include <math.h>
 
 /* just to make sure this is defined... */
@@ -35,8 +34,8 @@
 #define min(x, y) ( ((x) < (y)) ? (x) : (y) )
 #endif
 
-#ifndef max
-#define max(x, y) ( ((x) > (y)) ? (x) : (y) )
+#ifndef abs
+#define abs(x) ( ((x) > (0)) ? (x) : -(x) )
 #endif
 
 
@@ -50,17 +49,6 @@
 
 
 /*-------------------------------------------------------------------------*/
-/* this filter (Kaiser-window beta=6.8) gives a decent -80dB attentuation  */
-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
-};
-
-
-/*-------------------------------------------------------------------------*/
 /* 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
@@ -87,7 +75,7 @@
    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.
+   movement is stored in flength, always positive.
 
    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
@@ -95,7 +83,7 @@
    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,
+   Finally the decay of the filter is done by linp and llength like finp,
    flength, but in reverse order.
 
    buffer denotes the start or the end of the output buffer, depending
@@ -106,7 +94,7 @@
 
 typedef struct
 {
-    Sint16 inbuffer[6*_fsize];
+    Sint16 inbuffer[24*_fsize];
     Sint16 *finp, *cinp, *linp;
     Sint16 *buffer;
     int flength, clength, llength;
@@ -361,24 +349,28 @@
 }
 
 /*-------------------------------------------------------------------------*/
+enum RateConverterType { varRate = 0, hlfRate = 1, dblRate = 2 };
 static void initRateConverterBuffer( RateConverterBuffer *rcb,
-    AdapterC* Data, int length, int rel_size )
+    AdapterC* Data, int length, RateConverterType r, int rel_size )
 {
-    int size, slength;
-    int den, num;
+    int size, dir;
+    int den[] = { 0, 1, 2};
+    int num[] = { 0, 2, 1};
     int i;
 
-    den = Data->filter->denominator;
-    num = Data->filter->numerator;
-    size = _fsize * rel_size;
+    den[0] = Data->filter->denominator;
+    num[0] = Data->filter->numerator;
+
+    size = 2 * _fsize * abs(rel_size);
+    dir = rel_size > 0 ? 1 : 0;
     length >>= 1;
-    slength = rel_size > 0 ? length : -length;
 
     rcb->buffer = (Sint16*)( Data->buffer );
 
     if( Data->mode & SDL_AI_Loop )
     {
-        // !!!FIXME: modulo length, take scale into account
+        // !!!FIXME: modulo length, take scale into account,
+        // check against the 'else' part
         for( i = 0; i < size; i++ )
         {
             rcb->inbuffer[i] = rcb->buffer[length-size+i];
@@ -386,26 +378,35 @@
         }
         rcb->finp = rcb->linp = rcb->inbuffer + size;
         if( size < 0 )
-            rcb->buffer += num * ( length + 2 * size ) / den;
+            rcb->buffer += num[r] * ( length + 2 * size ) / den[r];
     }
     else
     {
         for( i = 0; i < size; i++ )
         {
-            int j;
-            j = length-size+i;
-            rcb->inbuffer[i] = j < 0 ? 0 : rcb->buffer[j];
+            int k;
+            k = length-size+i;
+            rcb->inbuffer[i] = k < 0 ? 0 : rcb->buffer[k];
             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;
+        rcb->flength = rcb->llength = size;
+        rcb->clength = length - size;
 
-        if( size < 0 )
-            rcb->buffer += num * ( length + 2 * size ) / den;
+        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];
+        }
+        else
+        {
+            rcb->finp = rcb->inbuffer + size/2;
+            rcb->cinp = rcb->buffer + size/2;
+            rcb->linp = rcb->inbuffer + 3*size/2;
+        }
     }
 }
 
@@ -436,14 +437,14 @@
 static int doubleRateMono( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, 1 );
+    initRateConverterBuffer( &rcb, &Data, length, dblRate, 1 );
     return doRateConversion( &rcb, doubleRate1, NULL );
 }
 
 static int doubleRateStereo( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, 2 );
+    initRateConverterBuffer( &rcb, &Data, length, dblRate, 2 );
     doRateConversion( &rcb, doubleRate2, NULL );
     nextRateConverterBuffer( &rcb );
     return 2 + doRateConversion( &rcb, doubleRate2, NULL );
@@ -453,14 +454,14 @@
 static int halfRateMono( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, -1 );
+    initRateConverterBuffer( &rcb, &Data, length, hlfRate, -1 );
     return doRateConversion( &rcb, halfRate1, NULL );
 }
 
 static int halfRateStereo( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, -2 );
+    initRateConverterBuffer( &rcb, &Data, length, hlfRate, -2 );
     doRateConversion( &rcb, halfRate2, NULL );
     nextRateConverterBuffer( &rcb );
     return 2 + doRateConversion( &rcb, halfRate2, NULL );
@@ -470,14 +471,14 @@
 static int increaseRateMono( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, 2 );
+    initRateConverterBuffer( &rcb, &Data, length, varRate, 2 );
     return doRateConversion( &rcb, increaseRate1, Data.filter );
 }
 
 static int increaseRateStereo( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, 4 );
+    initRateConverterBuffer( &rcb, &Data, length, varRate, 4 );
     doRateConversion( &rcb, increaseRate2, Data.filter );
     nextRateConverterBuffer( &rcb );
     return 2 + doRateConversion( &rcb, increaseRate2, Data.filter );
@@ -487,14 +488,14 @@
 static int decreaseRateMono( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, -2 );
+    initRateConverterBuffer( &rcb, &Data, length, varRate, -2 );
     return doRateConversion( &rcb, decreaseRate1, Data.filter );
 }
 
 static int decreaseRateStereo( AdapterC Data, int length )
 {
     RateConverterBuffer rcb;
-    initRateConverterBuffer( &rcb, &Data, length, -4 );
+    initRateConverterBuffer( &rcb, &Data, length, varRate, -4 );
     doRateConversion( &rcb, decreaseRate2, Data.filter );
     nextRateConverterBuffer( &rcb );
     return doRateConversion( &rcb, decreaseRate2, Data.filter );
@@ -535,7 +536,7 @@
     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 < SDL_TABLESIZE(frac); num=frac[n++] )
     {
          if( num < 0 ) den++;
          RelErr = Value * num / den;
@@ -609,10 +610,10 @@
         if( phase >= n )
         {
             phase -= d;
-            filter->incr[i] = Direction.incr;
+            filter->incr[i] = abs(Direction.incr);
         }
         else
-            filter->incr[i] = 1+Direction.incr;
+            filter->incr[i] = abs(1+Direction.incr);
 
         calculateVarFilter( filter->c[i], Ratio, phase/(float)n,
                             Direction.scale );
@@ -899,13 +900,11 @@
         AdapterDesc(decreaseRateStereo),
         { NULL,    "----------NULL-----------" }
     };
-    const int AdapterDescMax = sizeof(AdapterDescription)
-                             / sizeof(*AdapterDescription);
 
     fprintf( stderr, "\nAdapter List:    \n" );
     for( i = 0; i < 32; i++ )
     {
-        for( j = 0; j < AdapterDescMax; j++ )
+        for( j = 0; j < SDL_TABLESIZE(AdapterDescription); j++ )
         {
             if( Data->adapter[i] == AdapterDescription[j].adapter )
             {
--- a/alt_audio_convert.h	Tue Jun 18 21:49:44 2002 +0000
+++ b/alt_audio_convert.h	Fri Jun 21 20:03:46 2002 +0000
@@ -25,16 +25,16 @@
  * (This code blatantly abducted for SDL_sound. Thanks, Frank! --ryan.)
  */
 
-#ifndef _INCLUDE_ALT_AUDIO_CONVERT_H_
-#define _INCLUDE_ALT_AUDIO_CONVERT_H_
+#ifndef _INCLUDE_AUDIO_CONVERT_H_
+#define _INCLUDE_AUDIO_CONVERT_H_
 
 #include "SDL_audio.h"
 #define Sound_AI_Loop 0x2
-#define _fsize 64
+#define _fsize 32
 
 
 typedef struct{
-   Sint16 c[16][2*_fsize];
+   Sint16 c[16][4*_fsize];
    char incr[16];
    int denominator;
    int numerator;
@@ -74,5 +74,5 @@
    Uint16 src_format, Uint8 src_channels, int src_rate,
    Uint16 dst_format, Uint8 dst_channels, int dst_rate );
 
-#endif /* _INCLUDE_ALT_AUDIO_CONVERT_H_ */
+#endif /* _INCLUDE_AUDIO_CONVERT_H_ */
 
--- a/filter_templates.h	Tue Jun 18 21:49:44 2002 +0000
+++ b/filter_templates.h	Fri Jun 21 20:03:46 2002 +0000
@@ -29,57 +29,81 @@
 #error include filter_template.h with defined Suffix macro!
 #else
 #define CH(x) (Suffix((x)*))
-/*-------------------------------------------------------------------------*/
-   /*
-    * !!! FIXME !!!
-    *
-    *
-    * Tune doubleRate(), halfRate() and varRate() for speed
-    * - Frank
-    */
 
 /*-------------------------------------------------------------------------*/
+/* this filter (Kaiser-window beta=6.8) gives a decent -80dB attentuation  */
+/*-------------------------------------------------------------------------*/
+#define sum_d(v,dx) ((int) v[CH(dx)] + v[CH(1-dx)])
 static Sint16* Suffix(doubleRate)( Sint16 *outp, Sint16 *inp, int length,
                                    VarFilter* filt, int* cpos  )
 {
-    static const int fsize = _fsize;
-    int i, out;
-    Sint16* to;
+    int out;
+    Sint16 *to;
+
+    to = inp - length;
 
-    inp += fsize;
-    to = inp + length;
-
-    for(; inp > to; inp -= CH(1) )
+    while( inp > to )
     {
-        out = 0;
-        for( i = 1; i < 1+fsize; i++ )
-            out+= filter[2*i] * ( inp[CH(i)] + inp[CH(1-i)] );
+        out =     0;
+        out-=     9 * sum_d( inp, 16);
+        out+=    23 * sum_d( inp, 15);
+        out-=    46 * sum_d( inp, 14);
+        out+=    83 * sum_d( inp, 13);
+        out-=   138 * sum_d( inp, 12);
+        out+=   217 * sum_d( inp, 11);
+        out-=   326 * sum_d( inp, 10);
+        out+=   474 * sum_d( inp,  9);
+        out-=   671 * sum_d( inp,  8);
+        out+=   936 * sum_d( inp,  7);
+        out-=  1295 * sum_d( inp,  6);
+        out+=  1800 * sum_d( inp,  5);
+        out-=  2560 * sum_d( inp,  4);
+        out+=  3863 * sum_d( inp,  3);
+        out-=  6764 * sum_d( inp,  2);
+        out+= 20798 * sum_d( inp,  1);
 
         outp[CH(1)] = ( 32770 * inp[CH(1)] + out) >> 16;
         outp[CH(0)] = ( 32770 * inp[CH(0)] + out) >> 16;
+
+        inp -= CH(1);
         outp -= CH(2);
     }
     return outp;
 }
 
 /*-------------------------------------------------------------------------*/
+#define sum_h(v,dx) ((int) v[CH(dx)] + v[CH(-dx)])
 static Sint16* Suffix(halfRate)( Sint16 *outp, Sint16 *inp, int length,
                                  VarFilter* filt, int* cpos  )
 {
-    static const int fsize = CH(_fsize/2);
-    int i, out;
+    int out;
     Sint16* to;
 
-    inp -= fsize;
     to = inp + length;
 
-    for(; inp < to; inp+= CH(2) )
+    while( inp < to )
     {
-        out = 32770 * inp[0];
-        for( i = 1; i < fsize/2; i+=2 )
-    	    out+= filter[i]*( (int)inp[CH(i)] + inp[CH(-i)] );
+        out =     0;
+        out-=     9 * sum_h( inp, 31);
+        out+=    23 * sum_h( inp, 29);
+        out-=    46 * sum_h( inp, 27);
+        out+=    83 * sum_h( inp, 25);
+        out-=   138 * sum_h( inp, 23);
+        out+=   217 * sum_h( inp, 21);
+        out-=   326 * sum_h( inp, 19);
+        out+=   474 * sum_h( inp, 17);
+        out-=   671 * sum_h( inp, 15);
+        out+=   936 * sum_h( inp, 13);
+        out-=  1295 * sum_h( inp, 11);
+        out+=  1800 * sum_h( inp,  9);
+        out-=  2560 * sum_h( inp,  7);
+        out+=  3863 * sum_h( inp,  5);
+        out+= 20798 * sum_h( inp,  1);
+        out+= 32770 * (int)inp[0];
+
         outp[0] = out >> 16;
 
+        inp+= CH(2);
         outp += CH(1);
     }
     return outp;
@@ -89,21 +113,21 @@
 static Sint16* Suffix(increaseRate)( Sint16 *outp, Sint16 *inp, int length,
                                      VarFilter* filt, int* cpos )
 {
-    const static int fsize = 2*_fsize;
+    const static int fsize = CH(2*_fsize);
     Sint16 *filter;
     int out;
     int i, pos;
     Sint16* to;
 
-    inp += fsize;
-    to = inp + length;
+    inp -= fsize;
+    to = inp - length;
 
     while( inp > to )
     {
         pos = *cpos;
         out = 0;
         filter = filt->c[pos];
-        for( i = 0; i < 2*_fsize; i++ )
+        for( i = 0; i < 4*_fsize; i++ )
     	    out+= filter[i] * (int)inp[CH(i)];
         outp[0] = out >> 16;
 
@@ -118,7 +142,7 @@
 static Sint16* Suffix(decreaseRate)( Sint16 *outp, Sint16 *inp, int length,
                                      VarFilter* filt, int* cpos )
 {
-    const static int fsize = 2*_fsize;
+    const static int fsize = CH(2*_fsize);
     Sint16 *filter;
     int out;
     int i, pos;
@@ -132,8 +156,8 @@
         pos = *cpos;
         out = 0;
         filter = filt->c[pos];
-        for( i = 0; i < 2*_fsize; i++ )
-    	    out+= filter[i] * (int)inp[CH(i)];
+        for( i = 0; i < 4*_fsize; i++ )
+    	    out+= filter[i] * inp[CH(i)];
         outp[0] = out >> 16;
 
         inp += CH(filt->incr[pos]);
@@ -144,6 +168,8 @@
 }
 
 /*-------------------------------------------------------------------------*/
+#undef sum_d
+#undef sum_h
 #undef CH
 #endif /* Suffix */