add: use Media Foundation to play sound effect

This commit is contained in:
Nomango 2018-10-11 20:00:21 +08:00
parent fdbece1663
commit 80d1a87955
13 changed files with 1277 additions and 747 deletions

View File

@ -25,38 +25,29 @@ namespace e2d
{ {
class Music; class MediaAsyncCallback : public IMFAsyncCallback
// ÒôÔ´»Øµ÷
class VoiceCallback
: public IXAudio2VoiceCallback
{ {
public: public:
VoiceCallback(); MediaAsyncCallback(
HWND hwnd,
IMFMediaSession * pSession,
HANDLE hCloseEvent
);
~VoiceCallback(); // IUnknown methods
STDMETHODIMP QueryInterface(REFIID iid, void** ppv);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) {} // IMFAsyncCallback methods
STDMETHODIMP GetParameters(DWORD*, DWORD*);
STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) {} STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult);
STDMETHOD_(void, OnStreamEnd) (THIS);
STDMETHOD_(void, OnBufferStart) (THIS_ void* pBufferContext) {}
STDMETHOD_(void, OnBufferEnd) (THIS_ void* pBufferContext);
STDMETHOD_(void, OnLoopEnd) (THIS_ void* pBufferContext);
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) {}
STDMETHOD_(void, SetCallbackOnStreamEnd) (THIS_ const Function& func);
STDMETHOD_(void, SetCallbackOnLoopEnd) (THIS_ const Function& func);
protected: protected:
Function loop_end_callback_; long m_nRefCount;
Function stream_end_callback_; IMFMediaSession * m_pSession;
HWND m_hwnd;
HANDLE m_hCloseEvent;
}; };

View File

@ -45,7 +45,9 @@
# define DIRECTINPUT_VERSION 0x0800 # define DIRECTINPUT_VERSION 0x0800
#endif #endif
#ifndef INITGUID
# define INITGUID # define INITGUID
#endif
// Windows Header Files // Windows Header Files
@ -55,8 +57,12 @@
#include <d2d1.h> #include <d2d1.h>
#include <dwrite.h> #include <dwrite.h>
#include <dinput.h> #include <dinput.h>
#include <d2d1helper.h> #include <shlwapi.h>
#include <xaudio2.h> #include <mfapi.h>
#include <mfidl.h>
#include <mferror.h>
#include <evr.h>
#include <mmdeviceapi.h>
// C++ RunTime Header Files // C++ RunTime Header Files
#include <map> #include <map>
@ -76,8 +82,12 @@
#pragma comment(lib, "dwrite.lib") #pragma comment(lib, "dwrite.lib")
#pragma comment(lib, "windowscodecs.lib") #pragma comment(lib, "windowscodecs.lib")
#pragma comment(lib, "winmm.lib") #pragma comment(lib, "winmm.lib")
#pragma comment(lib, "xaudio2.lib")
#pragma comment(lib, "dinput8.lib") #pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "shlwapi")
#pragma comment(lib, "mfplay.lib")
#pragma comment(lib, "mf.lib")
#pragma comment(lib, "mfplat.lib")
#pragma comment(lib, "mfuuid.lib")
#ifndef HINST_THISCOMPONENT #ifndef HINST_THISCOMPONENT

View File

