My lame FreeBSD copying audio CD's script

NOTE! This page, like many of the pages on this site, is severely dated. I'm not sure how much of it still holds true.

My wife, who is a dance teacher, needed to make backup copies of several CDs. After doing a few for her, I decided to make a script (and use sudo to allow her to use it) so that she could do it herself.

If one reads the excellent handbook's guide to creating CD's they'll see that there are a few ways to do it. One doesn't actually need cdparanoia and cdrecord. Instead, one can use the builtin FreeBSD tools--dd which is pretty standard in all *nix's and *nix clones and FreeBSD's burncd.

There is an an excellent guide on burning CD's which can be found here. Although it's primarily about Linux, there's a section (which links back to ~this~ page as well as the handbook) with notes for FreeBSD users.

The handbook mentions the method of first getting the names of all the audio tracks, which will be something like /dev/acd1t01 /dev/acd1t02 etc. The author just gives the method of extracting them one by one, such as

dd if=/dev/acd1t01 of=/usr/track01.cdr
dd if=/dev/acd1t02 of=/usr/track02.cdr

Then, one can use burncd to write each track to a CD.

burncd -f /dev/acd1 audio track1.cdr track2.cdr track3.cdr fixate

This can, of course, be a bit of a nuisance. So, I wrote a rather lame shell script to do it for her. I should point out that you have to have sh or another Bourne style shell for this to work.


