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