Mercurial > hg > smallbox
comparison util/matlab_midi/readmidi.m @ 81:a30e8bd6d948
matlab_midi scripts
author | Ivan <ivan.damnjanovic@eecs.qmul.ac.uk> |
---|---|
date | Mon, 28 Mar 2011 17:35:01 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
80:16df822019f1 | 81:a30e8bd6d948 |
---|---|
1 function midi = readmidi(filename, rawbytes) | |
2 % midi = readmidi(filename, rawbytes) | |
3 % midi = readmidi(filename) | |
4 % | |
5 % Read MIDI file and store in a Matlab structure | |
6 % (use midiInfo.m to see structure detail) | |
7 % | |
8 % Inputs: | |
9 % filename - input MIDI file | |
10 % rawbytes - 0 or 1: Include raw bytes in structure | |
11 % This info is redundant, but can be | |
12 % useful for debugging. default=0 | |
13 % | |
14 | |
15 % Copyright (c) 2009 Ken Schutte | |
16 % more info at: http://www.kenschutte.com/midi | |
17 | |
18 | |
19 if (nargin<2) | |
20 rawbytes=0; | |
21 end | |
22 | |
23 fid = fopen(filename); | |
24 [A count] = fread(fid,'uint8'); | |
25 fclose(fid); | |
26 | |
27 if (rawbytes) midi.rawbytes_all = A; end | |
28 | |
29 % realtime events: status: [F8, FF]. no data bytes | |
30 %clock, undefined, start, continue, stop, undefined, active | |
31 %sensing, systerm reset | |
32 | |
33 % file consists of "header chunk" and "track chunks" | |
34 % 4B 'MThd' (header) or 'MTrk' (track) | |
35 % 4B 32-bit unsigned int = number of bytes in chunk, not | |
36 % counting these first 8 | |
37 | |
38 | |
39 % HEADER CHUNK -------------------------------------------------------- | |
40 % 4B 'Mthd' | |
41 % 4B length | |
42 % 2B file format | |
43 % 0=single track, 1=multitrack synchronous, 2=multitrack asynchronous | |
44 % Synchronous formats start all tracks at the same time, while asynchronous formats can start and end any track at any time during the score. | |
45 % 2B track cout (must be 1 for format 0) | |
46 % 2B num delta-time ticks per quarter note | |
47 % | |
48 | |
49 if ~isequal(A(1:4)',[77 84 104 100]) % double('MThd') | |
50 error('File does not begin with header ID (MThd)'); | |
51 end | |
52 | |
53 header_len = decode_int(A(5:8)); | |
54 if (header_len == 6) | |
55 else | |
56 error('Header length != 6 bytes.'); | |
57 end | |
58 | |
59 format = decode_int(A(9:10)); | |
60 if (format==0 || format==1 || format==2) | |
61 midi.format = format; | |
62 else | |
63 error('Format does not equal 0,1,or 2'); | |
64 end | |
65 | |
66 num_tracks = decode_int(A(11:12)); | |
67 if (format==0 && num_tracks~=1) | |
68 error('File is format 0, but num_tracks != 1'); | |
69 end | |
70 | |
71 time_unit = decode_int(A(13:14)); | |
72 if (bitand(time_unit,2^15)==0) | |
73 midi.ticks_per_quarter_note = time_unit; | |
74 else | |
75 error('Header: SMPTE time format found - not currently supported'); | |
76 end | |
77 | |
78 if (rawbytes) | |
79 midi.rawbytes_header = A(1:14); | |
80 end | |
81 | |
82 % end header parse ---------------------------------------------------- | |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | |
89 % BREAK INTO SEPARATE TRACKS ------------------------------------------ | |
90 % midi.track(1).data = [byte byte byte ...]; | |
91 % midi.track(2).date = ... | |
92 % ... | |
93 % | |
94 % Track Chunks--------- | |
95 % 4B 'MTrk' | |
96 % 4B length (after first 8B) | |
97 % | |
98 ctr = 15; | |
99 for i=1:num_tracks | |
100 | |
101 if ~isequal(A(ctr:ctr+3)',[77 84 114 107]) % double('MTrk') | |
102 error(['Track ' num2str(i) ' does not begin with track ID=MTrk']); | |
103 end | |
104 ctr = ctr+4; | |
105 | |
106 track_len = decode_int(A(ctr:ctr+3)); | |
107 ctr = ctr+4; | |
108 | |
109 % have track.rawbytes hold initial 8B also... | |
110 track_rawbytes{i} = A((ctr-8):(ctr+track_len-1)); | |
111 | |
112 if (rawbytes) | |
113 midi.track(i).rawbytes_header = A(ctr-8:ctr-1); | |
114 end | |
115 | |
116 ctr = ctr+track_len; | |
117 end | |
118 % ---------------------------------------------------------------------- | |
119 | |
120 | |
121 | |
122 | |
123 | |
124 | |
125 % Events: | |
126 % - meta events: start with 'FF' | |
127 % - MIDI events: all others | |
128 | |
129 % MIDI events: | |
130 % optional command byte + 0,1,or 2 bytes of parameters | |
131 % "running mode": command byte omitted. | |
132 % | |
133 % all midi command bytes have MSB=1 | |
134 % all data for inside midi command have value <= 127 (ie MSB=0) | |
135 % -> so can determine running mode | |
136 % | |
137 % meta events' data may have any values (meta events have to set | |
138 % len) | |
139 % | |
140 | |
141 | |
142 | |
143 % 'Fn' MIDI commands: | |
144 % no chan. control the entire system | |
145 %F8 Timing Clock | |
146 %FA start a sequence | |
147 %FB continue a sequence | |
148 %FC stop a sequence | |
149 | |
150 % Meta events: | |
151 % 1B 0xFF | |
152 % 1B event type | |
153 % 1B length of additional data | |
154 % ?? additional data | |
155 % | |
156 | |
157 | |
158 % "channel mode messages" | |
159 % have same code as "control change": 0xBn | |
160 % but uses reserved controller numbers 120-127 | |
161 % | |
162 | |
163 | |
164 %Midi events consist of an optional command byte | |
165 % followed by zero, one or two bytes of parameters. | |
166 % In running mode, the command can be omitted, in | |
167 % which case the last MIDI command specified is | |
168 % assumed. The first bit of a command byte is 1, | |
169 % while the first bit of a parameter is always 0. | |
170 % In addition, the last 4 bits of a command | |
171 % indicate the channel to which the event should | |
172 % be sent; therefore, there are 6 possible | |
173 % commands (really 7, but we will discuss the x'Fn' | |
174 % commands later) that can be specified. They are: | |
175 | |
176 | |
177 % parse tracks ----------------------------------------- | |
178 for i=1:num_tracks | |
179 | |
180 track = track_rawbytes{i}; | |
181 | |
182 if (rawbytes); midi.track(i).rawbytes = track; end | |
183 | |
184 msgCtr = 1; | |
185 ctr=9; % first 8B were MTrk and length | |
186 while (ctr < length(track_rawbytes{i})) | |
187 | |
188 clear currMsg; | |
189 currMsg.used_running_mode = 0; | |
190 % note: | |
191 % .used_running_mode is necessary only to | |
192 % be able to reconstruct a file _exactly_ from | |
193 % the 'midi' structure. this is helpful for | |
194 % debugging since write(read(filename)) can be | |
195 % tested for exact replication... | |
196 % | |
197 | |
198 ctr_start_msg = ctr; | |
199 | |
200 [deltatime,ctr] = decode_var_length(track, ctr); | |
201 | |
202 % ? | |
203 %if (rawbytes) | |
204 % currMsg.rawbytes_deltatime = track(ctr_start_msg:ctr-1); | |
205 %end | |
206 | |
207 % deltaime must be 1-4 bytes long. | |
208 % could check here... | |
209 | |
210 | |
211 % CHECK FOR META EVENTS ------------------------ | |
212 % 'FF' | |
213 if track(ctr)==255 | |
214 | |
215 type = track(ctr+1); | |
216 | |
217 ctr = ctr+2; | |
218 | |
219 % get variable length 'length' field | |
220 [len,ctr] = decode_var_length(track, ctr); | |
221 | |
222 % note: some meta events have pre-determined lengths... | |
223 % we could try verifiying they are correct here. | |
224 | |
225 thedata = track(ctr:ctr+len-1); | |
226 chan = []; | |
227 | |
228 ctr = ctr + len; | |
229 | |
230 midimeta = 0; | |
231 | |
232 else | |
233 midimeta = 1; | |
234 % MIDI EVENT --------------------------- | |
235 | |
236 | |
237 | |
238 | |
239 % check for running mode: | |
240 if (track(ctr)<128) | |
241 | |
242 % make it re-do last command: | |
243 %ctr = ctr - 1; | |
244 %track(ctr) = last_byte; | |
245 currMsg.used_running_mode = 1; | |
246 | |
247 B = last_byte; | |
248 nB = track(ctr); % ? | |
249 | |
250 else | |
251 | |
252 B = track(ctr); | |
253 nB = track(ctr+1); | |
254 | |
255 ctr = ctr + 1; | |
256 | |
257 end | |
258 | |
259 % nibbles: | |
260 %B = track(ctr); | |
261 %nB = track(ctr+1); | |
262 | |
263 | |
264 Hn = bitshift(B,-4); | |
265 Ln = bitand(B,15); | |
266 | |
267 chan = []; | |
268 | |
269 msg_type = midi_msg_type(B,nB); | |
270 | |
271 % DEBUG: | |
272 if (i==2) | |
273 if (msgCtr==1) | |
274 disp(msg_type); | |
275 end | |
276 end | |
277 | |
278 | |
279 switch msg_type | |
280 | |
281 case 'channel_mode' | |
282 | |
283 % UNSURE: if all channel mode messages have 2 data byes (?) | |
284 type = bitshift(Hn,4) + (nB-120+1); | |
285 thedata = track(ctr:ctr+1); | |
286 chan = Ln; | |
287 | |
288 ctr = ctr + 2; | |
289 | |
290 % ---- channel voice messages: | |
291 case 'channel_voice' | |
292 | |
293 type = bitshift(Hn,4); | |
294 len = channel_voice_msg_len(type); % var length data: | |
295 thedata = track(ctr:ctr+len-1); | |
296 chan = Ln; | |
297 | |
298 % DEBUG: | |
299 if (i==2) | |
300 if (msgCtr==1) | |
301 disp([999 Hn type]) | |
302 end | |
303 end | |
304 | |
305 ctr = ctr + len; | |
306 | |
307 case 'sysex' | |
308 | |
309 % UNSURE: do sysex events (F0-F7) have | |
310 % variable length 'length' field? | |
311 | |
312 [len,ctr] = decode_var_length(track, ctr); | |
313 | |
314 type = B; | |
315 thedata = track(ctr:ctr+len-1); | |
316 chan = []; | |
317 | |
318 ctr = ctr + len; | |
319 | |
320 case 'sys_realtime' | |
321 | |
322 % UNSURE: I think these are all just one byte | |
323 type = B; | |
324 thedata = []; | |
325 chan = []; | |
326 | |
327 end | |
328 | |
329 last_byte = Ln + bitshift(Hn,4); | |
330 | |
331 end % end midi event 'if' | |
332 | |
333 | |
334 currMsg.deltatime = deltatime; | |
335 currMsg.midimeta = midimeta; | |
336 currMsg.type = type; | |
337 currMsg.data = thedata; | |
338 currMsg.chan = chan; | |
339 | |
340 if (rawbytes) | |
341 currMsg.rawbytes = track(ctr_start_msg:ctr-1); | |
342 end | |
343 | |
344 midi.track(i).messages(msgCtr) = currMsg; | |
345 msgCtr = msgCtr + 1; | |
346 | |
347 | |
348 end % end loop over rawbytes | |
349 end % end loop over tracks | |
350 | |
351 | |
352 function val=decode_int(A) | |
353 | |
354 val = 0; | |
355 for i=1:length(A) | |
356 val = val + bitshift(A(length(A)-i+1), 8*(i-1)); | |
357 end | |
358 | |
359 | |
360 function len=channel_voice_msg_len(type) | |
361 | |
362 if (type==128); len=2; | |
363 elseif (type==144); len=2; | |
364 elseif (type==160); len=2; | |
365 elseif (type==176); len=2; | |
366 elseif (type==192); len=1; | |
367 elseif (type==208); len=1; | |
368 elseif (type==224); len=2; | |
369 else | |
370 disp(type); error('bad channel voice message type'); | |
371 end | |
372 | |
373 | |
374 % | |
375 % decode variable length field (often deltatime) | |
376 % | |
377 % return value and new position of pointer into 'bytes' | |
378 % | |
379 function [val,ptr] = decode_var_length(bytes, ptr) | |
380 | |
381 keepgoing=1; | |
382 binarystring = ''; | |
383 while (keepgoing) | |
384 % check MSB: | |
385 % if MSB=1, then delta-time continues into next byte... | |
386 if(~bitand(bytes(ptr),128)) | |
387 keepgoing=0; | |
388 end | |
389 % keep appending last 7 bits from each byte in the deltatime: | |
390 binbyte = ['00000000' dec2base(bytes(ptr),2)]; | |
391 binarystring = [binarystring binbyte(end-6:end)]; | |
392 ptr=ptr+1; | |
393 end | |
394 val = base2dec(binarystring,2); | |
395 | |
396 | |
397 | |
398 | |
399 % | |
400 % Read first 2 bytes of msg and | |
401 % determine the type | |
402 % (most require only 1st byte) | |
403 % | |
404 % str is one of: | |
405 % 'channel_mode' | |
406 % 'channel_voice' | |
407 % 'sysex' | |
408 % 'sys_realtime' | |
409 % | |
410 function str=midi_msg_type(B,nB) | |
411 | |
412 Hn = bitshift(B,-4); | |
413 Ln = bitand(B,7); | |
414 | |
415 % ---- channel mode messages: | |
416 %if (Hn==11 && nB>=120 && nB<=127) | |
417 if (Hn==11 && nB>=122 && nB<=127) | |
418 str = 'channel_mode'; | |
419 | |
420 % ---- channel voice messages: | |
421 elseif (Hn>=8 && Hn<=14) | |
422 str = 'channel_voice'; | |
423 | |
424 % ---- sysex events: | |
425 elseif (Hn==15 && Ln>=0 && Ln<=7) | |
426 str = 'sysex'; | |
427 | |
428 % system real-time messages | |
429 elseif (Hn==15 && Ln>=8 && Ln<=15) | |
430 % UNSURE: how can you tell between 0xFF system real-time | |
431 % message and 0xFF meta event? | |
432 % (now, it will always be processed by meta) | |
433 str = 'sys_realtime'; | |
434 | |
435 else | |
436 % don't think it can get here... | |
437 error('bad midi message'); | |
438 end |