mpg123 is a
real time MPEG 1.0/2.0/2.5 audio player/decoder for layers 1,2 and 3 (MPEG 1.0 layer 3 aka MP3 most commonly tested).
Among others working with Linux, MacOSX, FreeBSD, SunOS4.1.3, Solaris 2.5, HPUX 9.x, SGI Irix and Cygwin or plain MS Windows.
It is free software licensed under LGPL 2.1 (the officially released sources, some files in subversion repository may differ).
Improved portability of SSE code (with speed improvement, even), windows network streaming (merged into trunk), lower levels of API... simple audio output library using mpg123's output plugins... stuff.
The optional large file support on Linux/Solaris still troubles the mpg123 project. Of course the troubles started with me unwittingly choosing to expose off_t in the API. From mpg123-1.5.0 on up to the recently released 1.10.1, I at least opted to prevent runtime damage by renaming API functions according to the selection in large file support. This, again, is not a good idea when leaving the library name unchanged: A new build with large file support actually exposes a different ABI and thus is not compatible with an old binary.
So, here is my second attempt on getting the situation predictable: Not just some symbols, the whole library gets renamed when large file support is enabled. You get libmpg123_64 instead of libmpg123. That means a one-time incompatible switch for any binary that depends on a libmpg123 with 64 bit file offsets (on the affected systems), but it preserves compatibility for older and future binaries that depend on "default" file offset size (that is, 32 bit on a 32 bit Linux system). It hurts once, but after the switch, we have, if not a pretty, but at least predictable vision of the future.
If nobody comes up with a better idea (no, supporting 32 bit and 64 bit offsets in one build is not considered better... it's not worth the maintenance work and is error-prone, in my view), the next release of mpg123 will bring the change of library name depending on enabled large file support.
So please test it and be prepared, perhaps give some comments about it: mpg123-1.11.0 preview for the large file name change
To all users of systems that are not sensitive to variable off_t size (most non-Linux/Solaris, 64 bit systems): Be happy and do not worry about this mess. For anyone who wants to worry and understand the issue, have a read of Guido Draheim's work on the matter.
And, not to forget, there are other goodies with mpg123-1.11.0: Also concerning portability and ABI stability, the SSE code does not rely on aligned variables on the stack anymore.
At least that is the idea behind doing all explicit alignments now on the heap with pointer arithmetic -- as a side effect, I have seen speedup from that change, too.
Then, we got enhancements of the networking code, enabling network streams for plain Windows builds (MinGW) and fixing sub-optimal behaviour with respect to IPv6 (not asking for IPv6 name resolution unless there are IPv6 interfaces configured).
For older news see the news archive
This is a rough log of an automated compliance test on the mpg123 webserver (Athlon-XP, GNU/Linux), using each one test bitstream from the ISO MPEG reference set. At least the floating point output should really be close enough to the reference.
Regarding the method: This is comparing mpg123's output (with gapless code deactivated) from reference bitstreams to the reference output. A simple RMS error measure is employed, relative to full scale, just summing over mono or stereo data indiscriminently. This is my interpretation of the rules... maximum allowed RMS=8.80967e-06, maximum signal difference 6.10352e-05.
compliance test for mpg123-20100311000000 First decoder in this list will be tested first, then generic: Supported decoders: SSE 3DNowExt 3DNow MMX i586 i586_dither i386 generic generic_dither Testing default decoder... ==== Layer 1 ==== --> 16 bit signed integer output fl1.bit: RMS=4.364373e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl2.bit: RMS=4.353138e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl3.bit: RMS=4.348759e-06 (PASS) maxdiff=7.688999e-06 (PASS) fl4.bit: RMS=4.403421e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl5.bit: RMS=4.323457e-06 (PASS) maxdiff=7.688999e-06 (PASS) fl6.bit: RMS=4.389618e-06 (PASS) maxdiff=7.688999e-06 (PASS) fl7.bit: RMS=3.826083e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl8.bit: RMS=4.362205e-06 (PASS) maxdiff=7.629395e-06 (PASS) --> 32 bit integer output fl1.bit: RMS=1.966499e-08 (PASS) maxdiff=1.518056e-07 (PASS) fl2.bit: RMS=1.971040e-08 (PASS) maxdiff=1.117587e-07 (PASS) fl3.bit: RMS=2.002126e-08 (PASS) maxdiff=1.378357e-07 (PASS) fl4.bit: RMS=1.903406e-08 (PASS) maxdiff=1.266599e-07 (PASS) fl5.bit: RMS=3.629701e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl6.bit: RMS=3.123047e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl7.bit: RMS=1.768818e-08 (PASS) maxdiff=8.568168e-08 (PASS) fl8.bit: RMS=1.857690e-08 (PASS) maxdiff=8.568168e-08 (PASS) --> 32 bit floating point output fl1.bit: RMS=1.966507e-08 (PASS) maxdiff=1.518056e-07 (PASS) fl2.bit: RMS=1.971032e-08 (PASS) maxdiff=1.117587e-07 (PASS) fl3.bit: RMS=2.002131e-08 (PASS) maxdiff=1.378357e-07 (PASS) fl4.bit: RMS=1.903395e-08 (PASS) maxdiff=1.266599e-07 (PASS) fl5.bit: RMS=3.629702e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl6.bit: RMS=3.123049e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl7.bit: RMS=1.768797e-08 (PASS) maxdiff=8.568168e-08 (PASS) fl8.bit: RMS=1.857691e-08 (PASS) maxdiff=8.568168e-08 (PASS) ==== Layer 2 ==== --> 16 bit signed integer output fl10.bit: RMS=3.512100e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl11.bit: RMS=3.837267e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl12.bit: RMS=3.901071e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl13.bit: RMS=4.379583e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl14.bit: RMS=4.112578e-06 (PASS) maxdiff=7.688999e-06 (PASS) fl15.bit: RMS=4.388568e-06 (PASS) maxdiff=7.688999e-06 (PASS) fl16.bit: RMS=4.147495e-06 (PASS) maxdiff=7.688999e-06 (PASS) --> 32 bit integer output fl10.bit: RMS=1.777913e-08 (PASS) maxdiff=8.381903e-08 (PASS) fl11.bit: RMS=1.789437e-08 (PASS) maxdiff=9.313226e-08 (PASS) fl12.bit: RMS=1.780945e-08 (PASS) maxdiff=8.195639e-08 (PASS) fl13.bit: RMS=1.760690e-08 (PASS) maxdiff=4.470348e-08 (PASS) fl14.bit: RMS=3.641389e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl15.bit: RMS=2.416479e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl16.bit: RMS=1.922802e-08 (PASS) maxdiff=1.490116e-07 (PASS) --> 32 bit floating point output fl10.bit: RMS=1.777907e-08 (PASS) maxdiff=8.381903e-08 (PASS) fl11.bit: RMS=1.789437e-08 (PASS) maxdiff=9.313226e-08 (PASS) fl12.bit: RMS=1.780943e-08 (PASS) maxdiff=8.195639e-08 (PASS) fl13.bit: RMS=1.760693e-08 (PASS) maxdiff=4.470348e-08 (PASS) fl14.bit: RMS=3.641389e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl15.bit: RMS=2.416472e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl16.bit: RMS=1.922769e-08 (PASS) maxdiff=1.490116e-07 (PASS) ==== Layer 3 ==== --> 16 bit signed integer output compl.bit: RMS=4.300908e-06 (PASS) maxdiff=7.688999e-06 (PASS) --> 32 bit integer output compl.bit: RMS=1.904423e-08 (PASS) maxdiff=1.415610e-07 (PASS) --> 32 bit floating point output compl.bit: RMS=1.904423e-08 (PASS) maxdiff=1.415610e-07 (PASS) Now the generic decoder: ==== Layer 1 ==== --> 16 bit signed integer output fl1.bit: RMS=4.364373e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl2.bit: RMS=4.353138e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl3.bit: RMS=4.348747e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl4.bit: RMS=4.403421e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl5.bit: RMS=4.323446e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl6.bit: RMS=4.389573e-06 (PASS) maxdiff=7.688999e-06 (PASS) fl7.bit: RMS=3.826083e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl8.bit: RMS=4.362205e-06 (PASS) maxdiff=7.629395e-06 (PASS) --> 32 bit integer output fl1.bit: RMS=1.852264e-08 (PASS) maxdiff=1.129229e-07 (PASS) fl2.bit: RMS=1.858920e-08 (PASS) maxdiff=9.639189e-08 (PASS) fl3.bit: RMS=1.860519e-08 (PASS) maxdiff=9.080395e-08 (PASS) fl4.bit: RMS=1.827816e-08 (PASS) maxdiff=9.802170e-08 (PASS) fl5.bit: RMS=3.011849e-08 (PASS) maxdiff=1.245644e-07 (PASS) fl6.bit: RMS=2.662860e-08 (PASS) maxdiff=1.455192e-07 (PASS) fl7.bit: RMS=1.738850e-08 (PASS) maxdiff=8.288771e-08 (PASS) fl8.bit: RMS=1.799578e-08 (PASS) maxdiff=8.079223e-08 (PASS) --> 32 bit floating point output fl1.bit: RMS=1.853064e-08 (PASS) maxdiff=1.126900e-07 (PASS) fl2.bit: RMS=1.860675e-08 (PASS) maxdiff=9.685755e-08 (PASS) fl3.bit: RMS=1.861782e-08 (PASS) maxdiff=9.080395e-08 (PASS) fl4.bit: RMS=1.829747e-08 (PASS) maxdiff=9.685755e-08 (PASS) fl5.bit: RMS=3.145808e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl6.bit: RMS=2.694313e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl7.bit: RMS=1.740548e-08 (PASS) maxdiff=8.940697e-08 (PASS) fl8.bit: RMS=1.800653e-08 (PASS) maxdiff=8.195639e-08 (PASS) ==== Layer 2 ==== --> 16 bit signed integer output fl10.bit: RMS=3.512100e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl11.bit: RMS=3.837267e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl12.bit: RMS=3.901071e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl13.bit: RMS=4.379583e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl14.bit: RMS=4.112572e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl15.bit: RMS=4.388568e-06 (PASS) maxdiff=7.688999e-06 (PASS) fl16.bit: RMS=4.147492e-06 (PASS) maxdiff=7.688999e-06 (PASS) --> 32 bit integer output fl10.bit: RMS=1.753398e-08 (PASS) maxdiff=9.825453e-08 (PASS) fl11.bit: RMS=1.761345e-08 (PASS) maxdiff=8.195639e-08 (PASS) fl12.bit: RMS=1.753216e-08 (PASS) maxdiff=7.753260e-08 (PASS) fl13.bit: RMS=1.748657e-08 (PASS) maxdiff=4.121102e-08 (PASS) fl14.bit: RMS=2.851873e-08 (PASS) maxdiff=1.147855e-07 (PASS) fl15.bit: RMS=2.142128e-08 (PASS) maxdiff=1.455192e-07 (PASS) fl16.bit: RMS=1.823392e-08 (PASS) maxdiff=9.615906e-08 (PASS) --> 32 bit floating point output fl10.bit: RMS=1.755612e-08 (PASS) maxdiff=9.872019e-08 (PASS) fl11.bit: RMS=1.763760e-08 (PASS) maxdiff=8.195639e-08 (PASS) fl12.bit: RMS=1.754899e-08 (PASS) maxdiff=7.823110e-08 (PASS) fl13.bit: RMS=1.750654e-08 (PASS) maxdiff=4.097819e-08 (PASS) fl14.bit: RMS=2.884949e-08 (PASS) maxdiff=1.148474e-07 (PASS) fl15.bit: RMS=2.161260e-08 (PASS) maxdiff=1.452863e-07 (PASS) fl16.bit: RMS=1.831598e-08 (PASS) maxdiff=9.685755e-08 (PASS) ==== Layer 3 ==== --> 16 bit signed integer output compl.bit: RMS=4.300908e-06 (PASS) maxdiff=7.688999e-06 (PASS) --> 32 bit integer output compl.bit: RMS=1.878697e-08 (PASS) maxdiff=1.431908e-07 (PASS) --> 32 bit floating point output compl.bit: RMS=1.880739e-08 (PASS) maxdiff=1.415610e-07 (PASS)
Depending on what integer quality mode you choose at compile time (and the decoder in use), the 16bit output can vary between PASS and LIMITED for fully or limited accuracy compliance.
But keep in mind:
For the integer output, you have to give +-1 for rounding... that's what I append to any integer number read from some measurement device anyway, by default.
That minimum possible deviation already brings the output close (or over) the border of full compliance... that really does not mean that the output sounds bad!
It shall be noted that a measure to improve subjective quality, namely the dithering before rounding to integers, can also increase the theoretical decoding error.
In the end, RMS values in the order of 10 to the power of -5 should sound just fine.
To get 16bit output to PASS, you usually need to enable proper rounding using the --enable-int-quality configure flag.
It is not on by default because it mostly (yeah, there are odd cases) needs somewhat more CPU time and the simple truncation is fine for most people...
For comparisong with other decoders (as well as older incarnations of the mpg123 engine), have a read of the Underbit compliance tests. Actually, my testing method follows that example, including their quoting of ISO MPEG rules.
A test (GNU/Linux OS) with 0.60-beta2 showed 3% to 4% CPU usage on decoding high quality VBR MP3 with a pentiumII laptop with 366MHz, while a pentium 100MHz can easily handle two mpg123 instances in realtime (plus the mixing daemon that works on decoded data).
Also, we have reports from such devices as nintendo DS or Sony PSP, or various embedded systems...
Plays Layer 3 in stereo on an AMD-486-120Mhz or (of course) a faster machine.
Just for info: mpg123 plays an average 128bps stream, with about 66%
in full quality on an AMD 486-133MHz machine.