MIDI input OR slider for control

I have a little SnythDef that I’m working on. It has a GUI I built with just five or six sliders. I’m wondering if I can work out some kind of Midi input that would accept input from either the slider or a keyboard. I’m not that interested in implementing noteOn() and noteOff()) right now as it’s kind of drone anyway. So I think I would just parse out two different inputs and then compare to last input and which ever was different from the currently playing pitch - just play that. So in a sense I just need an if clause to compare some inputs.

I guess the midi input should set the slider to the new value also.

Any help or suggestions of function files that I might employ will be helpful.

Paul

(
// define a synth
SynthDef(“SawNoiseLP”, { arg note = 36, noteOffset = 0, fc = 1000, rq = 0.25, bal = 0, amp=0.4, ampFactor = 1.0, width=0.3, gate = 1.0, nDepth = 0.1, nFact = 1.0, nFreq = 80, nFFact = 1.0 ;
var x;

x = Mix.fill(4, {
	VarSaw.ar(((note + noteOffset) + {0.1.rand2}.dup).midicps, 0, width, 0.02)
});"/Users/foo/Documents/Documents - MacBook Pro/SuperColliderSketches/SawNoiseResonant_GUI/SawNoiseResonLowPass BetterMaster.scd"

x = RLPF.ar(x, fc, rq, amp * ampFactor).softclip;
x = Balance2.ar(x[0], x[1], bal);
x = x * EnvGen.kr(Env.cutoff, gate, 5, doneAction: 2);
y =  Balance2.ar(BPF.ar(BrownNoise.ar(nDepth * nFact, 0.001), nFreq * nFFact, nDepth * nFact),
	BPF.ar(BrownNoise.ar(nDepth * nFact, 0.001), nFreq * nFFact * 1.033, nDepth * nFact), bal);
y = RLPF.ar(y, fc, rq, nDepth * nFact).softclip;
z = Mix([x,y]);
Out.ar(0, z);

}, [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
).add;
)

f.value; //first window - creates another clone if invoked again

( // evaluate (CMD-return) this section - then evaluate f.value above to start the GUI
f = {
// start server

var w, startButton, cloneButton, killButton, sliders, noiseDep;
var node, cmdPeriodFunc, gate;
var specs, params, margin = 65, xGrid = 72, blueGridOffset = 44;

params = ["note", "fc", "rq", "bal", "amp",  "nDepth", "nFreq"];
specs = [
	ControlSpec(24, 110, \lin, 1, 36, \note),
	ControlSpec(200, 10000, \exp,0.01,1000,\Hz),
	ControlSpec(0.01, 2.0,\lin,0.001,0.2,\rq),
	ControlSpec(-1, 1, \lin, 0, 0, \pan),
	ControlSpec(0, 3, \lin, 0, 0.1, \vol), // db spec,  use self made one
	ControlSpec(0, 1.5, \lin, 0.01, 0.01, \nDepth),
	ControlSpec(10, 3000.0, \lin, 0.01, 0.3, \nFreq),
];

// make the window
w = Window("Saw Noise Resonant LowPass", Rect(20, 400, 660, 220));
w.front; // make window visible and front window.
w.alwaysOnTop = true;
w.view.decorator = FlowLayout(w.view.bounds);
w.view.decorator.gap=4@5;"/Users/foo/Library/Application Support/SuperCollider/Help/Search.html";


// add a button to start and stop the sound.
startButton = Button(w, 50 @ 20);
startButton.states = [
	["Start", Color.black, Color.green(0.7)],
	["Stop", Color.white, Color.red(0.7)]
];

// clones window
cloneButton = Button(w, 50 @ 20);
cloneButton.states = [
	["Clone", Color.black, Color.green(0.7)]
];

cloneButton.action = {
	f.value;
};

killButton = Button(w, 50 @ 20);
killButton.states = [
	["Kill All", Color.black, Color.green(0.7)]
];

killButton.action = {
	g.freeAll;
};

startButton.action = {|view|
	var args;
	if (view.value == 1) {
		// start sound
		params.do { |param, i|
			args = args.add(param);
			args = args.add(sliders[i].value)
		};
		node = Synth("SawNoiseLP", args.postcs, g, addAction: 'addToTail');

	} {
		// set gate to zero to cause envelope to release
		node.release;
		node = nil;
	};
};

// create controls for all parameters
w.view.decorator.nextLine;
sliders = params.collect { |param, i|
	EZSlider(w, 650 @ 20, param, specs[i],
		{|ez| node.set( param, ez.value )})
	.setColors(Color.grey,Color.white,
		Color.grey(0.7),Color.grey, Color.white, Color.yellow);
};

w.drawFunc = {
	10.do ({|i|
		Pen.strokeColor = Color.red;
		Pen.width_(2.0);
		Pen.moveTo(margin @ 0);
		Pen.lineTo(margin + (i * xGrid) @ 0 );
		Pen.lineTo(margin  + (i * xGrid) @ 180);
	});
	Pen.stroke;

	10.do ({|i|
		Pen.strokeColor = Color.blue;
		Pen.width_(2.0);
		Pen.moveTo(margin + blueGridOffset @ 0);
		Pen.lineTo(margin + blueGridOffset + (i * xGrid) @ 0 );
		Pen.lineTo(margin  + blueGridOffset + (i * xGrid) @ 180);
	});
	Pen.stroke;

};

w.refresh;

// set start button to zero upon a cmd-period
cmdPeriodFunc = { startButton.value = 0; };
CmdPeriod.add(cmdPeriodFunc);

// stop the sound when window closes and remove cmdPeriodFunc.
w.onClose = {
	node.free; node = nil;
	CmdPeriod.remove(cmdPeriodFunc);
};

}
)

Hi,

Maybe this can be useful: Knobs, sliders, textfields that can send and listen to midi devices

I’m thinking of e.g. this example in particular: sc-midi-controls/drivingsynth.scd at main · shimpe/sc-midi-controls · GitHub

Thanks shiihs If I can’t figure out something simpler I’ll dig into your code.

I really just wanted to compare two values and take the one that doesn’t match. There must be some function for this? I remember reading a discussion of why “if statements” don’t work in SC but as newb it wasn’t fully parsed

“if” doesn’t work in SC is only relevant inside SynthDef’s, i.e. code that eventually will run on the audio server. The code that runs on the client (i.e. most of the rest of your code) can use “if” without limitations.
You can look into MIDIdef documentation to see how to listen for a midi CC change (which is typically what you want to do when observing some hardware slider).