ivan@81: function rawbytes=writemidi(midi,filename,do_run_mode) ivan@81: % rawbytes=writemidi(midi,filename,do_run_mode) ivan@81: % ivan@81: % writes to a midi file ivan@81: % ivan@81: % midi is a structure like that created by readmidi.m ivan@81: % ivan@81: % do_run_mode: flag - use running mode when possible. ivan@81: % if given, will override the msg.used_running_mode ivan@81: % default==0. (1 may not work...) ivan@81: % ivan@81: % TODO: use note-on for note-off... (for other function...) ivan@81: % ivan@81: ivan@81: % Copyright (c) 2009 Ken Schutte ivan@81: % more info at: http://www.kenschutte.com/midi ivan@81: ivan@81: ivan@81: %if (nargin<3) ivan@81: do_run_mode = 0; ivan@81: %end ivan@81: ivan@81: ivan@81: % do each track: ivan@81: Ntracks = length(midi.track); ivan@81: ivan@81: for i=1:Ntracks ivan@81: ivan@81: databytes_track{i} = []; ivan@81: ivan@81: for j=1:length(midi.track(i).messages) ivan@81: ivan@81: msg = midi.track(i).messages(j); ivan@81: ivan@81: msg_bytes = encode_var_length(msg.deltatime); ivan@81: ivan@81: if (msg.midimeta==1) ivan@81: ivan@81: % check for doing running mode ivan@81: run_mode = 0; ivan@81: run_mode = msg.used_running_mode; ivan@81: ivan@81: % should check that prev msg has same type to allow run ivan@81: % mode... ivan@81: ivan@81: ivan@81: % if (j>1 && do_run_mode && msg.type == midi.track(i).messages(j-1).type) ivan@81: % run_mode = 1; ivan@81: % end ivan@81: ivan@81: ivan@81: msg_bytes = [msg_bytes; encode_midi_msg(msg, run_mode)]; ivan@81: ivan@81: ivan@81: else ivan@81: ivan@81: msg_bytes = [msg_bytes; encode_meta_msg(msg)]; ivan@81: ivan@81: end ivan@81: ivan@81: % disp(msg_bytes') ivan@81: ivan@81: %if (msg_bytes ~= msg.rawbytes) ivan@81: % error('rawbytes mismatch'); ivan@81: %end ivan@81: ivan@81: databytes_track{i} = [databytes_track{i}; msg_bytes]; ivan@81: ivan@81: end ivan@81: end ivan@81: ivan@81: ivan@81: % HEADER ivan@81: % double('MThd') = [77 84 104 100] ivan@81: rawbytes = [77 84 104 100 ... ivan@81: 0 0 0 6 ... ivan@81: encode_int(midi.format,2) ... ivan@81: encode_int(Ntracks,2) ... ivan@81: encode_int(midi.ticks_per_quarter_note,2) ... ivan@81: ]'; ivan@81: ivan@81: % TRACK_CHUCKS ivan@81: for i=1:Ntracks ivan@81: a = length(databytes_track{i}); ivan@81: % double('MTrk') = [77 84 114 107] ivan@81: tmp = [77 84 114 107 ... ivan@81: encode_int(length(databytes_track{i}),4) ... ivan@81: databytes_track{i}']'; ivan@81: rawbytes(end+1:end+length(tmp)) = tmp; ivan@81: end ivan@81: ivan@81: ivan@81: % write to file ivan@81: fid = fopen(filename,'w'); ivan@81: %fwrite(fid,rawbytes,'char'); ivan@81: fwrite(fid,rawbytes,'uint8'); ivan@81: fclose(fid); ivan@81: ivan@81: % return a _column_ vector ivan@81: function A=encode_int(val,Nbytes) ivan@81: ivan@81: for i=1:Nbytes ivan@81: A(i) = bitand(bitshift(val, -8*(Nbytes-i)), 255); ivan@81: end ivan@81: ivan@81: ivan@81: function bytes=encode_var_length(val) ivan@81: ivan@81: binStr = dec2base(round(val),2); ivan@81: Nbytes = ceil(length(binStr)/7); ivan@81: ivan@81: binStr = ['00000000' binStr]; ivan@81: bytes = []; ivan@81: for i=1:Nbytes ivan@81: if (i==1) ivan@81: lastbit = '0'; ivan@81: else ivan@81: lastbit = '1'; ivan@81: end ivan@81: B = bin2dec([lastbit binStr(end-i*7+1:end-(i-1)*7)]); ivan@81: bytes = [B; bytes]; ivan@81: end ivan@81: ivan@81: ivan@81: function bytes=encode_midi_msg(msg, run_mode) ivan@81: ivan@81: bytes = []; ivan@81: ivan@81: if (run_mode ~= 1) ivan@81: bytes = msg.type; ivan@81: % channel: ivan@81: bytes = bytes + msg.chan; % lower nibble should be chan ivan@81: end ivan@81: ivan@81: bytes = [bytes; msg.data]; ivan@81: ivan@81: function bytes=encode_meta_msg(msg) ivan@81: ivan@81: bytes = 255; ivan@81: bytes = [bytes; msg.type]; ivan@81: bytes = [bytes; encode_var_length(length(msg.data))]; ivan@81: bytes = [bytes; msg.data]; ivan@81: