diff --git a/src/openrct2-ui/windows/Options.cpp b/src/openrct2-ui/windows/Options.cpp index b4edb0b41e..9314de143b 100644 --- a/src/openrct2-ui/windows/Options.cpp +++ b/src/openrct2-ui/windows/Options.cpp @@ -1375,7 +1375,7 @@ static void window_options_audio_mouseup(rct_window* w, rct_widgetindex widgetIn gConfigSound.ride_music_enabled = !gConfigSound.ride_music_enabled; if (!gConfigSound.ride_music_enabled) { - RideAudioStopAllChannels(); + OpenRCT2::RideAudio::StopAllChannels(); } config_save_default(); w->Invalidate(); diff --git a/src/openrct2/audio/Audio.cpp b/src/openrct2/audio/Audio.cpp index 4294a4577e..3869dee744 100644 --- a/src/openrct2/audio/Audio.cpp +++ b/src/openrct2/audio/Audio.cpp @@ -292,7 +292,7 @@ namespace OpenRCT2::Audio { StopTitleMusic(); StopVehicleSounds(); - RideAudioStopAllChannels(); + RideAudio::StopAllChannels(); peep_stop_crowd_noise(); StopWeatherSound(); } @@ -357,7 +357,7 @@ namespace OpenRCT2::Audio { peep_stop_crowd_noise(); StopTitleMusic(); - RideAudioStopAllChannels(); + RideAudio::StopAllChannels(); StopWeatherSound(); _currentAudioDevice = -1; } @@ -382,7 +382,7 @@ namespace OpenRCT2::Audio { gGameSoundsOff = true; StopVehicleSounds(); - RideAudioStopAllChannels(); + RideAudio::StopAllChannels(); peep_stop_crowd_noise(); StopWeatherSound(); } diff --git a/src/openrct2/interface/Window.cpp b/src/openrct2/interface/Window.cpp index c05a43343a..572eef55c4 100644 --- a/src/openrct2/interface/Window.cpp +++ b/src/openrct2/interface/Window.cpp @@ -1785,7 +1785,7 @@ void window_close_construction_windows() */ void window_update_viewport_ride_music() { - RideAudioClearAllViewportInstances(); + OpenRCT2::RideAudio::ClearAllViewportInstances(); g_music_tracking_viewport = nullptr; for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++) diff --git a/src/openrct2/ride/Ride.cpp b/src/openrct2/ride/Ride.cpp index ac26bb3e2d..5ec4b111e5 100644 --- a/src/openrct2/ride/Ride.cpp +++ b/src/openrct2/ride/Ride.cpp @@ -2038,7 +2038,7 @@ void Ride::UpdateAll() for (auto& ride : GetRideManager()) ride.Update(); - RideUpdateMusicChannels(); + OpenRCT2::RideAudio::UpdateMusicChannels(); } std::unique_ptr Ride::SaveToTrackDesign() const @@ -2923,7 +2923,7 @@ static void ride_music_update(Ride* ride) sampleRate += 22050; } - RideUpdateMusicInstance(*ride, rideCoords, sampleRate); + OpenRCT2::RideAudio::UpdateMusicInstance(*ride, rideCoords, sampleRate); } #pragma endregion diff --git a/src/openrct2/ride/RideAudio.cpp b/src/openrct2/ride/RideAudio.cpp index a12440e266..c87e34fc95 100644 --- a/src/openrct2/ride/RideAudio.cpp +++ b/src/openrct2/ride/RideAudio.cpp @@ -24,399 +24,404 @@ using namespace OpenRCT2; using namespace OpenRCT2::Audio; -constexpr size_t MAX_RIDE_MUSIC_CHANNELS = 32; - -/** - * Represents a particular instance of ride music that can be heard in a viewport. - * These are created each frame via enumerating each ride / viewport. - */ -struct ViewportRideMusicInstance +namespace OpenRCT2::RideAudio { - ride_id_t RideId; - uint8_t TrackIndex{}; + constexpr uint8_t TUNE_ID_NULL = 0xFF; + constexpr size_t MAX_RIDE_MUSIC_CHANNELS = 32; - size_t Offset{}; - int16_t Volume{}; - int16_t Pan{}; - uint16_t Frequency{}; -}; - -/** - * Represents an audio channel to play a particular ride's music track. - */ -struct RideMusicChannel -{ - ride_id_t RideId{}; - uint8_t TrackIndex{}; - - size_t Offset{}; - int16_t Volume{}; - int16_t Pan{}; - uint16_t Frequency{}; - - void* Channel{}; - - RideMusicChannel(const ViewportRideMusicInstance& instance, void* channel) + /** + * Represents a particular instance of ride music that can be heard in a viewport. + * These are created each frame via enumerating each ride / viewport. + */ + struct ViewportRideMusicInstance { - RideId = instance.RideId; - TrackIndex = instance.TrackIndex; + ride_id_t RideId; + uint8_t TrackIndex{}; - Offset = std::max(0, instance.Offset - 10000); - Volume = instance.Volume; - Pan = instance.Pan; - Frequency = instance.Frequency; + size_t Offset{}; + int16_t Volume{}; + int16_t Pan{}; + uint16_t Frequency{}; + }; - Channel = channel; - - Mixer_Channel_SetOffset(channel, Offset); - Mixer_Channel_Volume(channel, DStoMixerVolume(Volume)); - Mixer_Channel_Pan(channel, DStoMixerPan(Pan)); - Mixer_Channel_Rate(channel, DStoMixerRate(Frequency)); - } - - RideMusicChannel(const RideMusicChannel&) = delete; - - RideMusicChannel(RideMusicChannel&& src) noexcept + /** + * Represents an audio channel to play a particular ride's music track. + */ + struct RideMusicChannel { - *this = std::move(src); - } + ride_id_t RideId{}; + uint8_t TrackIndex{}; - RideMusicChannel& operator=(RideMusicChannel&& src) noexcept - { - RideId = src.RideId; - TrackIndex = src.TrackIndex; + size_t Offset{}; + int16_t Volume{}; + int16_t Pan{}; + uint16_t Frequency{}; - Offset = src.Offset; - Volume = src.Volume; - Pan = src.Pan; - Frequency = src.Frequency; + void* Channel{}; - if (Channel != nullptr) + RideMusicChannel(const ViewportRideMusicInstance& instance, void* channel) { - Mixer_Stop_Channel(Channel); - } - Channel = src.Channel; - src.Channel = nullptr; + RideId = instance.RideId; + TrackIndex = instance.TrackIndex; - return *this; - } - - ~RideMusicChannel() - { - if (Channel != nullptr) - { - Mixer_Stop_Channel(Channel); - Channel = nullptr; - } - } - - bool IsPlaying() const - { - if (Channel != nullptr) - { - return Mixer_Channel_IsPlaying(Channel); - } - return false; - } - - size_t GetOffset() const - { - if (Channel != nullptr) - { - return Mixer_Channel_GetOffset(Channel); - } - return 0; - } - - void Update(const ViewportRideMusicInstance& instance) - { - if (Volume != instance.Volume) - { + Offset = std::max(0, instance.Offset - 10000); Volume = instance.Volume; - if (Channel != nullptr) - { - Mixer_Channel_Volume(Channel, DStoMixerVolume(Volume)); - } - } - if (Pan != instance.Pan) - { Pan = instance.Pan; - if (Channel != nullptr) - { - Mixer_Channel_Pan(Channel, DStoMixerPan(Pan)); - } - } - if (Frequency != instance.Frequency) - { Frequency = instance.Frequency; + + Channel = channel; + + Mixer_Channel_SetOffset(channel, Offset); + Mixer_Channel_Volume(channel, DStoMixerVolume(Volume)); + Mixer_Channel_Pan(channel, DStoMixerPan(Pan)); + Mixer_Channel_Rate(channel, DStoMixerRate(Frequency)); + } + + RideMusicChannel(const RideMusicChannel&) = delete; + + RideMusicChannel(RideMusicChannel&& src) noexcept + { + *this = std::move(src); + } + + RideMusicChannel& operator=(RideMusicChannel&& src) noexcept + { + RideId = src.RideId; + TrackIndex = src.TrackIndex; + + Offset = src.Offset; + Volume = src.Volume; + Pan = src.Pan; + Frequency = src.Frequency; + if (Channel != nullptr) { - Mixer_Channel_Rate(Channel, DStoMixerRate(Frequency)); + Mixer_Stop_Channel(Channel); } + Channel = src.Channel; + src.Channel = nullptr; + + return *this; } - } -}; -static std::vector _musicInstances; -static std::vector _musicChannels; - -void RideAudioStopAllChannels() -{ - _musicChannels.clear(); -} - -void RideAudioClearAllViewportInstances() -{ - _musicInstances.clear(); -} - -static void StartRideMusicChannel(const ViewportRideMusicInstance& instance) -{ - // Create new music channel - auto ride = get_ride(instance.RideId); - if (ride->type == RIDE_TYPE_CIRCUS) - { - auto channel = Mixer_Play_Music(PATH_ID_CSS24, MIXER_LOOP_NONE, true); - if (channel != nullptr) + ~RideMusicChannel() { - // Move circus music to the sound mixer group - Mixer_Channel_SetGroup(channel, Audio::MixerGroup::Sound); - - _musicChannels.emplace_back(instance, channel); - } - } - else - { - auto& objManager = GetContext()->GetObjectManager(); - auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, ride->music)); - if (musicObj != nullptr) - { - auto track = musicObj->GetTrack(instance.TrackIndex); - if (track != nullptr) + if (Channel != nullptr) { - auto stream = track->Asset.GetStream(); - auto channel = Mixer_Play_Music(std::move(stream), MIXER_LOOP_NONE); - if (channel != nullptr) + Mixer_Stop_Channel(Channel); + Channel = nullptr; + } + } + + bool IsPlaying() const + { + if (Channel != nullptr) + { + return Mixer_Channel_IsPlaying(Channel); + } + return false; + } + + size_t GetOffset() const + { + if (Channel != nullptr) + { + return Mixer_Channel_GetOffset(Channel); + } + return 0; + } + + void Update(const ViewportRideMusicInstance& instance) + { + if (Volume != instance.Volume) + { + Volume = instance.Volume; + if (Channel != nullptr) { - _musicChannels.emplace_back(instance, channel); + Mixer_Channel_Volume(Channel, DStoMixerVolume(Volume)); + } + } + if (Pan != instance.Pan) + { + Pan = instance.Pan; + if (Channel != nullptr) + { + Mixer_Channel_Pan(Channel, DStoMixerPan(Pan)); + } + } + if (Frequency != instance.Frequency) + { + Frequency = instance.Frequency; + if (Channel != nullptr) + { + Mixer_Channel_Rate(Channel, DStoMixerRate(Frequency)); + } + } + } + }; + + static std::vector _musicInstances; + static std::vector _musicChannels; + + void StopAllChannels() + { + _musicChannels.clear(); + } + + void ClearAllViewportInstances() + { + _musicInstances.clear(); + } + + static void StartRideMusicChannel(const ViewportRideMusicInstance& instance) + { + // Create new music channel + auto ride = get_ride(instance.RideId); + if (ride->type == RIDE_TYPE_CIRCUS) + { + auto channel = Mixer_Play_Music(PATH_ID_CSS24, MIXER_LOOP_NONE, true); + if (channel != nullptr) + { + // Move circus music to the sound mixer group + Mixer_Channel_SetGroup(channel, Audio::MixerGroup::Sound); + + _musicChannels.emplace_back(instance, channel); + } + } + else + { + auto& objManager = GetContext()->GetObjectManager(); + auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, ride->music)); + if (musicObj != nullptr) + { + auto track = musicObj->GetTrack(instance.TrackIndex); + if (track != nullptr) + { + auto stream = track->Asset.GetStream(); + auto channel = Mixer_Play_Music(std::move(stream), MIXER_LOOP_NONE); + if (channel != nullptr) + { + _musicChannels.emplace_back(instance, channel); + } } } } } -} -static void StopInactiveRideMusicChannels() -{ - _musicChannels.erase( - std::remove_if( - _musicChannels.begin(), _musicChannels.end(), - [](const auto& channel) { - auto found = std::any_of(_musicInstances.begin(), _musicInstances.end(), [&channel](const auto& instance) { - return instance.RideId == channel.RideId && instance.TrackIndex == channel.TrackIndex; - }); - if (!found || !channel.IsPlaying()) - { - return true; - } - else - { - return false; - } - }), - _musicChannels.end()); -} + static void StopInactiveRideMusicChannels() + { + _musicChannels.erase( + std::remove_if( + _musicChannels.begin(), _musicChannels.end(), + [](const auto& channel) { + auto found = std::any_of(_musicInstances.begin(), _musicInstances.end(), [&channel](const auto& instance) { + return instance.RideId == channel.RideId && instance.TrackIndex == channel.TrackIndex; + }); + if (!found || !channel.IsPlaying()) + { + return true; + } + else + { + return false; + } + }), + _musicChannels.end()); + } -static void UpdateRideMusicChannelForMusicParams(const ViewportRideMusicInstance& instance) -{ - // Find existing music channel - auto foundChannel = std::find_if( - _musicChannels.begin(), _musicChannels.end(), [&instance](const RideMusicChannel& channel) { - return channel.RideId == instance.RideId && channel.TrackIndex == instance.TrackIndex; + static void UpdateRideMusicChannelForMusicParams(const ViewportRideMusicInstance& instance) + { + // Find existing music channel + auto foundChannel = std::find_if( + _musicChannels.begin(), _musicChannels.end(), [&instance](const RideMusicChannel& channel) { + return channel.RideId == instance.RideId && channel.TrackIndex == instance.TrackIndex; + }); + + if (foundChannel != _musicChannels.end()) + { + foundChannel->Update(instance); + } + else if (_musicChannels.size() < MAX_RIDE_MUSIC_CHANNELS) + { + StartRideMusicChannel(instance); + } + } + + /** + * Start, update and stop audio channels for each ride music instance that can be heard across all viewports. + */ + void UpdateMusicChannels() + { + if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) != 0) + return; + + // TODO Allow circus music (CSS24) to play if ride music is disabled (that should be sound) + if (gGameSoundsOff || !gConfigSound.ride_music_enabled) + return; + + StopInactiveRideMusicChannels(); + for (const auto& instance : _musicInstances) + { + UpdateRideMusicChannelForMusicParams(instance); + } + } + + static std::pair RideMusicGetTrackOffsetLength(const Ride& ride) + { + if (ride.type == RIDE_TYPE_CIRCUS) + { + return { 1378, 12427456 }; + } + else + { + auto& objManager = GetContext()->GetObjectManager(); + auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, ride.music)); + if (musicObj != nullptr) + { + auto numTracks = musicObj->GetTrackCount(); + if (ride.music_tune_id < numTracks) + { + auto track = musicObj->GetTrack(ride.music_tune_id); + return { track->BytesPerTick, track->Size }; + } + } + } + return { 0, 0 }; + } + + static void RideUpdateMusicPosition(Ride& ride) + { + auto [trackOffset, trackLength] = RideMusicGetTrackOffsetLength(ride); + auto position = ride.music_position + trackOffset; + if (position < trackLength) + { + ride.music_position = position; + } + else + { + ride.music_tune_id = TUNE_ID_NULL; + ride.music_position = 0; + } + } + + static void RideUpdateMusicPosition( + Ride& ride, size_t offset, size_t length, int16_t volume, int16_t pan, uint16_t sampleRate) + { + if (offset < length) + { + if (_musicInstances.size() < MAX_RIDE_MUSIC_CHANNELS) + { + auto& instance = _musicInstances.emplace_back(); + instance.RideId = ride.id; + instance.TrackIndex = ride.music_tune_id; + instance.Offset = offset; + instance.Volume = volume; + instance.Pan = pan; + instance.Frequency = sampleRate; + } + ride.music_position = static_cast(offset); + } + else + { + ride.music_tune_id = TUNE_ID_NULL; + ride.music_position = 0; + } + } + + static void RideUpdateMusicPosition(Ride& ride, int16_t volume, int16_t pan, uint16_t sampleRate) + { + auto foundChannel = std::find_if(_musicChannels.begin(), _musicChannels.end(), [&ride](const auto& channel) { + return channel.RideId == ride.id && channel.TrackIndex == ride.music_tune_id; }); - if (foundChannel != _musicChannels.end()) - { - foundChannel->Update(instance); - } - else if (_musicChannels.size() < MAX_RIDE_MUSIC_CHANNELS) - { - StartRideMusicChannel(instance); - } -} - -/** - * Start, update and stop audio channels for each ride music instance that can be heard across all viewports. - */ -void RideUpdateMusicChannels() -{ - if ((gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) != 0 || (gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) != 0) - return; - - // TODO Allow circus music (CSS24) to play if ride music is disabled (that should be sound) - if (gGameSoundsOff || !gConfigSound.ride_music_enabled) - return; - - StopInactiveRideMusicChannels(); - for (const auto& instance : _musicInstances) - { - UpdateRideMusicChannelForMusicParams(instance); - } -} - -static std::pair RideMusicGetTrackOffsetLength(const Ride& ride) -{ - if (ride.type == RIDE_TYPE_CIRCUS) - { - return { 1378, 12427456 }; - } - else - { - auto& objManager = GetContext()->GetObjectManager(); - auto musicObj = static_cast(objManager.GetLoadedObject(ObjectType::Music, ride.music)); - if (musicObj != nullptr) + auto [trackOffset, trackLength] = RideMusicGetTrackOffsetLength(ride); + if (foundChannel != _musicChannels.end()) { - auto numTracks = musicObj->GetTrackCount(); - if (ride.music_tune_id < numTracks) + if (foundChannel->IsPlaying()) { - auto track = musicObj->GetTrack(ride.music_tune_id); - return { track->BytesPerTick, track->Size }; + // Since we have a real music channel, use the offset from that + auto newOffset = foundChannel->GetOffset(); + RideUpdateMusicPosition(ride, newOffset, trackLength, volume, pan, sampleRate); + } + else + { + // We had a real music channel, but it isn't playing anymore, so stop the track + ride.music_position = 0; + ride.music_tune_id = TUNE_ID_NULL; } } - } - return { 0, 0 }; -} - -static void RideUpdateMusicPosition(Ride& ride) -{ - auto [trackOffset, trackLength] = RideMusicGetTrackOffsetLength(ride); - auto position = ride.music_position + trackOffset; - if (position < trackLength) - { - ride.music_position = position; - } - else - { - ride.music_tune_id = TUNE_ID_NULL; - ride.music_position = 0; - } -} - -static void RideUpdateMusicPosition(Ride& ride, size_t offset, size_t length, int16_t volume, int16_t pan, uint16_t sampleRate) -{ - if (offset < length) - { - if (_musicInstances.size() < MAX_RIDE_MUSIC_CHANNELS) + else { - auto& instance = _musicInstances.emplace_back(); - instance.RideId = ride.id; - instance.TrackIndex = ride.music_tune_id; - instance.Offset = offset; - instance.Volume = volume; - instance.Pan = pan; - instance.Frequency = sampleRate; - } - ride.music_position = static_cast(offset); - } - else - { - ride.music_tune_id = TUNE_ID_NULL; - ride.music_position = 0; - } -} - -static void RideUpdateMusicPosition(Ride& ride, int16_t volume, int16_t pan, uint16_t sampleRate) -{ - auto foundChannel = std::find_if(_musicChannels.begin(), _musicChannels.end(), [&ride](const auto& channel) { - return channel.RideId == ride.id && channel.TrackIndex == ride.music_tune_id; - }); - - auto [trackOffset, trackLength] = RideMusicGetTrackOffsetLength(ride); - if (foundChannel != _musicChannels.end()) - { - if (foundChannel->IsPlaying()) - { - // Since we have a real music channel, use the offset from that - auto newOffset = foundChannel->GetOffset(); + // We do not have a real music channel, so simulate the playing of the music track + auto newOffset = ride.music_position + trackOffset; RideUpdateMusicPosition(ride, newOffset, trackLength, volume, pan, sampleRate); } - else + } + + static uint8_t CalculateVolume(int32_t pan) + { + uint8_t result = 255; + int32_t v = std::min(std::abs(pan), 6143) - 2048; + if (v > 0) { - // We had a real music channel, but it isn't playing anymore, so stop the track - ride.music_position = 0; - ride.music_tune_id = TUNE_ID_NULL; + v = -((v / 4) - 1024) / 4; + result = static_cast(std::clamp(v, 0, 255)); } + return result; } - else - { - // We do not have a real music channel, so simulate the playing of the music track - auto newOffset = ride.music_position + trackOffset; - RideUpdateMusicPosition(ride, newOffset, trackLength, volume, pan, sampleRate); - } -} -static uint8_t CalculateVolume(int32_t pan) -{ - uint8_t result = 255; - int32_t v = std::min(std::abs(pan), 6143) - 2048; - if (v > 0) + /** + * Register an instance of audible ride music for this frame at the given coordinates. + */ + void UpdateMusicInstance(Ride& ride, const CoordsXYZ& rideCoords, uint16_t sampleRate) { - v = -((v / 4) - 1024) / 4; - result = static_cast(std::clamp(v, 0, 255)); - } - return result; -} - -/** - * Register an instance of audible ride music for this frame at the given coordinates. - */ -void RideUpdateMusicInstance(Ride& ride, const CoordsXYZ& rideCoords, uint16_t sampleRate) -{ - if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gGameSoundsOff && g_music_tracking_viewport != nullptr) - { - auto rotatedCoords = translate_3d_to_2d_with_z(get_current_rotation(), rideCoords); - auto viewport = g_music_tracking_viewport; - auto viewWidth = viewport->view_width; - auto viewWidth2 = viewWidth * 2; - auto viewX = viewport->viewPos.x - viewWidth2; - auto viewY = viewport->viewPos.y - viewWidth; - auto viewX2 = viewWidth2 + viewWidth2 + viewport->view_width + viewX; - auto viewY2 = viewWidth + viewWidth + viewport->view_height + viewY; - if (viewX >= rotatedCoords.x || viewY >= rotatedCoords.y || viewX2 < rotatedCoords.x || viewY2 < rotatedCoords.y) + if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gGameSoundsOff && g_music_tracking_viewport != nullptr) { - RideUpdateMusicPosition(ride); - } - else - { - auto x2 = (viewport->pos.x + ((rotatedCoords.x - viewport->viewPos.x) / viewport->zoom)) * 0x10000; - auto screenWidth = std::max(context_get_width(), 64); - auto panX = ((x2 / screenWidth) - 0x8000) >> 4; - - auto y2 = (viewport->pos.y + ((rotatedCoords.y - viewport->viewPos.y) / viewport->zoom)) * 0x10000; - auto screenHeight = std::max(context_get_height(), 64); - auto panY = ((y2 / screenHeight) - 0x8000) >> 4; - - auto volX = CalculateVolume(panX); - auto volY = CalculateVolume(panY); - auto volXY = std::min(volX, volY); - if (volXY < gVolumeAdjustZoom * 3) - { - volXY = 0; - } - else - { - volXY = volXY - (gVolumeAdjustZoom * 3); - } - - int16_t newVolume = -((static_cast(-volXY - 1) * static_cast(-volXY - 1)) / 16) - 700; - if (volXY != 0 && newVolume >= -4000) - { - auto newPan = std::clamp(panX, -10000, 10000); - RideUpdateMusicPosition(ride, newVolume, newPan, sampleRate); - } - else + auto rotatedCoords = translate_3d_to_2d_with_z(get_current_rotation(), rideCoords); + auto viewport = g_music_tracking_viewport; + auto viewWidth = viewport->view_width; + auto viewWidth2 = viewWidth * 2; + auto viewX = viewport->viewPos.x - viewWidth2; + auto viewY = viewport->viewPos.y - viewWidth; + auto viewX2 = viewWidth2 + viewWidth2 + viewport->view_width + viewX; + auto viewY2 = viewWidth + viewWidth + viewport->view_height + viewY; + if (viewX >= rotatedCoords.x || viewY >= rotatedCoords.y || viewX2 < rotatedCoords.x || viewY2 < rotatedCoords.y) { RideUpdateMusicPosition(ride); } + else + { + auto x2 = (viewport->pos.x + ((rotatedCoords.x - viewport->viewPos.x) / viewport->zoom)) * 0x10000; + auto screenWidth = std::max(context_get_width(), 64); + auto panX = ((x2 / screenWidth) - 0x8000) >> 4; + + auto y2 = (viewport->pos.y + ((rotatedCoords.y - viewport->viewPos.y) / viewport->zoom)) * 0x10000; + auto screenHeight = std::max(context_get_height(), 64); + auto panY = ((y2 / screenHeight) - 0x8000) >> 4; + + auto volX = CalculateVolume(panX); + auto volY = CalculateVolume(panY); + auto volXY = std::min(volX, volY); + if (volXY < gVolumeAdjustZoom * 3) + { + volXY = 0; + } + else + { + volXY = volXY - (gVolumeAdjustZoom * 3); + } + + int16_t newVolume = -((static_cast(-volXY - 1) * static_cast(-volXY - 1)) / 16) - 700; + if (volXY != 0 && newVolume >= -4000) + { + auto newPan = std::clamp(panX, -10000, 10000); + RideUpdateMusicPosition(ride, newVolume, newPan, sampleRate); + } + else + { + RideUpdateMusicPosition(ride); + } + } } } -} +} // namespace OpenRCT2::RideAudio diff --git a/src/openrct2/ride/RideAudio.h b/src/openrct2/ride/RideAudio.h index 61f1e1a681..c91de90e9c 100644 --- a/src/openrct2/ride/RideAudio.h +++ b/src/openrct2/ride/RideAudio.h @@ -14,9 +14,10 @@ struct CoordsXYZ; struct Ride; -constexpr uint8_t TUNE_ID_NULL = 0xFF; - -void RideAudioClearAllViewportInstances(); -void RideAudioStopAllChannels(); -void RideUpdateMusicChannels(); -void RideUpdateMusicInstance(Ride& ride, const CoordsXYZ& rideCoords, uint16_t sampleRate); +namespace OpenRCT2::RideAudio +{ + void ClearAllViewportInstances(); + void StopAllChannels(); + void UpdateMusicChannels(); + void UpdateMusicInstance(Ride& ride, const CoordsXYZ& rideCoords, uint16_t sampleRate); +} // namespace OpenRCT2::RideAudio