I want to tackle internal routings but first I want to make sure I got things correct
As always , folliwing Eli’s fabulous tuts
I get 1024 , while in Ei’s example he gets 128 .
When it comes to inputs I get only 2 ,
More Issues ,
Why is= the declaration of the outputbus not recognized in the arguments ?
It appears at channel 0 while it should appear at channel 8
I am aware I should not hear anything , but the scope should show a signal at channel 8 while it doesn’t
(
SynthDef(\Sinner,
{
arg frequ=110,amp=0.5,att = 0.001 ,dec = 0.125,pan=0,out=8;
var sig;
sig=SinOsc.ar(frequ,mul:amp);
sig=sig*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]),doneAction:2);
sig=Pan2.ar(sig,pos:pan);
Out.ar(out,sig);
}).add
)
~ward=Synth(\Sinner,[\frequency,200,\dec,5]);
(
Pdef(\test,
Pbind(\instrument,
\Sinner,
\dur,Pseq([0.5,0.25,0.5,0.25,0.5,0.25,0.5,Pwhite(0.01,0.125,16)],inf),
\dec,Pwhite(0.5,3,inf),
\frequ,Pseq([100,200,300,400,500,600,700,800,900,Pwhite(1000,2000,64)],inf),
\pan,Pwhite(-0.7,0.7,inf),
)
)
)
Pdef(\test).play
Pdef(\test).stop
But , if I type bus 8 directly in the Outgen then the scope shows it correctly
(
SynthDef(\Sinner,
{
arg frequ=110,amp=0.5,att = 0.001 ,dec = 0.125,pan=0,out=8;
var sig;
sig=SinOsc.ar(frequ,mul:amp);
sig=sig*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]),doneAction:2);
sig=Pan2.ar(sig,pos:pan);
Out.ar(8,sig);
}).add
)
~ward=Synth(\Sinner,[\frequency,200,\dec,5]);
(
Pdef(\test,
Pbind(\instrument,
\Sinner,
\dur,Pseq([0.5,0.25,0.5,0.25,0.5,0.25,0.5,Pwhite(0.01,0.125,16)],inf),
\dec,Pwhite(0.5,3,inf),
\frequ,Pseq([100,200,300,400,500,600,700,800,900,Pwhite(1000,2000,64)],inf),
\pan,Pwhite(-0.7,0.7,inf),
)
)
)
Pdef(\test).play
Pdef(\test).stop
If I rename the out arg to any other name , then it works , in this case the name is whynot
(
SynthDef(\Sinner,
{
arg frequ=110,amp=0.5,att = 0.001 ,dec = 0.125,pan=0,whynot=31;
var sig;
sig=SinOsc.ar(frequ,mul:amp);
sig=sig*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]),doneAction:2);
sig=Pan2.ar(sig,pos:pan);
Out.ar(whynot,sig);
}).add
)
~ward=Synth(\Sinner,[\frequency,200,\dec,5]);
(
Pdef(\test,
Pbind(\instrument,
\Sinner,
\dur,Pseq([0.5,0.25,0.5,0.25,0.5,0.25,0.5,Pwhite(0.01,0.125,16)],inf),
\dec,Pwhite(0.5,3,inf),
\frequ,Pseq([100,200,300,400,500,600,700,800,900,Pwhite(1000,2000,64)],inf),
\pan,Pwhite(-0.7,0.7,inf),
)
)
)
Pdef(\test).play
Pdef(\test).stop
Why is the reverb not sounding ?
It takes the input from bus 31 and should output a processed sound at bus 0
(
SynthDef(\Sinner,
{
arg frequ=110,amp=0.5,att = 0.001 ,dec = 0.125,pan=0,opb=31;
var sig;
sig=SinOsc.ar(frequ,mul:amp);
sig=sig*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]),doneAction:2);
sig=Pan2.ar(sig,pos:pan);
Out.ar(opb,sig);
}).add
)
/////
(
SynthDef.new(\reverb,{
arg in=31,out=0;
var sig;
sig=In.ar(in,1);
sig=FreeVerb.ar(sig,0.5,0.8,0.2)!2;
Out.ar(out,sig);
}).add
)
//////////////////
(
Pdef(\test,
Pbind(\instrument,
\Sinner,
\dur,Pseq([0.5,0.25,0.5,0.25,0.5,0.25,0.5,Pwhite(0.01,0.125,16)],inf),
\dec,Pwhite(0.5,3,inf),
\frequ,Pseq([100,200,300,400,500,600,700,800,900,Pwhite(1000,2000,64)],inf),
\pan,Pwhite(-0.7,0.7,inf),
)
)
)
Pdef(\test).play
Pdef(\test).stop
Weird , why the out argument refuses to accept it’s declaration when it’s named out
Is that name reserved ,how come it accepts decalration when it’s renamed ?
Still , the routing into a SynthDef is still not working
You need to include \out in the Pbind as well.
The default event defines default values for some standard parameter names. The default \out is 0. This is a property of the event. Values in the event take precedence over values in the SynthDef.
Best practice is that the note player should be responsible for assigning the output bus, and not the SynthDef.
hjh
May be different in different environments. Also at some point, the default number of buses changed.
hjh
Still no reverb
(
SynthDef(\Sinner,
{
arg frequ=110,amp=0.5,att = 0.001 ,dec = 0.125,pan=0,out=128;
var sig;
sig=SinOsc.ar(frequ,mul:amp);
sig=sig*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]),doneAction:2);
sig=Pan2.ar(sig,pos:pan);
Out.ar(out,sig);
}).add
)
/////
(
SynthDef.new(\reverb,
{
arg indio=128,out=0;
var sig;
sig=In.ar(128,1);
sig=FreeVerb.ar(sig,0.5,0.8,0.2)!2;
Out.ar(0,sig);
}).add
)
//////////////////
(
Pdef(\test,
Pbind(\instrument,
\Sinner,
\dur,Pseq([0.5,0.25,0.5,0.25,0.5,0.25,0.5,Pwhite(0.01,0.125,16)],inf),
\dec,Pwhite(0.5,3,inf),
\frequ,Pseq([100,200,300,400,500,600,700,800,900,Pwhite(1000,2000,64)],inf),
\pan,Pwhite(-0.7,0.7,inf),
\out,128,
)
)
)
Pdef(\test).play
Pdef(\test).stop
Edit , I need to trigger the reverb
(
SynthDef(\Sinner,
{
arg frequ=110,amp=0.5,att = 0.001 ,dec = 0.125,pan=0,out=128;
var sig;
sig=SinOsc.ar(frequ,mul:amp);
sig=sig*EnvGen.ar(Env([0,1,0],[att,dec],[0,-5]),doneAction:2);
sig=Pan2.ar(sig,pos:pan);
Out.ar(out,sig);
}).add
)
/////
(
SynthDef.new(\reverb,
{
arg indio=128,out=0;
var sig;
sig=In.ar(128,1);
sig=FreeVerb.ar(sig,0.5,0.8,0.2)!2;
Out.ar(0,sig);
}).add
)
//////////////////
Synth(\reverb);
(
Pdef(\test,
Pbind(\instrument,
\Sinner,
\dur,Pseq([0.5,0.25,0.5,0.25,0.5,0.25,0.5,Pwhite(0.01,0.125,16)],inf),
\dec,Pwhite(0.5,3,inf),
\frequ,Pseq([100,200,300,400,500,600,700,800,900,Pwhite(1000,2000,64)],inf),
\pan,Pwhite(-0.7,0.7,inf),
\out,128,
)
)
)
Pdef(\test).play
Pdef(\test).stop
And again not working
This means when using out as argument you can’t choose another outputbus ?
It always routes to bus zero when named ‘out’
(
{
arg out=31;
var freq,trig,sig;
freq=LFNoise0.kr(3).exprange(300,1200).round(300);
sig=SinOsc.ar(freq)*0.25;
trig=Dust.kr(2);
sig=sig*EnvGen.kr(Env.perc(0.01,0.2),trig);
Out.ar(out,sig);
}.play
)
Excute reverb and then the bleep , you won’t hear reverb
Now , change the bleepinstrument out argument on the last line from ‘out’ to 32 , or rename out to ‘trout’ and you will hear a reverb !
Why is that ?
//bleepsintrument
(
{
arg out=32;
var freq,trig,sig;
freq=LFNoise0.kr(20).exprange(300,1200).round(300);
sig=SinOsc.ar(freq)*0.25;
trig=Dust.kr(2);
sig=sig*EnvGen.kr(Env.perc(0.01,0.50),trig)!2;
Out.ar(out,sig);//////////////change out to 32
}.play
)
////REverb
(
{
arg in=32,out=0;
var sig;
sig=In.ar(in,1);
sig=FreeVerb.ar(sig,0.8,0.8,0.2)!2;
Out.ar(out,sig);
}.play
)
///
the Pbind is setting the out control on the synths it generates! As Jamshark explained.
Pbind uses a default Event which has \out set to 0.
so you need to add \out,32 to the Pbind if you want the resulting synths to send to that bus
In my last example I am not using Pbinds , out arguments always defaults to zero while they have been assigned 32 ,
I either have to type in 32 in the Out.ar OR rename the out arg to a different name , then it will adopt the assigned value
Please , See last code
First screenshot shows out 0 while arg out = 32 in arg. declaration , so this has to be wrong , right ?
The last two screenshots show a correct output since I have either typed in 32 manually or renamed the out argument
No one ?
Please see last screenhots
I’m not sure specifically the mechanics of what’s causing it, but it seems that even with the play
method, out
is a reserved key, so it gets set. The workaround for this is either to use a diff arg name, which is probably not the best way, or to set out
explicitly when play
ing the synth:
(
{
arg out=32;
var freq,trig,sig;
freq=LFNoise0.kr(20).exprange(300,1200).round(300);
sig=SinOsc.ar(freq)*0.25;
trig=Dust.kr(2);
sig=sig*EnvGen.kr(Env.perc(0.01,0.50),trig)!2;
Out.ar(out,sig);//////////////change out to 32
}.play(args: [out: 32])
)
Just note that in your example above, even with the routing working as you intend, you’ll need to evaluate the reverb first, unless you provide extra arguments in either the reverb’s or bleeps’s play
method. This is because of how nodes are arranged by default on the server: Order of execution | SuperCollider 3.12.2 Help
Actually, I just saw why it’s playing by default on zero.
It’s because the play
method for the Function
class specifies the outbus as 0 by default.
(
a = {
arg out=32;
var freq,trig,sig;
freq=LFNoise0.kr(20).exprange(300,1200).round(300);
sig=SinOsc.ar(freq)*0.25;
trig=Dust.kr(2);
sig=sig*EnvGen.kr(Env.perc(0.01,0.50),trig)!2;
Out.ar(out,sig);//////////////change out to 32
}
)
a.class // -> Function
When creating Synths like this, you actually don’t need to explicitly provide an Out
UGen…
// still works:
(
{
arg out=32;
var freq,trig,sig;
freq=LFNoise0.kr(20).exprange(300,1200).round(300);
sig=SinOsc.ar(freq)*0.25;
trig=Dust.kr(2);
sig=sig*EnvGen.kr(Env.perc(0.01,0.50),trig)!2;
// Out.ar(out,sig);//////////////change out to 32
}.play
)
Under the hood, SuperCollider adds this UGen for you, taking the last line of your code, and wrapping it in an Out.ar(out, _your_last_line_of_code_)
.
If you explicitly provide the same thing, as you’re doing in your example, and if you use the same argument key: out
, the Function’s mechanism overwrites whatever value unless you explicitly set it.
That’s why using a different argument name in its place achieves your desired result, it blocks the language from overwriting the value for out.
So the other way to do this:
(
{
arg out=32;
var freq,trig,sig;
freq=LFNoise0.kr(20).exprange(300,1200).round(300);
sig=SinOsc.ar(freq)*0.25;
trig=Dust.kr(2);
sig=sig*EnvGen.kr(Env.perc(0.01,0.50),trig)!2;
Out.ar(out,sig);//////////////change out to 32
}.play(outbus: 32)
)
Where outbus is what sets the value of out.
This is achieving a similar thing as the example in my previous post.
Check out the help page for Function, specifically looking at the play
method.
Since the play
method can work differently for different classes, it’s important to know which class your object belongs to. Hence me trying a.class
.
Yes , I know about evaluating reverb first
Interesting find ., let’s see how it behaves with synthdefs
All I want to achieve is some internal routing , dry wet settings and then call it a day
When you call play
on a Synth or SynthDef, it uses a different play method, so outbus
will not work, but your technique of providing the out
arg a default value will, no additional steps required.
(
SynthDef(\bleeps, {
arg out=32;
var freq,trig,sig;
freq=LFNoise0.kr(20).exprange(300,1200).round(300);
sig=SinOsc.ar(freq)*0.25;
trig=Dust.kr(2);
sig=sig*EnvGen.kr(Env.perc(0.01,0.50),trig)!2;
Out.ar(out.poll,sig);//////////////change out to 32
}).add
)
a = Synth(\bleeps)
// UGen(OutputProxy): 32
This is all due to the fundamental differences between a Function and SynthDef, and how they handle play
ing on the server.
As an aside, you can also do:
(
SynthDef(\bleeps, {
arg out=32;
var freq,trig,sig;
freq=LFNoise0.kr(20).exprange(300,1200).round(300);
sig=SinOsc.ar(freq)*0.25;
trig=Dust.kr(2);
sig=sig*EnvGen.kr(Env.perc(0.01,0.50),trig)!2;
Out.ar(out.poll,sig);//////////////change out to 32
}).play
)
Which is is like doing both add
and play
all in one step.
Got rid of the reverb , just kep the frequency shifter
Tied to Pdef, pbind sequencing the frequency shifter’s frequencies , but the sound keeps adding up,
Voices are not released for the effect , as expected since the effect has no done action .
But since it’s a stereo effect how come voices are added when sequenced from Pbind?
So another problem to tackle ,
(
SynthDef(\twoop,
{
|fmamt=1,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,output=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(bus:output,carr);
}).add
);
/////////
(
SynthDef(\revv,
{ | inbus=20,ff=50|
var in;
in=In.ar(inbus,2);
in=FreqShift.ar(in,ff);
Out.ar(0,in);
}
).add
)
//////////////
~reverb=Synth(\revv);
~reverb.free;
(
Pdef(\shifter,
Pbind(\instrument,
\revv,
\dur,4,
\inbus,20,
\ff,Pseq([1000,50],inf),
)
))
(
Pdef(
\crt,
Pbind(
\instrument,
\twoop,
\pitch,Pseq([40,42,47,[45,52],37,34,31,28,40,42,47,[45,52],47,42,40,28,31,34,37],inf),
\dur,Pseq([1/2,1,1/2,1/4,1/4,1/4,1/4],inf),
\fmamt,Prand([2,1,3,4],inf),
\modrel,Prand([0.425,0.525,0.500,0.550,1,0.625,0.500,0.5,2.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.5,inf),
\output,20,
)
)
)
//////////
;
////////////////////
Pdef(\shifter).stop;///////////FM
Pdef(\shifter).play(t);
Pdef(\crt).stop;///////////FM
Pdef(\crt).play(t);
t=TempoClock(175/60).permanent_(true);
No, of course it does not. Synth arguments would be pointless if you can’t set them.
The trouble is that you didn’t set it.
To cut through some of the confusion: In my opinion (with 20 years behind it), the best practice for bus routing is:
- SynthDef: Name the output bus argument
out
. Function:play: Do not add your ownout
. - Then, whatever is playing the synth is responsible for supplying the correct value for
out
.
The longer I do this, the more I find that I prefer simple rules with fewer exceptions. This is as clear and as exception-free as I can make it: when bus routing is important, always supply the bus number at the time of playing.
Do not write the desired bus as a SynthDef argument default and assume that this will always take effect. As you found, it doesn’t always work. That is, it’s not reliable. Because it’s not reliable, it’s not a good approach. Now, you could spend the next day trying to puzzle out why it isn’t reliable, or fighting with it to try to make it reliable, but the end result will be the same – you will just find that it isn’t reliable and that it will work better if you go with the above principle.
Another source of confusion is that { }.play
manages its own output-bus argument and Out
UGen. So you should not create these in this context. You do need them for SynthDef. You don’t need them for Function:play.
s.boot;
~rvbBus = Bus.audio(s, 2);
// Function:play, no out = YES
// note that the `play` method has an 'outbus' argument -- USE IT
// "but the function has no outbus" -- `play` created a control input for it, invisibly, don't worry about it
(
~rvb = { |inbus|
var sig = In.ar(inbus, 2);
FreeVerb2.ar(sig[0], sig[1], 0.4, 0.9, 0.2)
}.play(outbus: 0, args: [inbus: ~rvbBus]);
)
// SynthDef with out = YES
// note that I have written NO DEFAULT for out here
(
SynthDef(\boop, { |out, freq = 440, time = 0.1, amp = 0.1|
var sig = SinOsc.ar(freq);
var eg = EnvGen.ar(Env.perc(0.001, time), doneAction: 2);
Out.ar(out, (sig * (eg * amp)).dup);
}).add;
)
// ... because the bus number will be given HERE
Synth(\boop, args: [out: ~rvbBus]);
// ... or here
(
p = Pbind(
\instrument, \boop,
\freq, Pexprand(200, 800, inf),
\dur, Pexprand(0.05, 0.8, inf),
\out, ~rvbBus
).play;
)
p.stop;
hjh
“another problem to tackle” but you already know the answer to this one – if you’re going to Pbind-sequence the effect synths, then the effect needs an envelope with a doneAction. (So it isn’t a very big problem, is it?)
It’s true that there aren’t many examples in the help of fx synths being sequenced, but sequencing doesn’t work differently just because it’s an fx synthdef. You use the same rule that you’d use with other types of SynthDefs!
(
SynthDef(\revv, { |inbus = 20, ff = 50, gate = 1|
var in;
var eg = EnvGen.kr(Env.asr(0.01, 1, 0.01), gate, doneAction: 2);
in = In.ar(inbus, 2);
in = FreqShift.ar(in, ff);
Out.ar(0, in * eg);
}).add
)
//////////////
~reverb=Synth(\revv);
~reverb.free;
(
Pdef(\shifter,
Pbind(\instrument,
\revv,
\dur, 4,
\legato, 1,
\inbus, 20,
\ff, Pseq([1000, 50], inf)
)
).play
)
No pileup.
The next thing you’re going to run into is that source and fx synths will be interspersed this way. So it’s better to be explicit about order:
(
Pdef(\shifter,
Pbind(\instrument,
\revv,
\dur, 4,
\legato, 1,
\inbus, 20,
\ff, Pseq([1000, 50], inf),
\addAction, \addToTail // fx at the end
)
).play
)
hjh
So what would be the best way to keep an effect constantly active after creating the synthdef (with add method at the end )
Would it be like this , lke triggering an instance and then freeing it for bypassing the effect ?
~thiseffect=Synth(\reverbah).
~thiseffect.free