#!/bin/bash
#
#########
#  say  #
#########
#
# Speak text from stdin or from a file or from commandline argument.
# Optionally save results to sound file.
# Version: 1.0
# Author:  vodoo@vakw.ch
# License: GPL-v2
# usage:   say [-h] [-u] [-q] [-f] [-de|-en|-fr] \
#              [-v <voice>] [-o <file>] [<file>|"text"]
#
VERSION='1.0'

case "$1" in (-h|-H|--help)
	echo 'Usage:'
	echo 'say [-h] [-u] [-q] [-f] [-de|-en|-fr] [-v <voice>] [-o <file>] [<file>|"text"]'
	echo '   -h  print this help message'
	echo '   -u  text input is UTF-8'
	echo "   -q  quiet mode, don't speak"
	echo '   -f  use festival instead of mbrola for english text'
	echo '  -de  speak german input text'
	echo '  -fr  speak french input text'
	echo '  -en  speak english input text'
	echo '   -v  use mbrola voice de[1..8] | fr[1..7] | en[1] | us[1..3]'
	echo '       for festival: awb, bdl, clb, jmk, ksp, rms, slt, kal (default)'
	echo '   -i  <file> File contains input text'
	echo '   -o  output sound to <file.{wav|au}>'
	echo '   -t  "<text>" With -t text can be entered at any position.'
	echo
	echo 'Input text to speak as filename or as last argument or with the -t option.'
	echo 'When text is missing or it is a hyphen (-) text input is expected on stdin.'
	echo 'Text may be in English, German or French. The language is autodetected'
	echo 'whenever the text sample is big enough.'
	echo
	echo 'Note: Cross-speaking is supported for en->de and en->fr. This means that'
	echo '      you may select a german or french voice for english text.'
	exit 0
	;;
esac


# pick a default voice here for each supported language and it's sex:
#
# German
MAXVOICE_DE=8
VOICESEXDE[0]=x
VOICESEXDE[1]=f
VOICESEXDE[2]=m
VOICESEXDE[3]=f
VOICESEXDE[4]=m
VOICESEXDE[5]=f
VOICESEXDE[6]=m
VOICESEXDE[7]=f
VOICESEXDE[8]=m
#
VOICEFREQDE[0]=''
VOICEFREQDE[1]='-f 1.2 -t 1.0'
VOICEFREQDE[2]='-f 1.1'
VOICEFREQDE[3]=''
VOICEFREQDE[4]=''
VOICEFREQDE[5]=''
VOICEFREQDE[6]=''
VOICEFREQDE[7]='-f 1.1'
VOICEFREQDE[8]=''
# Default:
VOICE_DE=de7
FREQ_DE='-f 1.0 -t 1.0'
SEX_DE=f

# English
MAXVOICE_EN=1
VOICESEXEN[0]=x
VOICESEXEN[1]=m
VOICEFREQEN[1]='-f 1.0 -t 1.2'
# Default:
VOICE_EN=en1
FREQ_EN='-f 1.0 -t 1.2'
SEX_EN=m
#
MAXVOICE_US=3
VOICESEXUS[0]=x
VOICESEXUS[1]=f
VOICESEXUS[2]=m
VOICESEXUS[3]=m
VOICEFREQUS[0]=''
VOICEFREQUS[1]=''
VOICEFREQUS[2]=''
VOICEFREQUS[3]=''

# French
MAXVOICE_FR=7
VOICESEXFR[0]=x
VOICESEXFR[1]=m
VOICESEXFR[2]=f
VOICESEXFR[3]=m
VOICESEXFR[4]=f
VOICESEXFR[5]=m
VOICESEXFR[6]=m
VOICESEXFR[7]=m
VOICEFREQFR[0]=''
VOICEFREQFR[1]='-v 1.1 -f 1.1'
VOICEFREQFR[2]='-v 1.2 -f 1.65 -t 1.1'
VOICEFREQFR[3]='-v 1.1 -f 1.2'
VOICEFREQFR[4]='-v 1.0 -f 1.6 -t 1.0'
VOICEFREQFR[5]='-v 1.3 -f 1.1'
VOICEFREQFR[6]='-v 1.1 -f 1.1'
VOICEFREQFR[7]='-v 1.3 -f 1.1'
# Default:
VOICE_FR=fr4
SEX_FR=f
FREQ_FR='-f 1.6 -t 1.0'

# Default voice for festival
FVOICE='kal'

