Audio : implemented API for seeking capability in streamed ogg files. It doesn't work fine yet

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@8967 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 13 years ago
parent f3675227e0
commit 1f2193a2b9
  1. 7
      engine/src/core/com/jme3/audio/AudioNode.java
  2. 14
      engine/src/core/com/jme3/audio/AudioStream.java
  3. 15
      engine/src/core/com/jme3/audio/SeekableStream.java
  4. 58
      engine/src/jogg/com/jme3/audio/plugins/OGGLoader.java
  5. 18
      engine/src/test/jme3test/audio/TestMusicPlayer.java

@ -448,6 +448,13 @@ public class AudioNode extends Node {
} }
this.timeOffset = timeOffset; this.timeOffset = timeOffset;
if (data instanceof AudioStream) {
System.out.println("request setTime");
((AudioStream) data).setTime(timeOffset);
}else if(status == Status.Playing){
stop();
play();
}
} }
/** /**

@ -36,6 +36,8 @@ import com.jme3.util.NativeObject;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/** /**
* <code>AudioStream</code> is an implementation of AudioData that * <code>AudioStream</code> is an implementation of AudioData that
@ -47,6 +49,7 @@ import java.io.InputStream;
*/ */
public class AudioStream extends AudioData implements Closeable{ public class AudioStream extends AudioData implements Closeable{
private final static Logger logger = Logger.getLogger(AudioStream.class.getName());
protected InputStream in; protected InputStream in;
protected float duration = -1f; protected float duration = -1f;
protected boolean open = false; protected boolean open = false;
@ -60,7 +63,6 @@ public class AudioStream extends AudioData implements Closeable{
// Pass some dummy ID so handle // Pass some dummy ID so handle
// doesn't get created. // doesn't get created.
super(-1); super(-1);
// This is what gets destroyed in reality // This is what gets destroyed in reality
this.ids = ids; this.ids = ids;
} }
@ -189,4 +191,14 @@ public class AudioStream extends AudioData implements Closeable{
} }
} }
public void setTime(float time){
if(in instanceof SeekableStream){
((SeekableStream)in).setTime(time);
}else{
logger.log(Level.WARNING,"Cannot use setTime on a stream that is not seekable. You must load the file with the streamCache option set to true");
}
}
} }

@ -0,0 +1,15 @@
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.jme3.audio;
/**
*
* @author Nehon
*/
public interface SeekableStream{
public void setTime(float time);
}

