diff options
author | Simon Howard | 2008-03-13 18:33:59 +0000 |
---|---|---|
committer | Simon Howard | 2008-03-13 18:33:59 +0000 |
commit | de318a6f06dd24136a3d538a27ecef43a1bce1e5 (patch) | |
tree | b2f54f49265ab2429498e68ee45047357f35497e | |
parent | 0b01221f1bc6dd40e918d2d19a7c62896b057744 (diff) | |
download | chocolate-doom-de318a6f06dd24136a3d538a27ecef43a1bce1e5.tar.gz chocolate-doom-de318a6f06dd24136a3d538a27ecef43a1bce1e5.tar.bz2 chocolate-doom-de318a6f06dd24136a3d538a27ecef43a1bce1e5.zip |
Apply SRC patch from David Flater.
Subversion-branch: /trunk/chocolate-doom
Subversion-revision: 1105
-rw-r--r-- | src/i_sdlsound.c | 93 |
1 files changed, 68 insertions, 25 deletions
diff --git a/src/i_sdlsound.c b/src/i_sdlsound.c index 6764d19e..a250cc36 100644 --- a/src/i_sdlsound.c +++ b/src/i_sdlsound.c @@ -57,8 +57,8 @@ static int channels_playing[NUM_CHANNELS]; static int mixer_freq; static Uint16 mixer_format; static int mixer_channels; -static void (*ExpandSoundData)(byte *data, int samplerate, int length, - Mix_Chunk *destination) = NULL; +static uint32_t (*ExpandSoundData)(byte *data, int samplerate, int length, + Mix_Chunk *destination) = NULL; int use_libsamplerate = 0; @@ -97,15 +97,16 @@ static void ReleaseSoundOnChannel(int channel) // unsigned 8 bits --> signed 16 bits // mono --> stereo // samplerate --> mixer_freq +// Returns number of clipped samples. // DWF 2008-02-10 with cleanups by Simon Howard. -static void ExpandSoundData_SRC(byte *data, - int samplerate, - int length, - Mix_Chunk *destination) +static uint32_t ExpandSoundData_SRC(byte *data, + int samplerate, + int length, + Mix_Chunk *destination) { SRC_DATA src_data; - uint32_t i, abuf_index=0; + uint32_t i, abuf_index=0, clipped=0; int retn; int16_t *expanded; @@ -123,12 +124,15 @@ static void ExpandSoundData_SRC(byte *data, for (i=0; i<length; ++i) { + // Unclear whether 128 should be interpreted as "zero" or whether a + // symmetrical range should be assumed. The following assumes a + // symmetrical range. src_data.data_in[i] = data[i] / 127.5 - 1; } // Do the sound conversion - retn = src_simple(&src_data, SRC_SINC_FASTEST, 1); + retn = src_simple(&src_data, SRC_SINC_BEST_QUALITY, 1); assert(retn == 0); // Convert the result back into 16-bit integers. @@ -140,21 +144,48 @@ static void ExpandSoundData_SRC(byte *data, for (i=0; i<src_data.output_frames_gen; ++i) { - // libsamplerate does not limit itself to the -1.0 .. 1.0 range - // on output, so some slack is required to avoid overflows or - // clipping. The amount of slack is a fudge factor. - - float cvtval = src_data.data_out[i] * 20000; - cvtval += (cvtval < 0 ? -0.5 : 0.5); + // libsamplerate does not limit itself to the -1.0 .. 1.0 range on + // output, so a multiplier less than INT16_MAX (32767) is required + // to avoid overflows or clipping. However, the smaller the + // multiplier, the quieter the sound effects get, and the more you + // have to turn down the music to keep it in balance. + + // 22265 is the largest multiplier that can be used to resample all + // of the Vanilla DOOM sound effects to 48 kHz without clipping + // using SRC_SINC_BEST_QUALITY. It is close enough (only slightly + // too conservative) for SRC_SINC_MEDIUM_QUALITY and + // SRC_SINC_FASTEST. PWADs with interestingly different sound + // effects or target rates other than 48 kHz might still result in + // clipping--I don't know if there's a limit to it. + + // As the number of clipped samples increases, the signal is + // gradually overtaken by noise, with the loudest parts going first. + // However, a moderate amount of clipping is often tolerated in the + // quest for the loudest possible sound overall. The results of + // using INT16_MAX as the multiplier are not all that bad, but + // artifacts are noticeable during the loudest parts. + + float cvtval_f = src_data.data_out[i] * 22265; + int32_t cvtval_i = cvtval_f + (cvtval_f < 0 ? -0.5 : 0.5); + + // Asymmetrical sound worries me, so we won't use -32768. + if (cvtval_i < -INT16_MAX) { + cvtval_i = -INT16_MAX; + ++clipped; + } else if (cvtval_i > INT16_MAX) { + cvtval_i = INT16_MAX; + ++clipped; + } // Left and right channels - expanded[abuf_index++] = cvtval; - expanded[abuf_index++] = cvtval; + expanded[abuf_index++] = cvtval_i; + expanded[abuf_index++] = cvtval_i; } free(src_data.data_in); free(src_data.data_out); + return clipped; } #endif @@ -188,12 +219,13 @@ static boolean ConvertibleRatio(int freq1, int freq2) } } -// Generic sound expansion function for any sample rate +// Generic sound expansion function for any sample rate. +// Returns number of clipped samples (always 0). -static void ExpandSoundData_SDL(byte *data, - int samplerate, - int length, - Mix_Chunk *destination) +static uint32_t ExpandSoundData_SDL(byte *data, + int samplerate, + int length, + Mix_Chunk *destination) { SDL_AudioCVT convertor; uint32_t expanded_length; @@ -284,6 +316,8 @@ static void ExpandSoundData_SDL(byte *data, } #endif /* #ifdef LOW_PASS_FILTER */ } + + return 0; } // Load and convert a sound effect @@ -294,6 +328,7 @@ static boolean CacheSFX(int sound) int lumpnum; unsigned int lumplen; int samplerate; + int clipped; unsigned int length; byte *data; @@ -332,10 +367,18 @@ static boolean CacheSFX(int sound) sound_chunks[sound].allocated = 1; sound_chunks[sound].volume = MIX_MAX_VOLUME; - ExpandSoundData(data + 8, - samplerate, - length, - &sound_chunks[sound]); + + clipped = ExpandSoundData(data + 8, + samplerate, + length, + &sound_chunks[sound]); + + if (clipped) + { + fprintf(stderr, "Sound %d: clipped %u samples (%0.2f %%)\n", + sound, clipped, + 400.0 * clipped / sound_chunks[sound].alen); + } // don't need the original lump any more |