upstream version 1.2.2
[debian/freetts] / com / sun / speech / freetts / cart / Durator.java
1 /**
2  * Portions Copyright 2001 Sun Microsystems, Inc.
3  * Portions Copyright 1999-2001 Language Technologies Institute, 
4  * Carnegie Mellon University.
5  * All Rights Reserved.  Use is subject to license terms.
6  * 
7  * See the file "license.terms" for information on usage and
8  * redistribution of this file, and for a DISCLAIMER OF ALL 
9  * WARRANTIES.
10  */
11 package com.sun.speech.freetts.cart;
12
13 import com.sun.speech.freetts.Item;
14 import com.sun.speech.freetts.PathExtractor;
15 import com.sun.speech.freetts.PathExtractorImpl;
16 import com.sun.speech.freetts.PhoneDuration;
17 import com.sun.speech.freetts.PhoneDurations;
18 import com.sun.speech.freetts.ProcessException;
19 import com.sun.speech.freetts.Relation;
20 import com.sun.speech.freetts.Utterance;
21 import com.sun.speech.freetts.UtteranceProcessor;
22
23 /**
24  * Determines duration timing for
25  * <code>Relation.SEGMENT</code> relations in an utterance.
26  * Annotates the <code>Relation.SEGMENT</code> relation with an
27  * "end" time feature.
28  *
29  * <p>[[[TODO: The mean words-per-minute rate should become part
30  * of the CART data.  For now, it is passed into the constructor.]]]
31  *
32  * @see Relation#SEGMENT
33  */
34 public class Durator implements UtteranceProcessor {
35     /**
36      * The nominal speaking rate in words per minute.  Set in the
37      * constructor.
38      */
39     private final float meanRate;
40     
41     /**
42      * The CART used for this duration UtteranceProcessor.  It is
43      * passed into the constructor.
44      */
45     protected final CART cart;
46
47     /**
48      * The PhoneDurations used for this duration UtteranceProcessor.
49      * It is passed into the constructor.
50      */
51     protected final PhoneDurations durations;
52
53
54     private static final PathExtractor DURATION_STRETCH_PATH  =
55         new PathExtractorImpl(
56         "R:SylStructure.parent.parent.R:Token.parent.local_duration_stretch", 
57         true);
58     
59     /**
60      * Creates a new duration UtteranceProcessor with the given
61      * CART and phone durations.
62      *
63      * @param cart contains zscore duration data
64      * @param meanRate the mean words per minute rate of the CART data
65      * @param durations contains mean and standard deviation phone durations
66      */
67     public Durator(CART cart, float meanRate, PhoneDurations durations) {
68         this.cart = cart;
69         this.meanRate = meanRate;
70         this.durations = durations;
71     }
72     
73     /**
74      * Annotates the <code>Relation.SEGMENT</code> relations with
75      * cumulative "end" time
76      * features based on phone durations.  Expects the CART to return
77      * a zscore for each phone, which specifies the number of standard
78      * deviations from the mean.  This is coupled with a phone
79      * durations table that returns the mean and standard deviation
80      * for phones.
81      * 
82      * @param  utterance the utterance to process
83      *
84      * @throws ProcessException if a problem is encountered during the
85      *         processing of the utterance
86      */
87     public void processUtterance(Utterance utterance) throws ProcessException {
88         float durStretch;
89         PhoneDuration durStat;
90         float durationStretch = utterance.getVoice().getDurationStretch();
91         float zdur;
92         float dur;
93         float end = 0.0f;
94         float localDurationStretch;
95         
96         // Figure out how far to stretch the durations (speed things
97         // up or slow them down.
98         //
99
100         durStretch = meanRate / utterance.getVoice().getRate();
101
102         // Go through each of the segments and calculate a duration
103         // for it.  Store the cumulative end time for the duration in
104         // the "end" feature of the segment.
105         //
106         for (Item segment =
107                  utterance.getRelation(Relation.SEGMENT).getHead();
108                 segment != null; segment = segment.getNext()) {
109             zdur = ((Float) cart.interpret(segment)).floatValue();
110             durStat = durations.getPhoneDuration(
111                 segment.getFeatures().getString("name"));
112
113             Object tval = DURATION_STRETCH_PATH.findFeature(segment);
114             localDurationStretch = Float.parseFloat(tval.toString());
115
116             if (localDurationStretch == 0.0) {
117                 localDurationStretch = durationStretch;
118             } else {
119                 localDurationStretch *= durationStretch;
120             }
121
122             dur = localDurationStretch * ((zdur*durStat.getStandardDeviation())
123                                  + durStat.getMean());
124             end += dur;
125             segment.getFeatures().setFloat("end", end);
126         }
127     }
128
129     // inherited from Object
130     public String toString() {
131         return "CARTDurator";
132     }
133 }