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

Commit 3149d60

Browse files
committed
Added a bunch of features to SoundContainer - the ability to add groups and add sounds to specific groups (that way you can play compound sounds), the ability to set offsets and minimum audible distance and override attenuation start distance for individual sounds in sound groups, the ability to set cycle modes to choose how SelectNextSoundSet acts
Cleaned up various stuff in SoundContainer
1 parent b777d03 commit 3149d60

File tree

3 files changed

+264
-93
lines changed

3 files changed

+264
-93
lines changed

Entities/SoundContainer.cpp

Lines changed: 177 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,21 @@ namespace RTE {
55

66
CONCRETECLASSINFO(SoundContainer, Entity, 0);
77

8+
const std::unordered_map<std::string, SoundContainer::SoundCycleMode> SoundContainer::c_CycleModeMap = {
9+
{"Random", SoundContainer::SoundCycleMode::MODE_RANDOM},
10+
{"Forwards", SoundContainer::SoundCycleMode::MODE_FORWARDS}
11+
};
12+
813
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
914

1015
void SoundContainer::Clear() {
11-
m_Sounds.clear();
12-
m_SelectedSounds.clear();
16+
m_SoundSets.clear();
17+
m_SelectedSoundSet = 0;
18+
m_SoundSelectionCycleMode = MODE_RANDOM;
19+
1320
m_PlayingChannels.clear();
14-
m_AttenuationStartDistance = 1;
21+
22+
m_AttenuationStartDistance = c_DefaultAttenuationStartDistance;
1523
m_Loops = 0;
1624
m_Priority = AudioMan::PRIORITY_NORMAL;
1725
m_AffectedByGlobalPitch = true;
@@ -25,10 +33,16 @@ namespace RTE {
2533
int SoundContainer::Create(const SoundContainer &reference) {
2634
Entity::Create(reference);
2735

28-
for (std::vector<std::pair<ContentFile, FMOD::Sound *>>::const_iterator itr = reference.m_Sounds.begin(); itr != reference.m_Sounds.end(); ++itr) {
29-
m_Sounds.push_back(*itr);
36+
for (std::vector<SoundData> referenceSoundSet : reference.m_SoundSets) {
37+
std::vector<SoundData> soundSet;
38+
for (SoundData referenceData : referenceSoundSet) {
39+
soundSet.push_back(SoundData {referenceData.SoundFile, referenceData.SoundObject, referenceData.Offset, referenceData.MinimumAudibleDistance, referenceData.AttenuationStartDistance});
40+
}
41+
m_SoundSets.push_back(soundSet);
3042
}
31-
m_SelectedSounds = reference.m_SelectedSounds;
43+
m_SelectedSoundSet = reference.m_SelectedSoundSet;
44+
m_SoundSelectionCycleMode = reference.m_SoundSelectionCycleMode;
45+
3246
m_PlayingChannels.clear();
3347

3448
m_AttenuationStartDistance = reference.m_AttenuationStartDistance;
@@ -43,12 +57,15 @@ namespace RTE {
4357
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4458

4559
int SoundContainer::ReadProperty(std::string propName, Reader &reader) {
46-
if (propName == "AddSound") {
47-
ContentFile newFile;
48-
reader >> newFile;
49-
FMOD::Sound *pNewSample = newFile.GetAsSample();
50-
if (!pNewSample) { reader.ReportError(std::string("Failed to load the sample from the file")); }
51-
m_Sounds.push_back(std::pair<ContentFile, FMOD::Sound *>(newFile, pNewSample));
60+
if (propName == "AddSound" || propName == "AddSoundSet") {
61+
return ReadSoundSet(propName, reader);
62+
} else if (propName == "CycleMode") {
63+
std::string cycleModeString = reader.ReadPropValue();
64+
if (c_CycleModeMap.find(cycleModeString) != c_CycleModeMap.end()) {
65+
m_SoundSelectionCycleMode = c_CycleModeMap.find(cycleModeString)->second;
66+
} else {
67+
reader.ReportError("Cycle mode " + cycleModeString + " is invalid.");
68+
}
5269
} else if (propName == "AttenuationStartDistance") {
5370
reader >> m_AttenuationStartDistance;
5471
} else if (propName == "LoopSetting") {
@@ -69,8 +86,66 @@ namespace RTE {
6986
}
7087

7188
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
89+
90+
int SoundContainer::ReadSoundSet(std::string propName, Reader &reader) {
91+
vector<SoundData> soundSet;
92+
if (propName == "AddSound") {
93+
soundSet.push_back(ReadSound(reader));
94+
} else if (propName == "AddSoundSet") {
95+
reader.ReadPropValue();
96+
while (reader.NextProperty()) {
97+
std::string soundSetSubPropertyName = reader.ReadPropName();
98+
if (soundSetSubPropertyName == "AddSound") {
99+
soundSet.push_back(ReadSound(reader));
100+
} else {
101+
reader.ReportError(soundSetSubPropertyName + " is not a valid property of SoundSets.");
102+
}
103+
}
104+
}
105+
106+
m_SoundSets.push_back(soundSet);
107+
return 0;
108+
}
109+
110+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
111+
112+
SoundContainer::SoundData SoundContainer::ReadSound(Reader &reader) {
113+
std::string propValue = reader.ReadPropValue();
114+
SoundData soundData;
115+
116+
auto readSound = [](const std::string &soundPath, Reader &parentReader, SoundData *outSoundData) {
117+
ContentFile soundFile(soundPath.c_str());
118+
FMOD::Sound *soundObject = soundFile.GetAsSample();
119+
if (g_AudioMan.IsAudioEnabled() && !soundObject) { parentReader.ReportError(std::string("Failed to load the sound from the file")); }
120+
121+
outSoundData->SoundFile = soundFile;
122+
outSoundData->SoundObject = soundObject;
123+
};
124+
125+
if (propValue != "Sound" && propValue != "ContentFile") {
126+
readSound(propValue, reader, &soundData);
127+
return soundData;
128+
}
129+
130+
while (reader.NextProperty()) {
131+
std::string soundSubPropertyName = reader.ReadPropName();
132+
if (soundSubPropertyName == "FilePath" || soundSubPropertyName == "Path") {
133+
readSound(reader.ReadPropValue(), reader, &soundData);
134+
} else if (soundSubPropertyName == "Offset") {
135+
reader >> soundData.Offset;
136+
} else if (soundSubPropertyName == "MinimumAudibleDistance") {
137+
reader >> soundData.MinimumAudibleDistance;
138+
} else if (soundSubPropertyName == "AttenuationStartDistance") {
139+
reader >> soundData.AttenuationStartDistance;
140+
}
141+
}
72142

73-
void SoundContainer::AddSound(std::string const &soundFilePath, unsigned int soundSetIndex, const Vector &offset, float attenuationStartDistance, bool abortGameForInvalidSound) {
143+
return soundData;
144+
}
145+
146+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
147+
148+
void SoundContainer::AddSound(std::string const &soundFilePath, unsigned int soundSetIndex, const Vector &offset, float minimumAudibleDistance, float attenuationStartDistance, bool abortGameForInvalidSound) {
74149
vector<SoundData> soundSet;
75150
if (soundSetIndex < m_SoundSets.size()) { soundSet = m_SoundSets[soundSetIndex]; }
76151

@@ -80,7 +155,8 @@ namespace RTE {
80155
return;
81156
}
82157

83-
soundSet.push_back({soundFile, soundObject, offset, attenuationStartDistance});
158+
attenuationStartDistance = attenuationStartDistance < 0 ? c_DefaultAttenuationStartDistance : attenuationStartDistance;
159+
soundSet.push_back({soundFile, soundObject, offset, minimumAudibleDistance, attenuationStartDistance});
84160
if (soundSetIndex >= m_SoundSets.size()) { m_SoundSets.push_back(soundSet); }
85161

86162
m_AllSoundPropertiesUpToDate = false;
@@ -90,49 +166,59 @@ namespace RTE {
90166

91167
std::vector<size_t> SoundContainer::GetSelectedSoundHashes() {
92168
std::vector<size_t> soundHashes;
93-
for (size_t selectedSoundIndex : m_SelectedSounds) {
94-
soundHashes.push_back(m_Sounds[selectedSoundIndex].first.GetHash());
169+
for (SoundData selectedSoundData : m_SoundSets[m_SelectedSoundSet]) {
170+
soundHashes.push_back(selectedSoundData.SoundFile.GetHash());
95171
}
96172
return soundHashes;
97173
}
98174

99175
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
100-
101-
std::vector<FMOD::Sound *> SoundContainer::GetSelectedSoundObjects() {
102-
std::vector<FMOD::Sound *> soundObjects;
103-
for (size_t selectedSoundIndex : m_SelectedSounds) {
104-
soundObjects.push_back(m_Sounds[selectedSoundIndex].second);
176+
177+
SoundContainer::SoundData *SoundContainer::GetSoundDataForSound(FMOD::Sound *sound) {
178+
for (std::vector<SoundData> soundSet : m_SoundSets) {
179+
for (SoundData soundData : soundSet) {
180+
if (sound == soundData.SoundObject) {
181+
return &soundData;
182+
}
183+
}
105184
}
106-
return soundObjects;
185+
return NULL;
107186
}
108187

109188
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
110189

111-
bool SoundContainer::SelectNextSounds() {
112-
int soundCount = GetSoundCount();
113-
if (soundCount == 0) {
114-
return false;
115-
}
116-
size_t previouslySelectedSound = (m_SelectedSounds.size() > 0) ? m_SelectedSounds[0] : 0;
190+
bool SoundContainer::SelectNextSoundSet() {
191+
int soundSetCount = m_SoundSets.size();
192+
switch (soundSetCount) {
193+
case 0:
194+
return false;
195+
case 1:
196+
return true;
197+
case 2:
198+
m_SelectedSoundSet = (m_SelectedSoundSet + 1) % 2;
199+
break;
200+
default:
201+
auto selectRandomSound = [](int soundSetSize, size_t *outSelectedSoundSet) {
202+
size_t soundToSelect = floorf(static_cast<float>(soundSetSize) * PosRand());
203+
while (soundToSelect == *outSelectedSoundSet) {
204+
soundToSelect = floorf(static_cast<float>(soundSetSize) * PosRand());
205+
}
206+
*outSelectedSoundSet = soundToSelect;
207+
};
117208

118-
if (m_SelectedSounds.empty() || soundCount == 1) {
119-
m_SelectedSounds.clear();
120-
m_SelectedSounds.push_back(previouslySelectedSound);
121-
} else {
122-
m_SelectedSounds.clear();
123-
if (soundCount == 2) {
124-
m_SelectedSounds.push_back((previouslySelectedSound + 1) % soundCount);
125-
} else if (soundCount > 2) {
126-
size_t soundToSelect = floorf(static_cast<float>(soundCount) * PosRand());
127-
// Mix it up again if we got the same sound twice
128-
while (soundToSelect == previouslySelectedSound) {
129-
soundToSelect = floorf(static_cast<float>(soundCount) * PosRand());
209+
switch (m_SoundSelectionCycleMode) {
210+
case MODE_RANDOM:
211+
selectRandomSound(soundSetCount, &m_SelectedSoundSet);
212+
break;
213+
case MODE_FORWARDS:
214+
m_SelectedSoundSet = (m_SelectedSoundSet + 1) % soundSetCount;
215+
break;
216+
default:
217+
RTEAbort("Invalid sound cycle mode " + m_SoundSelectionCycleMode);
218+
break;
130219
}
131-
m_SelectedSounds.push_back(soundToSelect);
132-
}
220+
RTEAssert(m_SelectedSoundSet >= 0 && m_SelectedSoundSet < soundSetCount, "Failed to select next sound, either none was selected or the selected sound was invalid.");
133221
}
134-
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.");
135-
136222
return true;
137223
}
138224

@@ -141,19 +227,57 @@ namespace RTE {
141227
FMOD_RESULT SoundContainer::UpdateSoundProperties() {
142228
FMOD_RESULT result = FMOD_OK;
143229

144-
for (std::vector<std::pair<ContentFile, FMOD::Sound * >>::const_iterator itr = m_Sounds.begin(); itr != m_Sounds.end() && result == FMOD_OK; ++itr) {
145-
FMOD_MODE soundMode = (m_Loops == 0) ? FMOD_LOOP_OFF : FMOD_LOOP_NORMAL;
146-
if (m_Immobile) {
147-
soundMode |= FMOD_3D_HEADRELATIVE;
148-
m_AttenuationStartDistance = 100000;
149-
}
230+
for (std::vector<SoundData> &soundSet : m_SoundSets) {
231+
for (SoundData &soundData : soundSet) {
232+
FMOD_MODE soundMode = (m_Loops == 0) ? FMOD_LOOP_OFF : FMOD_LOOP_NORMAL;
233+
if (m_Immobile) {
234+
soundMode |= FMOD_3D_HEADRELATIVE;
235+
m_AttenuationStartDistance = c_SoundMaxAudibleDistance;
236+
} else {
237+
soundMode |= FMOD_3D_CUSTOMROLLOFF;
238+
}
239+
240+
result = (result == FMOD_OK) ? soundData.SoundObject->setMode(soundMode) : result;
241+
result = (result == FMOD_OK) ? soundData.SoundObject->setLoopCount(m_Loops) : result;
242+
if (m_Immobile) {
243+
result = (result == FMOD_OK) ? soundData.SoundObject->set3DMinMaxDistance(m_AttenuationStartDistance, c_SoundMaxAudibleDistance) : result;
244+
} else {
245+
//FMOD_VECTOR customRolloffPoints[10];
246+
//CalculateCustomRolloffPoints(soundData, customRolloffPoints, 10);
150247

151-
result = (result == FMOD_OK) ? itr->second->setMode(soundMode) : result;
152-
result = (result == FMOD_OK) ? itr->second->setLoopCount(m_Loops) : result;
153-
result = (result == FMOD_OK) ? itr->second->set3DMinMaxDistance(m_AttenuationStartDistance, 100000) : result;
248+
//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.
249+
soundData.CustomRolloffPoints[0] = FMOD_VECTOR{soundData.MinimumAudibleDistance, 0, 0};
250+
soundData.CustomRolloffPoints[1] = FMOD_VECTOR{soundData.AttenuationStartDistance < 0 ? m_AttenuationStartDistance : soundData.AttenuationStartDistance, 1, 0};
251+
result = (result == FMOD_OK) ? soundData.SoundObject->set3DCustomRolloff(soundData.CustomRolloffPoints, 2) : result;
252+
}
253+
}
154254
}
155255
m_AllSoundPropertiesUpToDate = result == FMOD_OK;
156256

157257
return result;
158258
}
259+
260+
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
261+
262+
//TODO this needs to be used or be deleted
263+
void SoundContainer::CalculateCustomRolloffPoints(const SoundData &soundDataToCalculateFor, FMOD_VECTOR *rolloffPoints, int numRolloffPoints) {
264+
int attenuationStartDistance = soundDataToCalculateFor.AttenuationStartDistance < 0 ? m_AttenuationStartDistance : soundDataToCalculateFor.AttenuationStartDistance;
265+
float currentDistance = attenuationStartDistance;
266+
float currentVolumeLevel = 1;
267+
268+
int i = 0;
269+
if (soundDataToCalculateFor.MinimumAudibleDistance > 0) {
270+
i = 2;
271+
currentDistance += soundDataToCalculateFor.MinimumAudibleDistance;
272+
rolloffPoints[0] = FMOD_VECTOR{0, 0, 0};
273+
rolloffPoints[1] = FMOD_VECTOR{soundDataToCalculateFor.MinimumAudibleDistance - 0.1F, 0, 0};
274+
}
275+
276+
for (i = (soundDataToCalculateFor.MinimumAudibleDistance > 0 ? 2 : 0); i < numRolloffPoints - 1; i++) {
277+
rolloffPoints[i] = FMOD_VECTOR{currentDistance, currentVolumeLevel, 0};
278+
currentDistance += attenuationStartDistance;
279+
currentVolumeLevel = currentDistance < c_SoundMaxAudibleDistance ? currentVolumeLevel * 0.5 : 0;
280+
}
281+
rolloffPoints[numRolloffPoints - 1] = FMOD_VECTOR{currentDistance, 0, 0};
282+
}
159283
}

0 commit comments

Comments
 (0)