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.
7 * See the file "license.terms" for information on usage and
8 * redistribution of this file, and for a DISCLAIMER OF ALL
11 package com.sun.speech.freetts.diphone;
13 import java.io.IOException;
16 import com.sun.speech.freetts.FeatureSet;
17 import com.sun.speech.freetts.Item;
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 import com.sun.speech.freetts.relp.Sample;
23 import com.sun.speech.freetts.relp.SampleInfo;
27 * Generates the Unit Relation of an Utterance from the
30 public class DiphoneUnitSelector implements UtteranceProcessor {
32 // the UnitDatabase to use
33 private DiphoneUnitDatabase diphoneDatabase;
35 // The Utterance that this DiphoneUnitSelector works on
36 // private Utterance utterance;
40 * Constructs a DiphoneUnitSelector.
42 * @param url the URL for the unit database. If the URL path ends
43 * with a '.bin' it is assumed that the DB is a binary database,
44 * otherwise, its assumed that its a text database1
46 * @throws IOException if an error occurs while loading the
50 public DiphoneUnitSelector(URL url) throws IOException {
52 throw new IOException("Can't load unit database");
54 boolean binary = url.getPath().endsWith(".bin");
55 diphoneDatabase = new DiphoneUnitDatabase(url, binary);
59 * Get the sample info for the underlying database.
60 * @return the sample info object
62 public SampleInfo getSampleInfo() {
63 return diphoneDatabase.getSampleInfo();
67 * Generates the Unit Relation from the Segment Relation.
69 * @param utterance the utterance to generate the Unit Relation
71 * @throws ProcessException if an IOException is thrown during the
72 * processing of the utterance
74 public void processUtterance(Utterance utterance) throws ProcessException {
76 if (utterance.getRelation(Relation.SEGMENT) == null) {
77 throw new IllegalStateException
78 ("DiphoneUnitSelector: Segment relation does not exist");
81 utterance.setObject(SampleInfo.UTT_NAME,
82 diphoneDatabase.getSampleInfo());
83 createUnitRelation(utterance);
87 * Creates the Unit Relation in the given utterance from
88 * the diphone units and their some associated information from
91 * @param utterance the utterance that gets the new unit relation
93 private void createUnitRelation(Utterance utterance) {
95 Item segmentItem0, segmentItem1;
99 Item unitItem0, unitItem1;
103 Relation unitRelation = utterance.createRelation(Relation.UNIT);
104 Relation segmentRelation = utterance.getRelation(Relation.SEGMENT);
106 for (segmentItem0 = segmentRelation.getHead();
107 segmentItem0 != null && segmentItem0.getNext() != null;
108 segmentItem0 = segmentItem1) {
109 segmentItem1 = segmentItem0.getNext();
110 diphoneName = segmentItem0.getFeatures().getString("name") + "-" +
111 segmentItem1.getFeatures().getString("name");
114 // First half of diphone
115 end0 = segmentItem0.getFeatures().getFloat("end");
116 targetEnd = (int) (end0 *
117 diphoneDatabase.getSampleInfo().getSampleRate());
118 unitItem0 = createUnitItem(unitRelation, diphoneName, targetEnd, 1);
119 segmentItem0.addDaughter(unitItem0);
121 // Second half of diphone
122 end1 = segmentItem1.getFeatures().getFloat("end");
123 targetEnd = (int) (((end0 + end1)/2.0) *
124 diphoneDatabase.getSampleInfo().getSampleRate());
125 unitItem1 = createUnitItem(unitRelation, diphoneName, targetEnd, 2);
126 segmentItem1.addDaughter(unitItem1);
131 * Returns a new Item (a Unit) in the given Relation, and
132 * sets the new Item to the given diphone name, target end,
133 * unit entry (index in the database), and unit part (1 or 2).
135 * @param unitRelation the relation that gets the new item
136 * @param diphoneName the name of the dipohone
137 * @param targetEnd the time at the end of this unit
138 * @param unitPart the item can be in the first(1) or second part (2)
140 private Item createUnitItem(Relation unitRelation,
144 Diphone diphone = (Diphone) diphoneDatabase.getUnit(diphoneName);
145 if (diphone == null) {
147 ("FreeTTS: unit database failed to find entry for: " +
150 Item unit = unitRelation.appendItem();
151 FeatureSet unitFeatureSet = unit.getFeatures();
153 unitFeatureSet.setString("name", diphoneName);
154 unitFeatureSet.setInt("target_end", targetEnd);
155 unitFeatureSet.setObject("unit", new DiphoneUnit(diphone, unitPart));
156 // unitFeatureSet.setInt("unit_part", unitPart);
161 * Returns a string representation of this object.
163 * @return a string representation of this object
165 public String toString() {
166 return "DiphoneUnitSelector";
172 * A wrapper around the Diphone class that turns the
173 * diphone into a unit
175 class DiphoneUnit implements com.sun.speech.freetts.Unit {
177 private Diphone diphone;
178 private int unitPart;
181 * Contructs a diphone unit given a diphone and unit part.
183 * @param diphone the diphone to wrap
184 * @param unitPart which half (1 or 2) does this unit represent
186 public DiphoneUnit(Diphone diphone, int unitPart) {
187 this.diphone = diphone;
188 this.unitPart = unitPart;
192 * Returns the name of this Unit.
194 * @return the name of the unit
196 public String getName() {
197 return diphone.getName();
201 * Returns the size of the unit.
203 * @return the size of the unit
205 public int getSize() {
206 return diphone.getUnitSize(unitPart);
210 * Retrieves the nearest sample.
212 * @param index the ideal index
214 * @return the nearest Sample
216 public Sample getNearestSample(float index) {
217 return diphone.nearestSample(index, unitPart);
221 * Returns a string representation of this object.
223 * @return a string representation of this object
225 public String toString() {