All Downloads are FREE. Search and download functionalities are using the official Maven repository.

marytts.tools.voiceimport.WavReader Maven / Gradle / Ivy

The newest version!
/**
 * Portions Copyright 2006 DFKI GmbH.
 * Portions Copyright 2001 Sun Microsystems, Inc.
 * Portions Copyright 1999-2001 Language Technologies Institute, 
 * Carnegie Mellon University.
 * All Rights Reserved.  Use is subject to license terms.
 * 
 * Permission is hereby granted, free of charge, to use and distribute
 * this software and its documentation without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of this work, and to
 * permit persons to whom this work is furnished to do so, subject to
 * the following conditions:
 * 
 * 1. The code must retain the above copyright notice, this list of
 *    conditions and the following disclaimer.
 * 2. Any modifications must be clearly marked as such.
 * 3. Original authors' names are not deleted.
 * 4. The authors' names are not used to endorse or promote products
 *    derived from this software without specific prior written
 *    permission.
 *
 * DFKI GMBH AND THE CONTRIBUTORS TO THIS WORK DISCLAIM ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL DFKI GMBH NOR THE
 * CONTRIBUTORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 * THIS SOFTWARE.
 */
package marytts.tools.voiceimport;

import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import marytts.util.io.General;

/**
 * File reader for a wave (RIFF) waveform
 */
public class WavReader {

	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;

	/****************/
	/* CONSTRUCTORS */
	/****************/

	/**
	 * Constructor from an already open DataInputStream
	 * 
	 * @param dis
	 *            DataInputStream to read the wav data from
	 * 
	 */
	public WavReader(DataInputStream dis) {
		loadHeaderAndData(dis);
	}

	/**
	 * Constructor from a file name
	 * 
	 * @param fileName
	 *            the name of the file to read the wav data from
	 * 
	 */
	public WavReader(String fileName) {
		try {
			/* Open the file */
			FileInputStream fis = new FileInputStream(fileName);
			/* Stick the file to a DataInputStream to allow easy reading of primitive classes (numbers) */
			DataInputStream dis = new DataInputStream(fis);
			/* Parse the header and load the data */
			loadHeaderAndData(dis);
			/* Close the file */
			fis.close();
		} catch (FileNotFoundException e) {
			throw new Error("WAV file [" + fileName + "] was not found.");
		} catch (SecurityException e) {
			throw new Error("You do not have read access to the file [" + fileName + "].");
		} catch (IOException e) {
			throw new Error("IO Exception caught when closing file [" + fileName + "]: " + e.getMessage());
		}
	}

	/*****************/
	/* OTHER METHODS */
	/*****************/

	/**
	 * Read in a wave from a riff format
	 * 
	 * @param dis
	 *            DataInputStream to read data from
	 */
	private void loadHeaderAndData(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(General.readChars(dis, 4));

				if (s.equals("data")) {
					numSamples = General.readInt(dis, false) / 2;
					break;
				} else if (s.equals("fact")) {
					int i = General.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] = General.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 = General.readInt(dis, false);
		if (!checkChars(dis, "WAVEfmt ")) {
			throw new Error("Invalid wave file format.");
		}

		headerSize = General.readInt(dis, false);

		if (General.readShort(dis, false) != RIFF_FORMAT_PCM) {
			throw new Error("Invalid wave file format.");
		}

		if (General.readShort(dis, false) != 1) {
			throw new Error("Only mono wave files supported.");
		}

		sampleRate = General.readInt(dis, false);
		General.readInt(dis, false);
		General.readShort(dis, false);
		General.readShort(dis, false);

	}

	/**
	 * Make sure that a string of characters appear next in the file
	 * 
	 * @param dis
	 *            DataInputStream to read in
	 * @param chars
	 *            a String containing the ascii characters you want the dis to contain.
	 * 
	 * @return true if chars appears next in dis, else false
	 * @throws IOException
	 *             ill-formatted input (end of file, for example)
	 */
	private boolean checkChars(DataInputStream dis, String chars) throws IOException {
		char[] carray = chars.toCharArray();
		for (int i = 0; i < carray.length; i++) {
			if ((char) dis.readByte() != carray[i]) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Get the sample rate for this wave
	 * 
	 * @return sample rate
	 */
	public int getSampleRate() {
		return sampleRate;
	}

	/**
	 * Get the number of samples for this wave
	 * 
	 * @return number of samples
	 */
	public int getNumSamples() {
		return numSamples;
	}

	/**
	 * Get the sample data of this wave
	 * 
	 * @return samples
	 */
	public short[] getSamples() {
		return samples;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy