update: ChunkWare Simple Source - now with limiter

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

i have just uploaded a new version of the Simple series, along with an updated EnvelopeDetector. the new files are now in 1 zip file, which can be downloaded here:

DOWNLOAD CHUNKWARE SIMPLE SOURCE

Updates:

Introducing: SimpleLimit - a simple, look-ahead peak limiter in a prêt à porter C++ class. in answer to the multiple requests for look-ahead limiter code on this forum, i have taken time to thoroughly document the runtime process. please give this a good look first if you have any questions on how this code works. also note that this is just my humble interpretation of how a simple -- yet effective -- look-ahead limiter might operate. there are other equally, if not more, effective methods that some might prefer to this method. i like this code because it is fairly cheap, works on a "per-sample" basis, and doesn't require too much buffering. i have gotten decent results with this code and have even used a variation on it in the Vanilla Compressor's output limiter.

PLEASE NOTE: as with any look-ahead device, some buffering is necessary, thereby introducing latency in the output. in the case of SimpleLimit, this latency is equal to the length of the attack time constant. the exact sample value can be obtained by calling getLatency(), which returns an unsigned int. it is recommended that the attack time remain fixed, not user-adjustable, as changing the attack time also changes the latency. there are ways of avoiding this problem by using multiple buffers for both sidechain and output, but i didn't want to complicate things too much.

SimpleComp:
- minor fixes

SimpleGate:
- minor fixes

EnvelopeDetector:
- member variables now have protected access (as opposed to private), so as to facilitate the derived class, FastEnvelope, in SimpleLimit. i normally avoid protected members, in favor of private data and public methods. but in this case, it just seemed like the simplest, most straight-forward option.

i didn't have much time to thoroughly test the new class, so i hope there aren't any glaring bugs. i also hope that this is useful to some of you who have been asking about this stuff. sorry about the website and the lack of links/info. i'm working on that ... sort of... ;)

enjoy!
== chunk
Last edited by citizenchunk on Tue Feb 14, 2006 4:46 am, edited 1 time in total.

Post

Hi, thanx for the limiter code:), just have a few questions. How do you set up the buffers, my question really is, can you provide an example of how to actually use this class. Thanx

Post

timjay wrote:Hi, thanx for the limiter code:), just have a few questions. How do you set up the buffers, my question really is, can you provide an example of how to actually use this class. Thanx
you don't need to even think about the buffers. just set the threshold, attack, release, and GO! :) it's that simple. but if you really must see some code...

Code: Select all

// in plugin class definition...
private:
   SimpleLimit  limiter_;   // use as object for encapsulation

// in constructor...
limiter_.setThresh( -0.1 );   // i like to set it to just under 0dB
limiter_.setAttack( 1.0 );     // 1ms seems like a good look-ahead to me
limiter_.setRelease( 10.0 ); // 10ms release is good
setInitialDelay( limiter_.getLatency() );   // don't forget to update init delay

// in process() ...
double in1, in2;
limiter_.process( in1, in2 );   // runtime function

and that's it. no buffers to deal with at all. you're on your own from here...

== chunk

Post

Thanks again. :wink:

Post

Tried Compiling the the classes with VC++, get the following errors?

Code: Select all

C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleCompProcess.inl(45) : error C2039: 'max' : is not a member of 'std'
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleCompProcess.inl(45) : error C2065: 'max' : undeclared identifier
SimpleGate.cpp
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleCompProcess.inl(45) : error C2039: 'max' : is not a member of 'std'
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleCompProcess.inl(45) : error C2065: 'max' : undeclared identifier
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleGateProcess.inl(47) : error C2039: 'max' : is not a member of 'std'
SimpleLimit.cpp
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleCompProcess.inl(45) : error C2039: 'max' : is not a member of 'std'
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleCompProcess.inl(45) : error C2065: 'max' : undeclared identifier
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleLimit.h(102) : error C2258: illegal pure syntax, must be '= 0'
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleLimit.h(102) : error C2252: 'BUFFER_SIZE' : pure specifier can only be specified for functions
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleLimitProcess.inl(43) : error C2039: 'max' : is not a member of 'std'
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleLimit.cpp(42) : error C2065: 'BUFFER_SIZE' : undeclared identifier
Complaining about max? When I comment out all the includes for the inline processes from the header files I only get 3 errors as follows:

Code: Select all

C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleLimit.h(102) : error C2258: illegal pure syntax, must be '= 0'
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleLimit.h(102) : error C2252: 'BUFFER_SIZE' : pure specifier can only be specified for functions
C:\PRODUCTION2\SimpleLimiter\simpleSource\SimpleLimit.cpp(42) : error C2065: 'BUFFER_SIZE' : undeclared identifier

Post

ugh... the max() problem is a stupid Visual Studio problem that i've faced in the past. MS has defined their own min/max macros, which conflict with the STL functions in <algorithm>. supposedly, the way to fix this is to #define NOMINMAX before including algorithm, which i've done in the EnvelopeDetector.h header. but for some reason, i've found it doesn't always work with certain 3rd party sources. for instance, i tried it out with the VC++ VST template that was posted here a while ago and had the same max() problem. i just gave up and "rolled my own".

