;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<--OGI-->;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                                        ;;
;;             Center for Spoken Language Understanding                   ;;
;;        Oregon Graduate Institute of Science & Technology               ;;
;;                         Portland, OR USA                               ;;
;;                        Copyright (c) 1999                              ;;
;;                                                                        ;;
;;      This module is not part of the CSTR/University of Edinburgh       ;;
;;               release of the Festival TTS system.                      ;;
;;                                                                        ;;
;;  In addition to any conditions disclaimers below, please see the file  ;;
;;  "license_ogi_tts.txt" distributed with this software for information  ;;
;;  on usage and redistribution, and for a DISCLAIMER OF ALL WARRANTIES.  ;;
;;                                                                        ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;<--OGI-->;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;  Set up diphone voice
;;;  AEC diphones: male American English collected May 1997 by OGI

(require 'phrase)
(require 'pos)
(require 'tobi)
(require 'f2bf0lr)
(require 'ogi_worldbet_phones)
(require 'ogi_lexicons)
(require 'ogi_token)
(require 'ogi_postlex)
(require 'ogi_phrase)
(require 'ogi_lts_worldbet)
(require 'ogi_kddurtreeZ_wb)
(require 'ogi_hack)
(require 'ogi_unitsel)
(require 'ogi_synthesis)


;;;  Set up the MOBY+CMU lexicon
(setup_ogi_lex)

;;; Use the grouped file by default
(defvar aecdi_grouped_or_ungrouped 'grouped)

;; Location at runtime
(defvar aec_diphone_dir (cdr (assoc 'aec_diphone voice-locations))
  "aec_diphone_dir
  The default directory for the aec diphone database.")
(set! load-path (cons (path-append aec_diphone_dir "festvox") load-path))
 

(define (voice_aec_diphone)
"(voice_aec_diphone)
 Set up the current voice to be an American male AEC using
 the AEC diphone set and OGIresLPC."

  ;; reset global parameters
  (voice_reset)

  ;; Phone set
  (Parameter.set 'Language 'americanenglish)
  (Parameter.set 'PhoneSet 'worldbet)
  (PhoneSet.select 'worldbet)
  
  ;; Token to word rules
  (set! token_to_words english_token_to_words)
  (set! token_pos_cart_trees OGI_english_token_pos_cart_trees)
  
  ;; POS tagger
  (set! pos_lex_name "english_poslex")
  (set! pos_ngram_name 'english_pos_ngram)
  (set! pos_supported t)
  (set! guess_pos english_guess_pos)   ;; need this for accents
  (set! pos_map english_pos_map_wp39_to_wp20)
  ;(set! pos_map nil)

  ;; Lexicon selection
  (lex.select "ogi")
  
  ;; Postlexical rules (some defined in "ogi_postlex.scm")
  (set! postlex_vowel_reduce_cart_tree  OGI_postlex_vowel_reduce_cart_tree_hand) ;; must set this!
  (set! postlex_rules_hooks (list PostLex_Reduce The_Before_Vowel postlex_apos_s_check flap_hack))
  
  ;; Phrase prediction
  (set! festival-phrasify Phrasify)
  (set! Phrasify OGI_PuncPhrasify)
  (Parameter.set 'Phrase_Method 'prob_models)  
  (set! phr_break_params OGI_english_phr_break_params)
  
  ;; Accent and tone prediction
  (set! int_tone_cart_tree f2b_int_tone_cart_tree)
  (set! int_accent_cart_tree f2b_int_accent_cart_tree)
  
  ;; F0 prediction
  (set! f0_lr_start f2b_f0_lr_start)
  (set! f0_lr_mid f2b_f0_lr_mid)
  (set! f0_lr_end f2b_f0_lr_end)
  (Parameter.set 'Int_Method Intonation_Tree)
  (set! int_lr_params
	'((target_f0_mean 105) (target_f0_std 19)
	  (model_f0_mean 170) (model_f0_std 34)))
  (Parameter.set 'Int_Target_Method Int_Targets_LR)
  
  ;; Duration prediction
  (set! duration_cart_tree kd_duration_cart_tree_wb)
  (set! duration_ph_info kd_durs_wb)
  (Parameter.set 'Duration_Method Duration_Tree_ZScores)
  (Parameter.set 'Duration_Stretch 1.00)

  ;; diphone unit selection fallbacks
  (set! ogi_di_alt_L '((m= (m)) (n= (n)) (l= (l)) (h (pau)) 
		       (j (i:)) (dx (t d)) (& (^))
		       (k>9r (k)) (k>w (k)) (k>l (k))
		       (p>9r (p)) (p>w (p)) (p>l (p))
		       (t>9r (t)) (t>w (t)) (t>l (t)) (t>9r<s (t>9r t<s t)) 
		       (p>9r<s (p>9r p)) (t<s (t))))

  (set! ogi_di_alt_R '((m= (m)) (n= (n)) (l= (l)) (h (pau)) 
		       (j (i:)) (dx (t d)) (& (^))
		       (k>9r (k)) (k>w (k)) (k>l (k))
		       (p>9r (p)) (p>w (p)) (p>l (p))
		       (t>9r (t)) (t>w (t)) (t>l (t)) 
		       (t>9r<s (t>9r t<s t)) (p>9r<s (p>9r p))
		       (t<s (t))))

  (set! ogi_di_default "pau-h")

  (Parameter.set 'Synth_Method 'OGIdiphone)
  (OGIdbase.activate "aec_diphone")      
  (OGIresLPC.init aecdi_OGI_syn_params)  
  (set! current_voice_reset aecdi_voice_reset)
  (set! current-voice 'aec_diphone)  
)
(define (aecdi_voice_reset)
  (set! Phrasify festival-phrasify)
  )

;; Context-dependent smoothing:
;;   (feat val int) for each
;;   Can put any feat,val pair here, as long as feat is defined in phoneset definition.
;;   Smoother setup algorithm iterates through list until feat, val is matched, then uses int as 
;;     smoothing window length.  This could be improved.
(set! aecdi_smooth_spectra   ;;; max number of frames to use in smoothing LPC at joins
      '(spectra_smooth
        ((vc + 5)   ; vowel
         (ctype s 0) ; stop
         (ctype f 2) ; fricative
         (ctype a 0) ; affricate
         (ctype n 5) ; nasal
         (ctype l 5) ; lateral
         (ctype r 5) ; approximant
         )))

(set! aecdi_smooth_power   ;;; max number of frames to use in smoothing power at joins
      '(power_smooth
        ((vc + 6)   ; vowel
         (ctype s 0) ; stop
         (ctype f 2) ; fricative
         (ctype a 0) ; affricate
         (ctype n 5) ; nasal
         (ctype l 5) ; lateral
         (ctype r 5) ; approximant 
         )))

;;
;;  Residual LPC synthesizer parameters - used by OGIresLPC.init
;;
(set! aecdi_OGI_syn_params  
 (list
  '(F0_default 50.0)      ;; default Fo used if can't find any Fo targets
  '(T0_UV_thresh 0.020)   ;; used to make V/UV decision 
  '(T0_UV_pm 0.010)       ;; used to place UV pmarks
  '(post_gain 1.0)        ;; adjust final loudness
  '(deemphasis 0.94)      ;; opposite of preemphasis (lowpass filter)
  '(mod_method "direct")  ;; method for realizing prosodic targets
  '(beta_smooth 5)        ;; smoother len for pitch mod factor in "soft" mod method
  '(window_type "trapezoid") 
  '(smooth_cross_ph_join "Y") ;; smooth across joins at phone boundaries?
  '(spectra_match_or_replace "match") ;; for join smoothing
  '(power_match_or_replace   "match") ;; for join smoothing
  aecdi_smooth_spectra
  aecdi_smooth_power
;  mwmdi_dump
  ))


(define (init_aec_diphone)
"(init_aec_diphone)
  Initialise the AEC diphone database.  This sets up the 16K version
  for residual excited LPC."
(if (equal? aecdi_grouped_or_ungrouped 'ungrouped)

    ;;  ungrouped
    (OGIdbase.init
     (list
      '(dbname aec_diphone)
      (list 'unitdic_file (path-append aec_diphone_dir "festvox" "aecdiph.msec"))
      (list 'gain_file (path-append aec_diphone_dir "festvox" "aecgain.dat"))
      '(phoneset "worldbet")  
      '(base_dir "/u/macon/TTS/tts_data/aec/")
      '(lpc_dir "lpc16/")
      '(lpc_ext ".lpc")
      '(exc_dir "lpc16/")
      '(exc_ext ".res")
      '(pm_dir "pm/")
      '(pm_ext ".pmv")
      '(data_type "resLPC")
      '(access_mode "ondemand")
      '(samp_freq 16000)
      '(sig_band 0.010)
      '(isCompressed "Y") ;; if "Y", compress when saving group file
      '(preemph 0.96)  
      ))

    ;;  grouped -- parameters set here override those in groupfile
    (OGIdbase.init   
     (list
      '(dbname aec_diphone)
      (list 'groupfile (path-append aec_diphone_dir "group" "aec_di_resLPC.group"))
      '(access_mode "ondemand")
      ))
    t)
)

(init_aec_diphone)


(proclaim_voice
 'aec_diphone
 '((language english)
   (gender male)
   (dialect american)
   (description
    "This voice provides an American English male voice using a
     residual excited LPC diphone synthesis module created at
     OGI.  It uses a lexicon compiled from MOBY and CMU lexicons, and
     other trained modules used by CSTR voices.")))

(provide 'aec_diphone)





