New feature: XAudio2.
This commit is contained in:
parent
71b39a8149
commit
342b8e050a
|
|
@ -20,35 +20,65 @@ bool e2d::EGame::init(LPCTSTR sTitle, UINT32 nWidth, UINT32 nHeight, LPCTSTR pIc
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化 COM 组件
|
do
|
||||||
if (SUCCEEDED(CoInitialize(NULL)))
|
|
||||||
{
|
{
|
||||||
// 创建设备无关资源
|
// 初始化 COM 组件
|
||||||
if (ERenderer::__createDeviceIndependentResources())
|
if (FAILED(CoInitializeEx(NULL, COINIT_MULTITHREADED)))
|
||||||
{
|
{
|
||||||
// 初始化窗口
|
WARN_IF(true, "CoInitializeEx Failed!");
|
||||||
if (EWindow::__init(sTitle, nWidth, nHeight, pIconID))
|
break;
|
||||||
{
|
|
||||||
// 创建设备相关资源
|
|
||||||
if (ERenderer::__createDeviceResources())
|
|
||||||
{
|
|
||||||
// 重设 Client 大小
|
|
||||||
EWindow::setSize(nWidth, nHeight);
|
|
||||||
// 设置 AppName
|
|
||||||
if (sAppname)
|
|
||||||
{
|
|
||||||
s_sAppName = sAppname;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s_sAppName = EWindow::getTitle();
|
|
||||||
}
|
|
||||||
// 标志初始化成功
|
|
||||||
s_bInitialized = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
// 创建设备无关资源
|
||||||
|
if (!ERenderer::__createDeviceIndependentResources())
|
||||||
|
{
|
||||||
|
WARN_IF(true, "ERenderer::__createDeviceIndependentResources Failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化窗口
|
||||||
|
if (!EWindow::__init(sTitle, nWidth, nHeight, pIconID))
|
||||||
|
{
|
||||||
|
WARN_IF(true, "EWindow::__init Failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建设备相关资源
|
||||||
|
if (!ERenderer::__createDeviceResources())
|
||||||
|
{
|
||||||
|
WARN_IF(true, "ERenderer::__createDeviceResources Failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化计时
|
||||||
|
if (!ETime::__init())
|
||||||
|
{
|
||||||
|
WARN_IF(true, "ETime::__init Failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化 DirectInput
|
||||||
|
if (!EInput::__init())
|
||||||
|
{
|
||||||
|
WARN_IF(true, "EInput::__init Failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化播放器
|
||||||
|
if (!EMusicManager::__init())
|
||||||
|
{
|
||||||
|
WARN_IF(true, "EMusicManager::__init Failed!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重设 Client 大小
|
||||||
|
EWindow::setSize(nWidth, nHeight);
|
||||||
|
// 设置 AppName
|
||||||
|
s_sAppName = (sAppname != nullptr) ? sAppname : EWindow::getTitle();
|
||||||
|
// 标志初始化成功
|
||||||
|
s_bInitialized = true;
|
||||||
|
|
||||||
|
} while (0);
|
||||||
|
|
||||||
return s_bInitialized;
|
return s_bInitialized;
|
||||||
}
|
}
|
||||||
|
|
@ -61,12 +91,8 @@ int e2d::EGame::run()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 初始化 DirectInput
|
// 初始化场景管理器
|
||||||
EInput::__init();
|
ESceneManager::__init();
|
||||||
// 初始化计时操作
|
|
||||||
ETime::__init();
|
|
||||||
// 进入第一个场景
|
|
||||||
ESceneManager::__enterNextScene();
|
|
||||||
// 显示窗口
|
// 显示窗口
|
||||||
::ShowWindow(EWindow::getHWnd(), SW_SHOWNORMAL);
|
::ShowWindow(EWindow::getHWnd(), SW_SHOWNORMAL);
|
||||||
// 刷新窗口内容
|
// 刷新窗口内容
|
||||||
|
|
@ -93,8 +119,8 @@ int e2d::EGame::run()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 挂起线程
|
EObjectManager::__flush(); // 刷新内存池
|
||||||
ETime::__sleep();
|
ETime::__sleep(); // 挂起线程
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,16 +157,24 @@ void e2d::EGame::quit()
|
||||||
|
|
||||||
void e2d::EGame::uninit()
|
void e2d::EGame::uninit()
|
||||||
{
|
{
|
||||||
|
// 删除所有场景
|
||||||
|
ESceneManager::__uninit();
|
||||||
// 重置窗口属性
|
// 重置窗口属性
|
||||||
EWindow::__uninit();
|
EWindow::__uninit();
|
||||||
// 关闭输入
|
// 关闭输入
|
||||||
EInput::__uninit();
|
EInput::__uninit();
|
||||||
|
// 关闭播放器
|
||||||
|
EMusicManager::__uninit();
|
||||||
// 恢复计时操作
|
// 恢复计时操作
|
||||||
ETime::__uninit();
|
ETime::__uninit();
|
||||||
// 删除渲染相关资源
|
// 删除渲染相关资源
|
||||||
ERenderer::__discardResources();
|
ERenderer::__discardResources();
|
||||||
|
// 刷新内存池
|
||||||
|
EObjectManager::__flush();
|
||||||
|
|
||||||
CoUninitialize();
|
CoUninitialize();
|
||||||
|
|
||||||
|
s_bInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::EGame::__update()
|
void e2d::EGame::__update()
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ void EInput::__uninit()
|
||||||
SafeReleaseInterface(&s_pDirectInput);
|
SafeReleaseInterface(&s_pDirectInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT EInput::__init()
|
bool EInput::__init()
|
||||||
{
|
{
|
||||||
ZeroMemory(s_KeyBuffer, sizeof(s_KeyBuffer));
|
ZeroMemory(s_KeyBuffer, sizeof(s_KeyBuffer));
|
||||||
ZeroMemory(s_KeySecBuffer, sizeof(s_KeySecBuffer));
|
ZeroMemory(s_KeySecBuffer, sizeof(s_KeySecBuffer));
|
||||||
|
|
@ -41,7 +41,7 @@ HRESULT EInput::__init()
|
||||||
DIRECTINPUT_VERSION,
|
DIRECTINPUT_VERSION,
|
||||||
IID_IDirectInput8,
|
IID_IDirectInput8,
|
||||||
(void**)&s_pDirectInput,
|
(void**)&s_pDirectInput,
|
||||||
NULL
|
nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
|
@ -50,7 +50,7 @@ HRESULT EInput::__init()
|
||||||
hr = s_pDirectInput->CreateDevice(
|
hr = s_pDirectInput->CreateDevice(
|
||||||
GUID_SysKeyboard,
|
GUID_SysKeyboard,
|
||||||
&s_KeyboardDevice,
|
&s_KeyboardDevice,
|
||||||
NULL
|
nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
|
|
@ -77,7 +77,7 @@ HRESULT EInput::__init()
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
// 初始化鼠标设备
|
// 初始化鼠标设备
|
||||||
hr = s_pDirectInput->CreateDevice(GUID_SysMouse, &s_MouseDevice, NULL);
|
hr = s_pDirectInput->CreateDevice(GUID_SysMouse, &s_MouseDevice, nullptr);
|
||||||
|
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -33,9 +33,10 @@ static steady_clock::time_point s_tNow;
|
||||||
static steady_clock::time_point s_tLast;
|
static steady_clock::time_point s_tLast;
|
||||||
|
|
||||||
|
|
||||||
void e2d::ETime::__init()
|
bool e2d::ETime::__init()
|
||||||
{
|
{
|
||||||
s_tStart = s_tLast = s_tNow = steady_clock::now();
|
s_tStart = s_tLast = s_tNow = steady_clock::now();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::ETime::__uninit()
|
void e2d::ETime::__uninit()
|
||||||
|
|
@ -83,12 +84,23 @@ static LARGE_INTEGER s_tLast;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void e2d::ETime::__init()
|
bool e2d::ETime::__init()
|
||||||
{
|
{
|
||||||
::timeBeginPeriod(1); // 修改时间精度
|
bool bRet = false;
|
||||||
::QueryPerformanceFrequency(&s_tFreq); // 获取时钟频率
|
if (::timeBeginPeriod(1))
|
||||||
::QueryPerformanceCounter(&s_tNow); // 刷新当前时间
|
{
|
||||||
s_tStart = s_tLast = s_tNow;
|
// 修改时间精度
|
||||||
|
if (::QueryPerformanceFrequency(&s_tFreq)) // 获取时钟频率
|
||||||
|
{
|
||||||
|
|
||||||
|
if (::QueryPerformanceCounter(&s_tNow)) // 刷新当前时间
|
||||||
|
{
|
||||||
|
s_tStart = s_tLast = s_tNow;
|
||||||
|
bRet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::ETime::__uninit()
|
void e2d::ETime::__uninit()
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ bool e2d::EWindow::__init(LPCTSTR sTitle, UINT32 nWidth, UINT32 nHeight, LPCTSTR
|
||||||
s_HWnd = CreateWindow(
|
s_HWnd = CreateWindow(
|
||||||
L"Easy2DApp",
|
L"Easy2DApp",
|
||||||
sTitle,
|
sTitle,
|
||||||
WS_OVERLAPPED | WS_SYSMENU,
|
WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX,
|
||||||
0, 0, nWidth, nHeight,
|
0, 0, nWidth, nHeight,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
|
|
@ -193,7 +193,7 @@ void e2d::EWindow::showConsole(bool show /* = true */)
|
||||||
FILE * stdoutStream, * stdinStream, * stderrStream;
|
FILE * stdoutStream, * stdinStream, * stderrStream;
|
||||||
freopen_s(&stdoutStream, "conout$", "w+t", stdout);
|
freopen_s(&stdoutStream, "conout$", "w+t", stdout);
|
||||||
freopen_s(&stdinStream, "conin$", "r+t", stdin);
|
freopen_s(&stdinStream, "conin$", "r+t", stdin);
|
||||||
freopen_s(&stderrStream, "conerr$", "w+t", stderr);
|
freopen_s(&stderrStream, "conout$", "w+t", stderr);
|
||||||
// 禁用控制台关闭按钮
|
// 禁用控制台关闭按钮
|
||||||
HMENU hmenu = ::GetSystemMenu(hwnd, FALSE);
|
HMENU hmenu = ::GetSystemMenu(hwnd, FALSE);
|
||||||
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
|
::RemoveMenu(hmenu, SC_CLOSE, MF_BYCOMMAND);
|
||||||
|
|
|
||||||
|
|
@ -211,7 +211,6 @@ bool e2d::EImage::preload(LPCTSTR resourceName, LPCTSTR resourceType)
|
||||||
IWICBitmapFrameDecode *pSource = nullptr;
|
IWICBitmapFrameDecode *pSource = nullptr;
|
||||||
IWICStream *pStream = nullptr;
|
IWICStream *pStream = nullptr;
|
||||||
IWICFormatConverter *pConverter = nullptr;
|
IWICFormatConverter *pConverter = nullptr;
|
||||||
IWICBitmapScaler *pScaler = nullptr;
|
|
||||||
ID2D1Bitmap *pBitmap = nullptr;
|
ID2D1Bitmap *pBitmap = nullptr;
|
||||||
|
|
||||||
HRSRC imageResHandle = nullptr;
|
HRSRC imageResHandle = nullptr;
|
||||||
|
|
@ -329,7 +328,6 @@ bool e2d::EImage::preload(LPCTSTR resourceName, LPCTSTR resourceType)
|
||||||
SafeReleaseInterface(&pSource);
|
SafeReleaseInterface(&pSource);
|
||||||
SafeReleaseInterface(&pStream);
|
SafeReleaseInterface(&pStream);
|
||||||
SafeReleaseInterface(&pConverter);
|
SafeReleaseInterface(&pConverter);
|
||||||
SafeReleaseInterface(&pScaler);
|
|
||||||
|
|
||||||
return SUCCEEDED(hr);
|
return SUCCEEDED(hr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
#include "..\emanagers.h"
|
||||||
|
#include "..\etools.h"
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
static IXAudio2 * s_pXAudio2 = nullptr;
|
||||||
|
static IXAudio2MasteringVoice * s_pMasteringVoice = nullptr;
|
||||||
|
|
||||||
|
typedef std::pair<UINT, e2d::EMusic *> MusicPair;
|
||||||
|
typedef std::map<UINT, e2d::EMusic *> MusicList;
|
||||||
|
|
||||||
|
static MusicList& getMusicList()
|
||||||
|
{
|
||||||
|
static MusicList s_List;
|
||||||
|
return s_List;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
e2d::EMusic * e2d::EMusicManager::add(const EString & strFilePath)
|
||||||
|
{
|
||||||
|
EMusic * pPlayer = get(strFilePath);
|
||||||
|
if (pPlayer)
|
||||||
|
{
|
||||||
|
return pPlayer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UINT nRet = strFilePath.hash();
|
||||||
|
|
||||||
|
getMusicList().insert(MusicPair(nRet, new EMusic()));
|
||||||
|
pPlayer = getMusicList()[nRet];
|
||||||
|
|
||||||
|
if (pPlayer->_open(strFilePath))
|
||||||
|
{
|
||||||
|
return pPlayer;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delete pPlayer;
|
||||||
|
getMusicList().erase(nRet);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e2d::EMusic * e2d::EMusicManager::get(const EString & strFilePath)
|
||||||
|
{
|
||||||
|
if (strFilePath.isEmpty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
UINT nRet = strFilePath.hash();
|
||||||
|
|
||||||
|
if (getMusicList().end() != getMusicList().find(nRet))
|
||||||
|
return getMusicList()[nRet];
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void e2d::EMusicManager::pauseAllMusics()
|
||||||
|
{
|
||||||
|
for (auto iter = getMusicList().begin(); iter != getMusicList().end(); iter++)
|
||||||
|
{
|
||||||
|
(*iter).second->pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void e2d::EMusicManager::resumeAllMusics()
|
||||||
|
{
|
||||||
|
for (auto iter = getMusicList().begin(); iter != getMusicList().end(); iter++)
|
||||||
|
{
|
||||||
|
(*iter).second->resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void e2d::EMusicManager::stopAllMusics()
|
||||||
|
{
|
||||||
|
for (auto iter = getMusicList().begin(); iter != getMusicList().end(); iter++)
|
||||||
|
{
|
||||||
|
(*iter).second->stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IXAudio2 * e2d::EMusicManager::getIXAudio2()
|
||||||
|
{
|
||||||
|
return s_pXAudio2;
|
||||||
|
}
|
||||||
|
|
||||||
|
IXAudio2MasteringVoice * e2d::EMusicManager::getIXAudio2MasteringVoice()
|
||||||
|
{
|
||||||
|
return s_pMasteringVoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool e2d::EMusicManager::__init()
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
if (FAILED(hr = XAudio2Create(&s_pXAudio2, 0)))
|
||||||
|
{
|
||||||
|
WARN_IF(true, "Failed to init XAudio2 engine");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FAILED(hr = s_pXAudio2->CreateMasteringVoice(&s_pMasteringVoice)))
|
||||||
|
{
|
||||||
|
WARN_IF(true, "Failed creating mastering voice");
|
||||||
|
SafeReleaseInterface(&s_pXAudio2);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void e2d::EMusicManager::__uninit()
|
||||||
|
{
|
||||||
|
for (auto iter = getMusicList().begin(); iter != getMusicList().end(); iter++)
|
||||||
|
{
|
||||||
|
(*iter).second->_close();
|
||||||
|
(*iter).second->release();
|
||||||
|
}
|
||||||
|
getMusicList().clear();
|
||||||
|
|
||||||
|
if (s_pMasteringVoice)
|
||||||
|
{
|
||||||
|
s_pMasteringVoice->DestroyVoice();
|
||||||
|
}
|
||||||
|
|
||||||
|
SafeReleaseInterface(&s_pXAudio2);
|
||||||
|
}
|
||||||
|
|
@ -94,8 +94,24 @@ void e2d::ESceneManager::__update()
|
||||||
// 下一场景指针不为空时,切换场景
|
// 下一场景指针不为空时,切换场景
|
||||||
if (s_pNextScene)
|
if (s_pNextScene)
|
||||||
{
|
{
|
||||||
// 进入下一场景
|
// 若要保存当前场景,把它放入栈中
|
||||||
__enterNextScene();
|
if (s_pCurrentScene->m_bWillSave)
|
||||||
|
{
|
||||||
|
s_SceneStack.push(s_pCurrentScene);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SafeRelease(&s_pCurrentScene);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行当前场景的 onExit 函数
|
||||||
|
s_pCurrentScene->onExit();
|
||||||
|
|
||||||
|
// 执行下一场景的 onEnter 函数
|
||||||
|
s_pNextScene->onEnter();
|
||||||
|
|
||||||
|
s_pCurrentScene = s_pNextScene; // 切换场景
|
||||||
|
s_pNextScene = nullptr; // 下一场景置空
|
||||||
}
|
}
|
||||||
|
|
||||||
// 断言当前场景非空
|
// 断言当前场景非空
|
||||||
|
|
@ -119,30 +135,21 @@ void e2d::ESceneManager::__render()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void e2d::ESceneManager::__enterNextScene()
|
bool e2d::ESceneManager::__init()
|
||||||
{
|
{
|
||||||
if (s_pNextScene == nullptr)
|
if (s_pNextScene == nullptr)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// 执行当前场景的 onCloseWindow 函数
|
s_pCurrentScene = s_pNextScene;
|
||||||
if (s_pCurrentScene)
|
s_pCurrentScene->onEnter();
|
||||||
{
|
s_pNextScene = nullptr;
|
||||||
s_pCurrentScene->onExit();
|
return true;
|
||||||
|
}
|
||||||
if (s_pCurrentScene->m_bWillSave)
|
|
||||||
{
|
void e2d::ESceneManager::__uninit()
|
||||||
// 若要保存当前场景,把它放入栈中
|
{
|
||||||
s_SceneStack.push(s_pCurrentScene);
|
SafeRelease(&s_pCurrentScene);
|
||||||
}
|
SafeRelease(&s_pNextScene);
|
||||||
else
|
SafeRelease(&s_pTransition);
|
||||||
{
|
ESceneManager::clearScene();
|
||||||
SafeRelease(&s_pCurrentScene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 执行下一场景的 onEnter 函数
|
|
||||||
s_pNextScene->onEnter();
|
|
||||||
|
|
||||||
s_pCurrentScene = s_pNextScene; // 切换场景
|
|
||||||
s_pNextScene = nullptr; // 下一场景置空
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,443 +1,469 @@
|
||||||
#include "..\etools.h"
|
#include "..\etools.h"
|
||||||
#include <map>
|
#include "..\emanagers.h"
|
||||||
#include <mmsystem.h>
|
|
||||||
#pragma comment(lib , "winmm.lib")
|
|
||||||
|
|
||||||
#define WIN_CLASS_NAME L"MciPlayerCallbackWnd"
|
using namespace e2d;
|
||||||
|
|
||||||
static HINSTANCE s_hInstance = nullptr;
|
#ifndef SAFE_DELETE
|
||||||
|
#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; } }
|
||||||
|
#endif
|
||||||
|
|
||||||
LRESULT WINAPI _MciPlayerProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
inline bool TraceError(LPCTSTR sPrompt)
|
||||||
static bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName);
|
|
||||||
|
|
||||||
class MciPlayer
|
|
||||||
{
|
{
|
||||||
public:
|
WARN_IF(true, "EMusic error: %s failed!", sPrompt);
|
||||||
MciPlayer();
|
return false;
|
||||||
~MciPlayer();
|
}
|
||||||
|
|
||||||
void close();
|
inline bool TraceError(LPCTSTR sPrompt, HRESULT hr)
|
||||||
bool open(const e2d::EString & pFileName, UINT uId);
|
{
|
||||||
bool open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId);
|
WARN_IF(true, "EMusic error: %s (%#X)", sPrompt, hr);
|
||||||
void play(int repeatTimes);
|
return false;
|
||||||
void pause();
|
}
|
||||||
void resume();
|
|
||||||
void stop();
|
|
||||||
void rewind();
|
|
||||||
bool isPlaying();
|
|
||||||
UINT getMusicID();
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend LRESULT WINAPI _MciPlayerProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
|
|
||||||
void _sendCommand(int nCommand, DWORD_PTR param1 = 0, DWORD_PTR parma2 = 0);
|
|
||||||
|
|
||||||
MCIDEVICEID m_dev;
|
|
||||||
HWND m_wnd;
|
|
||||||
UINT m_nMusicID;
|
|
||||||
bool m_bPlaying;
|
|
||||||
int m_nRepeatTimes;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
MciPlayer::MciPlayer()
|
EMusic::EMusic()
|
||||||
: m_wnd(NULL)
|
: m_bOpened(false)
|
||||||
, m_dev(0L)
|
|
||||||
, m_nMusicID(0)
|
|
||||||
, m_bPlaying(false)
|
, m_bPlaying(false)
|
||||||
, m_nRepeatTimes(0)
|
, m_pwfx(nullptr)
|
||||||
|
, m_hmmio(nullptr)
|
||||||
|
, m_pResourceBuffer(nullptr)
|
||||||
|
, m_pbWaveData(nullptr)
|
||||||
|
, m_dwSize(0)
|
||||||
|
, m_pSourceVoice(nullptr)
|
||||||
{
|
{
|
||||||
if (!s_hInstance)
|
|
||||||
{
|
|
||||||
s_hInstance = HINST_THISCOMPONENT;
|
|
||||||
|
|
||||||
WNDCLASS wc;
|
|
||||||
wc.style = 0;
|
|
||||||
wc.lpfnWndProc = _MciPlayerProc;
|
|
||||||
wc.cbClsExtra = 0;
|
|
||||||
wc.cbWndExtra = 0;
|
|
||||||
wc.hInstance = s_hInstance;
|
|
||||||
wc.hIcon = 0;
|
|
||||||
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
|
|
||||||
wc.hbrBackground = NULL;
|
|
||||||
wc.lpszMenuName = NULL;
|
|
||||||
wc.lpszClassName = WIN_CLASS_NAME;
|
|
||||||
|
|
||||||
if (!RegisterClass(&wc) && 1410 != GetLastError())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
m_wnd = CreateWindowEx(
|
|
||||||
WS_EX_APPWINDOW,
|
|
||||||
WIN_CLASS_NAME,
|
|
||||||
NULL,
|
|
||||||
WS_POPUPWINDOW,
|
|
||||||
0, 0, 0, 0,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
s_hInstance,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (m_wnd)
|
|
||||||
{
|
|
||||||
SetWindowLongPtr(m_wnd, GWLP_USERDATA, (LONG_PTR)this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MciPlayer::~MciPlayer()
|
EMusic::~EMusic()
|
||||||
{
|
{
|
||||||
close();
|
_close();
|
||||||
DestroyWindow(m_wnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MciPlayer::open(const e2d::EString & pFileName, UINT uId)
|
bool EMusic::_open(LPWSTR strFileName)
|
||||||
{
|
{
|
||||||
if (pFileName.isEmpty())
|
if (m_bOpened)
|
||||||
|
{
|
||||||
|
WARN_IF(true, L"EMusic can be opened only once!");
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
close();
|
|
||||||
|
|
||||||
MCI_OPEN_PARMS mciOpen = { 0 };
|
|
||||||
mciOpen.lpstrDeviceType = 0;
|
|
||||||
mciOpen.lpstrElementName = pFileName;
|
|
||||||
|
|
||||||
MCIERROR mciError;
|
|
||||||
mciError = mciSendCommand(
|
|
||||||
0,
|
|
||||||
MCI_OPEN,
|
|
||||||
MCI_OPEN_ELEMENT,
|
|
||||||
reinterpret_cast<DWORD_PTR>(&mciOpen)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (mciError == 0)
|
|
||||||
{
|
|
||||||
m_dev = mciOpen.wDeviceID;
|
|
||||||
m_nMusicID = uId;
|
|
||||||
m_bPlaying = false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
if (strFileName == nullptr)
|
||||||
|
{
|
||||||
|
WARN_IF(true, L"EMusic::_open Invalid file name.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IXAudio2 * pXAudio2 = EMusicManager::getIXAudio2();
|
||||||
|
if (!pXAudio2)
|
||||||
|
{
|
||||||
|
WARN_IF(true, L"IXAudio2 nullptr pointer error!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定位 wave 文件
|
||||||
|
wchar_t strFilePath[MAX_PATH];
|
||||||
|
if (!_findMediaFileCch(strFilePath, MAX_PATH, strFileName))
|
||||||
|
{
|
||||||
|
WARN_IF(true, L"Failed to find media file: %s", strFileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_hmmio = mmioOpen(strFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
|
||||||
|
|
||||||
|
if (nullptr == m_hmmio)
|
||||||
|
{
|
||||||
|
return TraceError(L"mmioOpen");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_readMMIO())
|
||||||
|
{
|
||||||
|
// 读取非 wave 文件时 ReadMMIO 调用失败
|
||||||
|
mmioClose(m_hmmio, 0);
|
||||||
|
return TraceError(L"_readMMIO");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_resetFile())
|
||||||
|
return TraceError(L"_resetFile");
|
||||||
|
|
||||||
|
// 重置文件后,wave 文件的大小是 m_ck.cksize
|
||||||
|
m_dwSize = m_ck.cksize;
|
||||||
|
|
||||||
|
// 将样本数据读取到内存中
|
||||||
|
m_pbWaveData = new BYTE[m_dwSize];
|
||||||
|
|
||||||
|
if (!_read(m_pbWaveData, m_dwSize))
|
||||||
|
{
|
||||||
|
TraceError(L"Failed to read WAV data");
|
||||||
|
SAFE_DELETE_ARRAY(m_pbWaveData);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建音源
|
||||||
|
HRESULT hr;
|
||||||
|
if (FAILED(hr = pXAudio2->CreateSourceVoice(&m_pSourceVoice, m_pwfx)))
|
||||||
|
{
|
||||||
|
TraceError(L"Error %#X creating source voice", hr);
|
||||||
|
SAFE_DELETE_ARRAY(m_pbWaveData);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_bOpened = true;
|
||||||
|
m_bPlaying = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MciPlayer::open(const e2d::EString & pResouceName, const e2d::EString & pResouceType, const e2d::EString & musicExtension, UINT uId)
|
bool EMusic::play(int nLoopCount)
|
||||||
{
|
{
|
||||||
// 忽略不存在的文件
|
HRESULT hr;
|
||||||
if (pResouceName.isEmpty() || pResouceType.isEmpty() || musicExtension.isEmpty()) return false;
|
|
||||||
|
|
||||||
// 获取临时文件目录
|
|
||||||
e2d::EString tempFileName = e2d::EFile::getTempPath();
|
|
||||||
|
|
||||||
// 产生临时文件的文件名
|
|
||||||
tempFileName = tempFileName + L"\\" + uId + L"." + musicExtension;
|
|
||||||
|
|
||||||
// 导出资源为临时文件
|
|
||||||
if (ExtractResource(tempFileName, pResouceType, pResouceName))
|
|
||||||
{
|
|
||||||
return open(tempFileName, uId);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MciPlayer::play(int repeatTimes)
|
|
||||||
{
|
|
||||||
if (!m_dev)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
MCI_PLAY_PARMS mciPlay = { 0 };
|
|
||||||
mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(m_wnd);
|
|
||||||
|
|
||||||
// 播放声音
|
|
||||||
MCIERROR mciError = mciSendCommand(
|
|
||||||
m_dev,
|
|
||||||
MCI_PLAY,
|
|
||||||
MCI_FROM | MCI_NOTIFY,
|
|
||||||
reinterpret_cast<DWORD_PTR>(&mciPlay)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!mciError)
|
|
||||||
{
|
|
||||||
m_bPlaying = true;
|
|
||||||
m_nRepeatTimes = repeatTimes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MciPlayer::close()
|
|
||||||
{
|
|
||||||
if (m_bPlaying)
|
if (m_bPlaying)
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_dev)
|
// 提交 wave 样本数据
|
||||||
|
XAUDIO2_BUFFER buffer = { 0 };
|
||||||
|
buffer.pAudioData = m_pbWaveData;
|
||||||
|
buffer.Flags = XAUDIO2_END_OF_STREAM;
|
||||||
|
buffer.AudioBytes = m_dwSize;
|
||||||
|
buffer.LoopCount = nLoopCount;
|
||||||
|
|
||||||
|
if (FAILED(hr = m_pSourceVoice->SubmitSourceBuffer(&buffer)))
|
||||||
{
|
{
|
||||||
_sendCommand(MCI_CLOSE);
|
TraceError(L"Error %#X submitting source buffer", hr);
|
||||||
}
|
m_pSourceVoice->DestroyVoice();
|
||||||
|
SAFE_DELETE_ARRAY(m_pbWaveData);
|
||||||
m_dev = 0;
|
|
||||||
m_bPlaying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MciPlayer::pause()
|
|
||||||
{
|
|
||||||
_sendCommand(MCI_PAUSE);
|
|
||||||
m_bPlaying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MciPlayer::resume()
|
|
||||||
{
|
|
||||||
_sendCommand(MCI_RESUME);
|
|
||||||
m_bPlaying = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MciPlayer::stop()
|
|
||||||
{
|
|
||||||
_sendCommand(MCI_STOP);
|
|
||||||
m_bPlaying = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MciPlayer::rewind()
|
|
||||||
{
|
|
||||||
if (!m_dev)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mciSendCommand(m_dev, MCI_SEEK, MCI_SEEK_TO_START, 0);
|
|
||||||
|
|
||||||
MCI_PLAY_PARMS mciPlay = { 0 };
|
|
||||||
mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(m_wnd);
|
|
||||||
|
|
||||||
MCIERROR mciError = mciSendCommand(
|
|
||||||
m_dev,
|
|
||||||
MCI_PLAY,
|
|
||||||
MCI_NOTIFY,
|
|
||||||
reinterpret_cast<DWORD_PTR>(&mciPlay)
|
|
||||||
);
|
|
||||||
m_bPlaying = mciError ? false : true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MciPlayer::isPlaying()
|
|
||||||
{
|
|
||||||
return m_bPlaying;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT MciPlayer::getMusicID()
|
|
||||||
{
|
|
||||||
return m_nMusicID;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MciPlayer::_sendCommand(int nCommand, DWORD_PTR param1, DWORD_PTR parma2)
|
|
||||||
{
|
|
||||||
// 空设备时忽略这次操作
|
|
||||||
if (!m_dev)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 向当前设备发送操作
|
|
||||||
mciSendCommand(m_dev, nCommand, param1, parma2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool ExtractResource(LPCTSTR strDstFile, LPCTSTR strResType, LPCTSTR strResName)
|
|
||||||
{
|
|
||||||
// 创建文件
|
|
||||||
HANDLE hFile = ::CreateFile(strDstFile, GENERIC_WRITE, NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL);
|
|
||||||
if (hFile == INVALID_HANDLE_VALUE)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// 查找资源文件中、加载资源到内存、得到资源大小
|
if (SUCCEEDED(hr = m_pSourceVoice->Start(0)))
|
||||||
HRSRC hRes = ::FindResource(NULL, strResName, strResType);
|
{
|
||||||
HGLOBAL hMem = ::LoadResource(NULL, hRes);
|
m_bPlaying = true;
|
||||||
DWORD dwSize = ::SizeofResource(NULL, hRes);
|
}
|
||||||
|
|
||||||
// 写入文件
|
return SUCCEEDED(hr);
|
||||||
DWORD dwWrite = 0; // 返回写入字节
|
}
|
||||||
::WriteFile(hFile, hMem, dwSize, &dwWrite, NULL);
|
|
||||||
::CloseHandle(hFile);
|
bool EMusic::pause()
|
||||||
|
{
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(m_pSourceVoice->Stop()))
|
||||||
|
{
|
||||||
|
m_bPlaying = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EMusic::resume()
|
||||||
|
{
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(m_pSourceVoice->Start()))
|
||||||
|
{
|
||||||
|
m_bPlaying = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EMusic::stop()
|
||||||
|
{
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(m_pSourceVoice->Stop()))
|
||||||
|
{
|
||||||
|
m_pSourceVoice->ExitLoop();
|
||||||
|
m_pSourceVoice->FlushSourceBuffers();
|
||||||
|
m_bPlaying = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EMusic::isPlaying()
|
||||||
|
{
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
XAUDIO2_VOICE_STATE state;
|
||||||
|
m_pSourceVoice->GetState(&state);
|
||||||
|
|
||||||
|
if (state.BuffersQueued == 0)
|
||||||
|
{
|
||||||
|
m_bPlaying = false;
|
||||||
|
}
|
||||||
|
return m_bPlaying;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float e2d::EMusic::getVolume() const
|
||||||
|
{
|
||||||
|
float fVolume = 0.0f;
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
m_pSourceVoice->GetVolume(&fVolume);
|
||||||
|
}
|
||||||
|
return fVolume;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool e2d::EMusic::setVolume(float fVolume)
|
||||||
|
{
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
return SUCCEEDED(m_pSourceVoice->SetVolume(min(max(fVolume, -224), 224)));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
float e2d::EMusic::getFrequencyRatio() const
|
||||||
|
{
|
||||||
|
float fFrequencyRatio = 0.0f;
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
m_pSourceVoice->GetFrequencyRatio(&fFrequencyRatio);
|
||||||
|
}
|
||||||
|
return fFrequencyRatio;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool e2d::EMusic::setFrequencyRatio(float fFrequencyRatio)
|
||||||
|
{
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
fFrequencyRatio = min(max(fFrequencyRatio, XAUDIO2_MIN_FREQ_RATIO), XAUDIO2_MAX_FREQ_RATIO);
|
||||||
|
return SUCCEEDED(m_pSourceVoice->SetFrequencyRatio(fFrequencyRatio));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IXAudio2SourceVoice * e2d::EMusic::getIXAudio2SourceVoice() const
|
||||||
|
{
|
||||||
|
return m_pSourceVoice;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EMusic::_close()
|
||||||
|
{
|
||||||
|
if (m_pSourceVoice)
|
||||||
|
{
|
||||||
|
m_pSourceVoice->DestroyVoice();
|
||||||
|
m_pSourceVoice = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_hmmio != nullptr)
|
||||||
|
{
|
||||||
|
mmioClose(m_hmmio, 0);
|
||||||
|
m_hmmio = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SAFE_DELETE_ARRAY(m_pResourceBuffer);
|
||||||
|
SAFE_DELETE_ARRAY(m_pbWaveData);
|
||||||
|
SAFE_DELETE_ARRAY(m_pwfx);
|
||||||
|
|
||||||
|
m_bOpened = false;
|
||||||
|
m_bPlaying = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EMusic::_readMMIO()
|
||||||
|
{
|
||||||
|
MMCKINFO ckIn;
|
||||||
|
PCMWAVEFORMAT pcmWaveFormat;
|
||||||
|
|
||||||
|
memset(&ckIn, 0, sizeof(ckIn));
|
||||||
|
|
||||||
|
m_pwfx = nullptr;
|
||||||
|
|
||||||
|
if ((0 != mmioDescend(m_hmmio, &m_ckRiff, nullptr, 0)))
|
||||||
|
return TraceError(L"mmioDescend");
|
||||||
|
|
||||||
|
// 确认文件是一个合法的 wave 文件
|
||||||
|
if ((m_ckRiff.ckid != FOURCC_RIFF) ||
|
||||||
|
(m_ckRiff.fccType != mmioFOURCC('W', 'A', 'V', 'E')))
|
||||||
|
return TraceError(L"mmioFOURCC");
|
||||||
|
|
||||||
|
// 在输入文件中查找 'fmt' 块
|
||||||
|
ckIn.ckid = mmioFOURCC('f', 'm', 't', ' ');
|
||||||
|
if (0 != mmioDescend(m_hmmio, &ckIn, &m_ckRiff, MMIO_FINDCHUNK))
|
||||||
|
return TraceError(L"mmioDescend");
|
||||||
|
|
||||||
|
// 'fmt' 块至少应和 PCMWAVEFORMAT 一样大
|
||||||
|
if (ckIn.cksize < (LONG)sizeof(PCMWAVEFORMAT))
|
||||||
|
return TraceError(L"sizeof(PCMWAVEFORMAT)");
|
||||||
|
|
||||||
|
// 将 'fmt' 块读取到 pcmWaveFormat 中
|
||||||
|
if (mmioRead(m_hmmio, (HPSTR)&pcmWaveFormat,
|
||||||
|
sizeof(pcmWaveFormat)) != sizeof(pcmWaveFormat))
|
||||||
|
return TraceError(L"mmioRead");
|
||||||
|
|
||||||
|
// 分配 WAVEFORMATEX,但如果它不是 PCM 格式,再读取一个 WORD 大小
|
||||||
|
// 的数据,这个数据就是额外分配的大小
|
||||||
|
if (pcmWaveFormat.wf.wFormatTag == WAVE_FORMAT_PCM)
|
||||||
|
{
|
||||||
|
m_pwfx = (WAVEFORMATEX*)new CHAR[sizeof(WAVEFORMATEX)];
|
||||||
|
|
||||||
|
// 拷贝数据
|
||||||
|
memcpy(m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
|
||||||
|
m_pwfx->cbSize = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 读取额外数据的大小
|
||||||
|
WORD cbExtraBytes = 0L;
|
||||||
|
if (mmioRead(m_hmmio, (CHAR*)&cbExtraBytes, sizeof(WORD)) != sizeof(WORD))
|
||||||
|
return TraceError(L"mmioRead");
|
||||||
|
|
||||||
|
m_pwfx = (WAVEFORMATEX*)new CHAR[sizeof(WAVEFORMATEX) + cbExtraBytes];
|
||||||
|
|
||||||
|
// 拷贝数据
|
||||||
|
memcpy(m_pwfx, &pcmWaveFormat, sizeof(pcmWaveFormat));
|
||||||
|
m_pwfx->cbSize = cbExtraBytes;
|
||||||
|
|
||||||
|
// 读取额外数据
|
||||||
|
if (mmioRead(m_hmmio, (CHAR*)(((BYTE*)&(m_pwfx->cbSize)) + sizeof(WORD)),
|
||||||
|
cbExtraBytes) != cbExtraBytes)
|
||||||
|
{
|
||||||
|
SAFE_DELETE(m_pwfx);
|
||||||
|
return TraceError(L"mmioRead");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != mmioAscend(m_hmmio, &ckIn, 0))
|
||||||
|
{
|
||||||
|
SAFE_DELETE(m_pwfx);
|
||||||
|
return TraceError(L"mmioAscend");
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT WINAPI _MciPlayerProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
bool EMusic::_resetFile()
|
||||||
{
|
{
|
||||||
MciPlayer * pPlayer = NULL;
|
// Seek to the data
|
||||||
|
if (-1 == mmioSeek(m_hmmio, m_ckRiff.dwDataOffset + sizeof(FOURCC),
|
||||||
|
SEEK_SET))
|
||||||
|
return TraceError(L"mmioSeek");
|
||||||
|
|
||||||
if (Msg == MM_MCINOTIFY
|
// Search the input file for the 'data' chunk.
|
||||||
&& wParam == MCI_NOTIFY_SUCCESSFUL
|
m_ck.ckid = mmioFOURCC('d', 'a', 't', 'a');
|
||||||
&& (pPlayer = (MciPlayer *)GetWindowLongPtr(hWnd, GWLP_USERDATA)))
|
if (0 != mmioDescend(m_hmmio, &m_ck, &m_ckRiff, MMIO_FINDCHUNK))
|
||||||
|
return TraceError(L"mmioDescend");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EMusic::_read(BYTE* pBuffer, DWORD dwSizeToRead)
|
||||||
|
{
|
||||||
|
MMIOINFO mmioinfoIn; // current status of m_hmmio
|
||||||
|
|
||||||
|
if (0 != mmioGetInfo(m_hmmio, &mmioinfoIn, 0))
|
||||||
|
return TraceError(L"mmioGetInfo");
|
||||||
|
|
||||||
|
UINT cbDataIn = dwSizeToRead;
|
||||||
|
if (cbDataIn > m_ck.cksize)
|
||||||
|
cbDataIn = m_ck.cksize;
|
||||||
|
|
||||||
|
m_ck.cksize -= cbDataIn;
|
||||||
|
|
||||||
|
for (DWORD cT = 0; cT < cbDataIn; cT++)
|
||||||
{
|
{
|
||||||
if (pPlayer->m_nRepeatTimes > 0)
|
// Copy the bytes from the io to the buffer.
|
||||||
|
if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
|
||||||
{
|
{
|
||||||
pPlayer->m_nRepeatTimes--;
|
if (0 != mmioAdvance(m_hmmio, &mmioinfoIn, MMIO_READ))
|
||||||
|
return TraceError(L"mmioAdvance");
|
||||||
|
|
||||||
|
if (mmioinfoIn.pchNext == mmioinfoIn.pchEndRead)
|
||||||
|
return TraceError(L"mmioinfoIn.pchNext");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pPlayer->m_nRepeatTimes)
|
// Actual copy.
|
||||||
|
*((BYTE*)pBuffer + cT) = *((BYTE*)mmioinfoIn.pchNext);
|
||||||
|
mmioinfoIn.pchNext++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != mmioSetInfo(m_hmmio, &mmioinfoIn, 0))
|
||||||
|
return TraceError(L"mmioSetInfo");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EMusic::_findMediaFileCch(WCHAR* strDestPath, int cchDest, LPCWSTR strFilename)
|
||||||
|
{
|
||||||
|
bool bFound = false;
|
||||||
|
|
||||||
|
if (nullptr == strFilename || strFilename[0] == 0 || nullptr == strDestPath || cchDest < 10)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Get the exe name, and exe path
|
||||||
|
WCHAR strExePath[MAX_PATH] = { 0 };
|
||||||
|
WCHAR strExeName[MAX_PATH] = { 0 };
|
||||||
|
WCHAR* strLastSlash = nullptr;
|
||||||
|
GetModuleFileName(HINST_THISCOMPONENT, strExePath, MAX_PATH);
|
||||||
|
strExePath[MAX_PATH - 1] = 0;
|
||||||
|
strLastSlash = wcsrchr(strExePath, TEXT('\\'));
|
||||||
|
if (strLastSlash)
|
||||||
|
{
|
||||||
|
wcscpy_s(strExeName, MAX_PATH, &strLastSlash[1]);
|
||||||
|
|
||||||
|
// Chop the exe name from the exe path
|
||||||
|
*strLastSlash = 0;
|
||||||
|
|
||||||
|
// Chop the .exe from the exe name
|
||||||
|
strLastSlash = wcsrchr(strExeName, TEXT('.'));
|
||||||
|
if (strLastSlash)
|
||||||
|
*strLastSlash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wcscpy_s(strDestPath, cchDest, strFilename);
|
||||||
|
if (GetFileAttributes(strDestPath) != 0xFFFFFFFF)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Search all parent directories starting at .\ and using strFilename as the leaf name
|
||||||
|
WCHAR strLeafName[MAX_PATH] = { 0 };
|
||||||
|
wcscpy_s(strLeafName, MAX_PATH, strFilename);
|
||||||
|
|
||||||
|
WCHAR strFullPath[MAX_PATH] = { 0 };
|
||||||
|
WCHAR strFullFileName[MAX_PATH] = { 0 };
|
||||||
|
WCHAR strSearch[MAX_PATH] = { 0 };
|
||||||
|
WCHAR* strFilePart = nullptr;
|
||||||
|
|
||||||
|
GetFullPathName(L".", MAX_PATH, strFullPath, &strFilePart);
|
||||||
|
if (strFilePart == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while (strFilePart != nullptr && *strFilePart != '\0')
|
||||||
|
{
|
||||||
|
swprintf_s(strFullFileName, MAX_PATH, L"%s\\%s", strFullPath, strLeafName);
|
||||||
|
if (GetFileAttributes(strFullFileName) != 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
mciSendCommand(static_cast<MCIDEVICEID>(lParam), MCI_SEEK, MCI_SEEK_TO_START, 0);
|
wcscpy_s(strDestPath, cchDest, strFullFileName);
|
||||||
|
bFound = true;
|
||||||
MCI_PLAY_PARMS mciPlay = { 0 };
|
break;
|
||||||
mciPlay.dwCallback = reinterpret_cast<DWORD_PTR>(hWnd);
|
|
||||||
mciSendCommand(static_cast<MCIDEVICEID>(lParam), MCI_PLAY, MCI_NOTIFY, reinterpret_cast<DWORD_PTR>(&mciPlay));
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
swprintf_s(strFullFileName, MAX_PATH, L"%s\\%s\\%s", strFullPath, strExeName, strLeafName);
|
||||||
|
if (GetFileAttributes(strFullFileName) != 0xFFFFFFFF)
|
||||||
{
|
{
|
||||||
pPlayer->m_bPlaying = false;
|
wcscpy_s(strDestPath, cchDest, strFullFileName);
|
||||||
return 0;
|
bFound = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
swprintf_s(strSearch, MAX_PATH, L"%s\\..", strFullPath);
|
||||||
|
GetFullPathName(strSearch, MAX_PATH, strFullPath, &strFilePart);
|
||||||
}
|
}
|
||||||
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
if (bFound)
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef std::pair<UINT, MciPlayer *> MusicPair;
|
|
||||||
typedef std::map<UINT, MciPlayer *> MusicList;
|
|
||||||
|
|
||||||
static MusicList& getMciPlayerList()
|
|
||||||
{
|
|
||||||
static MusicList s_List;
|
|
||||||
return s_List;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
UINT e2d::EMusic::play(const EString & musicFilePath, int repeatTimes)
|
|
||||||
{
|
|
||||||
UINT nRet = preload(musicFilePath);
|
|
||||||
|
|
||||||
if (nRet)
|
|
||||||
{
|
|
||||||
getMciPlayerList()[nRet]->play(repeatTimes);
|
|
||||||
}
|
|
||||||
return nRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT e2d::EMusic::play(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension, int repeatTimes)
|
|
||||||
{
|
|
||||||
UINT nRet = preload(musicResourceName, musicResourceType, musicExtension);
|
|
||||||
|
|
||||||
if (nRet)
|
|
||||||
{
|
|
||||||
getMciPlayerList()[nRet]->play(repeatTimes);
|
|
||||||
}
|
|
||||||
return nRet;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT e2d::EMusic::preload(const EString & musicFilePath)
|
|
||||||
{
|
|
||||||
if (musicFilePath.isEmpty())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
UINT nRet = musicFilePath.hash();
|
|
||||||
|
|
||||||
if (getMciPlayerList().end() != getMciPlayerList().find(nRet))
|
|
||||||
return nRet;
|
|
||||||
|
|
||||||
getMciPlayerList().insert(MusicPair(nRet, new MciPlayer()));
|
|
||||||
MciPlayer * pPlayer = getMciPlayerList()[nRet];
|
|
||||||
pPlayer->open(musicFilePath, nRet);
|
|
||||||
|
|
||||||
if (nRet == pPlayer->getMusicID()) return nRet;
|
|
||||||
|
|
||||||
delete pPlayer;
|
|
||||||
getMciPlayerList().erase(nRet);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT e2d::EMusic::preload(const EString & musicResourceName, const EString & musicResourceType, const EString & musicExtension)
|
|
||||||
{
|
|
||||||
if (musicResourceName.isEmpty() || musicResourceType.isEmpty())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
UINT nRet = musicResourceName.hash();
|
|
||||||
|
|
||||||
if (getMciPlayerList().end() != getMciPlayerList().find(nRet))
|
|
||||||
return nRet;
|
|
||||||
|
|
||||||
getMciPlayerList().insert(MusicPair(nRet, new MciPlayer()));
|
|
||||||
MciPlayer * pPlayer = getMciPlayerList()[nRet];
|
|
||||||
pPlayer->open(musicResourceName, musicResourceType, musicExtension, nRet);
|
|
||||||
|
|
||||||
if (nRet == pPlayer->getMusicID()) return nRet;
|
|
||||||
|
|
||||||
delete pPlayer;
|
|
||||||
getMciPlayerList().erase(nRet);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::EMusic::resume(UINT musicId)
|
|
||||||
{
|
|
||||||
MusicList::iterator p = getMciPlayerList().find(musicId);
|
|
||||||
if (p != getMciPlayerList().end())
|
|
||||||
{
|
|
||||||
p->second->resume();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
// 失败时,将文件作为路径返回,同时也返回错误代码
|
||||||
|
wcscpy_s(strDestPath, cchDest, strFilename);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool e2d::EMusic::resume(const EString & musicName)
|
|
||||||
{
|
|
||||||
return resume(musicName.hash());;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::EMusic::pause(UINT musicId)
|
|
||||||
{
|
|
||||||
MusicList::iterator p = getMciPlayerList().find(musicId);
|
|
||||||
if (p != getMciPlayerList().end())
|
|
||||||
{
|
|
||||||
p->second->pause();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::EMusic::pause(const EString & musicName)
|
|
||||||
{
|
|
||||||
return pause(musicName.hash());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::EMusic::stop(UINT musicId)
|
|
||||||
{
|
|
||||||
MusicList::iterator p = getMciPlayerList().find(musicId);
|
|
||||||
if (p != getMciPlayerList().end())
|
|
||||||
{
|
|
||||||
p->second->stop();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool e2d::EMusic::stop(const EString & musicName)
|
|
||||||
{
|
|
||||||
return stop(musicName.hash());;
|
|
||||||
}
|
|
||||||
|
|
||||||
void e2d::EMusic::pauseAllMusics()
|
|
||||||
{
|
|
||||||
for (auto iter = getMciPlayerList().begin(); iter != getMciPlayerList().end(); iter++)
|
|
||||||
{
|
|
||||||
(*iter).second->pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void e2d::EMusic::resumeAllMusics()
|
|
||||||
{
|
|
||||||
for (auto iter = getMciPlayerList().begin(); iter != getMciPlayerList().end(); iter++)
|
|
||||||
{
|
|
||||||
(*iter).second->resume();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void e2d::EMusic::stopAllMusics()
|
|
||||||
{
|
|
||||||
for (auto iter = getMciPlayerList().begin(); iter != getMciPlayerList().end(); iter++)
|
|
||||||
{
|
|
||||||
(*iter).second->stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 初始化计时操作
|
// 初始化计时操作
|
||||||
static void __init();
|
static bool __init();
|
||||||
|
|
||||||
// 重置计时操作
|
// 重置计时操作
|
||||||
static void __uninit();
|
static void __uninit();
|
||||||
|
|
@ -208,7 +208,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// 初始化 DirectInput 以及键盘鼠标设备
|
// 初始化 DirectInput 以及键盘鼠标设备
|
||||||
static HRESULT __init();
|
static bool __init();
|
||||||
|
|
||||||
// 获得输入信息
|
// 获得输入信息
|
||||||
static void __updateDeviceState();
|
static void __updateDeviceState();
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ public:
|
||||||
bool operator > (EString const&) const;
|
bool operator > (EString const&) const;
|
||||||
bool operator >= (EString const&) const;
|
bool operator >= (EString const&) const;
|
||||||
|
|
||||||
operator const wchar_t*() const { return _string; }
|
operator wchar_t*() const { return _string; }
|
||||||
operator bool() const { return _size != 0; }
|
operator bool() const { return _size != 0; }
|
||||||
|
|
||||||
friend EString operator+(const wchar_t, const EString &);
|
friend EString operator+(const wchar_t, const EString &);
|
||||||
|
|
|
||||||
|
|
@ -35,14 +35,19 @@
|
||||||
// C RunTime Header Files
|
// C RunTime Header Files
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
|
#include <wincodec.h>
|
||||||
|
#include <mmsystem.h>
|
||||||
#include <d2d1.h>
|
#include <d2d1.h>
|
||||||
#include <d2d1helper.h>
|
|
||||||
#include <dwrite.h>
|
#include <dwrite.h>
|
||||||
#include <dinput.h>
|
#include <dinput.h>
|
||||||
#include <wincodec.h>
|
#include <xaudio2.h>
|
||||||
|
#include <d2d1helper.h>
|
||||||
|
|
||||||
#pragma comment(lib, "d2d1.lib")
|
#pragma comment(lib, "d2d1.lib")
|
||||||
#pragma comment(lib, "dwrite.lib")
|
#pragma comment(lib, "dwrite.lib")
|
||||||
|
#pragma comment(lib, "xaudio2.lib")
|
||||||
#pragma comment(lib, "windowscodecs.lib")
|
#pragma comment(lib, "windowscodecs.lib")
|
||||||
|
#pragma comment(lib, "winmm.lib")
|
||||||
|
|
||||||
|
|
||||||
#ifndef HINST_THISCOMPONENT
|
#ifndef HINST_THISCOMPONENT
|
||||||
|
|
@ -53,7 +58,7 @@ EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
#ifndef ASSERT_IF
|
#ifndef ASSERT_IF
|
||||||
#if defined( DEBUG ) || defined( _DEBUG )
|
#if defined( DEBUG ) || defined( _DEBUG )
|
||||||
#define ASSERT(b, m) do {if (!(b)) { fprintf(stderr, "Assert: " #m "\n"); assert(b); }} while(0)
|
#define ASSERT(b, m, ...) do {if (!(b)) { fwprintf(stderr, L"Assert: " #m L"\n", __VA_ARGS__); assert(b); }} while(0)
|
||||||
#else
|
#else
|
||||||
#define ASSERT(b, m) ((void)0)
|
#define ASSERT(b, m) ((void)0)
|
||||||
#endif //DEBUG || _DEBUG
|
#endif //DEBUG || _DEBUG
|
||||||
|
|
@ -61,7 +66,7 @@ EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
#ifndef WARN_IF
|
#ifndef WARN_IF
|
||||||
#if defined( DEBUG ) || defined( _DEBUG )
|
#if defined( DEBUG ) || defined( _DEBUG )
|
||||||
#define WARN_IF(b, m) do {if (b) { fprintf(stderr, "Warning: " #m "\n"); }} while(0)
|
#define WARN_IF(b, m, ...) do {if (b) { fwprintf(stderr, L"Warning: " #m L"\n", __VA_ARGS__); }} while(0)
|
||||||
#else
|
#else
|
||||||
#define WARN_IF(b, m) ((void)0)
|
#define WARN_IF(b, m) ((void)0)
|
||||||
#endif //DEBUG || _DEBUG
|
#endif //DEBUG || _DEBUG
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ class EScene;
|
||||||
class ENode;
|
class ENode;
|
||||||
class ETimer;
|
class ETimer;
|
||||||
class EAction;
|
class EAction;
|
||||||
|
class EMusic;
|
||||||
class EGeometry;
|
class EGeometry;
|
||||||
class ETransition;
|
class ETransition;
|
||||||
class EListenerPhysics;
|
class EListenerPhysics;
|
||||||
|
|
@ -68,8 +69,11 @@ private:
|
||||||
// äÖȾ³¡¾°»Ãæ
|
// äÖȾ³¡¾°»Ãæ
|
||||||
static void __render();
|
static void __render();
|
||||||
|
|
||||||
// 进入下一场景
|
// 初始化场景
|
||||||
static void __enterNextScene();
|
static bool __init();
|
||||||
|
|
||||||
|
// 回收场景资源
|
||||||
|
static void __uninit();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -199,6 +203,46 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// 音乐管理工具
|
||||||
|
class EMusicManager
|
||||||
|
{
|
||||||
|
friend EGame;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// 添加音乐文件
|
||||||
|
static EMusic * add(
|
||||||
|
const EString & strFilePath /* 音乐文件路径 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// 获取指定音乐的 EMusic 对象
|
||||||
|
static EMusic * get(
|
||||||
|
const EString & strFilePath /* 音乐文件路径 */
|
||||||
|
);
|
||||||
|
|
||||||
|
// 暂停所有音乐
|
||||||
|
static void pauseAllMusics();
|
||||||
|
|
||||||
|
// 继续播放所有音乐
|
||||||
|
static void resumeAllMusics();
|
||||||
|
|
||||||
|
// 停止所有音乐
|
||||||
|
static void stopAllMusics();
|
||||||
|
|
||||||
|
// 获取 IXAudio2 对象
|
||||||
|
static IXAudio2 * getIXAudio2();
|
||||||
|
|
||||||
|
// 获取 IXAudio2MasteringVoice 对象
|
||||||
|
static IXAudio2MasteringVoice * getIXAudio2MasteringVoice();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// 初始化 XAudio2
|
||||||
|
static bool __init();
|
||||||
|
|
||||||
|
// 回收相关资源
|
||||||
|
static void __uninit();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class EPhysicsManager
|
class EPhysicsManager
|
||||||
{
|
{
|
||||||
friend EGame;
|
friend EGame;
|
||||||
|
|
|
||||||
122
core/etools.h
122
core/etools.h
|
|
@ -6,7 +6,7 @@ namespace e2d
|
||||||
{
|
{
|
||||||
|
|
||||||
class ETimerManager;
|
class ETimerManager;
|
||||||
class EAction;
|
class EMusicManager;
|
||||||
|
|
||||||
// 随机数产生器
|
// 随机数产生器
|
||||||
class ERandom
|
class ERandom
|
||||||
|
|
@ -215,74 +215,88 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 稜있밗잿묏야
|
// 音乐播放器
|
||||||
class EMusic
|
class EMusic
|
||||||
|
: public EObject
|
||||||
{
|
{
|
||||||
|
friend EMusicManager;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// 꺄렴稜있
|
// 播放
|
||||||
static UINT play(
|
bool play(
|
||||||
const EString & musicFilePath, /* 稜있匡숭쨌쓺 */
|
int nLoopCount = 0 /* 重复播放次数 */
|
||||||
int repeatTimes = 1
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// 꺄렴稜있
|
// 暂停
|
||||||
static UINT play(
|
bool pause();
|
||||||
const EString & musicResourceName, /* 栗都츰냔 */
|
|
||||||
const EString & musicResourceType, /* 栗都잚깎 */
|
// 继续
|
||||||
const EString & musicExtension, /* 寧땍栗都돨윈嵐츰 */
|
bool resume();
|
||||||
int repeatTimes = 1
|
|
||||||
|
// 停止
|
||||||
|
bool stop();
|
||||||
|
|
||||||
|
// 获取音乐播放状态
|
||||||
|
bool isPlaying();
|
||||||
|
|
||||||
|
// 获取音量
|
||||||
|
float getVolume() const;
|
||||||
|
|
||||||
|
// 设置音量
|
||||||
|
bool setVolume(
|
||||||
|
float fVolume /* 音量范围为 -224 ~ 224,其中 0 是静音,1 是正常音量 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 董界稜있
|
// 获取频率比
|
||||||
static bool pause(
|
float getFrequencyRatio() const;
|
||||||
UINT musicId
|
|
||||||
|
// 设置频率比
|
||||||
|
bool setFrequencyRatio(
|
||||||
|
float fFrequencyRatio /* 频率比范围为 1/1024.0f ~ 1024.0f,其中 1.0 为正常声调 */
|
||||||
);
|
);
|
||||||
|
|
||||||
// 董界稜있
|
// 获取 IXAudio2SourceVoice 对象
|
||||||
static bool pause(
|
IXAudio2SourceVoice* getIXAudio2SourceVoice() const;
|
||||||
const EString& musicName
|
|
||||||
|
protected:
|
||||||
|
EMusic();
|
||||||
|
|
||||||
|
virtual ~EMusic();
|
||||||
|
|
||||||
|
// 打开音乐文件
|
||||||
|
bool _open(
|
||||||
|
LPWSTR strFileName
|
||||||
);
|
);
|
||||||
|
|
||||||
// 셨崎꺄렴稜있
|
// 关闭该播放器
|
||||||
static bool resume(
|
void _close();
|
||||||
UINT musicId
|
|
||||||
|
bool _readMMIO();
|
||||||
|
|
||||||
|
bool _resetFile();
|
||||||
|
|
||||||
|
bool _read(
|
||||||
|
BYTE* pBuffer,
|
||||||
|
DWORD dwSizeToRead
|
||||||
);
|
);
|
||||||
|
|
||||||
// 셨崎꺄렴稜있
|
bool _findMediaFileCch(
|
||||||
static bool resume(
|
WCHAR* strDestPath,
|
||||||
const EString& musicName
|
int cchDest,
|
||||||
|
LPCWSTR strFilename
|
||||||
);
|
);
|
||||||
|
|
||||||
// 界岺稜있
|
protected:
|
||||||
static bool stop(
|
bool m_bOpened;
|
||||||
UINT musicId
|
bool m_bPlaying;
|
||||||
);
|
DWORD m_dwSize;
|
||||||
|
CHAR* m_pResourceBuffer;
|
||||||
// 界岺稜있
|
BYTE* m_pbWaveData;
|
||||||
static bool stop(
|
HMMIO m_hmmio;
|
||||||
const EString& musicName
|
MMCKINFO m_ck;
|
||||||
);
|
MMCKINFO m_ckRiff;
|
||||||
|
WAVEFORMATEX* m_pwfx;
|
||||||
// 渡속潼稜있
|
IXAudio2SourceVoice* m_pSourceVoice;
|
||||||
static UINT preload(
|
|
||||||
const EString & musicFilePath
|
|
||||||
);
|
|
||||||
|
|
||||||
// 渡속潼稜있
|
|
||||||
static UINT preload(
|
|
||||||
const EString & musicResourceName, /* 栗都츰냔 */
|
|
||||||
const EString & musicResourceType, /* 栗都잚깎 */
|
|
||||||
const EString & musicExtension /* 寧땍栗都돨윈嵐츰 */
|
|
||||||
);
|
|
||||||
|
|
||||||
// 董界杰唐稜있
|
|
||||||
static void pauseAllMusics();
|
|
||||||
|
|
||||||
// 셨崎꺄렴杰唐稜있
|
|
||||||
static void resumeAllMusics();
|
|
||||||
|
|
||||||
// 界岺杰唐稜있
|
|
||||||
static void stopAllMusics();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
<Optimization>Disabled</Optimization>
|
<Optimization>Disabled</Optimization>
|
||||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
<SDLCheck>true</SDLCheck>
|
<SDLCheck>true</SDLCheck>
|
||||||
<DebugInformationFormat>None</DebugInformationFormat>
|
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||||
<MinimalRebuild>false</MinimalRebuild>
|
<MinimalRebuild>false</MinimalRebuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<Link>
|
<Link>
|
||||||
|
|
@ -227,6 +227,7 @@
|
||||||
<ClCompile Include="..\..\core\Listener\Listener.cpp" />
|
<ClCompile Include="..\..\core\Listener\Listener.cpp" />
|
||||||
<ClCompile Include="..\..\core\Listener\ListenerPhysics.cpp" />
|
<ClCompile Include="..\..\core\Listener\ListenerPhysics.cpp" />
|
||||||
<ClCompile Include="..\..\core\Manager\ActionManager.cpp" />
|
<ClCompile Include="..\..\core\Manager\ActionManager.cpp" />
|
||||||
|
<ClCompile Include="..\..\core\Manager\MusicManager.cpp" />
|
||||||
<ClCompile Include="..\..\core\Manager\ObjectManager.cpp" />
|
<ClCompile Include="..\..\core\Manager\ObjectManager.cpp" />
|
||||||
<ClCompile Include="..\..\core\Manager\PhysicsManager.cpp" />
|
<ClCompile Include="..\..\core\Manager\PhysicsManager.cpp" />
|
||||||
<ClCompile Include="..\..\core\Manager\SceneManager.cpp" />
|
<ClCompile Include="..\..\core\Manager\SceneManager.cpp" />
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,9 @@
|
||||||
<ClCompile Include="..\..\core\Tool\File.cpp">
|
<ClCompile Include="..\..\core\Tool\File.cpp">
|
||||||
<Filter>Tool</Filter>
|
<Filter>Tool</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\core\Manager\MusicManager.cpp">
|
||||||
|
<Filter>Manager</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="..\..\core\etools.h" />
|
<ClInclude Include="..\..\core\etools.h" />
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue