#! python
'''This script converts mlf labels generated by HVite to wavesurfer .lab format and
stores them in the corresponding proce/response/$SPEAKER/$SESSION/$FILE folder.
It is normally called by .../bin/rec_e.sh .

Usage: convert_ws_lab.py outpart fiat_file mlf_folder
where:
-	C{outpart} is typically the name of the original MFCC file containing the
	audio feature vectors
-	C{fiat_file} is
-	C{mlf_folder} is
'''


import os
import sys

from gmisclib import die
from gmisclib import fiatio
from gmisclib import threaded_io
from gmisclib import wavesurfer_lab as WS
from gmisclib import HTK_MLF_io as HTK

RESP = '/proj/aesop/proc'


class NoMLFfileError(ValueError):
	def __init__(self, *s):
		ValueError.__init__(self, *s)



def convert_mlf(file):
	"""We convert from MLF format, as produced by HVite to wavesurfer label format.
	We also post-process the labels, eliminating "I" transition labels and merging
	sequences of identical phonemes into big vocalic and consonantal regions.
	"""
	HTK_labs = HTK.read(file, findfile=False, time_quantum=1e-07)
	if len(HTK_labs) != 1:
		die.warn("Whoops - %d utterance in MLF file; need one." % len(HTK_labs))
		raise NoMLFfileError
	derived = []
	for (s, e, l, q) in HTK_labs[0]['symbols']:
		derived.append((s, e, l))

	# i = 1
	# while i+1 < len(derived):
		# if derived[i][2]=='I':
			# assert derived[i-1][2]!='I' and derived[i+1][2]!='I'
			# imid = 0.5*(derived[i][0] + derived[i][1])
			# derived[i-1] = (derived[i-1][0], imid, derived[i-1][2])
			# derived[i+1] = (imid, derived[i+1][0], derived[i+1][2])
			# del derived[i]
		# else:
			# i += 1
	i = 1
	while i < len(derived):
		if derived[i-1][2] == derived[i][2]:
			derived[i-1] = (derived[i-1][0], derived[i][1], derived[i-1][2])
			del derived[i]
		else:
			i += 1
	return sorted(derived)
	



def process(argv):
	print 'start'
	assert len(argv)>=4
	outpart = argv[1]
	inbase = argv[2]
	hdr, data, comments = fiatio.read(open(argv[3], 'r'))
	print len(data), 'lines in', argv[3]
	index = {}
	for line in data:
		index[line['fncore']+'.mlf'] = line
	mlf = os.listdir(inbase)
	print len(mlf), 'Entries in directory', inbase
	tp = threaded_io.Thread_poolW(4)
	for fn in mlf:
		if fn in index:
			info = index[fn]
			tp.start(process_one, args=(info, outpart, inbase, fn))
			# process_one(info, outpart, inbase, fn)
		else:
			die.warn('FN not in index: %s' % fn)


def process_one(info, outpart, inbase, fn):
	ofn = os.path.join(info['dbdir'], info['d'], info['f'], outpart+'.lab')
	print fn, '->', ofn
	try:
		wslabs = convert_mlf(os.path.join(inbase, fn))
	except NoMLFfileError:
		die.info("Error processing %s" % os.path.join(info['dbdir'], info['d'], info['f']))
		try:
			os.remove(ofn)
		except (OSError, IOError):
			pass
	else:
		WS.write(open(ofn, 'w'),
			{'file':fn, 'd': info['d'], 'f': info['f'],
			'dbdir': info['dbdir'],
			'metadatafile': info['metadatafile']
			},
			wslabs)


if __name__ == '__main__':
	process(sys.argv)
