Strengthens raw midi packet.

It now very strongly depends on U7s when appropriate
This commit is contained in:
beau trepp 2019-12-20 15:51:23 +08:00
parent 55d94f7024
commit d151a05787
13 changed files with 63 additions and 62 deletions

View file

@ -9,4 +9,4 @@ edition = "2018"
[dependencies] [dependencies]
embedded-hal = "0.2.2" embedded-hal = "0.2.2"
nb = "0.1.2" nb = "0.1.2"
usb-device = {version = "0.2.3"} usb-device = {version = "0.2.3"}

View file

@ -0,0 +1,12 @@
/// Like from, but will conceptually overflow if the value is too big
/// this is useful from going from higher ranges to lower ranges
pub trait FromOverFlow<T>:Sized {
fn from_overflow(_:T) -> Self;
}
/// Like from, but will clamp the value to a maximum value
pub trait FromClamped<T>:Sized{
fn from_clamped(_:T) -> Self;
}

View file

@ -1,2 +1,3 @@
pub mod u7; pub mod u7;
pub mod u4; pub mod u4;
pub mod from_traits;

View file

@ -26,7 +26,7 @@ impl From<U4> for u8 {
impl U4 { impl U4 {
pub const MAX: U4= U4(0x0F); pub const MAX: U4= U4(0x0F);
pub const MIN: U4 = U4(0); pub const MIN: U4= U4(0);
/// Combines two nibbles (u4) eg half byte /// Combines two nibbles (u4) eg half byte
/// result will be a full byte /// result will be a full byte

View file

@ -1,4 +1,5 @@
use core::convert::TryFrom; use core::convert::TryFrom;
use crate::data::byte::from_traits::{FromOverFlow,FromClamped};
/// A primitive value that can be from 0-0x7F /// A primitive value that can be from 0-0x7F
pub struct U7(u8); pub struct U7(u8);
@ -24,7 +25,25 @@ impl From<U7> for u8 {
} }
} }
impl FromOverFlow<u8> for U7 {
fn from_overflow(value:u8) -> U7 {
const MASK :u8 = 0b0111_1111;
let value = MASK & value;
U7(value)
}
}
impl FromClamped<u8> for U7{
fn from_clamped(value:u8) -> U7{
match U7::try_from(value) {
Ok(x) => x,
_ => U7::MAX
}
}
}
impl U7 { impl U7 {
pub const MAX: U7= U7(0x7F); pub const MAX: U7= U7(0x7F);
pub const MIN: U7 = U7(0); pub const MIN: U7 = U7(0);
} }

View file

@ -1,10 +1,11 @@
use crate::data::midi::channel::Channel; use crate::data::midi::channel::Channel;
use crate::data::midi::velocity::Velocity;
use crate::data::midi::notes::Note; use crate::data::midi::notes::Note;
use crate::data::byte::u7::U7; use crate::data::byte::u7::U7;
use crate::data::midi::message::raw::{Raw,Payload}; use crate::data::midi::message::raw::{Raw,Payload};
type Velocity = 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
/// being a confusing case. So are currently note implemented /// being a confusing case. So are currently note implemented
@ -29,32 +30,32 @@ impl From<Message> for Raw {
fn from(value:Message) -> Raw { fn from(value:Message) -> Raw {
match value { match value {
Message::NoteOn(chan,note,vel) => { Message::NoteOn(chan,note,vel) => {
let payload = Payload::DoubleByte(note.into(),vel.into()); let payload = Payload::DoubleByte(note.into(),vel);
let status = NOTE_ON_MASK | u8::from(chan); let status = NOTE_ON_MASK | u8::from(chan);
Raw { status, payload } Raw { status, payload }
}, },
Message::NoteOff(chan,note,vel) => { Message::NoteOff(chan,note,vel) => {
let payload = Payload::DoubleByte(note.into(),vel.into()); let payload = Payload::DoubleByte(note.into(),vel);
let status = NOTE_OFF_MASK | u8::from(chan); let status = NOTE_OFF_MASK | u8::from(chan);
Raw {status, payload} Raw {status, payload}
}, },
Message::PolyphonicAftertouch(chan,note,pressure) => { Message::PolyphonicAftertouch(chan,note,pressure) => {
let payload = Payload::DoubleByte(note.into(),pressure.into()); let payload = Payload::DoubleByte(note.into(),pressure);
let status = POLYPHONIC_MASK | u8::from(chan); let status = POLYPHONIC_MASK | u8::from(chan);
Raw {status, payload} Raw {status, payload}
}, },
Message::ProgramChange(chan,program) => { Message::ProgramChange(chan,program) => {
let payload = Payload::SingleByte(u8::from(program)); let payload = Payload::SingleByte(program);
let status = PROGRAM_MASK | u8::from(chan); let status = PROGRAM_MASK | u8::from(chan);
Raw {status, payload} Raw {status, payload}
}, },
Message::ChannelAftertouch(chan,pressure) => { Message::ChannelAftertouch(chan,pressure) => {
let payload = Payload::SingleByte(u8::from(pressure)); let payload = Payload::SingleByte(pressure);
let status = CHANNEL_AFTERTOUCH_MASK | u8::from(chan); let status = CHANNEL_AFTERTOUCH_MASK | u8::from(chan);
Raw {status, payload} Raw {status, payload}
}, },
Message::PitchWheelChange(chan,lsb,msb) => { Message::PitchWheelChange(chan,lsb,msb) => {
let payload = Payload::DoubleByte(u8::from(lsb),u8::from(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}
} }

View file

@ -1,4 +1,3 @@
pub mod voice;
pub mod message; pub mod message;
pub mod raw; pub mod raw;
pub use crate::data::midi::message::message::{Message}; pub use crate::data::midi::message::message::{Message};

View file

@ -1,8 +1,10 @@
use crate::data::byte::u7::U7;
/// Represents the payloads that the midi message may contain /// Represents the payloads that the midi message may contain
pub enum Payload { pub enum Payload {
Empty, Empty,
SingleByte(u8), SingleByte(U7),
DoubleByte(u8,u8) DoubleByte(U7,U7)
} }
/// A struct that captures the valid states /// A struct that captures the valid states
@ -13,4 +15,4 @@ pub enum Payload {
pub struct Raw { pub struct Raw {
pub status: u8, pub status: u8,
pub payload: Payload pub payload: Payload
} }

View file

@ -1,15 +0,0 @@
pub use crate::data::midi::channel::Channel;
pub use crate::data::midi::notes::Note;
pub use crate::data::midi::velocity::Velocity;
pub enum Voice {
NoteOff(Channel,Note,Velocity),
NoteOn(Channel,Note,Velocity),
PolyPressure(Channel)
}
impl Voice {
}

View file

@ -1,4 +1,3 @@
pub mod notes; pub mod notes;
pub mod channel; pub mod channel;
pub mod message; pub mod message;
pub mod velocity;

View file

@ -1,4 +1,5 @@
use crate::data::byte::u7::U7;
use crate::data::byte::from_traits::FromOverFlow;
/// A simple enum type that represents all the midi 'notes' /// A simple enum type that represents all the midi 'notes'
/// note the flat versions are associated constants /// note the flat versions are associated constants
/// but can be referenced like Note::Bb3 /// but can be referenced like Note::Bb3
@ -26,6 +27,14 @@ impl Into<u8> for Note {
} }
} }
impl From<Note> for U7 {
fn from(value:Note) -> U7{
let byte = value as u8;
U7::from_overflow(byte)
}
}
impl Note { impl Note {
#[allow(non_upper_case_globals)] pub const Db1m : Note = Note::Cs1m; #[allow(non_upper_case_globals)] pub const Db1m : Note = Note::Cs1m;
#[allow(non_upper_case_globals)] pub const Eb1m : Note = Note::Ds1m; #[allow(non_upper_case_globals)] pub const Eb1m : Note = Note::Ds1m;

View file

@ -1,28 +0,0 @@
use core::convert::TryFrom;
pub struct Velocity(u8);
pub struct InvalidVelocity(u8);
impl TryFrom<u8> for Velocity{
type Error = InvalidVelocity;
fn try_from(value:u8) -> Result<Self,Self::Error> {
if value > 0x7F {
Err(InvalidVelocity(value))
} else {
Ok(Velocity(value))
}
}
}
impl Into<u8> for Velocity {
fn into(self) -> u8 {
self.0
}
}
impl Velocity {
pub const MAX: Velocity= Velocity(0x7F);
pub const MIN: Velocity = Velocity(0);
}

View file

@ -28,8 +28,10 @@ impl From<UsbMidiEventPacket> for [u8;4] {
match raw_midi.payload { match raw_midi.payload {
Payload::Empty => [header,status,0,0], Payload::Empty => [header,status,0,0],
Payload::SingleByte(byte) => [header,status,byte,0], Payload::SingleByte(byte) =>
Payload::DoubleByte(byte1,byte2) => [header,status,byte1,byte2] [header,status,byte.into(),0],
Payload::DoubleByte(byte1,byte2) =>
[header,status,byte1.into(),byte2.into()]
} }
} }
} }