# set defaults
DEBUG='false'
#DEBUG='true'
DEFAULTLANGUAGE='xx'
LANGUAGE=''
VOICELANG=''
VOICENUMBER='0'
CONVERSION=''
SEX='f'
QUIET='false'
SYNTH='mbrola'
OFILE='false'
IFILE='false'
BINDIR='/usr/bin'
CMULEAD='cmu_us_'
CMUTAIL='_arctic_clunits'
PACKMAN='false'
OPTTTXT='false'
WARNING='false'
XLANG=''

# Where are the needed files?
LANGDIR='/usr/share/mbrola'

# User might install mbrola from packman
# Packman provides mbrola with pipefilt, preproc and txt2pho
# Search data for preproc:
if test -r "$LANGDIR/Hadifix.abk" && test -r "$LANGDIR/Rules.lst" ; then
	PPDIR="$LANGDIR"
	PACKMAN='true'
else
	PPDIR='/usr/share/preproc'
fi

# Search data for txt2pho:
if $PACKMAN && test -r "$LANGDIR/data/hadifix.cfg" ; then
	TTPDIR="$LANGDIR/data"
else
	TTPDIR='/usr/share/txt2pho/data'
fi

# Other paths
LLIADIR='/usr/share/lliaphon'
FRPHDIR='/usr/share/freephone/lexicon'
FESTVCE='/usr/share/festival/voices'

# options for dvi2tty (-w 132 already set)
DVIOPTIONS="-v 600000"

# test the arguments; can be: -u -q -w -d -f -de -en -fr -v -o
DOARGS='true'
while $DOARGS ; do
    if test -n "$1" ; then
	if test "$1" == '-V' ; then
		echo "say version $VERSION"
		exit 0
	elif test "$1" == '-w' ; then
		WARNING='true'
		shift 1
	elif test "$1" == '-d' ; then
		DEBUG='true'
		shift 1
	elif test "$1" == '-u' ; then
		CONVERSION='| iconv -c -f UTF-8 -t ISO_8859-1 -'
		#CONVERSION='| recode -f UTF-8..Latin-1'
		shift 1
	elif test "$1" == '-q' ; then
		QUIET='true'
		shift 1
	elif test "$1" == '-f' || test "$1" == '--festival' ; then
		SYNTH='festival'
		shift 1
	elif test "$1" == '-de' ; then
		LANGUAGE='de'
		shift 1
	elif test "$1" == '-en' ; then
		LANGUAGE='en'
		shift 1
	elif test "$1" == '-fr' ; then
		LANGUAGE='fr'
		shift 1
	elif test "$1" == '-v' ; then
		shift 1
		# there must be another argument for the voice
		if test -n "$1" ; then
		    case "$1" in
			de|fr|en|us|de[12345678]|fr[1234567]|en1|us[123]|1|2|3|4|5|6|7|8)
				VOICESELECTED="$1"
				shift 1
				;;

			awb|bdl|clb|jmk|ksp|rms|slt|kal)
				FVOICE="$1"
				SYNTH='festival'
				shift 1
				;;

			*)	echo "Illegal argument -v $1" 1>&2
				exit 1
				;;
		    esac
		else
			echo "Missing voice argument after -v" 1>&2
			exit 1
		fi
	elif test "$1" == '-o' ; then
		shift 1
		# there must be another argument for the output file
		if test -n "$1" ; then
			OUTFILEARG="$1"
			shift 1
			SUFFIX=$(echo $OUTFILEARG | sed \
				-e 's/^\(.*\.\)\(.*\)/.\2/')

			OPATH=$(dirname "$OUTFILEARG")
			OARG=$(basename "$OUTFILEARG")

			case $SUFFIX in
				.au)	OUTFILETMP="$OARG"
					OFILE='true'
					;;
				.wav)	OUTFILETMP=$(echo "$OARG" | sed \
					-e 's/\.wav$/.au/')
					OFILE='true'
					;;
				*)	echo "Illegal outfile suffix. Got '$OARG'. Must be *.au or *.wav" 1>&2
					exit 1
					;;
			esac
		else
			echo "Missing outfile argument after -o" 1>&2
		fi
	elif test "$1" == '-t' ; then
		shift 1
		# there must be another argument for the text
		if test -n "$1" ; then
			INTEXT="$1"
			OPTTTXT='true'
			shift 1
		else
			echo "Missing text argument after -t" 1>&2
		fi
	elif test "$1" == '-i' ; then
		shift 1
		if test -n "$1" ; then
			INFILE="$1"
			IFILE='true'
			shift 1
		else
			echo "Missing file argument after -t" 1>&2
		fi
	else
		DOARGS='false'
	fi
    else
	DOARGS='false'
    fi
