Audiobus(server,numchann)

Busses again …
So venturing into the next and crucial chapter of busses , still following eli’s tutorials
I have a basic Fm synth and a reverb
The output of the synth is set to bus 30 (argument for bus out ) , the input of the reverb same channel (argument bus in ) , and output to bus 0
The reverb is processing both dry and wet , but that’s not relevant here
Assigning the reverb to a variable and sequencing the Synth et voila we have a functioning reverb

Following elis tutorrial introducing ~variable=Audiobus(server,numchannels )
I assigned a variable called ~bus=Audiobus ,and put these both in the reverbsynth parameter settings , and the two op synth pbind
Looking at the scope it appears that this overrides the channel nr .30
Executng the same variable a few times , creates new busses ( see screenshot , new busses created up to audio 22 ).
So , I am correct in thinking that with each execution ( and thus creating of new bus ) the synth is automatically routed to that new buss assignment ?
At least , the scope shows it does , but there is also a signal present on bus 3-4 whcih are normally reserved for audio in
How is this possible ?
Also how can we check which bus nr channel whas created without creating a new one , adding the .value method just creates a new bus and thus reroutes it
Edit , this is easily fixed by just executing the variable without a declaration , it shows the assigned busses
And also , can we change the assigned bus for that variable ?
Here’s the file
Most importantly why is there signal present on bus channel 3??

(
SynthDef(\Reverberate,
	{
		|in=30,out=0,mix=1|
		var signal,processed;
		signal=In.ar(in,2);
		processed=FreeVerb.ar(signal,mix:mix);
		processed=(signal+processed)*0.5;
		Out.ar(out,processed);
}).add
)
~revv=Synth(\Reverberate,[\in,~bus]);
~revv.free
~revv.pause;
~revv.resume

~bus=Bus.audio(s,2).value

(
SynthDef(\twoop,
{
|fmamt=2,modoffset=24,moatt=0.001,modrel=0.500,ampatt=0.001,amprel=0.800,pitch=48,outt=0.3,pan=0.2,feed=0.2,out=30|
var mod,modenv,ampenv,carr;

		mod=SinOscFB.ar((pitch+modoffset).midicps,feedback:feed)*fmamt;
		modenv=EnvGen.ar(Env.perc(moatt,modrel),doneAction:0);
		ampenv=EnvGen.ar(Env.perc(ampatt,amprel),doneAction:2);
		carr=SinOsc.ar(pitch.midicps,(mod*modenv))*ampenv*outt;
		carr=Pan2.ar(carr,pos:pan);
		Out.ar(out,carr);
}).add
);
/////////
(
Pdef(
	\crt,
	Pbind(
		\instrument,
		\twoop,
		\pitch,Pseq([40,40,40,49,37,42,42,54],inf)-2,
		\dur,Pseq([1/4,1/4,1/2,1/4],inf),
		\fmamt,Prand([2,1,3,10,2,10,2,3,4,11],inf),
		\modrel,Prand([0.425,0.525,0.500,0.550,1,0.625,0.500,0.5,0.8],inf),
		\modoffset,Prand([12,0,12,24],inf),
		\feed,Pwhite(0.3,0.5,inf),
		\pan,Prand([-0.3,0,0.3],inf),
		\amprel,Pwhite (0.08,0.3,inf),
		\out,~bus,
		)
	)
)
//////////
Pdef(\crt).stop;///////////FM
Pdef(\crt).play(t);
t=TempoClock(126/60).permanent_(true);
s.newBusAllocators;




1

What I also think is srange , when I put the globbaly declared variable ~bus ( declared outside synthdef ) inside the synthdef output it does not give an error

.value doesn’t do anything on audio busses - its used to asynchronously get the value from a control bus. You can skip that.

to assign an already allocated bus to a variable use:

Bus.new(index: index)
or Bus.new (\audio, index)

but you can also just store the number. If you decide 30 will be your verb bus you can just set

~verbBus = 30. and use that in your Pbind (\out, ~verbBus)

remember that SynthDef controls take numbers - your out control just needs the index number for the Bus you want to use.

