Audiobus(server,numchann)

This is explained in the other thread, which describes my approach in full – Bus routing: ddwMixerChannel's approach

I took time to write that up because I see you struggling with this for like a week, and I thought it might help to describe a known, working approach from the ground up, which you could take bits of and imitate. It’s right there, waiting for you to take a look…

hjh

A week ? now let’s not exaggerate :slight_smile: ,it’s two days since I started exploring busses
I just thought there was something wrong because of the activity on channel 2-3 , it now works pretty well .
I haven’t even looked into groups etc…
Thanks for the write up ,about the mixer ,much appreciated

Really got a hold of the busses
For me the easiest is just to provide a Xfade ugen in the synthdef too xfade between processed and wet
Here I created 1 comdelay Synthdefeffect
Three variations all having their own bus


//
(
SynthDef(\layla,
	{|mdt=0.250,dt=0.10,dect=0.1,modspeed=0.5,modamt=0.01,hpf=100,in,xfadecontrol=0|
		var sig ,modulator,processed;

		sig=In.ar(in,2);
		modulator=SinOsc.ar(modspeed)*modamt;
		processed=CombC.ar(sig,mdt,dt+modulator,dect);
		processed=HPF.ar(processed,hpf);
		processed=XFade2.ar(processed,sig,xfadecontrol);
		Out.ar(0,processed)
}).add)
///......
~comber=Synth(\layla,[\in,~speak])
~comber.free
(
~comber.set(
	\mdt,0.5,
	\dt,0.01 ,
	\dect,4,
	\modspeed,0.1,
	\modamt,0.001,
	\hpf,40,
	\xfadecontrol,0.9)
)
//...
(
~comber.set(
	\mdt,0.5,
	\dt,0.450 ,
	\dect,44 ,
	\modspeed,0.0,
	\modamt,0.000,
	\hpf,100,
	\xfadecontrol,0.8)
)//  long delay
//

~speak=Bus.audio(s,2)
~speak
//...
~kam=Synth(\layla,[\in,~answer])
(
~kam.set(
	\mdt,0.5,
	\dt,0.1 ,
	\dect,10 ,
	\modspeed,0.1,
	\modamt,0.03,
	\hpf,100,
	\xfadecontrol,0.7)//  long delay
)
~kam.free
~answer=Bus.audio(s,2)
~answer
///.....
~ploink=Synth(\layla,[\in,~phonetic])
~ploink.free
(
~ploink.set(
	\mdt,1,
	\dt,0.5 ,
	\dect,22 ,
	\modspeed,0.000,
	\modamt,0.03,
	\hpf,100,
	\xfadecontrol,0.8)//  long delay
)
~phonetic=Bus.audio(s,2)
/////

Ahhhh hahahaha – you’re quite right. It’s been a very busy thread – I guess to me it felt like a week’s worth of conversation.

Hmmmm… I think the way that you’re doing it, you’re losing some control over the dry/wet ratio.

For a mix parameter to mean what you think it means, you need to keep all the signal processing for the channel on the same bus, and XFade2 + ReplaceOut.

Also, your SynthDef(\layla) makes it impossible to run different effect synths in series.

hjh

But all the dry wet mixing is happening on the same bus
The xfade ugen is in the FX synthdef that processes incoming synths
Setting xfadecontrol to 1 =totally dry , 0=50/50% ,-1=totally wet and it all happens on the same bus .
Ofcourse the bus send it;s all to back to 0

Perhaps you’re mistaken with send efffects for pure wet mixing, in that case you’re right
Either way , the dry-wet mixing in my posted code is all happning on a dedicated bus .

The main synthdef effect has three variation synth effects (not sets ) which all have their dedicated bus
Just load any of your instrument through the posted code and you’ll see

I also suspect that the osciloscope only shows the audio that is going into that bus , not the actual processing of the audio ON that bus
Which I have demonstrated a few posts back
A dry saw wave goes to bus 10 , highpass filter synthdef receives on bus 10 for HIGH PASS filtering
The osciloscope still shows a saw wave with unfiltered harmonics on bus 10