done

# Safeguard against wrong /etc/txt2pho
if ! test -r /etc/txt2pho ; then
	echo "Error: /etc/txt2pho missing or not readable." 1>&2
	exit 1
fi

if $WARNING || $DEBUG ; then
	DCONFBAD=$(cat /etc/txt2pho | sed -e '/^DATAPATH=/!d' \
	-e "s|^DATAPATH=${TTPDIR}/$|false|; s/DATAPATH=.*/true/; s/^$/true/")

	ICONFBAD=$(cat /etc/txt2pho | sed -e '/^INVPATH=/!d' \
	-e "s|^INVPATH=${TTPDIR}/$|false|; s/INVPATH=.*/true/; s/^$/true/")

	if $DCONFBAD || $ICONFBAD ; then
	echo "Check /etc/txt2pho: DATAPATH= or INVPATH= point to wrong directory." 1>&2
	echo "                    Both should point to ${TTPDIR}/" 1>&2
	fi
fi

# Check that festival and required voice is available
if test $SYNTH == 'festival' ; then
	if ! test -x $BINDIR/festival || ! test -x $BINDIR/text2wave ; then
		echo "'festival' is not installed. Don't use -f or any festival voice."
		exit 1
	fi

	# Check for the voice too
	case "$FVOICE" in
		(awb|bdl|clb|jmk|ksp|rms|slt)
		VDIR="$FESTVCE/english/${CMULEAD}${FVOICE}${CMUTAIL}"
		;;
		(kal)
		VDIR="$FESTVCE/english/kal_diphone"
		;;
		(*)
		VDIR='foo'
		;;
	esac

	if ! test -d "$VDIR" ; then
		echo "'festival' voice '$FVOICE' is not installed."
		exit 1
	fi
fi

# Prepare sound output method
if $QUIET ; then
	SOUNDPLAYER='> /dev/null'
else
	if test $SYNTH == 'mbrola' ; then
		SOUNDPLAYER='| play -q -t au -'
	else
		SOUNDPLAYER='| play -q -t wav -'
	fi
fi

# Prepare output argument for synthesizer
if $OFILE ; then
	if test $SYNTH == 'mbrola' ; then
		OCMD="-.au | tee $OPATH/$OUTFILETMP"
	else
		# It must be a .wav file anyway
		OUTFILETMP=$(echo "$OUTFILETMP" | sed -e 's/\.au$/.wav/')
		OCMD="| tee $OPATH/$OUTFILETMP"
	fi
else
	if test $SYNTH == 'mbrola' ; then
		OCMD='-.au'
	else
		OCMD=''
	fi
fi

if $DEBUG ; then
	echo "Evaluation of arguments resulted in:" 1>&2
	echo "LANGUAGE      = $LANGUAGE" 1>&2
	echo "VOICESELECTED = $VOICESELECTED" 1>&2
	echo "CONVERSION    = $CONVERSION" 1>&2
	echo "WARNING       = $WARNING" 1>&2
	echo "QUIET         = $QUIET" 1>&2
	echo "SYNTH         = $SYNTH" 1>&2
	echo "OUTFILE       = $OUTFILETMP" 1>&2
	echo 1>&2
fi


# Set values for VOICELANG and VOICENUMBER when -v <voice> is given
if test $SYNTH == 'mbrola' ; then
    VOICESTRIPPED=$(echo "$VOICESELECTED" | sed -e "s/[0-9]//g")
    if test -n "$VOICESTRIPPED" ; then
	# More than a bare number was given
	case "$VOICESTRIPPED" in (de|fr|en|us)
		VOICELANG="$VOICESTRIPPED"
		VOICENUMBER=$(echo "$VOICESELECTED" | sed -e "s/[defrnus]//g")
		if test -z "$VOICENUMBER" ; then
			# Fall back to default values
			case "$VOICESTRIPPED" in
			de) VOICENUMBER=$(echo $VOICE_DE | sed -e 's/de//') ;;
			fr) VOICENUMBER=$(echo $VOICE_FR | sed -e 's/fr//') ;;
			en) VOICENUMBER=$(echo $VOICE_EN | sed -e 's/en//') ;;
			us) VOICENUMBER=$(echo $VOICE_US | sed -e 's/us//') ;;
			esac
		fi
	;;

	# This should never happen, as we checked arguments before
	*) echo "Illegal argument -v $VOICENUMBER" 1>&2
	   exit 1
	   ;;
	esac
    else
	# Maybe just the voice number was given
	if test -n "$VOICESELECTED" ; then
		case "$VOICESELECTED" in
			1|2|3|4|5|6|7|8) VOICENUMBER="$VOICESELECTED"
			;;

			*) echo "Illegal voice number $VOICESELECTED" 1>&2
			;;
		esac
	fi
    fi
