midi_codec/
en.rs

1use crate::{
2    io::WriteSimple,
3    message::{ChannelVoiceMessage, Message, RealTimeMessage, SystemCommonMessage},
4    status::{ChannelStatus, ChannelVoiceStatus, RequiredDataBytes, SystemCommonStatus},
5};
6
7/// An encoder state machine
8pub struct Encoder<W> {
9    writer: W,
10
11    running_status: Option<ChannelVoiceStatus>,
12}
13
14impl<W> Encoder<W>
15where
16    W: WriteSimple,
17{
18    pub fn new(writer: W) -> Encoder<W> {
19        Encoder {
20            writer,
21            running_status: None,
22        }
23    }
24
25    pub fn write_message(&mut self, message: Message) -> Result<(), W::Error> {
26        let (maybe_status, data_size, data) = match message {
27            Message::ChannelVoice { channel, message } => {
28                let (status, data) = deconstruct_channel_voice_message(channel, message);
29
30                let new_running_status = Some(status);
31
32                let maybe_status = if new_running_status == self.running_status {
33                    None
34                } else {
35                    Some(status.into())
36                };
37
38                self.running_status = new_running_status;
39
40                (maybe_status, status.status.required_data_bytes(), data)
41            }
42            Message::SystemCommon(message) => {
43                let (status, data) = deconstruct_system_common_message(message);
44                (Some(status.into()), status.required_data_bytes(), data)
45            }
46            Message::RealTime(message) => {
47                let status_byte = encode_real_time(message);
48
49                return self.writer.write_all_simple(&[status_byte]);
50            }
51            Message::SystemExclusive => return self.writer.write_all_simple(&[0b1111_0000]),
52        };
53
54        let data = [data[0] & DATA_MASK, data[1] & DATA_MASK];
55
56        match (maybe_status, data_size) {
57            (None, RequiredDataBytes::D0) => Ok(()),
58            (None, RequiredDataBytes::D1) => self.writer.write_all_simple(&[data[0]]),
59            (None, RequiredDataBytes::D2) => self.writer.write_all_simple(&[data[0], data[1]]),
60            (Some(status_byte), RequiredDataBytes::D0) => {
61                self.writer.write_all_simple(&[status_byte])
62            }
63            (Some(status_byte), RequiredDataBytes::D1) => {
64                self.writer.write_all_simple(&[status_byte, data[0]])
65            }
66            (Some(status_byte), RequiredDataBytes::D2) => {
67                self.writer
68                    .write_all_simple(&[status_byte, data[0], data[1]])
69            }
70        }
71    }
72
73    pub fn write_sysex(&mut self, data: impl Iterator<Item = u8>) -> Result<(), W::Error> {
74        self.write_message(Message::SystemExclusive)?;
75
76        for byte in data {
77            self.writer.write_all_simple(&[byte & DATA_MASK])?;
78        }
79
80        self.write_message(Message::SystemCommon(SystemCommonMessage::EOX))?;
81
82        Ok(())
83    }
84}
85
86const DATA_MASK: u8 = 0b0111_1111;
87
88fn deconstruct_channel_voice_message(
89    channel: u8,
90    message: ChannelVoiceMessage,
91) -> (ChannelVoiceStatus, [u8; 2]) {
92    let (status, data) = match message {
93        ChannelVoiceMessage::NoteOff { note, velocity } => {
94            (ChannelStatus::NoteOff, [note, velocity])
95        }
96        ChannelVoiceMessage::NoteOn { note, velocity } => (ChannelStatus::NoteOn, [note, velocity]),
97        ChannelVoiceMessage::PolyphonicPressure { note, pressure } => {
98            (ChannelStatus::PolyphonicPressure, [note, pressure])
99        }
100        ChannelVoiceMessage::ControlChange { control, value } => {
101            (ChannelStatus::ControlChange, [control, value])
102        }
103        ChannelVoiceMessage::ProgramChange { program } => {
104            (ChannelStatus::ProgramChange, [program, 0])
105        }
106        ChannelVoiceMessage::ChannelPressure { pressure } => {
107            (ChannelStatus::ChannelPressure, [pressure, 0])
108        }
109        ChannelVoiceMessage::PitchBend { pitch_bend } => (
110            ChannelStatus::PitchBend,
111            [pitch_bend as u8, (pitch_bend >> 7) as u8],
112        ),
113    };
114
115    let status = ChannelVoiceStatus { status, channel };
116
117    (status, data)
118}
119
120fn deconstruct_system_common_message(
121    message: SystemCommonMessage,
122) -> (SystemCommonStatus, [u8; 2]) {
123    match message {
124        SystemCommonMessage::MTCQuarterFrame { data } => {
125            (SystemCommonStatus::MTCQuarterFrame, [data, 0])
126        }
127        SystemCommonMessage::SongPositionPointer { low, high } => {
128            (SystemCommonStatus::SongPositionPointer, [low, high])
129        }
130        SystemCommonMessage::SongSelect { song } => (SystemCommonStatus::SongSelect, [song, 0]),
131        SystemCommonMessage::Undefined1 => (SystemCommonStatus::Undefined1, [0, 0]),
132        SystemCommonMessage::Undefined2 => (SystemCommonStatus::Undefined2, [0, 0]),
133        SystemCommonMessage::TuneRequest => (SystemCommonStatus::TuneRequest, [0, 0]),
134        SystemCommonMessage::EOX => (SystemCommonStatus::EOX, [0, 0]),
135    }
136}
137
138fn encode_real_time(real_time: RealTimeMessage) -> u8 {
139    match real_time {
140        RealTimeMessage::TimingClock => 0b1111_1000,
141        RealTimeMessage::Undefined1 => 0b1111_1001,
142        RealTimeMessage::Start => 0b1111_1010,
143        RealTimeMessage::Continue => 0b1111_1011,
144        RealTimeMessage::Stop => 0b1111_1100,
145        RealTimeMessage::Undefined2 => 0b1111_1101,
146        RealTimeMessage::ActiveSensing => 0b1111_1110,
147        RealTimeMessage::SystemReset => 0b1111_1111,
148    }
149}