Update Sound && SoundPlayer

This commit is contained in:
Nomango 2019-08-19 09:28:59 +08:00
parent bdedf76b5e
commit 7b8e4814a9
25 changed files with 181 additions and 154 deletions

View File

@ -4,14 +4,14 @@
<ClInclude Include="..\src\kiwano-audio\kiwano-audio.h" />
<ClInclude Include="..\src\kiwano-audio\src\audio-modules.h" />
<ClInclude Include="..\src\kiwano-audio\src\audio.h" />
<ClInclude Include="..\src\kiwano-audio\src\Player.h" />
<ClInclude Include="..\src\kiwano-audio\src\SoundPlayer.h" />
<ClInclude Include="..\src\kiwano-audio\src\Sound.h" />
<ClInclude Include="..\src\kiwano-audio\src\Transcoder.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\kiwano-audio\src\audio-modules.cpp" />
<ClCompile Include="..\src\kiwano-audio\src\audio.cpp" />
<ClCompile Include="..\src\kiwano-audio\src\Player.cpp" />
<ClCompile Include="..\src\kiwano-audio\src\SoundPlayer.cpp" />
<ClCompile Include="..\src\kiwano-audio\src\Sound.cpp" />
<ClCompile Include="..\src\kiwano-audio\src\Transcoder.cpp" />
</ItemGroup>

View File

@ -8,15 +8,15 @@
<ClInclude Include="..\src\kiwano-audio\src\audio-modules.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\kiwano-audio\src\Player.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\kiwano-audio\src\Sound.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\kiwano-audio\src\Transcoder.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\src\kiwano-audio\src\SoundPlayer.h">
<Filter>src</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\kiwano-audio\src\audio.cpp">
@ -25,15 +25,15 @@
<ClCompile Include="..\src\kiwano-audio\src\audio-modules.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\kiwano-audio\src\Player.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\kiwano-audio\src\Sound.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\kiwano-audio\src\Transcoder.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\src\kiwano-audio\src\SoundPlayer.cpp">
<Filter>src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="src">

View File

@ -22,4 +22,4 @@
#include "src/audio.h"
#include "src/Sound.h"
#include "src/Player.h"
#include "src/SoundPlayer.h"

View File

@ -22,7 +22,6 @@
#include <kiwano/utils/FileUtil.h>
#include "Sound.h"
#include "audio.h"
#include "Transcoder.h"
namespace kiwano
{
@ -32,12 +31,16 @@ namespace kiwano
Sound::Sound()
: opened_(false)
, playing_(false)
, size_(0)
, wave_data_(nullptr)
, voice_(nullptr)
{
}
Sound::Sound(String const& file_path)
: Sound()
{
Load(file_path);
}
Sound::Sound(Resource const& res)
: Sound()
{
@ -51,21 +54,19 @@ namespace kiwano
bool Sound::Load(String const& file_path)
{
if (opened_)
{
Close();
}
#if defined(KGE_DEBUG)
if (!FileUtil::ExistsFile(file_path))
{
KGE_WARNING_LOG(L"Media file '%s' not found", file_path.c_str());
return false;
}
#endif
if (opened_)
{
Close();
}
Transcoder transcoder;
HRESULT hr = transcoder.LoadMediaFile(file_path, &wave_data_, &size_);
HRESULT hr = transcoder.LoadMediaFile(file_path);
if (FAILED(hr))
{
@ -73,14 +74,11 @@ namespace kiwano
return false;
}
hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetBuffer().format);
if (FAILED(hr))
{
if (wave_data_)
{
delete[] wave_data_;
wave_data_ = nullptr;
}
Close();
KGE_ERROR_LOG(L"Create source voice failed with HRESULT of %08X", hr);
return false;
}
@ -97,7 +95,7 @@ namespace kiwano
}
Transcoder transcoder;
HRESULT hr = transcoder.LoadMediaResource(res, &wave_data_, &size_);
HRESULT hr = transcoder.LoadMediaResource(res);
if (FAILED(hr))
{
@ -105,14 +103,11 @@ namespace kiwano
return false;
}
hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetWaveFormatEx());
hr = Audio::GetInstance()->CreateVoice(&voice_, transcoder.GetBuffer().format);
if (FAILED(hr))
{
if (wave_data_)
{
delete[] wave_data_;
wave_data_ = nullptr;
}
Close();
KGE_ERROR_LOG(L"Create source voice failed with HRESULT of %08X", hr);
return false;
}
@ -140,10 +135,12 @@ namespace kiwano
// clamp loop count
loop_count = (loop_count < 0) ? XAUDIO2_LOOP_INFINITE : std::min(loop_count, XAUDIO2_LOOP_INFINITE - 1);
auto wave_buffer = transcoder_.GetBuffer();
XAUDIO2_BUFFER buffer = { 0 };
buffer.pAudioData = wave_data_;
buffer.pAudioData = wave_buffer.data;
buffer.Flags = XAUDIO2_END_OF_STREAM;
buffer.AudioBytes = size_;
buffer.AudioBytes = wave_buffer.size;
buffer.LoopCount = static_cast<UInt32>(loop_count);
HRESULT hr = voice_->SubmitSourceBuffer(&buffer);
@ -202,11 +199,7 @@ namespace kiwano
voice_ = nullptr;
}
if (wave_data_)
{
delete[] wave_data_;
wave_data_ = nullptr;
}
transcoder_.ClearBuffer();
opened_ = false;
playing_ = false;