fi

# Test where our input comes from (stdin, file, commandline)
# OPTTTXT means that -t was used and text is in $INTEXT
BLANKS=''
if test -n "$1" && ! $OPTTTXT && ! $IFILE ; then
	# there is an argument: text or filename
	# when this is text we expect some blanks in it
	BLANKS=$(echo "$1" | tr -d '\012' | sed -e "s/[^ ]//g; s/ /Y/g")
	if test -z "$BLANKS" ; then
		if test "$1" == '-' ; then
			FTYPE='stdin'
		# no blanks, try this as a file
		elif test -r "$1" ; then
			# file is present and readable, use as text input
			FTYPE='file'
		else
			# argument is the text
			FTYPE='arg'
		fi
	else
		# contains blanks, $1 is the text
		FTYPE='arg'
	fi
elif $OPTTTXT || $IFILE ; then
	if $OPTTTXT ; then
		if test "$INTEXT" == '-' ; then
			FTYPE='stdin'
		else
			FTYPE='arg'
		fi
	fi

	if $IFILE ; then
		if test "$INFILE" == '-' ; then
			FTYPE='stdin'
		else
			FTYPE='file'
		fi
	fi
else # no more arguments
	FTYPE='stdin'
fi

# Make a simple temporary filename to buffer input text
TMPFILE="/tmp/say.tmp.$$.txt"

# If text is a file we may have to convert according to the suffix
if test $FTYPE == 'file' ; then
	# Check that file is readable
	if $IFILE ; then
		if ! test -r "$INFILE" ; then
			echo "Input file $INFILE is missing or not readable" 1>&2
			exit 1
		fi
	else
		if ! test -r "$1" ; then
			echo "Input file $1 is missing or not readable" 1>&2
			exit 1
		fi
	fi

	# get the suffix
	SUFF=$(echo "$1" | sed  -e 's/^\(.*\)\(\.[a-z][a-z]*\)$/\2/i; s/^.//')

	case "$SUFF" in
		pdf)	pdftotext -raw "$1" - > $TMPFILE ;;
		html)	lynx -nolist -dump "$1" > $TMPFILE ;;
		dvi)	dvi2tty -w 132 $DVIOPTS "$1" > $TMPFILE ;;
		*)	if $IFILE ; then
			    cat "$INFILE" > $TMPFILE
			else
			    cat "$1" > $TMPFILE # Assume plain text
			fi
			;;
	esac
elif test $FTYPE == 'arg' ; then
	if $OPTTTXT ; then
		echo "$INTEXT" > $TMPFILE
	else
		echo "$1" > $TMPFILE
	fi
elif test $FTYPE == 'stdin' ; then
	cat - > $TMPFILE
else
	echo "ERROR: missing input text" 1>&2
	exit 1
fi


