From b9a10455bb3359660cbb1bbb3a7af499c56d2148 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Thu, 7 Apr 2022 20:54:37 +0200 Subject: [PATCH] Add polyphonic aftertouch support --- plugins/examples/sine/src/lib.rs | 1 + src/plugin.rs | 19 ++++++++++++++++++- src/wrapper/clap/wrapper.rs | 30 +++++++++++++++++++++--------- src/wrapper/vst3/wrapper.rs | 10 ++++++++++ 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/plugins/examples/sine/src/lib.rs b/plugins/examples/sine/src/lib.rs index 1e87bf51..a96a329f 100644 --- a/plugins/examples/sine/src/lib.rs +++ b/plugins/examples/sine/src/lib.rs @@ -153,6 +153,7 @@ impl Plugin for Sine { self.midi_note_gain.set_target(self.sample_rate, 0.0); } } + _ => (), }, _ => break 'midi_events, } diff --git a/src/plugin.rs b/src/plugin.rs index a3a25df9..385ed30e 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -313,7 +313,8 @@ pub enum MidiConfig { Basic, // // TODO: // /// The plugin receives full MIDI CCs as well as pitch bend information. For VST3 plugins this - // /// involves adding + // /// involves adding 130*16 parameters to bind to the the 128 MIDI CCs, pitch bend, and channel + // /// pressure. // MidiCCs, } @@ -325,6 +326,7 @@ pub enum MidiConfig { /// /// TODO: Add more events as needed #[derive(Debug, Clone, Copy, PartialEq)] +#[non_exhaustive] pub enum NoteEvent { /// A note on event, available on [`MidiConfig::Basic`] and up. NoteOn { @@ -348,6 +350,20 @@ pub enum NoteEvent { /// 127 levels available in MIDI. velocity: f32, }, + /// A polyphonic note pressure/aftertouch event, available on [`MidiConfig::Basic`] and up. Not + /// all hosts may support polyphonic aftertouch. + PolyPressure { + timing: u32, + /// The note's channel, from 0 to 16. + channel: u8, + /// The note's MIDI key number, from 0 to 127. + note: u8, + /// The note's velocity, from 0 to 1. Some plugin APIs may allow higher precision than the + /// 127 levels available in MIDI. + pressure: f32, + }, + // TODO: Add the other non-CC expressions supported by Bitwig and CLAP, register VST3 note + // expressions for hosts that support those } impl NoteEvent { @@ -356,6 +372,7 @@ impl NoteEvent { match &self { NoteEvent::NoteOn { timing, .. } => *timing, NoteEvent::NoteOff { timing, .. } => *timing, + NoteEvent::PolyPressure { timing, .. } => *timing, } } } diff --git a/src/wrapper/clap/wrapper.rs b/src/wrapper/clap/wrapper.rs index f75292da..0d5df6d6 100644 --- a/src/wrapper/clap/wrapper.rs +++ b/src/wrapper/clap/wrapper.rs @@ -5,11 +5,12 @@ use atomic_float::AtomicF32; use atomic_refcell::{AtomicRefCell, AtomicRefMut}; use clap_sys::events::{ - clap_event_header, clap_event_note, clap_event_param_gesture, clap_event_param_value, - clap_event_type, clap_input_events, clap_output_events, CLAP_CORE_EVENT_SPACE_ID, - CLAP_EVENT_IS_LIVE, CLAP_EVENT_MIDI, CLAP_EVENT_NOTE_EXPRESSION, CLAP_EVENT_NOTE_OFF, - CLAP_EVENT_NOTE_ON, CLAP_EVENT_PARAM_GESTURE_BEGIN, CLAP_EVENT_PARAM_GESTURE_END, - CLAP_EVENT_PARAM_VALUE, CLAP_TRANSPORT_HAS_BEATS_TIMELINE, CLAP_TRANSPORT_HAS_SECONDS_TIMELINE, + clap_event_header, clap_event_note, clap_event_note_expression, clap_event_param_gesture, + clap_event_param_value, clap_event_type, clap_input_events, clap_output_events, + CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_IS_LIVE, CLAP_EVENT_MIDI, CLAP_EVENT_NOTE_EXPRESSION, + CLAP_EVENT_NOTE_OFF, CLAP_EVENT_NOTE_ON, CLAP_EVENT_PARAM_GESTURE_BEGIN, + CLAP_EVENT_PARAM_GESTURE_END, CLAP_EVENT_PARAM_VALUE, CLAP_NOTE_EXPRESSION_PRESSURE, + CLAP_TRANSPORT_HAS_BEATS_TIMELINE, CLAP_TRANSPORT_HAS_SECONDS_TIMELINE, CLAP_TRANSPORT_HAS_TEMPO, CLAP_TRANSPORT_HAS_TIME_SIGNATURE, CLAP_TRANSPORT_IS_LOOP_ACTIVE, CLAP_TRANSPORT_IS_PLAYING, CLAP_TRANSPORT_IS_RECORDING, CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL, }; @@ -898,9 +899,20 @@ impl Wrapper

{ } (CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_EXPRESSION) => { if P::MIDI_INPUT >= MidiConfig::Basic { - // We currently don't report supporting this at all in the event filter, add that once - // we support MIDI CCs - // TODO: Implement pressure and other expressions along with MIDI CCs + // TODO: Add support for the other expression types + let event = &*(event as *const clap_event_note_expression); + match event.expression_id { + CLAP_NOTE_EXPRESSION_PRESSURE => { + input_events.push_back(NoteEvent::PolyPressure { + timing: raw_event.time - current_sample_idx as u32, + channel: event.channel as u8, + note: event.key as u8, + pressure: event.value as f32, + }); + dbg!(event.value); + } + n => nih_debug_assert_failure!("Unhandled note expression ID {}", n), + } } false @@ -1617,8 +1629,8 @@ impl Wrapper

{ (CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_PARAM_VALUE) => true, (CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_ON) | (CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_OFF) + | (CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_EXPRESSION) // TODO: Implement midi CC handling - // | (CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_EXPRESSION) // | (CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_MIDI) if P::MIDI_INPUT >= MidiConfig::Basic => { diff --git a/src/wrapper/vst3/wrapper.rs b/src/wrapper/vst3/wrapper.rs index 7af8b6de..c9650ded 100644 --- a/src/wrapper/vst3/wrapper.rs +++ b/src/wrapper/vst3/wrapper.rs @@ -781,6 +781,16 @@ impl IAudioProcessor for Wrapper

{ note: event.pitch as u8, velocity: event.velocity, }); + } else if event.type_ + == vst3_sys::vst::EventTypes::kPolyPressureEvent as u16 + { + let event = event.event.poly_pressure; + input_events.push_back(NoteEvent::PolyPressure { + timing, + channel: event.channel as u8, + note: event.pitch as u8, + pressure: event.pressure, + }); } } }