mirror of https://github.com/auygun/kaliber.git
Move AudioDriver ownership to AudioMixer
This commit is contained in:
parent
b160ae0bd3
commit
8d28d85a09
|
@ -1,12 +1,8 @@
|
|||
#ifndef ENGINE_AUDIO_AUDIO_DRIVER_H
|
||||
#define ENGINE_AUDIO_AUDIO_DRIVER_H
|
||||
|
||||
#include "engine/audio/audio_driver.h"
|
||||
|
||||
namespace eng {
|
||||
|
||||
class AudioDriverDelegate;
|
||||
|
||||
// Models an audio sink sending mixed audio to the audio driver. Audio data from
|
||||
// the mixer source is delivered on a pull model using AudioDriverDelegate.
|
||||
class AudioDriver {
|
||||
|
@ -14,12 +10,8 @@ class AudioDriver {
|
|||
AudioDriver() = default;
|
||||
virtual ~AudioDriver() = default;
|
||||
|
||||
virtual void SetDelegate(AudioDriverDelegate* delegate) = 0;
|
||||
|
||||
virtual bool Initialize() = 0;
|
||||
|
||||
virtual void Shutdown() = 0;
|
||||
|
||||
virtual void Suspend() = 0;
|
||||
virtual void Resume() = 0;
|
||||
|
||||
|
|
|
@ -11,17 +11,19 @@ using namespace base;
|
|||
|
||||
namespace eng {
|
||||
|
||||
AudioDriverAlsa::AudioDriverAlsa() = default;
|
||||
AudioDriverAlsa::AudioDriverAlsa(AudioDriverDelegate* delegate)
|
||||
: delegate_(delegate) {}
|
||||
|
||||
AudioDriverAlsa::~AudioDriverAlsa() = default;
|
||||
AudioDriverAlsa::~AudioDriverAlsa() {
|
||||
LOG << "Shutting down audio.";
|
||||
|
||||
void AudioDriverAlsa::SetDelegate(AudioDriverDelegate* delegate) {
|
||||
delegate_ = delegate;
|
||||
Resume();
|
||||
TerminateAudioThread();
|
||||
snd_pcm_drop(device_);
|
||||
snd_pcm_close(device_);
|
||||
}
|
||||
|
||||
bool AudioDriverAlsa::Initialize() {
|
||||
LOG << "Initializing audio system.";
|
||||
LOG << "Initializing audio.";
|
||||
|
||||
int err;
|
||||
|
||||
|
@ -142,13 +144,6 @@ bool AudioDriverAlsa::Initialize() {
|
|||
return false;
|
||||
}
|
||||
|
||||
void AudioDriverAlsa::Shutdown() {
|
||||
LOG << "Shutting down audio system.";
|
||||
TerminateAudioThread();
|
||||
snd_pcm_drop(device_);
|
||||
snd_pcm_close(device_);
|
||||
}
|
||||
|
||||
void AudioDriverAlsa::Suspend() {
|
||||
suspend_audio_thread_.store(true, std::memory_order_relaxed);
|
||||
}
|
||||
|
@ -162,15 +157,16 @@ int AudioDriverAlsa::GetHardwareSampleRate() {
|
|||
}
|
||||
|
||||
void AudioDriverAlsa::StartAudioThread() {
|
||||
DCHECK(!audio_thread_.joinable());
|
||||
|
||||
LOG << "Starting audio thread.";
|
||||
terminate_audio_thread_.store(false, std::memory_order_relaxed);
|
||||
suspend_audio_thread_.store(delegate_ ? false : true,
|
||||
std::memory_order_relaxed);
|
||||
suspend_audio_thread_.store(false, std::memory_order_relaxed);
|
||||
audio_thread_ = std::thread(&AudioDriverAlsa::AudioThreadMain, this);
|
||||
}
|
||||
|
||||
void AudioDriverAlsa::TerminateAudioThread() {
|
||||
if (terminate_audio_thread_.load(std::memory_order_relaxed))
|
||||
if (!audio_thread_.joinable())
|
||||
return;
|
||||
|
||||
LOG << "Terminating audio thread";
|
||||
|
@ -180,6 +176,8 @@ void AudioDriverAlsa::TerminateAudioThread() {
|
|||
}
|
||||
|
||||
void AudioDriverAlsa::AudioThreadMain() {
|
||||
DCHECK(delegate_);
|
||||
|
||||
size_t num_frames = period_size_ / (num_channels_ * sizeof(float));
|
||||
auto buffer = std::make_unique<float[]>(num_frames * 2);
|
||||
|
||||
|
|
|
@ -10,17 +10,15 @@ typedef struct _snd_pcm snd_pcm_t;
|
|||
|
||||
namespace eng {
|
||||
|
||||
class AudioDriverDelegate;
|
||||
|
||||
class AudioDriverAlsa final : public AudioDriver {
|
||||
public:
|
||||
AudioDriverAlsa();
|
||||
AudioDriverAlsa(AudioDriverDelegate* delegate);
|
||||
~AudioDriverAlsa() final;
|
||||
|
||||
void SetDelegate(AudioDriverDelegate* delegate) final;
|
||||
|
||||
bool Initialize() final;
|
||||
|
||||
void Shutdown() final;
|
||||
|
||||
void Suspend() final;
|
||||
void Resume() final;
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ class AudioDriverDelegate {
|
|||
AudioDriverDelegate() = default;
|
||||
virtual ~AudioDriverDelegate() = default;
|
||||
|
||||
virtual int GetChannelCount() = 0;
|
||||
|
||||
virtual void RenderAudio(float* output_buffer, size_t num_frames) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,28 +8,19 @@ using namespace base;
|
|||
|
||||
namespace eng {
|
||||
|
||||
AudioDriverOboe::AudioDriverOboe()
|
||||
: callback_(std::make_unique<StreamCallback>(this)) {}
|
||||
AudioDriverOboe::AudioDriverOboe(AudioDriverDelegate* delegate)
|
||||
: callback_(std::make_unique<StreamCallback>(this)), delegate_(delegate) {}
|
||||
|
||||
AudioDriverOboe::~AudioDriverOboe() = default;
|
||||
|
||||
void AudioDriverOboe::SetDelegate(AudioDriverDelegate* delegate) {
|
||||
delegate_ = delegate;
|
||||
stream_->start();
|
||||
AudioDriverOboe::~AudioDriverOboe() {
|
||||
LOG << "Shutting down audio.";
|
||||
stream_->stop();
|
||||
}
|
||||
|
||||
bool AudioDriverOboe::Initialize() {
|
||||
LOG << "Initializing audio system.";
|
||||
|
||||
LOG << "Initializing audio.";
|
||||
return RestartStream();
|
||||
}
|
||||
|
||||
void AudioDriverOboe::Shutdown() {
|
||||
LOG << "Shutting down audio system.";
|
||||
|
||||
stream_->stop();
|
||||
}
|
||||
|
||||
void AudioDriverOboe::Suspend() {
|
||||
stream_->pause();
|
||||
}
|
||||
|
@ -70,7 +61,7 @@ bool AudioDriverOboe::RestartStream() {
|
|||
builder.setSharingMode(oboe::SharingMode::Exclusive)
|
||||
->setPerformanceMode(oboe::PerformanceMode::LowLatency)
|
||||
->setFormat(oboe::AudioFormat::Float)
|
||||
->setChannelCount(kChannelCount)
|
||||
->setChannelCount(delegate_->GetChannelCount())
|
||||
->setDirection(oboe::Direction::Output)
|
||||
->setUsage(oboe::Usage::Game)
|
||||
->setCallback(callback_.get())
|
||||
|
@ -88,8 +79,7 @@ bool AudioDriverOboe::RestartStream() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (delegate_)
|
||||
stream_->start();
|
||||
stream_->start();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,25 +10,21 @@
|
|||
|
||||
namespace eng {
|
||||
|
||||
class AudioDriverDelegate;
|
||||
|
||||
class AudioDriverOboe final : public AudioDriver {
|
||||
public:
|
||||
AudioDriverOboe();
|
||||
AudioDriverOboe(AudioDriverDelegate* delegate);
|
||||
~AudioDriverOboe() final;
|
||||
|
||||
void SetDelegate(AudioDriverDelegate* delegate) final;
|
||||
|
||||
bool Initialize() final;
|
||||
|
||||
void Shutdown() final;
|
||||
|
||||
void Suspend() final;
|
||||
void Resume() final;
|
||||
|
||||
int GetHardwareSampleRate() final;
|
||||
|
||||
private:
|
||||
static constexpr int kChannelCount = 2;
|
||||
|
||||
class StreamCallback final : public oboe::AudioStreamCallback {
|
||||
public:
|
||||
StreamCallback(AudioDriverOboe* audio);
|
||||
|
|
|
@ -7,12 +7,26 @@
|
|||
#include "base/thread_pool.h"
|
||||
#include "engine/sound.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "engine/audio/audio_driver_oboe.h"
|
||||
#elif defined(__linux__)
|
||||
#include "engine/audio/audio_driver_alsa.h"
|
||||
#endif
|
||||
|
||||
using namespace base;
|
||||
|
||||
namespace eng {
|
||||
|
||||
AudioMixer::AudioMixer()
|
||||
: main_thread_task_runner_(TaskRunner::GetThreadLocalTaskRunner()) {}
|
||||
: main_thread_task_runner_(TaskRunner::GetThreadLocalTaskRunner()),
|
||||
#if defined(__ANDROID__)
|
||||
audio_driver_{std::make_unique<AudioDriverOboe>(this)} {
|
||||
#elif defined(__linux__)
|
||||
audio_driver_{std::make_unique<AudioDriverAlsa>(this)} {
|
||||
#endif
|
||||
bool res = audio_driver_->Initialize();
|
||||
CHECK(res) << "Failed to initialize audio driver.";
|
||||
}
|
||||
|
||||
AudioMixer::~AudioMixer() = default;
|
||||
|
||||
|
@ -139,6 +153,18 @@ void AudioMixer::SetEndCallback(uint64_t resource_id, base::Closure cb) {
|
|||
it->second->end_cb = std::move(cb);
|
||||
}
|
||||
|
||||
void AudioMixer::Suspend() {
|
||||
audio_driver_->Suspend();
|
||||
}
|
||||
|
||||
void AudioMixer::Resume() {
|
||||
audio_driver_->Resume();
|
||||
}
|
||||
|
||||
int AudioMixer::GetHardwareSampleRate() {
|
||||
return audio_driver_->GetHardwareSampleRate();
|
||||
}
|
||||
|
||||
void AudioMixer::RenderAudio(float* output_buffer, size_t num_frames) {
|
||||
{
|
||||
std::unique_lock<std::mutex> scoped_lock(lock_, std::try_to_lock);
|
||||
|
|
|
@ -16,10 +16,11 @@ class TaskRunner;
|
|||
|
||||
namespace eng {
|
||||
|
||||
class AudioDriver;
|
||||
class Sound;
|
||||
|
||||
// Mix and render audio with low overhead. A platform specific AudioDriver
|
||||
// implementation is expected to periodically call Render() in a background
|
||||
// implementation is expected to periodically call RenderAudio() in a background
|
||||
// thread.
|
||||
class AudioMixer : public AudioDriverDelegate {
|
||||
public:
|
||||
|
@ -44,6 +45,11 @@ class AudioMixer : public AudioDriverDelegate {
|
|||
|
||||
void SetEnableAudio(bool enable) { audio_enabled_ = enable; }
|
||||
|
||||
void Suspend();
|
||||
void Resume();
|
||||
|
||||
int GetHardwareSampleRate();
|
||||
|
||||
private:
|
||||
enum SampleFlags { kLoop = 1, kStopped = 2, kSimulateStereo = 4 };
|
||||
static constexpr int kChannelCount = 2;
|
||||
|
@ -80,9 +86,12 @@ class AudioMixer : public AudioDriverDelegate {
|
|||
|
||||
base::TaskRunner* main_thread_task_runner_;
|
||||
|
||||
std::unique_ptr<AudioDriver> audio_driver_;
|
||||
|
||||
bool audio_enabled_ = true;
|
||||
|
||||
// AudioDriverDelegate implementation
|
||||
int GetChannelCount() final { return kChannelCount; }
|
||||
void RenderAudio(float* output_buffer, size_t num_frames) final;
|
||||
|
||||
void DoStream(std::shared_ptr<Resource> sample, bool loop);
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
#include "base/log.h"
|
||||
#include "engine/animator.h"
|
||||
#include "engine/audio/audio_driver.h"
|
||||
#include "engine/audio/audio_mixer.h"
|
||||
#include "engine/drawable.h"
|
||||
#include "engine/font.h"
|
||||
|
@ -26,17 +25,13 @@ namespace eng {
|
|||
|
||||
Engine* Engine::singleton = nullptr;
|
||||
|
||||
Engine::Engine(Platform* platform,
|
||||
Renderer* renderer,
|
||||
AudioDriver* audio_driver)
|
||||
Engine::Engine(Platform* platform, Renderer* renderer)
|
||||
: platform_(platform),
|
||||
renderer_(renderer),
|
||||
audio_driver_(audio_driver),
|
||||
audio_mixer_{std::make_unique<AudioMixer>()} {
|
||||
DCHECK(!singleton);
|
||||
singleton = this;
|
||||
|
||||
audio_driver_->SetDelegate(audio_mixer_.get());
|
||||
renderer_->SetContextLostCB(std::bind(&Engine::ContextLost, this));
|
||||
|
||||
quad_ = CreateRenderResource<Geometry>();
|
||||
|
@ -143,14 +138,14 @@ void Engine::Draw(float frame_frac) {
|
|||
}
|
||||
|
||||
void Engine::LostFocus() {
|
||||
audio_driver_->Suspend();
|
||||
audio_mixer_->Suspend();
|
||||
|
||||
if (game_)
|
||||
game_->LostFocus();
|
||||
}
|
||||
|
||||
void Engine::GainedFocus(bool from_interstitial_ad) {
|
||||
audio_driver_->Resume();
|
||||
audio_mixer_->Resume();
|
||||
|
||||
if (game_)
|
||||
game_->GainedFocus(from_interstitial_ad);
|
||||
|
@ -488,7 +483,7 @@ const std::string& Engine::GetSharedDataPath() const {
|
|||
}
|
||||
|
||||
int Engine::GetAudioHardwareSampleRate() {
|
||||
return audio_driver_->GetHardwareSampleRate();
|
||||
return audio_mixer_->GetHardwareSampleRate();
|
||||
}
|
||||
|
||||
bool Engine::IsMobile() const {
|
||||
|
|
|
@ -16,7 +16,6 @@ class TextureCompressor;
|
|||
namespace eng {
|
||||
|
||||
class Animator;
|
||||
class AudioDriver;
|
||||
class AudioMixer;
|
||||
class Font;
|
||||
class Game;
|
||||
|
@ -34,7 +33,7 @@ class Engine {
|
|||
public:
|
||||
using CreateImageCB = std::function<std::unique_ptr<Image>()>;
|
||||
|
||||
Engine(Platform* platform, Renderer* renderer, AudioDriver* audio_driver);
|
||||
Engine(Platform* platform, Renderer* renderer);
|
||||
~Engine();
|
||||
|
||||
static Engine& Get();
|
||||
|
@ -176,9 +175,9 @@ class Engine {
|
|||
|
||||
Platform* platform_ = nullptr;
|
||||
Renderer* renderer_ = nullptr;
|
||||
AudioDriver* audio_driver_ = nullptr;
|
||||
|
||||
std::unique_ptr<AudioMixer> audio_mixer_;
|
||||
|
||||
std::unique_ptr<Game> game_;
|
||||
|
||||
std::unique_ptr<Geometry> quad_;
|
||||
|
|
|
@ -6,12 +6,6 @@
|
|||
#include "engine/renderer/opengl/renderer_opengl.h"
|
||||
#include "engine/renderer/vulkan/renderer_vulkan.h"
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
#include "engine/audio/audio_driver_oboe.h"
|
||||
#elif defined(__linux__)
|
||||
#include "engine/audio/audio_driver_alsa.h"
|
||||
#endif
|
||||
|
||||
#define USE_VULKAN_RENDERER 1
|
||||
|
||||
using namespace base;
|
||||
|
@ -47,14 +41,6 @@ void Platform::InitializeCommon() {
|
|||
thread_pool_.Initialize();
|
||||
TaskRunner::CreateThreadLocalTaskRunner();
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
audio_driver_ = std::make_unique<AudioDriverOboe>();
|
||||
#elif defined(__linux__)
|
||||
audio_driver_ = std::make_unique<AudioDriverAlsa>();
|
||||
#endif
|
||||
bool res = audio_driver_->Initialize();
|
||||
CHECK(res) << "Failed to initialize audio driver.";
|
||||
|
||||
#if (USE_VULKAN_RENDERER == 1)
|
||||
renderer_ = std::make_unique<RendererVulkan>();
|
||||
#else
|
||||
|
@ -65,13 +51,12 @@ void Platform::InitializeCommon() {
|
|||
void Platform::ShutdownCommon() {
|
||||
LOG << "Shutting down platform.";
|
||||
|
||||
audio_driver_->Shutdown();
|
||||
renderer_->Shutdown();
|
||||
}
|
||||
|
||||
void Platform::RunMainLoop() {
|
||||
engine_ =
|
||||
std::make_unique<Engine>(this, renderer_.get(), audio_driver_.get());
|
||||
std::make_unique<Engine>(this, renderer_.get());
|
||||
bool res = engine_->Initialize();
|
||||
CHECK(res) << "Failed to initialize the engine.";
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ struct ANativeWindow;
|
|||
|
||||
namespace eng {
|
||||
|
||||
class AudioDriver;
|
||||
class Renderer;
|
||||
class Engine;
|
||||
|
||||
|
@ -79,7 +78,6 @@ class Platform {
|
|||
bool has_focus_ = false;
|
||||
bool should_exit_ = false;
|
||||
|
||||
std::unique_ptr<AudioDriver> audio_driver_;
|
||||
std::unique_ptr<Renderer> renderer_;
|
||||
std::unique_ptr<Engine> engine_;
|
||||
|
||||
|
|
Loading…
Reference in New Issue