1const Q_MAX : usize = 128;
9const BUF_SIZE : usize = 2 * 1024 * 1024;
13const HMP_TRACK0 : [u8; 19] = [
14 b'M', b'T', b'r', b'k', 0, 0, 0, 11, 0, 0xFF, 0x51, 0x03, 0x18, 0x7F, 0xFF,
15 0, 0xFF, 0x2F, 0
16];
17
18pub struct Hmi2mid {
19 bw : u32,
20 buf : Vec <u8>,
21 q_rel : Vec <QRel>
22}
23
24#[derive(Clone, Default)]
25struct QRel {
26 pub tm : u32,
27 pub ch : u8,
28 pub n : u8
29}
30
31impl Hmi2mid {
32 pub fn new() -> Self {
33 Hmi2mid {
34 bw: 0,
35 buf: vec![0; BUF_SIZE],
36 q_rel: vec![QRel::default(); Q_MAX]
37 }
38 }
39 pub fn hmi_rip (&mut self, source : Vec <u8>) -> Result <Vec <u8>, ()> {
40 let mut out = Vec::new();
41 out.resize(14, 0);
42 let bbuf = &source;
43 let mut ptr = 0;
44 loop {
45 if ptr >= bbuf.len() {
46 eprintln!("ptr >= bbuf.len()");
47 return Err(())
48 }
49 if &bbuf[ptr..ptr+4] == &b"TRAC"[..] {
50 break
51 }
52 ptr += 1;
53 }
54 ptr -= 8;
55 let nft : u32 = u32::from_le_bytes([
56 bbuf[0xE4],
57 bbuf[0xE4+1],
58 bbuf[0xE4+2],
59 bbuf[0xE4+3]
60 ]);
61 let mut ntrax : u16 = 1;
62 out.extend_from_slice (&HMP_TRACK0);
63 for _ in 0..nft {
64 if &bbuf[ptr..ptr+13] != &b"HMI-MIDITRACK"[..] {
65 eprintln!(r#"&bbuf[ptr..ptr+13] != &b"HMI-MIDITRACK"[..]"#);
66 return Err(())
67 }
68 ntrax += 1;
69 ptr += bbuf[ptr + 0x57] as usize;
70 let dd = self.do_track(&bbuf[ptr..]);
71 if dd == std::usize::MAX {
72 eprintln!("dd == std::usize::MAX");
73 return Err(())
74 }
75 ptr += dd;
76 out.extend_from_slice(&b"MTrk"[..]);
77 out.extend_from_slice(&self.bw.to_be_bytes());
78 out.extend_from_slice(&self.buf[0..self.bw as usize]);
79 }
80 &out[0..4].copy_from_slice(&b"MThd"[..]);
81 &out[4..8].copy_from_slice(&0x06000000u32.to_le_bytes());
82 out[8] = 0x00;
84 out[9] = 0x01;
85 &out[10..12].copy_from_slice(&ntrax.to_be_bytes());
86 out[12] = 0x00;
87 out[13] = 0xC0;
88
89 Ok (out)
90 }
91
92 fn do_track (&mut self, t : &[u8]) -> usize {
93 for n in 0..Q_MAX {
94 self.q_rel[n].tm = std::u32::MAX;
95 }
96 let mut pt : usize = 0;
97 let mut ct : u32 = 0;
98 let mut tw : u32 = 0;
99 let mut run : u8 = 0;
100 let mut rrun : u8 = 0;
101 self.bw = 0;
102 loop {
103 ct += self.read_delta (t, &mut pt);
104 self.do_queue (ct, &mut tw, &mut rrun);
105 let mut c : u8 = t[pt];
106 if c == 0xFF {
107 self.do_queue (std::u32::MAX-1, &mut tw, &mut rrun);
108 if t[pt+1] == 0x2F {
109 pt += 3;
110 self.buf[self.bw as usize] = 0;
111 self.bw += 1;
112 self.buf[self.bw as usize] = 0xFF;
113 self.bw += 1;
114 self.buf[self.bw as usize] = 0x2F;
115 self.bw += 1;
116 self.buf[self.bw as usize] = 0;
117 self.bw += 1;
118 break
119 }
120 return std::usize::MAX
121 } else if c == 0xF0 {
122 self.bw += Self::write_delta (
123 &mut self.buf[self.bw as usize..], ct - tw);
124 tw = ct;
125 while t[pt] != 0xF7 {
126 self.buf[self.bw as usize] = t[pt];
127 self.bw += 1;
128 pt += 1;
129 }
130 } else if c == 0xFE {
131 c = t[pt+1];
132 if c == 0x10 {
133 pt += t[pt+4] as usize + 9;
134 } else if c == 0x14 {
135 pt += 4;
136 } else if c == 0x15 {
137 pt += 8;
138 } else {
139 return std::usize::MAX
140 }
141 } else {
142 self.bw += Self::write_delta (
143 &mut self.buf[self.bw as usize..], ct - tw);
144 tw = ct;
145 if c & 0x80 != 0 {
146 pt += 1;
147 run = c;
148 } else {
149 c = run;
150 }
151 if c != rrun {
152 self.buf[self.bw as usize] = c;
153 self.bw += 1;
154 rrun = c;
155 }
156 self.buf[self.bw as usize] = t[pt];
157 self.bw += 1;
158 pt += 1;
159 let c1 : u8 = c & 0xF0;
160 if c1 != 0xC0 && c1 != 0xD0 {
161 self.buf[self.bw as usize] = t[pt];
162 self.bw += 1;
163 pt += 1;
164 }
165 if c1 == 0x90 {
166 let b : u8 = t[pt-2];
167 let tt : u32 = ct + self.read_delta (t, &mut pt);
168 self.q_add (c & 0xF, b, tt);
169 }
170 }
171 }
172 pt
173 }
174
175 fn q_add (&mut self, ch : u8, nt : u8, t : u32) {
176 let mut n : usize = 0;
177 while self.q_rel[n].tm != std::u32::MAX {
178 n += 1;
179 }
180 self.q_rel[n] = QRel {
181 tm: t,
182 n: nt,
183 ch
184 };
185 }
186
187 fn write_delta (t : &mut [u8], dt : u32) -> u32 {
188 let mut tl : isize = 3;
189 let mut pos : usize = 0;
190 if dt != 0 {
191 while dt >> (7*tl) == 0 {
192 tl -= 1;
193 }
194 loop {
195 t[pos] = (((dt >> (7*tl)) & 0x7F) | 0x80) as u8;
196 tl -= 1;
197 pos += 1;
198 if tl < 0 {
199 break
200 }
201 }
202 t[pos-1] &= 0x7F;
203 } else {
204 t[pos] = 0;
205 pos += 1;
206 }
207 pos as u32
208 }
209
210 fn read_delta (&self, t : &[u8], p : &mut usize) -> u32 {
211 let mut d : u32 = 0;
212 let mut b;
213 loop {
214 b = t[*p];
215 *p += 1;
216 d = (d << 7) | (b & 0x7F) as u32;
217 if b & 0x80 == 0 {
218 break
219 }
220 }
221 d
222 }
223
224 fn do_queue (&mut self, ct : u32, tw : &mut u32, run : &mut u8) {
225 let mut mt : u32;
226 let mut nn : usize = std::usize::MAX;
227 loop {
228 mt = std::u32::MAX;
229 for n in 0..Q_MAX {
230 if self.q_rel[n].tm < mt {
231 nn = n;
232 mt = self.q_rel[n].tm;
233 }
234 }
235 if mt > ct {
236 return
237 }
238 debug_assert!(nn != std::usize::MAX);
239 self.bw += Self::write_delta (
240 &mut self.buf[self.bw as usize..], mt - *tw);
241 *tw = mt;
242 let e : u8 = self.q_rel[nn].ch | 0x90;
243 if e != *run {
244 self.buf[self.bw as usize] = e;
245 self.bw += 1;
246 *run = e;
247 }
248 self.buf[self.bw as usize] = self.q_rel[nn].n;
249 self.bw += 1;
250 self.buf[self.bw as usize] = 0;
251 self.bw += 1;
252 self.q_rel[nn].tm = std::u32::MAX;
253 }
254 }
255}