forked from Mirrors/openclonk
C4SoundSystem: Load all sounds statically
Enable true wildcards in sound names Fix #680 / 115b63d14d54
parent
dab09d89d6
commit
74af3071e3
|
@ -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();
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue