Move MIDI parsing from CLAP wrapper to NoteEvent
This commit is contained in:
parent
4e021dd0bb
commit
66f5a0e7de
2 changed files with 55 additions and 56 deletions
48
src/midi.rs
48
src/midi.rs
|
@ -1,5 +1,7 @@
|
||||||
//! Constants and definitions surrounding MIDI support.
|
//! Constants and definitions surrounding MIDI support.
|
||||||
|
|
||||||
|
use midi_consts::channel_event as midi;
|
||||||
|
|
||||||
pub use midi_consts::channel_event::control_change;
|
pub use midi_consts::channel_event::control_change;
|
||||||
|
|
||||||
/// Determines which note events a plugin receives.
|
/// Determines which note events a plugin receives.
|
||||||
|
@ -184,6 +186,52 @@ impl NoteEvent {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
// point, right now the plugin has to figure it out for itself
|
||||||
|
let event_type = midi_data[0] & midi::EVENT_TYPE_MASK;
|
||||||
|
let channel = midi_data[0] & midi::MIDI_CHANNEL_MASK;
|
||||||
|
match event_type {
|
||||||
|
midi::NOTE_ON => Ok(NoteEvent::NoteOn {
|
||||||
|
timing,
|
||||||
|
channel,
|
||||||
|
note: midi_data[1],
|
||||||
|
velocity: midi_data[2] as f32 / 127.0,
|
||||||
|
}),
|
||||||
|
midi::NOTE_OFF => Ok(NoteEvent::NoteOff {
|
||||||
|
timing,
|
||||||
|
channel,
|
||||||
|
note: midi_data[1],
|
||||||
|
velocity: midi_data[2] as f32 / 127.0,
|
||||||
|
}),
|
||||||
|
midi::POLYPHONIC_KEY_PRESSURE => Ok(NoteEvent::PolyPressure {
|
||||||
|
timing,
|
||||||
|
channel,
|
||||||
|
note: midi_data[1],
|
||||||
|
pressure: midi_data[2] as f32 / 127.0,
|
||||||
|
}),
|
||||||
|
midi::CHANNEL_KEY_PRESSURE => Ok(NoteEvent::MidiChannelPressure {
|
||||||
|
timing,
|
||||||
|
channel,
|
||||||
|
pressure: midi_data[1] as f32 / 127.0,
|
||||||
|
}),
|
||||||
|
midi::PITCH_BEND_CHANGE => Ok(NoteEvent::MidiPitchBend {
|
||||||
|
timing,
|
||||||
|
channel,
|
||||||
|
value: (midi_data[1] as u16 + ((midi_data[2] as u16) << 7)) as f32
|
||||||
|
/ ((1 << 14) - 1) as f32,
|
||||||
|
}),
|
||||||
|
midi::CONTROL_CHANGE => Ok(NoteEvent::MidiCC {
|
||||||
|
timing,
|
||||||
|
channel,
|
||||||
|
cc: midi_data[1],
|
||||||
|
value: midi_data[2] as f32 / 127.0,
|
||||||
|
}),
|
||||||
|
n => Err(n),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Subtract a sample offset from this event's timing, needed to compensate for the block
|
/// Subtract a sample offset from this event's timing, needed to compensate for the block
|
||||||
/// splitting in the VST3 wrapper implementation because all events have to be read upfront.
|
/// splitting in the VST3 wrapper implementation because all events have to be read upfront.
|
||||||
pub(crate) fn subtract_timing(&mut self, samples: u32) {
|
pub(crate) fn subtract_timing(&mut self, samples: u32) {
|
||||||
|
|
|
@ -1360,63 +1360,14 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
if P::MIDI_INPUT >= MidiConfig::MidiCCs {
|
if P::MIDI_INPUT >= MidiConfig::MidiCCs {
|
||||||
let event = &*(event as *const clap_event_midi);
|
let event = &*(event as *const clap_event_midi);
|
||||||
|
|
||||||
// TODO: Maybe add special handling for 14-bit CCs and RPN messages at some
|
match NoteEvent::from_midi(
|
||||||
// point, right now the plugin has to figure it out for itself
|
raw_event.time - current_sample_idx as u32,
|
||||||
let event_type = event.data[0] & midi::EVENT_TYPE_MASK;
|
event.data,
|
||||||
let channel = event.data[0] & midi::MIDI_CHANNEL_MASK;
|
) {
|
||||||
match event_type {
|
Ok(note_event) => {
|
||||||
// Hosts shouldn't be sending this, bu twe'll handle it just in case
|
input_events.push_back(note_event);
|
||||||
midi::NOTE_ON => {
|
|
||||||
input_events.push_back(NoteEvent::NoteOn {
|
|
||||||
timing: raw_event.time - current_sample_idx as u32,
|
|
||||||
channel,
|
|
||||||
note: event.data[1],
|
|
||||||
velocity: event.data[2] as f32 / 127.0,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
// Hosts shouldn't be sending this, bu twe'll handle it just in case
|
Err(n) => nih_debug_assert_failure!("Unhandled MIDI message type {}", n),
|
||||||
midi::NOTE_OFF => {
|
|
||||||
input_events.push_back(NoteEvent::NoteOff {
|
|
||||||
timing: raw_event.time - current_sample_idx as u32,
|
|
||||||
channel,
|
|
||||||
note: event.data[1],
|
|
||||||
velocity: event.data[2] as f32 / 127.0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Hosts shouldn't be sending this, bu twe'll handle it just in case
|
|
||||||
midi::POLYPHONIC_KEY_PRESSURE => {
|
|
||||||
input_events.push_back(NoteEvent::PolyPressure {
|
|
||||||
timing: raw_event.time - current_sample_idx as u32,
|
|
||||||
channel,
|
|
||||||
note: event.data[1],
|
|
||||||
pressure: event.data[2] as f32 / 127.0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
midi::CHANNEL_KEY_PRESSURE => {
|
|
||||||
input_events.push_back(NoteEvent::MidiChannelPressure {
|
|
||||||
timing: raw_event.time - current_sample_idx as u32,
|
|
||||||
channel,
|
|
||||||
pressure: event.data[1] as f32 / 127.0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
midi::PITCH_BEND_CHANGE => {
|
|
||||||
input_events.push_back(NoteEvent::MidiPitchBend {
|
|
||||||
timing: raw_event.time - current_sample_idx as u32,
|
|
||||||
channel,
|
|
||||||
value: (event.data[1] as u16 + ((event.data[2] as u16) << 7))
|
|
||||||
as f32
|
|
||||||
/ ((1 << 14) - 1) as f32,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
midi::CONTROL_CHANGE => {
|
|
||||||
input_events.push_back(NoteEvent::MidiCC {
|
|
||||||
timing: raw_event.time - current_sample_idx as u32,
|
|
||||||
channel,
|
|
||||||
cc: event.data[1],
|
|
||||||
value: event.data[2] as f32 / 127.0,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
n => nih_debug_assert_failure!("Unhandled MIDI message type {}", n),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue