From 6b700c891ecb9f1ca2e9a7e0a875fbe43baccb7a Mon Sep 17 00:00:00 2001 From: Benjamin Klum Date: Mon, 26 Feb 2024 11:10:42 +0100 Subject: [PATCH] Playtime: Make loop end MIDI reset messages work and don't make loop reset messages part of the default --- base/src/tracing_util.rs | 8 ++++ playtime-api/src/persistence/mod.rs | 62 +++++++++++++++++++++++------ playtime-clip-engine | 2 +- 3 files changed, 58 insertions(+), 14 deletions(-) diff --git a/base/src/tracing_util.rs b/base/src/tracing_util.rs index f043edffb..e8b1ac003 100644 --- a/base/src/tracing_util.rs +++ b/base/src/tracing_util.rs @@ -1,3 +1,4 @@ +use std::error::Error; use std::fmt::Display; pub fn ok_or_log_as_warn(result: Result) -> Option { @@ -9,3 +10,10 @@ pub fn ok_or_log_as_warn(result: Result) -> Option { } } } + +pub fn log_if_error(result: Result>) { + if let Err(error) = result { + let error = error.as_ref(); + tracing::error!(msg = "Error", error); + } +} diff --git a/playtime-api/src/persistence/mod.rs b/playtime-api/src/persistence/mod.rs index 62ebfec30..58bdc1378 100644 --- a/playtime-api/src/persistence/mod.rs +++ b/playtime-api/src/persistence/mod.rs @@ -1259,14 +1259,43 @@ impl Default for ClipAudioSettings { #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] pub struct ClipMidiSettings { - /// For fixing the source itself. - pub source_reset_settings: MidiResetMessageRange, - /// For fine-tuning the section. - pub section_reset_settings: MidiResetMessageRange, + /// For fine-tuning instant start/stop of a MIDI clip when in the middle of the source or section. + /// + /// - The left interaction reset messages are sent whenever resuming after pause. + /// - The right interaction reset messages are sent at immediate stops/retriggers or quantized stops/retriggers. + /// They are *not* sent on stops when the stop timing is "Until end of clip" (in this case, either section or + /// source reset settings take effect). + pub interaction_reset_settings: MidiResetMessageRange, /// For fine-tuning the complete loop. + /// + /// - The left loop reset messages are sent when the loop starts from the beginning. + /// - The right loop reset messages are sent when the loop ends naturally (without immediate or quantized stop + /// interaction). + /// + /// This exists separately from the source/section reset settings because one might want to do just a light or + /// no reset at loop boundaries but a harder reset when the complete loop starts/ends (naturally). pub loop_reset_settings: MidiResetMessageRange, - /// For fine-tuning instant start/stop of a MIDI clip when in the middle of a source or section. - pub interaction_reset_settings: MidiResetMessageRange, + /// For fine-tuning the section. + /// + /// - The left section reset messages are sent when a section start position > 0 is defined and playback starts + /// from the beginning. + /// - The right section reset messages are sent when a section length is defined (= source length constrained) + /// and playback stops naturally (without immediate or quantized stop interaction) at the ending. + /// - If the clip is looped, the messages will be sent at each loop cycle. + pub section_reset_settings: MidiResetMessageRange, + /// For fixing the source itself. + /// + /// - The left source reset messages are sent when section start position == 0 and playback starts + /// from the beginning. + /// - The right source reset messages are sent when no section length is defined (= source length unconstrained) + /// and playback stops naturally (without immediate or quantized stop interaction) at the ending. + /// - If the clip is looped, the messages will be sent at *each* loop cycle. + /// + /// This exists separately from the section reset settings because one might prefer using the original MIDI + /// sequence with less reset logic when playing without section. After all, the source itself might already + /// be perfect as it is. But as soon as we introduce a section, this is not guaranteed anymore and introducing + /// reset messages almost always makes sense. + pub source_reset_settings: MidiResetMessageRange, } impl Default for ClipMidiSettings { @@ -1277,17 +1306,20 @@ impl Default for ClipMidiSettings { impl ClipMidiSettings { pub const NONE: Self = Self { - source_reset_settings: MidiResetMessageRange::NONE, - section_reset_settings: MidiResetMessageRange::NONE, - loop_reset_settings: MidiResetMessageRange::NONE, interaction_reset_settings: MidiResetMessageRange::NONE, + loop_reset_settings: MidiResetMessageRange::NONE, + section_reset_settings: MidiResetMessageRange::NONE, + source_reset_settings: MidiResetMessageRange::NONE, }; pub const RIGHT_LIGHT: Self = Self { - source_reset_settings: MidiResetMessageRange::RIGHT_LIGHT, - section_reset_settings: MidiResetMessageRange::RIGHT_LIGHT, - loop_reset_settings: MidiResetMessageRange::RIGHT_LIGHT, interaction_reset_settings: MidiResetMessageRange::RIGHT_LIGHT, + // Source and section resets are applied in a mutually exclusive manner but loop resets are + // applied in addition to them. So no need to define them if they don't do more than the source/section + // resets. + loop_reset_settings: MidiResetMessageRange::NONE, + section_reset_settings: MidiResetMessageRange::RIGHT_LIGHT, + source_reset_settings: MidiResetMessageRange::RIGHT_LIGHT, }; } @@ -1313,12 +1345,16 @@ impl MidiResetMessageRange { #[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)] pub struct MidiResetMessages { - /// Only supported at "right" position at the moment. + /// Sends note-off events for all notes that are currently playing in this clip. #[serde(default)] pub on_notes_off: bool, + /// Sends MIDI CC 123 (all-notes-off). pub all_notes_off: bool, + /// Sends MIDI CC 120 (all-sound-off). pub all_sound_off: bool, + /// Sends MIDI CC121 (reset-all-controllers). pub reset_all_controllers: bool, + /// Sends CC64 value 0 (damper-pedal-off). pub damper_pedal_off: bool, } diff --git a/playtime-clip-engine b/playtime-clip-engine index 82f8a0897..63f5bb0c7 160000 --- a/playtime-clip-engine +++ b/playtime-clip-engine @@ -1 +1 @@ -Subproject commit 82f8a089738c2a901ea373216ffa686a7e989298 +Subproject commit 63f5bb0c74ae588126dc761d4a4b043313920697