Generational loss in MP3 re-encoding

Okay, name this tune:

madplay / lame – 1000 iterations

(You’ll have to scroll about half way in before anything starts)

Didn’t get it? Try this:

madplay 24-bit / lame – 1000 iterations

(Again, you’ll have to scroll about half way in before anything starts)

Missed that one? Okay then, how about:

lame / lame – 1000 iterations

(no need to scroll here.)

Unless you’ve been living under a rock, it’s a clip from Adele‘s Someone Like You. Sure, you can’t make out the words too well in the last one, but at least they don’t sound like some dire paen to Cthulhu, like the first two do.

All of the above samples are the same source file re-encoded 1000 times. I’d heard that there was some loss to encoding MP3s, but thought that if you kept about the same bitrate, there wouldn’t be too much loss. I wanted to test out my theory, so I took:

  • LAME — a quality mp3 encoder (that can also decode to WAV)
  • madplay — a decent mp3 decoder that uses fixed point for speed
  • a shell script (see below) that encodes an MP3 1000 times, feeding the output of the last run as the input of the next.
  • a sample clip; in this case, ganked from Amazon.com: 21: Adele: Music using Audio Hijack Pro.

The original sample looks pretty clean; it’s not the highest quality, but it’s clear:

The first thing that strikes about the multiply-reencoded file is that it’s much longer:

This is because LAME adds padding to the beginning and end of each song. All this padding adds up over 1000 runs.

I’d used madplay extensively before, so I knew it worked reliably. First, I tried it using an intermediate sample size of 16 bits (same as the source) and no dithering. Just after 100 runs, Ms Adkins’ plaintive voice becomes hard to understand:
madplay / lame – 100 iterations

I’d turned dithering off in the first test, as I thought it would overcome the signal. As the signal was pretty much gone, I didn’t think I had much to lose, so I tried it at madplay’s full capability of 24 bit internal processing. Again, 100 runs was where things started to go really sideways:
madplay 24-bit / lame – 100 iterations

LAME can also decode MP3s, and remarkably, the lyrics remained discernable after 1000 interations (so go and see the third sample up top). Sure, it sounds scratchy, but the piano sounds like a piano and not like some underwater harp. LAME is clearly able to recognize its own input, and decode it accordingly. madplay, on the other hand, just treats an MP3 as a generic MP3, hence the over-compression and extra silences.

So really, if you’re going to re-encode music, it matters more what you use to decode your MP3s. If you can use the same tool for both, all the better.


Here’s the script. It takes one argument, the input WAV file. This is the LAME→LAME version; the others just differ in two lines:

#!/bin/bash
# generations.sh - re-encode a WAV file many times to check losses
# created by scruss on Mon Feb 20 14:41:18 EST 2012
# $Id$

filebase=$(basename $1 .wav)

for n in {1..1000}
do
    m=$((n-1))
    if
	[ $n -eq 1 ]
    then
	cp $1 ${filebase}-$(printf "%04d" $m).wav
    fi
    lame -V2 --silent ${filebase}-$(printf "%04d" $m).wav ${filebase}-$(printf "%04d" $n).mp3
    lame --silent --decode ${filebase}-$(printf "%04d" $n).mp3 ${filebase}-$(printf "%04d" $n).wav
    if
	[ $n -gt 1 ]
    then
	rm -f ${filebase}-$(printf "%04d" $m).wav
    fi
    echo $n
done
rm -f ${filebase}-$(printf "%04d" $n).wav

madplay (no dithering, 16 bits)→LAME changes (lines 16-17):

    lame -V2 --silent ${filebase}-$(printf "%04d" $m).wav ${filebase}-$(printf "%04d" $n).mp3
    madplay -b 16 -d -q -o ${filebase}-$(printf "%04d" $n).wav ${filebase}-$(printf "%04d" $n).mp3

madplay (dithering, 24 bits)→LAME changes (lines 16-17):

    lame -V2 --silent ${filebase}-$(printf "%04d" $m).wav ${filebase}-$(printf "%04d" $n).mp3
    madplay -q -o ${filebase}-$(printf "%04d" $n).wav ${filebase}-$(printf "%04d" $n).mp3

3 comments

  1. This was exactly what I was looking for! It’s great that you’ve already tried this! I use LAME often to re-encode higher bitrate files to a more manageable size for my phones, so what would you recommend I use as a player for Android and Windows (desktop)? There are plenty of apps using LAME to encode, but not too many that advertise their use of it for decoding.

  2. Alaap — it really only matters if you’re decoding to re-encode. If you’re playing music, choose what works for you. I used Rocket Player on Android, mainly because Google’s own app is dreadful.

Leave a comment

Your email address will not be published. Required fields are marked *