1
1
#include " SoundSet.h"
2
+ #include " AudioMan.h"
3
+ #include " RTETools.h"
4
+ #include " RTEError.h"
2
5
3
6
namespace RTE {
4
7
5
8
const std::string SoundSet::m_sClassName = " SoundSet" ;
6
9
7
- const std::unordered_map<std::string, SoundContainer::SoundCycleMode> SoundContainer::c_SoundCycleModeMap = {
8
- {" Random" , SoundSet::SoundCycleMode ::RANDOM},
9
- {" Forwards" , SoundSet::SoundCycleMode ::FORWARDS},
10
- {" All" , SoundSet::SoundCycleMode ::ALL}
10
+ const std::unordered_map<std::string, SoundSet::SoundSelectionCycleMode> SoundSet::c_SoundSelectionCycleModeMap = {
11
+ {" Random" , SoundSelectionCycleMode ::RANDOM},
12
+ {" Forwards" , SoundSelectionCycleMode ::FORWARDS},
13
+ {" All" , SoundSelectionCycleMode ::ALL}
11
14
};
12
15
13
16
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
14
17
15
18
void SoundSet::Clear () {
16
19
m_SoundSelectionCycleMode = SoundSelectionCycleMode::RANDOM;
17
- m_CurrentSelection. clear () ;
20
+ m_CurrentSelection = { false , 0 } ;
18
21
19
22
m_SoundData.clear ();
20
23
m_SubSoundSets.clear ();
@@ -28,7 +31,7 @@ namespace RTE {
28
31
for (SoundData referenceSoundData : reference.m_SoundData ) {
29
32
m_SoundData.push_back (referenceSoundData);
30
33
}
31
- for (const SoundSet &referenceSoundSet : reference.m_SoundSets ) {
34
+ for (const SoundSet &referenceSoundSet : reference.m_SubSoundSets ) {
32
35
SoundSet soundSet;
33
36
soundSet.Create (referenceSoundSet);
34
37
m_SubSoundSets.push_back (soundSet);
@@ -43,7 +46,7 @@ namespace RTE {
43
46
if (propName == " SoundSelectionCycleMode" || propName == " CycleMode" ) {
44
47
m_SoundSelectionCycleMode = ReadSoundSelectionCycleMode (reader);
45
48
} else if (propName == " AddSound" ) {
46
- AddSoundData (ReadAndGetSound (reader));
49
+ AddSoundData (ReadAndGetSoundData (reader));
47
50
} else if (propName == " AddSoundSet" || propName == " AddSubSoundSet" ) {
48
51
SoundSet subSoundSet;
49
52
reader >> subSoundSet;
@@ -56,14 +59,14 @@ namespace RTE {
56
59
57
60
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58
61
59
- static SoundData ReadAndGetSound (Reader &reader) {
60
- SoundData soundData;
62
+ SoundSet:: SoundData SoundSet::ReadAndGetSoundData (Reader &reader) {
63
+ SoundSet:: SoundData soundData;
61
64
62
65
// / <summary>
63
66
// / Internal lambda function to load an audio file by path in as a ContentFile, which in turn loads it into FMOD, then returns SoundData for it in the outParam outSoundData.
64
67
// / </summary>
65
68
// / <param name="soundPath">The path to the sound file.</param>
66
- auto readSoundDirectlyFromPath = [&soundData, &reader](const std::string &soundPath) {
69
+ auto readSoundFromPath = [&soundData, &reader](const std::string &soundPath) {
67
70
ContentFile soundFile (soundPath.c_str ());
68
71
soundFile.SetFormattedReaderPosition (" in file " + reader.GetCurrentFilePath () + " on line " + std::to_string (reader.GetCurrentFileLine ()));
69
72
FMOD::Sound *soundObject = soundFile.GetAsSound ();
@@ -75,14 +78,14 @@ namespace RTE {
75
78
76
79
std::string propValue = reader.ReadPropValue ();
77
80
if (propValue != " Sound" && propValue != " ContentFile" ) {
78
- readSoundDirectlyFromPath (propValue);
81
+ readSoundFromPath (propValue);
79
82
return soundData;
80
83
}
81
84
82
85
while (reader.NextProperty ()) {
83
86
std::string soundSubPropertyName = reader.ReadPropName ();
84
87
if (soundSubPropertyName == " FilePath" || soundSubPropertyName == " Path" ) {
85
- readSound (reader.ReadPropValue ());
88
+ readSoundFromPath (reader.ReadPropValue ());
86
89
} else if (soundSubPropertyName == " Offset" ) {
87
90
reader >> soundData.Offset ;
88
91
} else if (soundSubPropertyName == " MinimumAudibleDistance" ) {
@@ -97,15 +100,16 @@ namespace RTE {
97
100
98
101
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
99
102
100
- static SoundSelectionCycleMode SoundSet::ReadSoundSelectionCycleMode (const Reader &reader) {
101
- std::string cycleModeString = reader.ReadPropValue ();
102
- SoundSelectionCycleMode soundSelectionCycleMode = SoundSelectionCycleMode::RANDOM;
103
- if (c_SoundCycleModeMap.find (cycleModeString) != c_SoundCycleModeMap.end ()) {
104
- soundSelectionCycleMode = c_SoundCycleModeMap.find (cycleModeString)->second ;
105
- } else {
106
- reader.ReportError (" Cycle mode " + cycleModeString + " is invalid." );
103
+ SoundSet::SoundSelectionCycleMode SoundSet::ReadSoundSelectionCycleMode (Reader &reader) {
104
+ std::string soundSelectionCycleModeString = reader.ReadPropValue ();
105
+
106
+ std::unordered_map<std::string, SoundSelectionCycleMode>::const_iterator soundSelectionCycleMode = c_SoundSelectionCycleModeMap.find (soundSelectionCycleModeString);
107
+ if (soundSelectionCycleMode != c_SoundSelectionCycleModeMap.end ()) {
108
+ return soundSelectionCycleMode->second ;
107
109
}
108
- return soundSelectionCycleMode;
110
+
111
+ reader.ReportError (" Sound selection cycle mode " + soundSelectionCycleModeString + " is invalid." );
112
+ return SoundSelectionCycleMode::RANDOM;
109
113
}
110
114
111
115
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -114,7 +118,7 @@ namespace RTE {
114
118
Serializable::Save (writer);
115
119
116
120
writer.NewProperty (" SoundSelectionCycleMode" );
117
- SaveSoundSelectionCycleMode (m_SoundSelectionCycleMode);
121
+ SaveSoundSelectionCycleMode (writer, m_SoundSelectionCycleMode);
118
122
119
123
for (const SoundData &soundData : m_SoundData) {
120
124
writer.NewProperty (" AddSound" );
@@ -144,9 +148,9 @@ namespace RTE {
144
148
145
149
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
146
150
147
- static void SoundSet::SaveSoundSelectionCycleMode (Writer &writer, SoundSelectionCycleMode soundSelectionCycleMode) {
148
- std::list<std::pair<const std::string, SoundCycleMode >>::const_iterator cycleModeMapEntry = std::find_if (c_SoundCycleModeMap .begin (), c_SoundCycleModeMap .end (), [&soundSelectionCycleMode = soundSelectionCycleMode](auto element) { return element.second == soundSelectionCycleMode; });
149
- if (cycleModeMapEntry != c_SoundCycleModeMap .end ()) {
151
+ void SoundSet::SaveSoundSelectionCycleMode (Writer &writer, SoundSelectionCycleMode soundSelectionCycleMode) {
152
+ std::list<std::pair<const std::string, SoundSelectionCycleMode >>::const_iterator cycleModeMapEntry = std::find_if (c_SoundSelectionCycleModeMap .begin (), c_SoundSelectionCycleModeMap .end (), [&soundSelectionCycleMode = soundSelectionCycleMode](auto element) { return element.second == soundSelectionCycleMode; });
153
+ if (cycleModeMapEntry != c_SoundSelectionCycleModeMap .end ()) {
150
154
writer << cycleModeMapEntry->first ;
151
155
} else {
152
156
RTEAbort (" Tried to write invalid SoundSelectionCycleMode when saving SoundContainer/SoundSet." );
@@ -168,8 +172,8 @@ namespace RTE {
168
172
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
169
173
170
174
bool SoundSet::HasAnySounds (bool includeSubSoundSets) const {
171
- bool hasAnySounds = !m_SoundSets .empty ();
172
- if (!hasAySounds && includeSubSoundSets) {
175
+ bool hasAnySounds = !m_SoundData .empty ();
176
+ if (!hasAnySounds && includeSubSoundSets) {
173
177
for (const SoundSet &subSoundSet : m_SubSoundSets) {
174
178
hasAnySounds = subSoundSet.HasAnySounds ();
175
179
if (hasAnySounds) { break ; }
@@ -180,55 +184,96 @@ namespace RTE {
180
184
181
185
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
182
186
183
- void SoundSet::GetFlattenedSoundData (std::vector<SoundData *> &flattenedSoundData, bool onlyGetSelectedSoundData) const {
187
+ void SoundSet::GetFlattenedSoundData (std::vector<SoundData *> &flattenedSoundData, bool onlyGetSelectedSoundData) {
184
188
if (!onlyGetSelectedSoundData || m_SoundSelectionCycleMode == SoundSelectionCycleMode::ALL) {
185
189
for (SoundData &soundData : m_SoundData) { flattenedSoundData.push_back (&soundData); }
190
+ for (SoundSet &subSoundSet : m_SubSoundSets) { subSoundSet.GetFlattenedSoundData (flattenedSoundData, onlyGetSelectedSoundData); }
191
+ } else {
192
+ if (m_CurrentSelection.first == false ) {
193
+ flattenedSoundData.push_back (&m_SoundData[m_CurrentSelection.second ]);
194
+ } else {
195
+ m_SubSoundSets[m_CurrentSelection.second ].GetFlattenedSoundData (flattenedSoundData, onlyGetSelectedSoundData);
196
+ }
197
+ }
198
+ }
199
+
200
+ // ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
201
+
202
+ void SoundSet::GetFlattenedSoundData (std::vector<const SoundData *> &flattenedSoundData, bool onlyGetSelectedSoundData) const {
203
+ if (!onlyGetSelectedSoundData || m_SoundSelectionCycleMode == SoundSelectionCycleMode::ALL) {
204
+ for (const SoundData &soundData : m_SoundData) { flattenedSoundData.push_back (&soundData); }
186
205
for (const SoundSet &subSoundSet : m_SubSoundSets) { subSoundSet.GetFlattenedSoundData (flattenedSoundData, onlyGetSelectedSoundData); }
187
206
} else {
188
207
if (m_CurrentSelection.first == false ) {
189
208
flattenedSoundData.push_back (&m_SoundData[m_CurrentSelection.second ]);
190
209
} else {
191
- m_CurrentSelection.second .GetFlattenedSoundData (flattenedSoundData, onlyGetSelectedSoundData);
210
+ m_SubSoundSets[ m_CurrentSelection.second ] .GetFlattenedSoundData (flattenedSoundData, onlyGetSelectedSoundData);
192
211
}
193
212
}
194
213
}
195
214
196
215
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
197
216
198
- bool SoundSet::SelectNextSoundSet () const {
199
- int soundSetCount = m_SoundSets.size ();
200
- switch (soundSetCount) {
217
+ bool SoundSet::SelectNextSounds () {
218
+ if (m_SoundSelectionCycleMode == SoundSelectionCycleMode::ALL) {
219
+ return true ;
220
+ }
221
+ int selectedVectorSize = m_CurrentSelection.first == false ? m_SoundData.size () : m_SubSoundSets.size ();
222
+ int unselectedVectorSize = m_CurrentSelection.first == true ? m_SoundData.size () : m_SubSoundSets.size ();
223
+ int soundDataAndSetSize = selectedVectorSize + unselectedVectorSize;
224
+
225
+ // / <summary>
226
+ // / Internal lambda function to pick a random sound that's not the previously played sound. Done to avoid scoping issues inside the switch below.
227
+ // / </summary>
228
+ auto selectSoundRandom = [&selectedVectorSize, &unselectedVectorSize, this ]() {
229
+ if (selectedVectorSize == 1 || RandomNum (0 , 1 ) == 1 ) {
230
+ std::swap (selectedVectorSize, unselectedVectorSize);
231
+ m_CurrentSelection = {!m_CurrentSelection.first , RandomNum (0 , selectedVectorSize - 1 )};
232
+ } else {
233
+ size_t soundToSelect = RandomNum (0 , selectedVectorSize - 1 );
234
+ while (soundToSelect == m_CurrentSelection.second ) {
235
+ soundToSelect = RandomNum (0 , selectedVectorSize - 1 );
236
+ }
237
+ m_CurrentSelection.second = soundToSelect;
238
+ }
239
+ };
240
+
241
+ // / <summary>
242
+ // / Internal lambda function to pick the next sound in the forwards direction.
243
+ // / </summary>
244
+ auto selectSoundForwards = [&selectedVectorSize, &unselectedVectorSize, this ]() {
245
+ m_CurrentSelection.second ++;
246
+ if (m_CurrentSelection.second > selectedVectorSize) {
247
+ m_CurrentSelection = {!m_CurrentSelection.first , 0 };
248
+ std::swap (selectedVectorSize, unselectedVectorSize);
249
+ if (selectedVectorSize == 0 ) {
250
+ m_CurrentSelection.first = !m_CurrentSelection.first ;
251
+ std::swap (selectedVectorSize, unselectedVectorSize);
252
+ }
253
+ }
254
+ };
255
+
256
+ switch (soundDataAndSetSize) {
201
257
case 0 :
202
258
return false ;
203
259
case 1 :
204
260
return true ;
205
261
case 2 :
206
- m_SelectedSoundSet = (m_SelectedSoundSet + 1 ) % 2 ;
262
+ selectSoundForwards () ;
207
263
break ;
208
264
default :
209
- // / <summary>
210
- // / Internal lambda function to pick a random sound that's not the previously played sound. Done to avoid scoping issues inside the switch below.
211
- // / </summary>
212
- auto selectRandomSound = [&soundSetCount, this ]() {
213
- size_t soundToSelect = RandomNum (0 , soundSetCount - 1 );
214
- while (soundToSelect == m_SelectedSoundSet) {
215
- soundToSelect = RandomNum (0 , soundSetCount - 1 );
216
- }
217
- m_SelectedSoundSet = soundToSelect;
218
- };
219
-
220
265
switch (m_SoundSelectionCycleMode) {
221
- case RANDOM:
222
- selectRandomSound ();
266
+ case SoundSelectionCycleMode:: RANDOM:
267
+ selectSoundRandom ();
223
268
break ;
224
- case FORWARDS:
225
- m_SelectedSoundSet = (m_SelectedSoundSet + 1 ) % soundSetCount ;
269
+ case SoundSelectionCycleMode:: FORWARDS:
270
+ selectSoundForwards () ;
226
271
break ;
227
272
default :
228
- RTEAbort (" Invalid sound cycle mode " + m_SoundSelectionCycleMode );
273
+ RTEAbort (" Invalid sound selection sound cycle mode. " );
229
274
break ;
230
275
}
231
- RTEAssert (m_SelectedSoundSet >= 0 && m_SelectedSoundSet < soundSetCount , " Failed to select next sound, either none was selected or the selected sound was invalid." );
276
+ RTEAssert (m_CurrentSelection. second >= 0 && m_CurrentSelection. second < selectedVectorSize , " Failed to select next sound, either none was selected or the selected sound was invalid." );
232
277
}
233
278
return true ;
234
279
}
0 commit comments