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

Commit 7c647bd

Browse files
committed
Cleaned up various stuff in AudioMan and supported changes to SoundContainer
Added separate channel groups for mobile and immobile sounds Added a vector of sound channel rolloffs for safety Added methods to handle customization of 3d effects (panning, attenuation) for mobile sound channels. This should probably be replaced with a DSP eventually.
1 parent 3149d60 commit 7c647bd

File tree

2 files changed

+169
-36
lines changed

2 files changed

+169
-36
lines changed

Managers/AudioMan.cpp

Lines changed: 142 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ namespace RTE {
1515
void AudioMan::Clear() {
1616
m_AudioEnabled = false;
1717

18+
soundChannelRolloffs.clear();
19+
1820
m_MusicPath.clear();
1921
m_SoundsVolume = 1.0;
2022
m_MusicVolume = 1.0;
@@ -42,8 +44,12 @@ namespace RTE {
4244
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_AudioSystem->getMasterChannelGroup(&m_MasterChannelGroup) : audioSystemSetupResult;
4345
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_AudioSystem->createChannelGroup("Music", &m_MusicChannelGroup) : audioSystemSetupResult;
4446
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_AudioSystem->createChannelGroup("Sounds", &m_SoundChannelGroup) : audioSystemSetupResult;
47+
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_AudioSystem->createChannelGroup("MobileSounds", &m_MobileSoundChannelGroup) : audioSystemSetupResult;
48+
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_AudioSystem->createChannelGroup("ImmobileSounds", &m_ImmobileSoundChannelGroup) : audioSystemSetupResult;
4549
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_MasterChannelGroup->addGroup(m_MusicChannelGroup) : audioSystemSetupResult;
4650
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_MasterChannelGroup->addGroup(m_SoundChannelGroup) : audioSystemSetupResult;
51+
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_SoundChannelGroup->addGroup(m_MobileSoundChannelGroup) : audioSystemSetupResult;
52+
audioSystemSetupResult = (audioSystemSetupResult == FMOD_OK) ? m_SoundChannelGroup->addGroup(m_ImmobileSoundChannelGroup) : audioSystemSetupResult;
4753

4854
m_AudioEnabled = audioSystemSetupResult == FMOD_OK;
4955

@@ -92,16 +98,20 @@ namespace RTE {
9298
int audioSystemPlayerNumber = 0;
9399
for (int player = 0; player < currentActivity->GetPlayerCount() && audioSystemPlayerNumber < m_CurrentActivityHumanCount; player++) {
94100
if (currentActivity->PlayerHuman(player)) {
95-
status = m_AudioSystem->set3DListenerAttributes(audioSystemPlayerNumber, &GetAsFMODVector(g_SceneMan.GetScrollTarget(currentActivity->ScreenOfPlayer(player))), NULL, &c_FMODForward, &c_FMODUp);
96-
audioSystemPlayerNumber++;
101+
status = m_AudioSystem->set3DListenerAttributes(audioSystemPlayerNumber, &GetAsFMODVector(g_SceneMan.GetScrollTarget(currentActivity->ScreenOfPlayer(player)), g_SettingsMan.c_ListenerZOffset()), NULL, &c_FMODForward, &c_FMODUp);
102+
audioSystemPlayerNumber++;
97103
}
98104
}
105+
106+
if (g_SettingsMan.SoundPanningEffectStrength() < 1) {
107+
UpdateCalculated3DEffectsForMobileSoundChannels();
108+
}
99109
} else {
100110
if (m_CurrentActivityHumanCount != 1) {
101111
m_CurrentActivityHumanCount = 1;
102112
status = m_AudioSystem->set3DNumListeners(1);
103113
}
104-
status = m_AudioSystem->set3DListenerAttributes(0, &GetAsFMODVector(g_SceneMan.GetScrollTarget()), NULL, &c_FMODForward, &c_FMODUp);
114+
status = m_AudioSystem->set3DListenerAttributes(0, &GetAsFMODVector(g_SceneMan.GetScrollTarget(), g_SettingsMan.c_ListenerZOffset()), NULL, &c_FMODForward, &c_FMODUp);
105115
}
106116

107117
status = m_AudioSystem->update();
@@ -112,7 +122,7 @@ namespace RTE {
112122

113123
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
114124

115-
void AudioMan::SetGlobalPitch(double pitch, bool excludeMusic) {
125+
void AudioMan::SetGlobalPitch(double pitch, bool excludeImmobileSounds, bool excludeMusic) {
116126
if (!m_AudioEnabled) {
117127
return;
118128
}
@@ -122,8 +132,10 @@ namespace RTE {
122132
m_GlobalPitch = Limit(pitch, 8, 0.125);
123133
if (!excludeMusic) { m_MusicChannelGroup->setPitch(m_GlobalPitch); }
124134

135+
FMOD::ChannelGroup *channelGroupToUse = excludeImmobileSounds ? m_MobileSoundChannelGroup : m_SoundChannelGroup;
136+
125137
int numChannels;
126-
FMOD_RESULT result = m_SoundChannelGroup->getNumChannels(&numChannels);
138+
FMOD_RESULT result = channelGroupToUse->getNumChannels(&numChannels);
127139
if (result != FMOD_OK) {
128140
g_ConsoleMan.PrintString("ERROR: Could not set global pitch: " + std::string(FMOD_ErrorString(result)));
129141
return;
@@ -132,7 +144,7 @@ namespace RTE {
132144
FMOD::Channel *soundChannel;
133145
bool isPlaying;
134146
for (int i = 0; i < numChannels; i++) {
135-
result = m_SoundChannelGroup->getChannel(i, &soundChannel);
147+
result = channelGroupToUse->getChannel(i, &soundChannel);
136148
result = (result == FMOD_OK) ? soundChannel->isPlaying(&isPlaying) : result;
137149

138150
if (result == FMOD_OK && isPlaying) {
@@ -222,13 +234,21 @@ namespace RTE {
222234

223235
FMOD_RESULT result = FMOD_OK;
224236
FMOD::Channel *soundChannel;
237+
FMOD::Sound *sound;
225238

226-
std::unordered_set<unsigned short> const *channels = soundContainer->GetPlayingChannels();
227-
for (std::unordered_set<unsigned short>::iterator channelIterator = channels->begin(); channelIterator != channels->end(); ++channelIterator) {
228-
result = m_AudioSystem->getChannel((*channelIterator), &soundChannel);
229-
result = (result == FMOD_OK) ? soundChannel->set3DAttributes(&GetAsFMODVector(position), NULL) : result;
239+
std::unordered_set<unsigned short> const *playingChannels = soundContainer->GetPlayingChannels();
240+
for (unsigned short channelIndex : *playingChannels) {
241+
result = m_AudioSystem->getChannel(channelIndex, &soundChannel);
242+
result = (result == FMOD_OK) ? soundChannel->getCurrentSound(&sound) : result;
243+
SoundContainer::SoundData const *soundData = soundContainer->GetSoundDataForSound(sound);
244+
245+
result = (result == FMOD_OK) ? soundChannel->set3DAttributes(&GetAsFMODVector(position + (soundData == NULL ? Vector() : soundData->Offset)), NULL) : result;
246+
if (result != FMOD_OK) {
247+
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)));
248+
}
249+
result = (result == FMOD_OK) ? UpdateMobileSoundChannelCalculated3DEffects(soundChannel) : result;
230250
if (result != FMOD_OK) {
231-
g_ConsoleMan.PrintString("ERROR: Could not set sound position for the sound being played on channel " + std::to_string(*channelIterator) + " for SoundContainer " + soundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
251+
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)));
232252
}
233253
}
234254
return result == FMOD_OK;
@@ -282,7 +302,7 @@ namespace RTE {
282302
}
283303

284304
FMOD::Channel *musicChannel;
285-
result = musicStream->set3DMinMaxDistance(100000, 100000);
305+
result = musicStream->set3DMinMaxDistance(c_SoundMaxAudibleDistance, c_SoundMaxAudibleDistance);
286306
result = (result == FMOD_OK) ? m_AudioSystem->playSound(musicStream, m_MusicChannelGroup, true, &musicChannel) : result;
287307
result = (result == FMOD_OK) ? musicChannel->set3DAttributes(&GetAsFMODVector(Vector()), NULL) : result;
288308
if (result != FMOD_OK) {
@@ -419,7 +439,7 @@ namespace RTE {
419439
return false;
420440
}
421441
}
422-
if (!soundContainer->SelectNextSounds()) {
442+
if (!soundContainer->SelectNextSoundSet()) {
423443
g_ConsoleMan.PrintString("Unable to select new sounds to play for SoundContainer " + soundContainer->GetPresetName());
424444
return false;
425445
}
@@ -429,24 +449,39 @@ namespace RTE {
429449

430450
FMOD::Channel *channel;
431451
int channelIndex;
432-
for (FMOD::Sound *sound : soundContainer->GetSelectedSoundObjects()) {
433-
result = (result == FMOD_OK) ? m_AudioSystem->playSound(sound, m_SoundChannelGroup, true, &channel) : result;
434-
result = (result == FMOD_OK) ? channel->getIndex(&channelIndex) : result;
435-
result = (result == FMOD_OK) ? channel->setUserData(soundContainer) : result;
436-
result = (result == FMOD_OK) ? channel->setCallback(SoundChannelEndedCallback) : result;
437-
result = (result == FMOD_OK) ? channel->set3DAttributes(&GetAsFMODVector(position), NULL) : result;
438-
result = (result == FMOD_OK) ? channel->set3DLevel(g_SettingsMan.SoundPanningEffectStrength()) : result;
439-
result = (result == FMOD_OK) ? channel->setPriority(priority) : result;
440-
result = (result == FMOD_OK) ? channel->setPitch(pitch) : result;
441-
}
442-
if (result != FMOD_OK) {
443-
g_ConsoleMan.PrintString("ERROR: Could not play sounds from SoundContainer " + soundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
444-
return false;
452+
Vector sceneWrapHandlingPositions[2] = {position, position + Vector(position.m_X < g_SceneMan.GetSceneWidth() * 0.5 ? g_SceneMan.GetSceneWidth() : -g_SceneMan.GetSceneWidth(), 0)};
453+
for (SoundContainer::SoundData soundData : soundContainer->GetSelectedSoundSet()) {
454+
for (int copyToHandleSceneWrapping = 0; copyToHandleSceneWrapping < ((!soundContainer->IsImmobile() && g_SceneMan.SceneWrapsX()) ? 1 : 2); copyToHandleSceneWrapping++) {
455+
result = (result == FMOD_OK) ? m_AudioSystem->playSound(soundData.SoundObject, soundContainer->IsImmobile() ? m_ImmobileSoundChannelGroup : m_MobileSoundChannelGroup, true, &channel) : result;
456+
result = (result == FMOD_OK) ? channel->getIndex(&channelIndex) : result;
457+
result = (result == FMOD_OK) ? channel->setUserData(soundContainer) : result;
458+
result = (result == FMOD_OK) ? channel->setCallback(SoundChannelEndedCallback) : result;
459+
result = (result == FMOD_OK) ? channel->set3DAttributes(&GetAsFMODVector(sceneWrapHandlingPositions[copyToHandleSceneWrapping] + soundData.Offset), NULL) : result;
460+
result = (result == FMOD_OK) ? channel->set3DLevel(g_SettingsMan.SoundPanningEffectStrength()) : result;
461+
result = (result == FMOD_OK) ? channel->setPriority(priority) : result;
462+
result = (result == FMOD_OK) ? channel->setPitch(pitch) : result;
463+
464+
if (!soundContainer->IsImmobile()) {
465+
soundChannelRolloffs.insert({static_cast<unsigned short>(channelIndex), {FMOD_VECTOR(soundData.CustomRolloffPoints[0]), FMOD_VECTOR(soundData.CustomRolloffPoints[1])}});
466+
result = (result == FMOD_OK) ? channel->set3DCustomRolloff(soundChannelRolloffs.at(channelIndex).data(), 2) : result;
467+
result = (result == FMOD_OK) ? UpdateMobileSoundChannelCalculated3DEffects(channel) : result;
468+
}
469+
470+
if (result != FMOD_OK) {
471+
g_ConsoleMan.PrintString("ERROR: Could not play sounds from SoundContainer " + soundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
472+
return false;
473+
}
474+
475+
result = channel->setPaused(false);
476+
if (result != FMOD_OK) {
477+
g_ConsoleMan.PrintString("ERROR: Failed to start playing sounds from SoundContainer " + soundContainer->GetPresetName() + " after setting it up: " + std::string(FMOD_ErrorString(result)));
478+
return false;
479+
}
480+
481+
soundContainer->AddPlayingChannel(channelIndex);
482+
}
445483
}
446-
result = channel->setPaused(false);
447-
if (result != FMOD_OK) { g_ConsoleMan.PrintString("ERROR: Failed to start playing sounds from SoundContainer " + soundContainer->GetPresetName() + " after setting it up: " + std::string(FMOD_ErrorString(result))); }
448484

449-
soundContainer->AddPlayingChannel(channelIndex);
450485

451486
// 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.
452487
if (m_IsInMultiplayerMode) {
@@ -622,6 +657,9 @@ namespace RTE {
622657
if (channelSoundContainer->IsBeingPlayed()) { channelSoundContainer->RemovePlayingChannel(channelIndex); }
623658
result = (result == FMOD_OK) ? channel->setUserData(NULL) : result;
624659

660+
// Remove the stored rolloff for this channel
661+
if (AudioMan::Instance().soundChannelRolloffs.find(channelIndex) != AudioMan::Instance().soundChannelRolloffs.end()) { AudioMan::Instance().soundChannelRolloffs.erase(channelIndex); }
662+
625663
if (result != FMOD_OK) {
626664
g_ConsoleMan.PrintString("ERROR: An error occurred when Ending a sound in SoundContainer " + channelSoundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
627665
return result;
@@ -632,6 +670,81 @@ namespace RTE {
632670

633671
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
634672

673+
//TODO remove or use this
674+
FMOD_RESULT F_CALLBACK AudioMan::PanAndAttenuationDSPCallback(FMOD_DSP_STATE *dspState, float *inBuffer, float *outBuffer, unsigned int length, int inChannels, int *outChannels) {
675+
return FMOD_OK;
676+
}
677+
678+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
679+
680+
void AudioMan::UpdateCalculated3DEffectsForMobileSoundChannels() {
681+
int numberOfPlayingChannels;
682+
FMOD::Channel *channel;
683+
684+
FMOD_RESULT result = m_MobileSoundChannelGroup->getNumChannels(&numberOfPlayingChannels);
685+
if (result == FMOD_OK) {
686+
for (int i = 0; i < numberOfPlayingChannels; i++) {
687+
result = m_MobileSoundChannelGroup->getChannel(i, &channel);
688+
result = result == FMOD_OK ? UpdateMobileSoundChannelCalculated3DEffects(channel) : result;
689+
if (result != FMOD_OK) {
690+
g_ConsoleMan.PrintString("ERROR: An error occured when manually attenuating all playing channels, for channel index " + std::to_string(i) + ": " + std::string(FMOD_ErrorString(result)));
691+
}
692+
}
693+
} else {
694+
g_ConsoleMan.PrintString("ERROR: Failed to get the number of playing channels when manually attenuating all playing channels: " + std::string(FMOD_ErrorString(result)));
695+
}
696+
}
697+
698+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
699+
700+
FMOD_RESULT AudioMan::UpdateMobileSoundChannelCalculated3DEffects(FMOD::Channel *channel) {
701+
FMOD_VECTOR channelPosition;
702+
FMOD_RESULT result = channel->get3DAttributes(&channelPosition, NULL);
703+
if (result != FMOD_OK) {
704+
return result;
705+
}
706+
707+
Activity const *currentActivity = g_ActivityMan.GetActivity();
708+
float shortestDistance = g_SceneMan.GetSceneDim().GetMagnitude();
709+
float longestDistance = 0;
710+
for (int player = 0; player < currentActivity->GetPlayerCount(); player++) {
711+
if (currentActivity->PlayerHuman(player)) {
712+
float distance = g_SceneMan.ShortestDistance(GetAsVector(channelPosition), g_SceneMan.GetScrollTarget(currentActivity->ScreenOfPlayer(player)), g_SceneMan.SceneWrapsX()).GetMagnitude();
713+
shortestDistance = min(shortestDistance, distance);
714+
longestDistance = max(longestDistance, distance);
715+
}
716+
}
717+
718+
719+
float channel3dLevel;
720+
result = (result == FMOD_OK) ? channel->get3DLevel(&channel3dLevel) : result;
721+
if (result == FMOD_OK && m_CurrentActivityHumanCount == 1) {
722+
if (shortestDistance < g_SettingsMan.c_MinimumDistanceForPanning()) {
723+
channel->set3DLevel(0);
724+
} else if (shortestDistance < g_SettingsMan.c_MinimumDistanceForPanning() * 2) {
725+
channel->set3DLevel(LERP(0, 1, 0, g_SettingsMan.SoundPanningEffectStrength(), channel3dLevel));
726+
} else {
727+
channel->set3DLevel(g_SettingsMan.SoundPanningEffectStrength());
728+
}
729+
}
730+
731+
FMOD_VECTOR *rolloffPoints; // NOTE: Rolloff points are - 1. Minimum audible distance, 2. Attenuation start distance
732+
result = (result == FMOD_OK) ? channel->get3DCustomRolloff(&rolloffPoints, NULL) : result;
733+
734+
if (result == FMOD_OK && channel3dLevel < 1) {
735+
float volume;
736+
if (longestDistance < rolloffPoints[0].x || shortestDistance > c_SoundMaxAudibleDistance) {
737+
volume = 0;
738+
} else if (shortestDistance < rolloffPoints[0].x + rolloffPoints[1].x) {
739+
volume = 1;
740+
} else {
741+
volume = rolloffPoints[1].x / (shortestDistance - rolloffPoints[0].x);
742+
}
743+
result = (result == FMOD_OK) ? channel->setVolume(volume) : result;
744+
}
745+
746+
return result;
747+
}
635748

636749
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
637750

0 commit comments

Comments
 (0)