Files
FC1/CrySoundSystem/MusicSystem.h
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

291 lines
9.6 KiB
C++

#pragma once
#include <vector>
#include <isound.h>
#include <itimer.h>
#include <SmartPtr.h>
#include "MusicPattern.h"
#include "RandGen.h"
//#define TRACE_MUSIC
#ifdef TRACE_MUSIC
#define MTRACE TRACE
#else
#define MTRACE __noop
#endif
#define PATTERNSET_CHANGE_FADETIME 2.0
// Forward declarations
struct ISystem;
// Smart Pattern-Ptr
typedef _smart_ptr<CMusicPatternInstance> TPatternInstancePtr;
// Type of blending
enum EBlendingType
{
EBlend_FadeOut,
EBlend_ToEnd,
EBlend_Stop
};
// Info-Structure for automated fading
struct SMusicPatternPlayInfo
{
SMusicPatternPlayInfo()
{
nLayer=MUSICLAYER_MAIN;
pPatternInstance=NULL;
eBlendType=EBlend_ToEnd;
pRefCount=NULL;
fPhase=1.0;
fFadeTime=0.0; // use default fade time...
bRefCountAdjusted=false;
}
~SMusicPatternPlayInfo()
{
pPatternInstance=NULL;
}
TPatternInstancePtr pPatternInstance;
int nLayer;
EBlendingType eBlendType;
int *pRefCount;
// internal
double fPhase; // phase for fading (0-1)
double fFadeTime; // time in seconds to fade
bool bRefCountAdjusted;
};
//////////////////////////////////////////////////////////////////////////
// A couple of typedefs for various stl-containers
//////////////////////////////////////////////////////////////////////////
typedef std::map<string,CMusicPattern*,stl::less_stricmp<string> > TPatternMap;
typedef TPatternMap::iterator TPatternMapIt;
typedef std::vector<string> TStringVec;
typedef TStringVec::iterator TStringVecIt;
typedef std::vector<SMusicPatternPlayInfo> TPatternPlayInfoVec;
typedef TPatternPlayInfoVec::iterator TPatternPlayInfoVecIt;
//////////////////////////////////////////////////////////////////////////
// Structure to collect/handle mood-events
//////////////////////////////////////////////////////////////////////////
struct SMoodEventInfo
{
bool operator<(const SMoodEventInfo &b) const
{
if (stricmp(sMood.c_str(),b.sMood.c_str()) < 0)
return true;
return false;
}
string sMood;// name of mood
float fTime; // time of consecutive event-occurance
};
typedef std::set<SMoodEventInfo> TMoodEventSet;
typedef TMoodEventSet::iterator TMoodEventSetIt;
//////////////////////////////////////////////////////////////////////////
// The MusicSystem itself
//////////////////////////////////////////////////////////////////////////
class CMusicSystem : public IMusicSystem
{
protected:
CRITICAL_SECTION m_CS;
// system pointers
ISystem *m_pSystem;
ITimer *m_pTimer;
ILog *m_pLog;
ISoundSystem *m_pSoundSystem;
// random generator
CPseudoRandGen m_RandGen;
// notification sink
IMusicSystemSink *m_pSink;
// current data (allocated externally)
SMusicData *m_pDataPtr;
bool m_bOwnMusicData;
// sound-playback params
float m_fMasterVolume;
int m_nSampleRate;
float m_fLatency;
// bytes/sample in output stream
int m_nBytesPerSample;
// fmod stream data
CS_STREAM *m_pStream;
int m_nChannel;
// states
bool m_bDataLoaded;
bool m_bPause;
bool m_bPlaying;
bool m_bBridging; // bridging in progress
bool m_bCurrPatternIsBridge;
bool m_bForcePatternChange; // change pattern asap (next fadepoint), do not play to the end (last fadepoint)
// status
SMusicSystemStatus m_Status;
// all patterns
TPatternMap m_mapPatterns;
// current patterns
TPatternInstancePtr m_pCurrPattern;
TPatternInstancePtr m_pNextPattern;
int m_nLayeredRhythmicPatterns;
int m_nLayeredIncidentalPatterns;
// temporary mix-buffer
void *m_pMixBuffer;
// array of currently playing patterns
TPatternPlayInfoVec m_vecPlayingPatterns;
// all themes (moods inside)
TThemeMap m_mapThemes;
// current theme/mood
SMusicTheme *m_pThemeOverride; // overriding theme (eg. for vehicle)
SMusicTheme *m_pCurrTheme;
SMusicTheme *m_pNextTheme; // in case a theme change occured, this is the new theme... NULL otherwise
SMusicMood *m_pCurrMood;
SMusicMood *m_pNextMood;
// mood event arrays
TMoodEventSet m_setMoodEvents; // active mood events
TMoodEventSet m_setFrameMoodEvents; // mood events arrived last frame
// default mood
//SMusicMood *m_pDefaultMood;
float m_fDefaultMoodTime; // current time 'till default-mood-timeout
string m_sDefaultMood; // override of theme-specific default-mood (set by SetDefaultMood); set to "" to use theme-specific
// fading
double m_fCurrCrossfadeTime;
// logging
TStringVec m_vecLog;
bool m_bEnableEventProcessing;
ICVar *m_pCVarDebugMusic;
ICVar *m_pCVarMusicEnable;
ICVar *m_pCVarMusicMaxSimultaniousPatterns;
ICVar *m_pCVarMusicStreamedData;
int m_musicEnable;
protected:
virtual ~CMusicSystem();
bool Init();
void Shutdown();
void FlushLog();
CMusicPattern* AddPattern(const char *pszName, const char *pszFilename);
bool FlushPatterns();
bool StartPlaying();
bool StopPlaying();
SMusicMood* GetMood(SMusicTheme *pTheme, const char *pszMood);
bool SetTheme(SMusicTheme *pNewTheme, bool bOverride);
bool SetMood(SMusicMood *pNewMood);
SMusicMood* GetDefaultMood(SMusicTheme *pTheme);
void PushPatternToMixList(SMusicPatternPlayInfo &PlayInfo);
void EnterDefaultMood();
void Silence();
void AdjustMixStreamsRefCount(int nSamples);
void MixStreams(void *pBuffer, int nLength);
bool FadeStream(SMusicPatternPlayInfo &PlayInfo, signed short *pBuffer, int nSamples);
void FadeOutAllSecondaryLayers(double fFadeTime);
CMusicPatternInstance* GetPatternInstance(const char *pszPattern);
bool UpdateCurrentPatternSet(SMusicMood *pMood, int nSamples, bool bAllowChange);
bool ChoosePatternSet(SMusicMood *pMood);
CMusicPatternInstance* ChooseBridge(SMusicTheme *pCurrTheme, SMusicTheme *pNewTheme);
CMusicPatternInstance* ChoosePattern(SMusicMood *pMood, int nLayer=MUSICLAYER_MAIN);
signed char StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength);
//friend signed char __cdecl _StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength, INT_PTR nParam);
#ifndef CS_VERSION_372
#ifdef CS_VERSION_361
friend signed char F_CALLBACKAPI _StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength, int nParam);
#else
friend signed char F_CALLBACKAPI _StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength, INT_PTR nParam);
#endif
#else
friend signed char F_CALLBACKAPI _StreamingCallback(CS_STREAM *pStream, void *pBuffer, int nLength, void * nParam);
#endif
friend class CMusicLoadSink;
public:
CMusicSystem(ISystem *pSystem);
void Release();
ISystem* GetSystem() { return m_pSystem; }
int GetBytesPerSample() { return m_nBytesPerSample; }
IMusicSystemSink* SetSink(IMusicSystemSink *pSink);
bool SetData(struct SMusicData *pMusicData,bool bNoRelease=false);
void ReleaseData();
void Unload();
void Pause(bool bPause);
void EnableEventProcessing(bool bEnable) { m_bEnableEventProcessing=bEnable; }
bool ResetThemeOverride();
bool SetTheme(const char *pszTheme, bool bOverride=false);
const char* GetTheme() { if (m_pCurrTheme) return m_pCurrTheme->sName.c_str(); return ""; }
bool SetMood(const char *pszMood);
bool SetDefaultMood(const char *pszMood);
const char* GetMood() { if (m_pCurrMood) return m_pCurrMood->sName.c_str(); return ""; }
IStringItVec* GetThemes();
IStringItVec* GetMoods(const char *pszTheme);
bool AddMusicMoodEvent(const char *pszMood, float fTimeout);
void Update();
SMusicSystemStatus* GetStatus(); // retrieve status of music-system... dont keep returning pointer !
//! compute memory-consumption
void GetMemoryUsage(class ICrySizer* pSizer);
bool LoadMusicDataFromLUA(IScriptSystem* pScriptSystem, const char *pszFilename);
bool StreamOGG();
void LogMsg( const char *pszFormat, ... );
//////////////////////////////////////////////////////////////////////////
//! Load music data from XML.
//! @param bAddAdata if true data from XML will be added to currently loaded music data.
bool LoadFromXML( const char *sFilename,bool bAddData );
//////////////////////////////////////////////////////////////////////////
// Editing support.
//////////////////////////////////////////////////////////////////////////
virtual void UpdateTheme( SMusicTheme *pTheme );
virtual void UpdateMood( SMusicMood *pMood );
virtual void UpdatePattern( SPatternDef *pPattern );
virtual void RenamePattern( const char *sOldName,const char *sNewName );
virtual void PlayPattern( const char *sPattern,bool bStopPrevious );
virtual void DeletePattern( const char *sPattern );
private:
//////////////////////////////////////////////////////////////////////////
// Loading.
//////////////////////////////////////////////////////////////////////////
void LoadPatternFromXML( XmlNodeRef node,SPatternDef *pPattern );
void LoadMoodFromXML( XmlNodeRef &node,SMusicMood *pMood );
void LoadThemeFromXML( XmlNodeRef &node,SMusicTheme *pTheme );
};
//////////////////////////////////////////////////////////////////////////
// String-vector-class to iterate data from other DLLs
//////////////////////////////////////////////////////////////////////////
class CStringItVec : public IStringItVec
{
public:
CStringItVec(TStringVec &Vec)
{
m_nRefCount=0;
m_Vec=Vec;
MoveFirst();
};
bool IsEnd() { return (m_itVec==m_Vec.end()); };
const char* Next() { return IsEnd() ? "" : (*m_itVec++).c_str(); };
void MoveFirst() { m_itVec = m_Vec.begin(); };
void AddRef() { m_nRefCount++; }
void Release() { --m_nRefCount; if (m_nRefCount<=0) { delete this; } };
protected:
int m_nRefCount;
TStringVec m_Vec;
TStringVecIt m_itVec;
};
//////////////////////////////////////////////////////////////////////////
// SmartCriticalSection-class to make things easier
//////////////////////////////////////////////////////////////////////////
class CSmartCriticalSection
{
private:
CRITICAL_SECTION *m_pCS;
public:
CSmartCriticalSection(CRITICAL_SECTION &CS) { m_pCS=&CS; EnterCriticalSection(m_pCS); }
~CSmartCriticalSection() { LeaveCriticalSection(m_pCS); }
};