@ -149,22 +149,30 @@ namespace e2d
~Audio(); ~Audio();
// 开启设备 // 获取音量
void Open(); float GetVolume();
// 关闭设备 // 设置音量
void Close(); void SetVolume(
float volume
);
// 创建音源 // 是否静音
HRESULT CreateVoice( bool GetMute();
IXAudio2SourceVoice ** voice,
WAVEFORMATEX * wfx, // 设置静音
VoiceCallback * callback void SetMute(
bool mute
); );
protected: protected:
IXAudio2 * x_audio2_; LPWSTR device_id; // Device ID.
IXAudio2MasteringVoice* mastering_voice_; IMMDeviceEnumerator *enum_; // Audio device enumerator.
IMMDeviceCollection *devices_; // Audio device collection.
IMMDevice *device_; // An audio device.
IMFAttributes *attributes_; // Attribute store.
IMFMediaSink *sink_; // Streaming audio renderer (SAR)
IMFSimpleAudioVolume *audio_volume;
}; };
@ -301,9 +309,6 @@ namespace e2d
int height int height
); );
// 进入下一场景
void EnterNextScene();
// Win32 ´°¿ÚÏûÏ¢»Øµ÷³ÌÐò // Win32 ´°¿ÚÏûÏ¢»Øµ÷³ÌÐò
static LRESULT CALLBACK WndProc( static LRESULT CALLBACK WndProc(
HWND hwnd, HWND hwnd,

View File

@ -71,6 +71,7 @@ namespace e2d
// 稜있 // 稜있
class Music class Music
: public IMFAsyncCallback
{ {
public: public:
Music(); Music();
@ -97,15 +98,12 @@ namespace e2d
// 꺄렴 // 꺄렴
bool Play( bool Play(
int loopCount = 0 int loop_count = 0
); );
// 董界 // 董界
void Pause(); void Pause();
// 继续
void Resume();
// 界岺 // 界岺
void Stop(); void Stop();
@ -117,51 +115,97 @@ namespace e2d
// <20>零稜좆 // <20>零稜좆
bool SetVolume( bool SetVolume(
float volume float volume /* ·¶Î§: 0.0 ~ 1.0 */
); );
// 设置播放结束时的执行函数 // »ñÈ¡ÒôÁ¿
void SetCallbackOnEnd( float GetVolume() const;
const Function& func
);
// 设置循环播放中每一次播放结束时的执行函数 // IUnknown methods
void SetCallbackOnLoopEnd( STDMETHODIMP QueryInterface(REFIID iid, void** ppv) override;
const Function& func STDMETHODIMP_(ULONG) AddRef() override;
); STDMETHODIMP_(ULONG) Release() override;
// 获取 IXAudio2SourceVoice 对象 // IMFAsyncCallback methods
IXAudio2SourceVoice * GetSourceVoice() const; STDMETHODIMP GetParameters(DWORD*, DWORD*) override;
STDMETHODIMP Invoke(IMFAsyncResult* pAsyncResult) override;
protected: protected:
enum class State : int
{
Closed = 0,
Loaded,
Started,
Paused,
Stopped,
Closing
};
E2D_DISABLE_COPY(Music); E2D_DISABLE_COPY(Music);
bool ReadMMIO(); // Media event handlers
HRESULT OnNewPresentation(IMFMediaEvent *pEvent);
bool ResetFile(); HRESULT StartPlayback();
HRESULT CreateMediaSource(PCWSTR sURL, IMFMediaSource **ppSource);
HRESULT HandleEvent(UINT_PTR pUnkPtr);
bool Read( // Add a source node to a topology.
BYTE* buffer, HRESULT AddSourceNode(
DWORD size_to_read IMFTopology *pTopology, // Topology.
IMFMediaSource *pSource, // Media source.
IMFPresentationDescriptor *pPD, // Presentation descriptor.
IMFStreamDescriptor *pSD, // Stream descriptor.
IMFTopologyNode **ppNode // Receives the node pointer.
); );
bool FindMediaFileCch( // Add an output node to a topology.
wchar_t* dest_path, HRESULT AddOutputNode(
int cch_dest, IMFTopology *pTopology, // Topology.
const wchar_t * file_name IMFActivate *pActivate, // Media sink activation object.
DWORD dwId, // Identifier of the stream sink.
IMFTopologyNode **ppNode // Receives the node pointer.
);
HRESULT AddBranchToPartialTopology(
IMFTopology *pTopology, // Topology.
IMFMediaSource *pSource, // Media source.
IMFPresentationDescriptor *pPD, // Presentation descriptor.
DWORD iStream // Stream index.
);
// Create a playback topology from a media source.
HRESULT CreatePlaybackTopology(
IMFMediaSource *pSource, // Media source.
IMFPresentationDescriptor *pPD, // Presentation descriptor.
IMFTopology **ppTopology // Receives a pointer to the topology.
);
// Create an activation object for a renderer, based on the stream media type.
HRESULT CreateMediaSinkActivate(
IMFStreamDescriptor *pSourceSD, // Pointer to the stream descriptor.
IMFActivate **ppActivate
);
HRESULT GetSimpleAudioVolume(
IMFSimpleAudioVolume** ppAudioVolume
) const;
static LRESULT CALLBACK MediaProc(
HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam
); );
protected: protected:
bool opened_; long m_nRefCount;
DWORD size_; int m_nTimes;
CHAR* buffer_; IMFMediaSession * m_pSession;
BYTE* wave_data_; IMFMediaSource *m_pSource;
HMMIO hmmio_; HWND m_hwndEvent;
MMCKINFO ck_; State m_state;
MMCKINFO ck_riff_; HANDLE m_hCloseEvent;
WAVEFORMATEX* wfx_;
VoiceCallback callback_;
IXAudio2SourceVoice* voice_;
}; };
@ -240,7 +284,7 @@ namespace e2d
// <20>零稜좆 // <20>零稜좆
void SetVolume( void SetVolume(
float volume /* 音量范围为 -224 ~ 2240 是静音1 是正常音量 */ float volume /* ·¶Î§: 0.0 ~ 1.0 */
); );
// 董界杰唐稜있 // 董界杰唐稜있

View File

@ -0,0 +1,116 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "..\e2dimpl.h"
e2d::MediaAsyncCallback::MediaAsyncCallback(HWND hwnd, IMFMediaSession * pSession, HANDLE hCloseEvent)
: m_pSession(pSession)
, m_hCloseEvent(hCloseEvent)
, m_hwnd(hwnd)
{
}
HRESULT e2d::MediaAsyncCallback::QueryInterface(REFIID riid, void** ppv)
{
static const QITAB qit[] =
{
QITABENT(MediaAsyncCallback, IMFAsyncCallback),
{ 0 }
};
return QISearch(this, qit, riid, ppv);
}
ULONG e2d::MediaAsyncCallback::AddRef()
{
return InterlockedIncrement(&m_nRefCount);
}
ULONG e2d::MediaAsyncCallback::Release()
{
ULONG uCount = InterlockedDecrement(&m_nRefCount);
if (uCount == 0)
{
delete this;
}
return uCount;
}
HRESULT e2d::MediaAsyncCallback::GetParameters(DWORD *, DWORD *)
{
// Implementation of this method is optional.
return E_NOTIMPL;
}
HRESULT e2d::MediaAsyncCallback::Invoke(IMFAsyncResult *pResult)
{
MediaEventType meType = MEUnknown; // Event type
IMFMediaEvent *pEvent = NULL;
// Get the event from the event queue.
HRESULT hr = m_pSession->EndGetEvent(pResult, &pEvent);
if (FAILED(hr))
{
goto done;
}
// Get the event type.
hr = pEvent->GetType(&meType);
if (FAILED(hr))
{
goto done;
}
if (meType == MESessionClosed)
{
// The session was closed.
// The application is waiting on the m_hCloseEvent event handle.
SetEvent(m_hCloseEvent);
}
else
{
// For all other events, get the next event in the queue.
hr = m_pSession->BeginGetEvent(this, NULL);
if (FAILED(hr))
{
goto done;
}
}
// Check the application state.
// If a call to IMFMediaSession::Close is pending, it means the
// application is waiting on the m_hCloseEvent event and
// the application's message loop is blocked.
// Otherwise, post a private window message to the application.
//if (m_state != Closing)
{
// Leave a reference count on the event.
pEvent->AddRef();
::PostMessage(m_hwnd, WM_APP + 1, (WPARAM)pEvent, (LPARAM)meType);
}
done:
SafeRelease(pEvent);
return S_OK;
}

View File

@ -1,64 +0,0 @@
// Copyright (c) 2016-2018 Easy2D - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#include "..\e2dimpl.h"
#include "..\e2dutil.h"
e2d::VoiceCallback::VoiceCallback()
{
}
e2d::VoiceCallback::~VoiceCallback()
{
}
void e2d::VoiceCallback::OnLoopEnd(void * pBufferContext)
{
if (loop_end_callback_)
{
loop_end_callback_();
}
}
void e2d::VoiceCallback::OnStreamEnd()
{
if (stream_end_callback_)
{
stream_end_callback_();
}
}
void e2d::VoiceCallback::OnBufferEnd(void * pBufferContext)
{
if (loop_end_callback_)
{
loop_end_callback_();
}
}
void e2d::VoiceCallback::SetCallbackOnStreamEnd(const Function & func)
{
stream_end_callback_ = func;
}
void e2d::VoiceCallback::SetCallbackOnLoopEnd(const Function & func)
{
loop_end_callback_ = func;
}

View File

@ -22,40 +22,128 @@
e2d::Audio::Audio() e2d::Audio::Audio()
: x_audio2_(nullptr) : enum_(nullptr)
, mastering_voice_(nullptr) , devices_(nullptr)
, device_(nullptr)
, attributes_(nullptr)
, sink_(nullptr)
, device_id(nullptr)
, audio_volume(nullptr)
{ {
ThrowIfFailed( ThrowIfFailed(
XAudio2Create(&x_audio2_, 0) MFStartup(MF_VERSION)
);
// Create the device enumerator.
ThrowIfFailed(
CoCreateInstance(
__uuidof(MMDeviceEnumerator),
NULL,
CLSCTX_ALL,
__uuidof(IMMDeviceEnumerator),
(void**)&enum_
)
);
// Enumerate the rendering devices.
ThrowIfFailed(
enum_->EnumAudioEndpoints(eRender, DEVICE_STATE_ACTIVE, &devices_)
);
// Get ID of the first device in the list.
ThrowIfFailed(
devices_->Item(0, &device_)
); );
ThrowIfFailed( ThrowIfFailed(
x_audio2_->CreateMasteringVoice(&mastering_voice_) device_->GetId(&device_id)
); );
// Create an attribute store and set the device ID attribute.
ThrowIfFailed(
MFCreateAttributes(&attributes_, 2)
);
ThrowIfFailed(
attributes_->SetString(
MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID,
device_id
)
);
// Create the audio renderer.
ThrowIfFailed(
MFCreateAudioRenderer(attributes_, &sink_)
);
IMFGetService* service = NULL;
ThrowIfFailed(
sink_->QueryInterface(IID_IMFGetService, (void **)&service)
);
ThrowIfFailed(
service->GetService(MR_POLICY_VOLUME_SERVICE, IID_PPV_ARGS(&audio_volume))
);
SafeRelease(service);
} }
e2d::Audio::~Audio() e2d::Audio::~Audio()
{ {
if (mastering_voice_) SafeRelease(enum_);
{ SafeRelease(devices_);
mastering_voice_->DestroyVoice(); SafeRelease(device_);
mastering_voice_ = nullptr; SafeRelease(attributes_);
SafeRelease(audio_volume);
SafeRelease(sink_);
CoTaskMemFree(device_id);
MFShutdown();
} }
SafeRelease(x_audio2_); float e2d::Audio::GetVolume()
{
float volume = 0.f;
if (audio_volume)
{
HRESULT hr = audio_volume->GetMasterVolume(&volume);
if (SUCCEEDED(hr))
{
return volume;
}
}
return 0.f;
} }
HRESULT e2d::Audio::CreateVoice(IXAudio2SourceVoice ** voice, WAVEFORMATEX * wfx, VoiceCallback * callback) void e2d::Audio::SetVolume(float volume)
{ {
return x_audio2_->CreateSourceVoice(voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO, callback); if (audio_volume)
{
volume = std::min(std::max(volume, 0.f), 1.f);
HRESULT hr = audio_volume->SetMasterVolume(volume);
printf("ºÇºÇ%#X\n", hr);
}
} }
void e2d::Audio::Open() bool e2d::Audio::GetMute()
{ {
x_audio2_->StartEngine(); BOOL mute = FALSE;
if (audio_volume)
{
HRESULT hr = audio_volume->GetMute(&mute);
if (SUCCEEDED(hr))
{
return mute ? true : false;
}
}
return FALSE;
} }
void e2d::Audio::Close() void e2d::Audio::SetMute(bool mute)
{ {
x_audio2_->StopEngine(); if (audio_volume)
{
audio_volume->SetMute(mute ? TRUE : FALSE);
}
} }

View File

@ -93,7 +93,12 @@ void e2d::Game::Run(const Options& options)
Start(); Start();
// 刷新场景 // 刷新场景
EnterNextScene(); if (next_scene_)
{
next_scene_->OnEnter();
curr_scene_ = next_scene_;
next_scene_ = nullptr;
}
::ShowWindow(hwnd_, SW_SHOWNORMAL); ::ShowWindow(hwnd_, SW_SHOWNORMAL);
::UpdateWindow(hwnd_); ::UpdateWindow(hwnd_);
@ -189,17 +194,21 @@ bool e2d::Game::IsTransitioning() const
void e2d::Game::UpdateScene(float dt) void e2d::Game::UpdateScene(float dt)
{ {
if (curr_scene_) auto update = [&](Scene * scene) -> void
{ {
curr_scene_->Update(dt); if (scene)
curr_scene_->GetRoot()->UpdateChildren(dt); {
scene->Update(dt);
Node * root = scene->GetRoot();
if (root)
{
root->UpdateChildren(dt);
} }
}
};
if (next_scene_) update(curr_scene_);
{ update(next_scene_);
next_scene_->Update(dt);
next_scene_->GetRoot()->UpdateChildren(dt);
}
if (transition_) if (transition_)
{ {
@ -216,7 +225,19 @@ void e2d::Game::UpdateScene(float dt)
} }
} }
EnterNextScene(); if (next_scene_)
{
if (curr_scene_)
{
curr_scene_->OnExit();
curr_scene_->Release();
}
next_scene_->OnEnter();
curr_scene_ = next_scene_;
next_scene_ = nullptr;
}
} }
void e2d::Game::DrawScene() void e2d::Game::DrawScene()
@ -281,7 +302,7 @@ void e2d::Game::Init()
} }
// 注册窗口类 // 注册窗口类
RegisterClassEx(&wcex); ::RegisterClassEx(&wcex);
// 计算窗口大小 // 计算窗口大小
Rect client_rect = Locate(width_, height_); Rect client_rect = Locate(width_, height_);
@ -309,6 +330,12 @@ void e2d::Game::Init()
return; return;
} }
::SetWindowLongPtrW(
hwnd_,
GWLP_USERDATA,
PtrToUlong(this)
);
// 初始化设备 // 初始化设备
Device::Init(hwnd_); Device::Init(hwnd_);
@ -379,23 +406,6 @@ e2d::Rect e2d::Game::Locate(int width, int height)
return std::move(client_rect); return std::move(client_rect);
} }
void e2d::Game::EnterNextScene()
{
if (next_scene_)
{
if (curr_scene_)
{
curr_scene_->OnExit();
curr_scene_->Release();
}
next_scene_->OnEnter();
curr_scene_ = next_scene_;
next_scene_ = nullptr;
}
}
int e2d::Game::GetWidth() const int e2d::Game::GetWidth() const
{ {
return width_; return width_;
@ -481,27 +491,9 @@ void e2d::Game::SetIcon(int resource_id)
LRESULT e2d::Game::WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param) LRESULT e2d::Game::WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
{ {
LRESULT result = 0; LRESULT result = 0;
if (msg == WM_CREATE)
{
LPCREATESTRUCT pcs = (LPCREATESTRUCT)l_param;
Game * game = (Game *)pcs->lpCreateParams;
::SetWindowLongPtrW(
hwnd,
GWLP_USERDATA,
PtrToUlong(game)
);
result = 1;
}
else
{
bool was_handled = false; bool was_handled = false;
Game * game = reinterpret_cast<Game*>( Game * game = reinterpret_cast<Game*>(
static_cast<LONG_PTR>( static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA))
::GetWindowLongPtrW(hwnd, GWLP_USERDATA)
)
); );
switch (msg) switch (msg)
@ -628,6 +620,5 @@ LRESULT e2d::Game::WndProc(HWND hwnd, UINT msg, WPARAM w_param, LPARAM l_param)
{ {
result = ::DefWindowProc(hwnd, msg, w_param, l_param); result = ::DefWindowProc(hwnd, msg, w_param, l_param);
} }
}
return result; return result;
} }

