/* * Copyright 1999-2002 Carnegie Mellon University. * Portions Copyright 2002 Sun Microsystems, Inc. * Portions Copyright 2002 Mitsubishi Electric Research Laboratories. * 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. * */ package edu.cmu.sphinx.frontend.util; import edu.cmu.sphinx.frontend.*; import edu.cmu.sphinx.util.ExtendedStreamTokenizer; import edu.cmu.sphinx.util.Utilities; import edu.cmu.sphinx.util.props.*; import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStream; /** * Produces Mel-cepstrum data from an InputStream. To set the inputstream with cepstral data, use the {@link * #setInputStream(InputStream,boolean) setInputStream} method, and then call {@link #getData} to obtain the Data * objects that have cepstra data in it. */ public class StreamCepstrumSource extends BaseDataProcessor { /** The property specifying whether the input is in binary. */ @S4Boolean(defaultValue = true) public final static String PROP_BINARY = "binary"; /** The property name for frame size in milliseconds. */ @S4Double(defaultValue = 25.625) public static final String PROP_FRAME_SIZE_MS = "frameSizeInMs"; /** The property name for frame shift in milliseconds, which has a default value of 10F. */ @S4Double(defaultValue = 10.0) public static final String PROP_FRAME_SHIFT_MS = "frameShiftInMs"; /** The property specifying the length of the cepstrum data. */ @S4Integer(defaultValue = 13) public static final String PROP_CEPSTRUM_LENGTH = "cepstrumLength"; /** The property specifying whether the input data is big-endian. */ @S4Boolean(defaultValue = false) public static final String PROP_BIG_ENDIAN_DATA = "bigEndianData"; /** The property that defines the sample rate */ @S4Integer(defaultValue = 16000) public static final String PROP_SAMPLE_RATE = "sampleRate"; private boolean binary; private ExtendedStreamTokenizer est; // for ASCII files private DataInputStream binaryStream; // for binary files private int numPoints; private int curPoint; private int cepstrumLength; private int frameShift; private int frameSize; private int sampleRate; private long firstSampleNumber; private boolean bigEndian; public StreamCepstrumSource( int cepstrumLength, boolean binary, float frameShiftMs, float frameSizeMs, int sampleRate ) { initLogger(); this.cepstrumLength = cepstrumLength; this.binary = binary; this.sampleRate = sampleRate; this.frameShift = DataUtil.getSamplesPerWindow(sampleRate, frameShiftMs); this.frameSize = DataUtil.getSamplesPerShift(sampleRate, frameSizeMs); } public StreamCepstrumSource( ) { } /* * (non-Javadoc) * * @see edu.cmu.sphinx.util.props.Configurable#newProperties(edu.cmu.sphinx.util.props.PropertySheet) */ @Override public void newProperties(PropertySheet ps) throws PropertyException { super.newProperties(ps); cepstrumLength = ps.getInt(PROP_CEPSTRUM_LENGTH); binary = ps.getBoolean(PROP_BINARY); bigEndian = ps.getBoolean(PROP_BIG_ENDIAN_DATA); float frameShiftMs = ps.getFloat(PROP_FRAME_SHIFT_MS); float frameSizeMs = ps.getFloat(PROP_FRAME_SIZE_MS); sampleRate = ps.getInt(PROP_SAMPLE_RATE); frameShift = DataUtil.getSamplesPerWindow(sampleRate, frameShiftMs); frameSize = DataUtil.getSamplesPerShift(sampleRate, frameSizeMs); } /** Constructs a StreamCepstrumSource that reads MelCepstrum data from the given path. */ @Override public void initialize() { super.initialize(); curPoint = -1; firstSampleNumber = 0; bigEndian = false; } /** * Sets the InputStream to read cepstral data from. * * @param is the InputStream to read cepstral data from * @param bigEndian true if the InputStream data is in big-endian, false otherwise * @throws IOException if an I/O error occurs */ public void setInputStream(InputStream is, boolean bigEndian) throws IOException { this.bigEndian = bigEndian; if (binary) { binaryStream = new DataInputStream(new BufferedInputStream(is)); if (bigEndian) { numPoints = binaryStream.readInt(); System.out.println("BigEndian"); } else { numPoints = Utilities.readLittleEndianInt(binaryStream); System.out.println("LittleEndian"); } System.out.println("Frames: " + numPoints / cepstrumLength); } else { est = new ExtendedStreamTokenizer(is, false); numPoints = est.getInt("num_frames"); est.expectString("frames"); } curPoint = -1; firstSampleNumber = 0; } /** * Returns the next Data object, which is the mel cepstrum of the input frame. However, it can also be other Data * objects like DataStartSignal. * * @return the next available Data object, returns null if no Data object is available * @throws DataProcessingException if a data processing error occurs */ @Override public Data getData() throws DataProcessingException { Data data; if (curPoint == -1) { data = new DataStartSignal(sampleRate); curPoint++; } else if (curPoint == numPoints) { if (numPoints > 0) { firstSampleNumber = (firstSampleNumber - frameShift + frameSize - 1); } // send a DataEndSignal int numberFrames = curPoint / cepstrumLength; int totalSamples = (numberFrames - 1) * frameShift + frameSize; long duration = (long) (((double) totalSamples / (double) sampleRate) * 1000.0); data = new DataEndSignal(duration); try { if (binary) { binaryStream.close(); } else { est.close(); } curPoint++; } catch (IOException ioe) { throw new DataProcessingException("IOException closing cepstrum stream", ioe); } } else if (curPoint > numPoints) { data = null; } else { double[] vectorData = new double[cepstrumLength]; for (int i = 0; i < cepstrumLength; i++) { try { if (binary) { if (bigEndian) { vectorData[i] = binaryStream.readFloat(); } else { vectorData[i] = Utilities.readLittleEndianFloat(binaryStream); } } else { vectorData[i] = est.getFloat("cepstrum data"); } curPoint++; } catch (IOException ioe) { throw new DataProcessingException("IOException reading from cepstrum stream", ioe); } } // System.out.println("Read: " + curPoint); data = new DoubleData (vectorData, sampleRate, firstSampleNumber); firstSampleNumber += frameShift; // System.out.println(data); } return data; } }