Category: Audio
Author/Contact Info

Derek Thomson derek@wedgetail.com

Description:

I use cdparanoia and lame to copy tracks from my CDs and convert them to MP3s (for my MP3 player - which is fair use!)

I got tired of converting each track to an MP3 (with appropriate artist/album/title tags) by hand, and so I wrote two programs - one to fetch the CDDB data for a CD, and the other to use that data to convert each track into a nicely named MP3 file (no spaces!!) that is properly tagged.

You can use one program without the other - the track names file format is very simple, so you could just enter it by hand. To use cddb_get you need to install the CDDB_get module from CPAN.

It is assumed that you ripped the tracks off the CD first with something like "cdparanoia -B", as I assume the cdparanoia track naming convention is used.

Note: The cddb_get code is not entirely my own. The core of it was cut-and-pasted directly from the CDDB_get module's manpage.

PROGRAM 1 "cddb_get":

#!/usr/bin/env perl

use warnings;
use strict;

use CDDB_get qw( get_cddb );

sub show_usage;

# Get the output file name

if (@ARGV != 1) {
  show_usage;
  exit 1;
}

my $output_file_name = shift @ARGV;

# Open the output file for writing

open my $output_file, "> $output_file_name";
die "Error opening $output_file_name: $!" unless defined $output_file;

# following variables just need to be declared if different from defau
+lts

my %config;


$config{CDDB_HOST} = "freedb.freedb.org";    # set cddb host
$config{CDDB_PORT} = 8880;            # set cddb port
$config{CDDB_MODE} = "cddb";            # set cddb mode: cddb or http
$config{CD_DEVICE} = "/dev/cdrom";        # set cd device

# User interaction welcome?

$config{input} = 1;   # 1: ask user if more than one possibility
                        # 0: no user interaction

# get it on

my %cd = get_cddb(\%config);
die "No cddb entry found" unless defined $cd{title};

# Write the results to the output file

print $output_file "$cd{artist}\n";
print $output_file "$cd{title}\n";
print $output_file "\n";

foreach my $i ( @{$cd{track}} ) {
  print $output_file "$i\n";
}

exit 0;


sub show_usage
{
  print STDERR "Usage: cddb_get output_file\n";
}
PROGRAM 2 "bulklame":

#!/usr/bin/env perl

# Usage: bulklame tracks_file

use warnings;
use strict;

sub normalize;

#
# Get the artist name from stdin
#

my $artist = <>;
chomp $artist;

#
# Get the album name from stdin
#

my $album = <>;
chomp $album;

#
# Get the track names from stdin
#

my @titles;

while (<>) {
  # Throw away newlines
  chomp;

  # Ignore blank lines
  next if /^\s*$/;

  push @titles, $_;
}

print "$artist\n";
print "$album\n";

print "-----\n";

for my $title (@titles) {
  print "$title\n";
}

print "-----\n";

#
# For each track, get the corresponding wav file and
# convert to mp3 with the normalized name of the track
# for a file name.
#

# Remove any single quote characters in the album or artist
$album =~ s/'//g;
$artist =~ s/'//g;

my $track_count = 1;

for my $title (@titles) {
  my $wav_name = sprintf 'track%02d.cdda.wav', $track_count;
  
  my $file_name = normalize $title;

  # Remove any single quote characters in the title
  $title =~ s/'//g;

  print "$title\n";

  system("lame --ta '$artist' --tl '$album' --tt '$title' $wav_name $f
+ile_name.mp3");

  $track_count++;
}

#
# The normalized name will be all lowercase, using
# underscores instead of spaces, and removing all
# punctuation marks.
#
sub normalize
{
  my $title = shift;

  # Convert to lower case

  $title = lc $title;

  # Turn every group of whitespace characters into a single
  # underscore

  $title =~ s/\s+/_/g;

  # Remove all of the punctuation characters (we'll just
  # define "punctuation" as anything not a letter or a
  # digit)

  $title =~ s/\W//g;

  # And we are done ...

  return $title;
}