summaryrefslogtreecommitdiffstats
path: root/src/java/com/jogamp/openal/util/WAVLoader.java
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2014-02-21 14:47:36 +0100
committerSven Gothel <[email protected]>2014-02-21 14:47:36 +0100
commitd199e6cdbf1fe1283bad79f68d05a9037a91863b (patch)
treec9b5f489f44e75adb6beeea23f71fc97f98f0f79 /src/java/com/jogamp/openal/util/WAVLoader.java
parentb49859e5ea464a978812036bef05718e6ea00909 (diff)
WAVLoader: Use Bitstream and support big-endian RIFX; Fix ALutWAVLoaderTest
Diffstat (limited to 'src/java/com/jogamp/openal/util/WAVLoader.java')
-rw-r--r--src/java/com/jogamp/openal/util/WAVLoader.java144
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();
}
}
-
+
}