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