Hi Will,

I agree with your reasoning regarding M_PI

Yesterday evening I tidied up my changeset, and now it occurred to me
that this also touches the topic of "dB values for volume".
Obviously, it would be possible to rationalise and unify the calculation
for dB-factors to some degree. The question is what changes are acceptable?

To expand a bit on the technical details, the powf() function is also used
on many places to translate a parameter, which relates to a logarithmic
scale (in decibel), into an amplitude factor (or factor for a filter).
And, as usual, the situation is somewhat confusing, since the same stuff
is done in several different ways.

- there is the db2rap() function, which uses the generic formula for decibel
- but at various places, instead a powf(0.1f, ....) is used..
- and the dB-parameter is again prepared using several formulations

And, to add to the confusion, the db2rap() function uses a compile time switch

#if defined(HAVE_EXP10F)

The problem with this is twofold. For one, the exp10f() function produces
slightly more accurate values, which means (taken the other way round),
that *if* the the build system picks the HAVE_EXP10F, the compiled Yoshimi
will generate slightly different sample values.
And then, the other problem is that the HAVE_EXP10F is defined in the
CMakeList.text in a way known to be problematic:

check_function_exists(exp10f EXP10F)

This macro is known to be unreliable, and it very commonly fails especially
on such ubiquitous functions like exp, log, exp10f etc (because they are
typically optimised in various ways).

exp10f() is not part of the C99 standard, yet is is part of numerics
extensions for an upcoming C standard. As far as I can see, it is
available in the STDLIB on modern Linux systems. But in all systems
where I checked, the CMake build did not detect that, leading to
HAVE_EXP10F being undefined; so the compile will then fall back
to our old friend expf(10.0f, ...).


Thus, right now I see several Options for a refactoring...

Option-1 : only apply the refactoring discussed thus far, i.e.
           replace powf() by a expf() with a precomputed constant
           logarithm factor. This would also apply within db2rap().

Option-2 : also create a new front-end function for all volume factors,
           and thereby rationalise all those various magic numbers and
           differing formulations. Instead, the actual dB value would
           now be obvious at usage site.

Option-3 : additionally send all those usages (through the new front-end)
           through the db2rap() function. Which means, the problem with
           exp10f not being detected would even be expanded in scope

Option-4 : get rid of the HAVE_EXP10F branching and use the optimised
           exp()-of-logarithm everywhere. (Rationale: most people building
           with CMake would have gotten the powf() branch in past anyway)

Option-5 : use doubles internally for calculating the exp() and the
           precomputed logarithm, just return a float value.
           Benefits:
            * more precise values everywhere
            * less difference between -O0 and -O3
           Drawbacks:
            * this would change computed samples under -O3
               order of Magnitude: -123dB
               (smallest value of float mantissa is 20*lg(2^-23) = -138dB)
            * /might/ have a performance impact (rather unlikely on modern CPU)


Right now, personally I am leaning towards Option-4
(and maybe revisit Option-5 later)


Let's have a look at some numbers!
What follows is the output of a small test program,
computing some common decibel factors. For one, we compute...
10^-exponent  vs powf(10, -exponent)
1/10^exponent vs powf(0.1, exponent)
And additionally exp10f(-exponent)

And this with -O0, -03  and then computing with doubles -O0 and -O3

CompileFlags:
-std=gnu++11 -march=athlon64 -m64 -msse -msse2 -mfpmath=sse -ffast-math -fno-finite-math-only -fomit-frame-pointer -g3 -ggdb


Observations:
 * the optimised exp()-from-precomputed-log always
   yields same values for 10^-exponent vs 1/10^exponent
 * the powf() differs with -O3
 * using doubles in our optimised variant yields same values as exp10f


## float with -O0 ##

======  -20dB
1/10^v  =    0.099999994        |powf:     0.100000001
10^-v   =    0.099999994        |powf:     0.100000001
                                |exp10f    0.100000001

======  -40dB
1/10^v  =  0.00999999978        |powf:    0.0100000007
10^-v   =  0.00999999978        |powf:   0.00999999978
                                |exp10f  0.00999999978

======  -60dB
1/10^v  = 0.000999999931        |powf:   0.00100000005
10^-v   = 0.000999999931        |powf:   0.00100000005
                                |exp10f  0.00100000005

======  -100dB
1/10^v  = 9.99999338e-06        |powf:  1.00000007e-05
10^-v   = 9.99999338e-06        |powf:  9.99999975e-06
                                |exp10f 9.99999975e-06



## float with -O3 ##

======  -20dB
1/10^v  =    0.099999994        |powf:     0.099999994
10^-v   =    0.099999994        |powf:     0.099999994
                                |exp10f    0.100000001

======  -40dB
1/10^v  =  0.00999999978        |powf:   0.00999999978
10^-v   =  0.00999999978        |powf:   0.00999999978
                                |exp10f  0.00999999978

======  -60dB
1/10^v  = 0.000999999931        |powf:  0.000999999931
10^-v   = 0.000999999931        |powf:  0.000999999931
                                |exp10f  0.00100000005

======  -100dB
1/10^v  = 9.99999338e-06        |powf:  9.99999338e-06
10^-v   = 9.99999338e-06        |powf:  9.99999338e-06
                                |exp10f 9.99999975e-06



## double with -O0 ##

======  -20dB
1/10^v  =    0.100000001        |powf:     0.100000001
10^-v   =    0.100000001        |powf:     0.100000001
                                |exp10f    0.100000001

======  -40dB
1/10^v  =  0.00999999978        |powf:    0.0100000007
10^-v   =  0.00999999978        |powf:   0.00999999978
                                |exp10f  0.00999999978

======  -60dB
1/10^v  =  0.00100000005        |powf:   0.00100000005
10^-v   =  0.00100000005        |powf:   0.00100000005
                                |exp10f  0.00100000005

======  -100dB
1/10^v  = 9.99999975e-06        |powf:  1.00000007e-05
10^-v   = 9.99999975e-06        |powf:  9.99999975e-06
                                |exp10f 9.99999975e-06



## double with -O3 ##

======  -20dB
1/10^v  =    0.100000001        |powf:     0.099999994
10^-v   =    0.100000001        |powf:     0.099999994
                                |exp10f    0.100000001

======  -40dB
1/10^v  =  0.00999999978        |powf:   0.00999999978
10^-v   =  0.00999999978        |powf:   0.00999999978
                                |exp10f  0.00999999978

======  -60dB
1/10^v  =  0.00100000005        |powf:  0.000999999931
10^-v   =  0.00100000005        |powf:  0.000999999931
                                |exp10f  0.00100000005

======  -100dB
1/10^v  = 9.99999975e-06        |powf:  9.99999338e-06
10^-v   = 9.99999975e-06        |powf:  9.99999338e-06
                                |exp10f 9.99999975e-06



_______________________________________________
Yoshimi-devel mailing list
Yoshimi-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/yoshimi-devel

Reply via email to