# WavPack's roundtrip advantage over FLAC This page is about a non-obvious advantage of the audio codec [WavPack](!W). I discovered it some years ago when archiving music I had made with samples as a teenager. (Don't ask to hear it. It is not good.) WavPack has other cool features, like ["hybrid mode"](!W "WavPack#Hybrid_mode"), but I am not going to cover them here. Current lossless audio codecs all have a compression ratio of [around 50%](https://wiki.hydrogenaud.io/index.php?title=Lossless_comparison). Most people seem to use [FLAC](!W) for lossless audio compression. FLAC is widely supported, including in browsers, and compresses as well as the rest. So why choose WavPack, a less popular alternative? WavPack has an unusual property: as far as I can tell, it always allows you to recover a bit-for-bit identical [PCM](!W "Pulse-code modulation") [WAV file](!W "WAV"). This means a WAV file roundtripped through WavPack will have an identical [checksum](!W). This property got my attention in the 2010s when I wanted to save disk space while preserving my old files exactly as they were. With more abundant disk space, it is less of a concern than it used to be. If you need to get the same bits back, you can use a [good general-purpose compressor like Zstandard](/compressors) and eat the cost in storage and bandwidth because it's small. Still, I find this feature fascinating, and I can think of cases where it is useful. For example, when preserving a computer game in a public archive where it will be downloaded repeatedly, you want to both provide the original data and minimize the download size. ## Contents ## Demo The following test shows the difference between FLAC and WavPack. We will try a file where FLAC gets the exact file back and one where it doesn't. For this demo, I will be using Debian 12 and issuing commands that work in both the POSIX shell and [fish](https://fishshell.com/). First, let's create the files we will use for the test. One we will download from [Wikimedia Commons](!W) as-is, and another we will download in MP3 and convert to PCM WAV. ```plaintext $ sudo apt install -y b3sum curl file flac mpg123 wavpack xxd [...] $ curl -Lfs -o test.mp3 https://upload.wikimedia.org/wikipedia/commons/transcoded/2/2e/Mysterioso_Pizzicato.mid/Mysterioso_Pizzicato.mid.mp3 $ curl -Lfs -o test2.wav 'https://upload.wikimedia.org/wikipedia/commons/2/29/Drawing_of_the_word_Wikipedia_transformed_into_a_wav_file_%28Coagula_software%29.wav' $ mpg123 -w test.wav -q test.mp3 $ b3sum test*.wav ef1ec2c71350ddec9b7a4d4143075020270651a2ffd1a605031ba7db43929cf9 test.wav 13cf3f16d09e7e120a3cd1d3dec500c8283c4cae1dd4278defc4505ba1801463 test2.wav ``` Let's compress each WAV file with both FLAC and WavPack using maximum compression. ```plaintext $ flac --version flac 1.4.2 $ wavpack --version wavpack 5.6.0 libwavpack 5.6.0 $ flac -8 --silent test.wav $ flac -8 --silent test2.wav $ wavpack -hhx -q test.wav $ wavpack -hhx -q test2.wav $ du -h ./test* 532K ./test.flac 252K ./test.mp3 2.1M ./test.wav 524K ./test.wv 124K ./test2.flac 432K ./test2.wav 140K ./test2.wv ``` Now, we'll decompress the files back to WAV and checksum the source and the result. ```plaintext $ flac -d -o test.flac.wav --silent test.flac $ flac -d -o test2.flac.wav --silent test2.flac $ wvunpack -o test.wv.wav -q test.wv $ wvunpack -o test2.wv.wav -q test2.wv $ b3sum test*.wav ef1ec2c71350ddec9b7a4d4143075020270651a2ffd1a605031ba7db43929cf9 test.flac.wav ef1ec2c71350ddec9b7a4d4143075020270651a2ffd1a605031ba7db43929cf9 test.wav ef1ec2c71350ddec9b7a4d4143075020270651a2ffd1a605031ba7db43929cf9 test.wv.wav a81b51460336e39fd9e1055075e92a7d394da82be989232aa5b2b0ea3a670dfe test2.flac.wav 13cf3f16d09e7e120a3cd1d3dec500c8283c4cae1dd4278defc4505ba1801463 test2.wav 13cf3f16d09e7e120a3cd1d3dec500c8283c4cae1dd4278defc4505ba1801463 test2.wv.wav ``` You can see the checksums are identical for `test.wav`. However, only the checksum of `test2.wv.wav` matches `test2.wav`; the file that passed through FLAC doesn't match. Let's confirm that the files are in the same format. ```plaintext $ file test2.wav test2.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 22050 Hz $ file test2.wv.wav test2.wv.wav: RIFF (little-endian) data, WAVE audio, Microsoft PCM, 16 bit, stereo 22050 Hz ``` An [xxd(1)](https://linux.die.net/man/1/xxd) hexadecimal dump shows the difference between `test2.wav` and `test2.flac.wav`. ```plaintext $ xxd test2.wav | head -n 880 00000000: 5249 4646 a4b6 0600 5741 5645 666d 7420 RIFF....WAVEfmt 00000010: 1400 0000 0100 0200 2256 0000 8858 0100 ........"V...X.. 00000020: 0400 1000 0000 0000 6461 7461 7cb6 0600 ........data|... 00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ [...] 00003670: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00003680: 0000 0000 0000 0000 0300 0000 feff 0000 ................ 00003690: f7ff 0000 ffff 0000 0c00 0000 0800 0000 ................ 000036a0: f8ff 0000 f5ff 0000 0100 0000 0800 0000 ................ 000036b0: 0400 0000 0200 0000 ffff 0000 f2ff ffff ................ 000036c0: f3ff 0000 1400 0100 2500 0100 f5ff ffff ........%....... 000036d0: c1ff ffff f0ff 0000 4e00 0200 3c00 0000 ........N...<... 000036e0: b7ff feff 93ff ffff 2700 0200 9500 0200 ........'....... 000036f0: 1300 ffff 5eff fdff a4ff 0000 8c00 0300 ....^........... $ xxd test2.flac.wav | head -n 880 00000000: 5249 4646 a0b6 0600 5741 5645 666d 7420 RIFF....WAVEfmt 00000010: 1000 0000 0100 0200 2256 0000 8858 0100 ........"V...X.. 00000020: 0400 1000 6461 7461 7cb6 0600 0000 0000 ....data|....... 00000030: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................ [...] 00003670: 0000 0000 0000 0000 0000 0000 0000 0000 ................ 00003680: 0000 0000 0300 0000 feff 0000 f7ff 0000 ................ 00003690: ffff 0000 0c00 0000 0800 0000 f8ff 0000 ................ 000036a0: f5ff 0000 0100 0000 0800 0000 0400 0000 ................ 000036b0: 0200 0000 ffff 0000 f2ff ffff f3ff 0000 ................ 000036c0: 1400 0100 2500 0100 f5ff ffff c1ff ffff ....%........... 000036d0: f0ff 0000 4e00 0200 3c00 0000 b7ff feff ....N...<....... 000036e0: 93ff ffff 2700 0200 9500 0200 1300 ffff ....'........... 000036f0: 5eff fdff a4ff 0000 8c00 0300 a000 0100 ^............... ``` The data is offset due to differences in the file header. ## Possible questions {#questions} ### Do you need to be able to recover the WAV? {#do-you-need-it .unlisted} In most cases, you don't. ### Why not use gzip or Zstandard? {#gzip .unlisted} You _could_ use gzip or Zstandard to save yourself work. However, lossless audio codecs compress audio better than generic compressors. Importantly, more audio players can play WavPack files than `.wav.gz` or `.wav.zst`. ```plaintext $ gzip -6 --keep test.wav $ zstd -7q test.wav $ du -h test.wav test.wav.gz test.wav.zst test.wv 2.1M test.wav 1.5M test.wav.gz 1.4M test.wav.zst 524K test.wv ``` ### Can't I just use WAV files that FLAC preserves bit-for-bit? {#choose-wav .unlisted} You can when you are creating the WAV files. ### Does passing `--keep-foreign-metadata` to flac(1) make a difference? {#keep-foreign-metadata .unlisted} No. ```plaintext $ flac -8f --silent test2.wav && flac -df -o test2.flac.wav --silent test2.flac $ b3sum test2.flac.wav a81b51460336e39fd9e1055075e92a7d394da82be989232aa5b2b0ea3a670dfe test2.flac.wav $ flac -8f --keep-foreign-metadata --silent test2.wav && flac -df -o test2.flac.wav --keep-foreign-metadata --silent test2.flac NOTE: --keep-foreign-metadata is a new feature; make sure to test the output file before deleting the original. NOTE: --keep-foreign-metadata is a new feature; make sure to test the output file before deleting the original. $ b3sum test2.flac.wav a81b51460336e39fd9e1055075e92a7d394da82be989232aa5b2b0ea3a670dfe test2.flac.wav ``` ### Do you think one should use WavPack everywhere? {#wavpack-everywhere .unlisted} No, FLAC is a good default and entrenched. (I like FLAC!) ## Page metadata URL: Published 2024-11-20, updated 2025-10-20. Tags: - archival - audio - compression - data - file format