edited example 8b-mlp-synth-control

brought it in line with the max example.

the user must put the synth params and 2D slider where they want them, _and then_ click 'add point'.

also simplified some of the SC code.
nix
Ted Moore 4 years ago
parent bff1b1fe80
commit c103897eb8

@ -1,90 +1,101 @@
//1- make the gui then the synth below
(
var trained = 0, entering = 0;
var va = Array.fill(10,{0.5});
var input = Buffer.alloc(s,2);
var output = Buffer.alloc(s,10);
var mlp = FluidMLPRegressor(s,[6],activation: 1,outputActivation: 1,maxIter: 1000,learnRate: 0.1,momentum: 0,batchSize: 1,validation: 0);
var entry = 0;
Window.closeAll;
s.waitForBoot{
Task{
var trained = 0, entering = 0;
var input_buffer = Buffer.alloc(s,2);
var output_buffer = Buffer.alloc(s,10);
var mlp = FluidMLPRegressor(s,[6],activation: 1,outputActivation: 1,maxIter: 1000,learnRate: 0.1,momentum: 0.9,batchSize: 1);
var entry_counter = 0;
var win, multislider, xyslider, synth, error_st, prediction_but, addPoints_but, train_but;
var item_width = 100;
var inData = FluidDataSet(s);
var outData = FluidDataSet(s);
~inData = FluidDataSet(s);
~outData = FluidDataSet(s);
win = Window("ChaosSynth", Rect(10, 10, 840, 320)).front;
w = Window("ChaosSynth", Rect(10, 10, 790, 320)).front;
a = MultiSliderView(w,Rect(10, 10, 400, 300)).elasticMode_(1).isFilled_(1);
a.value=va;
a.action = {arg q;
b.set(\val, q.value);
va = q.value;};
f = Slider2D(w,Rect(420,10,300, 300));
f.x = 0.5;
f.y = 0.5;
f.action = {arg x,y; //if trained, predict the point f.x f.y
if (entering == 1, { //if entering a point, add to the the database f.x f.y against the array va
input.setn(0, [f.x, f.y]);
output.setn(0, va);
~inData.addPoint(entry.asSymbol,input);
~outData.addPoint(entry.asSymbol,output);
entering = 0;
entry = entry + 1;
{d.value = 0;}.defer;
}, { //if not entering a point
if (trained == 1, { //if trained
input.setn(0, [f.x, f.y]);
mlp.predictPoint(input,output,{
output.getn(0,10,{
|x|va = x; b.set(\val, va); {a.value = va;}.defer;});
multislider = MultiSliderView(win,Rect(10, 10, 400, 300))
.elasticMode_(1)
.isFilled_(1)
.action_({
arg ms;
// ms.value.postln;
synth.set(\val,ms.value);
output_buffer.setn(0,ms.value);
})
.value_(0.5.dup(10));
xyslider = Slider2D(win,Rect(420,10,300, 300))
.x_(0.5)
.y_(0.5)
.action_({
arg sl;
input_buffer.setn(0,[sl.x,sl.y]);
if(prediction_but.value.asBoolean,{
mlp.predictPoint(input_buffer,output_buffer,{
output_buffer.getn(0,10,{
arg output_values;
synth.set(\val, output_values);
{
multislider.value_(output_values)
}.defer;
});
});
});
});
});
};
c = Button(w, Rect(730,240,50, 20)).states_([["train", Color.red, Color.white], ["trained", Color.white, Color.grey]]).action_{
mlp.fit(~inData,~outData,{|x|
trained = 1;
{
c.value = 1;
e.value = x.round(0.001).asString;
}.defer;
});//train the network
};
d = Button(w, Rect(730,10,50, 20)).states_([["entry", Color.white, Color.grey], ["entry", Color.red, Color.white]]).action_{
entering = 1;
};
StaticText(w,Rect(732,260,50,20)).string_("Error:");
e = TextField(w,Rect(730,280,50,20)).string_(0.asString);
StaticText(w,Rect(732,70,50,20)).string_("rate:");
TextField(w,Rect(730,90,50,20)).string_(0.1.asString).action_{|in|mlp.learnRate = in.value.asFloat.postln;};
StaticText(w,Rect(732,110,50,20)).string_("momentum:");
TextField(w,Rect(730,130,50,20)).string_(0.0.asString).action_{|in|mlp.momentum = in.value.asFloat.postln;};
StaticText(w,Rect(732,150,50,20)).string_("maxIter:");
TextField(w,Rect(730,170,50,20)).string_(1000.asString).action_{|in| mlp.maxIter = in.value.asInteger.postln;};
StaticText(w,Rect(732,190,50,20)).string_("validation:");
TextField(w,Rect(730,210,50,20)).string_(0.0.asString).action_{|in|mlp.validation = in.value.asFloat.postln;};
)
addPoints_but = Button(win, Rect(730,10,item_width, 20))
.states_([["add points", Color.white, Color.grey]])
.action_({
inData.addPoint(entry_counter.asSymbol,input_buffer);
outData.addPoint(entry_counter.asSymbol,output_buffer);
entry_counter = entry_counter + 1;
inData.print;
outData.print;
});
//2- the synth
(
b = {
arg val = #[0,0,0,0,0,0,0,0,0,0];
var osc1, osc2, feed1, feed2, base1=69, base2=69, base3 = 130;
#feed2,feed1 = LocalIn.ar(2);
osc1 = MoogFF.ar(SinOsc.ar((((feed1 * val[0]) + val[1]) * base1).midicps,mul: (val[2] * 50).dbamp).atan,(base3 - (val[3] * (FluidLoudness.kr(feed2, 1, 0, hopSize: 64)[0].clip(-120,0) + 120))).lag(128/44100).midicps, val[4] * 3.5);
osc2 = MoogFF.ar(SinOsc.ar((((feed2 * val[5]) + val[6]) * base2).midicps,mul: (val[7] * 50).dbamp).atan,(base3 - (val[8] * (FluidLoudness.kr(feed1, 1, 0, hopSize: 64)[0].clip(-120,0) + 120))).lag(128/44100).midicps, val[9] * 3.5);
Out.ar(0,LeakDC.ar([osc1,osc2],mul: 0.1));
LocalOut.ar([osc1,osc2]);
}.play;
)
train_but = Button(win, Rect(730,240,item_width, 20))
.states_([["train", Color.red, Color.white]])
.action_({
mlp.fit(inData,outData,{
arg loss;
{error_st.string_("loss: %".format(loss.round(0.001)))}.defer;
});
});
prediction_but = Button(win, Rect(730,40,item_width, 20))
.states_([["Not Predicting", Color.black, Color.white],["Predicting",Color.black,Color.white]]);
error_st = StaticText(win,Rect(732,260,item_width,20)).string_("Error:");
StaticText(win,Rect(732,70,item_width,20)).string_("rate:");
TextField(win,Rect(730,90,item_width,20)).string_(0.1.asString).action_{|in|mlp.learnRate = in.value.asFloat.postln;};
StaticText(win,Rect(732,110,item_width,20)).string_("momentum:");
TextField(win,Rect(730,130,item_width,20)).string_(0.9.asString).action_{|in|mlp.momentum = in.value.asFloat.postln;};
StaticText(win,Rect(732,150,item_width,20)).string_("maxIter:");
TextField(win,Rect(730,170,item_width,20)).string_(1000.asString).action_{|in| mlp.maxIter = in.value.asInteger.postln;};
~inData.print;
~outData.print;
s.sync;
//2- the synth
synth = {
arg val = #[0,0,0,0,0,0,0,0,0,0];
var osc1, osc2, feed1, feed2, base1=69, base2=69, base3 = 130;
#feed2,feed1 = LocalIn.ar(2);
osc1 = MoogFF.ar(SinOsc.ar((((feed1 * val[0]) + val[1]) * base1).midicps,mul: (val[2] * 50).dbamp).atan,(base3 - (val[3] * (FluidLoudness.kr(feed2, 1, 0, hopSize: 64)[0].clip(-120,0) + 120))).lag(128/44100).midicps, val[4] * 3.5);
osc2 = MoogFF.ar(SinOsc.ar((((feed2 * val[5]) + val[6]) * base2).midicps,mul: (val[7] * 50).dbamp).atan,(base3 - (val[8] * (FluidLoudness.kr(feed1, 1, 0, hopSize: 64)[0].clip(-120,0) + 120))).lag(128/44100).midicps, val[9] * 3.5);
Out.ar(0,LeakDC.ar([osc1,osc2],mul: 0.1));
LocalOut.ar([osc1,osc2]);
}.play;
}.play(AppClock);
};
)
/////////
//3 - play with the multislider
//4 - when you like a spot, click entry (become read) then a position in the 2D graph where this point should be
//4 - when you like a spot, move the 2d slider to a position that you want to represent that sound and click "add point"
//5 - do that for a few points
//6 - click train
//6 - click train, keep clicking train until the loss is at or below 0.01 or so. feel free to adjust the learning rate, momentum, and max iter.
//7 - the 2D graph controls the 10D
//8 - if you like a new sound and you want to update the graph, just click entry, then where it should be in the 2D, then retrain when you are happy

Loading…
Cancel
Save