When you use ~bus in the SynthDef, the interpreter resolves it before compiling the def. So whatever ~bus it is pointing to at the time you compile the synthdef gets coded into the synthdef and won’t change if you reassign ~bus. Same with Pbind.

re the question as to Bus 3 I can’t tell what processes you have running - I don’t see anything on Bus 3 when I run your example

So If Undestand correctly , to have individual channels (either processing the input or letting it thourgh )
We need to
1 -create a synthdef with in ( pick up audio from ) and output ,in supplied example I am using a reverb
2-create an additional variable to turn ON the revern and free the variable to turn it off
3-Creat a variable to create busses (overriding the synthdef bus arguments )

So basically 3 steps for every created channel ?
Please correct me when wrong

Anything to streamline this procedure ?

(
SynthDef(\Reverberatuh,
	{
		|in=30,out=0,mix=1|
		var signal,processed;
		signal=In.ar(in,2);
		processed=FreeVerb.ar(signal,mix:mix);
		processed=(signal+processed)*0.5;
		Out.ar(out,processed);
}).add
)//A synthdef reverb

~reverbon=Synth(\Reverberatuh,[\in,~reverbchannel])//varaibel for turning on the reverb 

~revberchannel.free//varaible for turnng OFF the reverb 
~reverbchannel=Bus.audio(s,2)//varaible for creating a bus and overridding the synthdefs argument

I’d suggest here that this is the first mistake :wink:

Most of what semiquaver said is exactly right – I’d just like to clarify, from the standpoint of best practice:

The whole point of using the bus allocator is that you should never have to write specific bus numbers into your code. You let the allocator give you the bus number! And then you just refer to it by variable.

So this – “to assign an already allocated bus to a variable” – in normal usage you would not do this. If you find yourself tempted to do this, it’s likely to be going down the wrong road.

Also this – “Looking at the scope it appears that this overrides the channel nr .30” – YES! If you’re using the bus allocator, then this is what you want.

When you’re using the bus allocator, you’re giving up control over specific bus numbers. So then, any bus numbers that you wrote into arg defaults will always be overridden – hence it’s irrelevant to write defaults for them anyway. It’s noise – a distraction. So, don’t write them. (It’s not harmful to write them, except that someone reading your code would get confused, “why is that in there?” and there is some benefit to avoiding distraction.)

hjh

I’d already commented on this – S.options,OutputBusChannels - #29 by jamshark70

My opinion is, fwiw, that SC’s built in bus routing objects are too low level to be pleasant for normal usage. It’s possible to do mixing with them, but you have to rebuild architecture in various places. And it’s too easy to forget to include the bus and group objects in patterns. Too many ways to get it wrong.

For these reasons, I wrote a MixerChannel class (to avoid repeating architecture, and to support DAW-like signal routing, including sends), and a wrapper class for patterns that “binds” a pattern to resources upon which it depends.

I can give an example later.

hjh

I think I 've go the hang of it
created two synthdefs
one reverb , the other a high pass filter
Each having their own buss
We can automate the bus assignemnent in pbinds

But for some reason it’s not always working the first timeon some instruments , altough it has the correct bus assignment in the pbind and default 0 in Synthdef
What I would really like to know is the only method of turning ON-OFF a synthdef effect is this ?
~filteron=Synth(\HPFILTER,[\in,~filterchannel,\freq,2000,\res,0.5])//
~filteron.free//varaible for turnng OFF the reverb

Just wanted to say thanks guys , you’re help and expertise is highly appreciated .
I am loving the experience of discovering the huge potential of SC ,
The gathered knowledge of the amazing pbinds and actually making stuff made it so much more worth to keep going on.
I shouldn’t have given up on it 2 years ago .
Cheers :clinking_glasses:

1 Like

Here’s a MixerChannel usage (Quarks.install("ddwMixerChannel") if you’ve got git set up already).

