#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::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::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::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::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; e->run(taskflow_).wait(); post_process(in_frames); // dummy_track* master = get_master(); // master->buffer.multiple(master->volume); } void mixer::reset() { for (const auto track: tracks_) { track->buffer.clear(); } } void mixer::build_process_node() { if (tracks_.empty()) return; std::map processed_tracks; auto* master = get_master(); build_process_node_internal(master, processed_tracks, 0); const auto& instruments = g_plugin_host_manager.get_plugin_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_); } void mixer::request_build_process_node() { g_audio_thread_hub.push_message([this] { build_process_node(); update_taskflow(g_audio_device_manager.get_buffer_size()); }); } void post_process_internal(mixer_track* track, uint32_t in_frames, std::set& processed_tracks) { if (std::ranges::find(processed_tracks, track) != processed_tracks.end()) return; for (const auto& link: track->children) { post_process_internal(link.track, in_frames, processed_tracks); track->buffer.mix(link.track->buffer, link.send_level); } track->post_process(in_frames); processed_tracks.emplace(track); } void mixer::post_process(uint32_t in_frames) const { const auto master = get_master(); std::set processed_tracks; post_process_internal(master, in_frames, processed_tracks); } void mixer::thread_register_track(mixer_track* track) { tracks_.push_back(track); build_process_node(); update_taskflow(g_audio_device_manager.get_buffer_size()); 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); build_process_node(); update_taskflow(g_audio_device_manager.get_buffer_size()); on_remove_track.broadcast(track); g_main_thread_hub.push_message([track, this]() { on_remove_track_main_thread.broadcast(track); delete track; }); } void mixer::update_taskflow(uint32_t in_frames) { tf::Taskflow taskflow; std::vector> layer_tasks; for (int32_t i = layer_order_.size() - 1; i >= 0; --i) { const auto& order = layer_order_[i]; auto new_layer = std::vector(); for (const auto& layer = layer_tracks_[order]; const auto& track: layer) { auto t = taskflow.emplace([track, in_frames] { track->process(in_frames); }); new_layer.push_back(t); } layer_tasks.push_back(std::move(new_layer)); } for (int i = layer_tasks.size() - 1; i >= 0; --i) { tf::Task layer_task = taskflow.emplace([]{}); for (auto& task: layer_tasks[i]) { task.precede(layer_task); } } taskflow_ = std::move(taskflow); } void mixer::begin_release(singleton_release_guard &release_guard) { singleton::begin_release(release_guard); auto e = executor_.exchange(nullptr); e->wait_for_all(); delete e; }