From the original SynthMaker forum (2004–2014), with its members’ names and dates.
bootsy ·
Hiho,
thanks to kirkagur who posted sometimes ago somewhere a simple but really decent limiter algorithm I've stripped it down to avoid the cpu expensive log encoding of the entire stream data. Saves tons of cpu without sounding worse.
I've attached both versions.
peace,
bootsy
infuzion ·
Thanks for sharing!
For an even more light weight limiter:
streamin i;streamout o;
float Fmin=0.999;
float Fmax=-0.999;
movaps xmm0,i;
minps xmm0,Fmin;
maxps xmm0,Fmax;
movaps o,xmm0;
But won't sound as sexy as the ones above, since this is more of a clipper-limiter, where that is more like a static-compressor-limiter 🙂
aliasant ·
Hey. What is the difference between this static limiter and any clipper?
infuzion ·
aliasant wrote: Hey. What is the difference between this static limiter and any clipper?
My ASM code is indeed a "clipper" which is a subset of limiters:
http://en.wikipedia.org/wiki/Limiting
I believe the above OSM has "soft limiting", due to a sort of compression to it.
Each have their uses; mine is better if an OSC or a ENV on rare occation touches outside of the +/-1.0 boundaries of a signal, as a final peak tamer when 99.99% of the signal is under max but you are pressing to CD, or if you crank up the volume & want that icky digital sound that dance tracks have now. Soft limiting is better for a more musical taming of peaks, like to hone in the occasional peaks of a vocal track after you compressed it, or part of the mastering process.
aliasant ·
OK.
Well.
As I see it a limiter is a compressor with a high Ratio and high threshold.
Often the ratio is at or above 10:1 and the threshold might be -6 dB or so. There should be no attack but a variable release time. Thats why you had me a bit confused 😉
bootsy ·
Be aware that soft-limiting introduces aliasing if not oversampled to the right amount and hard-clipping introduces heavy aliasing in any case (can't be compensated).
So an envelope driven approach (which features less distortion) might be more suitable in most cases.
exonerate ·
infuzion wrote: I believe the above OSM has "soft limiting", due to a sort of compression to it.
It's not correct to call it soft limiting, soft limiting/clipping doesn't actually clip it just distorts the waveshape so that it doesn't go above one. The higher the amplitude is above one the greater the distortion, which can be good sometimes for the 'analog' sound, basically a saturation algo on your output is soft limiting.
Hard limiting is actually clipping in that it clips the top of the waveform off, also affecting the sound.
Neither hard or soft limiting take into account the current amplitude.
kirkagurs/bootsys example would be a brickwall limiter, which justs adjusts the amplitude when it goes above one and doesn't distort the waveform like the other methods.
Thanks for this bootsy I think I'm going to use this on my synth, I've been playing around with limiting methods, I wanted to use a brickwall limiter but I couldn't make one efficent enough, but this one is thanks 😀
Cheers 😉
Exo
exonerate ·
Ok I saw some glaring obvious optimizations so I just couldn't help my self 😀 .......
Now the limiter is inside one ASM block, I've not checked the CPU usage but It will be considerabily less.
Cheers 😉
Exo
bootsy ·
Awesome, Exo!
I'm now setting up a basic compressor without logencoding just to see how far we can go avoiding expensive log or exp operations. It already features attack and release control, simple ratio control and even soft knee.
The only drawback I can see at the moment is that the attack and release curve shape is different than on a logencoded stream but I maybe err on that.
infuzion ·
bootsy wrote: ...hard-clipping introduces heavy aliasing in any case (can't be compensated).
Very true! That's why most of the scenarios I listed I was expecting the signal to be over only 0.0001 or so.
aliasant ·
OK. Here is my latest small limiter code as asm. It is not optimized. I just turned it into asm to keep my secrets.
We really do need lockable modules!
There is a variable release ( same as the envelope follower we already have)
You can push it to about -60 dB reduction before it squeels. The louder the input the longer the release time needs to be.
At least if you dont want to much aliasing.
Oh. If you want to see how much it is compressing the signal use the red output. Hook it into a linear to dB converter.
You could do that in green.
Maybe someone can optimize this?
Wow. I just compared the Kirkagur Limiter (optimised by you guys) and my own and they sound and act very very similar.
But the code is not that similar.
I made it in a different way and I think my limiter might sound better with shorter release times.
Probably because of the way I did the threshold but Im not sure.
They do sound alike with higher release times though. Very much alike.
exonerate ·
Bootsy do you mind me adding this limiter to the Developer toolkit ?
Cheers 😉
Exo
infuzion ·
exonerate wrote: Ok I saw some glaring obvious optimizations so I just couldn't help my self.. Now the limiter is inside one ASM block, I've not checked the CPU usage but It will be considerably less.
That's some tight ASM! I can't do better
/bow
bootsy ·
exonerate wrote: Bootsy do you mind me adding this limiter to the Developer toolkit ?
Cheers 😉
Exo
If it's ok to kirkagur its fine to me 😀
kirkagur ·
wow this is all great stuff!!!!!!!!!!!!!!
sure !
you can add this to the tool kit!!!!!!!!
exonerate ·
kirkagur wrote: wow this is all great stuff!!!!!!!!!!!!!!
sure !
you can add this to the tool kit!!!!!!!!
Nice one 😀
infuzion ·
exonerate wrote: Ok I saw some glaring obvious optimizations so I just couldn't help my self 😀 .......
Just noticed the GateRelease out isn't assigned; here is the edited code (I reused the IN xmm, so I shuffled around another xmm):
...
movaps oldOut,xmm5;
//GateRelease
movaps xmm4,F1;
movaps xmm0,xmm5;
cmpps xmm0,xmm4,6;
movaps xmm1,xmm4;
divps xmm1,xmm5;
andps xmm0,xmm1;
cmpps xmm5,xmm4,2;
andps xmm5,xmm4;
addps xmm0,xmm5;
movaps GR,xmm0;
mulps xmm7,xmm0; //*in;
movaps out,xmm7;
Are there other creations that depend on the GR that are affected?
bootsy: is the Release input range linear [0..1] please?
cheers
bootsy ·
The GR (Gain Reduction) is redundant and can be dropped. We just need the 'out'.
If you look into the original schematic you see that this was just provided to have the gain reduction information outside the module e.g. to hook a metering on it.
The release input is [0..1]. Just use the coeff calculator in the schematic.
infuzion ·
bootsy wrote: If you look into the original schematic you see that this was just provided to have the gain reduction information outside the module e.g. to hook a metering on it.
Exactly; who doesn't love that little red LED that tells you that you've kicked in the limiter!
I re-added GR to Exo's great ASM version, did alot of reduction, removed De-Zipper (typically the Release won't be moved much), added a glowing LED to show when the limiter is active. Unfortunately, it is hard-wired to mono due to the Mono to Float, but one can add a Poly to Float easily inside.
ccpurno ·
Found out that the optimized versions (released after bootsies 2 osm's) have an issue.
After playing some notes and waiting a while, the idle CPU usage suddenly climbs to 3%. (on core i7 system)
This does not happen with bootsies original versions.
In all versions, the time for the GR output to go back to 1 (= no limiting anymore)
is dependent on the GR value that has been reached.
Eample:
- With release input set to 4 seconds and lowest GR output of 0.5, it only takes 2 seconds to go back to GR of one.
- Only when lowest GR has been ~0, it really takes ~4 seconds to go to 1.
Is this correct behavior for a limiter?
CC
aliasant ·
ccpurno wrote: Found out that the optimized versions (released after bootsies 2 osm's) have an issue.
After playing some notes and waiting a while, the idle CPU usage suddenly climbs to 3%. (on core i7 system)
This does not happen with bootsies original versions.
In all versions, the time for the GR output to go back to 1 (= no limiting anymore)
is dependent on the GR value that has been reached.
Eample:
- With release input set to 4 seconds and lowest GR output of 0.5, it only takes 2 seconds to go back to GR of one.
- Only when lowest GR has been ~0, it really takes ~4 seconds to go to 1.
Is this correct behavior for a limiter?
CC
Denormals inside the envelope part. Add and then subtract a low number in the envelope line. Number could be 0.0000001 or similar.
MichaelBenjamin ·
or if you want to be cheap, you could also maxps clip, so it never reaches denormal land, because only monster cable guys can hear the difference.
ccpurno ·
Ok, thnx for the tip guys. Hmmm... Let's see if I can put this denormal fix in the asm code on the right place .... 😉
What do you think about the other remark?: the way the release time is dependant on the GR value?
CC
trogluddite ·
ccpurno wrote: the way the release time is dependant on the GR value?
That's not particularly unusual behaviour - some analogue designs even have panel markings for 'dB per second' because it is technically more correct - the attack and release are really 'rates' rather than 'times' in most designs.
It's also not unusual for the attack and release rates to be non-linear - so for example, when there is greater GR, the release rate may be 'faster' to recover quickly from short peaks, but when GR is small the rate gets slower for a more natural sound. Those kind of non-linear behaviour is a big part of the 'character' of a compressor/limiter - well worth experimenting with.
ccpurno ·
ok, that clears things up..!
CC
Disco_Steve ·
actually... most releases are exponential (or similar) and so the time to half released is constant, hence using the words release times. just like with half life of radioactive sources.
Gaussian release shape is my favourite, harder to do though
Wrote something here? To have a post removed or your name hidden, write to [email protected].