diff --git a/src/midi.rs b/src/midi.rs index f2e02260..ad549c6f 100644 --- a/src/midi.rs +++ b/src/midi.rs @@ -1,5 +1,7 @@ //! Constants and definitions surrounding MIDI support. +use midi_consts::channel_event as midi; + pub use midi_consts::channel_event::control_change; /// 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 { + // 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 /// splitting in the VST3 wrapper implementation because all events have to be read upfront. pub(crate) fn subtract_timing(&mut self, samples: u32) { diff --git a/src/wrapper/clap/wrapper.rs b/src/wrapper/clap/wrapper.rs index 07ac14db..70a56a3b 100644 --- a/src/wrapper/clap/wrapper.rs +++ b/src/wrapper/clap/wrapper.rs @@ -1360,63 +1360,14 @@ impl Wrapper

{ if P::MIDI_INPUT >= MidiConfig::MidiCCs { let event = &*(event as *const clap_event_midi); - // 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 = event.data[0] & midi::EVENT_TYPE_MASK; - let channel = event.data[0] & midi::MIDI_CHANNEL_MASK; - match event_type { - // Hosts shouldn't be sending this, bu twe'll handle it just in case - 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, - }); + match NoteEvent::from_midi( + raw_event.time - current_sample_idx as u32, + event.data, + ) { + Ok(note_event) => { + input_events.push_back(note_event); } - // Hosts shouldn't be sending this, bu twe'll handle it just in case - 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), + Err(n) => nih_debug_assert_failure!("Unhandled MIDI message type {}", n), }; }