upstream version 1.2.2
[debian/freetts] / tools / ArcticToFreeTTS / src / UnitCatalog.java
1 import java.io.IOException;
2 import java.io.BufferedReader;
3 import java.io.DataInputStream;
4 import java.io.FileInputStream;
5 import java.io.InputStreamReader;
6 import java.io.IOException;
7
8 import java.util.ArrayList;
9 import java.util.HashMap;
10 import java.util.Iterator;
11 import java.util.StringTokenizer;
12 import java.util.TreeSet;
13
14 /**
15  * Reads in a festival clunits unit catalog.  The units are stored
16  * as a HashMap of ArrayLists where the HashMap is indexed by unit
17  * type (e.g., "ae_afternoon"), and the ArrayList is a list of the
18  * actual units themselves (e.g., "ae_afternoon_23").
19  *    
20  * Assumption: unit indeces are in reverse order.
21  */
22 public class UnitCatalog extends HashMap {
23     /* Helpers for handling the previous and next units for each
24      * unit being read in.
25      */
26     private String currentFilename;
27     private Unit previousUnit;
28     private int currentIndex;
29     
30     /**
31      * Creates a new UnitCatalog from the festival unit catalog file.
32      *
33      * @param filename the festival unit catalog file
34      */
35     public UnitCatalog(String filename) throws IOException {
36         super();
37
38         BufferedReader reader =
39             new BufferedReader(
40                 new InputStreamReader(
41                     new FileInputStream(filename)));
42
43         /* Skip past the preamble.
44          */
45         String line = reader.readLine();
46         while (!line.equals("EST_Header_End")) {
47             line = reader.readLine();
48         }
49
50         /* Process each of the lines that have "real" content.
51          */
52         currentFilename = null;
53         previousUnit = null;
54         currentIndex = 0;
55         line = reader.readLine();
56         while (line != null) {
57             processLine(line);
58             line = reader.readLine();
59         }
60
61         reader.close();
62     }
63
64     /**
65      * Processes a single line from the catalog.
66      */
67     void processLine(String line) {
68         StringTokenizer tokenizer = new StringTokenizer(line);
69
70         /* The whole unit, including its instance (e.g.,
71          * "ae_afternoon_25")
72          */
73         String unitName = tokenizer.nextToken();
74
75         /* Split the unit into type ("ae_afternoon") and instance
76          * number (25).
77          */
78         String unitType = unitName.substring(0, unitName.lastIndexOf("_"));
79         int unitNum = Integer.parseInt(
80             unitName.substring(unitName.lastIndexOf("_") + 1));
81
82         /* Get the remaining parameters.
83          */
84         String filename = tokenizer.nextToken();
85         float start = Float.parseFloat(tokenizer.nextToken());
86         float middle = Float.parseFloat(tokenizer.nextToken());
87         float end = Float.parseFloat(tokenizer.nextToken());
88
89         /* Create a new ArrayList for this unit type if it
90          * is not in the catalog yet.
91          */
92         ArrayList units = (ArrayList) get(unitType);
93         if (units == null) {
94             units = new ArrayList();
95             put(unitType, units);
96         }
97
98         /**
99          * Make adjustments for previous and next units.
100          */
101         if (!filename.equals(currentFilename)) {
102             previousUnit = null;
103             currentFilename = filename;
104         }
105             
106         /* The units come in reverse order, so always
107          * add the unit to the begining of the entries.
108          */
109         Unit unit = new Unit(unitType,
110                              unitNum,
111                              filename,
112                              start,
113                              middle,
114                              end,
115                              previousUnit,
116                              null,
117                              currentIndex++);
118         units.add(0, unit);
119
120         /* Save away this unit as the next unit of the previous unit.
121          */
122         if (previousUnit != null) {
123             previousUnit.next = unit;
124         }
125         previousUnit = unit;    
126     }
127
128     /**
129      * Performs minimal checking on the catalog to make sure it was
130      * read in correctly.
131      */
132     void checkCatalog() {
133         /* Just make sure the unit numbers match the indexes in the
134          * ArrayList.
135          */
136         Iterator keys = keySet().iterator();
137         while (keys.hasNext()) {
138             String key = (String) keys.next();
139             ArrayList units = (ArrayList) get(key);
140             for (int i = 0; i < units.size(); i++) {
141                 Unit unit = (Unit) units.get(i);
142                 if (unit.unitNum != i) {
143                     System.out.println(key + " check failed: expected "
144                                        + i + ", got " + unit.unitNum);
145                 }
146             }
147         }
148     }    
149
150     /**
151      * Returns the given Unit or null if no such Unit exists.
152      *
153      * @param unitType the unit type (e.g., "ae_afternoon")
154      * @param unitNum the unit number
155      */
156     public Unit getUnit(String unitType, int unitNum) {
157         ArrayList units = (ArrayList) get(unitType);
158         if ((units == null) || (units.size() < unitNum)){
159             return null;
160         } else {
161             return (Unit) units.get(unitNum);
162         }
163     }    
164      
165     /**
166      * For testing.  args[0] = festival/clunits/*.catalogue.
167      */
168     public static void main(String[] args) {        
169         try {
170             UnitCatalog catalog = new UnitCatalog(args[0]);
171             catalog.checkCatalog();
172         } catch (IOException e) {
173             e.printStackTrace();
174         }
175     }
176 }