COCKOS
CONFEDERATED FORUMS
Cockos : REAPER : NINJAM : Forums
Forum Home : Register : FAQ : Members List : Search :
Old 12-10-2009, 01:55 AM   #1
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default 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.
junioreq is offline   Reply With Quote
Old 12-10-2009, 08:13 AM   #2
Mich
Human being with feelings
 
Join Date: May 2009
Posts: 1,265
Default

Quote:
Originally Posted by junioreq View Post
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.
Mich is offline   Reply With Quote
Old 12-10-2009, 11:28 AM   #3
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

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.
junioreq is offline   Reply With Quote
Old 12-11-2009, 05:25 AM   #4
cturner
Human being with feelings
 
cturner's Avatar
 
Join Date: Apr 2009
Location: GWB
Posts: 76
Default

Hi-

I've found these texts to be useful while trying to understand how a limiter works:

The compression tutorial from Max/MSP:
http://vze26m98.net/reaper/OctiMaxCo...onTutorial.pdf

Screenshot of the basic compressor mentioned:
http://vze26m98.net/reaper/basic_compression.png
(I'll put up others if you're interested.)

And Christian Budde's compressor algorithm:
http://www.musicdsp.org/archive.php?classid=4#274
(There's other good stuff on <musicdsp.org>)

HTH, Charles
cturner is offline   Reply With Quote
Old 12-11-2009, 09:56 AM   #5
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

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.
junioreq is offline   Reply With Quote
Old 12-11-2009, 07:36 PM   #6
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

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.
junioreq is offline   Reply With Quote
Old 12-12-2009, 01:20 AM   #7
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

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.
cc_ is offline   Reply With Quote
Old 12-12-2009, 03:13 AM   #8
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

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.
junioreq is offline   Reply With Quote
Old 12-12-2009, 06:32 PM   #9
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

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.
junioreq is offline   Reply With Quote
Old 12-12-2009, 06:42 PM   #10
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

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.
junioreq is offline   Reply With Quote
Old 12-13-2009, 02:10 AM   #11
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

Is "gain" cumulative? might be my big hangup.

~Rob.
junioreq is offline   Reply With Quote
Old 12-13-2009, 03:05 AM   #12
cc_
Human being with feelings
 
Join Date: Mar 2009
Posts: 256
Default

Yes, it is initialised to 1 when the plug is loaded, then each sample it just goes up or down a little bit.
cc_ is offline   Reply With Quote
Old 12-14-2009, 02:04 AM   #13
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

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.
junioreq is offline   Reply With Quote
Old 12-14-2009, 12:36 PM   #14
Fergo
Human being with feelings
 
Fergo's Avatar
 
Join Date: Mar 2009
Location: Curitiba - Brazil
Posts: 371
Default

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
__________________
My new application: Fergo JoystickMIDI - Send commands using your joystick/gamepad
Portfolio: www.fbirck.com
Homepage: www.fergonez.net - Programming stuff

Last edited by Fergo; 12-14-2009 at 02:46 PM.
Fergo is offline   Reply With Quote
Old 12-14-2009, 11:48 PM   #15
junioreq
Human being with feelings
 
junioreq's Avatar
 
Join Date: Aug 2008
Location: Buffalo NY
Posts: 1,091
Default

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.
junioreq is offline   Reply With Quote
Old 12-15-2009, 05:49 PM   #16
Andrew J
Human being with feelings
 
Join Date: Mar 2009
Posts: 11
Default

Are you still initialising gain to 1?
Andrew J is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -7. The time now is 10:23 PM.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.