home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Multimed / Multimed.zip / fest-141.zip / festival / lib / sable-mode.scm < prev    next >
Lisp/Scheme  |  1999-11-16  |  20KB  |  552 lines

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;;                                                                       ;;
  3. ;;;                Centre for Speech Technology Research                  ;;
  4. ;;;                     University of Edinburgh, UK                       ;;
  5. ;;;                         Copyright (c) 1998                            ;;
  6. ;;;                        All Rights Reserved.                           ;;
  7. ;;;                                                                       ;;
  8. ;;;  Permission is hereby granted, free of charge, to use and distribute  ;;
  9. ;;;  this software and its documentation without restriction, including   ;;
  10. ;;;  without limitation the rights to use, copy, modify, merge, publish,  ;;
  11. ;;;  distribute, sublicense, and/or sell copies of this work, and to      ;;
  12. ;;;  permit persons to whom this work is furnished to do so, subject to   ;;
  13. ;;;  the following conditions:                                            ;;
  14. ;;;   1. The code must retain the above copyright notice, this list of    ;;
  15. ;;;      conditions and the following disclaimer.                         ;;
  16. ;;;   2. Any modifications must be clearly marked as such.                ;;
  17. ;;;   3. Original authors' names are not deleted.                         ;;
  18. ;;;   4. The authors' names are not used to endorse or promote products   ;;
  19. ;;;      derived from this software without specific prior written        ;;
  20. ;;;      permission.                                                      ;;
  21. ;;;                                                                       ;;
  22. ;;;  THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK        ;;
  23. ;;;  DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING      ;;
  24. ;;;  ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT   ;;
  25. ;;;  SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE     ;;
  26. ;;;  FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES    ;;
  27. ;;;  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN   ;;
  28. ;;;  AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,          ;;
  29. ;;;  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF       ;;
  30. ;;;  THIS SOFTWARE.                                                       ;;
  31. ;;;                                                                       ;;
  32. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  33. ;;;                                                                       ;;
  34. ;;;  Festival (1.3.X) support for SABLE 0.2 the SGML/XML based mark up    ;;
  35. ;;;  language.                                                            ;;
  36. ;;;                                                                       ;;
  37. ;;;  This is XML version requiring Edinburgh's LTG's rxp XML parser as    ;;
  38. ;;;  distributed with Festival                                            ;;
  39. ;;;                                                                       ;;
  40.  
  41. (require_module 'rxp)
  42.  
  43. ;;(set! auto-text-mode-alist
  44. ;;      (cons
  45. ;;       (cons "\\.sable$" 'sable)
  46. ;;       auto-text-mode-alist))
  47.  
  48.  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  49.  ;;                                                                       ;;
  50.  ;; Remember where to find these two XML entities.                        ;;
  51.  ;;                                                                       ;;
  52.  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  53.  
  54.  
  55. (xml_register_id "-//SABLE//DTD SABLE speech mark up//EN"
  56.         (path-append libdir "Sable.v0_2.dtd")
  57.         )
  58.  
  59. (xml_register_id "-//SABLE//ENTITIES Added Latin 1 for SABLE//EN"
  60.          (path-append libdir  "sable-latin.ent")
  61.          )
  62.  
  63. ;; (print (xml_registered_ids))
  64.  
  65. (defvar SABLE_RXDOUBLE "-?\\(\\([0-9]+\\.[0-9]*\\)\\|\\([0-9]+\\)\\|\\(\\.[0-9]+\\)\\)\\([eE][---+]?[0-9]+\\)?")
  66.  
  67. (defvar sable_pitch_base_map
  68.   '((highest 1.2)
  69.     (high 1.1)
  70.     (medium 1.0)
  71.     (default 1.0)
  72.     (low 0.9)
  73.     (lowest 0.8)))
  74. (defvar sable_pitch_med_map
  75.   '((highest 1.2)
  76.     (high 1.1)
  77.     (medium 1.0)
  78.     (default 1.0)
  79.     (low 0.9)
  80.     (lowest 0.8)))
  81. (defvar sable_pitch_range_map
  82.   '((largest 1.2)
  83.     (large 1.1)
  84.     (medium 1.0)
  85.     (default 1.0)
  86.     (small 0.9)
  87.     (smallest 0.8)))
  88. (defvar sable_rate_speed_map
  89.   '((fastest 1.5)
  90.     (fast 1.2)
  91.     (medium 1.0)
  92.     (default 1.0)
  93.     (slow 0.8)
  94.     (slowest 0.6)))
  95. (defvar sable_volume_level_map
  96.   '((loudest 2.0) 
  97.     (loud 1.5)
  98.     (default 1.0)
  99.     (medium 1.0)
  100.     (quiet 0.5)))
  101.  
  102. (define (sable_init_globals)
  103.   (set! utts nil)
  104.   (set! sable_omitted_mode nil)
  105.   (set! sable_word_features_stack nil)
  106.   (set! sable_pitch_context nil)
  107.   (set! sable_vol_context nil)
  108.   (set! sable_vol_type 'no_change)
  109.   (set! sable_vol_factor 1.0)
  110.   (set! sable_current_language 'britishenglish)
  111.   (set! sable_unsupported_language nil)
  112.   (set! sable_language_stack nil)
  113.   (set! sable_current_speaker 'voice_rab_diphone)
  114.   (set! sable_speaker_stack nil)
  115. )
  116.  
  117. (define (sable_token_to_words token name)
  118.   "(sable_token_to_words utt token name)
  119. SABLE mode token specific analysis."
  120.   (cond
  121.    ((or sable_omitted_mode sable_unsupported_language)
  122.     ;; don't say anything (whole utterance)
  123.     nil)
  124.    ((string-equal "1" (item.feat token "done_sable_sub"))
  125.     ;; to catch recursive calls this when splitting up sub expressions
  126.     (sable_previous_token_to_words token name))
  127.    ((and (not (string-equal "0" (item.feat token "sable_sub")))
  128.      (string-equal "0" (item.feat token "p.sable_sub")))
  129.     (let (words (sub (item.feat token "sable_sub")))
  130.       (item.set_feat token "done_sable_sub" "1")
  131.       (set! words 
  132.         (apply append
  133.            (mapcar
  134.             (lambda (w)
  135.               (set! www (sable_previous_token_to_words token w))
  136.               www)
  137.             (read-from-string sub))))
  138.       (item.set_feat token "done_sable_sub" "0")
  139.       words))
  140.    ((string-equal "1" (item.feat token "sable_ignore"))
  141.     ;; don't say anything (individual word)
  142.     nil)
  143.    ((string-equal "1" (item.feat token "sable_ipa"))
  144.     ;; Each token is an IPA phone
  145.     (item.set_feat token "phonemes" (sable-map-ipa name))
  146.     (list name))
  147.    ((string-equal "1" (item.feat token "sable_literal"))
  148.     ;; Only deal with spell here
  149.     (let ((subwords) (subword))
  150.       (item.set_feat token "pos" token.letter_pos)
  151.       (mapcar
  152.        (lambda (letter)
  153.      ;; might be symbols or digits
  154.      (set! subword (sable_previous_token_to_words token letter))
  155.      (if subwords
  156.          (set! subwords (append subwords subword))
  157.          (set! subwords subword)))
  158.        (symbolexplode name))
  159.       subwords))
  160.    ((not (string-equal "0" (item.feat token "token_pos")))
  161.     ;; bypass the prediction stage, if English
  162.     (if (member_string (Parameter.get 'Language)
  163.                '(britishenglish americanenglish))
  164.     (builtin_english_token_to_words token name)
  165.     (sable_previous_token_to_words token name)))
  166.    ;; could be others here later
  167.    (t  
  168.     (sable_previous_token_to_words token name))))
  169.  
  170. (defvar sable_elements
  171. '(
  172.   ("(SABLE" (ATTLIST UTT)
  173.     (eval (list sable_current_speaker))  ;; so we know what state we start in
  174.     (sable_setup_voice_params)
  175.     nil
  176.   )
  177.   (")SABLE" (ATTLIST UTT)
  178.     (xxml_synth UTT)  ;;  Synthesis the remaining tokens
  179.     nil
  180.   )
  181.   ;; Utterance break elements
  182.   ("(LANGUAGE" (ATTLIST UTT)
  183.    ;; Status: probably complete 
  184.    (xxml_synth UTT)
  185.    (set! sable_language_stack 
  186.      (cons 
  187.       (list sable_current_language sable_unsupported_language)
  188.       sable_language_stack))
  189.    ;; Select a new language
  190.    (let ((language (upcase (car (xxml_attval "ID" ATTLIST)))))
  191.      (cond
  192.       ((or (string-equal language "SPANISH")
  193.        (string-equal language "ES"))
  194.        (set! sable_current_language 'spanish)
  195.        (set! sable_unsupported_language nil)
  196.        (select_language 'spanish))
  197.       ((or (string-equal language "ENGLISH")
  198.        (string-equal language "EN"))
  199.        (set! sable_current_language 'britishenglish)
  200.        (set! sable_unsupported_language nil)
  201.        (select_language 'britishenglish))
  202.       (t  ;; skip languages you don't know
  203.        ;; BUG: if current language isn't English this wont work
  204.        (apply_hooks tts_hooks
  205.             (eval (list 'Utterance 'Text
  206.                 (string-append "Some text in " language))))
  207.        (set! sable_unsupported_language t)))
  208.      nil))
  209.   (")LANGUAGE" (ATTLIST UTT)
  210.    (xxml_synth UTT)
  211.    (set! sable_unsupported_language (car (cdr (car sable_language_stack))))
  212.    (set! sable_current_language (car (car sable_language_stack)))
  213.    (set! sable_language_stack (cdr sable_language_stack))
  214.    (if (not sable_omitted_mode)
  215.        (begin
  216.      (select_language sable_current_language)
  217.      (sable_setup_voice_params)))
  218.    nil)
  219.   ("(SPEAKER" (ATTLIST UTT)
  220.    ;; Status: GENDER/AGE ignored, should be done by sable-def-speaker 
  221.    ;;         function to define Festival voices to SABLE
  222.    (xxml_synth UTT)
  223.    (set! sable_speaker_stack (cons sable_current_speaker sable_speaker_stack))
  224.    (cond
  225.     ((not equal? sable_current_language 'britishenglish)
  226.      (print "SABLE: choosen unknown voice, current voice unchanged"))
  227.     ((equal? (car (xxml_attval "NAME" ATTLIST)) 'male1)
  228.      (set! sable_current_speaker 'voice_rab_diphone)
  229.      (voice_rab_diphone))
  230.     ((equal? (car (xxml_attval "NAME" ATTLIST)) 'male2)
  231.      (set! sable_current_speaker 'voice_don_diphone)
  232.      (voice_don_diphone))
  233.     ((equal? (car (xxml_attval "NAME" ATTLIST)) 'male3)
  234.      (set! sable_current_speaker 'voice_ked_diphone)
  235.      (voice_ked_diphone))
  236.     (t
  237.      (print "SABLE: selecting unknown voice")
  238.      (set! sable_current_speaker voice_rab_diphone)
  239.      (voice_rab_diphone)))
  240.     (sable_setup_voice_params)
  241.    nil)
  242.   (")SPEAKER" (ATTLIST UTT)
  243.    (xxml_synth UTT)
  244.    (set! sable_current_speaker (car sable_speaker_stack))
  245.    (set! sable_speaker_stack (cdr sable_speaker_stack))
  246.    (eval (list sable_current_speaker))
  247.    (sable_setup_voice_params)
  248.    nil)
  249.   ("BREAK" (ATTLIST UTT)
  250.    ;; Status: probably complete
  251.    ;; may cause an utterance break
  252.    (let ((level (upcase (car (xxml_attval "LEVEL" ATTLIST)))))
  253.      (cond
  254.       ((null UTT) nil)
  255.       ((string-equal "LARGE" level)
  256.        (xxml_synth UTT)
  257.        nil)
  258.       (t
  259.        (let ((last_token (utt.relation.last UTT'Token)))
  260.      (if last_token
  261.          (item.set_feat last_token "pbreak" "B"))
  262.      UTT)))))
  263.   ("(DIV" (ATLIST UTT)
  264.    ;; Status: probably complete
  265.    (xxml_synth UTT)
  266.    nil)
  267.   ("AUDIO" (ATTLIST UTT)
  268.    ;; Status: MODE (background) ignored, only insertion supported
  269.    ;; mime type of file also ignored, as its LEVEL
  270.    (let ((tmpfile (make_tmp_filename)))
  271.      ;; ignoring mode-background (and will for sometime)
  272.      ;; ignoring level option
  273.      (xxml_synth UTT)  ;; synthesizing anything ready to be synthesized
  274.      (get_url (car (xxml_attval "SRC" ATTLIST)) tmpfile)
  275.      (apply_hooks tts_hooks
  276.           (eval (list 'Utterance 'Wave tmpfile)))
  277.      (delete-file tmpfile)
  278.      nil))
  279.   ("(EMPH" (ATTLIST UTT)
  280.    ;; Status: nesting makes no difference, levels ignored
  281.    ;; Festival is particularly bad at adding specific emphasis
  282.    ;; that's what happens when you use statistical methods that
  283.    ;; don't include any notion of emphasis
  284.    ;; This is *not* recursive and only one level of EMPH supported
  285.    (sable_push_word_features)
  286.    (set! xxml_word_features 
  287.      (cons (list "dur_stretch" 1.6)
  288.            (cons
  289.         (list "EMPH" "1") xxml_word_features)))
  290.    UTT)
  291.   (")EMPH" (ATTLIST UTT)
  292.    (set! xxml_word_features (sable_pop_word_features))
  293.    UTT)
  294.   ("(PITCH" (ATTLIST UTT)
  295.    ;; Status: probably complete
  296.    ;; At present festival requires an utterance break here
  297.    (xxml_synth UTT)
  298.    (set! sable_pitch_context (cons int_lr_params sable_pitch_context))
  299.    (let ((base (sable_interpret_param
  300.         (car (xxml_attval "BASE" ATTLIST))
  301.         sable_pitch_base_map
  302.         (cadr (assoc 'target_f0_mean int_lr_params))
  303.         sable_pitch_base_original))
  304.      (med (sable_interpret_param
  305.            (car (xxml_attval "MED" ATTLIST))
  306.            sable_pitch_med_map
  307.            (cadr (assoc 'target_f0_mean int_lr_params))
  308.            sable_pitch_med_original))
  309.      (range (sable_interpret_param
  310.          (car (xxml_attval "RANGE" ATTLIST))
  311.          sable_pitch_range_map
  312.          (cadr (assoc 'target_f0_std int_lr_params))
  313.          sable_pitch_range_original))
  314.      (oldmean (cadr (assoc 'target_f0_mean int_lr_params))))
  315.      ;; Festival (if it supports anything) supports mean and std
  316.      ;; so we treat base as med if med doesn't seem to do anything
  317.      (if (equal? med oldmean)
  318.      (set! med base))
  319.      (set! int_lr_params
  320.        (cons
  321.         (list 'target_f0_mean med)
  322.         (cons
  323.          (list 'target_f0_std range)
  324.          int_lr_params)))
  325.    nil))
  326.   (")PITCH" (ATTLIST UTT)
  327.    (xxml_synth UTT)
  328.    (set! int_lr_params (car sable_pitch_context))
  329.    (set! sable_pitch_context (cdr sable_pitch_context))
  330.    nil)
  331.   ("(RATE" (ATTLIST UTT)
  332.    ;; Status: can't deal with absolute word per minute SPEED.
  333.    (sable_push_word_features)
  334.    ;; can't deal with words per minute value
  335.    (let ((rate (sable_interpret_param
  336.         (car (xxml_attval "SPEED" ATTLIST))
  337.         sable_rate_speed_map
  338.         (sable_find_fval "dur_stretch" xxml_word_features 1.0)
  339.         sable_rate_speed_original)))
  340.      (set! xxml_word_features 
  341.        (cons (list "dur_stretch" (/ 1.0 rate)) xxml_word_features))
  342.      UTT))
  343.   (")RATE" (ATTLIST UTT)
  344.    (set! xxml_word_features (sable_pop_word_features))
  345.    UTT)
  346.   ("(VOLUME" (ATTLIST UTT)
  347.    ;; Status: probably complete
  348.    ;; At present festival requires an utterance break here
  349.    (xxml_synth UTT)
  350.    (set! sable_vol_context (cons (list sable_vol_type sable_vol_factor)
  351.                  sable_vol_context))
  352.    (let ((level (sable_interpret_param
  353.         (car (xxml_attval "LEVEL" ATTLIST))
  354.         sable_volume_level_map
  355.         sable_vol_factor
  356.         1.0)))
  357.      (cond
  358.       ((string-matches (car (xxml_attval "LEVEL" ATTLIST)) ".*%")
  359.        (set! sable_vol_type 'relative))
  360.       ((string-matches (car (xxml_attval "LEVEL" ATTLIST))  SABLE_RXDOUBLE)
  361.        (set! sable_vol_type 'absolute))
  362.       (t
  363.        (set! sable_vol_type 'relative)))
  364.      (set! sable_vol_factor level))
  365.    nil)
  366.   (")VOLUME" (ATTLIST UTT)
  367.    (xxml_synth UTT)
  368.    (set! sable_vol_type (car (car sable_vol_context)))
  369.    (set! sable_vol_factor (car (cdr (car sable_vol_context))))
  370.    (set! sable_vol_context (cdr sable_vol_context))
  371.    nil)
  372.   ("(ENGINE" (ATTLIST UTT)
  373.    ;; Status: probably complete
  374.    (xxml_synth UTT)
  375.    (if (string-matches (car (xxml_attval "ID" ATTLIST)) "festival.*")
  376.        (let ((datastr ""))
  377.      (mapcar
  378.       (lambda (c) (set! datastr (string-append datastr " " c)))
  379.       (xxml_attval "DATA" ATTLIST))
  380.      (apply_hooks tts_hooks (eval (list 'Utterance 'Text datastr)))
  381.      (set! sable_omitted_mode t)) ;; ignore contents 
  382.        ;; else 
  383.        ;;  its not relevant to me
  384.        )
  385.    nil)
  386.   (")ENGINE" (ATTLIST UTT)
  387.    (xxml_synth UTT)
  388.    (set! sable_omitted_mode nil)
  389.    nil)
  390.   ("MARKER" (ATTLIST UTT)
  391.    ;; Status: does nothing
  392.    ;; Can't support this without low-level control of audio spooler
  393.    (format t "SABLE: marker \"%s\"\n" 
  394.        (car (xxml_attval "MARK" ATTLIST)))
  395.    UTT)
  396.   ("(PRON" (ATTLIST UTT)
  397.    ;; Status: IPA currently ignored
  398.    (sable_push_word_features)
  399.    ;; can't deal with words per minute value
  400.    (let ((ipa (xxml_attval "IPA" ATTLIST))
  401.      (sub (xxml_attval "SUB" ATTLIST)))
  402.      (cond
  403.       (ipa
  404.        (format t "SABLE: ipa ignored\n")
  405.        (set! xxml_word_features 
  406.          (cons (list "sable_ignore" "1") xxml_word_features)))
  407.       (sub
  408.        (set! xxml_word_features 
  409.          (cons (list "sable_sub" (format nil "%l" sub))
  410.            xxml_word_features))
  411.        (set! xxml_word_features 
  412.          (cons (list "sable_ignore" "1") xxml_word_features))))
  413.      UTT))
  414.   (")PRON" (ATTLIST UTT)
  415.    (set! xxml_word_features (sable_pop_word_features))
  416.    UTT)
  417.   ("(SAYAS" (ATTLIST UTT)
  418.    ;; Status: only a few of the types are dealt with
  419.    (sable_push_word_features)
  420.     (set! sable_utt UTT)
  421.    ;; can't deal with words per minute value
  422.    (let ((mode (downcase (car (xxml_attval "MODE" ATTLIST))))
  423.      (modetype (car (xxml_attval "MODETYPE" ATTLIST))))
  424.      (cond
  425.       ((string-equal mode "literal")
  426.        (set! xxml_word_features 
  427.          (cons (list "sable_literal" "1") xxml_word_features)))
  428.       ((string-equal mode "phone")
  429.        (set! xxml_word_features 
  430.          (cons (list "token_pos" "digits") xxml_word_features)))
  431.       ((string-equal mode "ordinal")
  432.        (set! xxml_word_features 
  433.          (cons (list "token_pos" "ordinal") xxml_word_features)))
  434.       ((string-equal mode "cardinal")
  435.        (set! xxml_word_features 
  436.          (cons (list "token_pos" "cardinal") xxml_word_features)))
  437.       (t
  438.        ;; blindly trust festival to get it right 
  439.        t))
  440.      UTT))
  441.   (")SAYAS" (ATTLIST UTT)
  442.    (set! xxml_word_features (sable_pop_word_features))
  443.    UTT)
  444.  
  445.          
  446. ))
  447.  
  448. (define (sable_init_func)
  449.   "(sable_init_func)
  450. Initialisation for SABLE mode"
  451.   (sable_init_globals)
  452.   (voice_rab_diphone)
  453.   (set! sable_previous_elements xxml_elements)
  454.   (set! xxml_elements sable_elements)
  455.   (set! sable_previous_token_to_words english_token_to_words)
  456.   (set! english_token_to_words sable_token_to_words)
  457.   (set! token_to_words sable_token_to_words))
  458.  
  459. (define (sable_exit_func)
  460.   "(sable_exit_func)
  461. Exit function for SABLE mode"
  462.   (set! xxml_elements sable_previous_elements)
  463.   (set! token_to_words sable_previous_token_to_words)
  464.   (set! english_token_to_words sable_previous_token_to_words))
  465.  
  466. (define (sable_push_word_features)
  467. "(sable_push_word_features)
  468. Save current word features on stack."
  469.   (set! sable_word_features_stack 
  470.     (cons xxml_word_features sable_word_features_stack)))
  471.  
  472. (define (sable_adjust_volume utt)
  473.   "(sable_adjust_volume utt)
  474. Amplify or attenutate signale based on value of sable_vol_factor
  475. and sable_vol_type (absolute or relative)."
  476.   (set! utts (cons utt utts))
  477.   (cond
  478.    ((equal? sable_vol_type 'no_change)
  479.     utt)
  480.    ((equal? sable_vol_type 'absolute)
  481.     (utt.wave.rescale utt sable_vol_factor 'absolute))
  482.    ((equal? sable_vol_type 'relative)
  483.     (utt.wave.rescale utt sable_vol_factor))
  484.    (t
  485.     (format stderr "SABLE: volume unknown type \"%s\"\n" sable_vol_type)
  486.     utt))
  487.    utt)
  488.  
  489. (define (sable_pop_word_features)
  490. "(sable_pop_word_features)
  491. Pop word features from stack."
  492.   (let ((r (car sable_word_features_stack)))
  493.     (set! sable_word_features_stack (cdr sable_word_features_stack))
  494.     r))
  495.  
  496. (define (sable_find_fval feat flist def)
  497.   (cond
  498.    ((null flist) def)
  499.    ((string-equal feat (car (car flist)))
  500.     (car (cdr (car flist))))
  501.    (t
  502.     (sable_find_fval feat (cdr flist) def))))
  503.  
  504. (define (sable_interpret_param ident map original current)
  505. "(sable_interpret_param IDENT MAP ORIGINAL CURRENT)
  506. If IDENT is in map return ORIGINAL times value in map, otherwise
  507. treat IDENT of the form +/-N% and modify CURRENT accordingly."
  508.   (let ((mm (assoc ident map)))
  509.     (cond 
  510.      (mm
  511.       (* original (car (cdr mm))))
  512.      ((string-matches ident SABLE_RXDOUBLE)
  513.       (parse-number ident))
  514.      ((string-matches ident ".*%")
  515.       (+ current (* current (/ (parse-number (string-before ident "%")) 
  516.                    100.0))))
  517. ;;     ((string-matches ident ".*%")
  518. ;;      (* current (/ (parse-number (string-before ident "%")) 100.0)))
  519.      ((not ident) current)
  520.      (t
  521.       (format stderr "SABLE: modifier \"%s\" not of float, tag or +/-N\n"
  522.           ident)
  523.       current))))
  524.  
  525. (define (sable_setup_voice_params)
  526. "(sable_setup_voice_params)
  527. Set up original values for various voice parameters."
  528.  (set! sable_pitch_base_original (cadr (assoc 'target_f0_mean int_lr_params)))
  529.  (set! sable_pitch_med_original (cadr (assoc 'target_f0_mean int_lr_params)))
  530.  (set! sable_pitch_range_original (cadr (assoc 'target_f0_std int_lr_params)))
  531.  (set! sable_rate_speed_original 1.0)
  532.  (if (and after_synth_hooks (not (consp after_synth_hooks)))
  533.      (set! after_synth_hooks 
  534.        (cons after_synth_hooks (list sable_adjust_volume)))
  535.      (set! after_synth_hooks 
  536.        (append after_synth_hooks (list sable_adjust_volume))))
  537. )
  538.  
  539. ;;; Declare the new mode to Festival
  540. (set! tts_text_modes
  541.    (cons
  542.     (list
  543.       'sable   ;; mode name
  544.       (list         
  545.        (list 'init_func sable_init_func)
  546.        (list 'exit_func sable_exit_func)
  547.        '(analysis_type xml)
  548.        ))
  549.     tts_text_modes))
  550.  
  551. (provide 'sable-mode)
  552.