About serial routing , I guess you’re right about that

Here’s the oscilsocope issue clearly demonstrated ( not using ~bus=Bus.audio)
Saw goes to bus 10 , and bus 10 clearly shows an UNFILTERED signal
Hp filter synthdef recieves on bus 10 and sends to bus 20
The filtered signal is showing on bus 20 , so in my opinion this shows that either the filtering is happening on bus 10 but the osciloscope only shows the ingoing signal BEFORE processing .
Or the processing is happening on bus 20 .

Xfade in the set line crossfades between totally unfiltered and filtered , question is on what BUS is the filtering happening ?

(
SynthDef(\filter,
	{
		|in,vol=0.5,cutoff=800,reso=0.5,xfade=(-1)|
		var sig,processed;
		sig=In.ar(in,2);
		processed=RHPF.ar(sig,freq:cutoff,rq:reso);
		processed=XFade2.ar(processed,sig,pan:xfade);
		Out.ar(0,processed)
}).add
)

///////
~filtah=Synth(\filter,[\cutoff,1200,\reso,0.1,\in,10,\xfade,-1])
~filtah.set(\cutoff,1500,\reso,0.2,\xfade,-1)
~filtah.free

/////
(
SynthDef(\saw,
{ |out,freq=60,vol=0.5,att=0.001,dec=0.250|
var sig,env;
sig=SawDPW.ar(freq.midicps)*vol;
env=EnvGen.ar(Env([0,1,0],[0.001,0.250],[0,-5]),doneAction:2);
sig=sig*env!2;
Out.ar(out,sig);
}).add
)
////
~yoda=Synth(\saw)
~yoda.free;
/////
(
Pdef(\seq,
	Pbind(\instrument,
		\saw,
		\dur,0.125,
		\freq,Pseq([48,51,49,55,52],inf),
		\out,10,
	)
)
)
//
Pdef(\seq).play
Pdef(\seq).stop

