From 1b8248d67223e359a245678e4d7017680ad7ff0b Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Wed, 19 Jan 2022 18:18:20 +0100 Subject: [PATCH] Process offline audio from the GUI thread Because T-RackS 5 won't have it any other way. --- CHANGELOG.md | 10 ++++++++++ src/wine-host/bridges/vst3.cpp | 36 +++++++++++++++++++++++----------- src/wine-host/bridges/vst3.h | 4 ++-- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3373e45..ee717219 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,16 @@ Versioning](https://semver.org/spec/v2.0.0.html). [!1120](https://gitlab.freedesktop.org/pipewire/pipewire/-/merge_requests/1120) have been merged. +### Fixed + +- Fixed the VST3 version of _IK Multimedia's T-RackS 5_ producing silence while + doing offline rendering. This could happen when exporting or bouncing audio in + **Bitwig Studio 4.1**, **Ardour** and in **REAPER**. These plugins apparently + need to process audio from the main GUI thread when in offline rendering mode. + If you try to process audio from the...audio thread, then they will produce + silence and hang afterwards (which a fix in yabridge 3.7.0 previously + addressed). + ## [3.8.0] - 2022-01-15 ### Added diff --git a/src/wine-host/bridges/vst3.cpp b/src/wine-host/bridges/vst3.cpp index f402c873..d9ce9c8e 100644 --- a/src/wine-host/bridges/vst3.cpp +++ b/src/wine-host/bridges/vst3.cpp @@ -115,10 +115,7 @@ bool Vst3Bridge::inhibits_event_loop() noexcept { std::shared_lock lock(object_instances_mutex_); for (const auto& [instance_id, instance] : object_instances_) { - // HACK: IK Multimedia's T-RackS 5 will deadlock if it receives a timer - // proc during offline processing, so we need to prevent that from - // happening. - if (!instance.is_initialized || instance.is_offline_processing) { + if (!instance.is_initialized) { return true; } } @@ -1562,8 +1559,8 @@ size_t Vst3Bridge::register_object_instance( const auto& [instance, _] = get_instance(request.instance_id); - // See the comment in - // `Vst3Bridge::inhibits_event_loop()` + // See the comment in the + // `YaAudioProcessor::Process` handler instance.is_offline_processing = request.setup.processMode == Steinberg::Vst::kOffline; @@ -1631,11 +1628,28 @@ size_t Vst3Bridge::register_object_instance( // The actual audio is stored in the shared memory // buffers, so the reconstruction function will need to // know where it should point the `AudioBusBuffers` to - const tresult result = - instance.interfaces.audio_processor->process( - request.data.reconstruct( - instance.process_buffers_input_pointers, - instance.process_buffers_output_pointers)); + // HACK: IK-Multimedia's T-RackS 5 will hang if audio + // processing is done from the audio thread while + // the plugin is in offline processing mode. Yes + // that's as silly as it sounds. + tresult result; + auto& reconstructed = request.data.reconstruct( + instance.process_buffers_input_pointers, + instance.process_buffers_output_pointers); + if (instance.is_offline_processing) { + result = main_context_ + .run_in_context([&instance = instance, + &reconstructed]() { + return instance.interfaces + .audio_processor->process( + reconstructed); + }) + .get(); + } else { + result = + instance.interfaces.audio_processor->process( + reconstructed); + } return YaAudioProcessor::ProcessResponse{ .result = result, diff --git a/src/wine-host/bridges/vst3.h b/src/wine-host/bridges/vst3.h index b962bda3..a4fff201 100644 --- a/src/wine-host/bridges/vst3.h +++ b/src/wine-host/bridges/vst3.h @@ -249,8 +249,8 @@ struct Vst3PluginInstance { /** * Whether the plugin instance is currently in offline processing mode or * not. Needed as a HACK for IK Multimedia's T-RackS 5 because those plugins - * will deadlock if they receive a timer proc on the Win32 message loop - * while doing offline processing. + * will deadlock if they don't process audio from the GUI thread while doing + * offline processing. */ bool is_offline_processing = false; };