View File

@ -78,6 +78,12 @@ void e2d::Scene::Draw()
void e2d::Scene::Dispatch(const MouseEvent & e) void e2d::Scene::Dispatch(const MouseEvent & e)
{ {
auto handler = dynamic_cast<MouseEventHandler*>(this);
if (handler)
{
handler->Handle(e);
}
if (root_) if (root_)
{ {
root_->Dispatch(e, false); root_->Dispatch(e, false);
@ -86,6 +92,12 @@ void e2d::Scene::Dispatch(const MouseEvent & e)
void e2d::Scene::Dispatch(const KeyEvent & e) void e2d::Scene::Dispatch(const KeyEvent & e)
{ {
auto handler = dynamic_cast<KeyEventHandler*>(this);
if (handler)
{
handler->Handle(e);
}
if (root_) if (root_)
{ {
root_->Dispatch(e, false); root_->Dispatch(e, false);

File diff suppressed because it is too large Load Diff

View File

@ -68,7 +68,7 @@ void e2d::Player::Resume(const String & file_path)
size_t hash = file_path.GetHash(); size_t hash = file_path.GetHash();
if (musics_.end() != musics_.find(hash)) if (musics_.end() != musics_.find(hash))
musics_[hash]->Resume(); musics_[hash]->Play();
} }
void e2d::Player::Stop(const String & file_path) void e2d::Player::Stop(const String & file_path)
@ -137,7 +137,7 @@ void e2d::Player::Pause(const Resource& res)
void e2d::Player::Resume(const Resource& res) void e2d::Player::Resume(const Resource& res)
{ {
if (musics_.end() != musics_.find(res.id)) if (musics_.end() != musics_.find(res.id))
musics_[res.id]->Resume(); musics_[res.id]->Play();
} }
void e2d::Player::Stop(const Resource& res) void e2d::Player::Stop(const Resource& res)
@ -160,7 +160,7 @@ float e2d::Player::GetVolume()
void e2d::Player::SetVolume(float volume) void e2d::Player::SetVolume(float volume)
{ {
volume_ = std::min(std::max(volume, -224.f), 224.f); volume_ = std::min(std::max(volume, 0.f), 1.f);
for (const auto& pair : musics_) for (const auto& pair : musics_)
{ {
pair.second->SetVolume(volume_); pair.second->SetVolume(volume_);
@ -179,7 +179,7 @@ void e2d::Player::ResumeAll()
{ {
for (const auto& pair : musics_) for (const auto& pair : musics_)
{ {
pair.second->Resume(); pair.second->Play();
} }
} }

View File

@ -222,7 +222,7 @@
<ClCompile Include="..\..\core\events\KeyEvent.cpp" /> <ClCompile Include="..\..\core\events\KeyEvent.cpp" />
<ClCompile Include="..\..\core\events\MouseEvent.cpp" /> <ClCompile Include="..\..\core\events\MouseEvent.cpp" />
<ClCompile Include="..\..\core\impl\TextRenderer.cpp" /> <ClCompile Include="..\..\core\impl\TextRenderer.cpp" />
<ClCompile Include="..\..\core\impl\VoiceCallback.cpp" /> <ClCompile Include="..\..\core\impl\MediaAsyncCallback.cpp" />
<ClCompile Include="..\..\core\modules\Audio.cpp" /> <ClCompile Include="..\..\core\modules\Audio.cpp" />
<ClCompile Include="..\..\core\modules\Device.cpp" /> <ClCompile Include="..\..\core\modules\Device.cpp" />
<ClCompile Include="..\..\core\modules\Game.cpp" /> <ClCompile Include="..\..\core\modules\Game.cpp" />

View File

@ -141,9 +141,6 @@
<ClCompile Include="..\..\core\impl\TextRenderer.cpp"> <ClCompile Include="..\..\core\impl\TextRenderer.cpp">
<Filter>impl</Filter> <Filter>impl</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\core\impl\VoiceCallback.cpp">
<Filter>impl</Filter>
</ClCompile>
<ClCompile Include="..\..\core\events\KeyEvent.cpp"> <ClCompile Include="..\..\core\events\KeyEvent.cpp">
<Filter>events</Filter> <Filter>events</Filter>
</ClCompile> </ClCompile>
@ -219,6 +216,9 @@
<ClCompile Include="..\..\core\modules\Device.cpp"> <ClCompile Include="..\..\core\modules\Device.cpp">
<Filter>modules</Filter> <Filter>modules</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\core\impl\MediaAsyncCallback.cpp">
<Filter>impl</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\core\easy2d.h" /> <ClInclude Include="..\..\core\easy2d.h" />