diff options
Diffstat (limited to 'src/java/com/jogamp/openal/util/WAVLoader.java')
-rw-r--r-- | src/java/com/jogamp/openal/util/WAVLoader.java | 144 |
1 files changed, 68 insertions, 76 deletions
diff --git a/src/java/com/jogamp/openal/util/WAVLoader.java b/src/java/com/jogamp/openal/util/WAVLoader.java index 22b4194..5547ed2 100644 --- a/src/java/com/jogamp/openal/util/WAVLoader.java +++ b/src/java/com/jogamp/openal/util/WAVLoader.java @@ -1,21 +1,20 @@ /** -* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved. -* Copyright (c) 2011 JogAmp Community. All rights reserved. +* Copyright (c) 2013 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * -* -Redistribution of source code must retain the above copyright notice, +* -Redistribution of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * -* -Redistribution in binary form must reproduce the above copyright notice, +* -Redistribution in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * -* Neither the name of Sun Microsystems, Inc. or the names of contributors may -* be used to endorse or promote products derived from this software without +* Neither the name of Sun Microsystems, Inc. or the names of contributors may +* be used to endorse or promote products derived from this software without * specific prior written permission. -* +* * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR @@ -30,41 +29,39 @@ * * You acknowledge that this software is not designed or intended for use in the * design, construction, operation or maintenance of any nuclear facility. +* +* Note: Rewrite started by Julien Goussej 2013-03-27 commit 6292ed9712b17f849f22221aea9d586c3a363c09 */ package com.jogamp.openal.util; -import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteOrder; +import com.jogamp.common.util.Bitstream; import com.jogamp.openal.ALException; /** * A Loader utility for (.wav) files. Creates a WAVData object containing the * data used by the AL.alBufferData method. - * - * @author Athomas Goldberg, et.al */ public class WAVLoader { - // private static final int BUFFER_SIZE = 128000; /** * This method loads a (.wav) file into a WAVData object. * * @param filename The name of the (.wav) file * - * @return a WAVData object containing the audio data + * @return a WAVData object containing the audio data * - * @throws UnsupportedAudioFileException if the format of the audio if not - * supported. - * @throws IOException If the file can no be found or some other IO error + * @throws ALException if the format of the audio if not supported. + * @throws IOException If the file can no be found or some other IO error * occurs */ - public static WAVData loadFromFile(String filename) throws IOException { + public static WAVData loadFromFile(String filename) throws ALException, IOException { File soundFile = new File(filename); InputStream is = new FileInputStream(soundFile); return loadFromStreamImpl(is); @@ -75,30 +72,24 @@ public class WAVLoader { * * @param stream An InputStream for the .WAV stream. * - * @return a WAVData object containing the audio data + * @return a WAVData object containing the audio data * - * @throws UnsupportedAudioFileException if the format of the audio if not - * supported. - * @throws IOException If the file can no be found or some other IO error + * @throws ALException if the format of the audio if not supported. + * @throws IOException If the file can no be found or some other IO error * occurs */ - public static WAVData loadFromStream(InputStream stream) throws IOException { + public static WAVData loadFromStream(InputStream stream) throws ALException, IOException { return loadFromStreamImpl(stream); } - - private static long readUnsignedIntLittleEndian(DataInputStream is) throws IOException { - byte[] buf = new byte[4]; - is.readFully(buf); - return (buf[0] & 0xFF | ((buf[1] & 0xFF) << 8) | ((buf[2] & 0xFF) << 16) | ((buf[3] & 0xFF) << 24)); - } - - private static short readUnsignedShortLittleEndian(DataInputStream is) throws IOException { - byte[] buf = new byte[2]; - is.readFully(buf); - return (short) (buf[0] & 0xFF | ((buf[1] & 0xFF) << 8)); - } - private static WAVData loadFromStreamImpl(InputStream aIn) throws IOException { + private static final int RIFF = 0x52494646; + private static final int RIFX = 0x52494658; + private static final int WAVE = 0x57415645; + private static final int FACT = 0x66616374; + private static final int FMT = 0x666D7420; + private static final int DATA = 0x64617461; + + private static WAVData loadFromStreamImpl(InputStream aIn) throws ALException, IOException { /** * references: * http://www.sonicspot.com/guide/wavefiles.html @@ -106,21 +97,25 @@ public class WAVLoader { * http://stackoverflow.com/questions/1111539/is-the-endianness-of-format-params-guaranteed-in-riff-wav-files * http://sharkysoft.com/archive/lava/docs/javadocs/lava/riff/wave/doc-files/riffwave-content.htm */ - final DataInputStream din; - if (aIn instanceof DataInputStream) { - din = (DataInputStream) aIn; - } else { - din = new DataInputStream(aIn); - } + final Bitstream.ByteInputStream bis = new Bitstream.ByteInputStream(aIn); + final Bitstream<InputStream> bs = new Bitstream<InputStream>(bis, false); + bs.setThrowIOExceptionOnEOF(true); try { - if (din.readInt() != 0x52494646) {// "RIFF", little endian - //FIXME "RIFX", big endian, read the data in big endian in this case - throw new ALException("Invalid WAV header"); + final boolean bigEndian; // FIXME: for all data incl. signatures ? + + final long riffMarker = bs.readUInt32(true /* msbFirst */, true /* bigEndian */); + if ( RIFF == riffMarker ) { + bigEndian = false; + } else if( RIFX == riffMarker ) { + bigEndian = true; + } else { + throw new ALException("Invalid RIF header: 0x"+Integer.toHexString((int)riffMarker)+", "+bs); } - // length of the RIFF, unused - readUnsignedIntLittleEndian(din); - if (din.readInt() != 0x57415645) {// "WAVE" - throw new ALException("Invalid WAV header"); + final long riffLenL = bs.readUInt32(true /*msbFirst*/, bigEndian); + final int riffLenI = Bitstream.uint32LongToInt(riffLenL); + final long wavMarker = bs.readUInt32(true /* msbFirst */, true /* bigEndian */); + if ( WAVE != wavMarker ) { + throw new ALException("Invalid WAV header: 0x"+Integer.toHexString((int)wavMarker)+", "+bs); } boolean foundFmt = false; boolean foundData = false; @@ -130,49 +125,46 @@ public class WAVLoader { long chunkLength = 0; while (!foundData) { - int chunkId = din.readInt(); - chunkLength = readUnsignedIntLittleEndian(din); + int chunkId = (int)bs.readUInt32(true /* msbFirst */, true /* bigEndian */); + chunkLength = bs.readUInt32(true /* msbFirst */, bigEndian); switch (chunkId) { - case 0x666D7420: // "fmt " + case FMT: foundFmt = true; - // compression code, unused - readUnsignedShortLittleEndian(din); - sChannels = readUnsignedShortLittleEndian(din); - sampleRate = readUnsignedIntLittleEndian(din); - // bytes per second, unused - readUnsignedIntLittleEndian(din); - // block alignment, unused - readUnsignedShortLittleEndian(din); - sSampleSizeInBits = readUnsignedShortLittleEndian(din); - din.skip(chunkLength - 16); + @SuppressWarnings("unused") + final int compressionCode = bs.readUInt16(true /* msbFirst */, bigEndian); + sChannels = (short)bs.readUInt16(true /* msbFirst */, bigEndian); + sampleRate = bs.readUInt32(true /* msbFirst */, bigEndian); + @SuppressWarnings("unused") + final long bytesPerSeconds = bs.readUInt32(true /* msbFirst */, bigEndian); + @SuppressWarnings("unused") + final short blockAlignment = (short) bs.readUInt16(true /* msbFirst */, bigEndian); + sSampleSizeInBits = (short) bs.readUInt16(true /* msbFirst */, bigEndian); + bs.skip( 8 * ( chunkLength - 16 ) ); break; - case 0x66616374: // "fact" + case FACT: // FIXME: compression format dependent data? - din.skip(chunkLength); + bs.skip( 8 * chunkLength ); break; - case 0x64617461: // "data" - if (!foundFmt) - throw new ALException( - "WAV fmt chunks must be before data chunks"); + case DATA: + if (!foundFmt) { + throw new ALException("WAV fmt chunks must be before data chunks: "+bs); + } foundData = true; break; default: // unrecognized chunk, skips it - din.skip(chunkLength); + bs.skip( 8 * chunkLength ); } } - final int channels = (int) sChannels; + final int channels = sChannels; final int sampleSizeInBits = sSampleSizeInBits; - final float fSampleRate = (float) sampleRate; - //FIXME big endian not supported yet - final boolean isBigEndian = false; - return WAVData.loadFromStream(aIn, -1, channels, sampleSizeInBits, - Math.round(fSampleRate), isBigEndian ? ByteOrder.BIG_ENDIAN - : ByteOrder.LITTLE_ENDIAN, false); + final float fSampleRate = sampleRate; + return WAVData.loadFromStream(bs.getSubStream(), riffLenI, channels, sampleSizeInBits, + Math.round(fSampleRate), bigEndian ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN, false); } finally { - din.close(); + bs.close(); } } - + } |