You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
(
// This is b700ish
// A vague attempt to implement a rough guess of the
// Buchla 700 voice architecture in Supercollider
// Aaron Lanterman, October 21, 2020
// Make sure you also have b700ish_patches.scd file.
// Also, find the line that reads
// "/Users/lanterma/buchla700_supercollider/b700ish_patches.scd".load;
// and change it to an appropriate path on your machine.
// Execute this whole-file code block to start.
// There's a bug where you need to manually select a patch from the patch menu before sound will start.
// The Patch drop-down menu is in the upper right corner; I think any patch will do.
// You can use a MIDI controller or the key buttons in the lower right corner of the GUI.
s.boot;
s.scope;
FreqScope.new;
var cfreq = freq;
var po = LocalIn.ar(4);
var freqs = cfreq * numerators / denominators;
var out, oo, fmodinputs, tm2, tm5, wsAoutput, wsBoutput, wsMix;
var levelA, levelB, rawlevelA, rawlevelB;
var acousticVars,rawindexes,max_rawindex,io0,io1,io2,io3,io4,io5,io6;
var envidx1, envidx2, envidx3, envidx4, envidx5, envidx6;
var envfilt, envres, envlevelA, envlevelB;
var filtercontrol, rescontrol;
var envidx1trick = Env.newClear(8);
var envidx2trick = Env.newClear(8);
var envidx3trick = Env.newClear(8);
var envidx4trick = Env.newClear(8);
var envidx5trick = Env.newClear(8);
var envidx6trick = Env.newClear(8);
var envfilttrick = Env.newClear(8);
var envrestrick = Env.newClear(8);
var envlevelAtrick = Env.newClear(8);
var envlevelBtrick = Env.newClear(8);
envidx1 = \env1.kr(envidx1trick.asArray);
envidx2 = \env2.kr(envidx2trick.asArray);
envidx3 = \env3.kr(envidx3trick.asArray);
envidx4 = \env4.kr(envidx4trick.asArray);
envidx5 = \env5.kr(envidx5trick.asArray);
envidx6 = \env6.kr(envidx6trick.asArray);
envlevelA = \envlA.kr(envlevelAtrick.asArray);
envlevelB = \envlB.kr(envlevelBtrick.asArray);
envfilt = \envf.kr(envfilttrick.asArray);
envres = \envr.kr(envrestrick.asArray);
acousticVars = Clip.kr(offsets.lag(0.5) +
[EnvGen.kr(envidx1,gate), EnvGen.kr(envidx2,gate), EnvGen.kr(envidx3,gate),
EnvGen.kr(envidx4,gate), EnvGen.kr(envidx5,gate), EnvGen.kr(envidx6,gate),
EnvGen.kr(envlevelA,gate,doneAction: Done.freeSelf),
EnvGen.kr(envlevelB,gate,doneAction: Done.freeSelf),
EnvGen.kr(envfilt,gate), EnvGen.kr(envres,gate)],
0,10);
filtercontrol = acousticVars[~filteno];
rescontrol = acousticVars[~reseno];
levelA = acousticVars[~levelAeno];
levelB = acousticVars[~levelBeno];
//rawindexes =
// 8*pi*(2**(((127*[acousticVars[~idx1eno],acousticVars[~idx2eno],acousticVars[~idx3eno],
// acousticVars[~idx4eno],acousticVars[~idx5eno],acousticVars[~idx6eno]]
// /10)-135)/8));
rawindexes = pi*(2**((33/16)-((100-(10*
[acousticVars[~idx1eno],acousticVars[~idx2eno],acousticVars[~idx3eno],
acousticVars[~idx4eno],acousticVars[~idx5eno],acousticVars[~idx6eno]]))/8)));
max_rawindex = pi*(2**(33/16));
// index triangle outputs
io0 = rawindexes[0] * Select.ar(config,
[po[2-1],po[2-1],po[2-1],po[1-1],po[1-1],po[1-1],
po[3-1],po[4-1],po[3-1],po[4-1],po[3-1],po[1-1]]);
io1 = rawindexes[1] * Select.ar(config,
[po[4-1],po[2-1],po[3-1],po[3-1],po[2-1],po[4-1],
po[2-1],po[2-1],po[2-1],po[3-1],po[2-1],po[2-1]]);
io3 = rawindexes[3] * Select.ar(config,
[po[2-1],po[4-1],po[4-1],po[2-1],po[3-1],po[3-1],
po[4-1],po[4-1],po[3-1],po[2-1],po[1-1],po[4-1]]);
io4 = rawindexes[4] * Select.ar(config,
[po[4-1],po[4-1],po[1-1],po[3-1],po[4-1],po[2-1],
po[1-1],po[4-1],po[1-1],po[1-1],po[2-1],po[3-1]]);
// index triangles 3 and 6 (on images), i.e. 2 and 5 in code, only feed wavetables
fmodinputs = [Select.ar(config,[io0,io0,io0,io1,io1,io1,
io1,io1,io1,io0,io1,io4]),
Select.ar(config,[Silent.ar,Silent.ar,io1,io4,io3,Silent.ar,
io0,io0,io3,io1,Silent.ar,io0]),
Select.ar(config,[io3,io3,io3,Silent.ar,Silent.ar,io4,
Silent.ar,Silent.ar,Silent.ar,io3,io4,Silent.ar]),
Select.ar(config,[Silent.ar,Silent.ar,io4,Silent.ar,Silent.ar,Silent.ar,
Silent.ar,Silent.ar,Silent.ar,io4,Silent.ar,Silent.ar])];
fmodinputs[0] = fmodinputs[0] +
Select.ar(config,[Silent.ar,Silent.ar,Silent.ar,Silent.ar,Silent.ar,Silent.ar,
io3,io3,Silent.ar,Silent.ar,Silent.ar,Silent.ar]);
fmodinputs[1] = fmodinputs[1] +
Select.ar(config,[Silent.ar,Silent.ar,Silent.ar,Silent.ar,io4,Silent.ar,
Silent.ar,Silent.ar,Silent.ar,Silent.ar,Silent.ar,Silent.ar]);
// oscillator outputs
oo = SinOsc.ar(freqs,fmodinputs);
// index triangles 3 and 6 (on images), i.e. 2 and 5 in code, only feed wavetables
tm2 = Select.ar(config,[io1,io1,Silent.ar,io0,Silent.ar,io0,
Silent.ar,Silent.ar,io0,Silent.ar,io0,io3]);
tm5 = Select.ar(config,[io4,io4,Silent.ar,io3,Silent.ar,io3,
Silent.ar,io4,io4,Silent.ar,io3,io1]);
// Since the output of index triangles 3 and 6 (on images), i.e. 2 and 5 in code,
// doesn't involve any feedback mechanisms, we might as well use oo intead of po.
io2 = ((rawindexes[2] + tm2) / max_rawindex) *
Select.ar(config,
[oo[1-1],oo[1-1],oo[1-1],oo[4-1],oo[1-1],oo[2-1],
oo[1-1],oo[1-1],oo[1-1],oo[1-1],oo[1-1],oo[1-1]]);
io5 = ((rawindexes[5] + tm5) / max_rawindex) *
Select.ar(config, [oo[3-1],oo[3-1],oo[3-1],oo[4-1],oo[1-1],oo[4-1],
oo[1-1],oo[4-1],oo[4-1],oo[3-1],oo[3-1],oo[1-1]]);
LocalOut.ar(oo);
wsAoutput = Shaper.ar(wsAbuf, io2);
wsBoutput = Shaper.ar(wsBbuf, io5);
//rawlevelA = 8*pi*(2**(((127*levelA/10)-135)/8));
//rawlevelB = 8*pi*(2**(((127*levelB/10)-135)/8));
rawlevelA = pi*(2**((33/16)-((100-(10*levelA))/8)));
rawlevelB = pi*(2**((33/16)-((100-(10*levelB))/8)));
wsAoutput = (rawlevelA / max_rawindex) * wsAoutput;
wsBoutput = (rawlevelB / max_rawindex) * wsBoutput;
wsMix = (wsBoutput * cf) + (wsAoutput * (1 - cf));
out = wsMix;
out = MoogFF.ar(wsMix, 20*(2**filtercontrol), 4 * rescontrol/10);
Out.ar(0, 0.2*[out, out]);
}).add;
///////////////
MIDIClient.init;
MIDIIn.connectAll;
~notes = Array.newClear(128); // array has one slot per possible MIDI note
~startNote = { arg velocity, noteNumber;
~vel = velocity / 127;
~nn = noteNumber;
~genvstr.do({arg item, i;
var realenv = try {item.compile.value;} {arg error; };
if(realenv.isKindOf(Env),
{~genv[i] = realenv;
{~envtitles[i].stringColor = ~darkGreen;}.defer;
},
{~genv[i] = nil;
postln("Charm");
{~envtitles[i].stringColor = Color.red;}.defer;}
);
});
~notes[noteNumber] = Synth.new(\fbfm, [\freq, (noteNumber).midicps, \gate, 1,
\config, ~gconfig,
\offsets, ~goffsets,
\numerators, ~gnumerators,
\denominators, ~gdenominators,
\cf, ~gcf,
\wsAbuf, ~gwsAbuf, \wsBbuf, ~gwsBbuf,
// it seems like SC doesn't want me to pass in ~genvinv all at once,
// as an array; when compiling the synthdef, it complains that
// the "message 'at' is not understood" -- not sure why...
\env1, ~genv[~idx1eno], \env2, ~genv[~idx2eno], \env3, ~genv[~idx3eno],
\env4, ~genv[~idx4eno], \env5, ~genv[~idx5eno], \env6, ~genv[~idx6eno],
\envlA, ~genv[~levelAeno], \envlB, ~genv[~levelBeno],
\envf, ~genv[~filteno], \envr, ~genv[~reseno]
]);
~notes[noteNumber].register;
};
~makeAplots = {
~plotterA = Plotter("",Rect(350,182,190,100),w);
~plotterA.plotColor_(Color.red);
~plotterA.value = ~wsAsig;
~plotterAsinin = Plotter("",Rect(550,182,100,100),w);
~plotterAsinin.plotColor_(Color.red);
// There has to be a more elegant way to do this...
~plotterAsinin.value =
Array.fill(100,{arg n; ~wsAsig[(~wsAsig.size - 1) * (sin(2pin / 100)+1)/2]});
};
~makeBplots = {
~plotterB = Plotter("",Rect(350,310,190,100),w);
~plotterB.plotColor_(Color.green);
~plotterB.value = ~wsBsig;
~plotterBsinin = Plotter("",Rect(550,310,100,100),w);
~plotterBsinin.plotColor_(Color.green);
// There has to be a more elegant way to do this...
~plotterBsinin.value =
Array.fill(100,{arg n; ~wsBsig[(~wsBsig.size - 1) * (sin(2pin / 100)+1)/2]});
};
I added keyboard functionality
(
// This is b700ish
// A vague attempt to implement a rough guess of the
// Buchla 700 voice architecture in Supercollider
// Aaron Lanterman, October 21, 2020
// Make sure you also have b700ish_patches.scd file.
// Also, find the line that reads
// "/Users/lanterma/buchla700_supercollider/b700ish_patches.scd".load;
// and change it to an appropriate path on your machine.
// Execute this whole-file code block to start.
// There's a bug where you need to manually select a patch from the patch menu before sound will start.
// The Patch drop-down menu is in the upper right corner; I think any patch will do.
// You can use a MIDI controller or the key buttons in the lower right corner of the GUI.
s.boot;
s.scope;
FreqScope.new;
~trianglePink = Color(255/255,0,170/255,1);
~circleBlue = Color(0,170/255,255/255,1);
~squareOrange = Color(255/255,170/255,0,1);
~squareGreen = Color(0,255/255,170/255,1);
~envTitleStrings = ["Idx1","Idx2","Idx3","Idx4","Idx5","Idx6", "LvlA", "LvlB", "Filt", "Res"];
~envTitleColors = (~trianglePink ! 6) ++ [~squareOrange] ++ [~squareGreen] ++ (Color.black ! 2);
~numberEnvs = ~envTitleStrings.size;
~idx1eno = 0; ~idx2eno = 1; ~idx3eno = 2;
~idx4eno = 3; ~idx5eno = 4; ~idx6eno = 5;
~levelAeno = 6; ~levelBeno = 7;
~filteno = 8; ~reseno = 9;
"/Users/ss/Downloads/b700ish-main/b700ish_patches.scd".load;
if (~currentPatch.isNil,{~currentPatch=0});
~instruments[~currentPatch].value;
~chebyNames = Array.new;
~chebyCoefs = Array.new;
~chebyNames = ~chebyNames.add("Default");
~chebyCoefs = ~chebyCoefs.add([1]);
~chebyNames = ~chebyNames.add("True Triangle ");
~chebyCoefs = ~chebyCoefs.add([1,0] / ((1..32).squared));
~chebyNames = ~chebyNames.add("Square-Compatible Triangle");
~chebyCoefs = ~chebyCoefs.add([1,0,-1,0] / ((1..32).squared));
~chebyNames = ~chebyNames.add("Jimmy Smith (All Positive)");
~chebyCoefs = ~chebyCoefs.add([1,1,1]);
~chebyNames = ~chebyNames.add("Jimmy Smith");
~chebyCoefs = ~chebyCoefs.add([1,1,-1]);
~chebyNames = ~chebyNames.add("Full Tonewheel");
~chebyCoefs = ~chebyCoefs.add([1,1,-1,-1,0,1,0,-1,0,1,0,-1,0,0,0,1]);
~chebyNames = ~chebyNames.add("True Square");
~chebyCoefs = ~chebyCoefs.add([1,0,-1,0] / (1..32));
~chebyNames = ~chebyNames.add("Triangle-Compatible Square");
~chebyCoefs = ~chebyCoefs.add([1,0] / (1..32));
~chebyNames = ~chebyNames.add("Alt Saw");
~chebyCoefs = ~chebyCoefs.add(0.25*[1,-1,-1,1] / (1..32));
~chebyNames = ~chebyNames.add("Alt Impulse Train");
~chebyCoefs = ~chebyCoefs.add(0.1*[1,-1,-1,1]Array.fill(32,1));
~chebyNames = ~chebyNames.add("Alt Sign-Flipping Impulse Train");
~chebyCoefs = ~chebyCoefs.add(0.1[1,0,-1,0]*Array.fill(32,1));
~wsdefaultsig = Signal.chebyFill(4096, [1], normalize: true, zeroOffset:false);
~wsdefault = ~wsdefaultsig.asWavetableNoWrap;
~wsdefaultbuf = Buffer.loadCollection(s, ~wsdefault);
SynthDef.new(\fbfm, {
arg freq = 220, gate = 0, config = 1, offsets = #[0,0,10,0,0,10,10,10,10,0],
numerators = #[1,1,1,1], denominators = #[1,1,1,1],
cf = 0,
wsAbuf = ~wsdefaultbuf, wsBbuf = ~wsdefaultbuf;
// index triangles 3 and 6 (on images), i.e. 2 and 5 in code, only feed wavetables
fmodinputs = [Select.ar(config,[io0,io0,io0,io1,io1,io1,
io1,io1,io1,io0,io1,io4]),
Select.ar(config,[Silent.ar,Silent.ar,io1,io4,io3,Silent.ar,
io0,io0,io3,io1,Silent.ar,io0]),
Select.ar(config,[io3,io3,io3,Silent.ar,Silent.ar,io4,
Silent.ar,Silent.ar,Silent.ar,io3,io4,Silent.ar]),
Select.ar(config,[Silent.ar,Silent.ar,io4,Silent.ar,Silent.ar,Silent.ar,
Silent.ar,Silent.ar,Silent.ar,io4,Silent.ar,Silent.ar])];
}).add;
///////////////
MIDIClient.init;
MIDIIn.connectAll;
~notes = Array.newClear(128); // array has one slot per possible MIDI note
~startNote = { arg velocity, noteNumber;
~vel = velocity / 127;
~nn = noteNumber;
~genvstr.do({arg item, i;
var realenv = try {item.compile.value;} {arg error; };
if(realenv.isKindOf(Env),
{~genv[i] = realenv;
{~envtitles[i].stringColor = ~darkGreen;}.defer;
},
{~genv[i] = nil;
postln("Charm");
{~envtitles[i].stringColor = Color.red;}.defer;}
);
});
~notes[noteNumber] = Synth.new(\fbfm, [\freq, (noteNumber).midicps, \gate, 1,
\config, ~gconfig,
\offsets, ~goffsets,
\numerators, ~gnumerators,
\denominators, ~gdenominators,
\cf, ~gcf,
\wsAbuf, ~gwsAbuf, \wsBbuf, ~gwsBbuf,
// it seems like SC doesn't want me to pass in ~genvinv all at once,
// as an array; when compiling the synthdef, it complains that
// the "message 'at' is not understood" -- not sure why...
\env1, ~genv[~idx1eno], \env2, ~genv[~idx2eno], \env3, ~genv[~idx3eno],
\env4, ~genv[~idx4eno], \env5, ~genv[~idx5eno], \env6, ~genv[~idx6eno],
\envlA, ~genv[~levelAeno], \envlB, ~genv[~levelBeno],
\envf, ~genv[~filteno], \envr, ~genv[~reseno]
]);
~notes[noteNumber].register;
};
~stopNote = { arg velocity, noteNumber;
~notes[noteNumber].set(\gate, 0);
~notes[noteNumber] = nil;
};
MIDIdef.noteOn(\noteOnTest,{ arg velocity, noteNumber, chan, src;
~startNote.value(velocity, noteNumber)});
MIDIdef.noteOff(\noteOffTest, { arg velocity, noteNumber, chan, src;
~stopNote.value(velocity, noteNumber); });
~updateGUI = {
~cfimages = Array.fill(12,
{arg i;
Image.new("/Users/ss/Downloads/b700ish-main/fm_config_c_"
++ i.asStringToBase(width: 2) ++ ".png"); });
if(w.notNil,
{if(w.isClosed,
{~currentBounds = Rect(0,540,700,600)},
{~currentBounds = w.bounds;
~currentBounds.top = ~currentBounds.top+22;
});},
{~currentBounds = Rect(0,540,700,600)});
Window.closeAll;
~forceOnTop = false;
w = Window("B700ish",~currentBounds,resizable: false).front.alwaysOnTop_(~forceOnTop);
~cfknob = Knob(w,Rect(330,110,32,32))
.action_({arg obj;
~notes.do({arg item;
~gcf = obj.value;
if (item.isPlaying,
{item.set(\cf,~gcf);});
});
})
.value = ~gcf;
StaticText(w, Rect(165,150,160,40)).string_("Frequency Ratios:");
~numtextboxes = Array.fill(4,
{arg i;
var tf = TextField(w,Rect(165+(40*i),182,37,22))
.action_({arg obj;
var vaf = obj.value.asFloat;
if(vaf != 0,
{~gnumerators[i] = vaf;
~notes.do({arg item;
if(item.isPlaying,
{item.seti(\numerators,i,vaf);});
})
});
obj.value = ~gnumerators[i].asString;
});
tf.string = ~gnumerators[i].asString;
tf;
});
~denomtextboxes = Array.fill(4,
{arg i;
var tf = TextField(w,Rect(165+(40*i),207,37,22))
.action_({arg obj;
var vaf = obj.value.asFloat;
if(vaf != 0,
{~gdenominators[i] = vaf;
~notes.do({arg item;
if(item.isPlaying,
{item.seti(\denominators,i,vaf);});
})
});
obj.value = ~gdenominators[i].asString;
});
tf.string = ~gdenominators[i].asString;
tf;
});
w.drawFunc_({~cfimages[~gconfig].tileInRect(Rect(10,182,128,128))});
w.refresh;
StaticText(w, Rect(10,150,160,40)).string_("Config:");
~configselect = PopUpMenu(w, Rect(60, 160, 40, 20));
~configselect.items = Array.series(12);
~configselect.value = ~gconfig;
~configselect.action =
{ arg obj;
~gconfig = obj.value;
w.drawFunc_({~cfimages[~gconfig].tileInRect(Rect(10,182,128,128))});
w.refresh; // need this so new image appears
~notes.do({arg item;
if(item.isPlaying,
{item.set(\config,~gconfig);})
});
};
~setupAbuf = { arg selection;
~wsAsig = Signal.chebyFill(4096, ~chebyCoefs[selection],
normalize: true, zeroOffset:false);
~wsA = ~wsAsig.asWavetableNoWrap;
~gwsAbuf = Buffer.loadCollection(s, ~wsA);
};
~setupBbuf = { arg selection;
~wsBsig = Signal.chebyFill(4096, ~chebyCoefs[selection],
normalize: true, zeroOffset:false);
~wsB = ~wsBsig.asWavetableNoWrap;
~gwsBbuf = Buffer.loadCollection(s, ~wsB);
};
~envtitles = Array.fill(~numberEnvs,
{arg i;
StaticText(w, Rect(5,310+(25*i),40,40)).string_(~envTitleStrings[i] ++ ":").align_(\left)
});
~darkGreen = Color(0,0.5,0,1);
~genv = Array.fill(~numberEnvs);
~envtextboxes = Array.fill(~numberEnvs,
{arg i;
var realenv = nil;
var tf = TextField(w,Rect(40,320+(25*i),300,22))
.action_({arg obj;
var realenv = nil;
~vel = 1; ~nn = 60;
realenv = try {obj.value.compile.value;} {arg error; };
~genvstr[i] = obj.value;
if(realenv.isKindOf(Env),
{~genv[i] = realenv;
~envtitles[i].stringColor = ~darkGreen;},
{~genv[i] = nil;
~envtitles[i].stringColor = Color.red;}
);
});
~genvstr;
tf.value = ~genvstr[i];
~vel = 1; ~nn = 60;
realenv = try {~genvstr[i].compile.value;} {arg error; };
if(realenv.isKindOf(Env),
{~genv[i] = realenv;
~envtitles[i].stringColor = ~darkGreen;
},
{~genv[i] = nil;
~envtitles[i].stringColor = Color.red;}
);
tf;
});
~goffsets[1]; //8.4
~offsetSliders = Array.fill(~numberEnvs,
{arg i;
Slider(w,Rect(10+(32i),6,20,128))
.action_({arg obj;
~goffsets[i] = 10(obj.value);
~notes.do({arg item;
if (item.isPlaying,
{item.seti(\offsets,i,~goffsets[i]);}
);
});
}).knobColor_(~envTitleColors[i]).value = (~goffsets[i] / 10);
StaticText(w, Rect(0+(32*i),120,40,40)).string_(~envTitleStrings[i]).align_(\center);
});
~setupAbuf.value(~gwsAselect);
~setupBbuf.value(~gwsBselect);
~makeAplots = {
~plotterA = Plotter("",Rect(350,182,190,100),w);
~plotterA.plotColor_(Color.red);
~plotterA.value = ~wsAsig;
~plotterAsinin = Plotter("",Rect(550,182,100,100),w);
~plotterAsinin.plotColor_(Color.red);
// There has to be a more elegant way to do this...
~plotterAsinin.value =
Array.fill(100,{arg n; ~wsAsig[(~wsAsig.size - 1) * (sin(2pin / 100)+1)/2]});
};
~makeBplots = {
~plotterB = Plotter("",Rect(350,310,190,100),w);
~plotterB.plotColor_(Color.green);
~plotterB.value = ~wsBsig;
~plotterBsinin = Plotter("",Rect(550,310,100,100),w);
~plotterBsinin.plotColor_(Color.green);
// There has to be a more elegant way to do this...
~plotterBsinin.value =
Array.fill(100,{arg n; ~wsBsig[(~wsBsig.size - 1) * (sin(2pin / 100)+1)/2]});
};
~makeAplots.value();
~makeBplots.value();
StaticText(w, Rect(350,150,160,40)).string_("WaSh A:");
~wsAselect = PopUpMenu(w, Rect(408, 160, 130,20));
~wsAselect.items = ~chebyNames;
~wsAselect.value = ~gwsAselect;
~wsAselect.action = { arg obj;
~gwsAselect = obj.value;
~setupAbuf.value(~gwsAselect);
~makeAplots.value();
};
StaticText(w, Rect(350,278,160,40)).string_("WaSh B:");
~wsBselect = PopUpMenu(w, Rect(408, 288, 130, 20));
~wsBselect.items = ~chebyNames;
~wsBselect.value = ~gwsBselect;
~wsBselect.action = { arg obj;
~gwsBselect = obj.value;
~setupBbuf.value(~gwsBselect);
~makeBplots.value();
};
StaticText(w, Rect(350,50,160,40)).string_("Patch:");
~patchselect = PopUpMenu(w, Rect(395, 60, 250,20));
~patchselect.items = ~instrumentNames;
~patchselect.value = ~currentPatch;
~patchselect.action = { arg obj;
~currentPatch = obj.value;
~instruments[~currentPatch].value;
~updateGUI.value;
};
~keysrow1 = Array.fill(13, {arg i;
Button(w, Rect(350+(22*i), 430, 20, 40))
.states_([["", Color.white, Color.white]])
.mouseDownAction_({~startNote.value(127, 36+i)})
.mouseLeaveAction_({~stopNote.value(127, 36+i)})
.action_({~stopNote.value(127, 36+i)});
});
~keysrow2 = Array.fill(13, {arg i;
Button(w, Rect(350+(22*i), 472, 20, 40))
.states_([["", Color.white, Color.white]])
.mouseDownAction_({~startNote.value(127, 12+36+i)})
.mouseLeaveAction_({~stopNote.value(127, 12+36+i)})
.action_({~stopNote.value(127, 12+36+i)});
});
~keysrow2 = Array.fill(13, {arg i;
Button(w, Rect(350+(22*i), 514, 20, 40))
.states_([["", Color.white, Color.white]])
.mouseDownAction_({~startNote.value(127, 24+36+i)})
.mouseLeaveAction_({~stopNote.value(127, 24+36+i)})
.action_({~stopNote.value(127, 24+36+i)});
});
~keyboardActiveButton = Button(w, Rect(350, 560, 150, 30))
.states_([
["Activate Keyboard", Color.black, Color.gray],
["Deactivate Keyboard", Color.white, Color.red]
])
.action_({ |butt|
~keyboardActive = butt.value == 1;
});
~keyboardActive = false;
~keyboardActiveButton = Button(w, Rect(350, 560, 150, 30))
.states_([
["Activate Keyboard", Color.black, Color.gray],
["Deactivate Keyboard", Color.white, Color.red]
])
.action_({ |butt|
~keyboardActive = butt.value == 1;
});
};
~updateGUI.value;
)
The text was updated successfully, but these errors were encountered: