138 public Steinberg::Vst::IMidiMapping,
139 public Steinberg::Vst::INoteExpressionController,
140 public Steinberg::Vst::IKeyswitchController {
149 void** obj)
override;
150 Steinberg::uint32 PLUGIN_API
addRef()
override {
151 return Steinberg::Vst::SingleComponentEffect::addRef();
153 Steinberg::uint32 PLUGIN_API
release()
override {
154 return Steinberg::Vst::SingleComponentEffect::release();
158 Steinberg::tresult PLUGIN_API
initialize(Steinberg::FUnknown* context)
override;
164 Steinberg::int32 busIndex, Steinberg::int16 channel,
165 Steinberg::Vst::CtrlNumber midiControllerNumber,
166 Steinberg::Vst::ParamID&
id)
override;
174 Steinberg::int32 busIndex, Steinberg::int16 channel)
override;
176 Steinberg::int32 busIndex, Steinberg::int16 channel,
177 Steinberg::int32 noteExpressionIndex,
178 Steinberg::Vst::NoteExpressionTypeInfo& info )
override;
180 Steinberg::int32 busIndex, Steinberg::int16 channel,
181 Steinberg::Vst::NoteExpressionTypeID
id,
182 Steinberg::Vst::NoteExpressionValue valueNormalized ,
183 Steinberg::Vst::String128
string )
override;
185 Steinberg::int32 busIndex, Steinberg::int16 channel,
186 Steinberg::Vst::NoteExpressionTypeID
id,
187 const Steinberg::Vst::TChar*
string ,
188 Steinberg::Vst::NoteExpressionValue& valueNormalized )
override;
197 Steinberg::int32 busIndex, Steinberg::int16 channel)
override;
199 Steinberg::int32 busIndex, Steinberg::int16 channel,
200 Steinberg::int32 keySwitchIndex,
201 Steinberg::Vst::KeyswitchInfo& info )
override;
205 Steinberg::int32 unitIndex, Steinberg::Vst::UnitInfo& info)
override;
208 Steinberg::int32, Steinberg::Vst::ProgramListInfo&)
override;
210 Steinberg::Vst::ProgramListID, Steinberg::int32,
211 Steinberg::Vst::String128)
override;
213 Steinberg::Vst::ProgramListID, Steinberg::int32,
214 Steinberg::Vst::CString, Steinberg::Vst::String128)
override;
216 Steinberg::Vst::ProgramListID, Steinberg::int32)
override;
218 Steinberg::Vst::ProgramListID, Steinberg::int32, Steinberg::int16,
219 Steinberg::Vst::String128)
override;
221 Steinberg::tresult PLUGIN_API
selectUnit(Steinberg::Vst::UnitID)
override;
223 Steinberg::Vst::MediaType, Steinberg::Vst::BusDirection,
224 Steinberg::int32, Steinberg::int32,
225 Steinberg::Vst::UnitID&)
override;
227 Steinberg::int32, Steinberg::int32, Steinberg::IBStream*)
override;
236 Steinberg::Vst::ParamID tag,
237 Steinberg::Vst::ParamValue valueNormalized,
238 Steinberg::Vst::String128
string)
override;
240 Steinberg::Vst::ParamID tag, Steinberg::Vst::TChar*
string,
241 Steinberg::Vst::ParamValue& valueNormalized)
override;
247 Steinberg::Vst::ParamID
id, Steinberg::Vst::ParamValue valueNormalized)
override;
249 Steinberg::Vst::ParamID
id, Steinberg::Vst::ParamValue plainValue)
override;
252 Steinberg::IPlugView* PLUGIN_API
createView(Steinberg::FIDString name)
override;
256 Steinberg::Vst::SpeakerArrangement* inputs, Steinberg::int32 numIns,
257 Steinberg::Vst::SpeakerArrangement* outputs, Steinberg::int32 numOuts)
override;
260 Steinberg::int32 symbolicSampleSize)
override;
263 Steinberg::Vst::ProcessSetup& setup)
override;
271 Steinberg::Vst::ProcessData& data)
override;
274 return param_events_;
278 return param_events_monitor_;
295 return note_expression_drops_.load(std::memory_order_relaxed);
304 Steinberg::Vst::ParamValue value)
override;
305 Steinberg::tresult PLUGIN_API
getState(Steinberg::IBStream*
state)
override;
306 Steinberg::tresult PLUGIN_API
setState(Steinberg::IBStream*
state)
override;
314 factory_presets_dir_ = std::move(dir);
327 void terminate_contract_views();
342 std::unique_ptr<Processor> processor_;
344 std::shared_ptr<PanicState> panic_state_;
345 std::unique_ptr<ParamGroupProjection> param_groups_;
346 Steinberg::Vst::UnitID selected_unit_ = Steinberg::Vst::kRootUnitId;
352 std::filesystem::path factory_presets_dir_;
354 bool program_list_active_ =
false;
359 std::atomic<std::int64_t> program_index_{0};
360 std::atomic<bool> program_applied_{
false};
361 bool program_change_needed(std::size_t index)
const;
364 std::atomic<bool> parameter_objects_stale_{
false};
367 void apply_program(std::size_t index,
bool audio_thread, std::int32_t offset);
370 void sync_parameter_objects_from_store();
373 StateRestoreGate state_restore_gate_;
378 std::vector<ContractPlugView*> contract_views_;
381 std::vector<float*> input_ptrs_;
382 std::vector<float*> output_ptrs_;
383 std::vector<const double*> input64_ptrs_;
384 std::vector<double*> output64_ptrs_;
385 std::vector<std::vector<float>> f64_input_scratch_;
386 std::vector<std::vector<float>> f64_output_scratch_;
393 std::vector<float*> sidechain_ptrs_;
394 std::vector<const double*> sidechain64_ptrs_;
395 std::vector<std::vector<float>> f64_sidechain_scratch_;
405 std::vector<std::vector<float*>> aux_output_ptrs_;
406 std::vector<std::vector<double*>> aux_output64_ptrs_;
412 std::vector<int> declared_aux_channels_;
413 std::vector<std::vector<std::vector<float>>> f64_aux_output_scratch_;
430 std::unique_ptr<HostParameterEditBridge> edit_bridge_;
433 std::vector<float> param_snapshot_;
436 bool sample_accurate_params_ =
false;
438 ParamEventsOptOutMonitor param_events_monitor_;
442 std::vector<state::StateStore::ParamWrite> param_writes_;
445 std::vector<state::ParameterEvent> param_sort_scratch_;
446 std::vector<std::uint32_t> param_offset_counts_;
457 std::vector<std::uint8_t> output_param_has_event_;
458 std::vector<Steinberg::Vst::IParamValueQueue*> output_param_queue_cache_;
465 boundary::ParamSnapshotState snapshot_state_;
466 std::uint64_t pre_process_generation_ = 0;
472 std::array<ProcessBusBufferView<const double>, 2> rt_input64_buses_{};
476 static constexpr std::size_t kCachedBusCount = 32;
477 std::array<int, kCachedBusCount> expected_in_channels_{};
478 std::array<int, kCachedBusCount> expected_out_channels_{};
479 std::size_t cached_in_bus_count_ = 0;
480 std::size_t cached_out_bus_count_ = 0;
481 std::atomic<bool> bus_channel_cache_valid_{
false};
482 void refresh_bus_channel_cache();
491 bool warming_render_path_ =
false;
492 void warm_render_path();
503 boundary::MpeSidecar mpe_;
513 Steinberg::int32 note_id = -1;
517 static constexpr std::size_t kMaxLiveNoteIds = 128;
518 std::array<NoteIdSlot, kMaxLiveNoteIds> note_id_map_{};
524 std::atomic<std::uint32_t> note_expression_drops_{0};
530 bool note_id_map_insert(Steinberg::int32 note_id, uint8_t channel,
532 void note_id_map_erase(Steinberg::int32 note_id);
533 const NoteIdSlot* note_id_map_find(Steinberg::int32 note_id)
const;
534 void note_id_map_clear();
544 bool midi_controller_mapping_active_ =
false;
556 std::vector<bool> registered_controller_ids_;
573 void process_decode_input_parameters(Steinberg::Vst::ProcessData& data);
578 bool process_validate_layout(Steinberg::Vst::ProcessData& data,
580 int original_num_samples);
586 void process_wire_buffers(Steinberg::Vst::ProcessData& data,
bool host_f64,
587 bool native_f64,
bool boundary_f64,
588 int num_samples,
int original_num_samples,
589 int& in_channels,
int& out_channels,
595 bool process_maybe_bypass(Steinberg::Vst::ProcessData& data,
bool host_f64,
596 int in_channels,
int out_channels,
597 int original_num_samples);
601 void process_decode_input_events(Steinberg::Vst::ProcessData& data);
605 void process_publish_output_params(
606 Steinberg::Vst::ProcessData& data,
607 std::span<const state::ParamInfo> all_params);
612 void process_publish_restart_flags();
627 HostQuirks quirks_{};
639 bool descriptor_main_mono_ =
false;
640 bool silence_unsupported_active_ =
false;
641 bool native_f64_enabled_ =
false;
642 Steinberg::int32 selected_sample_size_ = Steinberg::Vst::kSample32;
646 PrepareContext prepared_context_{};
647 Processor::BusesLayout prepared_layout_{};
648 bool has_prepared_context_ =
false;
654 int max_block_size_ = 0;
660 detail::PlayheadSnapshot playhead_prev_{};
673 detail::Vst3RestartPublisher restart_publisher_;
681 std::shared_ptr<std::atomic<bool>> drain_alive_;
686 std::shared_ptr<std::atomic<bool>> poll_active_;
704 enum class InlineFallback : std::uint8_t {
716 void schedule_host_notifications(InlineFallback fallback);
717 void deliver_pending_restart();
721 void deliver_pending_dirty();
725 void deliver_pending_host_notifications();
730 std::shared_ptr<std::atomic<bool>> deferred_delivery_posted_;
733 bool delivering_host_notifications_ =
false;
738 void start_restart_poll();
739 void schedule_restart_poll_tick();
746 std::int32_t delivered = 0;
747 if (parameter_objects_stale_.exchange(
false, std::memory_order_acq_rel))
748 sync_parameter_objects_from_store();
749 auto* handler = getComponentHandler();
750 restart_publisher_.poll_main_thread(
751 [&](std::int32_t flags) {
753 if (handler) handler->restartComponent(flags);
759 return restart_publisher_.dispatch_armed();