Wow, that was quick!

It can be so simple. So you intialize the value to -DBL_MAX now? It
think it should rather be zero, though. The power computation starts
with the maximum of the mean squared sample values and only at the end
is converted to decibel scale with values ≤ 0 (only rounding errors
triggering values > 0). See lines 219-220:

  /* scale the pow value to be in the range 0.0 -- 1.0 */
  ds.maxpow = ds.maxpow / (samplemin * (double)samplemin);

I suspect samplemin is 32768 for 16 bit data here … ah, yes, it's
-32768. Probably starting with a negative value is fine, but I do
wonder what happens with an empty MP3 file:

$ echo -n | out123 -w nothing.wav
$ lame nothing.wav
LAME 3.100 64bits (http://lame.sf.net)
Using polyphase lowpass filter, transition band: 16538 Hz - 17071 Hz
Encoding nothing.wav to nothing.mp3
Encoding as 44.1 kHz j-stereo MPEG-1 Layer III (11x) 128 kbps qval=3
    Frame          |  CPU time/estim | REAL time/estim | play/CPU |    ETA 
     1/1     (100%)|    0:00/    0:00|    0:00/    0:00|   109.30x|    0:00 
---------------------------------------------------------------------------------------------------------------------------------------------------------------------
   kbps        MS  %     long  %
  128.0      100.0       100.0
Writing LAME Tag...done
ReplayGain: 0.0dB

Arguably, 0 dB is the correct gain for nothing, without getting
philosophical. Now, just for fun, what does the faulty normalize-audio
do?

$ LANG=C normalize-audio -n nothing.mp3 
Computing levels...
  level        peak         gain
normalize-audio: error reading nothing.mp3: Numerical argument out of domain
$ LANG=C normalize-audio -n nothing.mp3 
Computing levels...
  level        peak         gain
618.7626dBFS -infdBFS     -630.7626dB nothing.mp3                          
$ LANG=C normalize-audio -n nothing.mp3 
Computing levels...
  level        peak         gain
920.3700dBFS -infdBFS     -932.3700dB nothing.mp3                          
$ LANG=C normalize-audio -n nothing.mp3 
Computing levels...
  level        peak         gain
normalize-audio: error reading nothing.mp3: Numerical argument out of domain
$ LANG=C normalize-audio -n nothing.mp3 
Computing levels...
  level        peak         gain
File nothing.mp3 has zero power, ignoring...                               

Ah, at last! This test case very clearly shows the differing
intialization values, even sometimes evaluating to zero. The error
about failed read of nothing.mp3 probably comes from the callback
structure of the libmad API … (still weird)

Anyhow, when I set ds.maxpow = -DBL_MAX:

$ LANG=C src/normalize -n nothing.mp3 
Computing levels...
  level        peak         gain
normalize: error reading nothing.mp3: Numerical argument out of domain:00) 

This is not a good result. With ds.maxpow = 0:

$ LANG=C src/normalize -n nothing.mp3 
Computing levels...
  level        peak         gain
File nothing.mp3 has zero power, ignoring...                               

This is what should happen. It also makes a lot more sense for the
memory usually being intialized to zero for most builds. This obvious
error wouldn't have gone unnoticed for _decades_ otherwise.

So, what does the Debian build do to make the ds struct _not_ zeroed at
the beginning? It's interesting that 'luck' worked since the early
2000s to have that uninitialized initial power value be zero by chance,
and only recently this got broken, and that also only on my machine,
not yours.

Maybe you can better reproduce it with the empty mp3 file? I guess some
hardening, memory randomization is to blame. Maybe that's only active
for Ubuntu and not stock Debian libc/kernel … but it does trigger with
Debian's binary.

So, the proper fix should be intializing ds.maxpow = 0 so that the
correct/expected result is computed also for empty input.


Alrighty then,

Thomas

PS: Is upstream clearly dead? Chis Vaill is still listed as 'active' on
https://savannah.nongnu.org/project/memberlist.php?group=normalize
Would be nice to get an official version 0.7.8.

Reply via email to