# AUTODETECT LANGUAGE
# Here we have the text in $TMPFILE
# if LANGUAGE is still unset do auto-detection
# get the first few lines, split into words
if test -z "$LANGUAGE" ; then

	if "$DEBUG" ; then
		echo "autodetecting language ..." 1>&2
	fi

	WORDS=$(head -n 10 $TMPFILE | tr 'A-Z' 'a-z' | sed \
	-e "s/'/ /g" \
	-e 's/[^a-z ]/ /g' \
	-e 's/  */ /g' \
	-e 's/^  *//' \
	-e 's/  *$//' \
	-e '/^$/ d' | tr ' ' '\012')

	# set initial scores to zero
	GERMAN='0'
	FRENCH='0'
	ENGLISH='0'

	for word in $WORDS ; do
	case $word in
	# top 100 german words
	# der|die|und|den|von|zu|das|mit|sich|auf|fr|ist|im|dem|nicht|ein|eine|als|auch|es|an|werden|aus|er|hat|dass|sie|nach|wird|bei|einer|um|am|sind|noch|wie|einem|ber|einen|zum|war|haben|nur|oder|aber|vor|zur|bis|mehr|durch|man|sein|wurde|sei|hatte|kann|gegen|vom|knnen|schon|wenn|habe|seine|ihre|dann|unter|wir|soll|ich|eines|jahr|zwei|jahren|diese|dieser|wieder|keine|uhr|seiner|worden|will|zwischen|immer|millionen|was|sagte)
	# top 255 german words
	ich|ist|nicht|sie|du|das|die|es|und|der|zu|ein|'in'|wir|mir|mit|was|den|mich|auf|dass|er|eine|hat|so|sind|von|dich|war|haben|fr|ja|hier|an|habe|bin|wie|noch|dir|uns|sich|nur|einen|nein|dem|ihn|auch|hast|sein|ihr|da|aus|kann|aber|schon|wenn|wird|um|als|bist|im|mal|doch|gut|meine|jetzt|weiss|werden|nach|oder|dann|will|mein|mehr|keine|etwas|alles|muss|immer|nichts|man|wieder|bei|hab|machen|vor|mann|ihm|einem|tun|zum|knnen|sagen|werde|denn|warum|einer|gehen|sehen|sehr|geht|alle|ber|mssen|diese|einfach|euch|des|nie|also|wo|los|zeit|ihnen|gibt|wirklich|danke|deine|wrde|soll|hatte|wissen|bitte|viel|gesagt|am|kein|komm|wer|zurck|wurde|wollte|frau|leben|wre|damit|gott|leute|kannst|heute|meinen|dieser|dein|kommt|kommen|willst|na|wollen|sicher|ganz|zur|htte|weil|tut|hallo|okay|macht|waren|bis|vielleicht|knnte|weg|seine|lassen|vater|gesehen|nun|gerade|glaube|tag|ab|geld|gemacht|sollte|sagte|keinen|durch|zwei|diesen|passiert|wohl|ihre|mutter|reden|anderen|dachte|mchte|wirst|gehrt|weisst|raus|paar|besser|ob|her|musst|ordnung|meiner|klar|diesem|meinem|lange|lass|dieses|helfen|unsere|selbst|finden|jemand|denke|ach|nacht|genau|gar|sagt|welt|mdchen|ins|hin|vom|schn|weiter|leid|gleich|ohne|menschen|deinen|wieso|dort|hause|sollten|davon|zusammen|geben|hr|machst|freund|richtig|angst|viele|sieht|haus|tot|sollen|ganze|andere|getan|rein|moment|bleiben|brauchen|kinder|unter|arbeit|problem)
	GERMAN=$(($GERMAN + 1))
	if $DEBUG ; then
		echo "de=$word" 1>&2
	fi
	;;

	# top 100 french words
	# de|la|le|et|les|en|un|du|une|que|est|pour|qui|dans|par|plus|pas|au|sur|ne|se|ce|il|sont|ou|avec|son|aux|cette|ont|ses|mais|comme|on|tout|nous|sa|fait|t|aussi|leur|bien|peut|ces|y|deux|ans|encore|march|donc|cours|moins|sans|si|entre|faire|elle|peu|vous|prix|dont|lui|galement|effet|pays|cas|millions|mois|leurs|taux|annes|temps|groupe)
	# top 255 french words
	je|de|est|pas|le|vous|la|tu|que|un|il|et|ne|les|ce|en|on|a|une|ai|pour|des|moi|qui|nous|mais|me|dans|du|bien|elle|si|tout|plus|non|mon|suis|te|au|avec|va|oui|toi|fait|ils|as|tre|faire|se|comme|tait|sur|quoi|ici|sais|lui|veux|ma|l|rien|dit|es|o|votre|pourquoi|sont|cette|quand|par|son|ton|peux|vais|dire|alors|comment|avez|bon|ou|trs|merci|ont|mme|jamais|aussi|voir|chose|allez|tous|deux|ces|faut|sa|tes|t|ta|fais|avoir|peut|autre|encore|maintenant|peu|mes|vraiment|temps|notre|toujours|vie|sans|juste|avait|accord|vu|monde|quelque|fois|aller|trop|viens|crois|dieu|dois|homme|pre|sr|aux|leur|avant|tais|besoin|femme|aime|personne|avais|chez|vrai|ans|mal|ses|parler|vos|aprs|mort|veut|eu|sera|bonne|parce|mieux|petit|voil|tes|ca|dis|beaucoup|depuis|doit|vois|mre|vas|monsieur|quel|dj|fille|gens|donc|jour|soir|autres|ii|toute|bonjour|maison|nom|argent|nos|ouais|pense|merde|nuit|papa|cela|salut|cet|avons|reste|dsol|maman|peur|arrive|seul|vite|prendre|regarde|air|soit|trois|quelle|pass|savoir|plat|choses|moins|fils|entre|bas|appelle|passe|ah|tte|demain|grand|arrte|faites|voulez|h|attends|hein|enfants|assez|raison|aurais|voulais|elles|parle|jours|d|moment|heure|puis|gars|hommes|amour|tard|toutes|sommes|tuer|eh|ami|connais|petite|aider|chance|savez|partir|sait|combien|voiture|tant|pris|part|problme|prends|porte)
	FRENCH=$(($FRENCH + 1))
	if $DEBUG ; then
		echo "fr=$word" 1>&2
	fi
	;;

	# top 100 english words
	# the|of|to|and|'for'|is|that|on|said|with|be|was|by|as|are|at|from|it|has|an|have|will|or|its|he|not|were|which|this|but|can|more|his|been|would|about|their|also|they|million|had|than|up|who|one|you|new|other|year|all|two|company|into|system|some|when|out|last|only|after|first|'time'|says|years|market|no|over|we|could|'if'|people|percent|such|most|use|because|any|data|there|them|government|may|software|now|many|my)
	# top 255 english words
	you|to|the|and|that|it|of|me|what|is|'in'|this|know|'for'|no|have|my|just|not|'do'|be|on|your|was|we|with|so|but|all|well|are|he|about|right|get|here|out|going|like|yeah|'if'|her|she|can|up|want|think|now|go|him|at|how|got|there|one|did|why|see|come|good|they|really|as|would|look|when|'time'|will|okay|back|mean|tell|from|were|could|yes|his|been|or|something|who|because|some|had|'then'|say|take|an|way|us|little|make|need|gonna|never|too|love|sure|them|more|over|our|sorry|where|let|thing|am|maybe|down|man|has|uh|very|by|should|anything|said|much|any|life|even|off|please|doing|thank|give|only|thought|help|two|talk|people|god|still|wait|into|find|nothing|again|things|call|told|great|before|better|ever|night|than|away|first|believe|other|feel|everything|work|fine|home|after|last|these|day|keep|does|put|around|stop|guy|long|always|listen|wanted|mr.|guys|huh|those|big|lot|happened|thanks|trying|kind|wrong|through|talking|made|new|being|guess|care|bad|remember|getting|together|leave|mother|place|understand|actually|hear|baby|nice|father|'else'|stay|'done'|their|course|might|mind|every|enough|try|hell|came|someone|own|family|whole|another|house|yourself|idea|ask|best|must|coming|old|looking|woman|hello|which|years|room|money|left|knew|tonight|real|son|hope|name|same|went|um|hmm|happy|pretty|saw|girl|show|friend|already|saying|may|next)
	ENGLISH=$(($ENGLISH + 1))
	if $DEBUG ; then
		echo "en=$word" 1>&2
	fi
	;;
	esac

	# bail out as soon as sample is big enough
	if test $(($GERMAN + $FRENCH + $ENGLISH)) -gt $((12)) ; then
		break
	fi
	done

	# set language according to the counts
	if test $(($GERMAN)) -gt $(($FRENCH)) ; then
		if test $(($GERMAN)) -gt $(($ENGLISH)) ; then
			LANGUAGE='de'
		fi
	fi

	if test $(($FRENCH)) -gt $(($GERMAN)) ; then
		if test $(($FRENCH)) -gt $(($ENGLISH)) ; then
			LANGUAGE='fr'
		fi
	fi

	if test $(($ENGLISH)) -gt $(($GERMAN)) ; then
		if test $(($ENGLISH)) -gt $(($FRENCH)) ; then
			LANGUAGE='en'
		fi
	fi

	if test -z "$LANGUAGE" ; then
		# Remember: DEFAULTLANGUAGE=xx
		LANGUAGE=$DEFAULTLANGUAGE
	fi

	if $DEBUG ; then
		# Show the scores
		echo "German score      = $GERMAN" 1>&2
		echo "French score      = $FRENCH" 1>&2
		echo "English score     = $ENGLISH" 1>&2
		echo "selected LANGUAGE = $LANGUAGE" 1>&2
	fi

