Monday, June 9, 2014

Multiple FLAC to single CUE-WAV script

For a while I've thought about creating single files with corresponding cue files.  Instead of re-ripping my collection, the script below will reassemble the flac files in a directory to a single wav and then create the necessary cue file.  It's a simple script and only processes one directory at a time.  Later, I'll put the code into this to process an artist and all album directories.

#!/usr/bin/perl
use strict;
use warnings;
use Cwd;
use File::Glob;
use Sysadm::Install qw(tap);

# Read directory for all flac
# soxi -d *.flac to get the times
# shntool join -o flac *.flac
# note: shntool cue *.flac > joined.cue will create the correct cue sheet without TITLE info.
# Had to install Sysadm::Install (did it through CPAN)

sub System_Call {
        my @args = @_;
        system (@args);
        if ($? == -1) {
                print "\nFailed to execute: $!\n";
                exit 2;
        }
        elsif ($? & 127) {
                printf "\nChild died with signal %d, %s coredump\n",
                ($? & 127),  ($? & 128) ? 'with' : 'without';
                exit 2;
        }
        return $?;
}

sub Get_Artist_Album {
        return ( split m!/!, cwd() )[-2,-1];
}

sub Add_Times {
        my $NewTime;
        my $BeginTime = $_[0];
        my $TrackLen = $_[1];
        my $NewSec = 0;
        my $NewMin = 0;
        my $NewHr = 0;
        my ($bMM, $bSS) = ( split m!:!, $BeginTime )[-2,-1];
        my ($tMM, $tSS) = ( split m!:!, $TrackLen )[-2,-1];
        $NewSec = $bSS+$tSS;
        if ($NewSec > 59) {
                $bMM = $bMM + 1;
                $NewSec = $NewSec-60;
        }
        $NewMin = $bMM+$tMM;
#       if ($NewMin > 59) {
#               $NewMin = $NewMin-60;
#       }
        $NewTime = sprintf("%02d",$NewMin).":".sprintf("%02.2f",$NewSec);
        return $NewTime;
}

sub Create_CUE {
        my $WAV_FILE = $_[0] or die "I need the name of the WAV\n\n";;
        my $i = 1;
        my $Track = 1;
        my @files = sort <*.flac>;
        my $StartTime = "00:00:00";
        my ($Artist, $Album) = Get_Artist_Album;
        open (CUEFILE, '>CDImage.cue');
        print CUEFILE "PERFORMER \"".$Artist."\"\n";
        print CUEFILE "TITLE \"".$Album."\"\n";
        print CUEFILE "FILE \"$WAV_FILE\" WAVE\n";
        foreach my $file (@files) {
                $Track = sprintf("%02d", $i);
                my $Title = $file;
                $Title =~ s{\.[^.]+$}{}; #Remove the extension
                $Title =~ s(^\d+[\.\_\-\ ]+)(); #Remove the leading track number
                print CUEFILE "  TRACK ".$Track." AUDIO\n";
                print CUEFILE "    TITLE \"".$Title."\"\n";
                if ($i > 1) {
                        my ($NewMM, $NewSS) = ( split m!:!, $StartTime )[-2,-1];
                        my ($NewSecL,$NewSecR) = ( split m!\.!, $NewSS )[-2,-1];
                        $NewSecL = sprintf("%02d",$NewSecL);
                        $NewSecR = $NewSecR * 0.6;
                        $NewSecR = sprintf("%02d",$NewSecR);
                        my $NewSecF = $NewMM.":".$NewSecL.":".$NewSecR;
                        print CUEFILE "    INDEX 01 ".$NewSecF."\n";
                } else {
                        print CUEFILE "    INDEX 01 ".$StartTime."\n";
                }
                my ($TrackTime, $stderr, $rc) = tap "soxi", "-d", $file;
                $StartTime = Add_Times $StartTime, $TrackTime;
                $i++;
        }
        close (CUEFILE);
}

sub Create_Single_WAV {
        my @files = sort <*.flac>;
        my $rc = System_Call "shntool", "join", "-o wav", @files;
        print "Error Code: $rc \n";
        if ($rc == 0) {
                rename "joined.wav","CDImage.wav";
                return 0;
        }
        return $rc;
}

unless (-x "/usr/bin/shntool") {
        print "I need the program shntool to function\n";
        exit 1;
}

unless (-x "/usr/bin/soxi") {
        print "I need the program soxi to function\n";
        exit 1;
}

my $results = Create_Single_WAV();
if ($results == 0) {
        Create_CUE "CDImage.wav";
}