Also cache audioMasterGetCurrentProcessLevel()

Melda plugins seem to call this during every processing cycle.
This commit is contained in:
Robbert van der Helm
2021-04-29 01:02:10 +02:00
parent 383b0c3f10
commit c82eb35243
5 changed files with 52 additions and 8 deletions
+2
View File
@@ -19,6 +19,8 @@ Versioning](https://semver.org/spec/v2.0.0.html).
information repeatedly for every sample they process. Previously yabridge had
a `cache_time_info` compatibility option to mitigate the performance hit for
those plugins, but this new caching behaviour supercedes that.
- Similarly, yabridge will also cache the current process level during audio
processing to reduce bridging overhead for plugins that use this.
- We now always force the CPU's flush-to-zero flag to be set when processing
audio. Most plugins will already do this themselves, but plugins like _Kush
Audio REDDI_ and _Expressive E Noisy_ that don't will otherwise suffer from
+9 -2
View File
@@ -559,11 +559,16 @@ struct AudioBuffers {
* We'll send the current transport information as part of an audio
* processing call. This lets us a void an unnecessary callback (or in some
* cases, more than one) during every processing cycle.
*
* TODO: Do the same thing for the current process level
*/
std::optional<VstTimeInfo> current_time_info;
/**
* Some plugins will also ask for the current process level during audio
* processing. To prevent unnecessary expensive callbacks, we'll send this
* information along with the processing call.
*/
int current_process_level;
/**
* We'll periodically synchronize the realtime priority setting of the
* host's audio thread with the Wine plugin host. We'll do this
@@ -592,6 +597,8 @@ struct AudioBuffers {
s.value4b(sample_frames);
s.ext(current_time_info, bitsery::ext::StdOptional{});
s.value4b(current_process_level);
s.ext(new_realtime_priority, bitsery::ext::StdOptional{},
[](S& s, int& priority) { s.value4b(priority); });
}
+10 -1
View File
@@ -568,10 +568,18 @@ void Vst2PluginBridge::do_process(T** inputs, T** outputs, int sample_frames) {
current_time_info = *returned_time_info;
}
// Some plugisn also ask for the current process level, so we'll cache that
// information as well
const int current_process_level = static_cast<int>(host_callback_function(
&plugin, audioMasterGetCurrentProcessLevel, 0, 0, nullptr, 0.0));
if (returned_time_info) {
current_time_info = *returned_time_info;
}
// We'll synchronize the scheduling priority of the audio thread on the Wine
// plugin host with that of the host's audio thread every once in a while
std::optional<int> new_realtime_priority;
time_t now = std::time(nullptr);
const time_t now = std::time(nullptr);
if (now > last_audio_thread_priority_synchronization +
audio_thread_priority_synchronization_interval) {
new_realtime_priority = get_realtime_priority();
@@ -590,6 +598,7 @@ void Vst2PluginBridge::do_process(T** inputs, T** outputs, int sample_frames) {
const AudioBuffers request{.buffers = input_buffers,
.sample_frames = sample_frames,
.current_time_info = current_time_info,
.current_process_level = current_process_level,
.new_realtime_priority = new_realtime_priority};
sockets.host_vst_process_replacing.send(request, process_buffer);
+25 -5
View File
@@ -190,11 +190,17 @@ Vst2Bridge::Vst2Bridge(MainContext& main_context,
// we'll send the current transport information as part of the
// request so we cache it to avoid unnecessary callbacks from
// the audio thread
std::optional<decltype(time_info_cache)::Guard> cache_guard =
request.current_time_info
? std::optional(
time_info_cache.set(*request.current_time_info))
: std::nullopt;
std::optional<decltype(time_info_cache)::Guard>
time_info_cache_guard =
request.current_time_info
? std::optional(time_info_cache.set(
*request.current_time_info))
: std::nullopt;
// We'll also cache the process level, since some plugins will
// ask for this during every processing cycle
decltype(process_level_cache)::Guard process_level_cache_guard =
process_level_cache.set(request.current_process_level);
// As suggested by Jack Winter, we'll synchronize this thread's
// audio processing priority with that of the host's audio
@@ -266,6 +272,7 @@ Vst2Bridge::Vst2Bridge(MainContext& main_context,
.buffers = output_buffers_single_precision,
.sample_frames = request.sample_frames,
.current_time_info = std::nullopt,
.current_process_level = 0,
.new_realtime_priority = std::nullopt};
sockets.host_vst_process_replacing.send(response,
buffer);
@@ -295,6 +302,7 @@ Vst2Bridge::Vst2Bridge(MainContext& main_context,
.buffers = output_buffers_double_precision,
.sample_frames = request.sample_frames,
.current_time_info = std::nullopt,
.current_process_level = 0,
.new_realtime_priority = std::nullopt};
sockets.host_vst_process_replacing.send(response,
buffer);
@@ -620,6 +628,18 @@ intptr_t Vst2Bridge::host_callback(AEffect* effect,
return result;
}
} break;
case audioMasterGetCurrentProcessLevel: {
// We also send the current process level for similar reasons
const int* current_process_level = process_level_cache.get();
if (current_process_level) {
logger.log_event(false, opcode, index, value, nullptr, option,
std::nullopt);
logger.log_event_response(false, opcode, *current_process_level,
nullptr, std::nullopt, true);
return *current_process_level;
}
} break;
}
HostCallbackDataConverter converter(effect, last_time_info);
+6
View File
@@ -129,6 +129,12 @@ class Vst2Bridge : public HostBridge {
*/
ScopedValueCache<VstTimeInfo> time_info_cache;
/**
* Some plugins will also ask for the current process level during audio
* processing, so we'll also cache that to prevent expensive callbacks.
*/
ScopedValueCache<int> process_level_cache;
// FIXME: This emits `-Wignored-attributes` as of Wine 5.22
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-attributes"