#!/usr/bin/perl # # splitmp3album (c) 2002 Richard van den Berg # # Distributed under the GPL: http://www.gnu.org/copyleft/gpl.html # # This tool splits mp3 albums into separate tracks. # It is based on the assumption that when merging mp3 files together, # the headers will introduce errors in the otherwise continuous stream of # mp3 frames. A tool like mp3check can identify these errors. # This script just takes the markers from mp3check and splits the album. # # Usage: mp3check -e album.mp3|splitmp3album [-d dest] [-i] [-m] [-h] album.mp3 # # Joining tracks into an album is now as simple as: # # cat *.mp3 > album.mp3 # # Get mp3check at http://packages.debian.org/mp3check # MPEG::MP3Info is at http://sourceforge.net/projects/mp3-info/ # # 04/07/2003 version 1.1: added hex() to push statement use Getopt::Std; use File::Basename; $version="v1.1"; $dest="."; $bsize=8*1024; $id3=0; $m3u=0; getopts('himd:',\%opt) || exit; &usage if($opt{'h'}); $id3=1 if($opt{'i'}); $m3u=1 if($opt{'m'}); $dest=$opt{'d'} if(defined($opt{'d'})); if($id3) { use MPEG::MP3Info; } &usage if($#ARGV<0); $file=$ARGV[0]; while() { @line=split; push(@track,hex($line[5])) if($line[5]=~m/^0x/); } push(@track,2**32); # 4 Gb for last file marker..should be enough &usage if($#track<3); open(IN,"<$file") || die "Can't open file $file: $!\n"; $tnum=0; $total=0; $tname=sprintf("%s/%02i.mp3",$dest,$tnum+1); die "Aborting: $tname exists\n" if(-e $tname); open(OUT,">$tname") || die "Can't write to file $tname: $!\n"; while($read=read(IN,$buf,$bsize)){ if($read+$total>=$track[$tnum]){ syswrite(OUT,$buf,$track[$tnum]-$total) || die "Error writing: $!\n"; close(OUT); $total=$track[$tnum++]; print "Closed file $tname at $total\n"; seek(IN,$total,0); $tname=sprintf("%s/%02i.mp3",$dest,$tnum+1); die "Aborting: $tname exists\n" if(-e $tname); open(OUT,">$tname") || die "Can't write to file $tname: $!\n"; } else { syswrite(OUT,$buf) || die "Error writing: $!\n"; $total+=$read; } } close(OUT); print "Closed file $tname at $total\n"; close(IN); if($id3){ print "Renaming files...\n"; if($m3u){ $mfile=$dest."/".basename($file,".mp3").".m3u"; print "Appending to $mfile\n" if(-e $mfile); open(M3U,">>$mfile") || die "Cannot write to $mfile: $!\n"; } loop: for($tnum=1;$tnum-1<=$#track;$tnum++){ $tname=sprintf("%s/%02i.mp3",$dest,$tnum); $info=get_mp3tag($tname); $artist=$info->{ARTIST}; $title=$info->{TITLE}; $artist=~tr/\"\'\?//d; $title=~tr/\"\'\?//d; if(!$artist || !$title){ print "$tname does not have a usable ID3 tag: not renaming\n"; print M3U basename($tname)."\n" if($m3u); next loop; } $newname="$dest/$artist - $title.mp3"; if(-e $newname) { print "$newname exists: not renaming $tname\n"; print M3U basename($tname)."\n" if($m3u); next loop; } print "Renaming $tname to $newname\n"; rename $tname,$newname || print "Failed to rename $tname to $newname: $!\n"; print M3U basename($newname)."\n" if($m3u); } close(M3U) if($m3u); } exit(0); sub usage { $name=basename($0); print "splitmp3album($version): splits an mp3 album into separate tracks\n"; print "(c) 2002 Richard van den Berg \n\n"; print "Usage: mp3check -e album.mp3 | $name [-d dest] [-i] [-m] [-h] album.mp3\n"; print " -d create files in this directory\n"; print " -i use id3 tags to rename files after separation\n"; print " -m write m3u file after renaming files\n"; print " -h print this help page\n\n"; print "Get mp3check at http://packages.debian.org/mp3check\n"; exit(1); }