Fixing oggs created by sox

Posted by: Andrew Smith
Poster contact info: andrew at littlesvr ca
Author: behavedave, lofty
Originally published: http://forums.lugradio.org
Software: Sox 12.17.8

Well I bothered to find a solid state music player that will play oggs. And then I found that most of my oggs are damaged and make the player freeze.

All of them were converted from mp3 using sox on Slackware 10.1/10.2

When running ogginfo on a broken file, I get something like this:
Processing file "abc.ogg"...

Note: Stream 1 has serial number 0, which is legal but may cause problems with s ome tools.
...
User comments section follows...
        TITLE=a
        ARTIST=b
        ALBUM=c
        DATE=1992
        COMMENT=d
        TRACKNUMBER=1
Warning: Hole in data found at approximate offset 4657500 bytes. Corrupted ogg.
Warning: EOS not set on stream 1
Vorbis stream 1:
        Total data length: 4650846 bytes
        Playback length: 3m:52.453s
        Average bitrate: 160,061112 kb/s

Note the three problems above. I'm not sure which one causes the freeze but it doesn't matter, they will all be eliminated.

The only way I found (even with help) to fix this is to convert every file from ogg to wav and then back to ogg. The computer seems to have no trouble reading/playing the files. There are two potential problems with this procedure:
1. conversions from and to a compressed format usully means some quality is lost . I haven't noticed any so this didn't bother me.
2. the id3 info will be lost since a wav cannot hold it. this is not a problem for me since I tell what a song is by it's directory/file name.

Anyway, the solution is to create a script (maybe call it fixoggs.sh) with the following contents:
# convert spaces to underscores in filenames
for NAME in *.ogg
do
  mv -v "$NAME" `echo $NAME | tr ' ' '_'`
done

# convert from ogg to wav and back
for NAME in *.ogg
do
  echo "Fixing $NAME:"
  sox $NAME `basename $NAME .ogg`.wav
  sox `basename $NAME .ogg`.wav $NAME
done

# to see whether there are errors
ogginfo *.ogg

echo -n "Delete wav files? (y/N) "
read DELETE
if [ "$DELETE" = "y" ]
then
  rm *.wav
fi

Don't forget to make the script executable. Your run it in a directory with ogg files.

Unfortunately both basename and sox have trouble with spaces in filenames so if you have playlists, you will need to regenerate them.

Hope this helped.

Add something to this article