#!/usr/bin/perl # # Programmer: Craig Stuart Sapp # Creation Date: Mon Jun 26 02:43:23 PDT 2006 # Last Modified: Sun May 17 14:47:37 PDT 2009 (added generalized meter input) # Filename: ...info/revcond/bin/sv2revcond # URL: http://mazurka.org.uk/info/revcond/bin/sv2revcond # Syntax: perl 5 # # Description: Convert SV tap file into a reverse conducting file. # # Four arguments can be input into this program: # (1) A Sonic Visualiser time-instant annotation layer saved as a text file. # (2) The starting beat number for the first beat, for specifying pick-up # beats. If no value is given, then the first beat will be a downbeat. # (3) The number of beats per bar/measure. If no value is given, then the # meter will contain three beats (for mazurkas). # (4) The Humdrum rhythm value representing the duration of a beat. If no # value is given, then "4" is used, which represents a quarter notes. # Other values might include: # "4." for a dotted quarter note (e.g., for compound meters such # as 6/8. # "2" for a half-note, such as in 2/2 or cut-time. # "8" for an eighth-note, such as in 3/8 when there are three beats # per measure. # "16" for a sixteenth note, such as in 3/16 when there are three beats # per measure. # "1" or a whole-note, such as in 4/4 when you only tap once per # measure. # "1." for a dotted whole note (6 beats) when you only tap once per # measure in a 6/4 meter. # "2." for a dotted half-note (3 beats) when you only tap once per # measure in 3/4. # "8." for a dotted eighth-note (0.75 quarter notes) when you only # tap once per measure in 3/8 meter. # # Example input file to this program: # http://mazurka.org.uk/info/revcond/pid9048-15/pid9048-15-clean.txt # Example output file from this program: # http://mazurka.org.uk/info/revcond/pid9048-15/pid9048-15-01.tap # # which would be created with this command-line use of this program: # sv2revcond pid9048-15-clean.txt 1 3 4 > pid9048-15-01.tap # use strict; my $time; my $oldtime; my $file = $ARGV[0]; my $startbeat = $ARGV[1]; my $meter = $ARGV[2]; my $beatrhythm = $ARGV[3]; $startbeat = 1 if $startbeat =~ /^\s*$/; # default starting beat $meter = 3 if $meter =~ /^\s*$/; # default beats per bar $beatrhythm = "4" if $beatrhythm =~ /^\s*$/; # default rhythm per beat open (FILE, $file) or die "Cannot read file $file."; my @contents = ; close FILE; my $beatcounter = 0; my $lasttime = 0; my $currenttime = 0; printComments(@contents); print "**kern\t**beat\t**abstime\t**deltatime\n"; printData(@contents); print "*-\t*-\t*-\t*-\n"; exit(0); ################################################################# ############################## ## ## printData -- ## sub printData { my @contents = @_; my $barnumber = 1; if ($startbeat < 0) { $barnumber = 0; } my $meterbeat = abs($startbeat); if ($meterbeat == 1 && $barnumber == 1) { print "=1-\t=1-\t=1-\t=1-\n"; } my $diff; my $time = 0; my $oldtime = 0; my $i; for ($i=0; $i<@contents; $i++) { if ($contents[$i] =~ /^\s*\#\s*(.*)/) { next; } if ($contents[$i] =~ /^\s*$/) { next; } if ($contents[$i] =~ /^\s*([\d\.\+-]+)\s/) { $oldtime = $time; $time = $1; $time = int($time * 1000.0 + 0.5); $diff = $time - $oldtime; print "$beatrhythm\t$meterbeat\t$time\t$diff\n"; } $meterbeat++; if ($meterbeat > $meter) { $meterbeat = 1; $barnumber++; print "=$barnumber\t=$barnumber\t=$barnumber\t=$barnumber\n"; } } } ############################## ## ## printComments -- ## sub printComments { my @contents = @_; my $offset = 0; my $i; for ($i=0; $i<@contents; $i++) { if ($contents[$i] =~ /^\s*\#/) { $contents[$i] =~ s/^\#\#\#/\!\!\!/; $contents[$i] =~ s/^\#\#/\!\!/; $contents[$i] =~ s/^\#/\!/; chomp $contents[$i]; $contents[$i] =~ s/\s*$//; print "$contents[$i]\n"; next; } next if $contents[$i] =~ /^\s*$/; next if $offset == 1; $offset = 1; if ($contents[$i] =~ /^\s*([\d\.\+-]+)\s/) { $time = $1; $time = int($time * 1000.0 + 0.5); print "!!!offset:\t\t0\n"; $oldtime = $time; } } }