| Author |
Message |
Dr. Spankenstein
Joined: Mar 03, 2007 Posts: 135 Location: Cambridge
Audio files: 1
|
Posted: Mon Dec 31, 2007 7:52 am Post subject:
How do I obtain final gain level for output? |
 |
|
Is there a method for returning the gain level of the output of ChucK corresponding to all the Ugens that are a connected to the dac?
For example if I were to have...
| Code: |
SinOsc SinOsc => Gain Gain => dac;
0.5 => Gain.gain;
|
....it will be obvious what the gain level is, but how do I get the dac to return this value?
Oh and is this a sensible way to mix various levels?
| Code: |
Gain Gain => NRev r => Echo Echo1 => Echo Echo2 => Gain Mixer => dac;
SinOsc SinOsc => Gain;
//Dry
Gain => Mixer;
//Wet
Echo1 => Mixer;
1.0 => Gain.gain;
0.5 => Mixer.gain; // Gain Of Final Output
|
This way I can adjust the overall gain on the Mixer to affect the final output gain...
...or is there a more sensible way to do it?
Many thanks and a happy new year to all.
Rhys |
|
|
Back to top
|
|
 |
Kassen
Janitor


Joined: Jul 06, 2004 Posts: 5961 Location: The Hague, NL
G2 patch files: 3
|
Posted: Mon Dec 31, 2007 10:16 am Post subject:
|
 |
|
That's a very good question.
First of all; the dac doesn't know about the gains of attached Ugens, it only knows about the values it receives and sums. Because on ChucK's side of the dac the values are double-floats (which can get very large indeed) but on the soundcard side they will eventually need to be normal 16 bit integers (asuming you are using CD quality sound) this process may lead to clipping.
There is good news though; the dac has a .gain function. Since there is only one dac for the whole system adjusting this in one shred will affect the whole system. This is nice, when I'm livecoding I'll often have one MiniAudicle screen open saying just
0.8 => dac.gain;
(of course with different values for .8 it could also be 1.2 or so)
Think of this as a master fader.
Not sure if that answers the question but at least it's a useful trick.
You could also make a shred that sends the dac's output to a envelope follower,
dac => my_ugen;
will work, you see. Based on that envelope follower's output you could also adjust the dac's gain. There's a example envelope-follower by Perry Cook in the examples dir, I think in /deep _________________ while(!machine.crash() ) <<<"all is well">>>; |
|
|
Back to top
|
|
 |
Dr. Spankenstein
Joined: Mar 03, 2007 Posts: 135 Location: Cambridge
Audio files: 1
|
Posted: Fri Jan 04, 2008 6:24 am Post subject:
|
 |
|
Thanks for the clear info.
I've been looking into perhaps limiting the output so that it doesnt clip.
I can see how this could be done with the Dyno Ugen with one shred running but what if I were to have say 3 shreds running at the same time?
Would I have to create some kind of Public Class Dyno Ugen to connect them all to (before the dac) using a similar approach as the "dinky try" code in the examples/class folder?
Or is there an alternative method that is best suited for this kind of problem?
Thanks
Rhys |
|
|
Back to top
|
|
 |
Dr. Spankenstein
Joined: Mar 03, 2007 Posts: 135 Location: Cambridge
Audio files: 1
|
Posted: Fri Jan 04, 2008 7:56 am Post subject:
|
 |
|
Here's a simple non-working summary of what I've been trying to do..
| Code: |
public class Limiter
{
Dyno Limiter;
Limiter.limit();
public void connect(UGen UGen)
{
UGen => Limiter => dac;
}
}
Limiter limiter; // Instantiate Limiter Class
SinOsc SinOsc1;
SinOsc SinOsc2;
10.0 => SinOsc1.gain; // Huge gain to be limited
10.0 => SinOsc2.gain;
SinOsc1 => dac;
SinOsc2 => dac;
440 => SinOsc1.freq;
441 => SinOsc2.freq;
limiter.connect(dac); // Connect the Limiter
10:: second => now;
|
WARNING: My code is completely wrong so there is no limiting of the final signal.
I'm not sure how I could go about placing the limiter before the dac and have the two Oscillators going through that limiter first, with this current setup.
Thanks again,
Rhys |
|
|
Back to top
|
|
 |
Kassen
Janitor


Joined: Jul 06, 2004 Posts: 5961 Location: The Hague, NL
G2 patch files: 3
|
Posted: Fri Jan 04, 2008 8:15 am Post subject:
|
 |
|
I'm no Dyno-expert. To be honest I tend to either use multiple outputs then mix the analogue way (shock! :¬) ) or simply turn the gains down manually...
But when I look at your code I'm fairly certain " Limiter.limit(); " would like some sort of parameter?
A public Dyno sounds to me like a good solution to your issue though the strategy I outlined above with the envelope follower may also have some strengths. It'll be slower in response but could be added to any situation without code changes to the rest. If you don't try it I'll build it myself some time (just not now :¬) ). _________________ while(!machine.crash() ) <<<"all is well">>>; |
|
|
Back to top
|
|
 |
Dr. Spankenstein
Joined: Mar 03, 2007 Posts: 135 Location: Cambridge
Audio files: 1
|
Posted: Fri Jan 04, 2008 10:12 am Post subject:
|
 |
