#pragma once #include "audio/ALAudioSystem.h" #include "audio/ALAudioSource.h" #include "audio/ALListener.h" #include "AudioDef.h" typedef int GSID; class CAudioInterface { struct Source { AudioSource* NiSource; DWORD IdelTime; // if IdelTime > 0 表示已经处于空闲状态. }; enum { MUSIC_FADE_TIME = 200, // 200 ms MAX_SOURCES = 64, MAX_UISOURCE =32, }; public: CAudioInterface(void); ~CAudioInterface(void); BOOL Initialize(HWND hWnd); void Destroy(); void ReleaseAllSource(); void ReleaseIdelSource(); // Note : 我们目前只支持简单的3D,2d 音效, 也就是说, 忽略多声源普勒效应, Cone 等. int PlaySound(GSID id, const NiPoint3& Pos = NiPoint3::ZERO, float Volumn = 1.0f, int LoopCount = 1); int PlaySound(const char* Name, const NiPoint3& Pos = NiPoint3::ZERO, float Volumn = 1.0f, int loopcount = 1); AudioSourcePtr Play3DSound(const char* szName, const NiTransform& kLocalTransform, float fMinDistance, float fMaxDistance, float Volumn = 1.0f, int loopcount = 1); int PlayMusic(const char* Name, int LoopCnt = 1); int PlaySound(AudioSource* voice, const char* szName); int PlaySoundByList( AudioSource* voice, const char* szName ); void PlayUiSound( GSID id, const NiPoint3& Pos = NiPoint3::ZERO, float Volumn = 1.0f, int loopcount = 1 ); void PlayUiSound( const char* Name, const NiPoint3& Pos = NiPoint3::ZERO, float Volumn = 1.0f, int loopcount = 1 ); void StopSound(int Index); void OnlyPlaySound(int Index); void StopAllSound(); void Update(DWORD dt); void OnArea(unsigned int uiAreaID); void SetSoundStateChangedCBFn(int index, AudioSource::StateChangedCallBack fn, AudioSource::Status eStatus = AudioSource::NOT_SET); BOOL IsPlaying(INT Index) const; // 查找声音句柄, 返回句柄索引, 如果没有找到则返回 -1. int FindSound(const NiFixedString& BufferName); BOOL ReleaseSource(INT Index); void SetListenerNode(NiNode* pkNode); // media void Register(GSID id, const NiString& fn); void RegisterZoneMusic(unsigned int zoneid, const NiString& fn); void RegisterMapMusic(unsigned int mapid, const NiString& fn); void ChangeMapMusic( const NiString& fn ); void PreLoad( int areaId ); void PreLoadAll(); NiFixedString GetSoundFile(GSID sid) const; NiFixedString GetZoneMusic(unsigned int zoneid) const; NiFixedString GetMapMusic(unsigned int zoneid) const; protected: void LoadMedia(); BOOL _PlaySound(int Index, const NiPoint3& Pos, float Volumn = 1.0f); BOOL _PlaySound(int Index); AudioSource* GetSource(int iIndex); protected: INT GetFreeSourceIndex(); void QueryMusicState(); void RandomPlayMusic(); protected: class AudioSystem* m_AudioSystem; float m_MasterVolumn; float m_AmbientVolumn; float m_EffectVolumn; DWORD m_MusicRestartTime; // AudioSource* m_CurrentMusic; // 目前只支持1个 bool m_bInit; AudioSourcePtr m_Sources[MAX_SOURCES]; // 这种做法本身不是安全的, 因为在所有声卡上, 有效的声源个数是有硬件限制的. // AC'97芯片大多数都是支持32个, DSOUND 驱动可以支持64个(software render to surface.). 但不管怎么, 都是有限制, MSS 如何处理 // 目前不得而知, 所以也不好确定NIMilesAudio 的处理是否正确, 但愿AudioSource其实只是表示一个缓冲, 而且 // MSS 会自适应地分配声源. AudioSourcePtr m_UiSources[MAX_UISOURCE]; FixedStringHashMap m_SourceMap; typedef FixedStringHashMap::value_type SourcePair; NiTMap m_SMMap; NiTMap m_ZoneM; NiTMap m_MapM; unsigned int m_curActZoneID; unsigned int m_curZoneID; int m_curActMapId; float m_fNextTime; std::list< NiFixedString > m_listMusic; }; inline int CAudioInterface::FindSound(const NiFixedString& BufferName) { NIASSERT(BufferName); FixedStringHashMap::const_iterator it = m_SourceMap.find(BufferName); if (it != m_SourceMap.end()) { return it->second; } return -1; } inline INT CAudioInterface::GetFreeSourceIndex() { int i; for (i = 0; i < MAX_SOURCES; i++) { if (m_Sources[i] == NULL) { return i; } } // 所有缓冲区均被占用, 尝试释放一个已经停止播放的. if (i == MAX_SOURCES) { for (int j = 0; j < MAX_SOURCES; j++) { if(!IsPlaying(j) && ReleaseSource(j)) { return j; } } } // 强制释放 0 !!!! ReleaseSource(0); return 0; }