001/**
002 * Portions Copyright 2001 Sun Microsystems, Inc.
003 * Portions Copyright 1999-2001 Language Technologies Institute, 
004 * Carnegie Mellon University.
005 * All Rights Reserved.  Use is subject to license terms.
006 * 
007 * See the file "license.terms" for information on usage and
008 * redistribution of this file, and for a DISCLAIMER OF ALL 
009 * WARRANTIES.
010 */
011package com.sun.speech.freetts.cart;
012
013import com.sun.speech.freetts.Item;
014import com.sun.speech.freetts.PathExtractor;
015import com.sun.speech.freetts.PathExtractorImpl;
016import com.sun.speech.freetts.PhoneDuration;
017import com.sun.speech.freetts.PhoneDurations;
018import com.sun.speech.freetts.ProcessException;
019import com.sun.speech.freetts.Relation;
020import com.sun.speech.freetts.Utterance;
021import com.sun.speech.freetts.UtteranceProcessor;
022
023/**
024 * Determines duration timing for <code>Relation.SEGMENT</code> relations in an
025 * utterance. Annotates the <code>Relation.SEGMENT</code> relation with an "end"
026 * time feature.
027 * 
028 * <p>
029 * [[[TODO: The mean words-per-minute rate should become part of the CART data.
030 * For now, it is passed into the constructor.]]]
031 * 
032 * @see Relation#SEGMENT
033 */
034public class Durator implements UtteranceProcessor {
035    /**
036     * The CART used for this duration UtteranceProcessor. It is passed into the
037     * constructor.
038     */
039    protected final CART cart;
040
041    /**
042     * The PhoneDurations used for this duration UtteranceProcessor. It is
043     * passed into the constructor.
044     */
045    protected final PhoneDurations durations;
046
047    private static final PathExtractor DURATION_STRETCH_PATH = new PathExtractorImpl(
048            "R:SylStructure.parent.parent.R:Token.parent.local_duration_stretch",
049            true);
050
051    /**
052     * Creates a new duration UtteranceProcessor with the given CART and phone
053     * durations.
054     * 
055     * @param cart
056     *            contains zscore duration data
057     * @param durations
058     *            contains mean and standard deviation phone durations
059     */
060    public Durator(CART cart, PhoneDurations durations) {
061        this.cart = cart;
062        this.durations = durations;
063    }
064
065    /**
066     * Annotates the <code>Relation.SEGMENT</code> relations with cumulative
067     * "end" time features based on phone durations. Expects the CART to return
068     * a zscore for each phone, which specifies the number of standard
069     * deviations from the mean. This is coupled with a phone durations table
070     * that returns the mean and standard deviation for phones.
071     * 
072     * @param utterance
073     *            the utterance to process
074     * 
075     * @throws ProcessException
076     *             if a problem is encountered during the processing of the
077     *             utterance
078     */
079    public void processUtterance(Utterance utterance) throws ProcessException {
080        PhoneDuration durStat;
081        float durationStretch = utterance.getVoice().getDurationStretch();
082        float zdur;
083        float dur;
084        float end = 0.0f;
085        float localDurationStretch;
086
087        // Go through each of the segments and calculate a duration
088        // for it. Store the cumulative end time for the duration in
089        // the "end" feature of the segment.
090        //
091        for (Item segment = utterance.getRelation(Relation.SEGMENT).getHead(); segment != null; segment = segment
092                .getNext()) {
093            zdur = ((Float) cart.interpret(segment)).floatValue();
094            durStat = durations.getPhoneDuration(segment.getFeatures()
095                    .getString("name"));
096
097            Object tval = DURATION_STRETCH_PATH.findFeature(segment);
098            localDurationStretch = Float.parseFloat(tval.toString());
099
100            if (localDurationStretch == 0.0) {
101                localDurationStretch = durationStretch;
102            } else {
103                localDurationStretch *= durationStretch;
104            }
105
106            dur = localDurationStretch
107                    * ((zdur * durStat.getStandardDeviation()) + durStat
108                            .getMean());
109            end += dur;
110            segment.getFeatures().setFloat("end", end);
111        }
112    }
113
114    // inherited from Object
115    public String toString() {
116        return "CARTDurator";
117    }
118}