From 585ebed6005178a435f7faa572c71345bc877884 Mon Sep 17 00:00:00 2001 From: Ted John Date: Mon, 27 Jun 2022 17:41:53 +0100 Subject: [PATCH] Fix #17297: Crash when switching language (#17370) * Refactor all uses of IAudioChannel and the audio mixer. * Use shared_ptr to avoid dead pointers hanging about. * Reload particular audio channels where necessary after object reload. --- src/openrct2-ui/UiContext.cpp | 15 +- src/openrct2-ui/audio/AudioChannel.cpp | 9 +- src/openrct2-ui/audio/AudioContext.cpp | 16 -- src/openrct2-ui/audio/AudioMixer.cpp | 21 +-- src/openrct2-ui/audio/AudioMixer.h | 5 +- src/openrct2-ui/audio/FlacAudioSource.cpp | 3 + src/openrct2-ui/audio/MemoryAudioSource.cpp | 1 + src/openrct2-ui/audio/OggAudioSource.cpp | 2 + src/openrct2-ui/audio/SDLAudioSource.cpp | 11 ++ src/openrct2-ui/audio/WavAudioSource.cpp | 1 + src/openrct2-ui/libopenrct2ui.vcxproj | 2 +- src/openrct2-ui/windows/Options.cpp | 16 +- src/openrct2/Intro.cpp | 20 +-- src/openrct2/audio/Audio.cpp | 110 ++++++++---- src/openrct2/audio/AudioChannel.h | 1 + src/openrct2/audio/AudioContext.h | 5 - src/openrct2/audio/AudioMixer.cpp | 180 -------------------- src/openrct2/audio/AudioMixer.h | 51 ++---- src/openrct2/audio/DummyAudioContext.cpp | 17 -- src/openrct2/audio/audio.h | 25 ++- src/openrct2/config/Config.cpp | 3 +- src/openrct2/config/Config.h | 2 +- src/openrct2/entity/Peep.cpp | 18 +- src/openrct2/interface/Chat.cpp | 3 +- src/openrct2/libopenrct2.vcxproj | 1 - src/openrct2/object/AudioSampleTable.h | 3 + src/openrct2/object/ObjectManager.cpp | 5 + src/openrct2/ride/RideAudio.cpp | 37 ++-- src/openrct2/ride/Vehicle.cpp | 19 ++- src/openrct2/ride/VehicleEntry.h | 8 +- src/openrct2/world/Climate.cpp | 41 +++-- src/openrct2/world/Climate.h | 1 + 32 files changed, 257 insertions(+), 395 deletions(-) delete mode 100644 src/openrct2/audio/AudioMixer.cpp diff --git a/src/openrct2-ui/UiContext.cpp b/src/openrct2-ui/UiContext.cpp index 51f6a57bb4..04d9dc39bf 100644 --- a/src/openrct2-ui/UiContext.cpp +++ b/src/openrct2-ui/UiContext.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -382,11 +383,11 @@ public: { if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) { - Mixer_SetVolume(1); + SetAudioVolume(1); } if (e.window.event == SDL_WINDOWEVENT_FOCUS_LOST) { - Mixer_SetVolume(0); + SetAudioVolume(0); } } break; @@ -986,6 +987,16 @@ private: return ie; } + + void SetAudioVolume(float value) + { + auto audioContext = GetContext()->GetAudioContext(); + auto mixer = audioContext->GetMixer(); + if (mixer != nullptr) + { + mixer->SetVolume(value); + } + } }; std::unique_ptr OpenRCT2::Ui::CreateUiContext(const std::shared_ptr& env) diff --git a/src/openrct2-ui/audio/AudioChannel.cpp b/src/openrct2-ui/audio/AudioChannel.cpp index 00cea51b28..623408decc 100644 --- a/src/openrct2-ui/audio/AudioChannel.cpp +++ b/src/openrct2-ui/audio/AudioChannel.cpp @@ -19,7 +19,7 @@ namespace OpenRCT2::Audio { - template class AudioChannelImpl : public ISDLAudioChannel + template class AudioChannelImpl final : public ISDLAudioChannel { static_assert(std::is_base_of_v); @@ -185,7 +185,7 @@ namespace OpenRCT2::Audio return _stopping; } - void SetStopping(bool value) override + void SetStopping(bool value) final override { _stopping = value; } @@ -223,6 +223,11 @@ namespace OpenRCT2::Audio _done = false; } + void Stop() override + { + SetStopping(true); + } + void UpdateOldVolume() override { _oldvolume = _volume; diff --git a/src/openrct2-ui/audio/AudioContext.cpp b/src/openrct2-ui/audio/AudioContext.cpp index c192f044f8..1862bd0c61 100644 --- a/src/openrct2-ui/audio/AudioContext.cpp +++ b/src/openrct2-ui/audio/AudioContext.cpp @@ -128,19 +128,6 @@ namespace OpenRCT2::Audio { } - IAudioChannel* PlaySound(int32_t soundId, int32_t volume, int32_t pan) override - { - return nullptr; - } - IAudioChannel* PlaySoundAtLocation(int32_t soundId, int16_t x, int16_t y, int16_t z) override - { - return nullptr; - } - IAudioChannel* PlaySoundPanned(int32_t soundId, int32_t pan, int16_t x, int16_t y, int16_t z) override - { - return nullptr; - } - void ToggleAllSounds() override { } @@ -157,9 +144,6 @@ namespace OpenRCT2::Audio void StopCrowdSound() override { } - void StopWeatherSound() override - { - } void StopRideMusic() override { } diff --git a/src/openrct2-ui/audio/AudioMixer.cpp b/src/openrct2-ui/audio/AudioMixer.cpp index 92cbf68c7a..22c8096a66 100644 --- a/src/openrct2-ui/audio/AudioMixer.cpp +++ b/src/openrct2-ui/audio/AudioMixer.cpp @@ -51,10 +51,6 @@ void AudioMixer::Close() { // Free channels Lock(); - for (IAudioChannel* channel : _channels) - { - delete channel; - } _channels.clear(); Unlock(); @@ -79,10 +75,10 @@ void AudioMixer::Unlock() SDL_UnlockAudioDevice(_deviceId); } -IAudioChannel* AudioMixer::Play(IAudioSource* source, int32_t loop, bool deleteondone) +std::shared_ptr AudioMixer::Play(IAudioSource* source, int32_t loop, bool deleteondone) { Lock(); - auto* channel = AudioChannel::Create(); + auto channel = std::shared_ptr(AudioChannel::Create()); if (channel != nullptr) { channel->Play(source, loop); @@ -93,13 +89,6 @@ IAudioChannel* AudioMixer::Play(IAudioSource* source, int32_t loop, bool deleteo return channel; } -void AudioMixer::Stop(IAudioChannel* channel) -{ - Lock(); - channel->SetStopping(true); - Unlock(); -} - void AudioMixer::SetVolume(float volume) { _volume = volume; @@ -146,12 +135,12 @@ void AudioMixer::GetNextAudioChunk(uint8_t* dst, size_t length) auto it = _channels.begin(); while (it != _channels.end()) { - auto channel = *it; + auto& channel = *it; auto channelSource = channel->GetSource(); auto channelSourceReleased = channelSource == nullptr || channelSource->IsReleased(); if (channelSourceReleased || (channel->IsDone() && channel->DeleteOnDone()) || channel->IsStopping()) { - delete channel; + channel->SetDone(true); it = _channels.erase(it); } else @@ -160,7 +149,7 @@ void AudioMixer::GetNextAudioChunk(uint8_t* dst, size_t length) if ((group != MixerGroup::Sound || gConfigSound.sound_enabled) && gConfigSound.master_sound_enabled && gConfigSound.master_volume != 0) { - MixChannel(channel, dst, length); + MixChannel(channel.get(), dst, length); } it++; } diff --git a/src/openrct2-ui/audio/AudioMixer.h b/src/openrct2-ui/audio/AudioMixer.h index 8ce6fabe0f..286a77ee64 100644 --- a/src/openrct2-ui/audio/AudioMixer.h +++ b/src/openrct2-ui/audio/AudioMixer.h @@ -33,7 +33,7 @@ namespace OpenRCT2::Audio SDL_AudioDeviceID _deviceId = 0; AudioFormat _format = {}; - std::list _channels; + std::list> _channels; float _volume = 1.0f; float _adjustSoundVolume = 0.0f; float _adjustMusicVolume = 0.0f; @@ -52,8 +52,7 @@ namespace OpenRCT2::Audio void Close() override; void Lock() override; void Unlock() override; - IAudioChannel* Play(IAudioSource* source, int32_t loop, bool deleteondone) override; - void Stop(IAudioChannel* channel) override; + std::shared_ptr Play(IAudioSource* source, int32_t loop, bool deleteondone) override; void SetVolume(float volume) override; SDLAudioSource* AddSource(std::unique_ptr source); diff --git a/src/openrct2-ui/audio/FlacAudioSource.cpp b/src/openrct2-ui/audio/FlacAudioSource.cpp index a3e114850f..f74863488b 100644 --- a/src/openrct2-ui/audio/FlacAudioSource.cpp +++ b/src/openrct2-ui/audio/FlacAudioSource.cpp @@ -9,9 +9,12 @@ #include "SDLAudioSource.h" +#include + #ifndef DISABLE_FLAC # include # include +# include # include #endif diff --git a/src/openrct2-ui/audio/MemoryAudioSource.cpp b/src/openrct2-ui/audio/MemoryAudioSource.cpp index 71e7ff2238..9e25a61c50 100644 --- a/src/openrct2-ui/audio/MemoryAudioSource.cpp +++ b/src/openrct2-ui/audio/MemoryAudioSource.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace OpenRCT2::Audio diff --git a/src/openrct2-ui/audio/OggAudioSource.cpp b/src/openrct2-ui/audio/OggAudioSource.cpp index 369a901a40..f5ae7c7d32 100644 --- a/src/openrct2-ui/audio/OggAudioSource.cpp +++ b/src/openrct2-ui/audio/OggAudioSource.cpp @@ -9,6 +9,8 @@ #include "SDLAudioSource.h" +#include + #ifndef DISABLE_VORBIS # include # include diff --git a/src/openrct2-ui/audio/SDLAudioSource.cpp b/src/openrct2-ui/audio/SDLAudioSource.cpp index 928ecd3219..6be5672dce 100644 --- a/src/openrct2-ui/audio/SDLAudioSource.cpp +++ b/src/openrct2-ui/audio/SDLAudioSource.cpp @@ -1,5 +1,16 @@ +/***************************************************************************** + * Copyright (c) 2014-2022 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + #include "SDLAudioSource.h" +#include + using namespace OpenRCT2::Audio; enum class AudioCodecKind diff --git a/src/openrct2-ui/audio/WavAudioSource.cpp b/src/openrct2-ui/audio/WavAudioSource.cpp index 39a21082cb..4379900338 100644 --- a/src/openrct2-ui/audio/WavAudioSource.cpp +++ b/src/openrct2-ui/audio/WavAudioSource.cpp @@ -10,6 +10,7 @@ #include "SDLAudioSource.h" #include +#include namespace OpenRCT2::Audio { diff --git a/src/openrct2-ui/libopenrct2ui.vcxproj b/src/openrct2-ui/libopenrct2ui.vcxproj index 87e793a070..6e5f50c6a6 100644 --- a/src/openrct2-ui/libopenrct2ui.vcxproj +++ b/src/openrct2-ui/libopenrct2ui.vcxproj @@ -232,4 +232,4 @@ - \ No newline at end of file + diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index 4c397b1796..3d44ffcc60 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,9 @@ #include #include +using namespace OpenRCT2; +using namespace OpenRCT2::Audio; + // clang-format off enum WindowOptionsPage { WINDOW_OPTIONS_PAGE_DISPLAY, @@ -1384,17 +1388,17 @@ private: OpenRCT2::Audio::InitRideSounds(dropdownIndex); if (dropdownIndex < OpenRCT2::Audio::GetDeviceCount()) { + auto audioContext = GetContext()->GetAudioContext(); if (dropdownIndex == 0) { - Mixer_Init(nullptr); - gConfigSound.device = nullptr; + audioContext->SetOutputDevice(""); + gConfigSound.device = ""; } else { - const char* devicename = OpenRCT2::Audio::GetDeviceName(dropdownIndex).c_str(); - Mixer_Init(devicename); - SafeFree(gConfigSound.device); - gConfigSound.device = strndup(devicename, OpenRCT2::Audio::MaxDeviceNameSize); + const auto& deviceName = GetDeviceName(dropdownIndex); + audioContext->SetOutputDevice(deviceName); + gConfigSound.device = deviceName; } config_save_default(); OpenRCT2::Audio::PlayTitleMusic(); diff --git a/src/openrct2/Intro.cpp b/src/openrct2/Intro.cpp index c640ff5788..fafbfff5ff 100644 --- a/src/openrct2/Intro.cpp +++ b/src/openrct2/Intro.cpp @@ -10,11 +10,14 @@ #include "Intro.h" #include "Context.h" +#include "audio/AudioChannel.h" #include "audio/AudioMixer.h" #include "audio/audio.h" #include "drawing/Drawing.h" #include "sprites.h" +using namespace OpenRCT2::Audio; + #define BACKROUND_COLOUR_DARK PALETTE_INDEX_10 #define BACKROUND_COLOUR_LOGO PALETTE_INDEX_245 #define BORDER_COLOUR_PUBLISHER PALETTE_INDEX_129 @@ -27,7 +30,7 @@ IntroState gIntroState; // Used mainly for timing but also for Y coordinate and fading. static int32_t _introStateCounter; -static void* _soundChannel = nullptr; +static std::shared_ptr _soundChannel = nullptr; static bool _chainLiftFinished; static void screen_intro_process_mouse_input(); @@ -55,8 +58,7 @@ void intro_update() _introStateCounter = -580; // Play the chain lift sound - _soundChannel = Mixer_Play_Effect( - OpenRCT2::Audio::SoundId::LiftBM, MIXER_LOOP_INFINITE, MIXER_VOLUME_MAX, 0.5f, 1, true); + _soundChannel = CreateAudioChannel(SoundId::LiftBM, true); _chainLiftFinished = false; gIntroState = IntroState::PublisherScroll; break; @@ -89,13 +91,12 @@ void intro_update() // Stop the chain lift sound if (_soundChannel != nullptr) { - Mixer_Stop_Channel(_soundChannel); + _soundChannel->Stop(); _soundChannel = nullptr; } // Play the track friction sound - _soundChannel = Mixer_Play_Effect( - OpenRCT2::Audio::SoundId::TrackFrictionBM, MIXER_LOOP_INFINITE, MIXER_VOLUME_MAX, 0.25f, 0.75, true); + _soundChannel = CreateAudioChannel(SoundId::TrackFrictionBM, true, MIXER_VOLUME_MAX, 0.25f, 0.75); } // Check if logo is off the screen...ish @@ -104,13 +105,12 @@ void intro_update() // Stop the track friction sound if (_soundChannel != nullptr) { - Mixer_Stop_Channel(_soundChannel); + _soundChannel->Stop(); _soundChannel = nullptr; } // Play long peep scream sound - _soundChannel = Mixer_Play_Effect( - OpenRCT2::Audio::SoundId::Scream1, MIXER_LOOP_NONE, MIXER_VOLUME_MAX, 0.5f, 1, false); + _soundChannel = CreateAudioChannel(SoundId::Scream1); gIntroState = IntroState::LogoFadeIn; _introStateCounter = 0; @@ -148,7 +148,7 @@ void intro_update() // Stop any playing sound if (_soundChannel != nullptr) { - Mixer_Stop_Channel(_soundChannel); + _soundChannel->Stop(); _soundChannel = nullptr; } diff --git a/src/openrct2/audio/Audio.cpp b/src/openrct2/audio/Audio.cpp index b82d2dfd9c..03b473ac3f 100644 --- a/src/openrct2/audio/Audio.cpp +++ b/src/openrct2/audio/Audio.cpp @@ -27,10 +27,13 @@ #include "../ride/RideAudio.h" #include "../ui/UiContext.h" #include "../util/Util.h" +#include "../world/Climate.h" +#include "AudioChannel.h" #include "AudioContext.h" #include "AudioMixer.h" #include +#include #include namespace OpenRCT2::Audio @@ -50,8 +53,7 @@ namespace OpenRCT2::Audio bool gGameSoundsOff = false; int32_t gVolumeAdjustZoom = 0; - void* gTitleMusicChannel = nullptr; - void* gWeatherSoundChannel = nullptr; + static std::shared_ptr _titleMusicChannel = nullptr; VehicleSound gVehicleSoundList[MaxVehicleSounds]; @@ -70,14 +72,15 @@ namespace OpenRCT2::Audio void Init() { - if (str_is_null_or_empty(gConfigSound.device)) + auto audioContext = GetContext()->GetAudioContext(); + if (gConfigSound.device.empty()) { - Mixer_Init(nullptr); + audioContext->SetOutputDevice(""); _currentAudioDevice = 0; } else { - Mixer_Init(gConfigSound.device); + audioContext->SetOutputDevice(gConfigSound.device); PopulateDevices(); for (int32_t i = 0; i < GetDeviceCount(); i++) @@ -189,7 +192,7 @@ namespace OpenRCT2::Audio mixerPan = ((x2 / screenWidth) - 0x8000) >> 4; } - Mixer_Play_Effect(audioSource, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(mixerPan), 1, 1); + CreateAudioChannel(audioSource, MixerGroup::Sound, false, DStoMixerVolume(volume), DStoMixerPan(mixerPan), 1, true); } void Play3D(SoundId soundId, const CoordsXYZ& loc) @@ -255,7 +258,7 @@ namespace OpenRCT2::Audio return; } - if (gTitleMusicChannel != nullptr) + if (_titleMusicChannel != nullptr && !_titleMusicChannel->IsDone()) { return; } @@ -272,11 +275,7 @@ namespace OpenRCT2::Audio auto source = audioObject->GetSample(0); if (source != nullptr) { - gTitleMusicChannel = Mixer_Play_Music(source, MIXER_LOOP_INFINITE, true); - if (gTitleMusicChannel != nullptr) - { - Mixer_Channel_SetGroup(gTitleMusicChannel, MixerGroup::TitleMusic); - } + _titleMusicChannel = CreateAudioChannel(source, MixerGroup::TitleMusic, true); } } } @@ -287,7 +286,7 @@ namespace OpenRCT2::Audio StopVehicleSounds(); RideAudio::StopAllChannels(); peep_stop_crowd_noise(); - StopWeatherSound(); + ClimateStopWeatherSound(); } int32_t GetDeviceCount() @@ -312,10 +311,10 @@ namespace OpenRCT2::Audio void StopTitleMusic() { - if (gTitleMusicChannel != nullptr) + if (_titleMusicChannel != nullptr) { - Mixer_Stop_Channel(gTitleMusicChannel); - gTitleMusicChannel = nullptr; + _titleMusicChannel->Stop(); + _titleMusicChannel = nullptr; } // Unload the audio object @@ -331,15 +330,6 @@ namespace OpenRCT2::Audio } } - void StopWeatherSound() - { - if (gWeatherSoundChannel != nullptr) - { - Mixer_Stop_Channel(gWeatherSoundChannel); - gWeatherSoundChannel = nullptr; - } - } - void InitRideSoundsAndInfo() { InitRideSounds(0); @@ -362,7 +352,7 @@ namespace OpenRCT2::Audio peep_stop_crowd_noise(); StopTitleMusic(); RideAudio::StopAllChannels(); - StopWeatherSound(); + ClimateStopWeatherSound(); _currentAudioDevice = -1; } @@ -389,7 +379,7 @@ namespace OpenRCT2::Audio StopVehicleSounds(); RideAudio::StopAllChannels(); peep_stop_crowd_noise(); - StopWeatherSound(); + ClimateStopWeatherSound(); } void Resume() @@ -409,14 +399,76 @@ namespace OpenRCT2::Audio vehicleSound.id = SoundIdNull; if (vehicleSound.TrackSound.Id != SoundId::Null) { - Mixer_Stop_Channel(vehicleSound.TrackSound.Channel); + vehicleSound.TrackSound.Channel->Stop(); } if (vehicleSound.OtherSound.Id != SoundId::Null) { - Mixer_Stop_Channel(vehicleSound.OtherSound.Channel); + vehicleSound.OtherSound.Channel->Stop(); } } } } + static IAudioMixer* GetMixer() + { + auto audioContext = GetContext()->GetAudioContext(); + return audioContext->GetMixer(); + } + + std::shared_ptr CreateAudioChannel( + SoundId id, bool loop, int32_t volume, float pan, double rate, bool forget) + { + // Get sound from base object + auto baseAudioObject = GetBaseAudioObject(); + if (baseAudioObject != nullptr) + { + auto source = baseAudioObject->GetSample(EnumValue(id)); + if (source != nullptr) + { + return CreateAudioChannel(source, MixerGroup::Sound, loop, volume, pan, rate, forget); + } + } + return nullptr; + } + + std::shared_ptr CreateAudioChannel( + IAudioSource* source, MixerGroup group, bool loop, int32_t volume, float pan, double rate, bool forget) + { + auto* mixer = GetMixer(); + if (mixer == nullptr) + { + return nullptr; + } + + mixer->Lock(); + auto channel = mixer->Play(source, loop ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, forget); + if (channel != nullptr) + { + channel->SetGroup(group); + channel->SetVolume(volume); + channel->SetPan(pan); + channel->SetRate(rate); + channel->UpdateOldVolume(); + } + mixer->Unlock(); + return channel; + } + + int32_t DStoMixerVolume(int32_t volume) + { + return static_cast(MIXER_VOLUME_MAX * (std::pow(10.0f, static_cast(volume) / 2000))); + } + + float DStoMixerPan(int32_t pan) + { + constexpr int32_t DSBPAN_LEFT = -10000; + constexpr int32_t DSBPAN_RIGHT = 10000; + return ((static_cast(pan) + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2; + } + + double DStoMixerRate(int32_t frequency) + { + return static_cast(frequency) / 22050; + } + } // namespace OpenRCT2::Audio diff --git a/src/openrct2/audio/AudioChannel.h b/src/openrct2/audio/AudioChannel.h index 4ba828dca6..c05284c2b0 100644 --- a/src/openrct2/audio/AudioChannel.h +++ b/src/openrct2/audio/AudioChannel.h @@ -61,6 +61,7 @@ namespace OpenRCT2::Audio virtual bool IsPlaying() const abstract; virtual void Play(IAudioSource* source, int32_t loop = 0) abstract; + virtual void Stop() abstract; virtual void UpdateOldVolume() abstract; virtual size_t Read(void* dst, size_t len) abstract; diff --git a/src/openrct2/audio/AudioContext.h b/src/openrct2/audio/AudioContext.h index 815cf5eb61..fb33b4e4e3 100644 --- a/src/openrct2/audio/AudioContext.h +++ b/src/openrct2/audio/AudioContext.h @@ -39,17 +39,12 @@ namespace OpenRCT2::Audio virtual void StartTitleMusic() abstract; - virtual IAudioChannel* PlaySound(int32_t soundId, int32_t volume, int32_t pan) abstract; - virtual IAudioChannel* PlaySoundAtLocation(int32_t soundId, int16_t x, int16_t y, int16_t z) abstract; - virtual IAudioChannel* PlaySoundPanned(int32_t soundId, int32_t pan, int16_t x, int16_t y, int16_t z) abstract; - virtual void ToggleAllSounds() abstract; virtual void PauseSounds() abstract; virtual void UnpauseSounds() abstract; virtual void StopAll() abstract; virtual void StopCrowdSound() abstract; - virtual void StopWeatherSound() abstract; virtual void StopRideMusic() abstract; virtual void StopTitleMusic() abstract; virtual void StopVehicleSounds() abstract; diff --git a/src/openrct2/audio/AudioMixer.cpp b/src/openrct2/audio/AudioMixer.cpp deleted file mode 100644 index 50223b9b1b..0000000000 --- a/src/openrct2/audio/AudioMixer.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/***************************************************************************** - * Copyright (c) 2014-2020 OpenRCT2 developers - * - * For a complete list of all authors, please refer to contributors.md - * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 - * - * OpenRCT2 is licensed under the GNU General Public License version 3. - *****************************************************************************/ - -#include "AudioMixer.h" - -#include "../Context.h" -#include "../config/Config.h" -#include "../object/AudioObject.h" -#include "../object/ObjectManager.h" -#include "AudioChannel.h" -#include "AudioContext.h" -#include "AudioSource.h" -#include "audio.h" - -#include - -using namespace OpenRCT2; -using namespace OpenRCT2::Audio; - -static IAudioMixer* GetMixer() -{ - auto audioContext = GetContext()->GetAudioContext(); - return audioContext->GetMixer(); -} - -void Mixer_Init(const char* device) -{ - auto audioContext = GetContext()->GetAudioContext(); - if (device == nullptr) - { - device = ""; - } - audioContext->SetOutputDevice(std::string(device)); -} - -IAudioChannel* Mixer_Play_Effect(SoundId id, int32_t loop, int32_t volume, float pan, double rate, int32_t deleteondone) -{ - if (gConfigSound.sound_enabled) - { - // Get sound from base object - auto baseAudioObject = GetBaseAudioObject(); - if (baseAudioObject != nullptr) - { - auto source = baseAudioObject->GetSample(EnumValue(id)); - if (source != nullptr) - { - return Mixer_Play_Effect(source, loop, volume, pan, rate, deleteondone); - } - } - } - return nullptr; -} - -IAudioChannel* Mixer_Play_Effect( - IAudioSource* source, int32_t loop, int32_t volume, float pan, double rate, int32_t deleteondone) -{ - IAudioChannel* channel = nullptr; - if (gConfigSound.sound_enabled) - { - IAudioMixer* mixer = GetMixer(); - if (mixer != nullptr) - { - mixer->Lock(); - channel = mixer->Play(source, loop, deleteondone != 0); - if (channel != nullptr) - { - channel->SetVolume(volume); - channel->SetPan(pan); - channel->SetRate(rate); - channel->UpdateOldVolume(); - } - mixer->Unlock(); - } - } - return channel; -} - -void Mixer_Stop_Channel(void* channel) -{ - auto mixer = GetMixer(); - if (mixer != nullptr) - { - mixer->Stop(static_cast(channel)); - } -} - -void Mixer_Channel_Volume(void* channel, int32_t volume) -{ - IAudioMixer* audioMixer = GetMixer(); - if (audioMixer != nullptr) - { - audioMixer->Lock(); - static_cast(channel)->SetVolume(volume); - audioMixer->Unlock(); - } -} - -void Mixer_Channel_Pan(void* channel, float pan) -{ - IAudioMixer* audioMixer = GetMixer(); - if (audioMixer != nullptr) - { - audioMixer->Lock(); - static_cast(channel)->SetPan(pan); - audioMixer->Unlock(); - } -} - -void Mixer_Channel_Rate(void* channel, double rate) -{ - IAudioMixer* audioMixer = GetMixer(); - if (audioMixer != nullptr) - { - audioMixer->Lock(); - static_cast(channel)->SetRate(rate); - audioMixer->Unlock(); - } -} - -int32_t Mixer_Channel_IsPlaying(void* channel) -{ - return static_cast(channel)->IsPlaying(); -} - -uint64_t Mixer_Channel_GetOffset(void* channel) -{ - return static_cast(channel)->GetOffset(); -} - -int32_t Mixer_Channel_SetOffset(void* channel, uint64_t offset) -{ - return static_cast(channel)->SetOffset(offset); -} - -void Mixer_Channel_SetGroup(void* channel, MixerGroup group) -{ - static_cast(channel)->SetGroup(group); -} - -IAudioChannel* Mixer_Play_Music(IAudioSource* source, int32_t loop, int32_t streaming) -{ - auto* mixer = GetMixer(); - if (mixer == nullptr) - { - return nullptr; - } - - auto* channel = mixer->Play(source, loop, false); - if (channel != nullptr) - { - channel->SetGroup(MixerGroup::RideMusic); - } - return channel; -} - -void Mixer_SetVolume(float volume) -{ - GetMixer()->SetVolume(volume); -} - -int32_t DStoMixerVolume(int32_t volume) -{ - return static_cast(MIXER_VOLUME_MAX * (std::pow(10.0f, static_cast(volume) / 2000))); -} - -float DStoMixerPan(int32_t pan) -{ - return ((static_cast(pan) + -DSBPAN_LEFT) / DSBPAN_RIGHT) / 2; -} - -double DStoMixerRate(int32_t frequency) -{ - return static_cast(frequency) / 22050; -} diff --git a/src/openrct2/audio/AudioMixer.h b/src/openrct2/audio/AudioMixer.h index 6ef2536a87..5852f558cd 100644 --- a/src/openrct2/audio/AudioMixer.h +++ b/src/openrct2/audio/AudioMixer.h @@ -9,17 +9,14 @@ #pragma once -#include "../common.h" -#include "../core/IStream.hpp" - #include -#define MIXER_VOLUME_MAX 128 -#define MIXER_LOOP_NONE 0 -#define MIXER_LOOP_INFINITE (-1) - namespace OpenRCT2::Audio { + constexpr int32_t MIXER_VOLUME_MAX = 128; + constexpr int32_t MIXER_LOOP_NONE = 0; + constexpr int32_t MIXER_LOOP_INFINITE = -1; + enum class SoundId : uint8_t; enum class MixerGroup : int32_t @@ -39,39 +36,11 @@ namespace OpenRCT2::Audio { virtual ~IAudioMixer() = default; - virtual void Init(const char* device) abstract; - virtual void Close() abstract; - virtual void Lock() abstract; - virtual void Unlock() abstract; - virtual IAudioChannel* Play(IAudioSource* source, int32_t loop, bool deleteondone) abstract; - virtual void Stop(IAudioChannel* channel) abstract; - virtual void SetVolume(float volume) abstract; + virtual void Init(const char* device) = 0; + virtual void Close() = 0; + virtual void Lock() = 0; + virtual void Unlock() = 0; + virtual std::shared_ptr Play(IAudioSource* source, int32_t loop, bool deleteondone) = 0; + virtual void SetVolume(float volume) = 0; }; } // namespace OpenRCT2::Audio - -#ifndef DSBPAN_LEFT -# define DSBPAN_LEFT (-10000) -#endif -#ifndef DSBPAN_RIGHT -# define DSBPAN_RIGHT 10000 -#endif - -void Mixer_Init(const char* device); -OpenRCT2::Audio::IAudioChannel* Mixer_Play_Effect( - OpenRCT2::Audio::SoundId id, int32_t loop, int32_t volume, float pan, double rate, int32_t deleteondone); -OpenRCT2::Audio::IAudioChannel* Mixer_Play_Effect( - OpenRCT2::Audio::IAudioSource* source, int32_t loop, int32_t volume, float pan, double rate, int32_t deleteondone); -void Mixer_Stop_Channel(void* channel); -void Mixer_Channel_Volume(void* channel, int32_t volume); -void Mixer_Channel_Pan(void* channel, float pan); -void Mixer_Channel_Rate(void* channel, double rate); -int32_t Mixer_Channel_IsPlaying(void* channel); -uint64_t Mixer_Channel_GetOffset(void* channel); -int32_t Mixer_Channel_SetOffset(void* channel, uint64_t offset); -void Mixer_Channel_SetGroup(void* channel, OpenRCT2::Audio::MixerGroup group); -OpenRCT2::Audio::IAudioChannel* Mixer_Play_Music(OpenRCT2::Audio::IAudioSource* source, int32_t loop, int32_t streaming); -void Mixer_SetVolume(float volume); - -int32_t DStoMixerVolume(int32_t volume); -float DStoMixerPan(int32_t pan); -double DStoMixerRate(int32_t frequency); diff --git a/src/openrct2/audio/DummyAudioContext.cpp b/src/openrct2/audio/DummyAudioContext.cpp index fe88cec760..b6f15bf51b 100644 --- a/src/openrct2/audio/DummyAudioContext.cpp +++ b/src/openrct2/audio/DummyAudioContext.cpp @@ -40,20 +40,6 @@ namespace OpenRCT2::Audio { } - IAudioChannel* PlaySound(int32_t /*soundId*/, int32_t /*volume*/, int32_t /*pan*/) override - { - return nullptr; - } - IAudioChannel* PlaySoundAtLocation(int32_t /*soundId*/, int16_t /*x*/, int16_t /*y*/, int16_t /*z*/) override - { - return nullptr; - } - IAudioChannel* PlaySoundPanned( - int32_t /*soundId*/, int32_t /*pan*/, int16_t /*x*/, int16_t /*y*/, int16_t /*z*/) override - { - return nullptr; - } - void ToggleAllSounds() override { } @@ -70,9 +56,6 @@ namespace OpenRCT2::Audio void StopCrowdSound() override { } - void StopWeatherSound() override - { - } void StopRideMusic() override { } diff --git a/src/openrct2/audio/audio.h b/src/openrct2/audio/audio.h index 7c6d13503e..96c460c44f 100644 --- a/src/openrct2/audio/audio.h +++ b/src/openrct2/audio/audio.h @@ -12,6 +12,7 @@ #include "../Identifiers.h" #include "../common.h" #include "../ride/RideTypes.h" +#include "AudioMixer.h" #include @@ -27,6 +28,9 @@ namespace OpenRCT2::Audio #define AUDIO_PLAY_AT_CENTRE 0x8000 + struct IAudioChannel; + struct IAudioSource; + enum class MixerGroup : int32_t; enum class SoundId : uint8_t; struct Sound @@ -35,7 +39,7 @@ namespace OpenRCT2::Audio int16_t Volume; int16_t Pan; uint16_t Frequency; - void* Channel; + std::shared_ptr Channel; }; struct VehicleSound @@ -139,9 +143,6 @@ namespace OpenRCT2::Audio extern bool gGameSoundsOff; extern int32_t gVolumeAdjustZoom; - extern void* gTitleMusicChannel; - extern void* gWeatherSoundChannel; - extern VehicleSound gVehicleSoundList[MaxVehicleSounds]; /** @@ -224,11 +225,6 @@ namespace OpenRCT2::Audio */ void PlayTitleMusic(); - /** - * Stops the weather sound effect from playing. - */ - void StopWeatherSound(); - /** * Stops the title music from playing. * rct2: 0x006BD0BD @@ -257,4 +253,15 @@ namespace OpenRCT2::Audio AudioObject* GetBaseAudioObject(); + std::shared_ptr CreateAudioChannel( + SoundId soundId, bool loop = false, int32_t volume = MIXER_VOLUME_MAX, float pan = 0.5f, double rate = 1, + bool forget = false); + std::shared_ptr CreateAudioChannel( + IAudioSource* source, MixerGroup group, bool loop = false, int32_t volume = MIXER_VOLUME_MAX, float pan = 0.5f, + double rate = 1, bool forget = false); + + int32_t DStoMixerVolume(int32_t volume); + float DStoMixerPan(int32_t pan); + double DStoMixerRate(int32_t frequency); + } // namespace OpenRCT2::Audio diff --git a/src/openrct2/config/Config.cpp b/src/openrct2/config/Config.cpp index fc59f098f4..924ddc1f23 100644 --- a/src/openrct2/config/Config.cpp +++ b/src/openrct2/config/Config.cpp @@ -357,7 +357,7 @@ namespace Config if (reader->ReadSection("sound")) { auto model = &gConfigSound; - model->device = reader->GetCString("audio_device", nullptr); + model->device = reader->GetString("audio_device", ""); model->master_sound_enabled = reader->GetBoolean("master_sound", true); model->master_volume = reader->GetInt32("master_volume", 100); model->title_music = static_cast(reader->GetInt32("title_music", EnumValue(TitleMusicKind::Rct2))); @@ -802,7 +802,6 @@ void config_release() SafeFree(gConfigGeneral.custom_currency_symbol); SafeFree(gConfigInterface.current_theme_preset); SafeFree(gConfigInterface.current_title_sequence_preset); - SafeFree(gConfigSound.device); SafeFree(gConfigFonts.file_name); SafeFree(gConfigFonts.font_name); } diff --git a/src/openrct2/config/Config.h b/src/openrct2/config/Config.h index 1599129f8d..3cffd67cb2 100644 --- a/src/openrct2/config/Config.h +++ b/src/openrct2/config/Config.h @@ -138,7 +138,7 @@ struct InterfaceConfiguration struct SoundConfiguration { - utf8* device; + std::string device; bool master_sound_enabled; uint8_t master_volume; TitleMusicKind title_music; diff --git a/src/openrct2/entity/Peep.cpp b/src/openrct2/entity/Peep.cpp index 55a9db480f..0c4a794bc7 100644 --- a/src/openrct2/entity/Peep.cpp +++ b/src/openrct2/entity/Peep.cpp @@ -15,6 +15,7 @@ #include "../Input.h" #include "../OpenRCT2.h" #include "../actions/GameAction.h" +#include "../audio/AudioChannel.h" #include "../audio/AudioMixer.h" #include "../audio/audio.h" #include "../config/Config.h" @@ -59,6 +60,8 @@ #include #include +using namespace OpenRCT2::Audio; + uint8_t gGuestChangeModifier; uint32_t gNumGuestsInPark; uint32_t gNumGuestsInParkLastWeek; @@ -78,7 +81,7 @@ std::unique_ptr gGuestPathfinder = std::make_unique _crowdSoundChannel = nullptr; static void peep_128_tick_update(Peep* peep, int32_t index); static void peep_release_balloon(Guest* peep, int16_t spawn_height); @@ -1203,7 +1206,7 @@ void peep_stop_crowd_noise() { if (_crowdSoundChannel != nullptr) { - Mixer_Stop_Channel(_crowdSoundChannel); + _crowdSoundChannel->Stop(); _crowdSoundChannel = nullptr; } } @@ -1259,7 +1262,7 @@ void peep_update_crowd_noise() // Mute crowd noise if (_crowdSoundChannel != nullptr) { - Mixer_Channel_Volume(_crowdSoundChannel, 0); + _crowdSoundChannel->SetVolume(0); } } else @@ -1273,18 +1276,17 @@ void peep_update_crowd_noise() volume = (viewport->zoom.ApplyInversedTo(207360000 - volume) - 207360000) / 65536 - 150; // Load and play crowd noise if needed and set volume - if (_crowdSoundChannel == nullptr) + if (_crowdSoundChannel == nullptr || _crowdSoundChannel->IsDone()) { - _crowdSoundChannel = Mixer_Play_Effect( - OpenRCT2::Audio::SoundId::CrowdAmbience, MIXER_LOOP_INFINITE, 0, 0.5f, 1, false); + _crowdSoundChannel = CreateAudioChannel(SoundId::CrowdAmbience, true, 0); if (_crowdSoundChannel != nullptr) { - Mixer_Channel_SetGroup(_crowdSoundChannel, OpenRCT2::Audio::MixerGroup::Sound); + _crowdSoundChannel->SetGroup(OpenRCT2::Audio::MixerGroup::Sound); } } if (_crowdSoundChannel != nullptr) { - Mixer_Channel_Volume(_crowdSoundChannel, DStoMixerVolume(volume)); + _crowdSoundChannel->SetVolume(DStoMixerVolume(volume)); } } } diff --git a/src/openrct2/interface/Chat.cpp b/src/openrct2/interface/Chat.cpp index 4227eb3a63..e1e05a2b8c 100644 --- a/src/openrct2/interface/Chat.cpp +++ b/src/openrct2/interface/Chat.cpp @@ -24,6 +24,7 @@ #include using namespace OpenRCT2; +using namespace OpenRCT2::Audio; bool gChatOpen = false; static char _chatCurrentLine[CHAT_MAX_MESSAGE_LENGTH]; @@ -230,7 +231,7 @@ void chat_history_add(std::string_view s) // Log to file (src only as logging does its own timestamp) network_append_chat_log(s); - Mixer_Play_Effect(OpenRCT2::Audio::SoundId::NewsItem, 0, MIXER_VOLUME_MAX, 0.5f, 1.5f, true); + CreateAudioChannel(SoundId::NewsItem, 0, MIXER_VOLUME_MAX, 0.5f, 1.5f, true); } void chat_input(ChatInput input) diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index aa9e302d60..0249cf33b8 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -626,7 +626,6 @@ - diff --git a/src/openrct2/object/AudioSampleTable.h b/src/openrct2/object/AudioSampleTable.h index 0f340e137a..e80f626d4f 100644 --- a/src/openrct2/object/AudioSampleTable.h +++ b/src/openrct2/object/AudioSampleTable.h @@ -11,6 +11,9 @@ #include "../audio/AudioSource.h" #include "../core/JsonFwd.hpp" +#include "Object.h" + +#include struct IReadObjectContext; diff --git a/src/openrct2/object/ObjectManager.cpp b/src/openrct2/object/ObjectManager.cpp index f4f8b9fd1f..c8b1b26eca 100644 --- a/src/openrct2/object/ObjectManager.cpp +++ b/src/openrct2/object/ObjectManager.cpp @@ -11,6 +11,7 @@ #include "../Context.h" #include "../ParkImporter.h" +#include "../audio/audio.h" #include "../core/Console.hpp" #include "../core/Memory.hpp" #include "../localisation/StringIds.h" @@ -238,6 +239,10 @@ public: } UpdateSceneryGroupIndexes(); ResetTypeToRideEntryIndexMap(); + + // We will need to replay the title music if the title music object got reloaded + OpenRCT2::Audio::StopTitleMusic(); + OpenRCT2::Audio::PlayTitleMusic(); } std::vector GetPackableObjects() override diff --git a/src/openrct2/ride/RideAudio.cpp b/src/openrct2/ride/RideAudio.cpp index 6734ab163f..645606dd6c 100644 --- a/src/openrct2/ride/RideAudio.cpp +++ b/src/openrct2/ride/RideAudio.cpp @@ -60,10 +60,11 @@ namespace OpenRCT2::RideAudio int16_t Pan{}; uint16_t Frequency{}; - void* Channel{}; + std::shared_ptr Channel{}; IAudioSource* Source{}; - RideMusicChannel(const ViewportRideMusicInstance& instance, void* channel, IAudioSource* source) + RideMusicChannel( + const ViewportRideMusicInstance& instance, std::shared_ptr channel, IAudioSource* source) { RideId = instance.RideId; TrackIndex = instance.TrackIndex; @@ -73,13 +74,13 @@ namespace OpenRCT2::RideAudio Pan = instance.Pan; Frequency = instance.Frequency; - Channel = channel; - Source = source; + channel->SetOffset(Offset); + channel->SetVolume(DStoMixerVolume(Volume)); + channel->SetPan(DStoMixerPan(Pan)); + channel->SetRate(DStoMixerRate(Frequency)); + Channel = std::move(channel); - Mixer_Channel_SetOffset(channel, Offset); - Mixer_Channel_Volume(channel, DStoMixerVolume(Volume)); - Mixer_Channel_Pan(channel, DStoMixerPan(Pan)); - Mixer_Channel_Rate(channel, DStoMixerRate(Frequency)); + Source = source; } RideMusicChannel(const RideMusicChannel&) = delete; @@ -101,7 +102,7 @@ namespace OpenRCT2::RideAudio if (Channel != nullptr) { - Mixer_Stop_Channel(Channel); + Channel->Stop(); } Channel = src.Channel; src.Channel = nullptr; @@ -116,7 +117,7 @@ namespace OpenRCT2::RideAudio { if (Channel != nullptr) { - Mixer_Stop_Channel(Channel); + Channel->Stop(); Channel = nullptr; if (Source != nullptr) { @@ -130,7 +131,7 @@ namespace OpenRCT2::RideAudio { if (Channel != nullptr) { - return Mixer_Channel_IsPlaying(Channel); + return Channel->IsPlaying(); } return false; } @@ -139,7 +140,7 @@ namespace OpenRCT2::RideAudio { if (Channel != nullptr) { - return Mixer_Channel_GetOffset(Channel); + return Channel->GetOffset(); } return 0; } @@ -151,7 +152,7 @@ namespace OpenRCT2::RideAudio Volume = instance.Volume; if (Channel != nullptr) { - Mixer_Channel_Volume(Channel, DStoMixerVolume(Volume)); + Channel->SetVolume(DStoMixerVolume(Volume)); } } if (Pan != instance.Pan) @@ -159,7 +160,7 @@ namespace OpenRCT2::RideAudio Pan = instance.Pan; if (Channel != nullptr) { - Mixer_Channel_Pan(Channel, DStoMixerPan(Pan)); + Channel->SetPan(DStoMixerPan(Pan)); } } if (Frequency != instance.Frequency) @@ -167,7 +168,7 @@ namespace OpenRCT2::RideAudio Frequency = instance.Frequency; if (Channel != nullptr) { - Mixer_Channel_Rate(Channel, DStoMixerRate(Frequency)); + Channel->SetRate(DStoMixerRate(Frequency)); } } } @@ -201,11 +202,9 @@ namespace OpenRCT2::RideAudio auto source = audioObj->GetSample(0); if (source != nullptr) { - auto channel = Mixer_Play_Music(source, MIXER_LOOP_NONE, true); + auto channel = CreateAudioChannel(source, MixerGroup::Sound, false); if (channel != nullptr) { - // Move circus music to the sound mixer group - channel->SetGroup(Audio::MixerGroup::Sound); _musicChannels.emplace_back(instance, channel, nullptr); } } @@ -227,7 +226,7 @@ namespace OpenRCT2::RideAudio if (source != nullptr) { auto shouldLoop = musicObj->GetTrackCount() == 1; - auto channel = Mixer_Play_Music(source, shouldLoop ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, true); + auto channel = CreateAudioChannel(source, MixerGroup::RideMusic, shouldLoop); if (channel != nullptr) { _musicChannels.emplace_back(instance, channel, source); diff --git a/src/openrct2/ride/Vehicle.cpp b/src/openrct2/ride/Vehicle.cpp index fb4e3b8269..8b798b9752 100644 --- a/src/openrct2/ride/Vehicle.cpp +++ b/src/openrct2/ride/Vehicle.cpp @@ -14,6 +14,7 @@ #include "../Game.h" #include "../OpenRCT2.h" #include "../actions/RideSetStatusAction.h" +#include "../audio/AudioChannel.h" #include "../audio/AudioMixer.h" #include "../audio/audio.h" #include "../config/Config.h" @@ -53,6 +54,7 @@ #include #include +using namespace OpenRCT2::Audio; using namespace OpenRCT2::TrackMetaData; static bool vehicle_boat_is_location_accessible(const CoordsXYZ& location); @@ -1088,7 +1090,7 @@ static void UpdateSound( if (id != sound.Id && sound.Id != OpenRCT2::Audio::SoundId::Null) { sound.Id = OpenRCT2::Audio::SoundId::Null; - Mixer_Stop_Channel(sound.Channel); + sound.Channel->Stop(); } if (id == OpenRCT2::Audio::SoundId::Null) { @@ -1100,9 +1102,8 @@ static void UpdateSound( auto frequency = SoundFrequency(id, sound_params->frequency); auto looping = _soundParams[static_cast(id)][0]; auto pan = sound_params->pan_x; - auto channel = Mixer_Play_Effect( - id, looping ? MIXER_LOOP_INFINITE : MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), - DStoMixerRate(frequency), 0); + auto channel = CreateAudioChannel( + id, looping, DStoMixerVolume(volume), DStoMixerPan(pan), DStoMixerRate(frequency), false); if (channel != nullptr) { sound.Id = id; @@ -1120,12 +1121,12 @@ static void UpdateSound( if (volume != sound.Volume) { sound.Volume = volume; - Mixer_Channel_Volume(sound.Channel, DStoMixerVolume(volume)); + sound.Channel->SetVolume(DStoMixerVolume(volume)); } if (sound_params->pan_x != sound.Pan) { sound.Pan = sound_params->pan_x; - Mixer_Channel_Pan(sound.Channel, DStoMixerPan(sound_params->pan_x)); + sound.Channel->SetPan(DStoMixerPan(sound_params->pan_x)); } if (!(gCurrentTicks & 3) && sound_params->frequency != sound.Frequency) { @@ -1133,7 +1134,7 @@ static void UpdateSound( if (ShouldUpdateChannelRate(id)) { uint16_t frequency = SoundFrequency(id, sound_params->frequency); - Mixer_Channel_Rate(sound.Channel, DStoMixerRate(frequency)); + sound.Channel->SetRate(DStoMixerRate(frequency)); } } } @@ -1179,11 +1180,11 @@ void vehicle_sounds_update() if (vehicle_sound.TrackSound.Id != OpenRCT2::Audio::SoundId::Null) { - Mixer_Stop_Channel(vehicle_sound.TrackSound.Channel); + vehicle_sound.TrackSound.Channel->Stop(); } if (vehicle_sound.OtherSound.Id != OpenRCT2::Audio::SoundId::Null) { - Mixer_Stop_Channel(vehicle_sound.OtherSound.Channel); + vehicle_sound.OtherSound.Channel->Stop(); } vehicle_sound.id = OpenRCT2::Audio::SoundIdNull; } diff --git a/src/openrct2/ride/VehicleEntry.h b/src/openrct2/ride/VehicleEntry.h index d047acf555..3be5d5970c 100644 --- a/src/openrct2/ride/VehicleEntry.h +++ b/src/openrct2/ride/VehicleEntry.h @@ -9,16 +9,20 @@ #pragma once -#include "../audio/AudioMixer.h" -#include "../common.h" #include "../entity/Yaw.hpp" #include "../util/Util.h" #include "../world/Location.hpp" #include +#include #include #include +namespace OpenRCT2::Audio +{ + enum class SoundId : uint8_t; +} + enum : uint32_t { CAR_ENTRY_FLAG_POWERED_RIDE_UNRESTRICTED_GRAVITY = 1 diff --git a/src/openrct2/world/Climate.cpp b/src/openrct2/world/Climate.cpp index 9fd16ebed8..6df1660599 100644 --- a/src/openrct2/world/Climate.cpp +++ b/src/openrct2/world/Climate.cpp @@ -13,6 +13,7 @@ #include "../Context.h" #include "../Game.h" #include "../OpenRCT2.h" +#include "../audio/AudioChannel.h" #include "../audio/AudioMixer.h" #include "../audio/audio.h" #include "../config/Config.h" @@ -25,6 +26,8 @@ #include "../util/Util.h" #include "../windows/Intent.h" +using namespace OpenRCT2::Audio; + #include #include @@ -58,7 +61,7 @@ uint16_t gClimateLightningFlash; static int32_t _weatherVolume = 1; static uint32_t _lightningTimer; static uint32_t _thunderTimer; -static void* _thunderSoundChannels[MAX_THUNDER_INSTANCES]; +static std::shared_ptr _thunderSoundChannels[MAX_THUNDER_INSTANCES]; static THUNDER_STATUS _thunderStatus[MAX_THUNDER_INSTANCES] = { THUNDER_STATUS::NONE, THUNDER_STATUS::NONE, @@ -66,6 +69,7 @@ static THUNDER_STATUS _thunderStatus[MAX_THUNDER_INSTANCES] = { static OpenRCT2::Audio::SoundId _thunderSoundId; static int32_t _thunderVolume; static int32_t _thunderStereoEcho = 0; +static std::shared_ptr _weatherSoundChannel; static int8_t climate_step_weather_level(int8_t currentWeatherLevel, int8_t nextWeatherLevel); static void climate_determine_future_weather(int32_t randomDistribution); @@ -101,7 +105,7 @@ void climate_reset(ClimateType climate) _thunderTimer = 0; if (_weatherVolume != 1) { - OpenRCT2::Audio::StopWeatherSound(); + ClimateStopWeatherSound(); _weatherVolume = 1; } @@ -312,10 +316,9 @@ static void climate_update_weather_sound() if (gClimateCurrent.WeatherEffect == WeatherEffectType::Rain || gClimateCurrent.WeatherEffect == WeatherEffectType::Storm) { // Start playing the weather sound - if (OpenRCT2::Audio::gWeatherSoundChannel == nullptr) + if (_weatherSoundChannel == nullptr) { - OpenRCT2::Audio::gWeatherSoundChannel = Mixer_Play_Effect( - OpenRCT2::Audio::SoundId::Rain, MIXER_LOOP_INFINITE, DStoMixerVolume(-4000), 0.5f, 1, 0); + _weatherSoundChannel = CreateAudioChannel(SoundId::Rain, true, DStoMixerVolume(-4000)); } if (_weatherVolume == 1) { @@ -325,9 +328,9 @@ static void climate_update_weather_sound() { // Increase weather sound _weatherVolume = std::min(-1400, _weatherVolume + 80); - if (OpenRCT2::Audio::gWeatherSoundChannel != nullptr) + if (_weatherSoundChannel != nullptr) { - Mixer_Channel_Volume(OpenRCT2::Audio::gWeatherSoundChannel, DStoMixerVolume(_weatherVolume)); + _weatherSoundChannel->SetVolume(DStoMixerVolume(_weatherVolume)); } } } @@ -337,19 +340,28 @@ static void climate_update_weather_sound() _weatherVolume -= 80; if (_weatherVolume > -4000) { - if (OpenRCT2::Audio::gWeatherSoundChannel != nullptr) + if (_weatherSoundChannel != nullptr) { - Mixer_Channel_Volume(OpenRCT2::Audio::gWeatherSoundChannel, DStoMixerVolume(_weatherVolume)); + _weatherSoundChannel->SetVolume(DStoMixerVolume(_weatherVolume)); } } else { - OpenRCT2::Audio::StopWeatherSound(); + ClimateStopWeatherSound(); _weatherVolume = 1; } } } +void ClimateStopWeatherSound() +{ + if (_weatherSoundChannel != nullptr) + { + _weatherSoundChannel->Stop(); + _weatherSoundChannel = nullptr; + } +} + static void climate_update_thunder_sound() { if (_thunderStereoEcho) @@ -364,10 +376,10 @@ static void climate_update_thunder_sound() { if (_thunderStatus[i] != THUNDER_STATUS::NONE) { - void* channel = _thunderSoundChannels[i]; - if (!Mixer_Channel_IsPlaying(channel)) + auto& channel = _thunderSoundChannels[i]; + if (!channel->IsPlaying()) { - Mixer_Stop_Channel(channel); + channel->Stop(); _thunderStatus[i] = THUNDER_STATUS::NONE; } } @@ -428,8 +440,7 @@ static void climate_update_thunder() static void climate_play_thunder(int32_t instanceIndex, OpenRCT2::Audio::SoundId soundId, int32_t volume, int32_t pan) { - _thunderSoundChannels[instanceIndex] = Mixer_Play_Effect( - soundId, MIXER_LOOP_NONE, DStoMixerVolume(volume), DStoMixerPan(pan), 1, 0); + _thunderSoundChannels[instanceIndex] = CreateAudioChannel(soundId, false, DStoMixerVolume(volume), DStoMixerPan(pan)); if (_thunderSoundChannels[instanceIndex] != nullptr) { _thunderStatus[instanceIndex] = THUNDER_STATUS::PLAYING; diff --git a/src/openrct2/world/Climate.h b/src/openrct2/world/Climate.h index 35af4f6808..60abb0d452 100644 --- a/src/openrct2/world/Climate.h +++ b/src/openrct2/world/Climate.h @@ -80,6 +80,7 @@ int32_t climate_celsius_to_fahrenheit(int32_t celsius); void climate_reset(ClimateType climate); void climate_update(); void climate_update_sound(); +void ClimateStopWeatherSound(); void climate_force_weather(WeatherType weather); bool climate_is_raining();