/** * 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.util.data; import java.io.DataOutput; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; public class Datagram { public static final int NUM_HEADER_BYTES = (Long.SIZE + Integer.SIZE) / Byte.SIZE; // the duration and the length /****************/ /* DATA FIELDS */ /****************/ /** * The datagram duration, in samples. */ protected long duration = 0l; // The (time) duration of the datagram, in samples /** * The datagram's contents, as a generic byte array. */ protected byte[] data = null; /****************/ /* CONSTRUCTORS */ /****************/ /** * Constructor for subclasses which want to represent data in a different format. * * @param duration * the datagram duration, in samples. Must be non-negative. * @throws IllegalArgumentException * if duration is negative */ protected Datagram(long duration) { if (duration < 0) { throw new IllegalArgumentException("Can't create a datagram with the negative duration [" + duration + "]."); } this.duration = duration; } /** * Constructor from external data. * * @param setDuration * the datagram duration, in samples. Must be non-negative. * @param setData * the datagram. * @throws IllegalArgumentException * if duration is negative * @throws NullPointerException * if setData is null. */ public Datagram(long setDuration, byte[] setData) { if (setDuration < 0) { throw new IllegalArgumentException("Can't create a datagram with the negative duration [" + setDuration + "]."); } if (setData == null) { throw new NullPointerException("null argument"); } duration = setDuration; data = setData; } /** * Constructor which reads a datagram from a random access file. * * @param raf * the random access file to read the datagram from. * * @throws IOException * if there is a problem initialising the datagram from the file */ public Datagram(RandomAccessFile raf) throws IOException { duration = raf.readLong(); if (duration < 0) { throw new IOException("Can't create a datagram with a negative duration [" + duration + "]."); } int len = raf.readInt(); if (len < 0) { throw new IOException("Can't create a datagram with a negative data size [" + len + "]."); } data = new byte[len]; raf.readFully(data); } /** * Constructor which reads a datagram from a byte buffer. * * @param bb * the byte buffer to read the datagram from. * * @throws IOException * if the datagram has wrong format or if the datagram cannot be fully read */ public Datagram(ByteBuffer bb) throws IOException { this(bb, true); } /** * Constructor which reads a datagram from a byte buffer. * * @param bb * the byte buffer to read the datagram from. * @param readData * whether to try and read the actual data * * @throws IOException * if the datagram has wrong format or if the datagram cannot be fully read */ public Datagram(ByteBuffer bb, boolean readData) throws IOException { duration = bb.getLong(); if (duration < 0) { throw new IOException("Can't create a datagram with a negative duration [" + duration + "]."); } int len = bb.getInt(); if (len < 0) { throw new IOException("Can't create a datagram with a negative data size [" + len + "]."); } data = new byte[len]; if (!readData) { return; } if (bb.limit() - bb.position() < len) { throw new IOException("Not enough data in byte buffer to read the full datagram: datagram length is " + len + ", but can read only " + (bb.limit() - bb.position())); } bb.get(data); } /****************/ /* SETTERS */ /****************/ /** * Set the new duration. * * @param setDuration * the datagram duration, in samples. Must be non-negative. * @throws IllegalArgumentException * if duration is negative */ public void setDuration(long setDuration) { if (setDuration < 0) { throw new IllegalArgumentException("Can't create a datagram with the negative duration [" + setDuration + "]."); } this.duration = setDuration; } /****************/ /* I/O METHODS */ /****************/ /** * Write this datagram to a random access file or data output stream. Must only be called if data is not null. * * @param raf * the data output to write to. * @throws IllegalStateException * if called when data is null. * @throws IOException * if a write error occurs. */ public void write(DataOutput raf) throws IOException { assert duration >= 0; if (data == null) { throw new IllegalStateException("This method can only be called for data that is not null"); } raf.writeLong(duration); raf.writeInt(data.length); raf.write(data); } /****************/ /* ACCESSORS */ /****************/ /** * Get the datagram duration, in samples. Note: the sample rate has to be provided externally. * * @return the non-negative duration. */ public long getDuration() { assert duration >= 0; return duration; } /** * Get the length, in bytes, of the datagram's data field. Must only be called if data is not null. * * @return a non-negative integer representing the number of bytes in the data field. * @throws IllegalStateException * if called when data is null. */ public int getLength() { if (data == null) { throw new IllegalStateException("This method must not be called if data is null"); } return data.length; } /** * Get the datagram's data field. * * @return the data in this Datagram, or null if there is no such data (should be the case only for subclasses). */ public byte[] getData() { return data; } /****************/ /* MISC METHODS */ /****************/ /** * Tests if this datagram is equal to another datagram. */ @Override public boolean equals(Object obj) { if (!(obj instanceof Datagram)) { return false; } Datagram other = (Datagram) obj; if (this.duration != other.duration) return (false); if (this.data.length != other.data.length) return (false); for (int i = 0; i < this.data.length; i++) { if (this.data[i] != other.data[i]) return (false); } return (true); } }