Hi folks.
Here's my first attempt at emulating an analog summing device. Give it a try: put it on every track (not busses or masters) and let me know if you like it. Suggestions are welcome. Thanks
have you plotted this ?
i wouldn't double the input gain...as is, you need to limit to -6 dBFS +/- or it starts to fold over / fall apart.
didn't check it out too much yet but that caught my eye right away...
Yes, i plotted it. It's a classic sigmoid function. The pre and post gain is there to increase saturation. I just chose the number by ear. I guess soft clipping would be better than limiting, just to stay in the realm of analog. Does this makes sense?
the sin/cos functions have a limit (pi/2), so you need to hard clip <= that or else use another function that doesn't have a limit. (tanh(x) is very popular these days)
you could get rid of the default *2 for the gain and put an input gain slider there in place... let the user decide. (people love their input/output gain.)
i attached a screnshot of what happens with 0 dBFS sine input...that's not good...
the sin/cos functions have a limit (pi/2), so you need to hard clip <= that or else use another function that doesn't have a limit. (tanh(x) is very popular these days)
you could get rid of the default *2 for the gain and put an input gain slider there in place... let the user decide. (people love their input/output gain.)
i attached a screnshot of what happens with 0 dBFS sine input...that's not good...
Cool! So i made some changes and removed that multiplication. Actually i've changed the entire waveshaping. For now i want something without controls for simplicity.
Why do you not just use a signoid function? All those sin and cos and tan and htan in order to approximate a function with a single exponential? In my experience, one sigmoid is slightly less efficient than one one (clamped) sin, and slightly more efficient than a real tanh, but it's definitely faster than even two sins in a row. It requires no external clamping and will never explode at any input value.
Maybe I'm missing something?
What's going on in that analog stereo function? I kind of only glanced at it.
Edit to add -
I've been doing everything with sigmoids for a while. Even rebuilding things I did with tanh just to save that tick or two. See my Logistic Sidechain Distortion in the stash.
I've also been thinking about making some "black box" type character plugs. No sliders or maybe just input and output level. Drop it on there, it does...something...and if you like it you keep it and if not, you try a different one.
Edit again - But also I think it was about 2003 when analog summing devices were really the talk of the town and I predicted that before long we'd have virtual analog summing devices.
-It increases loudness as well as peak level (the latter by a couple dBfs) making it difficult to know what it really does in a simple on/off test. I'd recommend at least reducing the peak output to the same peak level as the bypassed signal, or provide an output level control.
-This does a lot; it's not subtle. This isn't something that should be referred to as "summing". It's distortion. Well that's the most noticeable part of it anyway, by a large margin. If you want this to be thought of in the same general realm as BussColors by AirWindows (etc.), either you need to dial it way back or provide controls for the different aspects.
Using this on a single channel, I can see its potential benefits as-is. Running this on an entire mix (every channel), a mix that I thought was already good, pretty much made it a mess especially in the high end (to be fair, I did like how it sounded for a fair portion of the frequency range). I would never mix with this plugin on every channel, and probably only ever use it on a single channel as a fairly noticeable distortion/saturation effect. If it had controls for each aspect and output level, I could then consider using it on a whole mix.
Again, this is only my opinion. Thanks for bothering to make a plugin and release it for free, in any case! Whether you modify this or not, I do appreciate your effort.
Ok following the suggestions i made a few edits to the code:
- used a single sigmoid function (witch is a combination of two);
- tried to level-match the output;
- randomized the stereo-spread effect per track.
If you add controls for the functions, I'll be glad to try it again. Otherwise it's a bit too over-the-top for me in general.
Oh something else I forgot to mention: I don't like noise being intentionally added by the plugin. I'm not nostalgic for cassette tapes or something. The noise is quite noticeable and I think it takes away from what you're trying to do.
Ok, here's another turn of improvements. Now you can choose between 3 types of saturation and they get updated on all instances at once with global registers.
Well if you were asking me, I decided to not use the plugin again unless controls are added to dial back the various aspects to taste. Also that the noise, which apparently has been intentionally added, would be removed.
Well if you were asking me, I decided to not use the plugin again unless controls are added to dial back the various aspects to taste. Also that the noise, which apparently has been intentionally added, would be removed.
Did you test after the modes were added?
And can one use wet/dry knob for dailing in amounts?
Oh, my bad... you were meaning being able to control the "aspects" of the noise and saturation.
-It increases loudness as well as peak level (the latter by a couple dBfs) making it difficult to know what it really does in a simple on/off test. I'd recommend at least reducing the peak output to the same peak level as the bypassed signal, or provide an output level control.
-This does a lot; it's not subtle. This isn't something that should be referred to as "summing". It's distortion. Well that's the most noticeable part of it anyway, by a large margin. If you want this to be thought of in the same general realm as BussColors by AirWindows (etc.), either you need to dial it way back or provide controls for the different aspects.
Using this on a single channel, I can see its potential benefits as-is. Running this on an entire mix (every channel), a mix that I thought was already good, pretty much made it a mess especially in the high end (to be fair, I did like how it sounded for a fair portion of the frequency range). I would never mix with this plugin on every channel, and probably only ever use it on a single channel as a fairly noticeable distortion/saturation effect. If it had controls for each aspect and output level, I could then consider using it on a whole mix.
Again, this is only my opinion. Thanks for bothering to make a plugin and release it for free, in any case! Whether you modify this or not, I do appreciate your effort.
This does a lot? Why not just turn the wetness down and use it like taste? Its not even adding delay or anything critical. If you use such saturation plugins on every track or not also depends on what kind of music you make. There is no rule - only taste and ears.
There are bands making rockabilly records today with equipment right from the 60ies. And they really do a lot!
This does a lot? Why not just turn the wetness down and use it like taste?
If I have to use wet/dry in Reaper itself, I will. However, I want to adjust some of the plugin's parameters individually. Some, I would never use at all (as I've already mentioned). Others, I would.
There are already other plugins I use for similar effects, so I feel more comfortable just using those.
Quote:
Originally Posted by Eliseat
Its not even adding delay or anything critical.
Actually, consider the "panning" aspect built into this plugin. Blending that wet/dry in Reaper's fx window can affect the sound in a way that's unwanted (phase, stereo imaging). Since it can't be adjusted separately, it's "all or nothing".
Quote:
Originally Posted by Eliseat
If you use such saturation plugins on every track or not also depends on what kind of music you make. There is no rule - only taste and ears.
I know.
I'm also not saying that others shouldn't use this plugin. That's up to them. Others might appreciate this plugin. But if I'm asked to keep testing this plugin, I don't want to bother unless it ends up with controls to adjust the parameters. I provided my reasons, that's all.
Last edited by JamesPeters; 09-12-2018 at 10:57 AM.
The picture shows some kind of severe distortion ?!?!?!?
The name "Summing" suggest, that the plugin should see all channels to be summed and somehow "mediate" between them, bnut I don't see any trace of this in the source code.
Can somebody elaborate on the theory, practical sound advantages and usage cases for the algorithm implemented here ?
Ok, here's another turn of improvements. Now you can choose between 3 types of saturation and they get updated on all instances at once with global registers.
Code:
...
Hi solarfall,
i tested this version of your JSFX and i find it very useful. Its nice sounding and carves different harmonics on top of the signal. Its a great opportunity to grind drum loops or to clean synths in a mix. It helps to place them in 3d. And I really like mixes where every instrument is perfectly separated and has this tiny silk like vibration on top.
Of course it would be a great addition - like JamesPeters mentioned - to have a saturation input to maybe slowly dive into the audio material. I have no idea how much effort it costs. But anyway. I'm already satisfied with the actual state and guaranty you i will use it in further projects. Saturation is always appreciated especially in a uncomplicated way like an JS.
The picture shows some kind of severe distortion ?!?!?!?
The name "Summing" suggest, that the plugin should see all channels to be summed and somehow "mediate" between them, bnut I don't see any trace of this in the source code.
Can somebody elaborate on the theory, practical sound advantages and usage cases for the algorithm implemented here ?
Thanks,
-Michael
I would say it simulates the adding of analog gear effects just straight forward by adding fuzzyness to the signal. Its no emulation. But i always wondered why there is no real emulation of a signal flow thru various analog gear. Everybody who worked in analog times knows, it was a great bummer to don't have digital possibilities like today. But also knows, how every cable, every effect rack, tape machine and mixing desk added something (and not only good). With high end equipment it were only tiny amounts of random imperfections, noise, hum etc. But they gave the mojo whats missed in some modern productions out of the box.
The picture shows some kind of severe distortion ?!?!?!?
that is the first version, i didn't check the other versions.
it's usually a good idea to limit the input if the function only works correctly within a certain range.
There has been a lot of discussion about sigmoids, especially tanh. You can search for it, but a few years ago (when I was a lot more active and had time) I compiled a kind of list.
My favorite subtle saturation is Loser/Saturation. It's subtle, it's sweet, you can cascade it, I really really really like it. If you're going to go the route of analog summing you want subtle, not obvious. This is one way to do it and it's adjustable. I'm almost positive that I figured out a more generalized way to do it that didn't rely on calling sin()... but it's apparently been years and I just don't remember.
Argitoth's post about sigmoids is definitely one to look at. If you like long-winded discussions about math you can read some of my posts, I tried to explain some of my reasoning a few different times in a few different posts.
...
If I was to attempt this style of saturator I would probably use a compression-style waveshaper with a soft knee, e.g. a ratio of maybe 2:1 and a super wide knee, like from -15 or -20 to 15 or some such. Would probably want to have the saturation in parallel, probably filter it as well. You can find a post that I wrote on soft knees using a quadratic spline in that list above. Again, probably overly long-winded, but sometimes you get excited about things.
Well, I looked into it and it ended up being more of a hassle than I remembered, with an abs() and sign() call and blah. I did find this one, though, I hadn't remembered it.
out = (a*x)/sqrt(a + x*x);
It's pretty close to tanh(x) when a = 1 but of course feel free to experiment...
Regarding Loser's saturation, I find that one just OK. I'm not really a fan of sine saturation. It clamps to 1 a little too early (around +4 dB). Loser/Saturation basically morphs between hard clipping and sine saturation with a little extra gain, meaning the input gain is higher as the curve morphs toward sine.
Quote:
Originally Posted by SaulT
out = (a*x)/sqrt(a + x*x)
I'm familiar with x/sqrt(1+x^2). Yours is that with input and output scaling, though it's not exactly well-behaved because input is scaled by 1/sqrt(a) while the output is scaled by a, so you get a massive output volume boost as a increases.
Slightly different
(a*x)/sqrt(a^2 + x^2)
would give you a variable ceiling.
I love sigmoids and have spent way too much time messing around with them.
He he ... Cunning, as I am, I stole your formula and copied it into the video processor's Morph preset. And yes! It worked! Now I will get rich! I WILL RULE THE WORLD!!
Just joking! It did nothing spectacular. The gif shows a preset with a fantasy formula I made myself. What a bummer.
Thanks for asking. I use my own JS which is tanh-based. Nothing out of the ordinary, but after spending time with every sigmoid algorithm I could find or come up with, I find it to be the best.
Thanks for asking. I use my own JS which is tanh-based. Nothing out of the ordinary, but after spending time with every sigmoid algorithm I could find or come up with, I find it to be the best.
I do like the tanh, but saturation can lead to pretty bad aliasing. For most waveshapers, you can use a trick to reduce the aliasing quite a bit at low cost (without resorting to oversampling). One can construct a continuous time approximation of the input signal and then apply the non-linearity to it in continuous time. The paper title is in the comments if you are interested in reading more about it. It's quite a fun read. If all you're doing is waveshaping, then at least the rect version is pretty easy to implement. All you need is an integrated version of your waveshaping function (F0 in this code).
Anyways, code if you like. I'll add it to my jsfx repo too.
Code:
DO NOT USE THIS VERSION, BETTER VERSION IN LATER POST.
desc:Anti-aliased Tanh Saturation
tags: saturation distortion anti-aliased
version: 1.00
author: Joep Vanlier
license: MIT
Uses technique from: Parker et al, "REDUCING THE ALIASING OF NONLINEAR WAVESHAPING USING CONTINUOUS-TIME CONVOLUTION",
Proceedings of the 19th International Conference on Digital Audio Effects (DAFx-16), Brno, Czech Republic, September 5–9, 2016
I have only implemented the rect version, since the linear one depends on Li2 and LUTs aren't so fast in JSFX.
in_pin:left input
in_pin:right input
out_pin:left output
out_pin:right output
slider1:0<-6,24,1>Gain (dB)
slider2:0<-18,0,1>Ceiling (dB)
slider3:1<0,1,1>Antialias?
slider4:0<0,1,1>Fix DC?
@init
bpos=0;
@slider
preamp = 10^(slider1/20);
ceiling = 10^(-slider2/20);
inv_ceiling = 10^(slider2/20);
@block
blah+=samplesblock;
@sample
spl0=spl0;
spl1=spl1;
@sample
function F0(x, em2x)
local()
global()
instance()
(
x - log(2/(1 + em2x))
);
function atanh_prec(x, em2x)
local()
global()
instance()
(
(2/(1+em2x))-1
);
function atanh(x)
local()
global()
instance()
(
(2/(1+exp(-2*x)))-1
);
function antialiased_atanh_rect(x)
local(diff, em2x, F0_xn)
global(slider4)
instance(antialias, F0_xnm1, xnm1)
(
em2x = exp(-2*x);
F0_xn = F0(x, em2x);
diff = ( x - xnm1 );
antialias = (abs(diff) > 0.000000001) ? ( F0_xn - F0_xnm1 ) / diff : .5 * atanh_prec(.5*(x+xnm1), em2x);
F0_xnm1 = F0_xn;
xnm1 = x;
antialias
);
function fix_dc(x)
local()
global()
instance(DC_fixed, prev)
(
DC_fixed=0.999*DC_fixed + x - prev;
prev=x;
DC_fixed
);
spl0 *= preamp;
spl1 *= preamp;
spl0 *= ceiling;
spl1 *= ceiling;
slider3 ? (
spl0 = ch0.antialiased_atanh_rect(spl0);
spl1 = ch1.antialiased_atanh_rect(spl1);
) : (
spl0 = atanh(spl0);
spl1 = atanh(spl1);
);
slider4 ? (
spl0 = dc0.fix_dc(spl0);
spl1 = dc1.fix_dc(spl1);
);
spl0 *= inv_ceiling;
spl1 *= inv_ceiling;
On the left you see a sine sweep without the anti-aliasing, on the right you see one with (same colorscale of course). The difference is substantial.
Thanks! This is very interesting. I'll have to read up to understand what's going on here.
Quote:
Originally Posted by sai'ke
I do like the tanh, but saturation can lead to pretty bad aliasing.
Of course you're right in theory, but I haven't found aliasing to be a problem at reasonable gain levels. In fact, I was testing this just last night. On a pure input tone the aliasing is easily noticable after a certain amount of gain. But on more complex signals it's much harder to pick out the aliasing if you can hear it at all.
And yeah, you're right, it depends on how hard you push the saturator and how busy the high frequencies are already. I just took this sine sweep because it's easy to visualize in this case.
On synths, I can usually spot aliasing pretty well though. Given that the difference in computational cost is low, I'd probably go with the anti-aliased one.
Really though, I've read this paper a while ago, and just wanted an excuse to try it out. DSP is fun
Not knowing much of these, to me it feels, the art is in finetuning all. So a boring game can be made almost something much more interesting just by finetuning all the important parameters, plus a few original and interesting changes here and there, ignoring what is available so far. Example would be the scoring or energy distribution algorithms among players, not only using 'egoistic algorithms', meaning all score/energy to me, nothing to the rest.
Which language you used above? What are your recommendations? Possible to test?
Same for Hypercoaster. Does it make a big change in feel if used with a 3D glass/display or what is the official term?
As this thread is boarded with a general saturation discussion I also have to ask something. (And for such a thing its always good to have Sai'ke (The Grandmaster of Filtering) around.)
I read once about the Spectre vst saturation plugin in a forum discussion where all people praised it. A demo download gave me the certainty that this is really an amazing plugin. It has such an impact that you can shape even flat and boring sound into warm and sparkling mixes.
My question is: Is this only an over-saturated EQ that could be reproduced by sending saturated signal thru ReaEq? Because that doesn't even come close to that amazing sound of Spectre.
Quote:
Spectre processes the difference between the input signal and the EQ signal, introducing harmonic content to just the part of the spectrum that you want from a variety of saturation algorithms based on classic recording hardware.
I can read this again and again but don't come to a conclusion. Does this mean they subtract (delta) the original signal from the processed EQ to add it (saturated) in again?
Anyway. This is by far the best saturation plugin I've ever heard. And its flexibility is unbeatable. Maybe this could be a cool project for a Reaper JS. (づ。◕‿‿◕。)づ
Anyways, code if you like. I'll add it to my jsfx repo too.
Joep,
I've encountered a couple problems with this implementation. See my video.
1) Feeding in a sine tone from tone generator, there is click injected at the top peak, depending on frequency. 441 Hz seems to be "safe". 440 Hz is not. Flipping from 440 to 441 then back to 440, the click sometimes goes away. Restarting the transport brings it back. Using MOscillator instead, the problem doesn't exist.
2) With >51 dB of gain, the lower peak folds over. What should be -1 flips up to +1, with increasing severity as the gain increases.
Anyway, I still need to read the paper to understand your code. I'm very interested in what's causing this and if this anti-aliased algorithm can handle higher gain levels. Any ideas?