ivan@81
|
1 function midi=matrix2midi(M,ticks_per_quarter_note,timesig)
|
ivan@81
|
2 % midi=matrix2midi(M,ticks_per_quarter_note)
|
ivan@81
|
3 %
|
ivan@81
|
4 % generates a midi matlab structure from a matrix
|
ivan@81
|
5 % specifying a list of notes. The structure output
|
ivan@81
|
6 % can then be used by writemidi.m
|
ivan@81
|
7 %
|
ivan@81
|
8 % M: input matrix:
|
ivan@81
|
9 % 1 2 3 4 5 6
|
ivan@81
|
10 % [track chan nn vel t1 t2] (any more cols ignored...)
|
ivan@81
|
11 %
|
ivan@81
|
12 % optional arguments:
|
ivan@81
|
13 % - ticks_per_quarter_note: integer (default 300)
|
ivan@81
|
14 % - timesig: a vector of len 4 (default [4,2,24,8])
|
ivan@81
|
15 %
|
ivan@81
|
16
|
ivan@81
|
17 % Copyright (c) 2009 Ken Schutte
|
ivan@81
|
18 % more info at: http://www.kenschutte.com/midi
|
ivan@81
|
19
|
ivan@81
|
20 % TODO options:
|
ivan@81
|
21 % - note-off vs vel=0
|
ivan@81
|
22 % - tempo, ticks, etc
|
ivan@81
|
23
|
ivan@81
|
24 if nargin < 2
|
ivan@81
|
25 ticks_per_quarter_note = 300;
|
ivan@81
|
26 end
|
ivan@81
|
27
|
ivan@81
|
28 if nargin < 3
|
ivan@81
|
29 timesig = [4,2,24,8];
|
ivan@81
|
30 end
|
ivan@81
|
31
|
ivan@81
|
32 tracks = unique(M(:,1));
|
ivan@81
|
33 Ntracks = length(tracks);
|
ivan@81
|
34
|
ivan@81
|
35 % start building 'midi' struct
|
ivan@81
|
36
|
ivan@81
|
37 if (Ntracks==1)
|
ivan@81
|
38 midi.format = 0;
|
ivan@81
|
39 else
|
ivan@81
|
40 midi.format = 1;
|
ivan@81
|
41 end
|
ivan@81
|
42
|
ivan@81
|
43 midi.ticks_per_quarter_note = ticks_per_quarter_note;
|
ivan@81
|
44
|
ivan@81
|
45 tempo = 500000; % could be set by user, etc...
|
ivan@81
|
46 % (microsec per quarter note)
|
ivan@81
|
47
|
ivan@81
|
48 for i=1:Ntracks
|
ivan@81
|
49
|
ivan@81
|
50 trM = M(i==M(:,1),:);
|
ivan@81
|
51
|
ivan@81
|
52 note_events_onoff = [];
|
ivan@81
|
53 note_events_n = [];
|
ivan@81
|
54 note_events_ticktime = [];
|
ivan@81
|
55
|
ivan@81
|
56 % gather all the notes:
|
ivan@81
|
57 for j=1:size(trM,1)
|
ivan@81
|
58 % note on event:
|
ivan@81
|
59 note_events_onoff(end+1) = 1;
|
ivan@81
|
60 note_events_n(end+1) = j;
|
ivan@81
|
61 note_events_ticktime(end+1) = 1e6 * trM(j,5) * ticks_per_quarter_note / tempo;
|
ivan@81
|
62
|
ivan@81
|
63 % note off event:
|
ivan@81
|
64 note_events_onoff(end+1) = 0;
|
ivan@81
|
65 note_events_n(end+1) = j;
|
ivan@81
|
66 note_events_ticktime(end+1) = 1e6 * trM(j,6) * ticks_per_quarter_note / tempo;
|
ivan@81
|
67 end
|
ivan@81
|
68
|
ivan@81
|
69
|
ivan@81
|
70 msgCtr = 1;
|
ivan@81
|
71
|
ivan@81
|
72 % set tempo...
|
ivan@81
|
73 midi.track(i).messages(msgCtr).deltatime = 0;
|
ivan@81
|
74 midi.track(i).messages(msgCtr).type = 81;
|
ivan@81
|
75 midi.track(i).messages(msgCtr).midimeta = 0;
|
ivan@81
|
76 midi.track(i).messages(msgCtr).data = encode_int(tempo,3);
|
ivan@81
|
77 midi.track(i).messages(msgCtr).chan = [];
|
ivan@81
|
78 msgCtr = msgCtr + 1;
|
ivan@81
|
79
|
ivan@81
|
80 % set time sig...
|
ivan@81
|
81 midi.track(i).messages(msgCtr).deltatime = 0;
|
ivan@81
|
82 midi.track(i).messages(msgCtr).type = 88;
|
ivan@81
|
83 midi.track(i).messages(msgCtr).midimeta = 0;
|
ivan@81
|
84 midi.track(i).messages(msgCtr).data = timesig(:);
|
ivan@81
|
85 midi.track(i).messages(msgCtr).chan = [];
|
ivan@81
|
86 msgCtr = msgCtr + 1;
|
ivan@81
|
87
|
ivan@81
|
88 [junk,ord] = sort(note_events_ticktime);
|
ivan@81
|
89
|
ivan@81
|
90 prevtick = 0;
|
ivan@81
|
91 for j=1:length(ord)
|
ivan@81
|
92
|
ivan@81
|
93 n = note_events_n(ord(j));
|
ivan@81
|
94 cumticks = note_events_ticktime(ord(j));
|
ivan@81
|
95
|
ivan@81
|
96 midi.track(i).messages(msgCtr).deltatime = cumticks - prevtick;
|
ivan@81
|
97 midi.track(i).messages(msgCtr).midimeta = 1;
|
ivan@81
|
98 midi.track(i).messages(msgCtr).chan = trM(n,2);
|
ivan@81
|
99 midi.track(i).messages(msgCtr).used_running_mode = 0;
|
ivan@81
|
100
|
ivan@81
|
101 if (note_events_onoff(ord(j))==1)
|
ivan@81
|
102 % note on:
|
ivan@81
|
103 midi.track(i).messages(msgCtr).type = 144;
|
ivan@81
|
104 midi.track(i).messages(msgCtr).data = [trM(n,3); trM(n,4)];
|
ivan@81
|
105 else
|
ivan@81
|
106 %-- note off msg:
|
ivan@81
|
107 %midi.track(i).messages(msgCtr).type = 128;
|
ivan@81
|
108 %midi.track(i).messages(msgCtr).data = [trM(n,3); trM(n,4)];
|
ivan@81
|
109 %-- note on vel=0:
|
ivan@81
|
110 midi.track(i).messages(msgCtr).type = 144;
|
ivan@81
|
111 midi.track(i).messages(msgCtr).data = [trM(n,3); 0];
|
ivan@81
|
112 end
|
ivan@81
|
113 msgCtr = msgCtr + 1;
|
ivan@81
|
114
|
ivan@81
|
115 prevtick = cumticks;
|
ivan@81
|
116 end
|
ivan@81
|
117
|
ivan@81
|
118 % end of track:
|
ivan@81
|
119 midi.track(i).messages(msgCtr).deltatime = 0;
|
ivan@81
|
120 midi.track(i).messages(msgCtr).type = 47;
|
ivan@81
|
121 midi.track(i).messages(msgCtr).midimeta = 0;
|
ivan@81
|
122 midi.track(i).messages(msgCtr).data = [];
|
ivan@81
|
123 midi.track(i).messages(msgCtr).chan = [];
|
ivan@81
|
124 msgCtr = msgCtr + 1;
|
ivan@81
|
125
|
ivan@81
|
126 end
|
ivan@81
|
127
|
ivan@81
|
128
|
ivan@81
|
129 % return a _column_ vector
|
ivan@81
|
130 % (copied from writemidi.m)
|
ivan@81
|
131 function A=encode_int(val,Nbytes)
|
ivan@81
|
132
|
ivan@81
|
133 A = zeros(Nbytes,1); %ensure col vector (diff from writemidi.m...)
|
ivan@81
|
134 for i=1:Nbytes
|
ivan@81
|
135 A(i) = bitand(bitshift(val, -8*(Nbytes-i)), 255);
|
ivan@81
|
136 end
|
ivan@81
|
137
|