新增query_timer用于查看函数执行时间

修复circular_audio_buffer编译错误
临时将taskflow移除,因为在执行任务时等待时间很长
This commit is contained in:
Nanako 2024-05-21 01:36:43 +08:00
parent cc44f2bbae
commit b493dc1e0f
9 changed files with 117 additions and 46 deletions

View File

@ -1,5 +1,6 @@
#include "application.h"
#include "audio/device/audio_device_manager.h"
#include "misc/singleton/singleton_manager.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/daily_file_sink.h"
@ -31,6 +32,9 @@ void application::init() {
spdlog::set_default_logger(logger);
singleton_manager::get()->init();
get_audio_device_manager()->start();
}
void application::shutdown() {

View File

@ -7,30 +7,32 @@
#include "spdlog/spdlog.h"
#include "thread_message/thread_message_hubs.h"
int rt_audio_callback(void *output_buffer, void *input_buffer,
int rt_audio_callback(void* output_buffer, void *input_buffer,
unsigned int frames_nums,
double stream_time,
RtAudioStreamStatus status,
void* user_data)
{
auto* API = static_cast<audio_device_manager*>(user_data);
return API->stream_callback((float**)output_buffer, static_cast<float**>(input_buffer), frames_nums, stream_time, status);
return API->stream_callback(static_cast<float*>(output_buffer), static_cast<float*>(input_buffer), frames_nums, stream_time, status);
}
void audio_device_manager::init(singleton_initliazer& initliazer) {
singleton_t<audio_device_manager>::init(initliazer);
options_.flags = RTAUDIO_NONINTERLEAVED;
audio_ = new RtAudio();
log_all_devices();
output_params_.deviceId = audio_->getDefaultOutputDevice();
// output_params_.deviceId = audio_->getDefaultOutputDevice();
output_params_.deviceId = 131;
output_params_.nChannels = get_output_channel_count();
spdlog::info("using output device id: {}", output_params_.deviceId);
output_params_.firstChannel = 0;
buffer_size_ = 512;
}
void audio_device_manager::release(singleton_release_guard& release_guard) {
singleton_t<audio_device_manager>::release(release_guard);
release_guard.require_release<mixer>();
audio_->stopStream();
stop_render_thread();
delete audio_;
}
@ -39,7 +41,22 @@ void audio_device_manager::start() {
if (input_params_.deviceId != 0) {
input_params = &input_params_;
}
audio_->openStream(&output_params_, input_params, RTAUDIO_FLOAT32, get_sample_rate(), &options_.numberOfBuffers, &rt_audio_callback, this, &options_);
log_current_device_info();
options_.flags = RTAUDIO_NONINTERLEAVED;
auto err = audio_->openStream(&output_params_, input_params, RTAUDIO_FLOAT32, get_sample_rate(), &buffer_size_, &rt_audio_callback, this, &options_);
if (err != RTAUDIO_NO_ERROR) {
spdlog::error("failed to open audio stream: {}", audio_->getErrorText());
return;
}
err = audio_->startStream();
if (err != RTAUDIO_NO_ERROR) {
spdlog::error("failed to start audio stream: {}", audio_->getErrorText());
return;
}
spdlog::info("audio stream opened");
start_render_thread();
}
uint32_t audio_device_manager::get_sample_rate() const {
@ -51,11 +68,11 @@ void audio_device_manager::set_sample_rate(uint32_t sample_rate) {
}
uint32_t audio_device_manager::get_buffer_size() const {
return options_.numberOfBuffers;
return buffer_size_;
}
void audio_device_manager::set_buffer_size(int buffer_size) {
options_.numberOfBuffers = buffer_size;
buffer_size_ = buffer_size;
}
uint32_t audio_device_manager::get_input_channel_count() const {
@ -66,12 +83,14 @@ uint32_t audio_device_manager::get_output_channel_count() const {
return 2; // 现在是固定值, 以后可能会改
}
int audio_device_manager::stream_callback(float** output, float** input, unsigned long frame_count, double stream_time,
RtAudioStreamStatus status) {
if (render_buffer_.Num() < frame_count * output_params_.nChannels)
int audio_device_manager::stream_callback(float* output, float* input, unsigned long frame_count, double stream_time, RtAudioStreamStatus status) {
if (render_buffers_[0].Num() < frame_count) {
// spdlog::warn("render buffer underflow: {}", render_buffers_[0].Num());
return 0;
}
for (int i = 0; i < output_params_.nChannels; ++i) {
render_buffer_.Pop(input[i], frame_count);
render_buffers_[i].Pop(output, frame_count);
output += frame_count;
}
return 0;
}
@ -84,6 +103,16 @@ void audio_device_manager::log_all_devices() {
}
}
void audio_device_manager::log_current_device_info() {
spdlog::info("using output device: {}", audio_->getDeviceInfo(output_params_.deviceId).name);
spdlog::info("using input device: {}",
input_params_.deviceId == 0 ? "none" : audio_->getDeviceInfo(input_params_.deviceId).name);
spdlog::info("using sample rate: {}", get_sample_rate());
spdlog::info("using buffer size: {}", get_buffer_size());
spdlog::info("using output channel count: {}", get_output_channel_count());
spdlog::info("using input channel count: {}", get_input_channel_count());
}
void audio_device_manager::start_render_thread() {
render_thread_ = std::thread(&audio_device_manager::render_thread, this);
render_thread_.detach();
@ -98,16 +127,21 @@ void audio_device_manager::render_thread() {
dummy_track* master = g_mixer.get_master();
spdlog::info("port_audio render thread started");
render_buffer_.SetCapacity(get_buffer_size() * 4);
render_buffers_.resize(get_output_channel_count());
const uint32_t frames = get_buffer_size();
const uint32_t rate = get_sample_rate();
for (auto& render_buffer : render_buffers_)
render_buffer.SetCapacity(frames * 3);
while (audio_->isStreamRunning()) {
const uint32_t milliseconds = 1.f / (rate / (frames / 4)) * 1000;
// const float milliseconds = 1.f / (rate / (frames / 4)) * 1e4;
g_audio_thread_hub.process_messages();
if (render_buffer_.Num() >= render_buffer_size_) {
std::this_thread::sleep_for(std::chrono::milliseconds(milliseconds));
if (render_buffers_[0].Remainder() < frames) {
// std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<uint64_t>(milliseconds)));
std::this_thread::yield();
continue;
}
g_midi_sequencer.process(rate, frames);
@ -116,8 +150,9 @@ void audio_device_manager::render_thread() {
g_mixer.process(frames);
const auto& master_headers = master->buffer.get_headers_vector();
for (const auto element: master_headers) {
render_buffer_.Push(element, frames);
for (int i = 0; i < master_headers.size(); ++i) {
const auto element = master_headers[i];
render_buffers_[i].Push(element, frames);
}
}
spdlog::info("port_audio render thread stopped");

View File

@ -20,23 +20,24 @@ public:
[[nodiscard]] CORE_API uint32_t get_input_channel_count() const;
[[nodiscard]] CORE_API uint32_t get_output_channel_count() const;
int stream_callback(float** output, float** input, unsigned long frame_count, double stream_time, RtAudioStreamStatus status);
int stream_callback(float* output, float* input, unsigned long frame_count, double stream_time, RtAudioStreamStatus status);
void log_all_devices();
void log_current_device_info();
protected:
#pragma region render_thread
void start_render_thread();
void stop_render_thread();
void render_thread();
std::thread render_thread_;
circular_audio_buffer<float> render_buffer_;
uint32_t render_buffer_size_ = 512;
std::vector<circular_audio_buffer<float>> render_buffers_;
std::atomic_bool render_thread_running_ = false;
#pragma endregion
private:
RtAudio::StreamParameters input_params_ = {};
RtAudio::StreamParameters output_params_ = {};
RtAudio::StreamOptions options_ = {};
uint32_t sample_rate_ = 44100;
uint32_t sample_rate_ = 48000;
uint32_t buffer_size_ = 2048;
RtAudio* audio_ = nullptr;
};

View File

@ -122,8 +122,8 @@ public:
int32_t NumToZeroEnd = std::min<int32_t>(NumSamplesOfZeros, Remainder());
const int32_t NumToZeroBegin = std::min<int32_t>(NumToZeroEnd, Capacity - WriteIndex);
memzero(&DestBuffer[WriteIndex], NumToZeroBegin * sizeof(SampleType));
memzero(&DestBuffer[0], (NumToZeroEnd - NumToZeroBegin) * sizeof(SampleType));
memset(&DestBuffer[WriteIndex], 0, NumToZeroBegin * sizeof(SampleType));
memset(&DestBuffer[0], 0, (NumToZeroEnd - NumToZeroBegin) * sizeof(SampleType));
WriteCounter = (WriteIndex + NumToZeroEnd) % Capacity;

View File

@ -6,8 +6,8 @@
#include "audio/device/audio_device_manager.h"
#include "audio/plugin_host/plugin_host.h"
#include "audio/plugin_host/plugin_host_manager.h"
#include "misc/query_timer.h"
#include "thread_message/thread_message_hubs.h"
#include "taskflow/taskflow.hpp"
void build_effect_channel_interface(mixer_track* track, const channel_interface* in_interface, std::map<mixer_track*, int32_t>& processed_tracks) {
int32_t& track_current_layer = processed_tracks[track];
@ -68,8 +68,6 @@ void mixer::init(singleton_initliazer& initliazer) {
master->rename("master");
master->init();
tracks_.push_back(master);
device_manager->start();
}
void mixer::release(singleton_release_guard& release_guard) {
@ -121,27 +119,34 @@ void mixer::remove_track(mixer_track* track) {
}
void mixer::process(uint32_t in_frames) {
tf::Executor executor;
tf::Taskflow taskflow;
{
query_timer timer("mixer process");
// tf::Executor executor;
// tf::Taskflow taskflow;
tf::Task previous_task = taskflow.emplace([] {});
for (const auto& order: layer_order_) {
for (const auto& layer = layer_tracks_[order]; const auto& track: layer) {
taskflow.emplace([track, in_frames] {
track->process(in_frames);
}).succeed(previous_task);
// tf::Task previous_task = taskflow.emplace([] {});
for (const auto& order: layer_order_) {
for (const auto& layer = layer_tracks_[order]; const auto& track: layer) {
// taskflow.emplace([track, in_frames] {
track->process(in_frames);
// }).succeed(previous_task);
}
// tf::Task new_layer = taskflow.emplace([] {});
// new_layer.succeed(previous_task);
// previous_task = new_layer;
}
tf::Task new_layer = taskflow.emplace([] {});
new_layer.succeed(previous_task);
previous_task = new_layer;
// executor.run(taskflow).wait();
}
{
query_timer timer("mixer post process");
post_process(in_frames);
}
executor.run(taskflow).wait();
post_process(in_frames);
dummy_track* master = get_master();
master->buffer.multiple(master->volume);
}
void mixer::reset() {
query_timer timer("mixer reset");
for (const auto track: tracks_) {
track->buffer.clear();
}

View File

@ -4,6 +4,7 @@
#include <map>
#include <string>
#include "taskflow/taskflow.hpp"
class plugin_host;
class channel_interface;

View File

@ -7,6 +7,7 @@
#include "audio/mixer/channel_interface.h"
#include "audio/mixer/mixer.h"
#include "audio/mixer/mixer_track.h"
#include "misc/query_timer.h"
#include "misc/singleton/singleton_manager.h"
#include "thread_message/thread_message_hubs.h"
#include "vst2/vst2_plugin_host.h"
@ -81,14 +82,15 @@ void plugin_host_manager::register_instrument_plugin(plugin_host* host) {
}
void plugin_host_manager::process(uint32_t in_frames) const {
tf::Executor executor;
tf::Taskflow taskflow;
query_timer timer("host process");
// tf::Executor executor;
// tf::Taskflow taskflow;
for (auto host : plugin_hosts_) {
taskflow.emplace([host, in_frames] {
// taskflow.emplace([host, in_frames] {
host->process(in_frames);
});
// });
}
executor.run(taskflow).wait();
// executor.run(taskflow).wait();
}
void plugin_host_manager::on_mixer_track_removed(mixer_track* track) {

23
core/misc/query_timer.h Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <chrono>
#include "spdlog/spdlog.h"
class query_timer {
public:
query_timer(std::string name) : name_(std::move(name)) {
start();
}
~query_timer() {
const auto end = std::chrono::high_resolution_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start_);
spdlog::info("{}: {} ms", name_, duration.count() / 1000.f);
}
private:
void start() {
start_ = std::chrono::high_resolution_clock::now();
}
std::chrono::high_resolution_clock::time_point start_;
std::string name_;
};

View File

@ -72,7 +72,7 @@ void window_manager::destroy_plugin_window(plugin_host* host) {
}
void window_manager::update() {
glfwPollEvents();
// glfwPollEvents();
for (auto& info : host_infos_) {
if (!info.second.window) {
continue;