View File

@ -23,6 +23,7 @@
#include <kiwano/base/ObjectBase.h>
#include <kiwano/base/Resource.h>
#include <xaudio2.h>
#include "Transcoder.h"
namespace kiwano
{
@ -88,8 +89,7 @@ namespace kiwano
protected:
bool opened_;
bool playing_;
UInt32 size_;
BYTE* wave_data_;
Transcoder transcoder_;
IXAudio2SourceVoice* voice_;
};
}

View File

@ -18,23 +18,23 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "Player.h"
#include "SoundPlayer.h"
namespace kiwano
{
namespace audio
{
Player::Player()
SoundPlayer::SoundPlayer()
: volume_(1.f)
{
}
Player::~Player()
SoundPlayer::~SoundPlayer()
{
ClearCache();
}
UInt32 Player::Load(String const& file_path)
UInt32 SoundPlayer::Load(String const& file_path)
{
UInt32 hash_code = file_path.hash();
if (sound_cache_.end() != sound_cache_.find(hash_code))
@ -54,7 +54,7 @@ namespace kiwano
return false;
}
UInt32 Player::Load(Resource const& res)
UInt32 SoundPlayer::Load(Resource const& res)
{
UInt32 hash_code = res.GetId();
if (sound_cache_.end() != sound_cache_.find(hash_code))
@ -74,35 +74,35 @@ namespace kiwano
return false;
}
void Player::Play(UInt32 id, Int32 loop_count)
void SoundPlayer::Play(UInt32 id, Int32 loop_count)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Play(loop_count);
}
void Player::Pause(UInt32 id)
void SoundPlayer::Pause(UInt32 id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Pause();
}
void Player::Resume(UInt32 id)
void SoundPlayer::Resume(UInt32 id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Resume();
}
void Player::Stop(UInt32 id)
void SoundPlayer::Stop(UInt32 id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
iter->second->Stop();
}
bool Player::IsPlaying(UInt32 id)
bool SoundPlayer::IsPlaying(UInt32 id)
{
auto iter = sound_cache_.find(id);
if (sound_cache_.end() != iter)
@ -110,12 +110,12 @@ namespace kiwano
return false;
}
Float32 Player::GetVolume() const
Float32 SoundPlayer::GetVolume() const
{
return volume_;
}
void Player::SetVolume(Float32 volume)
void SoundPlayer::SetVolume(Float32 volume)
{
volume_ = std::min(std::max(volume, -224.f), 224.f);
for (const auto& pair : sound_cache_)
@ -124,7 +124,7 @@ namespace kiwano
}
}
void Player::PauseAll()
void SoundPlayer::PauseAll()
{
for (const auto& pair : sound_cache_)
{
@ -132,7 +132,7 @@ namespace kiwano
}
}
void Player::ResumeAll()
void SoundPlayer::ResumeAll()
{
for (const auto& pair : sound_cache_)
{
@ -140,7 +140,7 @@ namespace kiwano
}
}
void Player::StopAll()
void SoundPlayer::StopAll()
{
for (const auto& pair : sound_cache_)
{
@ -148,7 +148,7 @@ namespace kiwano
}
}
void Player::ClearCache()
void SoundPlayer::ClearCache()
{
sound_cache_.clear();
}

