summaryrefslogtreecommitdiff
path: root/lib/voices/finnish/suo_fi_lj_diphone/festvox
diff options
context:
space:
mode:
authorNiko Tyni <ntyni@iki.fi>2005-12-04 14:34:26 +0100
committerNiko Tyni <ntyni@iki.fi>2005-12-04 14:34:26 +0100
commitefc580d40dc9f67c6edb5f7c5852f0fbef22578d (patch)
tree2b361b354cf44fefe9c4fa6f644ed6ebff870de1 /lib/voices/finnish/suo_fi_lj_diphone/festvox
Import festvox-suopuhe-lj_1.0g-20051204.orig.tar.gz
[dgit import orig festvox-suopuhe-lj_1.0g-20051204.orig.tar.gz]
Diffstat (limited to 'lib/voices/finnish/suo_fi_lj_diphone/festvox')
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_aux_funcs.scm412
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_duration.scm1315
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_lex.scm216
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_lts.scm829
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_mv_int.scm506
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_mv_phrase.scm410
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_phones.scm147
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/hy_fi_mv_diphone.scm355
l---------lib/voices/finnish/suo_fi_lj_diphone/festvox/suo_fi_lj_diphone.scm1
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe.dtd153
-rwxr-xr-xlib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe_filter.perl75
-rw-r--r--lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe_mode.scm634
12 files changed, 5053 insertions, 0 deletions
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_aux_funcs.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_aux_funcs.scm
new file mode 100644
index 0000000..4215c0d
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_aux_funcs.scm
@@ -0,0 +1,412 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Department of General Linguistics / Suopuhe project ;;
+;;; University of Helsinki, FI ;;
+;;; Copyright (c) 2000, 2001, 2002, 2003 ;;
+;;; All Rights Reserved. ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Authors: ;;
+;;; ;;
+;;; Martti Vainio ;;
+;;; e-mail: martti.vainio@helsinki.fi ;;
+;;; address: Department of General Linguistics ;;
+;;; PL 9 (Siltavuorenpenger 20A) ;;
+;;; 00014 University of Helsinki ;;
+;;; FINLAND ;;
+;;; ;;
+;;; Nicholas Volk ;;
+;;; e-mail: nvolk@ling.helsinki.fi ;;
+;;; address: Department of General Linguistics ;;
+;;; PL 9 (Siltavuorenpenger 20A) ;;
+;;; 00014 University of Helsinki ;;
+;;; FINLAND ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Auxiliary functions for development work; nothing for end users here
+;;;
+
+
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+
+(define (phones utt)
+ "(phones UTT)
+Prints a list of phone names in UTTerance and returns the original utterance
+unchanged.."
+ (print (utt.features utt 'Segment '(name)))
+ utt)
+
+
+
+
+(define (wavesurf utt)
+ "(wavesurf UTT)
+Saves the utterance UTT as a wav file
+and the creates the corresponding lab file.
+The files are placed in the /tmp dir.
+Then starts the wavesurfer-program for speech analysis."
+;; WISH LIST:
+;; 1) optinal file name
+;; 2) optional path (compare with SUOPUHE-mode)
+ (utt.save.wave utt "/tmp/xxx.wav" "wav")
+ (system "chmod a+rw /tmp/xxx.wav") ;; I read&write, other just (over)write
+
+
+ ;; create the .lab file
+; (let ((file "/tmp/xxx.lab" fp))
+ (let ((file "/tmp/xxx.lab")
+ fp)
+ (set! fp (fopen file "w"))
+ (fwrite
+ (string-append
+ "separator ;\n"
+ "nfields 1\n"
+ "#\n"
+ (lab_body (utt.relation.first utt 'Segment)))
+ fp)
+ (fclose fp))
+ (system "chmod a+rw /tmp/xxx.lab")
+
+ (system "wavesurfer -config WAVES /tmp/xxx.wav &")
+ nil)
+
+
+(define (extract_feats relname feats utt)
+ "(extract_feats relname feats utt outfd)
+Extract the features and write them to the screen."
+ (mapcar
+ (lambda (si)
+ (mapcar
+ (lambda (f)
+ (format t "%s " (item.feat si f)))
+ feats)
+ (format t "\n"))
+ (utt.relation.items utt relname)))
+
+
+
+;; NV's redefinition of SayText
+(define (SayText text)
+ "(SayText TEXT)
+TEXT, a string, is rendered as speech. (Suopuhe redifinion)"
+ (let ((utter (utt.synth (eval (list 'Utterance 'Text text)))))
+ (if utter
+ (utt.play utter)
+ nil)))
+
+
+
+
+
+
+
+
+
+
+(define (lab_header UTT)
+ "(lab_header UTT)
+Returns the contents for the to-be *.lab file based on the UTTerance.
+Saving the output to a file is done somewhere higher."
+ (string-append
+ "separator ;\n"
+ "nfields 1\n"
+ "#\n"
+ (lab_body (utt.relation.first UTT 'Segment))))
+
+(define (lab_body PHONE)
+ "(lab_body PHONE)
+Writes the LAB data for a given phone and recursively call
+itself while there are phones left (ortographically right:).
+The header is done in lab_header procedure which typically
+is the caller of this function."
+ (string-append
+ ;;(item.features (item.next PHONE)););)
+ "\t"
+ (item.feat PHONE "end")
+ "\t121\t"
+ (item.feat PHONE "name")
+ " ;\n"
+ (if (item.next PHONE)
+ (lab_body (item.next PHONE))
+ "")))
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; UNUSED STUFF FROM OTHER DIRECTORIES
+;; PLACED HERE SINCE NO BETTER PLACES CAME INTO MIND
+(define (one_by_one word)
+ "(one_by_one WORD)
+Speaks the letters in the given WORD one by one."
+ (let ((output "")
+ (grapheme nil))
+ (while (> (string-length word) 0)
+ (set! grapheme (substring word 0 1) ". ")
+ (cond
+ ((string-equal grapheme ".")
+ (set! output (string-append output "pisteel. ")))
+ ((string-equal grapheme ",")
+ (set! output (string-append output "pilkkuul. ")))
+
+ (t
+ (set! output (string-append output grapheme ". "))))
+ (set! word (substring word 1 (- (string-length word) 1))))
+ ;; (print output)
+ (SayText output)))
+
+
+;;; Martti did this functions. Dunno for what though...
+; (define (remove_long_consonants utt)
+; "(remove_long_consonants UTT)
+; Remove long consonant markers (:) from the segment names"
+; (mapcar
+; (lambda (s)
+; (let ((name (item.name s)))
+; (if (and (string-equal "-" (item.feat s "ph_vc")) ;;; consonant
+; (string-equal "l" (item.feat s "ph_len"))) ;;; long
+; (item.set_name s (substring name 0 1)))
+; ))
+; (utt.relation.items utt 'Segment))
+; utt)
+
+; (define (klusiili phone)
+; (if (string-matches phone "^[bdgkpt]:?$" )
+; t
+; nil))
+
+; (define (konsonantti phone)
+; (if (string-matches phone "^[bdfghjklmnprstvNT]:?$" )
+; t
+; nil))
+
+
+; (define (lyhyt phone)
+; (if (string-matches phone "^[abdefghijklmnoprstuvy@7NT]$" )
+; t
+; nil))
+
+; (define (nasaali phone)
+; (if (string-matches phone "^[mnN]:?$" )
+; t
+; nil))
+
+
+
+; (define (pitka phone)
+; (if (string-matches phone "^[abdefghijklmnoprstuvy@7NT]:$" )
+; t
+; nil))
+
+; (define (vokaali phone)
+; (if (string-matches phone "^[aeiouy@7]:?$" )
+; t
+; nil))
+
+
+(define (intro-finnish)
+ "(intro-finnish)
+Synthesize an introduction to the Festival Speech Synthesis System
+in Finnish."
+ (if (or (string-equal "hy_fi_mv_diphone" current-voice)
+ (string-equal "suo_fi_lj_diphone" current-voice))
+ (tts (path-append hy_fi_mv_dir "fi-intro.txt") nil)
+ (format stderr "Please set the (hy_fi_mv_diphone) voice first")))
+
+
+
+(define (language_finnish)
+ "(language_finnish)
+Set up language parameters for Finnish."
+ (set! male1 hy_fi_mv_diphone)
+ (set! female1 suo_fi_lj_diphone)
+ ;; LISÄÄ TÄHÄN MYÖHEMMÄN DIFONITIETOKANNAT...
+ (set! language "finnish")
+ (male1)
+ (Parameter.set 'Language 'finnish)
+)
+
+
+
+;; alla olevaa kamaa käytettiin kestomallin opetukseen:
+
+; (define (puhunnoksen_alku phone)
+; (cond
+; ;; on itse tauko
+; ((not (item.relation phone 'SylStructure))
+; 0)
+; ;; edellinen on tauko
+; ((not (item.prev
+; (item.relation
+; (item.parent
+; (item.parent
+; (item.relation phone 'SylStructure)))
+; 'Word)))
+; 1)
+; ((not (item.prev
+; (item.prev
+; (item.relation
+; (item.parent
+; (item.parent
+; (item.relation phone 'SylStructure)))
+; 'Word))))
+; 2)
+; (t
+; 0)))
+
+; (define (puhunnoksen_loppu phone)
+; (cond
+; ;; on itse tauko
+; ((not (item.relation phone 'SylStructure))
+; 0)
+; ;; seuraava on tauko
+; ((not (item.next
+; (item.relation
+; (item.parent
+; (item.parent
+; (item.relation phone 'SylStructure)))
+; 'Word)))
+; 1)
+; ((not (item.next
+; (item.next
+; (item.relation
+; (item.parent
+; (item.parent
+; (item.relation phone 'SylStructure)))
+; 'Word))))
+; 2)
+; (t
+; 0)))
+
+; (define (painotettu_eka_tavu phone)
+; (if (and (= (item.feat phone 'R:SylStructure.parent.pos_in_word) 0)
+; (not (string-equal (item.name phone) "#"))
+; (string-equal (item.feat phone 'R:SylStructure.parent.parent.gpos)
+; "content"))
+; (begin
+; ;; (print (string-append (item.name phone) " 1"))
+; 1)
+; (begin
+; ;; (print (string-append (item.name phone) " 0"))
+; 0)))
+
+; (define (eka_tavu phone)
+; (if (and (= (item.feat phone 'R:SylStructure.parent.pos_in_word) 0)
+; (not (string-equal (item.name phone) "#")))
+; (begin
+; ;; (print (string-append (item.name phone) " 1"))
+; 1)
+; (begin
+; ;; (print (string-append (item.name phone) " 0"))
+; 0)))
+
+
+
+
+; (define (fraasin_alku phone)
+; (cond
+; ;; on itse tauko
+; ((or (not (item.relation phone 'SylStructure)))
+; 0)
+; ;; seuraava on tauko
+; ((or
+; (not (item.prev
+; (item.relation
+; (item.parent
+; (item.parent
+; (item.relation phone 'SylStructure)))
+; 'Word)))
+; (string-matches (item.name
+; (item.prev
+; (item.relation
+; (item.first_leaf
+; (item.parent
+; (item.parent
+; (item.relation phone 'SylStructure))))
+; 'Segment)))
+; "^#+$"))
+; 1)
+; ((or
+; (not (item.prev
+; (item.prev
+; (item.relation
+; (item.parent
+; (item.parent
+; (item.relation phone 'SylStructure)))
+; 'Word))))
+; (string-matches (item.name
+; (item.prev
+; (item.relation
+; (item.first_leaf
+; (item.relation
+; (item.prev
+; (item.relation
+; (item.parent
+; (item.parent
+; (item.relation phone 'SylStructure)))
+; 'Word))
+; 'SylStructure))
+; 'Segment)))
+; "^#+"))
+; 2)
+; (t
+; 0)))
+
+
+
+
+; (item.prev
+; (item.relation
+; (item.parent
+; (item.parent
+; (item.relation phone
+; 'SylStructure)))
+; 'Word)))
+
+
+
+; (define (round number)
+; "(round number)
+; Removes some \"extra\" decimals from floats...
+; Keeps log decimals manageable..."
+; (let ((pos 1)
+; (koko 0))
+; (if (< number 0)
+; (begin
+; (set! number (* -1 number))
+; (set! pos -1)))
+
+; (while (> number 1)
+; (set! koko (+ koko 1))
+; (set! number (- number 1)))
+; ;; (print pos) (print koko) (print number)
+; (* pos (+ koko (read-from-string (format nil "%.2f" number))))))
+
+; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+(provide 'finnish_aux_funcs)
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_duration.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_duration.scm
new file mode 100644
index 0000000..0e944db
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_duration.scm
@@ -0,0 +1,1315 @@
+;
+; finnish_duration.scm - duration model based on 692 sentences
+;
+; Copyright (c) 2000-2003
+; Department of General Linguistics, University of Helsinki
+; Department of Foreign Languages, University of Joensuu
+; All Rights Reserved.
+;
+; Author: Nicholas Volk (nvolk@ling.helsinki.fi)
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+
+; FEATURE 1 R:SylStructure.parent.position_type: 0.2493
+; FEATURE 2 lisp_end_of_phrase: 0.3704
+; FEATURE 3 n.ph_ctype: 0.4334
+; FEATURE 4 pos_in_syl: 0.5047
+; FEATURE 5 p.ph_vc: 0.5382
+; FEATURE 6 ph_ctype: 0.5784
+; FEATURE 7 lisp_mora: 0.6033
+; FEATURE 8 p.ph_ctype: 0.6158
+; FEATURE 9 p.ph_cplace2: 0.6267
+; FEATURE 10 n.seg_onsetcoda: 0.6330
+; FEATURE 11 ph_cplace2: 0.6385
+; FEATURE 12 n.ph_vfront: 0.6427
+; FEATURE 13 p.ph_clng: 0.6460
+; FEATURE 14 n.ph_cplace: 0.6492
+; FEATURE 15 pp.ph_vlng: 0.6530
+; RMSE 0.7550 Correlation is 0.6530 Mean (abs) Error 0.5636 (0.5024)
+; ;;; Test the duration model
+; ;; RMSE 0.7679 Correlation is 0.6300 Mean (abs) Error 0.5778 (0.5059)
+
+
+
+;; averages durations and deviations as counted by Festvox 1.6
+;; from 692 mv sentences + some modifications
+(set!
+ hy_fi_mv2::phone_durs '
+ (
+ (# 0.2 0.1)
+ (## 0.050 0.1)
+ (7 0.074 0.021091)
+ (7: 0.144 0.0343)
+ (@ 0.066 0.02502)
+ (@: 0.142 0.039752)
+ (N 0.054 0.019307)
+ (N: 0.105 0.031537)
+ (S 0.107 0.074051)
+ (S: 0.162 0.002122)
+ (T 0.100 0.02)
+ (T: 0.150 0.02)
+ (a 0.072 0.027)
+ (a: 0.134 0.034379)
+ (b 0.087 0.020942)
+ (b: 0.150 0.05)
+ (d 0.052 0.017189)
+ (d: 0.150 0.05)
+ (e 0.068 0.02284)
+ (e: 0.118 0.031648)
+ ;; (f 0.111 0.04366)
+ ;; (f: 0.123 0.025)
+ (f 0.090 0.04366)
+ (f: 0.160 0.025)
+ (g 0.083 0.028302)
+ (g: 0.150 0.05)
+ (h 0.068 0.022465)
+ (h: 0.128 0.014142)
+ (i 0.057 0.02158)
+ (i: 0.117 0.028321)
+ (j 0.062 0.019587)
+ (j: 0.078 0.011561)
+ (k 0.089 0.026993)
+ (k: 0.163 0.037839)
+ (l 0.058 0.014875)
+ ;; (l: 0.085 0.026515)
+ (l: 0.130 0.025)
+ (m 0.067 0.018604)
+ (m: 0.101 0.021473)
+ (n 0.052 0.01586)
+ (n: 0.093 0.028081)
+ (o 0.075 0.024718)
+ (o: 0.139 0.045108)
+ (p 0.096 0.028916)
+ (p: 0.176 0.043074)
+ (r 0.062 0.015694)
+ (r: 0.103 0.040321)
+ (s 0.078 0.023607)
+ (s: 0.146 0.038235)
+ (t 0.088 0.026786)
+ (t: 0.150 0.036228)
+ (u 0.066 0.023676)
+ (u: 0.132 0.036521)
+ (v 0.060 0.015418)
+ (v: 0.093 0.022544)
+ (y 0.070 0.027444)
+ (y: 0.130 0.030567)
+ ))
+
+
+
+(set! hy_fi_mv2::zdur_tree '
+((name is ##)
+ ((0.0 0.0))
+ ((name is #)
+ ((n.name is #) ;; lauseen loppu (tunnus 2*#)
+ ((0.0 -1.8)) ;; lyhennetään niin maan perkeleesti
+ ((p.name is 0) ;; puhunnoksen alku
+ ((0.0 -1.8)) ;; ja taas lyhyenä (emacspeakin vasteajan takia)
+ ((p.R:SylStructure.parent.parent.pbreak is BB)
+ ((0.0 0.0))
+ ((0.0 0.0)))))
+
+((R:SylStructure.parent.position_type is initial)
+ ((lisp_end_of_phrase is 0)
+ ((pos_in_syl < 1.2)
+ ((p.ph_vc is 0)
+ ((ph_ctype is s)
+ ((ph_cplace2 is r) ((0.414358 -2.16199)) ((0.874005 -2.4695)))
+ ((ph_ctype is 0)
+ ((pp.ph_vlng is 0)
+ ((n.seg_onsetcoda is coda)
+ ((1.05861 1.62942))
+ ((1.172 1.17007)))
+ ((1.08052 0.293028)))
+ ((ph_cplace2 is a)
+ ((n.ph_vfront is 1)
+ ((1.14796 0.487189))
+ ((ph_ctype is f) ((0.584116 0.460911)) ((1.5297 1.02475))))
+ ((ph_ctype is n)
+ ((lisp_mora is 2) ((0.880194 -1.15771)) ((1.17857 -0.557597)))
+ ((lisp_mora is 2) ((1.1581 0.0696902)) ((1.00619 -0.432983)))))))
+ ((n.ph_ctype is s)
+ ((pos_in_syl < 0.1)
+ ((n.seg_onsetcoda is coda)
+ ((0.697916 1.4032))
+ ((p.ph_ctype is n)
+ ((1.0436 1.18853))
+ ((lisp_mora is 2) ((1.02962 -0.0361715)) ((0.952024 0.580176)))))
+ ((n.seg_onsetcoda is coda)
+ ((p.ph_cplace2 is r)
+ ((0.691754 0.228866))
+ ((p.ph_cplace2 is l)
+ ((0.442573 0.720269))
+ ((0.593858 0.55871))))
+ ((ph_ctype is f)
+ ((pp.ph_vlng is s)
+ ((0.625067 -0.431548))
+ ((0.521233 -0.571476)))
+ ((p.ph_ctype is n)
+ ((n.ph_cplace is a)
+ ((0.778804 -0.56443))
+ ((0.750129 0.0464458)))
+ ((p.ph_ctype is r)
+ ((pp.ph_vlng is s)
+ ((1.07725 -0.16798))
+ ((0.891796 -0.425804)))
+ ((lisp_mora is 2)
+ ((p.ph_ctype is s)
+ ((0.521263 0.500136))
+ ((pp.ph_vlng is 0)
+ ((n.ph_cplace is a)
+ ((0.699937 -0.0663515))
+ ((0.838917 0.306609)))
+ ((0.732822 0.411336))))
+ ((p.ph_cplace2 is l)
+ ((0.610493 0.304215))
+ ((n.ph_cplace is l)
+ ((0.440354 0.190908))
+ ((p.ph_vc is +)
+ ((0.708797 -0.181432))
+ ((p.ph_cplace2 is a)
+ ((p.ph_ctype is s)
+ ((0.507732 0.162633))
+ ((0.701973 -0.0615322)))
+ ((0.497253 -0.0607969))))))))))))
+ ((ph_ctype is 0)
+ ((lisp_mora is 2)
+ ((pos_in_syl < 0.1)
+ ((n.seg_onsetcoda is coda)
+ ((n.ph_cplace is a)
+ ((p.ph_ctype is n) ((0.846843 1.98492)) ((1.28616 1.76399)))
+ ((1.10419 1.37166)))
+ ((n.ph_ctype is l) ((1.09167 0.707285)) ((1.00628 1.5813))))
+ ((n.ph_ctype is r)
+ ((n.seg_onsetcoda is coda)
+ ((p.ph_ctype is s)
+ ((pp.ph_vlng is 0) ((0.793108 1.6759)) ((0.686577 1.46816)))
+ ((p.ph_cplace2 is l)
+ ((1.02811 1.5475))
+ ((0.797975 1.08187))))
+ ((1.23028 0.848184)))
+ ((p.ph_ctype is r)
+ ((p.ph_cplace2 is a)
+ ((1.03257 0.930175))
+ ((0.844828 -0.17997)))
+ ((n.ph_ctype is n)
+ ((n.seg_onsetcoda is coda)
+ ((pp.ph_vlng is 0)
+ ((0.566015 1.01837))
+ ((0.641936 1.2535)))
+ ((pp.ph_vlng is s)
+ ((0.958101 1.00167))
+ ((0.756233 0.717495))))
+ ((n.ph_cplace is a)
+ ((n.seg_onsetcoda is coda)
+ ((p.ph_cplace2 is a)
+ ((0.565396 1.10786))
+ ((n.ph_ctype is f)
+ ((p.ph_cplace2 is r)
+ ((0.785843 0.922216))
+ ((0.620961 0.483967)))
+ ((p.ph_cplace2 is l)
+ ((0.518981 1.07022))
+ ((0.777028 0.626201)))))
+ ((p.ph_cplace2 is a)
+ ((0.854425 0.404668))
+ ((0.883663 0.766847))))
+ ((n.ph_cplace is g)
+ ((p.ph_ctype is s)
+ ((0.588436 0.573801))
+ ((0.875701 0.741857)))
+ ((p.ph_cplace2 is l)
+ ((0.812018 0.592433))
+ ((0.8093 0.408434)))))))))
+ ((n.ph_cplace is b)
+ ((pos_in_syl < 0.1)
+ ((1.15445 -0.163448))
+ ((p.ph_cplace2 is a)
+ ((0.663495 0.537209))
+ ((0.687391 0.141296))))
+ ((pos_in_syl < 0.1)
+ ((n.ph_ctype is l)
+ ((p.ph_ctype is n)
+ ((1.11183 0.916437))
+ ((pp.ph_vlng is 0)
+ ((1.09516 0.399922))
+ ((1.18411 -0.276583))))
+ ((pp.ph_vlng is 0)
+ ((n.seg_onsetcoda is coda)
+ ((1.08438 0.911585))
+ ((0.820251 1.1614)))
+ ((p.ph_ctype is s) ((1.00213 1.07576)) ((1.24814 1.58642)))))
+ ((n.seg_onsetcoda is coda)
+ ((p.ph_ctype is s)
+ ((n.ph_cplace is a)
+ ((0.727405 0.660093))
+ ((p.ph_cplace2 is l)
+ ((0.742461 1.11747))
+ ((pp.ph_vlng is 0)
+ ((0.734555 0.927789))
+ ((0.73705 0.806348)))))
+ ((p.ph_cplace2 is r)
+ ((0.852441 0.239643))
+ ((pp.ph_vlng is 0)
+ ((n.ph_vfront is 3)
+ ((0.822279 0.306066))
+ ((p.ph_cplace2 is a)
+ ((0.853881 0.699284))
+ ((0.871431 0.446849))))
+ ((p.ph_ctype is n)
+ ((1.03132 0.965835))
+ ((n.ph_vfront is 1)
+ ((0.873465 0.816313))
+ ((0.917851 0.467496)))))))
+ ((p.ph_cplace2 is l)
+ ((p.ph_ctype is n)
+ ((0.642136 0.211476))
+ ((n.ph_ctype is r)
+ ((0.652363 0.978806))
+ ((p.ph_ctype is f)
+ ((0.633854 0.697683))
+ ((0.665691 0.477371)))))
+ ((p.ph_ctype is f)
+ ((p.ph_cplace2 is a)
+ ((0.551109 0.143966))
+ ((0.876272 -0.22467)))
+ ((p.ph_cplace2 is r)
+ ((pp.ph_vlng is 0)
+ ((0.717158 0.387737))
+ ((0.704496 0.14666)))
+ ((pp.ph_vlng is s)
+ ((p.ph_ctype is s)
+ ((0.756359 0.404007))
+ ((0.95238 0.722275)))
+ ((n.ph_ctype is l)
+ ((0.600341 0.275517))
+ ((n.ph_ctype is f)
+ ((0.63293 0.300704))
+ ((0.743196 0.509984))))))))))))
+ ((p.ph_cplace2 is a)
+ ((p.ph_ctype is s)
+ ((ph_cplace2 is l)
+ ((n.ph_vfront is 1)
+ ((0.658511 -1.04505))
+ ((0.764273 -0.579458)))
+ ((ph_ctype is f)
+ ((0.67381 -0.385443))
+ ((ph_ctype is s)
+ ((0.669678 -0.387274))
+ ((1.24196 0.0205493)))))
+ ((ph_ctype is f)
+ ((ph_cplace2 is a)
+ ((n.ph_vfront is 3)
+ ((0.727442 0.566241))
+ ((0.727165 0.75547)))
+ ((n.ph_vfront is 1)
+ ((ph_cplace2 is l)
+ ((0.909459 -0.0993548))
+ ((0.980587 0.321758)))
+ ((n.seg_onsetcoda is coda)
+ ((0.903312 0.625847))
+ ((0.813008 0.375792)))))
+ ((ph_ctype is r)
+ ((ph_cplace2 is a)
+ ((1.28399 0.917389))
+ ((0.843269 0.424056)))
+ ((ph_cplace2 is l)
+ ((ph_ctype is n)
+ ((n.ph_vfront is 1)
+ ((0.665766 -0.560041))
+ ((0.688994 -0.1633)))
+ ((n.seg_onsetcoda is coda)
+ ((n.ph_vfront is 1)
+ ((0.612282 -0.212725))
+ ((0.622185 0.0863764)))
+ ((0.799478 0.339492))))
+ ((ph_ctype is s)
+ ((pp.ph_vlng is s)
+ ((p.ph_ctype is n)
+ ((n.ph_vfront is 3)
+ ((n.seg_onsetcoda is coda)
+ ((ph_cplace2 is a)
+ ((0.593878 0.0926664))
+ ((0.597355 -0.0915215)))
+ ((0.559002 0.134849)))
+ ((0.80247 0.218785)))
+ ((1.43028 0.546898)))
+ ((ph_cplace2 is a)
+ ((0.443011 -0.381483))
+ ((0.704263 0.0768767))))
+ ((0.848131 0.435969)))))))
+ ((n.ph_ctype is f)
+ ((ph_ctype is s) ((0.565053 -0.295846)) ((1.07037 0.259748)))
+ ((ph_ctype is r)
+ ((ph_cplace2 is a)
+ ((n.ph_vfront is 3)
+ ((0.949098 0.360166))
+ ((0.574453 0.066609)))
+ ((0.891948 0.717105)))
+ ((ph_cplace2 is a)
+ ((ph_ctype is s)
+ ((pp.ph_vlng is 0)
+ ((0.998088 0.854391))
+ ((0.701013 0.508697)))
+ ((n.ph_vfront is 1)
+ ((lisp_mora is 1)
+ ((0.919257 0.855378))
+ ((1.04349 1.02608)))
+ ((n.seg_onsetcoda is coda)
+ ((0.906812 0.977146))
+ ((1.0171 1.22371)))))
+ ((ph_ctype is f)
+ ((ph_cplace2 is l)
+ ((n.seg_onsetcoda is coda)
+ ((n.ph_vfront is 1)
+ ((0.871274 0.435394))
+ ((1.04888 0.673423)))
+ ((1.06361 0.865767)))
+ ((pos_in_syl < 0.1)
+ ((n.ph_vfront is 1)
+ ((1.19273 0.164819))
+ ((0.989494 0.412502)))
+ ((0.957089 -0.0737841))))
+ ((n.ph_vfront is 3)
+ ((ph_ctype is n)
+ ((0.940868 1.07394))
+ ((lisp_mora is 2)
+ ((0.868656 0.728722))
+ ((ph_cplace2 is l)
+ ((0.781457 0.821993))
+ ((1.04734 0.988019)))))
+ ((ph_cplace2 is l)
+ ((ph_ctype is n)
+ ((0.951098 0.80061))
+ ((lisp_mora is 2)
+ ((0.653205 0.478247))
+ ((0.632344 0.169985))))
+ ((lisp_mora is 2)
+ ((0.942891 1.12906))
+ ((0.838455 0.830946)))))))))))))
+ ((pp.ph_vlng is 0)
+ ((lisp_mora is 2)
+ ((ph_ctype is n)
+ ((n.ph_cplace is a) ((0.992075 0.715216)) ((0.966096 0.45234)))
+ ((n.ph_cplace is b)
+ ((0.997309 0.462189))
+ ((ph_ctype is s)
+ ((n.ph_ctype is f)
+ ((0.705022 -0.0571909))
+ ((0.68043 0.408178)))
+ ((n.ph_cplace is l)
+ ((0.953455 0.163587))
+ ((ph_cplace2 is r)
+ ((0.81628 -0.329822))
+ ((n.ph_cplace is p)
+ ((0.558684 -0.351913))
+ ((ph_ctype is f)
+ ((0.869936 0.0522303))
+ ((0.837145 -0.127896)))))))))
+ ((n.ph_ctype is s)
+ ((n.ph_cplace is a)
+ ((ph_ctype is 0) ((0.666094 -0.561262)) ((0.67667 -0.90291)))
+ ((0.716715 -0.154598)))
+ ((n.ph_ctype is r)
+ ((0.849713 0.305567))
+ ((n.ph_cplace is a)
+ ((n.ph_ctype is n)
+ ((0.810898 0.0721763))
+ ((0.757718 -0.365141)))
+ ((n.ph_ctype is n)
+ ((0.644913 -0.0967719))
+ ((0.831196 0.100217)))))))
+ ((ph_ctype is f) ((0.678479 -0.884737)) ((0.774502 -0.714391)))))
+ ((ph_ctype is 0)
+ ((pos_in_syl < 1.2)
+ ((n.ph_ctype is s)
+ ((0.998406 1.39843))
+ ((n.ph_vfront is 1)
+ ((0.968515 2.57223))
+ ((lisp_mora is 2) ((0.917282 2.32119)) ((1.09961 1.84692)))))
+ ((0.920013 0.866701)))
+ ((lisp_mora is 2)
+ ((pp.ph_vlng is 0)
+ ((ph_cplace2 is a) ((1.2236 2.06478)) ((1.26739 1.56763)))
+ ((1.00706 1.12254)))
+ ((ph_cplace2 is r) ((1.29876 0.73761)) ((1.15951 1.07969))))))
+ ((lisp_end_of_phrase is 0)
+ ((n.ph_ctype is 0)
+ ((pos_in_syl < 0.3)
+ ((n.seg_onsetcoda is onset)
+ ((p.ph_ctype is n)
+ ((n.ph_vfront is 1)
+ ((0.568545 -0.372535))
+ ((0.691604 -0.0313148)))
+ ((ph_ctype is f)
+ ((lisp_mora is 1)
+ ((ph_cplace2 is a)
+ ((0.594369 0.581908))
+ ((n.ph_vfront is 1)
+ ((0.721584 0.130575))
+ ((0.930026 0.396382))))
+ ((1.11599 0.746493)))
+ ((ph_ctype is l)
+ ((n.ph_vfront is 1)
+ ((0.900054 0.261192))
+ ((0.697786 -0.106809)))
+ ((p.ph_cplace2 is a)
+ ((ph_ctype is s)
+ ((R:SylStructure.parent.position_type is final)
+ ((0.562343 0.100754))
+ ((0.671633 -0.13135)))
+ ((1.20928 0.372015)))
+ ((R:SylStructure.parent.position_type is single)
+ ((1.22288 0.626556))
+ ((ph_ctype is r)
+ ((0.86283 0.040434))
+ ((pp.ph_vlng is s)
+ ((0.441464 0.410568))
+ ((lisp_mora is 1)
+ ((0.535682 0.30082))
+ ((ph_ctype is s)
+ ((0.509292 0.278067))
+ ((0.612567 -0.00251823)))))))))))
+ ((R:SylStructure.parent.position_type is final)
+ ((lisp_mora is 3)
+ ((p.ph_cplace2 is a)
+ ((0.886962 0.182227))
+ ((ph_cplace2 is a)
+ ((ph_ctype is n)
+ ((0.585278 -0.182946))
+ ((n.ph_vfront is 1)
+ ((ph_ctype is f)
+ ((0.643504 0.0106825))
+ ((0.431145 0.241959)))
+ ((0.680088 -0.0184326))))
+ ((n.ph_vfront is 1)
+ ((0.701176 -0.260645))
+ ((ph_ctype is s) ((0.52602 0.102609)) ((0.752803 -0.186949))))))
+ ((p.ph_ctype is r)
+ ((0.934638 -0.0194497))
+ ((p.ph_vc is +)
+ ((ph_ctype is f)
+ ((ph_cplace2 is l)
+ ((lisp_mora is 1)
+ ((0.638637 -0.263461))
+ ((n.ph_vfront is 1)
+ ((0.665793 -0.7841))
+ ((0.669529 -0.508022))))
+ ((n.ph_vfront is 1)
+ ((0.639215 -0.335894))
+ ((0.507619 -0.521445))))
+ ((lisp_mora is 2)
+ ((ph_ctype is s)
+ ((n.ph_vfront is 1)
+ ((ph_cplace2 is a)
+ ((pp.ph_vlng is 0)
+ ((0.56605 -0.290392))
+ ((0.587672 -0.427569)))
+ ((0.600395 0.0798048)))
+ ((ph_cplace2 is r)
+ ((0.626045 -0.156842))
+ ((0.604648 0.0259143))))
+ ((ph_ctype is l)
+ ((0.815216 -0.185746))
+ ((ph_ctype is r)
+ ((n.ph_vfront is 1)
+ ((0.640864 -0.444553))
+ ((0.773282 -0.788709)))
+ ((n.ph_vfront is 1)
+ ((0.619612 -0.484726))
+ ((0.789049 -0.322862))))))
+ ((ph_ctype is n)
+ ((ph_cplace2 is a)
+ ((0.609116 -0.121808))
+ ((0.631903 -0.277501)))
+ ((ph_ctype is s)
+ ((ph_cplace2 is a)
+ ((0.520252 -0.576212))
+ ((pp.ph_vlng is 0)
+ ((0.536619 -0.399986))
+ ((0.548853 -0.546965))))
+ ((ph_cplace2 is a)
+ ((pp.ph_vlng is s)
+ ((0.571261 -0.549291))
+ ((0.61215 -0.369827)))
+ ((0.701239 -0.0779188)))))))
+ ((p.ph_ctype is l)
+ ((lisp_mora is 1)
+ ((0.51591 -0.442291))
+ ((0.751446 -0.011766)))
+ ((p.ph_cplace2 is r)
+ ((p.ph_ctype is f)
+ ((0.823907 0.0602389))
+ ((0.609257 -0.608541)))
+ ((p.ph_ctype is s)
+ ((0.710088 -0.74423))
+ ((lisp_mora is 1)
+ ((n.ph_vfront is 1)
+ ((p.ph_ctype is f)
+ ((0.434611 -0.519039))
+ ((0.500458 -0.660443)))
+ ((ph_ctype is f)
+ ((0.416119 -0.526136))
+ ((0.41308 -0.666634))))
+ ((p.ph_ctype is f)
+ ((0.551416 -0.58939))
+ ((0.49131 -0.343446))))))))))
+ ((p.ph_ctype is s)
+ ((ph_ctype is f)
+ ((p.ph_cplace2 is a)
+ ((0.558559 -1.06672))
+ ((0.546486 -0.503908)))
+ ((ph_cplace2 is r)
+ ((0.62139 -0.761093))
+ ((R:SylStructure.parent.position_type is 0)
+ ((0.538951 -0.241701))
+ ((1.09057 0.263472)))))
+ ((lisp_mora is 3)
+ ((R:SylStructure.parent.position_type is mid)
+ ((ph_cplace2 is a)
+ ((0.672133 0.230903))
+ ((0.80338 0.0400124)))
+ ((1.69056 0.50114)))
+ ((ph_ctype is 0)
+ ((p.ph_vc is 0)
+ ((n.ph_vfront is 1)
+ ((0.501554 0.26615))
+ ((0.416151 0.388289)))
+ ((lisp_mora is 1)
+ ((0.987786 0.206331))
+ ((n.seg_onsetcoda is 0)
+ ((pp.ph_vlng is s)
+ ((3.63498 0.300449))
+ ((p.ph_vc is +)
+ ((0.316186 -0.0912046))
+ ((0.378855 -0.137722))))
+ ((0.63434 -0.490483)))))
+ ((p.ph_ctype is n)
+ ((ph_cplace2 is r)
+ ((n.ph_vfront is 1)
+ ((0.620663 -0.502778))
+ ((1.0622 -0.222376)))
+ ((R:SylStructure.parent.position_type is mid)
+ ((ph_cplace2 is a)
+ ((n.ph_vfront is 1)
+ ((0.599848 -0.462058))
+ ((0.582839 -0.617057)))
+ ((0.754908 -0.661127)))
+ ((0.707766 -0.325685))))
+ ((p.ph_cplace2 is r)
+ ((ph_ctype is s)
+ ((lisp_mora is 1)
+ ((0.485732 0.262402))
+ ((0.639091 0.395967)))
+ ((0.75426 -0.415642)))
+ ((p.ph_ctype is f)
+ ((ph_ctype is s)
+ ((ph_cplace2 is r)
+ ((0.522713 -0.507001))
+ ((0.516307 -0.413684)))
+ ((1.44597 -0.00853439)))
+ ((ph_ctype is f)
+ ((ph_cplace2 is a)
+ ((lisp_mora is 1)
+ ((0.659259 -0.034664))
+ ((n.ph_vfront is 1)
+ ((0.664414 0.0984968))
+ ((0.658419 0.382264))))
+ ((lisp_mora is 2)
+ ((n.ph_vfront is 1)
+ ((ph_cplace2 is l)
+ ((0.693631 -0.643123))
+ ((0.649306 -0.281858)))
+ ((0.83365 -0.135963)))
+ ((ph_cplace2 is l)
+ ((0.867115 0.0178028))
+ ((0.724301 -0.31404)))))
+ ((p.ph_vc is 0)
+ ((1.53813 -0.682428))
+ ((ph_cplace2 is a)
+ ((ph_ctype is n)
+ ((0.784693 -0.0930149))
+ ((n.ph_vfront is 1)
+ ((ph_ctype is s)
+ ((lisp_mora is 1)
+ ((0.606571 -0.136641))
+ ((pp.ph_vlng is 0)
+ ((0.500308 -0.257488))
+ ((0.580499 -0.36123))))
+ ((pp.ph_vlng is 0)
+ ((ph_ctype is l)
+ ((lisp_mora is 1)
+ ((0.616096 -0.341244))
+ ((0.602307 -0.132246)))
+ ((0.591382 -0.46949)))
+ ((0.670605 -0.53436))))
+ ((ph_ctype is l)
+ ((pp.ph_vlng is s)
+ ((0.91185 0.177441))
+ ((0.720048 -0.0126887)))
+ ((p.ph_vc is +)
+ ((pp.ph_vlng is 0)
+ ((0.5792 -0.2432))
+ ((0.525133 -0.365416)))
+ ((0.398956 -0.147817))))))
+ ((ph_ctype is s)
+ ((pp.ph_vlng is s)
+ ((p.ph_vc is +)
+ ((n.ph_vfront is 1)
+ ((0.520408 -0.228262))
+ ((0.611901 -0.437854)))
+ ((0.631179 -0.126642)))
+ ((ph_cplace2 is l)
+ ((0.45656 -0.246684))
+ ((lisp_mora is 1)
+ ((0.557288 -0.0837172))
+ ((n.ph_vfront is 1)
+ ((0.686151 -0.00979517))
+ ((0.635011 0.193597))))))
+ ((R:SylStructure.parent.position_type is mid)
+ ((ph_ctype is n)
+ ((p.ph_vc is +)
+ ((0.635443 -0.0443977))
+ ((0.667539 -0.192734)))
+ ((pp.ph_vlng is s)
+ ((1.07378 0.0364854))
+ ((0.906008 0.377596))))
+ ((0.714999 -0.158161)))))))))))))))
+ ((pos_in_syl < 2)
+ ((p.ph_clng is l)
+ ((n.ph_vfront is 1)
+ ((p.ph_cplace2 is a)
+ ((0.700828 0.0274336))
+ ((0.677255 -0.111315)))
+ ((p.ph_ctype is s)
+ ((0.618852 -0.193819))
+ ((0.724311 -0.329287))))
+ ((pp.ph_vlng is s)
+ ((p.ph_ctype is r)
+ ((p.ph_cplace2 is a)
+ ((0.937351 0.317126))
+ ((0.849952 -0.139897)))
+ ((lisp_mora is 1)
+ ((p.ph_ctype is f)
+ ((n.ph_vfront is 1)
+ ((R:SylStructure.parent.position_type is mid)
+ ((0.76535 0.790169))
+ ((1.03739 0.558797)))
+ ((0.90394 0.524563)))
+ ((R:SylStructure.parent.position_type is final)
+ ((n.ph_vfront is 1)
+ ((0.864259 0.530013))
+ ((p.ph_ctype is n)
+ ((0.925474 0.385941))
+ ((0.839374 0.0860296))))
+ ((p.ph_cplace2 is r)
+ ((0.842425 0.331699))
+ ((p.ph_ctype is l)
+ ((0.846849 0.421375))
+ ((p.ph_ctype is n)
+ ((0.794562 0.498626))
+ ((p.ph_cplace2 is a)
+ ((0.664718 0.548134))
+ ((0.866985 0.820401))))))))
+ ((p.ph_ctype is n)
+ ((0.720299 -0.150627))
+ ((ph_ctype is 0)
+ ((p.ph_cplace2 is l)
+ ((0.801496 0.738192))
+ ((p.ph_cplace2 is a)
+ ((0.765104 0.419409))
+ ((0.705522 0.243006))))
+ ((1.22977 0.000188928))))))
+ ((p.ph_vc is +)
+ ((lisp_mora is 3)
+ ((n.ph_vfront is 1)
+ ((0.93838 0.197776))
+ ((0.701688 -0.0627497)))
+ ((ph_ctype is n) ((0.881802 0.595966)) ((0.708916 0.403764))))
+ ((p.ph_ctype is s)
+ ((R:SylStructure.parent.position_type is final)
+ ((p.ph_cplace2 is a)
+ ((0.71706 -0.0729048))
+ ((0.793548 0.133463)))
+ ((R:SylStructure.parent.position_type is mid)
+ ((0.680685 0.145939))
+ ((0.60824 0.307953))))
+ ((R:SylStructure.parent.position_type is single)
+ ((0.914759 -0.423949))
+ ((p.ph_cplace2 is r)
+ ((0.81343 -0.284817))
+ ((pp.ph_vlng is 0)
+ ((p.ph_cplace2 is a)
+ ((0.671806 -0.0742459))
+ ((0.703139 0.137603)))
+ ((0.794418 0.203018)))))))))
+ ((p.ph_vc is +) ((0.93074 0.182872)) ((0.181943 -2.7517)))))
+ ((lisp_mora is 1)
+ ((p.ph_clng is l)
+ ((n.ph_ctype is r)
+ ((R:SylStructure.parent.position_type is final)
+ ((0.66389 -0.180732))
+ ((0.599906 -0.595642)))
+ ((R:SylStructure.parent.position_type is mid)
+ ((p.ph_ctype is s)
+ ((n.ph_cplace is l)
+ ((0.533117 -0.968386))
+ ((n.ph_ctype is l)
+ ((0.523188 -0.989232))
+ ((0.418059 -0.825256))))
+ ((n.ph_ctype is f)
+ ((0.530341 -0.816161))
+ ((0.609714 -0.468383))))
+ ((p.ph_ctype is f)
+ ((n.ph_ctype is s) ((0.255965 -1.16391)) ((0.281458 -1.08328)))
+ ((p.ph_ctype is s)
+ ((n.ph_ctype is s)
+ ((0.309995 -1.09552))
+ ((0.373794 -0.968148)))
+ ((n.ph_ctype is s)
+ ((0.55278 -0.916649))
+ ((0.386578 -0.73261)))))))
+ ((pp.ph_vlng is s)
+ ((n.ph_cplace is v)
+ ((R:SylStructure.parent.position_type is mid)
+ ((0.66849 -0.385247))
+ ((0.561963 -0.639861)))
+ ((p.ph_ctype is r)
+ ((R:SylStructure.parent.position_type is single)
+ ((0.431664 -0.72181))
+ ((n.ph_cplace is a)
+ ((0.563895 -0.386133))
+ ((0.773353 -0.214832))))
+ ((n.ph_ctype is r)
+ ((n.ph_cplace is a)
+ ((0.80164 0.449338))
+ ((R:SylStructure.parent.position_type is mid)
+ ((0.608827 -0.427038))
+ ((0.713475 -0.129587))))
+ ((R:SylStructure.parent.position_type is final)
+ ((p.ph_ctype is n)
+ ((0.675759 -0.0711996))
+ ((n.ph_cplace is a)
+ ((p.ph_ctype is s)
+ ((0.536365 -0.150662))
+ ((0.547778 -0.288462)))
+ ((0.600451 -0.517365))))
+ ((p.ph_ctype is l)
+ ((n.ph_ctype is n)
+ ((0.7461 0.146578))
+ ((n.ph_ctype is s)
+ ((0.677136 -0.0470136))
+ ((0.604616 -0.224768))))
+ ((p.ph_cplace2 is l)
+ ((p.ph_ctype is n)
+ ((0.667951 -0.494344))
+ ((0.667624 -0.0213202)))
+ ((p.ph_ctype is n)
+ ((0.86803 0.12581))
+ ((n.ph_ctype is l)
+ ((0.715877 -0.0238713))
+ ((p.ph_cplace2 is a)
+ ((n.ph_ctype is s)
+ ((0.642383 -0.163298))
+ ((0.725958 -0.441871)))
+ ((n.ph_cplace is a)
+ ((0.796113 -0.368086))
+ ((0.551508 0.0142687))))))))))))
+ ((pos_in_syl < 0.3)
+ ((1.00356 0.0241227))
+ ((n.ph_ctype is r)
+ ((n.ph_cplace is a)
+ ((0.7926 -0.0106655))
+ ((R:SylStructure.parent.position_type is mid)
+ ((0.564627 -0.715817))
+ ((0.713114 -0.326565))))
+ ((p.ph_ctype is r)
+ ((R:SylStructure.parent.position_type is single)
+ ((0.342482 -1.24585))
+ ((0.591421 -0.842725)))
+ ((p.ph_cplace2 is a)
+ ((n.ph_cplace is v)
+ ((0.37148 -0.997771))
+ ((pp.ph_vlng is 0)
+ ((R:SylStructure.parent.position_type is mid)
+ ((p.ph_ctype is f)
+ ((0.566184 -0.883607))
+ ((n.ph_cplace is b)
+ ((0.486445 -0.860645))
+ ((0.519562 -0.746008))))
+ ((n.ph_cplace is b)
+ ((0.537189 -0.651737))
+ ((n.ph_ctype is s)
+ ((0.297647 -1.00349))
+ ((n.ph_cplace is a)
+ ((n.ph_ctype is f)
+ ((0.307224 -1.01861))
+ ((0.413763 -0.777775)))
+ ((0.452027 -0.803768))))))
+ ((0.566495 -0.631796))))
+ ((n.ph_cplace is a)
+ ((n.ph_ctype is s)
+ ((0.475403 -0.761056))
+ ((p.ph_ctype is f)
+ ((0.694206 -0.439748))
+ ((R:SylStructure.parent.position_type is mid)
+ ((n.ph_ctype is l)
+ ((0.513707 -0.725154))
+ ((0.511479 -0.623081)))
+ ((0.721193 -0.488443)))))
+ ((p.ph_cplace2 is r)
+ ((n.ph_cplace is l)
+ ((0.547292 -0.739571))
+ ((0.506041 -0.875932)))
+ ((R:SylStructure.parent.position_type is final)
+ ((n.ph_ctype is s)
+ ((0.469445 -0.722393))
+ ((0.608242 -0.332834)))
+ ((0.674525 -0.325557)))))))))))
+ ((p.ph_vc is 0)
+ ((n.ph_ctype is f)
+ ((0.490377 0.14904))
+ ((n.ph_cplace is a)
+ ((n.ph_ctype is n) ((0.610979 0.235261)) ((0.46348 0.372425)))
+ ((0.541258 0.237457))))
+ ((n.ph_ctype is s)
+ ((ph_ctype is s)
+ ((n.seg_onsetcoda is coda)
+ ((0.798423 2.41817))
+ ((n.ph_cplace is v)
+ ((0.445275 -0.171309))
+ ((0.796616 0.315213))))
+ ((ph_ctype is n)
+ ((lisp_mora is 2)
+ ((pp.ph_vlng is s)
+ ((n.ph_cplace is v)
+ ((0.94266 -0.290003))
+ ((0.706687 -0.862965)))
+ ((n.ph_cplace is v)
+ ((R:SylStructure.parent.position_type is mid)
+ ((0.77751 -0.167354))
+ ((0.794132 -0.0397283)))
+ ((n.ph_cplace is a)
+ ((R:SylStructure.parent.position_type is final)
+ ((0.717463 -0.395321))
+ ((0.859088 -0.10108)))
+ ((R:SylStructure.parent.position_type is final)
+ ((0.676595 -0.214784))
+ ((0.976023 -0.662831))))))
+ ((R:SylStructure.parent.position_type is final)
+ ((0.683003 -0.641977))
+ ((0.461195 -0.846843))))
+ ((ph_cplace2 is a)
+ ((n.ph_cplace is v)
+ ((0.782669 -0.332275))
+ ((pos_in_syl < 2)
+ ((ph_ctype is f)
+ ((0.567608 -0.900861))
+ ((0.941499 -0.732118)))
+ ((0.497955 -1.24758))))
+ ((p.ph_clng is l)
+ ((p.ph_ctype is n)
+ ((0.377335 -0.827169))
+ ((0.43858 -0.961623)))
+ ((pos_in_syl < 0.3)
+ ((0.694012 -0.153702))
+ ((R:SylStructure.parent.position_type is final)
+ ((pp.ph_vlng is s)
+ ((p.ph_ctype is n)
+ ((0.393129 -0.498547))
+ ((p.ph_cplace2 is l)
+ ((0.379415 -0.591128))
+ ((p.ph_ctype is f)
+ ((0.519226 -0.826579))
+ ((0.550936 -0.619726)))))
+ ((p.ph_ctype is f)
+ ((0.344598 -0.974665))
+ ((0.467213 -0.760801))))
+ ((p.ph_ctype is r)
+ ((0.557746 -0.788657))
+ ((ph_ctype is 0)
+ ((pp.ph_vlng is s)
+ ((p.ph_ctype is f)
+ ((p.ph_cplace2 is a)
+ ((0.657189 -0.461298))
+ ((0.804463 -0.0564339)))
+ ((p.ph_cplace2 is a)
+ ((n.ph_cplace is a)
+ ((0.516349 -0.487186))
+ ((0.652126 -0.24901)))
+ ((0.516932 -0.599442))))
+ ((n.ph_cplace is v)
+ ((p.ph_ctype is s)
+ ((0.45193 -0.584097))
+ ((0.526092 -0.839978)))
+ ((n.seg_onsetcoda is coda)
+ ((0.828519 -0.366318))
+ ((0.501974 -0.642094)))))
+ ((0.998996 -0.207612))))))))))
+ ((ph_cplace2 is a)
+ ((n.ph_ctype is f)
+ ((n.ph_cplace is a)
+ ((ph_ctype is n)
+ ((lisp_mora is 2)
+ ((R:SylStructure.parent.position_type is final)
+ ((0.845547 -0.490197))
+ ((0.868322 -0.86479)))
+ ((0.583089 -1.32664)))
+ ((0.659799 -0.166974)))
+ ((pp.ph_vlng is s)
+ ((pos_in_syl < 1.2)
+ ((0.545178 -0.0838595))
+ ((0.745166 -0.343245)))
+ ((lisp_mora is 2)
+ ((ph_ctype is s)
+ ((0.553365 0.210636))
+ ((0.809561 0.399364)))
+ ((0.696307 -0.116787)))))
+ ((ph_ctype is l)
+ ((0.990092 -0.339027))
+ ((lisp_mora is 3)
+ ((n.ph_cplace is a)
+ ((1.07935 -0.12981))
+ ((0.882304 0.0823764)))
+ ((pp.ph_vlng is 0)
+ ((n.ph_cplace is l)
+ ((ph_ctype is s) ((0.646903 1.15249)) ((1.10717 0.496918)))
+ ((1.01146 0.434096)))
+ ((n.ph_ctype is n)
+ ((0.887008 -0.0745151))
+ ((0.812587 0.169537)))))))
+ ((n.ph_ctype is f)
+ ((n.ph_cplace is a)
+ ((pp.ph_vlng is 0)
+ ((p.ph_cplace2 is l)
+ ((0.56388 -0.836105))
+ ((p.ph_cplace2 is r)
+ ((0.681996 -0.798265))
+ ((R:SylStructure.parent.position_type is single)
+ ((0.722674 -0.240226))
+ ((n.seg_onsetcoda is coda)
+ ((pos_in_syl < 1.2)
+ ((0.532268 -0.482672))
+ ((0.573514 -0.810443)))
+ ((0.486268 -0.535983))))))
+ ((p.ph_clng is s)
+ ((p.ph_cplace2 is r)
+ ((0.840044 -0.137973))
+ ((R:SylStructure.parent.position_type is mid)
+ ((p.ph_ctype is s)
+ ((0.676392 -0.317128))
+ ((p.ph_cplace2 is a)
+ ((p.ph_ctype is r)
+ ((0.717006 -0.533094))
+ ((p.ph_ctype is f)
+ ((0.742985 -0.454561))
+ ((0.7368 -0.27739))))
+ ((0.533025 -0.571322))))
+ ((0.619673 -0.514244))))
+ ((p.ph_cplace2 is a)
+ ((0.497439 -0.806519))
+ ((0.476752 -0.693539)))))
+ ((n.seg_onsetcoda is coda)
+ ((0.95952 -0.135029))
+ ((p.ph_cplace2 is a)
+ ((0.598809 -0.486134))
+ ((0.495617 -0.20274)))))
+ ((R:SylStructure.parent.position_type is mid)
+ ((pp.ph_vlng is s)
+ ((n.ph_cplace is a)
+ ((p.ph_ctype is n)
+ ((p.ph_clng is l)
+ ((0.521479 -0.175804))
+ ((0.682339 -0.0022929)))
+ ((lisp_mora is 2)
+ ((n.seg_onsetcoda is coda)
+ ((0.702162 0.465337))
+ ((p.ph_cplace2 is r)
+ ((0.730895 -0.0114749))
+ ((0.716493 0.313177))))
+ ((0.747677 0.00177269))))
+ ((p.ph_ctype is f)
+ ((0.922175 0.203941))
+ ((n.ph_cplace is l)
+ ((0.687174 -0.0363329))
+ ((0.797603 -0.344224)))))
+ ((n.ph_ctype is r)
+ ((1.02108 0.282636))
+ ((p.ph_ctype is r)
+ ((0.54182 -0.5994))
+ ((p.ph_cplace2 is a)
+ ((p.ph_ctype is f)
+ ((0.52293 -0.613554))
+ ((0.61755 -0.265341)))
+ ((p.ph_ctype is f)
+ ((0.861973 0.0372255))
+ ((n.ph_ctype is l)
+ ((0.730478 -0.349741))
+ ((0.757481 -0.145898))))))))
+ ((p.ph_clng is s)
+ ((lisp_mora is 3)
+ ((p.ph_ctype is s)
+ ((pp.ph_vlng is 0)
+ ((0.517808 -0.479629))
+ ((0.534339 -0.339318)))
+ ((p.ph_cplace2 is l)
+ ((0.603803 -0.640758))
+ ((pp.ph_vlng is s)
+ ((0.712351 -0.330568))
+ ((0.568915 -0.560679)))))
+ ((p.ph_cplace2 is r)
+ ((p.ph_ctype is r)
+ ((0.476332 -0.66412))
+ ((R:SylStructure.parent.position_type is single)
+ ((0.555318 -0.445519))
+ ((p.ph_ctype is f)
+ ((0.692326 -0.584272))
+ ((0.649426 -0.235355)))))
+ ((pp.ph_vlng is s)
+ ((p.ph_ctype is f)
+ ((p.ph_cplace2 is a)
+ ((0.694916 -0.403756))
+ ((0.648391 -0.0108221)))
+ ((n.seg_onsetcoda is coda)
+ ((p.ph_ctype is l)
+ ((0.634274 0.189092))
+ ((p.ph_cplace2 is a)
+ ((0.622436 -0.0801574))
+ ((0.659552 0.0564502))))
+ ((0.613115 -0.274092))))
+ ((R:SylStructure.parent.position_type is single)
+ ((0.890316 0.100146))
+ ((0.555715 -0.393896))))))
+ ((lisp_mora is 3)
+ ((0.470997 -0.778816))
+ ((pos_in_syl < 1.2)
+ ((R:SylStructure.parent.position_type is single)
+ ((0.786515 -0.460109))
+ ((pp.ph_vlng is s)
+ ((p.ph_ctype is n)
+ ((0.580053 -0.392255))
+ ((0.506821 -0.529974)))
+ ((R:SylStructure.parent.position_type is 0)
+ ((0.297801 -0.379085))
+ ((0.845351 -0.117591)))))
+ ((R:SylStructure.parent.position_type is final)
+ ((0.58491 -0.464601))
+ ((0.637256 -0.652212)))))))))))))
+ ((n.ph_vfront is 0)
+ ((lisp_mora is 1)
+ ((R:SylStructure.parent.position_type is final)
+ ((p.ph_clng is l)
+ ((p.ph_ctype is l)
+ ((0.581768 -1.19027))
+ ((p.ph_ctype is f) ((0.751442 -0.985889)) ((0.81301 -0.645655))))
+ ((p.ph_ctype is s)
+ ((pp.ph_vlng is 0)
+ ((0.706418 -0.704896))
+ ((0.971941 -0.206601)))
+ ((p.ph_ctype is f)
+ ((0.910496 -0.223875))
+ ((0.955915 -0.378582)))))
+ ((n.ph_ctype is s)
+ ((0.720567 0.000321504))
+ ((n.ph_ctype is f)
+ ((0.847069 0.243405))
+ ((pp.ph_vlng is 0) ((0.698901 0.345199)) ((0.912286 0.674266))))))
+ ((n.ph_ctype is n)
+ ((p.ph_ctype is n)
+ ((0.702047 0.319904))
+ ((lisp_mora is 2)
+ ((R:SylStructure.parent.position_type is final)
+ ((0.865349 0.460549))
+ ((1.08463 1.00808)))
+ ((pp.ph_vlng is 0) ((0.922977 1.0134)) ((1.12538 1.26623)))))
+ ((ph_ctype is f)
+ ((0.996002 0.871986))
+ ((ph_ctype is s)
+ ((ph_cplace2 is a) ((0.824457 1.24974)) ((0.543244 0.450197)))
+ ((lisp_mora is 3)
+ ((ph_cplace2 is a)
+ ((0.777385 -0.343544))
+ ((0.956584 0.337526)))
+ ((n.ph_ctype is s)
+ ((p.ph_cplace2 is a)
+ ((0.594385 -0.37777))
+ ((0.940047 -0.0249902)))
+ ((n.ph_ctype is f)
+ ((p.ph_cplace2 is a)
+ ((pp.ph_vlng is s)
+ ((0.736129 0.0641271))
+ ((0.653832 -0.371453)))
+ ((pos_in_syl < 1.2)
+ ((0.847296 0.149207))
+ ((1.13276 0.4653))))
+ ((pos_in_syl < 1.2)
+ ((n.ph_ctype is l)
+ ((0.842123 0.474713))
+ ((p.ph_ctype is s)
+ ((1.06371 0.634879))
+ ((1.10028 1.26986))))
+ ((1.03168 0.11122))))))))))
+ ((lisp_end_of_phrase is 1)
+ ((p.ph_cplace2 is a)
+ ((p.ph_ctype is f)
+ ((lisp_mora is 1)
+ ((n.ph_vfront is 1) ((0.858409 0.569369)) ((0.600806 0.297108)))
+ ((0.966558 1.03672)))
+ ((lisp_mora is 1)
+ ((ph_cplace2 is a) ((0.75622 0.996286)) ((0.898703 1.26713)))
+ ((1.09981 1.37918))))
+ ((ph_ctype is s)
+ ((n.ph_vfront is 1)
+ ((ph_cplace2 is r) ((1.15655 1.42386)) ((1.16713 1.80448)))
+ ((1.08963 1.38385)))
+ ((ph_ctype is r)
+ ((0.807953 0.43703))
+ ((lisp_mora is 2)
+ ((pp.ph_vlng is 0) ((0.853256 0.60538)) ((1.17451 1.00819)))
+ ((ph_ctype is n)
+ ((1.11399 0.823994))
+ ((n.ph_vfront is 1)
+ ((ph_ctype is l)
+ ((0.90164 1.2336))
+ ((p.ph_ctype is s) ((0.734892 1.24618)) ((1.02358 1.614))))
+ ((0.888684 1.27728))))))))
+ ((ph_ctype is 0)
+ ((p.ph_cplace2 is a) ((0.718485 1.10805)) ((0.932929 1.2986)))
+ ((n.seg_onsetcoda is coda)
+ ((p.ph_cplace2 is a)
+ ((lisp_mora is 1) ((0.590999 0.228387)) ((0.699974 0.413645)))
+ ((ph_cplace2 is l)
+ ((ph_ctype is n) ((0.700411 0.449788)) ((0.564384 0.214491)))
+ ((lisp_mora is 2)
+ ((ph_ctype is f)
+ ((0.698342 0.453959))
+ ((pp.ph_vlng is 0)
+ ((0.827512 0.514166))
+ ((0.801421 0.748086))))
+ ((ph_ctype is s)
+ ((0.782835 0.90533))
+ ((ph_ctype is l) ((0.886991 0.499058)) ((0.55558 0.703079)))))))
+ ((pp.ph_vlng is s) ((0.806638 1.23657)) ((0.748911 0.750108)))))))))
+)
+))
+
+(define (Duration_Finnish utt)
+ "(Duration_Finnish)
+Lengthens the final phone after the duration cart tree."
+ (if hy_debug (format stderr "<PHONE DURATIONS>\n"))
+ (let ((end 0))
+ (if hy_debug (format stderr "Phone\tDur\tEnd"))
+ (mapcar
+ (lambda (s)
+ (item.get_utt s)
+ (let ((dur (wagon_predict s duration_cart_tree))
+ (di (assoc_string (item.name s) hy_fi_mv2::phone_durs)))
+ ;; (nth 1 di) mean
+ ;; (nth 2 di) dev
+ (set! dur (+ (nth 1 di) (* dur (nth 2 di))))
+
+ ;; lengthening of the final phoneme
+ ;; (we're not perfectly happy of duration in phrase final position)
+ (if (and (item.next s)
+ (string-equal (item.name (item.next s)) "#"))
+ (begin
+ (set! dur (* dur 1.0)))) ;; 1.3
+
+
+
+ (set! dur (* (Parameter.get 'Duration_Stretch) dur))
+ (if (> 0.03 dur)
+ (begin
+ (set! dur 0.03)
+ (if hy_debug
+ (format stderr
+ " %s is shorter than 30 ms! Lengthening it!\n"
+ (item.name s))))
+ (if hy_debug (format stderr "\n")))
+
+ ;; too short final phoneme can cause a crash...
+ ;; an awfully terrible bug fix...
+ (if (not (item.next s))
+ (begin
+ (set! dur 0.2)))
+
+ (set! end (+ dur end))
+
+ (if hy_debug (format stderr "%s\t%s\t%s " (item.name s) dur end))
+ (if (and hy_debug (not (item.next s))) (format stderr "\n"))
+ (item.set_feat s "target_dur" dur)
+ (item.set_function s "start" "unisyn_start")
+ (item.set_feat s "end" end)
+ (item.set_feat s "dur" dur)
+ );; end of let
+ ) ;; end of lambda
+ (utt.relation.items utt 'Segment)) ;; end of mapcar
+ utt))
+
+
+(define (mora aanne)
+ "(mora PHONE)
+Counts the number of morae in the syllable.
+Used by the duration model."
+;; if syllable ends in a long C, is it counted as 1 (as it should be)
+;; or as 2 (as it probably is)????
+ (let ((coda (item.feat aanne 'R:SylStructure.parent.syl_codasize))
+ (onset (item.feat aanne 'R:SylStructure.parent.syl_onsetsize))
+ (head (if (item.parent (item.relation aanne 'SylStructure))
+ (item.relation (item.daughter1 (item.parent (item.relation aanne 'SylStructure))) 'Segment)
+ nil))
+ (mora 0))
+ (while (> onset 0)
+ (set! onset (- onset 1))
+ (set! head (item.next head)))
+ (while (> coda 0)
+ (if (string-matches (item.name head) "^[abdefghijklmnoprstuvy@7NT]:$" )
+
+ (set! mora (+ mora 2))
+ (set! mora (+ mora 1)))
+ (set! coda (- coda 1))
+ (set! head (item.next head)))
+ (if (and head
+ (string-matches (item.name head) "^[abdefghijklmnoprstuvy@7NT]:$" )
+ (string-matches (item.name head) "^[bdfghjklmnprstvNT]:?$" ))
+ (set! mora (+ mora 1)))
+;; (print mora)
+ mora))
+
+
+(define (end_of_phrase phone)
+ "(end_of_phrase PHONE)
+Used by the duration tree to detect phrase boundary.
+Returns either 1 (last syllable), 2 (penultimate syllable of the phrase)
+or 0 (other). Somehow I'm sure that there are easier and faster
+ways to do this..."
+ (cond
+ ((not (item.relation phone 'SylStructure))
+ 0)
+ ((string-equal "#" (item.feat phone "R:SylStructure.parent.daughtern.R:Segment.n.name"))
+;; (format stderr "1: %s\n" (item.name phone))
+ 1)
+
+ ((string-equal "#" (item.feat phone "R:SylStructure.parent.n.daughtern.R:Segment.n.name"))
+;; (format stderr "2: %s\n" (item.name phone))
+ 2)
+ (t
+ 0)))
+
+
+(provide 'finnish_duration
+
+)
+
+
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_lex.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_lex.scm
new file mode 100644
index 0000000..2a98ae2
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_lex.scm
@@ -0,0 +1,216 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Department of General Linguistics / Suopuhe project ;;
+;;; University of Helsinki, FI ;;
+;;; Copyright (c) 2000-2003 ;;
+;;; All Rights Reserved. ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Finnish lexicon for function word determination ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; Authors: Nicholas Volk & Martti Vainio
+;
+
+
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+
+(define (word_list_entry? word lexicon)
+ "(word_list_entry? STRING LIST)
+Checks whether the STRING is member of any of the sublists of LIST."
+ ;; (format stderr "%s in %l?\n" sana (car leksikko))
+ (cond
+ ((null lexicon)
+ nil)
+ ((member_string word (cdr (car lexicon)))
+ t)
+ (t
+ (word_list_entry? word (cdr lexicon)))))
+
+
+
+(set! doubler_words
+ '((a terve tuore )
+ (n aihe aste kone laite lause luode näyte oire puhe purje tunne vene virhe)
+ (v aja auta mene ole ota pue pure syö tule ))
+ )
+
+(set! finnish_guess_coord
+ '((coord ja tai vai)))
+
+(set! finnish_guess_cop
+ '(
+ (cop
+ olen olet on olemme olette ovat olla ole olleet ollut
+ olin olit oli olimme olitte olivat
+ olisin olisit olisi olisimme olisitte olisivat
+ lienen lienet lienee lienemme lienette lienevät liene lienneet)))
+
+(set! finnish_guess_pron
+ '(
+ (pron
+ minä sinä hän me te he se ne
+ minun sinun hänen meidän teidän heidän sen niiden niitten
+ minua sinua häntä meitä teitä heitä sitä niitä
+ minut sinut hänet meidät teidät heidät
+ minusta sinusta hänestä meistä teistä heistä siitä niistä
+ minussa sinussa hänessä meissä heissä siinä niissä
+ minuun sinuun häneen meihin teihin heihin siihen niille
+ minulla sinulla hänellä meillä teillä heillä niillä
+ minulta sinulta häneltä meiltä teiltä heiltä niiltä
+ minulle sinulle hänelle meille teille heille sille niille
+ mä mun mua mut mussa muhun mulla mulle
+ sä sun sua sut sussa susta suhun sulla sulta sulle
+ tämä tämän tätä tässä tästä tähän tällä tältä tälle tänä
+ nämä näiden näitten näitä näissä näistä näihin näillä näiltä näille näinä
+ tuo tuon tuota tuossa tuosta tuohon tuolla tuolta tuolle tuona
+ nuo noiden noitten noissa noista noihin noilla noilta noille noina
+ joka jonka jota jossa josta johon jolla jolle jolta jona
+ jotka joiden joita joissa joista joihin joilla joilta joille joina
+ mikä minkä mitä missä mistä mihin millä miltä mille miksi
+ minne tänne sinne jonne
+ kuka ketä kenen kenessä kenestä keneen kenellä keneltä kenelle
+ ken keitä ketkä keiden keitten keissä keistä keihin keillä keiltä keille
+ kumpi kumpaa kumman kummassa kummasta kumpaan kummalla kummalta kummalle kumpana
+ )))
+
+(set! finnish_guess_pos
+ '(
+ (copula
+ olen olet on olemme olette ovat olla ole olleet ollut
+ olin olit oli olimme olitte olivat
+ olisin olisit olisi olisimme olisitte olisivat
+ lienen lienet lienee lienemme lienette lienevät liene lienneet)
+
+ (coord
+ ja tai vai)
+ (neg
+ en et ei emme ette eivät)
+ (xxx
+ ali alla allaan alle alleen alta
+ and
+ edelle edelleen edellä edellään edessä edessämme edessäni edessään edestä edestään
+ ehkei
+ eli
+ ellei ellen
+ ennen
+ eteen
+ ettei etteivät etten
+ että
+ huolimatta
+ ilman
+ joko
+ jokunen
+ jollei jolleivät
+ jos
+ jäljessä jälkeen jälkeensä
+ kanssa
+ kautta kauttaan
+ kera
+ kerran
+ keskelle keskellä keskeltä kesken
+ kohti
+ koska
+ kuin
+ kun
+ luokse luokseen luona luota luotasi
+ lähelle lähellä läheltä lähettyville
+ lähtien
+ läpi
+ miksei
+ mikäli
+ mutta muttei
+ ohella ohessa
+ ohi ohitse ohitseni
+ olemaan olemassa olemasta olematta oleva olevaa olevaan olevalla olevalle olevamme olevan olevani olevansa olevassa olevasta olevia olevien oleviin oleville olevissa olevista olkoon ollaan ollakseen olleelle olleen olleensa olleeseen olleessa olleiden olleille olleisiin olleissa olleista olleita ollen ollenkaan ollessa ollessaan ollessani ollutta oltaisiin oltaisiinko oltava oltu oltua oltuaan
+ paitsi
+ pitkin
+ poikki
+ päin päälle päälleen päällä päältään
+ riippumatta
+ saati
+ sekä
+ suhteen suhteensa
+ taakse taakseen
+ takaa takana takanaan
+ vaan
+ vaikka vaikkei
+ vailla vaille
+ varrella varrelta varressa varresta varteen
+ vastapäätä
+ vasten vastoin
+ yli ylitse
+ ympäri
+ ynnä
+ älkää älköön
+ )
+ (punc
+ "." "," ":" "!" "?" "(" ")" "\"")))
+
+;;;========================================================================
+(lex.create "finnish")
+(lex.set.phoneset "finnish")
+
+;(lex.set.compile.file "/home/n/v/nvolk/festival/lib/voices/finnish/hy_fi_mv_diphone/lex.lex" )
+;;(lex.set.compile.file "/home/n/v/nvolk/festival/lib/voices/finnish/hy_fi_mv_diphone/festvox/lex.lex" )
+;;;(lex.set.pos.map finnish_pos_map) ; turha...
+(lex.set.lts.method 'finnish_lts)
+;;;(lex.set.lts.ruleset 'finnish) ; turha...
+
+;;;========================================================================
+;;(lex.add.entry '("." "punc" ((( # # ) 0 ))))
+;;(lex.add.entry '(":" "punc" ((( # ) 0 ))))
+;;(lex.add.entry '(";" "punc" ((( # ) 0 ))))
+;;(lex.add.entry '("," "punc" ((( # ) 0 ))))
+;;(lex.add.entry '("?" "punc" ((( # # ) 0 ))))
+;;(lex.add.entry '("!" "punc" ((( # # ) 0 ))))
+
+;;;========================================================================
+(lex.add.entry '("a" "char" ((( a: ) 2))))
+(lex.add.entry '("b" "char" ((( b e: ) 2))))
+(lex.add.entry '("c" "char" ((( s e: ) 2))))
+(lex.add.entry '("d" "char" ((( d e: ) 2))))
+(lex.add.entry '("e" "char" ((( e: ) 2))))
+(lex.add.entry '("f" "char" ((( @ f ) 2))))
+(lex.add.entry '("g" "char" ((( g e: ) 2))))
+(lex.add.entry '("h" "char" ((( h o: ) 2))))
+(lex.add.entry '("i" "char" ((( i: ) 2))))
+(lex.add.entry '("j" "char" ((( j i: ) 2))))
+(lex.add.entry '("k" "char" ((( k o: ) 2))))
+(lex.add.entry '("l" "char" ((( @ l ) 2))))
+(lex.add.entry '("m" "char" ((( @ m ) 2))))
+(lex.add.entry '("n" "char" ((( @ n ) 2))))
+(lex.add.entry '("o" "char" ((( o: ) 2))))
+(lex.add.entry '("p" "char" ((( p e: ) 2))))
+(lex.add.entry '("q" "char" ((( k u: ) 2))))
+(lex.add.entry '("r" "char" ((( @ r ) 2))))
+(lex.add.entry '("s" "char" ((( @ s ) 2))))
+(lex.add.entry '("t" "char" ((( t e: ) 2))))
+(lex.add.entry '("u" "char" ((( u: ) 2))))
+(lex.add.entry '("v" "char" ((( v e: ) 2))))
+(lex.add.entry '("w" "char" ((( k a k ) 2) (( s o i s ) 0) (( v e: ) 1))))
+(lex.add.entry '("x" "char" ((( @ k s ) 2))))
+(lex.add.entry '("y" "char" ((( y: ) 2))))
+(lex.add.entry '("z" "char" ((( b e: ) 2))))
+(lex.add.entry '("å" "char" ((( r u o t ) 2 ) (( s a ) 0 ) (( l a i ) 1 ) (( n e n) 0 )(( o: ) 2))))
+(lex.add.entry '("ä" "char" ((( @: ) 2))))
+(lex.add.entry '("ö" "char" ((( 7: ) 2))))
+
+
+;;;========================================================================
+(provide 'finnish_lex)
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_lts.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_lts.scm
new file mode 100644
index 0000000..a9e88b9
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_lts.scm
@@ -0,0 +1,829 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Department of General Linguistics / Suopuhe project ;;
+;;; University of Helsinki, FI ;;
+;;; Copyright (c) 2000-2003 ;;
+;;; All Rights Reserved. ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;;
+;;; ;;;
+;;; Author: Nicholas Volk ;;;
+;;; e-mail: nvolk@ling.helsinki.fi ;;;
+;;; address: Department of General Linguistics ;;;
+;;; PL 9 (Siltavuorenpenger 20A) ;;;
+;;; 00014 University of Helsinki ;;;
+;;; FINLAND ;;;
+;;; ;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Finnish LTS-rules, which fake the lexicon
+;;; (somewhat similar to the Festival Spanish)
+;;;
+;;; This file contains the LTS rules for Finnish.
+;;; The LTS rules also syllabify and mark the stressed syllables
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+
+(require 'finnish_lex) ;; POS (content vs. function) information is in lex
+
+
+(define (finnish_lts word)
+ "(finnish_lts WORD)
+Creates the lexical entry for the given WORD."
+ (if hy_debug (format stderr "Creating the lexical entry for %s.\n" word))
+
+ ;; in suopuhe-mode:
+ ;; reverse the stacks, if that has not been done yet...
+ (if (and suopuhe
+ (not pos_reversed))
+ (begin
+ (set! suopuhe_accent_stack (reverse suopuhe_accent_stack))
+ (set! suopuhe_pos_stack (reverse suopuhe_pos_stack))
+ (set! pos_reversed t)))
+
+
+ ;; check the string
+ ;; if there are unknown characters, replace them with "tuntematonmerkki"
+ ;; ("unknowncharacter")
+ (set! word
+ (let ((new "")
+ (state 0) ;; 0: initial state 1: prev is ordinary 2: unknown prev
+ char)
+ (while (> (string-length word) 0)
+ (begin
+ (set! char (substring word 0 1))
+ (set! word (substring word 1 (- (string-length word) 1)))
+ (cond
+ ;; ad hoc: LTS can't replace right bracket \] "]"
+ ((string-equal "\]" char)
+ (set! new
+ (string-append
+ (if new new "")
+ (if (> state 0) "-" "")
+ "oikeahakasulku"))
+ (set! state 2))
+ ((string-matches char "^[ a-zA-Z0-9\"\'\`\$%&\(\)\*\+\-~_\^/\\\?\}\{\@\.:!àáâãäöæçèéêëìíîïðñòóôõöøùúûüýþÀÁÂÃÄÅÆÇÐÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝÞ]$" )
+ (set! new
+ (string-append
+ (if new new "")
+ (if (= state 2) "-" "")
+ char))
+ (set! state 1))
+ (t
+ (set! new
+ (string-append
+ (if new new "")
+ (if (> state 0) "-" "")
+ "tuntematonmerkki"))
+ (set! state 2)))))
+ new))
+
+
+ (cond
+ ;; suopuhe mode gets hopefully the pos from a stack
+ (suopuhe
+ (let ((pos (pop_pos))
+ (acc (pop_accent)))
+ (set! pos (if (string-equal "unknown" pos)
+ (cond
+ ((word_list_entry? word finnish_guess_coord)
+ "COORD")
+ ((word_list_entry? word finnish_guess_cop)
+ "COP")
+ ((word_list_entry? word finnish_guess_pron)
+ "PRON")
+ ((word_list_entry? word finnish_guess_pos)
+ "function")
+ (t
+ "content"))))
+ ;; anyway... if word is defined as accentless we change
+ ;; the POS in the lexical entry to FUNCTION overriding the
+ ;; defined POS!
+ ;; accented words get POS CONTENT on the same basis...
+ (if (string-equal acc "no")
+ (set! pos "function")
+ (if (string-equal acc "yes")
+ (set! pos "content")))
+
+ (let ((x (list word (pop_pos) (compound_stress word))))
+ x)))
+ ;; non-suopuhe mode
+ ((word_list_entry? word finnish_guess_coord)
+ (list word "COORD" (compound_stress word)))
+ ((word_list_entry? word finnish_guess_cop)
+ (list word "COP" (compound_stress word)))
+ ((word_list_entry? word finnish_guess_pron)
+ (list word "PRON" (compound_stress word)))
+ ((word_list_entry? word finnish_guess_pos)
+ (list word "function" (compound_stress word)))
+ (t
+ (list word "content" (compound_stress word)))))
+
+(define (finnish_token_to_words token name)
+ "(finnish_token_to_words token name)
+A few simple ad hoc solutions for the most common simple T2W-problems.
+It was much nicer to use an external Perl text normalizer than scheme."
+ (cond
+ ;; NAN: begins with a 0, thsus sequence of digit
+ ((string-matches name "^0[0-9]*$")
+ (symbolexplode name))
+ ;; hundereds of millions are read as digits
+ ((string-matches name "^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]+$")
+ (symbolexplode name))
+ ;; ordinary number (no inflections in scheme, use perl)
+ ((string-matches name "^[1-9][0-9]*$")
+ (list (finnish_number name)))
+ ;; Too many initial consonants
+ ((string-matches name "^[BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz][BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz][BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz][BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz].*$")
+ (symbolexplode name))
+ ;; separate consonant sequence from each other : "KGB" => "K G B"
+ ((string-matches name "^\\(.*\-\\)?[BCDFGHJKLMNPQRSTVWXZbcdfghjklmnpqrstvwxz]+\\(\-.*\\)?$")
+ (symbolexplode name))
+ ;; do nothing
+ (t
+ (list name))))
+
+(define (finnish_number int)
+ "(finnish_number INT)
+Converts the INT into a corresponding string.
+Very simple. Does not handle cases."
+ (remove_head_and_tail_spaces (make_number int)))
+
+(define (remove_head_and_tail_spaces text)
+ "(remove_head_and_tail_spaces string)
+Removes unspoken space sequences from the beginning and end of a give string."
+ (if (not (string-equal (typeof text) "string"))
+ (begin
+ (set! text "The input was not a string!")))
+
+ ;; remove the initial whitespaces
+ (while (and (> (string-length text) 0)
+ (string-matches (substring text 0 1) "^[ \t\n\015]$"))
+ ;; \015 = CTRL-M = carriage return
+ (set! text (substring text 1 (- (string-length text) 1))))
+ ;; remove the final whitespaces
+ (while (and (> (string-length text) 0)
+ (string-matches
+ (substring text (- (string-length text) 1) 1)
+ "^[ \t\n\015]$"))
+ (set! text (substring text 0 (- (string-length text) 1))))
+ text)
+
+
+(define (make_number int)
+ "(make_number INT)
+Splits numbers into 3-letter chunks, which are converted into a number.
+Also adds an appropriate quantifier (like thousands) to each triplet,
+thus producing any int between 1 - 999999999."
+ (let (head)
+ (cond
+ ((> (string-length int) 6)
+ (set! head (substring int 0 (- (string-length int) 6)))
+ (set! int (substring int (string-length head) 6))
+ (if (string-equal head "1")
+ (string-append
+ "miljoona "
+ (make_number int))
+ (string-append
+ (make_number2 head)
+ "miljoonaa "
+ (make_number int))))
+ ((> (string-length int) 3)
+ (set! head (substring int 0 (- (string-length int) 3)))
+ (set! int (substring int (string-length head) 3))
+ (cond
+ ((string-equal head "000")
+ (make_number int))
+ ((or (string-equal head "1")
+ (string-equal head "001"))
+ (string-append
+ "tuhat "
+ (make_number int)))
+ (t
+ (string-append
+ (make_number2 head)
+ "tuhatta "
+ (make_number int)))))
+ (t
+ (make_number2 int)))))
+
+(define (make_number2 int)
+ "(make_number2 INT)
+Converts an up-to-three digit sequence into a number."
+
+ (let (ones dozens hundreds output)
+ (cond
+ ((= (string-length int) 3)
+ (set! hundreds (substring int 0 1))
+ (set! dozens (substring int 1 1))
+ (set! ones (substring int 2 1)))
+ ((= (string-length int) 2)
+ (set! hundreds "0")
+ (set! dozens (substring int 0 1))
+ (set! ones (substring int 1 1)))
+ (t
+ (set! hundreds "0")
+ (set! dozens "0")
+ (set! ones (substring int 0 1))))
+ ;; HUNDREDS
+ (cond
+ ((string-equal hundreds "0")
+ (set! output ""))
+ ((string-equal hundreds "1")
+ (set! output "sata"))
+ (t
+ (set! output (string-append (number_list hundreds) "sataa"))))
+ ;; DOZENS & ONES
+ (cond
+ ((string-equal dozens "0")
+ (set! output (string-append output (number_list ones))))
+ ((string-equal dozens "1")
+ (if (string-equal ones "0")
+ (set! output (string-append output "kymmenen"))
+ (set! output (string-append output (number_list ones) "toista"))))
+ (t
+ (set! output (string-append output
+ (number_list dozens) "kymmentä"
+ (number_list ones)))))
+ output))
+
+
+
+(define (number_list digit)
+ "(number_list DIGIT)
+Returns the corresponding string for a given DIGIT"
+ (cond
+ ((string-equal digit "9") "yhdeksän")
+ ((string-equal digit "8") "kahdeksan")
+ ((string-equal digit "7") "seitsemän")
+ ((string-equal digit "6") "kuusi")
+ ((string-equal digit "5") "viisi")
+ ((string-equal digit "4") "neljä")
+ ((string-equal digit "3") "kolme")
+ ((string-equal digit "2") "kaksi")
+ ((string-equal digit "1") "yksi")
+ (t
+ "")))
+
+
+(define (finnish_tosyl_brackets phones accent)
+ "(finnish_tosyl_brackets phones)
+Takes a list of phones containing - as syllable boundary.
+Should we add a compound boundary? Probably...
+Construct the Festival bracket structure.
+Used by finnish_lts-function."
+ (let ((tavu nil) (syls nil) (p phones) (stress 0) (syltotal 1)
+ (cvcvcvcv nil)
+ (which 1) (secondary_stress 0))
+ ;; lasketaan tavujen määrä
+ (while p
+ (if (eq? '- (car p))
+ (begin
+ (set! tavu (reverse tavu))
+ ;; if the 3rd syllable has 1 "mora"
+ ;; the secondary stress goes to the 4th syllable
+ (if (and (= syltotal 3)
+ (= (mora2 tavu) 1)
+ (or (string-matches (cadr p)
+ "^[abdefghijklmnoprstuvy@7NT]$")
+ (string-matches (cadr p) "^[aeiouy@7]:?$" )))
+ ;; had but 1 mora
+ (begin
+ ;; cvcvcvcv takes care of 4-syl words
+ ;; with a short 3rd syl
+ (set! cvcvcvcv t)
+ (set! secondary_stress 4)))
+ (if (and (= secondary_stress 4)
+ (= syltotal 4)
+ (= (mora2 tavu) 1)
+ (or (string-matches ;; short
+ (cadr p)
+ "^[abdefghijklmnoprstuvy@7NT]$" )
+ (string-matches (cadr p) "^[aeiouy@7]:?$" )))
+ (set! secondary_stress 3))
+
+
+
+ (set! syltotal (+ syltotal 1)) ;; N:s tavu alkaa
+
+ (set! tavu nil))
+ ;; muuten lisää tavu
+ (set! tavu (cons (car p) tavu)))
+ (set! p (cdr p)))
+
+
+ (set! p phones)
+ (if (and (> syltotal 3) ;; secondary_stress is possible
+ (> accent 0)) ;; the word is stressed
+ ;; ON SECONDARY_STRESS
+ (begin
+ ;; 4-tavuinen, jossa 3:s oli lyhyt omaa väärän arvon, korjataan:
+ (if (and (= syltotal 4)
+ cvcvcvcv)
+ (set! secondary_stress 3))
+ ;; tarpeeksi pitkä secondary_stresslliselle, mutta secondary_stress ei päällä:
+ (if (= secondary_stress 0)
+ (set! secondary_stress 3)));; nyt aina kolmannelle tavulle
+ (set! secondary_stress 0))
+
+ (set! which 1)
+ (while p
+ (set! tavu nil)
+ (set! stress accent)
+ ;; asetetaan secondary_stress, jos on tarvis
+
+ (if (and (= which secondary_stress)
+ (> syltotal secondary_stress))
+ (begin
+ (set! secondary_stress (+ secondary_stress 2))
+ (set! stress 1)))
+
+ (while (and p
+ (not (eq? '- (car p))))
+ ;;;(set! name (list2string (cons (car p) syl)))
+ (set! tavu (cons (car p) tavu))
+ ;;;(item.set_name syl name)
+ (set! p (cdr p)))
+ (set! which (+ which 1))
+ (set! p (cdr p)) ;; hyppää '-':n yli
+ (set! accent 0) ;; jälkitavuille
+ (set! syls (cons (list (reverse tavu) stress) syls)))
+ (reverse syls)))
+
+(define (mora2 list_of_phones)
+"(mora2 list_of_phones)
+Counts the moras (morae?) in a given list of phones.
+Does not support ambisyllabic long consonants."
+(let ((onset t)
+ (total 0)
+ phone)
+
+ (while list_of_phones
+ (set! phone (car list_of_phones))
+ ;; as long as we get Cs we're in the onset
+ (if (not (and onset
+ (string-matches phone "^[bdfghjklmnprstvNT]:?$" )))
+ (begin
+ (set! onset nil)
+ (if (string-matches phone "^[abdefghijklmnoprstuvy@7NT]:$" )
+ (set! total (+ total 2)) ;; long
+ (set! total (+ total 1))))) ;; short
+ (set! list_of_phones (cdr list_of_phones)))
+ total))
+
+
+
+(define (compound_stress compound)
+ "(compound_stress WORD)
+Handles the exception stress placement in compounds.
+The few compounds supported are recognized by the '-' separator.
+However secondary word stress did not show up in duration and intonation
+models... We could also add boundary detection based on vowel positions
+in neighboring syllables."
+
+ (let ((suitable (string-matches compound "^\\([A-ZÅÄÖa-zåäö][A-ZÅÄÖa-zåäö]+\-\\)+[A-ZÅÄÖa-zåäö][A-ZÅÄÖa-zåäö]+$"))
+ (word1 "")
+ (word2 nil)) ;; word2 will be a list
+ (if (not suitable) (set! word1 compound))
+ (while (and (> (string-length compound) 0)
+ suitable)
+ ;; compound marker has been found yet
+ (if (string-equal (substring compound 0 1) "-")
+ (begin
+ ;; behead the compound
+ (if (= (string-length compound) 1)
+ (set! compound "")
+ (set! compound (substring compound 1 (- (string-length compound) 1))))
+ (if (not (string-equal word1 ""))
+ (set! word2
+ (append word2 (finnish_tosyl_brackets
+ (lts.apply
+ (lts.apply
+ (lts.apply word1 'normalize)
+ 'finnish_cv)
+ 'remove_unneeded) 2))))
+
+ (set! word1 ""))
+ ;; else
+ (begin
+ (set! word1 (string-append word1 (substring compound 0 1)))
+ (if (= (string-length compound) 1)
+ (set! compound "")
+ (set! compound (substring compound 1 (- (string-length compound) 1))))))) ;; end of while
+
+ (if word2
+ (set! word2 (append word2
+ (finnish_tosyl_brackets
+ (lts.apply
+ (lts.apply
+ (lts.apply word1 'normalize)
+ 'finnish_cv)
+ 'remove_unneeded) 2)))
+ (set! word2 (finnish_tosyl_brackets
+ (lts.apply
+ (lts.apply
+ (lts.apply word1 'normalize)
+ 'finnish_cv)
+ 'remove_unneeded) 2)))
+ word2))
+
+;;;=======================================================================
+
+(lts.ruleset
+ normalize
+ ; sets
+ ( ( NUMERO 0 1 2 3 4 5 6 7 8 9 )
+ ( POIS "\"" "\'" "\`" )
+
+ ( CON b c d f g h j k l m n p q r s t v w x z
+ B C D F G H J K L M N P Q R S T V W X Z)
+ ( VOW a e i o u y ä ö
+ A E I O U Y Ä Ö)
+ ( LET A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Å Ä Ö
+ a b c d e f g h i j k l m n o p q r s t u v w x y z å ä ö )
+ )
+;
+; ;rules
+ (
+
+ ;; a lone "
+ ( # [ "\"" ] # = l a i n a u s m e r k k i )
+ ( # [ POIS ] # = h e i t t o m e r k k i )
+ ; seuraavat pois:
+ ( [ POIS ] = )
+ ( [ " " ] = ) ;; tokenisoija ei vielä jaa merkkijonoa wordlistaksi...
+
+ ( [ 1 ] = y k s i )
+ ( [ 2 ] = k a k s i )
+ ( [ 3 ] = k o l m e )
+ ( [ 4 ] = n e l j @ )
+ ( [ 5 ] = v i i s i )
+ ( [ 6 ] = k u u s i )
+ ( [ 7 ] = s e i t s e m @ n )
+ ( [ 8 ] = k a h d e k s a n )
+ ( [ 9 ] = y h d e k s @ n )
+ ( [ 0 ] = n o l l a )
+
+ ( [ "#" ] = r i s u a i t a )
+ ( [ "$" ] = d o l l a r i )
+ ( [ "%" ] = p r o s e n t t i )
+ ( [ "&" ] = e t )
+
+ ;; should these be spoken (SayText "(word)")
+ ( [ "(" ] = v a s e n s u l k u )
+ ( [ ")" ] = o i k e a s u l k u )
+
+ ( [ * ] = a s t e r i s k i )
+ ( [ + ] = p l u s )
+ ;( [ "\/" = j a k o v i i v a )
+
+
+ ( # [ - ] # = v i i v a )
+ ( LET [ - ] LET = ) ;; morphemeboundary
+ ( LET [ - ] # = ) ;; word- => word
+ ( # [ - ] LET = ) ;; -word => word
+ ( [ - ] NUMERO = m i i n u s - )
+
+;; ( # [ - ] = )
+;; ( [ " " - " " ] = )
+;; ( " " [ - ] = )
+;; ( [ - ] # = )
+;; ( [ - ] " " = )
+
+ ( [ - ] = v i i v a )
+
+ ( [ "~" ] = a a l t o v i i v a )
+ ( [ _ ] = a l a v i i v a )
+ ( [ "^" ] = h a t t u )
+ ( [ "!" ] = h u u t o m e r k k i )
+ ( [ "/" ] = k a u t t a )
+ ( [ "\\" ] = k e n o v i i v a ) ;; kenoviiva kannattaa laventaa etukäteen..
+ ( [ "?" ] = k y s y m y s m e r k k i )
+ ( [ \] ] = o i k e a h a k a s u l k u ) ;; finnish_lts ongelma
+ ( [ "}" ] = o i k e a k a a r i s u l k u )
+ ( [ "=" ] = o n y h t a k u i n )
+ ( [ "<" ] = p i e n e m p i k u i n )
+ ( [ "," ] = p i l k k u )
+ ( [ "£" ] = p u n t a )
+ ( [ ";" ] = p u o l i p i s t e )
+ ( [ "|" ] = p y s t y v i i v a )
+ ( [ ">" ] = s u u r e m p i k u i n )
+ ( [ "[" ] = v a s e n h a k a s u l k u ) ;; finnish_lts ongelma
+ ( [ "{" ] = v a s e n k a a r i s u l k u ) ;; "{}" toimii oudosti...
+ ( [ "@" ] = @ t )
+
+ ( [ "." ] = p i s t e ) ;; token2words temppuilee
+ ( [ ":" ] i n # = )
+ ( [ ":" ] = k a k s o i s p i s t e )
+ ( [ " " ] = " " ) ;; separeted chars use this
+
+
+
+ ; # SH-äänne
+ ( [ s c h ] = S ) ; schubert
+ ( [ S c h ] = S )
+ ( t [ s h ] = s ) ; tshetsheeni
+ ( T [ s h ] = s )
+ ( [ s h ] CON = S ) ; pushkin
+ ( [ S h ] = S )
+ ( VOW VOW [ s h ] = s h ) ; talOUSHallinto
+ ( [ s h ] y = s h ) ;
+ ( [ s h ] ä = s h ) ; mieshän
+ ( [ s h ] ö = s h ) ; ykköshörhö
+ ( i l a [ s h ] = s h ) ; sotilashenkilö
+ ( l l i [ s h ] = s h ) ; paikallishallinto
+ ( s k u [ s h ] = s h ) ; keskushallinto
+ ( n n u [ s h ] = s h ) ;
+ ( t u [ s h ] = s h ) ; opetushallitus
+ ( y [ s h ] = s h ) ; yrityshautomo
+ ( ä [ s h ] = s h ) ; seiväshyppy
+ ( ö [ s h ] = s h ) ; ykköshenkilö
+ ( # [ s h ] = S ) ; shakki
+ ( [ s h ] # = S ) ; bush
+ ( e i [ s h ] = s h ) ; yhteishenki
+ ( [ s h ] i # = S ) ; takeshi
+ ( w a [ s h ] i n g t = S S ) ; washington
+ ( [ s h ] o w = S )
+ ( m u [ s h ] = S ) ; kokoomushan
+ ( i h m i [ s h ] = s h ) ; ihmishenki
+ ( [ s h ] = S )
+
+;; ( [ a h l ] = a a l )
+ ( [ t z ] = t s )
+
+
+
+
+ ( [ à ] = a ) ( [ À ] = a )
+ ( [ á ] = a ) ( [ Á ] = a )
+ ( [ â ] = a ) ( [ "Â" ] = a )
+ ( [ ã ] = a ) ( [ Ã ] = a )
+ ( [ æ ] = @ ) ( [ Æ ] = @ )
+ ( [ ç ] = s ) ( [ Ç ] = s )
+ ( [ ð ] = t h ) ( [ Ð ] = t h )
+ ( [ è ] = e ) ( [ È ] = e )
+ ( [ é ] = e ) ( [ É ] = e )
+ ( [ ê ] = e ) ( [ Ê ] = e )
+ ( [ ë ] = e ) ( [ Ë ] = e )
+ ( [ ì ] = i ) ( [ Ì ] = i )
+ ( [ í ] = i ) ( [ Í ] = i )
+ ( [ ï ] = i ) ( [ Ï ] = i )
+ ( [ î ] = i ) ( [ Î ] = i )
+ ( [ ñ ] = n j ) ( [ Ñ ] = n j )
+ ( [ ø ] = 7 ) ( [ Ø ] = 7 )
+ ( [ ò ] = o ) ( [ Ò ] = o )
+ ( [ ó ] = o ) ( [ ó ] = o )
+ ( [ ô ] = o ) ( [ Ô ] = o )
+ ( [ õ ] = o ) ( [ Õ ] = o )
+ ( [ ß ] = s s )
+ ( [ þ ] = t h ) ( [ Þ ] = t h )
+ ( [ ù ] = u ) ( [ Ù ] = u )
+ ( [ ú ] = u ) ( [ Ù ] = u )
+ ( [ û ] = u ) ( [ Û ] = u )
+ ( [ ü ] = y ) ( [ Ü ] = y )
+ ( [ ý ] = y ) ( [ Ý ] = y )
+ ( [ ÿ ] = y )
+
+ ; "lowercase"
+ ( [ a ] = a ) ( [ b ] = b )
+ ( [ A ] = a ) ( [ B ] = b )
+
+ ( [ c ] = c )
+ ( [ C ] = c )
+
+ ( [ d ] = d ) ( [ e ] = e )
+ ( [ D ] = d ) ( [ E ] = e )
+ ( [ f ] = f ) ( [ g ] = g ) ( [ h ] = h ) ( [ i ] = i ) ( [ j ] = j )
+ ( [ F ] = f ) ( [ G ] = g ) ( [ H ] = h ) ( [ I ] = i ) ( [ J ] = j )
+
+ ( [ K ] = k ) ( [ L ] = l ) ( [ M ] = m )
+ ( [ N ] = n )
+ ( [ k ] = k ) ( [ l ] = l ) ( [ m ] = m )
+
+ ( [ n ] = n )
+
+ ( [ O ] = o ) ( [ P ] = p ) ( [ Q ] = q ) ( [ R ] = r ) ( [ S ] = s )
+ ( [ o ] = o ) ( [ p ] = p ) ( [ q ] = q ) ( [ r ] = r ) ( [ s ] = s )
+ ( [ T ] = t ) ( [ U ] = u ) ( [ V ] = v ) ( [ W ] = w ) ( [ X ] = x )
+ ( [ t ] = t ) ( [ u ] = u ) ( [ v ] = v ) ( [ w ] = w ) ( [ x ] = x )
+ ( [ Y ] = y ) ( [ Z ] = z ) ( [ Å ] = å ) ( [ Ä ] = @ ) ( [ Ö ] = 7 )
+ ( [ y ] = y ) ( [ z ] = z ) ( [ å ] = å ) ( [ ä ] = @ ) ( [ ö ] = 7 )
+
+ ))
+
+(lts.ruleset
+ finnish_cv
+ ; sets
+ (( LAITONA e o y @ 7 )
+ ( LAITONEI a o y @ 7 )
+ ( LAITONOU a e y @ 7 )
+ ( LAITONY7 a e o u @ )
+ ( LAITON@ a e u o 7 )
+ ( VOW a e i o u y @ 7 ö å )
+ ( CON b c d f g h j k l m n p q r s t v w x z )
+ )
+ ;rules
+ (
+; ( # [ s h ] = __ S )
+; ( # [ s c h ] = __ S )
+ ( # [ t h ] = __ T )
+ ( [ t h ] # = __ T ) ;; cheat
+ ( [ t h ] CON = __ T )
+
+ ( [ a - a ] = _ a - a )
+ ( [ e - e ] = _ e - e )
+ ( [ i - i ] = _ i - i )
+ ( [ o - o ] = _ o - o )
+ ( [ u - u ] = _ u - u )
+ ( [ y - i ] = _ y - y )
+ ( [ @ - @ ] = _ @ - @ )
+ ( [ 7 - 7 ] = _ 7 - 7 )
+
+
+ ( [ a ] LAITONA = _ a - )
+ ;; ( [ e ] a # = _ e )
+ ( [ e ] LAITONEI = _ e - )
+ ;; ( [ i ] a # = _ i )
+ ( [ i ] LAITONEI = _ i - )
+ ;;( [ o ] a # = _ o )
+ ( [ o ] LAITONOU = _ o - )
+ ( [ u ] LAITONOU = _ u - )
+ ( [ y ] LAITONY7 = _ y - )
+ ;; ( [ 7 ] ä # _ 7 )
+ ( [ 7 ] LAITONY7 = _ 7 - )
+ ( [ @ ] LAITON@ = _ @ - )
+
+ ;; some assimilations
+ ( VOW [ n m ] VOW = __ m: )
+ ( VOW [ n ] p VOW = m )
+ ( [ n g ] VOW = __ N: )
+ ( [ n g ] = __ N )
+ ( [ n ] k = __ N )
+
+
+
+ ( [ a a ] = _ a: )
+ ( [ b b ] = "__" b: )
+ ( [ c c ] = "__" k: ) ( [ c k ] = k: )
+ ( [ d d ] = "__" d: )
+ ( [ e e ] = _ e: )
+ ( [ f f ] = "__" f: )
+ ( [ g g ] = "__" g: )
+ ( [ h h ] = "__" h: )
+ ( [ i i ] = _ i: )
+ ( [ j j ] = "__" j: )
+ ( [ k k ] = "__" k: )
+ ( [ l l ] = "__" l: )
+ ( [ m m ] = "__" m: )
+ ( [ n n ] = "__" n: )
+ ( [ o o ] = _ o: )
+ ( [ p p ] = "__" p: )
+ ( [ r r ] = "__" r: )
+ ( [ s s ] = "__" s: )
+ ( [ S S ] = "__" S: )
+ ( [ t t ] = "__" t: )
+ ( [ u u ] = _ u: )
+ ( [ v v ] = "__" v: )
+ ( [ y y ] = _ y: )
+ ( [ @ @ ] = _ @: )
+ ( [ 7 7 ] = _ 7: )
+
+ ( [ a ] = _ a )
+ ( [ b ] = __ b )
+ ( [ c ] e = __ s )
+ ( [ c ] = __ k )
+ ( [ d ] = __ d )
+ ( [ e ] = _ e )
+ ( [ f ] = __ f )
+ ( [ g ] = __ g )
+ ( [ h ] = __ h )
+
+ ( [ i ] = _ i )
+ ( [ j ] = __ j )
+ ( [ k ] = __ k )
+ ( [ l ] = __ l )
+ ( [ m ] = __ m )
+ ( [ n ] = __ n )
+ ( [ o ] = _ o )
+ ( [ p ] = __ p )
+ ( # [ q u ] = k v )
+ ( [ q u ] = - k v )
+ ( # [ q ] = k v )
+ ( [ q ] = - k v ) ; frek-venssi
+ ( [ r ] = __ r )
+ ( [ s ] = __ s )
+ ( [ t ] = __ t )
+ ( [ u ] = _ u )
+ ( [ v ] = __ v )
+ ( [ w ] = __ v )
+ ( [ x ] = __ k __ s ) ; tak-si
+ ( [ y ] = _ y )
+ ( # [ z ] = t s )
+ ( [ z ] = - t s )
+ ( [ å ] = _ o )
+ ( [ @ ] = _ @ )
+ ( [ 7 ] = _ 7 )
+ ( [ - ] = - )
+ ( [ L ] = __ L ) ;; this is our light /l/
+ ( [ S ] = __ S ) ;; this is our palatal /s/
+ ( [ " "+ ] = " " )
+))
+
+(lts.ruleset remove_unneeded
+ ( ; sets
+ ( CON b d f g h j k l m n p r s t v N T S L
+ b: d: f: g: h: j: k: l: m: n: p: r: s: t: v: N: T: S: L:)
+ ( VOW a e i o u y @ 7 a: e: i: o: u: y: @: 7: )
+ ( LONG a: e: i: o: u: y: @: 7: )
+ ( EOS # " " )
+ )
+ ( ; rules
+ ( [ - _ ] = - )
+ ( [ - __ ] = - )
+
+ ( EOS __ CON __ CON __ CON [ __ ] = )
+ ( EOS __ CON __ CON [ __ ] = )
+ ( EOS __ CON [ __ ] = )
+ ( EOS [ __ ] = )
+ ( [ __ ] CON _ VOW = - )
+ ( [ __ ] = )
+
+ ( EOS [ _ ] = )
+ ( CON [ _ ] = )
+ ( - [ _ ] = )
+ ( LONG [ _ ] = - )
+ ( [ _ a _ ] = a - )
+ ( [ _ e _ ] = e - )
+ ( [ _ i _ ] = i - )
+ ( [ _ o _ ] = o - )
+ ( [ _ u _ ] = u - )
+ ( [ _ y _ ] = y - )
+ ( [ _ @ _ ] = @ - )
+ ( [ _ 7 _ ] = 7 - )
+ ( [ _ ] = )
+
+ ( [ a: ] = a: )
+ ( [ b: ] __ CON = b ) ( [ b: ] # = b ) ( # __ [ b: ] = b ) ( [ b: ] = b: )
+ ( [ d: ] __ CON = d ) ( [ d: ] # = d ) ( # __ [ d: ] = d ) ( [ d: ] = d: )
+ ( [ e: ] = e: )
+ ( [ f: ] __ CON = f ) ( [ f: ] # = f ) ( # __ [ f: ] = f ) ( [ f: ] = f: )
+ ( [ g: ] __ CON = g ) ( [ g: ] # = g ) ( # __ [ g: ] = g ) ( [ g: ] = g: )
+ ( [ h: ] __ CON = h ) ( [ h: ] # = h ) ( # __ [ h: ] = h ) ( [ h: ] = h: )
+ ( [ i: ] = i: )
+ ( [ j: ] __ CON = j ) ( [ j: ] # = j ) ( # __ [ j: ] = j ) ( [ j: ] = j: )
+ ( [ k: ] __ CON = k ) ( [ k: ] # = k ) ( # __ [ k: ] = k ) ( [ k: ] = k: )
+ ( [ l: ] __ CON = l ) ( [ l: ] # = l ) ( # __ [ l: ] = l ) ( [ l: ] = l: )
+ ( [ m: ] __ CON = m ) ( [ m: ] # = m ) ( # __ [ m: ] = m ) ( [ m: ] = m: )
+ ( [ n: ] __ CON = n ) ( [ n: ] # = n ) ( # __ [ n: ] = n ) ( [ n: ] = n: )
+ ( [ N: ] __ CON = N ) ( [ N: ] # = N ) ( # __ [ N: ] = N ) ( [ N: ] = N: )
+ ( [ o: ] = o: )
+ ( [ p: ] __ CON = p ) ( [ p: ] # = p ) ( # __ [ p: ] = p ) ( [ p: ] = p: )
+ ( [ r: ] __ CON = r ) ( [ r: ] # = r ) ( # __ [ r: ] = r ) ( [ r: ] = r: )
+ ( [ s: ] __ CON = s ) ( [ s: ] # = s ) ( # __ [ s: ] = s ) ( [ s: ] = s: )
+ ( [ t: ] __ CON = t ) ( [ t: ] # = t ) ( # __ [ t: ] = t ) ( [ t: ] = t: )
+ ( [ u: ] = u: )
+ ( [ v: ] __ CON = v ) ( [ v: ] # = v ) ( # __ [ v: ] = v ) ( [ v: ] = v: )
+ ( [ y: ] = y: )
+ ( [ @: ] = @: )
+ ( [ 7: ] = 7: )
+ ( [ L: ] __ CON = L ) ( [ L: ] # = L ) ( # __ [ L: ] = L ) ( [ L: ] = L: ) ;; our light /l/
+ ( [ S: ] __ CON = S ) ( [ S: ] # = S ) ( # __ [ S: ] = S ) ( [ S: ] = S: ) ;; our palatal /s/
+ ( [ T: ] __ CON = T ) ( [ T: ] # = T ) ( # __ [ T: ] = T ) ( [ T: ] = T: )
+ ( [ D: ] __ CON = D ) ( [ D: ] # = D ) ( # __ [ D: ] = D ) ( [ D: ] = D: )
+
+ ;;; short (these are the original rules)
+ ( [ a ] = a ) ( [ b ] = b ) ( [ d ] = d ) ( [ e ] = e )
+ ( [ f ] = f ) ( [ g ] = g ) ( [ h ] = h ) ( [ i ] = i ) ( [ j ] = j )
+ ( [ k ] = k ) ( [ l ] = l ) ( [ m ] = m ) ( [ n ] = n ) ( [ o ] = o )
+ ( [ p ] = p ) ( [ q ] = q ) ( [ r ] = r ) ( [ s ] = s ) ( [ t ] = t )
+ ( [ u ] = u ) ( [ v ] = v ) ( [ y ] = y )
+ ( [ @ ] = @ ) ( [ ö ] = ö ) ( [ 7 ] = 7 ) ( [ z ] = z )
+ ( [ - ] = - )
+ ( [ L ] = L ) ;; this is our light /l/
+ ( [ S ] = S ) ;; this is our palatal /s/
+ ( [ T ] = T )
+ ( [ D ] = D )
+ ( [ N ] = N )
+ ( [ _ ] = _ ) ( [ __ ] = __ )
+ ( [ " " ] = "" ) ;; cheat for LSEQs
+ ))
+
+
+(provide 'finnish_lts)
+
+
+
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_mv_int.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_mv_int.scm
new file mode 100644
index 0000000..fb1572c
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_mv_int.scm
@@ -0,0 +1,506 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Department of General Linguistics / Suopuhe project ;;
+;;; University of Helsinki, FI ;;
+;;; Copyright (c) 2000,2001,2002,2003 ;;
+;;; All Rights Reserved. ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;
+;;; Authors: ;
+;;; ;
+;;; Martti Vainio ;
+;;; e-mail: martti.vainio@helsinki.fi ;
+;;; address: Department of General Linguistics ;
+;;; PL 9 (Siltavuorenpenger 20A) ;
+;;; 00014 University of Helsinki ;
+;;; FINLAND ;
+;;; ;
+;;; Nicholas Volk ;
+;;; e-mail: nvolk@ling.helsinki.fi ;
+;;; address: Department of General Linguistics ;
+;;; PL 9 (Siltavuorenpenger 20A) ;
+;;; 00014 University of Helsinki ;
+;;; FINLAND ;
+;;; ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Accent and F0 prediction
+;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Intonation
+
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+
+;;; (SayText "sanoisin että en sano" )
+(define (monotone utt syl)
+ "(monotone UTT SYL)
+Monotonous intonation model."
+ (let ((middle (/ (+ (item.feat syl 'syllable_start) (item.feat syl 'syllable_end)) 2)))
+ (list (list middle 100))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; Intonation
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(set! finnish_accent_cart_tree
+ '((stress is 2)
+ ((R:SylStructure.parent.pos is function)
+ ((NONE))
+ ((R:SylStructure.parent.pos is COP)
+ ((NONE))
+ ((R:SylStructure.parent.pos is PRON)
+ ((NONE))
+ ((R:SylStructure.parent.pos is COORD)
+ ((NONE))
+
+ ((Accented))))))
+ ((NONE))))
+
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Fujisaki model
+;;
+
+; The model and algorith is as follows:
+;-----------------------------------------------------------------------
+; Variables:
+; ...
+; points = once in very 50 ms (points where (time_in_seconds * 1000 % 50 == 0)
+; but atleast once in each syllable
+; alpha = defined in voice_WHATEVER
+; beta = defined in voice_WHATEVER
+; f_min = defined in voice_WHATEVER
+;-----------------------------------------------------------------------
+; Algorithm:
+; for each utterance
+; accent_levels = predict accent levels
+; accent_types = predict accent type
+; accent_list = calculate_accent_commands(accent_levels, accent_types)
+; phrase_list = calculate_phrase_commands(utterance, pharases)
+; syllables = syllables(utterance)
+; calculate fujisaki_contour(segments, phrase_list, accent_list)
+;
+; fujisaki_contour:
+; for syllable in syllables:
+; for point in points:
+; ph_level = calculate_phrase_level(point, phrase_list, alpha)
+; ac_level = calculate_accent_level(point, accent_list, beta)
+; f0 = exp(ph_level + ac_level + f_min)
+
+;; global parameters for the Fujisaki model
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; we should use the Parameter.set etc. methods:
+
+
+;; Some auxiliary functions, which should be somewhere else
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; this is not called anywhere?
+;;(define (incf var val)
+;; (+ var val))
+
+(define (sqr number)
+ "(sqr NUM)
+NUM ** 2."
+ (* number number))
+
+(define (neg number)
+ "(neg number)
+Negates a number -- Festival SIOD doesn't understand (- number), but
+requires TWO arguments to the '-' operator"
+ (* -1 number))
+
+
+(define (min num1 num2)
+ "(min num1 num2)
+Returns the smaller of the two."
+ (cond ((<= num1 num2)
+ num1)
+ (t num2)))
+
+(define (max num1 num2)
+ "(max num1 num2)
+Returns the greater of the two."
+ (cond ((<= num1 num2)
+ num2)
+ (t num1)))
+
+
+(define (accented_p syl)
+ "(accented_p SYL)
+Sees if the syllable is accented..."
+ (cond
+ ((not (equal? (item.feat syl "R:Intonation.daughter1.name") "Accented"))
+ nil)
+ ((string-equal (item.feat syl 'R:SylStructure.parent.pos) "function")
+ nil)
+ ((string-equal (item.feat syl 'R:SylStructure.parent.pos) "COP")
+ nil)
+ ((string-equal (item.feat syl 'R:SylStructure.parent.pos) "PRON")
+ nil)
+ (t
+ t)))
+;
+;
+; (and (string-equal (item.feat syl 'R:SylStructure.parent.pos) "content")
+; ;; eka tavu
+; (equal? (item.feat syl "R:Intonation.daughter1.name") "Accented")))
+
+
+;; Accent and Phrase parameter prediction
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define (get_accent_list utt)
+ "(get_accent_list UTT)"
+ (let ((syllables (utt.relation.items utt 'Syllable))
+ (ennakko 0.00)
+ (no_accent nil) ;; debug variable: removes accent commands
+ (ac_list nil))
+ (mapcar
+ (lambda (syl) ;; for each syllable
+
+ (let ((onset (- (item.feat syl 'syllable_start) ennakko))
+ (offset (item.feat syl 'syllable_end)))
+
+ (cond
+ (no_accent
+ nil)
+ ;; only syllable
+ ((and (not (item.next syl))
+ (not (item.prev syl)))
+ (set! ac_list (append ac_list (list (list onset offset 0.1)))))
+ ;; only word, first syllable
+ ((and (not (item.prev syl))
+ (not (item.next (item.parent (item.relation syl 'SylStructure)))))
+ (set! ac_list (append ac_list (list (list onset offset 0.25)))))
+ ;; first syllable on an accented word
+ ((and (accented_p syl)
+ (or (not (item.prev syl))
+ (not (string-equal
+ (item.feat syl 'R:SylStructure.parent.name)
+ (item.feat syl "p.R:SylStructure.parent.name")))))
+
+ ;; minimum of (120ms * stretch)
+ (if (< (- offset onset) (* 0.120 (Param.get 'Duration_Stretch)))
+ (set! offset (+ onset (* 0.120 (Param.get 'Duration_Stretch)))))
+
+ (set! ac_list (append ac_list (list (list onset offset 0.4)))))
+ ;; unstressed last syllable: negative accent.
+ ((and (not (accented_p syl))
+ (not (item.next syl)))
+ (set! onset (- onset (/ (- onset (item.feat (item.prev syl) 'syllable_start)) 2)))
+
+ (set! ac_list
+ (append ac_list
+ (list (list
+ onset
+ (+ offset (* 0.2 (Param.get 'Duration_Stretch )))
+ -0.3)))))
+ ;; default: do nothing
+ (t
+ nil))))
+ syllables)
+ ac_list))
+
+;; find all phrases within an utterance:
+(define (find_phrases utt)
+ "(define (find_phrases utt)
+Returns a list of phrases from an utterance in the form
+of lists whose car is the break level followed by start and end times"
+ (let ((wrds (utt.relation.items utt 'Word))
+ ;; end is problematic if (SayText UTT) contains more
+ ;; than one sentence. SEP..
+ (end (item.feat (utt.relation.last utt 'Word) 'word_end))
+ (result nil)
+ (start -0.2))
+
+ (mapcar
+ (lambda (wrd)
+;; (set! end (item.feat wrd 'word_end))
+ (let ((break (item.feat wrd 'pbreak))
+; (end (item.feat wrd 'word_end))
+ (next (item.next wrd)))
+ (cond
+ ;; ordinary break
+ ((or (equal? break "B")
+ (equal? break "BB")
+ (equal? break "PB")) ;; Phrasal Break
+ (set! result (append result (list (list break start end))))
+ (set! start (item.feat wrd 'word_end)))
+ ;; break within list
+ ((equal? break "LB")
+ (set! result (append result (list (list break start end))))
+ (set! start
+ (if next
+ (max
+ (- (item.feat wrd 'word_end) 0.1)
+ (/ (+ (item.feat wrd 'word_start)
+ (item.feat wrd 'word_end))
+ 2))
+ "no_start")))
+ (t nil))))
+ wrds)
+
+ result))
+
+(define (utt.length utt)
+ "(utt.length utt)
+Returns the length of an utterance in syllables"
+ (length (utt.relation.items utt 'Syllable)))
+
+;;; produce a list of phrase commands:
+(define (get_phrase_list utt)
+ "(get_phrase_list utt)
+Returns a list of phrase commands for an utterance. The first command
+is higher than the following ones."
+ (let ((phrases (find_phrases utt))
+ (phrase_list nil)
+ (len nil))
+ (set! len (length phrases))
+ (set! phrase_list
+ (mapcar
+ (lambda (phrase)
+ (let ((b_type (car phrase))
+ (start (nth 1 phrase))
+ (end (nth 2 phrase))
+ (level 0))
+ (cond ((or (and (= len 1) (> (utt.length utt) 5))
+ (and (= (position phrase phrases) 0)
+ (not (string-equal b_type "BB")))) ;; first phrase of more than one
+ (if (string-equal current-voice "suo_fi_lj_diphone")
+ (list start end 0.4)
+ ;; male voice
+ (list start end 0.6))) ;; was 0.7
+ ((or (string-equal b_type "LB")
+ (string-equal b_type "PB"))
+ ;; list intonation
+ (list start end 0.05))
+ (t
+ (list start end 0.3)))))
+ phrases))
+ phrase_list))
+
+
+;;; this is the actual Fujisaki equation:
+;;;
+;;; calculate accent amplitude for a given point:
+(define (get_amplitude time beta)
+ "(get_amplitude point beta)
+Calculate the amplitude from time and beta information:"
+ (if (< time 0)
+ 0 ;; <- THEN
+ (min 0.9 ;; <- ELSE
+ (- 1 (* (+ 1 (* beta time))
+ (exp (* (neg beta) time)))))))
+
+;;; calculate phrase amplitude for a given point:
+(define (get_phrase_amplitude time alpha)
+ "(get_phrase_amplitude time alpha)
+calculate phrase amplitude for a given point in time."
+ (cond ((>= time 0)
+ (begin
+ (* (sqr alpha)
+ time
+ (exp (* (neg alpha) time)))))
+ (t 0.0)))
+
+
+;;; calculate the actual f0 for a given time (point):
+(define (calculate_fujisaki accent_list phrase_list point alpha beta f_min)
+ " (calculate_fujisaki acc_list phrase list point alpha beta f_min)
+Calculates the Fujisaki parameter values for a given point. Returns an absolute
+Hertz value"
+;; (print point)
+ (let (ph_level
+ ac_level
+ speed_level
+ result)
+ (set! ph_level
+ (let ((Sum_Pa 0.0))
+ (mapcar
+ (lambda (p)
+ (let ((onset (+ (car p) (/ -1 beta))) ;;
+ (offset (nth 1 p))
+ (amp (nth 2 p)))
+ (set! Sum_Pa
+ (+ Sum_Pa
+ (* amp
+ (get_phrase_amplitude
+ (if (> point offset)
+ 0.0
+ (- point onset))
+ alpha ))))))
+ phrase_list)
+ Sum_Pa))
+ (set! ac_level
+ (let ((Sum_Aa 0.0))
+ (mapcar
+ (lambda (ac)
+ (let ((onset (car ac)) ;; onset of the accent command
+ (offset (nth 1 ac)) ;; offset of the acc. com.
+ (amp (nth 2 ac))) ;; amplitude of the acc. com.
+ (set! Ga_T1
+ (get_amplitude (- point onset) beta))
+ (set! Ga_T2
+ (get_amplitude (- point offset) beta))
+ (set! Sum_Aa
+ (+ Sum_Aa (* amp (- Ga_T1 Ga_T2))))))
+ accent_list)
+ Sum_Aa))
+ ;;; speed level raises f0 in fast speech
+ (set! speed_level (* 100 (- 1 (min (Parameter.get 'Duration_Stretch) 1))))
+ ;; maximum raise of 40dB
+ (set! speed_level (min 40 speed_level))
+
+
+ ;; fast speech is also more monotonous...
+ (set! result (+ speed_level
+ (exp
+ (+ (* ph_level (min (Parameter.get 'Duration_Stretch) 1))
+ (* ac_level (min (Parameter.get 'Duration_Stretch) 1))
+
+ (log f_min)))))
+ result))
+
+;;; calculate the local f0 contour for a syllable
+;;; for a given number of points, determined by
+;;; the parameter *points*
+(define (fujisaki_targ_func utt syl)
+ "(fujisaki_targ_func UTT STREAMITEM)
+Returns a list of targets for the given syllable."
+ ;; (if hy_debug (print "Fujisaki_targ_func"))
+
+
+ (baptize syl) ;; give names to syllables
+
+ (begin
+ (let ((start (item.feat syl 'syllable_start))
+ (end (item.feat syl 'syllable_end))
+ (accent_list (or suopuhe_accent
+ ;; wierd way to print status reports (:
+ (if hy_debug (format stderr "------ COUNTING THE F0 CONTOUR ------\n"))
+ (get_accent_list utt)))
+ (phrase_list (or suopuhe_phrase
+ (get_phrase_list utt)))
+
+
+ (*points* nil)
+ result dur)
+ ;; nint was the easiest way to create an integer, where's abs?
+ ;; calculate f0 after every 50 mseconds
+ (let ((i (if (< start (nint start))
+ (- (nint start) 1)
+ (nint start))))
+ (while (< i end)
+ (begin
+ (if (>= i start)
+ (set! *points* (flatten (list *points* i))))
+ (set! i (+ i 0.050))))) ;; + 50 ms
+ ;; if too short a syllable, use start and end times instead.
+ (if (not *points*)
+ (set! *points* (list start end))
+ (begin
+ (if (not (item.next syl))
+ (set! *points* (flatten (list *points* end (+ end 0.1)))))
+ (if (not (item.prev syl))
+ (set! *points* (flatten (list 0.0 *points*))))))
+
+
+
+ (set! dur (- end start))
+ (set! result (mapcar
+ (lambda (point)
+ ;; (if (> (+ start (* dur point))
+ ;; end)
+ ;;(print (string-append "Dur: " dur " point " (+ start (* dur point)) " end " end))
+;; (list (+ start (* dur point))
+ (list point
+ (min *f_max*
+ (calculate_fujisaki
+ accent_list
+ phrase_list
+ ;; IN ABSOLUT TIME
+ point
+ ;; THIS WAS IN THE RELATIVE APPROACH:
+ ;;(+ start (* point dur))
+ *alpha* *beta* *f_min*))))
+ *points*))
+
+ (set! suopuhe_accent accent_list)
+ (set! suopuhe_phrase phrase_list)
+ (if hy_debug
+ (begin
+
+ (format t " Time F0 in syllable \"%s\".\n" (item.name syl))
+
+ (mapcar (lambda (x)
+ (mapcar (lambda (y)
+ (format t "%7.3f " y))
+ x)
+ (format t "\n"))
+ result)))
+ (if (and hy_debug
+ (not (item.next syl)))
+ (begin
+ (format t "Phrase commands\n Start End Size\n")
+ (mapcar (lambda (x)
+ (mapcar (lambda (y)
+ (format t "%7.3f " y))
+ x)
+ (format t "\n"))
+ phrase_list)
+ (format t "Accent commands\n Start End Size\n")
+ (mapcar (lambda (x)
+ (mapcar (lambda (y)
+ (format t "%7.3f " y))
+ x)
+ (format t "\n"))
+
+ accent_list)))
+
+ ;;; (print phrase_list)
+ ;;;(print accent_list)
+
+; (if hy_debug
+; (begin
+; (format t "f0 at the first point of %l = %l\n" (item.name syl) (car result))
+; (print result)))
+ result)))
+
+
+(define (baptize syl)
+ "(baptize SYL)
+Baptizes the given syllable by concatenating together the names
+of it's daughters (phones). Useful in debugging."
+ (item.set_name syl
+ (let ((str ""))
+ (mapcar
+ (lambda (x)
+ (set! str (string-append str (item.feat x "name"))))
+ (item.daughters (item.relation syl 'SylStructure)))
+ str)))
+
+(provide 'finnish_mv_int)
+
+
+
+
+
+
+
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_mv_phrase.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_mv_phrase.scm
new file mode 100644
index 0000000..28c540a
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_mv_phrase.scm
@@ -0,0 +1,410 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Department of General Linguistics / Suopuhe project ;;
+;;; University of Helsinki, FI ;;
+;;; Copyright (c) 2000,2001,2002,2003 ;;
+;;; All Rights Reserved. ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Authors: ;;
+;;; ;;
+;;; Martti Vainio ;;
+;;; e-mail: martti.vainio@helsinki.fi ;;
+;;; address: Department of General Linguistics ;;
+;;; PL 9 (Siltavuorenpenger 20A) ;;
+;;; 00014 University of Helsinki ;;
+;;; FINLAND ;;
+;;; ;;
+;;; Nicholas Volk ;;
+;;; e-mail: nvolk@ling.helsinki.fi ;;
+;;; address: Department of General Linguistics ;;
+;;; PL 9 (Siltavuorenpenger 20A) ;;
+;;; 00014 University of Helsinki ;;
+;;; FINLAND ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Phrase break prediction
+;;;
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+
+(require 'finnish_lex) ;; causers of initial doubling are in a word list
+
+;; tällekin pitäisi opettaa listaintonaatio
+(set! finnish_phrase_cart_tree
+'
+;; phrasal break
+((R:Token.parent.pbreak is PB)
+ ((PB))
+ ;; list break
+ ((R:Token.parent.pbreak is LB)
+ ((LB))
+ ((R:Token.parent.pbreak is BB)
+ ((BB))
+ ((lisp_token_end_punc in ("?" "." ":"))
+ ((BB))
+ ((R:Token.parent.pbreak is B)
+ ((B))
+ ((lisp_token_end_punc in (";" ","))
+ ((B))
+ ((n.name is 0) ;; end of utterance
+ ((BB))
+ ((NB))))))))))
+
+
+(define (word_has_break? word)
+ "(word_has_break? WORD)
+True, if the WORD is followed by # or ## \"phone\"."
+ (let ((final
+ (item.relation
+ (item.last_leaf
+ (item.relation word 'SylStructure))
+ 'Segment)))
+ (and (item.next final)
+ (string-matches (item.name (item.next final)) "^#+$"))))
+
+(define (distance_to_next_pause word)
+ "(distance_to_next_pause WORD)
+Counts the distance from the end of the word to the next pause in syllables."
+ (cond
+ ((not (item.next word))
+ 0)
+ ((word_has_break? word)
+ 0)
+ (t
+ (+ (syllables_in_word (item.daughter1 (item.relation word 'SylStructure)))
+ (distance_to_next_pause (item.next word))))))
+
+(define (syllables_in_word SYL)
+ "(syllables_in_word SYL)
+Counts the number of syllables in a given word. Actually counts the numebr
+of syllables from a given syllable to the end of word."
+ (if (item.next SYL)
+ (+ 1 (syllables_in_word (item.next SYL)))
+ 1))
+
+(define (distance_from_prev_pause word)
+ "(distance_from_prev_pause WORD)
+Distance (in syllables) from the previous word."
+ (cond
+ ((not (item.prev word))
+ 0)
+ ((word_has_break? (item.prev word))
+ 0)
+ (t
+ (+
+ (syllables_in_word
+ (item.daughter1 (item.relation (item.prev word) 'SylStructure)))
+ (distance_from_prev_pause (item.prev word))))))
+
+
+(define(insert_pause2 word pausetype)
+ "(insert_pause2 WORDITEM)
+ Insert a little break (pause segment) after the last segment in WORDITEM in UTT."
+
+ (if hy_debug (print (string-append "Lisätään tauko (" pausetype ") " (item.name word) "-sanan perään.")))
+
+ ;; sets the value pbreak feature, not too useful...
+ (if (not (string-equal (item.feat word 'pbreak) "BB"))
+ (item.set_feat word 'pbreak pausetype))
+ ; ... since the trick is done by adding a #
+ (let ((lastseg (find_last_seg word))
+ (silence (if (or (string-equal (item.feat word 'pbreak) "PB")
+ (string-equal (item.feat word 'pbreak) "LB"))
+ "##" ;; pikkutauko
+ "#")))
+ (if lastseg
+ (item.relation.insert
+ lastseg 'Segment (list silence) 'after))))
+
+;(define (lingvistinen_tauon_esto sana)
+; "(lingvistinen_tauon_esto WORD)
+;Estää tauon tulemisen tähän kohtaan...
+;Ei juuri implementoitu vielä...
+;Pitää vähän miettiä...
+;Mitä tehdään sanatasolla ja mikä muualla?"
+; (let ((thispos (item.feat sana 'pos))
+; (nextpos (if (item.next sana)
+; (item.feat (item.next sana) 'pos)
+; nil)))
+;
+; (cond
+; ((and (string-equal thispos "adjective" nextpos "noun"))
+; ;;(print "ei taukoa a+n väliin!")
+; t)
+; ((and (string-equal thispos "noun" nextpos "noun"))
+; (print "ei taukoa n+n väliin!")
+; t)
+; (t
+; ;;(print (string-append thispos " + " nextpos))
+; nil))))
+
+
+(define (find_phrase_break word)
+ "(find_phrase_break WORD)
+If the distance from previous break to the next break is
+long enough (now 25 syllables), try to add more pauses
+in between. New pauses are added between certain word classes."
+ (cond
+ ;; something went wrong... return
+ ((not word)
+ nil)
+ ;; less than N syllables (current 25 is an arbitrary choice): no break
+ ((< (+ (distance_to_next_pause word) (distance_from_prev_pause word))
+ 25)
+ (find_phrase_break (skip_pause word)))
+ ;; break needed
+ (t
+ (if hy_debug (format t
+ "Trying to add a break after \"%s\"\n"
+ (upcase (item.name word))))
+
+ (find_phrase_break (skip_pause (add_linguistic_break word))))))
+
+
+(define (add_linguistic_break word)
+ "(add_linguistic_break WORD)
+Adds a phrase break after the word, if the context is appropriate.
+If the word is final return nil. If there already is a pause
+return the word itself. Also is pause is added, return the word itself.
+If pause couldn't be added, try the same with the next word. Simple!"
+(if (not (item.next word))
+ nil
+ (let ((thispos (item.feat word 'pos))
+ (nextpos (item.feat (item.next word) 'pos)))
+ ;; (print (string-append thispos "#" nextpos " paired"))
+ (cond
+ ;; we already have a pause, so let's not try to add one...
+ ((word_has_break? word)
+ word)
+ ;; not far enough from the phrase beginning
+ ((or (not (item.prev word))
+ (word_has_break? (item.prev word)))
+ (add_linguistic_break (item.next word)))
+ ;; put a break after a PoStPosition
+ ((string-equal thispos "psp")
+ (print (string-append " Pause after PSP \""(item.name word)"\"."))
+ (insert_pause2 word "B")
+ word)
+ ;; (NOUN|NUM|PROP) # V
+ ((and (or (string-equal thispos "adjective")
+ (string-equal thispos "noun")
+ (string-equal thispos "num")
+ (string-equal thispos "prop"))
+ (string-equal nextpos "verb"))
+ (format t "\nInserted pause after in N#V postition after %s."
+ (upcase (item.name word)))
+ (insert_pause2 word "PB")
+ word)
+ ;; NUM # PROP
+ ((and (or (string-equal thispos "num")
+ (string-equal thispos "noun"))
+ (string-equal nextpos "prop"))
+ (format t "\nInserted pause after in NUM#PROP postition after %s."
+ (upcase (item.name word)))
+ (insert_pause2 word "PB")
+ word)
+
+ ;; NOUN # CC NOUN
+ ((and (string-equal thispos "noun")
+ (string-equal nextpos "conj")
+ (item.next (item.next word))
+ (string-equal (item.feat (item.next (item.next word)) 'pos) "noun"))
+ (print (string-append "Inserted pause between NOUN \""
+ (item.name word)
+ "\" CONJ and \""
+ (item.name (item.next word)) "\"."))
+ (insert_pause2 word "PB")
+ word)
+ ;; ADJ # CC ADJ
+ ((and (string-equal thispos "adjective")
+ (string-equal nextpos "conj")
+ (item.next (item.next word))
+ (string-equal (item.feat
+ (item.next (item.next word)) 'pos) "adjective"))
+ (print (string-append "Inserted pause between ADJ \""
+ (item.name word)
+ "\" CONJ and \""
+ (item.name (item.next word)) "\"."))
+ (insert_pause2 word "PB")
+ word)
+
+ ;; ADJ # ADJ
+ ((and (string-equal thispos "adjective")
+ (string-equal nextpos "adjective"))
+
+ (print (string-append "Inserted pause between ADJ \""
+ (item.name word) "\" and ADJ \""
+ (item.name (item.next word)) "\"."))
+ (insert_pause2 word "PB")
+ word)
+ ;; V # NUM
+ ((and (string-equal thispos "verb")
+ (string-equal nextpos "num"))
+
+ (insert_pause2 word "PB")
+ word)
+ (t
+ (add_linguistic_break (item.next word)))))))
+
+
+(define (skip_pause WORD)
+ "(skip_pause WORD)
+Returns the word after the next pause or nil if there are no intersentence
+pauses left."
+ (if (item.next WORD)
+ (if (word_has_break? WORD)
+ (item.next WORD)
+ (skip_pause (item.next WORD)))
+ nil))
+
+(define (suopuhe_add_break utterance)
+ "(suopuhe_add_break UTT)
+Adds pauses if necessary to a (overlong) utterance.
+Applies some linguistic intelligence in the process..."
+ (if hy_debug (format stderr "------- PAUSE-ADDING BEGINS ----------\n"))
+
+
+ ;; converts punctions in breaks
+ (suopuhe_Pauses utterance)
+
+ ;; suopuhe-mode can provide linguistic information.
+ ;; we may be able to place additional breaks based on that information
+ (if suopuhe
+ (find_phrase_break (utt.relation.first utterance 'Word))
+ ;; on the other hand initial doubling is only done (here)
+ ;; when not using the suopuhe-mode.
+ ;; we only hope that the xml input's creator took care of them...
+ ;; A bit optimistic assumption, but doing things twice can cause
+ ;; mayhem...
+ (begin
+ (if hy_debug ( format stderr "------ ALKUKAHDENNUS ALKAA -----------\n"))
+ (initial_doubling (utt.relation.first utterance 'Word))))
+
+ ;; these global variables contains the accent and intonation
+ ;; commands for the fujisaki model
+ ;; we want to calculate them only once
+ ;; so these variables tell, whether they have already been counted
+ ;; for the given utterance
+ (set! suopuhe_accent nil)
+ (set! suopuhe_phrase nil)
+
+ utterance)
+
+(define (suopuhe_Pauses utt)
+ "(suopuhe_Pauses utt)
+Converts the punctuation marks into appropriate pauses.
+Does the list intonation too."
+ (let ((words (utt.relation.items utt 'Word))
+ lastword)
+ (if words
+ (begin
+ (insert_initial_pause utt) ;; always have a start pause
+ (set! lastword (car (last words)))
+ (mapcar
+ (lambda (w)
+ (let ((pbreak (item.feat w "pbreak"))
+ (emph (item.feat w "R:Token.parent.EMPH")))
+
+ (cond
+ ((equal? w lastword)
+ ;; last word is followed by a double pause
+ ;; this is to reduce the effect of an annoying syntesis
+ ;; feature...
+ (insert_pause utt w)
+ (insert_pause utt w))
+ ((or (string-equal "BB" pbreak)
+ (string-equal "LB" pbreak)
+ (string-equal "PB" pbreak)
+ (string-equal "B" pbreak))
+ ;; list intonation
+ (let ((a (equal? (item.feat w "p.p.lisp_token_end_punc") ","))
+ (b (equal? (item.feat w "p.lisp_token_end_punc") ","))
+ (c (equal? (item.feat w "lisp_token_end_punc") ","))
+ (d (equal? (item.feat w "n.lisp_token_end_punc") ","))
+ (e (equal? (item.feat w "n.n.lisp_token_end_punc") ",")))
+ (cond
+ ((or (and b c)
+ (and c d)
+ (and c (equal? (item.feat w "n.n.pos") "COORD")))
+ (set! pbreak "LB"))))
+
+ (insert_pause2 w pbreak)))))
+ words)))
+ utt))
+
+(define (initial_doubling WORD)
+ "(initial_doubling WORD)
+Checks wheter the current WORD can triggers initial doubling on the
+next word or not."
+ (let ((name (downcase (item.name WORD))))
+ (if (and (item.next WORD)
+ (not (word_has_break? WORD))
+ ;; (not suopuhe) ;; suopuhe-mode deal this personally ???
+ (word_list_entry? name doubler_words))
+ (begin
+ (if hy_debug
+ (format stderr
+ "%s triggers initial doubling (word list)\n"
+ name))
+ (set! next_initial (item.next (item.relation (item.last_leaf (item.relation WORD 'SylStructure)) 'Segment)))
+
+ (let ((char (item.name next_initial)))
+ (if hy_debug (print (string-append char " => " char ":")))
+ (cond ;; the following consonants are doubled:
+ ((string-equal "b" char)
+ (item.set_name next_initial "b:"))
+ ((string-equal "d" char)
+ (item.set_name next_initial "d:"))
+ ((string-equal "g" char)
+ (item.set_name next_initial "g:"))
+ ((string-equal "h" char)
+ (item.set_name next_initial "h:"))
+ ((string-equal "j" char)
+ (item.set_name next_initial "j:"))
+ ((string-equal "k" char)
+ (item.set_name next_initial "k:"))
+ ((string-equal "l" char)
+ (item.set_name next_initial "l:"))
+ ((string-equal "m" char)
+ (item.set_name next_initial "m:"))
+ ((string-equal "n" char)
+ (item.set_name next_initial "n:"))
+ ((string-equal "p" char)
+ (item.set_name next_initial "p:"))
+ ((string-equal "r" char)
+ (item.set_name next_initial "r:"))
+ ((string-equal "s" char)
+ (item.set_name next_initial "s:"))
+ ((string-equal "S" char)
+ (item.set_name next_initial "S:"))
+ ((string-equal "t" char)
+ (item.set_name next_initial "t:"))
+ ((string-equal "v" char)
+ (item.set_name next_initial "v:"))))))
+ (if (item.next WORD)
+ (initial_doubling (item.next WORD)))))
+
+
+
+
+
+
+(provide 'finnish_mv_phrase)
+
+
+
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_phones.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_phones.scm
new file mode 100644
index 0000000..9315bdd
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/finnish_phones.scm
@@ -0,0 +1,147 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Department of General Linguistics / Suopuhe project ;;
+;;; University of Helsinki, FI ;;
+;;; Copyright (c) 2000,2001,2002 ;;
+;;; All Rights Reserved. ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; ;
+; Authors: ;
+; ;
+; Martti Vainio ;
+; e-mail: martti.vainio@helsinki.fi ;
+; address: ;
+; ;
+; Nicholas Volk ;
+; e-mail: nvolk@ling.helsinki.fi ;
+; address: Department of General Linguistics ;
+; PL 9 (Siltavuorenpenger 20A) ;
+; 00014 University of Helsinki ;
+; FINLAND ;
+; ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; Phoneset definition
+;;;
+;;; Finnish phonemes according to a simplified WorldBet alphabet
+
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+
+(defPhoneSet finnish
+ (
+ (vc + - 0) ;; vowel/consonant
+ (vlng s l 0) ;; vowel length
+ (vheight 1 2 3 0) ;; vowel height
+ (vfront 1 2 3 0) ;; vowel frontness
+ (vrnd + - 0) ;; vowel rounding
+ (ctype s f a n l r 0) ;; articulation type
+ (cplace l a p b d v g 0) ;; articulation place
+ (cvox + - 0) ;; consonant voicing
+ (nasaali + - 0) ;; nasal
+ (klusiili + - 0) ;; plosive
+ (frikatiivi + - 0) ;; fricative
+ (sibilantti + - 0) ;; sibilant
+ (likvida + - 0) ;; liquid
+ (lateraali + - 0) ;; lateral
+ (puolivokaali + - 0) ;; semivowel
+ (clng s l 0) ;; consonant length
+ (cplace2 l a r 0) ;; Lips Alveolar Rest 0
+ )
+ (
+ ;; VOWELS
+ (a + s 3 3 - 0 0 0 0 0 0 0 0 0 0 0 0) ;; ei-worldbet
+ (e + s 2 1 - 0 0 0 0 0 0 0 0 0 0 0 0)
+ (i + s 1 1 - 0 0 0 0 0 0 0 0 0 0 0 0)
+ (o + s 2 3 + 0 0 0 0 0 0 0 0 0 0 0 0)
+ (u + s 1 3 + 0 0 0 0 0 0 0 0 0 0 0 0)
+ (y + s 1 1 + 0 0 0 0 0 0 0 0 0 0 0 0)
+ (@ + s 3 1 - 0 0 0 0 0 0 0 0 0 0 0 0) ;; ä
+ (7 + s 2 1 + 0 0 0 0 0 0 0 0 0 0 0 0) ;; ö
+ (& + s 2 2 - 0 0 0 0 0 0 0 0 0 0 0 0);; schwa
+ (a: + l 3 3 - 0 0 0 0 0 0 0 0 0 0 0 0) ;; ei-worldbet
+ (e: + l 2 1 - 0 0 0 0 0 0 0 0 0 0 0 0)
+ (i: + l 1 1 - 0 0 0 0 0 0 0 0 0 0 0 0)
+ (o: + l 2 3 + 0 0 0 0 0 0 0 0 0 0 0 0)
+ (u: + l 1 3 + 0 0 0 0 0 0 0 0 0 0 0 0)
+ (y: + l 1 1 + 0 0 0 0 0 0 0 0 0 0 0 0)
+ (@: + l 3 1 - 0 0 0 0 0 0 0 0 0 0 0 0) ;; ä
+ (7: + l 2 1 + 0 0 0 0 0 0 0 0 0 0 0 0) ;; ö
+ ;; stops
+ (p - 0 0 0 0 s l - - + - - - - - s l)
+ (t - 0 0 0 0 s a - - + - - - - - s a)
+ (k - 0 0 0 0 s v - - + - - - - - s r)
+;; (? - s 0 0 0 s g -) ;; glottaaliklusiili
+ (b - 0 0 0 0 s l + - + - - - - - s l)
+ (d - 0 0 0 0 s a + - + - - - - - s a)
+ (g - 0 0 0 0 s v + - + - - - - - s r)
+ ;; fricatives
+ (f - 0 0 0 0 f b - - - + - - - - s l)
+ (T - 0 0 0 0 f d - - - + - - - - s a) ;; th
+;; (D - s 0 0 0 f d +)
+ (s - 0 0 0 0 f a - - - + + - - - s a)
+;; (z - s 0 0 0 f a +)
+ (S - 0 0 0 0 f p - - - + + - - - s a) ;; sh
+;; (Z - s 0 0 0 f p +) ;; zh
+ (h - 0 0 0 0 f g - - - + - - - - s r)
+ (v - 0 0 0 0 f b + - - + - - - - s l)
+ ;; nasals
+ (m - 0 0 0 0 n l + + - - - - - - s l)
+ (n - 0 0 0 0 n a + + - - - - - - s a)
+ (N - 0 0 0 0 n v + + - - - - - - s r) ;; ng
+ ;; approximants and liquids
+ (l - 0 0 0 0 l a + - - - - + + - s a)
+ (L - 0 0 0 0 l a + - - - - + + - s a)
+ (r - 0 0 0 0 r a + - - - - + - - s a)
+ (j - 0 0 0 0 r p + - - - - - - + s r)
+ (w - 0 0 0 0 r l + - - - - - - + s r)
+ ;;;;;;;;;;;;;;;
+ ;;; long phones
+ ;; stops
+ (p: - 0 0 0 0 s l - - + - - - - - l l)
+ (t: - 0 0 0 0 s a - - + - - - - - l a)
+ (k: - 0 0 0 0 s v - - + - - - - - l r)
+ (b: - 0 0 0 0 s l + - + - - - - - l l)
+ (d: - 0 0 0 0 s a + - + - - - - - l a)
+ (g: - 0 0 0 0 s v + - + - - - - - l r)
+ ;; fricatives
+ (f: - 0 0 0 0 f b - - - + - - - - l l)
+ (T: - 0 0 0 0 f d - - - + - - - - l a) ;; th
+ (D: - 0 0 0 0 f d + - - + - - - - l a) ;; th voiced
+ (s: - 0 0 0 0 f a - - - + + - - - l a)
+ (z: - 0 0 0 0 f a + - - + + - - - l a)
+ (S: - 0 0 0 0 f p - - - + + - - - l a) ;; sh
+ (Z: - 0 0 0 0 f p + - - + + - - - l a) ;; zh
+ (h: - 0 0 0 0 f g - - - + - - - - l r)
+ (v: - 0 0 0 0 f b + - - + - - - - l l)
+ ;; nasals
+ (m: - 0 0 0 0 n l + + - + - - - - l l)
+ (n: - 0 0 0 0 n a + + - + - - - - l a)
+ (N: - 0 0 0 0 n v + + - + - - - - l r) ;; ng
+ ;; approximants and liquids
+ (w: - 0 0 0 0 r l + - - - - - - + l r)
+ (l: - 0 0 0 0 l a + - - + - + + - l a)
+ (L: - 0 0 0 0 l a + - - + - + + - l a)
+ (r: - 0 0 0 0 r a + - - + - + - - l a)
+ (j: - 0 0 0 0 r p + - - + - - - + l r)
+ ;; pauses
+ (## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) ;; phrase break
+ (# 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))
+
+
+(PhoneSet.silences '(#))
+(provide 'finnish_phones)
+
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/hy_fi_mv_diphone.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/hy_fi_mv_diphone.scm
new file mode 100644
index 0000000..757f32e
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/hy_fi_mv_diphone.scm
@@ -0,0 +1,355 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Suopuhe project ;;
+;;; Department of General Linguistics, University of Helsinki, FI ;;
+;;; Copyright (c) 2000, 2001, 2002, 2003 ;;
+;;; All Rights Reserved. ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; ;
+; Authors: ;
+; ;
+; Martti Vainio ;
+; e-mail: martti.vainio@helsinki.fi ;
+; address: Department of General Linguistics ;
+; PL 9 (Siltavuorenpenger 20A) ;
+; 00014 University of Helsinki ;
+; FINLAND ;
+; ;
+; Nicholas Volk ;
+; e-mail: nvolk@ling.helsinki.fi ;
+; address: Department of General Linguistics ;
+; PL 9 (Siltavuorenpenger 20A) ;
+; 00014 University of Helsinki ;
+; FINLAND ;
+; ;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;
+;;; THE MASTER FILE OF FINNISH VOICES
+;;; =================================
+;;;
+;;; contains:
+;;; The Finnish adult male voice "MV"
+;;; The Finnish adlut female voice "LJ"
+;;;
+;;; The files have been combined since they share a lot
+;;; and combining them makes updating easier
+;;;
+;;; The female voice is linked to this file via two symbolic links
+;;; first in the finnish/VOICE_NAME
+;;; and then in festvox/VOICE_NAME.scm
+
+(if (not (boundp 'suopuhe_output_file_prefix))
+ (set! suopuhe_output_file_prefix "/tmp/"))
+
+;; unless the debug mode is already on, set debug mode off...
+(if (not (boundp 'hy_debug))
+ (set! hy_debug nil))
+
+;; Determine the location of the Finnish male voice:
+;; The location is stored in variable hy_fi_mv_dir.
+;; If it isn't present, the voice is not loaded!
+(cond
+ ;; 0th: use my absolute path in my www demo
+ ((probe_file "/home/nvolk/public_html/cgi-bin/festival/lib/voices/finnish/hy_fi_mv_diphone/festvox/hy_fi_mv_diphone.scm")
+ (defvar hy_fi_mv_dir "/home/nvolk/public_html/cgi-bin/festival/lib/voices/finnish/hy_fi_mv_diphone/")
+ ;; this one is for my www demo
+ (set! suopuhe_output_file_prefix "/home/nvolk/public_html/cgi-bin/lavennin/tmp/"))
+ ;; 1st: try default place in the Festival hierarchy:
+ ((assoc 'hy_fi_mv_diphone voice-locations)
+ (defvar hy_fi_mv_dir
+ (cdr (assoc 'hy_fi_mv_diphone voice-locations))))
+ ;; 2nd: use (my) absolute path in www demo
+ ((probe_file "/home/n/v/nvolk/festival/lib/voices/finnish/hy_fi_mv_diphone/festvox/hy_fi_mv_diphone.scm")
+ (defvar hy_fi_mv_dir "/home/n/v/nvolk/festival/lib/voices/finnish/hy_fi_mv_diphone/"))
+ (t
+ (format stderr "The location of (hy_fi_mv_diphone) could not be determined!\n")
+ ))
+
+
+
+;; Determine the location of the Finnish female voice:
+;; The location is stored in variable suo_fi_lj_dir.
+;; If it isn't present, the voice is not loaded!
+(cond
+ ;; 1st: try default place in the Festival hierarchy:
+ ((assoc 'suo_fi_lj_diphone voice-locations)
+ (defvar suo_fi_lj_dir
+ (cdr (assoc 'suo_fi_lj_diphone voice-locations))))
+ ;; 2nd: use (my) absolute path
+ ((probe_file "/home/n/v/nvolk/festival/lib/voices/finnish/suo_fi_lj_diphone/festvox/suo_fi_lj_diphone.scm")
+ (defvar hy_fi_mv_dir "/home/n/v/nvolk/festival/lib/voices/finnish/suo_fi_lj_diphone/"))
+ (t
+ (format stderr "The location of (suo_fi_lj_diphone) could not be determined!\n")
+ ))
+
+
+
+;; add the finnish stuff to Festival's load-path variable
+(if (boundp 'hy_fi_mv_dir)
+ (set! load-path (cons (string-append hy_fi_mv_dir "festvox/") load-path)))
+(if (boundp 'suo_fi_lj_dir)
+ (set! load-path (cons (string-append suo_fi_lj_dir "festvox/") load-path)))
+
+
+;;;=== THE OTHER FILES WE NEED ================================================
+(require_module 'UniSyn)
+
+(if (or (boundp 'hy_fi_mv_dir)
+ (boundp 'suo_fi_lj_dir))
+ (begin
+ ;; (require 'finnish_aux_funcs) ;; this one makes writes to /tmp a system call (calling wavesurfer, fix paths if you need to use (wavesurf UTT) function
+ (require 'finnish_phones)
+ (require 'finnish_lex)
+ (require 'finnish_lts) ;; handles also the tokens
+ (require 'finnish_mv_int)
+ (require 'finnish_duration)
+ (require 'finnish_mv_phrase)
+ (require 'suopuhe_mode))) ;; suopuhe, our TTS mode
+;;;========================================================================
+
+
+;; if one uses the bitlips modifications to Festival's C++ code
+;; alternatives (a a:) (b b:) etc. could be also used safely...
+;; I've informed the festival-talk lisy about this improvement, but
+;; since the current standard version Festival lacks the improvement
+;; in alternative diphone selecection, I'm still using the old code
+(set! suopuhe_alternatives '(
+ (## #)
+ (a: a) ;; (a a:)
+ (b: b)
+ (d: d)
+ (D: D)
+ (e: e) ;; (e e:)
+ (f: f)
+ (g: g)
+ (h: h)
+ (i: i)
+ (j: j)
+ (k: k)
+ (l: l)
+ (m: m)
+ (n: n)
+ (N: N)
+ (o: o) ;; (o o:)
+ (p: p)
+ (r: r)
+ (s: s)
+ (S: S)
+ (t: t)
+ (T: t)
+ (T t)
+ ;; (T: T)
+ (u: u) ;; (u u:)
+ (v: v)
+ (w: w)
+ (y: y) ;; (y y:)
+ (7: 7) ;; (7 7:)
+ (@: @) ;; (@ @:)
+ ))
+
+
+;; hy_fi_mv_diphone grouped lpc data
+(if (boundp 'hy_fi_mv_dir)
+ (set! hy_fi_mv_lpc_group
+ (list
+ '(name "mv_lpc_group")
+ (list 'index_file
+ (path-append hy_fi_mv_dir "group/mvlpc.group"))
+ '(grouped "true")
+ (list 'alternates_left suopuhe_alternatives)
+ (list 'alternates_right suopuhe_alternatives)
+ (list 'default_diphone "#-#"))))
+
+;; suo_fi_lj_diphone grouped voice
+(if (boundp 'suo_fi_lj_dir)
+ (set! suo_fi_lj_lpc_group
+ (list
+ '(name "lj_lpc_group")
+ (list 'index_file
+ (path-append suo_fi_lj_dir "group/ljlpc.group"))
+ '(grouped "true")
+ (list 'alternates_left suopuhe_alternatives)
+ (list 'alternates_right suopuhe_alternatives)
+ (list 'default_diphone "#-#"))))
+
+(if (boundp 'hy_fi_mv_dir) (set! hy_fi_mv_db_name (us_diphone_init hy_fi_mv_lpc_group)))
+(if (boundp 'suo_fi_lj_dir) (set! suo_fi_lj_db_name (us_diphone_init suo_fi_lj_lpc_group)))
+
+;;;========================================================================
+
+
+(if (boundp 'hy_fi_mv_dir)
+ (define (hy_fi_mv_diphone)
+ "(hy_fi_mv_diphone)
+Switch to the Finnish male voice,
+Suopuhe's support for Festival's in-build voice-locating mechanism."
+ (voice_hy_fi_mv_diphone)))
+
+(if (boundp 'suo_fi_lj_dir)
+ (define (voice_suo_fi_lj_diphone)
+ "(suo_fi_lj_diphone)
+Switch to the Finnish female voice.
+Suopuhe's support for Festival's in-build voice-locating mechanism."
+ (voice_suo_fi_lj_diphone)))
+
+(if (boundp 'suo_fi_lj_dir)
+ (define (voice_suo_fi_lj_diphone)
+ "(voice_suo_fi_lj_diphone)
+Suopuhe Finnish female voice "
+ (general_fi_diphone)
+
+ ;; local fujisaki params (and others) for female voice;
+ (set! *alpha* 2)
+ (set! *beta* 15)
+ (set! *f_min* 115.0)
+ (set! *f_max* 300.0)
+ (us_db_select suo_fi_lj_db_name)
+ (if (not (string-equal current-voice "suo_fi_lj_diphone"))
+ (set! current-voice 'suo_fi_lj_diphone))
+ 'suo_fi_lj_diphone
+ ))
+
+(if (boundp 'hy_fi_mv_dir)
+ (define (voice_hy_fi_mv_diphone)
+ "(voice_hy_fi_mv_diphone)
+Suopuhe Finnish male voice "
+ (general_fi_diphone)
+ ;; local fujisaki params;
+ (set! *alpha* 2)
+ (set! *beta* 15)
+ (set! *f_min* 55.0)
+ (set! *f_max* 120.0)
+ ;; if-lause estää äänen tuplakäynnistämisen siteinit,scm:n yhteydessä
+ (us_db_select hy_fi_mv_db_name)
+ (if (not (string-equal current-voice "hy_fi_mv_diphone"))
+ (set! current-voice 'hy_fi_mv_diphone))
+ 'hy_fi_mv_diphone))
+
+
+(define (general_fi_diphone)
+ "(general_fi_diphone)
+Shared settings for all Suopuhe voices."
+ (voice_reset)
+ (Parameter.set 'Language 'finnish)
+ (Parameter.set 'PhoneSet 'finnish)
+ (PhoneSet.select 'finnish)
+
+ (Parameter.set 'Token_Method 'Token_Any)
+ (Parameter.set 'Phrase_Method 'cart_tree)
+
+ ;; we use are our own redifined "default" duration method
+ ;; (which is probably a bad idea since it may cause headaches
+ ;; for other languages)
+ (Parameter.set 'Duration_Method 'Duration_Finnish)
+
+ (Parameter.set 'Int_Target_Method 'General)
+ (Parameter.set 'Int_Method 'General)
+ ;; Numeric expansion of sorts
+ ;; These should be handled externaly
+ (set! token_to_words finnish_token_to_words)
+
+
+ ;; No POS prediction (get it from TTS mode or from lexicon)...
+ (set! pos_lex_name nil)
+ (set! pos_supported nil)
+ ;; Phrasing
+ (set! phrase_cart_tree finnish_phrase_cart_tree)
+
+ ;; Lexicon and postlexical rules
+ (lex.select "finnish")
+
+ ;; Duration
+ (set! duration_cart_tree hy_fi_mv2::zdur_tree)
+ (set! duration_ph_info hy_fi_mv2::phone_durs)
+
+ ;; Accent
+ (set! int_accent_cart_tree finnish_accent_cart_tree)
+ ;;(set! multfactor 0.88 )
+
+
+ ;; FUJISAKI as the intonation model
+ (set! int_general_params (list (list 'targ_func fujisaki_targ_func)))
+
+
+ ;; TTS might complain if these are not set...
+ (set! int_lr_params
+ '((target_f0_mean 110) (target_f0_std 29) ; was 100 and 19
+ ;; the standard value for target_f0_mean 124
+ (model_f0_mean 170) (model_f0_std 34)))
+
+ (set! guess_pos nil) ;; no educaterd guesses
+
+
+ ;; Waveform synthesizer: diphones
+ (set! UniSyn_module_hooks nil)
+ (set! us_abs_offset 0.0)
+ (set! window_factor 1.0)
+ (set! us_rel_offset 0.0)
+ (set! us_gain 0.9)
+
+ (Parameter.set 'Synth_Method 'UniSyn)
+ (Parameter.set 'us_sigpr 'lpc)
+ (Parameter.set 'Duration_Stretch 1.0) ;; we are speeding up...
+
+ ;; pause insertion and also initial doubling
+ (Parameter.set 'Pause_Method suopuhe_add_break)
+
+
+
+ (set! suopuhe nil) ;; tts-mode off. SHOULD WE USE BOUNDP here? (nv)
+
+ ;; Initializing global variables (sigh!) for storing Fujisaki's
+ ;; accent and phrase commands
+ (set! suopuhe_accent nil)
+ (set! suopuhe_phrase nil)
+
+ (Parameter.set 'Language 'finnish)
+ )
+
+
+(if (symbol-bound? 'hy_fi_mv_dir)
+ (proclaim_voice
+ 'hy_fi_mv_diphone
+ '((language finnish)
+ (gender male)
+ (dialect helsinki)
+ (description
+ "Festival diphone voice for Finnish"
+ )
+ (builtwith festvox-1.2))))
+
+
+(if (symbol-bound? 'hy_fi_mv_dir)
+ (proclaim_voice
+ 'suo_fi_lj_diphone
+ '((language finnish)
+ (gender male)
+ (dialect karjala)
+ (description
+ "Festival diphone voice for Finnish"
+ )
+ (builtwith festvox-1.2))))
+
+;; this is the shared main file for all finnish voices
+(if (boundp 'hy_fi_mv_dir)
+ (provide 'hy_fi_mv_diphone))
+
+(if (boundp 'suo_fi_lj_dir)
+ (provide 'suo_fi_lj_diphone))
+
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/suo_fi_lj_diphone.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/suo_fi_lj_diphone.scm
new file mode 120000
index 0000000..0e9e4c6
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/suo_fi_lj_diphone.scm
@@ -0,0 +1 @@
+hy_fi_mv_diphone.scm \ No newline at end of file
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe.dtd b/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe.dtd
new file mode 100644
index 0000000..8eb2d62
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe.dtd
@@ -0,0 +1,153 @@
+<!--
+
+ SuoPuhe-project speech synthesizer input XML
+
+ Copyright (c) 2000-2003 Dept. General Linguistics, University of Helsinki
+ All Rights Reserved.
+
+ Author: Nicholas Volk (nvolk@ling.helsinki.fi)
+
+ This program is distributed under Gnu Lesser General Public License (cf. the
+ file LICENSE in distribution).
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ TODO: different kinds of accents...
+ break-types need to be reconsidered
+ audio could read stuff from www
+
+ v.0.6.1 -audio tag
+
+ v.0.6.0 -changed "sentence" to "utterance"
+ -initial doubling is done with sayas, not with
+ "triggers_doubling"
+ -token can contain breaks and phrase boundaries
+ -added language
+
+ v0.5.1 (nv) minor bug fix + modification on breaks
+ v0.5.0 replaced sayas with original
+ the motivation was that I needed include tags within the tokens:
+
+ <token original="1351"> yksi kolme <phrase/> viisi yksi </token>
+
+
+ v0.4.5 (Nicholas Volk 18.6.2002)
+ -changed accent from accent ( yes | no ) "no"
+ to accent ( yes | neutral | no ) "neutral" >
+
+
+ v. 0.4.1 added list-argument to <TOKEN>
+ -sanaluokkatiedot kesken ja muuttuvat varmasti
+ -puhuvalle päälle voi välittää ilme-tiedon ennen sanaa ja sanan jälkeen,
+ ei sanan aikana
+ -mitenköhän kielen generointi
+ -
+-->
+
+<!ELEMENT suopuhe ((speaker|audio)+)>
+
+
+
+<!ELEMENT speaker ((utterance, pause?)+)>
+<!ATTLIST speaker
+ name CDATA #IMPLIED
+ gender (male|female) #IMPLIED
+ age (child|youth|adult|aged) #IMPLIED >
+
+<!-- speaker -->
+<!-- if the name refers to an existing voice, try to use that one, -->
+<!-- instead of the default voice. Otherwise the voice selection -->
+<!-- is primarily based on the sex and secondarily on the age. -->
+<!-- Without only 2 Finnish, you don't get much support for these. -->
+<!-- Jos nimi viittaa johonkin käytettävissä järjestelmässä olevaan -->
+<!-- ääneen, käytetään sitä, muuten oletusääntä. -->
+<!-- Muuten ääni valitaan ensisijaisesti sukupuolen ja toissijaisesti -->
+<!-- iän perusteella. Sitten kun toinen ääni on valmis, -->
+<!-- niin tällä tagilla on oikeasti väliä. -->
+
+<!ELEMENT pause EMPTY>
+<!ATTLIST pause
+ duration CDATA #IMPLIED >
+
+<!-- pause -->
+<!-- A long pause between utterances, not a phrase break -->
+<!-- Aito pitkän hiljainen hetki, ei hapentankkauskatko keskellä -->
+<!-- lausetta -->
+
+<!ELEMENT audio EMPTY>
+<!ATTLIST audio
+ file CDATA #IMPLIED>
+
+<!ELEMENT utterance ((facial?, token, (break|phrase)?)*, token, facial?)>
+<!ATTLIST utterance
+ language CDATA "FI"
+ type (declaration|question|exclamation) "declaration"
+ manner (normal|whisper|creaky|fast) "normal"
+ tone (neutral|sarcastic) "neutral">
+
+<!-- utterance -->
+<!-- "type" sets the baseline/intonation type -->
+<!-- "manner" and "tone" are hard to support in diphone-based synthesis -->
+<!-- so they are not really supported yet. -->
+<!-- "type" määrää lauseen baselinen (fujisakin fraasikomponentin jne.), -->
+<!-- "manner" ja "tone" ovat -->
+<!-- vaikeasti tuettavissa difonipohjaisessa synteesissä, mutta ehkä -->
+<!-- ne joskus tekevät jotain... -->
+
+
+<!ELEMENT facial EMPTY>
+<!ATTLIST facial
+ expression CDATA "plain">
+
+
+<!-- facial -->
+<!-- simplistic talking head support -->
+<!-- expression tells what expression to use at the end of that word -->
+<!-- expression kertoo millaiseen yleisilmeiseen pitäisi päätyä sanan -->
+<!-- loputtua. Alkeellinen Puhuva pää -tuki. -->
+
+<!ELEMENT token (#PCDATA|break|phrase)*>
+<!ATTLIST token
+ pos ( abbr | adjective| adverb | char | conj | foreign |
+ hybrid | multiword | name | noun | num | punc |
+ unknown | verb ) "unknown"
+ original CDATA #IMPLIED
+ list ( yes | no ) "no"
+ accent ( yes | neutral | no ) "neutral" >
+
+
+<!-- token -->
+<!-- "token" means any string. Punctuation marks have been separated -->
+<!-- from the words they were attached to and now appear as individual -->
+<!-- tokens -->
+<!-- Lisäksi ilmoitetaan onko sana painotettu vai ei lausepainon -->
+<!-- kannalta. -->
+
+
+ <!ELEMENT phrase EMPTY>
+
+<!-- marks a phrase break thus supporting fujisaki model -->
+<!-- uuden fraasin alku, signaloi fujisakin mallille -->
+<!-- phrase-komentoa, voitaneen käyttää myös potentiaalisen -->
+<!-- tauon ilmaisemiseen... -->
+
+
+ <!ELEMENT break EMPTY>
+ <!ATTLIST break level ( -1 | 0 | 1 | 2 | 3 | 4 ) "1" >
+
+
+<!-- -1 no break -->
+<!-- 0 no break, phrase boundary; we have a separate phrase though -->
+<!-- 1+ breaks with phrase boundaries -->
+
+
+
+
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe_filter.perl b/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe_filter.perl
new file mode 100755
index 0000000..db0912a
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe_filter.perl
@@ -0,0 +1,75 @@
+#!/usr/bin/perl -w
+use strict;
+#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#;; ;;
+#;; Department of General Linguistics / Suopuhe project ;;
+#;; University of Helsinki, FI ;;
+#;; Copyright (c) 2000,2001,2002,2003 ;;
+#;; All Rights Reserved. ;;
+#;; ;;
+#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+
+#; This program is distributed under Gnu Lesser General Public License (cf. the
+#; file LICENSE in distribution).
+
+#; This program is free software; you can redistribute it and/or modify
+#; it under the terms of the GNU Lesser General Public License as published by
+#; the Free Software Foundation; either version 2 of the License, or
+#; (at your option) any later version.
+
+#; This program is distributed in the hope that it will be useful,
+#; but WITHOUT ANY WARRANTY; without even the implied warranty of
+#; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+#; GNU Lesser General Public License for more details.
+
+# suopuheen BASH-filtteri
+# syötteen tulisi olla lause/rivi -muotoista
+
+# Tue Sep 9 11:23:05 EEST 2003
+# -Added of forgotten 'g': s/// => s///g which caused list intonation to
+# remove wrong words
+
+# Fri Oct 26 12:04:40 EEST 2001
+# -Added partial sayas-replacement already here, because of Festival
+# (rxp-parser?) bug.
+
+# read the whole input into $_
+undef $/;
+$_ = <>;
+
+# kommentit pois
+s/<!\-\-.*?\-\->//gs;
+s/\s+/ /gs;
+
+# XML-parserin bugeja:
+s/ original=\"<\"//g;
+s/ original=\"\&\"//g;
+
+#> yksi kaksi <# muuttuu muotoon #> yksi-kaksi <#
+# (korjaa raa'asti festarin token-mokan):
+while ( s/> ([A-Za-zåäö\-]+) ([A-Za-zåäö])/> $1-$2/ ) {}
+# tyhjät pois:
+s/<token( +[a-z]+=\"[^\"]*\")*> +<\/token>\s*//g;
+
+
+# allow phrase and break only in mid positon of token
+while ( s/(<break\/>)\s*(<\/token>)/$2 $1/ ||
+ s/(<phrase\/>)\s*(<\/token>)/$2 $1/ ) {}
+
+while ( s/(<token( +[a-z]+=\"[^\"]*\")*>)\s+(<(break|phrase)\/>)/$3 $1/g ) {}
+
+# eliminate <break/> <phrase\/> sequences: the first one wins
+
+s/(<(break|phrase)\/>)( <(break|phrase)\/>)*/$1/g;
+
+
+
+
+
+
+s/> />\n/g;
+s/ </\n</g;
+
+print $_;
diff --git a/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe_mode.scm b/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe_mode.scm
new file mode 100644
index 0000000..28af66a
--- /dev/null
+++ b/lib/voices/finnish/suo_fi_lj_diphone/festvox/suopuhe_mode.scm
@@ -0,0 +1,634 @@
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Department of General Linguistics / Suopuhe project ;;
+;;; University of Helsinki, FI ;;
+;;; Copyright (c) 2000, 2001, 2002, 2003 ;;
+;;; All Rights Reserved. ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; This program is distributed under Gnu Lesser General Public License (cf. the
+; file LICENSE in distribution).
+
+; This program is free software; you can redistribute it and/or modify
+; it under the terms of the GNU Lesser General Public License as published by
+; the Free Software Foundation; either version 2 of the License, or
+; (at your option) any later version.
+
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU Lesser General Public License for more details.
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;; ;;
+;;; Author(s): ;;
+;;; ;;
+;;; Nicholas Volk ;;
+;;; e-mail: nvolk@ling.helsinki.fi ;;
+;;; address: Department of General Linguistics ;;
+;;; PL 9 (Siltavuorenpenger 20A) ;;
+;;; 00014 University of Helsinki ;;
+;;; FINLAND ;;
+;;; ;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; This file contains the suopuhe mode. It's based on the Festival's
+;; Sable mode, though certain typical text-to-speech mark-up
+;; language tags have been omitted, and some more linguistics stuff
+;; has been added.
+;; (I think that for example. F0/speed etc. are properties of the voice,
+;; and thus I don't allow any mark-up writer to modify it.
+;; Thus, no Donald Ducks!)
+;;
+;; WISH LIST:
+;;
+;; Add male/female-option into SPEAKER-tag
+;; Audio plays local files, how about WWW (compare with SABLE)...
+;;
+;; KNOWN BUGS
+;;
+
+;; XML-mode's output directory
+(if (not (boundp 'suopuhe_output_file_prefix))
+ (set! suopuhe_output_file_prefix "/tmp/"))
+
+(if (not (boundp 'suopuhe_default_voice))
+ (set! suopuhe_default_voice 'voice_hy_fi_mv_diphone))
+
+;; the maximum number of sentences to synthetize & save
+(if (not (boundp 'suopuhe_max_sentences))
+ (set! suopuhe_max_sentences 1000))
+
+;; are the SGML utterances spoken or not?
+(if (not (boundp 'suopuhe_aloud))
+ (set! suopuhe_aloud t))
+
+
+(if hy_debug
+ (format stderr "Using %s as the output directory!\n" suopuhe_output_file_prefix))
+
+
+(require_module 'rxp) ;; Richard Tobin's XML parser
+
+
+(define (list2string list)
+ "(list2string LIST)
+Construct a string from a list of symbols"
+ (let ((str ""))
+ (mapcar (lambda (x)
+ (set! str (string-append str x)))
+ list)
+ str))
+
+;; Add Suopuhe-mode to mode-from-suffix list
+(set! auto-text-mode-alist
+ (cons
+ (cons "\\.suo$" 'suopuhe)
+ (cons
+ (cons "\\.suopuhe$" 'suopuhe)
+ auto-text-mode-alist)))
+
+
+(xml_register_id "-//SUOPUHE//DTD SUOPUHE speech mark up//EN"
+ (cond
+; (t
+; "/home/nvolk/public_html/cgi-bin/festival/lib/voices/finnish/festvox/suopuhe.dtd")
+ ((boundp 'hy_fi_mv_dir)
+ (path-append hy_fi_mv_dir "festvox/suopuhe.dtd"))
+ ((boundp 'suo_fi_lj_dir)
+ (path-append suo_fi_lj_dir "festvox/suopuhe.dtd"))
+ (t
+ nil)))
+
+(xml_register_id "-//SABLE//ENTITIES Added Latin 1 for SABLE//EN"
+ (path-append libdir "sable-latin.ent"))
+
+
+;; select the filter for suopuhe
+(set! suopuhe_filter
+ (cond
+ ((boundp 'hy_fi_mv_dir)
+ (string-append hy_fi_mv_dir "festvox/suopuhe_filter.perl"))
+ ((boundp 'suo_fi_lj_dir)
+ (string-append suo_fi_lj_dir "festvox/suopuhe_filter.perl"))
+ (t
+ nil)))
+
+(define (suopuhe_init_globals)
+ "(suopuhe_init_globals)
+Initialize various global variables."
+ (set! suopuhe_language "finnish")
+ (set! suopuhe_file_number 1) ;; utts are stored into separate files
+ (set! utts nil)
+ (set! suopuhe_vol_type 'no_change)
+ (set! suopuhe_vol_factor 1.0)
+ (set! suopuhe t)
+ (set! suopuhe_within_token 0)
+ (set! suopuhe_pos_stack nil)
+ (set! suopuhe_accent_stack nil)
+)
+
+
+;; TOKENIZATION
+(define (suopuhe_token_to_words token name)
+ "(suopuhe_token_to_words token name)
+SUOPUHE mode token specific analysis."
+ (let ((skip (car suopuhe_skip_stack)))
+ ;; (format stderr "skip \"%s\"? %s\n" name skip)
+ (set! suopuhe_skip_stack (cdr suopuhe_skip_stack))
+ (cond
+ (skip
+ (format stderr "suopuhe_mode: removed %s\n" name)
+ nil)
+
+ ;; default: do the standard t2w stuff:
+ (t
+ (finnish_token_to_words token name)))))
+ ;; (original_token_to_words token name)))))
+
+
+
+
+
+(defvar suopuhe_elements
+'(
+ ("(suopuhe" (ATTLIST UTT)
+ ;(eval (list suopuhe_current_voice)) ;; so we know what state we start in
+ (eval (list suopuhe_default_voice))
+ (suopuhe_voice_param_setup)
+ UTT ;; or nil
+ )
+ (")suopuhe" (ATTLIST UTT)
+ (if (not (null? UTT))
+ (begin
+ (xxml_synth UTT)
+ (suopuhe_voice_param_setup)))
+ nil
+ )
+ ("(speaker" (ATTLIST UTT)
+ (let ((name (list2string (xxml_attval "name" ATTLIST)))
+ (age (list2string (xxml_attval "age" ATTLIST)))
+ (gender (list2string (xxml_attval "gender" ATTLIST))))
+ ;; (print name)
+ ;; (print age)
+ ;; (print gender)
+
+ ;;; turn the appropriate age/gender/name on
+ (cond
+ ((and (string-equal name "martti")
+ (not (string-equal current-voice "hy_fi_mv_diphone")))
+ (hy_fi_mv_diphone))
+ ;; we should check whether the voice exits!
+ ((and (string-equal name "suo_fi_lj_diphone")
+ ;; not yet on
+ (not (string-equal current-voice "suo_fi_lj_diphone")))
+ (suo_fi_lj_diphone))
+ ((and (string-equal gender "female")
+ (not (string-equal current-voice "suo_fi_lj_diphone")))
+ (suo_fi_lj_diphone))
+ ((and (string-equal gender "male")
+ (not (string-equal current-voice "hy_fi_mv_diphone")))
+ (hy_fi_mv_diphone))
+ ((not (string-equal age "")
+ (format stderr "The age-parameter is not yet supported!")))
+ (t
+ nil))
+ (set! token_to_words suopuhe_token_to_words)
+ UTT))
+ (")speaker" (ATTLIST UTT)
+ (if (not (null? UTT))
+ (begin
+ (xxml_synth UTT)
+ (suopuhe_voice_param_setup)))
+ nil
+ )
+ ;; PAUSE: does not create a file, instead uses unix's sleep command
+ ;; to doze off for a while
+ ("pause" (ATTLIST UTT)
+ (if (not (null? UTT))
+ (begin
+ (let ((dur (car (xxml_attval "duration" ATTLIST))))
+ (set! dur (string-append "sleep " dur))
+ ;; since we are not currently creating empty wavs
+ ;; there no point dozing off when we are in the
+ ;; silent mode (suopuhe_aloud is nil)
+ (if (and suopuhe_aloud
+ (string-matches dur "sleep [1-9][0-9]*"))
+ (system dur)))))
+
+
+ nil)
+
+
+ ("audio" (ATTLIST UTT)
+ (if (not (null? UTT))
+ (begin
+ (xxml_synth UTT)
+ (suopuhe_voice_param_setup))) ;; synthesizing anything ready to be synthesized
+ (wave.play (wave.load (car (xxml_attval "file" ATTLIST)) "wav"))
+ nil)
+
+ ("(utterance" (ATTLIST UTT)
+ (if (not (null? UTT))
+ (begin
+ (xxml_synth UTT)
+ (suopuhe_voice_param_setup)))
+ nil)
+
+ (")utterance" (ATTLIST UTT)
+ (if (not (null? UTT))
+ (begin
+ (xxml_synth UTT)
+ (suopuhe_voice_param_setup)))
+ nil
+ )
+;;;;;;;;;;;; TOKENS
+ ("(token" (ATTLIST UTT)
+ (set! suopuhe_within_token 1)
+ ;; some variables affecting intonation and stuff...
+ (let ((tokpos (list2string (xxml_attval "pos" ATTLIST)))
+ (tokacc (list2string (xxml_attval "accent" ATTLIST)))
+ (toklis (list2string (xxml_attval "list" ATTLIST)))
+ )
+ (set! xxml_word_features
+ (cons (list "pos" tokpos) xxml_word_features))
+
+ (cond
+ ((string-equal tokpos "punc")
+ ;; add pause to the end of last word
+ (let ((last_token (utt.relation.last UTT 'Token)))
+ (if (and last_token
+ (string-equal (item.feat last_token "pbreak") "0"))
+ (begin
+ (item.set_feat last_token "pbreak" "B"))))
+ ;; delete the actual string
+ (set! suopuhe_skip_stack (append suopuhe_skip_stack (list t))))
+ ;; no punc, no (must) pause:
+ (t
+ (push_pos tokpos)
+ (push_accent tokacc)
+ (set! suopuhe_skip_stack (append suopuhe_skip_stack (list nil)))
+ ;; list intonation
+ (if (string-equal toklis "yes")
+ (let ((last_token (utt.relation.last UTT 'Token)))
+ (if last_token
+ (begin
+ (item.set_feat last_token "pbreak" "LB")
+ (if hy_debug
+ (format t "ListBreak after %s\n" (item.name last_token)))))))
+ )))
+
+
+ UTT)
+
+ (")token" (ATTLIST UTT)
+ (set! suopuhe_within_token 0)
+ UTT)
+
+ ("break" (ATTLIST UTT)
+ ;; check that there really is a word after which the pause will be put
+ (if (utt.relation.last UTT 'Token)
+ (let ((blevel (list2string (xxml_attval "level" ATTLIST)))
+ (last_token (utt.relation.last UTT 'Token)))
+
+ ;; some stack manipulation
+ (if (> suopuhe_within_token 0)
+ (begin
+ (set! suopuhe_skip_stack (append suopuhe_skip_stack (list nil)))
+ (push_pos (car suopuhe_pos_stack))
+ (push_accent (car suopuhe_accent_stack))))
+ ;; since PUNC-tags are deleted,
+ ;; we make this a property of the previous token
+ ;; hope it's a word!
+ (if (string-equal "punc" (item.feat last_token "pos"))
+ (set! last_token (item.prev last_token)))
+ (cond
+ ((string-equal blevel "1")
+ (if last_token
+ (begin
+ (if hy_debug
+ (format t "Adding a B pause after %s.\n" (item.name last_token)))
+
+ (item.set_feat last_token "pbreak" "B"))))
+ ((string-equal blevel "0")
+ ;; add a no-break marker
+ ;; but do we honour it? can't remember...
+ (if last_token
+ (item.set_feat last_token "pbreak" "NB")))
+ (t
+ (print (string-append "Unexpected value blevel: " blevel))
+ ))))
+ UTT)
+
+
+ ("phrase" (ATTLIST UTT)
+ ;; add a phrase boundary
+ ;; marks a phrase command in the dujisaki model
+ ;; but does not result in a pause (if I remember correctly)
+ (let ((last_token (utt.relation.last UTT 'Token)))
+ ;; if within a token, that token consists of many words and
+ ;; thus many pos and accent data: copy the information for all of them
+ (if (> suopuhe_within_token 0)
+ (begin
+ (set! suopuhe_skip_stack (append suopuhe_skip_stack (list nil)))
+ (push_pos (car suopuhe_pos_stack))
+ (push_accent (car suopuhe_accent_stack))))
+
+ (if last_token
+ (begin
+ (if hy_debug
+ (format t "Lisätään tauko %s-sanan perään (PB)\n" (item.name last_token)))
+ (item.set_feat last_token "pbreak" "PB"))))
+
+
+ ;; duplicate stack properties
+ (if (> suopuhe_within_token 0)
+ (begin
+ (push_pos (car suopuhe_pos_stack))
+ ;; (push_ini (car suopuhe_ini_stack))
+ (push_accent (car suopuhe_accent_stack))))
+
+ ;; add a phrase command?
+ UTT)
+
+
+))
+
+
+
+(define (suopuhe_init_func)
+ "(suopuhe_init_func)
+Initialisation for SUOPUHE mode"
+ (suopuhe_init_globals)
+ (set! original_xxml_elements xxml_elements) ; fixed
+ (set! xxml_elements suopuhe_elements) ; fixed
+ (set! original_token_to_words token_to_words)
+ (set! original_english_token_to_words english_token_to_words) ; new
+ (set! english_token_to_words suopuhe_token_to_words)
+ (set! token_to_words suopuhe_token_to_words))
+
+
+(define (suopuhe_exit_func) ; VALMIS
+ "(suopuhe_exit_func)
+Exit function for SUOPUHE mode"
+ (set! xxml_elements original_xxml_elements) ; ok
+ (set! token_to_words original_token_to_words)
+ (set! english_token_to_words original_english_token_to_words)
+ (set! suopuhe nil))
+
+
+(define (= x y)
+ "(= N1 N2)
+Return true if N1 and N2 are equal numbers."
+ (and (<= x y) (>= x y)))
+
+(define (suopuhe_voice_param_setup)
+ "(suopuhe_voice_param_setup)
+Set up original values for various voice parameters."
+ (set! suopuhe_pos_stack nil) ;; tieto sanaluokasta/sana
+ (set! suopuhe_accent_stack nil) ;; tieto aksentista
+ (set! suopuhe_skip_stack nil) ;; t: remove nil: don't
+ (set! pos_reversed nil)
+ (set! suopuhe_pitch_base_original (cadr (assoc 'target_f0_mean int_lr_params)))
+ (set! suopuhe_pitch_med_original (cadr (assoc 'target_f0_mean int_lr_params)))
+ (set! suopuhe_pitch_range_original (cadr (assoc 'target_f0_std int_lr_params)))
+ (set! suopuhe_rate_speed_original 1.0)
+
+ (if (and after_synth_hooks (not (consp after_synth_hooks)))
+ (set! after_synth_hooks
+ (cons after_synth_hooks (list suopuhe_adjust_volume)))
+ (set! after_synth_hooks
+ (append after_synth_hooks (list suopuhe_adjust_volume)))))
+
+(define (suopuhe_adjust_volume utt)
+ "(suopuhe_adjust_volume utt)
+Amplify or attenutate signale based on value of suopuhe_vol_factor
+and suopuhe_vol_type (absolute or relative)."
+ (set! utts (cons utt utts))
+ (cond
+ ((equal? suopuhe_vol_type 'no_change)
+ utt)
+ ((equal? suopuhe_vol_type 'absolute)
+ (utt.wave.rescale utt suopuhe_vol_factor 'absolute))
+ ((equal? suopuhe_vol_type 'relative)
+ (utt.wave.rescale utt suopuhe_vol_factor))
+ (t
+ (format stderr "SUOPUHE: volume unknown type \"%s\"\n" suopuhe_vol_type)
+ utt))
+ utt)
+
+
+
+;;; Declare the new mode to Festival
+;;; Keep this at the end of the file!
+(set! tts_text_modes
+ (cons
+ (list
+ 'suopuhe ;; mode name
+ (list
+ (list 'init_func suopuhe_init_func)
+ (list 'exit_func suopuhe_exit_func)
+ (list 'filter (format nil "%s" suopuhe_filter))
+ ;; now we can use suopuhe-mode from anywhere
+ '(analysis_type xml)
+ ))
+ tts_text_modes))
+
+(define (tts file mode)
+ "(tts FILE MODE)
+ Convert FILE to speech. MODE identifies any special treatment
+ necessary for FILE. This is simply a front end to tts_file but
+ puts the system in sync audio mode first. [see TTS]"
+ (audio_mode 'sync)
+ ;; (print (tts_find_text_mode file auto-text-mode-alist))
+ (if (and mode
+ (not (string-equal mode "suopuhe")))
+ (tts_file file mode)
+ (if (string-equal "suopuhe"
+ (tts_find_text_mode file auto-text-mode-alist))
+ (begin
+ (suopuhe_setup)
+ (tts_file file 'suopuhe))
+ (tts_file file (tts_find_text_mode file auto-text-mode-alist))))
+ (audio_mode 'sync) ;; Hmm this is probably bad
+ )
+;; korvaava versio tts-viritelmiin...
+;(define (utt.play utt)
+; "(utt.play UTT)
+;Play waveform in utt by current audio method."
+; (print (utt.relationnames utt))
+; (wave.play (utt.wave utt))
+; utt)
+
+
+
+
+(define (push_pos alkio)
+ "(push_pos alkio)
+Adds alkio to the top of the suopuhe_pos_stack."
+ (set! suopuhe_pos_stack
+ (cons alkio suopuhe_pos_stack)))
+
+(define (pop_pos)
+ "(pop_pos)
+Removes and returns the topmost whatever from the suopuhe_pos_stack."
+ (let ((alkio (car suopuhe_pos_stack)))
+ (set! suopuhe_pos_stack (cdr suopuhe_pos_stack))
+ alkio))
+
+(define (push_accent alkio)
+ "(push_accent alkio)
+Adds alkio to the top of the suopuhe_accent_stack."
+ (set! suopuhe_accent_stack
+ (cons alkio suopuhe_accent_stack)))
+
+(define (pop_accent)
+ "(pop_accent)
+Removes and returns the topmost whatever from the suopuhe_accent_stack."
+ (let ((alkio (car suopuhe_accent_stack)))
+ (set! suopuhe_accent_stack (cdr suopuhe_accent_stack))
+ alkio))
+
+
+
+
+
+;; kukin lause talletetaan omaan tiedostoonsa
+;; lausenumero on nelilukuinen merkkijono
+;; levytilan säästämiseksi talletetaan vain 100 erinimistä tiedostoa
+;; eli 99 ensimmäistä ja viimeinen...
+(define (file_id int)
+ (if (> int suopuhe_max_sentences)
+ suopuhe_max_sentences
+ int))
+
+
+
+
+
+(define (suopuhe_setup)
+ "(suopuhe_setup)
+Reset tts hooks for suopuhe mode."
+ (set! tts_hooks
+ (append
+ tts_hooks
+ (list save_suopuhe_output)))
+ ;; remove (utt.play) from tts_hooks
+ (if (not suopuhe_aloud)
+ (set! tts_hooks (remove (car (list utt.play)) tts_hooks)))
+ )
+
+(define (save_suopuhe_output utt)
+ "(save_suopuhe_output UTT)
+Saves the UTT and some textual data about it to files."
+ ;; (format stderr "%s" suopuhe_file_number)
+ (if (> suopuhe_file_number suopuhe_max_sentences)
+ (begin
+ (format stderr "Muuttuja suopuhe_file_number ylittää muuttujan suopuhe_max_sentences\nasenttaman raja-arvon! Tiedostoa ei talleteta!\n")
+ (if (not suopuhe_aloud)
+ (begin
+ (SayText "Muuttuja suopuhe_file_number ylitti muuttujan
+suopuhe_max_sentences\nasenttaman raja-arvon")
+ (SayText "Tiedostojen tallennus lopetetaan ja poistutaan ohjelmasta.")
+ (SayText "Näkemiin!")
+ (exit 0)))))
+
+ (if (and utt
+ (or suopuhe_aloud
+ (< (+ suopuhe_max_sentences 1) suopuhe_file_number)))
+ (begin
+ (let ((file (string-append
+ suopuhe_output_file_prefix
+ "suopuhe-"
+ (file_id suopuhe_file_number)
+ ".wav")))
+ (format stderr "suopuhe: saving files into %s!\n" file)
+ (utt.save.wave utt file "wav")
+ (system (string-append "chmod 622 " file)))
+ (if hy_debug
+ (begin
+ (print "SANA===LUOKKA==TAUKO===ALKU===LOPPU===")
+ (print (parts_of_speech utt))))
+ ;; write phone durations into a file
+ (let ((file (string-append
+ suopuhe_output_file_prefix
+ "suopuhe-sanakestot-"
+ (file_id suopuhe_file_number)
+ ".txt"))
+ suopuhe_fp)
+ (set! suopuhe_fp (fopen file "w"))
+ (fwrite
+ (word_durations (utt.relation.first utt 'Word))
+ suopuhe_fp)
+ (fclose suopuhe_fp)
+ (system (string-append "chmod 622 " file)))
+ ;; <= kirjoitus päättyy
+
+ (if hy_debug (print "===== SYLLABLE STRESS ====="))
+ (if hy_debug (print (syllable_stress utt)))
+ ;;(print "==FOONIT (aannekestot.txt)")
+ ;; kirjoita aannekestot tiedostoon:
+ (let ((file (string-append
+ suopuhe_output_file_prefix
+ "suopuhe-aannekestot-"
+ (file_id suopuhe_file_number)
+ ".txt"))
+ suopuhe_fp)
+ (set! suopuhe_fp (fopen file "w"))
+ (fwrite
+ (phone_durations (utt.relation.first utt 'Segment))
+ suopuhe_fp);
+ (fclose suopuhe_fp)
+ (system (string-append "chmod 622 " file)))))
+
+ ;; <= kirjoitus päättyy
+ ;;(print (aannekestot2 (utt.relation.first utt 'Segment)))
+ ;; do something more with utt, if you want...
+ (set! suopuhe_file_number (+ suopuhe_file_number 1)))
+
+
+
+(define (word_durations word)
+ "(word durations2 WORD)
+Returns the name and start and end times of the given word.
+Then recursively calls the next word if any and finally
+returns a string consisting of data from all words visited."
+ (string-append
+ (item.feat word "name") "\t"
+ ;; (item.feat word "pos") "\t"
+ ;; (item.feat word "pbreak") "\t"
+ (item.feat word "word_start") "\t"
+ (item.feat word "word_end") "\n"
+ (if (item.next word)
+ (word_durations (item.next word))
+ "")))
+
+
+(define (phone_durations phone)
+ "(phone_durations PHONE)
+Prints the name and duration of a given PHONE.
+The recursively goes through the next phones and does the same for them also."
+ (string-append
+ ;; (item.features (item.next phone)););)
+ (item.feat phone "name") "\t"
+ (item.feat phone "end") "\n"
+ ;; (item.feat phone "source_end") "\t" ;; dunno what this is...
+ ;; (item.feat phone "dur_factor") "\n" ))
+ (if (item.next phone)
+ (phone_durations (item.next phone))
+ "")))
+
+(define (parts_of_speech utt)
+ "(parts_of_speech UTT)
+Returns a list of sublists. Each sublist consists of a word's name
+and part-of-speech based on the UTTerance."
+ (utt.features utt 'Word '(name pos)))
+
+(define (syllable_stress utt)
+ "(syllable stress UTT)
+Returns a list of sublists. Each sublist consists of a syllable name
+and a syllable stress value based on the UTTerance."
+ (utt.features utt 'Syllable '(name stress)))
+
+
+(provide 'suopuhe_mode) \ No newline at end of file