From 8e058c2d27961bdd1db883679b5743f418e8b854 Mon Sep 17 00:00:00 2001 From: rubidium Date: Sun, 9 Aug 2009 23:04:08 +0000 Subject: (svn r17140) -Change: allow higher sample rate and higher quality samples. Based on work by orudge. --- src/mixer.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++--- src/mixer.h | 2 +- src/sound.cpp | 34 +++++++++++++++++++----------- src/sound/allegro_s.cpp | 2 +- src/sound/cocoa_s.cpp | 2 +- src/sound/sdl_s.cpp | 2 +- src/sound/win32_s.cpp | 4 ++-- 7 files changed, 80 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/mixer.cpp b/src/mixer.cpp index cf8b30c9a..5a8370df8 100644 --- a/src/mixer.cpp +++ b/src/mixer.cpp @@ -21,6 +21,8 @@ struct MixerChannel { /* Mixing volume */ int volume_left; int volume_right; + + bool is16bit; }; static MixerChannel _channels[8]; @@ -34,6 +36,46 @@ static uint32 _play_rate = 11025; */ static const int MAX_VOLUME = 128 * 128; +static void mix_int16(MixerChannel *sc, int16 *buffer, uint samples) +{ + int16 *b; + uint32 frac_pos; + uint32 frac_speed; + int volume_left; + int volume_right; + + if (samples > sc->samples_left) samples = sc->samples_left; + sc->samples_left -= samples; + assert(samples > 0); + + b = (int16*)sc->memory + sc->pos; + frac_pos = sc->frac_pos; + frac_speed = sc->frac_speed; + volume_left = sc->volume_left; + volume_right = sc->volume_right; + + if (frac_speed == 0x10000) { + /* Special case when frac_speed is 0x10000 */ + do { + buffer[0] = Clamp(buffer[0] + (*b * volume_left >> 16), -MAX_VOLUME, MAX_VOLUME); + buffer[1] = Clamp(buffer[1] + (*b * volume_right >> 16), -MAX_VOLUME, MAX_VOLUME); + b++; + buffer += 2; + } while (--samples > 0); + } else { + do { + buffer[0] = Clamp(buffer[0] + (*b * volume_left >> 16), -MAX_VOLUME, MAX_VOLUME); + buffer[1] = Clamp(buffer[1] + (*b * volume_right >> 16), -MAX_VOLUME, MAX_VOLUME); + buffer += 2; + frac_pos += frac_speed; + b += frac_pos >> 16; + frac_pos &= 0xffff; + } while (--samples > 0); + } + + sc->frac_pos = frac_pos; + sc->pos = b - (int16*)sc->memory; +} static void mix_int8_to_int16(MixerChannel *sc, int16 *buffer, uint samples) { @@ -93,7 +135,11 @@ void MxMixSamples(void *buffer, uint samples) /* Mix each channel */ for (mc = _channels; mc != endof(_channels); mc++) { if (mc->active) { - mix_int8_to_int16(mc, (int16*)buffer, samples); + if (mc->is16bit) { + mix_int16(mc, (int16*)buffer, samples); + } else { + mix_int8_to_int16(mc, (int16*)buffer, samples); + } if (mc->samples_left == 0) MxCloseChannel(mc); } } @@ -110,7 +156,7 @@ MixerChannel *MxAllocateChannel() return NULL; } -void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, size_t size, uint rate) +void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, size_t size, uint rate, bool is16bit) { mc->memory = mem; mc->frac_pos = 0; @@ -124,7 +170,10 @@ void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, size_t size, uint rate) rate = (rate >> 1) + 1; } - mc->samples_left = (uint)size * _play_rate / rate; + int div = is16bit ? 2 : 1; + + mc->samples_left = (uint)size * _play_rate / rate / div; + mc->is16bit = is16bit; } void MxSetChannelVolume(MixerChannel *mc, uint left, uint right) diff --git a/src/mixer.h b/src/mixer.h index cdd6f65b4..fcb3faade 100644 --- a/src/mixer.h +++ b/src/mixer.h @@ -11,7 +11,7 @@ bool MxInitialize(uint rate); void MxMixSamples(void *buffer, uint samples); MixerChannel *MxAllocateChannel(); -void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, size_t size, uint rate); +void MxSetChannelRawSrc(MixerChannel *mc, int8 *mem, size_t size, uint rate, bool is16bit); void MxSetChannelVolume(MixerChannel *mc, uint left, uint right); void MxActivateChannel(MixerChannel*); diff --git a/src/sound.cpp b/src/sound.cpp index 99799002d..c1cb1c02e 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -29,7 +29,12 @@ static void OpenBankFile(const char *filename) FioOpenFile(SOUND_SLOT, filename); size_t pos = FioGetPos(); - uint count = FioReadDword() / 8; + uint count = FioReadDword(); + + /* The new format has the highest bit always set */ + bool new_format = HasBit(count, 31); + ClrBit(count, 31); + count /= 8; /* Simple check for the correct number of original sounds. */ if (count != ORIGINAL_SAMPLE_COUNT) { @@ -44,7 +49,7 @@ static void OpenBankFile(const char *filename) for (uint i = 0; i != ORIGINAL_SAMPLE_COUNT; i++) { _original_sounds[i].file_slot = SOUND_SLOT; - _original_sounds[i].file_offset = FioReadDword() + pos; + _original_sounds[i].file_offset = GB(FioReadDword(), 0, 31) + pos; _original_sounds[i].file_size = FioReadDword(); } @@ -56,7 +61,7 @@ static void OpenBankFile(const char *filename) /* Check for special case, see else case */ FioReadBlock(name, FioReadByte()); // Read the name of the sound - if (strcmp(name, "Corrupt sound") != 0) { + if (new_format || strcmp(name, "Corrupt sound") != 0) { FioSeekTo(12, SEEK_CUR); // Skip past RIFF header /* Read riff tags */ @@ -66,11 +71,11 @@ static void OpenBankFile(const char *filename) if (tag == ' tmf') { FioReadWord(); // wFormatTag - sound->channels = FioReadWord(); // wChannels - FioReadDword(); // samples per second - sound->rate = 11025; // seems like all samples should be played at this rate. - FioReadDword(); // avg bytes per second - FioReadWord(); // alignment + sound->channels = FioReadWord(); // wChannels + sound->rate = FioReadDword(); // samples per second + if (!new_format) sound->rate = 11025; // seems like all old samples should be played at this rate. + FioReadDword(); // avg bytes per second + FioReadWord(); // alignment sound->bits_per_sample = FioReadByte(); // bits per sample FioSeekTo(size - (2 + 2 + 4 + 4 + 2 + 1), SEEK_CUR); } else if (tag == 'atad') { @@ -109,13 +114,18 @@ static bool SetBankSource(MixerChannel *mc, const SoundEntry *sound) FioSeekToFile(sound->file_slot, sound->file_offset); FioReadBlock(mem, sound->file_size); - for (uint i = 0; i != sound->file_size; i++) { - mem[i] += -128; // Convert unsigned sound data to signed + /* 16-bit PCM WAV files should be signed by default */ + if (sound->bits_per_sample == 8) { + for (uint i = 0; i != sound->file_size; i++) { + mem[i] += -128; // Convert unsigned sound data to signed + } } - assert(sound->bits_per_sample == 8 && sound->channels == 1 && sound->file_size != 0 && sound->rate != 0); + assert(sound->bits_per_sample == 8 || sound->bits_per_sample == 16); + assert(sound->channels == 1); + assert(sound->file_size != 0 && sound->rate != 0); - MxSetChannelRawSrc(mc, mem, sound->file_size, sound->rate); + MxSetChannelRawSrc(mc, mem, sound->file_size, sound->rate, sound->bits_per_sample == 16); return true; } diff --git a/src/sound/allegro_s.cpp b/src/sound/allegro_s.cpp index a94f6d238..26d184ab5 100644 --- a/src/sound/allegro_s.cpp +++ b/src/sound/allegro_s.cpp @@ -57,7 +57,7 @@ const char *SoundDriver_Allegro::Start(const char * const *parm) return "No sound card found"; } - _stream = play_audio_stream(BUFFER_SIZE, 16, true, 11025, 255, 128); + _stream = play_audio_stream(BUFFER_SIZE, 16, true, 44100, 255, 128); MxInitialize(11025); return NULL; } diff --git a/src/sound/cocoa_s.cpp b/src/sound/cocoa_s.cpp index f50b6bd94..4e4fdd20a 100644 --- a/src/sound/cocoa_s.cpp +++ b/src/sound/cocoa_s.cpp @@ -47,7 +47,7 @@ const char *SoundDriver_Cocoa::Start(const char * const *parm) requestedDesc.mFormatID = kAudioFormatLinearPCM; requestedDesc.mFormatFlags = kLinearPCMFormatFlagIsPacked; requestedDesc.mChannelsPerFrame = 2; - requestedDesc.mSampleRate = GetDriverParamInt(parm, "hz", 11025); + requestedDesc.mSampleRate = GetDriverParamInt(parm, "hz", 44100); requestedDesc.mBitsPerChannel = 16; requestedDesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger; diff --git a/src/sound/sdl_s.cpp b/src/sound/sdl_s.cpp index 7c89331f7..df7673da0 100644 --- a/src/sound/sdl_s.cpp +++ b/src/sound/sdl_s.cpp @@ -25,7 +25,7 @@ const char *SoundDriver_SDL::Start(const char * const *parm) const char *s = SdlOpen(SDL_INIT_AUDIO); if (s != NULL) return s; - spec.freq = GetDriverParamInt(parm, "hz", 11025); + spec.freq = GetDriverParamInt(parm, "hz", 44100); spec.format = AUDIO_S16SYS; spec.channels = 2; spec.samples = 512; diff --git a/src/sound/win32_s.cpp b/src/sound/win32_s.cpp index 776158adf..a7327863e 100644 --- a/src/sound/win32_s.cpp +++ b/src/sound/win32_s.cpp @@ -56,11 +56,11 @@ const char *SoundDriver_Win32::Start(const char * const *parm) wfex.wFormatTag = WAVE_FORMAT_PCM; wfex.nChannels = 2; wfex.wBitsPerSample = 16; - wfex.nSamplesPerSec = GetDriverParamInt(parm, "hz", 11025); + wfex.nSamplesPerSec = GetDriverParamInt(parm, "hz", 44100); wfex.nBlockAlign = (wfex.nChannels * wfex.wBitsPerSample) / 8; wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; - _bufsize = GetDriverParamInt(parm, "bufsize", (GB(GetVersion(), 0, 8) > 5) ? 2048 : 1024); + _bufsize = GetDriverParamInt(parm, "bufsize", (GB(GetVersion(), 0, 8) > 5) ? 8192 : 4096); if (waveOutOpen(&_waveout, WAVE_MAPPER, &wfex, (DWORD_PTR)&waveOutProc, 0, CALLBACK_FUNCTION) != MMSYSERR_NOERROR) return "waveOutOpen failed"; -- cgit v1.2.3-54-g00ecf