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