Disks are cheap -- take the FLAC!

by Edd Dumbill

I now have three audio players I use regularly: my PC, my MP3 player, and my phone. The PC can play any sound format. The MP3 player will only play MP3s, and my phone (a Sony Ericsson P800) can play Oggs or MP3s.



By choice I'd rather encode my music to the free Ogg Vorbis standard, but so few hardware players support it, it's hard to make that choice. Also, if Ogg Vorbis is replaced by another standard further down the line, I will have to reconvert from the original CDs -- assuming they're playable at all! Reading a Slashdot discussion on this topic the other day, I saw a suggestion to use the FLAC encoding method to insure against future hardware support and encoding changes.



FLAC, Free Lossless Audio Codec, is as its name suggests a non-lossy way of encoding audio. FLAC files are typically around 50-60% the size of WAV files. They can be easily converted back into WAV files and from their into MP3 or Ogg Vorbis files.



Each of my devices have different storage limits. The optimum space/quality trade-off for the MP3 player is 128kbps, while the phone (max storage 64MB) is suited to an Ogg rate of 64kbps.



This is where FLAC wins. It's very difficult to step down an MP3's bitrate or transcode it to an Ogg without really degrading the sound quality. Mind you, with FLAC there is a price to pay: each of my CDs encoded in FLAC takes over seven times the amount of disk space as the 128kpbs MP3s.



However, disk space is becoming ridiculously cheap. So, I plan to convert my CD collection into FLAC files, and downconvert to other formats for the MP3 player and phone.



Playing around with implementing this on my Linux machine, I noticed two things. Firstly, you need to ensure to encode the CD metadata into your FLAC file when ripping. For the CD-ripper grip that meant using these encoding parameters: -V -o %m -T TITLE="%n" -T ARTIST="%a" -T ALBUM="%d" -T DATE="%y" -T TRACKNUMBER="%t" -T GENRE="%G" %w.



Secondly, as oggenc will only encode from WAV files or raw input, this metadata needs re-extracting when downconverting to WAVs. The same is true if you're downconverting to MP3s, of course.



All of which brings me to the point of this weblog post, to share with you my hacky script, flac2ogg, which converts FLAC files to Ogg Vorbis audio files, preserving the audio metadata. Enjoy and improve!




#!/bin/bash

# by Edd Dumbill
#
# converts a flac file to ogg, preserving the vorbiscomments metadata
# writes filenames like 01-song_title.ogg into the current directory
#
# usage:
# flac2ogg file [file2 ... fileN]
#
# your .flac files should be encoded with this command line:
#
# flac -V -o <FLAC-FILENAME> -T TITLE="albumtitle" -T ARTIST="artist" \
# -T ALBUM="album" -T DATE="date" -T TRACKNUMBER="n" \
# -T GENRE="genre" <WAV-FILENAME>
#
# if you use grip, use this format string (all one line)
#
# -V -o %m -T TITLE="%n" -T ARTIST="%a" -T ALBUM="%d" -T DATE="%y"
# -T TRACKNUMBER="%t" -T GENRE="%G" %w
#
# prerequisites: flac, metaflac, oggenc, bash, sed, tr

tmpnam="flac2ogg-$$.wav"

if test "x$OGG_BITRATE" = "x"; then
OGG_BITRATE=64
fi

ME=`basename $0`

for file in $*; do

if test -f $file; then
ARTIST=`metaflac --show-vc-field=artist $file | sed -e 's/^.*=//'`
TITLE=`metaflac --show-vc-field=title $file | sed -e 's/^.*=//'`
ALBUM=`metaflac --show-vc-field=album $file | sed -e 's/^.*=//'`
DATE=`metaflac --show-vc-field=date $file | sed -e 's/^.*=//'`
TRACK=`metaflac --show-vc-field=tracknumber $file | sed -e 's/^.*=//'`
GENRE=`metaflac --show-vc-field=genre $file | sed -e 's/^.*=//'`
cmd="flac --silent --decode -o /tmp/$tmpnam $file"
echo "$ME: Decoding $file"
eval $cmd
# crop leading 0, if any
TRACKINT=`expr 0 + $TRACK`
# normalise to 2 digits, with leading 0 if required
fname=`printf "%2.2d-%s.ogg" $TRACK "$TITLE"`
fname=`echo $fname | sed -e 's/[ \"]/_/g'| tr A-Z a-z `
cmd="oggenc --quiet -b $OGG_BITRATE \
--artist=\"$ARTIST\" --title=\"$TITLE\" \
--album=\"$ALBUM\" --date=\"$DATE\" \
--tracknum=\"$TRACK\" --genre=\"$GENRE\" \
--output=\"$fname\" /tmp/$tmpnam"
echo "$ME: Encoding $fname"
eval $cmd
rm "/tmp/$tmpnam"
else
echo "$ME: Can't find $file, skipping"
fi

done



Got any more tips for FLAC, Ogg and MP3? Let me know.