diff --git a/src/engine/audio/BUILD.gn b/src/engine/audio/BUILD.gn index 5a73770..6ab1d03 100644 --- a/src/engine/audio/BUILD.gn +++ b/src/engine/audio/BUILD.gn @@ -2,9 +2,9 @@ source_set("audio") { sources = [ "audio_bus.cc", "audio_bus.h", + "audio_device.h", "audio_mixer.cc", "audio_mixer.h", - "audio_sink.h", "mixer_input.cc", "mixer_input.h", "sinc_resampler.cc", @@ -16,16 +16,16 @@ source_set("audio") { if (target_os == "linux") { sources += [ - "audio_sink_alsa.cc", - "audio_sink_alsa.h", + "audio_device_alsa.cc", + "audio_device_alsa.h", ] libs += [ "asound" ] } else if (target_os == "win") { - sources += [ "audio_sink_null.h" ] + sources += [ "audio_device_null.h" ] } else if (target_os == "android") { sources += [ - "audio_sink_oboe.cc", - "audio_sink_oboe.h", + "audio_device_oboe.cc", + "audio_device_oboe.h", ] deps += [ "//src/third_party/oboe" ] } diff --git a/src/engine/audio/audio_device.h b/src/engine/audio/audio_device.h new file mode 100644 index 0000000..f1a09fc --- /dev/null +++ b/src/engine/audio/audio_device.h @@ -0,0 +1,37 @@ +#ifndef ENGINE_AUDIO_AUDIO_DEVICE_H +#define ENGINE_AUDIO_AUDIO_DEVICE_H + +namespace eng { + +// Models an audio device sending mixed audio to the audio driver. Audio data +// from the mixer source is delivered on a pull model using Delegate. +class AudioDevice { + public: + class Delegate { + public: + Delegate() = default; + virtual ~Delegate() = default; + + virtual int GetChannelCount() = 0; + + virtual void RenderAudio(float* output_buffer, size_t num_frames) = 0; + }; + + AudioDevice() = default; + virtual ~AudioDevice() = default; + + virtual bool Initialize() = 0; + + virtual void Suspend() = 0; + virtual void Resume() = 0; + + virtual size_t GetHardwareSampleRate() = 0; + + private: + AudioDevice(const AudioDevice&) = delete; + AudioDevice& operator=(const AudioDevice&) = delete; +}; + +} // namespace eng + +#endif // ENGINE_AUDIO_AUDIO_DEVICE_H diff --git a/src/engine/audio/audio_sink_alsa.cc b/src/engine/audio/audio_device_alsa.cc similarity index 91% rename from src/engine/audio/audio_sink_alsa.cc rename to src/engine/audio/audio_device_alsa.cc index 73fc75a..1b1d104 100644 --- a/src/engine/audio/audio_sink_alsa.cc +++ b/src/engine/audio/audio_device_alsa.cc @@ -1,4 +1,4 @@ -#include "engine/audio/audio_sink_alsa.h" +#include "engine/audio/audio_device_alsa.h" #include @@ -11,10 +11,10 @@ using namespace base; namespace eng { -AudioSinkAlsa::AudioSinkAlsa(AudioSink::Delegate* delegate) +AudioDeviceAlsa::AudioDeviceAlsa(AudioDevice::Delegate* delegate) : delegate_(delegate) {} -AudioSinkAlsa::~AudioSinkAlsa() { +AudioDeviceAlsa::~AudioDeviceAlsa() { LOG(0) << "Shutting down audio."; TerminateAudioThread(); @@ -22,7 +22,7 @@ AudioSinkAlsa::~AudioSinkAlsa() { snd_pcm_close(device_); } -bool AudioSinkAlsa::Initialize() { +bool AudioDeviceAlsa::Initialize() { LOG(0) << "Initializing audio."; int err; @@ -145,28 +145,28 @@ bool AudioSinkAlsa::Initialize() { return false; } -void AudioSinkAlsa::Suspend() { +void AudioDeviceAlsa::Suspend() { suspend_audio_thread_.store(true, std::memory_order_relaxed); } -void AudioSinkAlsa::Resume() { +void AudioDeviceAlsa::Resume() { suspend_audio_thread_.store(false, std::memory_order_relaxed); } -size_t AudioSinkAlsa::GetHardwareSampleRate() { +size_t AudioDeviceAlsa::GetHardwareSampleRate() { return sample_rate_; } -void AudioSinkAlsa::StartAudioThread() { +void AudioDeviceAlsa::StartAudioThread() { DCHECK(!audio_thread_.joinable()); LOG(0) << "Starting audio thread."; terminate_audio_thread_.store(false, std::memory_order_relaxed); suspend_audio_thread_.store(false, std::memory_order_relaxed); - audio_thread_ = std::thread(&AudioSinkAlsa::AudioThreadMain, this); + audio_thread_ = std::thread(&AudioDeviceAlsa::AudioThreadMain, this); } -void AudioSinkAlsa::TerminateAudioThread() { +void AudioDeviceAlsa::TerminateAudioThread() { if (!audio_thread_.joinable()) return; @@ -176,7 +176,7 @@ void AudioSinkAlsa::TerminateAudioThread() { audio_thread_.join(); } -void AudioSinkAlsa::AudioThreadMain() { +void AudioDeviceAlsa::AudioThreadMain() { DCHECK(delegate_); size_t num_frames = period_size_ / (num_channels_ * sizeof(float)); diff --git a/src/engine/audio/audio_sink_alsa.h b/src/engine/audio/audio_device_alsa.h similarity index 64% rename from src/engine/audio/audio_sink_alsa.h rename to src/engine/audio/audio_device_alsa.h index 8d3ca6a..2325bd2 100644 --- a/src/engine/audio/audio_sink_alsa.h +++ b/src/engine/audio/audio_device_alsa.h @@ -1,19 +1,19 @@ -#ifndef ENGINE_AUDIO_AUDIO_SINK_ALSA_H -#define ENGINE_AUDIO_AUDIO_SINK_ALSA_H +#ifndef ENGINE_AUDIO_AUDIO_DEVICE_ALSA_H +#define ENGINE_AUDIO_AUDIO_DEVICE_ALSA_H #include #include -#include "engine/audio/audio_sink.h" +#include "engine/audio/audio_device.h" typedef struct _snd_pcm snd_pcm_t; namespace eng { -class AudioSinkAlsa final : public AudioSink { +class AudioDeviceAlsa final : public AudioDevice { public: - AudioSinkAlsa(AudioSink::Delegate* delegate); - ~AudioSinkAlsa() final; + AudioDeviceAlsa(AudioDevice::Delegate* delegate); + ~AudioDeviceAlsa() final; bool Initialize() final; @@ -34,7 +34,7 @@ class AudioSinkAlsa final : public AudioSink { size_t sample_rate_ = 0; size_t period_size_ = 0; - AudioSink::Delegate* delegate_ = nullptr; + AudioDevice::Delegate* delegate_ = nullptr; void StartAudioThread(); void TerminateAudioThread(); @@ -44,4 +44,4 @@ class AudioSinkAlsa final : public AudioSink { } // namespace eng -#endif // ENGINE_AUDIO_AUDIO_SINK_ALSA_H +#endif // ENGINE_AUDIO_AUDIO_DEVICE_ALSA_H diff --git a/src/engine/audio/audio_device_null.h b/src/engine/audio/audio_device_null.h new file mode 100644 index 0000000..6a5df90 --- /dev/null +++ b/src/engine/audio/audio_device_null.h @@ -0,0 +1,23 @@ +#ifndef ENGINE_AUDIO_AUDIO_DEVICE_NULL_H +#define ENGINE_AUDIO_AUDIO_DEVICE_NULL_H + +#include "engine/audio/audio_device.h" + +namespace eng { + +class AudioDeviceNull final : public AudioDevice { + public: + AudioDeviceNull() = default; + ~AudioDeviceNull() final = default; + + bool Initialize() final { return true; } + + void Suspend() final {} + void Resume() final {} + + size_t GetHardwareSampleRate() final { return 0; } +}; + +} // namespace eng + +#endif // ENGINE_AUDIO_AUDIO_DEVICE_NULL_H diff --git a/src/engine/audio/audio_sink_oboe.cc b/src/engine/audio/audio_device_oboe.cc similarity index 69% rename from src/engine/audio/audio_sink_oboe.cc rename to src/engine/audio/audio_device_oboe.cc index bdb8143..f775e07 100644 --- a/src/engine/audio/audio_sink_oboe.cc +++ b/src/engine/audio/audio_device_oboe.cc @@ -1,4 +1,4 @@ -#include "engine/audio/audio_sink_oboe.h" +#include "engine/audio/audio_device_oboe.h" #include "base/log.h" #include "third_party/oboe/include/oboe/Oboe.h" @@ -7,54 +7,54 @@ using namespace base; namespace eng { -AudioSinkOboe::AudioSinkOboe(AudioSink::Delegate* delegate) +AudioDeviceOboe::AudioDeviceOboe(AudioDevice::Delegate* delegate) : callback_(std::make_unique(this)), delegate_(delegate) {} -AudioSinkOboe::~AudioSinkOboe() { +AudioDeviceOboe::~AudioDeviceOboe() { LOG(0) << "Shutting down audio."; stream_->stop(); } -bool AudioSinkOboe::Initialize() { +bool AudioDeviceOboe::Initialize() { LOG(0) << "Initializing audio."; return RestartStream(); } -void AudioSinkOboe::Suspend() { +void AudioDeviceOboe::Suspend() { stream_->pause(); } -void AudioSinkOboe::Resume() { +void AudioDeviceOboe::Resume() { stream_->start(); } -size_t AudioSinkOboe::GetHardwareSampleRate() { +size_t AudioDeviceOboe::GetHardwareSampleRate() { return stream_->getSampleRate(); } -AudioSinkOboe::StreamCallback::StreamCallback(AudioSinkOboe* audio_sink) - : audio_sink_(audio_sink) {} +AudioDeviceOboe::StreamCallback::StreamCallback(AudioDeviceOboe* audio_device) + : audio_device_(audio_device) {} -AudioSinkOboe::StreamCallback::~StreamCallback() = default; +AudioDeviceOboe::StreamCallback::~StreamCallback() = default; -oboe::DataCallbackResult AudioSinkOboe::StreamCallback::onAudioReady( +oboe::DataCallbackResult AudioDeviceOboe::StreamCallback::onAudioReady( oboe::AudioStream* oboe_stream, void* audio_data, int32_t num_frames) { float* output_buffer = static_cast(audio_data); - audio_sink_->delegate_->RenderAudio(output_buffer, num_frames); + audio_device_->delegate_->RenderAudio(output_buffer, num_frames); return oboe::DataCallbackResult::Continue; } -void AudioSinkOboe::StreamCallback::onErrorAfterClose( +void AudioDeviceOboe::StreamCallback::onErrorAfterClose( oboe::AudioStream* oboe_stream, oboe::Result error) { LOG(0) << "Error after close. Error: " << oboe::convertToText(error); - audio_sink_->RestartStream(); + audio_device_->RestartStream(); } -bool AudioSinkOboe::RestartStream() { +bool AudioDeviceOboe::RestartStream() { oboe::AudioStreamBuilder builder; oboe::Result result = builder.setSharingMode(oboe::SharingMode::Exclusive) diff --git a/src/engine/audio/audio_sink_oboe.h b/src/engine/audio/audio_device_oboe.h similarity index 67% rename from src/engine/audio/audio_sink_oboe.h rename to src/engine/audio/audio_device_oboe.h index c973517..fd01834 100644 --- a/src/engine/audio/audio_sink_oboe.h +++ b/src/engine/audio/audio_device_oboe.h @@ -1,19 +1,19 @@ -#ifndef ENGINE_AUDIO_AUDIO_SINK_OBOE_H -#define ENGINE_AUDIO_AUDIO_SINK_OBOE_H +#ifndef ENGINE_AUDIO_AUDIO_DEVICE_OBOE_H +#define ENGINE_AUDIO_AUDIO_DEVICE_OBOE_H #include #include "third_party/oboe/include/oboe/AudioStream.h" #include "third_party/oboe/include/oboe/AudioStreamCallback.h" -#include "engine/audio/audio_sink.h" +#include "engine/audio/audio_device.h" namespace eng { -class AudioSinkOboe final : public AudioSink { +class AudioDeviceOboe final : public AudioDevice { public: - AudioSinkOboe(AudioSink::Delegate* delegate); - ~AudioSinkOboe() final; + AudioDeviceOboe(AudioDevice::Delegate* delegate); + ~AudioDeviceOboe() final; bool Initialize() final; @@ -25,7 +25,7 @@ class AudioSinkOboe final : public AudioSink { private: class StreamCallback final : public oboe::AudioStreamCallback { public: - StreamCallback(AudioSinkOboe* audio); + StreamCallback(AudioDeviceOboe* audio); ~StreamCallback() final; oboe::DataCallbackResult onAudioReady(oboe::AudioStream* oboe_stream, @@ -36,17 +36,17 @@ class AudioSinkOboe final : public AudioSink { oboe::Result error) final; private: - AudioSinkOboe* audio_sink_; + AudioDeviceOboe* audio_device_; }; oboe::ManagedStream stream_; std::unique_ptr callback_; - AudioSink::Delegate* delegate_ = nullptr; + AudioDevice::Delegate* delegate_ = nullptr; bool RestartStream(); }; } // namespace eng -#endif // ENGINE_AUDIO_AUDIO_SINK_OBOE_H +#endif // ENGINE_AUDIO_AUDIO_DEVICE_OBOE_H diff --git a/src/engine/audio/audio_mixer.cc b/src/engine/audio/audio_mixer.cc index 71e2ba5..1eb82db 100644 --- a/src/engine/audio/audio_mixer.cc +++ b/src/engine/audio/audio_mixer.cc @@ -8,11 +8,11 @@ #include "engine/audio/mixer_input.h" #if defined(__ANDROID__) -#include "engine/audio/audio_sink_oboe.h" +#include "engine/audio/audio_device_oboe.h" #elif defined(__linux__) -#include "engine/audio/audio_sink_alsa.h" +#include "engine/audio/audio_device_alsa.h" #elif defined(_WIN32) -#include "engine/audio/audio_sink_null.h" +#include "engine/audio/audio_device_null.h" #endif using namespace base; @@ -22,19 +22,19 @@ namespace eng { AudioMixer::AudioMixer() : main_thread_task_runner_(TaskRunner::GetThreadLocalTaskRunner()), #if defined(__ANDROID__) - audio_sink_{std::make_unique(this)} { + audio_device_{std::make_unique(this)} { #elif defined(__linux__) - audio_sink_{std::make_unique(this)} { + audio_device_{std::make_unique(this)} { #elif defined(_WIN32) - // TODO: Implement AudioSinkWindows - audio_sink_{std::make_unique()} { + // TODO: Implement AudioDeviceWindows + audio_device_{std::make_unique()} { #endif - bool res = audio_sink_->Initialize(); - CHECK(res) << "Failed to initialize audio sink."; + bool res = audio_device_->Initialize(); + CHECK(res) << "Failed to initialize audio device."; } AudioMixer::~AudioMixer() { - audio_sink_.reset(); + audio_device_.reset(); } void AudioMixer::AddInput(std::shared_ptr mixer_input) { @@ -45,15 +45,15 @@ void AudioMixer::AddInput(std::shared_ptr mixer_input) { } void AudioMixer::Suspend() { - audio_sink_->Suspend(); + audio_device_->Suspend(); } void AudioMixer::Resume() { - audio_sink_->Resume(); + audio_device_->Resume(); } size_t AudioMixer::GetHardwareSampleRate() { - return audio_sink_->GetHardwareSampleRate(); + return audio_device_->GetHardwareSampleRate(); } void AudioMixer::RenderAudio(float* output_buffer, size_t num_frames) { diff --git a/src/engine/audio/audio_mixer.h b/src/engine/audio/audio_mixer.h index a2f424a..0fa7953 100644 --- a/src/engine/audio/audio_mixer.h +++ b/src/engine/audio/audio_mixer.h @@ -6,7 +6,7 @@ #include #include "base/closure.h" -#include "engine/audio/audio_sink.h" +#include "engine/audio/audio_device.h" namespace base { class TaskRunner; @@ -21,9 +21,9 @@ class MixerInput; // when it needs more data. Input source will be removed once end-of-stream is // reached. Any unfilled frames will be filled with silence. The mixer always // outputs audio when active, even if input sources underflow. A platform -// specific AudioSink implementation is expected to periodically call +// specific AudioDevice implementation is expected to periodically call // RenderAudio() in a background thread. -class AudioMixer : public AudioSink::Delegate { +class AudioMixer : public AudioDevice::Delegate { public: AudioMixer(); ~AudioMixer(); @@ -48,11 +48,11 @@ class AudioMixer : public AudioSink::Delegate { std::shared_ptr main_thread_task_runner_; - std::unique_ptr audio_sink_; + std::unique_ptr audio_device_; bool audio_enabled_ = true; - // AudioSink::Delegate interface + // AudioDevice::Delegate interface int GetChannelCount() final { return kChannelCount; } void RenderAudio(float* output_buffer, size_t num_frames) final; diff --git a/src/engine/audio/audio_sink.h b/src/engine/audio/audio_sink.h deleted file mode 100644 index 5f48aa3..0000000 --- a/src/engine/audio/audio_sink.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef ENGINE_AUDIO_AUDIO_SINK_H -#define ENGINE_AUDIO_AUDIO_SINK_H - -namespace eng { - -// Models an audio sink sending mixed audio to the audio driver. Audio data from -// the mixer source is delivered on a pull model using Delegate. -class AudioSink { - public: - class Delegate { - public: - Delegate() = default; - virtual ~Delegate() = default; - - virtual int GetChannelCount() = 0; - - virtual void RenderAudio(float* output_buffer, size_t num_frames) = 0; - }; - - AudioSink() = default; - virtual ~AudioSink() = default; - - virtual bool Initialize() = 0; - - virtual void Suspend() = 0; - virtual void Resume() = 0; - - virtual size_t GetHardwareSampleRate() = 0; - - private: - AudioSink(const AudioSink&) = delete; - AudioSink& operator=(const AudioSink&) = delete; -}; - -} // namespace eng - -#endif // ENGINE_AUDIO_AUDIO_SINK_H diff --git a/src/engine/audio/audio_sink_null.h b/src/engine/audio/audio_sink_null.h deleted file mode 100644 index d8c2055..0000000 --- a/src/engine/audio/audio_sink_null.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef ENGINE_AUDIO_AUDIO_SINK_NULL_H -#define ENGINE_AUDIO_AUDIO_SINK_NULL_H - -#include "engine/audio/audio_sink.h" - -namespace eng { - -class AudioSinkNull final : public AudioSink { - public: - AudioSinkNull() = default; - ~AudioSinkNull() final = default; - - bool Initialize() final { return true; } - - void Suspend() final {} - void Resume() final {} - - size_t GetHardwareSampleRate() final { return 0; } -}; - -} // namespace eng - -#endif // ENGINE_AUDIO_AUDIO_SINK_NULL_H diff --git a/src/engine/audio/mixer_input.h b/src/engine/audio/mixer_input.h index 22b7a6a..dee38b5 100644 --- a/src/engine/audio/mixer_input.h +++ b/src/engine/audio/mixer_input.h @@ -11,8 +11,8 @@ namespace eng { class AudioBus; class AudioMixer; -// An audio input stream that gets mixed and rendered to the audio sink. Handles -// playback and volume control. +// An audio input stream that gets mixed and rendered to the audio device. +// Handles playback and volume control. class MixerInput : public std::enable_shared_from_this { public: enum Flags { kLoop = 1, kStopped = 2, kSimulateStereo = 4 };