fi # end of language autodetect


# When autodetect failed language may be inferred from the voice used
if test "$LANGUAGE" == 'xx' ; then
	if test $SYNTH == 'mbrola' ; then
		case "$VOICELANG" in
			de|fr|en)	LANGUAGE="$VOICELANG"
			;;

			us)		LANGUAGE='en'
			;;
		esac
	else
		LANGUAGE='en'
	fi
fi

# When language is still not found give up
if test "$LANGUAGE" == 'xx' ; then
	echo 'Unknown input text language. Please use -de|-fr|-en on the command line' 1>&2
	exit 1
fi

# When VOICELANG is not set on the commandline (or just a voice number given),
# it defaults to language.
if test $SYNTH == 'mbrola' ; then

if test -z "$VOICELANG" ; then
    if test $VOICENUMBER == '0' ; then
	case $LANGUAGE in
		de) VOICELANG=$(echo $VOICE_DE   | sed -e "s/[0-9]//g")
		    VOICENUMBER=$(echo $VOICE_DE | sed -e "s/[a-z]//g")
		    ;;
		fr) VOICELANG=$(echo $VOICE_FR   | sed -e "s/[0-9]//g")
		    VOICENUMBER=$(echo $VOICE_FR | sed -e "s/[a-z]//g")
		    ;;
		en) VOICELANG=$(echo $VOICE_EN   | sed -e "s/[0-9]//g")
		    VOICENUMBER=$(echo $VOICE_EN | sed -e "s/[a-z]//g")
		    ;;
	esac
    else
	case $LANGUAGE in
		de) VOICELANG='de' ;;
		fr) VOICELANG='fr' ;;
		en) if test $VOICENUMBER == '1' ; then
			VOICELANG='en'
		    else
			VOICELANG='us'
		    fi
		    ;;
	esac
    fi
