Old 12-24-2014, 03:32 AM   #1
squidward
Banned
 
Join Date: Dec 2014
Posts: 62
Default modifying a clipper

hi,
i have modified the utility limiter to be a simple clipper with a threshold and a mix slider and i would like to add some more features but i don't know how to implement them correctly.
this is what i have for my code so far...
i know it's very simple, but i'm a newb and just learning so bear with me here.

Code:
desc: parallel clipper

slider1:-24<-120,0,1>clip threshold
slider2:-6<-120,12,1>clip mix 

@slider

  t = 2^(slider1/6);
  g = 2^(slider2/6);
  
@sample

  clipL = min(max(spl0,-t),t);
  clipR = min(max(spl1,-t),t);
 
  
  spl0 = spl0 + (clipL*g);
  spl1 = spl1 + (clipR*g);
so what i would like to know is 2 things:
1 > how do i add asymmetrical clipping to this ? i am able to do it by adding DC before the clipping (c=g, spl0=spl0+c), but i don't think this is the 'proper' way to do it.

2 > is there a way to implement lookahead/attack/release/hold on the clipping ?
i would like it to have some parameters to play with. i use ReaComp for this usually, but thought it would be fun to try and make something.
i really couldn't find any code for a clipping limiter like this in my searches. the js_master limiter is close to what i want, but trying to modify it made my head hurt.

anyway, thanks in advance for any help/thoughts on this.

Last edited by squidward; 12-24-2014 at 02:15 PM. Reason: changed desc:
squidward is offline   Reply With Quote
Old 12-24-2014, 09:28 AM   #2
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,223
Default

You realize that this isn't actually clipping the output in any sort of limiter sort of way? You're basically just mixing the clipped signal in with the original, which should actually make the output louder than the input. If the clip threshold is low enough to clip much, it will reduce the crest factor, but it doesn't really stop the big peaks pushing through.

For assymetrical clipping you certainly can just add DC at the input. You could also use some other number in place of the "-t" in the min(max()) thing. Call it t2 or something. Either way, there will be a bit of DC offset in the output, and it's a good idea to strip that out before your output. Just rip the code out of the dc_remove plugin that's already there and stick it at the end. I have made this switchable on some of my plugs, but...

If you want attack and decay and lookahead, then you're not really making a clipper any more. It gets a lot more complex pretty fast. The code that's giving you headaches (gets me sometimes too!) is in fact what you need.
ashcat_lt is offline   Reply With Quote
Old 12-24-2014, 11:03 AM   #3
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 766
Default

This type of clipping is called hard clipping - once the signal crosses the threshold it is sharply clamped. In your case the effective ratio above the threshold is infinity:1. Something that you should be aware of is that the sharper the "kink" in the waveform, the more harmonics are produced, and at a certain point those harmonics are going to fold back over (i.e. reflect back from the Nyquist limit) and cause aliasing.

A "proper" hard-limit would simply look like this -

Code:
@sample
  spl0 = min(max(spl0,-t),t);
  spl1 = min(max(spl1,-t),t);
Can this code be adapted to provide asymmetrical limiting? Of course. There are a number of different ways to do it. One could be applying different amounts of gain to each side, for example

Code:
@desc
slider5:0<-15,15>Positive gain (dB)
slider6:0<-15,15>Negative gain (dB)

@slider
Pgain = 10^(slider5/20);
Ngain = 10^(slider6/20);

@sample
spl0 > 0 ? spl0 *= Pgain;
spl0 < 0 ? spl0 *= Ngain;
spl1 > 0 ? spl1 *= Pgain;
spl1 < 0 ? spl1 *= Ngain;
Follow that up with your limiter (whichever flavor you prefer) and you have created your imbalance. Another way to do it would be to set different thresholds, one for positive, one for negative. Another way to do it would be to add a DC offset, although as ashcat said, if you're going to do that be sure to add a DC blocker at the output.

...

As far as your plugin as written, ashcat is right - it is more of a clean/clipped blend rather than a limiter per se. There's nothing wrong with mixing clean and distorted signals, but there is a bit of art in doing it. The Tubescreamer guitar pedal, for instance, mixes a clean-ish low end with a clipped top-end.

Okay, so I'll put out a couple of suggestions for you to look at that might give you some inspiration. We all started not knowing what we were doing, it's a learning process, so just take it slow and work at it. There's a lot of code and math to wrap your brain around.

The two algo's that I have used over and over are the ones found in Loser/saturation and especially schwa/Soft_clipper. E.g.

"Softwall Limiter"
http://forum.cockos.com/showthread.php?t=131168

"Formant Function" (a 'singing' type of formant filter)
http://forum.cockos.com/showthread.php?t=130194

"PM5", an FM synth
http://forum.cockos.com/showthread.php?t=134709

Multi-band "deharshing" soft clipper
http://forum.cockos.com/showthread.php?t=134966


