mpg123 - Fast console MPEG Audio Player and decoder library
The mpg123 distribution contains a real time MPEG 1.0/2.0/2.5 audio player/decoder for layers 1,2 and 3 (most commonly MPEG 1.0 layer 3 aka MP3), as well as re-usable decoding and output libraries. Among others, it works on GNU/Linux, MacOSX, the BSDs, Solaris, AIX, HPUX, SGI Irix, OS/2 and Cygwin or plain MS Windows (not all more exotic platforms tested regularily, but patches welcome). You may jump to the non-exhaustive list of features.
It is free software licensed under LGPL 2.1 .
Note that nowadays, the mpg123 decoder core can work with floating point or integer math and with some tuning between accuracy and performance at build-time, using assembly optimizations for several platforms, depending on your build configuration. There is detection and selection of assembly optimisations on x86, x86-64, and ARM at program runtime. It's fast, it's high-quality. Just use it;-)
Top News
- scripts/tag_lyrics.py: fix for python3 (thanks to cclauss, github PR 16)
- libout123: Use strtok_r() to avoid conflicts multithreaded contexts (both sides should avoid plain strtok()! Debian-bug 1089543).
-
libmpg123:
- Un-break DLL builds that need I/O functions defined in libmpg123.c (like mpg123_open(), bug 374).
- ports/cmake: More fixup to also produce .pc files with Libs.private.
Head over to the download section for getting your hands on the release.
Here comes just a small followup to the release fixing CVE-2024-10573. I forgot to increase the reported library patchlevel last time and a build improvement for MSVCRT also went in.
-
libmpg123:
- enable 64 bit offset path for MSVCRT and avoid warnings about MS's game about POSIX API with and without underscores (bug 373).
- Increase the library patchlevel, as was forgotten on previous release. Now you can check for distversion >= 1.32.8 or mpg123 libversion >= 48 patchlevel 3 to see if you're vulnerable to CVE-2024-10573.
Head over to the download section for getting your hands on the release.
Update: The buffer overflow got assigned the CVE ID CVE-2024-10573.
This is an important security update! There is possible buffer overflow (writing of decoded
PCM samples beyond allocated output buffer) for streams that change output properties together
with certain usage of libmpg123. This needed seeking around in the stream (including scanning
it before actual decoding) to trigger. So, your usual web radio stream as obvious attack
vector is unlikely, as you won't seek around in it. If you do work with stream dumps,
usage of MPG123_NO_FRANKENSTEIN
or the --no-frankenstein
option to the mpg123 application is a workaround to avoid
the formerly dangerous situation in earlier mpg123 releases. This also means that mpg123
will not decode streams of concatenated files with either varying format or leading Info frames
past the first track anymore.
With this release, the parser has been improved not to store certain stream properties before actual MPEG frame data matching that property has been stored. This avoids the inconsistency that triggered the overflow. Also note that if you always use a fixed decoding buffer for full stereo of the maximum of 1152 samples per frame, times two and your choice of encoding, your application is also not susceptible.
Exploitation of this is not trivial, but I cannot rule out the possibility of gaining code execution. Your exploit payload needs to pass through an MPEG decoder and PCM synth before possibly reaching the CPU. Some heap corruption can follow at the least. So update or mitigate. If you run 1.32.x, there is no excuse not to get the the latest bugfix release now. Basically any version of mpg123 is affected by this, at least those that explicitly support so-called Frankenstein streams.
-
libmpg123:
- Add sections to assembly to support PAC/BTI code for aarch64 (-mbranch-protection variants), thanks to Bill Roberts (github PR 15).
- Prevent premature application of header info into decoding structure, at worst having triggered out-of-bounds writes of decoded PCM data (bug 322, again).
- out123: Show --quiet in --longhelp.
Head over to the download section for getting your hands on the release.
- ports/cmake: Work around bug in CMake that does not detect FPU on Apple ARM CPUs (github PR 14).
- Fix some laziness (func() to func(void)) for standards conformance.
Head over to the download section for getting your hands on the release.
- build: Detect forced 64 bit offsets on a dual-mode system that used to default to 32 bits and drop ambiguous suffix-less symbols in that case. This avoids subtle ABI breakage (causing memory corruption) with existing binaries and instead has them fail during runtime linking. You trigger that when having -D_FILE_OFFSET_BITS=64 in your compiler flags during mpg123 build.
Head over to the download section for getting your hands on the release.
- build:
- libmpg123:
Head over to the download section for getting your hands on the release.
-
build:
- Reorganize shared headers, API headers into src/include.
- Use relative include paths, avoiding internal directories in CPPFLAGS except for config.h.
- Group C99 feature checks and make several standard headers mandatory.
- Get rid of SIZE_P, OFF_P and friends.
- Only enforce dummy module together with libout123, to be able to build individual modules using --disable-components logic.
-
out123:
- added --libversion
-
libmpg123:
- Avoid indirect branches into the assembly routines by using C wrappers also for dct36, relieving us of the need to care for bti / endbr instructions for control flow integrity.
Head over to the download section for getting your hands on the release.
- ports/cmake: Only enable modules with GetThreadErrorMode() on Windows.
- compat: Define EOVERFLOW for ancient Windows toolchains.
- libmpg123, libsyn123: always ifdef LFS_LARGEFILE_64 (not just if)
- libsyn123: re-introduce _32 wrappers in addition to suffix-less ones (regression from 1.31, bug 363)
This finally is, hopefully, the release to replace 1.31.x. This was a rough ride due to largefile API/ABI stuff being just … horror. I really, really, hope that I won't have to rework that another time.
Head over to the download section for getting your hands on the release.
- libmpg123: Re-introduce _64 symbols on native 64 bit offset platforms. This was a regression since 1.31 series. Sorry, too much cleanup, not enough testing.
-
build:
- Better O_LARGEFILE logic, avoiding redefintion.
- ports/cmake:
Head over to the download section for getting your hands on the release.
- Include man pages again in tarball and install. We cannot avoid the empty man directory when disabling programs with autoconf.
- Fix signal handler prototype, avoiding some justified warnings.
-
ports/cmake:
- Include CheckTypeSize, which seems to be needed sometimes (bug 357).
- Avoid O_LARGEFILE redefinition, logic closer to autoconf.
Head over to the download section for getting your hands on the release.
-
build:
- Move version handling out of configure.ac to ease other build systems.
- Include "fmt123.h" instead of <fmt123.h> in main API headers to make it more likely the correct one is included (at least gcc picks the one in the same directory as the including header first).
- All headers are build-independent now.
-
Fix build for picky linkers by avoiding definition of
wrap_getcpuflags()
where it is not used (spurious linker error to non-exitentgetcpuflags()
, bug 353). - Handle deprecation of C99 detection macro in autoconf 2.70.
- No use of AC_SYS_LARGEFILE anymore for explicit handling and differing choice for the libraries and frontend programs.
-
Added
--enable-portable
and--disable-largefile
to configure, removing the other largefile-related options. -
Added
--disable-components --enable-libmpg123
to only build libmpg123 (and likewise--enable-libout123
,--enable-libout123-modules
,--enable-libsyn123
) to autoconf build. CMake build has something similar with BUILD_PROGRAMS and BUILD_LIBOUT123, which leave only libmpg123 and libsyn123 if disabled). (bug 351) -
Consistent formatting of
./configure --help
with AS_HELP_STRING().
- ports/Sony_PSP: removed
-
mpg123:
-
Added
--libversion
. -
Added proper A-B looping with terminal control key 'o', renamed
--pauseloop
to--presetloop
. -
Really get rid of
mpg123_position()
usage. (It was all lies before!) - Fix terminal progress info when seeking in stopped mode (1.31 regression).
- Patch up interaction of output buffer with generic remote control, adding non-interruptible drain after P 3, and dropping buffer on QUIT.
- Uppercase some generic control replies for consinstency: SILENCE, PROGRESS, MUTE, UNMUTE
-
Added
-
libmpg123, libout123, libsyn123:
- Bumped API version for version query functions.
- Replaced nearly all symbol renames with explicit INT123_ prefix declarations (intsym.h close to empty now).
-
libout123:
- Add sleep builtin output module (silent, but proper timing).
-
libsyn123:
- Introduced SYN123_PORTABLE_API for an API without off_t and ssize_t (see NEWS.libsyn123).
-
libmpg123:
- Internal I/O using explicit largefile support via off64_t, lseek64, fallback to plain 32 bit off_t.
-
Added explicit 64 bit API with 64 suffix (
mpg123_tell64()
, notmpg123_tell_64()
). This allows full avoidance of ambiguus off_t. The API is always using 64 bit integers, regardless of internal implementation. (bug 344) - Introduced MPG123_PORTABLE_API for an API subset without off_t and ssize_t.
-
Made
mpg123_seek()
and friends ignore offset sign for SEEK_END (always seeking towards beginning, assuming negative offset) to make lseek()-conforming usage possible. Seeking beyond the end never made sense, so no loss of valid functionality.
-
Overall use of
INT123_strerror()
, trying to use thread-safestrerror_l()
if possible.
Head over to the download section for getting your hands on the release.
For older news see the news archive
ISO MPEG compliance
This is a rough log of an automated compliance test on the mpg123 webserver (Xeon E3, GNU/Linux), using the test bitstreams 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-1.32.10-dev+20241228022201 on Linux x86_64 First decoder in this list will be tested first, then generic: Supported decoders: AVX x86-64 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.323446e-06 (PASS) maxdiff=7.629395e-06 (PASS) fl6.bit: RMS=4.389602e-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.967634e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl2.bit: RMS=1.971686e-08 (PASS) maxdiff=1.117587e-07 (PASS) fl3.bit: RMS=2.002386e-08 (PASS) maxdiff=1.341105e-07 (PASS) fl4.bit: RMS=1.902169e-08 (PASS) maxdiff=1.266599e-07 (PASS) fl5.bit: RMS=3.655859e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl6.bit: RMS=3.069318e-08 (PASS) maxdiff=1.629815e-07 (PASS) fl7.bit: RMS=1.768833e-08 (PASS) maxdiff=8.940697e-08 (PASS) fl8.bit: RMS=1.857219e-08 (PASS) maxdiff=8.428469e-08 (PASS) --> 24 bit integer output fl1.bit: RMS=4.096055e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl2.bit: RMS=4.156199e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl3.bit: RMS=4.126996e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl4.bit: RMS=4.100406e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl5.bit: RMS=4.574976e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl6.bit: RMS=3.920292e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl7.bit: RMS=4.186568e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl8.bit: RMS=4.104751e-08 (PASS) maxdiff=1.192093e-07 (PASS) --> 32 bit floating point output fl1.bit: RMS=1.967635e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl2.bit: RMS=1.971679e-08 (PASS) maxdiff=1.117587e-07 (PASS) fl3.bit: RMS=2.002391e-08 (PASS) maxdiff=1.341105e-07 (PASS) fl4.bit: RMS=1.902160e-08 (PASS) maxdiff=1.266599e-07 (PASS) fl5.bit: RMS=3.655860e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl6.bit: RMS=3.069316e-08 (PASS) maxdiff=1.629815e-07 (PASS) fl7.bit: RMS=1.768828e-08 (PASS) maxdiff=8.940697e-08 (PASS) fl8.bit: RMS=1.857223e-08 (PASS) maxdiff=8.428469e-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.777418e-08 (PASS) maxdiff=8.475035e-08 (PASS) fl11.bit: RMS=1.789150e-08 (PASS) maxdiff=9.685755e-08 (PASS) fl12.bit: RMS=1.780872e-08 (PASS) maxdiff=8.940697e-08 (PASS) fl13.bit: RMS=1.760690e-08 (PASS) maxdiff=4.470348e-08 (PASS) fl14.bit: RMS=3.361258e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl15.bit: RMS=2.414684e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl16.bit: RMS=1.924891e-08 (PASS) maxdiff=1.192093e-07 (PASS) --> 24 bit integer output fl10.bit: RMS=4.086103e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl11.bit: RMS=4.098320e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl12.bit: RMS=4.095125e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl13.bit: RMS=4.108581e-08 (PASS) maxdiff=5.960464e-08 (PASS) fl14.bit: RMS=4.444728e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl15.bit: RMS=4.098525e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl16.bit: RMS=4.146825e-08 (PASS) maxdiff=1.192093e-07 (PASS) --> 32 bit floating point output fl10.bit: RMS=1.777416e-08 (PASS) maxdiff=8.475035e-08 (PASS) fl11.bit: RMS=1.789151e-08 (PASS) maxdiff=9.685755e-08 (PASS) fl12.bit: RMS=1.780868e-08 (PASS) maxdiff=8.940697e-08 (PASS) fl13.bit: RMS=1.760693e-08 (PASS) maxdiff=4.470348e-08 (PASS) fl14.bit: RMS=3.361258e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl15.bit: RMS=2.414676e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl16.bit: RMS=1.924847e-08 (PASS) maxdiff=1.192093e-07 (PASS) ==== Layer 3 ==== --> 16 bit signed integer output compl.bit: RMS=4.300912e-06 (PASS) maxdiff=7.688999e-06 (PASS) --> 32 bit integer output compl.bit: RMS=2.104434e-08 (PASS) maxdiff=1.881272e-07 (PASS) --> 24 bit integer output compl.bit: RMS=4.170551e-08 (PASS) maxdiff=2.384186e-07 (PASS) --> 32 bit floating point output compl.bit: RMS=2.104434e-08 (PASS) maxdiff=1.881272e-07 (PASS) ==== Layer 3 intensity stereo ==== (no official reference, comparing to mpg123 generic 24 bit) --> 16 bit signed integer output drumshort08kHz.bit: RMS=4.348691e-06 (PASS) maxdiff=7.629395e-06 (PASS) drumshort24kHz.bit: RMS=4.365981e-06 (PASS) maxdiff=7.688999e-06 (PASS) drumshort48kHz.bit: RMS=4.375106e-06 (PASS) maxdiff=8.106232e-06 (PASS) mono-is-ms.bit: RMS=4.389831e-06 (PASS) maxdiff=7.688999e-06 (PASS) --> 32 bit integer output drumshort08kHz.bit: RMS=3.281180e-08 (PASS) maxdiff=1.043081e-07 (PASS) drumshort24kHz.bit: RMS=3.282391e-08 (PASS) maxdiff=1.192093e-07 (PASS) drumshort48kHz.bit: RMS=4.068793e-08 (PASS) maxdiff=6.854534e-07 (PASS) mono-is-ms.bit: RMS=3.511104e-08 (PASS) maxdiff=2.197921e-07 (PASS) --> 24 bit integer output drumshort08kHz.bit: RMS=3.600636e-09 (PASS) maxdiff=5.960464e-08 (PASS) drumshort24kHz.bit: RMS=2.518008e-09 (PASS) maxdiff=1.192093e-07 (PASS) drumshort48kHz.bit: RMS=2.917921e-08 (PASS) maxdiff=7.152557e-07 (PASS) mono-is-ms.bit: RMS=1.635551e-08 (PASS) maxdiff=1.788139e-07 (PASS) --> 32 bit floating point output drumshort08kHz.bit: RMS=3.281174e-08 (PASS) maxdiff=1.043081e-07 (PASS) drumshort24kHz.bit: RMS=3.282395e-08 (PASS) maxdiff=1.192093e-07 (PASS) drumshort48kHz.bit: RMS=4.068791e-08 (PASS) maxdiff=6.854534e-07 (PASS) mono-is-ms.bit: RMS=3.511108e-08 (PASS) maxdiff=2.197921e-07 (PASS) ==== Overall result ==== PASS (limited or full) 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.348759e-06 (PASS) maxdiff=7.688999e-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.389641e-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.977733e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl2.bit: RMS=1.980311e-08 (PASS) maxdiff=1.117587e-07 (PASS) fl3.bit: RMS=2.006633e-08 (PASS) maxdiff=1.341105e-07 (PASS) fl4.bit: RMS=1.911986e-08 (PASS) maxdiff=1.266599e-07 (PASS) fl5.bit: RMS=4.047884e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl6.bit: RMS=3.178246e-08 (PASS) maxdiff=1.639128e-07 (PASS) fl7.bit: RMS=1.775744e-08 (PASS) maxdiff=1.043081e-07 (PASS) fl8.bit: RMS=1.866297e-08 (PASS) maxdiff=8.195639e-08 (PASS) --> 24 bit integer output fl1.bit: RMS=4.119282e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl2.bit: RMS=4.184623e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl3.bit: RMS=4.153068e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl4.bit: RMS=4.118697e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl5.bit: RMS=4.816338e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl6.bit: RMS=4.047773e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl7.bit: RMS=4.191854e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl8.bit: RMS=4.106042e-08 (PASS) maxdiff=1.192093e-07 (PASS) --> 32 bit floating point output fl1.bit: RMS=1.977741e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl2.bit: RMS=1.980280e-08 (PASS) maxdiff=1.117587e-07 (PASS) fl3.bit: RMS=2.006633e-08 (PASS) maxdiff=1.341105e-07 (PASS) fl4.bit: RMS=1.911983e-08 (PASS) maxdiff=1.266599e-07 (PASS) fl5.bit: RMS=4.047868e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl6.bit: RMS=3.178251e-08 (PASS) maxdiff=1.639128e-07 (PASS) fl7.bit: RMS=1.775792e-08 (PASS) maxdiff=1.043081e-07 (PASS) fl8.bit: RMS=1.866297e-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.112596e-06 (PASS) maxdiff=7.688999e-06 (PASS) fl15.bit: RMS=4.388557e-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.788206e-08 (PASS) maxdiff=8.195639e-08 (PASS) fl11.bit: RMS=1.798147e-08 (PASS) maxdiff=1.005828e-07 (PASS) fl12.bit: RMS=1.791770e-08 (PASS) maxdiff=8.568168e-08 (PASS) fl13.bit: RMS=1.770191e-08 (PASS) maxdiff=4.470348e-08 (PASS) fl14.bit: RMS=4.111211e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl15.bit: RMS=2.477557e-08 (PASS) maxdiff=1.639128e-07 (PASS) fl16.bit: RMS=1.970979e-08 (PASS) maxdiff=1.490116e-07 (PASS) --> 24 bit integer output fl10.bit: RMS=4.102704e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl11.bit: RMS=4.113184e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl12.bit: RMS=4.107583e-08 (PASS) maxdiff=1.192093e-07 (PASS) fl13.bit: RMS=4.127499e-08 (PASS) maxdiff=5.960464e-08 (PASS) fl14.bit: RMS=4.977907e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl15.bit: RMS=4.145519e-08 (PASS) maxdiff=1.788139e-07 (PASS) fl16.bit: RMS=4.171672e-08 (PASS) maxdiff=1.788139e-07 (PASS) --> 32 bit floating point output fl10.bit: RMS=1.788201e-08 (PASS) maxdiff=8.195639e-08 (PASS) fl11.bit: RMS=1.798150e-08 (PASS) maxdiff=1.005828e-07 (PASS) fl12.bit: RMS=1.791763e-08 (PASS) maxdiff=8.568168e-08 (PASS) fl13.bit: RMS=1.770194e-08 (PASS) maxdiff=4.470348e-08 (PASS) fl14.bit: RMS=4.111203e-08 (PASS) maxdiff=1.490116e-07 (PASS) fl15.bit: RMS=2.477554e-08 (PASS) maxdiff=1.639128e-07 (PASS) fl16.bit: RMS=1.970946e-08 (PASS) maxdiff=1.490116e-07 (PASS) ==== Layer 3 ==== --> 16 bit signed integer output compl.bit: RMS=4.300914e-06 (PASS) maxdiff=7.688999e-06 (PASS) --> 32 bit integer output compl.bit: RMS=2.147540e-08 (PASS) maxdiff=1.750886e-07 (PASS) --> 24 bit integer output compl.bit: RMS=4.202659e-08 (PASS) maxdiff=1.788139e-07 (PASS) --> 32 bit floating point output compl.bit: RMS=2.147539e-08 (PASS) maxdiff=1.750886e-07 (PASS) ==== Layer 3 intensity stereo ==== (no official reference, comparing to mpg123 generic 24 bit) --> 16 bit signed integer output drumshort08kHz.bit: RMS=4.348733e-06 (PASS) maxdiff=7.748604e-06 (PASS) drumshort24kHz.bit: RMS=4.366053e-06 (PASS) maxdiff=7.808208e-06 (PASS) drumshort48kHz.bit: RMS=4.375036e-06 (PASS) maxdiff=7.748604e-06 (PASS) mono-is-ms.bit: RMS=4.389819e-06 (PASS) maxdiff=7.629395e-06 (PASS) --> 32 bit integer output drumshort08kHz.bit: RMS=3.685351e-08 (PASS) maxdiff=4.172325e-07 (PASS) drumshort24kHz.bit: RMS=3.893594e-08 (PASS) maxdiff=7.450581e-07 (PASS) drumshort48kHz.bit: RMS=3.389556e-08 (PASS) maxdiff=2.607703e-07 (PASS) mono-is-ms.bit: RMS=3.372314e-08 (PASS) maxdiff=8.940697e-08 (PASS) --> 24 bit integer output drumshort08kHz.bit: RMS=2.297661e-08 (PASS) maxdiff=4.172325e-07 (PASS) drumshort24kHz.bit: RMS=2.677607e-08 (PASS) maxdiff=7.748604e-07 (PASS) drumshort48kHz.bit: RMS=1.460054e-08 (PASS) maxdiff=2.384186e-07 (PASS) mono-is-ms.bit: RMS=9.138218e-09 (PASS) maxdiff=5.960464e-08 (PASS) --> 32 bit floating point output drumshort08kHz.bit: RMS=3.685353e-08 (PASS) maxdiff=4.172325e-07 (PASS) drumshort24kHz.bit: RMS=3.893599e-08 (PASS) maxdiff=7.450581e-07 (PASS) drumshort48kHz.bit: RMS=3.389551e-08 (PASS) maxdiff=2.607703e-07 (PASS) mono-is-ms.bit: RMS=3.372002e-08 (PASS) maxdiff=8.940697e-08 (PASS) ==== Overall result ==== PASS (limited or full)
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, which is on by default since some time now. On a specific (older) system, you might consider turning that off for possibly a slight performance gain.
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.
Regression tests
This is output from the rudimentary regression test suite (which should eventually merge several approaches we had on testing in the past), working on the periodic snapshot:
cc -Os -I/tmp/mpg123-svn.8XPe4/prefix/include -c -o helpers.o helpers.c CC 2859531_id3_tag_not_skipped_when_NO_ID3V2_is_defined.bin CC 2950218_extra_samples_seek_last_frame.bin CC basic_resync.bin CC bug201_another_one.bin CC bug201_wrong_frame_buffer.bin CC chomp_strings.bin CC custom_io.bin CC frame_seek_weirdness.bin CC freeformat.bin CC less_bytes_after_seek2.bin CC less_bytes_after_seek.bin CC more_bytes_on_second_decode.bin CC out123_errorlist.bin CC out123_passthrough.bin CC premature_decoder_change.bin CC seek_accuracy.bin CC string_alloc.bin Running tests. Starting tests, look into test.log for messages. PASS|SKIP is good, FAIL is bad. 2859531_id3_tag_not_skipped_when_NO_ID3V2_is_defined: PASS 2950218_extra_samples_seek_last_frame: PASS basic_resync: PASS bug201_another_one: PASS bug201_wrong_frame_buffer: PASS chomp_strings: PASS custom_io: PASS frame_seek_weirdness: PASS freeformat: PASS less_bytes_after_seek2: PASS less_bytes_after_seek: PASS more_bytes_on_second_decode: PASS out123_errorlist: PASS out123_passthrough: PASS premature_decoder_change: PASS seek_accuracy: PASS string_alloc: PASS PASS
Build tests
Testing some build setups and looking at libmpg123 size.
Testing builds ... config: build default: PASS libmpg123.so=264K libsyn123.so=74K libout123.so=55K mpg123=139K out123=62K config: --disable-shared build static: PASS libmpg123.a=389K libsyn123.a=94K libout123.a=87K mpg123=456K out123=150K config: --enable-portable build portable: PASS libmpg123.so=256K libsyn123.so=74K libout123.so=55K out123=62K config: --disable-8bit build just no 8 bit: PASS libmpg123.so=256K libsyn123.so=74K libout123.so=55K mpg123=139K out123=62K config: --disable-buffer --disable-feeder config: --disable-messages --disable-moreinfo config: --disable-feature_report --disable-network config: --disable-icy --disable-id3v2 --disable-ntom config: --disable-8bit --disable-16bit --disable-32bit config: --disable-layer1 --disable-layer2 config: --enable-runtime-tables --disable-downsample config: --disable-equalizer --disable-ieeefloat build minimal mpg123: PASS libmpg123.so=124K libsyn123.so=74K libout123.so=34K mpg123=115K out123=54K config: --disable-buffer --disable-feeder config: --disable-messages --disable-moreinfo config: --disable-feature_report --disable-network config: --disable-icy --disable-id3v2 --disable-ntom config: --disable-8bit --disable-16bit --disable-32bit config: --disable-layer1 --disable-layer2 config: --enable-runtime-tables --disable-downsample config: --disable-equalizer --disable-ieeefloat config: --enable-portable --disable-string build minimal libmpg123: PASS libmpg123.so=111K config: --disable-buffer --disable-feeder config: --disable-messages --disable-moreinfo config: --disable-feature_report --disable-network config: --disable-icy --disable-id3v2 --disable-ntom config: --disable-8bit --disable-16bit --disable-32bit config: --disable-layer1 --disable-layer2 config: --enable-runtime-tables --disable-downsample config: --disable-equalizer --disable-ieeefloat config: --enable-portable --disable-string config: --with-cpu=generic build minimal generic libmpg123: PASS libmpg123.so=99K config: --with-audio=dummy build cross arm-linux-gnueabihf default: PASS libmpg123.so=264K libsyn123.so=74K libout123.so=55K mpg123=139K out123=62K config: --with-audio=dummy --disable-buffer config: --disable-feeder --disable-messages config: --disable-moreinfo --disable-feature_report config: --disable-network --disable-icy --disable-id3v2 config: --disable-ntom --disable-8bit --disable-16bit config: --disable-32bit --disable-layer1 --disable-layer2 config: --enable-runtime-tables --disable-downsample config: --disable-equalizer --disable-ieeefloat build cross arm-linux-gnueabihf minimal mpg123: PASS libmpg123.so=124K libsyn123.so=74K libout123.so=34K mpg123=115K out123=54K config: --with-audio=dummy --disable-buffer config: --disable-feeder --disable-messages config: --disable-moreinfo --disable-feature_report config: --disable-network --disable-icy --disable-id3v2 config: --disable-ntom --disable-8bit --disable-16bit config: --disable-32bit --disable-layer1 --disable-layer2 config: --enable-runtime-tables --disable-downsample config: --disable-equalizer --disable-ieeefloat config: --enable-portable --disable-string build cross arm-linux-gnueabihf minimal libmpg123: PASS libmpg123.so=111K config: --with-audio=dummy build cross aarch64-linux-gnu default: PASS libmpg123.so=264K libsyn123.so=74K libout123.so=55K mpg123=139K out123=62K config: --with-audio=dummy --disable-buffer config: --disable-feeder --disable-messages config: --disable-moreinfo --disable-feature_report config: --disable-network --disable-icy --disable-id3v2 config: --disable-ntom --disable-8bit --disable-16bit config: --disable-32bit --disable-layer1 --disable-layer2 config: --enable-runtime-tables --disable-downsample config: --disable-equalizer --disable-ieeefloat build cross aarch64-linux-gnu minimal mpg123: PASS libmpg123.so=124K libsyn123.so=74K libout123.so=34K mpg123=115K out123=54K config: --with-audio=dummy --disable-buffer config: --disable-feeder --disable-messages config: --disable-moreinfo --disable-feature_report config: --disable-network --disable-icy --disable-id3v2 config: --disable-ntom --disable-8bit --disable-16bit config: --disable-32bit --disable-layer1 --disable-layer2 config: --enable-runtime-tables --disable-downsample config: --disable-equalizer --disable-ieeefloat config: --enable-portable --disable-string build cross aarch64-linux-gnu minimal libmpg123: PASS libmpg123.so=111K
Needed computing power
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). Well, and more recently, A Core2Duo P8600 core can do 500 times realtime decoding (a track nearly five minutes long decoded in half a second).
Also, we have reports from such devices as nintendo DS or Sony PSP, or various embedded systems...
Michael said once upon a time
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.