(
SynthDef(\Reverberate, {
	|out = 0, mix = 1|
	var signal, processed;
	
	// in MixerChannel, you work within the same bus
	signal = In.ar(out, 2);
	
	// change to stereo reverb
	// also a send FX should always mix 100%
	processed = FreeVerb2.ar(signal[0], signal[1], mix: 1, room: 0.8, damp: 0.2);
	
	// huh, wait, you already mixed?
	// no need to mix again -- this line is unnecessary, deleting
	// processed = (signal+processed) * 0.5;
	
	// in MixerChannel, FX inserts should replace
	ReplaceOut.ar(out, processed);
}).add;

SynthDef(\twoop, {
	|fmamt = 2, modoffset = 24, moatt = 0.001, modrel = 0.500, ampatt = 0.001, amprel = 0.800, pitch = 48, outt = 0.3, pan = 0.2, feed = 0.2, out = 30|
	var mod, modenv, ampenv, carr;
	
	mod = SinOscFB.ar((pitch + modoffset).midicps, feedback:feed) * fmamt;
	modenv = EnvGen.ar(Env.perc(moatt, modrel), doneAction:0);
	ampenv = EnvGen.ar(Env.perc(ampatt, amprel), doneAction:2);
	carr = SinOsc.ar(pitch.midicps, (mod*modenv)) * ampenv * outt;
	carr = Pan2.ar(carr, pos:pan);
	Out.ar(out, carr);
}).add;
)

(
// DAW master channel
~main = MixerChannel(\main, s, 2, 2);

// DAW fx send-return channel
~rvbmc = MixerChannel(\rvb, s, 2, 2, level: 1,
	outbus: ~main,  // channel output routing
	completionFunc: { |chan|
		// 'playfx' fills in 'out' for you
		// because it's boring to have to deal with it
		// explicitly every time
		~rvb = chan.playfx(\Reverberate);
	}
);

// DAW source channel
~seqmc = MixerChannel(\mySequence, s, 2, 2, level: -18.dbamp,
	outbus: ~main,
	completionFunc: { |chan|
		chan.newPostSend(~rvbmc, 0.4);
	};
);
)

MixingBoard(mixers: [~seqmc, ~rvbmc, ~main]);

// hm, actually MixerChannel doesn't do Pdef transparently
// but it's not that bad...
(
Pdef(
	\crt,
	Pbind(
		\instrument,
		\twoop,
		\pitch, Pseq([40, 40, 40, 49, 37, 42, 42, 54], inf)-2,
		\dur, Pseq([1/4, 1/4, 1/2, 1/4], inf),
		\fmamt, Prand([2, 1, 3, 10, 2, 10, 2, 3, 4, 11], inf),
		\modrel, Prand([0.425, 0.525, 0.500, 0.550, 1, 0.625, 0.500, 0.5, 0.8], inf),
		\modoffset, Prand([12, 0, 12, 24], inf),
		\feed, Pwhite(0.3, 0.5, inf),
		\pan, Prand([-0.3, 0, 0.3], inf),
		\amprel, Pwhite (0.08, 0.3, inf),
		\outt, 1,  // level is set in the mixer! can work at FS here
		\out, ~seqmc.inbus,
		\group, ~seqmc.synthgroup
	)
)
)


Pdef(\crt).stop;///////////FM
Pdef(\crt).play;

Or you could have an envelope control the wet-dry mix.

hjh

Oh wait, here’s a better way:

Pdef(\crt).envir_((group: ~seqmc.synthgroup, out: ~seqmc.inbus));

Then just use the Pdef as normal. The bus and group will be picked up from the envir.

hjh

O.k .this is very strange
Just execute this code ,anything except the bus variable
So just reverberate synthdef
Reverb synth
Twoop synthdef
Twoop pbind
and Pdef play
The synth is going straight to bus 0 , not routed to reverb
The reverb takes input from 30 ( nothing on that channel ), yet we still hear reverb ?
Maybe Reverb takes a signal from the ~bus , but we haven’t executed the variable and the synth ittself isn’t using it neither .
And again there is audio on channel 2,3 ??
It’s get’s even weider , when I load instruments in a new tab , there is also reverb applied with just the default 0 output
Just execute the second piece of code , and notice how it’s also reverberated

