#!/usr/bin/env python

"""Duration estimator for speech.

Usage: s_slope [flags]
Flags:
	- -f FFF opens file FFF for reading.
	- -c XXX  selects column XXX (either a data name or an integer).
	- -o FFF  sets the output file.
	- -dt #.##   Sets the interval for calculating the output.

It takes a local spectrum,
bins it onto the Bark scale,
converts to perceptual loudness (via **E).
Then, it computes a measure of how far you can go
from each point before the spectrum changes too much.
"""

import sys
import math as M
import gpkimgclass
from gmisclib import die
from gmisclib import cache as CC
from gpk_voicing import pseudo_dur as PD

# These parameters are derived from /proj/aesop/QuasiDuration/adjust-med-v3.log,
# which derives from the code in /proj/aesop/QuasiDuration/bin/adjust-med-v3.py .
# This code optimized the match between the median quasiduration over a vowel and
# the duration, as determined by a manual segmentation.
C = 22.917
Lfac = M.exp(0.0753)
Nsv = 0.315
ROOT = '/tmp/pseudoduration_cache'



if __name__ == '__main__':
	# try:
		# import psyco
		# psyco.full()
	# except ImportError:
		# pass

	DT = 0.01	# Seconds.  Default output sampling interval.
	arglist = sys.argv[1:]
	arglist0 = arglist
	column = None
	Cache = None
	signalfile = None
	outfile = None
	extrahdr = {}
	RTYPE = 'pseudoduration'
	while arglist and arglist[0].startswith('-'):
		arg = arglist.pop(0)
		if arg == '--':
			break
		elif arg == '-DT' or arg == '-dt':
			DT = float(arglist.pop(0))
		elif arg == '-f':
			signalfile = arglist.pop(0)
		elif arg == '-c' or arg == '-col':
			tmp = arglist.pop(0)
			try:
				column = int( tmp )
			except ValueError:
				column = tmp
			die.note("signalfile", signalfile)
		elif arg == '-lfac':
			Lfac = M.exp(float(arglist.pop(0)))
		elif arg == '-Nsv':
			Nsv = float(arglist.pop(0))
			assert Nsv > 0.0
		elif arg == '-C':
			C = float(arglist.pop(0))
		elif arg == '-dur':
			RTYPE = 'pseudoduration'
		elif arg == '-logdur':
			RTYPE = 'log(pseudoduration)'
		elif arg == '-ctr':
			RTYPE = 'center_time'
		elif arg == '-o':
			outfile = arglist.pop(0)
		elif arg == '-cache':
			Cache = True
		elif arg == '-write':
			extrahdr = dict( [q.strip().split('=', 1)
					for q in arglist.pop(0).split(';') ]
					)
		else:
			die.info("Unrecognized flag: %s" % arg)
			print __doc__
			die.exit(1)
	if arglist and signalfile is None:
		signalfile = arglist.pop(0)
	if arglist and outfile is None:
		outfile = arglist.pop(0)
	elif outfile is None:
		outfile = 'pdur.dat'
	if column is None:
		column = 0
	if signalfile is None:
		die.info("No signal file specified.")
		print __doc__
		die.exit(1)
	if arglist:
		die.info('Extra arguments!')
		print __doc__
		die.exit(1)
	try:
		signal = gpkimgclass.read(signalfile)
	except gpkimgclass.CannotReadDataFile, x:
		die.die(x)
	try:
		signal.column(column)
	except KeyError:
		die.info("File has %d columns" % signal.n[1])
		die.die("Bad column: %s" % str(column))
	if Cache is not None:
		Cache = CC.cache_info(root=ROOT, file=signalfile, info=(column,))

	try:
		o = PD.pdur(signal.column(column), signal.dt(), DT, RTYPE, c=C, lfac=Lfac, Nsv=Nsv, cache_info=Cache)
	except:
		die.catch("Exception in pdur calculation")
		raise

	hdr = signal.hdr.copy()
	hdr['Pseudoduration_Params'] = "C=%s; Nsv=%s; lfac=%s" % (C, Nsv, Lfac)
	hdr['program'] = sys.argv[0]
	hdr['ARGV'] = arglist0
	hdr['input_file'] = signalfile
	hdr['column'] = column
	hdr['CDELT2'] = DT
	hdr['CRPIX2'] = 1
	hdr['CRVAL2'] = signal.start()
	hdr['CDELT1'] = 1
	hdr['TTYPE1'] = RTYPE
	hdr['BITPIX'] = -32
	hdr['DataSamplingFreq'] = 1.0/signal.dt()
	hdr.update( extrahdr )
	gpkimgclass.gpk_img(hdr, o).write(outfile)
