#!/usr/bin/perl
#
# juliusのセグメンテーションキットが出力した 'trans.align' 形式のファイルを、'CSV' 形式に変換します。
# ※ smpPeriod period, fsize sample, fshift sample の値はjuliusのデフォルト設定に準じます。
# ※ 音素は silB で始まり silE で終わっている必要があります。
# ※ 第一引数には .align ファイルの代わりに .log ファイルを指定することもできます。
#
# 実行例（第一引数：入力するファイルのパス　第二引数：出力するファイルのパス）
# > perl transalign2textgrid.pl sample.trans.align sample.csv
#
# 2013/04/04 宮澤幸希（m-kouki@moegi.waseda.jp）
# 詳細説明は http://shower.human.waseda.ac.jp/~m-kouki/pukiwiki_public/24.html#e7a18792 をご覧ください。
# 2013/08/14 改行記号の除去がPC環境によって失敗するため、処理を追記しました

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

#はじめに音素の総数を調べ、最終音素(silE)の終了時間も計算しておく
$segmentCount = 1;
$segmentSwitch1 = 0;
$segmentSwitch2 = 0;
$finalSegEndframe = 0;
$finalSegEndtime = 0;
#入力ファイル読み込み
open(IN1, $ARGV[0]);
while ($line = <IN1>) { 
	if ($line =~ /begin forced alignment/) {
		$segmentSwitch1 = 1;
	}
	if (($segmentSwitch1 == 1)&&($line =~ /silB/)) {
		$segmentSwitch2 = 1;
	} elsif (($segmentSwitch1 == 1)&&($line =~ /silE/)) {
		$segmentSwitch2 = 0;
		#最終音素(silE)の終了時間の計算
		@str1 = split(/]/, $line);
		@str2 = split(/ /, $str1[0]);
		$finalSegEndframe = $str2[$#str2];	#配列の最後の要素を得る
		#終了時間は「フレームシフトサイズ × (フレーム番号 + 1)」（次の音素の開始時間と合わせるためです）
		$finalSegEndtime = 0.010 * ($finalSegEndframe + 1);
	}
	if ($segmentSwitch2 == 1) {
		$segmentCount++;
	}
}
close(IN1);

#音素を読み込んで、時間情報を計算して、CSV形式で出力する
#出力ファイル初期化
open(OUT, "> $ARGV[1]");
print(OUT "");
close(OUT);
#入力ファイル読み込み
$segmentCount = 1;
$segmentSwitch1 = 0;
$segmentSwitch2 = 0;
open(IN2, $ARGV[0]);
while ($line = <IN2>) {
	#print $line;
	if ($line =~ /begin forced alignment/) {
		$segmentSwitch1 = 1;
	}
	if (($segmentSwitch1 == 1)&&($line =~ /silB/)) {
		$segmentSwitch2 = 1;
	}
	if ($segmentSwitch2 == 1) {
		#開始時間・終了時間を取得／計算
		@str1 = split(/]/, $line);
		@str2 = split(/ /, $str1[0]);
		#空の配列を削除した配列str3を作る
		@str3 = ();		#配列の初期化
		for($i = 0; $i < @str2; $i++) {
			if($str2[$i] ne "") {
				push(@str3, $str2[$i]);
			}
		}
		$segBeginframe = $str3[1];
		$segEndframe = $str3[2];
		#開始時間は「フレームシフトサイズ × フレーム番号」
		$segBegintime = 0.010 * $segBeginframe;
		#終了時間は「フレームシフトサイズ × (フレーム番号 + 1)」（次の音素の開始時間と合わせるためです）
		$segEndtime = 0.010 * ($segEndframe + 1);
		#音素名を得る
		@str4 = split(/ /, $str1[1]);
		$segmentName = $str4[$#str4];
		chomp($segmentName);	#改行記号を除去
		$segmentName =~ s/\r//;	#改行記号を除去
		$segmentName =~ s/\n//;	#改行記号を除去
		
		#出力ファイル書き込み
		open(OUT, ">> $ARGV[1]");
		print(OUT "$segmentName,$segBegintime,$segEndtime\n");
		close(OUT);
		$segmentCount++;
	}
	if (($segmentSwitch1 == 1)&&($line =~ /silE/)) {
		$segmentSwitch2 = 0;
	}
}
close(IN2);


