523 lines
17 KiB
Scheme
523 lines
17 KiB
Scheme
;; ---------------------------------------------------------------- ;;
|
|
;; Nagoya Institute of Technology and ;;
|
|
;; Carnegie Mellon University ;;
|
|
;; Copyright (c) 2002 ;;
|
|
;; All Rights Reserved. ;;
|
|
;; ;;
|
|
;; Permission is hereby granted, free of charge, to use and ;;
|
|
;; distribute this software and its documentation without ;;
|
|
;; restriction, including without limitation the rights to use, ;;
|
|
;; copy, modify, merge, publish, distribute, sublicense, and/or ;;
|
|
;; sell copies of this work, and to permit persons to whom this ;;
|
|
;; work is furnished to do so, subject to the following conditions: ;;
|
|
;; ;;
|
|
;; 1. The code must retain the above copyright notice, this list ;;
|
|
;; of conditions and the following disclaimer. ;;
|
|
;; ;;
|
|
;; 2. Any modifications must be clearly marked as such. ;;
|
|
;; ;;
|
|
;; 3. Original authors' names are not deleted. ;;
|
|
;; ;;
|
|
;; 4. The authors' names are not used to endorse or promote ;;
|
|
;; products derived from this software without specific prior ;;
|
|
;; written permission. ;;
|
|
;; ;;
|
|
;; NAGOYA INSTITUTE OF TECHNOLOGY, CARNEGIE MELLON UNIVERSITY AND ;;
|
|
;; THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL WARRANTIES WITH ;;
|
|
;; REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF ;;
|
|
;; MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NAGOYA INSTITUTE ;;
|
|
;; OF TECHNOLOGY, CARNEGIE MELLON UNIVERSITY NOR THE CONTRIBUTORS ;;
|
|
;; BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ;;
|
|
;; ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR ;;
|
|
;; PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER ;;
|
|
;; TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR ;;
|
|
;; PERFORMANCE OF THIS SOFTWARE. ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; Generic HTS support code and specific features ;;
|
|
;; http://hts.ics.nitech.ac.jp ;;
|
|
;; Author : Alan W Black <awb@cs.cmu.edu> ;;
|
|
;; Date : August 2002 (and April 2004) ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;; ;;
|
|
;; Still has language specific features in here, that will have to ;;
|
|
;; move out to the voices ;;
|
|
;; ;;
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
|
|
(defvar hts_synth_pre_hooks nil)
|
|
(defvar hts_synth_post_hooks nil)
|
|
(defvar hts_engine_params nil)
|
|
|
|
(defvar hts_duration_stretch 0)
|
|
(defvar hts_f0_mean 0)
|
|
(defvar hts_f0_std 1)
|
|
(defvar hts_fw_factor 0.42)
|
|
(defvar hts_total_length 0.0)
|
|
(defvar hts_uv_threshold 0.5)
|
|
(defvar hts_use_phone_align 0)
|
|
|
|
(defSynthType HTS
|
|
(let ((featfile (make_tmp_filename))
|
|
(mcepfile (make_tmp_filename))
|
|
(f0file (make_tmp_filename))
|
|
(wavfile (make_tmp_filename))
|
|
(labfile (make_tmp_filename)))
|
|
|
|
(apply_hooks hts_synth_pre_hooks utt)
|
|
|
|
(set! hts_output_params
|
|
(list
|
|
(list "-labelfile" featfile)
|
|
(list "-om" mcepfile)
|
|
(list "-of" f0file)
|
|
(list "-or" wavfile)
|
|
(list "-od" labfile))
|
|
)
|
|
|
|
(hts_dump_feats utt hts_feats_list featfile)
|
|
|
|
(HTS_Synthesize utt)
|
|
|
|
(delete-file featfile)
|
|
(delete-file mcepfile)
|
|
(delete-file f0file)
|
|
(delete-file wavfile)
|
|
(delete-file labfile)
|
|
|
|
(apply_hooks hts_synth_post_hooks utt)
|
|
utt)
|
|
)
|
|
|
|
(define (hts_feats_output ofd s)
|
|
"This is bad as it makes decisions about what the feats are"
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;; SEGMENT
|
|
|
|
; boundary
|
|
(format ofd "%10.0f %10.0f "
|
|
(* 10000000 (item.feat s "segment_start"))
|
|
(* 10000000 (item.feat s "segment_end")))
|
|
|
|
; pp.name
|
|
(format ofd "%s" (if (string-equal "0" (item.feat s "p.p.name"))
|
|
"x" (item.feat s "p.p.name")))
|
|
; p.name
|
|
(format ofd "^%s" (if (string-equal "0" (item.feat s "p.name"))
|
|
"x" (item.feat s "p.name")))
|
|
; c.name
|
|
(format ofd "-%s" (if (string-equal "0" (item.feat s "name"))
|
|
"x" (item.feat s "name")))
|
|
; n.name
|
|
(format ofd "+%s" (if (string-equal "0" (item.feat s "n.name"))
|
|
"x" (item.feat s "n.name")))
|
|
; nn.name
|
|
(format ofd "=%s" (if (string-equal "0" (item.feat s "n.n.name"))
|
|
"x" (item.feat s "n.n.name")))
|
|
|
|
; position in syllable (segment)
|
|
(format ofd "@")
|
|
(format ofd "%s" (if (string-equal "pau" (item.feat s "name"))
|
|
"x" (+ 1 (item.feat s "pos_in_syl"))))
|
|
(format ofd "_%s" (if (string-equal "pau" (item.feat s "name"))
|
|
"x" (- (item.feat s "R:SylStructure.parent.R:Syllable.syl_numphones")
|
|
(item.feat s "pos_in_syl"))))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
;;; SYLLABLE
|
|
|
|
;; previous syllable
|
|
|
|
; p.stress
|
|
(format ofd "/A:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "p.R:SylStructure.parent.R:Syllable.stress")
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.p.stress")))
|
|
; p.accent
|
|
(format ofd "_%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "p.R:SylStructure.parent.R:Syllable.accented")
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.p.accented")))
|
|
; p.length
|
|
(format ofd "_%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "p.R:SylStructure.parent.R:Syllable.syl_numphones")
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.p.syl_numphones")))
|
|
;; current syllable
|
|
|
|
; c.stress
|
|
(format ofd "/B:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.stress")))
|
|
; c.accent
|
|
(format ofd "-%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.accented")))
|
|
; c.length
|
|
(format ofd "-%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.syl_numphones")))
|
|
|
|
; position in word (syllable)
|
|
(format ofd "@%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(+ 1 (item.feat s "R:SylStructure.parent.R:Syllable.pos_in_word"))))
|
|
(format ofd "-%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(-
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.word_numsyls")
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.pos_in_word"))))
|
|
|
|
; position in phrase (syllable)
|
|
(format ofd "&%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(+ 1
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.syl_in"))))
|
|
(format ofd "-%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(+ 1
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.syl_out"))))
|
|
|
|
; position in phrase (stressed syllable)
|
|
(format ofd "#%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(+ 1
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.ssyl_in"))))
|
|
(format ofd "-%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(+ 1
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.ssyl_out"))))
|
|
|
|
; position in phrase (accented syllable)
|
|
(format ofd "$%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(+ 1
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.asyl_in"))))
|
|
(format ofd "-%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(+ 1
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.asyl_out"))))
|
|
|
|
; distance from stressed syllable
|
|
(format ofd "!%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_p_stress")))
|
|
(format ofd "-%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_n_stress")))
|
|
|
|
; distance from accented syllable
|
|
(format ofd ";%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_p_accent")))
|
|
(format ofd "-%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.lisp_distance_to_n_accent")))
|
|
|
|
; name of the vowel of current syllable
|
|
(format ofd "|%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.syl_vowel")))
|
|
|
|
;; next syllable
|
|
(format ofd "/C:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "n.R:SylStructure.parent.R:Syllable.stress")
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.n.stress")))
|
|
; n.accent
|
|
(format ofd "+%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "n.R:SylStructure.parent.R:Syllable.accented")
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.n.accented")))
|
|
; n.length
|
|
(format ofd "+%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "n.R:SylStructure.parent.R:Syllable.syl_numphones")
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.n.syl_numphones")))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; WORD
|
|
|
|
;;;;;;;;;;;;;;;;;;
|
|
;; previous word
|
|
|
|
; p.gpos
|
|
(format ofd "/D:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "p.R:SylStructure.parent.parent.R:Word.gpos")
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.p.gpos")))
|
|
; p.lenght (syllable)
|
|
(format ofd "_%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "p.R:SylStructure.parent.parent.R:Word.word_numsyls")
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.p.word_numsyls")))
|
|
|
|
;;;;;;;;;;;;;;;;;
|
|
;; current word
|
|
|
|
; c.gpos
|
|
(format ofd "/E:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.gpos")))
|
|
; c.lenght (syllable)
|
|
(format ofd "+%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.word_numsyls")))
|
|
|
|
; position in phrase (word)
|
|
(format ofd "@%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(+ 1 (item.feat s "R:SylStructure.parent.parent.R:Word.pos_in_phrase"))))
|
|
(format ofd "+%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.words_out")))
|
|
|
|
; position in phrase (content word)
|
|
(format ofd "&%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.content_words_in")))
|
|
(format ofd "+%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.content_words_out")))
|
|
|
|
; distance from content word in phrase
|
|
(format ofd "#%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.lisp_distance_to_p_content")))
|
|
(format ofd "+%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.lisp_distance_to_n_content")))
|
|
|
|
;;;;;;;;;;;;;;
|
|
;; next word
|
|
|
|
; n.gpos
|
|
(format ofd "/F:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "n.R:SylStructure.parent.parent.R:Word.gpos")
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.n.gpos")))
|
|
; n.lenghte (syllable)
|
|
(format ofd "_%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "n.R:SylStructure.parent.parent.R:Word.word_numsyls")
|
|
(item.feat s "R:SylStructure.parent.parent.R:Word.n.word_numsyls")))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; PHRASE
|
|
|
|
;;;;;;;;;;;;;;;;;;;;
|
|
;; previous phrase
|
|
|
|
; length of previous phrase (syllable)
|
|
(format ofd "/G:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")
|
|
(item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.p.lisp_num_syls_in_phrase")))
|
|
|
|
; length of previous phrase (word)
|
|
(format ofd "_%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "p.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")
|
|
(item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.p.lisp_num_words_in_phrase")))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;
|
|
;; current phrase
|
|
|
|
; length of current phrase (syllable)
|
|
(format ofd "/H:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")))
|
|
|
|
; length of current phrase (word)
|
|
(format ofd "=%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
"x"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")))
|
|
|
|
; position in major phrase (phrase)
|
|
(format ofd "@%s"
|
|
(+ 1 (item.feat s "R:SylStructure.parent.R:Syllable.sub_phrases")))
|
|
(format ofd "=%s"
|
|
(-
|
|
(item.feat s "lisp_total_phrases")
|
|
(item.feat s "R:SylStructure.parent.R:Syllable.sub_phrases")))
|
|
|
|
; type of tobi endtone of current phrase
|
|
(format ofd "|%s"
|
|
(item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.daughtern.R:SylStructure.daughtern.tobi_endtone"))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;
|
|
;; next phrase
|
|
|
|
; length of next phrase (syllable)
|
|
(format ofd "/I:%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase")
|
|
(item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.n.lisp_num_syls_in_phrase")))
|
|
|
|
; length of next phrase (word)
|
|
(format ofd "=%s"
|
|
(if (string-equal "pau" (item.feat s "name"))
|
|
(item.feat s "n.R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase")
|
|
(item.feat s "R:SylStructure.parent.parent.R:Phrase.parent.n.lisp_num_words_in_phrase")))
|
|
|
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
; UTTERANCE
|
|
|
|
; length (syllable)
|
|
(format ofd "/J:%s" (item.feat s "lisp_total_syls"))
|
|
|
|
; length (word)
|
|
(format ofd "+%s" (item.feat s "lisp_total_words"))
|
|
|
|
; length (phrase)
|
|
(format ofd "-%s" (item.feat s "lisp_total_phrases"))
|
|
|
|
(format ofd "\n")
|
|
|
|
)
|
|
|
|
(define (hts_dump_feats utt feats ofile)
|
|
(let ((ofd (fopen ofile "w")))
|
|
(mapcar
|
|
(lambda (s)
|
|
(hts_feats_output ofd s))
|
|
(utt.relation.items utt 'Segment))
|
|
(fclose ofd)
|
|
))
|
|
|
|
|
|
;;
|
|
;; Extra features
|
|
;; From Segment items refer by
|
|
;;
|
|
;; R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_syls_in_phrase
|
|
;; R:SylStructure.parent.parent.R:Phrase.parent.lisp_num_words_in_phrase
|
|
;; lisp_total_words
|
|
;; lisp_total_syls
|
|
;; lisp_total_phrases
|
|
;;
|
|
;; The last three will act on any item
|
|
|
|
(define (distance_to_p_content i)
|
|
(let ((c 0) (rc 0 ) (w (item.relation.prev i "Phrase")))
|
|
(while w
|
|
(set! c (+ 1 c))
|
|
(if (string-equal "1" (item.feat w "contentp"))
|
|
(begin
|
|
(set! rc c)
|
|
(set! w nil))
|
|
(set! w (item.prev w)))
|
|
)
|
|
rc))
|
|
|
|
(define (distance_to_n_content i)
|
|
(let ((c 0) (rc 0) (w (item.relation.next i "Phrase")))
|
|
(while w
|
|
(set! c (+ 1 c))
|
|
(if (string-equal "1" (item.feat w "contentp"))
|
|
(begin
|
|
(set! rc c)
|
|
(set! w nil))
|
|
(set! w (item.next w)))
|
|
)
|
|
rc))
|
|
|
|
(define (distance_to_p_accent i)
|
|
(let ((c 0) (rc 0 ) (w (item.relation.prev i "Syllable")))
|
|
(while (and w (member_string (item.feat w "syl_break") '("0" "1")))
|
|
(set! c (+ 1 c))
|
|
(if (string-equal "1" (item.feat w "accented"))
|
|
(begin
|
|
(set! rc c)
|
|
(set! w nil))
|
|
(set! w (item.prev w)))
|
|
)
|
|
rc))
|
|
|
|
(define (distance_to_n_accent i)
|
|
(let ((c 0) (rc 0 ) (w (item.relation.next i "Syllable")))
|
|
(while (and w (member_string (item.feat w "p.syl_break") '("0" "1")))
|
|
(set! c (+ 1 c))
|
|
(if (string-equal "1" (item.feat w "accented"))
|
|
(begin
|
|
(set! rc c)
|
|
(set! w nil))
|
|
(set! w (item.next w)))
|
|
)
|
|
rc))
|
|
|
|
(define (distance_to_p_stress i)
|
|
(let ((c 0) (rc 0 ) (w (item.relation.prev i "Syllable")))
|
|
(while (and w (member_string (item.feat w "syl_break") '("0" "1")))
|
|
(set! c (+ 1 c))
|
|
(if (string-equal "1" (item.feat w "stress"))
|
|
(begin
|
|
(set! rc c)
|
|
(set! w nil))
|
|
(set! w (item.prev w)))
|
|
)
|
|
rc))
|
|
|
|
(define (distance_to_n_stress i)
|
|
(let ((c 0) (rc 0 ) (w (item.relation.next i "Syllable")))
|
|
(while (and w (member_string (item.feat w "p.syl_break") '("0" "1")))
|
|
(set! c (+ 1 c))
|
|
(if (string-equal "1" (item.feat w "stress"))
|
|
(begin
|
|
(set! rc c)
|
|
(set! w nil))
|
|
(set! w (item.next w)))
|
|
)
|
|
rc))
|
|
|
|
(define (num_syls_in_phrase i)
|
|
(apply
|
|
+
|
|
(mapcar
|
|
(lambda (w)
|
|
(length (item.relation.daughters w 'SylStructure)))
|
|
(item.relation.daughters i 'Phrase))))
|
|
|
|
(define (num_words_in_phrase i)
|
|
(length (item.relation.daughters i 'Phrase)))
|
|
|
|
(define (total_words w)
|
|
(length
|
|
(utt.relation.items (item.get_utt w) 'Word)))
|
|
|
|
(define (total_syls s)
|
|
(length
|
|
(utt.relation.items (item.get_utt s) 'Syllable)))
|
|
|
|
(define (total_phrases s)
|
|
(length
|
|
(utt.relation_tree (item.get_utt s) 'Phrase)))
|
|
|
|
(provide 'hts)
|