upstream version 1.2.2
[debian/freetts] / com / sun / speech / freetts / relp / Sample.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.relp;
12
13 import java.io.BufferedReader;
14 import java.io.DataInputStream;
15 import java.io.DataOutputStream;
16 import java.io.IOException;
17 import java.nio.ByteBuffer;
18 import java.util.NoSuchElementException;
19 import java.util.StringTokenizer;
20
21 /**
22  * A single short term sample containing Residual Excited Linear Predictive
23  * (RELP) frame and residual voice data.  
24  */
25 public class Sample {
26     private final short[] frameData;
27     private final byte[]  residualData;
28     private final int residualSize;
29     
30
31     /**
32      * Constructs a RELP Sample from its component parts
33      *
34      * @param frameData the framedata
35      * @param residualData the residual data
36      */
37     public Sample(short[] frameData, byte[] residualData) {
38         this.frameData = frameData;
39         this.residualData = residualData;
40         this.residualSize = 0;
41     }
42
43     /**
44      * Constructs a Sample from its component parts
45      *
46      * @param frameData the framedata
47      * @param residualData the residual data
48      */
49     public Sample(short[] frameData, byte[] residualData, int residualSize) {
50         this.frameData = frameData;
51         this.residualData = residualData;
52         this.residualSize = residualSize;
53     }
54
55     /**
56      * Reads a sample from the input reader. 
57      *
58      * @param reader the input reader to read the data from
59      * @param numChannels the number of channels per frame
60      */
61     public Sample(BufferedReader reader, int numChannels) {
62         try {
63             String line = reader.readLine();
64
65             StringTokenizer tok = new StringTokenizer(line);
66             if (!tok.nextToken().equals("FRAME")) {
67                 throw new Error("frame Parsing sample error");
68             }
69
70             frameData = new short[numChannels];
71
72             for (int i = 0; i < numChannels; i++) {
73                 int svalue = Integer.parseInt(tok.nextToken()) - 32768;
74         
75                 if ( svalue <  -32768 || svalue > 32767) {
76                     throw new Error("data out of short range");
77                 }
78                 frameData[i] = (short) svalue;
79             }
80
81             line = reader.readLine();
82             tok = new StringTokenizer(line);
83             if (!tok.nextToken().equals("RESIDUAL")) {
84                 throw new Error("residual Parsing sample error");
85             }
86
87             residualSize = Integer.parseInt(tok.nextToken());
88             residualData = new byte[residualSize];
89
90             for (int i = 0; i < residualSize; i++) {
91                 int bvalue = Integer.parseInt(tok.nextToken()) - 128;
92
93                 if ( bvalue < -128 || bvalue > 127) {
94                     throw new Error("data out of byte range");
95                 }
96                 residualData[i] = (byte) bvalue;
97             }
98         } catch (NoSuchElementException nse) {
99             throw new Error("Parsing sample error " + nse.getMessage());
100         } catch (IOException ioe) {
101             throw new Error("IO error while parsing sample" + ioe.getMessage());
102         }
103     }
104
105     /**
106      * Gets the frame data associated with this sample
107      *
108      * @return the frame data associated with this sample
109      */
110     public short[] getFrameData() {
111         return frameData;
112     }
113
114     /**
115      * Gets the residual data associated with this sample
116      *
117      * @return the residual data associated with this sample
118      */
119     public byte[] getResidualData() {
120         return residualData;
121     }
122
123     /**
124      * Returns the number of residuals in this Sample.
125      *
126      * @return the number of residuals in this sample
127      */
128     public int getResidualSize() {
129         return residualSize;
130     }
131
132
133     /**
134      * Returns the normalized residual data. You may not want to 
135      * call this function because of the overhead involved.
136      *
137      * @param which the index of the data of interest
138      *
139      * @return the normalized data.
140      */
141     public int getResidualData(int which) {
142         return ((int)residualData[which]) + 128;
143     }
144
145     /**
146      * Returns the normalized frame data. You may not want to 
147      * call this function because of the overhead involved.
148      *
149      * @param which the index of the data of interest
150      *
151      * @return the normalized data.
152      */
153     public int getFrameData(int which) {
154         return ((int)frameData[which]) + 32768;
155     }
156
157
158     /**
159      * Dumps the sample:
160      */
161     public void dump() {
162         System.out.println(" FD Count: " + getFrameData().length);
163         for (int i = 0; i < getFrameData().length; i++) {
164             System.out.print(" " + getFrameData(i));
165         }
166         System.out.println();
167         System.out.println(" RD Count: " + getResidualSize());
168         // getResidualData().length);
169         for (int i = 0; i < getResidualData().length; i++) {
170             System.out.print(" " + getResidualData(i));
171         }
172         System.out.println();
173     }
174
175     /**
176      * Dumps the samples to the given ByteBuffer
177      *
178      * @param bb the ByteBuffer to write the data to.
179      *
180      * @throws IOException if IO error occurs
181      */
182     public void dumpBinary(ByteBuffer bb) throws IOException {
183         bb.putInt(frameData.length);
184         for (int i = 0; i < frameData.length; i++) {
185             bb.putShort(frameData[i]);
186         }
187         bb.putInt(residualData.length);
188         bb.put(residualData);
189     }
190
191     /**
192      * Dumps the samples to the given stream
193      *
194      * @param os the DataOutputStream to write the data to.
195      *
196      * @throws IOException if IO error occurs
197      */
198     public void dumpBinary(DataOutputStream os) throws IOException {
199         os.writeInt(frameData.length);
200         for (int i = 0; i < frameData.length; i++) {
201             os.writeShort(frameData[i]);
202         }
203         os.writeInt(residualData.length);
204         for (int i = 0; i < residualData.length; i++) {
205             os.writeByte(residualData[i]);
206         }
207     }
208
209     /**
210      * Loads the samples from the byte bufer
211      *
212      * @param bb the byte buffer to read the data from.
213      *
214      * @throws IOException if IO error occurs
215      */
216     public static Sample loadBinary(ByteBuffer bb) throws IOException {
217         int frameDataSize = bb.getInt();
218
219         short[] frameData = new short[frameDataSize];
220
221         for (int i = 0; i < frameData.length; i++) {
222             frameData[i] = bb.getShort();
223         }
224
225         int residualDataSize = bb.getInt();
226         byte[] residualData = new byte[residualDataSize];
227
228         for (int i = 0; i < residualData.length; i++) {
229             residualData[i] = bb.get();
230         }
231
232         return new Sample(frameData, residualData, residualDataSize);
233     }
234
235     /**
236      * Loads the samples from the given channel
237      *
238      * @param dis the DataInputStream to read the data from.
239      *
240      * @throws IOException if IO error occurs
241      */
242     public static Sample loadBinary(DataInputStream dis) 
243                         throws IOException {
244         int frameDataSize = dis.readInt();
245
246         short[] frameData = new short[frameDataSize];
247
248         for (int i = 0; i < frameData.length; i++) {
249             frameData[i] = dis.readShort();
250         }
251
252         int residualDataSize = dis.readInt();
253         byte[] residualData = new byte[residualDataSize];
254
255         for (int i = 0; i < residualData.length; i++) {
256             residualData[i] = dis.readByte();
257         }
258
259         return new Sample(frameData, residualData, residualDataSize);
260     }
261
262     /**
263      * Compares two samples. Note that this is not the same as
264      * "equals"
265      *
266      * @param other the other sample to compare this one to
267      *
268      * @return <code>true</code> if they compare; otherwise
269      *     <code>false</code> 
270      */
271     public boolean compare(Sample other) {
272
273         if (frameData.length != other.getFrameData().length) {
274             return false;
275         }
276
277         for (int i = 0; i < frameData.length; i++) {
278             if (frameData[i]  != other.frameData[i]) {
279                 return false;
280             }
281         }
282
283         if (residualData.length != other.residualData.length) {
284             return false;
285         }
286
287         for (int i = 0; i < residualData.length; i++) {
288             if (residualData[i]  != other.residualData[i]) {
289                 return false;
290             }
291         }
292         return true;
293     }
294 }
295     
296
297