@@ -16,10 +16,13 @@ s.boot;
1616SynthDef (\pluck , {
1717 var vel = \vel .kr;
1818 var signal = Saw .ar(\freq .kr, 0.2 ) * EnvGate .new(1 );
19+ var fr = 2 .pow(Decay .ar(Impulse .ar(0 ), 3 )*6 *vel+8 );
20+ signal = BLowPass .ar(signal, fr)*vel;
1921 Out .ar([0 ,1 ], signal);
2022}).add
2123)
2224
25+
2326// measure round-trip latency
2427(
2528OSCdef (\return , {
@@ -39,9 +42,27 @@ b.sendMsg("/predictor/predict", \pitch, 60+12.rand, \time, 0, \vel, 0);
3942// duet with the model
4043// feeds the model's predictions back to it as well as player input
4144(
45+ ~gate = 0 ;
4246t = Process .elapsedTime;
4347b.sendMsg("/predictor/reset" );
4448
49+ // footswitch
50+ MIDIdef .program(\switch , {
51+ arg num, chan, src;
52+ num.switch
53+ {1 }{~gate = 0 }
54+ {2 }{~gate = 1 }
55+ {3 }{
56+ ~gate = 0 ;
57+ SystemClock .clear;
58+ b.sendMsg("/predictor/reset" );
59+ y.release;
60+ SystemClock .clear;
61+ };
62+ ~gate .postln;
63+ });
64+
65+
4566// MIDI from controller
4667MIDIdef .noteOn(\input , {
4768 arg val, num, chan, src;
@@ -78,50 +99,52 @@ OSCdef(\return, {
7899 // time-to-next note gets 'censored' by the model
79100 // when over a threshold, in this case 10 seconds,
80101 // meaning it just predicts 10s rather than a any longer time
81- var censor = true ; // dt==10.0;
102+ var censor = dt==10.0 ;
82103
83104 censor.if{
84105 // if the predicted time is > 10 seconds, don't schedule it, just stop.
85- \censor .postln; // y.release(3.0)
106+ \censor .postln; y.release(3.0 )
86107 }{
87108 // schedule the predicted note
88109 SystemClock .sched(dt-~delay , {
89- (num==129 ).if{
90- // 129 is the 'stop token', meaning 'end-of-performance'
91- // in this case don't schedule a note, and reset the model
92- b.sendMsg("/predictor/reset" );
93- //release the last note
94- y.release(1.0 );
95- // unset time so next note will have dt=0
96- t = nil ;
97- \reset .postln
98- }{
99- // cancel any pending predictions
100- // (there shouldn't be any, but might
101- // be if there was a lot of fast MIDI input)
102- SystemClock .clear;
103- // feed model its own prediction as input
104- b.sendMsg("/predictor/predict" ,
105- \pitch , num, \time , dt, \vel , val);
106- // release the previous note
107- (dt<3e-2 ).if{
108- // if the time delay is very small, slow release for chord
109- y.release(1.0 )
110+ (~gate >0 ).if{
111+ (num==129 ).if{
112+ // 129 is the 'stop token', meaning 'end-of-performance'
113+ // in this case don't schedule a note, and reset the model
114+ b.sendMsg("/predictor/reset" );
115+ //release the last note
116+ y.release(1.0 );
117+ // unset time so next note will have dt=0
118+ t = nil ;
119+ \reset .postln
110120 }{
111- // otherwise release fast to play a melody
112- y.release(0.1 )
113- };
114- // play the current note
115- y = Synth (\pluck , [
116- \freq , num.midicps, \vel , val/127 ]);//.release(1);
117- // post the current note
118- [\model , dt, num].postln;
119- // mark the time of current note
120- t = Process .elapsedTime;
121- // crudely draw note on piano GUI
122- ~gui .if{
123- AppClock .sched(0 ,{k.keyDown(num)});
124- AppClock .sched(0.2 ,{k.keyUp(num)});
121+ // cancel any pending predictions
122+ // (there shouldn't be any, but might
123+ // be if there was a lot of fast MIDI input)
124+ SystemClock .clear;
125+ // feed model its own prediction as input
126+ b.sendMsg("/predictor/predict" ,
127+ \pitch , num, \time , dt, \vel , val);
128+ // release the previous note
129+ (dt<3e-2 ).if{
130+ // if the time delay is very small, slow release for chord
131+ y.release(1.0 )
132+ }{
133+ // otherwise release fast to play a melody
134+ y.release(0.1 )
135+ };
136+ // play the current note
137+ y = Synth (\pluck , [
138+ \freq , num.midicps, \vel , val/127 ]);//.release(1);
139+ // post the current note
140+ [\model , dt, num].postln;
141+ // mark the time of current note
142+ t = Process .elapsedTime;
143+ // crudely draw note on piano GUI
144+ ~gui .if{
145+ AppClock .sched(0 ,{k.keyDown(num)});
146+ AppClock .sched(0.2 ,{k.keyUp(num)});
147+ }
125148 }
126149 }
127150 })};
0 commit comments