@ -38,6 +38,7 @@ import com.jme3.audio.AudioBuffer;
import com.jme3.audio.AudioData; import com.jme3.audio.AudioData;
import com.jme3.audio.AudioKey; import com.jme3.audio.AudioKey;
import com.jme3.audio.AudioStream; import com.jme3.audio.AudioStream;
import com.jme3.audio.SeekableStream;
import com.jme3.util.BufferUtils; import com.jme3.util.BufferUtils;
import de.jarnbjo.ogg.EndOfOggStreamException; import de.jarnbjo.ogg.EndOfOggStreamException;
import de.jarnbjo.ogg.LogicalOggStream; import de.jarnbjo.ogg.LogicalOggStream;
@ -49,6 +50,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Collection; import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
public class OGGLoader implements AssetLoader { public class OGGLoader implements AssetLoader {
@ -64,7 +67,7 @@ public class OGGLoader implements AssetLoader {
private static class JOggInputStream extends InputStream { private static class JOggInputStream extends InputStream {
private boolean endOfStream = false; private boolean endOfStream = false;
private final VorbisStream vs; protected final VorbisStream vs;
public JOggInputStream(VorbisStream vs){ public JOggInputStream(VorbisStream vs){
this.vs = vs; this.vs = vs;
@ -88,8 +91,19 @@ public class OGGLoader implements AssetLoader {
int bytesRead = 0, cnt = 0; int bytesRead = 0, cnt = 0;
assert length % 2 == 0; // read buffer should be even assert length % 2 == 0; // read buffer should be even
while (bytesRead < buf.length) { while (bytesRead <length) {
if ((cnt = vs.readPcm(buf, offset + bytesRead, buf.length - bytesRead)) <= 0) { if ((cnt = vs.readPcm(buf, offset + bytesRead,length - bytesRead)) <= 0) {
System.out.println("Read "+cnt+" bytes");
System.out.println("offset "+offset);
System.out.println("bytesRead "+bytesRead);
System.out.println("buf length "+length);
for (int i = 0; i < bytesRead; i++) {
System.out.print(buf[i]);
}
System.out.println("");
System.out.println("EOS");
endOfStream = true; endOfStream = true;
break; break;
} }
@ -108,6 +122,36 @@ public class OGGLoader implements AssetLoader {
} }
private static class SeekableJOggInputStream extends JOggInputStream implements SeekableStream {
private LogicalOggStream los;
private float duration;
public SeekableJOggInputStream(VorbisStream vs, LogicalOggStream los, float duration){
super(vs);
this.los = los;
this.duration = duration;
}
public void setTime(float time) {
System.out.println("--setTime--)");
System.out.println("max granule : "+los.getMaximumGranulePosition());
System.out.println("current granule : "+los.getTime());
System.out.println("asked Time : "+time);
System.out.println("new granule : "+(time/duration*los.getMaximumGranulePosition()));
System.out.println("new granule2 : "+(time*vs.getIdentificationHeader().getSampleRate()));
try {
los.setTime((long)(time*vs.getIdentificationHeader().getSampleRate()));
} catch (IOException ex) {
Logger.getLogger(OGGLoader.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/** /**
* Returns the total of expected OGG bytes. * Returns the total of expected OGG bytes.
* *
@ -194,9 +238,13 @@ public class OGGLoader implements AssetLoader {
} }
} }
private InputStream readToStream(){ private InputStream readToStream(boolean seekable,float streamDuration){
if(seekable){
return new SeekableJOggInputStream(vorbisStream,loStream,streamDuration);
}else{
return new JOggInputStream(vorbisStream); return new JOggInputStream(vorbisStream);
} }
}
private AudioData load(InputStream in, boolean readStream, boolean streamCache) throws IOException{ private AudioData load(InputStream in, boolean readStream, boolean streamCache) throws IOException{
if (readStream && streamCache){ if (readStream && streamCache){
@ -228,7 +276,7 @@ public class OGGLoader implements AssetLoader {
// might return -1 if unknown // might return -1 if unknown
float streamDuration = computeStreamDuration(); float streamDuration = computeStreamDuration();
audioStream.updateData(readToStream(), streamDuration); audioStream.updateData(readToStream(oggStream.isSeekable(),streamDuration), streamDuration);
return audioStream; return audioStream;
} }
} }

@ -33,9 +33,11 @@
package jme3test.audio; package jme3test.audio;
import com.jme3.asset.AssetInfo; import com.jme3.asset.AssetInfo;
import com.jme3.asset.AssetLoader;
import com.jme3.audio.AudioNode.Status; import com.jme3.audio.AudioNode.Status;
import com.jme3.audio.*; import com.jme3.audio.*;
import com.jme3.audio.plugins.OGGLoader; import com.jme3.audio.plugins.OGGLoader;
import com.jme3.audio.plugins.WAVLoader;
import com.jme3.system.AppSettings; import com.jme3.system.AppSettings;
import com.jme3.system.JmeSystem; import com.jme3.system.JmeSystem;
import java.io.*; import java.io.*;
@ -172,7 +174,13 @@ public class TestMusicPlayer extends javax.swing.JFrame {
btnStopActionPerformed(null); btnStopActionPerformed(null);
final File selected = chooser.getSelectedFile(); final File selected = chooser.getSelectedFile();
OGGLoader loader = new OGGLoader(); AssetLoader loader = null;
if(selected.getName().endsWith(".wav")){
loader = new WAVLoader();
}else{
loader = new OGGLoader();
}
AudioKey key = new AudioKey(selected.getName(), true, true); AudioKey key = new AudioKey(selected.getName(), true, true);
try{ try{
musicData = (AudioData) loader.load(new AssetInfo(null, key) { musicData = (AudioData) loader.load(new AssetInfo(null, key) {
@ -255,10 +263,10 @@ public class TestMusicPlayer extends javax.swing.JFrame {
curTime = 0; curTime = 0;
musicSource.setTimeOffset(curTime); musicSource.setTimeOffset(curTime);
if (musicSource.getStatus() == Status.Playing){ // if (musicSource.getStatus() == Status.Playing){
musicSource.stop(); // musicSource.stop();
musicSource.play(); // musicSource.play();
} // }
updateTime(); updateTime();
} }
}//GEN-LAST:event_sldBarStateChanged }//GEN-LAST:event_sldBarStateChanged

Loading…
Cancel
Save