#! /usr/bin/perl
#
# Read a list of files with DTW's of the Shadow sentence label 
# and shift the times so they align with the original sentences
#
# use:
#> ShiftShadowTimes.pl filepattern
#
# Filepattern is a DTW path short text file with a time offset to the
# first x and y (that is extract with preservation of times)
#
###############################################################################
#
# Copyright R.J.J.H. van Son © 2000, 2001
#
# Author Rob van Son
# Institute of Phonetic Sciences & ACLC
# University of Amsterdam
# Herengracht 338
# NL-1016CG Amsterdam, The Netherlands
# Email: Rob.van.Son@hum.uva.nl
#        rob.van.son@workmail.com
# WWW  : http://www.fon.hum.uva.nl/rob/
# mail:  Institute of Phonetic Sciences
#        University of Amsterdam
#        Herengracht 338
#        NL-1016CG Amsterdam
#        The Netherlands
#        tel +31 205252183
#        fax +31 205252197
#
# License for use and disclaimers
#
# 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 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.
#
#
#######################################################
#
# Define and initialize
$HomeDir = '../../..';
require "$HomeDir/Links.pl";
require "$Scripts/SentenceLabel.pl";

my @GlobFileList = @ARGV;
my $FilePattern;

sub interpolatedValues  # ($r, @values)
{
    my $r = shift || return 0;
    my @values = @_;
    #
    my $low = int($r);
    my $high = $r - $low > 0 ? $low+1 : $low;
    my $DiffIndex = ($high-$low) <=> 0 ? ($high-$low) : 1;
    #
    # Get the interpolated value
    my $realValue = ($values[$high] - $values[$low])*($r - $low)/$DiffIndex + $values[$low];
    
    return $realValue;
};

