|
@@ -37,8 +37,10 @@ import com.jme3.audio.AudioBuffer;
|
|
|
import com.jme3.audio.AudioData;
|
|
|
import com.jme3.audio.AudioKey;
|
|
|
import com.jme3.audio.AudioStream;
|
|
|
+import com.jme3.audio.SeekableStream;
|
|
|
import com.jme3.util.BufferUtils;
|
|
|
import com.jme3.util.LittleEndien;
|
|
|
+import java.io.BufferedInputStream;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.nio.ByteBuffer;
|
|
@@ -63,7 +65,41 @@ public class WAVLoader implements AssetLoader {
|
|
|
private int bytesPerSec;
|
|
|
private float duration;
|
|
|
|
|
|
- private LittleEndien in;
|
|
|
+ private ResettableInputStream in;
|
|
|
+ private int inOffset = 0;
|
|
|
+
|
|
|
+ private static class ResettableInputStream extends LittleEndien implements SeekableStream {
|
|
|
+
|
|
|
+ private AssetInfo info;
|
|
|
+ private int resetOffset = 0;
|
|
|
+
|
|
|
+ public ResettableInputStream(AssetInfo info, InputStream in) {
|
|
|
+ super(in);
|
|
|
+ this.info = info;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setResetOffset(int resetOffset) {
|
|
|
+ this.resetOffset = resetOffset;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void setTime(float time) {
|
|
|
+ if (time != 0f) {
|
|
|
+ throw new UnsupportedOperationException("Seeking WAV files not supported");
|
|
|
+ }
|
|
|
+ InputStream newStream = info.openStream();
|
|
|
+ try {
|
|
|
+ newStream.skip(resetOffset);
|
|
|
+ this.in = new BufferedInputStream(newStream);
|
|
|
+ } catch (IOException ex) {
|
|
|
+ // Resource could have gotten lost, etc.
|
|
|
+ try {
|
|
|
+ newStream.close();
|
|
|
+ } catch (IOException ex2) {
|
|
|
+ }
|
|
|
+ throw new RuntimeException(ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
private void readFormatChunk(int size) throws IOException{
|
|
|
// if other compressions are supported, size doesn't have to be 16
|
|
@@ -118,12 +154,14 @@ public class WAVLoader implements AssetLoader {
|
|
|
in.close();
|
|
|
}
|
|
|
|
|
|
- private void readDataChunkForStream(int len) throws IOException {
|
|
|
+ private void readDataChunkForStream(int offset, int len) throws IOException {
|
|
|
+ in.setResetOffset(offset);
|
|
|
audioStream.updateData(in, duration);
|
|
|
}
|
|
|
|
|
|
- private AudioData load(InputStream inputStream, boolean stream) throws IOException{
|
|
|
- this.in = new LittleEndien(inputStream);
|
|
|
+ private AudioData load(AssetInfo info, InputStream inputStream, boolean stream) throws IOException{
|
|
|
+ this.in = new ResettableInputStream(info, inputStream);
|
|
|
+ inOffset = 0;
|
|
|
|
|
|
int sig = in.readInt();
|
|
|
if (sig != i_RIFF)
|
|
@@ -134,6 +172,8 @@ public class WAVLoader implements AssetLoader {
|
|
|
if (in.readInt() != i_WAVE)
|
|
|
throw new IOException("WAVE File does not contain audio");
|
|
|
|
|
|
+ inOffset += 4 * 3;
|
|
|
+
|
|
|
readStream = stream;
|
|
|
if (readStream){
|
|
|
audioStream = new AudioStream();
|
|
@@ -146,17 +186,20 @@ public class WAVLoader implements AssetLoader {
|
|
|
while (true) {
|
|
|
int type = in.readInt();
|
|
|
int len = in.readInt();
|
|
|
+
|
|
|
+ inOffset += 4 * 2;
|
|
|
|
|
|
switch (type) {
|
|
|
case i_fmt:
|
|
|
readFormatChunk(len);
|
|
|
+ inOffset += len;
|
|
|
break;
|
|
|
case i_data:
|
|
|
// Compute duration based on data chunk size
|
|
|
duration = len / bytesPerSec;
|
|
|
|
|
|
if (readStream) {
|
|
|
- readDataChunkForStream(len);
|
|
|
+ readDataChunkForStream(inOffset, len);
|
|
|
} else {
|
|
|
readDataChunkForBuffer(len);
|
|
|
}
|
|
@@ -166,6 +209,7 @@ public class WAVLoader implements AssetLoader {
|
|
|
if (skipped <= 0) {
|
|
|
return null;
|
|
|
}
|
|
|
+ inOffset += skipped;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
@@ -176,7 +220,7 @@ public class WAVLoader implements AssetLoader {
|
|
|
InputStream inputStream = null;
|
|
|
try {
|
|
|
inputStream = info.openStream();
|
|
|
- data = load(inputStream, ((AudioKey)info.getKey()).isStream());
|
|
|
+ data = load(info, inputStream, ((AudioKey)info.getKey()).isStream());
|
|
|
if (data instanceof AudioStream){
|
|
|
inputStream = null;
|
|
|
}
|