Add a time info caching compatibility option #62

This is needed to get good performance out of SWAM Cello until this
issue is fixed by the plugin.
This commit is contained in:
Robbert van der Helm
2020-11-30 14:49:02 +01:00
parent e08162fabf
commit 23d5567e72
6 changed files with 64 additions and 3 deletions
+7 -1
View File
@@ -78,7 +78,13 @@ Configuration::Configuration(const fs::path& config_path,
// their defaults. At this point I'd really wish C++ could do pattern
// matching.
for (const auto& [key, value] : table) {
if (key == "editor_double_embed") {
if (key == "cache_time_info") {
if (const auto parsed_value = value.as_boolean()) {
cache_time_info = parsed_value->get();
} else {
invalid_options.push_back(key);
}
} else if (key == "editor_double_embed") {
if (const auto parsed_value = value.as_boolean()) {
editor_double_embed = parsed_value->get();
} else {
+17 -2
View File
@@ -74,8 +74,22 @@ class Configuration {
const boost::filesystem::path& yabridge_path);
/**
* If this is set to true, then the plugin editor should be embedded in yet
* another window. This would result in an embedding sequence of
* If set to `true`, then after an `audioMasterGetTime()` call all
* subsequent calls to that function during a single processing cycle will
* reuse the results from the first call. In theory it would be a bug on the
* host's side if this did _not_ return the same value every time, but since
* yabridge tries to not have any behaviour of its own and since this
* function should only be called at most once every processing cycle this
* option is not enabled by default. An example of a situation where this
* does become necessary is the SWAM Cello plugin, which calls
* `audioMasterGetTime()` for every sample instead of only once. This would
* tank performance without this caching behaviour.
*/
bool cache_time_info = false;
/**
* If this is set to `true`, then the plugin editor should be embedded in
* yet another window. This would result in an embedding sequence of
* `<window_provided_by_host> <-> <wine_parent_window> <->
* <wine_child_window> <-> <window_created_by_plugin>`, where
* `<wine_child_window>` is the new addition. The only plugin I've
@@ -119,6 +133,7 @@ class Configuration {
template <typename S>
void serialize(S& s) {
s.value1b(cache_time_info);
s.value1b(editor_double_embed);
s.ext(group, bitsery::ext::StdOptional(),
[](S& s, auto& v) { s.text1b(v, 4096); });
+3
View File
@@ -653,6 +653,9 @@ void PluginBridge::log_init_message() {
init_msg << "other options: ";
std::vector<std::string> other_options;
if (config.cache_time_info) {
other_options.push_back("hack: time info cache");
}
if (config.editor_double_embed) {
other_options.push_back("editor: double embed");
}
+18
View File
@@ -169,6 +169,15 @@ Vst2Bridge::Vst2Bridge(MainContext& main_context,
// pointers to rather than copies of the events.
std::lock_guard lock(next_buffer_midi_events_mutex);
// HACK: Workaround for a bug in SWAM Cello where it would call
// `audioMasterGetTime()` once for every sample. The first
// value returned by this function during an audio
// processing cycle will be reused for the rest of the
// cycle.
if (config.cache_time_info) {
time_info.reset();
}
// Since the host should only be calling one of `process()`,
// processReplacing()` or `processDoubleReplacing()`, we can all
// handle them over the same socket. We pick which one to call
@@ -505,6 +514,15 @@ intptr_t Vst2Bridge::host_callback(AEffect* effect,
intptr_t value,
void* data,
float option) {
// HACK: Workaround for a bug in SWAM Cello where it would call
// `audioMasterGetTime()` once for every sample. When this option is
// enabled `time_info` should be reset in the process function. The
// `time_info` value is assigned inside of
// `HostCallbackDataConverter::write()`.
if (config.cache_time_info && time_info) {
return reinterpret_cast<intptr_t>(&*time_info);
}
HostCallbackDataConverter converter(effect, time_info);
return sockets.vst_host_callback.send_event(converter, std::nullopt, opcode,
index, value, data, option);