annotate util/matlab_midi/readmidi.m @ 107:dab78a3598b6

changes to comments for couple of scripts
author Ivan Damnjanovic lnx <ivan.damnjanovic@eecs.qmul.ac.uk>
date Wed, 18 May 2011 11:50:12 +0100
parents a30e8bd6d948
children
rev   line source
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