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

Commit d9661ae

Browse files
committed
Added SoundContainer::Create that doesn't take any filepaths, to allow empty sound containers to be made. Useful for multiplayer and lua.
Added parameter to SoundContainer::AddSound and ContentFile::GetAsSample to allow it to send errors to console instead of aborting the game. Used this in AudioMan::PlaySound(filePath), since that's only ever called from lua (all internal stuff uses SoundContainer::Play)
1 parent 50fd9e5 commit d9661ae

File tree

5 files changed

+58
-30
lines changed

5 files changed

+58
-30
lines changed

Entities/SoundContainer.cpp

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,6 @@ namespace RTE {
3333
m_AffectedByGlobalPitch = reference.m_AffectedByGlobalPitch;
3434
m_Hash = reference.m_Hash;
3535

36-
return 0;
37-
}
38-
39-
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
40-
41-
int SoundContainer::Create(std::string samplePath, int loops, bool affectedByGlobalPitch) {
42-
m_AffectedByGlobalPitch = affectedByGlobalPitch;
43-
m_Loops = loops;
44-
AddSound(samplePath);
4536

4637
return 0;
4738
}
@@ -75,16 +66,17 @@ namespace RTE {
7566

7667
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
7768

78-
void SoundContainer::AddSound(std::string soundPath) {
69+
void SoundContainer::AddSound(std::string const soundPath, bool abortGameForInvalidSound) {
7970
ContentFile newFile(soundPath.c_str());
80-
m_Hash = newFile.GetHash();
8171

82-
FMOD::Sound *pNewSample = newFile.GetAsSample();
83-
FMOD_RESULT result = pNewSample->setMode(m_Loops == 0 ? FMOD_LOOP_OFF : FMOD_LOOP_NORMAL);
84-
result = result == FMOD_OK ? pNewSample->setLoopCount(m_Loops) : result;
72+
FMOD::Sound *newSample = newFile.GetAsSample(abortGameForInvalidSound);
73+
if (newSample) {
74+
FMOD_RESULT result = newSample->setMode(m_Loops == 0 ? FMOD_LOOP_OFF : FMOD_LOOP_NORMAL);
75+
result = result == FMOD_OK ? newSample->setLoopCount(m_Loops) : result;
76+
m_Sounds.push_back(std::pair<ContentFile, FMOD::Sound *>(newFile, newSample));
77+
}
78+
}
8579

86-
RTEAssert(pNewSample, "Failed to load the sample from the file");
87-
m_Sounds.push_back(std::pair<ContentFile, FMOD::Sound *>(newFile, pNewSample));
8880
}
8981

9082
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Entities/SoundContainer.h

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,28 @@ namespace RTE {
3636
int Create(const SoundContainer &reference);
3737

3838
/// <summary>
39-
/// Creates a SoundContainer and gives it a path to its first sample.
39+
/// Creates an empty SoundContainer with no sounds.
40+
/// </summary>
41+
/// <param name="loops">The number of times this SoundContainer's sounds will loop. 0 means play once. -1 means play infinitely until stopped.</param>
42+
/// <param name="affectedByGlobalPitch">Whether this SoundContainer's sounds' frequency will be affected by the global pitch.</param>
43+
/// <returns>An error return value signaling success or any particular failure. Anything below 0 is an error signal.</returns>
44+
int Create(int loops = 0, bool affectedByGlobalPitch = true) { m_Loops = loops; m_AffectedByGlobalPitch = affectedByGlobalPitch; return 0; }
45+
46+
/// <summary>
47+
/// Creates a SoundContainer and gives it a path to its first sound.
4048
/// </summary>
4149
/// <param name="soundPath">A path to the sound for this sound to have.</param>
4250
/// <param name="loops">The number of times this SoundContainer's sounds will loop. 0 means play once. -1 means play infinitely until stopped.</param>
4351
/// <param name="affectedByGlobalPitch">Whether this SoundContainer's sounds' frequency will be affected by the global pitch.</param>
4452
/// <returns>An error return value signaling success or any particular failure. Anything below 0 is an error signal.</returns>
45-
int Create(std::string soundPath, int loops = 0, bool affectedByGlobalPitch = true);
53+
int Create(std::string const soundPath, int loops = 0, bool affectedByGlobalPitch = true) { int result = Create(loops, affectedByGlobalPitch); AddSound(soundPath); return result; }
4654

4755
/// <summary>
4856
/// Adds a new Sound to this SoundContainer, loaded from a file.
4957
/// </summary>
5058
/// <param name="soundPath">A path to the new sound to add. This will be handled through PresetMan.</param>
51-
void AddSound(std::string soundPath);
59+
/// <param name="abortGameForInvalidSound">Whether to abort the game if the sound couldn't be added, or just show a console error. Default true.</param>
60+
void AddSound(std::string const soundPath, bool abortGameForInvalidSound = true);
5261
#pragma endregion
5362

5463
#pragma region Destruction

Managers/AudioMan.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -407,8 +407,13 @@ namespace RTE {
407407
double pitch = affectedByGlobalPitch ? m_GlobalPitch : pitchOrAffectedByGlobalPitch;
408408

409409
SoundContainer *newSoundContainer = new SoundContainer();
410-
newSoundContainer->Create(filePath, loops, affectedByGlobalPitch);
411-
PlaySound(newSoundContainer, attenuation, player, priority, pitch);
410+
newSoundContainer->Create(loops, affectedByGlobalPitch);
411+
newSoundContainer->AddSound(filePath, false);
412+
if (newSoundContainer->HasAnySounds()) {
413+
PlaySound(newSoundContainer, attenuation, player, priority, pitch);
414+
} else {
415+
delete newSoundContainer;
416+
}
412417

413418
return newSoundContainer;
414419
}

System/ContentFile.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "ContentFile.h"
22
#include "PresetMan.h"
3+
#include "ConsoleMan.h"
34

45
namespace RTE {
56

@@ -207,11 +208,12 @@ namespace RTE {
207208

208209
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
209210

210-
FMOD::Sound * ContentFile::GetAsSample() {
211+
FMOD::Sound * ContentFile::GetAsSample(bool abortGameForInvalidSound) {
211212
if (m_DataPath.empty()) {
212213
return 0;
213214
}
214215
FMOD::Sound *pReturnSample = 0;
216+
std::string errorMessage;
215217

216218
// Check if the file has already been read and loaded from the disk and, if so, use that data. Otherwise, load it
217219
std::map<std::string, FMOD::Sound *>::iterator itr = m_sLoadedSamples.find(m_DataPath);
@@ -223,31 +225,45 @@ namespace RTE {
223225
char *pRawData = 0;
224226

225227
if (separatorPos == m_DataPath.length()) {
226-
RTEAbort("There was no object name following first pound sign in the ContentFile's datafile path, which means there was no actual object defined. The path was:\n\n" + m_DataPath);
228+
errorMessage = "There was no object name following first pound sign in the sound ContentFile's datafile path, which means there was no actual object defined. The path was: ";
229+
if (abortGameForInvalidSound) { RTEAbort(errorMessage + "\n\n" + m_DataPath); }
230+
g_ConsoleMan.PrintString("ERROR: " + errorMessage + m_DataPath);
231+
return pReturnSample;
227232
} else if (separatorPos == -1) {
228233
// Open the file, allocate space for it, read it and load it in as a Sound object
229234
fileSize = file_size(m_DataPath.c_str());
230235
PACKFILE *pFile = pack_fopen(m_DataPath.c_str(), F_READ);
231-
RTEAssert(pFile && fileSize > 0, "Failed to load datafile object with following path and name:\n\n" + m_DataPath);
236+
237+
if (!pFile || fileSize <= 0) {
238+
errorMessage = "Failed to load sound file with following path and name: ";
239+
if (abortGameForInvalidSound) { RTEAbort(errorMessage + "\n\n" + m_DataPath); }
240+
g_ConsoleMan.PrintString("ERROR: " + errorMessage + m_DataPath);
241+
return pReturnSample;
242+
}
232243

233244
pRawData = new char[fileSize];
234245
int bytesRead = pack_fread(pRawData, fileSize, pFile);
235-
RTEAssert(bytesRead == fileSize, "Tried to read a file but couldn't read the same amount of data as the reported file size!");
246+
RTEAssert(bytesRead == fileSize, "Tried to read a sound file but couldn't read the same amount of data as the reported file size! The path and name were: \n\n" +m_DataPath);
236247

237-
// Setup fmod info, and make sure to use mode OPENMEMORY_POINT since we're doing the loading ContentFile instead of fmod
248+
// Setup fmod info, and make sure to use mode OPENMEMORY since we're doing the loading with ContentFile instead of fmod, and we're deleting the raw data after loading it
238249
FMOD_CREATESOUNDEXINFO soundInfo = {};
239250
soundInfo.cbsize = sizeof(FMOD_CREATESOUNDEXINFO);
240251
soundInfo.length = fileSize;
241252
//TODO Consider doing FMOD_CREATESAMPLE for dumping audio files into memory and FMOD_NONBLOCKING to async create sounds
242253
FMOD_RESULT result = g_AudioMan.GetAudioSystem()->createSound(pRawData, FMOD_OPENMEMORY, &soundInfo, &pReturnSample);
243254

244-
RTEAssert(result == FMOD_OK, "Unable to create sound " + m_DataPath);
255+
if (result != FMOD_OK) {
256+
errorMessage = "Unable to create sound because of FMOD error " + std::string(FMOD_ErrorString(result)) + ". Path and name was: ";
257+
if (abortGameForInvalidSound) { RTEAbort(errorMessage + "\n\n" + m_DataPath); }
258+
g_ConsoleMan.PrintString("ERROR: " + errorMessage + m_DataPath);
259+
return pReturnSample;
260+
}
245261

246262
// Deallocate the intermediary data and close the file stream
247263
delete[] pRawData;
248264
pack_fclose(pFile);
249265
} else if (separatorPos != m_DataPath.length() - 1) {
250-
RTEAbort("Loading sound samples from allegro datafiles isn't supported yet!");
266+
RTEAbort("Loading sounds from allegro datafiles isn't supported yet!");
251267
/*
252268
// Split the datapath into the path and the object name and load the datafile from them
253269
m_pDataFile = load_datafile_object(m_DataPath.substr(0, separatorPos).c_str(), m_DataPath.substr(separatorPos + 1).c_str());
@@ -256,7 +272,12 @@ namespace RTE {
256272
pReturnSample = (FMOD::Sound *)m_pDataFile->dat;
257273
*/
258274
}
259-
RTEAssert(pReturnSample, "Failed to load datafile object with following path and name:\n\n" + m_DataPath);
275+
if (!pReturnSample) {
276+
errorMessage = "Failed to load sound file with following path and name:";
277+
if (abortGameForInvalidSound) { RTEAbort(errorMessage + "\n\n" + m_DataPath); }
278+
g_ConsoleMan.PrintString("Error: " + errorMessage + m_DataPath);
279+
return pReturnSample;
280+
}
260281

261282
// Insert the Sound object into the map, PASSING OVER OWNERSHIP OF THE LOADED DATAFILE
262283
m_sLoadedSamples.insert(std::pair<std::string, FMOD::Sound *>(m_DataPath, pReturnSample));

System/ContentFile.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,9 @@ namespace RTE {
190190
/// <summary>
191191
/// Loads and gets the data represented by this ContentFile object as an FMOD FSOUND_SAMPLE. Note that ownership of the SAMPLE IS NOT TRANSFERRED!
192192
/// </summary>
193+
/// <param name="abortGameForInvalidSound">Whether to abort the game if the sound couldn't be added, or just show a console error. Default true.</param>
193194
/// <returns>The pointer to the beginning of the data object loaded from the file. Ownership is NOT transferred! If 0, the file could not be found/loaded.</returns>
194-
virtual FMOD::Sound * GetAsSample();
195+
virtual FMOD::Sound * GetAsSample(bool abortGameForInvalidSound = true);
195196

196197
/// <summary>
197198
/// Loads and gets the data represented by this ContentFile object as a binary chunk of data. Note that ownership of the DATA IS NOT TRANSFERRED!

0 commit comments

Comments
 (0)