No, this is due to a mistake in your routing strategy. (Referring to Audiobus(server,numchann) - #45 by gentleclockdivider )

What would be required for bus 10’s contents to be altered?

The only way this can happen is if something writes to that bus.

Now where in your code is anything writing back to bus 10?

That’s right… Nowhere. You’re currently hardcoding a target of 0 (which btw will prevent you later from implementing submixes). So of course bus 10 can show only the dry signal.

This brings us back around to my model, where I had effect synths doing ReplaceOut back onto the same bus. In my approach, the scope would show the final signal in the channel’s bus.

See, I didn’t make that suggestion because “I kinda like it but other ways are just as good.” I do it this way because it really works better – conceptually simpler, modularized, expandable – than other ways. Yeah, I realize I’m tooting my own horn here, but I put a lot of thought into it at the beginning of my time with SC, and it’s paid off massively over the years in terms of not fighting with buses. I’d be very happy if others benefited from that experience.

hjh

ok , I appreciate your mixing model but I don’t want to get ahead of something which I clearly still struggle with
I don’t want to use other people’s implementations (no matter how good they are ) unless I understand it 100% , it would feel like cheating to me .

But at the same time I get the result I expect because I can actually hear what to expect ( dry wet mixing ) , so this means the bus routing is NOT intuitive at all !

Question 1 : So where is the filtering happening then on my previous post ( saw goes to 10 , filtereffect takes from 10 and out to 0)

Question 2 :On which bus does an effectsynthdef reside when it takes input from 10 and routes back to bus 0

Question 3 .: I create two audio busses ~foo=Bus.audio . the host shows info → Bus(audio, 14, 2, localhost) ,
and ~bar =Bus(audio, 16, 2, localhost)
To which bus does the synthdef sends it signal when out=~foo ?
Question 4 Which bus does synthdef EFFECT processes when it takes input from ~foo
Question 5 .Which Bus does synthdef EFFECT sits on when it takes input from ~bar and out is set to 0
Question 6 , When I set a synthdefEFFECT to in ~bar , and out=~bar I hear nothing , why ?

Answer1 = bus 0
Answer2=bus 10
Answer 3=bus 14
Answer4=bus 14
Answer 5=takes from bus 16 and sends to bus 0
Questin 6:because is sends the signal back to it’s receiving bus =16, and stays there

Could you tell me if all these answers are wrong ?

Let me put it in slightly different terms.

As you’re discovering, the field of possible mistakes with bus routing is very large.

My suggestions are intended to reduce the size of the field of possible mistakes.

It’s a valid learning approach, actually: like, if your piano teacher corrects your suboptimal fingering and you ask why??? And you don’t understand why, right now, but months or years later, you think back to it and… ohhhh… there was a reason.

And maybe at that point, you would be able to find an alternative that works just as well. But you don’t have to find that alternative today.

Synths don’t reside on buses.

They read from and write to buses.

Rethink all of the questions from this perspective.

Kinda late here, night night.

hjh

O.k I think I’ve got it
These are two examples of serial effects routing
The first piece of code is simply using output numbers
Synthdef saw goes into filter then in delay ,delay goes to output
you can varry the crossfade
Order of execution
Execution of busses is not necessary ( in this example )
First execute synthdef layla and ~comber=synth
The execute filter synthdef and ~filtah=Synth
This will bring the filter on top of the group , so first filtering then delay
You can alter the filter frequency by executing ~filtah.set second line , or set xfade in the
first ~comber.set line to +1 to let the filtered signal through but unnafected by delay
Lastly execute saw +pbind

~filterbus=Bus.audio(s,2)///bus 4
~filterbus
~delaybus=Bus.audio(s,2)//bus 6
~delaybus
~testbus=Bus.audio(s,2)//bus 8
~testbus

(
SynthDef(\filter,//takes saw input and filters it the sends it to ~delaybus
	{
		|in,out,vol=0.5,cutoff=800,reso=0.5,xfade=(-1)|
		var sig,processed;
		sig=In.ar(in,2);
		processed=RHPF.ar(sig,freq:cutoff,rq:reso);
		processed=XFade2.ar(processed,sig,pan:xfade);
		Out.ar(out,processed)
}).add
)
//...


(
SynthDef(\layla,///takes input from the filtered signal and sends it to bus 0
	{|mdt=0.250,dt=0.10,dect=0.1,modspeed=0.5,modamt=0.01,hpf=100,in,xfadecontrol=0,out|
		var sig ,modulator,processed;

		sig=In.ar(in,2);
		modulator=SinOsc.ar(modspeed)*modamt;
		processed=CombC.ar(sig,mdt,dt+modulator,dect);
		processed=HPF.ar(processed,hpf);
		processed=XFade2.ar(processed,sig,xfadecontrol);
		Out.ar(out,processed)
}).add)
///......

~comber=Synth(\layla,[\in,12,\out,0,\dt,0.222,\dect,2,])///delay
~comber.set(\mdt,0.5,\dt,0.25 ,\dect,4,\modspeed,0.001,\modamt,0.001,\hpf,40,\xfadecontrol,-1)//crossfade between -1 totally wet delay or 1 no delay
~comber.set(\in,12,\out,0)
~comber.set(\in,~delaybus,\out,0)
~comber.set(\in,~testbus,\out,0)
~comber.set(\in,18,\out,0)
~comber.set(\in,20,\out,0)
~comber.free

~comber.set(\mdt,0.5,\dt,0.25 ,\dect,4,\modspeed,0.001,\modamt,0.001,\hpf,40,\xfadecontrol,-1)//crossfade between -1 totally wet delay or 1 no delay

///////
~filtah=Synth(\filter,[\cutoff,2000,\reso,0.1,\in,10,\out,12,\xfade,-1])//crossfade between a filter saw =(-1) or a dry saw =1
~filtah.set(\cutoff,3500,\reso,0.3,\xfade,-1,\out,0,\xfade,-1,\in,10,\out,12)
~filtah.set(\cutoff,15000,\reso,0.3,\xfade,-1,\out,~testbus,\xfade,-1)
~filtah.set(\cutoff,1200,\reso,0.3,\xfade,-1,\out,14,\xfade,-1)
~filtah.set(\cutoff,1200,\reso,0.3,\xfade,-1,\out,16,\xfade,-1)
~filtah.set(\cutoff,1200,\reso,0.3,\xfade,-1,\out,18,\xfade,-1)
~filtah.set(\cutoff,1200,\reso,0.3,\xfade,-1,\out,20,\xfade,-1)
~filtah.free
/////Unfiltered saw goes to filterbus
(///execute last !
Pdef(\seq,
	Pbind(\instrument,
		\saw,
		\dur,Pseq([1/4,1/4,1/2],inf),
		\freq,Pseq([48,50,53,57],inf),
		\dec,Pseq([0.120,0.050,0.200,0.050,0.725,0.125,0.01,0.02,0.02,0.02,0.02,0.5],inf),
		\out,10,
	)
)
)
//
t=TempoClock(96/60).permanent_(true)
Pdef(\seq).play(t)
Pdef(\seq).stop


//////////////


/////
(
SynthDef(\saw,
{ |out,freq=60,vol=0.5,att=0.001,dec=0.0250|
var sig,env;
sig=SawDPW.ar(freq.midicps)*vol;
env=EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]),doneAction:2);
sig=sig*env!2;
Out.ar(out,sig);
}).add
)
////







