分离Music和Player类

This commit is contained in:
Nomango 2018-05-17 23:53:27 +08:00
parent b2ec817c81
commit 5ab9d822f3
10 changed files with 513 additions and 423 deletions

View File

@ -203,6 +203,8 @@ void e2d::Game::destroy()
ColliderManager::__uninit(); ColliderManager::__uninit();
// 删除动作 // 删除动作
ActionManager::__uninit(); ActionManager::__uninit();
// 回收音乐播放器资源
Player::__uninit();
// 删除所有对象 // 删除所有对象
ObjectManager::__clear(); ObjectManager::__clear();
// 清空图片缓存 // 清空图片缓存
@ -213,9 +215,7 @@ void e2d::Game::destroy()
Timer::__uninit(); Timer::__uninit();
// 关闭输入 // 关闭输入
Input::__uninit(); Input::__uninit();
// 恢复计时操作 // 回收渲染相关资源
Time::__uninit();
// 删除渲染相关资源
Renderer::__discardResources(); Renderer::__discardResources();
// 销毁窗口 // 销毁窗口
Window::__uninit(); Window::__uninit();

View File

@ -10,8 +10,8 @@ using namespace e2d;
static IDirectInput8* s_pDirectInput = nullptr; // DirectInput 接口对象 static IDirectInput8* s_pDirectInput = nullptr; // DirectInput 接口对象
static IDirectInputDevice8* s_KeyboardDevice = nullptr; // 键盘设备接口 static IDirectInputDevice8* s_KeyboardDevice = nullptr; // 键盘设备接口
static char s_KeyBuffer[BUFFER_SIZE] = { 0 }; // 用于保存键盘按键信息缓冲区 static char s_KeyBuffer[BUFFER_SIZE] = { 0 }; // 用于保存键盘按键信息缓冲区
static char s_KeyRecordBuffer[BUFFER_SIZE] = { 0 }; // 键盘消息二级缓冲区 static char s_KeyRecordBuffer[BUFFER_SIZE] = { 0 }; // 键盘消息二级缓冲区
static IDirectInputDevice8* s_MouseDevice = nullptr; // 鼠标设备接口 static IDirectInputDevice8* s_MouseDevice = nullptr; // 鼠标设备接口
static DIMOUSESTATE s_MouseState; // 鼠标信息存储结构体 static DIMOUSESTATE s_MouseState; // 鼠标信息存储结构体

View File

