#!/usr/bin/perl
#
# HTKのHviteコマンドに下記の"option"を設定し、出力した場合の 'labファイル 'を、Praatの 'textgrid' 形式に変換します。
#   -a [Perform alignment]
#   -m [During recognition keep track of model boundaries]
# ※ smpPeriod period, fsize sample, fshift sample の値はjuliusのデフォルト設定に準じます。
#
# 実行例（第一引数：入力するファイルのパス　第二引数：出力するファイルのパス）
# > perl transalignHTK2textgrid.pl sample_1.lab sample_1.Textgrid
#
# 2013/04/03 宮澤幸希（m-kouki@moegi.waseda.jp）　協力：早大GITI 鍔木様
# 詳細説明は http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/24.html#e7a18792 および
#            http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/92.html#wf331b9e をご覧ください。
#
# 2014/01/31 Word層、Auto align層、Segment層、Memo層を出力するよう修正
#   ※ UTT-START、UTT-END は使用しません（書いてあっても構いません）。全ての行を読み込んで変換しています。
#   ※ cache.txt は実行後削除して構いません。

######################################################################

#はじめに音素の総数と単語の総数を調べ、最終行の音素の終了時間も計算しておく
$segmentNumber = 0;
$wordNumber = 0;
open(IN1, $ARGV[0]);
while ($line = <IN1>) { 
	$segmentNumber++;
	@str = split(/ /, $line);
	$strlength = @str;
	if ($strlength == 5) {
		$wordNumber++;
	} elsif ($str[2] eq "sil"){
		$wordNumber++;
	}
}
close(IN1);
$finalSegEndtime = $str[1] * 0.0000001;		# 単位を[s]に変換する

# silラベルを単語扱いで追記したキャッシュファイルを出力する
open(OUT, "> cache.txt");
print(OUT "");								# キャッシュファイル初期化
$wordLabel = "";
open(IN2, $ARGV[0]);
while ($line = <IN2>) {
	@str = split(/ /, $line);
	$strlength = @str;
	if ($str[2] eq "sil") {
		open(OUT, ">> cache.txt");
		chomp($str[3]);
		print(OUT "$str[0] $str[1] $str[2] $str[3] sil\n");
	} else {
		open(OUT, ">> cache.txt");
		print(OUT "$line");
	}
}
close(IN2);

#出力ファイル初期化
open(OUT, "> $ARGV[1]");
print(OUT "File type = \"ooTextFile\"\n");
print(OUT "Object class = \"TextGrid\"\n");
print(OUT "\n");
print(OUT "xmin = 0\n");
print(OUT "xmax = $finalSegEndtime \n");
print(OUT "tiers? <exists>\n");
print(OUT "size = 4\n");
print(OUT "item []: \n");

#単語を読み込んで、時間情報を計算して、TextGrid形式で出力する (Word)
open(OUT, ">> $ARGV[1]");
print(OUT "    item [1]:\n");
print(OUT "        class = \"IntervalTier\" \n");
print(OUT "        name = \"Word\" \n");
print(OUT "        xmin = 0 \n");
print(OUT "        xmax = $finalSegEndtime \n");
print(OUT "        intervals: size = $wordNumber \n");
close(OUT);
#入力ファイル読み込み
$lineCount = 1;
$wordCount = 1;
$wordname = "sil";
$wordBegintime = 0;
open(IN3, "cache.txt");
while ($line = <IN3>) {
	#print $line;
	#開始時間・終了時間を取得／計算
	@str = split(/ /, $line);
	$strlength = @str;
	#音素の開始時間
	$segBegintime = $str[0] * 0.0000001;
	#音素の終了時間
	$segEndtime = $str[1] * 0.0000001;
	if ($lineCount > 1) {
		if ($strlength == 5) {
			#新しい単語ラベルが出現したとき
			open(OUT, ">> $ARGV[1]");
			print(OUT "        intervals [$wordCount]:\n");
			print(OUT "            xmin = $wordBegintime \n");
			print(OUT "            xmax = $segBegintime \n");
			print(OUT "            text = \"$wordname\" \n");
			close(OUT);
			$wordname = $str[4];
			chomp($wordname);
			$wordBegintime = $segBegintime;
			$wordCount++;
		}
	}
	$lineCount++;
}
#最後の単語
open(OUT, ">> $ARGV[1]");
print(OUT "        intervals [$wordCount]:\n");
print(OUT "            xmin = $wordBegintime \n");
print(OUT "            xmax = $segEndtime \n");
print(OUT "            text = \"$wordname\" \n");
close(OUT);
close(IN3);