The second piece of code is identical but using busses , so executing busses first , rest is thesame

~filterbus=Bus.audio(s,2)///bus 4
~filterbus
~delaybus=Bus.audio(s,2)//bus 6
~delaybus
~testbus=Bus.audio(s,2)//bus 8
~testbus

(
SynthDef(\filter,//takes saw input and filters it the sends it to ~delaybus
	{
		|in,out,vol=0.5,cutoff=800,reso=0.5,xfade=(-1)|
		var sig,processed;
		sig=In.ar(in,2);
		processed=RHPF.ar(sig,freq:cutoff,rq:reso);
		processed=XFade2.ar(processed,sig,pan:xfade);
		Out.ar(out,processed)
}).add
)
//...


(
SynthDef(\layla,///takes input from the filtered signal and sends it to bus 0
	{|mdt=0.250,dt=0.10,dect=0.1,modspeed=0.5,modamt=0.01,hpf=100,in,xfadecontrol=0,out|
		var sig ,modulator,processed;

		sig=In.ar(in,2);
		modulator=SinOsc.ar(modspeed)*modamt;
		processed=CombC.ar(sig,mdt,dt+modulator,dect);
		processed=HPF.ar(processed,hpf);
		processed=XFade2.ar(processed,sig,xfadecontrol);
		Out.ar(out,processed)
}).add)
///......

~comber=Synth(\layla,[\in,~delaybus,\out,0,\dt,0.222,\dect,2,])///delay
~comber.set(\in,12,\out,0)
~comber.set(\in,~delaybus,\out,0)
~comber.set(\in,~testbus,\out,0)
~comber.set(\in,18,\out,0)
~comber.set(\in,20,\out,0)
~comber.free

~comber.set(\mdt,0.5,\dt,0.325 ,\dect,4,\modspeed,0.001,\modamt,0.001,\hpf,40,\xfadecontrol,-1)//crossfade between -1 totally wet delay or 1 no delay