foreach $FilePattern (@GlobFileList)
{
        # Get the real filenames (expand * and ?)
        my @FileList = glob("$FilePattern");
        my $FileName;

        # Handle All files
        foreach $FileName (@FileList)
        {   
	    my @xTime = ();
	    my @yTime = ();
	    my @yDelay = ();
	    my ($xmin, $xmax, $x1) = (0, 0, 0);
	    my ($ymin, $ymax, $y1) = (0, 0, 0);
	    my ($nx, $ny) = (0, 0);
	    my ($dx, $dy) = (0, 0);
	    my $weightedDistance = 0;
	    my $pathLength = 0;
	    
	    $FileName =~ m@/?([^/\.]+)\.[\w\.]+$@;
	    my $LabelFileName = $1;
	    $LabelFileName =~ /^([FM][\d]+[A-Z]+)/;
	    my $CurrentSpeaker = $1;
	    my $LabelFile = "$HomeDir/home/Shadowing/$CurrentSpeaker/sentences/$LabelFileName.shadow";
	    
	    
	    # Get the DTW path     	
	    open(SHIFTFILE, "cat $FileName| gunzip -c |") || die "<$FileName: $!\n";
	   
	    while(<SHIFTFILE>)
	    {
	    	# Start of data section
	    	last if /path \[\]\:/;
		
		# Read ALL data
		split;
		# The original speech file
		$xmin = $_[2] if /^\s*xmin\s+\=\s+/i;
		$xmax = $_[2] if /^\s*xmax\s+\=\s+/i;
		$nx = $_[2] if /^\s*nx\s+\=\s+/i;
		$dx = $_[2] if /^\s*dx\s+\=\s+/i;
		$x1 = $_[2] if /^\s*x1\s+\=\s+/i;
		$x1 = $x1 > $xmin ? ($x1-$xmin)/2 : $xmin;
		# The shadow speech file
		$ymin = $_[2] if /^\s*ymin\s+\=\s+/i;
		$ymax = $_[2] if /^\s*ymax\s+\=\s+/i;
		$ny = $_[2] if /^\s*ny\s+\=\s+/i;
		$dy = $_[2] if /^\s*dy\s+\=\s+/i;
		$y1 = $_[2] if /^\s*y1\s+\=\s+/i;
		$y1 = $y1 > $ymin ? ($y1-$ymin)/2 : $ymin;
		# Path info
		$weightedDistance = $_[2] if /^\s*weightedDistance\s+\=\s+/i;
		$pathLength = $_[2] if /^\s*pathLength\s+\=\s+/i;
	    };
	    
	    # Read path combinations
	    while(<SHIFTFILE>)
	    {
	    	die "NOT a path: $_" unless /path\s*\[\s*(\d+)\s*\]\s*\:/;
		my $currentPath = $1;
		# Original path position
		$_ = <SHIFTFILE>;
		die "NOT an x value: $_" unless /^\s*x\s*\=\s*\d+/;
		split;
		my $currentxSlice = ($_[2] - 1);
		my $currentx = ($_[2] - 1) * $dx + $x1;
		$xTime[$currentPath-1] = $currentx;
		# Shadow path position
		$_ = <SHIFTFILE>;
		die "NOT an y value: $_" unless /^\s*y\s*\=\s*\d+/;
		split;
		my $currenty = ($_[2] - 1) * $dy + $y1;
		$yTime[$currentPath-1] = $currenty;
		#
		# Calculate the delay in y
		$yDelay[$currentxSlice] = $currenty - $currentx;
	    };
	    
	    # Now, handle the shadow tier
	    (print STDERR "$LabelFile does not exists\n", next) unless -e $LabelFile;
	    next if -e "$LabelFile.Shifted";
	    my $SentenceLabel = new SentenceLabel;
	    $SentenceLabel->ReadLabelFile($LabelFile);
	    $SentenceLabel->presetItem("PHONEMES");
	    while($SentenceLabel->nextItem("PHONEMES") > -1)
	    {
	    	# Where am I
		my $CurrentItem = $SentenceLabel->currentItem("PHONEMES");
		my $currentStart = $SentenceLabel->currentStart("PHONEMES");
		my $currentEnd = $SentenceLabel->currentEnd("PHONEMES");
		
		# Intialize SHADOW tier
		$SentenceLabel->currentItem('SHADOW', $CurrentItem);
		$SentenceLabel->currentStart('SHADOW', $currentStart);
		$SentenceLabel->currentEnd('SHADOW', $currentEnd);
		
	    	# Stay within current sentence
	    	next if $currentEnd < $x1;
	    	last if $currentStart > $xmax;
		
		my $shadowStartTime = $currentStart;
		my $shadowEndTime = $currentEnd;
		
		# Get shifted start times
		if($currentStart >= $x1 && $currentStart <= $xmax)
		{
			my $currentStartPath = ($currentStart - $x1) / $dx;
			$shadowStartTime = $currentStart + interpolatedValues($currentStartPath, @yDelay);
		};
		# Get shifted end times
		if($currentEnd >= $x1 && $currentEnd <= $xmax)
		{
			my $currentEndPath = ($currentEnd - $x1) / $dx;
			$shadowEndTime = $currentEnd + interpolatedValues($currentEndPath, @yDelay);
			
		};
		$shadowStartTime = $currentStart if $shadowStartTime < $currentStart;
		$shadowEndTime = $currentEnd if $shadowEndTime < $currentEnd;
		$shadowEndTime = $shadowStartTime if $shadowEndTime < $shadowStartTime;
		
		# Get Shadow item and change its times
		$SentenceLabel->currentItem('SHADOW', $CurrentItem);
		$SentenceLabel->currentStart('SHADOW', $shadowStartTime);
		$SentenceLabel->currentEnd('SHADOW', $shadowEndTime);
		$SentenceLabel->previousEnd('SHADOW', $shadowStartTime);
		$SentenceLabel->nextStart('SHADOW', $shadowEndTime);
	    };
	    $SentenceLabel->FoldedIDcodes();
	    my @AllTiers = reverse(@{$SentenceLabel->{'TIERORDER'}});
	    $SentenceLabel->print("$LabelFile.Shifted", @AllTiers);

    	};
};

