Blob Blame History Raw
#!/usr/bin/perl 
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

#Modified version of the original mp32dao distributed with cdrdao. 
#Now with cdtext, mp3 and ogg support
#Support for cdrecord: builds .inf files
#Giuseppe Corbelli <cowo@lugbs.linux.it>
#Original code by Joe Steward <mp32dao@httptech.com>
use FindBin;
use lib $FindBin::Bin;
use Cwd;
use strict;
use MediaHandler;
use Audio::Wav;
use Audio::Tools::Time;

my $wav = new Audio::Wav;
my ($count, $totalsamples, $divided, $rounded, $remainder, $artist, $album, $total, $song, $fh);
my $cdtext = 1;
my $samplestart = 0;
my (@tracklist, @filelist);

print "-------- MP3-to-DAO Helper Script ---------\n";
print "Usage: mp32dao.pl [tocfile]\n";

my $tocfile = $ARGV[0];
unless ($tocfile) {
    $tocfile = "cd.toc";
    warn "No toc file specified, using default \"cd.toc\"\n";
}
my ($list) = MediaHandler->new (getcwd());
die "No supported media files found!\n" if ($list->total == 0);
#Creates array of mediahandlers, sets artist and album.
foreach my $file (@{$list->list})	{
	if (!$file->artist || !$file->title || !$file->album) {$cdtext = 0};
	#Sets artist and album name
	if ($cdtext)	{
		#If artist is still not defined define as in first song tag
		if (!$artist)	{
			$artist=$file->artist;
		} 
		#If different artists mark as VVAA
		if ( ! $artist =~ /\s*\Q$file->artist\E\s*/i)	{
			$artist = "Various Artists";
		}
		#Same for album name
		if (!$album)	{ $album = $file->album }
		if (! $album =~ m/\Q$file->album\E/i)	{$album = "Compilation"};
	}
}
open ($fh, ">$tocfile") or die "Couldn't open $tocfile for write!\n";
tocfile_header($fh, $cdtext, $album, $artist);

#Set outputfiles and decode to wav.
print "\nDecoding compressed files to wav\n";
foreach my $file (@{$list->list})	{
	if ( $_=($file->to_wav) != 0 ) {
		printf ("\n\tWARNING: decoder for file %s exited with code %d\n", $file->Filename, $_);
	}
}
$count=0;
print "\nAnalyzing wav files and creating toc\n\n";
while ($count <= ($list->total-1))	{
	my $file = ${$list->list}[$count];
    my $read = $wav->read($file->Outfile);
    my $audio_bytes = $read->length;
    my $time = Audio::Tools::Time->new (44100, 16, 2);
    my $sample = $time->bytes_to_samples($audio_bytes);	
	tocfile_entry ($fh, $cdtext, $file, $samplestart, $count+1);
	#if ($cdtext) {build_inf ($file, $count)};
	if ($cdtext) {$file->write_inf ($count+1)};
    $totalsamples = $sample - $samplestart;
    $divided = $totalsamples / 588; 
    $rounded = int($divided) * 588;
    $remainder = $totalsamples - $rounded;
    printf ("\tNeed to pad up %d samples for track %d\n", $remainder, $count+1);
	if (($remainder != 0) && ($count ne ($list->total-1))) { 
		my $nextfile = ${$list->list}[$count+1];
		print $fh "FILE \"".$nextfile->Outfile."\" ";
		print $fh "0 $remainder\n\n";
		$samplestart = $remainder;
	}	
	$count++;
}
print "\nFinished writing TOC/inf files. You may now burn the CD using\n\
    \tcdrdao write $tocfile\
    \tcdrecord dev=X,Y,Z -useinfo -dao -text -audio *.wav\n\n";
print "You may want to normalize wav files right now.\n";
close ($fh);
exit;

sub seconds_to_cd_time {
    my $seconds = shift;
    my ($minutes, $frames);
    my $minute_increment = int($seconds / 60);
    if ($minute_increment) {
        $seconds = $seconds - ($minute_increment * 60);
        $minutes = $minutes + $minute_increment;
	}
    my $decimal = $seconds - int($seconds);
    if ($decimal) {
        $frames = int($decimal * 75);
	}
    return sprintf ("%02d:%02d:%02d", $minutes, $seconds, $frames);
}

#Arguments:
#	fh: filehandle opened for writing
#	cdtext: if != 0 cdtext info wanted
#	title: only if cdtext wanted, is the album title
#	performer: only if cdtext wanted, is the album performer
sub tocfile_header	{
	my ($fh, $cdtext, $title, $performer) = @_;
	print $fh "CD_DA\n";
	if ($cdtext)	{
		print $fh "CD_TEXT \{\n";
			print $fh "\tLANGUAGE_MAP \{\n";
 		   print $fh "\t\t0 : EN\n";
			print $fh "\t\}\n\n";
		print $fh "\tLANGUAGE 0 \{\n";
			print $fh "\t\tTITLE \"$title\"\n";
			print $fh "\t\tPERFORMER \"$performer\"\n";
			#print $fh "\t\tDISC_ID \"XY12345\"\n";
			#print $fh "\t\tUPC_EAN \"\"\n";
			print $fh "\t\}\n";
		print $fh "\}\n";
	}
}

#Arguments:
#	fh: Filehandle opened for writing
#	cdtext: scalar != 0 if cdtext ON
#	song: reference to song structure
#	samplestart: scalar containing sample offset
#	count: track number
sub tocfile_entry	{
	my ($fh, $cdtext, $song, $samplestart, $count) = @_;
	
    print $fh "// Track $count\n";
    print $fh "TRACK AUDIO\n";
    print $fh "TWO_CHANNEL_AUDIO\n";
	if ($cdtext)	{
    	print $fh "CD_TEXT {\n";
    	print $fh "\tLANGUAGE 0 {\n";
    	print $fh "\t\tTITLE \"".$song->title."\"\n";
    	print $fh "\t\tPERFORMER \"".$song->artist."\"\n";
		#print $fh "\t\tISRC \"US-XX1-98-01234\"\n";
    	print $fh "\t}\n}\n";
    }
    print $fh "FILE \"".$song->Outfile."\" ";
	print $fh "$samplestart";
    print $fh "\n";
}