Player类单例模式重做,Music类调整

This commit is contained in:
Nomango 2018-07-03 20:19:00 +08:00
parent 7bdadbe828
commit a85026e02d
6 changed files with 155 additions and 172 deletions

View File

@ -1,5 +1,5 @@
#include "..\e2dbase.h" #include "..\e2dbase.h"
#include "..\e2dtool.h"
// GC 机制,用于自动销毁单例 // GC 机制,用于自动销毁单例
e2d::GC e2d::GC::_instance; e2d::GC e2d::GC::_instance;
@ -10,6 +10,7 @@ e2d::GC::~GC()
Game::destroyInstance(); Game::destroyInstance();
Renderer::destroyInstance(); Renderer::destroyInstance();
Window::destroyInstance(); Window::destroyInstance();
Player::destroyInstance();
} }

View File

@ -64,13 +64,11 @@ bool e2d::Game::init(const String& mutexName)
// 初始化 COM 组件 // 初始化 COM 组件
CoInitialize(nullptr); CoInitialize(nullptr);
bool bInputInit = false, bool bInputInit = false;
bMusicInit = false;
auto DestroyResources = [&]() auto DestroyResources = [&]()
{ {
if (bInputInit) Input::__uninit(); if (bInputInit) Input::__uninit();
if (bMusicInit) Music::__uninit();
}; };
// 初始化 DirectInput // 初始化 DirectInput
@ -84,17 +82,6 @@ bool e2d::Game::init(const String& mutexName)
throw SystemException(L"初始化 DirectInput 组件失败"); throw SystemException(L"初始化 DirectInput 组件失败");
} }
// 初始化播放器
if (Music::__init())
{
bMusicInit = true;
}
else
{
DestroyResources();
throw SystemException(L"初始化 XAudio2 组件失败");
}
// 初始化路径 // 初始化路径
if (!Path::__init()) if (!Path::__init())
{ {
@ -211,12 +198,8 @@ void e2d::Game::cleanup()
Collision::__clearListeners(); Collision::__clearListeners();
// 删除动作 // 删除动作
ActionManager::__uninit(); ActionManager::__uninit();
// 回收音乐播放器资源
Player::__uninit();
// 清空图片缓存 // 清空图片缓存
Image::clearCache(); Image::clearCache();
// 回收音乐相关资源
Music::__uninit();
// 清空定时器 // 清空定时器
Timer::__uninit(); Timer::__uninit();
// 关闭输入 // 关闭输入

View File

@ -2,10 +2,11 @@
#ifndef SAFE_DELETE #ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if (p) { delete (p); (p)=nullptr; } } #define SAFE_DELETE(p) { if (p) { delete (p); (p)=nullptr; } }
#endif #endif
#ifndef SAFE_DELETE_ARRAY #ifndef SAFE_DELETE_ARRAY
#define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=nullptr; } } #define SAFE_DELETE_ARRAY(p) { if (p) { delete[] (p); (p)=nullptr; } }
#endif #endif
inline bool TraceError(wchar_t* sPrompt) inline bool TraceError(wchar_t* sPrompt)
@ -21,10 +22,6 @@ inline bool TraceError(wchar_t* sPrompt, HRESULT hr)
} }
static IXAudio2 * s_pXAudio2 = nullptr;
static IXAudio2MasteringVoice * s_pMasteringVoice = nullptr;
e2d::Music::Music() e2d::Music::Music()
: _opened(false) : _opened(false)
, _playing(false) , _playing(false)
@ -92,12 +89,6 @@ bool e2d::Music::open(const e2d::String& filePath)
return false; return false;
} }
if (!s_pXAudio2)
{
WARN("IXAudio2 nullptr pointer error!");
return false;
}
// 定位 wave 文件 // 定位 wave 文件
wchar_t pFilePath[MAX_PATH]; wchar_t pFilePath[MAX_PATH];
if (!_findMediaFileCch(pFilePath, MAX_PATH, (const wchar_t *)actualFilePath)) if (!_findMediaFileCch(pFilePath, MAX_PATH, (const wchar_t *)actualFilePath))
@ -137,8 +128,15 @@ bool e2d::Music::open(const e2d::String& filePath)
} }
// 创建音源 // 创建音源
HRESULT hr; HRESULT hr = Player::getInstance()->getIXAudio2()->CreateSourceVoice(
if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &this->_voiceCallback))) &_voice,
_wfx,
0,
XAUDIO2_DEFAULT_FREQ_RATIO,
&this->_voiceCallback
);
if (FAILED(hr))
{ {
TraceError(L"Create source voice error", hr); TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_waveData); SAFE_DELETE_ARRAY(_waveData);
@ -163,12 +161,6 @@ bool e2d::Music::open(int resNameId, const e2d::String& resType)
return false; return false;
} }
if (!s_pXAudio2)
{
WARN("IXAudio2 nullptr pointer error!");
return false;
}
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), (LPCWSTR)resType))) if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), (LPCWSTR)resType)))
return TraceError(L"FindResource"); return TraceError(L"FindResource");
@ -216,8 +208,15 @@ bool e2d::Music::open(int resNameId, const e2d::String& resType)
} }
// 创建音源 // 创建音源
HRESULT hr; HRESULT hr = Player::getInstance()->getIXAudio2()->CreateSourceVoice(
if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &this->_voiceCallback))) &_voice,
_wfx,
0,
XAUDIO2_DEFAULT_FREQ_RATIO,
&this->_voiceCallback
);
if (FAILED(hr))
{ {
TraceError(L"Create source voice error", hr); TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_waveData); SAFE_DELETE_ARRAY(_waveData);
@ -574,43 +573,3 @@ bool e2d::Music::_findMediaFileCch(wchar_t* strDestPath, int cchDest, const wcha
return false; return false;
} }
IXAudio2 * e2d::Music::getIXAudio2()
{
return s_pXAudio2;
}
IXAudio2MasteringVoice * e2d::Music::getIXAudio2MasteringVoice()
{
return s_pMasteringVoice;
}
bool e2d::Music::__init()
{
HRESULT hr;
if (FAILED(hr = XAudio2Create(&s_pXAudio2, 0)))
{
WARN("Failed to init XAudio2 engine");
return false;
}
if (FAILED(hr = s_pXAudio2->CreateMasteringVoice(&s_pMasteringVoice)))
{
WARN("Failed creating mastering voice");
e2d::SafeRelease(s_pXAudio2);
return false;
}
return true;
}
void e2d::Music::__uninit()
{
if (s_pMasteringVoice)
{
s_pMasteringVoice->DestroyVoice();
}
e2d::SafeRelease(s_pXAudio2);
}