#!/bin/sh
for i in /dev/acd0t*
do
dd if=$i of=/usr$i.cdr bs=2352
done
eject acd0
cd /usr/dev
for i in acd0t*cdr
do
mv $i track${i#acd0t}
done
burncd -f /dev/acd1 audio *cdr fixate
eject acd1
cd /usr/dev
rm track*.cdr

(A quick note--in FreeBSD 4.x one would have used acd1c rather than just acd1. I don't remember when this changed, but 5.3 BETAs and newer don't need the c at the end of the device name.)

One of the reasons I call it lame is because rather than strip /dev/ from the file name, I just made a directory /usr/dev. For those who are novices to shell scripting and simply want to have a vague understanding of what is going on so they can make (legitimate of course) copies of audio cds:

for i in /dev/acd0t*
do

These two lines begin a simple "for" loop, that will note each file beginning with the name /dev/acd0t, in other words, acd0t1, acd0t2 etc. These file names are given the variable name of i

Sometimes, one just puts the CD and devfs does the work. Doing a ls /dev/acd0t* gives the various tracks. Other times, it doesn't seem to realize that there's a CD in there. (I suspect this is simply because I have low end hardware). However, if I do an eject (which has to be installed from /usr/ports/sysutils/eject) then once again put the CD in, the ls command shows me the tracks. As I don't do a great deal of burning audio CD's this is one of those things I've never bothered researching.

dd if=$i of=/usr$i.cdr bs=2352

This line performs the dd action mentioned in the handbook. (This is where I got lazy, and rather than renaming each file here, I just created the directory /usr/dev). The $i refers to the value of the variable. So, it is saying, for every file on the cd with a name beginning with /dev/acd0t, such as /dev/acd0t01, take that file and directly copy it to /usr with the same name. So, it'll use the device directory and copy /dev/acd0t01 to /usr/dev/acd0t01.cdr. The loop will then continue through the list of files on the CD.

done

Finishes the for loop.

eject acd0

Ejects the CD which was being copied. (This script assumes you have two CD drives, acd0 and acd1. In my case, acd1 is the CD burner drive). Also note that the eject command has to be installed from /usr/ports/sysutils/eject.

cd /usr/dev
for i in acd0t*cdr
do
mv $i track${i#acd0t}
done

First you cd over to the directory holding the newly copied files. The mv command then renames them to track01.cdr, track02.cdr etc. For further explanation of this, see my shellscripting page, and check out the Daniel Robbins articles that are linked from that page. The next "done" finishes that for loop.

burncd -f /dev/acd1 audio *cdr fixate
eject acd1

The next line uses the builtin burncd command. Rather than do it the way it's suggested in the handbook, with burncd -f /dev/acd1 audio track01.cdr track02.cdr etc we're using * to catch all files with the suffix of .cdr

eject acd1 of course, then ejects the burned CD. (The two eject commands are handy if you're busy doing other things, as they let you know the procedure is finished.

cd /usr/dev
rm track*.cdr

You should actually still be in /usr/dev, but as this was for my wife's use, I figured I better make sure. :) (She isn't a computer person). Then, to clean up, one removes the .cdr files. The script can be customized as you wish. I'm just throwing it up here in the hope that it might be useful to someone.

Some people find that using burncd gives an error at the end, usally something like ioctl(CDRIOCFIXATE). In most cases, the error seems to be harmless and the CD is still burned without problem.

If not, there is always /usr/ports/sysutils/cdrtools which includes cdrecord. (See this page for an excellent guide, though it is Linux oriented.)

Some Miscellaneous Conversion Tips

I am not any sort of audio expert. At times, I run into things like this for various reasons, for instance, finding some classical or TV theme show music that I like, that is freely available, and then having a Windows using friend want it, or wanting to make a CD. All I need is playable music, and I don't get overly concerned about great quality or making sure there's no pause between tracks and the like. No doubt, many readers will know of better ways to do these things. That's fine, much of what I write below is simply to save me having to look up how to do it next time.

I should add there is a port, /usr/ports/audio/pacpl, which I haven't used yet. Supposedly, it can do all these conversions and the interested reader might wish to try it.

I should also add that in almost all cases, one can simply use ffmpeg. The syntax is
ffmpeg -i infile out.desired_format

In other words, to convert an mp3 to an ogg file
ffmpeg -i foo.mp3 foo.ogg

If one is more of an audiophile, there are a number of options that can be given ffmpeg. For a much better treatment of it, see my friend Howard Pritchett's page about it.

The ogg123 and oggenc are part of /usr/ports/audio/libogg. To convert the music file foo.ogg to an mp3 I've found the easiest way is to first convert it to a .wav file with ogg123 then use bladenc to convert the .wav to an mp3.
ogg123 -d wav -f foo.wav foo.ogg
bladeenc foo.wav

This is explained in the man page, but in a nutshell, the -d specifies the output device, in this case wav and the file will be foo.wav. The last argument, obviously enough is the input file, foo.ogg. Then we use bladeenc (available in /usr/ports/audio/bladeenc) to convert the wav file into an mp3. There is also a /usr/ports/audio/ogg2mp3 port, but I haven't tried it.

To convert foo.wav to foo.ogg
oggenc foo.wav

This is the simplest way to do it. It will create a new .ogg file, foo.ogg.

To take a file of one of these formats and burn it to CD, you want to wind up with the file in .wav format. If the file is an .ogg file you can use ogg123, if it's an mp3 file you can use lame from /usr/ports/audio/lame.
lame --decode foo.mp3 foo.wav
burncd -f /dev/acd0 audio foo.wav fixate

(That's assuming that your CD burner is /dev/acd0.) There are other tools--as well as the ogg2mp3 mentioned above, /usr/ports/audio also has mp32ogg. Of course, if you want to convert an mp3 to an ogg file without installing yet another port, you can use lame again. To convert foo.mp3 to foo.ogg

lame --decode foo.mp3 foo.wav
oggenc foo.wav

To convert realplayer type audio files to mp3 or ogg files, use mplayer (/usr/ports/multimedia/mplayer) to convert it to a wav file, then use oggenc or bladeenc to convert it to an ogg or mp3. (This also works with older iTunes m4a files).
In the example, we'll convert it to an ogg.
mplayer -ao pcm:file=foo.wav foo.ra
oggenc foo.wav

If you had a bunch of them then, assuming they are all in one directory, and you're in that directory
for i in *.ra; do mplayer -ao pcm:file=${i%ra}wav $i; done

(Realplayer files seem to come with a few different suffixes--.ra is one, I've also frequently seen .rmj. Obviously, use the suffix of the file you have.)

To move a track from a CD to your hard drive for playing with mplayer or whatever, I use cdparanoia (/usr/ports/audio/cdparanoia). Suppose I want track 4 from a CD
cdparanoia -d /dev/acd0 -w 4 track4.wav

I extract it as a .wav file, then usually change it to an ogg file as shown above. If I'm getting a bunch of tracks, I use the -B option. For example, if I want tracks 1-4
cdparanoia -d /dev/acd0 -w -B 1-4 wav

This will output them as track1.wav, track2.wav, etc. For the entire CD
cdparanoia -d /dev/acd0 -B
For a bit more detail on using cdparanoia, see the link I metioned previously.

One can take a youtube video and extract the audio with ffmpeg. (/usr/ports/multimedia/ffmpeg). There are various ways of downloading youtube videos--I use this page's method. You bookmark the indicated link, then, when you are on youtube and want a video, you open that link from your bookmarks, and right click on the link to save file as. (Its default is get_video.html, but even if you leave the default alone and then run mplayer get_video.html it will play).

At any rate, say you downloaded the video and renamed it to youtube.flv. You want to extract the audio to a file you will call outputfile.mp3
ffmpeg -i youtube.flv -vn -acodec mp3 -ab 128 -ac 2 outputfile.mp3

As I said, there are other methods, and some are probably better, but my needs are simple. Again, it is hoped that some readers, at least, will find this useful.

The ffmpeg program can do many more things. For an easy to follow tutorial, see Howard Pritchett's excellent page.

Let me add the disclaimer that none of the information here should be used for any illegal copying.