明确Resource的定义,不允许从本地文件创建Resource
This commit is contained in:
parent
a394eb0595
commit
00a2b9ebac
|
|
@ -2,7 +2,7 @@
|
|||
#include "..\e2dbase.h"
|
||||
#include "..\e2dtool.h"
|
||||
|
||||
std::map<e2d::Resource, ID2D1Bitmap*> e2d::Image::_bitmapCache;
|
||||
std::map<size_t, ID2D1Bitmap*> e2d::Image::_bitmapCache;
|
||||
|
||||
e2d::Image::Image()
|
||||
: _bitmap(nullptr)
|
||||
|
|
@ -29,14 +29,14 @@ e2d::Image::Image(const String & fileName)
|
|||
: _bitmap(nullptr)
|
||||
, _cropRect()
|
||||
{
|
||||
this->open(Resource(fileName));
|
||||
this->open(fileName);
|
||||
}
|
||||
|
||||
e2d::Image::Image(const String & fileName, const Rect & cropRect)
|
||||
: _bitmap(nullptr)
|
||||
, _cropRect()
|
||||
{
|
||||
this->open(Resource(fileName));
|
||||
this->open(fileName);
|
||||
this->crop(cropRect);
|
||||
}
|
||||
|
||||
|
|
@ -46,27 +46,31 @@ e2d::Image::~Image()
|
|||
|
||||
bool e2d::Image::open(const Resource& res)
|
||||
{
|
||||
if (res.isFile())
|
||||
{
|
||||
WARN_IF(res.getFileName().isEmpty(), "Image open failed! Invalid file name.");
|
||||
|
||||
if (res.getFileName().isEmpty())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Image::preload(res))
|
||||
{
|
||||
WARN("Load Image from file failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->_setBitmap(_bitmapCache.at(res));
|
||||
this->_setBitmap(_bitmapCache.at(res.resNameId));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool e2d::Image::open(const String & fileName)
|
||||
{
|
||||
return open(Resource(fileName));
|
||||
WARN_IF(fileName.isEmpty(), "Image open failed! Invalid file name.");
|
||||
|
||||
if (fileName.isEmpty())
|
||||
return false;
|
||||
|
||||
if (!Image::preload(fileName))
|
||||
{
|
||||
WARN("Load Image from file failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
this->_setBitmap(_bitmapCache.at(fileName.hash()));
|
||||
return true;
|
||||
}
|
||||
|
||||
void e2d::Image::crop(const Rect& cropRect)
|
||||
|
|
@ -148,98 +152,77 @@ e2d::Point e2d::Image::getCropPos() const
|
|||
|
||||
bool e2d::Image::preload(const Resource& res)
|
||||
{
|
||||
if (_bitmapCache.find(res) != _bitmapCache.end())
|
||||
if (_bitmapCache.find(res.resNameId) != _bitmapCache.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
Renderer* renderer = Game::getInstance()->getRenderer();
|
||||
ID2D1HwndRenderTarget* pRenderTarget = renderer->getRenderTarget();
|
||||
IWICImagingFactory *pImagingFactory = renderer->getImagingFactory();
|
||||
IWICBitmapDecoder *pDecoder = nullptr;
|
||||
IWICBitmapFrameDecode *pSource = nullptr;
|
||||
IWICStream *pStream = nullptr;
|
||||
IWICFormatConverter *pConverter = nullptr;
|
||||
ID2D1Bitmap *pBitmap = nullptr;
|
||||
IWICImagingFactory *pImagingFactory = Game::getInstance()->getRenderer()->getImagingFactory();
|
||||
HRSRC imageResHandle = nullptr;
|
||||
HGLOBAL imageResDataHandle = nullptr;
|
||||
void *pImageFile = nullptr;
|
||||
DWORD imageFileSize = 0;
|
||||
|
||||
if (!res.isFile())
|
||||
// 定位资源
|
||||
imageResHandle = ::FindResourceW(
|
||||
HINST_THISCOMPONENT,
|
||||
MAKEINTRESOURCE(res.resNameId),
|
||||
(LPCWSTR)res.resType
|
||||
);
|
||||
|
||||
HRESULT hr = imageResHandle ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
HRSRC imageResHandle = nullptr;
|
||||
HGLOBAL imageResDataHandle = nullptr;
|
||||
void *pImageFile = nullptr;
|
||||
DWORD imageFileSize = 0;
|
||||
// 加载资源
|
||||
imageResDataHandle = ::LoadResource(HINST_THISCOMPONENT, imageResHandle);
|
||||
|
||||
// 定位资源
|
||||
imageResHandle = ::FindResourceW(
|
||||
HINST_THISCOMPONENT,
|
||||
MAKEINTRESOURCE(res.getResNameId()),
|
||||
(LPCWSTR)res.getResType()
|
||||
);
|
||||
|
||||
hr = imageResHandle ? S_OK : E_FAIL;
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 加载资源
|
||||
imageResDataHandle = ::LoadResource(HINST_THISCOMPONENT, imageResHandle);
|
||||
|
||||
hr = imageResDataHandle ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 获取文件指针,并锁定资源
|
||||
pImageFile = ::LockResource(imageResDataHandle);
|
||||
|
||||
hr = pImageFile ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 计算大小
|
||||
imageFileSize = ::SizeofResource(HINST_THISCOMPONENT, imageResHandle);
|
||||
|
||||
hr = imageFileSize ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建 WIC 流
|
||||
hr = pImagingFactory->CreateStream(&pStream);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 初始化流
|
||||
hr = pStream->InitializeFromMemory(
|
||||
reinterpret_cast<BYTE*>(pImageFile),
|
||||
imageFileSize
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建流的解码器
|
||||
hr = pImagingFactory->CreateDecoderFromStream(
|
||||
pStream,
|
||||
nullptr,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&pDecoder
|
||||
);
|
||||
}
|
||||
hr = imageResDataHandle ? S_OK : E_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
String actualFilePath = File(res.getFileName()).getFilePath();
|
||||
if (actualFilePath.isEmpty())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建解码器
|
||||
hr = pImagingFactory->CreateDecoderFromFilename(
|
||||
(LPCWSTR)actualFilePath,
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 获取文件指针,并锁定资源
|
||||
pImageFile = ::LockResource(imageResDataHandle);
|
||||
|
||||
hr = pImageFile ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 计算大小
|
||||
imageFileSize = ::SizeofResource(HINST_THISCOMPONENT, imageResHandle);
|
||||
|
||||
hr = imageFileSize ? S_OK : E_FAIL;
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建 WIC 流
|
||||
hr = pImagingFactory->CreateStream(&pStream);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 初始化流
|
||||
hr = pStream->InitializeFromMemory(
|
||||
reinterpret_cast<BYTE*>(pImageFile),
|
||||
imageFileSize
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建流的解码器
|
||||
hr = pImagingFactory->CreateDecoderFromStream(
|
||||
pStream,
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&pDecoder
|
||||
);
|
||||
|
|
@ -273,7 +256,7 @@ bool e2d::Image::preload(const Resource& res)
|
|||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 从 WIC 位图创建一个 Direct2D 位图
|
||||
hr = Game::getInstance()->getRenderer()->getRenderTarget()->CreateBitmapFromWicBitmap(
|
||||
hr = pRenderTarget->CreateBitmapFromWicBitmap(
|
||||
pConverter,
|
||||
nullptr,
|
||||
&pBitmap
|
||||
|
|
@ -282,7 +265,84 @@ bool e2d::Image::preload(const Resource& res)
|
|||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_bitmapCache.insert(std::make_pair(res, pBitmap));
|
||||
_bitmapCache.insert(std::make_pair(res.resNameId, pBitmap));
|
||||
}
|
||||
|
||||
// 释放相关资源
|
||||
SafeRelease(pDecoder);
|
||||
SafeRelease(pSource);
|
||||
SafeRelease(pStream);
|
||||
SafeRelease(pConverter);
|
||||
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
bool e2d::Image::preload(const String & fileName)
|
||||
{
|
||||
String actualFilePath = File(fileName).getFilePath();
|
||||
if (actualFilePath.isEmpty())
|
||||
return false;
|
||||
|
||||
size_t hash = actualFilePath.hash();
|
||||
if (_bitmapCache.find(hash) != _bitmapCache.end())
|
||||
return true;
|
||||
|
||||
Renderer* renderer = Game::getInstance()->getRenderer();
|
||||
ID2D1HwndRenderTarget* pRenderTarget = renderer->getRenderTarget();
|
||||
IWICImagingFactory *pImagingFactory = renderer->getImagingFactory();
|
||||
IWICBitmapDecoder *pDecoder = nullptr;
|
||||
IWICBitmapFrameDecode *pSource = nullptr;
|
||||
IWICStream *pStream = nullptr;
|
||||
IWICFormatConverter *pConverter = nullptr;
|
||||
ID2D1Bitmap *pBitmap = nullptr;
|
||||
|
||||
// 创建解码器
|
||||
HRESULT hr = pImagingFactory->CreateDecoderFromFilename(
|
||||
(LPCWSTR)actualFilePath,
|
||||
nullptr,
|
||||
GENERIC_READ,
|
||||
WICDecodeMetadataCacheOnLoad,
|
||||
&pDecoder
|
||||
);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建初始化框架
|
||||
hr = pDecoder->GetFrame(0, &pSource);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 创建图片格式转换器
|
||||
hr = pImagingFactory->CreateFormatConverter(&pConverter);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 图片格式转换成 32bppPBGRA
|
||||
hr = pConverter->Initialize(
|
||||
pSource,
|
||||
GUID_WICPixelFormat32bppPBGRA,
|
||||
WICBitmapDitherTypeNone,
|
||||
nullptr,
|
||||
0.f,
|
||||
WICBitmapPaletteTypeMedianCut
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// 从 WIC 位图创建一个 Direct2D 位图
|
||||
hr = pRenderTarget->CreateBitmapFromWicBitmap(
|
||||
pConverter,
|
||||
nullptr,
|
||||
&pBitmap
|
||||
);
|
||||
}
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
_bitmapCache.insert(std::make_pair(hash, pBitmap));
|
||||
}
|
||||
|
||||
// 释放相关资源
|
||||
|
|
|
|||
|
|
@ -1,62 +1,8 @@
|
|||
#include "..\e2dtool.h"
|
||||
|
||||
e2d::Resource::Resource(const String & fileName)
|
||||
: _isFile(true)
|
||||
, _fileName(fileName)
|
||||
, _resNameId(0)
|
||||
, _resType()
|
||||
{
|
||||
}
|
||||
|
||||
e2d::Resource::Resource(size_t resNameId, const String & resType)
|
||||
: _isFile(false)
|
||||
, _fileName()
|
||||
, _resNameId(resNameId)
|
||||
, _resType(resType)
|
||||
: resNameId(resNameId)
|
||||
, resType(resType)
|
||||
{
|
||||
}
|
||||
|
||||
bool e2d::Resource::isFile() const
|
||||
{
|
||||
return _isFile;
|
||||
}
|
||||
|
||||
const e2d::String & e2d::Resource::getFileName() const
|
||||
{
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
size_t e2d::Resource::getResNameId() const
|
||||
{
|
||||
return _resNameId;
|
||||
}
|
||||
|
||||
const e2d::String & e2d::Resource::getResType() const
|
||||
{
|
||||
return _resType;
|
||||
}
|
||||
|
||||
size_t e2d::Resource::getKey() const
|
||||
{
|
||||
return _isFile ? _fileName.hash() : _resNameId;
|
||||
}
|
||||
|
||||
bool e2d::Resource::operator>(const Resource &res) const
|
||||
{
|
||||
return this->getKey() > res.getKey();
|
||||
}
|
||||
|
||||
bool e2d::Resource::operator>=(const Resource &res) const
|
||||
{
|
||||
return this->getKey() >= res.getKey();
|
||||
}
|
||||
|
||||
bool e2d::Resource::operator<(const Resource &res) const
|
||||
{
|
||||
return this->getKey() < res.getKey();
|
||||
}
|
||||
|
||||
bool e2d::Resource::operator<=(const Resource &res) const
|
||||
{
|
||||
return this->getKey() <= res.getKey();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,18 @@ bool e2d::Sprite::open(const Resource& res)
|
|||
|
||||
bool e2d::Sprite::open(const String & fileName)
|
||||
{
|
||||
return open(Resource(fileName));
|
||||
if (!_image)
|
||||
{
|
||||
_image = new (e2d::autorelease) Image();
|
||||
_image->retain();
|
||||
}
|
||||
|
||||
if (_image->open(fileName))
|
||||
{
|
||||
Node::setSize(_image->getWidth(), _image->getHeight());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void e2d::Sprite::crop(const Rect& cropRect)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,44 @@ inline bool TraceError(wchar_t* sPrompt, HRESULT hr)
|
|||
}
|
||||
|
||||
|
||||
e2d::Music::XAudio2Tool::XAudio2Tool()
|
||||
{
|
||||
CoInitialize(nullptr);
|
||||
|
||||
ThrowIfFailed(
|
||||
XAudio2Create(&_xAudio2, 0)
|
||||
);
|
||||
|
||||
ThrowIfFailed(
|
||||
_xAudio2->CreateMasteringVoice(&_masteringVoice)
|
||||
);
|
||||
}
|
||||
|
||||
e2d::Music::XAudio2Tool::~XAudio2Tool()
|
||||
{
|
||||
_masteringVoice->DestroyVoice();
|
||||
_xAudio2->Release();
|
||||
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
e2d::Music::XAudio2Tool* e2d::Music::XAudio2Tool::getInstance()
|
||||
{
|
||||
static XAudio2Tool instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
IXAudio2 * e2d::Music::XAudio2Tool::getXAudio2()
|
||||
{
|
||||
return _xAudio2;
|
||||
}
|
||||
|
||||
IXAudio2MasteringVoice * e2d::Music::XAudio2Tool::getMasteringVoice()
|
||||
{
|
||||
return _masteringVoice;
|
||||
}
|
||||
|
||||
|
||||
e2d::Music::Music()
|
||||
: _opened(false)
|
||||
, _playing(false)
|
||||
|
|
@ -32,10 +70,26 @@ e2d::Music::Music()
|
|||
, _dwSize(0)
|
||||
, _voice(nullptr)
|
||||
, _voiceCallback(this)
|
||||
, _xAudio2(nullptr)
|
||||
, _masteringVoice(nullptr)
|
||||
{
|
||||
CoInitialize(nullptr);
|
||||
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||
xAudio2->AddRef();
|
||||
}
|
||||
|
||||
e2d::Music::Music(const e2d::String & filePath)
|
||||
: _opened(false)
|
||||
, _playing(false)
|
||||
, _wfx(nullptr)
|
||||
, _hmmio(nullptr)
|
||||
, _resBuffer(nullptr)
|
||||
, _waveData(nullptr)
|
||||
, _dwSize(0)
|
||||
, _voice(nullptr)
|
||||
, _voiceCallback(this)
|
||||
{
|
||||
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||
xAudio2->AddRef();
|
||||
|
||||
this->open(filePath);
|
||||
}
|
||||
|
||||
e2d::Music::Music(const Resource& res)
|
||||
|
|
@ -48,129 +102,51 @@ e2d::Music::Music(const Resource& res)
|
|||
, _dwSize(0)
|
||||
, _voice(nullptr)
|
||||
, _voiceCallback(this)
|
||||
, _xAudio2(nullptr)
|
||||
, _masteringVoice(nullptr)
|
||||
{
|
||||
CoInitialize(nullptr);
|
||||
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||
xAudio2->AddRef();
|
||||
|
||||
this->open(res);
|
||||
}
|
||||
|
||||
e2d::Music::Music(IXAudio2 * xAudio2)
|
||||
: _opened(false)
|
||||
, _playing(false)
|
||||
, _wfx(nullptr)
|
||||
, _hmmio(nullptr)
|
||||
, _resBuffer(nullptr)
|
||||
, _waveData(nullptr)
|
||||
, _dwSize(0)
|
||||
, _voice(nullptr)
|
||||
, _voiceCallback(this)
|
||||
, _xAudio2(xAudio2)
|
||||
, _masteringVoice(nullptr)
|
||||
{
|
||||
CoInitialize(nullptr);
|
||||
|
||||
if (_xAudio2)
|
||||
{
|
||||
_xAudio2->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
e2d::Music::~Music()
|
||||
{
|
||||
close();
|
||||
|
||||
if (_masteringVoice)
|
||||
{
|
||||
_masteringVoice->DestroyVoice();
|
||||
_masteringVoice = nullptr;
|
||||
}
|
||||
|
||||
SafeRelease(_xAudio2);
|
||||
|
||||
CoUninitialize();
|
||||
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||
xAudio2->Release();
|
||||
}
|
||||
|
||||
bool e2d::Music::open(const Resource& res)
|
||||
bool e2d::Music::open(const e2d::String & filePath)
|
||||
{
|
||||
if (_opened)
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
if (!_xAudio2)
|
||||
if (filePath.isEmpty())
|
||||
{
|
||||
if (FAILED(XAudio2Create(&_xAudio2, 0)))
|
||||
{
|
||||
TraceError(L"Create IXAudio2 error");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(_xAudio2->CreateMasteringVoice(&_masteringVoice)))
|
||||
{
|
||||
TraceError(L"Create IXAudio2MasteringVoice error");
|
||||
return false;
|
||||
}
|
||||
WARN("MusicInfo::open Invalid file name.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!res.isFile())
|
||||
String actualFilePath = File(filePath).getFilePath();
|
||||
if (actualFilePath.isEmpty())
|
||||
{
|
||||
HRSRC hResInfo;
|
||||
HGLOBAL hResData;
|
||||
DWORD dwSize;
|
||||
void* pvRes;
|
||||
|
||||
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(res.getResNameId()), (LPCWSTR)res.getResType())))
|
||||
return TraceError(L"FindResource");
|
||||
|
||||
if (nullptr == (hResData = LoadResource(HINST_THISCOMPONENT, hResInfo)))
|
||||
return TraceError(L"LoadResource");
|
||||
|
||||
if (0 == (dwSize = SizeofResource(HINST_THISCOMPONENT, hResInfo)))
|
||||
return TraceError(L"SizeofResource");
|
||||
|
||||
if (nullptr == (pvRes = LockResource(hResData)))
|
||||
return TraceError(L"LockResource");
|
||||
|
||||
_resBuffer = new CHAR[dwSize];
|
||||
memcpy(_resBuffer, pvRes, dwSize);
|
||||
|
||||
MMIOINFO mmioInfo;
|
||||
ZeroMemory(&mmioInfo, sizeof(mmioInfo));
|
||||
mmioInfo.fccIOProc = FOURCC_MEM;
|
||||
mmioInfo.cchBuffer = dwSize;
|
||||
mmioInfo.pchBuffer = (CHAR*)_resBuffer;
|
||||
|
||||
_hmmio = mmioOpen(nullptr, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ);
|
||||
WARN("MusicInfo::open File not found.");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
|
||||
// 定位 wave 文件
|
||||
wchar_t pFilePath[MAX_PATH];
|
||||
if (!_findMediaFileCch(pFilePath, MAX_PATH, (const wchar_t *)actualFilePath))
|
||||
{
|
||||
String filePath = res.getFileName();
|
||||
if (filePath.isEmpty())
|
||||
{
|
||||
WARN("MusicInfo::open Invalid file name.");
|
||||
return false;
|
||||
}
|
||||
|
||||
String actualFilePath = File(filePath).getFilePath();
|
||||
if (actualFilePath.isEmpty())
|
||||
{
|
||||
WARN("MusicInfo::open File not found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ¶¨Î» wave Îļþ
|
||||
wchar_t pFilePath[MAX_PATH];
|
||||
if (!_findMediaFileCch(pFilePath, MAX_PATH, (const wchar_t *)actualFilePath))
|
||||
{
|
||||
WARN("Failed to find media file: %s", pFilePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
_hmmio = mmioOpen(pFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
|
||||
WARN("Failed to find media file: %s", pFilePath);
|
||||
return false;
|
||||
}
|
||||
|
||||
_hmmio = mmioOpen(pFilePath, nullptr, MMIO_ALLOCBUF | MMIO_READ);
|
||||
|
||||
if (nullptr == _hmmio)
|
||||
{
|
||||
return TraceError(L"mmioOpen");
|
||||
|
|
@ -200,7 +176,87 @@ bool e2d::Music::open(const Resource& res)
|
|||
}
|
||||
|
||||
// ´´½¨ÒôÔ´
|
||||
HRESULT hr = _xAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &_voiceCallback);
|
||||
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||
HRESULT hr = xAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &_voiceCallback);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
TraceError(L"Create source voice error", hr);
|
||||
SAFE_DELETE_ARRAY(_waveData);
|
||||
return false;
|
||||
}
|
||||
|
||||
_opened = true;
|
||||
_playing = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool e2d::Music::open(const Resource& res)
|
||||
{
|
||||
if (_opened)
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
HRSRC hResInfo;
|
||||
HGLOBAL hResData;
|
||||
DWORD dwSize;
|
||||
void* pvRes;
|
||||
|
||||
if (nullptr == (hResInfo = FindResourceW(HINST_THISCOMPONENT, MAKEINTRESOURCE(res.resNameId), (LPCWSTR)res.resType)))
|
||||
return TraceError(L"FindResource");
|
||||
|
||||
if (nullptr == (hResData = LoadResource(HINST_THISCOMPONENT, hResInfo)))
|
||||
return TraceError(L"LoadResource");
|
||||
|
||||
if (0 == (dwSize = SizeofResource(HINST_THISCOMPONENT, hResInfo)))
|
||||
return TraceError(L"SizeofResource");
|
||||
|
||||
if (nullptr == (pvRes = LockResource(hResData)))
|
||||
return TraceError(L"LockResource");
|
||||
|
||||
_resBuffer = new CHAR[dwSize];
|
||||
memcpy(_resBuffer, pvRes, dwSize);
|
||||
|
||||
MMIOINFO mmioInfo;
|
||||
ZeroMemory(&mmioInfo, sizeof(mmioInfo));
|
||||
mmioInfo.fccIOProc = FOURCC_MEM;
|
||||
mmioInfo.cchBuffer = dwSize;
|
||||
mmioInfo.pchBuffer = (CHAR*)_resBuffer;
|
||||
|
||||
_hmmio = mmioOpen(nullptr, &mmioInfo, MMIO_ALLOCBUF | MMIO_READ);
|
||||
|
||||
if (nullptr == _hmmio)
|
||||
{
|
||||
return TraceError(L"mmioOpen");
|
||||
}
|
||||
|
||||
if (!_readMMIO())
|
||||
{
|
||||
// 读取非 wave 文件时 ReadMMIO 调用失败
|
||||
mmioClose(_hmmio, 0);
|
||||
return TraceError(L"ReadMMIO");
|
||||
}
|
||||
|
||||
if (!_resetFile())
|
||||
return TraceError(L"ResetFile");
|
||||
|
||||
// 重置文件后,wave 文件的大小是 _ck.cksize
|
||||
_dwSize = _ck.cksize;
|
||||
|
||||
// 将样本数据读取到内存中
|
||||
_waveData = new BYTE[_dwSize];
|
||||
|
||||
if (!_read(_waveData, _dwSize))
|
||||
{
|
||||
TraceError(L"Failed to read WAV data");
|
||||
SAFE_DELETE_ARRAY(_waveData);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 创建音源
|
||||
auto xAudio2 = XAudio2Tool::getInstance()->getXAudio2();
|
||||
HRESULT hr = xAudio2->CreateSourceVoice(&_voice, _wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, &_voiceCallback);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,21 +3,7 @@
|
|||
|
||||
e2d::Player::Player()
|
||||
: _volume(1.f)
|
||||
, _enabled(true)
|
||||
, _xAudio2(nullptr)
|
||||
, _masteringVoice(nullptr)
|
||||
{
|
||||
CoInitialize(nullptr);
|
||||
|
||||
if (FAILED(XAudio2Create(&_xAudio2, 0)))
|
||||
{
|
||||
WARN("初始化 XAudio2 组件失败");
|
||||
}
|
||||
|
||||
if (FAILED(_xAudio2->CreateMasteringVoice(&_masteringVoice)))
|
||||
{
|
||||
WARN("初始化 MasteringVoice 组件失败");
|
||||
}
|
||||
}
|
||||
|
||||
e2d::Player::~Player()
|
||||
|
|
@ -30,30 +16,85 @@ e2d::Player::~Player()
|
|||
}
|
||||
}
|
||||
|
||||
if (_masteringVoice)
|
||||
{
|
||||
_masteringVoice->DestroyVoice();
|
||||
_masteringVoice = nullptr;
|
||||
}
|
||||
|
||||
SafeRelease(_xAudio2);
|
||||
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
IXAudio2 * e2d::Player::getXAudio2()
|
||||
bool e2d::Player::preload(const String & filePath)
|
||||
{
|
||||
return _xAudio2;
|
||||
if (filePath.isEmpty())
|
||||
return false;
|
||||
|
||||
Music * music = new (std::nothrow) Music();
|
||||
|
||||
if (music && music->open(filePath))
|
||||
{
|
||||
music->setVolume(_volume);
|
||||
_musicList.insert(std::make_pair(filePath.hash(), music));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
IXAudio2MasteringVoice * e2d::Player::getMasteringVoice()
|
||||
bool e2d::Player::play(const String & filePath, int nLoopCount)
|
||||
{
|
||||
return _masteringVoice;
|
||||
if (filePath.isEmpty())
|
||||
return false;
|
||||
|
||||
if (Player::preload(filePath))
|
||||
{
|
||||
auto music = _musicList[filePath.hash()];
|
||||
if (music->play(nLoopCount))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void e2d::Player::pause(const String & filePath)
|
||||
{
|
||||
if (filePath.isEmpty())
|
||||
return;
|
||||
|
||||
size_t hash = filePath.hash();
|
||||
if (_musicList.end() != _musicList.find(hash))
|
||||
_musicList[hash]->pause();
|
||||
}
|
||||
|
||||
void e2d::Player::resume(const String & filePath)
|
||||
{
|
||||
if (filePath.isEmpty())
|
||||
return;
|
||||
|
||||
size_t hash = filePath.hash();
|
||||
if (_musicList.end() != _musicList.find(hash))
|
||||
_musicList[hash]->resume();
|
||||
}
|
||||
|
||||
void e2d::Player::stop(const String & filePath)
|
||||
{
|
||||
if (filePath.isEmpty())
|
||||
return;
|
||||
|
||||
size_t hash = filePath.hash();
|
||||
if (_musicList.end() != _musicList.find(hash))
|
||||
_musicList[hash]->stop();
|
||||
}
|
||||
|
||||
bool e2d::Player::isPlaying(const String & filePath)
|
||||
{
|
||||
if (filePath.isEmpty())
|
||||
return false;
|
||||
|
||||
size_t hash = filePath.hash();
|
||||
if (_musicList.end() != _musicList.find(hash))
|
||||
return _musicList[hash]->isPlaying();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool e2d::Player::preload(const Resource& res)
|
||||
{
|
||||
if (_musicList.end() != _musicList.find(res))
|
||||
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||
return true;
|
||||
|
||||
Music * music = new (std::nothrow) Music();
|
||||
|
|
@ -61,7 +102,7 @@ bool e2d::Player::preload(const Resource& res)
|
|||
if (music && music->open(res))
|
||||
{
|
||||
music->setVolume(_volume);
|
||||
_musicList.insert(std::make_pair(res, music));
|
||||
_musicList.insert(std::make_pair(res.resNameId, music));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
@ -71,7 +112,7 @@ bool e2d::Player::play(const Resource& res, int nLoopCount)
|
|||
{
|
||||
if (Player::preload(res))
|
||||
{
|
||||
auto music = _musicList[res];
|
||||
auto music = _musicList[res.resNameId];
|
||||
if (music->play(nLoopCount))
|
||||
{
|
||||
return true;
|
||||
|
|
@ -82,26 +123,26 @@ bool e2d::Player::play(const Resource& res, int nLoopCount)
|
|||
|
||||
void e2d::Player::pause(const Resource& res)
|
||||
{
|
||||
if (_musicList.end() != _musicList.find(res))
|
||||
_musicList[res]->pause();
|
||||
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||
_musicList[res.resNameId]->pause();
|
||||
}
|
||||
|
||||
void e2d::Player::resume(const Resource& res)
|
||||
{
|
||||
if (_musicList.end() != _musicList.find(res))
|
||||
_musicList[res]->pause();
|
||||
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||
_musicList[res.resNameId]->resume();
|
||||
}
|
||||
|
||||
void e2d::Player::stop(const Resource& res)
|
||||
{
|
||||
if (_musicList.end() != _musicList.find(res))
|
||||
_musicList[res]->stop();
|
||||
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||
_musicList[res.resNameId]->stop();
|
||||
}
|
||||
|
||||
bool e2d::Player::isPlaying(const Resource& res)
|
||||
{
|
||||
if (_musicList.end() != _musicList.find(res))
|
||||
return _musicList[res]->isPlaying();
|
||||
if (_musicList.end() != _musicList.find(res.resNameId))
|
||||
return _musicList[res.resNameId]->isPlaying();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -143,15 +184,6 @@ void e2d::Player::stopAll()
|
|||
}
|
||||
}
|
||||
|
||||
void e2d::Player::setEnabled(bool enabled)
|
||||
{
|
||||
if (_enabled == enabled)
|
||||
return;
|
||||
|
||||
_enabled = enabled;
|
||||
_enabled ? _xAudio2->StartEngine() : _xAudio2->StopEngine();
|
||||
}
|
||||
|
||||
void e2d::Player::clearCache()
|
||||
{
|
||||
for (const auto& pair : _musicList)
|
||||
|
|
|
|||
|
|
@ -679,37 +679,14 @@ protected:
|
|||
class Resource
|
||||
{
|
||||
public:
|
||||
Resource(
|
||||
const String& fileName /* 文件路径 */
|
||||
);
|
||||
|
||||
Resource(
|
||||
size_t resNameId, /* 资源名称 */
|
||||
const String& resType /* 资源类型 */
|
||||
);
|
||||
|
||||
// 是否是本地文件
|
||||
bool isFile() const;
|
||||
|
||||
const String& getFileName() const;
|
||||
|
||||
size_t getResNameId() const;
|
||||
|
||||
const String& getResType() const;
|
||||
|
||||
size_t getKey() const;
|
||||
|
||||
// 比较运算符
|
||||
bool operator> (const Resource &) const;
|
||||
bool operator>= (const Resource &) const;
|
||||
bool operator< (const Resource &) const;
|
||||
bool operator<= (const Resource &) const;
|
||||
|
||||
protected:
|
||||
bool _isFile;
|
||||
size_t _resNameId;
|
||||
String _resType;
|
||||
String _fileName;
|
||||
public:
|
||||
size_t resNameId;
|
||||
String resType;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -810,6 +787,11 @@ public:
|
|||
// 获取 ID2D1Bitmap 对象
|
||||
ID2D1Bitmap * getBitmap();
|
||||
|
||||
// Ô¤¼ÓÔØÍ¼Æ¬×ÊÔ´
|
||||
static bool preload(
|
||||
const String& fileName
|
||||
);
|
||||
|
||||
// 预加载图片资源
|
||||
static bool preload(
|
||||
const Resource& res
|
||||
|
|
@ -830,7 +812,7 @@ protected:
|
|||
Rect _cropRect;
|
||||
ID2D1Bitmap * _bitmap;
|
||||
|
||||
static std::map<Resource, ID2D1Bitmap*> _bitmapCache;
|
||||
static std::map<size_t, ID2D1Bitmap*> _bitmapCache;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -58,15 +58,20 @@ public:
|
|||
Music();
|
||||
|
||||
explicit Music(
|
||||
const Resource& res /* 音乐资源 */
|
||||
const e2d::String& filePath /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
explicit Music(
|
||||
IXAudio2* xAudio2
|
||||
const Resource& res /* 音乐资源 */
|
||||
);
|
||||
|
||||
virtual ~Music();
|
||||
|
||||
// 打开音乐文件
|
||||
bool open(
|
||||
const e2d::String& filePath /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 댔역稜있栗都
|
||||
bool open(
|
||||
const Resource& res
|
||||
|
|
@ -110,6 +115,27 @@ public:
|
|||
// 삿혤 IXAudio2SourceVoice 뚤蹶
|
||||
IXAudio2SourceVoice * getIXAudio2SourceVoice() const;
|
||||
|
||||
public:
|
||||
class XAudio2Tool
|
||||
{
|
||||
public:
|
||||
XAudio2Tool();
|
||||
|
||||
~XAudio2Tool();
|
||||
|
||||
static XAudio2Tool* getInstance();
|
||||
|
||||
// 获取 XAudio2 实例对象
|
||||
IXAudio2 * getXAudio2();
|
||||
|
||||
// 获取 MasteringVoice 实例对象
|
||||
IXAudio2MasteringVoice* getMasteringVoice();
|
||||
|
||||
protected:
|
||||
IXAudio2 * _xAudio2;
|
||||
IXAudio2MasteringVoice* _masteringVoice;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool _readMMIO();
|
||||
|
||||
|
|
@ -137,9 +163,7 @@ protected:
|
|||
MMCKINFO _ckRiff;
|
||||
WAVEFORMATEX* _wfx;
|
||||
VoiceCallback _voiceCallback;
|
||||
IXAudio2* _xAudio2;
|
||||
IXAudio2SourceVoice* _voice;
|
||||
IXAudio2MasteringVoice* _masteringVoice;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -153,6 +177,37 @@ public:
|
|||
|
||||
~Player();
|
||||
|
||||
// 预加载音乐资源
|
||||
bool preload(
|
||||
const String& filePath /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 播放音乐
|
||||
bool play(
|
||||
const String& filePath, /* 音乐文件路径 */
|
||||
int nLoopCount = 0 /* 重复播放次数,设置 -1 为循环播放 */
|
||||
);
|
||||
|
||||
// 暂停音乐
|
||||
void pause(
|
||||
const String& filePath /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 继续播放音乐
|
||||
void resume(
|
||||
const String& filePath /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 停止音乐
|
||||
void stop(
|
||||
const String& filePath /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 获取音乐播放状态
|
||||
bool isPlaying(
|
||||
const String& filePath /* 音乐文件路径 */
|
||||
);
|
||||
|
||||
// 渡속潼稜있栗都
|
||||
bool preload(
|
||||
const Resource& res /* 稜있栗都 */
|
||||
|
|
@ -201,26 +256,12 @@ public:
|
|||
// 界岺杰唐稜있
|
||||
void stopAll();
|
||||
|
||||
// 打开或关闭播放器
|
||||
void setEnabled(
|
||||
bool enabled
|
||||
);
|
||||
|
||||
// 헌왕稜있뻠닸
|
||||
void clearCache();
|
||||
|
||||
// 获取 XAudio2 实例对象
|
||||
IXAudio2 * getXAudio2();
|
||||
|
||||
// 获取 MasteringVoice 实例对象
|
||||
IXAudio2MasteringVoice* getMasteringVoice();
|
||||
|
||||
private:
|
||||
bool _enabled;
|
||||
float _volume;
|
||||
IXAudio2* _xAudio2;
|
||||
IXAudio2MasteringVoice* _masteringVoice;
|
||||
std::map<Resource, Music*> _musicList;
|
||||
std::map<size_t, Music*> _musicList;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue