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.