1717// TODO: pitch blacklist option
1818// use case: forbid model from releasing a note held by the player
1919
20+ MIDIClient .init
21+ MIDIClient .destinations
22+ ~m1 = MIDIOut .newByName("IAC Driver" , "Bus 1" );
23+ ~m2 = MIDIOut .newByName("IAC Driver" , "IAC Bus 2" );
24+ /*
25+ ~m1.noteOn(0, 60, 127)
26+ ~m2.noteOn(0, 60, 127)
27+ ~m1.noteOff(0, 60, 64)
28+ ~m2.noteOff(0, 60, 64)*/
29+
30+ (
31+ ~prog2portchan = { arg prog;
32+ case
33+ {prog==0 }{"can't convert start token" .postln}
34+ {prog<=128 }{
35+ var group = (prog-1 /8 ).asInteger;
36+ var idx = (prog-1 %8 ).asInteger;
37+ var port = switch(group)
38+ { 0 }{(idx<6 ).if{~m1 }{~m2 }} //piano
39+ { 1 }{((idx<3 )||(idx==5 )).if{~m1 }{~m2 }} //chromatic perc
40+ { 2 }{(idx<4 ).if{~m1 }{~m2 }} //organ
41+ { 3 }{(idx<5 ).if{~m1 }{~m2 }} //guitar
42+ { 4 }{(idx<4 ).if{~m2 }{~m1 }} //bass
43+ { 5 }{(idx<5 ).if{~m1 }{~m2 }} //strings
44+ { 6 }{(idx<4 ).if{~m1 }{~m2 }} //ensemble
45+ { 7 }{(idx<3 ).if{~m1 }{~m2 }} //brass
46+ { 8 }{(idx<4 ).if{~m1 }{~m2 }} //reed
47+ { 9 }{(idx<3 ).if{~m1 }{~m2 }} //pipe
48+ {10 }{(idx%2 ==0 ).if{~m1 }{~m2 }} //synth lead
49+ {11 }{(idx<4 ).if{~m1 }{~m2 }} //synth pad
50+ {12 }{~m1 } //synth fx
51+ {13 }{case //'ethnic'
52+ {idx<=3 }{~m1 }
53+ {idx==4 }{~m2 }
54+ {idx==5 }{group=2 ;~m2 }
55+ {idx==6 }{group=5 ;~m1 }
56+ {idx==7 }{group=8 ;~m2 }
57+ }
58+ {14 }{~m1 } //percussive
59+ {15 }{~m1 } //sound fx
60+ ;
61+ // \melody.postln;
62+ (port: port, chan: group)
63+ }{(prog<=256 )||(prog>=265 )}{
64+ // \drum.postln;
65+ (port: ~m2 , chan: 12 )
66+ }{prog-257 < 8 }{
67+ // \anon.postln;
68+ (port: ~m1 , chan: 0 )
69+ }
70+ };
71+ ~release_all = {arg vel=0 ;
72+ [~m1 , ~m2 ].do{arg port; 128 .do{arg note; 16 .do{arg chan; port.noteOff(chan, note, vel)}}}
73+ };
74+ )
75+
76+ /*(
77+ ~prog2portchan.(257)[\chan]
78+ )*/
79+
2080(
2181~gui = false ;
2282MIDIIn .connectAll;
@@ -95,6 +155,7 @@ MIDIdef.noteOff(\input_off, {
95155 var t2 = Process .elapsedTime;
96156 var dt = t2-(t?(t2-~delay )); //time since last note
97157 var inst = ~player_inst ;
158+ var port_chan = ~prog2portchan .(inst);
98159
99160 // cancel any pending predictions
100161 SystemClock .clear;
@@ -112,6 +173,8 @@ MIDIdef.noteOff(\input_off, {
112173 // release the previous note
113174 ~synths [num]!?(_ .release(0.05 ));
114175 ~synths [num] = nil ;
176+ // send MIDI
177+ port_chan[\port ].noteOff(port_chan[\chan ], num);
115178
116179 // post the current note
117180 [\player , dt, inst, num, 0 ].postln;
@@ -130,6 +193,8 @@ MIDIdef.noteOn(\input_on, {
130193 var t2 = Process .elapsedTime;
131194 var dt = t2-(t?(t2-~delay )); //time since last note
132195 var inst = ~player_inst ;
196+ var port_chan = ~prog2portchan .(inst);
197+
133198
134199 // cancel any pending predictions
135200 SystemClock .clear;
@@ -145,11 +210,13 @@ MIDIdef.noteOn(\input_on, {
145210 ~pending_predictions = ~pending_predictions +1 ;
146211
147212
148- // release the previous note
213+ // release the previous note (if not properly released by noteoff)
149214 ~synths [num]!?(_ .release(0.05 ));
150215
151216 // play the current note
152217 ~synths [num] = Synth (\pluck , [\freq , num.midicps, \vel , val/127 ]);//.release(1);
218+ // send MIDI
219+ port_chan[\port ].noteOn(port_chan[\chan ], num, val);
153220
154221 // post the current note
155222 [\player , dt, inst, num, val].postln;
@@ -170,9 +237,11 @@ OSCdef(\return, {
170237 var inst = msg[1 ]; // instrument of predicted note
171238 var pitch = msg[2 ]; // MIDI number of predicted note
172239 var dt = msg[3 ]; // time to predicted note
173- var val = msg[4 ]; // velocity 0-127
240+ var vel = msg[4 ]; // velocity 0-127
174241 var end = msg[5 ];
175242 var step = msg[6 ];
243+ var port_chan = ~prog2portchan .(inst);
244+
176245
177246 // time-to-next note gets 'censored' by the model
178247 // when over a threshold, in this case 10 seconds,
@@ -199,6 +268,7 @@ OSCdef(\return, {
199268 // b.sendMsg("/predictor/reset");
200269 //release the last note
201270 ~synths .do(_ .release(1.0 ));
271+ ~release_all .(127 );
202272 // unset time so next note will have dt=0
203273 // t = nil;
204274 // \reset.postln
@@ -211,22 +281,30 @@ OSCdef(\return, {
211281 // ~pending_predictions.postln;
212282 // feed model its own prediction as input
213283 b.sendMsg("/predictor/predict" ,
214- \inst , inst, \pitch , pitch, \time , dt_actual, \vel , val ,
284+ \inst , inst, \pitch , pitch, \time , dt_actual, \vel , vel ,
215285 \allow_start , false , \allow_end , true ,
216- \pitch_temp , 0.7 , \rhythm_temp , 0.7 , \timing_temp , 0.1 ,
217- \min_time , ~delay *0 , \max_time , 5 ,
286+ \instrument_temp , 1 , \pitch_temp , 0.9 , \rhythm_temp , 0.7 , \timing_temp , 0.05 ,
287+ // \instrument_temp, 1, \pitch_temp, 1, \rhythm_temp, 1, \timing_temp, 1,
288+ \min_time , ~delay ,
289+ \max_time , 5 ,
290+
218291 );
219292 ~pending_predictions = ~pending_predictions +1 ;
220293
221294 // play the current note
222295 ~synths [pitch]!?(_ .release(0.05 ));
223- (val > 0 ).if{
224- ~synths [pitch] = Synth (\pluck , [\freq , pitch.midicps, \vel , val/127 ])
296+ // send MIDI
297+ port_chan[\port ].noteOff(port_chan[\chan ], pitch, 64 );
298+ (vel > 0 ).if{
299+ ~synths [pitch] = Synth (\pluck , [
300+ \freq , pitch.midicps, \vel , vel/127 ]);
301+ // send MIDI
302+ port_chan[\port ].noteOn(port_chan[\chan ], pitch, vel)
225303 }{
226- ~synths [pitch] = nil
304+ ~synths [pitch] = nil ;
227305 };
228306 // post the current note
229- [\model , step, dt, inst, pitch, val , end].postln;
307+ [\model , step, dt, inst, pitch, vel , end].postln;
230308 // mark the actual time of current note
231309 t = t2;
232310 ~machine_t = t;
@@ -248,9 +326,12 @@ OSCdef(\return, {
248326// send a note manually if you don't have a MIDI controller:
249327SystemClock .clear;
250328~synths .do(_ .release(1.0 ));
329+ ~release_all .(0 );
251330b.sendMsg("/predictor/reset" );
252- ~player_inst = 83 ;
253- {MIDIdef .all[\input_on ].func.value(99 , 60 )}.defer(0.5 );
331+ // ~player_inst = 272;
332+ // {MIDIdef.all[\input_on].func.value(99, 83)}.defer(0.5);
333+ ~player_inst = 128 .rand+1 ;
334+ {MIDIdef .all[\input_on ].func.value(128 .rand, 128 .rand)}.defer(0.1 );
254335SystemClock .clear;
255336)
256337// b.sendMsg("/predictor/predict", \pitch, 70, \time, 0, \vel, 64);
0 commit comments