-
Notifications
You must be signed in to change notification settings - Fork 17
Description
In the code for your Sine Clipping algorithm, you check if the abs() of the incoming sample is below Pi: if (fabsf(x) < juce::MathConstants<T>::pi) and then you run it through sin().
If the incoming absolute sample is abs(x) > 0.5 π, then the output of the sin() function will approach 0 again.
sin(0.0 * π) = 0
sin(0.5 * π) = 1
sin(1.0 * π) = 0
This means that the more the incoming signal exceeds +1.7 dBfs abs(x) = 0.5π, and the closer it approaches +4.3 dBfs abs(x) = π, the more it will descend to total silence. After +4.3 dBfs abs(x) > π your function returns +/- 1.0 using sgn(), which is full 0.0 dBfs volume again.
The way your function works should generate a very buzzy and clicky signal, since many of the loud samples will suddenly become reduced to absolute silence, and only slightly louder input samples will jump to the maximum 0.0 dBfs ceiling again.
I don't know if you WANT this weird behaviour, but if you don't then I recommend that you fix your if check to if (fabsf(x) < juce::MathConstants<T>::pi * 0.5, or ideally you create a "halfPi" constant if JUCE doesn't have one.
I do this in my JSFX Sine Clipper. It checks that the absolute input sample abs(x) < 0.5 π, because sin(0.5π) = 1.0 i.e. the 0.0 dBfs ceiling.
So any incoming signal can exceed 0.0 dBfs up to ~ +1.7 dBfs for clean sine-based soft-clipping, and anything that comes in above ~ +1.7 dBfs will be hard-clipped (using the sign). This will generate a much more consistent output, less buzzy and clicky, fewer drop-outs.
Also, I don't think it's necessary to multiply the output of sgn() with a float value. This conversion should be done implicitly by the compiler, you probably don't need to waste a CPU cycle for a multiplication on it. :)
Cheers
Rob