Add voice ID fields for all non-MIDI note events
This will be useful when adding polyphonic modulation.
This commit is contained in:
parent
f11b3c1a03
commit
a2f8a9bebf
|
@ -11,6 +11,7 @@ code then it will not be listed here.
|
|||
- The `CLAP_DESCRIPTION`, `CLAP_MANUAL_URL`, and `CLAP_SUPPORT_URL` associated
|
||||
constants from the `ClapPlugin` are now optional and have the type
|
||||
`Option<&'static str>` instead of `&'static str`.
|
||||
- Most `NoteEvent` variants now have an additional `voice_id` field.
|
||||
|
||||
## [2022-07-02]
|
||||
|
||||
|
|
|
@ -49,99 +49,117 @@ impl Plugin for MidiInverter {
|
|||
match event {
|
||||
NoteEvent::NoteOn {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
velocity,
|
||||
} => context.send_event(NoteEvent::NoteOn {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
velocity: 1.0 - velocity,
|
||||
}),
|
||||
NoteEvent::NoteOff {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
velocity,
|
||||
} => context.send_event(NoteEvent::NoteOff {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
velocity: 1.0 - velocity,
|
||||
}),
|
||||
NoteEvent::PolyPressure {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
pressure,
|
||||
} => context.send_event(NoteEvent::PolyPressure {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
pressure: 1.0 - pressure,
|
||||
}),
|
||||
NoteEvent::PolyVolume {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
gain,
|
||||
} => context.send_event(NoteEvent::PolyVolume {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
gain: 1.0 - gain,
|
||||
}),
|
||||
NoteEvent::PolyPan {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
pan,
|
||||
} => context.send_event(NoteEvent::PolyPan {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
pan: 1.0 - pan,
|
||||
}),
|
||||
NoteEvent::PolyTuning {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
tuning,
|
||||
} => context.send_event(NoteEvent::PolyTuning {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
tuning: 1.0 - tuning,
|
||||
}),
|
||||
NoteEvent::PolyVibrato {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
vibrato,
|
||||
} => context.send_event(NoteEvent::PolyVibrato {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
vibrato: 1.0 - vibrato,
|
||||
}),
|
||||
NoteEvent::PolyExpression {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
expression,
|
||||
} => context.send_event(NoteEvent::PolyExpression {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
expression: 1.0 - expression,
|
||||
}),
|
||||
NoteEvent::PolyBrightness {
|
||||
timing,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
brightness,
|
||||
} => context.send_event(NoteEvent::PolyBrightness {
|
||||
timing,
|
||||
voice_id,
|
||||
channel: 15 - channel,
|
||||
note: 127 - note,
|
||||
brightness: 1.0 - brightness,
|
||||
|
|
54
src/midi.rs
54
src/midi.rs
|
@ -30,6 +30,9 @@ pub enum NoteEvent {
|
|||
/// A note on event, available on [`MidiConfig::Basic`] and up.
|
||||
NoteOn {
|
||||
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.
|
||||
|
@ -41,6 +44,9 @@ pub enum NoteEvent {
|
|||
/// A note off event, available on [`MidiConfig::Basic`] and up.
|
||||
NoteOff {
|
||||
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.
|
||||
|
@ -59,6 +65,9 @@ pub enum NoteEvent {
|
|||
/// you may manually combine the polyphonic key pressure and MPE channel pressure.
|
||||
PolyPressure {
|
||||
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.
|
||||
|
@ -70,6 +79,9 @@ pub enum NoteEvent {
|
|||
/// support these expressions.
|
||||
PolyVolume {
|
||||
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.
|
||||
|
@ -81,6 +93,9 @@ pub enum NoteEvent {
|
|||
/// support these expressions.
|
||||
PolyPan {
|
||||
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.
|
||||
|
@ -93,6 +108,9 @@ pub enum NoteEvent {
|
|||
/// these expressions.
|
||||
PolyTuning {
|
||||
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.
|
||||
|
@ -104,6 +122,9 @@ pub enum NoteEvent {
|
|||
/// these expressions.
|
||||
PolyVibrato {
|
||||
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.
|
||||
|
@ -115,6 +136,9 @@ pub enum NoteEvent {
|
|||
/// [`MidiConfig::Basic`] and up. Not all hosts may support these expressions.
|
||||
PolyExpression {
|
||||
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.
|
||||
|
@ -126,6 +150,9 @@ pub enum NoteEvent {
|
|||
/// these expressions.
|
||||
PolyBrightness {
|
||||
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.
|
||||
|
@ -186,6 +213,24 @@ impl NoteEvent {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the event's voice ID, if it has any.
|
||||
pub fn voice_id(&self) -> Option<i32> {
|
||||
match &self {
|
||||
NoteEvent::NoteOn { voice_id, .. } => *voice_id,
|
||||
NoteEvent::NoteOff { voice_id, .. } => *voice_id,
|
||||
NoteEvent::PolyPressure { voice_id, .. } => *voice_id,
|
||||
NoteEvent::PolyVolume { voice_id, .. } => *voice_id,
|
||||
NoteEvent::PolyPan { voice_id, .. } => *voice_id,
|
||||
NoteEvent::PolyTuning { voice_id, .. } => *voice_id,
|
||||
NoteEvent::PolyVibrato { voice_id, .. } => *voice_id,
|
||||
NoteEvent::PolyExpression { voice_id, .. } => *voice_id,
|
||||
NoteEvent::PolyBrightness { voice_id, .. } => *voice_id,
|
||||
NoteEvent::MidiChannelPressure { .. } => None,
|
||||
NoteEvent::MidiPitchBend { .. } => None,
|
||||
NoteEvent::MidiCC { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse MIDI into a [`NoteEvent`]. Will return `Err(event_type)` if the parsing failed.
|
||||
pub fn from_midi(timing: u32, midi_data: [u8; 3]) -> Result<Self, u8> {
|
||||
// TODO: Maybe add special handling for 14-bit CCs and RPN messages at some
|
||||
|
@ -195,18 +240,21 @@ impl NoteEvent {
|
|||
match event_type {
|
||||
midi::NOTE_ON => Ok(NoteEvent::NoteOn {
|
||||
timing,
|
||||
voice_id: None,
|
||||
channel,
|
||||
note: midi_data[1],
|
||||
velocity: midi_data[2] as f32 / 127.0,
|
||||
}),
|
||||
midi::NOTE_OFF => Ok(NoteEvent::NoteOff {
|
||||
timing,
|
||||
voice_id: None,
|
||||
channel,
|
||||
note: midi_data[1],
|
||||
velocity: midi_data[2] as f32 / 127.0,
|
||||
}),
|
||||
midi::POLYPHONIC_KEY_PRESSURE => Ok(NoteEvent::PolyPressure {
|
||||
timing,
|
||||
voice_id: None,
|
||||
channel,
|
||||
note: midi_data[1],
|
||||
pressure: midi_data[2] as f32 / 127.0,
|
||||
|
@ -239,6 +287,7 @@ impl NoteEvent {
|
|||
match self {
|
||||
NoteEvent::NoteOn {
|
||||
timing: _,
|
||||
voice_id: _,
|
||||
channel,
|
||||
note,
|
||||
velocity,
|
||||
|
@ -249,6 +298,7 @@ impl NoteEvent {
|
|||
]),
|
||||
NoteEvent::NoteOff {
|
||||
timing: _,
|
||||
voice_id: _,
|
||||
channel,
|
||||
note,
|
||||
velocity,
|
||||
|
@ -259,6 +309,7 @@ impl NoteEvent {
|
|||
]),
|
||||
NoteEvent::PolyPressure {
|
||||
timing: _,
|
||||
voice_id: _,
|
||||
channel,
|
||||
note,
|
||||
pressure,
|
||||
|
@ -341,6 +392,7 @@ mod tests {
|
|||
fn test_note_on_midi_conversion() {
|
||||
let event = NoteEvent::NoteOn {
|
||||
timing: TIMING,
|
||||
voice_id: None,
|
||||
channel: 1,
|
||||
note: 2,
|
||||
// The value will be rounded in the conversion to MIDI, hence this overly specific value
|
||||
|
@ -357,6 +409,7 @@ mod tests {
|
|||
fn test_note_off_midi_conversion() {
|
||||
let event = NoteEvent::NoteOff {
|
||||
timing: TIMING,
|
||||
voice_id: None,
|
||||
channel: 1,
|
||||
note: 2,
|
||||
velocity: 0.6929134,
|
||||
|
@ -372,6 +425,7 @@ mod tests {
|
|||
fn test_poly_pressure_midi_conversion() {
|
||||
let event = NoteEvent::PolyPressure {
|
||||
timing: TIMING,
|
||||
voice_id: None,
|
||||
channel: 1,
|
||||
note: 2,
|
||||
pressure: 0.6929134,
|
||||
|
|
|
@ -909,6 +909,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
let push_successful = match event {
|
||||
NoteEvent::NoteOn {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
velocity,
|
||||
|
@ -922,7 +923,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
// We don't have a way to denote live events
|
||||
flags: 0,
|
||||
},
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -933,6 +934,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
NoteEvent::NoteOff {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
velocity,
|
||||
|
@ -945,7 +947,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
type_: CLAP_EVENT_NOTE_OFF,
|
||||
flags: 0,
|
||||
},
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -956,6 +958,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
NoteEvent::PolyPressure {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
pressure,
|
||||
|
@ -969,7 +972,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
flags: 0,
|
||||
},
|
||||
expression_id: CLAP_NOTE_EXPRESSION_PRESSURE,
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -980,6 +983,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
NoteEvent::PolyVolume {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
gain,
|
||||
|
@ -993,7 +997,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
flags: 0,
|
||||
},
|
||||
expression_id: CLAP_NOTE_EXPRESSION_VOLUME,
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -1004,6 +1008,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
NoteEvent::PolyPan {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
pan,
|
||||
|
@ -1017,7 +1022,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
flags: 0,
|
||||
},
|
||||
expression_id: CLAP_NOTE_EXPRESSION_PAN,
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -1028,6 +1033,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
NoteEvent::PolyTuning {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
tuning,
|
||||
|
@ -1041,7 +1047,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
flags: 0,
|
||||
},
|
||||
expression_id: CLAP_NOTE_EXPRESSION_TUNING,
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -1052,6 +1058,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
NoteEvent::PolyVibrato {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
vibrato,
|
||||
|
@ -1065,7 +1072,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
flags: 0,
|
||||
},
|
||||
expression_id: CLAP_NOTE_EXPRESSION_VIBRATO,
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -1076,6 +1083,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
NoteEvent::PolyExpression {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
expression,
|
||||
|
@ -1089,7 +1097,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
flags: 0,
|
||||
},
|
||||
expression_id: CLAP_NOTE_EXPRESSION_EXPRESSION,
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -1100,6 +1108,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
}
|
||||
NoteEvent::PolyBrightness {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
brightness,
|
||||
|
@ -1113,7 +1122,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
flags: 0,
|
||||
},
|
||||
expression_id: CLAP_NOTE_EXPRESSION_BRIGHTNESS,
|
||||
note_id: -1,
|
||||
note_id: voice_id.unwrap_or(-1),
|
||||
port_index: 0,
|
||||
channel: channel as i16,
|
||||
key: note as i16,
|
||||
|
@ -1264,6 +1273,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
// When splitting up the buffer for sample accurate automation all events
|
||||
// should be relative to the block
|
||||
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,
|
||||
velocity: event.velocity as f32,
|
||||
|
@ -1277,6 +1291,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
let event = &*(event as *const clap_event_note);
|
||||
input_events.push_back(NoteEvent::NoteOff {
|
||||
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,
|
||||
velocity: event.velocity as f32,
|
||||
|
@ -1293,6 +1312,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
CLAP_NOTE_EXPRESSION_PRESSURE => {
|
||||
input_events.push_back(NoteEvent::PolyPressure {
|
||||
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,
|
||||
pressure: event.value as f32,
|
||||
|
@ -1301,6 +1325,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
CLAP_NOTE_EXPRESSION_VOLUME => {
|
||||
input_events.push_back(NoteEvent::PolyVolume {
|
||||
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,
|
||||
gain: event.value as f32,
|
||||
|
@ -1309,6 +1338,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
CLAP_NOTE_EXPRESSION_PAN => {
|
||||
input_events.push_back(NoteEvent::PolyPan {
|
||||
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,
|
||||
// In CLAP this value goes from [0, 1] instead of [-1, 1]
|
||||
|
@ -1318,6 +1352,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
CLAP_NOTE_EXPRESSION_TUNING => {
|
||||
input_events.push_back(NoteEvent::PolyTuning {
|
||||
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,
|
||||
tuning: event.value as f32,
|
||||
|
@ -1326,6 +1365,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
CLAP_NOTE_EXPRESSION_VIBRATO => {
|
||||
input_events.push_back(NoteEvent::PolyVibrato {
|
||||
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,
|
||||
vibrato: event.value as f32,
|
||||
|
@ -1334,6 +1378,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
CLAP_NOTE_EXPRESSION_EXPRESSION => {
|
||||
input_events.push_back(NoteEvent::PolyExpression {
|
||||
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,
|
||||
expression: event.value as f32,
|
||||
|
@ -1342,6 +1391,11 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
CLAP_NOTE_EXPRESSION_BRIGHTNESS => {
|
||||
input_events.push_back(NoteEvent::PolyBrightness {
|
||||
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,
|
||||
brightness: event.value as f32,
|
||||
|
|
|
@ -105,7 +105,8 @@ impl NoteExpressionController {
|
|||
timing: u32,
|
||||
event: &NoteExpressionValueEvent,
|
||||
) -> Option<NoteEvent> {
|
||||
let (_, note, channel) = *self
|
||||
// We're calling it a voice ID, VST3 (and CLAP) calls it a note ID
|
||||
let (note_id, note, channel) = *self
|
||||
.note_ids
|
||||
.iter()
|
||||
.find(|(note_id, _, _)| *note_id == event.note_id)?;
|
||||
|
@ -113,6 +114,7 @@ impl NoteExpressionController {
|
|||
match event.type_id {
|
||||
VOLUME_EXPRESSION_ID => Some(NoteEvent::PolyVolume {
|
||||
timing,
|
||||
voice_id: Some(note_id),
|
||||
channel,
|
||||
note,
|
||||
// Because expression values in VST3 are always in the `[0, 1]` range, they added a
|
||||
|
@ -121,6 +123,7 @@ impl NoteExpressionController {
|
|||
}),
|
||||
PAN_EXPRESSION_ID => Some(NoteEvent::PolyPan {
|
||||
timing,
|
||||
voice_id: Some(note_id),
|
||||
channel,
|
||||
note,
|
||||
// Our panning expressions are symmetrical around 0
|
||||
|
@ -128,6 +131,7 @@ impl NoteExpressionController {
|
|||
}),
|
||||
TUNING_EXPRESSION_ID => Some(NoteEvent::PolyTuning {
|
||||
timing,
|
||||
voice_id: Some(note_id),
|
||||
channel,
|
||||
note,
|
||||
// This denormalized to the same [-120, 120] range used by CLAP and our expression
|
||||
|
@ -136,18 +140,21 @@ impl NoteExpressionController {
|
|||
}),
|
||||
VIBRATO_EXPRESSION_ID => Some(NoteEvent::PolyVibrato {
|
||||
timing,
|
||||
voice_id: Some(note_id),
|
||||
channel,
|
||||
note,
|
||||
vibrato: event.value as f32,
|
||||
}),
|
||||
EXPRESSION_EXPRESSION_ID => Some(NoteEvent::PolyBrightness {
|
||||
timing,
|
||||
voice_id: Some(note_id),
|
||||
channel,
|
||||
note,
|
||||
brightness: event.value as f32,
|
||||
}),
|
||||
BRIGHTNESS_EXPRESSION_ID => Some(NoteEvent::PolyExpression {
|
||||
timing,
|
||||
voice_id: Some(note_id),
|
||||
channel,
|
||||
note,
|
||||
expression: event.value as f32,
|
||||
|
|
|
@ -1162,6 +1162,11 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
|
|||
timing,
|
||||
event: NoteEvent::NoteOn {
|
||||
timing,
|
||||
voice_id: if event.note_id != -1 {
|
||||
Some(event.note_id)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
channel: event.channel as u8,
|
||||
note: event.pitch as u8,
|
||||
velocity: event.velocity,
|
||||
|
@ -1173,6 +1178,11 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
|
|||
timing,
|
||||
event: NoteEvent::NoteOff {
|
||||
timing,
|
||||
voice_id: if event.note_id != -1 {
|
||||
Some(event.note_id)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
channel: event.channel as u8,
|
||||
note: event.pitch as u8,
|
||||
velocity: event.velocity,
|
||||
|
@ -1184,6 +1194,11 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
|
|||
timing,
|
||||
event: NoteEvent::PolyPressure {
|
||||
timing,
|
||||
voice_id: if event.note_id != -1 {
|
||||
Some(event.note_id)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
channel: event.channel as u8,
|
||||
note: event.pitch as u8,
|
||||
pressure: event.pressure,
|
||||
|
@ -1531,9 +1546,13 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
|
|||
// There's also a ppqPos field, but uh how about no
|
||||
vst3_event.sample_offset = event.timing() as i32 + block_start as i32;
|
||||
|
||||
// `voice_id.onwrap_or(|| ...)` triggers
|
||||
// https://github.com/rust-lang/rust-clippy/issues/8522
|
||||
#[allow(clippy::unnecessary_lazy_evaluations)]
|
||||
match event {
|
||||
NoteEvent::NoteOn {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
velocity,
|
||||
|
@ -1547,11 +1566,13 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
|
|||
length: 0, // What?
|
||||
// We'll use this for our note IDs, that way we don't have
|
||||
// to do anything complicated here
|
||||
note_id: ((channel as i32) << 8) | note as i32,
|
||||
note_id: voice_id
|
||||
.unwrap_or_else(|| ((channel as i32) << 8) | note as i32),
|
||||
};
|
||||
}
|
||||
NoteEvent::NoteOff {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
velocity,
|
||||
|
@ -1561,12 +1582,14 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
|
|||
channel: channel as i16,
|
||||
pitch: note as i16,
|
||||
velocity,
|
||||
note_id: ((channel as i32) << 8) | note as i32,
|
||||
note_id: voice_id
|
||||
.unwrap_or_else(|| ((channel as i32) << 8) | note as i32),
|
||||
tuning: 0.0,
|
||||
};
|
||||
}
|
||||
NoteEvent::PolyPressure {
|
||||
timing: _,
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
pressure,
|
||||
|
@ -1575,20 +1598,50 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
|
|||
vst3_event.event.poly_pressure = PolyPressureEvent {
|
||||
channel: channel as i16,
|
||||
pitch: note as i16,
|
||||
note_id: ((channel as i32) << 8) | note as i32,
|
||||
note_id: voice_id
|
||||
.unwrap_or_else(|| ((channel as i32) << 8) | note as i32),
|
||||
pressure,
|
||||
};
|
||||
}
|
||||
event @ (NoteEvent::PolyVolume { channel, note, .. }
|
||||
| NoteEvent::PolyPan { channel, note, .. }
|
||||
| NoteEvent::PolyTuning { channel, note, .. }
|
||||
| NoteEvent::PolyVibrato { channel, note, .. }
|
||||
| NoteEvent::PolyExpression { channel, note, .. }
|
||||
| NoteEvent::PolyBrightness { channel, note, .. })
|
||||
if P::MIDI_OUTPUT >= MidiConfig::Basic =>
|
||||
{
|
||||
event @ (NoteEvent::PolyVolume {
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
..
|
||||
}
|
||||
| NoteEvent::PolyPan {
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
..
|
||||
}
|
||||
| NoteEvent::PolyTuning {
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
..
|
||||
}
|
||||
| NoteEvent::PolyVibrato {
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
..
|
||||
}
|
||||
| NoteEvent::PolyExpression {
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
..
|
||||
}
|
||||
| NoteEvent::PolyBrightness {
|
||||
voice_id,
|
||||
channel,
|
||||
note,
|
||||
..
|
||||
}) if P::MIDI_OUTPUT >= MidiConfig::Basic => {
|
||||
match NoteExpressionController::translate_event_reverse(
|
||||
((channel as i32) << 8) | note as i32,
|
||||
voice_id
|
||||
.unwrap_or_else(|| ((channel as i32) << 8) | note as i32),
|
||||
&event,
|
||||
) {
|
||||
Some(translated_event) => {
|
||||
|
|
Loading…
Reference in a new issue