Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit 862eb55

Browse files
committed
Fixed sound panning and changed rolloff model to standard inverse again
Changed methods and members around in AudioMan to support this, and changed audioman player management stuff. Cleaned up cruft accordingly Made SceneMan GetScrollTarget return a constant vector reference so audioman can hang onto it instead of recopying each player's scroll target vector every frame Missed a couple spots in AudioMan.h and ContentFile.h that should have been in the previous commit
1 parent 16fae2f commit 862eb55

File tree

5 files changed

+107
-103
lines changed

5 files changed

+107
-103
lines changed

Entities/SoundContainer.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -350,22 +350,12 @@ namespace RTE {
350350
soundMode |= FMOD_3D_HEADRELATIVE;
351351
m_AttenuationStartDistance = c_SoundMaxAudibleDistance;
352352
} else {
353-
soundMode |= FMOD_3D_CUSTOMROLLOFF;
353+
soundMode |= FMOD_3D_INVERSEROLLOFF;
354354
}
355355

356356
result = (result == FMOD_OK) ? soundData.SoundObject->setMode(soundMode) : result;
357357
result = (result == FMOD_OK) ? soundData.SoundObject->setLoopCount(m_Loops) : result;
358-
if (m_Immobile) {
359-
result = (result == FMOD_OK) ? soundData.SoundObject->set3DMinMaxDistance(std::max(0.0F, m_AttenuationStartDistance), c_SoundMaxAudibleDistance) : result;
360-
} else {
361-
//FMOD_VECTOR customRolloffPoints[10];
362-
//CalculateCustomRolloffPoints(soundData, customRolloffPoints, 10);
363-
364-
//TODO Consider replacing this with normal min and max distance (but keep custom rolloff mode) so we can save some pointing issues. Might need to store min audible distance in audioman if fmod is strict about min and max distance sizes wrt each other.
365-
soundData.CustomRolloffPoints[0] = FMOD_VECTOR{soundData.MinimumAudibleDistance, 0, 0};
366-
soundData.CustomRolloffPoints[1] = FMOD_VECTOR{(soundData.AttenuationStartDistance < 0) ? m_AttenuationStartDistance : soundData.AttenuationStartDistance, 1, 0};
367-
result = (result == FMOD_OK) ? soundData.SoundObject->set3DCustomRolloff(soundData.CustomRolloffPoints, 2) : result;
368-
}
358+
result = (result == FMOD_OK) ? soundData.SoundObject->set3DMinMaxDistance(soundData.MinimumAudibleDistance + std::max(0.0F, m_AttenuationStartDistance), c_SoundMaxAudibleDistance) : result;
369359
}
370360
}
371361
m_SoundPropertiesUpToDate = result == FMOD_OK;

Managers/AudioMan.cpp

