Skip to content
This repository was archived by the owner on Nov 23, 2023. It is now read-only.

Commit 0fd5cfb

Browse files
patch sc example changes from logistic branch
1 parent aed821f commit 0fd5cfb

2 files changed

Lines changed: 67 additions & 45 deletions

File tree

examples/notepredictor/midi-duet.scd

Lines changed: 60 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,13 @@ s.boot;
1616
SynthDef(\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
(
2528
OSCdef(\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;
4246
t = Process.elapsedTime;
4347
b.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
4667
MIDIdef.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
})};

notepredictor/notepredictor/model.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -308,16 +308,15 @@ def predict(self, pitch, time, vel, force=(None, None, None)):
308308
_, time_h = self.xformer(h[:3], embs[:1])
309309

310310
time_params = self.projections[1](time_h)
311-
# pred_time = self.time_dist.sample(time_params)
312-
311+
pred_time = self.time_dist.sample(time_params)
313312
### TODO: generalize, move into sample
314313
# pi only, fewer zeros:
315-
log_pi, loc, s = (
316-
t for t in self.time_dist.get_params(time_params))
317-
bias = float('inf')
318-
log_pi = torch.where(loc <= self.time_dist.res, log_pi-bias, log_pi)
319-
idx = D.Categorical(logits=log_pi).sample().item()
320-
pred_time = loc[...,idx].clamp(0,10)
314+
# log_pi, loc, s = (
315+
# t for t in self.time_dist.get_params(time_params))
316+
# bias = float('inf')
317+
# log_pi = torch.where(loc <= self.time_dist.res, log_pi-bias, log_pi)
318+
# idx = D.Categorical(logits=log_pi).sample().item()
319+
# pred_time = loc[...,idx].clamp(0,10)
321320
###
322321

323322
embs[1] = self.time_emb(pred_time)

0 commit comments

Comments
 (0)