diff options
-rw-r--r-- | src/java/com/jogamp/openal/util/ALut.java | 3 | ||||
-rw-r--r-- | src/java/com/jogamp/openal/util/WAVLoader.java | 122 |
2 files changed, 94 insertions, 31 deletions
diff --git a/src/java/com/jogamp/openal/util/ALut.java b/src/java/com/jogamp/openal/util/ALut.java index 2db47d0..c6439d7 100644 --- a/src/java/com/jogamp/openal/util/ALut.java +++ b/src/java/com/jogamp/openal/util/ALut.java @@ -37,9 +37,6 @@ package com.jogamp.openal.util; import java.io.*; import java.nio.ByteBuffer; - -import javax.sound.sampled.UnsupportedAudioFileException; - import com.jogamp.openal.*; /** diff --git a/src/java/com/jogamp/openal/util/WAVLoader.java b/src/java/com/jogamp/openal/util/WAVLoader.java index f997eb4..22b4194 100644 --- a/src/java/com/jogamp/openal/util/WAVLoader.java +++ b/src/java/com/jogamp/openal/util/WAVLoader.java @@ -34,16 +34,14 @@ 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 javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioInputStream; -import javax.sound.sampled.AudioSystem; - -import com.jogamp.openal.UnsupportedAudioFileException; +import com.jogamp.openal.ALException; /** * A Loader utility for (.wav) files. Creates a WAVData object containing the @@ -66,15 +64,10 @@ public class WAVLoader { * @throws IOException If the file can no be found or some other IO error * occurs */ - public static WAVData loadFromFile(String filename) - throws UnsupportedAudioFileException, IOException { + public static WAVData loadFromFile(String filename) throws IOException { File soundFile = new File(filename); - try { - AudioInputStream aIn = AudioSystem.getAudioInputStream(soundFile); - return loadFromStreamImpl(aIn); - } catch (javax.sound.sampled.UnsupportedAudioFileException e) { - throw new UnsupportedAudioFileException(e); - } + InputStream is = new FileInputStream(soundFile); + return loadFromStreamImpl(is); } /** @@ -89,24 +82,97 @@ public class WAVLoader { * @throws IOException If the file can no be found or some other IO error * occurs */ - public static WAVData loadFromStream(InputStream stream) - throws UnsupportedAudioFileException, IOException { - AudioInputStream aIn; - try { - aIn = AudioSystem.getAudioInputStream(stream); - return loadFromStreamImpl(aIn); - } catch (javax.sound.sampled.UnsupportedAudioFileException e) { - throw new UnsupportedAudioFileException(e); - } + public static WAVData loadFromStream(InputStream stream) throws 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 { + /** + * references: + * http://www.sonicspot.com/guide/wavefiles.html + * https://ccrma.stanford.edu/courses/422/projects/WaveFormat/ + * 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); + } + 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"); + } + // length of the RIFF, unused + readUnsignedIntLittleEndian(din); + if (din.readInt() != 0x57415645) {// "WAVE" + throw new ALException("Invalid WAV header"); + } + boolean foundFmt = false; + boolean foundData = false; + + short sChannels = 0, sSampleSizeInBits = 0; + long sampleRate = 0; + long chunkLength = 0; + while (!foundData) { + int chunkId = din.readInt(); + chunkLength = readUnsignedIntLittleEndian(din); + switch (chunkId) { + case 0x666D7420: // "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); + break; + case 0x66616374: // "fact" + // FIXME: compression format dependent data? + din.skip(chunkLength); + break; + case 0x64617461: // "data" + if (!foundFmt) + throw new ALException( + "WAV fmt chunks must be before data chunks"); + foundData = true; + break; + default: + // unrecognized chunk, skips it + din.skip(chunkLength); + } + } - private static WAVData loadFromStreamImpl(AudioInputStream aIn) - throws UnsupportedAudioFileException, IOException { - final AudioFormat fmt = aIn.getFormat(); - return WAVData.loadFromStream(aIn, -1, fmt.getChannels(), fmt.getSampleSizeInBits(), - Math.round(fmt.getSampleRate()), - fmt.isBigEndian() ? ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN, false); + final int channels = (int) 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); + } finally { + din.close(); + } } } |