@ -48,10 +48,6 @@ bool e2d::Time::__init()
return true; return true;
} }
void e2d::Time::__uninit()
{
}
bool e2d::Time::__isReady() bool e2d::Time::__isReady()
{ {
return s_tExceptedInvertal < duration_cast<milliseconds>(s_tNow - s_tFixedUpdate); return s_tExceptedInvertal < duration_cast<milliseconds>(s_tNow - s_tFixedUpdate);

View File

@ -1,6 +1,4 @@
#include "..\e2dtool.h" #include "..\e2dtool.h"
#include "..\e2dmanager.h"
#include <map>
#ifndef SAFE_DELETE #ifndef SAFE_DELETE
@ -22,109 +20,72 @@ inline bool TraceError(wchar_t* sPrompt, HRESULT hr)
return false; return false;
} }
static IXAudio2 * s_pXAudio2 = nullptr; static IXAudio2 * s_pXAudio2 = nullptr;
static IXAudio2MasteringVoice * s_pMasteringVoice = nullptr; static IXAudio2MasteringVoice * s_pMasteringVoice = nullptr;
static float s_fMusicVolume = 1.0;
// ÒôÀÖ²¥·ÅÆ÷ e2d::Music::Music()
class MusicPlayer : _opened(false)
{ , _playing(false)
public: , _wfx(nullptr)
MusicPlayer();
virtual ~MusicPlayer();
bool open(
const e2d::String& filePath
);
bool MusicPlayer::open(
int resNameId,
const e2d::String& resType
);
bool play(
int nLoopCount = 0
);
void pause();
void resume();
void stop();
void close();
bool setVolume(
float fVolume
);
bool isPlaying() const;
protected:
bool _readMMIO();
bool _resetFile();
bool _read(
BYTE* pBuffer,
DWORD dwSizeToRead
);
bool _findMediaFileCch(
wchar_t* strDestPath,
int cchDest,
const wchar_t * strFilename
);
protected:
bool _bOpened;
mutable bool _bPlaying;
DWORD _dwSize;
CHAR* _pResourceBuffer;
BYTE* _pbWaveData;
HMMIO _hmmio;
MMCKINFO _ck;
MMCKINFO _ckRiff;
WAVEFORMATEX* _pwfx;
IXAudio2SourceVoice* _pSourceVoice;
};
typedef std::map<UINT, MusicPlayer *> MusicMap;
static MusicMap& GetMusicFileList()
{
static MusicMap s_MusicFileList;
return s_MusicFileList;
}
static MusicMap& GetMusicResList()
{
static MusicMap s_MusicResList;
return s_MusicResList;
}
MusicPlayer::MusicPlayer()
: _bOpened(false)
, _bPlaying(false)
, _pwfx(nullptr)
, _hmmio(nullptr) , _hmmio(nullptr)
, _pResourceBuffer(nullptr) , _resBuffer(nullptr)
, _pbWaveData(nullptr) , _waveData(nullptr)
, _dwSize(0) , _dwSize(0)
, _pSourceVoice(nullptr) , _voice(nullptr)
{ {
} }
MusicPlayer::~MusicPlayer() e2d::Music::Music(const e2d::String & filePath)
: _opened(false)
, _playing(false)
, _wfx(nullptr)
, _hmmio(nullptr)
, _resBuffer(nullptr)
, _waveData(nullptr)
, _dwSize(0)
, _voice(nullptr)
{
this->open(filePath);
}
e2d::Music::Music(int resNameId, const String & resType)
: _opened(false)
, _playing(false)
, _wfx(nullptr)
, _hmmio(nullptr)
, _resBuffer(nullptr)
, _waveData(nullptr)
, _dwSize(0)
, _voice(nullptr)
{
this->open(resNameId, resType);
}
e2d::Music::~Music()
{ {
close(); close();
} }
bool MusicPlayer::open(const e2d::String& filePath) e2d::Music * e2d::Music::create()
{ {
if (_bOpened) return Create<Music>();
}
e2d::Music * e2d::Music::create(const e2d::String & filePath)
{
return Create<Music>(filePath);
}
e2d::Music * e2d::Music::create(int resNameId, const String & resType)
{
return Create<Music>(resNameId, resType);
}
bool e2d::Music::open(const e2d::String& filePath)
{
if (_opened)
{ {
WARN_IF(true, "MusicInfo can be opened only once!"); WARN_IF(true, "MusicInfo can be opened only once!");
return false; return false;
@ -171,37 +132,37 @@ bool MusicPlayer::open(const e2d::String& filePath)
_dwSize = _ck.cksize; _dwSize = _ck.cksize;
// 将样本数据读取到内存中 // 将样本数据读取到内存中
_pbWaveData = new (std::nothrow) BYTE[_dwSize]; _waveData = new (std::nothrow) BYTE[_dwSize];
if (!_read(_pbWaveData, _dwSize)) if (!_read(_waveData, _dwSize))
{ {
TraceError(L"Failed to read WAV data"); TraceError(L"Failed to read WAV data");
SAFE_DELETE_ARRAY(_pbWaveData); SAFE_DELETE_ARRAY(_waveData);
return false; return false;
} }
// 创建音源 // 创建音源
HRESULT hr; HRESULT hr;
if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_pSourceVoice, _pwfx))) if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx)))
{ {
TraceError(L"Create source voice error", hr); TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_pbWaveData); SAFE_DELETE_ARRAY(_waveData);
return false; return false;
} }
_bOpened = true; _opened = true;
_bPlaying = false; _playing = false;
return true; return true;
} }
bool MusicPlayer::open(int resNameId, const e2d::String& resType) bool e2d::Music::open(int resNameId, const e2d::String& resType)
{ {
HRSRC hResInfo; HRSRC hResInfo;
HGLOBAL hResData; HGLOBAL hResData;
DWORD dwSize; DWORD dwSize;
void* pvRes; void* pvRes;
if (_bOpened) if (_opened)
{ {
WARN_IF(true, "MusicInfo can be opened only once!"); WARN_IF(true, "MusicInfo can be opened only once!");
return false; return false;
@ -213,7 +174,6 @@ bool MusicPlayer::open(int resNameId, const e2d::String& resType)
return false; return false;
} }
// Loading it as a file failed, so try it as a resource
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), resType))) if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(resNameId), resType)))
return TraceError(L"FindResource"); return TraceError(L"FindResource");
@ -226,20 +186,20 @@ bool MusicPlayer::open(int resNameId, const e2d::String& resType)
if (nullptr == (pvRes = LockResource(hResData))) if (nullptr == (pvRes = LockResource(hResData)))
return TraceError(L"LockResource"); return TraceError(L"LockResource");
_pResourceBuffer = new (std::nothrow) CHAR[dwSize]; _resBuffer = new (std::nothrow) CHAR[dwSize];
memcpy(_pResourceBuffer, pvRes, dwSize); memcpy(_resBuffer, pvRes, dwSize);
MMIOINFO mmioInfo; MMIOINFO mmioInfo;
ZeroMemory(&mmioInfo, sizeof(mmioInfo)); ZeroMemory(&mmioInfo, sizeof(mmioInfo));
mmioInfo.fccIOProc = FOURCC_MEM; mmioInfo.fccIOProc = FOURCC_MEM;
mmioInfo.cchBuffer = dwSize; mmioInfo.cchBuffer = dwSize;
mmioInfo.pchBuffer = (CHAR*)_pResourceBuffer; mmioInfo.pchBuffer = (CHAR*)_resBuffer;
_hmmio = mmioOpen(nullptr, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ); _hmmio = mmioOpen(nullptr, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ);
if (!_readMMIO()) if (!_readMMIO())
{ {
// ReadMMIO will fail if its an not a wave file // 读取非 wave 文件时 ReadMMIO 调用失败
mmioClose(_hmmio, 0); mmioClose(_hmmio, 0);
return TraceError(L"ReadMMIO"); return TraceError(L"ReadMMIO");
} }
@ -247,48 +207,48 @@ bool MusicPlayer::open(int resNameId, const e2d::String& resType)
if (!_resetFile()) if (!_resetFile())
return TraceError(L"ResetFile"); return TraceError(L"ResetFile");
// After the reset, the size of the wav file is _ck.cksize so store it now // 重置文件后wave 文件的大小是 _ck.cksize
_dwSize = _ck.cksize; _dwSize = _ck.cksize;
// Read the sample data into memory // 将样本数据读取到内存中
_pbWaveData = new (std::nothrow) BYTE[_dwSize]; _waveData = new (std::nothrow) BYTE[_dwSize];
if (!_read(_pbWaveData, _dwSize)) if (!_read(_waveData, _dwSize))
{ {
TraceError(L"Failed to read WAV data"); TraceError(L"Failed to read WAV data");
SAFE_DELETE_ARRAY(_pbWaveData); SAFE_DELETE_ARRAY(_waveData);
return false; return false;
} }
// 创建音源 // 创建音源
HRESULT hr; HRESULT hr;
if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_pSourceVoice, _pwfx))) if (FAILED(hr = s_pXAudio2->CreateSourceVoice(&_voice, _wfx)))
{ {
TraceError(L"Create source voice error", hr); TraceError(L"Create source voice error", hr);
SAFE_DELETE_ARRAY(_pbWaveData); SAFE_DELETE_ARRAY(_waveData);
return false; return false;
} }
_bOpened = true; _opened = true;
_bPlaying = false; _playing = false;
return true; return true;
} }
bool MusicPlayer::play(int nLoopCount) bool e2d::Music::play(int nLoopCount)
{ {
if (!_bOpened) if (!_opened)
{ {
WARN_IF(true, "MusicInfo::play Failed: MusicInfo must be opened first!"); WARN_IF(true, "MusicInfo::play Failed: MusicInfo must be opened first!");
return false; return false;
} }
if (_pSourceVoice == nullptr) if (_voice == nullptr)
{ {
WARN_IF(true, "MusicInfo::play Failed: IXAudio2SourceVoice Null pointer exception!"); WARN_IF(true, "MusicInfo::play Failed: IXAudio2SourceVoice Null pointer exception!");
return false; return false;
} }
if (_bPlaying) if (_playing)
{ {
stop(); stop();
} }
@ -298,71 +258,72 @@ bool MusicPlayer::play(int nLoopCount)
// 提交 wave 样本数据 // 提交 wave 样本数据
XAUDIO2_BUFFER buffer = { 0 }; XAUDIO2_BUFFER buffer = { 0 };
buffer.pAudioData = _pbWaveData; buffer.pAudioData = _waveData;
buffer.Flags = XAUDIO2_END_OF_STREAM; buffer.Flags = XAUDIO2_END_OF_STREAM;
buffer.AudioBytes = _dwSize; buffer.AudioBytes = _dwSize;
buffer.LoopCount = nLoopCount; buffer.LoopCount = nLoopCount;
HRESULT hr; HRESULT hr;
if (FAILED(hr = _pSourceVoice->SubmitSourceBuffer(&buffer))) if (FAILED(hr = _voice->SubmitSourceBuffer(&buffer)))
{ {
TraceError(L"Submitting source buffer error", hr); TraceError(L"Submitting source buffer error", hr);
_pSourceVoice->DestroyVoice(); _voice->DestroyVoice();
SAFE_DELETE_ARRAY(_pbWaveData); SAFE_DELETE_ARRAY(_waveData);
return false; return false;
} }
if (SUCCEEDED(hr = _pSourceVoice->Start(0))) if (SUCCEEDED(hr = _voice->Start(0)))
{ {
_bPlaying = true; // 播放成功,保留这个对象
_playing = true;
} }
return SUCCEEDED(hr); return SUCCEEDED(hr);
} }
void MusicPlayer::pause() void e2d::Music::pause()
{ {
if (_pSourceVoice) if (_voice)
{ {
if (SUCCEEDED(_pSourceVoice->Stop())) if (SUCCEEDED(_voice->Stop()))
{ {
_bPlaying = false; _playing = false;
} }
} }
} }
void MusicPlayer::resume() void e2d::Music::resume()
{ {
if (_pSourceVoice) if (_voice)
{ {
if (SUCCEEDED(_pSourceVoice->Start())) if (SUCCEEDED(_voice->Start()))
{ {
_bPlaying = true; _playing = true;
} }
} }
} }
void MusicPlayer::stop() void e2d::Music::stop()
{ {
if (_pSourceVoice) if (_voice)
{ {
if (SUCCEEDED(_pSourceVoice->Stop())) if (SUCCEEDED(_voice->Stop()))
{ {
_pSourceVoice->ExitLoop(); _voice->ExitLoop();
_pSourceVoice->FlushSourceBuffers(); _voice->FlushSourceBuffers();
_bPlaying = false; _playing = false;
} }
} }
} }
void MusicPlayer::close() void e2d::Music::close()
{ {
if (_pSourceVoice) if (_voice)
{ {
_pSourceVoice->Stop(); _voice->Stop();
_pSourceVoice->FlushSourceBuffers(); _voice->FlushSourceBuffers();
_pSourceVoice->DestroyVoice(); _voice->DestroyVoice();
_pSourceVoice = nullptr; _voice = nullptr;
} }
if (_hmmio != nullptr) if (_hmmio != nullptr)
@ -371,26 +332,26 @@ void MusicPlayer::close()
_hmmio = nullptr; _hmmio = nullptr;
} }
SAFE_DELETE_ARRAY(_pResourceBuffer); SAFE_DELETE_ARRAY(_resBuffer);
SAFE_DELETE_ARRAY(_pbWaveData); SAFE_DELETE_ARRAY(_waveData);
SAFE_DELETE_ARRAY(_pwfx); SAFE_DELETE_ARRAY(_wfx);
_bOpened = false; _opened = false;
_bPlaying = false; _playing = false;
} }
bool MusicPlayer::isPlaying() const bool e2d::Music::isPlaying() const
{ {
if (_bOpened && _pSourceVoice) if (_opened && _voice)
{ {
XAUDIO2_VOICE_STATE state; XAUDIO2_VOICE_STATE state;
_pSourceVoice->GetState(&state); _voice->GetState(&state);
if (state.BuffersQueued == 0) if (state.BuffersQueued == 0)
{ {
_bPlaying = false; _playing = false;
} }
return _bPlaying; return _playing;
} }
else else
{ {
@ -398,23 +359,28 @@ bool MusicPlayer::isPlaying() const
} }
} }
bool MusicPlayer::setVolume(float fVolume) IXAudio2SourceVoice * e2d::Music::getIXAudio2SourceVoice() const
{ {
if (_pSourceVoice) return _voice;
}
bool e2d::Music::setVolume(double volume)
{
if (_voice)
{ {
return SUCCEEDED(_pSourceVoice->SetVolume(fVolume)); return SUCCEEDED(_voice->SetVolume(float(volume)));
} }
return false; return false;
} }
bool MusicPlayer::_readMMIO() bool e2d::Music::_readMMIO()
{ {
MMCKINFO ckIn; MMCKINFO ckIn;
PCMWAVEFORMAT pcmWaveFormat; PCMWAVEFORMAT pcmWaveFormat;
memset(&ckIn, 0, sizeof(ckIn)); memset(&ckIn, 0, sizeof(ckIn));
_pwfx = nullptr; _wfx = nullptr;
if ((0 != mmioDescend(_hmmio, &_ckRiff, nullptr, 0))) if ((0 != mmioDescend(_hmmio, &_ckRiff, nullptr, 0)))
return TraceError(L"mmioDescend"); return TraceError(L"mmioDescend");
@ -442,11 +408,11 @@ bool MusicPlayer::_readMMIO()
// 的数据,这个数据就是额外分配的大小 // 的数据,这个数据就是额外分配的大小
if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM) if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM)
{ {
_pwfx = (WAVEFORMATEX*) new (std::nothrow) CHAR[sizeof(WAVEFORMATEX)]; _wfx = (WAVEFORMATEX*) new (std::nothrow) CHAR[sizeof(WAVEFORMATEX)];
// 拷贝数据 // 拷贝数据
memcpy(_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat)); memcpy(_wfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
_pwfx->cbSize = 0; _wfx->cbSize = 0;
} }
else else
{ {
@ -455,31 +421,31 @@ bool MusicPlayer::_readMMIO()
if (mmioRead(_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD)) if (mmioRead(_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD))
return TraceError(L"mmioRead"); return TraceError(L"mmioRead");
_pwfx = (WAVEFORMATEX*) new (std::nothrow) CHAR[sizeof(WAVEFORMATEX) + cbExtraBytes]; _wfx = (WAVEFORMATEX*) new (std::nothrow) CHAR[sizeof(WAVEFORMATEX) + cbExtraBytes];
// 拷贝数据 // 拷贝数据
memcpy(_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat)); memcpy(_wfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
_pwfx->cbSize = cbExtraBytes; _wfx->cbSize = cbExtraBytes;
// 读取额外数据 // 读取额外数据
if (mmioRead(_hmmio, (CHAR*)(((BYTE*)&(_pwfx->cbSize)) + sizeof(WORD)), if (mmioRead(_hmmio, (CHAR*)(((BYTE*)&(_wfx->cbSize)) + sizeof(WORD)),
cbExtraBytes) != cbExtraBytes) cbExtraBytes) != cbExtraBytes)
{ {
SAFE_DELETE(_pwfx); SAFE_DELETE(_wfx);
return TraceError(L"mmioRead"); return TraceError(L"mmioRead");
} }
} }
if (0 != mmioAscend(_hmmio, &ckIn, 0)) if (0 != mmioAscend(_hmmio, &ckIn, 0))
{ {
SAFE_DELETE(_pwfx); SAFE_DELETE(_wfx);
return TraceError(L"mmioAscend"); return TraceError(L"mmioAscend");
} }
return true; return true;
} }
bool MusicPlayer::_resetFile() bool e2d::Music::_resetFile()
{ {
// Seek to the data // Seek to the data
if (-1 == mmioSeek(_hmmio, _ckRiff.dwDataOffset + sizeof(FOURCC), if (-1 == mmioSeek(_hmmio, _ckRiff.dwDataOffset + sizeof(FOURCC),
@ -494,7 +460,7 @@ bool MusicPlayer::_resetFile()
return true; return true;
} }
bool MusicPlayer::_read(BYTE* pBuffer, DWORD dwSizeToRead) bool e2d::Music::_read(BYTE* pBuffer, DWORD dwSizeToRead)
{ {
MMIOINFO mmioinfoIn; // current status of _hmmio MMIOINFO mmioinfoIn; // current status of _hmmio
@ -530,7 +496,7 @@ bool MusicPlayer::_read(BYTE* pBuffer, DWORD dwSizeToRead)
return true; return true;
} }
bool MusicPlayer::_findMediaFileCch(wchar_t* strDestPath, int cchDest, const wchar_t * strFilename) bool e2d::Music::_findMediaFileCch(wchar_t* strDestPath, int cchDest, const wchar_t * strFilename)
{ {
bool bFound = false; bool bFound = false;
@ -604,195 +570,6 @@ bool MusicPlayer::_findMediaFileCch(wchar_t* strDestPath, int cchDest, const wch
return false; return false;
} }
bool e2d::Music::preload(const String& filePath)
{
UINT nRet = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
{
return true;
}
else
{
MusicPlayer * pPlayer = new (std::nothrow) MusicPlayer();
if (pPlayer->open(filePath))
{
pPlayer->setVolume(s_fMusicVolume);
GetMusicFileList().insert(std::pair<UINT, MusicPlayer *>(nRet, pPlayer));
return true;
}
else
{
delete pPlayer;
pPlayer = nullptr;
}
}
return false;
}
bool e2d::Music::preload(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
{
return true;
}
else
{
MusicPlayer * pPlayer = new (std::nothrow) MusicPlayer();
if (pPlayer->open(resNameId, resType))
{
pPlayer->setVolume(s_fMusicVolume);
GetMusicResList().insert(std::pair<UINT, MusicPlayer *>(resNameId, pPlayer));
return true;
}
else
{
delete pPlayer;
pPlayer = nullptr;
}
}
return false;
}
bool e2d::Music::play(const String& filePath, int nLoopCount)
{
if (Music::preload(filePath))
{
UINT nRet = filePath.getHashCode();
auto pMusic = GetMusicFileList()[nRet];
if (pMusic->play(nLoopCount))
{
return true;
}
}
return false;
}
bool e2d::Music::play(int resNameId, const String& resType, int nLoopCount)
{
if (Music::preload(resNameId, resType))
{
auto pMusic = GetMusicResList()[resNameId];
if (pMusic->play(nLoopCount))
{
return true;
}
}
return false;
}
void e2d::Music::pause(const String& filePath)
{
if (filePath.isEmpty())
return;
UINT nRet = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
GetMusicFileList()[nRet]->pause();
}
void e2d::Music::pause(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->pause();
}
void e2d::Music::resume(const String& filePath)
{
if (filePath.isEmpty())
return;
UINT nRet = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
GetMusicFileList()[nRet]->resume();
}
void e2d::Music::resume(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->pause();
}
void e2d::Music::stop(const String& filePath)
{
if (filePath.isEmpty())
return;
UINT nRet = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
GetMusicFileList()[nRet]->stop();
}
void e2d::Music::stop(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->stop();
}
bool e2d::Music::isPlaying(const String& filePath)
{
if (filePath.isEmpty())
return false;
UINT nRet = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(nRet))
return GetMusicFileList()[nRet]->isPlaying();
return false;
}
bool e2d::Music::isPlaying(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
return GetMusicResList()[resNameId]->isPlaying();
return false;
}
double e2d::Music::getVolume()
{
return s_fMusicVolume;
}
void e2d::Music::setVolume(double fVolume)
{
s_fMusicVolume = min(max(float(fVolume), -224), 224);
for (auto pair : GetMusicFileList())
{
pair.second->setVolume(s_fMusicVolume);
}
}
void e2d::Music::pauseAll()
{
for (auto pair : GetMusicFileList())
{
pair.second->pause();
}
}
void e2d::Music::resumeAll()
{
for (auto pair : GetMusicFileList())
{
pair.second->resume();
}
}
void e2d::Music::stopAll()
{
for (auto pair : GetMusicFileList())
{
pair.second->stop();
}
}
IXAudio2 * e2d::Music::getIXAudio2() IXAudio2 * e2d::Music::getIXAudio2()
{ {
return s_pXAudio2; return s_pXAudio2;
@ -825,14 +602,6 @@ bool e2d::Music::__init()
void e2d::Music::__uninit() void e2d::Music::__uninit()
{ {
for (auto pair : GetMusicFileList())
{
pair.second->close();
delete pair.second;
}
GetMusicFileList().clear();
if (s_pMasteringVoice) if (s_pMasteringVoice)
{ {
s_pMasteringVoice->DestroyVoice(); s_pMasteringVoice->DestroyVoice();

218
core/Tool/Player.cpp Normal file
View File

@ -0,0 +1,218 @@
#include "..\e2dtool.h"
#include <map>
typedef std::map<UINT, e2d::Music *> MusicMap;
static MusicMap& GetMusicFileList()
{
static MusicMap s_MusicFileList;
return s_MusicFileList;
}
static MusicMap& GetMusicResList()
{
static MusicMap s_MusicResList;
return s_MusicResList;
}
static float s_fMusicVolume = 1.0;
bool e2d::Player::preload(const String& filePath)
{
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
{
return true;
}
else
{
Music * music = new (std::nothrow) Music();
if (music->open(filePath))
{
music->setVolume(s_fMusicVolume);
GetMusicFileList().insert(std::pair<UINT, Music *>(hash, music));
return true;
}
else
{
delete music;
music = nullptr;
}
}
return false;
}
bool e2d::Player::preload(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
{
return true;
}
else
{
Music * music = new (std::nothrow) Music();
if (music->open(resNameId, resType))
{
music->setVolume(s_fMusicVolume);
GetMusicResList().insert(std::pair<UINT, Music *>(resNameId, music));
return true;
}
else
{
delete music;
music = nullptr;
}
}
return false;
}
bool e2d::Player::play(const String& filePath, int nLoopCount)
{
if (Player::preload(filePath))
{
UINT hash = filePath.getHashCode();
auto music = GetMusicFileList()[hash];
if (music->play(nLoopCount))
{
return true;
}
}
return false;
}
bool e2d::Player::play(int resNameId, const String& resType, int nLoopCount)
{
if (Player::preload(resNameId, resType))
{
auto music = GetMusicResList()[resNameId];
if (music->play(nLoopCount))
{
return true;
}
}
return false;
}
void e2d::Player::pause(const String& filePath)
{
if (filePath.isEmpty())
return;
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
GetMusicFileList()[hash]->pause();
}
void e2d::Player::pause(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->pause();
}
void e2d::Player::resume(const String& filePath)
{
if (filePath.isEmpty())
return;
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
GetMusicFileList()[hash]->resume();
}
void e2d::Player::resume(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->pause();
}
void e2d::Player::stop(const String& filePath)
{
if (filePath.isEmpty())
return;
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
GetMusicFileList()[hash]->stop();
}
void e2d::Player::stop(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
GetMusicResList()[resNameId]->stop();
}
bool e2d::Player::isPlaying(const String& filePath)
{
if (filePath.isEmpty())
return false;
UINT hash = filePath.getHashCode();
if (GetMusicFileList().end() != GetMusicFileList().find(hash))
return GetMusicFileList()[hash]->isPlaying();
return false;
}
bool e2d::Player::isPlaying(int resNameId, const String& resType)
{
if (GetMusicResList().end() != GetMusicResList().find(resNameId))
return GetMusicResList()[resNameId]->isPlaying();
return false;
}
double e2d::Player::getVolume()
{
return s_fMusicVolume;
}
void e2d::Player::setVolume(double volume)
{
s_fMusicVolume = min(max(float(volume), -224), 224);
for (auto pair : GetMusicFileList())
{
pair.second->setVolume(s_fMusicVolume);
}
}
void e2d::Player::pauseAll()
{
for (auto pair : GetMusicFileList())
{
pair.second->pause();
}
}
void e2d::Player::resumeAll()
{
for (auto pair : GetMusicFileList())
{
pair.second->resume();
}
}
void e2d::Player::stopAll()
{
for (auto pair : GetMusicFileList())
{
pair.second->stop();
}
}
void e2d::Player::__uninit()
{
for (auto pair : GetMusicFileList())
{
pair.second->close();
delete pair.second;
}
GetMusicFileList().clear();
}

View File

@ -164,9 +164,6 @@ private:
// 初始化计时操作 // 初始化计时操作
static bool __init(); static bool __init();
// 重置计时操作
static void __uninit();
// 是否达到更新时间 // 是否达到更新时间
static bool __isReady(); static bool __isReady();

View File

@ -11,7 +11,7 @@ class Renderer;
class Node; class Node;
class Timer; class Timer;
class Action; class Action;
class Music; class Player;
class Collider; class Collider;
class Transition; class Transition;

View File

@ -50,8 +50,122 @@ private:
}; };
// 音乐
class Music :
public Object
{
friend Game;
public:
Music();
Music(
const e2d::String& filePath /* 音乐文件路径 */
);
Music(
int resNameId, /* 音乐资源名称 */
const String& resType /* 音乐资源类型 */
);
virtual ~Music();
// 创建音乐对象
static Music * create();
// 创建音乐对象
static Music * create(
const e2d::String& filePath /* 音乐文件路径 */
);
// 创建音乐对象
static Music * create(
int resNameId, /* 音乐资源名称 */
const String& resType /* 音乐资源类型 */
);
// 打开音乐文件
bool open(
const e2d::String& filePath /* 音乐文件路径 */
);
// 打开音乐资源
bool open(
int resNameId, /* 音乐资源名称 */
const String& resType /* 音乐资源类型 */
);
// 播放
bool play(
int nLoopCount = 0
);
// 暂停
void pause();
// 继续
void resume();
// 停止
void stop();
// 关闭并回收资源
void close();
// 设置音量
bool setVolume(
double volume
);
// 是否正在播放
bool isPlaying() const;
// 获取 IXAudio2SourceVoice 对象
IXAudio2SourceVoice * getIXAudio2SourceVoice() const;
// 获取 IXAudio2 对象
static IXAudio2 * getIXAudio2();
// 获取 IXAudio2MasteringVoice 对象
static IXAudio2MasteringVoice * getIXAudio2MasteringVoice();
protected:
bool _readMMIO();
bool _resetFile();
bool _read(
BYTE* pBuffer,
DWORD dwSizeToRead
);
bool _findMediaFileCch(
wchar_t* strDestPath,
int cchDest,
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;
IXAudio2SourceVoice* _voice;
};
// 稜있꺄렴포 // 稜있꺄렴포
class Music class Player
{ {
friend Game; friend Game;
@ -61,18 +175,38 @@ public:
const String& filePath /* 稜있匡숭쨌쓺 */ const String& filePath /* 稜있匡숭쨌쓺 */
); );
// 预加载音乐资源
static bool preload(
int resNameId, /* 音乐资源名称 */
const String& resType /* 音乐资源类型 */
);
// 꺄렴稜있 // 꺄렴稜있
static bool play( static bool play(
const String& filePath, /* 稜있匡숭쨌쓺 */ const String& filePath, /* 稜있匡숭쨌쓺 */
int nLoopCount = 0 /* 路릿꺄렴늴鑒<E99192>零 -1 槨琦뻔꺄렴 */ int nLoopCount = 0 /* 路릿꺄렴늴鑒<E99192>零 -1 槨琦뻔꺄렴 */
); );
// 暂停音乐
static void pause(
const String& filePath /* 音乐文件路径 */
);
// 继续播放音乐
static void resume(
const String& filePath /* 音乐文件路径 */
);
// 停止音乐
static void stop(
const String& filePath /* 音乐文件路径 */
);
// 获取音乐播放状态
static bool isPlaying(
const String& filePath /* 音乐文件路径 */
);
// 预加载音乐资源
static bool preload(
int resNameId, /* 音乐资源名称 */
const String& resType /* 音乐资源类型 */
);
// 꺄렴稜있 // 꺄렴稜있
static bool play( static bool play(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
@ -80,44 +214,24 @@ public:
int nLoopCount = 0 /* 路릿꺄렴늴鑒<E99192>零 -1 槨琦뻔꺄렴 */ int nLoopCount = 0 /* 路릿꺄렴늴鑒<E99192>零 -1 槨琦뻔꺄렴 */
); );
// 暂停音乐
static void pause(
const String& filePath /* 音乐文件路径 */
);
// 董界稜있 // 董界稜있
static void pause( static void pause(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType /* 稜있栗都잚謹 */ const String& resType /* 稜있栗都잚謹 */
); );
// 继续播放音乐
static void resume(
const String& filePath /* 音乐文件路径 */
);
// 셨崎꺄렴稜있 // 셨崎꺄렴稜있
static void resume( static void resume(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType /* 稜있栗都잚謹 */ const String& resType /* 稜있栗都잚謹 */
); );
// 停止音乐
static void stop(
const String& filePath /* 音乐文件路径 */
);
// 界岺稜있 // 界岺稜있
static void stop( static void stop(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
const String& resType /* 稜있栗都잚謹 */ const String& resType /* 稜있栗都잚謹 */
); );
// 获取音乐播放状态
static bool isPlaying(
const String& filePath /* 音乐文件路径 */
);
// 삿혤稜있꺄렴榴檄 // 삿혤稜있꺄렴榴檄
static bool isPlaying( static bool isPlaying(
int resNameId, /* 稜있栗都츰냔 */ int resNameId, /* 稜있栗都츰냔 */
@ -129,7 +243,7 @@ public:
// <20>零稜좆 // <20>零稜좆
static void setVolume( static void setVolume(
double fVolume /* 音量范围为 -224 ~ 2240 是静音1 是正常音量 */ double volume /* 音量范围为 -224 ~ 2240 是静音1 是正常音量 */
); );
// 董界杰唐稜있 // 董界杰唐稜있
@ -141,15 +255,7 @@ public:
// 界岺杰唐稜있 // 界岺杰唐稜있
static void stopAll(); static void stopAll();
// 获取 IXAudio2 对象
static IXAudio2 * getIXAudio2();
// 获取 IXAudio2MasteringVoice 对象
static IXAudio2MasteringVoice * getIXAudio2MasteringVoice();
private: private:
static bool __init();
static void __uninit(); static void __uninit();
}; };

View File

@ -250,8 +250,9 @@
<ClCompile Include="..\..\core\Node\Sprite.cpp" /> <ClCompile Include="..\..\core\Node\Sprite.cpp" />
<ClCompile Include="..\..\core\Node\Text.cpp" /> <ClCompile Include="..\..\core\Node\Text.cpp" />
<ClCompile Include="..\..\core\Tool\Data.cpp" /> <ClCompile Include="..\..\core\Tool\Data.cpp" />
<ClCompile Include="..\..\core\Tool\Path.cpp" />
<ClCompile Include="..\..\core\Tool\Music.cpp" /> <ClCompile Include="..\..\core\Tool\Music.cpp" />
<ClCompile Include="..\..\core\Tool\Path.cpp" />
<ClCompile Include="..\..\core\Tool\Player.cpp" />
<ClCompile Include="..\..\core\Tool\Random.cpp" /> <ClCompile Include="..\..\core\Tool\Random.cpp" />
<ClCompile Include="..\..\core\Tool\Timer.cpp" /> <ClCompile Include="..\..\core\Tool\Timer.cpp" />
<ClCompile Include="..\..\core\Transition\Transition.cpp" /> <ClCompile Include="..\..\core\Transition\Transition.cpp" />

View File

@ -96,9 +96,6 @@
<ClCompile Include="..\..\core\Base\Renderer.cpp"> <ClCompile Include="..\..\core\Base\Renderer.cpp">
<Filter>Base</Filter> <Filter>Base</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\core\Tool\Music.cpp">
<Filter>Tool</Filter>
</ClCompile>
<ClCompile Include="..\..\core\Common\Point.cpp"> <ClCompile Include="..\..\core\Common\Point.cpp">
<Filter>Common</Filter> <Filter>Common</Filter>
</ClCompile> </ClCompile>
@ -219,6 +216,12 @@
<ClCompile Include="..\..\core\Action\JumpTo.cpp"> <ClCompile Include="..\..\core\Action\JumpTo.cpp">
<Filter>Action</Filter> <Filter>Action</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\core\Tool\Player.cpp">
<Filter>Tool</Filter>
</ClCompile>
<ClCompile Include="..\..\core\Tool\Music.cpp">
<Filter>Tool</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\core\easy2d.h" /> <ClInclude Include="..\..\core\easy2d.h" />