127 lines
3.5 KiB
C++
127 lines
3.5 KiB
C++
#include "mixer.h"
|
|
|
|
#include "channel_interface.h"
|
|
#include "channel_node.h"
|
|
#include "audio/device/audio_device_manager.h"
|
|
#include "audio/misc/audio_buffer_pool.h"
|
|
#include "misc/query_timer.h"
|
|
#include "thread_message/thread_message_hubs.h"
|
|
|
|
IMPL_SINGLETON_INSTANCE(mixer)
|
|
|
|
void mixer::init(singleton_initliazer& initliazer) {
|
|
singleton_t<mixer>::init(initliazer);
|
|
on_latency_offset_changed.add_raw(this, &mixer::on_mixer_latency_changed);
|
|
initliazer.require<audio_buffer_pool>();
|
|
initliazer.require<audio_device_manager>(); // 依赖音频设备管理器, 用于获取采样率和缓冲区大小
|
|
|
|
null_channel_node::init();
|
|
|
|
zero_track_ = new dummy_track();
|
|
zero_track_->rename("zero");
|
|
zero_track_->init();
|
|
|
|
master_ = new dummy_track();
|
|
master_->rename("master");
|
|
master_->init();
|
|
push_track(master_);
|
|
}
|
|
|
|
void mixer::begin_release(singleton_release_guard &release_guard) {
|
|
singleton::begin_release(release_guard);
|
|
on_latency_offset_changed.remove_object(this);
|
|
}
|
|
|
|
void mixer::release(singleton_release_guard& release_guard) {
|
|
singleton_t<mixer>::release(release_guard);
|
|
release_guard.require_release<audio_device_manager>();
|
|
null_channel_node::destroy();
|
|
for (auto track : tracks_) {
|
|
delete track;
|
|
}
|
|
delete zero_track_;
|
|
tracks_.clear();
|
|
}
|
|
|
|
dummy_track* mixer::create_dummy_track(const std::string& in_name) {
|
|
auto* track = new dummy_track();
|
|
track->init();
|
|
track->rename(in_name);
|
|
|
|
g_audio_thread_hub.push_message([track, this]() {
|
|
processor_.add_link(track, get_master(), 1.0f);
|
|
thread_register_track(track);
|
|
});
|
|
return track;
|
|
}
|
|
|
|
instrument_track* mixer::create_instrument_track(plugin_host* in_instrument) {
|
|
auto* track = new instrument_track(in_instrument);
|
|
track->init();
|
|
|
|
// register track
|
|
g_audio_thread_hub.push_message([track, this] {
|
|
processor_.add_link(track, get_master(), 1.0f);
|
|
thread_register_track(track);
|
|
});
|
|
return track;
|
|
}
|
|
|
|
void mixer::remove_track(mixer_track* track) {
|
|
g_audio_thread_hub.push_message([track, this] {
|
|
if (const auto it = std::ranges::find(tracks_, track); it != tracks_.end()) {
|
|
tracks_.erase(it);
|
|
}
|
|
processor_.remove_track(track);
|
|
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::process(uint32_t in_frames, circular_buffer_vector_type& out_buffer) {
|
|
processor_.process(in_frames);
|
|
processor_.pop_master(in_frames, out_buffer);
|
|
}
|
|
|
|
void mixer::reset() {
|
|
if (process_node_dirty_) {
|
|
processor_.update_all();
|
|
process_node_dirty_ = false;
|
|
}
|
|
|
|
for (const auto track : tracks_) {
|
|
track->clear();
|
|
}
|
|
}
|
|
|
|
void mixer::request_build_process_node() {
|
|
g_audio_thread_hub.push_message([this] {
|
|
processor_.update_all();
|
|
});
|
|
}
|
|
|
|
void mixer::push_track(mixer_track* track) {
|
|
tracks_.push_back(track);
|
|
}
|
|
|
|
void mixer::thread_register_track(mixer_track* track) {
|
|
push_track(track);
|
|
processor_.update_all();
|
|
on_add_track.broadcast(track);
|
|
g_main_thread_hub.push_message([track, this] {
|
|
on_add_track_main_thread.broadcast(track);
|
|
});
|
|
}
|
|
|
|
void mixer::on_mixer_latency_changed() {
|
|
g_audio_thread_hub.push_message([this] {
|
|
processor_.update_latency();
|
|
});
|
|
}
|