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

Commit 3f7bb3e

Browse files
committed
Fixed SoundContainer::SelectNextSound to work with changed data structuring. Also fixed cleared-to priority being low instead of normal.
Fixed sound stop callback in AudioMan breaking if the sound was reset before the callback happened (e.g. gib sounds). Made number of channels a constant instead of a settings entry, since it's dumb to have it settable. Cleaned up various things in AudioMan - renamed distance to attenuation, Reorganized StopSound so there's an easy one for lua that stops all sounds and calls the player specific one and fixed iterator invalidation when stopping sound due to callback erasing it, fixed mutex positioning, made PlaySound iterate through all selected sound objects in a SoundContainer and added error print if it fails to select new sounds
1 parent cc298e2 commit 3f7bb3e

File tree

6 files changed

+55
-52
lines changed

6 files changed

+55
-52
lines changed

Entities/SoundContainer.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace RTE {
1212
m_SelectedSounds.clear();
1313
m_PlayingChannels.clear();
1414
m_Loops = 0;
15-
m_Priority = AudioMan::PRIORITY_LOW;
15+
m_Priority = AudioMan::PRIORITY_NORMAL;
1616
m_AffectedByGlobalPitch = true;
1717
}
1818

@@ -105,21 +105,32 @@ namespace RTE {
105105

106106
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
107107

108-
FMOD::Sound *SoundContainer::SelectNextSound() {
108+
bool SoundContainer::SelectNextSounds() {
109109
int soundCount = GetSoundCount();
110-
if (soundCount == 2) {
111-
m_CurrentSound = m_CurrentSound == 0 ? 1 : 0; // Alternate between 2 sounds
112-
} else if (soundCount > 2) {
113-
int lastSound = m_CurrentSound;
114-
m_CurrentSound = floorf((float)soundCount * PosRand());
115-
// Mix it up again if we got the same sound twice
116-
while (m_CurrentSound == lastSound) {
117-
m_CurrentSound = floorf((float)soundCount * PosRand());
110+
if (soundCount == 0) {
111+
return false;
112+
}
113+
114+
std::size_t previouslySelectedSound = m_SelectedSounds.size() > 0 ? m_SelectedSounds[0] : 0;
115+
116+
if (m_SelectedSounds.empty() || soundCount == 1) {
117+
m_SelectedSounds.clear();
118+
m_SelectedSounds.push_back(previouslySelectedSound);
119+
} else {
120+
m_SelectedSounds.clear();
121+
if (soundCount == 2) {
122+
m_SelectedSounds.push_back((previouslySelectedSound + 1) % soundCount);
123+
} else if (soundCount > 2) {
124+
size_t soundToSelect = floorf((float)soundCount * PosRand());
125+
// Mix it up again if we got the same sound twice
126+
while (soundToSelect == previouslySelectedSound) {
127+
soundToSelect = floorf((float)soundCount * PosRand());
128+
}
129+
m_SelectedSounds.push_back(soundToSelect);
118130
}
119131
}
120-
RTEAssert(m_CurrentSound >= 0 && m_CurrentSound < soundCount, "Sample index is out of bounds!");
132+
RTEAssert(m_SelectedSounds.size() > 0 && m_SelectedSounds[0] >= 0 && m_SelectedSounds[0] < soundCount, "Failed to select next sound, either none was selected or the selected sound was invalid.");
121133

122-
FMOD::Sound *soundToStart;
123-
return m_Sounds[m_CurrentSound].second;
134+
return true;
124135
}
125136
}

Managers/AudioMan.cpp

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ namespace RTE {
2424
int channelIndex;
2525
FMOD_RESULT result = channel->getIndex(&channelIndex);
2626

27+
// Remove this playing sound index from the SoundContainer if it has any playing sounds, i.e. it hasn't been reset before this callback happened.
2728
void *userData;
28-
result == FMOD_OK ? channel->getUserData(&userData) : result;
29+
result = result == FMOD_OK ? channel->getUserData(&userData) : result;
2930
SoundContainer *channelSoundContainer = (SoundContainer *)userData;
30-
//Account for PlaySound that doesn't create a SoundContainer
31-
if (channelSoundContainer != NULL) {
31+
if (channelSoundContainer->GetPlayingSoundCount() > 0) {
3232
channelSoundContainer->RemovePlayingChannel(channelIndex);
3333
}
34+
result = result == FMOD_OK ? channel->setUserData(NULL) : result;
3435

3536
if (result != FMOD_OK) {
3637
g_ConsoleMan.PrintString("ERROR: An error occurred when Ending a sound in SoundContainer " + channelSoundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
@@ -69,7 +70,7 @@ namespace RTE {
6970
//TODO 44.1 kHz came from data, fmod defaults to 48 kHz, see if we can just use this instead??
7071
m_AudioSystem->setSoftwareFormat(44100, FMOD_SPEAKERMODE_DEFAULT, 0);
7172

72-
soundSystemSetupResult = soundSystemSetupResult == FMOD_OK ? m_AudioSystem->init(g_SettingsMan.GetAudioChannels(), FMOD_INIT_NORMAL, 0) : soundSystemSetupResult;
73+
soundSystemSetupResult = soundSystemSetupResult == FMOD_OK ? m_AudioSystem->init(c_NumberOfAudioChannels, FMOD_INIT_NORMAL, 0) : soundSystemSetupResult;
7374
soundSystemSetupResult = soundSystemSetupResult == FMOD_OK ? m_AudioSystem->getMasterChannelGroup(&m_MasterChannelGroup) : soundSystemSetupResult;
7475
soundSystemSetupResult = soundSystemSetupResult == FMOD_OK ? m_AudioSystem->createChannelGroup("Music", &m_MusicChannelGroup) : soundSystemSetupResult;
7576
soundSystemSetupResult = soundSystemSetupResult == FMOD_OK ? m_AudioSystem->createChannelGroup("Sounds", &m_SoundChannelGroup) : soundSystemSetupResult;
@@ -220,20 +221,21 @@ namespace RTE {
220221

221222
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
222223

223-
bool AudioMan::SetSoundAttenuation(SoundContainer *pSoundContainer, float distance) {
224+
bool AudioMan::SetSoundAttenuation(SoundContainer *pSoundContainer, float attenuation) {
224225
if (!m_AudioEnabled || !pSoundContainer) {
225226
return false;
226227
}
227228

228-
distance = Limit(distance, 0.95, 0); //Limit distance so it can't be closer than 0 (no attenuation) or farther than 0.95 (quiet but not quite silent)
229+
230+
attenuation = Limit(attenuation, 0.95, 0); //Limit attenuation so it can't be closer than 0 (full volume) or farther than 0.95 (quiet but not quite silent)
229231

230232
FMOD_RESULT result = FMOD_OK;
231233
FMOD::Channel *soundChannel;
232234

233-
std::unordered_set<short int> channels = pSoundContainer->GetPlayingChannels();
234-
for (std::unordered_set<short int>::iterator channelIterator = channels.begin(); channelIterator != channels.end(); ++channelIterator) {
235+
std::unordered_set<unsigned short int> const *channels = pSoundContainer->GetPlayingChannels();
236+
for (std::unordered_set<unsigned short int>::iterator channelIterator = channels->begin(); channelIterator != channels->end(); ++channelIterator) {
235237
result = m_AudioSystem->getChannel((*channelIterator), &soundChannel);
236-
result = result == FMOD_OK ? soundChannel->setVolume(1 - distance) : result;
238+
result = result == FMOD_OK ? soundChannel->setVolume(1 - attenuation) : result;
237239
if (result != FMOD_OK) {
238240
g_ConsoleMan.PrintString("ERROR: Could not set sound attenuation for the sound being played on channel " + std::to_string(*channelIterator) + " for SoundContainer " + pSoundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
239241
}
@@ -429,13 +431,20 @@ namespace RTE {
429431
pitch = pSoundContainer->IsAffectedByGlobalPitch() ? m_GlobalPitch : pitch;
430432

431433
FMOD::Channel *channel;
434+
FMOD_RESULT result = FMOD_OK;
432435
int channelIndex;
433-
FMOD_RESULT result = m_AudioSystem->playSound(pSoundContainer->SelectNextSound(), m_SoundChannelGroup, true, &channel);
434-
result = result == FMOD_OK ? channel->getIndex(&channelIndex) : result;
435-
result = result == FMOD_OK ? channel->setUserData(pSoundContainer) : result;
436-
result = result == FMOD_OK ? channel->setCallback(SoundChannelEndedCallback) : result;
437-
result = result == FMOD_OK ? channel->setLoopCount(pSoundContainer->GetLoopSetting()) : result;
438-
result = result == FMOD_OK ? channel->setPriority(priority) : result;
436+
if (!pSoundContainer->SelectNextSounds()) {
437+
g_ConsoleMan.PrintString("Unable to select new sounds to play for SoundContainer " + pSoundContainer->GetPresetName() + ". No sounds will be played.");
438+
}
439+
440+
for (FMOD::Sound *sound : pSoundContainer->GetSelectedSoundObjects()) {
441+
result = result == FMOD_OK ? m_AudioSystem->playSound(sound, m_SoundChannelGroup, true, &channel) : result;
442+
result = result == FMOD_OK ? channel->getIndex(&channelIndex) : result;
443+
result = result == FMOD_OK ? channel->setUserData(pSoundContainer) : result;
444+
result = result == FMOD_OK ? channel->setCallback(SoundChannelEndedCallback) : result;
445+
result = result == FMOD_OK ? channel->setLoopCount(pSoundContainer->GetLoopSetting()) : result;
446+
result = result == FMOD_OK ? channel->setPriority(priority) : result;
447+
}
439448

440449
if (result != FMOD_OK) {
441450
g_ConsoleMan.PrintString("ERROR: Could not play sounds from SoundContainer " + pSoundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
@@ -461,7 +470,7 @@ namespace RTE {
461470

462471
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
463472

464-
bool AudioMan::StopSound(SoundContainer *pSoundContainer) {
473+
bool AudioMan::StopSound(SoundContainer *pSoundContainer, int player) {
465474
if (!m_AudioEnabled || !pSoundContainer) {
466475
return false;
467476
}
@@ -474,23 +483,16 @@ namespace RTE {
474483
std::unordered_set<unsigned short int> const *channels = pSoundContainer->GetPlayingChannels();
475484
for (std::unordered_set<unsigned short int>::iterator channelIterator = channels->begin(); channelIterator != channels->end();) {
476485
result = m_AudioSystem->getChannel((*channelIterator), &soundChannel);
486+
++channelIterator; // NOTE - stopping the sound will remove the channel, screwing things up if we don't move to the next iterator preemptively
477487
result = result == FMOD_OK ? soundChannel->stop() : result;
478488
if (result != FMOD_OK) {
479-
g_ConsoleMan.PrintString("Error: Failed to stop playing channel in SoundContainer "+pSoundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
489+
g_ConsoleMan.PrintString("Error: Failed to stop playing channel in SoundContainer " + pSoundContainer->GetPresetName() + ": " + std::string(FMOD_ErrorString(result)));
480490
}
481491

482492
}
483493
}
484-
return anySoundsPlaying;
485-
}
486-
487-
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
488494

489-
bool AudioMan::StopSound(SoundContainer *pSoundContainer, int player) {
490-
if (m_IsInMultiplayerMode && pSoundContainer) {
491-
RegisterSoundEvent(player, SOUND_STOP, pSoundContainer->GetHash(), 0, pSoundContainer->GetPlayingChannels(), pSoundContainer->GetLoopSetting(), 1.0, pSoundContainer->IsAffectedByGlobalPitch());
492-
}
493-
return StopSound(pSoundContainer);
495+
return anySoundsPlaying;
494496
}
495497

496498
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Managers/AudioMan.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ namespace RTE {
314314
/// </summary>
315315
/// <param name="pSound">Pointer to the SoundContainer to stop playing. Ownership is NOT transferred!</param>
316316
/// <returns>True if sounds were playing and were stopped, false otherwise.</returns>
317-
bool StopSound(SoundContainer *pSound);
317+
bool StopSound(SoundContainer *pSound) { return StopSound(pSound, -1); }
318318

319319
/// <summary>
320320
/// Stops playing all sounds in a given SoundContainer for a certain player.
@@ -410,6 +410,7 @@ namespace RTE {
410410
std::mutex g_SoundEventsListMutex[c_MaxClients]; //!< A list for locking sound events for multiplayer to avoid race conditions and other such problems.
411411

412412
private:
413+
413414
/// <summary>
414415
/// A static callback function for FMOD to invoke when the music channel finishes playing. See fmod docs - FMOD_SYSTEM_CALLBACK for details
415416
/// </summary>
@@ -429,7 +430,5 @@ namespace RTE {
429430
AudioMan(const AudioMan &reference);
430431
AudioMan & operator=(const AudioMan &rhs);
431432
};
432-
433-
std::mutex g_SoundEventsListMutex[c_MaxClients];
434433
}
435434
#endif

Managers/SettingsMan.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,6 @@ void SettingsMan::Clear()
7676

7777
m_UseNATService = false;
7878
m_DisableLoadingScreen = false;
79-
80-
m_AudioChannels = 512;
8179
}
8280

8381

@@ -271,8 +269,6 @@ int SettingsMan::ReadProperty(std::string propName, Reader &reader)
271269
reader >> m_ServerSleepWhenIdle;
272270
else if (propName == "ServerSimSleepWhenIdle")
273271
reader >> m_ServerSimSleepWhenIdle;
274-
else if (propName == "AudioChannels")
275-
reader >> m_AudioChannels;
276272
else if (propName == "DisableLoadingScreen")
277273
reader >> m_DisableLoadingScreen;
278274
else if (propName == "SoundVolume")
@@ -466,8 +462,6 @@ int SettingsMan::Save(Writer &writer) const
466462
writer.NewProperty("DisableLoadingScreen");
467463
writer << m_DisableLoadingScreen;
468464

469-
writer.NewProperty("AudioChannels");
470-
writer << m_AudioChannels;
471465
writer.NewProperty("SoundVolume");
472466
writer << g_AudioMan.GetSoundsVolume() * 100;
473467
writer.NewProperty("MusicVolume");

Managers/SettingsMan.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -567,8 +567,6 @@ class SettingsMan:
567567

568568
bool GetServerSimSleepWhenIdle() { return m_ServerSimSleepWhenIdle; }
569569

570-
int GetAudioChannels() { return m_AudioChannels; }
571-
572570
bool DisableLoadingScreen() { return m_DisableLoadingScreen; }
573571

574572

@@ -652,8 +650,6 @@ class SettingsMan:
652650

653651
bool m_ServerSimSleepWhenIdle;
654652

655-
int m_AudioChannels;
656-
657653
bool m_DisableLoadingScreen;
658654

659655
// List of assemblies groups always shown in editors

System/Constants.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ namespace RTE {
3535

3636
#pragma region Audio Constants
3737
static constexpr unsigned short int c_NumberOfAudioChannels = 512;
38+
static constexpr unsigned short int c_MaxPlayingSoundsPerContainer = 64;
3839
#pragma endregion
3940

4041
#pragma region Network Constants

0 commit comments

Comments
 (0)