From 9df2ee4b772b87fb47e05e8a2b117dbb54c96ec7 Mon Sep 17 00:00:00 2001 From: zsilencer Date: Tue, 7 Oct 2014 23:00:11 -0600 Subject: [PATCH] use mixer for title music, crowd noise, rain/thunder, and sound effects --- src/audio/audio.c | 45 ++++++++++++++++++++++--------- src/audio/audio.h | 3 ++- src/audio/mixer.cpp | 63 ++++++++++++++++++++++++++++++++++++++----- src/audio/mixer.h | 15 ++++++++--- src/peep/peep.c | 13 +++++++++ src/ride/vehicle.c | 4 +-- src/windows/options.c | 2 ++ src/world/climate.c | 40 +++++++++++++++++++++++++++ 8 files changed, 160 insertions(+), 25 deletions(-) diff --git a/src/audio/audio.c b/src/audio/audio.c index 2f819264d7..838569438f 100644 --- a/src/audio/audio.c +++ b/src/audio/audio.c @@ -27,12 +27,14 @@ #include "../world/map.h" #include "../world/sprite.h" #include "audio.h" +#include "mixer.h" int gAudioDeviceCount; audio_device *gAudioDevices = NULL; rct_vehicle_sound gVehicleSoundList[AUDIO_MAX_VEHICLE_SOUNDS]; rct_vehicle_sound_params gVehicleSoundParamsList[AUDIO_MAX_VEHICLE_SOUNDS]; rct_vehicle_sound_params *gVehicleSoundParamsListEnd; +void* gMusicChannels[4]; void audio_init(int i) { @@ -166,7 +168,7 @@ void audio_close() { if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_SOUND_DEVICE, uint32) != -1) { stop_other_sounds(); - stop_peep_sounds(); + stop_crowd_sound(); stop_title_music(); if (RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) { stop_ride_music(); @@ -1279,13 +1281,16 @@ int sound_play_panned(int sound_id, int ebx, sint16 x, sint16 y, sint16 z) if (!RCT2_GLOBAL(0x009AAC6D, uint8)) { pan = 0; } - +#ifdef USE_MIXER + Mixer_Play_Effect(sound_id, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), 1, 1); +#else RCT2_GLOBAL(0x014241BC, uint32) = 1; sound_prepare(sound_id, &other_sound->sound, 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32)); RCT2_GLOBAL(0x014241BC, uint32) = 0; RCT2_GLOBAL(0x014241BC, uint32) = 1; result = sound_play(&other_sound->sound, 0, volume, pan, 0); RCT2_GLOBAL(0x014241BC, uint32) = 0; +#endif } return result; } @@ -1330,6 +1335,9 @@ void start_title_music() { if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) && RCT2_GLOBAL(0x009AF59D, uint8) & 1 && RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 1) { if (!RCT2_GLOBAL(0x009AF600, uint8)) { +#ifdef USE_MIXER + gMusicChannels[3] = Mixer_Play_Music(gMusicChannels[3], PATH_ID_CSS17); +#else RCT2_GLOBAL(0x014241BC, uint32) = 1; int result = sound_channel_load_file2(3, (char*)get_file_path(PATH_ID_CSS17), 0); RCT2_GLOBAL(0x014241BC, uint32) = 0; @@ -1338,6 +1346,7 @@ void start_title_music() sound_channel_play(3, 1, 0, 0, 0); RCT2_GLOBAL(0x014241BC, uint32) = 0; } +#endif RCT2_GLOBAL(0x009AF600, uint8) = 1; } } else { @@ -1605,7 +1614,7 @@ void pause_sounds() stop_other_sounds(); stop_vehicle_sounds(); stop_ride_music(); - stop_peep_sounds(); + stop_crowd_sound(); } g_sounds_disabled = 1; } @@ -1695,13 +1704,20 @@ void stop_ride_music() * * rct2: 0x006BD07F */ -void stop_peep_sounds() +void stop_crowd_sound() { if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) { if (RCT2_GLOBAL(0x009AF5FC, uint32) != 1) { +#ifdef USE_MIXER + if (gMusicChannels[2]) { + Mixer_Stop_Channel(gMusicChannels[2]); + gMusicChannels[2] = 0; + } +#else RCT2_GLOBAL(0x014241BC, uint32) = 1; sound_channel_stop(2); RCT2_GLOBAL(0x014241BC, uint32) = 0; +#endif RCT2_GLOBAL(0x009AF5FC, uint32) = 1; } } @@ -1715,9 +1731,16 @@ void stop_title_music() { if (RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0)) { if (RCT2_GLOBAL(0x009AF600, uint8) != 0) { +#ifdef USE_MIXER + if (gMusicChannels[3]) { + Mixer_Stop_Channel(gMusicChannels[3]); + gMusicChannels[3] = 0; + } +#else RCT2_GLOBAL(0x014241BC, uint32) = 1; sound_channel_stop(3); RCT2_GLOBAL(0x014241BC, uint32) = 0; +#endif } } RCT2_GLOBAL(0x009AF600, uint8) = 0; @@ -1794,7 +1817,7 @@ void sub_6BC348() */ void sub_6BC6D8() { - int edi; + rct_music_info* edi; int ebx; if (!(RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & 2)) { if ((RCT2_GLOBAL(0x009AF284, uint32) & (1 << 0))) { @@ -1810,7 +1833,7 @@ void sub_6BC6D8() v8++; if (v9 >= music_info->volume) { v9 = music_info->volume; - edi = (int)music_info; + edi = music_info; } } } @@ -1819,7 +1842,7 @@ void sub_6BC6D8() if (v8 <= 1) { break; } - edi = -1; + edi->id = -1; } while (1) { @@ -1831,7 +1854,7 @@ void sub_6BC6D8() v8++; if (v9 >= music_info->volume) { v9 = music_info->volume; - edi = (int)music_info; + edi = music_info; } } music_info++; @@ -1839,9 +1862,8 @@ void sub_6BC6D8() if (v8 <= 2) { break; } - edi = -1; + edi->id = -1; } - rct_music_info2* music_info2 = &RCT2_GLOBAL(0x009AF46C, rct_music_info2); int channel = 0; do { @@ -1922,9 +1944,7 @@ void sub_6BC6D8() RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_MUSIC, uint8) = 0; } } - return; - } } @@ -1949,7 +1969,6 @@ void sub_6BC6D8() } } - } } } diff --git a/src/audio/audio.h b/src/audio/audio.h index 292b22c5dd..350b922a7e 100644 --- a/src/audio/audio.h +++ b/src/audio/audio.h @@ -149,6 +149,7 @@ typedef struct { extern rct_vehicle_sound gVehicleSoundList[AUDIO_MAX_VEHICLE_SOUNDS]; extern rct_vehicle_sound_params gVehicleSoundParamsList[AUDIO_MAX_VEHICLE_SOUNDS]; extern rct_vehicle_sound_params *gVehicleSoundParamsListEnd; +extern void* gMusicChannels[4]; int get_dsound_devices(); int dsound_create_primary_buffer(int a, int device, int channels, int samples, int bits); @@ -193,7 +194,7 @@ void stop_completed_sounds(); void stop_other_sounds(); void stop_vehicle_sounds(); void stop_ride_music(); -void stop_peep_sounds(); +void stop_crowd_sound(); void stop_title_music(); void start_title_music(); void unpause_sounds(); diff --git a/src/audio/mixer.cpp b/src/audio/mixer.cpp index b98a4493db..0f068fa202 100644 --- a/src/audio/mixer.cpp +++ b/src/audio/mixer.cpp @@ -109,6 +109,11 @@ void Sample::Unload() length = 0; } +bool Sample::Loaded() +{ + return data != 0; +} + bool Sample::Convert(AudioFormat format) { if(Sample::format.format != format.format || Sample::format.channels != format.channels || Sample::format.freq != format.freq){ @@ -193,9 +198,11 @@ const AudioFormat* Stream::Format() Channel::Channel() { - rate = 1; resampler = 0; + SetRate(1); SetVolume(SDL_MIX_MAXVOLUME); + SetPan(0.5f); + done = true; } Channel::~Channel() @@ -211,6 +218,7 @@ void Channel::Play(Stream& stream, int loop = MIXER_LOOP_NONE) Channel::stream = &stream; Channel::loop = loop; offset = 0; + done = false; } void Channel::SetRate(double rate) @@ -245,6 +253,11 @@ void Channel::SetPan(float pan) volume_r = (float)sin(Channel::pan * M_PI / 2.0); } +bool Channel::IsPlaying() +{ + return !done; +} + void Mixer::Init(const char* device) { Close(); @@ -291,12 +304,13 @@ void Mixer::Unlock() SDL_UnlockAudioDevice(deviceid); } -Channel* Mixer::Play(Stream& stream, int loop) +Channel* Mixer::Play(Stream& stream, int loop, bool deleteondone) { Lock(); Channel* newchannel = new (std::nothrow) Channel(); if (newchannel) { newchannel->Play(stream, loop); + newchannel->deleteondone = deleteondone; channels.push_back(newchannel); } Unlock(); @@ -311,18 +325,39 @@ void Mixer::Stop(Channel& channel) Unlock(); } +bool Mixer::LoadMusic(int pathid) +{ + if (pathid >= PATH_ID_END) { + return false; + } + if (!musicsamples[pathid].Loaded()) { + const char* filename = get_file_path(pathid); + musicstreams[pathid].SetSource_Sample(musicsamples[pathid]); + return musicsamples[pathid].Load(filename); + } else { + return true; + } +} + void SDLCALL Mixer::Callback(void* arg, uint8* stream, int length) { Mixer* mixer = (Mixer*)arg; memset(stream, 0, length); - for (std::list::iterator i = mixer->channels.begin(); i != mixer->channels.end(); i++){ + std::list::iterator i = mixer->channels.begin(); + while (i != mixer->channels.end()) { mixer->MixChannel(*(*i), stream, length); + if ((*i)->done && (*i)->deleteondone) { + delete (*i); + i = mixer->channels.erase(i); + } else { + i++; + } } } void Mixer::MixChannel(Channel& channel, uint8* data, int length) { - if (channel.stream) { + if (channel.stream && !channel.done) { if (!channel.resampler) { channel.resampler = speex_resampler_init(format.channels, format.freq, format.freq, 0, 0); } @@ -422,6 +457,9 @@ void Mixer::MixChannel(Channel& channel, uint8* data, int length) channel.offset = 0; } } while(loaded < length && channel.loop != 0); + if (channel.loop == 0 && channel.offset >= channel.stream->Length()) { + channel.done = true; + } } } @@ -478,13 +516,13 @@ void Mixer_Init(const char* device) gMixer.Init(device); } -void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate) +void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone) { if (id >= SOUND_MAXID) { return 0; } gMixer.Lock(); - Channel* channel = gMixer.Play(gMixer.css1streams[id], loop); + Channel* channel = gMixer.Play(gMixer.css1streams[id], loop, deleteondone != 0); if (channel) { channel->SetVolume(volume); channel->SetPan(pan); @@ -518,4 +556,17 @@ void Mixer_Channel_Rate(void* channel, double rate) gMixer.Lock(); ((Channel*)channel)->SetRate(rate); gMixer.Unlock(); +} + +int Mixer_Channel_IsPlaying(void* channel) +{ + return ((Channel*)channel)->IsPlaying(); +} + +void* Mixer_Play_Music(void* channel, int pathid) +{ + if (!(Channel*)channel && gMixer.LoadMusic(pathid)) { + return gMixer.Play(gMixer.musicstreams[pathid], MIXER_LOOP_INFINITE, false); + } + return channel; } \ No newline at end of file diff --git a/src/audio/mixer.h b/src/audio/mixer.h index b11a9ab4e0..16ef5e896b 100644 --- a/src/audio/mixer.h +++ b/src/audio/mixer.h @@ -51,6 +51,7 @@ public: bool Load(const char* filename); bool LoadCSS1(const char* filename, unsigned int offset); void Unload(); + bool Loaded(); bool Convert(AudioFormat format); const uint8* Data(); unsigned long Length(); @@ -92,6 +93,7 @@ public: void SetRate(double rate); void SetVolume(int volume); void SetPan(float pan); + bool IsPlaying(); friend class Mixer; @@ -102,6 +104,8 @@ private: int volume; float volume_l, volume_r; float pan; + bool done; + bool deleteondone; SpeexResamplerState* resampler; Stream* stream; }; @@ -113,10 +117,12 @@ public: void Close(); void Lock(); void Unlock(); - Channel* Play(Stream& stream, int loop); + Channel* Play(Stream& stream, int loop, bool deleteondone); void Stop(Channel& channel); + bool LoadMusic(int pathid); Stream css1streams[SOUND_MAXID]; + Stream musicstreams[PATH_ID_END]; private: static void SDLCALL Callback(void* arg, uint8* data, int length); @@ -129,6 +135,7 @@ private: AudioFormat format; uint8* effectbuffer; Sample css1samples[SOUND_MAXID]; + Sample musicsamples[PATH_ID_END]; std::list channels; }; @@ -137,13 +144,15 @@ extern "C" #endif void Mixer_Init(const char* device); -void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate); +void* Mixer_Play_Effect(int id, int loop, int volume, float pan, double rate, int deleteondone); void Mixer_Stop_Channel(void* channel); void Mixer_Channel_Volume(void* channel, int volume); void Mixer_Channel_Pan(void* channel, float pan); void Mixer_Channel_Rate(void* channel, double rate); +int Mixer_Channel_IsPlaying(void* channel); +void* Mixer_Play_Music(void* channel, int pathid); -static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (pow(10, (float)volume / 2000))); }; +static int DStoMixerVolume(int volume) { return (int)(SDL_MIX_MAXVOLUME * (SDL_pow(10, (float)volume / 2000))); }; static float DStoMixerPan(int pan) { return (((float)pan + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2; }; static double DStoMixerRate(int frequency) { return (double)frequency / 22050; }; diff --git a/src/peep/peep.c b/src/peep/peep.c index 1b80055efd..e22e44c237 100644 --- a/src/peep/peep.c +++ b/src/peep/peep.c @@ -21,6 +21,7 @@ #include #include "../addresses.h" #include "../audio/audio.h" +#include "../audio/mixer.h" #include "../interface/window.h" #include "../localisation/localisation.h" #include "../management/news_item.h" @@ -376,14 +377,26 @@ void peep_update_crowd_noise() // Check if crowd noise is already playing if (RCT2_GLOBAL(0x009AF5FC, uint32) == 1) { // Load and play crowd noise +#ifdef USE_MIXER + gMusicChannels[2] = Mixer_Play_Music(gMusicChannels[2], PATH_ID_CSS2); + if (gMusicChannels[2]) { + Mixer_Channel_Volume(gMusicChannels[2], DStoMixerVolume(volume)); + RCT2_GLOBAL(0x009AF5FC, uint32) = volume; + } +#else if (sound_channel_load_file2(2, (char*)get_file_path(PATH_ID_CSS2), 0)) { sound_channel_play(2, 1, volume, 0, 0); RCT2_GLOBAL(0x009AF5FC, uint32) = volume; } +#endif } else { // Alter crowd noise volume if (RCT2_GLOBAL(0x009AF5FC, uint32) != volume) { +#ifdef USE_MIXER + Mixer_Channel_Volume(gMusicChannels[2], DStoMixerVolume(volume)); +#else sound_channel_set_volume(2, volume);//RCT2_CALLPROC_2(0x00401AD3, int, int, 2, volume); +#endif RCT2_GLOBAL(0x009AF5FC, uint32) = volume; } } diff --git a/src/ride/vehicle.c b/src/ride/vehicle.c index fe7e9983fe..4b8321d083 100644 --- a/src/ride/vehicle.c +++ b/src/ride/vehicle.c @@ -380,7 +380,7 @@ void vehicle_sounds_update() pan = 0; } #ifdef USE_MIXER - vehicle_sound->sound1_channel = Mixer_Play_Effect(sprite->vehicle.sound1_id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency)); + vehicle_sound->sound1_channel = Mixer_Play_Effect(sprite->vehicle.sound1_id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency), 0); #else RCT2_GLOBAL(0x014241BC, uint32) = 1; sound_play(&vehicle_sound->sound1, looping, volume, pan, frequency); @@ -481,7 +481,7 @@ void vehicle_sounds_update() pan = 0; } #ifdef USE_MIXER - vehicle_sound->sound2_channel = Mixer_Play_Effect(sprite->vehicle.sound2_id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency)); + vehicle_sound->sound2_channel = Mixer_Play_Effect(sprite->vehicle.sound2_id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency), 0); #else RCT2_GLOBAL(0x014241BC, uint32) = 1; sound_play(&vehicle_sound->sound2, looping, volume, pan, frequency); diff --git a/src/windows/options.c b/src/windows/options.c index 6676158173..9dc154ee17 100644 --- a/src/windows/options.c +++ b/src/windows/options.c @@ -504,11 +504,13 @@ static void window_options_dropdown() case WIDX_SOUND_DROPDOWN: audio_init2(dropdownIndex); if (dropdownIndex < gAudioDeviceCount) { +#ifdef USE_MIXER int devicenum = dropdownIndex; if (devicenum == 0) { devicenum = 1; } Mixer_Init(gAudioDevices[devicenum].name); +#endif } /*#ifdef _MSC_VER __asm movzx ax, dropdownIndex diff --git a/src/world/climate.c b/src/world/climate.c index 387d5c01e2..2d8d849ce2 100644 --- a/src/world/climate.c +++ b/src/world/climate.c @@ -20,6 +20,7 @@ #include "../addresses.h" #include "../audio/audio.h" +#include "../audio/mixer.h" #include "../drawing/drawing.h" #include "../localisation/date.h" #include "../scenario.h" @@ -52,8 +53,10 @@ static const rct_weather_transition* climate_transitions[4]; // Sound data static int _rainVolume = 1; static rct_sound _rainSoundInstance; +static void* _rainSoundChannel; static unsigned int _lightningTimer, _thunderTimer; static rct_sound _thunderSoundInstance[MAX_THUNDER_INSTANCES]; +static void* _thunderSoundChannels[MAX_THUNDER_INSTANCES]; static int _thunderStatus[MAX_THUNDER_INSTANCES] = { THUNDER_STATUS_NULL, THUNDER_STATUS_NULL }; static unsigned int _thunderSoundId; static int _thunderVolume; @@ -203,21 +206,43 @@ static void climate_update_rain_sound() if (_climateCurrentWeatherEffect == 1 || _climateCurrentWeatherEffect == 2) { if (_rainVolume == 1) { // Start playing the rain sound +#ifdef USE_MIXER + _rainSoundChannel = Mixer_Play_Effect(SOUND_RAIN_1, MIXER_LOOP_INFINITE, DStoMixerVolume(-4000), 0.5f, 1, 0); +#else if (sound_prepare(SOUND_RAIN_1, &_rainSoundInstance, 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32))) sound_play(&_rainSoundInstance, 1, -4000, 0, 0); +#endif _rainVolume = -4000; } else { // Increase rain sound _rainVolume = min(-1400, _rainVolume + 80); +#ifdef USE_MIXER + if (_rainSoundChannel) { + Mixer_Channel_Volume(_rainSoundChannel, DStoMixerVolume(_rainVolume)); + } +#else sound_set_volume(&_rainSoundInstance, _rainVolume); +#endif } } else if (_rainVolume != 1) { // Decrease rain sound _rainVolume -= 80; if (_rainVolume > -4000) { +#ifdef USE_MIXER + if (_rainSoundChannel) { + Mixer_Channel_Volume(_rainSoundChannel, DStoMixerVolume(_rainVolume)); + } +#else sound_set_volume(&_rainSoundInstance, _rainVolume); +#endif } else { +#ifdef USE_MIXER + if (_rainSoundChannel) { + Mixer_Stop_Channel(_rainSoundChannel); + } +#else sound_stop(&_rainSoundInstance); +#endif _rainVolume = 1; } } @@ -247,10 +272,17 @@ static void climate_update_thunder_sound() if (_thunderStatus[i] == THUNDER_STATUS_NULL) continue; +#ifdef USE_MIXER + if (!Mixer_Channel_IsPlaying(_thunderSoundChannels[i])) { + Mixer_Stop_Channel(_thunderSoundChannels[i]); + _thunderStatus[i] = THUNDER_STATUS_NULL; + } +#else if (!sound_is_playing(&_thunderSoundInstance[i])) { sound_stop(&_thunderSoundInstance[i]); _thunderStatus[i] = THUNDER_STATUS_NULL; } +#endif } } @@ -293,12 +325,20 @@ static void climate_update_thunder() static int climate_play_thunder(int instanceIndex, int soundId, int volume, int pan) { +#ifdef USE_MIXER + _thunderSoundChannels[instanceIndex] = Mixer_Play_Effect(soundId, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), 1, 0); + if (_thunderSoundChannels[instanceIndex]) { + _thunderStatus[instanceIndex] = THUNDER_STATUS_PLAYING; + return 1; + } +#else if (sound_prepare(soundId, &_thunderSoundInstance[instanceIndex], 1, RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_SOUND_SW_BUFFER, uint32))) { sound_play(&_thunderSoundInstance[instanceIndex], 0, volume, pan, 0); _thunderStatus[instanceIndex] = THUNDER_STATUS_PLAYING; return 1; } +#endif return 0; }