fi

# set the voice for this language
if test $(($VOICENUMBER)) -gt $((0)) ; then

	case $VOICELANG in
	fr)	if test $(($VOICENUMBER)) -le $(($MAXVOICE_FR)) ; then
			VOICE=${VOICELANG}$VOICENUMBER
			SEX=${VOICESEXFR[$VOICENUMBER]}
			FREQ=${VOICEFREQFR[$VOICENUMBER]}
		else
			VOICENUMBER='0'
		fi
		;;

	de)	if test $(($VOICENUMBER)) -le $(($MAXVOICE_DE)) ; then
			VOICE=${VOICELANG}$VOICENUMBER
			SEX=${VOICESEXDE[$VOICENUMBER]}
			FREQ=${VOICEFREQDE[$VOICENUMBER]}
		else
			VOICENUMBER='0'
		fi
		;;

	en)	if test $(($VOICENUMBER)) -le $(($MAXVOICE_EN)) ; then
			VOICE=${VOICELANG}$VOICENUMBER
			SEX=${VOICESEXEN[$VOICENUMBER]}
			FREQ=${VOICEFREQEN[$VOICENUMBER]}
		else
			VOICENUMBER='0'
		fi
		;;

	us)	if test $(($VOICENUMBER)) -le $(($MAXVOICE_US)) ; then
			VOICE=${VOICELANG}$VOICENUMBER
			SEX=${VOICESEXUS[$VOICENUMBER]}
			FREQ=${VOICEFREQUS[$VOICENUMBER]}
		else
			VOICENUMBER='0'
		fi
		;;
	esac
fi

if test "$VOICENUMBER" == '0' ; then
	# use defaults
	case $VOICELANG in
	de)	VOICE=$VOICE_DE
		SEX=$SEX_DE
		FREQ=$FREQ_DE
		;;

	fr)	VOICE=$VOICE_FR
		SEX=$SEX_FR
		FREQ=$FREQ_FR
		;;

	en)	VOICE=$VOICE_EN
		SEX=$SEX_EN
		FREQ=$FREQ_EN
		;;

	us)	VOICE=$VOICE_EN
		SEX=$SEX_EN
		FREQ=$FREQ_EN
		;;
	esac
fi

# Path to the mbrola-voice
VOICE="$LANGDIR/$VOICE/$VOICE"

# Check that language is available
if ! test -r $VOICE ; then
	echo "'mbrola' voice '$VOICE' not found." 1>&2
	exit 1
fi

if $DEBUG ; then
	echo "LANGUAGE    = $LANGUAGE" 1>&2
	echo "VOICELANG   = $VOICELANG" 1>&2
	echo "VOICENUMBER = $VOICENUMBER" 1>&2
	echo "VOICE       = $VOICE" 1>&2
	echo "SEX         = $SEX" 1>&2
	echo "FREQ        = $FREQ" 1>&2
fi

