diff options
author | Franklin Wei <git@fwei.tk> | 2018-01-05 17:25:03 -0500 |
---|---|---|
committer | Franklin Wei <git@fwei.tk> | 2018-01-15 19:45:28 -0500 |
commit | cf07bb328deb71cf2dc602f435b5340b0b55a2e5 (patch) | |
tree | e90dc67756cedabb0e857ad2f44309791a92e38b /apps | |
parent | 69ff35ac497abddd0559412f82682d717888eb03 (diff) | |
download | rockbox-cf07bb328deb71cf2dc602f435b5340b0b55a2e5.tar.gz rockbox-cf07bb328deb71cf2dc602f435b5340b0b55a2e5.zip |
duke3d: further optimize audio mixing
Rather than holding intermediate results as fixed-point, this converts them
directly to normal integers (in the range of the PCM sample) while mixing,
instead of waiting till the end to perform a separate shifting step. Also,
this precalculates some constants in the reverb code.
Change-Id: Ie04e444d145bc28ce67eef9ae0ead6d328acf28a
Diffstat (limited to 'apps')
5 files changed, 65 insertions, 52 deletions
diff --git a/apps/plugins/sdl/progs/duke3d/Engine/src/display.c b/apps/plugins/sdl/progs/duke3d/Engine/src/display.c index 3883803bce..501ffa411c 100644 --- a/apps/plugins/sdl/progs/duke3d/Engine/src/display.c +++ b/apps/plugins/sdl/progs/duke3d/Engine/src/display.c @@ -1368,9 +1368,13 @@ int VBE_setPalette(uint8_t *palettebuffer) memcpy(lastPalette, palettebuffer, 768); for (i = 0; i < 256; i++){ - sdlp->b = (Uint8) ((((float) *p++) / 63.0) * 255.0); - sdlp->g = (Uint8) ((((float) *p++) / 63.0) * 255.0); - sdlp->r = (Uint8) ((((float) *p++) / 63.0) * 255.0); + /* doesn't map perfectly */ + sdlp->b = (Uint8) (*p << 2) | (*p >> 4); + p++; + sdlp->g = (Uint8) (*p << 2) | (*p >> 4); + p++; + sdlp->r = (Uint8) (*p << 2) | (*p >> 4); + p++; sdlp->unused = *p++; /* This byte is unused in BUILD, too. */ sdlp++; } diff --git a/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/multivoc.c b/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/multivoc.c index 7567d7314b..2c03a862f8 100644 --- a/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/multivoc.c +++ b/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/multivoc.c @@ -122,7 +122,7 @@ static int MV_FooMemory; static int MV_BufferDescriptor; static int MV_BufferEmpty[ NumberOfBuffers ]; char *MV_MixBuffer[ NumberOfBuffers + 1 ]; -/* fixed-point */ +/* raw samples in range [-2^15, 2^15-1], interleaved stereo */ long *MV_FooBuffer = NULL; static VoiceNode *MV_Voices = NULL; @@ -465,8 +465,8 @@ void MV_ServiceVoc } { - ClearBuffer_DW( MV_FooBuffer, 0, sizeof(long) / 4 * MV_BufferSize / MV_SampleSize * MV_Channels); - MV_BufferEmpty[ MV_MixPage ] = TRUE; + ClearBuffer_DW( MV_FooBuffer, 0, (sizeof(long) * MV_BufferSize / MV_SampleSize * MV_Channels) / 4); + MV_BufferEmpty[ MV_MixPage ] = TRUE; } // Play any waiting voices diff --git a/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mv_mix.c b/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mv_mix.c index 61485a1ca0..e44e432434 100644 --- a/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mv_mix.c +++ b/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mv_mix.c @@ -65,7 +65,7 @@ int MV_cubic(int position) } */ -static int MV_cubic16(const short *src, int position, int rate) +static inline int MV_cubic16(const short *src, int position, int rate) { int temp, hpos = position >> 16; @@ -88,7 +88,7 @@ static int MV_cubic16(const short *src, int position, int rate) return do_cubic ? MV_cubic(position) : gval(3); } -static int MV_cubic8to16(const unsigned char *src, int position, int rate) +static inline int MV_cubic8to16(const unsigned char *src, int position, int rate) { int temp, hpos = position >> 16; @@ -394,15 +394,17 @@ void MV_MixFPMono8( uint32_t position, for (i = 0; i < length; i++) { int s = MV_cubic8to16(src, position, rate) << FRACBITS; - long out; + int out; + + /* output is long in range [0, 2^16) */ + out = (s * MV_LeftScale) >> (FRACBITS * 2); - out = (s * MV_LeftScale) >> FRACBITS; *dest += out; position += rate; dest += MV_Channels; } - + MV_MixPosition = position; MV_MixDestination = (char *)dest; } @@ -423,8 +425,8 @@ void MV_MixFPStereo8( uint32_t position, int s = MV_cubic8to16(src, position, rate) << FRACBITS; long left, right; - left = (s * MV_LeftScale) >> FRACBITS; - right = (s * MV_RightScale) >> FRACBITS; + left = (s * MV_LeftScale) >> (FRACBITS * 2); + right = (s * MV_RightScale) >> (FRACBITS * 2); dest[0] += left; dest[1] += right; @@ -452,9 +454,9 @@ void MV_MixFPMono16( uint32_t position, for (i = 0; i < length; i++) { int s = MV_cubic16(src, position, rate) << FRACBITS; - long out; + int out; - out = (s * MV_LeftScale) >> FRACBITS; + out = (s * MV_LeftScale) >> (FRACBITS * 2); *dest += out; position += rate; @@ -480,10 +482,10 @@ void MV_MixFPStereo16( uint32_t position, for (i = 0; i < length; i++) { int s = MV_cubic16(src, position, rate) << FRACBITS; - long left, right; + int left, right; - left = (s * MV_LeftScale) >> FRACBITS; - right = (s * MV_RightScale) >> FRACBITS; + left = (s * MV_LeftScale) >> (FRACBITS * 2); + right = (s * MV_RightScale) >> (FRACBITS * 2); dest[0] += left; dest[1] += right; diff --git a/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mvreverb.c b/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mvreverb.c index 7d48d3271e..4c82f6eec0 100644 --- a/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mvreverb.c +++ b/apps/plugins/sdl/progs/duke3d/Game/src/audiolib/mvreverb.c @@ -18,24 +18,40 @@ static int FB_SRC_A, FB_SRC_B, IIR_DEST_A0, IIR_DEST_A1, ACC_SRC_A0, ACC_SRC_A1, ACC_SRC_C1, ACC_SRC_D0, ACC_SRC_D1, IIR_SRC_B1, IIR_SRC_B0, MIX_DEST_A0, MIX_DEST_A1, MIX_DEST_B0, MIX_DEST_B1; -static long IIR_ALPHA, ACC_COEF_A, ACC_COEF_B, ACC_COEF_C, ACC_COEF_D, IIR_COEF, FB_ALPHA, FB_X, - IN_COEF_L, IN_COEF_R; +//static long IIR_ALPHA, ACC_COEF_A, ACC_COEF_B, ACC_COEF_C, ACC_COEF_D, IIR_COEF, FB_ALPHA, FB_X, +// IN_COEF_L, IN_COEF_R; -static long iRVBLeft, iRVBRight; -static int cnv_offset(int src) +#define fp_scale ((double)(1<<FRACBITS)) +//static const double fp_scale = (double) (1 << FRACBITS); + +static const long IIR_ALPHA = 0.8701171875 * fp_scale, + ACC_COEF_A = 0.622314453125 * fp_scale, + ACC_COEF_B = -0.5244140625 * fp_scale, + ACC_COEF_C = 0.53955078125 * fp_scale, + ACC_COEF_D = -0.50830078125 * fp_scale, + IIR_COEF = -0.69921875 * fp_scale, + FB_ALPHA = 0.67578125 * fp_scale, + FB_X = 0.646484375 * fp_scale, + IN_COEF_L = -2. * fp_scale, + IN_COEF_R = -2. * fp_scale; + +static long iRVBLeft, iRVBRight; + +static inline int cnv_offset(int src) { - int64_t temp = ((int64_t)src * (int64_t)MV_MixRate) / 22050; - return (int)temp; + /* no need for 64-bit ints here */ + /* src can be no greater than 2^16-1, which allows sample rates up + * to 65KHz */ + int temp = (src * MV_MixRate) / 22050; + return temp; } // static char err[256]; // extern __stdcall OutputDebugStringA(char *); -static const double fp_scale = (double) (1 << FRACBITS); - -static void check_buffer() +static inline void check_buffer() { int new_delay = cnv_offset(MV_ReverbDelay); @@ -64,16 +80,6 @@ static void check_buffer() MIX_DEST_A1 = cnv_offset(0x238); MIX_DEST_B0 = cnv_offset(0x154); MIX_DEST_B1 = cnv_offset(0xAA); - IIR_ALPHA = 0.8701171875 * fp_scale; - ACC_COEF_A = 0.622314453125 * fp_scale; - ACC_COEF_B = -0.5244140625 * fp_scale; - ACC_COEF_C = 0.53955078125 * fp_scale; - ACC_COEF_D = -0.50830078125 * fp_scale; - IIR_COEF = -0.69921875 * fp_scale; - FB_ALPHA = 0.67578125 * fp_scale; - FB_X = 0.646484375 * fp_scale; - IN_COEF_L = -2. * fp_scale; - IN_COEF_R = -2. * fp_scale; if (reverbBuffer) reverbBuffer = (long*) realloc(reverbBuffer, new_delay * sizeof(long)); else reverbBuffer = (long*) malloc(new_delay * sizeof(long)); memset(reverbBuffer, 0, new_delay * sizeof(long)); @@ -83,7 +89,7 @@ static void check_buffer() } -long g_buffer(int iOff, long *ptr) // get_buffer content helper: takes care about wraps +static inline long g_buffer(int iOff, long *ptr) // get_buffer content helper: takes care about wraps { int correctDelay = delay; if(!correctDelay) @@ -104,7 +110,7 @@ long g_buffer(int iOff, long *ptr) // get_buffer conten return (long)*(ptr+iOff); } -void s_buffer(int iOff,long iVal, long *ptr) // set_buffer content helper: takes care about wraps and clipping +static inline void s_buffer(int iOff,long iVal, long *ptr) // set_buffer content helper: takes care about wraps and clipping { int correctDelay = delay; if(!correctDelay) @@ -125,7 +131,7 @@ void s_buffer(int iOff,long iVal, long *ptr) // set_buffer conten *(ptr+iOff)=iVal; } -void s_buffer1(int iOff,long iVal, long *ptr) // set_buffer (+1 sample) content helper: takes care about wraps and clipping +static inline void s_buffer1(int iOff,long iVal, long *ptr) // set_buffer (+1 sample) content helper: takes care about wraps and clipping { int correctDelay = delay; if(!correctDelay) @@ -146,7 +152,7 @@ void s_buffer1(int iOff,long iVal, long *ptr) // set_buffer (+1 s *(ptr+iOff)=iVal; } -long MixREVERBLeft(long INPUT_SAMPLE_L, long INPUT_SAMPLE_R, long *ptr) +static inline long MixREVERBLeft(long INPUT_SAMPLE_L, long INPUT_SAMPLE_R, long *ptr) { long ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1; @@ -186,8 +192,8 @@ long MixREVERBLeft(long INPUT_SAMPLE_L, long INPUT_SAMPLE_R, long *ptr) s_buffer(MIX_DEST_B0, fp_mul(FB_ALPHA , ACC0, FRACBITS) - fp_mul(FB_A0, (FB_ALPHA - one), FRACBITS) - fp_mul(FB_B0, FB_X, FRACBITS), ptr); s_buffer(MIX_DEST_B1, fp_mul(FB_ALPHA , ACC1, FRACBITS) - fp_mul(FB_A1, (FB_ALPHA - one), FRACBITS) - fp_mul(FB_B1, FB_X, FRACBITS), ptr); - iRVBLeft = fp_div((g_buffer(MIX_DEST_A0, ptr)+g_buffer(MIX_DEST_B0, ptr)), 3 << FRACBITS, FRACBITS); - iRVBRight = fp_div((g_buffer(MIX_DEST_A1, ptr)+g_buffer(MIX_DEST_B1, ptr)), 3 << FRACBITS, FRACBITS); + iRVBLeft = (g_buffer(MIX_DEST_A0, ptr)+g_buffer(MIX_DEST_B0, ptr)) / 3; + iRVBRight = (g_buffer(MIX_DEST_A1, ptr)+g_buffer(MIX_DEST_B1, ptr)) / 3; CurrAddr++; if(CurrAddr>delay-1) CurrAddr=0; @@ -195,7 +201,7 @@ long MixREVERBLeft(long INPUT_SAMPLE_L, long INPUT_SAMPLE_R, long *ptr) return (long)iRVBLeft; } -long MixREVERBRight(void) +static inline long MixREVERBRight(void) { return (long)iRVBRight; } @@ -227,12 +233,12 @@ void MV_FPReverb(int volume) { for (i = 0; i < count; i++) { - long temp = MV_FooBuffer[i]; + long temp = MV_FooBuffer[i] << FRACBITS; /* evaluation order matters */ long total = MixREVERBLeft(temp, temp, reverbBuffer); total += MixREVERBRight(); total /= 2; - MV_FooBuffer[i] += (scale * total) >> FRACBITS; + MV_FooBuffer[i] += (scale * total) >> (FRACBITS * 2); } } else @@ -240,12 +246,12 @@ void MV_FPReverb(int volume) count /= 2; for (i = 0; i < count; i++) { - long left = MV_FooBuffer[i*2]; - long right = MV_FooBuffer[i*2+1]; + long left = MV_FooBuffer[i*2] << FRACBITS; + long right = MV_FooBuffer[i*2+1] << FRACBITS; left += (scale * MixREVERBLeft(left, right, reverbBuffer)) >> FRACBITS; right += (scale * MixREVERBRight()) >> FRACBITS; - MV_FooBuffer[i*2] = left; - MV_FooBuffer[i*2+1] = right; + MV_FooBuffer[i*2] = left >> FRACBITS; + MV_FooBuffer[i*2+1] = right >> FRACBITS; } } @@ -275,7 +281,7 @@ void MV_16BitDownmix(char *dest, int count) for (i = 0; i < count; i++) { - int out = MV_FooBuffer[i] >> FRACBITS; + int out = MV_FooBuffer[i]; if (out < -32768) pdest[i] = -32768; else if (out > 32767) pdest[i] = 32767; else pdest[i] = out; @@ -288,7 +294,7 @@ void MV_8BitDownmix(char *dest, int count) for (i = 0; i < count; i++) { - int out = MV_FooBuffer[i] >> FRACBITS; + int out = MV_FooBuffer[i] >> 8; if (out < -128) dest[i] = 0; else if (out > 127) dest[i] = 255; else dest[i] = out + 0x80; diff --git a/apps/plugins/sdl/progs/duke3d/Game/src/config.c b/apps/plugins/sdl/progs/duke3d/Game/src/config.c index 038875a4e5..1649c40b07 100644 --- a/apps/plugins/sdl/progs/duke3d/Game/src/config.c +++ b/apps/plugins/sdl/progs/duke3d/Game/src/config.c @@ -728,6 +728,7 @@ void CONFIG_ReadSetup( void ) NumBits = 16; SCRIPT_GetNumber( scripthandle, "Sound Setup", "MixRate",&MixRate); MixRate = RB_SAMPR; + printf("MixRate = %d Hz", MixRate); SCRIPT_GetNumber( scripthandle, "Sound Setup", "MidiPort",&MidiPort); SCRIPT_GetNumber( scripthandle, "Sound Setup", "BlasterAddress",&dummy); BlasterConfig.Address = dummy; |