I have a small mp3 collection, and whenever I throw a party, I use MPD to play songs from it, so I don’t have to care about the music during the party.
MPD has always fulfilled my needs in mp3-playback, except for one detail: a good mix from one song into the next, or at least some sort of ”gapless playback”, that goes beyond the classical definition (the kind that is good for live concerts or classical music), and is a little more intelligent than simple time-based crossfading, because that sounds horrible most of the time.
A while ago, I decided to take a crack at building my own player (mostly as a programming exercise), and I played around with Gstreamer and its Python bindings for a while, using a pluging called ”level” to detect when the volume level of a song drops below a certain threshold near the end, and use that to start playback of the next song at the right time. The results were promising, not to say quite satisfactory, but my initial goal to create a drop-in replacement for MPD, or at least keep protocol compatibility to a large extent, seems a little too far-fetched right now.
Little did I know. Last Saturday, I discovered something called ‘MixRamp’, invented by Tim Phipps, already back in 2009, which has the exact same goal as my MPD rip-off, and implements it in a way similar to mine, only slightly better. Where my implementation was real-time (meaning audio level analysis is done during playback) and only considered the end of a song to set the mix-point, MixRamp considers both the start and the end of a song to create a better mix, and it is tag-based, so the audio analysis has to be done only once. And the best part: MPD has built-in support for MixRamp since version 0.16. The only thing I like better about my own solution is the fact, that in my case, the mixing is left to the audio output channel (I like PulseAudio, but it could be ALSA, or anything that Gstreamer supports), where with MPD + MixRamp, MPD does the mixing itself.
It would seem that the MixRamp approach is easily portable, although MPD seems to be the only player supporting it so far. If you know of any others, please let me know.
Adding MixRamp tags
So, what do you need?
- MPD, version 0.16 or newer (if you’re on Wheezy or newer, just ”apt-get install mpd”)
- MixRamp, latest version
- eyeD3 (
apt-get install eyed3); used by the
mixramp-tag wrapper script that comes with MixRamp
- mpg123 (
apt-get install mpg123); also used by
- (optional) a script called ‘ramptag‘, to make tagging even easier
- (optional) mid3v2 (
apt-get install python-mutagen);
ramptag uses it to read ID3 tags and find out if a file is already tagged
MixRamp is not in Debian, so you will have to compile it yourself. You need
libaudiofile-dev installed to make that work. Normally it would suffice to type ‘make’ in the unpacked archive directory, but on Wheezy (GCC 4.6), some (presumably harmless) compiler warnings turned up, and I had to edit the Makefile and remove
-Werror (“treat all warnings as errors”) from CFLAGS.
For the rest of this post, I assume you have
ramptag installed, somewhere in your PATH (p.e. /usr/local/bin). Tagging is now as easy as:
cd /path/to/mp3/collection && ramptag *
The result will be, that the mp3-files will have some TXXX tags, that look something like this:
TXXX=mixramp_end=-31.22 0.26;-15.93 3.96;-14.23 4.06;-7.86 4.16;-2.62 4.26;
TXXX=mixramp_start=1.83 0.00;3.72 0.10;6.06 2.30;
The sequences of numbers can be quite a bit longer than this, though.
Making MPD use the MixRamp tags
Like I said, MPD has had built-in support for MixRamp tags since version 0.16, so using them is a matter of tuning some MPD settings:
mpc crossfade 1
mpc mixrampdelay 0
mpc mixrampdb -5
It seems necessary to enable crossfading to make MPD use MixRamp. Traditional crossfading will be done as a fallback when MixRamp tags are not available, so I tend to keep the crossfade setting as low as possible. As for
mixrampdb, you’d have to play a little with those to find the result that you like. The settings above are quite agressive: the next song is started pretty quickly, and the overlap is relatively big. You might want to set
mixrampdb to a lower number. It is the threshold in dB, where MPD places the mix-point, so the lower the number, the longer MPD will wait to start the mix.
A note: at some point, I noticed the following in MPD’s logfile:
crossfade: audio_buffer_size too small for computed MixRamp overlap
I ended up with the following setting in
/etc/mpd.conf (I left the default commented):
Adding ReplayGain to the mix
Even though I have been using mp3′s for ages, I have never taken a serious look at ReplayGain. In combination with MixRamp, it seems to be the icing on the cake for a good party-player.
ReplayGain is also tag-based. Adding tags can be done with
mp3gain, which is available in Debian (and has been since 2004). So,
apt-get install mp3gain.
ReplayGain has two modes of operation: “Track gain” and “Album gain”. For simplicity, we use only “Track gain” here. A few notes on the use of
mp3gain writes APE tags by default. Specify
-s i to use ID3v2 tags. MPD only looks at the ID3 tags.
- when you specify multiple input files, mp3gain assumes it’s an album, unless
-e is given.
To avoid confusion, I’ll only feed
mp3gain one file at a time. That gives me the following command, to be run in a directory that contains mp3 files:
for f in *.mp3; do mp3gain -e -r -k -s i $f; done
You can run
mp3gain -h to see what all the options mean.