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

Commit aa73141

Browse files
committed
2 parents 6059d5d + c0b5bb3 commit aa73141

6 files changed

Lines changed: 167 additions & 105 deletions

File tree

examples/notochord/autopitch.scd

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// in this example the Linnstrument displays an interface to perform pitches
2-
// by their likelihood under the Notochord model instead of by MIDI number
2+
// by their likelihood under the NotePredictor model instead of by MIDI number
33

44
// the grid in the upper left gives control of pitches from
55
// the single most likely (cyan) to least likely (pink).
@@ -9,6 +9,9 @@
99

1010
// model predictions are conditioned on performed timing and velocity.
1111

12+
// TODO: this example is based an older, monophonic version of notochord without noteoffs
13+
// it is hacked to work similarly wit Notochord v3, but could use an update
14+
1215
(
1316
~use_linn = true; // use linnstrument
1417
~gui = false; // use keyboard GUI
@@ -33,7 +36,7 @@ Server.default.options.outDevice_("Built-in Output");
3336
{y==2}{x*4+16}
3437
{y==3}{x*8+40}
3538
{y==4}{127-x};
36-
idx.postln;
39+
// idx.postln;
3740
~midi_handle.(amp*127, idx);
3841
}{
3942
case
@@ -85,13 +88,13 @@ SynthDef(\pluck, {
8588

8689
// measure round-trip latency
8790
(
88-
OSCdef(\return, {
91+
OSCdef(\test, {
8992
arg msg, time, addr, recvPort;
9093
(Process.elapsedTime - t).postln;
9194
}, '/prediction', nil);
9295
t = Process.elapsedTime;
9396
b.sendMsg("/predictor/predict",
94-
\pitch, 60+12.rand, \time, 0, \vel, 0, \fix_time, 0, \fix_vel, 0);
97+
\inst, 257, \pitch, 60+12.rand, \time, 0, \vel, 0, \fix_time, 0, \fix_vel, 0);
9598
)
9699

97100
// set the delay for more precise timing
@@ -104,17 +107,16 @@ b.sendMsg("/predictor/predict",
104107
// model chooses pitches
105108
(
106109
~gate = 1;
110+
~instrument = 57;
107111

108112
~model_reset = {
109-
~last_pitch = nil;
113+
~last_pitch = 60;
110114
~last_dt = nil;
111115
~last_vel = nil;
112116
t = Process.elapsedTime;
113117
b.sendMsg("/predictor/reset");
114118
y!?{y.free};
115119
y = nil;
116-
b.sendMsg("/predictor/predict", \pitch, 128, \time, 0, \vel, 0);
117-
118120
};
119121

120122
~model_reset.();
@@ -151,13 +153,17 @@ MIDIdef.program(\switch, {
151153
// get a new prediction in light of last note,
152154
// fixing dt and vel to performed values so just pitch is predicted
153155
pitch.notNil.if{
156+
b.sendMsg("/predictor/feed",
157+
\inst, ~instrument, \pitch, ~last_pitch, \time, ~delay, \vel, ~last_vel);
154158
b.sendMsg("/predictor/predict",
155-
\pitch, ~last_pitch, \time, ~last_dt, \vel, ~last_vel,
156-
\index_pitch, pitch, \fix_time, dt, \fix_vel, vel);
159+
\inst, ~instrument, \pitch, ~last_pitch, \time, ~last_dt, \vel, 0,
160+
\index_pitch, pitch, \fix_time, dt, \fix_vel, vel, \fix_instrument, ~instrument);
157161
}{
162+
b.sendMsg("/predictor/feed",
163+
\inst, ~instrument, \pitch, ~last_pitch, \time, ~delay, \vel, ~last_vel);
158164
b.sendMsg("/predictor/predict",
159-
\pitch, ~last_pitch, \time, ~last_dt, \vel, ~last_vel,
160-
\fix_time, dt, \fix_vel, vel);
165+
\inst, ~instrument, \pitch, ~last_pitch, \time, ~last_dt, \vel, 0,
166+
\fix_time, dt, \fix_vel, vel, \fix_instrument, ~instrument);
161167
};
162168

163169
~last_dt = dt;
@@ -174,9 +180,10 @@ MIDIdef.program(\switch, {
174180
// OSC return from python
175181
OSCdef(\return, {
176182
arg msg, time, addr, recvPort;
177-
var pitch = msg[1]; // MIDI number of predicted note
178-
var dt = msg[2]; // time to predicted note
179-
var vel = msg[3]; // velocity 0-127
183+
var inst = msg[1]; // MIDI number of predicted note
184+
var pitch = msg[2]; // MIDI number of predicted note
185+
var dt = msg[3]; // time to predicted note
186+
var vel = msg[4]; // velocity 0-127
180187

181188
// store the pitch and immediately set (unless there is no synth,
182189
// indicating this is the first note)
@@ -192,7 +199,4 @@ OSCdef(\return, {
192199

193200
~model_reset.()
194201
// send a note manually if you don't have a midi controller
195-
MIDIdef.all[\input].func.(64, 16) //velocity, "pitch"
196-
197-
// load another model
198-
// b.sendMsg("/predictor/load", "/path/to/checkpoint");
202+
MIDIdef.all[\input].func.(64, 16) //velocity, "pitch"

examples/notochord/linnstrument-display.scd

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
// in this example, the most likely next pitches (according to Notochord)
22
// are drawn on the Linnstrument as you play
33

4+
// NOTE: for an older version of Notochord without note-offs. needs update
5+
46
(
7+
~instrument = 57; // trumpet
58
~use_linn = true; // use linnstrument
69
~gui = false; // use keyboard GUI
710
MIDIIn.connectAll;
@@ -25,9 +28,11 @@ Server.default.options.outDevice_("Built-in Output");
2528
// attack the current note
2629
~synth = Synth(\pluck, [\freq, freq, \vel, amp]);
2730

28-
//
31+
// monophonic -- release last note and immediately start new note
32+
b.sendMsg("/predictor/feed",
33+
\pitch, midinote, \time, ~delay, \vel, amp*127);
2934
b.sendMsg("/predictor/predict",
30-
\pitch, midinote, \time, dt, \vel, amp*127,
35+
\pitch, midinote, \time, dt, \vel, 0,
3136
\pitch_topk, 5);
3237

3338
// mark time of current note
@@ -51,17 +56,17 @@ s.waitForBoot{
5156

5257
(
5358
// set the delay for more precise timing
54-
~delay = 0.2;
59+
~delay = 0.01;
5560

5661
~model_reset = {
5762
t = Process.elapsedTime;
5863
b.sendMsg("/predictor/reset");
5964
// ~synth!?{~synth.free};
6065
s.freeAll;
6166
~synth = nil;
62-
b.sendMsg("/predictor/predict",
67+
/* b.sendMsg("/predictor/predict",
6368
\pitch, 128, \time, 0, \vel, 0,
64-
\pitch_topk, 5);
69+
\pitch_topk, 5);*/
6570

6671
};
6772
~model_reset.();
@@ -70,7 +75,7 @@ s.waitForBoot{
7075
// OSC return from python
7176
OSCdef(\return, {
7277
arg msg, time, addr, recvPort;
73-
var pitches, dts;
78+
var inst, pitches, dts;
7479
var last_pitch = nil;
7580
var colormap = [8,3,10,9,1];
7681
var color = 0;
@@ -85,8 +90,9 @@ OSCdef(\return, {
8590
};
8691
msg = stack[0];
8792

88-
pitches = msg[1];
89-
dts = msg[2];
93+
inst = msg[1]
94+
pitches = msg[2];
95+
dts = msg[3];
9096

9197
~linn.allLightsOff;
9298
pitches.do{arg pitch;

notochord/notochord/data.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from torch.utils.data import Dataset, DataLoader
88

99
class MIDIDataset(Dataset):
10-
def __init__(self, data_dir, batch_len, transpose=5, speed=0.1, glob='**/*.pkl'):
10+
def __init__(self, data_dir, batch_len, transpose=5, speed=0.1, glob='**/*.pkl', test_len=1024):
1111
#, clamp_time=(-,10)):
1212
"""
1313
"""
@@ -20,6 +20,8 @@ def __init__(self, data_dir, batch_len, transpose=5, speed=0.1, glob='**/*.pkl')
2020
self.n_anon = 8
2121
self.prog_start_token = 0
2222
# self.clamp_time = clamp_time
23+
self.testing = False
24+
self.max_test_len = 10000
2325

2426
def __len__(self):
2527
return len(self.files)
@@ -92,7 +94,7 @@ def __getitem__(self, idx):
9294
# pad with start tokens, zeros
9395
# always pad with batch_len so that end tokens don't appear in a biased
9496
# location
95-
pad = self.batch_len-1#max(0, self.batch_len-len(pitch))
97+
pad = 0 if self.testing else self.batch_len-1#max(0, self.batch_len-len(pitch))
9698
program = torch.cat((
9799
program.new_full((1,), self.prog_start_token),
98100
program,
@@ -117,14 +119,18 @@ def __getitem__(self, idx):
117119
if pad > 0:
118120
mask[-pad:] = False
119121

120-
# random slice
121-
i = random.randint(0, len(pitch)-self.batch_len)
122-
program = program[i:i+self.batch_len]
123-
pitch = pitch[i:i+self.batch_len]
124-
time = time[i:i+self.batch_len]
125-
velocity = velocity[i:i+self.batch_len]
126-
end = end[i:i+self.batch_len]
127-
mask = mask[i:i+self.batch_len]
122+
if self.testing:
123+
sl = slice(0, self.max_test_len)
124+
else:
125+
# random slice
126+
i = random.randint(0, len(pitch)-self.batch_len)
127+
sl = slice(i, i+self.batch_len)
128+
program = program[sl]
129+
pitch = pitch[sl]
130+
time = time[sl]
131+
velocity = velocity[sl]
132+
end = end[sl]
133+
mask = mask[sl]
128134

129135
return {
130136
'mask':mask,

0 commit comments

Comments
 (0)