Magic_Game/src/core/audio.cpp

248 lines
5.0 KiB
C++
Raw Normal View History

2018-10-03 22:02:46 +08:00
// 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 "audio.h"
#include "include-forwards.h"
#include "modules.h"
2018-11-15 17:59:18 +08:00
#include "logs.h"
#include <mfapi.h>
#include <mfidl.h>
#include <mfreadwrite.h>
#include <assert.h>
2018-11-08 00:21:59 +08:00
namespace easy2d
{
2018-11-12 20:46:54 +08:00
//-------------------------------------------------------
// Voice
//-------------------------------------------------------
Voice::Voice()
: source_voice_(nullptr)
{
}
Voice::Voice(IXAudio2SourceVoice * source_voice)
: source_voice_(source_voice)
{
}
Voice::~Voice()
{
Destroy();
Audio::Instance().DeleteVoice(this);
2018-11-12 20:46:54 +08:00
}
HRESULT Voice::Play(const BYTE * wave_data, UINT32 data_size, UINT32 loop_count)
{
if (!source_voice_)
return E_UNEXPECTED;
XAUDIO2_BUFFER buffer = { 0 };
buffer.pAudioData = wave_data;
buffer.Flags = XAUDIO2_END_OF_STREAM;
buffer.AudioBytes = data_size;
buffer.LoopCount = loop_count;
HRESULT hr = source_voice_->SubmitSourceBuffer(&buffer);
if (SUCCEEDED(hr))
{
hr = source_voice_->Start();
}
return hr;
}
HRESULT Voice::Pause()
{
if (!source_voice_)
return E_UNEXPECTED;
return source_voice_->Stop();
}
HRESULT Voice::Resume()
{
if (!source_voice_)
return E_UNEXPECTED;
return source_voice_->Start();
}
HRESULT Voice::Stop()
{
if (!source_voice_)
return E_UNEXPECTED;
HRESULT hr = source_voice_->Stop();
if (SUCCEEDED(hr))
{
hr = source_voice_->ExitLoop();
}
if (SUCCEEDED(hr))
{
hr = source_voice_->FlushSourceBuffers();
}
return hr;
}
HRESULT Voice::GetVolume(float * volume) const
{
if (!source_voice_)
return E_UNEXPECTED;
if (volume == nullptr)
return E_POINTER;
source_voice_->GetVolume(volume);
return S_OK;
}
HRESULT Voice::SetVolume(float volume)
{
if (!source_voice_)
return E_UNEXPECTED;
volume = std::min(std::max(volume, -224.f), 224.f);
return source_voice_->SetVolume(volume);
}
HRESULT Voice::GetBuffersQueued(UINT32 * queued) const
2018-05-10 14:03:54 +08:00
{
2018-11-12 20:46:54 +08:00
if (!source_voice_)
return E_UNEXPECTED;
if (queued == nullptr)
return E_POINTER;
XAUDIO2_VOICE_STATE state;
source_voice_->GetState(&state);
*queued = state.BuffersQueued;
return S_OK;
}
void Voice::Destroy()
{
if (source_voice_)
{
source_voice_->Stop();
source_voice_->FlushSourceBuffers();
source_voice_->DestroyVoice();
source_voice_ = nullptr;
}
}
void Voice::SetSourceVoice(IXAudio2SourceVoice * source_voice)
{
Destroy();
source_voice_ = source_voice;
}
2018-11-22 19:31:44 +08:00
//-------------------------------------------------------
2019-01-24 12:21:01 +08:00
// Audio
2018-11-22 19:31:44 +08:00
//-------------------------------------------------------
2019-01-24 12:21:01 +08:00
Audio::Audio()
2018-11-22 19:31:44 +08:00
: x_audio2_(nullptr)
, mastering_voice_(nullptr)
2018-11-12 20:46:54 +08:00
{
2018-11-22 19:31:44 +08:00
}
2019-01-24 12:21:01 +08:00
Audio::~Audio()
2018-11-22 19:31:44 +08:00
{
}
2018-11-12 20:46:54 +08:00
2019-01-24 12:21:01 +08:00
HRESULT Audio::Init(bool debug)
2018-11-22 19:31:44 +08:00
{
2019-02-03 00:16:53 +08:00
E2D_NOT_USED(debug);
E2D_LOG(L"Initing audio resources");
2018-11-12 20:46:54 +08:00
HRESULT hr = modules::MediaFoundation::Get().MFStartup(MF_VERSION, MFSTARTUP_FULL);
2018-11-12 20:46:54 +08:00
2018-11-22 19:31:44 +08:00
if (SUCCEEDED(hr))
{
hr = modules::XAudio2::Get().XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR);
2018-11-08 00:21:59 +08:00
}
2018-05-14 00:36:01 +08:00
2018-11-22 19:31:44 +08:00
if (SUCCEEDED(hr))
2018-11-08 00:21:59 +08:00
{
2018-11-22 19:31:44 +08:00
hr = x_audio2_->CreateMasteringVoice(&mastering_voice_);
}
2018-11-22 19:31:44 +08:00
return hr;
}
void Audio::Destroy()
{
E2D_LOG(L"Destroying audio resources");
ClearVoiceCache();
if (mastering_voice_)
{
mastering_voice_->DestroyVoice();
mastering_voice_ = nullptr;
}
SafeRelease(x_audio2_);
modules::MediaFoundation::Get().MFShutdown();
}
2019-01-24 12:21:01 +08:00
HRESULT Audio::CreateVoice(Voice& voice, const WAVEFORMATEX* wfx)
2018-11-22 19:31:44 +08:00
{
HRESULT hr;
IXAudio2SourceVoice* source_voice;
2018-11-22 19:31:44 +08:00
hr = x_audio2_->CreateSourceVoice(&source_voice, wfx, 0, XAUDIO2_DEFAULT_FREQ_RATIO);
if (SUCCEEDED(hr))
2018-11-08 00:21:59 +08:00
{
2018-11-22 19:31:44 +08:00
voice.SetSourceVoice(source_voice);
voice_cache_.insert(&voice);
2018-11-12 20:46:54 +08:00
}
2018-11-22 19:31:44 +08:00
return hr;
}
2019-01-24 12:21:01 +08:00
void Audio::DeleteVoice(Voice* voice)
2018-11-22 19:31:44 +08:00
{
voice_cache_.erase(voice);
}
2019-01-24 12:21:01 +08:00
void Audio::ClearVoiceCache()
2018-11-22 19:31:44 +08:00
{
for (auto voice : voice_cache_)
2018-05-10 14:03:54 +08:00
{
2018-11-22 19:31:44 +08:00
voice->Destroy();
2018-11-08 00:21:59 +08:00
}
2018-11-22 19:31:44 +08:00
voice_cache_.clear();
}
2018-11-08 00:21:59 +08:00
2019-01-24 12:21:01 +08:00
void Audio::Open()
2018-11-22 19:31:44 +08:00
{
x_audio2_->StartEngine();
}
2019-01-24 12:21:01 +08:00
void Audio::Close()
2018-11-22 19:31:44 +08:00
{
x_audio2_->StopEngine();
2018-05-10 14:03:54 +08:00
}
2018-11-22 19:31:44 +08:00
2018-11-08 00:21:59 +08:00
}