#include "mixer.h" #include #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" void build_effect_channel_interface(mixer_track* track, const channel_interface* in_interface, std::map& processed_tracks) { ZoneScoped; 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) { ZoneScoped; 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) { ZoneScoped; singleton_t::init(initliazer); null_channel_node::init(); executor_ = 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) { ZoneScoped; singleton_t::release(release_guard); null_channel_node::destroy(); for (const mixer_track* track : tracks_) { delete track; } delete zero_track; delete executor_; } dummy_track* mixer::create_dummy_track(const std::string& in_name) { ZoneScoped; 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) { ZoneScoped; 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) { ZoneScoped; 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 new_layer = taskflow.emplace([] {}); new_layer.succeed(previous_task); previous_task = new_layer; } executor_->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() { ZoneScoped; 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(); }); } void post_process_internal(mixer_track* track, uint32_t in_frames, std::vector& 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); } // CalculatePeak ? processed_tracks.push_back(track); } void mixer::post_process(uint32_t in_frames) const { ZoneScoped; const auto master = get_master(); std::vector 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(); 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(); on_remove_track.broadcast(track); g_main_thread_hub.push_message([track, this]() { on_remove_track_main_thread.broadcast(track); delete track; }); }