Move ride audio into own namespace

This commit is contained in:
Ted John 2021-01-20 21:10:17 +00:00
parent 28f4ec2b43
commit a9755609c2
6 changed files with 367 additions and 361 deletions

View File

@ -1375,7 +1375,7 @@ static void window_options_audio_mouseup(rct_window* w, rct_widgetindex widgetIn
gConfigSound.ride_music_enabled = !gConfigSound.ride_music_enabled; gConfigSound.ride_music_enabled = !gConfigSound.ride_music_enabled;
if (!gConfigSound.ride_music_enabled) if (!gConfigSound.ride_music_enabled)
{ {
RideAudioStopAllChannels(); OpenRCT2::RideAudio::StopAllChannels();
} }
config_save_default(); config_save_default();
w->Invalidate(); w->Invalidate();

View File

@ -292,7 +292,7 @@ namespace OpenRCT2::Audio
{ {
StopTitleMusic(); StopTitleMusic();
StopVehicleSounds(); StopVehicleSounds();
RideAudioStopAllChannels(); RideAudio::StopAllChannels();
peep_stop_crowd_noise(); peep_stop_crowd_noise();
StopWeatherSound(); StopWeatherSound();
} }
@ -357,7 +357,7 @@ namespace OpenRCT2::Audio
{ {
peep_stop_crowd_noise(); peep_stop_crowd_noise();
StopTitleMusic(); StopTitleMusic();
RideAudioStopAllChannels(); RideAudio::StopAllChannels();
StopWeatherSound(); StopWeatherSound();
_currentAudioDevice = -1; _currentAudioDevice = -1;
} }
@ -382,7 +382,7 @@ namespace OpenRCT2::Audio
{ {
gGameSoundsOff = true; gGameSoundsOff = true;
StopVehicleSounds(); StopVehicleSounds();
RideAudioStopAllChannels(); RideAudio::StopAllChannels();
peep_stop_crowd_noise(); peep_stop_crowd_noise();
StopWeatherSound(); StopWeatherSound();
} }

View File

@ -1785,7 +1785,7 @@ void window_close_construction_windows()
*/ */
void window_update_viewport_ride_music() void window_update_viewport_ride_music()
{ {
RideAudioClearAllViewportInstances(); OpenRCT2::RideAudio::ClearAllViewportInstances();
g_music_tracking_viewport = nullptr; g_music_tracking_viewport = nullptr;
for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++) for (auto it = g_window_list.rbegin(); it != g_window_list.rend(); it++)

View File

@ -2038,7 +2038,7 @@ void Ride::UpdateAll()
for (auto& ride : GetRideManager()) for (auto& ride : GetRideManager())
ride.Update(); ride.Update();
RideUpdateMusicChannels(); OpenRCT2::RideAudio::UpdateMusicChannels();
} }
std::unique_ptr<TrackDesign> Ride::SaveToTrackDesign() const std::unique_ptr<TrackDesign> Ride::SaveToTrackDesign() const
@ -2923,7 +2923,7 @@ static void ride_music_update(Ride* ride)
sampleRate += 22050; sampleRate += 22050;
} }
RideUpdateMusicInstance(*ride, rideCoords, sampleRate); OpenRCT2::RideAudio::UpdateMusicInstance(*ride, rideCoords, sampleRate);
} }
#pragma endregion #pragma endregion

View File

