Move AudioDriver ownership to AudioMixer

This commit is contained in:
Attila Uygun 2023-05-23 01:38:31 +02:00
parent b160ae0bd3
commit 8d28d85a09
12 changed files with 74 additions and 86 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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 {

View File

@ -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_;

View File

@ -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.";

View File

@ -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_;