1use crate::ReceiverContext;
2
3use super::parse_error::*;
4use super::util::*;
5use alloc::vec;
6use alloc::vec::Vec;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum ChannelVoiceMsg {
12 NoteOn {
14 note: u8,
16 velocity: u8,
18 },
19 NoteOff {
21 note: u8,
23 velocity: u8,
25 },
26 ControlChange { control: ControlChange },
28 HighResNoteOn { note: u8, velocity: u16 },
30 HighResNoteOff { note: u8, velocity: u16 },
32 PolyPressure {
36 note: u8,
38 pressure: u8,
40 },
41 ChannelPressure { pressure: u8 },
43 ProgramChange { program: u8 },
46 PitchBend { bend: u16 },
50}
51
52impl ChannelVoiceMsg {
53 pub(crate) fn extend_midi(&self, v: &mut Vec<u8>) {
54 match self {
55 ChannelVoiceMsg::NoteOff { .. } => v.push(0x80),
56 ChannelVoiceMsg::NoteOn { .. } => v.push(0x90),
57 ChannelVoiceMsg::HighResNoteOff { .. } => v.push(0x80),
58 ChannelVoiceMsg::HighResNoteOn { .. } => v.push(0x90),
59 ChannelVoiceMsg::PolyPressure { .. } => v.push(0xA0),
60 ChannelVoiceMsg::ControlChange { .. } => v.push(0xB0),
61 ChannelVoiceMsg::ProgramChange { .. } => v.push(0xC0),
62 ChannelVoiceMsg::ChannelPressure { .. } => v.push(0xD0),
63 ChannelVoiceMsg::PitchBend { .. } => v.push(0xE0),
64 }
65 self.extend_midi_running(v);
66 }
67
68 pub(crate) fn is_extensible(&self) -> bool {
70 match self {
71 Self::NoteOff { .. }
72 | Self::NoteOn { .. }
73 | Self::HighResNoteOff { .. }
74 | Self::HighResNoteOn { .. } => true,
75 Self::ControlChange {
76 control: ControlChange::Parameter(_),
77 } => true,
78 Self::ControlChange { control } => control.is_lsb() || control.is_msb(),
79 _ => false,
80 }
81 }
82
83 pub(crate) fn is_extension(&self) -> bool {
85 match self {
86 Self::ControlChange { control } => match control {
87 ControlChange::HighResVelocity(_) => true,
88 control => control.is_lsb() || control.is_msb(),
89 },
90 _ => false,
91 }
92 }
93
94 pub(crate) fn maybe_extend(&self, other: &Self) -> Result<Self, ()> {
95 match (self, other) {
96 (
97 Self::NoteOff { note, velocity },
98 Self::ControlChange {
99 control: ControlChange::HighResVelocity(v),
100 },
101 ) => Ok(Self::HighResNoteOff {
102 note: *note,
103 velocity: u14_from_u7s(*velocity, *v),
104 }),
105 (
106 Self::NoteOn { note, velocity },
107 Self::ControlChange {
108 control: ControlChange::HighResVelocity(v),
109 },
110 ) => Ok(Self::HighResNoteOn {
111 note: *note,
112 velocity: u14_from_u7s(*velocity, *v),
113 }),
114 (
115 Self::HighResNoteOff { note, velocity },
116 Self::ControlChange {
117 control: ControlChange::HighResVelocity(v),
118 },
119 ) => Ok(Self::HighResNoteOff {
120 note: *note,
121 velocity: replace_u14_lsb(*velocity, *v),
122 }),
123 (
124 Self::HighResNoteOn { note, velocity },
125 Self::ControlChange {
126 control: ControlChange::HighResVelocity(v),
127 },
128 ) => Ok(Self::HighResNoteOn {
129 note: *note,
130 velocity: replace_u14_lsb(*velocity, *v),
131 }),
132 (Self::ControlChange { control: ctrl1 }, Self::ControlChange { control: ctrl2 }) => {
133 match ctrl1.maybe_extend(ctrl2) {
134 Ok(control) => Ok(Self::ControlChange { control }),
135 Err(()) => Err(()),
136 }
137 }
138 _ => Err(()),
139 }
140 }
141
142 pub(crate) fn extend_midi_running(&self, v: &mut Vec<u8>) {
144 match *self {
145 ChannelVoiceMsg::NoteOff { note, velocity } => {
146 v.push(to_u7(note));
147 v.push(to_u7(velocity));
148 }
149 ChannelVoiceMsg::NoteOn { note, velocity } => {
150 v.push(to_u7(note));
151 v.push(to_u7(velocity));
152 }
153 ChannelVoiceMsg::HighResNoteOff { note, velocity } => {
154 let [msb, lsb] = to_u14(velocity);
155 push_u7(note, v);
156 v.push(msb);
157 v.push(0xB0);
158 v.push(0x58);
159 v.push(lsb);
160 }
161 ChannelVoiceMsg::HighResNoteOn { note, velocity } => {
162 let [msb, lsb] = to_u14(velocity);
163 push_u7(note, v);
164 v.push(msb);
165 v.push(0xB0);
166 v.push(0x58);
167 v.push(lsb);
168 }
169 ChannelVoiceMsg::PolyPressure { note, pressure } => {
170 v.push(to_u7(note));
171 v.push(to_u7(pressure));
172 }
173 ChannelVoiceMsg::ControlChange { control } => control.extend_midi_running(v),
174 ChannelVoiceMsg::ProgramChange { program } => v.push(to_u7(program)),
175 ChannelVoiceMsg::ChannelPressure { pressure } => v.push(to_u7(pressure)),
176 ChannelVoiceMsg::PitchBend { bend } => {
177 push_u14(bend, v);
178 }
179 }
180 }
181
182 pub(crate) fn from_midi(m: &[u8], ctx: &ReceiverContext) -> Result<(Self, usize), ParseError> {
183 let status = match m.first() {
184 Some(b) => match b >> 4 {
185 0x8 => Self::NoteOff {
186 note: 0,
187 velocity: 0,
188 },
189 0x9 => Self::NoteOn {
190 note: 0,
191 velocity: 0,
192 },
193 0xA => Self::PolyPressure {
194 note: 0,
195 pressure: 0,
196 },
197 0xB => Self::ControlChange {
198 control: ControlChange::BankSelect(0),
199 },
200 0xC => Self::ProgramChange { program: 0 },
201 0xD => Self::ChannelPressure { pressure: 0 },
202 0xE => Self::PitchBend { bend: 0 },
203 _ => return Err(ParseError::Invalid("This shouldn't be possible")),
204 },
205 None => return Err(ParseError::UnexpectedEnd),
206 };
207 let (msg, len) = Self::from_midi_running(&m[1..], &status, ctx)?;
208 Ok((msg, len + 1))
209 }
210
211 pub(crate) fn from_midi_running(
212 m: &[u8],
213 msg: &Self,
214 ctx: &ReceiverContext,
215 ) -> Result<(Self, usize), ParseError> {
216 match msg {
217 Self::NoteOff { .. } => Ok((
218 Self::NoteOff {
219 note: u7_from_midi(m)?,
220 velocity: u7_from_midi(&m[1..])?,
221 },
222 2,
223 )),
224 Self::NoteOn { .. } => Ok((
225 Self::NoteOn {
226 note: u7_from_midi(m)?,
227 velocity: u7_from_midi(&m[1..])?,
228 },
229 2,
230 )),
231 Self::PolyPressure { .. } => Ok((
232 Self::PolyPressure {
233 note: u7_from_midi(m)?,
234 pressure: u7_from_midi(&m[1..])?,
235 },
236 2,
237 )),
238 Self::ControlChange { .. } => Ok((
239 Self::ControlChange {
240 control: ControlChange::from_midi(m, ctx)?,
241 },
242 2,
243 )),
244 Self::ProgramChange { .. } => Ok((
245 Self::ProgramChange {
246 program: u7_from_midi(m)?,
247 },
248 1,
249 )),
250 Self::ChannelPressure { .. } => Ok((
251 Self::ChannelPressure {
252 pressure: u7_from_midi(m)?,
253 },
254 1,
255 )),
256 Self::PitchBend { .. } => Ok((
257 Self::PitchBend {
258 bend: u14_from_midi(m)?,
259 },
260 2,
261 )),
262 Self::HighResNoteOn { .. } | Self::HighResNoteOff { .. } => {
263 Ok((
266 Self::ControlChange {
267 control: ControlChange::from_midi(m, ctx)?,
268 },
269 2,
270 ))
271 }
272 }
273 }
274}
275
276#[derive(Debug, Clone, Copy, PartialEq, Eq)]
278pub enum ControlNumber {
279 BankSelect = 0,
280 BankSelectLSB = 32,
281 ModWheel = 1,
282 ModWheelLSB = 33,
283 Breath = 2,
284 BreathLSB = 34,
285 Foot = 4,
286 FootLSB = 36,
287 Portamento = 5,
288 PortamentoLSB = 37,
289 DataEntry = 6,
290 DataEntryLSB = 38,
291 Volume = 7,
292 VolumeLSB = 39,
293 Balance = 8,
294 BalanceLSB = 40,
295 Pan = 10,
296 PanLSB = 42,
297 Expression = 11,
298 ExpressionLSB = 43,
299 Effect1 = 12,
300 Effect1LSB = 44,
301 Effect2 = 13,
302 Effect2LSB = 45,
303 GeneralPurpose1 = 16,
304 GeneralPurpose1LSB = 48,
305 GeneralPurpose2 = 17,
306 GeneralPurpose2LSB = 49,
307 GeneralPurpose3 = 18,
308 GeneralPurpose3LSB = 50,
309 GeneralPurpose4 = 19,
310 GeneralPurpose4LSB = 51,
311 Hold = 64,
313 TogglePortamento = 65,
314 Sostenuto = 66,
315 SoftPedal = 67,
316 ToggleLegato = 68,
317 Hold2 = 69,
318 SoundControl1 = 70,
320 SoundControl2 = 71,
322 SoundControl3 = 72,
324 SoundControl4 = 73,
326 SoundControl5 = 74,
328 SoundControl6 = 75,
330 SoundControl7 = 76,
332 SoundControl8 = 77,
334 SoundControl9 = 78,
336 SoundControl10 = 79,
337 GeneralPurpose5 = 80,
338 GeneralPurpose6 = 81,
339 GeneralPurpose7 = 82,
340 GeneralPurpose8 = 83,
341 PortamentoControl = 84,
342 HighResVelocity = 88,
343 Effects1Depth = 91,
345 Effects2Depth = 92,
347 Effects3Depth = 93,
349 Effects4Depth = 94,
351 Effects5Depth = 95,
353 DataIncrement = 96,
354 DataDecrement = 97,
355 NonRegisteredParameterLSB = 98,
356 NonRegisteredParameter = 99,
357 RegisteredParameterLSB = 100,
358 RegisteredParameter = 101,
359}
360
361#[derive(Debug, Clone, Copy, PartialEq, Eq)]
366pub enum ControlChange {
367 CC {
371 control: u8,
372 value: u8,
374 },
375 CCHighRes {
379 control1: u8,
380 control2: u8,
381 value: u16,
383 },
384
385 BankSelect(u16),
387 ModWheel(u16),
389 Breath(u16),
391 Foot(u16),
393 Portamento(u16),
395 Volume(u16),
397 Balance(u16),
399 Pan(u16),
401 Expression(u16),
403 Effect1(u16),
405 Effect2(u16),
407 GeneralPurpose1(u16),
409 GeneralPurpose2(u16),
411 GeneralPurpose3(u16),
413 GeneralPurpose4(u16),
415 GeneralPurpose5(u8),
417 GeneralPurpose6(u8),
419 GeneralPurpose7(u8),
421 GeneralPurpose8(u8),
423 Hold(u8),
425 Hold2(u8),
427 TogglePortamento(bool),
429 Sostenuto(u8),
431 SoftPedal(u8),
433 ToggleLegato(bool),
435 SoundVariation(u8),
437 Timbre(u8),
439 ReleaseTime(u8),
441 AttackTime(u8),
443 Brightness(u8),
446 DecayTime(u8),
448 VibratoRate(u8),
450 VibratoDepth(u8),
452 VibratoDelay(u8),
454 SoundControl1(u8),
456 SoundControl2(u8),
458 SoundControl3(u8),
460 SoundControl4(u8),
462 SoundControl5(u8),
464 SoundControl6(u8),
466 SoundControl7(u8),
468 SoundControl8(u8),
470 SoundControl9(u8),
472 SoundControl10(u8),
474 HighResVelocity(u8),
477 PortamentoControl(u8),
479 Effects1Depth(u8),
481 Effects2Depth(u8),
483 Effects3Depth(u8),
485 Effects4Depth(u8),
487 Effects5Depth(u8),
489 ReverbSendLevel(u8),
491 TremoloDepth(u8),
493 ChorusSendLevel(u8),
495 CelesteDepth(u8),
497 PhaserDepth(u8),
499 Parameter(Parameter),
501 DataEntry(u16),
503 DataEntry2(u8, u8),
505 DataIncrement(u8),
507 DataDecrement(u8),
509}
510
511impl ControlChange {
512 pub fn to_complex(&self) -> Self {
513 match *self {
514 Self::CC { control, value } => {
515 match control {
516 0 => Self::BankSelect((value as u16) << 7),
518 1 => Self::ModWheel((value as u16) << 7),
519 2 => Self::Breath((value as u16) << 7),
520 4 => Self::Foot((value as u16) << 7),
521 5 => Self::Portamento((value as u16) << 7),
522 6 => Self::DataEntry((value as u16) << 7),
523 7 => Self::Volume((value as u16) << 7),
524 8 => Self::Balance((value as u16) << 7),
525 10 => Self::Pan((value as u16) << 7),
526 11 => Self::Expression((value as u16) << 7),
527 12 => Self::Effect1((value as u16) << 7),
528 13 => Self::Effect2((value as u16) << 7),
529 16 => Self::GeneralPurpose1((value as u16) << 7),
530 17 => Self::GeneralPurpose2((value as u16) << 7),
531 18 => Self::GeneralPurpose3((value as u16) << 7),
532 19 => Self::GeneralPurpose4((value as u16) << 7),
533 64 => Self::Hold(value),
535 65 => Self::TogglePortamento(value >= 0x40),
536 66 => Self::Sostenuto(value),
537 67 => Self::SoftPedal(value),
538 68 => Self::ToggleLegato(value >= 0x40),
539 69 => Self::Hold2(value),
540 70 => Self::SoundControl1(value),
541 71 => Self::SoundControl2(value),
542 72 => Self::SoundControl3(value),
543 73 => Self::SoundControl4(value),
544 74 => Self::SoundControl5(value),
545 75 => Self::SoundControl6(value),
546 76 => Self::SoundControl7(value),
547 77 => Self::SoundControl8(value),
548 78 => Self::SoundControl9(value),
549 79 => Self::SoundControl10(value),
550 80 => Self::GeneralPurpose5(value),
551 81 => Self::GeneralPurpose6(value),
552 82 => Self::GeneralPurpose7(value),
553 83 => Self::GeneralPurpose8(value),
554 84 => Self::PortamentoControl(value),
555 88 => Self::HighResVelocity(value),
556 91 => Self::Effects1Depth(value),
557 92 => Self::Effects2Depth(value),
558 93 => Self::Effects3Depth(value),
559 94 => Self::Effects4Depth(value),
560 95 => Self::Effects5Depth(value),
561 96 => Self::DataIncrement(value),
562 97 => Self::DataDecrement(value),
563 3 | 9 | 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 => {
565 Self::CCHighRes {
566 control1: control,
567 control2: control + 32,
568 value: (value as u16) << 7,
569 }
570 }
571 control => Self::CC { control, value },
572 }
573 }
574 Self::CCHighRes {
575 control1, value, ..
576 } => {
577 match control1 {
578 0 => Self::BankSelect(value),
580 1 => Self::ModWheel(value),
581 2 => Self::Breath(value),
582 4 => Self::Foot(value),
583 5 => Self::Portamento(value),
584 6 => Self::DataEntry(value),
585 7 => Self::Volume(value),
586 8 => Self::Balance(value),
587 10 => Self::Pan(value),
588 11 => Self::Expression(value),
589 12 => Self::Effect1(value),
590 13 => Self::Effect2(value),
591 16 => Self::GeneralPurpose1(value),
592 17 => Self::GeneralPurpose2(value),
593 18 => Self::GeneralPurpose3(value),
594 19 => Self::GeneralPurpose4(value),
595 _ => Self::CC {
596 control: control1,
597 value: (value >> 7) as u8,
598 }
599 .to_complex(),
600 }
601 }
602 rest => rest,
604 }
605 }
606
607 pub fn to_simple(&self) -> Self {
608 Self::CC {
609 control: self.control(),
610 value: self.value(),
611 }
612 }
613
614 pub fn to_simple_high_res(&self) -> Self {
615 match self {
616 Self::CCHighRes { .. } => *self,
617 _ => {
618 let cc = self.control();
619 Self::CCHighRes {
620 control1: cc,
621 control2: cc + 32,
622 value: self.value_high_res(),
623 }
624 }
625 }
626 }
627
628 pub fn control(&self) -> u8 {
629 match self {
630 Self::CC { control, .. } => *control,
631 Self::CCHighRes { control1, .. } => *control1,
632 Self::BankSelect(_) => ControlNumber::BankSelect as u8,
633 Self::ModWheel(_) => ControlNumber::ModWheel as u8,
634 Self::Breath(_) => ControlNumber::Breath as u8,
635 Self::Foot(_) => ControlNumber::Foot as u8,
636 Self::Portamento(_) => ControlNumber::Portamento as u8,
637 Self::Volume(_) => ControlNumber::Volume as u8,
638 Self::Balance(_) => ControlNumber::Balance as u8,
639 Self::Pan(_) => ControlNumber::Pan as u8,
640 Self::Expression(_) => ControlNumber::Expression as u8,
641 Self::Effect1(_) => ControlNumber::Effect1 as u8,
642 Self::Effect2(_) => ControlNumber::Effect2 as u8,
643 Self::GeneralPurpose1(_) => ControlNumber::GeneralPurpose1 as u8,
644 Self::GeneralPurpose2(_) => ControlNumber::GeneralPurpose2 as u8,
645 Self::GeneralPurpose3(_) => ControlNumber::GeneralPurpose3 as u8,
646 Self::GeneralPurpose4(_) => ControlNumber::GeneralPurpose4 as u8,
647 Self::GeneralPurpose5(_) => ControlNumber::GeneralPurpose5 as u8,
648 Self::GeneralPurpose6(_) => ControlNumber::GeneralPurpose6 as u8,
649 Self::GeneralPurpose7(_) => ControlNumber::GeneralPurpose7 as u8,
650 Self::GeneralPurpose8(_) => ControlNumber::GeneralPurpose8 as u8,
651 Self::Hold(_) => ControlNumber::Hold as u8,
652 Self::Hold2(_) => ControlNumber::Hold2 as u8,
653 Self::TogglePortamento(_) => ControlNumber::TogglePortamento as u8,
654 Self::Sostenuto(_) => ControlNumber::Sostenuto as u8,
655 Self::SoftPedal(_) => ControlNumber::SoftPedal as u8,
656 Self::ToggleLegato(_) => ControlNumber::ToggleLegato as u8,
657 Self::SoundVariation(_) => ControlNumber::SoundControl1 as u8,
658 Self::Timbre(_) => ControlNumber::SoundControl2 as u8,
659 Self::ReleaseTime(_) => ControlNumber::SoundControl3 as u8,
660 Self::AttackTime(_) => ControlNumber::SoundControl4 as u8,
661 Self::Brightness(_) => ControlNumber::SoundControl5 as u8,
662 Self::DecayTime(_) => ControlNumber::SoundControl6 as u8,
663 Self::VibratoRate(_) => ControlNumber::SoundControl7 as u8,
664 Self::VibratoDepth(_) => ControlNumber::SoundControl8 as u8,
665 Self::VibratoDelay(_) => ControlNumber::SoundControl9 as u8,
666 Self::SoundControl1(_) => ControlNumber::SoundControl1 as u8,
667 Self::SoundControl2(_) => ControlNumber::SoundControl2 as u8,
668 Self::SoundControl3(_) => ControlNumber::SoundControl3 as u8,
669 Self::SoundControl4(_) => ControlNumber::SoundControl4 as u8,
670 Self::SoundControl5(_) => ControlNumber::SoundControl5 as u8,
671 Self::SoundControl6(_) => ControlNumber::SoundControl6 as u8,
672 Self::SoundControl7(_) => ControlNumber::SoundControl7 as u8,
673 Self::SoundControl8(_) => ControlNumber::SoundControl8 as u8,
674 Self::SoundControl9(_) => ControlNumber::SoundControl9 as u8,
675 Self::SoundControl10(_) => ControlNumber::SoundControl10 as u8,
676 Self::HighResVelocity(_) => ControlNumber::HighResVelocity as u8,
677 Self::PortamentoControl(_) => ControlNumber::PortamentoControl as u8,
678 Self::Effects1Depth(_) => ControlNumber::Effects1Depth as u8,
679 Self::Effects2Depth(_) => ControlNumber::Effects2Depth as u8,
680 Self::Effects3Depth(_) => ControlNumber::Effects3Depth as u8,
681 Self::Effects4Depth(_) => ControlNumber::Effects4Depth as u8,
682 Self::Effects5Depth(_) => ControlNumber::Effects5Depth as u8,
683 Self::ReverbSendLevel(_) => ControlNumber::Effects1Depth as u8,
684 Self::TremoloDepth(_) => ControlNumber::Effects2Depth as u8,
685 Self::ChorusSendLevel(_) => ControlNumber::Effects3Depth as u8,
686 Self::CelesteDepth(_) => ControlNumber::Effects4Depth as u8,
687 Self::PhaserDepth(_) => ControlNumber::Effects5Depth as u8,
688 Self::Parameter(Parameter::Unregistered(..)) => {
689 ControlNumber::NonRegisteredParameter as u8
690 }
691 Self::Parameter(_) => ControlNumber::RegisteredParameter as u8,
692 Self::DataEntry(_) => ControlNumber::DataEntry as u8,
693 Self::DataEntry2(_, _) => ControlNumber::DataEntry as u8,
694 Self::DataIncrement(_) => ControlNumber::DataIncrement as u8,
695 Self::DataDecrement(_) => ControlNumber::DataDecrement as u8,
696 }
697 }
698
699 pub fn value(&self) -> u8 {
701 match self {
702 Self::CC { value, .. } => *value,
703 Self::CCHighRes { value, .. } => (*value >> 7) as u8,
704 Self::BankSelect(x)
705 | Self::ModWheel(x)
706 | Self::Breath(x)
707 | Self::Foot(x)
708 | Self::Portamento(x)
709 | Self::Volume(x)
710 | Self::Balance(x)
711 | Self::Pan(x)
712 | Self::Expression(x)
713 | Self::Effect1(x)
714 | Self::Effect2(x)
715 | Self::GeneralPurpose1(x)
716 | Self::GeneralPurpose2(x)
717 | Self::GeneralPurpose3(x)
718 | Self::GeneralPurpose4(x)
719 | Self::DataEntry(x) => (x >> 7) as u8,
720 Self::Hold(x)
721 | Self::Hold2(x)
722 | Self::Sostenuto(x)
723 | Self::SoftPedal(x)
724 | Self::SoundVariation(x)
725 | Self::Timbre(x)
726 | Self::ReleaseTime(x)
727 | Self::AttackTime(x)
728 | Self::Brightness(x)
729 | Self::DecayTime(x)
730 | Self::VibratoRate(x)
731 | Self::VibratoDepth(x)
732 | Self::VibratoDelay(x)
733 | Self::SoundControl1(x)
734 | Self::SoundControl2(x)
735 | Self::SoundControl3(x)
736 | Self::SoundControl4(x)
737 | Self::SoundControl5(x)
738 | Self::SoundControl6(x)
739 | Self::SoundControl7(x)
740 | Self::SoundControl8(x)
741 | Self::SoundControl9(x)
742 | Self::SoundControl10(x)
743 | Self::GeneralPurpose5(x)
744 | Self::GeneralPurpose6(x)
745 | Self::GeneralPurpose7(x)
746 | Self::GeneralPurpose8(x)
747 | Self::PortamentoControl(x)
748 | Self::Effects1Depth(x)
749 | Self::Effects2Depth(x)
750 | Self::Effects3Depth(x)
751 | Self::Effects4Depth(x)
752 | Self::Effects5Depth(x)
753 | Self::ReverbSendLevel(x)
754 | Self::TremoloDepth(x)
755 | Self::ChorusSendLevel(x)
756 | Self::CelesteDepth(x)
757 | Self::PhaserDepth(x)
758 | Self::HighResVelocity(x)
759 | Self::DataDecrement(x)
760 | Self::DataIncrement(x) => *x,
761 Self::DataEntry2(msb, _) => *msb,
762 Self::ToggleLegato(x) | Self::TogglePortamento(x) => {
763 if *x {
764 127
765 } else {
766 0
767 }
768 }
769 Self::Parameter(_) => 0,
770 }
771 }
772
773 pub fn value_high_res(&self) -> u16 {
775 match self {
776 Self::CC { value, .. } => (*value as u16) << 7,
777 Self::CCHighRes { value, .. } => *value,
778 Self::BankSelect(x)
779 | Self::ModWheel(x)
780 | Self::Breath(x)
781 | Self::Foot(x)
782 | Self::Portamento(x)
783 | Self::Volume(x)
784 | Self::Balance(x)
785 | Self::Pan(x)
786 | Self::Expression(x)
787 | Self::Effect1(x)
788 | Self::Effect2(x)
789 | Self::GeneralPurpose1(x)
790 | Self::GeneralPurpose2(x)
791 | Self::GeneralPurpose3(x)
792 | Self::GeneralPurpose4(x)
793 | Self::DataEntry(x) => *x,
794 Self::Hold(x)
795 | Self::Hold2(x)
796 | Self::Sostenuto(x)
797 | Self::SoftPedal(x)
798 | Self::SoundVariation(x)
799 | Self::Timbre(x)
800 | Self::ReleaseTime(x)
801 | Self::AttackTime(x)
802 | Self::Brightness(x)
803 | Self::DecayTime(x)
804 | Self::VibratoRate(x)
805 | Self::VibratoDepth(x)
806 | Self::VibratoDelay(x)
807 | Self::SoundControl1(x)
808 | Self::SoundControl2(x)
809 | Self::SoundControl3(x)
810 | Self::SoundControl4(x)
811 | Self::SoundControl5(x)
812 | Self::SoundControl6(x)
813 | Self::SoundControl7(x)
814 | Self::SoundControl8(x)
815 | Self::SoundControl9(x)
816 | Self::SoundControl10(x)
817 | Self::GeneralPurpose5(x)
818 | Self::GeneralPurpose6(x)
819 | Self::GeneralPurpose7(x)
820 | Self::GeneralPurpose8(x)
821 | Self::PortamentoControl(x)
822 | Self::Effects1Depth(x)
823 | Self::Effects2Depth(x)
824 | Self::Effects3Depth(x)
825 | Self::Effects4Depth(x)
826 | Self::Effects5Depth(x)
827 | Self::ReverbSendLevel(x)
828 | Self::TremoloDepth(x)
829 | Self::ChorusSendLevel(x)
830 | Self::CelesteDepth(x)
831 | Self::PhaserDepth(x)
832 | Self::HighResVelocity(x)
833 | Self::DataDecrement(x)
834 | Self::DataIncrement(x) => (*x as u16) << 7,
835 Self::DataEntry2(msb, lsb) => (*msb as u16) << 7 | *lsb as u16,
836 Self::ToggleLegato(x) | Self::TogglePortamento(x) => {
837 if *x {
838 127 << 7
839 } else {
840 0
841 }
842 }
843 Self::Parameter(_) => 0,
844 }
845 }
846
847 fn high_res_cc(v: &mut Vec<u8>, control: u8, value: u16) {
848 let [msb, lsb] = to_u14(value);
849 v.push(control);
850 v.push(msb);
851 v.push(control + 32);
852 v.push(lsb);
853 }
854
855 #[cfg(feature = "file")]
865 pub(crate) fn sub_ccs(&self) -> Option<Vec<(u8, u8)>> {
866 match self {
867 Self::Parameter(p) => Some(p.sub_ccs()),
868 Self::CCHighRes {
869 control1,
870 control2,
871 value,
872 } => {
873 let [msb, lsb] = to_u14(*value);
874 Some(vec![
875 ((*control1).min(119), msb),
876 ((*control2).min(119), lsb),
877 ])
878 }
879 Self::BankSelect(x) => Some(Self::high_res_sub_ccs(0, *x)),
880 Self::ModWheel(x) => Some(Self::high_res_sub_ccs(1, *x)),
881 Self::Breath(x) => Some(Self::high_res_sub_ccs(2, *x)),
882 Self::Foot(x) => Some(Self::high_res_sub_ccs(4, *x)),
883 Self::Portamento(x) => Some(Self::high_res_sub_ccs(5, *x)),
884 Self::DataEntry(x) => Some(Self::high_res_sub_ccs(6, *x)),
885 Self::DataEntry2(msb, lsb) => Some(vec![(6, *msb), (6 + 32, *lsb)]),
886 Self::Volume(x) => Some(Self::high_res_sub_ccs(7, *x)),
887 Self::Balance(x) => Some(Self::high_res_sub_ccs(8, *x)),
888 Self::Pan(x) => Some(Self::high_res_sub_ccs(10, *x)),
889 Self::Expression(x) => Some(Self::high_res_sub_ccs(11, *x)),
890 Self::Effect1(x) => Some(Self::high_res_sub_ccs(12, *x)),
891 Self::Effect2(x) => Some(Self::high_res_sub_ccs(13, *x)),
892 Self::GeneralPurpose1(x) => Some(Self::high_res_sub_ccs(16, *x)),
893 Self::GeneralPurpose2(x) => Some(Self::high_res_sub_ccs(17, *x)),
894 Self::GeneralPurpose3(x) => Some(Self::high_res_sub_ccs(18, *x)),
895 Self::GeneralPurpose4(x) => Some(Self::high_res_sub_ccs(19, *x)),
896 _ => None,
897 }
898 }
899
900 #[cfg(feature = "file")]
901 fn high_res_sub_ccs(control: u8, value: u16) -> Vec<(u8, u8)> {
902 let [msb, lsb] = to_u14(value);
903 vec![(control, msb), (control + 32, lsb)]
904 }
905
906 fn undefined(v: &mut Vec<u8>, control: u8, value: u8) {
907 v.push(control.min(119));
908 v.push(to_u7(value));
909 }
910
911 fn undefined_high_res(v: &mut Vec<u8>, control1: u8, control2: u8, value: u16) {
912 let [msb, lsb] = to_u14(value);
913 v.push(control1.min(119));
914 v.push(msb);
915 v.push(control2.min(119));
916 v.push(lsb);
917 }
918
919 fn is_msb(&self) -> bool {
920 match self {
921 Self::BankSelect(_)
922 | Self::ModWheel(_)
923 | Self::Breath(_)
924 | Self::DataEntry(_)
925 | Self::CCHighRes { .. }
926 | Self::Foot(_)
927 | Self::Portamento(_)
928 | Self::Volume(_)
929 | Self::Balance(_)
930 | Self::Pan(_)
931 | Self::Expression(_)
932 | Self::Effect1(_)
933 | Self::Effect2(_)
934 | Self::GeneralPurpose1(_)
935 | Self::GeneralPurpose2(_)
936 | Self::GeneralPurpose3(_)
937 | Self::GeneralPurpose4(_) => true,
938 Self::CC { control, .. } if control < &32 || control == &99 || control == &101 => true,
939 _ => false,
940 }
941 }
942
943 fn is_lsb(&self) -> bool {
944 matches!(self, Self::CC { control, .. } if (&32..&64).contains(&control) || control == &98 || control == &100)
945 }
946
947 pub fn to_midi_running(&self) -> Vec<u8> {
948 let mut r: Vec<u8> = vec![];
949 self.extend_midi_running(&mut r);
950 r
951 }
952
953 pub fn extend_midi_running(&self, v: &mut Vec<u8>) {
954 match *self {
955 ControlChange::BankSelect(x) => ControlChange::high_res_cc(v, 0, x),
956 ControlChange::ModWheel(x) => ControlChange::high_res_cc(v, 1, x),
957 ControlChange::Breath(x) => ControlChange::high_res_cc(v, 2, x),
958 ControlChange::CC { control, value } => ControlChange::undefined(v, control, value),
959 ControlChange::CCHighRes {
960 control1,
961 control2,
962 value,
963 } => ControlChange::undefined_high_res(v, control1, control2, value),
964 ControlChange::Foot(x) => ControlChange::high_res_cc(v, 4, x),
965 ControlChange::Portamento(x) => ControlChange::high_res_cc(v, 5, x),
966 ControlChange::Volume(x) => ControlChange::high_res_cc(v, 7, x),
967 ControlChange::Balance(x) => ControlChange::high_res_cc(v, 8, x),
968 ControlChange::Pan(x) => ControlChange::high_res_cc(v, 10, x),
969 ControlChange::Expression(x) => ControlChange::high_res_cc(v, 11, x),
970 ControlChange::Effect1(x) => ControlChange::high_res_cc(v, 12, x),
971 ControlChange::Effect2(x) => ControlChange::high_res_cc(v, 13, x),
972 ControlChange::GeneralPurpose1(x) => ControlChange::high_res_cc(v, 16, x),
973 ControlChange::GeneralPurpose2(x) => ControlChange::high_res_cc(v, 17, x),
974 ControlChange::GeneralPurpose3(x) => ControlChange::high_res_cc(v, 18, x),
975 ControlChange::GeneralPurpose4(x) => ControlChange::high_res_cc(v, 19, x),
976 ControlChange::GeneralPurpose5(x) => {
977 v.push(80);
978 v.push(to_u7(x));
979 }
980 ControlChange::GeneralPurpose6(x) => {
981 v.push(82);
982 v.push(to_u7(x));
983 }
984 ControlChange::GeneralPurpose7(x) => {
985 v.push(83);
986 v.push(to_u7(x));
987 }
988 ControlChange::GeneralPurpose8(x) => {
989 v.push(84);
990 v.push(to_u7(x));
991 }
992 ControlChange::Hold(x) => {
993 v.push(64);
994 v.push(to_u7(x));
995 }
996 ControlChange::Hold2(x) => {
997 v.push(69);
998 v.push(to_u7(x));
999 }
1000 ControlChange::TogglePortamento(on) => {
1001 v.push(65);
1002 v.push(if on { 127 } else { 0 });
1003 }
1004 ControlChange::Sostenuto(x) => {
1005 v.push(66);
1006 v.push(to_u7(x));
1007 }
1008 ControlChange::SoftPedal(x) => {
1009 v.push(67);
1010 v.push(to_u7(x));
1011 }
1012 ControlChange::ToggleLegato(on) => {
1013 v.push(68);
1014 v.push(if on { 127 } else { 0 });
1015 }
1016 ControlChange::SoundVariation(x) | ControlChange::SoundControl1(x) => {
1017 v.push(70);
1018 v.push(to_u7(x));
1019 }
1020 ControlChange::Timbre(x) | ControlChange::SoundControl2(x) => {
1021 v.push(71);
1022 v.push(to_u7(x));
1023 }
1024 ControlChange::ReleaseTime(x) | ControlChange::SoundControl3(x) => {
1025 v.push(72);
1026 v.push(to_u7(x));
1027 }
1028 ControlChange::AttackTime(x) | ControlChange::SoundControl4(x) => {
1029 v.push(73);
1030 v.push(to_u7(x));
1031 }
1032 ControlChange::Brightness(x) | ControlChange::SoundControl5(x) => {
1033 v.push(74);
1034 v.push(to_u7(x));
1035 }
1036 ControlChange::DecayTime(x) | ControlChange::SoundControl6(x) => {
1037 v.push(75);
1038 v.push(to_u7(x));
1039 }
1040 ControlChange::VibratoRate(x) | ControlChange::SoundControl7(x) => {
1041 v.push(76);
1042 v.push(to_u7(x));
1043 }
1044 ControlChange::VibratoDepth(x) | ControlChange::SoundControl8(x) => {
1045 v.push(77);
1046 v.push(to_u7(x));
1047 }
1048 ControlChange::VibratoDelay(x) | ControlChange::SoundControl9(x) => {
1049 v.push(78);
1050 v.push(to_u7(x));
1051 }
1052 ControlChange::SoundControl10(x) => {
1053 v.push(79);
1054 v.push(to_u7(x));
1055 }
1056 ControlChange::PortamentoControl(x) => {
1057 v.push(84);
1058 v.push(to_u7(x));
1059 }
1060 ControlChange::HighResVelocity(x) => {
1061 v.push(88);
1062 v.push(to_u7(x));
1063 }
1064 ControlChange::Effects1Depth(x) | ControlChange::ReverbSendLevel(x) => {
1065 v.push(91);
1066 v.push(to_u7(x));
1067 }
1068 ControlChange::Effects2Depth(x) | ControlChange::TremoloDepth(x) => {
1069 v.push(92);
1070 v.push(to_u7(x));
1071 }
1072 ControlChange::Effects3Depth(x) | ControlChange::ChorusSendLevel(x) => {
1073 v.push(93);
1074 v.push(to_u7(x));
1075 }
1076 ControlChange::Effects4Depth(x) | ControlChange::CelesteDepth(x) => {
1077 v.push(94);
1078 v.push(to_u7(x));
1079 }
1080 ControlChange::Effects5Depth(x) | ControlChange::PhaserDepth(x) => {
1081 v.push(95);
1082 v.push(to_u7(x));
1083 }
1084
1085 ControlChange::Parameter(p) => p.extend_midi_running(v),
1087 ControlChange::DataEntry(x) => ControlChange::high_res_cc(v, 6, x),
1088 ControlChange::DataEntry2(msb, lsb) => {
1089 v.push(6);
1090 v.push(msb);
1091 v.push(6 + 32);
1092 v.push(lsb);
1093 }
1094 ControlChange::DataIncrement(x) => {
1095 v.push(96);
1096 v.push(to_u7(x));
1097 }
1098 ControlChange::DataDecrement(x) => {
1099 v.push(97);
1100 v.push(to_u7(x));
1101 }
1102 }
1103 }
1104
1105 pub(crate) fn from_midi(m: &[u8], ctx: &ReceiverContext) -> Result<Self, ParseError> {
1106 if m.len() < 2 {
1107 return Err(crate::ParseError::UnexpectedEnd);
1108 }
1109
1110 if m[0] > 119 {
1111 return Err(ParseError::Invalid(
1112 "Tried to parse a control change message, but it looks like a channel mode message",
1113 ));
1114 }
1115
1116 let value = u8_from_u7(m[1])?;
1117 if !ctx.complex_cc {
1118 return Ok(ControlChange::CC {
1119 control: m[0],
1120 value,
1121 });
1122 }
1123 Ok(match m[0] {
1124 0 => Self::BankSelect((value as u16) << 7),
1126 1 => Self::ModWheel((value as u16) << 7),
1127 2 => Self::Breath((value as u16) << 7),
1128 4 => Self::Foot((value as u16) << 7),
1129 5 => Self::Portamento((value as u16) << 7),
1130 6 => Self::DataEntry((value as u16) << 7),
1131 7 => Self::Volume((value as u16) << 7),
1132 8 => Self::Balance((value as u16) << 7),
1133 10 => Self::Pan((value as u16) << 7),
1134 11 => Self::Expression((value as u16) << 7),
1135 12 => Self::Effect1((value as u16) << 7),
1136 13 => Self::Effect2((value as u16) << 7),
1137 16 => Self::GeneralPurpose1((value as u16) << 7),
1138 17 => Self::GeneralPurpose2((value as u16) << 7),
1139 18 => Self::GeneralPurpose3((value as u16) << 7),
1140 19 => Self::GeneralPurpose4((value as u16) << 7),
1141 64 => Self::Hold(value),
1143 65 => Self::TogglePortamento(bool_from_u7(m[1])?),
1144 66 => Self::Sostenuto(value),
1145 67 => Self::SoftPedal(value),
1146 68 => Self::ToggleLegato(bool_from_u7(m[1])?),
1147 69 => Self::Hold2(value),
1148 70 => Self::SoundControl1(value),
1149 71 => Self::SoundControl2(value),
1150 72 => Self::SoundControl3(value),
1151 73 => Self::SoundControl4(value),
1152 74 => Self::SoundControl5(value),
1153 75 => Self::SoundControl6(value),
1154 76 => Self::SoundControl7(value),
1155 77 => Self::SoundControl8(value),
1156 78 => Self::SoundControl9(value),
1157 79 => Self::SoundControl10(value),
1158 80 => Self::GeneralPurpose5(value),
1159 81 => Self::GeneralPurpose6(value),
1160 82 => Self::GeneralPurpose7(value),
1161 83 => Self::GeneralPurpose8(value),
1162 84 => Self::PortamentoControl(value),
1163 88 => Self::HighResVelocity(value),
1164 91 => Self::Effects1Depth(value),
1165 92 => Self::Effects2Depth(value),
1166 93 => Self::Effects3Depth(value),
1167 94 => Self::Effects4Depth(value),
1168 95 => Self::Effects5Depth(value),
1169 96 => Self::DataIncrement(value),
1170 97 => Self::DataDecrement(value),
1171 3 | 9 | 14 | 15 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 => {
1173 Self::CCHighRes {
1174 control1: m[0],
1175 control2: m[0] + 32,
1176 value: (value as u16) << 7,
1177 }
1178 }
1179 control => Self::CC { control, value },
1180 })
1181 }
1182
1183 fn maybe_extend(&self, other: &Self) -> Result<Self, ()> {
1184 match (self, other) {
1185 (Self::BankSelect(msb), Self::CC { control, value })
1186 | (Self::CC { control, value }, Self::BankSelect(msb))
1187 if *control == ControlNumber::BankSelectLSB as u8 =>
1188 {
1189 Ok(Self::BankSelect(replace_u14_lsb(*msb, *value)))
1190 }
1191 (Self::ModWheel(msb), Self::CC { control, value })
1192 | (Self::CC { control, value }, Self::ModWheel(msb))
1193 if *control == ControlNumber::ModWheelLSB as u8 =>
1194 {
1195 Ok(Self::ModWheel(replace_u14_lsb(*msb, *value)))
1196 }
1197 (Self::Breath(msb), Self::CC { control, value })
1198 | (Self::CC { control, value }, Self::Breath(msb))
1199 if *control == ControlNumber::BreathLSB as u8 =>
1200 {
1201 Ok(Self::Breath(replace_u14_lsb(*msb, *value)))
1202 }
1203 (Self::Foot(msb), Self::CC { control, value })
1204 | (Self::CC { control, value }, Self::Foot(msb))
1205 if *control == ControlNumber::FootLSB as u8 =>
1206 {
1207 Ok(Self::Foot(replace_u14_lsb(*msb, *value)))
1208 }
1209 (Self::Portamento(msb), Self::CC { control, value })
1210 | (Self::CC { control, value }, Self::Portamento(msb))
1211 if *control == ControlNumber::PortamentoLSB as u8 =>
1212 {
1213 Ok(Self::Portamento(replace_u14_lsb(*msb, *value)))
1214 }
1215 (Self::DataEntry(msb), Self::CC { control, value })
1216 | (Self::CC { control, value }, Self::DataEntry(msb))
1217 if *control == ControlNumber::DataEntryLSB as u8 =>
1218 {
1219 Ok(Self::DataEntry(replace_u14_lsb(*msb, *value)))
1220 }
1221 (Self::Volume(msb), Self::CC { control, value })
1222 | (Self::CC { control, value }, Self::Volume(msb))
1223 if *control == ControlNumber::VolumeLSB as u8 =>
1224 {
1225 Ok(Self::Volume(replace_u14_lsb(*msb, *value)))
1226 }
1227 (Self::Balance(msb), Self::CC { control, value })
1228 | (Self::CC { control, value }, Self::Balance(msb))
1229 if *control == ControlNumber::BalanceLSB as u8 =>
1230 {
1231 Ok(Self::Balance(replace_u14_lsb(*msb, *value)))
1232 }
1233 (Self::Pan(msb), Self::CC { control, value })
1234 | (Self::CC { control, value }, Self::Pan(msb))
1235 if *control == ControlNumber::PanLSB as u8 =>
1236 {
1237 Ok(Self::Pan(replace_u14_lsb(*msb, *value)))
1238 }
1239 (Self::Expression(msb), Self::CC { control, value })
1240 | (Self::CC { control, value }, Self::Expression(msb))
1241 if *control == ControlNumber::ExpressionLSB as u8 =>
1242 {
1243 Ok(Self::Expression(replace_u14_lsb(*msb, *value)))
1244 }
1245 (Self::Effect1(msb), Self::CC { control, value })
1246 | (Self::CC { control, value }, Self::Effect1(msb))
1247 if *control == ControlNumber::Effect1LSB as u8 =>
1248 {
1249 Ok(Self::Effect1(replace_u14_lsb(*msb, *value)))
1250 }
1251 (Self::Effect2(msb), Self::CC { control, value })
1252 | (Self::CC { control, value }, Self::Effect2(msb))
1253 if *control == ControlNumber::Effect2LSB as u8 =>
1254 {
1255 Ok(Self::Effect2(replace_u14_lsb(*msb, *value)))
1256 }
1257 (Self::GeneralPurpose1(msb), Self::CC { control, value })
1258 | (Self::CC { control, value }, Self::GeneralPurpose1(msb))
1259 if *control == ControlNumber::GeneralPurpose1LSB as u8 =>
1260 {
1261 Ok(Self::GeneralPurpose1(replace_u14_lsb(*msb, *value)))
1262 }
1263 (Self::GeneralPurpose2(msb), Self::CC { control, value })
1264 | (Self::CC { control, value }, Self::GeneralPurpose2(msb))
1265 if *control == ControlNumber::GeneralPurpose2LSB as u8 =>
1266 {
1267 Ok(Self::GeneralPurpose2(replace_u14_lsb(*msb, *value)))
1268 }
1269 (Self::GeneralPurpose3(msb), Self::CC { control, value })
1270 | (Self::CC { control, value }, Self::GeneralPurpose3(msb))
1271 if *control == ControlNumber::GeneralPurpose3LSB as u8 =>
1272 {
1273 Ok(Self::GeneralPurpose3(replace_u14_lsb(*msb, *value)))
1274 }
1275 (Self::GeneralPurpose4(msb), Self::CC { control, value })
1276 | (Self::CC { control, value }, Self::GeneralPurpose4(msb))
1277 if *control == ControlNumber::GeneralPurpose4LSB as u8 =>
1278 {
1279 Ok(Self::GeneralPurpose4(replace_u14_lsb(*msb, *value)))
1280 }
1281 (
1282 Self::CCHighRes {
1283 control1,
1284 control2,
1285 value: msb,
1286 },
1287 Self::CC { control, value },
1288 )
1289 | (
1290 Self::CC { control, value },
1291 Self::CCHighRes {
1292 control1,
1293 control2,
1294 value: msb,
1295 },
1296 ) if control == control2 => Ok(Self::CCHighRes {
1297 control1: *control1,
1298 control2: *control2,
1299 value: replace_u14_lsb(*msb, *value),
1300 }),
1301 (
1303 Self::CC {
1304 control: ctrl1,
1305 value: val1,
1306 },
1307 Self::CC {
1308 control: ctrl2,
1309 value: val2,
1310 },
1311 ) => {
1312 let ((ctrl_lsb, ctrl_msb), (val_lsb, val_msb)) = if ctrl1 < ctrl2 {
1313 ((*ctrl1, *ctrl2), (*val1, *val2))
1314 } else {
1315 ((*ctrl2, *ctrl1), (*val2, *val1))
1316 };
1317
1318 if ctrl_lsb == ControlNumber::NonRegisteredParameterLSB as u8
1319 && ctrl_msb == ControlNumber::NonRegisteredParameter as u8
1320 {
1321 Ok(Self::Parameter(Parameter::Unregistered(u14_from_u7s(
1322 val_msb, val_lsb,
1323 ))))
1324 } else if ctrl_lsb == ControlNumber::RegisteredParameterLSB as u8
1325 && ctrl_msb == ControlNumber::RegisteredParameter as u8
1326 {
1327 Ok(Self::Parameter(Parameter::maybe_extend_cc(
1328 val_msb, val_lsb,
1329 )?))
1330 } else {
1331 Err(())
1332 }
1333 }
1334 (Self::Parameter(param), Self::CC { control, value })
1335 | (Self::CC { control, value }, Self::Parameter(param))
1336 if *control == ControlNumber::DataEntryLSB as u8 =>
1337 {
1338 Ok(Self::Parameter(param.maybe_extend(None, Some(*value))?))
1339 }
1340
1341 (Self::Parameter(param), Self::DataEntry(value))
1342 | (Self::DataEntry(value), Self::Parameter(param)) => {
1343 Ok(Self::Parameter(param.maybe_extend(Some(*value), None)?))
1344 }
1345 _ => Err(()),
1346 }
1347 }
1348}
1349
1350#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1351pub enum Parameter {
1354 Unregistered(u16),
1356 Null,
1359 PitchBendSensitivity,
1363 PitchBendSensitivityEntry(u8, u8),
1364 FineTuning,
1367 FineTuningEntry(i16),
1368 CoarseTuning,
1370 CoarseTuningEntry(i8),
1371 TuningProgramSelect,
1375 TuningProgramSelectEntry(u8),
1376 TuningBankSelect,
1380 TuningBankSelectEntry(u8),
1381 ModulationDepthRange,
1385 ModulationDepthRangeEntry(u16),
1386 PolyphonicExpression,
1394 PolyphonicExpressionEntry(u8),
1395 AzimuthAngle3DSound,
1399 AzimuthAngle3DSoundEntry(u16),
1400 ElevationAngle3DSound,
1404 ElevationAngle3DSoundEntry(u16),
1405 Gain3DSound,
1411 Gain3DSoundEntry(u16),
1412 DistanceRatio3DSound,
1416 DistanceRatio3DSoundEntry(u16),
1417 MaxiumumDistance3DSound,
1420 MaxiumumDistance3DSoundEntry(u16),
1421 GainAtMaxiumumDistance3DSound,
1424 GainAtMaxiumumDistance3DSoundEntry(u16),
1425 ReferenceDistanceRatio3DSound,
1428 ReferenceDistanceRatio3DSoundEntry(u16),
1429 PanSpreadAngle3DSound,
1432 PanSpreadAngle3DSoundEntry(u16),
1433 RollAngle3DSound,
1436 RollAngle3DSoundEntry(u16),
1437}
1438
1439impl Parameter {
1440 pub(crate) fn sub_ccs(&self) -> Vec<(u8, u8)> {
1448 match self {
1449 Self::Null => vec![(100, 0x7F), (101, 0x7F)],
1450 Self::PitchBendSensitivity => vec![(100, 0), (101, 0)],
1451 Self::PitchBendSensitivityEntry(c, f) => {
1452 vec![(100, 0), (101, 0), (6, *c), (6 + 32, (*f).min(100))]
1453 }
1454 Self::FineTuning => vec![(100, 1), (101, 0)],
1455 Self::FineTuningEntry(x) => {
1456 let [msb, lsb] = i_to_u14(*x);
1457 vec![(100, 1), (101, 0), (6, msb), (6 + 32, lsb)]
1458 }
1459 Self::CoarseTuning => vec![(100, 2), (101, 0)],
1460 Self::CoarseTuningEntry(x) => {
1461 let msb = i_to_u7(*x);
1462 vec![(100, 2), (101, 0), (6, msb), (6 + 32, 0)]
1463 }
1464 Self::TuningProgramSelect => vec![(100, 3), (101, 0)],
1465 Self::TuningProgramSelectEntry(x) => vec![(100, 3), (101, 0), (6, *x)],
1466 Self::TuningBankSelect => vec![(100, 4), (101, 0)],
1467 Self::TuningBankSelectEntry(x) => vec![(100, 4), (101, 0), (6, *x)],
1468 Self::ModulationDepthRange => vec![(100, 5), (101, 0)],
1469 Self::ModulationDepthRangeEntry(x) => {
1470 let [msb, lsb] = to_u14(*x);
1471 vec![(100, 5), (101, 0), (6, msb), (6 + 32, lsb)]
1472 }
1473 Self::PolyphonicExpression => vec![(100, 6), (101, 0)],
1474 Self::PolyphonicExpressionEntry(x) => {
1475 vec![(100, 6), (101, 0), (6, (*x).min(16))]
1476 }
1477 Self::AzimuthAngle3DSound => vec![(100, 0), (101, 61)],
1478 Self::AzimuthAngle3DSoundEntry(x) => {
1479 let [msb, lsb] = to_u14(*x);
1480 vec![(100, 0), (101, 61), (6, msb), (6 + 32, lsb)]
1481 }
1482 Self::ElevationAngle3DSound => vec![(100, 1), (101, 61)],
1483 Self::ElevationAngle3DSoundEntry(x) => {
1484 let [msb, lsb] = to_u14(*x);
1485 vec![(100, 1), (101, 61), (6, msb), (6 + 32, lsb)]
1486 }
1487 Self::Gain3DSound => vec![(100, 2), (101, 61)],
1488 Self::Gain3DSoundEntry(x) => {
1489 let [msb, lsb] = to_u14(*x);
1490 vec![(100, 2), (101, 61), (6, msb), (6 + 32, lsb)]
1491 }
1492 Self::DistanceRatio3DSound => vec![(100, 3), (101, 61)],
1493 Self::DistanceRatio3DSoundEntry(x) => {
1494 let [msb, lsb] = to_u14(*x);
1495 vec![(100, 3), (101, 61), (6, msb), (6 + 32, lsb)]
1496 }
1497 Self::MaxiumumDistance3DSound => vec![(100, 4), (101, 61)],
1498 Self::MaxiumumDistance3DSoundEntry(x) => {
1499 let [msb, lsb] = to_u14(*x);
1500 vec![(100, 4), (101, 61), (6, msb), (6 + 32, lsb)]
1501 }
1502 Self::GainAtMaxiumumDistance3DSound => vec![(100, 5), (101, 61)],
1503 Self::GainAtMaxiumumDistance3DSoundEntry(x) => {
1504 let [msb, lsb] = to_u14(*x);
1505 vec![(100, 5), (101, 61), (6, msb), (6 + 32, lsb)]
1506 }
1507 Self::ReferenceDistanceRatio3DSound => vec![(100, 6), (101, 61)],
1508 Self::ReferenceDistanceRatio3DSoundEntry(x) => {
1509 let [msb, lsb] = to_u14(*x);
1510 vec![(100, 6), (101, 61), (6, msb), (6 + 32, lsb)]
1511 }
1512 Self::PanSpreadAngle3DSound => vec![(100, 7), (101, 61)],
1513 Self::PanSpreadAngle3DSoundEntry(x) => {
1514 let [msb, lsb] = to_u14(*x);
1515 vec![(100, 7), (101, 61), (6, msb), (6 + 32, lsb)]
1516 }
1517 Self::RollAngle3DSound => vec![(100, 8), (101, 61)],
1518 Self::RollAngle3DSoundEntry(x) => {
1519 let [msb, lsb] = to_u14(*x);
1520 vec![(100, 8), (101, 61), (6, msb), (6 + 32, lsb)]
1521 }
1522 Self::Unregistered(x) => {
1523 let [msb, lsb] = to_u14(*x);
1524 vec![(98, lsb), (99, msb)]
1525 }
1526 }
1527 }
1528
1529 fn extend_midi_running(&self, v: &mut Vec<u8>) {
1530 for (control, value) in self.sub_ccs() {
1531 v.push(control);
1532 v.push(value);
1533 }
1534 }
1535
1536 fn maybe_extend_cc(msb: u8, lsb: u8) -> Result<Self, ()> {
1537 match (msb, lsb) {
1538 (0x7F, 0x7F) => Ok(Self::Null),
1539 (0, 0) => Ok(Self::PitchBendSensitivity),
1540 (0, 1) => Ok(Self::FineTuning),
1541 (0, 2) => Ok(Self::CoarseTuning),
1542 (0, 3) => Ok(Self::TuningProgramSelect),
1543 (0, 4) => Ok(Self::TuningBankSelect),
1544 (0, 5) => Ok(Self::ModulationDepthRange),
1545 (0, 6) => Ok(Self::PolyphonicExpression),
1546 (61, 0) => Ok(Self::AzimuthAngle3DSound),
1547 (61, 1) => Ok(Self::ElevationAngle3DSound),
1548 (61, 2) => Ok(Self::Gain3DSound),
1549 (61, 3) => Ok(Self::DistanceRatio3DSound),
1550 (61, 4) => Ok(Self::MaxiumumDistance3DSound),
1551 (61, 5) => Ok(Self::GainAtMaxiumumDistance3DSound),
1552 (61, 6) => Ok(Self::ReferenceDistanceRatio3DSound),
1553 (61, 7) => Ok(Self::PanSpreadAngle3DSound),
1554 (61, 8) => Ok(Self::RollAngle3DSound),
1555 _ => Err(()),
1556 }
1557 }
1558
1559 fn maybe_extend(&self, msb: Option<u16>, lsb: Option<u8>) -> Result<Self, ()> {
1560 match self {
1561 Self::PitchBendSensitivity => Ok(Self::PitchBendSensitivityEntry(
1562 msb.map_or(0, |v| (v >> 7) as u8),
1563 lsb.unwrap_or(0),
1564 )),
1565 Self::PitchBendSensitivityEntry(v1, v2) => Ok(Self::PitchBendSensitivityEntry(
1566 msb.map_or(*v1, |v| v as u8),
1567 lsb.unwrap_or(*v2),
1568 )),
1569 Self::FineTuning => Ok(Self::FineTuningEntry(i14_from_u7s(
1570 msb.map_or(0, |v| (v >> 7) as u8),
1571 lsb.unwrap_or(0),
1572 ))),
1573 Self::FineTuningEntry(v) => Ok(Self::FineTuningEntry(i14_from_u7s(
1574 msb.map_or(i_to_u14(*v)[0], |v| v as u8),
1575 lsb.unwrap_or(i_to_u14(*v)[1]),
1576 ))),
1577 Self::CoarseTuning => Ok(Self::CoarseTuningEntry(msb.map_or(0, |v| u7_to_i(v as u8)))),
1578 Self::CoarseTuningEntry(v) => Ok(Self::CoarseTuningEntry(
1579 msb.map_or(*v, |v| u7_to_i(v as u8)),
1580 )),
1581 Self::TuningProgramSelect => {
1582 Ok(Self::TuningProgramSelectEntry(msb.map_or(0, |v| v as u8)))
1583 }
1584 Self::TuningProgramSelectEntry(v) => {
1585 Ok(Self::TuningProgramSelectEntry(msb.map_or(*v, |v| v as u8)))
1586 }
1587 Self::TuningBankSelect => Ok(Self::TuningBankSelectEntry(msb.map_or(0, |v| v as u8))),
1588 Self::TuningBankSelectEntry(v) => {
1589 Ok(Self::TuningBankSelectEntry(msb.map_or(*v, |v| v as u8)))
1590 }
1591 Self::ModulationDepthRange => Ok(Self::ModulationDepthRangeEntry(replace_u14_lsb(
1592 msb.unwrap_or(0),
1593 lsb.unwrap_or(0),
1594 ))),
1595 Self::ModulationDepthRangeEntry(v) => Ok(Self::ModulationDepthRangeEntry(
1596 replace_u14_lsb(msb.unwrap_or(*v), lsb.unwrap_or((*v as u8) & 0b01111111)),
1597 )),
1598 Self::PolyphonicExpression => {
1599 Ok(Self::PolyphonicExpressionEntry(msb.map_or(0, |v| v as u8)))
1600 }
1601 Self::PolyphonicExpressionEntry(v) => {
1602 Ok(Self::PolyphonicExpressionEntry(msb.map_or(*v, |v| v as u8)))
1603 }
1604 Self::AzimuthAngle3DSound => Ok(Self::AzimuthAngle3DSoundEntry(replace_u14_lsb(
1605 msb.unwrap_or(0),
1606 lsb.unwrap_or(0),
1607 ))),
1608 Self::AzimuthAngle3DSoundEntry(v) => Ok(Self::AzimuthAngle3DSoundEntry(
1609 replace_u14_lsb(msb.unwrap_or(*v), lsb.unwrap_or((*v as u8) & 0b01111111)),
1610 )),
1611 Self::ElevationAngle3DSound => Ok(Self::ElevationAngle3DSoundEntry(replace_u14_lsb(
1612 msb.unwrap_or(0),
1613 lsb.unwrap_or(0),
1614 ))),
1615 Self::ElevationAngle3DSoundEntry(v) => Ok(Self::ElevationAngle3DSoundEntry(
1616 replace_u14_lsb(msb.unwrap_or(*v), lsb.unwrap_or((*v as u8) & 0b01111111)),
1617 )),
1618 Self::Gain3DSound => Ok(Self::Gain3DSoundEntry(replace_u14_lsb(
1619 msb.unwrap_or(0),
1620 lsb.unwrap_or(0),
1621 ))),
1622 Self::Gain3DSoundEntry(v) => Ok(Self::Gain3DSoundEntry(replace_u14_lsb(
1623 msb.unwrap_or(*v),
1624 lsb.unwrap_or((*v as u8) & 0b01111111),
1625 ))),
1626 Self::DistanceRatio3DSound => Ok(Self::DistanceRatio3DSoundEntry(replace_u14_lsb(
1627 msb.unwrap_or(0),
1628 lsb.unwrap_or(0),
1629 ))),
1630 Self::DistanceRatio3DSoundEntry(v) => Ok(Self::DistanceRatio3DSoundEntry(
1631 replace_u14_lsb(msb.unwrap_or(*v), lsb.unwrap_or((*v as u8) & 0b01111111)),
1632 )),
1633 Self::MaxiumumDistance3DSound => Ok(Self::MaxiumumDistance3DSoundEntry(
1634 replace_u14_lsb(msb.unwrap_or(0), lsb.unwrap_or(0)),
1635 )),
1636 Self::MaxiumumDistance3DSoundEntry(v) => Ok(Self::MaxiumumDistance3DSoundEntry(
1637 replace_u14_lsb(msb.unwrap_or(*v), lsb.unwrap_or((*v as u8) & 0b01111111)),
1638 )),
1639 Self::GainAtMaxiumumDistance3DSound => Ok(Self::GainAtMaxiumumDistance3DSoundEntry(
1640 replace_u14_lsb(msb.unwrap_or(0), lsb.unwrap_or(0)),
1641 )),
1642 Self::GainAtMaxiumumDistance3DSoundEntry(v) => {
1643 Ok(Self::GainAtMaxiumumDistance3DSoundEntry(replace_u14_lsb(
1644 msb.unwrap_or(*v),
1645 lsb.unwrap_or((*v as u8) & 0b01111111),
1646 )))
1647 }
1648 Self::ReferenceDistanceRatio3DSound => Ok(Self::ReferenceDistanceRatio3DSoundEntry(
1649 replace_u14_lsb(msb.unwrap_or(0), lsb.unwrap_or(0)),
1650 )),
1651 Self::ReferenceDistanceRatio3DSoundEntry(v) => {
1652 Ok(Self::ReferenceDistanceRatio3DSoundEntry(replace_u14_lsb(
1653 msb.unwrap_or(*v),
1654 lsb.unwrap_or((*v as u8) & 0b01111111),
1655 )))
1656 }
1657 Self::PanSpreadAngle3DSound => Ok(Self::PanSpreadAngle3DSoundEntry(replace_u14_lsb(
1658 msb.unwrap_or(0),
1659 lsb.unwrap_or(0),
1660 ))),
1661 Self::PanSpreadAngle3DSoundEntry(v) => Ok(Self::PanSpreadAngle3DSoundEntry(
1662 replace_u14_lsb(msb.unwrap_or(*v), lsb.unwrap_or((*v as u8) & 0b01111111)),
1663 )),
1664 Self::RollAngle3DSound => Ok(Self::RollAngle3DSoundEntry(replace_u14_lsb(
1665 msb.unwrap_or(0),
1666 lsb.unwrap_or(0),
1667 ))),
1668 Self::RollAngle3DSoundEntry(v) => Ok(Self::RollAngle3DSoundEntry(replace_u14_lsb(
1669 msb.unwrap_or(*v),
1670 lsb.unwrap_or((*v as u8) & 0b01111111),
1671 ))),
1672 _ => Err(()),
1673 }
1674 }
1675}
1676
1677#[cfg(test)]
1678mod tests {
1679 use crate::*;
1680 use alloc::vec;
1681
1682 #[test]
1683 fn serialize_channel_voice_msg() {
1684 assert_eq!(
1685 MidiMsg::ChannelVoice {
1686 channel: Channel::Ch1,
1687 msg: ChannelVoiceMsg::NoteOn {
1688 note: 0x88,
1689 velocity: 0xff
1690 }
1691 }
1692 .to_midi(),
1693 vec![0x90, 0x7f, 127]
1694 );
1695
1696 assert_eq!(
1697 MidiMsg::RunningChannelVoice {
1698 channel: Channel::Ch10,
1699 msg: ChannelVoiceMsg::PitchBend { bend: 0xff44 }
1700 }
1701 .to_midi(),
1702 vec![0x7f, 0x7f]
1703 );
1704
1705 assert_eq!(
1706 MidiMsg::ChannelVoice {
1707 channel: Channel::Ch10,
1708 msg: ChannelVoiceMsg::PitchBend { bend: 1000 }
1709 }
1710 .to_midi(),
1711 vec![0xE9, 0x68, 0x07]
1712 );
1713
1714 assert_eq!(
1715 MidiMsg::ChannelVoice {
1716 channel: Channel::Ch2,
1717 msg: ChannelVoiceMsg::ControlChange {
1718 control: ControlChange::Volume(1000)
1719 }
1720 }
1721 .to_midi(),
1722 vec![0xB1, 7, 0x07, 39, 0x68]
1723 );
1724
1725 assert_eq!(
1726 MidiMsg::ChannelVoice {
1727 channel: Channel::Ch4,
1728 msg: ChannelVoiceMsg::ControlChange {
1729 control: ControlChange::CC {
1730 control: 85,
1731 value: 77
1732 }
1733 }
1734 }
1735 .to_midi(),
1736 vec![0xB3, 85, 77]
1737 );
1738
1739 assert_eq!(
1740 MidiMsg::ChannelVoice {
1741 channel: Channel::Ch2,
1742 msg: ChannelVoiceMsg::ControlChange {
1743 control: ControlChange::CCHighRes {
1744 control1: 3,
1745 control2: 35,
1746 value: 1000
1747 }
1748 }
1749 }
1750 .to_midi(),
1751 vec![0xB1, 3, 0x07, 35, 0x68]
1752 );
1753
1754 assert_eq!(
1755 MidiMsg::ChannelVoice {
1756 channel: Channel::Ch3,
1757 msg: ChannelVoiceMsg::ControlChange {
1758 control: ControlChange::TogglePortamento(true)
1759 }
1760 }
1761 .to_midi(),
1762 vec![0xB2, 65, 0x7f]
1763 );
1764
1765 assert_eq!(
1766 MidiMsg::ChannelVoice {
1767 channel: Channel::Ch2,
1768 msg: ChannelVoiceMsg::ControlChange {
1769 control: ControlChange::Parameter(Parameter::FineTuning)
1770 }
1771 }
1772 .to_midi(),
1773 vec![0xB1, 100, 0x01, 101, 0x00]
1774 );
1775
1776 assert_eq!(
1777 MidiMsg::ChannelVoice {
1778 channel: Channel::Ch2,
1779 msg: ChannelVoiceMsg::ControlChange {
1780 control: ControlChange::Parameter(Parameter::Unregistered(1000))
1781 }
1782 }
1783 .to_midi(),
1784 vec![0xB1, 98, 0x68, 99, 0x07]
1785 );
1786 }
1787
1788 #[test]
1789 fn deserialize_channel_voice_msg() {
1790 let mut ctx = ReceiverContext::new().complex_cc();
1791
1792 test_serialization(
1793 MidiMsg::ChannelVoice {
1794 channel: Channel::Ch1,
1795 msg: ChannelVoiceMsg::NoteOn {
1796 note: 0x7f,
1797 velocity: 0x7f,
1798 },
1799 },
1800 &mut ctx,
1801 );
1802
1803 test_serialization(
1804 MidiMsg::ChannelVoice {
1805 channel: Channel::Ch10,
1806 msg: ChannelVoiceMsg::PitchBend { bend: 1000 },
1807 },
1808 &mut ctx,
1809 );
1810
1811 test_serialization(
1812 MidiMsg::ChannelVoice {
1813 channel: Channel::Ch2,
1814 msg: ChannelVoiceMsg::ControlChange {
1815 control: ControlChange::Volume(1000),
1816 },
1817 },
1818 &mut ctx,
1819 );
1820
1821 test_serialization(
1822 MidiMsg::ChannelVoice {
1823 channel: Channel::Ch4,
1824 msg: ChannelVoiceMsg::ControlChange {
1825 control: ControlChange::CC {
1826 control: 85,
1827 value: 77,
1828 },
1829 },
1830 },
1831 &mut ctx,
1832 );
1833
1834 test_serialization(
1835 MidiMsg::ChannelVoice {
1836 channel: Channel::Ch2,
1837 msg: ChannelVoiceMsg::ControlChange {
1838 control: ControlChange::CCHighRes {
1839 control1: 3,
1840 control2: 35,
1841 value: 1000,
1842 },
1843 },
1844 },
1845 &mut ctx,
1846 );
1847
1848 test_serialization(
1849 MidiMsg::ChannelVoice {
1850 channel: Channel::Ch3,
1851 msg: ChannelVoiceMsg::ControlChange {
1852 control: ControlChange::TogglePortamento(true),
1853 },
1854 },
1855 &mut ctx,
1856 );
1857
1858 test_serialization(
1859 MidiMsg::ChannelVoice {
1860 channel: Channel::Ch2,
1861 msg: ChannelVoiceMsg::ControlChange {
1862 control: ControlChange::Parameter(Parameter::FineTuning),
1863 },
1864 },
1865 &mut ctx,
1866 );
1867
1868 test_serialization(
1869 MidiMsg::ChannelVoice {
1870 channel: Channel::Ch2,
1871 msg: ChannelVoiceMsg::ControlChange {
1872 control: ControlChange::Parameter(Parameter::Unregistered(1000)),
1873 },
1874 },
1875 &mut ctx,
1876 );
1877
1878 test_serialization(
1879 MidiMsg::ChannelVoice {
1880 channel: Channel::Ch3,
1881 msg: ChannelVoiceMsg::HighResNoteOn {
1882 note: 77,
1883 velocity: 1000,
1884 },
1885 },
1886 &mut ctx,
1887 );
1888
1889 test_serialization(
1890 MidiMsg::ChannelVoice {
1891 channel: Channel::Ch2,
1892 msg: ChannelVoiceMsg::ControlChange {
1893 control: ControlChange::Parameter(Parameter::FineTuningEntry(-30)),
1894 },
1895 },
1896 &mut ctx,
1897 );
1898
1899 test_serialization(
1900 MidiMsg::ChannelVoice {
1901 channel: Channel::Ch2,
1902 msg: ChannelVoiceMsg::ControlChange {
1903 control: ControlChange::Parameter(Parameter::Gain3DSoundEntry(1001)),
1904 },
1905 },
1906 &mut ctx,
1907 );
1908
1909 test_serialization(
1910 MidiMsg::ChannelVoice {
1911 channel: Channel::Ch2,
1912 msg: ChannelVoiceMsg::ControlChange {
1913 control: ControlChange::Parameter(Parameter::PitchBendSensitivityEntry(4, 78)),
1914 },
1915 },
1916 &mut ctx,
1917 );
1918
1919 test_serialization(
1920 MidiMsg::ChannelVoice {
1921 channel: Channel::Ch2,
1922 msg: ChannelVoiceMsg::ControlChange {
1923 control: ControlChange::GeneralPurpose1(50),
1924 },
1925 },
1926 &mut ctx,
1927 );
1928 }
1929
1930 #[test]
1931 fn test_cc_control_and_value() {
1932 assert_eq!(
1933 ControlChange::CC {
1934 control: 20,
1935 value: 40
1936 }
1937 .control(),
1938 20
1939 );
1940 assert_eq!(
1941 ControlChange::CC {
1942 control: 20,
1943 value: 40
1944 }
1945 .value(),
1946 40
1947 );
1948 assert_eq!(
1949 ControlChange::CC {
1950 control: 20,
1951 value: 40
1952 }
1953 .value_high_res(),
1954 40 << 7
1955 );
1956
1957 assert_eq!(ControlChange::Breath(40 << 7).control(), 2);
1958 assert_eq!(ControlChange::Breath(40 << 7).value(), 40);
1959 assert_eq!(ControlChange::Breath(40 << 7).value_high_res(), 40 << 7);
1960 }
1961
1962 #[test]
1963 fn test_cc_to_complex_and_to_simple() {
1964 assert_eq!(
1965 ControlChange::CC {
1966 control: 2,
1967 value: 40
1968 }
1969 .to_complex(),
1970 ControlChange::Breath(40 << 7)
1971 );
1972 assert_eq!(
1973 ControlChange::Breath(40 << 7).to_simple(),
1974 ControlChange::CC {
1975 control: 2,
1976 value: 40
1977 }
1978 );
1979 assert_eq!(
1980 ControlChange::Breath(40 << 7).to_simple_high_res(),
1981 ControlChange::CCHighRes {
1982 control1: 2,
1983 control2: 34,
1984 value: 40 << 7
1985 }
1986 );
1987
1988 assert_eq!(
1989 ControlChange::CC {
1990 control: 20,
1991 value: 40
1992 }
1993 .to_complex(),
1994 ControlChange::CCHighRes {
1995 control1: 20,
1996 control2: 52,
1997 value: 40 << 7,
1998 }
1999 );
2000 assert_eq!(
2001 ControlChange::CCHighRes {
2002 control1: 20,
2003 control2: 52,
2004 value: 40 << 7,
2005 }
2006 .to_simple(),
2007 ControlChange::CC {
2008 control: 20,
2009 value: 40,
2010 },
2011 );
2012 assert_eq!(
2013 ControlChange::CCHighRes {
2014 control1: 20,
2015 control2: 52,
2016 value: 40 << 7,
2017 }
2018 .to_simple_high_res(),
2019 ControlChange::CCHighRes {
2020 control1: 20,
2021 control2: 52,
2022 value: 40 << 7,
2023 }
2024 );
2025 }
2026}