|
12-10-2009, 01:55 AM
|
#1
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
Simple compressor Problem
I'm trying to port this compressor :
Code:
desc:Compressor
slider1:-10<-120,6,1>Threshold [dB]
slider2:3<1,10,1>Ratio
@init
gain=1;
@slider
thresh = 2 ^ (slider1 / 6) ;
ratio = slider2 ;
attack = 2 ^ ( (2000 / srate) / 6 );
release = 2 ^ ( (60 / srate) / 6 );
@sample
maxsamples = max(abs(spl0),abs(spl1));
maxsamples > thresh ?
(
seekgain = thresh + (maxsamples - thresh) / ratio;
) : (
seekgain = 1
);
gain > seekgain ? (gain /= attack; ):(gain *= release; );
spl0 *= gain;
spl1 *= gain;
To iplug:
Code:
double gain=1;
double seekgain = 0 ;
double thresh = 2 ^ (-8 / 6) ;
double ratio = 5 ;
double attack = 2 ^ ( (2000 / 44100) / 6 );
double release = 2 ^ ( (60 / 44100) / 6 );
double maxsamples = max(abs(*in1),abs(*in2));
if (maxsamples > thresh)
seekgain = thresh + (maxsamples - thresh) / ratio;
else seekgain = 1;
if (gain > seekgain)
gain /= attack;
else gain*=release;
*out1 = *in1 * gain;
*out2 = *in2 * gain;
And it just isn't working. Any ideas? or sample code for a very simple compressor? Honestly, I'm having ahard time understanding how the attack and release are working.... like.. attack is time....and release is time... but its all ending up as "gain"... ??
Last edited by junioreq; 12-10-2009 at 02:09 AM.
|
|
|
12-10-2009, 08:13 AM
|
#2
|
Human being with feelings
Join Date: May 2009
Posts: 1,265
|
Quote:
Originally Posted by junioreq
I'm trying to port this compressor :
Code:
desc:Compressor
slider1:-10<-120,6,1>Threshold [dB]
slider2:3<1,10,1>Ratio
@init
gain=1;
@slider
thresh = 2 ^ (slider1 / 6) ;
ratio = slider2 ;
attack = 2 ^ ( (2000 / srate) / 6 );
release = 2 ^ ( (60 / srate) / 6 );
@sample
maxsamples = max(abs(spl0),abs(spl1));
maxsamples > thresh ?
(
seekgain = thresh + (maxsamples - thresh) / ratio;
) : (
seekgain = 1
);
gain > seekgain ? (gain /= attack; ):(gain *= release; );
spl0 *= gain;
spl1 *= gain;
To iplug:
Code:
double gain=1;
double seekgain = 0 ;
double thresh = 2 ^ (-8 / 6) ;
double ratio = 5 ;
double attack = 2 ^ ( (2000 / 44100) / 6 );
double release = 2 ^ ( (60 / 44100) / 6 );
double maxsamples = max(abs(*in1),abs(*in2));
if (maxsamples > thresh)
seekgain = thresh + (maxsamples - thresh) / ratio;
else seekgain = 1;
if (gain > seekgain)
gain /= attack;
else gain*=release;
*out1 = *in1 * gain;
*out2 = *in2 * gain;
And it just isn't working. Any ideas? or sample code for a very simple compressor? Honestly, I'm having ahard time understanding how the attack and release are working.... like.. attack is time....and release is time... but its all ending up as "gain"... ??
|
JesuSonic and C/C++ have different syntax, so a^b has different semantics. In JS it is power while in C/C++ it is a bitwise exclusive OR. So you want a pow(a,b) in C/C++. Also 2000 is interpreted as an integer in C/C++, so you should make it 2000.0. Also activating a compiler warnings for implicit conversions will warn you about those issues.
Next abs() is/can/mostly is the absoulte value of an integer, so you might want to call fabs() and also keep in mind that not all functions in JS e.g. max(a,b) are defined in C/C++.
As for learning what a compressor does you might find this useful: http://www.kvraudio.com/forum/viewtopic.php?p=3750226 (C++ code is also in that thread).
Regarding why it all ends up in 'gain' that is just how digital audio volume scaling works, simply by multiplying the sample value by a gain factor and 'gain' is itself calculated based on the input sample value the threshold, attack/release coefficient, etc ... I recommend some reading up on DSP and digital audio in general before jumping into cold water.
Hope that helps.
|
|
|
12-10-2009, 11:28 AM
|
#3
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
Unfortunately I can't find anything on the net about the Logic of how this is working.
And quite honestly, i know this is simple code lol, just having a mental block - well actually, never really looked into how in DSP a comp was working.
~Rob.
|
|
|
12-11-2009, 09:56 AM
|
#5
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
Thank you! That cleared a lot of things up, just the one stumbling block i'm having now. Doing dsp compression, it doesnt seem like the attack is actually moving ahead or backwards in time is it? Looks like its just getting added to the signal. ? It looks like to me that attack time will just ADD signal, and release will just subtract. I think where i'm getting lost is the Per sample thing, visually I just cant picture it. lol racking my brain here.
~Rob.
Last edited by junioreq; 12-11-2009 at 10:20 AM.
|
|
|
12-11-2009, 07:36 PM
|
#6
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
Now kinda picking this apart I see this line:
Code:
double maxsamples = max(abs(*in1),abs(*in2));
This looks like full wave rectification - which would be the envelope follower/detector.
Is this block also part of the follower?
Code:
maxsamples > thresh ?
(
seekgain = thresh + (maxsamples - thresh) / ratio;
) : (
seekgain = 1
);
Not really sure why its called "max samples". But lets say that max samples is 10 and the threshold is 5 and ratio is 5:
seekgain = 5 + 5 / 5 which gives seekgain a value of 2. gain = 1 so seekgain is greater so we use "decay" which is like .0015. so that means
gain * release so 1 * .0015
So all we are doing is for this sample just multiplying the input signal by .0015 ..... ????
How does that equate to a "release" ? Time.
|
|
|
12-12-2009, 01:20 AM
|
#7
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
I think the thing you're missing is that the variable called 'release' is not the release time, it is the value the gain should increase by each sample when the signal is under the threshold. In the example above release works out to be 1.00015.
So in the release phase the gain is increased by 1.00015 time each sample time, just what you want for a compressor: gain = gain * release.
|
|
|
12-12-2009, 03:13 AM
|
#8
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
ok, making more sense, now that i know it isnt time. Still gotta visualize how this is working in my head. I cannot use code unless I 80% understand it.
~Rob.
|
|
|
12-12-2009, 06:32 PM
|
#9
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
Well, this is what I came up with:
Code:
double gain=1;
double seekgain = 0 ;
double threshnum = -15/6;
double thresh = pow(2,threshnum) ;
double ratio = 5 ;
double attack = pow(2, .036751 );
double release = pow(2, 122.5);
double maxsamples = abs(*in1),abs(*in2);
if (maxsamples > thresh)
seekgain = thresh + (maxsamples - thresh) / ratio;
else seekgain = 1;
if (gain > seekgain)
gain = gain / attack;
else gain = gain * release;
*out1 = *in1 * gain;
*out2 = *in2 * gain;
and it does nothing but distort with a constant like +235db redline lol.. Uhhh!!
~Rob.
|
|
|
12-12-2009, 06:42 PM
|
#10
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
So, if there are 10 samples that are over the threshold, it will apply GR and as soon as it goes under the threshold? what?
So it looks like the compressor is either on or off correct? It looks like the there will always be the same amount of gain reduction. which is set by the attack/release/thresh. if 1 > seekgain then add the attack value, no matter how many db it is over threshold... is this correct?
~Rob.
Last edited by junioreq; 12-12-2009 at 08:08 PM.
|
|
|
12-13-2009, 02:10 AM
|
#11
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
Is "gain" cumulative? might be my big hangup.
~Rob.
|
|
|
12-13-2009, 03:05 AM
|
#12
|
Human being with feelings
Join Date: Mar 2009
Posts: 256
|
Yes, it is initialised to 1 when the plug is loaded, then each sample it just goes up or down a little bit.
|
|
|
12-14-2009, 02:04 AM
|
#13
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
Still no luck getting this to run in iplug:
Code:
band1gain = -10;
double thresh = pow(2.0, (band1gain/44100.0)/6.0);
double ratio = 6 ;
double attack = pow(2.0, (200.0/44100.0)/6.0);
double release = pow(2.0,((60.0)/44100.0)/6.0);
double seekgain;
double maxsamples = max(fabs(*in1),abs(*in2));
if (maxsamples > thresh)
seekgain = thresh + (maxsamples - thresh) / ratio;
else
seekgain = 1;
if(gain > seekgain)
gain /= attack;
else;
gain *= release;
*out1 = *in1 *gain;
*out2 = *in2 * gain;
BTW: I finally understand how the gain is being reduced etc. But this line has me confused. Is there a REASON that this formula was created, or is it just thrown together to get a value? I guess what i'm saying is, what is the logic of this code. seekgain seems that its the target gain u are after, but WHY is ratio in there?? and why is it devided?:
Code:
seekgain = thresh + (maxsamples - thresh) / ratio;
~Rob.
Last edited by junioreq; 12-14-2009 at 02:31 AM.
|
|
|
12-14-2009, 12:36 PM
|
#14
|
Human being with feelings
Join Date: Mar 2009
Location: Curitiba - Brazil
Posts: 371
|
I've edited a picture originally taken from Wikipedia to try to make the code more clear:
By subtracting the threshold from the maxsamples, you'll have only the part the needs to be compressed (everything above the threshold). Dividing this difference by the ratio (let's suppose it's 2), you'll have the exceeding signal cut in half (the gain reduction in the pic), that added with the threshold will result in the final amplitude of you compressed sample.
The release/attack stuff made that code a little bit hard to "visualize". Most compression codes you find out there compress the signal to the given ration directly, in one single step (no attack time).
Regards,
Fergo
Last edited by Fergo; 12-14-2009 at 02:46 PM.
|
|
|
12-14-2009, 11:48 PM
|
#15
|
Human being with feelings
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
|
Wow! Thank you so much! Actually, the workings of this NOW finally are understood, I thank you so much for your time and effort
Here's the resulting audio though
http://dl.dropbox.com/u/1933049/CompressorFail.mp3
Code:
//double thresh = pow(2.0, (threshold/44100.0)/6.0);
double thresh = .08875;
double attack = 1.005;
double release = 1.0015;
double ratio = 8 ;
//double attack = pow(2.0, (2000.0/44100.0)/6.0);
//double release = pow(2.0,(600.0/44100.0)/6.0);
double maxsamples = max(fabs(*in1),fabs(*in2));
maxsamples += 10e-30f;
if (maxsamples > thresh) {seekgain = thresh + (maxsamples - thresh) / ratio;}
else {seekgain = 1;}
if(gain > seekgain) {gain /= attack;}
else {gain *= release;}
*out1 = *in1 * gain;
*out2 = *in2 * gain;
And just for testing, I am using 441 as my sample rate in reaper. Honestly, this SHOULD work, i don't see any reason for it not too???!!???
~Rob.
|
|
|
12-15-2009, 05:49 PM
|
#16
|
Human being with feelings
Join Date: Mar 2009
Posts: 11
|
Are you still initialising gain to 1?
|
|
|
Thread Tools |
|
Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -7. The time now is 10:23 PM.
|