修复退出时崩溃
This commit is contained in:
parent
fba1e94fb8
commit
065448c5a3
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -10,6 +10,3 @@
|
|||||||
[submodule "third_party/glfw"]
|
[submodule "third_party/glfw"]
|
||||||
path = third_party/glfw
|
path = third_party/glfw
|
||||||
url = https://github.com/glfw/glfw.git
|
url = https://github.com/glfw/glfw.git
|
||||||
[submodule "third_party/cppzmq"]
|
|
||||||
path = third_party/cppzmq
|
|
||||||
url = https://github.com/zeromq/cppzmq.git
|
|
||||||
|
@ -136,18 +136,15 @@ void audio_device_manager::start_render_thread() {
|
|||||||
|
|
||||||
void audio_device_manager::stop_render_thread() {
|
void audio_device_manager::stop_render_thread() {
|
||||||
render_thread_should_stop_ = true;
|
render_thread_should_stop_ = true;
|
||||||
if (render_thread_.joinable())
|
// if (render_thread_.joinable())
|
||||||
render_thread_.join();
|
// render_thread_.join();
|
||||||
// wait for render thread to stop
|
// wait for render thread to stop
|
||||||
while (render_thread_running_) {
|
std::scoped_lock lock(render_thread_mutex_);
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
|
||||||
}
|
|
||||||
spdlog::info("port_audio render thread stopped");
|
spdlog::info("port_audio render thread stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_device_manager::render_thread() {
|
void audio_device_manager::render_thread() {
|
||||||
set_thread_name("audio_render");
|
set_thread_name("audio_render");
|
||||||
render_thread_running_ = true;
|
|
||||||
g_audio_thread_id = std::this_thread::get_id();
|
g_audio_thread_id = std::this_thread::get_id();
|
||||||
dummy_track* master = g_mixer.get_master();
|
dummy_track* master = g_mixer.get_master();
|
||||||
|
|
||||||
@ -162,6 +159,7 @@ void audio_device_manager::render_thread() {
|
|||||||
const float milliseconds = frames / rate * 1000; // 512 / 48000
|
const float milliseconds = frames / rate * 1000; // 512 / 48000
|
||||||
|
|
||||||
while (!render_thread_should_stop_) {
|
while (!render_thread_should_stop_) {
|
||||||
|
std::scoped_lock lock(render_thread_mutex_);
|
||||||
g_audio_thread_hub.process_messages();
|
g_audio_thread_hub.process_messages();
|
||||||
if (render_buffers_[0].remainder() < frames) {
|
if (render_buffers_[0].remainder() < frames) {
|
||||||
// std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<uint64_t>(milliseconds)));
|
// std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<uint64_t>(milliseconds)));
|
||||||
@ -173,5 +171,4 @@ void audio_device_manager::render_thread() {
|
|||||||
g_plugin_host_manager.process(frames);
|
g_plugin_host_manager.process(frames);
|
||||||
g_mixer.process(frames, render_buffers_);
|
g_mixer.process(frames, render_buffers_);
|
||||||
}
|
}
|
||||||
render_thread_running_ = false;
|
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,8 @@ protected:
|
|||||||
void render_thread();
|
void render_thread();
|
||||||
std::thread render_thread_;
|
std::thread render_thread_;
|
||||||
circular_buffer_vector_type render_buffers_;
|
circular_buffer_vector_type render_buffers_;
|
||||||
std::atomic_bool render_thread_running_ = false;
|
|
||||||
std::atomic_bool render_thread_should_stop_ = false;
|
std::atomic_bool render_thread_should_stop_ = false;
|
||||||
|
std::mutex render_thread_mutex_;
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
private:
|
private:
|
||||||
RtAudio::StreamParameters input_params_ = {};
|
RtAudio::StreamParameters input_params_ = {};
|
||||||
|
@ -11,12 +11,13 @@
|
|||||||
|
|
||||||
IMPL_SINGLETON_INSTANCE(midi_sequencer)
|
IMPL_SINGLETON_INSTANCE(midi_sequencer)
|
||||||
|
|
||||||
|
smf::MidiFile midifile;
|
||||||
|
|
||||||
void midi_sequencer::test() {
|
void midi_sequencer::test() {
|
||||||
const char* path = R"(F:\VST\VST64\Serum_x64.dll)";
|
const char* path = R"(F:\VST\VST64\Addictive Keys.dll)";
|
||||||
// host->try_open_editor();
|
// host->try_open_editor();
|
||||||
|
|
||||||
smf::MidiFile midifile("E:/Projects/AronaStudio/Arona/resources/1.mid");
|
midifile.read("E:/Projects/AronaStudio/Arona/resources/1.mid");
|
||||||
if (!midifile.status())
|
if (!midifile.status())
|
||||||
spdlog::critical("Error reading MIDI file");
|
spdlog::critical("Error reading MIDI file");
|
||||||
midifile.doTimeAnalysis();
|
midifile.doTimeAnalysis();
|
||||||
@ -71,6 +72,7 @@ auto midi_sequencer::toggle_play() -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto midi_sequencer::create_clip_instance(clip* clip) -> clip_instance* {
|
auto midi_sequencer::create_clip_instance(clip* clip) -> clip_instance* {
|
||||||
|
check(IS_AUDIO_THREAD());
|
||||||
auto instance = new clip_instance(clip);
|
auto instance = new clip_instance(clip);
|
||||||
clip_instances_.push_back(instance);
|
clip_instances_.push_back(instance);
|
||||||
return instance;
|
return instance;
|
||||||
|
@ -15,7 +15,7 @@ public:
|
|||||||
|
|
||||||
void init(singleton_initliazer& initliazer) override;
|
void init(singleton_initliazer& initliazer) override;
|
||||||
void process(double sample_rate, uint32_t delta_frames);
|
void process(double sample_rate, uint32_t delta_frames);
|
||||||
auto toggle_play() -> bool ;
|
auto toggle_play() -> bool;
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
auto create_clip() -> T* {
|
auto create_clip() -> T* {
|
||||||
|
@ -12,6 +12,7 @@ void audio_buffer_pool::release(singleton_release_guard& release_guard) {
|
|||||||
for (auto& pool : pool_map_) {
|
for (auto& pool : pool_map_) {
|
||||||
delete pool.second;
|
delete pool.second;
|
||||||
}
|
}
|
||||||
|
pool_map_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
sample_t* audio_buffer_pool::alloc(uint32_t block_size) {
|
sample_t* audio_buffer_pool::alloc(uint32_t block_size) {
|
||||||
@ -22,5 +23,6 @@ sample_t* audio_buffer_pool::alloc(uint32_t block_size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void audio_buffer_pool::free(sample_t* block, uint32_t block_size) {
|
void audio_buffer_pool::free(sample_t* block, uint32_t block_size) {
|
||||||
pool_map_[block_size]->deallocate(block);
|
if (const auto pool = pool_map_[block_size])
|
||||||
|
pool->deallocate(block);
|
||||||
}
|
}
|
||||||
|
@ -134,11 +134,11 @@ void channel_interface::remove_track(mixer_track* track) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mixer_channel_interface::mixer_channel_interface(mixer_track* track) : channel_interface(0, 2), track_(track) {
|
mixer_channel_interface::mixer_channel_interface(mixer_track* track) : channel_interface(0, 2), track_(track) {
|
||||||
node_ = new mixer_channel_node(this, track, 0);
|
node_ = get_pool_obj<mixer_channel_node>(this, track, 0);
|
||||||
set_output_channel(0, node_);
|
set_output_channel(0, node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
mixer_channel_interface::~mixer_channel_interface() {
|
mixer_channel_interface::~mixer_channel_interface() {
|
||||||
delete node_;
|
free_pool_obj(node_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,60 @@
|
|||||||
|
|
||||||
IMPL_SINGLETON_INSTANCE(mixer)
|
IMPL_SINGLETON_INSTANCE(mixer)
|
||||||
|
|
||||||
|
void mixer_thread_cache::add_track(mixer_track* track) {
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
tracks_.push_back(track);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mixer_thread_cache::remove_track(mixer_track* track) {
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
|
||||||
|
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);
|
||||||
|
track_pool::free(track);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void mixer_thread_cache::process(uint32_t in_frames, circular_buffer_vector_type& out_buffer) {
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
processor_.process(in_frames);
|
||||||
|
processor_.pop_master(in_frames, out_buffer);
|
||||||
|
ready_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mixer_thread_cache::reset() {
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
for (const auto track : tracks_) {
|
||||||
|
track->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mixer_thread_cache::add_link(mixer_track* in_source, mixer_track* in_target, float in_gain) {
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
processor_.add_link(in_source, in_target, in_gain);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mixer_thread_cache::remove_link(mixer_track* in_source, mixer_track* in_target) {
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
processor_.remove_link(in_source, in_target);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mixer_thread_cache::build_process_node() {
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
processor_.update_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mixer_thread_cache::update_latency() {
|
||||||
|
std::lock_guard lock(mutex_);
|
||||||
|
processor_.update_latency();
|
||||||
|
}
|
||||||
|
|
||||||
void mixer::init(singleton_initliazer& initliazer) {
|
void mixer::init(singleton_initliazer& initliazer) {
|
||||||
singleton_t<mixer>::init(initliazer);
|
singleton_t<mixer>::init(initliazer);
|
||||||
on_latency_offset_changed.add_raw(this, &mixer::on_mixer_latency_changed);
|
on_latency_offset_changed.add_raw(this, &mixer::on_mixer_latency_changed);
|
||||||
@ -17,17 +71,12 @@ void mixer::init(singleton_initliazer& initliazer) {
|
|||||||
|
|
||||||
null_channel_node::init();
|
null_channel_node::init();
|
||||||
|
|
||||||
zero_track_ = new dummy_track();
|
zero_track_ = track_pool::construct<zero_track>();
|
||||||
zero_track_->rename("zero");
|
|
||||||
zero_track_->init();
|
zero_track_->init();
|
||||||
|
master_ = create_dummy_track("master");
|
||||||
master_ = new dummy_track();
|
|
||||||
master_->rename("master");
|
|
||||||
master_->init();
|
|
||||||
push_track(master_);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mixer::begin_release(singleton_release_guard &release_guard) {
|
void mixer::begin_release(singleton_release_guard& release_guard) {
|
||||||
singleton::begin_release(release_guard);
|
singleton::begin_release(release_guard);
|
||||||
on_latency_offset_changed.remove_object(this);
|
on_latency_offset_changed.remove_object(this);
|
||||||
}
|
}
|
||||||
@ -36,90 +85,37 @@ void mixer::release(singleton_release_guard& release_guard) {
|
|||||||
singleton_t<mixer>::release(release_guard);
|
singleton_t<mixer>::release(release_guard);
|
||||||
release_guard.require_release<audio_device_manager>();
|
release_guard.require_release<audio_device_manager>();
|
||||||
null_channel_node::destroy();
|
null_channel_node::destroy();
|
||||||
for (auto track : tracks_) {
|
track_pool::free_all();
|
||||||
delete track;
|
|
||||||
}
|
|
||||||
delete zero_track_;
|
|
||||||
tracks_.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dummy_track* mixer::create_dummy_track(const std::string& in_name) {
|
dummy_track* mixer::create_dummy_track(const std::string& in_name, bool register_to_manager) {
|
||||||
ready_dirty();
|
auto* track = track_pool::construct<dummy_track>();
|
||||||
auto* track = new dummy_track();
|
|
||||||
track->init();
|
track->init();
|
||||||
track->rename(in_name);
|
track->rename(in_name);
|
||||||
|
|
||||||
g_audio_thread_hub.push_message([track, this]() {
|
if (register_to_manager) {
|
||||||
processor_.add_link(track, get_master(), 1.0f);
|
mixer_thread_cache_.add_track(track);
|
||||||
thread_register_track(track);
|
mixer_thread_cache_.add_link(track, get_master(), 1.0f);
|
||||||
});
|
}
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
instrument_track* mixer::create_instrument_track(plugin_host* in_instrument) {
|
instrument_track* mixer::create_instrument_track(plugin_host* in_instrument, bool register_to_manager) {
|
||||||
ready_dirty();
|
auto* track = track_pool::construct<instrument_track>(in_instrument);
|
||||||
auto* track = new instrument_track(in_instrument);
|
|
||||||
track->init();
|
track->init();
|
||||||
|
|
||||||
// register track
|
if (register_to_manager) {
|
||||||
g_audio_thread_hub.push_message([track, this] {
|
mixer_thread_cache_.add_track(track);
|
||||||
processor_.add_link(track, get_master(), 1.0f);
|
mixer_thread_cache_.add_link(track, get_master(), 1.0f);
|
||||||
thread_register_track(track);
|
}
|
||||||
});
|
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mixer::remove_track(mixer_track* track) {
|
void mixer::remove_track(mixer_track* track) {
|
||||||
g_audio_thread_hub.push_message([track, this] {
|
mixer_thread_cache_.remove_track(track);
|
||||||
if (const auto it = std::ranges::find(tracks_, track); it != tracks_.end()) {
|
if (track == selected_track) selected_track = nullptr;
|
||||||
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);
|
|
||||||
ready_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mixer::reset() {
|
|
||||||
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() {
|
void mixer::on_mixer_latency_changed() {
|
||||||
ready_dirty();
|
mixer_thread_cache_.update_latency();
|
||||||
g_audio_thread_hub.push_message([this] {
|
|
||||||
processor_.update_latency();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,41 @@ class plugin_host;
|
|||||||
class channel_interface;
|
class channel_interface;
|
||||||
class mixer_track;
|
class mixer_track;
|
||||||
|
|
||||||
|
using track_pool = inherit_obj_pool<mixer_track, zero_track, dummy_track, instrument_track>;
|
||||||
|
inline multicast_delegate<mixer_track*> on_add_track;
|
||||||
|
inline multicast_delegate<mixer_track*> on_add_track_main_thread;
|
||||||
|
inline multicast_delegate<mixer_track*> on_remove_track;
|
||||||
|
inline multicast_delegate<mixer_track*> on_remove_track_main_thread;
|
||||||
|
|
||||||
|
class mixer_thread_cache {
|
||||||
|
public:
|
||||||
|
void add_track(mixer_track* track);
|
||||||
|
void remove_track(mixer_track* track);
|
||||||
|
void process(uint32_t in_frames, circular_buffer_vector_type& out_buffer);
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void add_link(mixer_track* in_source, mixer_track* in_target, float in_gain);
|
||||||
|
void remove_link(mixer_track* in_source, mixer_track* in_target);
|
||||||
|
|
||||||
|
void build_process_node();
|
||||||
|
void update_latency();
|
||||||
|
|
||||||
|
auto get_tracks() -> const std::vector<mixer_track*>& {
|
||||||
|
return tracks_;
|
||||||
|
}
|
||||||
|
auto begin() {
|
||||||
|
return tracks_.begin();
|
||||||
|
}
|
||||||
|
auto end() {
|
||||||
|
return tracks_.end();
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::vector<mixer_track*> tracks_;
|
||||||
|
mixer_processor processor_;
|
||||||
|
std::atomic<bool> ready_ = false;
|
||||||
|
std::mutex mutex_;
|
||||||
|
};
|
||||||
|
|
||||||
class mixer : public singleton_t<mixer> {
|
class mixer : public singleton_t<mixer> {
|
||||||
typedef std::pair<int32_t, std::vector<mixer_track*>> layer_type;
|
typedef std::pair<int32_t, std::vector<mixer_track*>> layer_type;
|
||||||
public:
|
public:
|
||||||
@ -22,38 +57,32 @@ public:
|
|||||||
void release(singleton_release_guard& release_guard) override;
|
void release(singleton_release_guard& release_guard) override;
|
||||||
const char* get_name() override { return "mixer"; }
|
const char* get_name() override { return "mixer"; }
|
||||||
|
|
||||||
dummy_track* create_dummy_track(const std::string& in_name);
|
dummy_track* create_dummy_track(const std::string& in_name, bool register_to_manager = true);
|
||||||
instrument_track* create_instrument_track(plugin_host* in_instrument);
|
instrument_track* create_instrument_track(plugin_host* in_instrument, bool register_to_manager = true);
|
||||||
void remove_track(mixer_track* track);
|
void remove_track(mixer_track* track);
|
||||||
[[nodiscard]] const std::vector<mixer_track*>& get_tracks() const { return tracks_; }
|
|
||||||
|
|
||||||
void process(uint32_t in_frames, circular_buffer_vector_type& out_buffer);
|
void process(uint32_t in_frames, circular_buffer_vector_type& out_buffer) {
|
||||||
void reset();
|
if (need_build_process_node_) {
|
||||||
|
mixer_thread_cache_.build_process_node();
|
||||||
|
need_build_process_node_ = false;
|
||||||
|
}
|
||||||
|
mixer_thread_cache_.process(in_frames, out_buffer);
|
||||||
|
}
|
||||||
|
void reset() { mixer_thread_cache_.reset(); }
|
||||||
|
void request_build_process_node() { need_build_process_node_ = true; }
|
||||||
|
auto get_tracks() -> const std::vector<mixer_track*>& { return mixer_thread_cache_.get_tracks(); }
|
||||||
|
|
||||||
[[nodiscard]] auto get_master() const -> dummy_track* { return master_; }
|
[[nodiscard]] auto get_master() const -> dummy_track* { return master_; }
|
||||||
[[nodiscard]] auto get_zero_track() const -> dummy_track* { return zero_track_; }
|
[[nodiscard]] auto get_zero_track() const -> zero_track* { return zero_track_; }
|
||||||
void request_build_process_node();
|
|
||||||
bool is_ready() const { return ready_; }
|
|
||||||
void ready_dirty() { ready_ = false; }
|
|
||||||
|
|
||||||
multicast_delegate<mixer_track*> on_add_track;
|
|
||||||
multicast_delegate<mixer_track*> on_add_track_main_thread;
|
|
||||||
multicast_delegate<mixer_track*> on_remove_track;
|
|
||||||
multicast_delegate<mixer_track*> on_remove_track_main_thread;
|
|
||||||
|
|
||||||
mixer_track* selected_track = nullptr;
|
mixer_track* selected_track = nullptr;
|
||||||
private:
|
private:
|
||||||
void push_track(mixer_track* track);
|
|
||||||
|
|
||||||
void thread_register_track(mixer_track* track);
|
|
||||||
|
|
||||||
void on_mixer_latency_changed();
|
void on_mixer_latency_changed();
|
||||||
|
|
||||||
dummy_track* master_;
|
dummy_track* master_ = nullptr;
|
||||||
dummy_track* zero_track_; // 用于没有任何音频输出的通道
|
zero_track* zero_track_ = nullptr; // 用于没有任何音频输出的通道
|
||||||
std::vector<mixer_track*> tracks_;
|
std::atomic<bool> need_build_process_node_ = false;
|
||||||
mixer_processor processor_;
|
mixer_thread_cache mixer_thread_cache_;
|
||||||
std::atomic<bool> ready_ = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
DEFINE_SINGLETON_INSTANCE(mixer)
|
DEFINE_SINGLETON_INSTANCE(mixer)
|
||||||
|
@ -7,8 +7,7 @@
|
|||||||
#include "thread_message/thread_message_hubs.h"
|
#include "thread_message/thread_message_hubs.h"
|
||||||
|
|
||||||
mixer_track::~mixer_track() {
|
mixer_track::~mixer_track() {
|
||||||
delete channel_interface_;
|
free_pool_obj(channel_interface_);
|
||||||
channel_interface_ = nullptr;
|
|
||||||
for (auto e : effects_) {
|
for (auto e : effects_) {
|
||||||
// e->on_latency_changed.remove_all(this);
|
// e->on_latency_changed.remove_all(this);
|
||||||
get_plugin_host_manager()->remove_effect_plugin_host(e);
|
get_plugin_host_manager()->remove_effect_plugin_host(e);
|
||||||
@ -25,7 +24,7 @@ void mixer_track::init() {
|
|||||||
buffer.set_capacity(block_size * 2);
|
buffer.set_capacity(block_size * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_interface_ = new mixer_channel_interface(this);
|
channel_interface_ = get_pool_obj<mixer_channel_interface>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mixer_track::add_effect(plugin_host* in_effect) {
|
void mixer_track::add_effect(plugin_host* in_effect) {
|
||||||
@ -67,7 +66,7 @@ void mixer_track::push_ui_buffer(const audio_buffer& in_buffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instrument_track::instrument_track(plugin_host* in_instrument): mixer_track(mixer_track_type::instrument)
|
instrument_track::instrument_track(plugin_host* in_instrument): mixer_track(type)
|
||||||
, instrument_(in_instrument) {}
|
, instrument_(in_instrument) {}
|
||||||
|
|
||||||
void instrument_track::rename(const std::string& in_name) {
|
void instrument_track::rename(const std::string& in_name) {
|
||||||
|
@ -3,17 +3,16 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "latency_compensator.h"
|
#include "latency_compensator.h"
|
||||||
#include "../../misc/mempool.h"
|
|
||||||
#include "audio/misc/audio_buffer.h"
|
#include "audio/misc/audio_buffer.h"
|
||||||
#include "audio/misc/circular_audio_buffer.h"
|
#include "audio/misc/circular_audio_buffer.h"
|
||||||
#include "misc/delegates.h"
|
|
||||||
|
|
||||||
class channel_interface;
|
class mixer_channel_interface;
|
||||||
class mixer_track;
|
class mixer_track;
|
||||||
class plugin_host;
|
class plugin_host;
|
||||||
|
|
||||||
enum class mixer_track_type {
|
enum class mixer_track_type {
|
||||||
unknown,
|
unknown,
|
||||||
|
zero,
|
||||||
dummy,
|
dummy,
|
||||||
instrument,
|
instrument,
|
||||||
};
|
};
|
||||||
@ -48,7 +47,7 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] auto get_type() const -> mixer_track_type { return type_; }
|
[[nodiscard]] auto get_type() const -> mixer_track_type { return type_; }
|
||||||
|
|
||||||
[[nodiscard]] auto get_channel_interface() const -> channel_interface* { return channel_interface_; }
|
[[nodiscard]] auto get_channel_interface() const -> mixer_channel_interface* { return channel_interface_; }
|
||||||
|
|
||||||
void set_volume(float in_volume) { volume_ = in_volume; }
|
void set_volume(float in_volume) { volume_ = in_volume; }
|
||||||
[[nodiscard]] auto get_volume() const -> float { return volume_; }
|
[[nodiscard]] auto get_volume() const -> float { return volume_; }
|
||||||
@ -69,12 +68,12 @@ private:
|
|||||||
circular_buffer_vector_type ui_buffers_;
|
circular_buffer_vector_type ui_buffers_;
|
||||||
std::vector<plugin_host*> effects_{};
|
std::vector<plugin_host*> effects_{};
|
||||||
audio_buffer buffer_;
|
audio_buffer buffer_;
|
||||||
channel_interface* channel_interface_ = nullptr;
|
mixer_channel_interface* channel_interface_ = nullptr;
|
||||||
const uint64_t id_ = 0;
|
const uint64_t id_ = 0;
|
||||||
float volume_ = 1.0f;
|
float volume_ = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
class instrument_track : public mixer_track, public pool_obj<instrument_track> {
|
class instrument_track : public mixer_track {
|
||||||
public:
|
public:
|
||||||
static constexpr auto type = mixer_track_type::instrument;
|
static constexpr auto type = mixer_track_type::instrument;
|
||||||
|
|
||||||
@ -92,10 +91,10 @@ private:
|
|||||||
plugin_host* instrument_;
|
plugin_host* instrument_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class dummy_track : public mixer_track, public pool_obj<dummy_track> {
|
class dummy_track : public mixer_track {
|
||||||
public:
|
public:
|
||||||
static constexpr auto type = mixer_track_type::dummy;
|
static constexpr auto type = mixer_track_type::dummy;
|
||||||
dummy_track() : mixer_track(mixer_track_type::dummy) {}
|
dummy_track() : mixer_track(type) {}
|
||||||
|
|
||||||
void rename(const std::string& in_name) override { name_ = in_name; }
|
void rename(const std::string& in_name) override { name_ = in_name; }
|
||||||
[[nodiscard]] auto get_name() const -> std::string override { return name_; }
|
[[nodiscard]] auto get_name() const -> std::string override { return name_; }
|
||||||
@ -103,3 +102,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
std::string name_;
|
std::string name_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class zero_track : public mixer_track {
|
||||||
|
public:
|
||||||
|
static constexpr auto type = mixer_track_type::zero;
|
||||||
|
zero_track() : mixer_track(type) {}
|
||||||
|
|
||||||
|
[[nodiscard]] auto get_name() const -> std::string override { return "zero"; }
|
||||||
|
void rename(const std::string& in_name) override {}
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
@ -24,9 +24,11 @@ void plugin_host::on_update_buffer_size(int buffer_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_host::push_stop_all_notes(uint32_t frame_delta) {
|
void plugin_host::push_stop_all_notes(uint8_t channel) {
|
||||||
smf::MidiEvent event(0xB0, 0x7B, 0x00);
|
for (uint8_t i = 0; i < 127; ++i) {
|
||||||
push_midi(event, frame_delta);
|
smf::MidiEvent event(0x80 | channel, i, 0x00);
|
||||||
|
push_midi(event, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_host::try_open_editor() {
|
void plugin_host::try_open_editor() {
|
||||||
|
@ -59,7 +59,7 @@ public:
|
|||||||
|
|
||||||
virtual void process(uint32_t frame_num) = 0;
|
virtual void process(uint32_t frame_num) = 0;
|
||||||
virtual void push_midi(const smf::MidiEvent& event, uint32_t frame_delta) = 0;
|
virtual void push_midi(const smf::MidiEvent& event, uint32_t frame_delta) = 0;
|
||||||
void push_stop_all_notes(uint32_t frame_delta = 0);
|
void push_stop_all_notes(uint8_t channel = 0);
|
||||||
|
|
||||||
void try_open_editor();
|
void try_open_editor();
|
||||||
|
|
||||||
|
@ -16,8 +16,7 @@ IMPL_SINGLETON_INSTANCE(plugin_host_manager)
|
|||||||
|
|
||||||
void plugin_host_manager::init(singleton_initliazer& initliazer) {
|
void plugin_host_manager::init(singleton_initliazer& initliazer) {
|
||||||
singleton_t::init(initliazer);
|
singleton_t::init(initliazer);
|
||||||
auto* mixer_ptr = initliazer.require<mixer>();
|
on_remove_track.add_raw(this, &plugin_host_manager::on_mixer_track_removed);
|
||||||
mixer_ptr->on_remove_track.add_raw(this, &plugin_host_manager::on_mixer_track_removed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_host_manager::release(singleton_release_guard& release_guard) {
|
void plugin_host_manager::release(singleton_release_guard& release_guard) {
|
||||||
@ -77,7 +76,7 @@ void plugin_host_manager::remove_instrument_plugin_host(plugin_host* host) {
|
|||||||
plugin_host* plugin_host_manager::load_plugin(const char* path) {
|
plugin_host* plugin_host_manager::load_plugin(const char* path) {
|
||||||
auto host = new vst2_plugin_host();
|
auto host = new vst2_plugin_host();
|
||||||
try {
|
try {
|
||||||
host->load_plugin(path);
|
host->load(path);
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
spdlog::error("Failed to load plugin: {}", e.what());
|
spdlog::error("Failed to load plugin: {}", e.what());
|
||||||
delete host;
|
delete host;
|
||||||
@ -91,14 +90,15 @@ plugin_host* plugin_host_manager::load_plugin(const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void plugin_host_manager::register_instrument_plugin(plugin_host* host) {
|
void plugin_host_manager::register_instrument_plugin(plugin_host* host) {
|
||||||
instrument_plugins_.push_back(host);
|
|
||||||
g_audio_thread_hub.push_message([this, host]() {
|
g_audio_thread_hub.push_message([this, host]() {
|
||||||
|
instrument_plugins_.push_back(host);
|
||||||
instrument_track* instrument_track = g_mixer.create_instrument_track(host);
|
instrument_track* instrument_track = g_mixer.create_instrument_track(host);
|
||||||
host->channel->set_input_channel(instrument_track->get_channel_interface()->input_channel_nodes);
|
host->channel->set_input_channel(instrument_track->get_channel_interface()->input_channel_nodes);
|
||||||
host->channel->set_output_channel(instrument_track->get_channel_interface()->output_channel_nodes);
|
host->channel->set_output_channel(instrument_track->get_channel_interface()->output_channel_nodes);
|
||||||
host->owner_tracks.push_back(instrument_track);
|
host->owner_tracks.push_back(instrument_track);
|
||||||
host->update_channel_node_name();
|
host->update_channel_node_name();
|
||||||
update_taskflow(g_audio_device_manager.get_buffer_size());
|
update_taskflow(g_audio_device_manager.get_buffer_size());
|
||||||
|
|
||||||
g_main_thread_hub.push_message([host, this]() {
|
g_main_thread_hub.push_message([host, this]() {
|
||||||
on_instrument_added.broadcast(host);
|
on_instrument_added.broadcast(host);
|
||||||
});
|
});
|
||||||
@ -106,16 +106,19 @@ void plugin_host_manager::register_instrument_plugin(plugin_host* host) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void plugin_host_manager::process(uint32_t in_frames) {
|
void plugin_host_manager::process(uint32_t in_frames) {
|
||||||
|
check(IS_AUDIO_THREAD());
|
||||||
g_executor->run(taskflow_).wait();
|
g_executor->run(taskflow_).wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_host_manager::on_mixer_track_removed(mixer_track* track) {
|
void plugin_host_manager::on_mixer_track_removed(mixer_track* track) {
|
||||||
|
check(IS_AUDIO_THREAD());
|
||||||
for (auto host : plugin_hosts_) {
|
for (auto host : plugin_hosts_) {
|
||||||
host->channel->remove_track(track);
|
host->channel->remove_track(track);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void plugin_host_manager::update_taskflow(uint32_t in_frames) {
|
void plugin_host_manager::update_taskflow(uint32_t in_frames) {
|
||||||
|
check(IS_AUDIO_THREAD());
|
||||||
tf::Taskflow taskflow;
|
tf::Taskflow taskflow;
|
||||||
for (auto host : instrument_plugins_) {
|
for (auto host : instrument_plugins_) {
|
||||||
taskflow.emplace([host, in_frames] {
|
taskflow.emplace([host, in_frames] {
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <coroutine>
|
||||||
|
|
||||||
#include "misc/delegates.h"
|
#include "misc/delegates.h"
|
||||||
#include "misc/singleton/singleton.h"
|
#include "misc/singleton/singleton.h"
|
||||||
#include "taskflow/taskflow.hpp"
|
#include "taskflow/taskflow.hpp"
|
||||||
#include "plugin_host.h"
|
#include "plugin_host.h"
|
||||||
#include "../../misc/mempool.h"
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
class mixer_track;
|
class mixer_track;
|
||||||
|
1
third_party/cppzmq
vendored
1
third_party/cppzmq
vendored
@ -1 +0,0 @@
|
|||||||
Subproject commit 6164cf7dbc1df6d1bd8e4c6c5f8e52d7dea63aa7
|
|
Loading…
x
Reference in New Issue
Block a user