1
0
Fork 0

Add note choke events

This commit is contained in:
Robbert van der Helm 2022-07-04 22:42:04 +02:00
parent d027a6319f
commit 5b264179d4
3 changed files with 48 additions and 11 deletions

View file

@ -8,6 +8,9 @@ code then it will not be listed here.
## [2022-07-04] ## [2022-07-04]
- There is a new `NoteEvent::Choke` event the host can send to a plugin to let
it know that it should immediately terminate all sound associated with a voice
or a key.
- There is a new `NoteEvent::VoiceTerminated` event to let the host know a voice - There is a new `NoteEvent::VoiceTerminated` event to let the host know a voice
has been terminated. This needs to be output by CLAP plugins that support has been terminated. This needs to be output by CLAP plugins that support
polyphonic modulation. polyphonic modulation.

View file

@ -9,10 +9,10 @@ pub use midi_consts::channel_event::control_change;
pub enum MidiConfig { pub enum MidiConfig {
/// The plugin will not have a note input port and will thus not receive any not events. /// The plugin will not have a note input port and will thus not receive any not events.
None, None,
/// The plugin receives note on/off events, pressure, and potentially a couple standardized /// The plugin receives note on/off/choke events, pressure, and potentially a couple
/// expression types depending on the plugin standard and host. If the plugin sets up /// standardized expression types depending on the plugin standard and host. If the plugin sets
/// configuration for polyphonic modulation (see [`ClapPlugin`][crate::prelude::ClapPlugin]) and /// up configuration for polyphonic modulation (see [`ClapPlugin`][crate::prelude::ClapPlugin])
/// assigns polyphonic modulation IDs to some of its parameters, then it will also receive /// and assigns polyphonic modulation IDs to some of its parameters, then it will also receive
/// polyphonic modulation events. /// polyphonic modulation events.
Basic, Basic,
/// The plugin receives full MIDI CCs as well as pitch bend information. For VST3 plugins this /// The plugin receives full MIDI CCs as well as pitch bend information. For VST3 plugins this
@ -58,6 +58,19 @@ pub enum NoteEvent {
/// 127 levels available in MIDI. /// 127 levels available in MIDI.
velocity: f32, velocity: f32,
}, },
/// A note choke event, available on [`MidiConfig::Basic`] and up. When the host sends this to
/// the plugin, it indicates that a voice or all sound associated with a note should immediately
/// stop playing.
Choke {
timing: u32,
/// A unique identifier for this note, if available. Using this to refer to a note is
/// required when allowing overlapping voices for CLAP plugins.
voice_id: Option<i32>,
/// The note's channel, from 0 to 16.
channel: u8,
/// The note's MIDI key number, from 0 to 127.
note: u8,
},
/// Sent by the plugin to the host to indicate that a voice has ended. This **needs** to be sent /// Sent by the plugin to the host to indicate that a voice has ended. This **needs** to be sent
/// when a voice terminates when using polyphonic modulation. Otherwise you can ignore this /// when a voice terminates when using polyphonic modulation. Otherwise you can ignore this
/// event. /// event.
@ -216,6 +229,7 @@ impl NoteEvent {
match &self { match &self {
NoteEvent::NoteOn { timing, .. } => *timing, NoteEvent::NoteOn { timing, .. } => *timing,
NoteEvent::NoteOff { timing, .. } => *timing, NoteEvent::NoteOff { timing, .. } => *timing,
NoteEvent::Choke { timing, .. } => *timing,
NoteEvent::VoiceTerminated { timing, .. } => *timing, NoteEvent::VoiceTerminated { timing, .. } => *timing,
NoteEvent::PolyPressure { timing, .. } => *timing, NoteEvent::PolyPressure { timing, .. } => *timing,
NoteEvent::PolyVolume { timing, .. } => *timing, NoteEvent::PolyVolume { timing, .. } => *timing,
@ -235,6 +249,7 @@ impl NoteEvent {
match &self { match &self {
NoteEvent::NoteOn { voice_id, .. } => *voice_id, NoteEvent::NoteOn { voice_id, .. } => *voice_id,
NoteEvent::NoteOff { voice_id, .. } => *voice_id, NoteEvent::NoteOff { voice_id, .. } => *voice_id,
NoteEvent::Choke { voice_id, .. } => *voice_id,
NoteEvent::VoiceTerminated { voice_id, .. } => *voice_id, NoteEvent::VoiceTerminated { voice_id, .. } => *voice_id,
NoteEvent::PolyPressure { voice_id, .. } => *voice_id, NoteEvent::PolyPressure { voice_id, .. } => *voice_id,
NoteEvent::PolyVolume { voice_id, .. } => *voice_id, NoteEvent::PolyVolume { voice_id, .. } => *voice_id,
@ -371,7 +386,8 @@ impl NoteEvent {
cc, cc,
(value * 127.0).round().clamp(0.0, 127.0) as u8, (value * 127.0).round().clamp(0.0, 127.0) as u8,
]), ]),
NoteEvent::VoiceTerminated { .. } NoteEvent::Choke { .. }
| NoteEvent::VoiceTerminated { .. }
| NoteEvent::PolyVolume { .. } | NoteEvent::PolyVolume { .. }
| NoteEvent::PolyPan { .. } | NoteEvent::PolyPan { .. }
| NoteEvent::PolyTuning { .. } | NoteEvent::PolyTuning { .. }
@ -387,6 +403,7 @@ impl NoteEvent {
match self { match self {
NoteEvent::NoteOn { timing, .. } => *timing -= samples, NoteEvent::NoteOn { timing, .. } => *timing -= samples,
NoteEvent::NoteOff { timing, .. } => *timing -= samples, NoteEvent::NoteOff { timing, .. } => *timing -= samples,
NoteEvent::Choke { timing, .. } => *timing -= samples,
NoteEvent::VoiceTerminated { timing, .. } => *timing -= samples, NoteEvent::VoiceTerminated { timing, .. } => *timing -= samples,
NoteEvent::PolyPressure { timing, .. } => *timing -= samples, NoteEvent::PolyPressure { timing, .. } => *timing -= samples,
NoteEvent::PolyVolume { timing, .. } => *timing -= samples, NoteEvent::PolyVolume { timing, .. } => *timing -= samples,

View file

@ -4,12 +4,12 @@ use clap_sys::events::{
clap_event_header, clap_event_midi, clap_event_note, clap_event_note_expression, clap_event_header, clap_event_midi, clap_event_note, clap_event_note_expression,
clap_event_param_gesture, clap_event_param_mod, clap_event_param_value, clap_event_transport, clap_event_param_gesture, clap_event_param_mod, clap_event_param_value, clap_event_transport,
clap_input_events, clap_output_events, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_IS_LIVE, clap_input_events, clap_output_events, CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_IS_LIVE,
CLAP_EVENT_MIDI, CLAP_EVENT_NOTE_END, CLAP_EVENT_NOTE_EXPRESSION, CLAP_EVENT_NOTE_OFF, CLAP_EVENT_MIDI, CLAP_EVENT_NOTE_CHOKE, CLAP_EVENT_NOTE_END, CLAP_EVENT_NOTE_EXPRESSION,
CLAP_EVENT_NOTE_ON, CLAP_EVENT_PARAM_GESTURE_BEGIN, CLAP_EVENT_PARAM_GESTURE_END, CLAP_EVENT_NOTE_OFF, CLAP_EVENT_NOTE_ON, CLAP_EVENT_PARAM_GESTURE_BEGIN,
CLAP_EVENT_PARAM_MOD, CLAP_EVENT_PARAM_VALUE, CLAP_EVENT_TRANSPORT, CLAP_EVENT_PARAM_GESTURE_END, CLAP_EVENT_PARAM_MOD, CLAP_EVENT_PARAM_VALUE,
CLAP_NOTE_EXPRESSION_BRIGHTNESS, CLAP_NOTE_EXPRESSION_EXPRESSION, CLAP_NOTE_EXPRESSION_PAN, CLAP_EVENT_TRANSPORT, CLAP_NOTE_EXPRESSION_BRIGHTNESS, CLAP_NOTE_EXPRESSION_EXPRESSION,
CLAP_NOTE_EXPRESSION_PRESSURE, CLAP_NOTE_EXPRESSION_TUNING, CLAP_NOTE_EXPRESSION_VIBRATO, CLAP_NOTE_EXPRESSION_PAN, CLAP_NOTE_EXPRESSION_PRESSURE, CLAP_NOTE_EXPRESSION_TUNING,
CLAP_NOTE_EXPRESSION_VOLUME, CLAP_TRANSPORT_HAS_BEATS_TIMELINE, CLAP_NOTE_EXPRESSION_VIBRATO, CLAP_NOTE_EXPRESSION_VOLUME, CLAP_TRANSPORT_HAS_BEATS_TIMELINE,
CLAP_TRANSPORT_HAS_SECONDS_TIMELINE, CLAP_TRANSPORT_HAS_TEMPO, 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_HAS_TIME_SIGNATURE, CLAP_TRANSPORT_IS_LOOP_ACTIVE, CLAP_TRANSPORT_IS_PLAYING,
CLAP_TRANSPORT_IS_RECORDING, CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL, CLAP_TRANSPORT_IS_RECORDING, CLAP_TRANSPORT_IS_WITHIN_PRE_ROLL,
@ -1328,6 +1328,23 @@ impl<P: ClapPlugin> Wrapper<P> {
false false
} }
(CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_CHOKE) => {
if P::MIDI_INPUT >= MidiConfig::Basic {
let event = &*(event as *const clap_event_note);
input_events.push_back(NoteEvent::Choke {
timing: raw_event.time - current_sample_idx as u32,
voice_id: if event.note_id != -1 {
Some(event.note_id)
} else {
None
},
channel: event.channel as u8,
note: event.key as u8,
});
}
false
}
(CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_EXPRESSION) => { (CLAP_CORE_EVENT_SPACE_ID, CLAP_EVENT_NOTE_EXPRESSION) => {
if P::MIDI_INPUT >= MidiConfig::Basic { if P::MIDI_INPUT >= MidiConfig::Basic {
// TODO: Add support for the other expression types // TODO: Add support for the other expression types