From dc28bf6e0ff27a287c567b77f3359831347ebac8 Mon Sep 17 00:00:00 2001 From: Nanako <469449812@qq.com> Date: Tue, 27 Feb 2024 16:25:18 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9Esingleton=5Fmanager=E9=87=8A?= =?UTF-8?q?=E6=94=BE=E9=A1=BA=E5=BA=8F=E6=95=B4=E7=90=86,=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9Eaudio=5Fdevice=5Fmanager?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/audio/device/audio_device_manager.cpp | 21 ++++++++++++++++++++ core/audio/device/audio_device_manager.h | 18 +++++++++++++++++ core/audio/device/port_audio_device.cpp | 19 +++++++++++------- core/audio/device/port_audio_device.h | 5 +++-- core/audio/misc/circular_audio_buffer.h | 4 ++-- core/audio/mixer/mixer.cpp | 2 +- core/misc/singleton/singleton_manager.cpp | 23 +++++++++++++++++----- core/misc/singleton/singleton_manager.h | 8 ++++++-- 8 files changed, 81 insertions(+), 19 deletions(-) create mode 100644 core/audio/device/audio_device_manager.cpp create mode 100644 core/audio/device/audio_device_manager.h diff --git a/core/audio/device/audio_device_manager.cpp b/core/audio/device/audio_device_manager.cpp new file mode 100644 index 0000000..626b3f2 --- /dev/null +++ b/core/audio/device/audio_device_manager.cpp @@ -0,0 +1,21 @@ +#include "audio_device_manager.h" + +#include "dummy_audio_device.h" +#include "port_audio_device.h" +#include "audio/mixer/mixer.h" + +void audio_device_manager::init(singleton_initliazer& initliazer) { + singleton_t::init(initliazer); + initliazer.require(); + dummy_audio_device_ = new dummy_audio_device(); + main_audio_device_ = new port_audio_device(); + + main_audio_device_->init(); + dummy_audio_device_->init(); +} + +void audio_device_manager::release() { + singleton_t::release(); + delete dummy_audio_device_; + delete main_audio_device_; +} diff --git a/core/audio/device/audio_device_manager.h b/core/audio/device/audio_device_manager.h new file mode 100644 index 0000000..506c979 --- /dev/null +++ b/core/audio/device/audio_device_manager.h @@ -0,0 +1,18 @@ +#pragma once +#include "misc/singleton/singleton.h" + +class dummy_audio_device; +class port_audio_device; + +class audio_device_manager : public singleton_t { +public: + void init(singleton_initliazer& initliazer) override; + void release() override; + + const char* get_name() override { return "audio_device_manager"; } +private: + port_audio_device* main_audio_device_ = nullptr; + dummy_audio_device* dummy_audio_device_ = nullptr; +}; + +CORE_API inline audio_device_manager g_audio_device_manager; diff --git a/core/audio/device/port_audio_device.cpp b/core/audio/device/port_audio_device.cpp index 1d788a2..568a95a 100644 --- a/core/audio/device/port_audio_device.cpp +++ b/core/audio/device/port_audio_device.cpp @@ -19,7 +19,7 @@ port_audio_device::~port_audio_device() { bool port_audio_device::init() { Pa_Initialize(); try { - open_stream(0, Pa_GetDefaultOutputDevice(), sample_rate(), buffer_size()); + open_stream(-1, Pa_GetDefaultOutputDevice(), sample_rate(), buffer_size()); } catch (const std::exception& e) { spdlog::error("Init failed: {}", e.what()); return false; @@ -36,12 +36,14 @@ void port_audio_device::stop() { Pa_StopStream(stream_); Pa_CloseStream(stream_); stream_ = nullptr; - render_thread_.join(); + while (!render_thread_running_) + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + spdlog::info("port_audio stopped"); } -void port_audio_device::open_stream(uint32_t input_device, uint32_t output_device, double in_sample_rate, uint32_t in_buffer_size) { - PaStreamParameters* input_params = nullptr; - if (input_device > 0) { +void port_audio_device::open_stream(PaDeviceIndex input_device, PaDeviceIndex output_device, double in_sample_rate, uint32_t in_buffer_size) { + const PaStreamParameters* input_params = nullptr; + if (input_device >= 0) { input_params_.device = input_device; input_params_.channelCount = 2; input_params_.sampleFormat = paFloat32 | paNonInterleaved; @@ -79,6 +81,7 @@ int port_audio_device::stream_callback(float** input, float** output, unsigned l bool port_audio_device::on_set_buffer_size(uint32_t in_buffer_size) { stop(); + render_buffer_size_ = in_buffer_size * 4; try { open_stream(input_params_.device, output_params_.device, sample_rate(), in_buffer_size); } catch (const std::exception& e) { @@ -101,8 +104,8 @@ bool port_audio_device::on_set_sample_rate(double in_sample_rate) { void port_audio_device::render_thread() { dummy_track* master = g_mixer.get_master(); - - + render_thread_running_ = true; + spdlog::info("port_audio render thread started"); while (stream_) { const uint32_t frames = buffer_size(); const double rate = sample_rate(); @@ -124,4 +127,6 @@ void port_audio_device::render_thread() { render_buffer_.Push(element, frames); } } + spdlog::info("port_audio render thread stopped"); + render_thread_running_ = false; } diff --git a/core/audio/device/port_audio_device.h b/core/audio/device/port_audio_device.h index 36dc762..a77c5f7 100644 --- a/core/audio/device/port_audio_device.h +++ b/core/audio/device/port_audio_device.h @@ -12,7 +12,7 @@ public: void stop(); - void open_stream(uint32_t input_device, uint32_t output_device, double in_sample_rate, uint32_t in_buffer_size); + void open_stream(PaDeviceIndex input_device, PaDeviceIndex output_device, double in_sample_rate, uint32_t in_buffer_size); int stream_callback(float** input, float** output, unsigned long frame_count, const PaStreamCallbackTimeInfo* time_info, PaStreamCallbackFlags status_flags); protected: @@ -24,7 +24,8 @@ private: void render_thread(); std::thread render_thread_; circular_audio_buffer render_buffer_; - uint32_t render_buffer_size_ = 0; + uint32_t render_buffer_size_ = 2048; + std::atomic_bool render_thread_running_ = false; #pragma endregion PaStreamParameters input_params_ = {}; diff --git a/core/audio/misc/circular_audio_buffer.h b/core/audio/misc/circular_audio_buffer.h index 3fe99de..f3914c3 100644 --- a/core/audio/misc/circular_audio_buffer.h +++ b/core/audio/misc/circular_audio_buffer.h @@ -51,8 +51,8 @@ public: Capacity = InCapacity + 1; ReadCounter = 0; WriteCounter = 0; - InternalBuffer.Reset(); - InternalBuffer.AddZeroed(Capacity); + InternalBuffer.clear(); + InternalBuffer.resize(Capacity); } /** Reserve capacity. diff --git a/core/audio/mixer/mixer.cpp b/core/audio/mixer/mixer.cpp index c7ab8ce..68d4d7f 100644 --- a/core/audio/mixer/mixer.cpp +++ b/core/audio/mixer/mixer.cpp @@ -73,7 +73,7 @@ void mixer::init(singleton_initliazer& initliazer) { void mixer::release() { singleton_t::release(); - for (mixer_track* const track: tracks_) { + for (const mixer_track* track : tracks_) { delete track; } delete zero_track; diff --git a/core/misc/singleton/singleton_manager.cpp b/core/misc/singleton/singleton_manager.cpp index 7e52b60..49b1545 100644 --- a/core/misc/singleton/singleton_manager.cpp +++ b/core/misc/singleton/singleton_manager.cpp @@ -2,26 +2,39 @@ #include "singleton.h" +bool singleton_initliazer::has_init(singleton* s) { + return std::ranges::find(singletons_, s) != singletons_.end(); +} + +void singleton_initliazer::init_singleton(singleton* s) { + if (!has_init(s)) { + singletons_.push_back(s); + s->init(*this); + } +} + void singleton_manager::add(singleton* s) { singletons_.push_back(s); } -void singleton_manager::init() const { +void singleton_manager::init() { singleton_initliazer initliazer; for (const auto s : singletons_) { - s->init(initliazer); - initliazer.singletons_.push_back(s); + initliazer.init_singleton(s); } for (const auto s : singletons_) { s->post_init(); } + singletons_ = initliazer.singletons_; } void singleton_manager::release() const { - for (const auto s : singletons_) { + for (int32_t j = singletons_.size() - 1; j >= 0; --j) { + auto s = singletons_[j]; s->begin_release(); } - for (const auto s : singletons_) { + for (int32_t j = singletons_.size() - 1; j >= 0; --j) { + auto s = singletons_[j]; s->release(); } } diff --git a/core/misc/singleton/singleton_manager.h b/core/misc/singleton/singleton_manager.h index d7c19df..425794d 100644 --- a/core/misc/singleton/singleton_manager.h +++ b/core/misc/singleton/singleton_manager.h @@ -4,10 +4,14 @@ class singleton; class singleton_initliazer { public: + bool has_init(singleton* s); + + void init_singleton(singleton* s); + template T* require() { auto instance = T::get(); - if (std::find(singletons_.begin(), singletons_.end(), instance) != singletons_.end()) { + if (has_init(instance)) { return instance; } singletons_.push_back(instance); @@ -27,7 +31,7 @@ public: void add(singleton* s); - void init() const; + void init(); void release() const; private: