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]
embedded-hal = "0.2.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 u4;
pub mod u4;
pub mod from_traits;

View file

@ -26,7 +26,7 @@ impl From<U4> for u8 {
impl U4 {
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
/// result will be a full byte

View file

@ -1,4 +1,5 @@
use core::convert::TryFrom;
use crate::data::byte::from_traits::{FromOverFlow,FromClamped};
/// A primitive value that can be from 0-0x7F
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 {
pub const MAX: U7= U7(0x7F);
pub const MIN: U7 = U7(0);
}

View file

@ -1,10 +1,11 @@
use crate::data::midi::channel::Channel;
use crate::data::midi::velocity::Velocity;
use crate::data::midi::notes::Note;
use crate::data::byte::u7::U7;
use crate::data::midi::message::raw::{Raw,Payload};
type Velocity = U7;
/// Represents midi messages
/// Note: not current exhaustive and SysEx messages end up
/// being a confusing case. So are currently note implemented
@ -29,32 +30,32 @@ impl From<Message> for Raw {
fn from(value:Message) -> Raw {
match value {
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);
Raw { status, payload }
},
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);
Raw {status, payload}
},
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);
Raw {status, payload}
},
Message::ProgramChange(chan,program) => {
let payload = Payload::SingleByte(u8::from(program));
let payload = Payload::SingleByte(program);
let status = PROGRAM_MASK | u8::from(chan);
Raw {status, payload}
},
Message::ChannelAftertouch(chan,pressure) => {
let payload = Payload::SingleByte(u8::from(pressure));
let payload = Payload::SingleByte(pressure);
let status = CHANNEL_AFTERTOUCH_MASK | u8::from(chan);
Raw {status, payload}
},
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);
Raw {status , payload}
}

View file

@ -1,4 +1,3 @@
pub mod voice;
pub mod message;
pub mod raw;
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
pub enum Payload {
Empty,
SingleByte(u8),
DoubleByte(u8,u8)
SingleByte(U7),
DoubleByte(U7,U7)
}
/// A struct that captures the valid states
@ -13,4 +15,4 @@ pub enum Payload {
pub struct Raw {
pub status: u8,
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 channel;
pub mod message;
pub mod velocity;
pub mod message;

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'
/// note the flat versions are associated constants
/// 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 {
#[allow(non_upper_case_globals)] pub const Db1m : Note = Note::Cs1m;
#[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 {
Payload::Empty => [header,status,0,0],
Payload::SingleByte(byte) => [header,status,byte,0],
Payload::DoubleByte(byte1,byte2) => [header,status,byte1,byte2]
Payload::SingleByte(byte) =>
[header,status,byte.into(),0],
Payload::DoubleByte(byte1,byte2) =>
[header,status,byte1.into(),byte2.into()]
}
}
}