|
| Quote: |
I'm no Dyno-expert
|
That's cool, I'm not hoping to do anything fancy with it but I am confused as to how I would connect a Public UGen at the end of list of UGens as opposed to the beginning?
For Example...
| Code: |
SinOsc SinOsc => "Public UGen";
|
as opposed to..
| Code: |
"Public UGen" => SinOsc SinOsc;
|
I really dont understand the envelope following/mixing techniques in ChucK fully just yet and this is kind of a quick fix until I figure out how to use the method you suggested.
Thanks
Rhys |
|
|
Back to top
|
|
 |
moudi
Joined: Oct 07, 2006 Posts: 58 Location: Bern Switzerland
|
Posted: Fri Jan 04, 2008 11:50 am Post subject:
|
 |
|
the handling with "public ugens" is a bit tricky at the moment.
if you want to use the same ugen from multiple shreds, you need to define a static ugen in your class.
so, declaring a static ugen is no problem in a class, but you can't instantiate it directly (a nice exception appears that this is not supported for now).
therefore you need to instantiate this public ugen within a shred.
this shred must be running the whole time you want to access this ugen, otherwise you'll get a null pointer exception.
(this means the instance of the public ugen gets disposed when the shred which has created the new instance is finished)
a short example could look like this....
please pay attention that this is written on the fly in this message and not tested in chuck!!
| Code: |
//the class
class xy
{
static ugen @ myugen;
}
//the shred
xy myobj;
new ugen @=> myobj.myugen;
myobj.myugen => dac;
//and so on...
|
i hope this helps...
/moudi |
|
|
Back to top
|
|
 |
Dr. Spankenstein
Joined: Mar 03, 2007 Posts: 135 Location: Cambridge
Audio files: 1
|
Posted: Fri Jan 04, 2008 12:41 pm Post subject:
|
 |
|
Very much so!
For those who might be interested, my working code now looks like this:
| Code: |
public class Limiter
{
static UGen @ myugen;
Dyno Limiter @=> myugen;
Limiter.limit();
}
Limiter limiter; // Instantiate Limiter Class
SinOsc SinOsc1;
SinOsc SinOsc2;
10.0 => SinOsc1.gain; // Huge gain to be limited
10.0 => SinOsc2.gain;
limiter.myugen => dac;
SinOsc1 => limiter.myugen;
SinOsc2 => limiter.myugen;
440 => SinOsc1.freq;
441 => SinOsc2.freq;
10:: second => now;
|
Thanks for your help guys and happy new year!
Rhys |
|
|
Back to top
|
|
 |
moudi
Joined: Oct 07, 2006 Posts: 58 Location: Bern Switzerland
|
Posted: Fri Jan 04, 2008 3:02 pm Post subject:
|
 |
|
aahhhm...
in your code here:
| Code: |
public class Limiter
{
static UGen @ myugen;
Dyno Limiter @=> myugen;
Limiter.limit();
}
|
you're declaring a static ugen, but then you assign to this ugen a none static ugen. therefore the ugen (myugen) is no more static and no more accesible for every shred.
i made a test with two different shreds:
1st shred plays a simple sine wave over the myugen.
2nd shred changes the gain of the myugen.
1st shred is not affected by this change.
if you want to connect multiple ugens from different shreds to the same instance of myugen, you need to create a never ending shred as i posted above:
| Code: |
//never ending shred
Limiter l;
new Dyno @=> l.myugen;
l.myugen => dac;
while (true)
{
10::minute => now;
}
//another shred with sound
//note that you don't need to instanciate Limiter again!
SinOsc s => Limiter.myugen;
// and so on
|
jassas
/moudi |
|
|
Back to top
|
|
 |
Dr. Spankenstein
Joined: Mar 03, 2007 Posts: 135 Location: Cambridge
Audio files: 1
|
Posted: Sat Jan 05, 2008 8:15 am Post subject:
|
 |
|
O.K. I think I understand but how would this work with something simple like an integer?
For example if I were to have the Public Class in a seperate Shred on an infinite loop how could I reference it?
Code to be run:
| Code: |
Machine.add( "PublicClass.txt" ) => int cutter2;
// I cant find a way to instantiate the public class or reference it?
// X x;
<<<X>>>;
10::second => now;
|
Public Class looks like:
| Code: |
public class X
{
int A;
public void setA(int value)
{
value => A;
}
public int returnA()
{
return A;
}
while (true)
{
10::minute => now;
}
}
|
I've absolutely no doubt what you are saying is correct but when I try and put it into practice it doesnt work out as planned ?!
I'm guessing this way seperate shreds will be able to communicate with each other via another shred on which the public class runs on a infinite time loop?
Thanks for your time,
Rhys |
|
|
Back to top
|
|
 |
moudi
Joined: Oct 07, 2006 Posts: 58 Location: Bern Switzerland
|
|
|
Back to top
|
|
 |
Dr. Spankenstein
Joined: Mar 03, 2007 Posts: 135 Location: Cambridge
Audio files: 1
|
Posted: Sat Feb 02, 2008 4:43 pm Post subject:
|
 |
|
Thanks for taking the time to upload the Master Gain code moudi.
It has now been implemented into my code and works perfectly. Not only that, I understand how it works!
Rhys |
|
|
Back to top
|
|
 |
|