Skip to main content

midi2/channel_voice2/
note_off.rs

1use crate::{
2    channel_voice2::{
3        attribute::{Attribute, AttributeProperty},
4        UMP_MESSAGE_TYPE,
5    },
6    detail::{common_properties, schema},
7    ux::{u4, u7},
8};
9
10pub(crate) const STATUS: u8 = 0b1000;
11
12/// MIDI 2.0 Channel Voice Note Off Message
13///
14/// See the [module docs](crate::channel_voice2) for more info.
15#[midi2_proc::generate_message(Via(crate::channel_voice2::ChannelVoice2), FixedSize, MinSizeUmp(2))]
16struct NoteOff {
17    #[property(common_properties::UmpMessageTypeProperty<UMP_MESSAGE_TYPE>)]
18    ump_type: (),
19    #[property(common_properties::ChannelVoiceStatusProperty<STATUS>)]
20    status: (),
21    #[property(common_properties::UmpSchemaProperty<u4, schema::Ump<0x000F_0000, 0x0, 0x0, 0x0>>)]
22    channel: u4,
23    #[property(common_properties::GroupProperty)]
24    group: u4,
25    #[property(common_properties::UmpSchemaProperty<u7, schema::Ump<0x0000_7F00, 0x0, 0x0, 0x0>>)]
26    note_number: u7,
27    #[property(common_properties::UmpSchemaProperty<u16, schema::Ump<0x0, 0xFFFF_0000, 0x0, 0x0>>)]
28    velocity: u16,
29    #[property(AttributeProperty)]
30    attribute: Option<Attribute>,
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36    use pretty_assertions::assert_eq;
37
38    #[test]
39    fn builder() {
40        use crate::traits::{Channeled, Grouped};
41
42        let mut message = NoteOff::<[u32; 4]>::new();
43        message.set_group(u4::new(0x2));
44        message.set_channel(u4::new(0x4));
45        message.set_note_number(u7::new(0x4E));
46        message.set_velocity(0x9DE6);
47        message.set_attribute(Some(Attribute::ManufacturerSpecific(0xCC6E)));
48
49        assert_eq!(message, NoteOff([0x4284_4E01, 0x9DE6_CC6E, 0x0, 0x0]),);
50    }
51
52    #[test]
53    fn builder_no_attribute() {
54        use crate::traits::{Channeled, Grouped};
55
56        let mut message = NoteOff::<[u32; 4]>::new();
57        message.set_group(u4::new(0x2));
58        message.set_channel(u4::new(0x4));
59        message.set_note_number(u7::new(0x4E));
60        message.set_velocity(0x9DE6);
61
62        assert_eq!(message, NoteOff([0x4284_4E00, 0x9DE6_0000, 0x0, 0x0]),);
63    }
64
65    #[test]
66    fn note_number() {
67        assert_eq!(
68            NoteOff::try_from(&[0x4284_4E01, 0x9DE6_CC6E][..])
69                .unwrap()
70                .note_number(),
71            u7::new(0x4E),
72        );
73    }
74
75    #[test]
76    fn volocity() {
77        assert_eq!(
78            NoteOff::try_from(&[0x4284_4E01, 0x9DE6_CC6E][..])
79                .unwrap()
80                .velocity(),
81            0x9DE6,
82        );
83    }
84
85    #[test]
86    fn attribute() {
87        assert_eq!(
88            NoteOff::try_from(&[0x4284_4E01, 0x9DE6_CC6E][..])
89                .unwrap()
90                .attribute(),
91            Some(Attribute::ManufacturerSpecific(0xCC6E)),
92        );
93    }
94}