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 "..\e2dtool.h"
// GC 机制,用于自动销毁单例
e2d::GC e2d::GC::_instance;
@ -10,6 +10,7 @@ e2d::GC::~GC()
Game::destroyInstance();
Renderer::destroyInstance();
Window::destroyInstance();
Player::destroyInstance();
}

View File

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

View File

@ -2,10 +2,11 @@
#ifndef SAFE_DELETE
#define SAFE_DELETE(p) { if (p) { delete (p); (p)=nullptr; } }
#define SAFE_DELETE(p) { if (p) { delete (p); (p)=nullptr; } }
#endif
#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
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()
: _opened(false)
, _playing(false)
@ -92,12 +89,6 @@ bool e2d::Music::open(const e2d::String& filePath)
return false;
}
if (!s_pXAudio2)
{
WARN("IXAudio2 nullptr pointer error!");
return false;
}
// 定位 wave 文件
wchar_t pFilePath[MAX_PATH];
if (!_findMediaFileCch(pFilePath, MAX_PATH, (const wchar_t *)actualFilePath))
@ -137,8 +128,15 @@ bool e2d::Music::open(const e2d::String& filePath)
}
// 创建音源
HRESULT hr;
if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &this->_voiceCallback)))
HRESULT hr = Player::getInstance()->getIXAudio2()->CreateSourceVoice(
&_voice,
_wfx,
0,
XAUDIO2_DEFAULT_FREQ_RATIO,
&this->_voiceCallback
);
if (FAILED(hr))
{
TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_waveData);
@ -163,12 +161,6 @@ bool e2d::Music::open(int resNameId, const e2d::String& resType)
return false;
}
if (!s_pXAudio2)
{
WARN("IXAudio2 nullptr pointer error!");
return false;
}
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), (LPCWSTR)resType)))
return TraceError(L"FindResource");
@ -216,8 +208,15 @@ bool e2d::Music::open(int resNameId, const e2d::String& resType)
}
// 创建音源
HRESULT hr;
if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &this->_voiceCallback)))
HRESULT hr = Player::getInstance()->getIXAudio2()->CreateSourceVoice(
&_voice,
_wfx,
0,
XAUDIO2_DEFAULT_FREQ_RATIO,
&this->_voiceCallback
);
if (FAILED(hr))
{
TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_waveData);
@ -574,43 +573,3 @@ bool e2d::Music::_findMediaFileCch(wchar_t* strDestPath, int cchDest, const wcha
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 <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;
return s_MusicResList;
for (auto pair : _fileList)
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)
{
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
if (_fileList.end() != _fileList.find(hash))
{
return true;
}
@ -32,8 +70,8 @@ bool e2d::Player::preload(const String& filePath)
if (music->open(filePath))
{
music->setVolume(s_fMusicVolume);
GetMusicFileList().insert(std::pair<UINT, Music *>(hash, music));
music->setVolume(_volume);
_fileList.insert(std::pair<UINT, Music *>(hash, music));
return true;
}
else
@ -47,7 +85,7 @@ bool e2d::Player::preload(const String& filePath)
bool e2d::Player::preload(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
if (_resList.end() != _resList.find(resNameId))
{
return true;
}
@ -57,8 +95,8 @@ bool e2d::Player::preload(int resNameId, const String& resType)
if (music->open(resNameId, resType))
{
music->setVolume(s_fMusicVolume);
GetMusicResList().insert(std::pair<UINT, Music *>(resNameId, music));
music->setVolume(_volume);
_resList.insert(std::pair<UINT, Music *>(resNameId, music));
return true;
}
else
@ -75,7 +113,7 @@ bool e2d::Player::play(const String& filePath, int nLoopCount)
if (Player::preload(filePath))
{
UINT hash = filePath.getHashCode();
auto music = GetMusicFileList()[hash];
auto music = _fileList[hash];
if (music->play(nLoopCount))
{
return true;
@ -88,7 +126,7 @@ bool e2d::Player::play(int resNameId, const String& resType, int nLoopCount)
{
if (Player::preload(resNameId, resType))
{
auto music = GetMusicResList()[resNameId];
auto music = _resList[resNameId];
if (music->play(nLoopCount))
{
return true;
@ -104,14 +142,14 @@ void e2d::Player::pause(const String& filePath)
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
GetMusicFileList()[hash]->pause();
if (_fileList.end() != _fileList.find(hash))
_fileList[hash]->pause();
}
void e2d::Player::pause(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->pause();
if (_resList.end() != _resList.find(resNameId))
_resList[resNameId]->pause();
}
void e2d::Player::resume(const String& filePath)
@ -121,14 +159,14 @@ void e2d::Player::resume(const String& filePath)
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
GetMusicFileList()[hash]->resume();
if (_fileList.end() != _fileList.find(hash))
_fileList[hash]->resume();
}
void e2d::Player::resume(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->pause();
if (_resList.end() != _resList.find(resNameId))
_resList[resNameId]->pause();
}
void e2d::Player::stop(const String& filePath)
@ -138,14 +176,14 @@ void e2d::Player::stop(const String& filePath)
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
GetMusicFileList()[hash]->stop();
if (_fileList.end() != _fileList.find(hash))
_fileList[hash]->stop();
}
void e2d::Player::stop(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->stop();
if (_resList.end() != _resList.find(resNameId))
_resList[resNameId]->stop();
}
bool e2d::Player::isPlaying(const String& filePath)
@ -155,36 +193,36 @@ bool e2d::Player::isPlaying(const String& filePath)
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
return GetMusicFileList()[hash]->isPlaying();
if (_fileList.end() != _fileList.find(hash))
return _fileList[hash]->isPlaying();
return false;
}
bool e2d::Player::isPlaying(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
return GetMusicResList()[resNameId]->isPlaying();
if (_resList.end() != _resList.find(resNameId))
return _resList[resNameId]->isPlaying();
return false;
}
double e2d::Player::getVolume()
{
return s_fMusicVolume;
return _volume;
}
void e2d::Player::setVolume(double volume)
{
s_fMusicVolume = min(max(float(volume), -224), 224);
for (auto pair : GetMusicFileList())
_volume = min(max(float(volume), -224), 224);
for (auto pair : _fileList)
{
pair.second->setVolume(s_fMusicVolume);
pair.second->setVolume(_volume);
}
}
void e2d::Player::pauseAll()
{
for (auto pair : GetMusicFileList())
for (auto pair : _fileList)
{
pair.second->pause();
}
@ -192,7 +230,7 @@ void e2d::Player::pauseAll()
void e2d::Player::resumeAll()
{
for (auto pair : GetMusicFileList())
for (auto pair : _fileList)
{
pair.second->resume();
}
@ -200,19 +238,8 @@ void e2d::Player::resumeAll()
void e2d::Player::stopAll()
{
for (auto pair : GetMusicFileList())
for (auto pair : _fileList)
{
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>
// C++ RunTime Header Files
#include <map>
#include <set>
#include <stack>
#include <vector>

View File

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