the complaints about "illegal pure syntax" are probably because you are commenting out the include of the inline implementations. put them back in.

sorry. i can't help out with every little programming problem. this is undoubtedly a problem specific to MS Visual Studio, so perhaps there is someone else here who knows who to fix it.

in the meantime, if you want a quick fix, just create your own min()/max() functions, but call them myMin() and myMax(). then do a find/replace in my code.

or... you might be able to fix it if you change min/max to MIN/MAX, or possibly _MIN/_MAX. i can't remember.

== chunk

Post

ok, well, perhaps i can help out with this problem. here's a msdn article on it:

http://support.microsoft.com/default.as ... -us;143208

there's a fix at the bottom. haven't tried it myself yet. good luck.

== chunk

Post

Thanks citizenchunk, i know you have already spend a bit of time on this, but its much appreciated, you're right it is a bug in VC, I have solved it by just adding

Code: Select all

#define max(a,b) (((a)>(b))?(a):(b))
in the compressor inline process, and removing all std:: , also changed the line

from this:

Code: Select all

static const int BUFFER_SIZE = 1024;
to this:

Code: Select all

enum {BUFFER_SIZE = 1024};
Ok the last problem Im having now is when I declare

SimpleLimit Limiter_; //In my plugin class def.

I get the following errors?

Code: Select all

error C2146: syntax error : missing ';' before identifier 'Limiter_'
: error C2501: 'SimpleLimit' : missing storage-class or type specifiers
: error C2501: 'Limiter_' : missing storage-class or type specifiers
SEModuleMain.cpp
 : error C2146: syntax error : missing ';' before identifier 'Limiter_'
 : error C2501: 'SimpleLimit' : missing storage-class or type specifiers
 : error C2501: 'Limiter_' : missing storage-class or type specifiers
Any help would be appreciated.

Post

ok..Solved that too..My mistake.All working now.!!:)

Post

thx CK.

I'll have a good pick over your code to see how you've done it :)

ATB
DSP
Image

Post

citizenchunk wrote:ok, well, perhaps i can help out with this problem. here's a msdn article on it:

http://support.microsoft.com/default.as ... -us;143208

there's a fix at the bottom. haven't tried it myself yet. good luck.

== chunk
just as an update to this problem...

i actually tried this "fix" today by adding NOMINMAX to the VC++ project's preprocessor directives (which i assume are defined before anything gets done). i then proceded to comment out the "#include <algorithm>", to see if the min/max calls were actually pointing to the correct STL library. no change. i then employed the "jump to definition" function to see where it thought the definition was, which took me to the macros windef.h -- exactly what i didn't want.

Visual Studio works really well for me, but it certainly is a strange app. nothing standard about its Standard Template Library implementation. have they dumped their oddball min/max macros in the 2005 version? i only have 2003.

anyway, i'm assuming that other compilers actually use the min/max in algorithm, so i'm leaving that include in -- even if it is superfluous.

== chunk

Post

timjay wrote:changed the line

from this:

Code: Select all

static const int BUFFER_SIZE = 1024;
to this:

Code: Select all

enum {BUFFER_SIZE = 1024};
Alternately, you can pull the static const int declaration out of the class and into a namespace that the class can see. The enum solution is fine for integers, but occasionally you want a relatively private const float or something:

Code: Select all

// anonymous namespace that the rest of the compilation unit can see
namespace
{
  const int BUFFER_SIZE = 1024;
  const float MAGIC_NUMBER = 1.732050807568877f;
}

class MyClass
{
 ...
}
Image
Don't do it my way.

Post

SMALL EDIT: in the initial post, i incorrectly stated that changing the attack time would resize the buffers. don't know what i was thinking there. as anyone can plainly see from the above snippets of code, the buffer size is a static const int, so the buffers get sized only once, during initialization.

that being said, it is possible to write this class with dynamically resizable buffers -- one of the benefits of using vectors. however, the benefits just didn't seem worth the added complexity.

== chunk

Post

citizenchunk wrote: Visual Studio works really well for me, but it certainly is a strange app. nothing standard about its Standard Template Library implementation. have they dumped their oddball min/max macros in the 2005 version? i only have 2003.
the min/max macros are included by windows.h

Post

citizenchunk wrote:ugh... the max() problem is a stupid Visual Studio problem that i've faced in the past. MS has defined their own min/max macros, which conflict with the STL functions in <algorithm>. supposedly, the way to fix this is to #define NOMINMAX before including algorithm, which i've done in the EnvelopeDetector.h header. but for some reason, i've found it doesn't always work with certain 3rd party sources. for instance, i tried it out with the VC++ VST template that was posted here a while ago and had the same max() problem. i just gave up and "rolled my own".
I find that sticking the std::max or std::min part in brackets works i.e. (std::min)( 2, 3);

The same thing works for the min and max members of std::numeric_limits i.e. (std::numeric_limits<int>::max)();

Also seen in a post to comp.lang.c++.moderated:

"there is still another solution: you can call the templated version directly, e.g.:

int x = std::min<int>( 0 , 1);

this works out of the box without defining anything else and is standard compliant." (Posted by Patrick Kowalzick)

Bye,
Steve

Post Reply

Return to “DSP and Plugin Development”