mirror of
https://github.com/italicsjenga/usbd-midi.git
synced 2024-12-23 20:31:30 +11:00
Implement receive for missing event types and added ControlChange
This commit is contained in:
parent
dea3594e37
commit
9db505d659
|
@ -8,6 +8,7 @@ use core::convert::TryFrom;
|
||||||
use crate::data::usb_midi::usb_midi_event_packet::MidiPacketParsingError;
|
use crate::data::usb_midi::usb_midi_event_packet::MidiPacketParsingError;
|
||||||
|
|
||||||
type Velocity = U7;
|
type Velocity = U7;
|
||||||
|
type ControllerNumber = U7;
|
||||||
|
|
||||||
/// Represents midi messages
|
/// Represents midi messages
|
||||||
/// Note: not current exhaustive and SysEx messages end up
|
/// Note: not current exhaustive and SysEx messages end up
|
||||||
|
@ -20,15 +21,17 @@ pub enum Message {
|
||||||
PolyphonicAftertouch(Channel,Note,U7),
|
PolyphonicAftertouch(Channel,Note,U7),
|
||||||
ProgramChange(Channel,U7),
|
ProgramChange(Channel,U7),
|
||||||
ChannelAftertouch(Channel,U7),
|
ChannelAftertouch(Channel,U7),
|
||||||
PitchWheelChange(Channel,U7,U7)
|
PitchWheelChange(Channel,U7,U7),
|
||||||
|
ControlChange(Channel, ControllerNumber, U7)
|
||||||
}
|
}
|
||||||
|
|
||||||
const NOTE_OFF_MASK :u8 = 0b1000_0000;
|
const NOTE_OFF_MASK :u8 = 0b1000_0000;
|
||||||
const NOTE_ON_MASK :u8 = 0b1001_0000;
|
const NOTE_ON_MASK :u8 = 0b1001_0000;
|
||||||
const POLYPHONIC_MASK :u8 = 0b1010_0000;
|
const POLYPHONIC_MASK :u8 = 0b1010_0000;
|
||||||
const PROGRAM_MASK :u8 = 0b1100_0000;
|
const PROGRAM_MASK :u8 = 0b1100_0000;
|
||||||
const CHANNEL_AFTERTOUCH_MASK :u8 = 0b1101_0000;
|
const CHANNEL_AFTERTOUCH_MASK :u8 = 0b1101_0000;
|
||||||
const PITCH_BEND_MASK :u8 = 0b1110_0000;
|
const PITCH_BEND_MASK :u8 = 0b1110_0000;
|
||||||
|
const CONTROL_CHANGE_MASK :u8 = 0b1011_0000;
|
||||||
|
|
||||||
impl From<Message> for Raw {
|
impl From<Message> for Raw {
|
||||||
fn from(value:Message) -> Raw {
|
fn from(value:Message) -> Raw {
|
||||||
|
@ -62,8 +65,12 @@ impl From<Message> for Raw {
|
||||||
let payload = Payload::DoubleByte(lsb,msb);
|
let payload = Payload::DoubleByte(lsb,msb);
|
||||||
let status = PITCH_BEND_MASK | u8::from(chan);
|
let status = PITCH_BEND_MASK | u8::from(chan);
|
||||||
Raw {status , payload}
|
Raw {status , payload}
|
||||||
|
},
|
||||||
|
Message::ControlChange(chan, controller_number, value) => {
|
||||||
|
let payload = Payload::DoubleByte(controller_number, value);
|
||||||
|
let status = CONTROL_CHANGE_MASK | u8::from(chan);
|
||||||
|
Raw {status, payload}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,21 +85,34 @@ impl<'a> TryFrom<&'a [u8]> for Message {
|
||||||
let channel = Channel::try_from(channel_bytes).ok().unwrap();
|
let channel = Channel::try_from(channel_bytes).ok().unwrap();
|
||||||
|
|
||||||
match event_type {
|
match event_type {
|
||||||
NOTE_OFF_MASK => Ok(Message::NoteOff(channel, get_note(data)?, get_velocity(data))),
|
NOTE_ON_MASK => Ok(Message::NoteOn(channel, get_note(data)?, get_u7_at(data, 2)?)),
|
||||||
NOTE_ON_MASK => Ok(Message::NoteOn(channel, get_note(data)?, get_velocity(data))),
|
NOTE_OFF_MASK => Ok(Message::NoteOff(channel, get_note(data)?, get_u7_at(data, 2)?)),
|
||||||
|
POLYPHONIC_MASK => Ok(Message::PolyphonicAftertouch(channel, get_note(data)?, get_u7_at(data, 2)?)),
|
||||||
|
PROGRAM_MASK => Ok(Message::ProgramChange(channel, get_u7_at(data, 1)?)),
|
||||||
|
CHANNEL_AFTERTOUCH_MASK => Ok(Message::ChannelAftertouch(channel, get_u7_at(data, 1)?)),
|
||||||
|
PITCH_BEND_MASK => Ok(Message::PitchWheelChange(channel, get_u7_at(data, 1)?, get_u7_at(data, 2)?)),
|
||||||
|
CONTROL_CHANGE_MASK => Ok(Message::ControlChange(channel, get_u7_at(data, 1)?, get_u7_at(data, 2)?)),
|
||||||
_ => Err(MidiPacketParsingError::InvalidEventType(event_type))
|
_ => Err(MidiPacketParsingError::InvalidEventType(event_type))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_note(data: &[u8]) -> Result<Note, MidiPacketParsingError> {
|
fn get_note(data: &[u8]) -> Result<Note, MidiPacketParsingError> {
|
||||||
let note_byte = data[1];
|
let note_byte = get_byte_at_position(data, 1)?;
|
||||||
match Note::try_from(note_byte) {
|
match Note::try_from(note_byte) {
|
||||||
Ok(note) => Ok(note),
|
Ok(note) => Ok(note),
|
||||||
Err(_) => Err(MidiPacketParsingError::InvalidNote(note_byte))
|
Err(_) => Err(MidiPacketParsingError::InvalidNote(note_byte))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_velocity(data: &[u8]) -> U7 {
|
fn get_u7_at(data: &[u8], index: usize) -> Result<U7, MidiPacketParsingError> {
|
||||||
U7::from_clamped(data[2])
|
let data_byte = get_byte_at_position(data, index)?;
|
||||||
|
Ok(U7::from_clamped(data_byte))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_byte_at_position(data: &[u8], index: usize) -> Result<u8, MidiPacketParsingError> {
|
||||||
|
match data.get(index) {
|
||||||
|
Some(byte) => Ok(*byte),
|
||||||
|
None => Err(MidiPacketParsingError::MissingDataPacket)
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -71,7 +71,8 @@ impl CodeIndexNumber {
|
||||||
Message::ChannelAftertouch(_,_) => CodeIndexNumber::CHANNEL_PRESSURE,
|
Message::ChannelAftertouch(_,_) => CodeIndexNumber::CHANNEL_PRESSURE,
|
||||||
Message::PitchWheelChange(_,_,_) => CodeIndexNumber::PITCHBEND_CHANGE,
|
Message::PitchWheelChange(_,_,_) => CodeIndexNumber::PITCHBEND_CHANGE,
|
||||||
Message::PolyphonicAftertouch(_,_,_) => CodeIndexNumber::POLY_KEYPRESS,
|
Message::PolyphonicAftertouch(_,_,_) => CodeIndexNumber::POLY_KEYPRESS,
|
||||||
Message::ProgramChange(_,_) => CodeIndexNumber::PROGRAM_CHANGE
|
Message::ProgramChange(_,_) => CodeIndexNumber::PROGRAM_CHANGE,
|
||||||
|
Message::ControlChange(_,_,_) => CodeIndexNumber::CONTROL_CHANGE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue