1pub mod consts;
37pub mod message;
38pub mod note;
39pub mod sysex;
40#[cfg(feature = "transport")]
41pub mod transport;
42pub mod vendor;
43
44pub use crate::message::{Channel, ControlEvent, KeyEvent, MidiMessage, SysExEvent};
45pub use crate::note::MidiNote;
46#[cfg(feature = "transport")]
47pub use crate::transport::MidiMessageSend;
48
49pub fn note_on(channel: Channel, note: MidiNote, velocity: u8) -> MidiMessage {
51 MidiMessage::NoteOn(
52 channel,
53 KeyEvent {
54 key: note,
55 value: velocity,
56 },
57 )
58}
59
60pub fn note_off(channel: Channel, note: MidiNote, velocity: u8) -> MidiMessage {
62 MidiMessage::NoteOff(
63 channel,
64 KeyEvent {
65 key: note,
66 value: velocity,
67 },
68 )
69}
70
71pub fn poly_key_pressure(channel: Channel, note: MidiNote, pressure: u8) -> MidiMessage {
73 MidiMessage::PolyKeyPressure(
74 channel,
75 KeyEvent {
76 key: note,
77 value: pressure,
78 },
79 )
80}
81
82pub fn control_change(channel: Channel, control: u8, value: u8) -> MidiMessage {
84 MidiMessage::ControlChange(channel, ControlEvent { control, value })
85}
86
87pub fn program_change(channel: Channel, program: u8) -> MidiMessage {
89 MidiMessage::ProgramChange(channel, program)
90}
91
92pub fn channel_pressure(channel: Channel, pressure: u8) -> MidiMessage {
94 MidiMessage::ProgramChange(channel, pressure)
95}
96
97pub fn pitch_bend(channel: Channel, change: u16) -> MidiMessage {
102 if change > 0x3fff {
103 return MidiMessage::Invalid;
104 }
105 let lsb: u8 = (change & 0b0111_1111) as u8;
106 let msb: u8 = ((change >> 7) & 0b0111_1111) as u8;
107 MidiMessage::PitchBend(channel, lsb, msb)
108}
109
110pub fn non_rt_usysex(device: u8, subid: [u8; 2], data: &[u8]) -> MidiMessage {
112 MidiMessage::SysEx(SysExEvent::new_non_realtime(device, subid, data))
113}
114
115#[cfg(test)]
116mod tests {
117 use super::*;
118
119 #[test]
120 pub fn test_simple_api() {
121 let msg = MidiMessage::NoteOn(Channel::Ch1, KeyEvent { key: 59, value: 88 });
122 assert_eq!(note_on(Channel::Ch1, 59, 88), msg);
123
124 let msg = MidiMessage::NoteOff(Channel::Ch1, KeyEvent { key: 60, value: 0 });
125 assert_eq!(note_off(Channel::Ch1, 60, 0), msg);
126
127 let msg = MidiMessage::ControlChange(
128 Channel::Ch1,
129 ControlEvent {
130 control: 114,
131 value: 65,
132 },
133 );
134 assert_eq!(control_change(Channel::Ch1, 114, 65), msg);
135
136 let msg = MidiMessage::PitchBend(Channel::Ch1, 0, 76);
137 assert_eq!(pitch_bend(Channel::Ch1, 0x2600), msg);
138
139 assert_eq!(pitch_bend(Channel::Ch1, 0x8000), MidiMessage::Invalid);
141
142 let msg = MidiMessage::SysEx(SysExEvent::new_non_realtime(
143 consts::usysex::ALL_CALL,
144 [0x06, 0x01],
145 &[0xf7],
146 ));
147 assert_eq!(
148 non_rt_usysex(consts::usysex::ALL_CALL, [0x06, 0x01], &[0xf7]),
149 msg
150 );
151 }
152}