Serial Control through Bus and Node

Hi there -

I’ve been experimenting with serial control lately - thanks to Fredrik’s tutorials - but I’m hitting a little bit of a snag in sending the serial channels to the node I’m working on.

All of the serial messages are being sent on a 6-channel control bus.
If I do something like this:

~nodeX.set(\slider1, \data.kr(0!6))

I’d presumably be bringing all 6 channels into the control for the slider1 (instead of controlling sliders 1 through 6)…

This idea produces an error (The preceding error dump is for ERROR: Message ‘addKr’ not understood.) - so this probably isn’t the proper way to map a bus onto a control node anyway…

~nodeX.set(\slider1, \data.kr[0])

Can anyone help me get sorted here?

Cheers!

Hard to see the full picture because of the limited code excerpt you’ve provided. I assume ~nodeX is a Synth, but I’m not sure what \data represents, nor what kind of argument \slider1 is supposed to be, nor exactly what you mean by “serial control” — do you just mean a collection of several busses with consecutive indices?

This might be way off, but here’s a simple example of working with control busses:

s.boot;

~ctlbus = Bus.control(s, 6); //create bus reference

(
SynthDef.new(\ctlbus, {
	arg ctlin=0, out=0;
	var sig, ampctl;
	ampctl = In.kr(ctlin, 6);
	sig = SinOsc.ar((1..6) * 300 - 75, mul:0.1);
	sig = sig * ampctl;
	sig = Splay.ar(sig);
	Out.ar(out, sig);
}).add;
)

x = Synth(\ctlbus, [\ctlin, ~ctlbus]);

~ctlbus.value_(1); //set all 6 control channels to 1
~ctlbus.setn(Array.rand(6,0.0,1.0)); //set all 6 channels randomly
~ctlbus.get(_.postln); //get bus values
~ctlbus.value_(0); //off

x.free;

Sorry, let me see if I can explain it a bit better… It’s a bit of a skill to figure out how much information…
~nodeX is a NodeProxy. I’m actually trying to send serial (10-bit) data for six channels, which is where the “data.kr” comes from…

.kr means a UGen – the values will exist only server side.

set is a language method to construct an OSC message to send to the server.

So, set and .kr are inherently incompatible. You can’t use kr in a set argument list.

It’s not clear where the data are coming from or their format, so I can’t be more specific at the moment.

hjh

Serial Code

I’m using this code, but I’d like to send the data to many multiple locations (I think sending to many locations within the Routine is maybe slow or CPU-intensive?) and I’d like to have a little more flexibility about where the data is going, instead of having to change an in-process Routine. Does that make sense? I’m sorry I’m not very good at explaining this, I’m still trying to understand some of these things.

Building from Eli’s example using control buses – something like this may help?

// create an array of 6 control buses
~busArray = Array.fill(6, { Bus.control(s, 1) });

// read or write 
~busArray[3].get;
~busArray[3].set(0.5);
~busArray[4].set(0.5);
~busArray.do({ arg bus; bus.set(0.0) });
~busArray.do({ arg bus; bus.set(rrand(0.1, 0.3)); bus.get.postln });

Now in your Routine, instead of Ndef(\arduino).setn(\data, data), you might write something like

~busArray.do({ arg bus, index; bus.set(data[index]) });

…so that data from each of the six sliders is continuously being written to a single control bus (one per slider)

Now in any Ndef or SynthDef context, you simply use the control data like so:

(
Ndef(\sound, {
	var snd = SinOsc.ar(
		freq: 100 * [1, 2, 3, 4, 5, 6],
		mul: In.kr(~busArray).lag(0.2)
	);
	snd.postln;
	snd = Splay.ar(snd);
	snd = Limiter.ar(snd);
}).play;
)

// simulated sliders in motion:
(
{
	var data;
	loop{
		data = Array.rand(6, 0.0, 0.4);
		// data.postln;
		~busArray.do({ arg bus, index; bus.set(data[index]) });
		0.2.wait;
	}
}.fork;
)

// or you could access individual control sliders individually anywhere
(
Ndef(\sound, {
	var snd = SinOsc.ar(
		// one slider for freq
		freq: In.kr(~busArray[0]).linexp(0, 1, 400, 800).lag,
		// another slider for amp, etc
		mul: In.kr(~busArray[1]).lag
	);
	snd.postln;
	snd = Splay.ar(snd);
	snd = Limiter.ar(snd);
}).play;
)

Thanks everyone, I understand now.

A quick follow-up - maybe this should be in a separate thread -
but if I use the bus with “.asMap” to a nodeProxy, is there any way to use “unset” and preserve the most recent value?