(
SynthDef(\Reverberate,
	{
		|in=30,out=0,mix=1|
		var signal,processed;
		signal=In.ar(in,2);
		processed=FreeVerb.ar(signal,mix:mix);
		processed=(signal+processed)*0.5;
		Out.ar(out,processed);
}).add
)

~revv=Synth(\Reverberate,[\in,~bus]);
~revv.free

~revv.pause;
~revv.resume

~bus=Bus.audio(s,2)
~bus.free
~bus
(

SynthDef(\twoop,
{
|fmamt=2,modoffset=24,moatt=0.001,modrel=0.500,ampatt=0.001,amprel=0.800,pitch=48,outt=0.3,pan=0.2,feed=0.2,bus=0|
var mod,modenv,ampenv,carr;

		mod=SinOscFB.ar((pitch+modoffset).midicps,feedback:feed)*fmamt;
		modenv=EnvGen.ar(Env.perc(moatt,modrel),doneAction:0);
		ampenv=EnvGen.ar(Env.perc(ampatt,amprel),doneAction:2);
		carr=SinOsc.ar(pitch.midicps,(mod*modenv))*ampenv*outt;
		carr=Pan2.ar(carr,pos:pan);
		Out.ar(0,carr);
}).add
)
/////////
(
Pdef(
	\crt,
	Pbind(
		\instrument,
		\twoop,
		\pitch,Pseq([40,40,40,49,37,42,42,54],inf)-2,
		\dur,Pseq([1/4,1/4,1/2,1/4],inf),
		\fmamt,Prand([2,1,3,10,2,10,2,3,4,11],inf),
		\modrel,Prand([0.425,0.525,0.500,0.550,1,0.625,0.500,0.5,0.8],inf),
		\modoffset,Prand([12,0,12,24],inf),
		\feed,Pwhite(0.3,0.5,inf),
		\pan,Prand([-0.3,0,0.3],inf),
		\amprel,Pwhite (0.08,0.3,inf),

		)
	)
)
//////////

Pdef(\crt).stop;///////////FM

Pdef(\crt).play(t);
t=TempoClock(126/60).permanent_(true);
s.newBusAllocators;
(
SynthDef(\Sqwer,
	{| ampattack =0.001,ampdecay=1,filtattack=0.001,filtdecay=0.500,osc1amp=0.3,osc2amp=0.3,osc3amp=0.3,offset1=0,offset2=0.2,offset3=(-0.2),filterfreq=600,res=1,freq=30,
		filteramount=100,pan=0,vol=0.7,fsh=5,xfade=0|
		var sig,sig1,sig2,sig3,ampenvelope,filterenvelope;
		filterenvelope=EnvGen.ar(Env([0,1,0],[filtattack,filtdecay],[0,-5]),doneAction:0);
		ampenvelope=EnvGen.ar(Env([0,1,0],[ampattack,ampdecay],[0,-5]),doneAction:2);
		sig1=Pulse.ar((freq+offset1).midicps,mul:osc1amp);
		sig2=Pulse.ar((freq+offset2).midicps,mul:osc2amp);
		sig3=Pulse.ar((freq+offset3).midicps,mul:osc3amp);
		sig=sig1+sig2+sig3;
		sig=RLPF.ar(sig,(filterfreq+(filterenvelope*filteramount)).clip(20,20000),rq:res);
		sig=sig*ampenvelope;
		sig=XFade2.ar(sig,FreqShift.ar(sig,fsh),pan:xfade);
		sig=sig*vol;
		sig=Pan2.ar(sig,pos:pan)!2;
		Out.ar(0,sig);
}).add
)

Synth(\Sqwer,[\freq,58,\offset1,-24,\offset2,-0.3,\offset3,0.1,\filterfreq,800,\filteramount,600,\xfade,0,\fsh,3]);


(
Pdef(\bebe,
	Pbind(\instrument,
		\Sqwer,
		\dur,Pseq([1,1,1,1],inf),
		\freq,Pseq([48,50,52,54],inf),
		\offset1,0,
		\offset2,0.2,
		\offset3,-0.1,
		\filterfreq,Prand([200,1000,400,1600,3000,500,120,2000],inf),
		\filteramount,2000,
		\filtdecay,0.300,
		\ampdecay,Pwhite(0.1,0.3,inf),
		\vol,0.3,
		\res,0.5,
		\xfade,-0.3,
		\fsh,Pwhite(2,50,inf),

	)
)
)