Basically I've been using schwa's soft clipper anytime I need a limiter because it has an exponential curve between the threshold and the ceiling, so I'll set the thresh to whatever (e.g. -3 dB) and the ceiling to -0.2 dB.

There are many different curves you can use in creating limiting/distortion/saturation... one good example is tanh().

efficient tanh
http://forum.cockos.com/showthread.php?t=143308

More elaborate saturation methods can be found. A new one for me can be found in the despot plugin source (which I have to note that I unfairly criticized). Tale's version is probably the most readable.

despot
http://forum.cockos.com/showthread.php?t=150463

...

Hope that gives you some useful information!
SaulT is offline   Reply With Quote
Old 12-24-2014, 11:37 AM   #4
squidward
Banned
 
Join Date: Dec 2014
Posts: 62
Default

wow, thank you both for the replies, very useful information from both. i do realize this is not actually a 'limiter' but more of a 'parallel clipper'. i am just using it as another way to add some dirt/distortion. funny (SaulT) you mention the guitar pedal because what got me thinking about this sound was an old peavey stereo chorus i had where you could run a clean & distorted signal at the same time...sometimes it sounded amazing like that. i was going to put 2 sliders on this for output gain, one for 'dry' and another for 'clipped'. also have separate sliders for symm/asymm clipping.

i wanted to try the envelope on the clipper because i have noticed that some of the popular limiters like elephant and pro-l have a 'clip' algorithm that basically has a lookahead/attack and release, so it can be a little 'cleaner' that way. i can replicate this with ReaComp, but i thought it would be cool to try and make something similar.

i have been playing around with some of the js_saturations and waveshapers and trying to learn the different methods used so maybe i can piece together an all in one kind of deal.
something similar to this plug-in waveshaper > http://pdp7.org/waveshaper.html which has several functions. it just seems nice to always have a little more control over 'whatever' if you need it. that's why i got into this, i wanted to change some things about some js plugs to make them 'better' for me to work with.

two questions...
i noticed js has a 'sin()' function...is that what you would use for that type of distortion ?
i tried it and it seems to work like that (comparing to another waveshaper).
and what about the 'tan()' function ? that isn't the same as 'tanh' ? it seems like it does something similar when viewing on an analyzer with a sine wave input.
i actually probably have a lot more but those are two good places to start.
squidward is offline   Reply With Quote
Old 12-24-2014, 12:57 PM   #5
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 766
Default

Digital audio exists between -1 and 1, so let's compare a few functions to see how the operate in that range. So y=x is the baseline - no shaping at all, what comes in goes out. Deviating from that changes the signal in some way. Going above linear is applying gain, going below linear is reduction. Saturation is all about reducing the signal in interesting and creative ways. The tanh() function [red] limits the signal to +/- 1, but tan() [purple] raises the gain in a non-linear fashion. Perhaps not a bad thing in and of itself, but it does raise the signal a lot, especially the closer you get to +/- 1, which means a greater chance of digital (bad) clipping and potential numerical instability.

https://www.desmos.com/calculator/jiarkg1t4o

The Loser saturation method uses sin() [blue]. That's a reasonably nice curve, but notice how it starts to curve back around at +/- pi/2.... so to be safe we would probably need to limit our input to that point, e.g.

Code:
function sin_sat(in) ( sin( max(min(in,1.570796),-1.570796) ); );
Reaper doesn't have a built-in tanh() function, so we have to use an approximation of some type. I provided a link earlier where we talk about different tanh() approximations.

The best advice that I can give you is to graph everything. It will help you look for errors in your code, but it will also give you a visual indication of how you can expect it to behave - the degree of non-linearity, how quickly it deviates from linear, the maximum value, and how sharp the "knee" is will all inform you as to how it's likely to sound.
SaulT is offline   Reply With Quote
Old 12-24-2014, 02:12 PM   #6
squidward
Banned
 
Join Date: Dec 2014
Posts: 62
Default

how about the 'cos()' function ?
it seems that using that instead of 'sin()' gives even harmonics for a sine wave.
when i type it into that calculator/plotter, it looks the same as 'sin' but phase offset.
maybe a dumb question, but can that be used like/with 'sin' for distortion ? it seems like it works, but i haven't tested too much, just writing a line and seeing what happens on an analyzer and a scope.
sorry if these are basic math questions but i always had a hard time with anything more complex than algebra. i'll get this stuff eventually.

i also had a question about something i 'stumbled' upon playing with the limit/clip code.

when i change the threshold value 't = 2^(slider1/6)' to 't = spl0*spl0' i get a clipping of sorts but it looks different. looks like something happening around zero crossing and not the usual flat top peaks. what is happening there ? (i think) i am setting the threshold at 2x the sample value and that way the current sample will always be over the threshold ? but it actually causes a 6dB rise in gain and not reduction. is this like an 'inflator' type of effect ?
squidward is offline   Reply With Quote
Old 12-24-2014, 02:54 PM   #7
SaulT
Human being with feelings
 