Lines changed: 94 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ namespace RTE {
1414

1515
void AudioMan::Clear() {
1616
m_AudioEnabled = false;
17+
m_CurrentActivityHumanPlayerPositions.clear();
18+
m_SoundChannelMinimumAudibleDistances.clear();
1719

18-
m_SoundChannelRolloffs.clear();
1920
m_MusicVolume = 1.0;
2021
m_SoundsVolume = 1.0;
2122
m_GlobalPitch = 1.0;
@@ -93,27 +94,33 @@ namespace RTE {
9394

9495
if (g_ActivityMan.ActivityRunning()) {
9596
const Activity *currentActivity = g_ActivityMan.GetActivity();
97+
int currentActivityHumanCount = m_IsInMultiplayerMode ? 1 : currentActivity->GetHumanCount();
9698

97-
if (m_CurrentActivityHumanCount != (m_IsInMultiplayerMode ? 1 : currentActivity->GetHumanCount())) {
98-
m_CurrentActivityHumanCount = m_IsInMultiplayerMode ? 1 : currentActivity->GetHumanCount();
99-
status = status == FMOD_OK ? m_AudioSystem->set3DNumListeners(m_CurrentActivityHumanCount) : status;
100-
}
99+
if (m_CurrentActivityHumanPlayerPositions.size() != currentActivityHumanCount) { status = status == FMOD_OK ? m_AudioSystem->set3DNumListeners(currentActivityHumanCount) : status; }
101100

102-
int audioSystemPlayerNumber = 0;
103-
for (short player = Players::PlayerOne; player < currentActivity->GetPlayerCount() && audioSystemPlayerNumber < m_CurrentActivityHumanCount; player++) {
104-
if (currentActivity->PlayerHuman(player)) {
105-
status = status == FMOD_OK ? m_AudioSystem->set3DListenerAttributes(audioSystemPlayerNumber, &GetAsFMODVector(g_SceneMan.GetScrollTarget(currentActivity->ScreenOfPlayer(player)), g_SettingsMan.c_ListenerZOffset()), NULL, &c_FMODForward, &c_FMODUp) : status;
106-
audioSystemPlayerNumber++;
101+
if (m_CurrentActivityHumanPlayerPositions.empty() || (m_CurrentActivityHumanPlayerPositions.at(0) == nullptr || m_CurrentActivityHumanPlayerPositions.at(0)->GetFloorIntX() > g_SceneMan.GetSceneWidth() || m_CurrentActivityHumanPlayerPositions.at(0)->GetX() < 0.0F)) {
102+
m_CurrentActivityHumanPlayerPositions.clear();
103+
for (short player = Players::PlayerOne; player < currentActivity->GetPlayerCount() && m_CurrentActivityHumanPlayerPositions.size() < currentActivityHumanCount; player++) {
104+
if (currentActivity->PlayerHuman(player)) {
105+
const Vector &humanPlayerPosition = g_SceneMan.GetScrollTarget(currentActivity->ScreenOfPlayer(player));
106+
m_CurrentActivityHumanPlayerPositions.push_back(&humanPlayerPosition);
107+
}
107108
}
108109
}
109110

110-
if (g_SettingsMan.SoundPanningEffectStrength() < 1) { UpdateCalculated3DEffectsForMobileSoundChannels(); }
111+
int listenerNumber = 0;
112+
for (const Vector *humanPlayerPosition : m_CurrentActivityHumanPlayerPositions) {
113+
status = status == FMOD_OK ? m_AudioSystem->set3DListenerAttributes(listenerNumber, &GetAsFMODVector(*humanPlayerPosition, g_SettingsMan.c_ListenerZOffset()), nullptr, &c_FMODForward, &c_FMODUp) : status;
114+
listenerNumber++;
115+
}
116+
117+
Update3DEffectsForMobileSoundChannels();
111118
} else {
112-
if (m_CurrentActivityHumanCount != 1) {
113-
m_CurrentActivityHumanCount = 1;
119+
if (!m_CurrentActivityHumanPlayerPositions.empty()) {
120+
m_CurrentActivityHumanPlayerPositions.clear();
114121
status = status == FMOD_OK ? m_AudioSystem->set3DNumListeners(1) : status;
115122
}
116-
status = status == FMOD_OK ? m_AudioSystem->set3DListenerAttributes(0, &GetAsFMODVector(g_SceneMan.GetScrollTarget(), g_SettingsMan.c_ListenerZOffset()), NULL, &c_FMODForward, &c_FMODUp) : status;
123+
status = status == FMOD_OK ? m_AudioSystem->set3DListenerAttributes(0, &GetAsFMODVector(g_SceneMan.GetScrollTarget(), g_SettingsMan.c_ListenerZOffset()), nullptr, &c_FMODForward, &c_FMODUp) : status;
117124
}
118125

119126
status = status == FMOD_OK ? m_AudioSystem->update() : status;
@@ -495,25 +502,20 @@ namespace RTE {
495502
FMOD::ChannelGroup *channelGroupToPlayIn = soundContainer->IsImmobile() ? m_ImmobileSoundChannelGroup : m_MobileSoundChannelGroup;
496503
FMOD::Channel *channel;
497504
int channelIndex;
498-
unsigned short channelIndexAsUnsignedShort;
499505
for (SoundContainer::SoundData soundData : soundContainer->GetSelectedSoundSet()) {
500506
result = (result == FMOD_OK) ? m_AudioSystem->playSound(soundData.SoundObject, channelGroupToPlayIn, true, &channel) : result;
501507
result = (result == FMOD_OK) ? channel->getIndex(&channelIndex) : result;
502-
channelIndexAsUnsignedShort = static_cast<unsigned short>(channelIndex);
503508

504509
result = (result == FMOD_OK) ? channel->setUserData(soundContainer) : result;
505510
result = (result == FMOD_OK) ? channel->setCallback(SoundChannelEndedCallback) : result;
506-
result = (result == FMOD_OK) ? channel->set3DAttributes(&GetAsFMODVector(soundContainer->GetPosition() + soundData.Offset), NULL) : result;
511+
result = (result == FMOD_OK) ? channel->set3DAttributes(&GetAsFMODVector(soundContainer->GetPosition() + soundData.Offset), nullptr) : result;
507512
result = (result == FMOD_OK) ? channel->set3DLevel(g_SettingsMan.SoundPanningEffectStrength()) : result;
508513
result = (result == FMOD_OK) ? channel->setPriority(soundContainer->GetPriority()) : result;
509514
result = (result == FMOD_OK) ? channel->setVolume(soundContainer->GetVolume()) : result;
510515
result = (result == FMOD_OK) ? channel->setPitch(soundContainer->GetPitch()) : result;
511516

512-
if (!soundContainer->IsImmobile()) {
513-
m_SoundChannelRolloffs.insert({static_cast<unsigned short>(channelIndex), {FMOD_VECTOR(soundData.CustomRolloffPoints[0]), FMOD_VECTOR(soundData.CustomRolloffPoints[1])}});
514-
result = (result == FMOD_OK) ? channel->set3DCustomRolloff(m_SoundChannelRolloffs.at(channelIndexAsUnsignedShort).data(), 2) : result;
515-
result = (result == FMOD_OK) ? UpdateMobileSoundChannelCalculated3DEffects(channel) : result;
516-
}
517+
m_SoundChannelMinimumAudibleDistances.insert({channelIndex, soundData.MinimumAudibleDistance});
518+
if (!soundContainer->IsImmobile()) { UpdatePositionalEffectsForSoundChannel(channel); }
517519

518520
if (result != FMOD_OK) {
519521
g_ConsoleMan.PrintString("ERROR: Could not play sounds from SoundContainer " + soundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
@@ -526,10 +528,9 @@ namespace RTE {
526528
return false;
527529
}
528530

529-
soundContainer->AddPlayingChannel(channelIndexAsUnsignedShort);
531+
soundContainer->AddPlayingChannel(channelIndex);
530532
}
531533

532-
// Now that the sound is playing we can register an event with the SoundContainer's channels, which can be used by clients to identify the sound being played.
533534
if (m_IsInMultiplayerMode) {
534535
RegisterSoundEvent(player, SOUND_PLAY, soundContainer->GetPlayingChannels(), &soundContainer->GetSelectedSoundHashes(), soundContainer->GetPosition(), soundContainer->GetLoopSetting(), soundContainer->GetVolume(), soundContainer->GetPitch(), soundContainer->IsAffectedByGlobalPitch(), soundContainer->GetAttenuationStartDistance(), soundContainer->IsImmobile());
535536
}
@@ -554,14 +555,11 @@ namespace RTE {
554555
result = (result == FMOD_OK) ? soundChannel->getCurrentSound(&sound) : result;
555556
const SoundContainer::SoundData *soundData = soundContainer->GetSoundDataForSound(sound);
556557

557-
result = (result == FMOD_OK) ? soundChannel->set3DAttributes(&GetAsFMODVector(position + ((soundData == NULL) ? Vector() : soundData->Offset)), NULL) : result;
558+
FMOD_VECTOR soundPosition = GetAsFMODVector(soundContainer->GetPosition() + ((soundData == nullptr) ? Vector() : soundData->Offset));
559+
result = (result == FMOD_OK) ? UpdatePositionalEffectsForSoundChannel(soundChannel, &soundPosition) : result;
558560
if (result != FMOD_OK) {
559561
g_ConsoleMan.PrintString("ERROR: Could not set sound position for the sound being played on channel " + std::to_string(channelIndex) + " for SoundContainer " + soundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
560562
}
561-
result = (result == FMOD_OK) ? UpdateMobileSoundChannelCalculated3DEffects(soundChannel) : result;
562-
if (result != FMOD_OK) {
563-
g_ConsoleMan.PrintString("ERROR: Could not update attenuation for the sound being played on channel " + std::to_string(channelIndex) + " for SoundContainer " + soundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
564-
}
565563
}
566564
return result == FMOD_OK;
567565
}
@@ -612,71 +610,99 @@ namespace RTE {
612610

613611
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
614612

613+
void AudioMan::Update3DEffectsForMobileSoundChannels() {
614+
int numberOfPlayingChannels;
615+
FMOD::Channel *soundChannel;
615616

617+
FMOD_RESULT result = m_MobileSoundChannelGroup->getNumChannels(&numberOfPlayingChannels);
618+
if (result != FMOD_OK) {
619+
g_ConsoleMan.PrintString("ERROR: Failed to get the number of playing channels when updating calculated sound effects for all playing channels: " + std::string(FMOD_ErrorString(result)));
620+
return;
621+
}
616622

623+
for (int i = 0; i < numberOfPlayingChannels; i++) {
624+
result = m_MobileSoundChannelGroup->getChannel(i, &soundChannel);
625+
FMOD_VECTOR channelPosition;
626+
result = result == FMOD_OK ? soundChannel->get3DAttributes(&channelPosition, nullptr) : result;
627+
result = result == FMOD_OK ? UpdatePositionalEffectsForSoundChannel(soundChannel, &channelPosition) : result;
628+
629+
float channel3dLevel;
630+
result = (result == FMOD_OK) ? soundChannel->get3DLevel(&channel3dLevel) : result;
631+
if (result == FMOD_OK && m_CurrentActivityHumanPlayerPositions.size() == 1) {
632+
float distanceToPlayer = (*m_CurrentActivityHumanPlayerPositions.at(0) - GetAsVector(channelPosition)).GetMagnitude();
633+
if (distanceToPlayer < g_SettingsMan.c_MinimumDistanceForPanning()) {
634+
soundChannel->set3DLevel(0);
635+
} else if (distanceToPlayer < g_SettingsMan.c_MinimumDistanceForPanning() * 2) {
636+
soundChannel->set3DLevel(LERP(0, 1, 0, g_SettingsMan.SoundPanningEffectStrength(), channel3dLevel));
637+
} else {
638+
soundChannel->set3DLevel(g_SettingsMan.SoundPanningEffectStrength());
639+
}
640+
}
617641

618642
if (result != FMOD_OK) {
643+
g_ConsoleMan.PrintString("ERROR: An error occurred updating calculated sound effects for playing channel with index " + std::to_string(i) + ": " + std::string(FMOD_ErrorString(result)));
644+
continue;
619645
}
620646
}
621647
}
622648

623649
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
624650

651+
FMOD_RESULT AudioMan::UpdatePositionalEffectsForSoundChannel(FMOD::Channel *soundChannel, const FMOD_VECTOR *positionOverride) const {
652+
FMOD_RESULT result = FMOD_OK;
653+
bool sceneWraps = g_SceneMan.SceneWrapsX();
625654

626-
void AudioMan::UpdateCalculated3DEffectsForMobileSoundChannels() {
627-
int numberOfPlayingChannels;
628-
FMOD::Channel *channel;
655+
FMOD_VECTOR channelPosition;
656+
if (positionOverride) {
657+
channelPosition = *positionOverride;
658+
} else if (sceneWraps) {
659+
//NOTE If the scene doesn't wrap and the position hasn't changed, this method doesn't set the channel position below, so there's no need to get it here.
660+
result = soundChannel->get3DAttributes(&channelPosition, nullptr);
661+
if (result != FMOD_OK) {
662+
return result;
663+
}
664+
}
629665

630-
FMOD_RESULT result = m_MobileSoundChannelGroup->getNumChannels(&numberOfPlayingChannels);
631-
if (result == FMOD_OK) {
632-
for (int i = 0; i < numberOfPlayingChannels; i++) {
633-
result = m_MobileSoundChannelGroup->getChannel(i, &channel);
634-
result = result == FMOD_OK ? UpdateMobileSoundChannelCalculated3DEffects(channel) : result;
635-
if (result != FMOD_OK) {
636-
g_ConsoleMan.PrintString("ERROR: An error occurred when manually attenuating all playing channels, for channel index " + std::to_string(i) + ": " + std::string(FMOD_ErrorString(result)));
666+
float halfSceneWidth = static_cast<float>(g_SceneMan.GetSceneWidth()) / 2.0F;
667+
std::array<FMOD_VECTOR, 2> wrappedChannelPositions;
668+
if (!sceneWraps) {
669+
wrappedChannelPositions = {channelPosition};
670+
} else {
671+
wrappedChannelPositions = (channelPosition.x <= halfSceneWidth) ?
672+
wrappedChannelPositions = {channelPosition, GetAsFMODVector({channelPosition.x + g_SceneMan.GetSceneWidth(), channelPosition.y})} :
673+
wrappedChannelPositions = {GetAsFMODVector({channelPosition.x - g_SceneMan.GetSceneWidth(), channelPosition.y}), channelPosition};
674+
}
675+
676+
float shortestDistance = -1;
677+
for (const Vector *humanPlayerPosition : m_CurrentActivityHumanPlayerPositions) {
678+
for (const FMOD_VECTOR &wrappedChannelPosition : wrappedChannelPositions) {
679+
float distanceToChannelPosition = (*humanPlayerPosition - GetAsVector(wrappedChannelPosition)).GetMagnitude();
680+
if (shortestDistance == -1 || distanceToChannelPosition < shortestDistance) {
681+
shortestDistance = distanceToChannelPosition;
682+
channelPosition = wrappedChannelPosition;
637683
}
638684
}
639-
} else {
640-
g_ConsoleMan.PrintString("ERROR: Failed to get the number of playing channels when manually attenuating all playing channels: " + std::string(FMOD_ErrorString(result)));
641685
}
686+
687+
int soundChannelIndex;
688+
result = result == FMOD_OK ? soundChannel->getIndex(&soundChannelIndex) : result;
689+
result = result == FMOD_OK ? soundChannel->setMute(shortestDistance < m_SoundChannelMinimumAudibleDistances.at(soundChannelIndex)) : result;
690+
result = (result == FMOD_OK && (sceneWraps || positionOverride)) ? soundChannel->set3DAttributes(&channelPosition, nullptr) : result;
691+
692+
return result;
642693
}
643694

644695
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
645696

646-
FMOD_RESULT AudioMan::UpdateMobileSoundChannelCalculated3DEffects(FMOD::Channel *channel) {
647-
FMOD_VECTOR channelPosition;
648-
FMOD_RESULT result = channel->get3DAttributes(&channelPosition, NULL);
649-
if (result != FMOD_OK) {
650-
return result;
651697
FMOD_RESULT F_CALLBACK AudioMan::MusicChannelEndedCallback(FMOD_CHANNELCONTROL *channelControl, FMOD_CHANNELCONTROL_TYPE channelControlType, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbackType, void *unusedCommandData1, void *unusedCommandData2) {
652698
if (channelControlType == FMOD_CHANNELCONTROL_CHANNEL && callbackType == FMOD_CHANNELCONTROL_CALLBACK_END) {
653699
g_AudioMan.PlayNextStream();
654700
}
655701
return FMOD_OK;
656702
}
657703

658-
const Activity *currentActivity = g_ActivityMan.GetActivity();
659-
float shortestDistance = g_SceneMan.GetSceneDim().GetMagnitude();
660-
float longestDistance = 0;
661-
for (unsigned short player = Players::PlayerOne; player < currentActivity->GetPlayerCount(); player++) {
662-
if (currentActivity->PlayerHuman(player)) {
663-
float distance = g_SceneMan.ShortestDistance(GetAsVector(channelPosition), g_SceneMan.GetScrollTarget(currentActivity->ScreenOfPlayer(player)), g_SceneMan.SceneWrapsX()).GetMagnitude();
664-
shortestDistance = min(shortestDistance, distance);
665-
longestDistance = max(longestDistance, distance);
666-
}
667-
}
704+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
668705

669-
float channel3dLevel;
670-
result = (result == FMOD_OK) ? channel->get3DLevel(&channel3dLevel) : result;
671-
if (result == FMOD_OK && m_CurrentActivityHumanCount == 1) {
672-
if (shortestDistance < g_SettingsMan.c_MinimumDistanceForPanning()) {
673-
channel->set3DLevel(0);
674-
} else if (shortestDistance < g_SettingsMan.c_MinimumDistanceForPanning() * 2) {
675-
channel->set3DLevel(LERP(0, 1, 0, g_SettingsMan.SoundPanningEffectStrength(), channel3dLevel));
676-
} else {
677-
channel->set3DLevel(g_SettingsMan.SoundPanningEffectStrength());
678-
}
679-
}
680706
FMOD_RESULT F_CALLBACK AudioMan::SoundChannelEndedCallback(FMOD_CHANNELCONTROL *channelControl, FMOD_CHANNELCONTROL_TYPE channelControlType, FMOD_CHANNELCONTROL_CALLBACK_TYPE callbackType, void *unusedCommandData1, void *unusedCommandData2) {
681707
if (channelControlType == FMOD_CHANNELCONTROL_CHANNEL && callbackType == FMOD_CHANNELCONTROL_CALLBACK_END) {
682708
FMOD::Channel *channel = reinterpret_cast<FMOD::Channel *>(channelControl);
@@ -691,30 +717,16 @@ namespace RTE {
691717
if (channelSoundContainer->IsBeingPlayed()) { channelSoundContainer->RemovePlayingChannel(channelIndex); }
692718
result = (result == FMOD_OK) ? channel->setUserData(nullptr) : result;
693719

694-
FMOD_VECTOR *rolloffPoints; // NOTE: Rolloff points are - 1. Minimum audible distance, 2. Attenuation start distance
695-
result = (result == FMOD_OK) ? channel->get3DCustomRolloff(&rolloffPoints, NULL) : result;
720+
if (g_AudioMan.m_SoundChannelMinimumAudibleDistances.find(channelIndex) != g_AudioMan.m_SoundChannelMinimumAudibleDistances.end()) { g_AudioMan.m_SoundChannelMinimumAudibleDistances.erase(channelIndex); }
696721

697-
if (result == FMOD_OK && channel3dLevel < 1 && rolloffPoints) {
698-
float attenuatedVolume;
699-
if (longestDistance < rolloffPoints[0].x || shortestDistance > c_SoundMaxAudibleDistance) {
700-
attenuatedVolume = 0;
701-
} else if (shortestDistance < rolloffPoints[0].x + rolloffPoints[1].x) {
702-
attenuatedVolume = 1;
703722
if (result != FMOD_OK) {
704723
g_ConsoleMan.PrintString("ERROR: An error occurred when Ending a sound in SoundContainer " + channelSoundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
705724
return result;
706725
}
707726
} else {
708-
attenuatedVolume = rolloffPoints[1].x / (shortestDistance - rolloffPoints[0].x);
709727
g_ConsoleMan.PrintString("ERROR: An error occurred when Ending a sound: " + std::string(FMOD_ErrorString(result)));
710728
}
711-
712-
void *userData;
713-
result = (result == FMOD_OK) ? channel->getUserData(&userData) : result;
714-
result = (result == FMOD_OK) ? channel->setVolume(attenuatedVolume * static_cast<SoundContainer *>(userData)->GetVolume()) : result;
715729
}
716-
717-
return result;
718730
return FMOD_OK;
719731
}
720732

0 commit comments

Comments
 (0)