- solved -

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Sorry for the clickbait, but I'm puzzled.

Everywhere I look (Parker, JOS, Chowdhury) the first antiderviative of the signum function is given as

Code: Select all

x * signum(x) - 0.5 for x < -1 and x > 1
But where does the -0.5 come from?

My rusty maths tell me it's just

Code: Select all

x * signum( x )
which my CAS totally agrees on:
image.png
Am I onto something or am I missing it?

#---------------------

I've been missing that the -0.5 is there to make the antiderivative continuous because 0.5*x^2 is 0.5 at +/- 1

:dog:
You do not have the required permissions to view the files attached to this post.

Post

Two more lines and I'm happy:
Screenshot 2021-09-30 at 13.07.24.png
In my example the term from -1 <= x <= 1 would result in a shifted version in order to make the antiderivative continuous.

(and of course, the constant component cancels out in the actual ADAA formula)
You do not have the required permissions to view the files attached to this post.

Post

I know you marked it as solved, but this gave me a mathematical itch.

The antiderivative of the sgn(x) function doesn't exist because of the discontinuity around x=0. You can of course integrate it in a piecewise fashion. If you then choose the constant of integration equal to zero on both pieces, the result becomes x*sgn(x) for x =/= 0.

In your (Maple?) code, function (4) is not the sgn(x) function. It's a continuous function for which the antiderivative exists. Since you're talking about ADAA, this is probably a hard clipper function? As you've found, you'll need the 0.5 constant to obtain a continuous antiderivative.

Post

Yes, well spotted! I wrapped the piecewise hardclip example into the good old branch free clamp trick. The result is still mathematically identical to that of the papers, even if shifted by a constant. The constant cancels out in the ADAA method.

And of course, we're always looking at sign(x) at x <= -1 and x > 1, such that the discontinuity doesn't pose a problem.

Post

Code: Select all

x * signum(x) - 0.5 for x < -1 and x > 1
Das ist mathematisch nicht falsch. Aber auch nicht ganz richtig.
-0.5 ist in dem Fall eine Konstante. Die kann einen beliebigen Wert haben. Die Konstante geht beim Ableiten immer verloren, da eine Kontante keine Steigung hat. Korrekt geschrieben wäre hier für die Stammfunktion:

Code: Select all

x * signum(x) + C for x < -1 and x > 1
https://www.gut-erklaert.de/mathematik/ ... igung.html

Post

Urs wrote: Mon Oct 04, 2021 8:14 am Yes, well spotted! I wrapped the piecewise hardclip example into the good old branch free clamp trick. The result is still mathematically identical to that of the papers, even if shifted by a constant. The constant cancels out in the ADAA method.
Mathematically it's identical, but numerically there might be a difference in increased relative precision loss at low signal levels. Not 100% sure, though.

Post

As for the reason for -0.5, it's not to make the antiderivative continuous per se, a correctly computed antiderivative (of a bounded function) should be continuous itself, to begin with, it's just mathematically:

Code: Select all

int_0..t clip(x) dx = int_0..t x dx = t^2/2  for |t|<=1
int_0..t clip(x) dx = int_0..1 x dx + int_1..t 1 dx = 1/2 + (t-1) = t-1/2  for t>=1

Post

Thanks guys,

Yes, I wasn't seeing the woods for the trees. It seemed to me from reading about anti derivatives that it's supposed to be the most simple form of an integral, with the constant element chosen to be absent (= zero). But that's of course not possible in this case of piecewise equations.

As for the clamp trick, I was checking if Maple might have know a trick to make the anti derivative branchless as well. Apparently it doesn't. Pity.

Btw. we still have quite some attenuation in the audible spectrum with 2x oversampling. So I think 4x oversampling is it, along with 1st order ADAA as a good compromise between CPU and sound quality. Any thought on this? (Maybe I'll start another topic, but I'm super busy with other stuff atm)

Cheers,

- U

Post

The waveshaper on my MixMaxtrix plugin uses this.

I know no DSP math, so I don't know how correct this is.

As ADAA order 1 has a boxcar N=2 effect, it delays the signal by half a sample. This has to be compensated. What I did to reequalize was, when processing sample-wise:

-Apply a half sample delay to the dry signal. I call this S-del.
-Apply a Boxcar N=2 to the dry signal. I call this S-lp.
-Add "S-del - S-lp" to S-del. Now the signal is pre-equalized.
-Adaa process S-del.
-After Adaa the signal is delayed by one sample.

It still didn't sound good but it was better than without it. Is this correct? Too naive?

But yes, 4-8x oversampling seemed a must to me.

Post

Urs wrote: Thu Sep 30, 2021 10:42 am ...

Everywhere I look (Parker, JOS, Chowdhury) the first antiderviative of the signum function is given as

Code: Select all

x * signum(x) - 0.5 for x < -1 and x > 1
But where does the -0.5 come from?

My rusty maths tell me it's just

Code: Select all

x * signum( x )
which my CAS totally agrees on:

...
By WolframAlpha, antiderviative of the signum 'function' is

Code: Select all

x * sgn(x) + constant
.

https://tinyurl.com/wbkhv8d8
https://tinyurl.com/3e3baau9

Post

Actually it's simply |x|. I guess x*sgn(x) is either a result of internal details of the engine (in case of Alpha) or written to better express particular aspects of the function's behavior (in papers).

Post

I'd vote for x * signum(x) + c for some arbitrary c in R.

Post

|x| and x*sgn(x) is the same of course. This may be nitpicking but the sgn(x) function doesn't have an antiderivative, I'm quite sure. You could prove this using limits, but the short answer is Darboux's theorem. Maybe WolframAlpha defines the "indefinite integral" not the same as "antiderivative", if not it's a mistake. sgn(x) is Riemann integrable however.

The piecewise hardclip from Urs post does have antiderivatives. It seems the 0,5 term is not the constant of integration. It's there to make the piecewise definition of the antiderivative seamless. When you add a constant of integration 'C', the antiderivative of the hardclip function becomes:

Code: Select all

x * sgn(x) - 0.5 + C	for x =< -1
0.5*x^2 + C		for -1 < x <1
x * sgn(x) - 0.5 + C	for x >= -1

Post

@flisk,
I bumped to these definitions (below) couple days ago but, as not being mathematically skilled, do not fully understand what said there:
1. Any function that does not have the intermediate value property does not have an antiderivative. This can be seen as an immediate consequence of Darboux theorem, but sure there are more "fundamental" ways to prove it.

2. Good example is the signum function. If F′(x)=sgn(x) for any x, then F′(x)=1 if x>0, so then F(x)=x+C. Similarly for x<0 we have F(x)=−x+D. Of course, F should be continuous at 0. Because F(0+)=C and F(0−)=D, we get F(0)=C=D. Hence F(x)=|x|+C for any x. But F is not differentiable and it could not be an antiderivative.
Source

Related to your post?

Post

Urs wrote: Mon Oct 04, 2021 2:31 pm
As for the clamp trick, I was checking if Maple might have know a trick to make the anti derivative branchless as well. Apparently it doesn't. Pity.
Hi, I don't know if this is what you're looking for, but the antiderivative of (|x+1| - |x-1|)/2 can be written as ( |x+1|(x+1) - |x-1|(x-1)|)/4, which avoid any if statement (I don't know if it is effectively faster). If you want it to be 0 in 0 you have to further subtract 0.5, so that is identical to the branchy one you found.

Cheers
Lorenzo from Italy. Developer, Mathematician

Post Reply

Return to “DSP and Plugin Development”