/* You may freely copy, distribute, modify and use this class as long as the original author attribution remains intact. See message below. Copyright (C) 2003 Christian Pesch. All Rights Reserved. */ package slash.metamusic.mp3; import slash.metamusic.mp3.util.BitConversion; import java.io.IOException; import java.io.InputStream; import java.util.logging.Logger; /** * My instances represent the properties an WAV audio file, * which is parsed. Then, information about the WAV meta data may * be queried. * * @author Christian Pesch * @version $Id: WAVProperties.java 242 2004-04-19 14:34:59Z cpesch $ */ public class WAVProperties extends AbstractAudioProperties { /** * Logging output */ protected static final Logger log = Logger.getLogger(WAVProperties.class.getName()); public static final String RIFF_HEADER = "RIFF"; public static final String WAVE_HEADER = "WAVE"; public static final String FMT_CHUNK = "fmt "; public static final String DATA_CHUNK = "data"; /** * Construct new (empty) WAV properties. */ public WAVProperties() { } // --- read/write object ----------------------------------- public boolean read(InputStream in) throws NoMP3FrameException, IOException { valid = false; readSize = 0; if (!findString(in, RIFF_HEADER, ENCODING)) return valid; long fileSize = BitConversion.extract4LittleEndian(in); setFileSize(fileSize + RIFF_HEADER.length() + 4); readSize += 4; if (!findString(in, WAVE_HEADER, ENCODING)) return valid; if (!findString(in, FMT_CHUNK, ENCODING)) return valid; long fmtDataSize = BitConversion.extract4LittleEndian(in); readSize += 4; if (16 != fmtDataSize) { log.severe("fmt size differs: 16 bytes expected, but " + fmtDataSize + " bytes in header"); return valid; } format = BitConversion.extract2LittleEndian(in); channels = BitConversion.extract2LittleEndian(in); sampleFrequency = BitConversion.extract4LittleEndian(in); bytesPerSecond = BitConversion.extract4LittleEndian(in); blockAlign = BitConversion.extract2LittleEndian(in); bitsPerSample = BitConversion.extract2LittleEndian(in); readSize += 16; // according to the spec, a DATA_CHUNK should follow, but I've // found chunks, so this is disabled // if(!findString(in, DATA_CHUNK)) // return valid; valid = true; return valid; } // --- get object ------------------------------------------ public boolean isMP3() { return false; } public boolean isWAV() { return isValid(); } public boolean isOgg() { return false; } public int getFormat() { return format; } public int getChannels() { return channels; } public long getBytesPerSecond() { return bytesPerSecond; } public int getBlockAlign() { return blockAlign; } public int getBitsPerSample() { return bitsPerSample; } public int getMode() { switch (getChannels()) { case 1: return MODE_SINGLE_CHANNEL; case 2: return MODE_DUAL_CHANNEL; default: return MODE_UNKNOWN; } } public long getBitRate() { return getBytesPerSecond() * 8; } public int getSeconds() { if (getBytesPerSecond() != getSampleFrequency() * getBlockAlign()) log.severe("Inconsistent bytes per second, header=" + getBytesPerSecond() + " properties=" + (getSampleFrequency() * getBlockAlign())); if (getBlockAlign() != (getChannels() * getBitsPerSample() / 8)) log.severe("Inconsistent block align, header=" + getBlockAlign() + " properties=" + (getChannels() * getBitsPerSample() / 8)); return (int) (getDataSize() / getBytesPerSecond()); } // --- member variables ------------------------------------ /** * WAV properties */ protected int format = 0; protected int channels = 0; protected long bytesPerSecond = 0; protected int blockAlign = 0; protected int bitsPerSample = 0; }