Pdef(\bebe).play(t)
Pdef(\bebe).stop(t)

Asked and answered already – these channels come from your soundcard hardware inputs. You cannot turn them off in software. The only thing you could do is to use a USB soundcard with a level trim control and turn it all the way down. Even then it would be nonzero, just very small.

It doesn’t.

When you use ~bus without initializing it, then its value is nil.

So you’re sending an argument list [in: nil].

The server, for good or ill, treats nil as 0 in argument lists. So the server reads in: 0.

Using an uninitialized variable is generally not a good idea; I’m not sure why you are doing it here.

hjh

My audio interface is a Roland integra , audio input is disabled and it is using USB .
When I just execute a synth from scratch from a fresh sc launch ( not using any busses at all ) channels 2 and 3 are Empty and there is NO signal present .
Only when using the ~bus routing ( which I posted in my previous post ) there is a signal on channel 2-3
See screen shot , just executing some Pbinds , everything is as expected on channel 0-1 and nothing more .
O.K so the server threads nil as bus 0 , well that says it all and is Nowhere explained .
The reason why I am not executing the ~bus was to find out whe there was a reverb , not knowing nil was treated as bus

In the screenshot, the scope is starting at bus 2…? So that screenshot shows buses 4 and 5 silent, 2 and 3 with a signal.

My suggestion is to decide on the bus routing you want, and then just do it that way. I had proposed a best practice of: 1. Allocate bus objects for the channels you need. 2. Use these bus objects consistently for the corresponding arg names in synths and patterns. When implemented correctly, this works.

Deviating away from a set of reasonably good practices is quite likely to produce weird behavior. The thing is, it isn’t always necessary to understand exactly why the weird behavior happened. It may be enough to just stick closer to best practices. (Because, the number of permutations is very large, and the number of well-functioning permutations is much much smaller.)

Oh here’s one thing: sig=Pan2.ar(sig,pos:pan)!2; – double-stereoizing a signal – I’m not sure if that would cause bus spillover but this doesn’t look right.

hjh

There is audio on bus 2-3 which are normally preserved for audio inputs , the local host meter also show activity on the input , and I can assure there is nothin plugged into my audio interface inputs .
All I know is that for supercollider to work it needs acces to the microphone (from windows system settings ) otherwise it wouldn’t start up

I didn’t mix two times
The dry signal is var signal which is incoming audio
The first processed lline of code is the dry signal 'sig’going through the reverb(mix set to 1 for 100% wet )
The second line of processed is the dry signal +processed , resulting in DRY+WET

(
SynthDef(\Reverberate,
	{
		|in=30,out=0,mix=1|
		var signal,processed;
		signal=In.ar(in,2);
		processed=FreeVerb.ar(signal,mix:mix);
		processed=(signal+processed)*0.5;
		Out.ar(out,processed);
}).add
)

What’s the best use for dry wet processing
Right now I use bus for the processed signal , by using two out.ar in the synthdefs
one decidated to bus , and the other straight to bus 0 (dry )
In the pbind I can set the bus for the effect ~crazy , while the Synthdef also sends to 0



SynthDef(\twoop,
{
|fmamt=2,modoffset=24,moatt=0.001,modrel=0.500,ampatt=0.001,amprel=0.800,pitch=48,outt=0.3,pan=0.2,feed=0.2,bus|
var mod,modenv,ampenv,carr;

		mod=SinOscFB.ar((pitch+modoffset).midicps,feedback:feed)*fmamt;
		modenv=EnvGen.ar(Env.perc(moatt,modrel),doneAction:0);
		ampenv=EnvGen.ar(Env.perc(ampatt,amprel),doneAction:2);
		carr=SinOsc.ar(pitch.midicps,(mod*modenv))*ampenv*outt;
		carr=Pan2.ar(carr,pos:pan);
		Out.ar(bus,carr);
		Out.ar(0,carr);
}).add
)
/////////
(
Pdef(
	\crt,
	Pbind(
		\instrument,
		\twoop,
		\pitch,Pseq([40,52,40,49,37,42,42,56,54],inf)+7,
		\dur,Pseq([1/3,1/3,1/3],inf),
		\fmamt,Prand([2,1,3,4,2,1.5,2,3,4,6],inf),
		\modrel,Prand([0.425,0.525,0.500,0.550,1,0.625,0.500,0.5,0.8],inf),
		\modoffset,Prand([12,0,12,24],inf),
		\feed,Pwhite(0.3,0.5,inf),
		\pan,Prand([-0.3,0,0.3],inf),
		\amprel,Pwhite (0.08,1.0,inf),
		\bus,~crazy,

		)
	)
)
//////////

Pdef(\crt).stop;///////////FM

Pdef(\crt).play(t);
t=TempoClock(126/60).permanent_(true);
s.newBusAllocators;

(
SynthDef(\ffect,
	{|mdt=0.5,dt=0.1,modamt=1,modspeed=0.1,hpf=500,hpres=0.5,bus|
		var sig,modulator;
		sig=In.ar(bus,2);
		sig=RHPF.ar(sig,hpf,hpres);
		modulator=SinOsc.ar(modspeed,mul:0.5,add:0.0);
		modulator=modulator*modamt;
		sig=DelayC.ar(sig,mdt,dt+modulator);
		Out.ar(0,sig);

}).add
)

~dlay=Synth(\ffect,[\dt,0.001,\bus,~crazy]);
~dlay.free
~dlay.set(\dt,0.01,  \modamt ,0.5,  \modspeed ,0.5,  \hpf,600,  \hpres,0.1);
~dlay.set(\dt,0.01,  \modamt ,0.01, \modspeed ,100,  \hpf,500, \hpres,0.5);
~dlay.set(\dt,0.5,   \modamt ,0.01, \modspeed ,0.1,    \hpf,500, \hpres,0.5);
~dlay.set(\dt,0.01,  \modamt ,0.1,  \modspeed ,4,    \hpf,500, \hpres,0.5);
//////


~crazy=Bus.audio(s,2)
~crazy

I believe it’s as jamshark mentioned in the previous post:

sig=Pan2.ar(sig,pos:pan)!2; in your Sqwer SynthDef that’s spilling over into your busses 2 & 3. If you remove the !2 from that line you should have the signal disappear from there.

You have both dry and wet signal currently being output from the Reverberate Synth. Since this is the case, do you need the original dry signal to have its own output as well?

Do you want to have the reverb as the last part of your signal chain, or as an effect send?

If you just want it as the last part, you don’t need to set up different busses. It’s enough to have everything on bus 0, with Synth(\Reverberate, addAction: \addToTail) when you call the reverb.

Check out Order of execution | SuperCollider 3.12.2 Help, and especially the “Using order of execution to your advantage” section. Some parts about Routines may not be specifcally relevant to what you’re doing right now, but that section is specifically about routing, and routing several things through an effects processor.

If you take this approach, another important thing is which out UGen you use. You’ll likely want to keep using Out.ar as you have been for the main sound sources, but for the reverb, you’ll want to switch to ReplaceOut.ar. ReplaceOut | SuperCollider 3.12.2 Help

The way audio rate Out works (kr is different!) is that it adds its signal to the bus. So for instance if you had 6 instances of \twoop all running at the same time, the Out.ar that’s writing to bus 0 in your example, all 6 of those \twoops would mix together. It’s what you’d expect.

This is an issue for effects though. ReplaceOut doesn’t do this. It replaces all the signals on the bus.

If you want the reverb to act as an effects send, then the routing is going to be similar to what you’re doing now. I believe jamshark went into that approach in one of their earlier posts in this thread. You’ll still likely need ReplaceOut and contend with how out UGens write to busses.

Just want to know if this is normal behaviour
If I free a bus ( example ~this bus ) and instantiate a new one ( same variable used ) , so new outputs are allocated
I also have to re instantiate all the pbinds that use ~this bus argument in order for it to point to the new allocated bus