;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;; ;;; Carnegie Mellon University and ;; ;;; Centre for Speech Technology Research ;; ;;; University of Edinburgh, UK ;; ;;; Copyright (c) 1998-2001 ;; ;;; 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. ;; ;;; ;; ;;; THE UNIVERSITY OF EDINBURGH, 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 THE UNIVERSITY OF EDINBURGH, 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. ;; ;;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Cluster Unit selection support (Black and Taylor Eurospeech '97) ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; ;;; Run-time support, selection and synthesis and some debugging functions ;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require_module 'clunits) (defvar cluster_synth_pre_hooks nil) (defvar cluster_synth_post_hooks nil) (defvar clunits_time time) ;; some old voices might use this (defSynthType Cluster (apply_hooks cluster_synth_pre_hooks utt) (Clunits_Select utt) (Clunits_Get_Units utt) (Clunits_Join_Units utt) (apply_hooks cluster_synth_post_hooks utt) utt ) (define (Clunits_Join_Units utt) "(Clunits_Join_Units utt) Join the preselected and gotten units into a waveform." (let ((join_method (get_param 'join_method clunits_params 'simple))) ;; Choice of function to put them together (cond ((string-equal join_method 'windowed) (Clunits_Windowed_Wave utt) (clunits::fix_segs_durs utt)) ((string-equal join_method 'smoothedjoin) (Clunits_SmoothedJoin_Wave utt) (clunits::fix_segs_durs utt)) ((string-equal join_method 'none) t) ((string-equal join_method 'modified_lpc) (defvar UniSyn_module_hooks nil) (Param.def "unisyn.window_name" "hanning") (Param.def "unisyn.window_factor" 1.0) (Parameter.def 'us_sigpr 'lpc) (mapcar (lambda (u s) (item.set_feat s "source_end" (item.feat u "end"))) (utt.relation.items utt 'Unit) (utt.relation.items utt 'Segment)) (us_unit_concat utt) (if (not (member 'f0 (utt.relationnames utt))) (targets_to_f0 utt)) (if (utt.relation.last utt 'Segment) (set! pm_end (+ (item.feat (utt.relation.last utt 'Segment) "end") 0.02)) (set! pm_end 0.02)) (us_f0_to_pitchmarks utt 'f0 'TargetCoef pm_end) (us_mapping utt 'segment_single) (us_generate_wave utt (Parameter.get 'us_sigpr) 'analysis_period)) ((string-equal join_method 'smoothed_lpc) ; (format t "smoothed_lpc\n") (defvar UniSyn_module_hooks nil) (Param.def "unisyn.window_name" "hanning") (Param.def "unisyn.window_factor" 1.0) (Parameter.def 'us_sigpr 'lpc) (mapcar (lambda (u s) (item.set_feat s "source_end" (item.feat u "end")) (item.set_feat s "unit_duration" (- (item.feat u "seg_end") (item.feat u "seg_start"))) ) (utt.relation.items utt 'Unit) (utt.relation.items utt 'Segment)) (us_unit_concat utt) (mapcar (lambda (u s) (item.set_feat s "num_frames" (item.feat u "num_frames"))) (utt.relation.items utt 'Unit) (utt.relation.items utt 'Segment)) (if (not (member 'f0 (utt.relationnames utt))) (targets_to_f0 utt)) (if (utt.relation.last utt 'Segment) (set! pm_end (+ (item.feat (utt.relation.last utt 'Segment) "end") 0.02)) (set! pm_end 0.02)) (us_f0_to_pitchmarks utt 'f0 'TargetCoef pm_end) (cl_mapping utt clunits_params) (us_generate_wave utt (Parameter.get 'us_sigpr) 'analysis_period)) (t (Clunits_Simple_Wave utt))) utt ) ) (define (clunits::units_selected utt filename) "(clunits::units_selected utt filename) Output selected unitsfile indexes for each unit in the given utterance. Results saved in given file name, or stdout if filename is \"-\"." (let ((fd (if (string-equal filename "-") t (fopen filename "w"))) (end 0) (sample_rate (cadr (assoc 'sample_rate (wave.info (utt.wave utt)))))) (format fd "#\n") (mapcar (lambda (s) (let ((dur (/ (- (item.feat s "samp_end") (item.feat s "samp_start")) sample_rate)) (start (/ (item.feat s "samp_start") sample_rate))) (set! end (+ end dur)) (format fd "%f 125 %s ; %s %10s %f %f %f\n" end (string-before (item.name s) "_") (item.name s) (item.feat s "fileid") (item.feat s "unit_start") (item.feat s "unit_middle") (item.feat s "unit_end")) )) (utt.relation.items utt 'Unit)) (if (not (string-equal filename "-")) (fclose fd)) t)) (define (clunits::units_segs utt filename) "(clunits::units_segs utt filename) Svaes the unit selections (alone) for display." (let ((fd (if (string-equal filename "-") t (fopen filename "w"))) (end 0) (sample_rate (cadr (assoc 'sample_rate (wave.info (utt.wave utt)))))) (format fd "#\n") (mapcar (lambda (s) (let ((dur (/ (- (item.feat s "samp_end") (item.feat s "samp_start")) sample_rate)) (start (/ (item.feat s "samp_start") sample_rate))) (set! end (+ end dur)) (format fd "%f 125 %s \n" end (string-before (item.name s) "_") ; (item.name s) ) )) (utt.relation.items utt 'Unit)) (if (not (string-equal filename "-")) (fclose fd)) t)) (define (clunits::fix_segs_durs utt) "(clunits::fix_segs_durs utt) Takes the actual unit times and places then back on the segs." (let ((end 0) (sample_rate (cadr (assoc 'sample_rate (wave.info (utt.wave utt)))))) (mapcar (lambda (u s) (let ((dur (/ (- (item.feat u "samp_end") (item.feat u "samp_start")) sample_rate)) (seg_start (/ (- (item.feat u "samp_seg_start") (item.feat u "samp_start")) sample_rate))) (if (item.prev s) (item.set_feat (item.prev s) "end" (+ (item.feat s "p.end") seg_start))) (set! end (+ end dur)) (item.set_feat s "end" end))) (utt.relation.items utt 'Unit) (utt.relation.items utt 'Segment) ) utt)) (define (clunits::display utt) "(clunits::display utt) Display utterance with emulabel. Note this saves files in scratch/wav/ and scratch/lab/." (let ((id "cl01")) (utt.save.wave utt (format nil "scratch/wav/%s.wav" id)) (utt.save.segs utt (format nil "scratch/lab/%s.lab" id)) (system "cd scratch; emulabel ../etc/emu_lab cl01 &") t)) ; (define (clunits::debug_resynth_units utt) ; "(clunits::debug_resynth_units utt) ; Check each of the units in utt against the related label ; files and re-synth with any given new boundaries. Note this is ; will only work if the segment still overlaps with its original and ; also note that with a rebuild of the clunits db a complete different ; set of units may be selected for this utterance." ; (let () ; (mapcar ; (lambda (unit) ; (clunits::check_unit_boundaries unit)) ; (utt.relation.items utt 'Unit)) ; ;; This can't be done like this ... ; (Clunits_Get_Units utt) ;; get unit signal/track stuff ; (Clunits_Join_Units utt) ;; make a complete waveform ; (apply_hooks cluster_synth_post_hooks utt) ; utt) ; ) (define (clunits::join_parameters utt) "(clunits::join_parameters utt) Join selected paremeters (rather than the signal), used in F0 and Articulatory selection." (let ((params nil) (num_channels 0) (num_frames 0 )) (mapcar (lambda (unit) (set! num_frames (+ num_frames (track.num_frames (item.feat unit "coefs")))) (set! num_channels (track.num_channels (item.feat unit "coefs"))) (format t "coounting %d %d\n" num_frames num_channels) ) (utt.relation.items utt 'Unit)) (set! params (track.resize nil 0 num_channels)) (mapcar (lambda (unit) (set! frames 0) (format t "inserting \n") (format t "%l %l %l %l %l\n" params (track.num_frames params) (item.feat unit "coefs") 0 (track.num_frames (item.feat unit "coefs"))) (track.insert params (track.num_frames params) (item.feat unit "coefs") 0 (track.num_frames (item.feat unit "coefs"))) ) (utt.relation.items utt 'Unit)) (utt.relation.create utt "AllCoefs") (set! coefs_item (utt.relation.append utt "AllCoefs")) (item.set_feat coefs_item "name" "AllCoefs") (item.set_feat coefs_item "AllCoefs" params) utt )) (provide 'clunits)