Join Date: Oct 2013
Location: Seattle, WA
Posts: 766
Default

Quote:
how about the 'cos()' function ?
it seems that using that instead of 'sin()' gives even harmonics for a sine wave.
when i type it into that calculator/plotter, it looks the same as 'sin' but phase offset. maybe a dumb question, but can that be used like/with 'sin' for distortion ?
By pure happenstance, when I was searching for the deharshing plugin I linked to earlier I found this, which should answer your question quite well. So, not a dumb question at all, the answer is yes.

http://forum.cockos.com/showthread.php?t=98491

Quote:
when i change the threshold value 't = 2^(slider1/6)' to 't = spl0*spl0' i get a clipping of sorts but it looks different.
Okay, so @sample and @slider run parallel to each other, or I should say that when you move the slider, the @slider section is triggered, but @sample is still running. At the moment that the slider is changed, you are telling Reaper to grab the current spl0 value from the @sample section, multiply it against itself, and set that as the current threshold.... basically making the threshold completely dependent upon whatever signal was coming through at the time. It could conceivably be anything from -1 to 1 to even 0, since the current sample value is constantly changing.

In other words, one moment the sample vale could be -0.2, which would square to 0.04, which is a threshold of about -28 dB. The next moment the sample value might be 0.6, which squares to 0.36, which is about -8 dB.... see what I mean?
SaulT is offline   Reply With Quote
Old 12-24-2014, 03:48 PM   #8
squidward
Banned
 
Join Date: Dec 2014
Posts: 62
Default

cool, thanks for all the help and info, i'm going to read some and play around with this stuff a little and see what i can come up with.
squidward is offline   Reply With Quote
Old 12-25-2014, 02:41 PM   #9
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,223
Default

IDK if this helps, but you were asking...

sinifier is pretty straight forward. Just basically scale the input value, take the sine, and then scale it again. The folding over of the waveform is interesting in a horrible kind of way. To be more useful, it should limit the input (times the scale) to half of pi in either direction.

...and it looks like I removed my cosinifier to replace it with a newer version and failed to reupload...bummer... :/

Anywho, the thing about cosine is that it starts at 1 when the input is at 0, and then it gets smaller as (absolute value of) input gets bigger so that by itself it sort of turns the wave inside out. This is much better used as a gain factor, so you end up with something like output = input * cos (input). That works a lot like the sine function, but is not quite the same at all. When I get home, I'll upload the code.

You should poke around in my stash. (Why does that sound dirty?) I have a tanh "diode" clipper (kind of what started that thread that SaulT linked) which allows asymmetrical clipping as well as full-wave rectification, and some other fun stuff.

I think I'm a cut hair away from a much more realistic diode-to-ground clipping function. It gets a bit deeper though, and I had to walk away from it for a while...

I also have a thing based on a tube-like power law, which is interesting, though I haven't really made it into anything useful yet.

Last edited by ashcat_lt; 12-25-2014 at 02:50 PM.
ashcat_lt is offline   Reply With Quote
Old 01-24-2015, 09:45 AM   #10
squidward
Banned
 
Join Date: Dec 2014
Posts: 62
Default

i guess i could use some help implementing my ratio parameter in my clipper i am making.
this is an example of what i have right now that does exactly what i want it to do...
but i am not sure it is 'correct' or the 'best' method of doing this conversion/translation.

Code:
slider1:2<0,4,0.01>x
slider2:0,ratio    // i am just using this to see the value

@slider
e = -4+slider1;
ratio = 1+(10^e);
slider2 = ratio;
basically i am just trying to 'scale' the slider and ratio.
i only stumbled upon this solution just piecing things together i knew about amp/db conversion. so i think i have the right idea, but not the right method ?

also a 'problem' i see is someone thinking 'what the hell does 0 > 4 represent ?' ratio ? gain ? power ?' etc...
so even though this works perfectly for me, it makes no sense...
help.
thanks.

Last edited by squidward; 01-24-2015 at 10:08 AM.
squidward is offline   Reply With Quote
Old 01-24-2015, 11:26 AM   #11
ashcat_lt
Human being with feelings
 
Join Date: Dec 2012
Posts: 4,223
Default

I don't think there's anything wrong with that really. You do what you gotta do. One would imagine that you'd actually label the slider with some description, or use a bit more abstract method. Sometimes the slider just needs to go from 0 to 10. The user doesn't need to know what that means, but everybody knows that 0 is none and 10 is max. B)


Edit - BTW, looking back through this I realized I never did get around to uploading the cosinifier, but it's there now. I also uploaded the sin_amp simulator thing.

Last edited by ashcat_lt; 01-24-2015 at 11:38 AM.
ashcat_lt 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 05:24 PM.


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