diff --git a/src/C4Game.cpp b/src/C4Game.cpp index 0583a8aab..25f11f3e3 100644 --- a/src/C4Game.cpp +++ b/src/C4Game.cpp @@ -297,7 +297,7 @@ bool C4Game::PreInit() // this loads font definitions in this group as well // the function may return false, if no extra group is present - that is OK Extra.InitGroup(); - + Log(LoadResStr("IDS_PRC_GFXRES")); if (!GraphicsResource.Init()) return false; Game.SetInitProgress(30.0f); @@ -564,7 +564,7 @@ void C4Game::Clear() // exit gui pGUI->Clear(); - + // next mission (shoud have been transferred to C4Application now if next mission was desired) NextMission.Clear(); NextMissionText.Clear(); NextMissionDesc.Clear(); @@ -618,6 +618,7 @@ void C4Game::Clear() PlayerControlDefaultAssignmentSets.Clear(); PlayerControlDefs.Clear(); ::MeshMaterialManager.Clear(); + Application.SoundSystem.Init(); // clear it up and re-init it for normal use // global fullscreen class is not cleared, because it holds the carrier window // but the menu must be cleared (maybe move Fullscreen.Menu somewhere else?) @@ -2008,6 +2009,9 @@ bool C4Game::InitGame(C4Group &hGroup, bool fLoadSection, bool fLoadSky, C4Value { LogFatal(LoadResStr("IDS_PRC_FAIL")); return false; } SetInitProgress(25); + // Sound (first part, some are loaded with the definitions, the (section) local file goes later) + Application.SoundSystem.Init(); + // Definitions if (!InitDefs()) return false; SetInitProgress(55); @@ -2041,6 +2045,9 @@ bool C4Game::InitGame(C4Group &hGroup, bool fLoadSection, bool fLoadSky, C4Value SetInitProgress(60); } + // Load setion sounds + Application.SoundSystem.LoadEffects(hGroup); + // determine startup player count if (!FrameCounter) StartupPlayerCount = PlayerInfos.GetStartupCount(); diff --git a/src/platform/C4SoundSystem.cpp b/src/platform/C4SoundSystem.cpp index ae6df8239..f800179fc 100644 --- a/src/platform/C4SoundSystem.cpp +++ b/src/platform/C4SoundSystem.cpp @@ -43,9 +43,7 @@ using namespace C4SoundLoaders; C4SoundEffect::C4SoundEffect(): - UsageTime (0), Instances (0), - Static (false), pSample (NULL), FirstInst (NULL), Next (NULL) @@ -73,7 +71,7 @@ void C4SoundEffect::Clear() pSample = NULL; } -bool C4SoundEffect::Load(const char *szFileName, C4Group &hGroup, bool fStatic) +bool C4SoundEffect::Load(const char *szFileName, C4Group &hGroup) { // Sound check if (!Config.Sound.RXSound) return false; @@ -81,13 +79,13 @@ bool C4SoundEffect::Load(const char *szFileName, C4Group &hGroup, bool fStatic) StdBuf WaveBuffer; if (!hGroup.LoadEntry(szFileName, &WaveBuffer)) return false; // load it from mem - if (!Load((BYTE*)WaveBuffer.getData(), WaveBuffer.getSize(), fStatic)) return false; + if (!Load((BYTE*)WaveBuffer.getData(), WaveBuffer.getSize())) return false; // Set name SCopy(szFileName,Name,C4MaxSoundName); return true; } -bool C4SoundEffect::Load(BYTE *pData, size_t iDataLen, bool fStatic, bool fRaw) +bool C4SoundEffect::Load(BYTE *pData, size_t iDataLen, bool fRaw) { // Sound check if (!Config.Sound.RXSound) return false; @@ -121,9 +119,6 @@ bool C4SoundEffect::Load(BYTE *pData, size_t iDataLen, bool fStatic, bool fRaw) } } *Name = '\0'; - // Set usage time - UsageTime=Game.Time; - Static=fStatic; return !!pSample; } @@ -244,8 +239,6 @@ bool C4SoundInstance::Create(C4SoundEffect *pnEffect, bool fLoop, int32_t inVolu fLooping = fLoop; // Start Execute(); - // Safe usage - pEffect->UsageTime = Game.Time; return true; } @@ -453,6 +446,8 @@ bool C4SoundSystem::Init() // Open sound file if (!SoundFile.IsOpen()) if (!Reloc.Open(SoundFile, C4CFN_Sound)) return false; + // Load static sound from Sound.ocg + LoadEffects(SoundFile); #ifdef HAVE_LIBSDL_MIXER Mix_AllocateChannels(C4MaxSoundInstances); #endif @@ -483,90 +478,44 @@ void C4SoundSystem::Execute() #ifdef USE_OPEN_AL Application.MusicSystem.SelectContext(); #endif - // Sound effect statistics & unload check - C4SoundEffect *csfx,*next=NULL,*prev=NULL; - for (csfx=FirstSound; csfx; csfx=next) + C4SoundEffect *csfx; + for (csfx=FirstSound; csfx; csfx=csfx->Next) { - next=csfx->Next; // Instance removal check csfx->Execute(); - // Unload check - if (!csfx->Static && Game.Time-csfx->UsageTime > SoundUnloadTime && !csfx->FirstInst) - { - if (prev) prev->Next=next; - else FirstSound=next; - delete csfx; - } - else - prev=csfx; } } -int32_t C4SoundSystem::EffectInBank(const char *szSound) -{ - int32_t iResult = 0; - C4SoundEffect *pSfx; - char szName[C4MaxSoundName+4+1]; - // Compose name (with extension) - SCopy(szSound,szName,C4MaxSoundName); - DefaultExtension(szName,"*"); - // Count all matching sounds in bank - for (pSfx=FirstSound; pSfx; pSfx=pSfx->Next) - if (WildcardMatch(szName,pSfx->Name)) - iResult++; - return iResult; -} - -C4SoundEffect* C4SoundSystem::AddEffect(const char *szSoundName) -{ - C4SoundEffect *nsfx; - // Allocate new bank entry - if (!( nsfx=new C4SoundEffect )) return NULL; - // Load sound to entry - C4GRP_DISABLE_REWINDWARN // dynamic load; must rewind here :( - if (!nsfx->Load(szSoundName,SoundFile,false)) - if (!nsfx->Load(szSoundName,Game.ScenarioFile,false)) - { C4GRP_ENABLE_REWINDWARN delete nsfx; return NULL; } - C4GRP_ENABLE_REWINDWARN - // Add sound to bank - nsfx->Next=FirstSound; - FirstSound=nsfx; - return nsfx; -} - C4SoundEffect* C4SoundSystem::GetEffect(const char *szSndName) { - C4SoundEffect *pSfx; - char szName[C4MaxSoundName+4+1]; - int32_t iNumber; + C4SoundEffect *pSfx = NULL; + char szName[C4MaxSoundName+2]; + int32_t iNumber = 1; + // Remember wildcards before adding .* extension - if there are 2 versions with different file extensions, play the first + bool bRandomSound = SCharCount('?',szName) || SCharCount('*',szName); // Evaluate sound name SCopy(szSndName,szName,C4MaxSoundName); // Any extension accepted DefaultExtension(szName,"*"); // Sound with a wildcard: determine number of available matches - if (SCharCount('?',szName)) + if (bRandomSound) { - // Search global sound file - if (!(iNumber=SoundFile.EntryCount(szName))) - // Search scenario local files - if (!(iNumber=Game.ScenarioFile.EntryCount(szName))) - // Search bank loaded sounds - if (!(iNumber=EffectInBank(szName))) - // None found: failure - return NULL; - // Insert index to name - iNumber=BoundBy(1+SafeRandom(iNumber),1,9); - SReplaceChar(szName,'?','0'+iNumber); + iNumber = 0; + // Count matching sounds + for (pSfx=FirstSound; pSfx; pSfx=pSfx->Next) + if (WildcardMatch(szName,pSfx->Name)) + ++iNumber; + // Nothing found? Abort + if(iNumber == 0) + return NULL; + iNumber=SafeRandom(iNumber)+1; } // Find requested sound effect in bank for (pSfx=FirstSound; pSfx; pSfx=pSfx->Next) - if (SEqualNoCase(szName,pSfx->Name)) - break; - // Sound not in bank, try add - if (!pSfx) - if (!(pSfx = AddEffect(szName))) - return NULL; - return pSfx; + if (WildcardMatch(szName,pSfx->Name)) + if(!--iNumber) + break; + return pSfx; // Is still NULL if nothing is found } C4SoundInstance *C4SoundSystem::NewEffect(const char *szSndName, bool fLoop, int32_t iVolume, C4Object *pObj, int32_t iCustomFalloffDistance) @@ -582,10 +531,10 @@ C4SoundInstance *C4SoundSystem::NewEffect(const char *szSndName, bool fLoop, int C4SoundInstance *C4SoundSystem::FindInstance(const char *szSndName, C4Object *pObj) { - char szName[C4MaxSoundName+4+1]; + char szName[C4MaxSoundName+2]; // Evaluate sound name (see GetEffect) SCopy(szSndName,szName,C4MaxSoundName); - DefaultExtension(szName,"*"); + DefaultExtension(szName,"*"); // Find an effect with a matching instance for (C4SoundEffect *csfx = FirstSound; csfx; csfx = csfx->Next) if (WildcardMatch(szName, csfx->Name)) @@ -596,11 +545,17 @@ C4SoundInstance *C4SoundSystem::FindInstance(const char *szSndName, C4Object *pO return NULL; } -// LoadEffects will load all sound effects of all known sound types (i.e. *.wav and *.ogg) -// LoadEffects is currently used for static loading from object definitions only. +// LoadEffects will load all sound effects of all known sound types (i.e. *.wav and *.ogg) as defined in C4CFN_SoundFiles -int32_t C4SoundSystem::LoadEffects(C4Group &hGroup, bool fStatic) +int32_t C4SoundSystem::LoadEffects(C4Group &hGroup) { + // if there is a Sound.ocg in the group, load the sound from there + if(hGroup.FindEntry(C4CFN_Sound)) + { + C4Group g; + g.OpenAsChild(&hGroup, C4CFN_Sound, false, false); + return LoadEffects(g); + } int32_t iNum=0; char szFilename[_MAX_FNAME+1]; char szFileType[_MAX_FNAME+1]; @@ -614,7 +569,7 @@ int32_t C4SoundSystem::LoadEffects(C4Group &hGroup, bool fStatic) // Create and load effect if ((nsfx = new C4SoundEffect)) { - if (nsfx->Load(szFilename,hGroup,fStatic)) + if (nsfx->Load(szFilename,hGroup)) { // Overload same name effects RemoveEffect(szFilename); diff --git a/src/platform/C4SoundSystem.h b/src/platform/C4SoundSystem.h index 7136ca1b1..c34e44630 100644 --- a/src/platform/C4SoundSystem.h +++ b/src/platform/C4SoundSystem.h @@ -60,16 +60,15 @@ public: ~C4SoundEffect(); public: char Name[C4MaxSoundName+1]; - int32_t UsageTime, Instances; + int32_t Instances; int32_t SampleRate, Length; - bool Static; C4SoundHandle pSample; C4SoundInstance *FirstInst; C4SoundEffect *Next; public: void Clear(); - bool Load(const char *szFileName, C4Group &hGroup, bool fStatic); - bool Load(BYTE *pData, size_t iDataLen, bool fStatic, bool fRaw=false); // load directly from memory + bool Load(const char *szFileName, C4Group &hGroup); + bool Load(BYTE *pData, size_t iDataLen, bool fRaw=false); // load directly from memory void Execute(); C4SoundInstance *New(bool fLoop = false, int32_t iVolume = 100, C4Object *pObj = NULL, int32_t iCustomFalloffDistance = 0); C4SoundInstance *GetInstance(C4Object *pObj); @@ -124,7 +123,7 @@ public: ~C4SoundSystem(); void Clear(); void Execute(); - int32_t LoadEffects(C4Group &hGroup, bool fStatic = true); + int32_t LoadEffects(C4Group &hGroup); C4SoundInstance *NewEffect(const char *szSound, bool fLoop = false, int32_t iVolume = 100, C4Object *pObj = NULL, int32_t iCustomFalloffDistance = 0); C4SoundInstance *FindInstance(const char *szSound, C4Object *pObj); bool Init(); @@ -134,9 +133,7 @@ protected: C4SoundEffect *FirstSound; void ClearEffects(); C4SoundEffect* GetEffect(const char *szSound); - C4SoundEffect* AddEffect(const char *szSound); int32_t RemoveEffect(const char *szFilename); - int32_t EffectInBank(const char *szSound); }; class C4SoundInstance *StartSoundEffect(const char *szSndName, bool fLoop = false, int32_t iVolume = 100, C4Object *pObj=NULL, int32_t iCustomFalloffDistance=0);