From e2e1069332289a714ebebc71db225510c6d8ebff Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 14 Mar 2009 15:28:41 +0000 Subject: Add check to allow sched_setaffinity code to work on older versions of libc. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 1470 --- src/i_main.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/i_main.c b/src/i_main.c index 7c5b16e7..3a9ec696 100644 --- a/src/i_main.c +++ b/src/i_main.c @@ -29,18 +29,6 @@ #include "SDL.h" -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#endif - -#ifdef HAVE_SCHED_SETAFFINITY -#include -#include -#endif - #include "doomdef.h" #include "i_system.h" #include "m_argv.h" @@ -48,6 +36,9 @@ #if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include + typedef BOOL WINAPI (*SetAffinityFunc)(HANDLE hProcess, DWORD_PTR mask); // This is a bit more complicated than it really needs to be. We really @@ -93,16 +84,24 @@ static void LockCPUAffinity(void) #elif defined(HAVE_SCHED_SETAFFINITY) +#include +#include + // Unix (Linux) version: static void LockCPUAffinity(void) { +#ifdef CPU_SET cpu_set_t set; CPU_ZERO(&set); CPU_SET(0, &set); sched_setaffinity(getpid(), sizeof(set), &set); +#else + unsigned long mask = 1; + sched_setaffinity(getpid(), sizeof(mask), &mask); +#endif } #else -- cgit v1.2.3 From 578fd9aafdee97bc95cb81811fdc63ca17dd2850 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sun, 15 Mar 2009 14:44:23 +0000 Subject: Fix clipped sounds when using libsamplerate (thanks David Flater) Subversion-branch: /trunk/chocolate-doom Subversion-revision: 1479 --- src/i_sdlsound.c | 378 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 214 insertions(+), 164 deletions(-) (limited to 'src') diff --git a/src/i_sdlsound.c b/src/i_sdlsound.c index b6fc9787..f3af667e 100644 --- a/src/i_sdlsound.c +++ b/src/i_sdlsound.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "SDL.h" #include "SDL_mixer.h" @@ -58,11 +59,12 @@ static int channels_playing[NUM_CHANNELS]; static int mixer_freq; static Uint16 mixer_format; static int mixer_channels; -static uint32_t (*ExpandSoundData)(byte *data, int samplerate, int length, - Mix_Chunk *destination) = NULL; int use_libsamplerate = 0; +extern int mb_used; + + // When a sound stops, check if it is still playing. If it is not, // we can mark the sound data as CACHE to be freed back for other // means. @@ -79,6 +81,12 @@ static void ReleaseSoundOnChannel(int channel) channels_playing[channel] = sfx_None; +#ifdef HAVE_LIBSAMPLERATE + // Don't allow precached sounds to be swapped out. + if (use_libsamplerate) + return; +#endif + for (i=0; i signed 16 bits -// mono --> stereo -// samplerate --> mixer_freq -// Returns number of clipped samples. -// DWF 2008-02-10 with cleanups by Simon Howard. - -static uint32_t ExpandSoundData_SRC(byte *data, - int samplerate, - int length, - Mix_Chunk *destination) -{ - SRC_DATA src_data; - uint32_t i, abuf_index=0, clipped=0; - int retn; - int16_t *expanded; - - src_data.input_frames = length; - src_data.data_in = malloc(length * sizeof(float)); - src_data.src_ratio = (double)mixer_freq / samplerate; - - // We include some extra space here in case of rounding-up. - src_data.output_frames = src_data.src_ratio * length + (mixer_freq / 4); - src_data.data_out = malloc(src_data.output_frames * sizeof(float)); - - assert(src_data.data_in != NULL && src_data.data_out != NULL); - - // Convert input data to floats - - for (i=0; ialen = src_data.output_frames_gen * 4; - destination->abuf = Z_Malloc(destination->alen, PU_STATIC, - &destination->abuf); - expanded = (int16_t *) destination->abuf; - - for (i=0; i INT16_MAX) { - cvtval_i = INT16_MAX; - ++clipped; - } - - // Left and right channels - - expanded[abuf_index++] = cvtval_i; - expanded[abuf_index++] = cvtval_i; - } - - free(src_data.data_in); - free(src_data.data_out); - return clipped; -} - #endif static boolean ConvertibleRatio(int freq1, int freq2) @@ -248,12 +162,11 @@ static boolean ConvertibleRatio(int freq1, int freq2) } // Generic sound expansion function for any sample rate. -// Returns number of clipped samples (always 0). -static uint32_t ExpandSoundData_SDL(byte *data, - int samplerate, - int length, - Mix_Chunk *destination) +static void ExpandSoundData_SDL(byte *data, + int samplerate, + uint32_t length, + Mix_Chunk *destination) { SDL_AudioCVT convertor; uint32_t expanded_length; @@ -265,7 +178,6 @@ static uint32_t ExpandSoundData_SDL(byte *data, // Double up twice: 8 -> 16 bit and mono -> stereo expanded_length *= 4; - destination->alen = expanded_length; destination->abuf = Z_Malloc(expanded_length, PU_STATIC, &destination->abuf); @@ -344,69 +256,92 @@ static uint32_t ExpandSoundData_SDL(byte *data, } #endif /* #ifdef LOW_PASS_FILTER */ } - - return 0; } -// Load and convert a sound effect -// Returns true if successful -static boolean CacheSFX(int sound) +// Load and validate a sound effect lump. +// Preconditions: +// S_sfx[sound].lumpnum has been set +// Postconditions if sound is valid: +// returns true +// starred parameters are set, with data_ref pointing to start of sound +// caller is responsible for releasing the identified lump +// Postconditions if sound is invalid: +// returns false +// starred parameters are garbage +// lump already released + +static boolean LoadSoundLump(int sound, + int *lumpnum, + int *samplerate, + uint32_t *length, + byte **data_ref) { - int lumpnum; - unsigned int lumplen; - int samplerate; - int clipped; - unsigned int length; - byte *data; - - // need to load the sound + // Load the sound - lumpnum = S_sfx[sound].lumpnum; - data = W_CacheLumpNum(lumpnum, PU_STATIC); - lumplen = W_LumpLength(lumpnum); + *lumpnum = S_sfx[sound].lumpnum; + *data_ref = W_CacheLumpNum(*lumpnum, PU_STATIC); + int lumplen = W_LumpLength(*lumpnum); + byte *data = *data_ref; - // Check the header, and ensure this is a valid sound + // Ensure this is a valid sound - if (lumplen < 8 - || data[0] != 0x03 || data[1] != 0x00) + if (lumplen < 8 || data[0] != 0x03 || data[1] != 0x00) { - // Invalid sound - - return false; + // Invalid sound + W_ReleaseLumpNum(*lumpnum); + return false; } // 16 bit sample rate field, 32 bit length field - samplerate = (data[3] << 8) | data[2]; - length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; + *samplerate = (data[3] << 8) | data[2]; + *length = (data[7] << 24) | (data[6] << 16) | (data[5] << 8) | data[4]; - // If the header specifies that the length of the sound is greater than - // the length of the lump itself, this is an invalid sound lump + // If the header specifies that the length of the sound is + // greater than the length of the lump itself, this is an invalid + // sound lump. - if (length > lumplen - 8) + if (*length > lumplen - 8) { - return false; + W_ReleaseLumpNum(*lumpnum); + return false; } + // Prune header + *data_ref += 8; + + return true; +} + + +// Load and convert a sound effect +// Returns true if successful + +static boolean CacheSFX_SDL(int sound) +{ + int lumpnum; + int samplerate; + uint32_t length; + byte *data; + +#ifdef HAVE_LIBSAMPLERATE + assert(!use_libsamplerate); // Should be using I_PrecacheSounds_SRC instead +#endif + + if (!LoadSoundLump(sound, &lumpnum, &samplerate, &length, &data)) + return false; + // Sample rate conversion - // DWF 2008-02-10: sound_chunks[sound].alen and abuf are determined - // by ExpandSoundData. + // sound_chunks[sound].alen and abuf are determined by ExpandSoundData. sound_chunks[sound].allocated = 1; sound_chunks[sound].volume = MIX_MAX_VOLUME; - 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); - } + ExpandSoundData_SDL(data, + samplerate, + length, + &sound_chunks[sound]); // don't need the original lump any more @@ -415,50 +350,169 @@ static boolean CacheSFX(int sound) return true; } + #ifdef HAVE_LIBSAMPLERATE -// Preload all the sound effects - stops nasty ingame freezes +// Preload and resample all sound effects with libsamplerate. -static void I_PrecacheSounds(void) +static void I_PrecacheSounds_SRC(void) { char namebuf[9]; - int i; + uint32_t sound_i, sample_i; + boolean good_sound[NUMSFX]; + float *resampled_sound[NUMSFX]; + uint32_t resampled_sound_length[NUMSFX]; + float norm_factor; + float max_amp = 0; - printf("I_PrecacheSounds: Precaching all sound effects.."); + assert(use_libsamplerate); - for (i=sfx_pistol; i 0); + resampled_sound[sound_i] = src_data.data_out; + resampled_sound_length[sound_i] = src_data.output_frames_gen; + free(src_data.data_in); + good_sound[sound_i] = true; + + // Track maximum amplitude for later normalization + + rsound = resampled_sound[sound_i]; + rlen = resampled_sound_length[sound_i]; + for (sample_i=0; sample_i max_amp) + max_amp = fabs_amp; + } + } + } + + // Pass 2: normalize and convert to signed 16-bit stereo. - S_sfx[i].lumpnum = W_CheckNumForName(namebuf); + if (max_amp <= 0) + max_amp = 1; + norm_factor = INT16_MAX / max_amp; - if (S_sfx[i].lumpnum != -1) + for (sound_i=sfx_pistol; sound_i