///////
~filtah=Synth(\filter,[\cutoff,2000,\reso,0.1,\in,~filterbus,\out,~delaybus,\xfade,-1])//crossfade between a filter saw =(-1) or a dry saw =1
~filtah.set(\cutoff,3500,\reso,0.3,\xfade,-1,\out,0,\xfade,-1,\in,~filterbus,\out,~delaybus)//change frequency
~filtah.set(\cutoff,15000,\reso,0.3,\xfade,-1,\out,~testbus,\xfade,-1)
~filtah.set(\cutoff,1200,\reso,0.3,\xfade,-1,\out,14,\xfade,-1)
~filtah.set(\cutoff,1200,\reso,0.3,\xfade,-1,\out,16,\xfade,-1)
~filtah.set(\cutoff,1200,\reso,0.3,\xfade,-1,\out,18,\xfade,-1)
~filtah.set(\cutoff,1200,\reso,0.3,\xfade,-1,\out,20,\xfade,-1)
~filtah.free
/////Unfiltered saw goes to filterbus
(///execute last !
Pdef(\seq,
	Pbind(\instrument,
		\saw,
		\dur,Pseq([1/4,1/4,1/2],inf),
		\freq,Pseq([48,50,53,57],inf),
		\dec,Pseq([0.120,0.050,0.200,0.050,0.725,0.125,0.01,0.02,0.02,0.02,0.02,0.5],inf),
		\out,~filterbus,
	)
)
)
//
t=TempoClock(96/60).permanent_(true)
Pdef(\seq).play(t)
Pdef(\seq).stop


//////////////


/////
(
SynthDef(\saw,
{ |out,freq=60,vol=0.5,att=0.001,dec=0.0250|
var sig,env;
sig=SawDPW.ar(freq.midicps)*vol;
env=EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]),doneAction:2);
sig=sig*env!2;
Out.ar(out,sig);
}).add
)
////




I know why it has been such a hassle because I have totally not been paying attention to the order of execution with serial routing ( previous code has comments for that reason )
Sometimes it was just silent other times it was not , absolutely crucial to first execute the effect that has to be last (bottom) in the chain .
I know , essential stuff …order of execution and groups is up next :slight_smile:

Last question then I am done
I have no problem with serial routing when using multiple busses like this
A test signal goes into ringmod effect , it’s then filtered and finally reverberated which goes to bus 0
Just simple in out buss , all we got to do is make sure is execution order
Idiot proof, but it works

~tester=Synth(\test,[\out,~ringbus])
~ringer=Synth(\ringmod,[\freq,4,\amt,1,\in,~ringbus,\out,~filterbus,\xfade,-1])
~filtah=Synth(\filter,[\cutoff,2000,\reso,0.1,\xfade,-1,\in,~filterbus,\out,~revbus])
~reverberate=Synth(\reverb,[\mix,0,\room,0.5,\in,~revbus,\out,0])

Now , is it possible to have serial effects routing on the same bus , adhering the order of execution
So the block graph looks like
1

All effects are set to ~awesome bus , reverberate has 0 as output
So far I haven’t managed to get the same result as with multiple busses
Just a simple yes or no is enough , I’ll investigate further

`~tester=Synth(\test,[\out,~awesomebus])
~ringer=Synth(\ringmod,[\freq,4,\amt,1,\in,~awesomebus,\out,~awesomebus,\xfade,-1])
~filtah=Synth(\filter,[\cutoff,2000,\reso,0.1,\in,10,\out,12,\xfade,-1,\in,~awesomebus,\out,~awesomebus])
~reverberate=Synth(\reverb,[\mix,0,\room,0.5,\in,~awesomebus,\out,0])`

Order of execution still applies when using separate busses. If you execute the synths in the wrong order in the first example things will still not work.

The good way to handle this is to provide an argument for the addAction key when declaring your Synths, or using one of the addAction methods. I like addAfter for serial routing

~tester=Synth(\test, [\out,~ringbus])
~ringer=Synth.addAfter(~tester, \ringmod,[\freq,4,\amt,1,\in,~ringbus,\out,~filterbus,\xfade,-1])
~filtah=Synth.addAfter(~ringer, \filter,[\cutoff,2000,\reso,0.1,\xfade,-1,\in,~filterbus,\out,~revbus])
~reverberate=Synth.addAfter(~filtah, \reverb,[\mix,0,\room,0.5,\in,~revbus,\out,0])
 

