annotate util/matlab_midi/writemidi.m @ 99:e22f8494c5ff

Merge
author Mark Plumbley <mark.plumbley@eecs.qmul.ac.uk>
date Tue, 12 Apr 2011 14:33:24 +0100
parents a30e8bd6d948
children
rev   line source
ivan@81 1 function rawbytes=writemidi(midi,filename,do_run_mode)
ivan@81 2 % rawbytes=writemidi(midi,filename,do_run_mode)
ivan@81 3 %
ivan@81 4 % writes to a midi file
ivan@81 5 %
ivan@81 6 % midi is a structure like that created by readmidi.m
ivan@81 7 %
ivan@81 8 % do_run_mode: flag - use running mode when possible.
ivan@81 9 % if given, will override the msg.used_running_mode
ivan@81 10 % default==0. (1 may not work...)
ivan@81 11 %
ivan@81 12 % TODO: use note-on for note-off... (for other function...)
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<3)
ivan@81 20 do_run_mode = 0;
ivan@81 21 %end
ivan@81 22
ivan@81 23
ivan@81 24 % do each track:
ivan@81 25 Ntracks = length(midi.track);
ivan@81 26
ivan@81 27 for i=1:Ntracks
ivan@81 28
ivan@81 29 databytes_track{i} = [];
ivan@81 30
ivan@81 31 for j=1:length(midi.track(i).messages)
ivan@81 32
ivan@81 33 msg = midi.track(i).messages(j);
ivan@81 34
ivan@81 35 msg_bytes = encode_var_length(msg.deltatime);
ivan@81 36
ivan@81 37 if (msg.midimeta==1)
ivan@81 38
ivan@81 39 % check for doing running mode
ivan@81 40 run_mode = 0;
ivan@81 41 run_mode = msg.used_running_mode;
ivan@81 42
ivan@81 43 % should check that prev msg has same type to allow run
ivan@81 44 % mode...
ivan@81 45
ivan@81 46
ivan@81 47 % if (j>1 && do_run_mode && msg.type == midi.track(i).messages(j-1).type)
ivan@81 48 % run_mode = 1;
ivan@81 49 % end
ivan@81 50
ivan@81 51
ivan@81 52 msg_bytes = [msg_bytes; encode_midi_msg(msg, run_mode)];
ivan@81 53
ivan@81 54
ivan@81 55 else
ivan@81 56
ivan@81 57 msg_bytes = [msg_bytes; encode_meta_msg(msg)];
ivan@81 58
ivan@81 59 end
ivan@81 60
ivan@81 61 % disp(msg_bytes')
ivan@81 62
ivan@81 63 %if (msg_bytes ~= msg.rawbytes)
ivan@81 64 % error('rawbytes mismatch');
ivan@81 65 %end
ivan@81 66
ivan@81 67 databytes_track{i} = [databytes_track{i}; msg_bytes];
ivan@81 68
ivan@81 69 end
ivan@81 70 end
ivan@81 71
ivan@81 72
ivan@81 73 % HEADER
ivan@81 74 % double('MThd') = [77 84 104 100]
ivan@81 75 rawbytes = [77 84 104 100 ...
ivan@81 76 0 0 0 6 ...
ivan@81 77 encode_int(midi.format,2) ...
ivan@81 78 encode_int(Ntracks,2) ...
ivan@81 79 encode_int(midi.ticks_per_quarter_note,2) ...
ivan@81 80 ]';
ivan@81 81
ivan@81 82 % TRACK_CHUCKS
ivan@81 83 for i=1:Ntracks
ivan@81 84 a = length(databytes_track{i});
ivan@81 85 % double('MTrk') = [77 84 114 107]
ivan@81 86 tmp = [77 84 114 107 ...
ivan@81 87 encode_int(length(databytes_track{i}),4) ...
ivan@81 88 databytes_track{i}']';
ivan@81 89 rawbytes(end+1:end+length(tmp)) = tmp;
ivan@81 90 end
ivan@81 91
ivan@81 92
ivan@81 93 % write to file
ivan@81 94 fid = fopen(filename,'w');
ivan@81 95 %fwrite(fid,rawbytes,'char');
ivan@81 96 fwrite(fid,rawbytes,'uint8');
ivan@81 97 fclose(fid);
ivan@81 98
ivan@81 99 % return a _column_ vector
ivan@81 100 function A=encode_int(val,Nbytes)
ivan@81 101
ivan@81 102 for i=1:Nbytes
ivan@81 103 A(i) = bitand(bitshift(val, -8*(Nbytes-i)), 255);
ivan@81 104 end
ivan@81 105
ivan@81 106
ivan@81 107 function bytes=encode_var_length(val)
ivan@81 108
ivan@81 109 binStr = dec2base(round(val),2);
ivan@81 110 Nbytes = ceil(length(binStr)/7);
ivan@81 111
ivan@81 112 binStr = ['00000000' binStr];
ivan@81 113 bytes = [];
ivan@81 114 for i=1:Nbytes
ivan@81 115 if (i==1)
ivan@81 116 lastbit = '0';
ivan@81 117 else
ivan@81 118 lastbit = '1';
ivan@81 119 end
ivan@81 120 B = bin2dec([lastbit binStr(end-i*7+1:end-(i-1)*7)]);
ivan@81 121 bytes = [B; bytes];
ivan@81 122 end
ivan@81 123
ivan@81 124
ivan@81 125 function bytes=encode_midi_msg(msg, run_mode)
ivan@81 126
ivan@81 127 bytes = [];
ivan@81 128
ivan@81 129 if (run_mode ~= 1)
ivan@81 130 bytes = msg.type;
ivan@81 131 % channel:
ivan@81 132 bytes = bytes + msg.chan; % lower nibble should be chan
ivan@81 133 end
ivan@81 134
ivan@81 135 bytes = [bytes; msg.data];
ivan@81 136
ivan@81 137 function bytes=encode_meta_msg(msg)
ivan@81 138
ivan@81 139 bytes = 255;
ivan@81 140 bytes = [bytes; msg.type];
ivan@81 141 bytes = [bytes; encode_var_length(length(msg.data))];
ivan@81 142 bytes = [bytes; msg.data];
ivan@81 143