View File

@ -1,28 +1,66 @@
#include "..\e2dtool.h" #include "..\e2dtool.h"
#include <map>
typedef std::map<UINT, e2d::Music *> MusicMap;
static MusicMap& GetMusicFileList() e2d::Player * e2d::Player::_instance = nullptr;
e2d::Player::Player()
: _volume(1.f)
, _xAudio2(nullptr)
, _masteringVoice(nullptr)
{ {
static MusicMap s_MusicFileList;
return s_MusicFileList;
} }
static MusicMap& GetMusicResList() e2d::Player::~Player()
{ {
static MusicMap s_MusicResList; for (auto pair : _fileList)
return s_MusicResList; delete pair.second;
_fileList.clear();
for (auto pair : _resList)
delete pair.second;
_resList.clear();
if (_masteringVoice)
_masteringVoice->DestroyVoice();
SafeRelease(_xAudio2);
} }
static float s_fMusicVolume = 1.0; e2d::Player * e2d::Player::getInstance()
{
if (!_instance)
{
_instance = new (std::nothrow) Player;
HRESULT hr;
if (FAILED(hr = XAudio2Create(&_instance->_xAudio2, 0)) ||
FAILED(hr = _instance->_xAudio2->CreateMasteringVoice(&_instance->_masteringVoice)))
{
throw SystemException("³õʼ»¯ XAudio2 ×é¼þʧ°Ü");
}
}
return _instance;
}
void e2d::Player::destroyInstance()
{
if (_instance)
{
delete _instance;
_instance = nullptr;
}
}
IXAudio2 * e2d::Player::getIXAudio2()
{
return _xAudio2;
}
bool e2d::Player::preload(const String& filePath) bool e2d::Player::preload(const String& filePath)
{ {
UINT hash = filePath.getHashCode(); UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash)) if (_fileList.end() != _fileList.find(hash))
{ {
return true; return true;
} }
@ -32,8 +70,8 @@ bool e2d::Player::preload(const String& filePath)
if (music->open(filePath)) if (music->open(filePath))
{ {
music->setVolume(s_fMusicVolume); music->setVolume(_volume);
GetMusicFileList().insert(std::pair<UINT, Music *>(hash, music)); _fileList.insert(std::pair<UINT, Music *>(hash, music));
return true; return true;
} }
else else
@ -47,7 +85,7 @@ bool e2d::Player::preload(const String& filePath)
bool e2d::Player::preload(int resNameId, const String& resType) bool e2d::Player::preload(int resNameId, const String& resType)
{ {
if (GetMusicResList().end() != GetMusicResList().find(resNameId)) if (_resList.end() != _resList.find(resNameId))
{ {
return true; return true;
} }
@ -57,8 +95,8 @@ bool e2d::Player::preload(int resNameId, const String& resType)
if (music->open(resNameId, resType)) if (music->open(resNameId, resType))
{ {
music->setVolume(s_fMusicVolume); music->setVolume(_volume);
GetMusicResList().insert(std::pair<UINT, Music *>(resNameId, music)); _resList.insert(std::pair<UINT, Music *>(resNameId, music));
return true; return true;
} }
else else
@ -75,7 +113,7 @@ bool e2d::Player::play(const String& filePath, int nLoopCount)
if (Player::preload(filePath)) if (Player::preload(filePath))
{ {
UINT hash = filePath.getHashCode(); UINT hash = filePath.getHashCode();
auto music = GetMusicFileList()[hash]; auto music = _fileList[hash];
if (music->play(nLoopCount)) if (music->play(nLoopCount))
{ {
return true; return true;
@ -88,7 +126,7 @@ bool e2d::Player::play(int resNameId, const String& resType, int nLoopCount)
{ {
if (Player::preload(resNameId, resType)) if (Player::preload(resNameId, resType))
{ {
auto music = GetMusicResList()[resNameId]; auto music = _resList[resNameId];
if (music->play(nLoopCount)) if (music->play(nLoopCount))
{ {
return true; return true;
@ -104,14 +142,14 @@ void e2d::Player::pause(const String& filePath)
UINT hash = filePath.getHashCode(); UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash)) if (_fileList.end() != _fileList.find(hash))
GetMusicFileList()[hash]->pause(); _fileList[hash]->pause();
} }
void e2d::Player::pause(int resNameId, const String& resType) void e2d::Player::pause(int resNameId, const String& resType)
{ {
if (GetMusicResList().end() != GetMusicResList().find(resNameId)) if (_resList.end() != _resList.find(resNameId))
GetMusicResList()[resNameId]->pause(); _resList[resNameId]->pause();
} }
void e2d::Player::resume(const String& filePath) void e2d::Player::resume(const String& filePath)
@ -121,14 +159,14 @@ void e2d::Player::resume(const String& filePath)
UINT hash = filePath.getHashCode(); UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash)) if (_fileList.end() != _fileList.find(hash))
GetMusicFileList()[hash]->resume(); _fileList[hash]->resume();
} }
void e2d::Player::resume(int resNameId, const String& resType) void e2d::Player::resume(int resNameId, const String& resType)
{ {
if (GetMusicResList().end() != GetMusicResList().find(resNameId)) if (_resList.end() != _resList.find(resNameId))
GetMusicResList()[resNameId]->pause(); _resList[resNameId]->pause();
} }
void e2d::Player::stop(const String& filePath) void e2d::Player::stop(const String& filePath)
@ -138,14 +176,14 @@ void e2d::Player::stop(const String& filePath)
UINT hash = filePath.getHashCode(); UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash)) if (_fileList.end() != _fileList.find(hash))
GetMusicFileList()[hash]->stop(); _fileList[hash]->stop();
} }
void e2d::Player::stop(int resNameId, const String& resType) void e2d::Player::stop(int resNameId, const String& resType)
{ {
if (GetMusicResList().end() != GetMusicResList().find(resNameId)) if (_resList.end() != _resList.find(resNameId))
GetMusicResList()[resNameId]->stop(); _resList[resNameId]->stop();
} }
bool e2d::Player::isPlaying(const String& filePath) bool e2d::Player::isPlaying(const String& filePath)
@ -155,36 +193,36 @@ bool e2d::Player::isPlaying(const String& filePath)
UINT hash = filePath.getHashCode(); UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash)) if (_fileList.end() != _fileList.find(hash))
return GetMusicFileList()[hash]->isPlaying(); return _fileList[hash]->isPlaying();
return false; return false;
} }
bool e2d::Player::isPlaying(int resNameId, const String& resType) bool e2d::Player::isPlaying(int resNameId, const String& resType)
{ {
if (GetMusicResList().end() != GetMusicResList().find(resNameId)) if (_resList.end() != _resList.find(resNameId))
return GetMusicResList()[resNameId]->isPlaying(); return _resList[resNameId]->isPlaying();
return false; return false;
} }
double e2d::Player::getVolume() double e2d::Player::getVolume()
{ {
return s_fMusicVolume; return _volume;
} }
void e2d::Player::setVolume(double volume) void e2d::Player::setVolume(double volume)
{ {
s_fMusicVolume = min(max(float(volume), -224), 224); _volume = min(max(float(volume), -224), 224);
for (auto pair : GetMusicFileList()) for (auto pair : _fileList)
{ {
pair.second->setVolume(s_fMusicVolume); pair.second->setVolume(_volume);
} }
} }
void e2d::Player::pauseAll() void e2d::Player::pauseAll()
{ {
for (auto pair : GetMusicFileList()) for (auto pair : _fileList)
{ {
pair.second->pause(); pair.second->pause();
} }
@ -192,7 +230,7 @@ void e2d::Player::pauseAll()
void e2d::Player::resumeAll() void e2d::Player::resumeAll()
{ {
for (auto pair : GetMusicFileList()) for (auto pair : _fileList)
{ {
pair.second->resume(); pair.second->resume();
} }
@ -200,19 +238,8 @@ void e2d::Player::resumeAll()
void e2d::Player::stopAll() void e2d::Player::stopAll()
{ {
for (auto pair : GetMusicFileList()) for (auto pair : _fileList)
{ {
pair.second->stop(); pair.second->stop();
} }
} }
void e2d::Player::__uninit()
{
for (auto pair : GetMusicFileList())
{
pair.second->close();
delete pair.second;
}
GetMusicFileList().clear();
}

View File

@ -39,6 +39,7 @@
#include <xaudio2.h> #include <xaudio2.h>
// C++ RunTime Header Files // C++ RunTime Header Files
#include <map>
#include <set> #include <set>
#include <stack> #include <stack>
#include <vector> #include <vector>

View File

@ -117,12 +117,6 @@ public:
// 삿혤 IXAudio2SourceVoice 뚤蹶 // 삿혤 IXAudio2SourceVoice 뚤蹶
IXAudio2SourceVoice * getIXAudio2SourceVoice() const; IXAudio2SourceVoice * getIXAudio2SourceVoice() const;
// »ñÈ¡ IXAudio2 ¶ÔÏó
static IXAudio2 * getIXAudio2();
// »ñÈ¡ IXAudio2MasteringVoice ¶ÔÏó
static IXAudio2MasteringVoice * getIXAudio2MasteringVoice();
protected: protected:
bool _readMMIO(); bool _readMMIO();
@ -139,23 +133,18 @@ protected:
const wchar_t * strFilename const wchar_t * strFilename
); );
private:
static bool __init();
static void __uninit();
protected: protected:
bool _opened; bool _opened;
mutable bool _playing; mutable bool _playing;
DWORD _dwSize; DWORD _dwSize;
CHAR* _resBuffer; CHAR* _resBuffer;
BYTE* _waveData; BYTE* _waveData;
HMMIO _hmmio; HMMIO _hmmio;
MMCKINFO _ck; MMCKINFO _ck;
MMCKINFO _ckRiff; MMCKINFO _ckRiff;
WAVEFORMATEX* _wfx; WAVEFORMATEX* _wfx;
VoiceCallback _voiceCallback; VoiceCallback _voiceCallback;
IXAudio2SourceVoice* _voice; IXAudio2SourceVoice* _voice;
}; };
@ -163,95 +152,118 @@ protected:
class Player class Player
{ {
friend class Game; friend class Game;
typedef std::map<UINT, Music*> MusicMap;
public: public:
// 获取播放器实例
static Player * getInstance();
// 销毁实例
static void destroyInstance();
// 渡속潼稜있栗都 // 渡속潼稜있栗都
static bool preload( bool preload(
const String& filePath /* 稜있匡숭쨌쓺 */ const String& filePath /* 稜있匡숭쨌쓺 */
); );
// 꺄렴稜있 // 꺄렴稜있
static bool play( bool play(
const String& filePath, /* 稜있匡숭쨌쓺 */ const String& filePath, /* 稜있匡숭쨌쓺 */
int nLoopCount = 0 /* 路릿꺄렴늴鑒<E99192>零 -1 槨琦뻔꺄렴 */ int nLoopCount = 0 /* 路릿꺄렴늴鑒<E99192>零 -1 槨琦뻔꺄렴 */
); );
// 董界稜있 // 董界稜있
static void pause( void pause(
const String& filePath /* 稜있匡숭쨌쓺 */ const String& filePath /* 稜있匡숭쨌쓺 */
); );
// 셨崎꺄렴稜있 // 셨崎꺄렴稜있
static void resume( void resume(
const String& filePath /* 稜있匡숭쨌쓺 */ const String& filePath /* 稜있匡숭쨌쓺 */
); );
// 界岺稜있 // 界岺稜있
static void stop( void stop(
const String& filePath /* 稜있匡숭쨌쓺 */ const String& filePath /* 稜있匡숭쨌쓺 */
); );
// 삿혤稜있꺄렴榴檄 // 삿혤稜있꺄렴榴檄
static bool isPlaying( bool isPlaying(
const String& filePath /* 稜있匡숭쨌쓺 */ const String& filePath /* 稜있匡숭쨌쓺 */
); );
// 渡속潼稜있栗都 // 渡속潼稜있栗都
static bool preload( bool preload(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType /* 稜있栗都잚謹 */ const String& resType /* 稜있栗都잚謹 */
); );
// 꺄렴稜있 // 꺄렴稜있
static bool play( bool play(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType, /* 稜있栗都잚謹 */ const String& resType, /* 稜있栗都잚謹 */
int nLoopCount = 0 /* 路릿꺄렴늴鑒<E99192>零 -1 槨琦뻔꺄렴 */ int nLoopCount = 0 /* 路릿꺄렴늴鑒<E99192>零 -1 槨琦뻔꺄렴 */
); );
// 董界稜있 // 董界稜있
static void pause( void pause(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType /* 稜있栗都잚謹 */ const String& resType /* 稜있栗都잚謹 */
); );
// 셨崎꺄렴稜있 // 셨崎꺄렴稜있
static void resume( void resume(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType /* 稜있栗都잚謹 */ const String& resType /* 稜있栗都잚謹 */
); );
// 界岺稜있 // 界岺稜있
static void stop( void stop(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType /* 稜있栗都잚謹 */ const String& resType /* 稜있栗都잚謹 */
); );
// 삿혤稜있꺄렴榴檄 // 삿혤稜있꺄렴榴檄
static bool isPlaying( bool isPlaying(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType /* 稜있栗都잚謹 */ const String& resType /* 稜있栗都잚謹 */
); );
// 삿혤稜좆 // 삿혤稜좆
static double getVolume(); double getVolume();
// <20>零稜좆 // <20>零稜좆
static void setVolume( void setVolume(
double volume /* 稜좆렀鍋槨 -224 ~ 2240 角쓰稜1 角攣끽稜좆 */ double volume /* 稜좆렀鍋槨 -224 ~ 2240 角쓰稜1 角攣끽稜좆 */
); );
// 董界杰唐稜있 // 董界杰唐稜있
static void pauseAll(); void pauseAll();
// 셨崎꺄렴杰唐稜있 // 셨崎꺄렴杰唐稜있
static void resumeAll(); void resumeAll();
// 界岺杰唐稜있 // 界岺杰唐稜있
static void stopAll(); void stopAll();
// 获取 IXAudio2 对象
IXAudio2 * getIXAudio2();
private: private:
static void __uninit(); Player();
~Player();
E2D_DISABLE_COPY(Player);
private:
float _volume;
MusicMap _fileList;
MusicMap _resList;
IXAudio2* _xAudio2;
IXAudio2MasteringVoice* _masteringVoice;
static Player * _instance;
}; };