You can use the same technique when routing to busses, or not. This begins to guarantee correct order of execution.

I think you might be getting results when using the same bus for everything, versus patching from one module’s output bus to another’s input bus if you’re not using ReplaceOut.

Try your series patch, but swap all the Outs for ReplaceOut (except for your \test Synth). I think it should sound the same as your first example

Yes , I am now well aware that order of execution matters with separate busses, see yesterday’s post
Thanks

Time machine:

SynthDef(\myFx, { |bus, mix|
    var sig = In.ar(bus, 2);
    var wet = ... your fx processing...;
    ReplaceOut.ar(bus, XFade2.ar(sig, wet, mix * 2 - 1));
}).add;

I usually start with a template like this.

I don’t get why there is the same bus arg for the Replace.out

… and now you understand.

Anyway ReplaceOut onto the same bus.

hjh

Jamshark ,tresholdpeople , thanks a million for having so much patience
The replace out was indeed the missing piece of the puzzle when using one bus for serial routing , it all falls into place now .
SO relieved I finally got it

Hmm , this brings u another issue
The replace out is working wonderfull with just one bus
I’ve routed a couple of instrument into 1 bus and processed them with a bunch off effects ., works a treat !
But , instruments that have absolutely no relation to the busses and which are routed straight to bus 0 just wont play
Ctrl/command . to free the server and then they will play
This is bizarre , seems that replace out somehow affects other instruments which are routed atraight to out with the regular Out.ar
What you see in the screenshot are the three effects on the same bus , I suspect the last effect Layla is ( which is also set to replace out and is going to output 0 ) is preventing the kick instrument ( no relation to the busses whatsoever ) to come through at all
1

Will try to post a simple example

EDIT , found it , the last effect in the chain should not be set to replace out ( the one that is going to 0)
I wonder why the replace out Layal effect prevents another signal ( which is not on the bus ) from going to output 0.
It seems it does not just replace the signals on the bus .

Actually my mixer design has an even simpler solution.

  • Effect synths only do effects – ReplaceOut to the same bus. Every effect can be written this way.
  • Fader and routing synths only do volume-panning-routing, using Out to a different bus. (I also ReplaceOut to the same bus here as well, for the sake of post-fader sends. You might not need that now, but I could make a prediction that two days later, you’ll be asking “now how can I get the post-fader signal”…)

You don’t know how many effect inserts you’ll have on a given channel.

So it does not make sense to have one style of effect SynthDef for most of them, and a different style of SynthDef for the last effect in the chain.

It does make sense to separate routing from effects.

Let me observe a pattern here. I made a suggestion, you rejected it and then came back around to need exactly the suggestion I made in the first place. Which is fine, except that I’m then explaining the same things three or four times. (I think I’m going to have to stop doing that.) Thus another reasonable way to proceed would be for you to try, just once, to follow exactly the design in the other thread, just to see what it’s like. Then you’re in a position to pick and choose what you like in it.

hjh

I did not reject your suggestion at all ( strange why you feel that way ) ,
I am sure your mixer works flawlesly and would probably save me a lot of headaches but what is the use in using something if I don’t yet understand it all ?
Failure is the best learning ,I have yet to encounter the many obstacles that you have conquered and ultimately lead to designing your own mixer .
So what’s wrong with another newbie to actually learn what you have learned (ages ago ) ?
Call me old skool but I really want to learn this stuff , the knowledge on this forum is crucial in that journey but just saying I rejeced your offer is kinda pointless and not true at all

Ok, “rejected” is too strong a word – it sounded a bit to me like “why would you do it that way?” followed by a search for every other way to do it.

I agree that failure is a part of learning, but I don’t entirely agree that there is no benefit in following a model before you fully understand it.

Bach copied scores from the Italian masters of his day as a way to learn their style.

The act of reproducing aspects of the structure is not passive. You might find that this helps you to understand how the components work.

It’s worth a try – just once. Try it once. Then you can try variations as you like.

hjh