Skip to content
 
 

Repository files navigation

packMP3

packMP3 is a lossless compression program for MPEG audio files — MP3 (Layer III) and, as of v3.0, MP1/MP2 (Layer I/II). It reconstructs the exact original file, bit for bit. MP3 is re-encoded with an adaptive arithmetic coder (typical reduction: ~11-16%); MP1/MP2 are handled by the sibling packMP2 library. Embedded ID3v2 cover art (JPEG or PNG) is losslessly recompressed too, via the sibling packJPG and packPNG libraries.

Supported platforms: Linux x64, Windows 7 SP1+ (x64 and x86).

📖 Wiki — FAQ, format details, benchmarks, troubleshooting.

Installation

Download the latest binary from the Releases page:

File Target
packMP3_linux_x64 Linux 64-bit
packMP3_win_x64.exe Windows 10/11 64-bit (also runs on Windows 7 SP1 x64)
packMP3_win_x86.exe Windows 7 SP1+ 32-bit

Windows binaries are statically linked (no MSVC redistributable, no UCRT/pthread DLL required) — they run on a clean Windows 7 install with no extra setup.

Building from source

MP1/MP2 and embedded cover-art support depend on three sibling projects, packMP2, packJPG and packPNG, vendored as shallow git submodules for header provenance (source/vendor/packmp2-src, source/vendor/packjpg-src, source/vendor/packpng-src — packJPG's own repo history is large, so --depth 1 matters):

git clone --recurse-submodules --shallow-submodules --depth 1 \
    https://github.com/YadeWira/packMP3

The prebuilt static libraries these headers pair with are not vendored (packMP3 doesn't build any of the three from source) — build libpackmp2.a/libpackJPG.a/libpackpng.a yourself from those repos (make lib, non-LTO for packmp2/packjpg) and copy them into source/vendor/packmp2/, source/vendor/packjpg/ and source/vendor/packpng/ (plus win64/win32 subdirs for the cross-compile targets) before running make. packPNG's own libpackpng.a bundles a copy of packJPG internally, whose C++ class/function names used to collide with both packMP3's own code and the standalone packJPG copy above. Up to packPNG v2.0c that required an extra objcopy --redefine-syms pass on our side; from v2.0d packPNG isolates those symbols in its own build (ppng_pjg_ prefix), so no rename is needed here — see the include comment above vendor/packpng-src/source/packpng.h in packmp3.cpp for the full history if rebuilding this from scratch.

Tests

cd source && make test

Generates a small synthetic corpus (tests/make_testdata.sh) and runs tests/regression.sh, which checks two separate things:

  1. Reversibility — compress, decompress, compare byte for byte.
  2. That the codecs actually ran — that every codec path a file is supposed to exercise left its own trace.

The second check exists because the first cannot see a dead codec. packMP3 stores data verbatim when a codec does not help, and cover-art recompression bails out silently on anything it does not like. Storing verbatim is perfectly reversible, so a build where every codec had stopped working would still round-trip every file byte-exact and pass a suite that only checked reversibility.

The three codec paths do not signal the same way, which is the awkward part: the audio coder signals by the absence of its no-gain note, cover art by the presence of its own result line, and chunking by a field that is not in the compression output at all and has to be read back from the archive with list. Those were found by diffing a healthy run against a run with each path disabled, not by picking likely-looking lines.

PMP3_SIMULATE_DEAD=cover (or =chunks) disables a codec with its own documented flag and is expected to fail — that is the run which proves the check works at all. PMP3_ALLOW_MISSING_CODECS=1 skips check 2 and says so loudly in the output.

Usage

packMP3 <subcommand> [switches] [filename(s)]

Subcommands

Subcommand Description
a compress MP3/MP2/MP1 files to .pm3 (archive)
x decompress .pm3 files back to MP3/MP2/MP1 (extract)
mix auto-detect and process both directions (use with caution)
list display info about .pm3 archives (MP3, MP2, or MP1) without decompressing
stats show source file info (size, MPEG layer/version, channels, bitrate) without compressing

packMP3 recognizes file types by content, not extension. MP3 goes to the .pm3 format ("MS"/"MK" magic); MP2 goes to a separate .pm3 container ("M2" magic) so the two never collide. Files that are neither a recognized MPEG audio format nor a .pm3 archive are silently skipped. Wildcards (*.mp3, *.*) and drag-and-drop work; on Windows, wildcard expansion is handled internally because cmd.exe doesn't expand them.

In default mode files are never overwritten — packMP3 appends underscores to make a fresh name. Pass -o to overwrite. Directories are silently ignored unless -r is given.

If "-" is used as a filename, input is read from stdin and output is written to stdout.

Examples

packMP3 a *.mp3                        # compress everything in cwd
packMP3 a -k4 -o -np -od out/ *.mp3    # 4 parallel chunks/file, overwrite, no pause
packMP3 a -r music/                    # recurse into music/
packMP3 x *.pm3                        # decompress
packMP3 mix *.*                        # auto-detect each file
packMP3 list *.pm3                     # show version + size, no decompress
packMP3 - < song.pm3 > song.mp3        # stream

mix — mixed mode

Auto-detects each file and compresses or decompresses accordingly.

Warning: running mix on a folder that was already compressed will decompress the .pm3 files back, undoing previous work.

list — list .pm3 info

Displays version, packed size, MPEG format, frame count, channels, rate and bitrate — without decompressing.

$ packMP3 list -np song.pm3
  version  : v2.0
  packed   : 798.8 KB
  chunks   : 4 (intra-file parallel)
  format   : MPEG-1 Layer III
  frames   : 1423
  channels : 2 (joint stereo)
  rate     : 44100 Hz
  bitrate  : 192 kbps (CBR)

The chunks line only appears for archives made with -k > 1 (MP3 archives only — chunking doesn't apply to MP2).

list/stats also work on MP2 files and their .pm3 archives (the sync-scan is header-only, no full decode):

$ packMP3 stats -np song.mp2
  size     : 1.20 MB
  format   : MPEG-1 Layer II
  frames   : 3266
  channels : 2 (joint stereo)
  rate     : 48000 Hz
  bitrate  : 128 kbps (CBR)

$ packMP3 list -np song.pm3
  version  : v3.0
  packed   : 929.3 KB
  original : 1.20 MB
  method   : packMP2 (zstd/zpaq) (packMP2 v0.5.0)
  format   : MPEG-1 Layer II
  frames   : 3266
  channels : 2 (joint stereo)
  rate     : 48000 Hz
  bitrate  : 128 kbps (CBR)

Embedded cover art

If an MP3's ID3v2 tag carries a JPEG or PNG cover (the common case for tagged music files), packMP3 automatically recompresses it losslessly — via packJPG for JPEG covers, packPNG for PNG covers — instead of storing it as generic bytes, shrinking files with high-resolution artwork further, with no extra flag needed. It's self-verifying (the recompressed image is decompressed and byte-compared before ever being used) and silently falls back to the ordinary generic encoding for anything unusual — other image formats (GIF, BMP, etc.), unsynchronised tags, multiple pictures, or any parsing surprise. Format detection goes by the image's own magic bytes (JPEG SOI / PNG signature), not the ID3v2 MIME tag — a real cover mislabeled with the wrong MIME (some taggers get this wrong) is still found and recompressed correctly. When it happens, the per-file result line shows the cover's own before/after size:

  ✓  song.mp3   9053 KB → 7714 KB  85.2%  4.16s
       cover art (PNG):    740.3 KB ->    324.5 KB   43.8%

-nc skips cover-art recompression specifically (the tag is still kept, just encoded generically like the rest) — -d (discard meta-info) is the broader switch that drops the whole tag entirely.

-sfth (matching packJPG's own flag of the same name) recompresses the cover using packJPG/packPNG's own intra-file multi-threading (Y/Cb/Cr in parallel for JPEG, a worker pool for PNG) instead of a single thread — worth it for large covers, likely not for small ones (neither library gates this by image size internally, so packMP3 doesn't either; it's a call the user makes when invoking the flag).

Command-line switches

Switch Description
-ver verify files after processing (encode → decode → byte-compare)
-v? level of verbosity; 0, 1 or 2 (default 0)
-vp progress bar mode (overrides -v?)
-np no pause after processing files
--no-color disable ANSI color output (also respected via NO_COLOR env var)
-o overwrite existing files
-od<path> write output files to directory <path> (created if needed)
-th<n> worker threads for batch processing across files; 0 = auto (forces -ver)
-k<n> intra-file parallel chunks for speed; default 1 = best ratio, 0 = auto
-r recurse into subdirectories
-fs preserve source folder structure under -od (use with -r)
-dry dry run: simulate without writing output files
-module machine-friendly output: OK/ERROR + elapsed time
-p proceed on warnings
-d discard meta-info (ID3 tags)
-nc skip embedded cover-art (APIC) recompression, keep the tag as-is
-sfth parallel single-cover recompression (packJPG/packPNG's own intra-file multi-threading)

Most of these switches — subcommands a/x/list, -od/-r/-fs/-dry/-ver/-np/-o/-module/-th<n>/-p/-d/-v<n> — follow a shared CLI convention coordinated with the sibling lossless-recompressor projects packJPG and packPNG. Release binaries also share the <name>_<platform>_<arch>[.exe] naming pattern across all three.

-p / -d / -ver — what they trade off

By default packMP3 cancels on warnings to guarantee bit-exact round-trip.

  • -p accepts non-spec-compliant MP3 quirks and compresses anyway. The reconstructed MP3 may not be byte-equal to the original (no loss of audio data or quality, though).
  • -d discards meta-info (ID3 tags) for smaller output. Reconstruction is no longer byte-equal.
  • -ver does a full encode → decode → byte-compare per file. Files that fail verification are not written.

-ver should never be combined with -p or -d — those flags intentionally drop byte-equality, so verification will always fail.

Threading

packMP3 has two orthogonal threading modes:

Flag Granularity Effect
-th<n> across files run N files in parallel, each on 1 thread
-k<n> within a file split one file into N independent chunks, each compressed/decompressed on its own thread
-th<n> -k<m> both batch of N files in parallel, each split into M chunks

-k<n> — intra-file parallel chunking

A .pm3 archive is normally a single serial arithmetic stream — encode and decode are inherently sequential. -k<n> splits the file at frame boundaries into n independent sub-streams (each with its own model state), so a single file can use multiple cores.

This trades a little compression ratio for speed — each chunk's adaptive model starts cold instead of carrying statistics from the whole file:

-k ratio (corpus avg) encode decode
1 (default) 88.6% ~265 ms ~274 ms
2 89.2% ~142 ms (~1.9×) ~153 ms (~1.8×)
4 89.8% ~82 ms (~3.2×) ~85 ms (~3.2×)

Use -k1 when ratio matters most (archival, bandwidth-constrained transfer). Use -k4/-k0 (auto) when speed matters most (interactive tools, batch pipelines). Chunking is format-visible: an archive split into more than one chunk uses its own container, and list reports it as a chunks line. A single-chunk archive is the plain format and has no such line — that includes -k1 and any -k0 (auto) run that resolves to one chunk, which is what happens on inputs too short to split. Either way every value reconstructs the input losslessly.

-th<n> (multi-file batch)

-th0 auto-detects core count. In batch mode, verification is forced on automatically — every file is encode→decode→compared before the output is committed.

Other modes

-dry — dry run

Simulates processing without writing any output. Useful to preview ratios before committing to a batch.

packMP3 a -dry -np *.mp3

-module — machine-friendly output

Single-line output: OK <seconds> or ERROR <code> <seconds>.

Library / DLL API

packMP3 has a C-linkage library API for embedding into other applications (archivers, media tools, servers). Same .pm3 format as the CLI.

Building

cd source
make lib      # -> packMP3lib.a          static lib (Linux)
make so       # -> libpackMP3.so         Unix shared object (Linux/macOS)
make dll      # -> bin/packMP3.dll + bin/libpackMP3.a     Windows x64 (mingw cross-compile)
make dll-x86  # -> bin/packMP332.dll + bin/libpackMP332.a Windows x86
make dll-all  # both dll and dll-x86

Pre-built library bundles (matching the sibling projects' packaging) are also attached to each release: packMP3-<ver>-linux-x64-lib.tar.gz, packMP3-<ver>-win64-lib.zip, packMP3-<ver>-win32-lib.zip — each includes the library, headers, a .def file for MSVC (lib /def:packMP3.def /machine:x64), and a short README.

Header: source/packmp3lib.h for building the library itself, source/packmp3dll.h for consumers linking against the shared lib/DLL. Both wrap the pmplib_* declarations in extern "C", so exported symbols have plain, unmangled names.

Functions

Function Purpose
pmplib_convert_stream2stream(msg) Convert using the streams bound by pmplib_init_streams
pmplib_convert_file2file(in, out, msg) Convenience wrapper: file → file
pmplib_convert_stream2mem(**out, *out_size, msg) Convenience wrapper: bound input stream → memory buffer
pmplib_init_streams(in_src, in_type, in_size, out_dest, out_type) Bind input/output streams (file, memory, or FILE*) for the next convert call
pmplib_version_info(), pmplib_short_name() Version metadata

in_type/out_type: 0 = file path, 1 = memory buffer (in_size = buffer length), 2 = FILE* stream (e.g. stdin/stdout).

Example

#include "packmp3lib.h"
#include <stdio.h>

int main(void) {
    char msg[256] = {0};
    pmplib_init_streams("song.mp3", 0, 0, "song.pm3", 0);
    if (!pmplib_convert_stream2stream(msg)) {
        fprintf(stderr, "failed: %s\n", msg);
        return 1;
    }
    return 0;
}

Current limitation: no thread/batch control in the library

The CLI's -th/-k threading is not yet exposed through the library API — pmplib_convert_* calls are single-threaded, single-file operations (no in-library batch function, no setter to enable intra-file chunking). This was confirmed against the sibling projects' library APIs, which do expose thread/batch control — closing this gap is a future decision for packMP3, not a blocker for the current release.

MP2 support and embedded cover-art recompression (JPEG and PNG covers, both added during the v3.0 LTS pre-release series) are also CLI-only — the library only ever handles MP3 (Layer III) .pm3 archives, same scope as the threading gap above.

Windows builds require the POSIX thread model

Every Windows target — the CLI, the DLL, x64 and x86 — is cross-compiled with x86_64-w64-mingw32-g++-posix / i686-w64-mingw32-g++-posix, not with the unsuffixed drivers. This is a correctness requirement, not a preference, and it applies to anyone linking the vendored sibling libraries, not just to whoever builds them.

Debian ships two mingw g++ drivers per target. The default uses the win32 thread model; the -posix one uses winpthreads. They are not link-compatible where C++ threading is involved: std::mutex, std::thread and std::call_once resolve against different runtimes. The vendored libpackJPG.a is built against winpthreads, so linking it into a win32-model binary produced a hard hang — compressing an embedded JPEG cover succeeded and the self-verify decompression immediately after it blocked forever, with the process accumulating no CPU.

That shipped in v3.0c: on Windows, any MP3 carrying a JPEG cover hung the program. Linux was never affected, and -nc (skip cover recompression) avoided it. Fixed in v3.0d.

The mismatch is invisible at build time. The link succeeds — exit 0, a complete executable, no warning — so a runtime deadlock is the only symptom it ever produces. If you build packMP3 for Windows yourself, confirm your driver reports Thread model: posix. To check a vendored library, nm --undefined-only on it should show pthread_* references and no __gthr_win32_* ones.

Known limitations

packMP3 compresses MPEG audio; other file types are silently skipped.

MP3 may stand for three different audio file types: MPEG-1, MPEG-2 and MPEG-2.5 Audio Layer III. As of v2.0, packMP3 compresses all three (mono, stereo, joint stereo and dual channel; constant and variable bitrate).

As of v3.0, MP1 (MPEG Audio Layer I) and MP2 (MPEG Audio Layer II) are also supported, backed by the packMP2 library — same a/x/ list/stats/-ver workflow, separate .pm3 container ("M2" magic) so neither collides with the MP3 format. Layer I has a meaningfully different frame structure from Layer II (different frame-length formula, no SCFSI, different bit-allocation tables), but packMP2 handles both.

MP2/MP1 compression is noticeably slower on Windows than on Linux for the same input (roughly 2x on real test material) — the compressed output is byte-identical either way, only speed differs. Root-caused jointly with packMP2: real profiling on both platforms (callgrind on Linux, a fixed-ASLR gprof build on Windows) confirms the same two functions dominate runtime everywhere (Predictor::update/predict in packMP2's zpaq backend, called ~17.5 million times per file), and the JIT-generated machine code they call into is verified correct on both platforms. Six specific hypotheses were ruled out with real measurements (pthread linkage, static vs. dynamic CRT, SEH unwind tables, -O2 vs -O3, JIT calling convention, missing -fomit-frame-pointer) — none explain the gap. What's left is an accumulation of small mingw-vs-native-GCC codegen differences in these hot C++ functions, not a single fixable flag; closing it for real would need hardware-level profiling (VTune or equivalent) that isn't available in this project's toolchain. If Windows compression speed matters for your workload, native Linux (or WSL) is meaningfully faster for MP2/MP1 today.

Some rare MP3 encodings are rejected (never damaged) rather than compressed: free-format bitrate, and frames mixing long and short blocks within one granule.

packMP3 has low error tolerance — MP3 files might not work with packMP3 even if they play fine in audio software. -p increases error tolerance and compatibility (see the -p/-d/-ver trade-off above).

Compressed archives are not always compatible across packMP3 major versions — v2.0 changed the on-disk format, so v1.x .pmp files cannot be decoded by v2.0 and vice versa. You'll get a clean error message rather than garbage output if you try. v3.0 is an exception: its format additions (MP2, MP1, embedded cover-art recompression) are purely additive and version-gated, so v2.0/v2.1 .pm3 archives still decode correctly on the current build. Note the archive format has its own internal version stamp, separate from the displayed "v3.0" product version — it has ticked forward more than once during this still-ongoing pre-release series as features were added (each bump gated the same way), so an older pre-release binary will cleanly reject an archive written by a newer one with a "newer build" error (rather than misdecode it), while still reading everything older correctly. It's a one-way street: older binaries can't read what a newer feature wrote, but everything older keeps working on newer binaries.

On Windows, dragging too many files at once may show a missing-privileges error; use the command line instead.

Version numbering

  • Main version (appversion in packmp3.cpp) is a two-digit number: v{main/10}.{main%10} — e.g. 20v2.0.
  • Compressed archives are only guaranteed compatible within the same main version. A change in main version may break the on-disk format (v2.0 did).
  • An optional sub-version string marks smaller, format-compatible changes (bug fixes, speed improvements): a, b, c, …

See docs/versionnumbering.txt for the full guideline.

License

All programs in this package are free software; you can redistribute them and/or modify them under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.

The package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details at http://www.gnu.org/copyleft/lgpl.html.

If the LGPL v3 license is not compatible with your software project you might contact us and ask for a special permission to use the packMP3 algorithm under different conditions. In any case, usage of the packMP3 algorithm under the LGPL v3 or above is highly advised and special permissions will only be given where necessary on a case by case basis. This offer is aimed mainly at closed source freeware developers seeking to add .pm3 support to their software projects.

Copyright 2010...2014 by Ratisbon University and Matthias Stirner. Copyright 2010...2026 by Yade Bravo & Matthias Stirner.

History

  • v3.0f — a truncated or corrupt archive is now refused instead of crashing, hanging, or quietly producing the wrong file. Read the last paragraph before updating: some archives that appeared to work will now be rejected.

    Decoding a damaged .pm3 could end three ways, and the third is the one that mattered: it crashed, it spun forever, or it ran to completion, printed 1 ok, exited 0 and wrote a file that was not the original. Truncating a single byte off a valid archive produced a full-size output differing from the source at byte 193310, with no error and no warning. Four checks now stop that, each using a bound the format itself supplies — stream exhaustion, an escape below the coder's lowest context, coefficients outside their own Huffman table's declared maximum, and a statistical model that was never allocated.

    The four checks do different things, and lumping them together is misleading either way. Measured by disabling each in turn over the same 216 truncation points, against v3.0e as the baseline:

    crashes wrong file, no error clean error
    v3.0e 32 170 14
    without the exhaustion check 0 166 50
    v3.0f 0 1 215

    So the exhaustion check is the one that detects truncation — it turns 166 wrong files into refusals. The other three change how a decode fails, not whether it is caught: they convert crashes into clean errors, both here and on full-length single-bit corruption, where 38 crashes become refusals and the number of wrong files is unchanged.

    It does not reach zero and provably cannot, because a truncated archive can be a valid encoding of a different file — where that happens there is nothing in the data to detect. Full-length corruption is the harder case: exhaustion never triggers there, so the wrong-file count is barely affected. Closing either needs information this format does not carry, a declared payload length or a checksum, and that is a format change.

    list now states what it verified: header only for the plain and Layer I/II containers, which after an 11-byte prefix are a single undelimited stream, and chunk table + every sub-stream header for chunked archives, the one container where every byte is length-accounted. list -module is unchanged, byte for byte, so machine consumers are not affected.

    No format change and full compatibility in both directions, verified against every published 3.0x binary rather than assumed: archives from v3.0 through v3.0e decode byte-exact here, archives written here decode byte-exact there, and the .pm3 this build produces is byte-identical to v3.0e's across a 104-file corpus. The one visible consequence: a damaged archive that v3.0e decoded with exit 0 will now be refused. That output was never your original file, but if you did not know that, it will look like something stopped working.

  • v3.0e — fixes a crash on malformed input. list segfaulted on a truncated chunked (-k) archive: the chunk table is four bytes per chunk, and neither the lister nor the decoder checked the file was long enough to hold it before walking it, so a truncated archive read up to 256 bytes past the end of its buffer. The decoder validated afterwards and bailed, which hid the over-read rather than preventing it; list had no such check and died. Both now verify the table fits first, and list gained the two validations the decoder already had — a lister should not accept an archive the decoder would reject. No format change, no effect on valid archives.

  • v3.0d — fixes a Windows hang and bounds what an embedded cover can make packMP3 allocate. On Windows, v3.0c hung forever on any MP3 carrying a JPEG cover: the cover compressed fine and the verification pass immediately after it blocked, with the process using no CPU. Linux was never affected, and -nc avoided it. The cause was a mingw thread-model mismatch — the Windows builds used the default (win32) driver while the vendored packJPG library is built against winpthreads, so std::mutex resolved against two different runtimes. All Windows targets now cross-compile with the -posix drivers; see "Windows builds require the POSIX thread model" above, since the same requirement applies to anyone linking these libraries. A .pm3 can be built by hand, and until now the cover-art decoder only checked the reconstructed size after packJPG or packPNG had already produced whatever the stored blob declared. Both backends now get an explicit output ceiling before every decode, set to the exact size the archive records — both are byte-exact, so a legitimate cover always reconstructs to exactly that and no headroom is needed. On a hand-tampered archive the decode now fails with the real numbers (output size 758042 exceeds configured max_output_size (4096)) and produces no output file. Archives are unchanged: same format, same sizes, and .pm3 files from earlier 3.0x releases still decode byte-exact. The library API also stops reporting "no mpeg audio data recognized" for chunked (-k) and Layer I/II archives, which it cannot open but which are perfectly valid packMP3 archives — it now names the container instead. Vendored packPNG bumped to v2.0f for the guard and its diagnostics; packJPG stays at v5.0c.

  • v3.0c — fixes two ways a file could be refused or left uncompressed. frame_size_table's Layer III rows for MPEG-2 and MPEG-2.5 were copies of the Layer II rows beside them; Layer II keeps 1152 samples per frame in the low-sampling-frequency extension but Layer III halves to 576, so those frame sizes were all 2x too large and the first-frame seeker stepped two frames at a time. CBR survived that by luck, VBR did not — any VBR MPEG-2/2.5 Layer III file (a low-bitrate VBR MP3, the usual shape for podcasts and voice) was rejected outright. Layer detection also scanned only one 8192-byte window, so a first frame further out than that left the MP3 default standing and a Layer I/II file was then refused by the Layer III reader; it now scans up to the same 64 KB tolerance the seeker uses. A ratio at or above 100% now says "no size gain — stored as-is" instead of leaving a bare 100.0%. Vendored siblings bumped to packMP2 v0.8.1, packJPG v5.0c and packPNG v2.0d.

  • v3.0b — faster arithmetic coding: the statistical models keep a Fenwick tree alongside their symbol counts, so the common no-exclusion path resolves a symbol in O(log n) instead of rebuilding the cumulative table in O(n) (~7–8% faster compression and decompression, byte-identical output). Also fixes an ID3v2 skip that read the layer-detection window from the wrong file offset, which could route a Layer III file to the Layer I/II codec and leave it stored uncompressed.

  • v3.0a — rebuilt against packMP2 v0.8 (retrained zstd dictionary).

  • v3.0 (LTS) — MP1/MP2 (MPEG Audio Layer I/II) support via the packMP2 library (a/x/list/stats/-ver, separate "M2" container); losslessly recompresses embedded ID3v2 cover art, JPEG via packJPG and PNG via packPNG; format additions are backward-compatible with v2.0/v2.1 archives throughout.

  • v2.0 — full MP3 family (MPEG-1/2/2.5 Layer III, all channel modes, CBR/VBR), new .pm3 extension, -k intra-file parallel chunking, retuned entropy models, link-time optimization and an optional profile-guided build (make pgo).

  • v1.0g (2016) — updated contact info, minor bugfix.

  • v1.0f (2014) — relicensed to LGPL v3.

  • v1.0e (2014) — source optimizations (cppcheck).

  • v1.0d (2013) — open-sourced under GPL v3.

  • v1.0c (2012) — first public version.

  • v1.0 (2012) — first release (non-public, testing only).

Full commit-level history is in the git log.

Acknowledgements

packMP3 is the result of countless hours of research and development. It started as Matthias Stirner's master's thesis project for Ratisbon University, supervised by Prof. Dr. Christian Wolff.

Prof. Dr. Gerhard Seelmann from Hochschule Aalen introduced Matthias to the field of data compression while studying at HTW Aalen University — without him, neither packJPG nor packMP3 would exist.

Thanks to Stephan Busch of SqueezeChart.com for many hours of beta-testing the original packMP3.

Logo and icon designed by Michael Kaufmann.

Contact

About

A compression program for further compressing MP3 audio files

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages