#include "mixer.h" #include "channel_interface.h" #include "channel_node.h" #include "mixer_track.h" #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" IMPL_SINGLETON_INSTANCE(mixer) void build_effect_channel_interface(mixer_track* track, const channel_interface* in_interface, std::unordered_map& processed_tracks) { int32_t& track_current_layer = processed_tracks[track]; auto& input_channel_nodes = in_interface->input_channel_nodes; auto& output_channel_nodes = in_interface->output_channel_nodes; // 如果这个效果器需要从其他轨道输入,那么目标轨道的深度就是这个轨道的深度+1 for (int i = 1; i < input_channel_nodes.size(); ++i) { channel_node* node = input_channel_nodes[i]; if (node->type != channel_node_type::mixer) continue; const mixer_channel_node* mixer_node = static_cast(node); auto* InputTrack = mixer_node->get_track(); int32_t& target_mixer_current_layer = processed_tracks[InputTrack]; target_mixer_current_layer = std::max(target_mixer_current_layer + 1, track_current_layer + 1); } // 如果这个效果器需要输出到其他轨道,那么这个轨道的深度就是目标轨道的深度+1 for (int i = 1; i < output_channel_nodes.size(); ++i) { auto* node = output_channel_nodes[i]; if (node->type != channel_node_type::mixer) continue; const auto* MixerChannelNode = static_cast(node); auto* MixerTrack = MixerChannelNode->get_track(); const int32_t& TargetMixerCurrentLayer = processed_tracks[MixerTrack]; track_current_layer = std::max(track_current_layer, TargetMixerCurrentLayer + 1); } } int32_t build_process_node_internal(mixer_track* track, std::unordered_map& processed_tracks, int32_t layer) { int32_t& track_current_layer = processed_tracks[track]; track_current_layer = std::max(track_current_layer, layer); for (const mixer_track_link& child_link: track->children) { mixer_track* ChildTrack = child_link.track; build_process_node_internal(ChildTrack, processed_tracks, layer + 1); for (const plugin_host* effect: ChildTrack->effects) { build_effect_channel_interface(ChildTrack, effect->channel, processed_tracks); } } return ++layer; } void build_instrument_process_node(const plugin_host* host, std::unordered_map& processed_tracks) { for (mixer_track* Track : host->owner_tracks) { build_effect_channel_interface(Track, host->channel, processed_tracks); } } void mixer::init(singleton_initliazer& initliazer) { singleton_t::init(initliazer); null_channel_node::init(); executor_.exchange(new tf::Executor(std::thread::hardware_concurrency())); auto device_manager = initliazer.require(); zero_track = new dummy_track(); zero_track->rename("zero"); zero_track->init(); const auto master = new dummy_track(); master->rename("master"); master->init(); tracks_.push_back(master); } void mixer::begin_release(singleton_release_guard &release_guard) { singleton::begin_release(release_guard); auto e = executor_.exchange(nullptr); if (e) e->wait_for_all(); delete e; } void mixer::release(singleton_release_guard& release_guard) { singleton_t::release(release_guard); release_guard.require_release(); null_channel_node::destroy(); for (const mixer_track* track : tracks_) { delete track; } tracks_.clear(); delete zero_track; zero_track = nullptr; } dummy_track* mixer::create_dummy_track(const std::string& in_name) { auto* track = new dummy_track(); track->rename(in_name); track->init(); mixer_track_link link{}; link.track = track; link.send_level = 1.0f; get_master()->children.push_back(link); g_audio_thread_hub.push_message([track, this]() { thread_register_track(track); }); return track; } instrument_track* mixer::create_instrument_track(plugin_host* in_instrument) { auto* track = new instrument_track(in_instrument); track->rename(in_instrument->name); track->init(); mixer_track_link link{}; link.track = track; link.send_level = 1.0f; get_master()->children.push_back(link); // register track g_audio_thread_hub.push_message([track, this] { thread_register_track(track); }); return track; } void mixer::remove_track(mixer_track* track) { g_audio_thread_hub.push_message([track, this] { thread_remove_track(track); }); } void mixer::process(uint32_t in_frames) { auto e = executor_.load(); if (!e) return; for (auto& flow: taskflow_) { e->run(flow).wait(); } } void mixer::reset() { for (const auto track: tracks_) { track->buffer.clear(); } } void mixer::request_build_process_node() { g_audio_thread_hub.push_message([this] { update_tasks(); }); } void mixer::thread_register_track(mixer_track* track) { tracks_.push_back(track); update_tasks(); on_add_track.broadcast(track); g_main_thread_hub.push_message([track, this] { on_add_track_main_thread.broadcast(track); }); } void mixer::thread_remove_track(mixer_track* track) { if (const auto it = std::ranges::find(tracks_, track); it != tracks_.end()) { tracks_.erase(it); } get_master()->remove_child(track); update_tasks(); on_remove_track.broadcast(track); g_main_thread_hub.push_message([track, this]() { on_remove_track_main_thread.broadcast(track); if (track == selected_track) selected_track = nullptr; delete track; }); } void mixer::build_process_node() { if (tracks_.empty()) return; std::unordered_map processed_tracks; auto* master = get_master(); build_process_node_internal(master, processed_tracks, 0); const auto& instruments = g_plugin_host_manager.get_instrument_hosts(); for (const plugin_host* instrument: instruments) { build_instrument_process_node(instrument, processed_tracks); } layer_tracks_.clear(); for (const auto& pair: processed_tracks) { layer_tracks_[pair.second].push_back(pair.first); } layer_order_.clear(); for (const auto& pair: layer_tracks_) { layer_order_.push_back(pair.first); } std::ranges::sort(layer_order_, std::greater()); } void mixer::update_taskflow(uint32_t in_frames) { taskflow_.clear(); for (int32_t order: layer_order_) { const auto& layer = layer_tracks_[order]; tf::Taskflow taskflow("mixer_update_layer" + std::to_string(order)); // 每层的轨道并行处理 for (mixer_track* track: layer) { taskflow.emplace([track, in_frames] { track->process(in_frames); }); } taskflow_.push_back(std::move(taskflow)); } } void mixer::update_tasks() { build_process_node(); update_taskflow(g_audio_device_manager.get_buffer_size()); }