else
	# festival is used
	LANGUAGE='en'
	VOICELANG='us'
	if test "$FVOICE" == 'kal' ; then
		VOICE='kal_diphone'
	else
		VOICE="${CMULEAD}${FVOICE}${CMUTAIL}"
	fi
fi


###############################################
##  speaking text
###############################################

# We need additional filters to cross-speak with the 'wrong' voice
LANGCOMPARE=$(echo "$VOICELANG" | sed -e 's/us/en/')
if test "$LANGUAGE" == 'en' && test "$VOICELANG" == 'de' ; then
	XLANG='| $BINDIR/en1tode'
elif test "$LANGUAGE" == 'en' && test "$VOICELANG" == 'fr' ; then
	XLANG='| $BINDIR/en1tofr'
elif test "$LANGUAGE" \!= "$LANGCOMPARE" ; then
	echo "Cross-speaking language $LANGUAGE with voice $VOICELANG is not supported" 1>&2
	exit 1
fi

# Generation of sound is done here
if test "$LANGUAGE" == 'de' ; then

	# Check for incomplete installation
	if ! test -x $BINDIR/txt2pho && test -x /usr/sbin/txt2pho-install-binary ; then
		echo "Error: $BINDIR/txt2pho not found" 1>&2
		echo "Please run /usr/sbin/txt2pho-install-binary as root" 1>&2
		exit 1
	fi

	if $DEBUG ; then
		echo 'speaking german ...' 1>&2
	fi

	eval "cat $TMPFILE $CONVERSION | sed -e 's/@/ t /g' \
	| $BINDIR/pipefilt \
	| $BINDIR/preproc $PPDIR/Rules.lst $PPDIR/Hadifix.abk \
	| $BINDIR/txt2pho -p $TTPDIR/ -$SEX \
	| $BINDIR/mbrola -e $FREQ $VOICE - $OCMD $SOUNDPLAYER"

elif test "$LANGUAGE" == 'en' ; then

	if $DEBUG ; then
		echo 'speaking english ...' 1>&2
	fi

	if test $SYNTH == 'mbrola' ; then
		if $DEBUG ; then
			echo "cat $TMPFILE $CONVERSION | sed -e 's/---*/ _ /g' | $BINDIR/freephone -h $FRPHDIR 2>/dev/null $XLANG | $BINDIR/mbrola -e $FREQ $VOICE - $OCMD $SOUNDPLAYER" 1>&2
		fi

		eval "cat $TMPFILE $CONVERSION | sed \
		-e 's/---*/ _ /g' \
		| $BINDIR/freephone -h $FRPHDIR 2>/dev/null $XLANG \
		| $BINDIR/mbrola -e $FREQ $VOICE - $OCMD $SOUNDPLAYER"

	elif test $SYNTH == 'festival' ; then
		if $DEBUG ; then
			echo "cat $TMPFILE $CONVERSION | sed -e 's/---*/ _ /g' | $BINDIR/text2wave -F 32000 -eval \"(voice_$VOICE)\" $OCMD $SOUNDPLAYER" 1>&2
		fi

		eval "cat $TMPFILE $CONVERSION | sed \
		-e 's/---*/ _ /g' \
		| $BINDIR/text2wave -F 32000 -eval \"(voice_$VOICE)\" \
		$OCMD $SOUNDPLAYER"

	else
		echo "Illegal synthesizer '$SYNTH'" 1>&2
		exit 1
	fi

elif test "$LANGUAGE" == 'fr' ; then

	if $DEBUG ; then
		echo 'speaking french ...' 1>&2
		echo "cat $TMPFILE $CONVERSION | $BINDIR/lliaphon 2>/dev/null | $BINDIR/mbrola -e $FREQ -I $LLIADIR/initfile.lia $VOICE - $OCMD $SOUNDPLAYER" 1>&2
	fi

	eval "cat $TMPFILE $CONVERSION \
	| $BINDIR/lliaphon 2>/dev/null \
	| $BINDIR/mbrola -e $FREQ -I $LLIADIR/initfile.lia $VOICE - \
	$OCMD $SOUNDPLAYER"

else
	echo 'Unknown language, please specify -de -en -fr' 1>&2
fi

rm -f $TMPFILE

if $OFILE && test $SYNTH == 'mbrola' ; then
	if test $SUFFIX == '.wav' ; then
		# Convert .au to .wav
		sox $OPATH/$OUTFILETMP -r 32k -c 1 $OPATH/$OARG
		rm -f $OPATH/$OUTFILETMP
	fi
fi

exit 0
