Add note choke events
This commit is contained in:
parent
d027a6319f
commit
5b264179d4
|
@ -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.
|
||||||
|
|
27
src/midi.rs
27
src/midi.rs
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue