?? findsts.java
字號(hào):
/** * Portions Copyright 2003 Sun Microsystems, Inc. * Portions Copyright 1999-2003 Language Technologies Institute, * Carnegie Mellon University. * All Rights Reserved. Use is subject to license terms. * * See the file "license.terms" for information on usage and * redistribution of this file, and for a DISCLAIMER OF ALL * WARRANTIES. * */import java.io.FileInputStream;import java.io.DataInputStream;import java.io.OutputStreamWriter;import java.io.FileOutputStream;import java.io.IOException;import java.io.FileNotFoundException;import javax.sound.sampled.spi.AudioFileReader;import javax.sound.sampled.AudioInputStream;/** * Performs the generation of STS files in FestVox to FreeTTS * conversion. * * <p> * This program is a port from flite/tools/find_sts_main.c * </p> * * <p> * Note: * The a/b diff result is slightly different than the C version due to * Intel floating-point math. * </p> */public strictfp class FindSTS { /** * Generate an sts file * * <p> * <b>Usage</b> * </p> * <p> * <code> java FindSTS lpc_min lpc_range lpcFile waveFile stsFile * </code> * </p> * <p> * <code> stsFile </code> the output file. * </p> */ public static void main(String[] args) { try { if (args.length != 5) { System.err.println("Usage: java FindSTS lpc_min lpc_range " + "lpcFile waveFile stsFile"); } else { float lpc_min = Float.parseFloat(args[0]); float lpc_range = Float.parseFloat(args[1]); FileInputStream lpcFile = new FileInputStream(args[2]); FileInputStream waveFile = new FileInputStream(args[3]); FileOutputStream stsFile = new FileOutputStream(args[4]); // Read input LPC lpc = new LPC(new DataInputStream(lpcFile)); Wave wave = new Wave(new DataInputStream(waveFile)); lpcFile.close(); waveFile.close(); // Generate sts data STS[] stsData = findSTS(wave, lpc, lpc_min, lpc_range); // Verify STS data for sanity Wave reconstructedWave = new Wave(wave.getSampleRate(), stsData, lpc, lpc_min, lpc_range); wave.compare(reconstructedWave); // Save output OutputStreamWriter stsWriter = new OutputStreamWriter(stsFile); saveSTS(stsData, lpc, wave, stsWriter, lpc_min, lpc_range); stsWriter.close(); stsFile.close(); } } catch (FileNotFoundException ioe) { throw new Error("Error while running FindSTS" + ioe.getMessage()); } catch (IOException ioe) { throw new Error("IO error while finding sts" + ioe.getMessage()); } } /** * Find the sts data. * * @param wave the data from the wave file * @param lpc the data from the lpc file * @param lpc_min the minimum lpc value * @param lpc_range the range of the lpc values * * @return an <code>STS</code> array containing the data */ private static STS[] findSTS(Wave wave, LPC lpc, float lpc_min, float lpc_range) { int size; int start = 0; int end; STS[] stsData = new STS[lpc.getNumFrames()]; // read wave data into a special array. short[] waveData = new short[wave.getNumSamples() + lpc.getNumChannels()]; System.arraycopy(wave.getSamples(), 0, waveData, lpc.getNumChannels(), wave.getNumSamples()); for (int i = 0; i < lpc.getNumFrames(); i++) { double[] resd; int[] frame; short[] residual; end = (int) ((float) wave.getSampleRate() * lpc.getTime(i)); size = end - start; if (size <= 0) { System.out.println("frame size at " + Float.toString(lpc.getTime(i)) + " is " + Integer.toString(size) + "."); } residual = generateResiduals(waveData, start + lpc.getNumChannels(), lpc.getFrame(i), lpc.getNumChannels(), size); frame = new int[lpc.getNumChannels() - 1]; for (int j = 1; j < lpc.getNumChannels(); j++) { frame[j - 1] = (int) ((((lpc.getFrameEntry(i, j) - lpc_min) / lpc_range)) * (float) 65535.0); } stsData[i] = new STS(frame, size, residual); start = end; } return stsData; } /** * Generate the residuals for this sts * * @param wave specially formatted wave data * @param start offset into the wave data * @param frame frame data from the lpc * @param order typically the number of lpc channels * @param size size of the residual * * @return sts residuals */ private static short[] generateResiduals(short[] wave, int start, float[] frame, int order, int size) { double r; short[] residual = new short[size]; for (int i = 0; i < order; i++) { r = wave[start + i]; for (int j = 1; j < order; j++) { r -= frame[j] * ((double) wave[start + (i - j)]); } residual[i] = Utility.shortToUlaw((short) r); } for (int i = order; i < size; i++) { r = wave[start + i]; for (int j = 1; j < order; j++) { r -= frame[j] * ((double) wave[start + (i - j)]); } residual[i] = Utility.shortToUlaw((short) r); } return residual; } /** * Save the sts data * * @param stsData generated sts data * @param lpc data loaded from the lpc file * @param wave data loaded from the wave file * @param osw the OutputStreamWriter to write the sts data to * @param lpc_min minimum lpc value * @param lpc_range range of lpc values * */ private static void saveSTS(STS[] stsData, LPC lpc, Wave wave, OutputStreamWriter osw, float lpc_min, float lpc_range) { try { osw.write("( " + Integer.toString(lpc.getNumFrames()) + " " + Integer.toString(lpc.getNumChannels() - 1) + " " + Integer.toString(wave.getSampleRate()) + " " + Float.toString(lpc_min) + " " + Float.toString(lpc_range) + ")\n"); for (int m=0, i=0; i < lpc.getNumFrames(); i++) { osw.write("( " + Float.toString(lpc.getTime(i)) + " ("); // Use the following line instead to compare against // the flite find_sts output //osw.write("( " + Utility.hex(lpc.getTime(i)) + " ("); for (int j = 1; j < lpc.getNumChannels(); j++) { osw.write(" " + Integer.toString(stsData[i].getFrameEntry(j - 1))); } osw.write(" ) " + Integer.toString(stsData[i].getNumSamples()) + " ( "); for (int j = 0; j < stsData[i].getNumSamples(); j++) { osw.write(" " + Integer.toString(stsData[i].getResidual(j))); } osw.write(" ))\n"); } } catch (IOException ioe) { throw new Error("IO error while writing sts." + ioe.getMessage()); } }}/** * The lpc data * */class LPC { private int numFrames; private int numChannels; float[] times; float[][] frames; /** Create lpc data from an input stream * * @param dis DataInputStream to read the lpc in from * */ public LPC(DataInputStream dis) { try { if (!Utility.readWord(dis).equals("EST_File") || !Utility.readWord(dis).equals("Track")) { throw new Error("Lpc file not EST Track file"); } boolean isBinary = false; boolean isBigEndian = false; // Read Header String token = Utility.readWord(dis); while (!token.equals("EST_Header_End")) { if (token.equals("DataType")) { if (Utility.readWord(dis).equals("binary")) { isBinary = true; } else { isBinary = false; } } else if (token.equals("ByteOrder")) { if (Utility.readWord(dis).equals("10")) { isBigEndian = true; } else { isBigEndian = false; } } else if (token.equals("NumFrames")) { numFrames = Integer.parseInt(Utility.readWord(dis)); } else if (token.equals("NumChannels")) { numChannels = Integer.parseInt(Utility.readWord(dis)); } // Ignore all other content in header token = Utility.readWord(dis); } times = new float[numFrames]; frames = new float[numFrames][numChannels]; // read data section if (isBinary) { loadBinaryData(dis, isBigEndian); } else { loadTextData(dis); } } catch (IOException ioe) { throw new Error("IO error while parsing lpc" + ioe.getMessage()); } } /** * load the data section of the lpc file as ascii text * * @param dis DataInputStream to read from * * @throws IOException on ill-formatted input */ private void loadTextData(DataInputStream dis) throws IOException { for (int f=0; f < numFrames; f++) { times[f] = Float.parseFloat(Utility.readWord(dis)); Utility.readWord(dis); // can be only 1 for (int c=0; c < numChannels; c++) { frames[f][c] = Float.parseFloat(Utility.readWord(dis)); } } } /** * load the data section of the lpc file as ascii text * * @param dis DataInputStream to read from * @param isBigEndian whether or not the data in the file is in * big endian byte order * * @throws IOException on ill-formatted input */ private void loadBinaryData(DataInputStream dis, boolean isBigEndian) throws IOException { for (int f=0; f < numFrames; f++) { times[f] = Utility.readFloat(dis, isBigEndian); // Ignore the 'breaks' field Utility.readFloat(dis, isBigEndian); for (int c=0; c < numChannels; c++) { frames[f][c] = Utility.readFloat(dis, isBigEndian); } } } /** * Get the number of frames in this lpc * * @return number of frames in this lpc */ public int getNumFrames() { return numFrames; } /** * Get the number of channels in this lpc * * @return number of channels in this lpc */ public int getNumChannels() { return numChannels; } /** * Get the times associated with this lpc * * @return an array of times associated with this lpc */ public float[] getTimes() { return times; } /** * Get an individual time associated with this lpc * * @param index index of time to get * * @return time value at given index */ public float getTime(int index) { return times[index]; } /** * Get an individual frame * * @param i index of frame * * @return the frame */ public float[] getFrame(int i) { return frames[i]; } /** * Get an individual frame entry * * @param i index of frame * @param j index into frame * * @return the frame entry in frame <code>i</code> at index * <code>j</code> */ public float getFrameEntry(int i, int j) { return frames[i][j]; }}/** * The wave (riff) data */class Wave { private int numSamples; private int sampleRate; private short[] samples; // Only really used in loading of data. private int headerSize; private int numBytes; private int numChannels = 1; // Only support mono static final short RIFF_FORMAT_PCM = 0x0001; /** * Read in a wave from a riff format * * @param dis DataInputStream to read data from */ public Wave (DataInputStream dis) { try { loadHeader(dis); if (dis.skipBytes(headerSize - 16) != (headerSize - 16)) { throw new Error("Unexpected error parsing wave file."); } // Bunch of potential random headers while (true) { String s = new String(Utility.readChars(dis, 4)); if (s.equals("data")) { numSamples = Utility.readInt(dis, false) / 2; break; } else if (s.equals("fact")) { int i = Utility.readInt(dis, false); if (dis.skipBytes(i) != i) { throw new Error("Unexpected error parsing wave file."); } } else { throw new Error("Unsupported wave header chunk type " + s); } } int dataLength = numSamples * numChannels; samples = new short[numSamples]; for (int i = 0; i < dataLength; i++) { samples[i] = Utility.readShort(dis, false); } } catch (IOException ioe) { throw new Error("IO error while parsing wave" + ioe.getMessage()); } } /** * load a RIFF header * * @param dis DataInputStream to read from * * @throws IOException on ill-formatted input */ private void loadHeader(DataInputStream dis) throws IOException { if (!checkChars(dis, "RIFF")) { throw new Error("Invalid wave file format."); } numBytes = Utility.readInt(dis,false); if (!checkChars(dis, "WAVEfmt ")) { throw new Error("Invalid wave file format."); } headerSize = Utility.readInt(dis, false); if (Utility.readShort(dis, false) != RIFF_FORMAT_PCM) { throw new Error("Invalid wave file format."); } if (Utility.readShort(dis, false) != 1) { throw new Error("Only mono wave files supported."); } sampleRate = Utility.readInt(dis, false); Utility.readInt(dis, false); Utility.readShort(dis, false); Utility.readShort(dis, false); } /**
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -