midi_msg/system_exclusive/
notation.rs1use crate::parse_error::*;
2use crate::util::*;
3use alloc::vec;
4use alloc::vec::Vec;
5
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[derive(Debug, Copy, Clone, PartialEq, Eq)]
11pub enum BarMarker {
12 NotRunning,
14 CountIn(u16), Number(u16),
18 RunningUnknown,
20}
21
22impl BarMarker {
23 pub(crate) fn extend_midi(&self, v: &mut Vec<u8>) {
24 match *self {
25 Self::NotRunning => {
26 v.push(0x00);
28 v.push(0x40);
29 }
30 Self::CountIn(x) => {
31 push_i14(-(x.min(8191) as i16), v);
32 }
33 Self::Number(x) => {
34 push_i14(x.min(8191) as i16, v);
35 }
36 Self::RunningUnknown => {
37 v.push(0x7F);
39 v.push(0x3F);
40 }
41 }
42 }
43
44 #[allow(dead_code)]
45 pub(crate) fn from_midi(_m: &[u8]) -> Result<(Self, usize), ParseError> {
46 Err(ParseError::NotImplemented("BarMarker"))
47 }
48}
49
50#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
53#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct TimeSignature {
55 pub signature: Signature,
57 pub midi_clocks_in_metronome_click: u8,
60 pub thirty_second_notes_in_midi_quarter_note: u8,
63 pub compound: Vec<Signature>,
65}
66
67impl Default for TimeSignature {
68 fn default() -> Self {
69 Self {
70 signature: Default::default(),
71 midi_clocks_in_metronome_click: 24, thirty_second_notes_in_midi_quarter_note: 8, compound: vec![],
74 }
75 }
76}
77
78impl TimeSignature {
79 pub(crate) fn extend_midi(&self, v: &mut Vec<u8>) {
80 v.push((4 + (self.compound.len() * 2)).min(126) as u8); self.signature.extend_midi(v);
82 v.push(to_u7(self.midi_clocks_in_metronome_click));
83 v.push(to_u7(self.thirty_second_notes_in_midi_quarter_note));
84 for (i, s) in self.compound.iter().enumerate() {
85 if i >= 61 {
86 break;
87 }
88 s.extend_midi(v);
89 }
90 }
91
92 #[allow(dead_code)]
93 pub(crate) fn from_midi(_m: &[u8]) -> Result<(Self, usize), ParseError> {
94 Err(ParseError::NotImplemented("TimeSignature"))
95 }
96}
97
98#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
100#[derive(Debug, Copy, Clone, PartialEq, Eq)]
101pub struct Signature {
102 pub beats: u8,
104 pub beat_value: BeatValue,
106}
107
108impl Signature {
109 fn extend_midi(&self, v: &mut Vec<u8>) {
110 v.push(to_u7(self.beats));
111 v.push(self.beat_value.to_u8());
112 }
113
114 #[allow(dead_code)]
115 pub(crate) fn from_midi(_m: &[u8]) -> Result<(Self, usize), ParseError> {
116 Err(ParseError::NotImplemented("Signature"))
117 }
118}
119
120impl Default for Signature {
121 fn default() -> Self {
122 Self {
123 beats: 4,
124 beat_value: BeatValue::Quarter,
125 }
126 }
127}
128
129#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
131#[derive(Debug, Copy, Clone, PartialEq, Eq)]
132pub enum BeatValue {
133 Whole,
134 Half,
135 Quarter,
136 Eighth,
137 Sixteenth,
138 ThirtySecond,
139 SixtyFourth,
140 Other(u8),
143}
144
145impl BeatValue {
146 fn to_u8(self) -> u8 {
147 match self {
148 Self::Whole => 0,
149 Self::Half => 1,
150 Self::Quarter => 2,
151 Self::Eighth => 3,
152 Self::Sixteenth => 4,
153 Self::ThirtySecond => 5,
154 Self::SixtyFourth => 6,
155 Self::Other(x) => to_u7(x),
156 }
157 }
158
159 #[allow(dead_code)]
160 fn from_byte(_m: u8) -> Self {
161 Self::Quarter
163 }
164}
165
166#[cfg(test)]
167mod tests {
168 use crate::*;
169 use alloc::vec;
170
171 #[test]
172 fn serialize_bar_marker() {
173 assert_eq!(
174 MidiMsg::SystemExclusive {
175 msg: SystemExclusiveMsg::UniversalRealTime {
176 device: DeviceID::AllCall,
177 msg: UniversalRealTimeMsg::BarMarker(BarMarker::NotRunning),
178 },
179 }
180 .to_midi(),
181 vec![0xF0, 0x7F, 0x7f, 0x3, 0x1, 0x00, 0x40, 0xF7]
182 );
183
184 assert_eq!(
185 MidiMsg::SystemExclusive {
186 msg: SystemExclusiveMsg::UniversalRealTime {
187 device: DeviceID::AllCall,
188 msg: UniversalRealTimeMsg::BarMarker(BarMarker::CountIn(1)),
189 },
190 }
191 .to_midi(),
192 vec![0xF0, 0x7F, 0x7f, 0x3, 0x1, 0x7f, 0x7f, 0xF7]
193 );
194
195 assert_eq!(
196 MidiMsg::SystemExclusive {
197 msg: SystemExclusiveMsg::UniversalRealTime {
198 device: DeviceID::AllCall,
199 msg: UniversalRealTimeMsg::BarMarker(BarMarker::Number(1)),
200 },
201 }
202 .to_midi(),
203 vec![0xF0, 0x7F, 0x7f, 0x3, 0x1, 0x01, 0x00, 0xF7]
204 );
205
206 assert_eq!(
207 MidiMsg::SystemExclusive {
208 msg: SystemExclusiveMsg::UniversalRealTime {
209 device: DeviceID::AllCall,
210 msg: UniversalRealTimeMsg::BarMarker(BarMarker::RunningUnknown),
211 },
212 }
213 .to_midi(),
214 vec![0xF0, 0x7F, 0x7f, 0x3, 0x1, 0x7f, 0x3f, 0xF7]
215 );
216 }
217
218 #[test]
219 fn serialize_time_signature() {
220 assert_eq!(
221 MidiMsg::SystemExclusive {
222 msg: SystemExclusiveMsg::UniversalRealTime {
223 device: DeviceID::AllCall,
224 msg: UniversalRealTimeMsg::TimeSignatureDelayed(TimeSignature::default()),
225 },
226 }
227 .to_midi(),
228 vec![0xF0, 0x7F, 0x7f, 0x3, 0x42, 4, 4, 2, 24, 8, 0xF7]
229 );
230
231 assert_eq!(
232 MidiMsg::SystemExclusive {
233 msg: SystemExclusiveMsg::UniversalRealTime {
234 device: DeviceID::AllCall,
235 msg: UniversalRealTimeMsg::TimeSignature(TimeSignature {
236 compound: vec! {Signature {
237 beats: 3,
238 beat_value: BeatValue::Eighth,
239 }},
240 ..Default::default()
241 }),
242 },
243 }
244 .to_midi(),
245 vec![0xF0, 0x7F, 0x7f, 0x3, 0x02, 6, 4, 2, 24, 8, 3, 3, 0xF7]
246 );
247 }
248}