@ -24,399 +24,404 @@
using namespace OpenRCT2; using namespace OpenRCT2;
using namespace OpenRCT2::Audio; using namespace OpenRCT2::Audio;
constexpr size_t MAX_RIDE_MUSIC_CHANNELS = 32; namespace OpenRCT2::RideAudio
/**
* 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
{ {
ride_id_t RideId; constexpr uint8_t TUNE_ID_NULL = 0xFF;
uint8_t TrackIndex{}; constexpr size_t MAX_RIDE_MUSIC_CHANNELS = 32;
size_t Offset{}; /**
int16_t Volume{}; * Represents a particular instance of ride music that can be heard in a viewport.
int16_t Pan{}; * These are created each frame via enumerating each ride / viewport.
uint16_t Frequency{}; */
}; struct ViewportRideMusicInstance
/**
* 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)
{ {
RideId = instance.RideId; ride_id_t RideId;
TrackIndex = instance.TrackIndex; uint8_t TrackIndex{};
Offset = std::max<size_t>(0, instance.Offset - 10000); size_t Offset{};
Volume = instance.Volume; int16_t Volume{};
Pan = instance.Pan; int16_t Pan{};
Frequency = instance.Frequency; uint16_t Frequency{};
};
Channel = channel; /**
* Represents an audio channel to play a particular ride's music track.
Mixer_Channel_SetOffset(channel, Offset); */
Mixer_Channel_Volume(channel, DStoMixerVolume(Volume)); struct RideMusicChannel
Mixer_Channel_Pan(channel, DStoMixerPan(Pan));
Mixer_Channel_Rate(channel, DStoMixerRate(Frequency));
}
RideMusicChannel(const RideMusicChannel&) = delete;
RideMusicChannel(RideMusicChannel&& src) noexcept
{ {
*this = std::move(src); ride_id_t RideId{};
} uint8_t TrackIndex{};
RideMusicChannel& operator=(RideMusicChannel&& src) noexcept size_t Offset{};
{ int16_t Volume{};
RideId = src.RideId; int16_t Pan{};
TrackIndex = src.TrackIndex; uint16_t Frequency{};
Offset = src.Offset; void* Channel{};
Volume = src.Volume;
Pan = src.Pan;
Frequency = src.Frequency;
if (Channel != nullptr) RideMusicChannel(const ViewportRideMusicInstance& instance, void* channel)
{ {
Mixer_Stop_Channel(Channel); RideId = instance.RideId;
} TrackIndex = instance.TrackIndex;
Channel = src.Channel;
src.Channel = nullptr;
return *this; Offset = std::max<size_t>(0, instance.Offset - 10000);
}
~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)
{
Volume = instance.Volume; Volume = instance.Volume;
if (Channel != nullptr)
{
Mixer_Channel_Volume(Channel, DStoMixerVolume(Volume));
}
}
if (Pan != instance.Pan)
{
Pan = instance.Pan; Pan = instance.Pan;
if (Channel != nullptr)
{
Mixer_Channel_Pan(Channel, DStoMixerPan(Pan));
}
}
if (Frequency != instance.Frequency)
{
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) if (Channel != nullptr)
{ {
Mixer_Channel_Rate(Channel, DStoMixerRate(Frequency)); Mixer_Stop_Channel(Channel);
} }
Channel = src.Channel;
src.Channel = nullptr;
return *this;
} }
}
};
static std::vector<ViewportRideMusicInstance> _musicInstances; ~RideMusicChannel()
static std::vector<RideMusicChannel> _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)
{ {
// Move circus music to the sound mixer group if (Channel != nullptr)
Mixer_Channel_SetGroup(channel, Audio::MixerGroup::Sound);
_musicChannels.emplace_back(instance, channel);
}
}
else
{
auto& objManager = GetContext()->GetObjectManager();
auto musicObj = static_cast<MusicObject*>(objManager.GetLoadedObject(ObjectType::Music, ride->music));
if (musicObj != nullptr)
{
auto track = musicObj->GetTrack(instance.TrackIndex);
if (track != nullptr)
{ {
auto stream = track->Asset.GetStream(); Mixer_Stop_Channel(Channel);
auto channel = Mixer_Play_Music(std::move(stream), MIXER_LOOP_NONE); Channel = nullptr;
if (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<ViewportRideMusicInstance> _musicInstances;
static std::vector<RideMusicChannel> _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<MusicObject*>(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() static void StopInactiveRideMusicChannels()
{ {
_musicChannels.erase( _musicChannels.erase(
std::remove_if( std::remove_if(
_musicChannels.begin(), _musicChannels.end(), _musicChannels.begin(), _musicChannels.end(),
[](const auto& channel) { [](const auto& channel) {
auto found = std::any_of(_musicInstances.begin(), _musicInstances.end(), [&channel](const auto& instance) { auto found = std::any_of(_musicInstances.begin(), _musicInstances.end(), [&channel](const auto& instance) {
return instance.RideId == channel.RideId && instance.TrackIndex == channel.TrackIndex; return instance.RideId == channel.RideId && instance.TrackIndex == channel.TrackIndex;
}); });
if (!found || !channel.IsPlaying()) if (!found || !channel.IsPlaying())
{ {
return true; return true;
} }
else else
{ {
return false; return false;
} }
}), }),
_musicChannels.end()); _musicChannels.end());
} }
static void UpdateRideMusicChannelForMusicParams(const ViewportRideMusicInstance& instance) static void UpdateRideMusicChannelForMusicParams(const ViewportRideMusicInstance& instance)
{ {
// Find existing music channel // Find existing music channel
auto foundChannel = std::find_if( auto foundChannel = std::find_if(
_musicChannels.begin(), _musicChannels.end(), [&instance](const RideMusicChannel& channel) { _musicChannels.begin(), _musicChannels.end(), [&instance](const RideMusicChannel& channel) {
return channel.RideId == instance.RideId && channel.TrackIndex == instance.TrackIndex; 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<size_t, size_t> RideMusicGetTrackOffsetLength(const Ride& ride)
{
if (ride.type == RIDE_TYPE_CIRCUS)
{
return { 1378, 12427456 };
}
else
{
auto& objManager = GetContext()->GetObjectManager();
auto musicObj = static_cast<MusicObject*>(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<uint32_t>(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()) auto [trackOffset, trackLength] = RideMusicGetTrackOffsetLength(ride);
{ 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<size_t, size_t> RideMusicGetTrackOffsetLength(const Ride& ride)
{
if (ride.type == RIDE_TYPE_CIRCUS)
{
return { 1378, 12427456 };
}
else
{
auto& objManager = GetContext()->GetObjectManager();
auto musicObj = static_cast<MusicObject*>(objManager.GetLoadedObject(ObjectType::Music, ride.music));
if (musicObj != nullptr)
{ {
auto numTracks = musicObj->GetTrackCount(); if (foundChannel->IsPlaying())
if (ride.music_tune_id < numTracks)
{ {
auto track = musicObj->GetTrack(ride.music_tune_id); // Since we have a real music channel, use the offset from that
return { track->BytesPerTick, track->Size }; 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;
} }
} }
} else
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(); // We do not have a real music channel, so simulate the playing of the music track
instance.RideId = ride.id; auto newOffset = ride.music_position + trackOffset;
instance.TrackIndex = ride.music_tune_id;
instance.Offset = offset;
instance.Volume = volume;
instance.Pan = pan;
instance.Frequency = sampleRate;
}
ride.music_position = static_cast<uint32_t>(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();
RideUpdateMusicPosition(ride, newOffset, trackLength, volume, pan, sampleRate); 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 v = -((v / 4) - 1024) / 4;
ride.music_position = 0; result = static_cast<uint8_t>(std::clamp(v, 0, 255));
ride.music_tune_id = TUNE_ID_NULL;
} }
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) /**
{ * Register an instance of audible ride music for this frame at the given coordinates.
uint8_t result = 255; */
int32_t v = std::min(std::abs(pan), 6143) - 2048; void UpdateMusicInstance(Ride& ride, const CoordsXYZ& rideCoords, uint16_t sampleRate)
if (v > 0)
{ {
v = -((v / 4) - 1024) / 4; if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gGameSoundsOff && g_music_tracking_viewport != nullptr)
result = static_cast<uint8_t>(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)
{ {
RideUpdateMusicPosition(ride); auto rotatedCoords = translate_3d_to_2d_with_z(get_current_rotation(), rideCoords);
} auto viewport = g_music_tracking_viewport;
else auto viewWidth = viewport->view_width;
{ auto viewWidth2 = viewWidth * 2;
auto x2 = (viewport->pos.x + ((rotatedCoords.x - viewport->viewPos.x) / viewport->zoom)) * 0x10000; auto viewX = viewport->viewPos.x - viewWidth2;
auto screenWidth = std::max(context_get_width(), 64); auto viewY = viewport->viewPos.y - viewWidth;
auto panX = ((x2 / screenWidth) - 0x8000) >> 4; auto viewX2 = viewWidth2 + viewWidth2 + viewport->view_width + viewX;
auto viewY2 = viewWidth + viewWidth + viewport->view_height + viewY;
auto y2 = (viewport->pos.y + ((rotatedCoords.y - viewport->viewPos.y) / viewport->zoom)) * 0x10000; if (viewX >= rotatedCoords.x || viewY >= rotatedCoords.y || viewX2 < rotatedCoords.x || viewY2 < rotatedCoords.y)
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<uint8_t>(-volXY - 1) * static_cast<uint8_t>(-volXY - 1)) / 16) - 700;
if (volXY != 0 && newVolume >= -4000)
{
auto newPan = std::clamp(panX, -10000, 10000);
RideUpdateMusicPosition(ride, newVolume, newPan, sampleRate);
}
else
{ {
RideUpdateMusicPosition(ride); 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<uint8_t>(-volXY - 1) * static_cast<uint8_t>(-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

View File

@ -14,9 +14,10 @@
struct CoordsXYZ; struct CoordsXYZ;
struct Ride; struct Ride;
constexpr uint8_t TUNE_ID_NULL = 0xFF; namespace OpenRCT2::RideAudio
{
void RideAudioClearAllViewportInstances(); void ClearAllViewportInstances();
void RideAudioStopAllChannels(); void StopAllChannels();
void RideUpdateMusicChannels(); void UpdateMusicChannels();
void RideUpdateMusicInstance(Ride& ride, const CoordsXYZ& rideCoords, uint16_t sampleRate); void UpdateMusicInstance(Ride& ride, const CoordsXYZ& rideCoords, uint16_t sampleRate);
} // namespace OpenRCT2::RideAudio