#音素を読み込んで、時間情報を計算して、TextGrid形式で出力する (Auto align)
open(OUT, ">> $ARGV[1]");
print(OUT "    item [2]:\n");
print(OUT "        class = \"IntervalTier\" \n");
print(OUT "        name = \"Auto align\" \n");
print(OUT "        xmin = 0 \n");
print(OUT "        xmax = $finalSegEndtime \n");
print(OUT "        intervals: size = $segmentNumber \n");
close(OUT);
#入力ファイル読み込み
$segmentCount = 1;
open(IN4, "cache.txt");
while ($line = <IN4>) {
	#print $line;
	#開始時間・終了時間を取得／計算
	@str = split(/ /, $line);
	#開始時間
	$segBegintime = $str[0] * 0.0000001;
	#終了時間
	$segEndtime = $str[1] * 0.0000001;
	#音素名
	$segmentName = $str[2];

	#出力ファイル書き込み
	open(OUT, ">> $ARGV[1]");
	print(OUT "        intervals [$segmentCount]:\n");
	print(OUT "            xmin = $segBegintime \n");
	print(OUT "            xmax = $segEndtime \n");
	print(OUT "            text = \"$segmentName\" \n");
	close(OUT);
	$segmentCount++;
}
close(IN4);

#音素を読み込んで、時間情報を計算して、TextGrid形式で出力する (Segment)
open(OUT, ">> $ARGV[1]");
print(OUT "    item [3]:\n");
print(OUT "        class = \"IntervalTier\" \n");
print(OUT "        name = \"Segment\" \n");
print(OUT "        xmin = 0 \n");
print(OUT "        xmax = $finalSegEndtime \n");
print(OUT "        intervals: size = $segmentNumber \n");
close(OUT);
#入力ファイル読み込み
$segmentCount = 1;
open(IN5, "cache.txt");
while ($line = <IN5>) {
	#print $line;
	#開始時間・終了時間を取得／計算
	@str = split(/ /, $line);
	#開始時間
	$segBegintime = $str[0] * 0.0000001;
	#終了時間
	$segEndtime = $str[1] * 0.0000001;
	#音素名
	$segmentName = $str[2];

	#出力ファイル書き込み
	open(OUT, ">> $ARGV[1]");
	print(OUT "        intervals [$segmentCount]:\n");
	print(OUT "            xmin = $segBegintime \n");
	print(OUT "            xmax = $segEndtime \n");
	print(OUT "            text = \"$segmentName\" \n");
	close(OUT);
	$segmentCount++;
}
close(IN5);

#単語を読み込んで、時間情報を計算して、TextGrid形式で出力する (Memo)
open(OUT, ">> $ARGV[1]");
print(OUT "    item [4]:\n");
print(OUT "        class = \"IntervalTier\" \n");
print(OUT "        name = \"Memo\" \n");
print(OUT "        xmin = 0 \n");
print(OUT "        xmax = $finalSegEndtime \n");
print(OUT "        intervals: size = $wordNumber \n");
close(OUT);
#入力ファイル読み込み
$lineCount = 1;
$wordCount = 1;
$wordname = "sil";
$wordBegintime = 0;
open(IN3, "cache.txt");
while ($line = <IN3>) {
	#print $line;
	#開始時間・終了時間を取得／計算
	@str = split(/ /, $line);
	$strlength = @str;
	#音素の開始時間
	$segBegintime = $str[0] * 0.0000001;
	#音素の終了時間
	$segEndtime = $str[1] * 0.0000001;
	if ($lineCount > 1) {
		if ($strlength == 5) {
			#新しい単語ラベルが出現したとき
			open(OUT, ">> $ARGV[1]");
			print(OUT "        intervals [$wordCount]:\n");
			print(OUT "            xmin = $wordBegintime \n");
			print(OUT "            xmax = $segBegintime \n");
			print(OUT "            text = \"\" \n");
			close(OUT);
			$wordname = $str[4];
			chomp($wordname);
			$wordBegintime = $segBegintime;
			$wordCount++;
		}
	}
	$lineCount++;
}
#最後の単語
open(OUT, ">> $ARGV[1]");
print(OUT "        intervals [$wordCount]:\n");
print(OUT "            xmin = $wordBegintime \n");
print(OUT "            xmax = $segEndtime \n");
print(OUT "            text = \"\" \n");
close(OUT);
close(IN3);