View File

@ -27,23 +27,23 @@ namespace kiwano
{
namespace audio
{
KGE_DECLARE_SMART_PTR(Player);
KGE_DECLARE_SMART_PTR(SoundPlayer);
// 稜있꺄렴포
class KGE_API Player
class KGE_API SoundPlayer
: protected ObjectBase
{
public:
Player();
SoundPlayer();
~Player();
~SoundPlayer();
// 加载本地音频文件, 返回该资源标识符
// 加载本地音频文件, 返回该资源标识符
UInt32 Load(
String const& file_path
);
// 加载音乐资源, 返回该资源标识符
// 加载音乐资源, 返回该资源标识符
UInt32 Load(
Resource const& res /* 稜있栗都 */
);

View File

@ -38,24 +38,39 @@ namespace kiwano
Transcoder::Transcoder()
: wave_format_(nullptr)
, wave_data_(nullptr)
, wave_size_(0)
{
}
Transcoder::~Transcoder()
{
ClearBuffer();
}
Transcoder::Buffer Transcoder::GetBuffer() const
{
return Buffer{ wave_data_, wave_size_, wave_format_ };
}
void Transcoder::ClearBuffer()
{
if (wave_format_)
{
::CoTaskMemFree(wave_format_);
wave_format_ = nullptr;
}
}
const WAVEFORMATEX* Transcoder::GetWaveFormatEx() const
if (wave_data_)
{
return wave_format_;
delete[] wave_data_;
wave_data_ = nullptr;
}
HRESULT Transcoder::LoadMediaFile(String const& file_path, BYTE** wave_data, UInt32* wave_data_size)
wave_size_ = 0;
}
HRESULT Transcoder::LoadMediaFile(String const& file_path)
{
HRESULT hr = S_OK;
@ -69,13 +84,13 @@ namespace kiwano
if (SUCCEEDED(hr))
{
hr = ReadSource(reader.get(), wave_data, wave_data_size);
hr = ReadSource(reader.get());
}
return hr;
}
HRESULT Transcoder::LoadMediaResource(Resource const& res, BYTE** wave_data, UInt32* wave_data_size)
HRESULT Transcoder::LoadMediaResource(Resource const& res)
{
HRESULT hr = S_OK;
@ -87,7 +102,7 @@ namespace kiwano
if (!data) { return E_FAIL; }
stream = kiwano::modules::Shlwapi::Get().SHCreateMemStream(
static_cast<const BYTE*>(data.buffer),
static_cast<const Byte*>(data.buffer),
static_cast<UInt32>(data.size)
);
@ -113,13 +128,13 @@ namespace kiwano
if (SUCCEEDED(hr))
{
hr = ReadSource(reader.get(), wave_data, wave_data_size);
hr = ReadSource(reader.get());
}
return hr;
}
HRESULT Transcoder::ReadSource(IMFSourceReader* reader, BYTE** wave_data, UInt32* wave_data_size)
HRESULT Transcoder::ReadSource(IMFSourceReader* reader)
{
HRESULT hr = S_OK;
DWORD max_stream_size = 0;
@ -203,7 +218,7 @@ namespace kiwano
{
DWORD flags = 0;
DWORD position = 0;
BYTE* data = new (std::nothrow) BYTE[max_stream_size];
Byte* data = new (std::nothrow) Byte[max_stream_size];
ComPtr<IMFSample> sample;
ComPtr<IMFMediaBuffer> buffer;
@ -236,7 +251,7 @@ namespace kiwano
if (SUCCEEDED(hr))
{
BYTE* audio_data = nullptr;
Byte* audio_data = nullptr;
DWORD sample_buffer_length = 0;
hr = buffer->Lock(
@ -245,7 +260,7 @@ namespace kiwano
&sample_buffer_length
);
if (SUCCEEDED(hr))
if (SUCCEEDED(hr) && sample_buffer_length <= max_stream_size)
{
for (DWORD i = 0; i < sample_buffer_length; i++)
{
@ -263,8 +278,8 @@ namespace kiwano
if (SUCCEEDED(hr))
{
*wave_data = data;
*wave_data_size = position;
wave_data_ = data;
wave_size_ = position;
}
}
}

View File

@ -31,31 +31,36 @@ namespace kiwano
class KGE_API Transcoder
{
public:
struct Buffer
{
Byte* data;
UInt32 size;
const WAVEFORMATEX* format;
};
Transcoder();
~Transcoder();
const WAVEFORMATEX* GetWaveFormatEx() const;
Buffer GetBuffer() const;
void ClearBuffer();
HRESULT LoadMediaFile(
String const& file_path,
BYTE** wave_data,
UInt32* wave_data_size
String const& file_path
);
HRESULT LoadMediaResource(
Resource const& res,
BYTE** wave_data,
UInt32* wave_data_size
Resource const& res
);
HRESULT ReadSource(
IMFSourceReader* reader,
BYTE** wave_data,
UInt32* wave_data_size
IMFSourceReader* reader
);
private:
Byte* wave_data_;
UInt32 wave_size_;
WAVEFORMATEX* wave_format_;
};
}

View File

@ -76,9 +76,17 @@ namespace kiwano
HRESULT Audio::CreateVoice(IXAudio2SourceVoice** voice, const WAVEFORMATEX* wfx)
{
KGE_ASSERT(x_audio2_ && "Audio engine hasn't been initialized!");
if (voice == nullptr)
{
return E_UNEXPECTED;
return E_INVALIDARG;
}
if (*voice)
{
(*voice)->DestroyVoice();
(*voice) = nullptr;
}
HRESULT hr = x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
@ -87,11 +95,15 @@ namespace kiwano
void Audio::Open()
{
KGE_ASSERT(x_audio2_ && "Audio engine hasn't been initialized!");
x_audio2_->StartEngine();
}
void Audio::Close()
{
KGE_ASSERT(x_audio2_ && "Audio engine hasn't been initialized!");
x_audio2_->StopEngine();
}
}

View File

@ -31,7 +31,7 @@ namespace kiwano
}
Resource::Resource(UInt32 id, LPCWSTR type)
Resource::Resource(UInt32 id, const WChar* type)
: id_(id)
, type_(type)
{

View File

@ -49,8 +49,8 @@ namespace kiwano
Resource();
Resource(
UInt32 id, /* ×ÊÔ´Ãû³Æ */
LPCWSTR type /* ×ÊÔ´ÀàÐÍ */
UInt32 id, /* ×ÊÔ´ ID */
const WChar* type /* ×ÊÔ´ÀàÐÍ */
);
// 获取二进制数据
@ -58,11 +58,12 @@ namespace kiwano
inline UInt32 GetId() const { return id_; }
inline LPCWSTR GetType() const { return type_; }
inline const WChar* GetType() const { return type_; }
private:
UInt32 id_;
LPCWSTR type_;
const WChar* type_;
mutable Resource::Data data_;
};
}

View File

@ -66,7 +66,7 @@ namespace kiwano
}
}
void Window::Init(String const& title, Int32 width, Int32 height, LPCWSTR icon, bool fullscreen, WNDPROC proc)
void Window::Init(String const& title, Int32 width, Int32 height, UInt32 icon, bool fullscreen, WNDPROC proc)
{
HINSTANCE hinst = GetModuleHandleW(nullptr);
WNDCLASSEX wcex = { 0 };
@ -84,7 +84,7 @@ namespace kiwano
if (icon)
{
wcex.hIcon = (HICON)::LoadImageW(hinst, icon, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(icon), IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
}
::RegisterClassExW(&wcex);
@ -216,14 +216,14 @@ namespace kiwano
return static_cast<Float32>(height_);
}
void Window::SetIcon(LPCWSTR icon_resource)
void Window::SetIcon(UInt32 icon_resource)
{
if (handle_)
{
HINSTANCE hinstance = GetModuleHandle(nullptr);
HICON icon = (HICON)::LoadImage(
hinstance,
icon_resource,
MAKEINTRESOURCE(icon_resource),
IMAGE_ICON,
0,
0,

View File

@ -48,7 +48,7 @@ namespace kiwano
void SetTitle(String const& title);
// 设置窗口图标
void SetIcon(LPCWSTR icon_resource);
void SetIcon(UInt32 icon_resource);
// 重设窗口大小
void Resize(Int32 width, Int32 height);
@ -64,7 +64,7 @@ namespace kiwano
String const& title,
Int32 width,
Int32 height,
LPCWSTR icon,
UInt32 icon,
bool fullscreen,
WNDPROC proc
);

View File

@ -28,6 +28,7 @@ namespace kiwano
KGE_DEFINE_NUMERIC_TYPE(Char, signed char);
KGE_DEFINE_NUMERIC_TYPE(UChar, unsigned char);
KGE_DEFINE_NUMERIC_TYPE(WChar, wchar_t);
KGE_DEFINE_NUMERIC_TYPE(Byte, UChar);
KGE_DEFINE_NUMERIC_TYPE(Int8, std::int8_t);
KGE_DEFINE_NUMERIC_TYPE(Int16, std::int16_t);

View File

@ -43,7 +43,7 @@ namespace kiwano
Queue<FunctionToPerform> functions_to_perform_;
}
Options::Options(String const& title, Int32 width, Int32 height, LPCWSTR icon, Color clear_color, bool vsync, bool fullscreen, bool debug)
Options::Options(String const& title, Int32 width, Int32 height, UInt32 icon, Color clear_color, bool vsync, bool fullscreen, bool debug)
: title(title)
, width(width)
, height(height)

View File

@ -32,7 +32,7 @@ namespace kiwano
String title; // 标题
Int32 width; // 宽度
Int32 height; // 高度
LPCWSTR icon; // ͼ±ê
UInt32 icon; // ͼ±ê×ÊÔ´ ID
Color clear_color; // 清屏颜色
bool vsync; // 垂直同步
bool fullscreen; // 全屏模式
@ -42,7 +42,7 @@ namespace kiwano
String const& title = L"Kiwano Game",
Int32 width = 640,
Int32 height = 480,
LPCWSTR icon = nullptr,
UInt32 icon = 0,
Color clear_color = Color::Black,
bool vsync = true,
bool fullscreen = false,

View File

@ -191,7 +191,7 @@ namespace kiwano
HRESULT GifImage::GetBackgroundColor(ComPtr<IWICMetadataQueryReader> metadata_reader)
{
BYTE bg_index = 0;
UChar bg_index = 0;
WICColor bgcolors[256];
UInt32 colors_copied = 0;
ComPtr<IWICPalette> wic_palette;

View File

@ -948,7 +948,7 @@ namespace kiwano
if (fileOffset <= resourceSize_ &&
fragmentSize <= resourceSize_ - fileOffset)
{
*fragmentStart = static_cast<BYTE const*>(resourcePtr_) + static_cast<UInt32>(fileOffset);
*fragmentStart = static_cast<Byte const*>(resourcePtr_) + static_cast<UInt32>(fileOffset);
*fragmentContext = NULL;
return S_OK;
}