Added the session resampler which now should work for 2.0 sessions and

almost work for 0.99 originated session (automation is not handled yet).
Stopped the creation on the automation/ directory in new sessions as 
it's not used anymore


git-svn-id: svn://localhost/ardour2/trunk@1725 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Sampo Savolainen 2007-04-15 20:47:21 +00:00
parent 0e8e5ddd90
commit fbdd0ab815
4 changed files with 382 additions and 7 deletions

View File

@ -487,13 +487,6 @@ Session::create (bool& new_session, string* mix_template, nframes_t initial_leng
return -1;
}
dir = automation_dir ();
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
error << string_compose(_("Session: cannot create session automation dir \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
return -1;
}
dir = export_dir ();
if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {

View File

@ -0,0 +1,61 @@
package ARDOUR::AutomationSRConverter;
sub new {
my ($type, $input, $output, $inputSR, $outputSR) = @_;
my $self = bless {}, $type;
$self->{Input} = $input;
$self->{Output} = $output;
$self->{Ratio} = ($outputSR+0) / ($inputSR+0);
return $self;
}
sub readline {
my ($self) = @_;
my $buf;
my $c='';
do {
$buf.=$c;
$c=$self->{Input}->getc;
} while ($c ne '' && $c ne "\n");
return $buf;
}
sub writeline {
my ($self, $line) = @_;
$self->{Output}->print($line."\n");
}
sub convert {
my ($self) = @_;
my $version=$self->readline;
if ($version ne "version 1") {
die ("Unsupported automation version $version");
}
$self->writeline($version);
my $buf = $self->readline;
while ( $buf ne "" ) {
if ( $buf eq "begin" ||
$buf eq "end") {
$self->writeline($buf);
} else {
my ($type, $position, $value) = split(' ', $buf);
$self->writeline($type." ".sprintf("%.0f",$position*$self->{Ratio})." ".$value);
}
$buf = $self->readline;
}
}
1;

View File

@ -0,0 +1,120 @@
package ARDOUR::SessionSRHandler;
use XML::Handler::XMLWriter;
use POSIX qw(floor);
@ISA = qw( XML::Handler::XMLWriter );
$VERSION = 0.1;
# This table maps the "names of XML elements" to lists of "names of attributes" which should
# be converted according to the SR change.
# TODO: The table is a bit dirty, i have to figure out how to do it cleanly
my $conversion_table = {
"Location" => { "end" => 0, "start" => 0 },
"Region" => { "length" => 0, "start" => 0, "position" => 0, "sync-position" => 0 },
"Crossfade" => { "left" => 0, "right" => 0 }
};
sub new {
my ($type, $original_sr, $new_sr, $output) = @_;
#my $self = XML::Handler::XMLWriter->new( { Output => $output } );
my $self = $type->SUPER::new( Output => $output );
$self->{Debug} = 0;
$self->{Ratio} = ($new_sr+0)/($original_sr+0);
$self->{OriginalSR} = $original_sr;
$self->{TargetSR} = $new_sr;
$self->{Output} = $output;
$self->{InEvents} = 0;
return $self;
}
sub start_element {
my $self = shift;
my $element = shift;
my $debug = $self->{Debug};
my $atts = $element->{Attributes};
my $convert_attributes = $conversion_table->{$element->{Name}};
foreach my $cAtt (keys %$convert_attributes) {
$atts->{$cAtt} = sprintf("%.0f", $atts->{$cAtt} * $self->{Ratio});
$debug = 0;
}
if ($debug eq 0) {
$self->SUPER::start_element($element, @_);
}
if ($element->{Name} eq "events") {
$self->{InEvents} = 1;
}
}
sub end_element {
my $self = shift;
my $element = shift;
if ($self->{Debug} eq 0) {
$self->SUPER::end_element($element,@_);
}
if ($element->{Name} eq "events") {
$self->{InEvents} = 0;
}
}
sub start_document {
my $self = shift;
$self->SUPER::start_document(@_);
$self->{Output}->print("<!-- Sample rate converted from $self->{OriginalSR}hz to $self->{TargetSR}hz -->\n");
}
sub end_document {
my $self = shift;
$self->SUPER::end_document(@_);
}
sub characters {
my $self = shift;
my $c = shift;
if ($self->{InEvents} > 0) {
my $converted = "";
foreach my $foo (split(' ',$c->{Data})) {
if ($self->{InEvents} eq 1) {
$converted .= floor($foo * $self->{Ratio})." ";
$self->{InEvents} = 2;
} else {
$converted .= $foo." ";
$self->{InEvents} = 1;
}
}
$c->{Data} = $converted;
}
if ($self->{Debug} eq 0) {
$self->SUPER::characters($c, @_);
}
}
1;

201
tools/resample_session.pl Executable file
View File

@ -0,0 +1,201 @@
#!/usr/bin/env perl
# Ardour session resampler, version 0.1
# (c)Sampo Savolainen 2005-2007
#
# Licensed under the GPL
#
# Copies the session to another directory and changes it's sampling rate in all respects.
# The frames in .ardour and .automation files are converted according to the conversion ration.
# The peakfiles and dead_sounds aren't copied. Only "identified" files are copied, instant.xml's
# or .bak's aren't copied either.
use XML::Parser::PerlSAX;
use XML::Handler::XMLWriter;
use IO::Handle;
use File::Basename;
use ARDOUR::SessionSRHandler;
# Let's hope this is never needed
#use ARDOUR::AutomationSRConverter;
if ( ! -f "/usr/bin/sndfile-resample" &&
! -f "/usr/local/bin/sndfile-resample") {
print "You don't have sndfile-resample installed. This script will not work without it, please install it and try again\n";
exit;
}
my ($sourceDirectory, $destDirectory, $sourceSR, $destSR) = @ARGV;
if ((@ARGV+0) ne 4 ||
($sourceSR+0) eq 0 ||
($destSR+0) eq 0) {
print "usage: ardour_sr.pl [ardour session directory] [destination directory] [original samplerate] [new samplerate]\n";
exit;
}
if ( ! -d $sourceDirectory) {
print $sourceDirectory.": directory does not exist!\n";
exit;
}
if ( -d $destDirectory) {
print $destDirectory.": directory exists!\n";
exit;
}
print "Checking source and destination directories\n";
my @sounds;
my @dead_sounds;
my @dot_ardour;
my @automation;
my $version_099x = 0;
# Read the names of all audio files in /sounds/
if ( -d $sourceDirectory."/sounds/") {
$version_099x = 1;
opendir(SOUNDS,$sourceDirectory."/sounds/") || die ($sourceDirectory.": not a valid session, no sounds/ directory");
while ( my $file=readdir(SOUNDS) ) {
if ( -f $sourceDirectory."/sounds/".$file ) {
push(@sounds,$file);
}
}
} else {
my $dirname = $sourceDirectory."/interchange/".basename($sourceDirectory)."/audiofiles/";
opendir(SOUNDS,$dirname) || die ($sourceDirectory.": not a valid session, no sounds/ directory");
while ( my $file=readdir(SOUNDS) ) {
if ( -f $dirname.$file ) {
push(@sounds,$file);
}
}
}
close(SOUNDS);
# Read the names of all audio files in /dead_sounds/
opendir(DEAD_SOUNDS,$sourceDirectory."/dead_sounds/") || die ($sourceDirectory.": not a valid session, no dead_sounds/ directory");
while ( my $file=readdir(DEAD_SOUNDS) ) {
if ( -f $sourceDirectory."/dead_sounds/".$file ) {
push(@dead_sounds,$file);
}
}
close(DEAD_SOUNDS);
# Read the names of all .ardour files in /
opendir(DOT_ARDOUR,$sourceDirectory) || die ($sourceDirectory.": could not open!");
while ( my $file=readdir(DOT_ARDOUR) ) {
if ( -f $sourceDirectory."/".$file &&
index($file,".ardour") eq (length($file)-7)) {
push(@dot_ardour,$file);
}
}
close(DOT_ARDOUR);
# Read the names of all automation files in /automation/
opendir(AUTOMATION,$sourceDirectory."/automation/") || die ($sourceDirectory."/automation: could not open!");
while ( my $file=readdir(AUTOMATION) ) {
if ( -f $sourceDirectory."/automation/".$file &&
index($file,".automation") eq (length($file)-11)) {
push(@automation,$file);
}
}
close(AUTOMATION);
# Check for /peaks/
if ( ! -d $sourceDirectory."/peaks" ) {
print $sourceDirectory.": not a valid session, no peaks/ directory\n";
exit;
}
##########################################
# Checks are done, let's go!
print "Converting session\n";
mkdir $destDirectory;
# Run all .ardour files through the SAX parser and write the results in the destination
# directory.
foreach my $xml (@dot_ardour) {
print "Doing samplerate conversion to ".$xml."...";
open(OUTFILE,">".$destDirectory."/".$xml);
my $output = new IO::Handle;
$output->fdopen(fileno(OUTFILE),"w");
my $handler = ARDOUR::SessionSRHandler->new($sourceSR,$destSR,$output);
my $parser = XML::Parser::PerlSAX->new( Handler => $handler );
$parser->parse(Source => { SystemId => $sourceDirectory."/".$xml });
$output->close();
close(OUTFILE);
print " done\n";
}
# This code is needed for 0.99.x sessions, thus the code is still here.
#
#mkdir $destDirectory."/automation";
#
#foreach my $file (@automation) {
# print "Converting automation file ".$file."...";
# open(INFILE,$sourceDirectory."/automation/".$file) || die "could not open source automation file $file!";
# open(OUTFILE,">".$destDirectory."/automation/".$file) || die "could not open destination automation file $file!";
# my $input=new IO::Handle;
# my $output=new IO::Handle;
#
# $input->fdopen(fileno(INFILE),"r");
# $output->fdopen(fileno(OUTFILE),"w");
#
# my $converter = ARDOUR::AutomationSRConverter->new($input,$output,$sourceSR,$destSR);
# $converter->convert;
#
# $input->close;
# $output->close;
# close(INFILE);
# close(OUTFILE);
# print " done\n";
#}
if ($version_099x eq 1) {
mkdir $destDirectory."/sounds";
foreach my $sound (@sounds) {
my @params=("-to", $destSR,
"-c", "0",
$sourceDirectory."/sounds/".$sound,
$destDirectory."/sounds/".$sound);
system("sndfile-resample",@params);
}
} else {
my $srcSndDir = $sourceDirectory."/interchange/".basename($sourceDirectory)."/audiofiles/";
my $dstSndDir = $destDirectory."/interchange/";
mkdir $dstSndDir;
$dstSndDir .= basename($sourceDirectory)."/";
mkdir $dstSndDir;
$dstSndDir .= "audiofiles/";
mkdir $dstSndDir;
foreach my $sound (@sounds) {
my @params=("-to", $destSR,
"-c", "0",
$srcSndDir."/".$sound,
$dstSndDir."/".$sound);
system("sndfile-resample",@params);
}
}
mkdir $destDirectory."/dead_sounds";
mkdir $destDirectory."/peaks";