diff --git a/CHANGELOG.md b/CHANGELOG.md index e4df291e..79373e61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ Versioning](https://semver.org/spec/v2.0.0.html). at configure-time. This can make it a bit easier to diagnose Wine-related compilation issues. +### Fixed + +- Prevent _Native Instruments' FM7_ from crashing when processing MIDI. As a + fix, MIDI events are now deallocated later then when they normally would have + to be. + ## [3.1.0] - 2021-04-15 ### Added diff --git a/src/wine-host/bridges/vst2.cpp b/src/wine-host/bridges/vst2.cpp index c660098c..1c47ca82 100644 --- a/src/wine-host/bridges/vst2.cpp +++ b/src/wine-host/bridges/vst2.cpp @@ -278,7 +278,9 @@ Vst2Bridge::Vst2Bridge(MainContext& main_context, }}, request.buffers); - next_audio_buffer_midi_events.clear(); + // See the docstrong on `should_clear_midi_events` for why we + // don't just clear `next_buffer_midi_events` here + should_clear_midi_events = true; }); }); } @@ -303,6 +305,14 @@ void Vst2Bridge::run() { // plugin. std::lock_guard lock(next_buffer_midi_events_mutex); + // See the docstring on `should_clear_midi_events` for why we + // only deallocate old MIDI events here instead of a at the end + // of every processing cycle + if (should_clear_midi_events) { + next_audio_buffer_midi_events.clear(); + should_clear_midi_events = false; + } + next_audio_buffer_midi_events.push_back( std::get(event.payload)); DynamicVstEvents& events = next_audio_buffer_midi_events.back(); diff --git a/src/wine-host/bridges/vst2.h b/src/wine-host/bridges/vst2.h index 83ec6491..c765e1f1 100644 --- a/src/wine-host/bridges/vst2.h +++ b/src/wine-host/bridges/vst2.h @@ -168,6 +168,16 @@ class Vst2Bridge : public HostBridge { * at least until the next audio buffer gets processed. */ std::vector next_audio_buffer_midi_events; + /** + * Whether `next_audio_buffer_midi_events` should be cleared before + * inserting new events. + * + * HACK: Normally we should be able to clear these immediately after the + * processing call, but Native Instruments' FM7 requires the last MIDI + * event to stay alive if there have not been any new MIDI events + * during the current processing cycle. + */ + bool should_clear_midi_events = false; /** * Mutex for locking the above event queue, since recieving and processing * now happens in two different threads.