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
This commit is contained in:
parent
f3675227e0
commit
1f2193a2b9
@ -448,6 +448,13 @@ public class AudioNode extends Node {
|
||||
}
|
||||
|
||||
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.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* <code>AudioStream</code> is an implementation of AudioData that
|
||||
@ -47,20 +49,20 @@ import java.io.InputStream;
|
||||
*/
|
||||
public class AudioStream extends AudioData implements Closeable{
|
||||
|
||||
private final static Logger logger = Logger.getLogger(AudioStream.class.getName());
|
||||
protected InputStream in;
|
||||
protected float duration = -1f;
|
||||
protected boolean open = false;
|
||||
protected int[] ids;
|
||||
|
||||
|
||||
public AudioStream(){
|
||||
super();
|
||||
super();
|
||||
}
|
||||
|
||||
protected AudioStream(int[] ids){
|
||||
// Pass some dummy ID so handle
|
||||
// doesn't get created.
|
||||
super(-1);
|
||||
|
||||
super(-1);
|
||||
// This is what gets destroyed in reality
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
15
engine/src/core/com/jme3/audio/SeekableStream.java
Normal file
15
engine/src/core/com/jme3/audio/SeekableStream.java
Normal file
@ -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.AudioKey;
|
||||
import com.jme3.audio.AudioStream;
|
||||
import com.jme3.audio.SeekableStream;
|
||||
import com.jme3.util.BufferUtils;
|
||||
import de.jarnbjo.ogg.EndOfOggStreamException;
|
||||
import de.jarnbjo.ogg.LogicalOggStream;
|
||||
@ -49,6 +50,8 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class OGGLoader implements AssetLoader {
|
||||
|
||||
@ -64,10 +67,10 @@ public class OGGLoader implements AssetLoader {
|
||||
private static class JOggInputStream extends InputStream {
|
||||
|
||||
private boolean endOfStream = false;
|
||||
private final VorbisStream vs;
|
||||
protected final VorbisStream vs;
|
||||
|
||||
public JOggInputStream(VorbisStream vs){
|
||||
this.vs = vs;
|
||||
public JOggInputStream(VorbisStream vs){
|
||||
this.vs = vs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -88,14 +91,25 @@ public class OGGLoader implements AssetLoader {
|
||||
int bytesRead = 0, cnt = 0;
|
||||
assert length % 2 == 0; // read buffer should be even
|
||||
|
||||
while (bytesRead < buf.length) {
|
||||
if ((cnt = vs.readPcm(buf, offset + bytesRead, buf.length - bytesRead)) <= 0) {
|
||||
endOfStream = true;
|
||||
while (bytesRead <length) {
|
||||
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;
|
||||
break;
|
||||
}
|
||||
bytesRead += cnt;
|
||||
}
|
||||
|
||||
}
|
||||
bytesRead += cnt;
|
||||
}
|
||||
|
||||
swapBytes(buf, offset, bytesRead);
|
||||
return bytesRead;
|
||||
|
||||
@ -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.
|
||||
*
|
||||
@ -194,8 +238,12 @@ public class OGGLoader implements AssetLoader {
|
||||
}
|
||||
}
|
||||
|
||||
private InputStream readToStream(){
|
||||
return new JOggInputStream(vorbisStream);
|
||||
private InputStream readToStream(boolean seekable,float streamDuration){
|
||||
if(seekable){
|
||||
return new SeekableJOggInputStream(vorbisStream,loStream,streamDuration);
|
||||
}else{
|
||||
return new JOggInputStream(vorbisStream);
|
||||
}
|
||||
}
|
||||
|
||||
private AudioData load(InputStream in, boolean readStream, boolean streamCache) throws IOException{
|
||||
@ -228,7 +276,7 @@ public class OGGLoader implements AssetLoader {
|
||||
// might return -1 if unknown
|
||||
float streamDuration = computeStreamDuration();
|
||||
|
||||
audioStream.updateData(readToStream(), streamDuration);
|
||||
audioStream.updateData(readToStream(oggStream.isSeekable(),streamDuration), streamDuration);
|
||||
return audioStream;
|
||||
}
|
||||
}
|
||||
|
@ -33,9 +33,11 @@
|
||||
package jme3test.audio;
|
||||
|
||||
import com.jme3.asset.AssetInfo;
|
||||
import com.jme3.asset.AssetLoader;
|
||||
import com.jme3.audio.AudioNode.Status;
|
||||
import com.jme3.audio.*;
|
||||
import com.jme3.audio.plugins.OGGLoader;
|
||||
import com.jme3.audio.plugins.WAVLoader;
|
||||
import com.jme3.system.AppSettings;
|
||||
import com.jme3.system.JmeSystem;
|
||||
import java.io.*;
|
||||
@ -172,7 +174,13 @@ public class TestMusicPlayer extends javax.swing.JFrame {
|
||||
btnStopActionPerformed(null);
|
||||
|
||||
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);
|
||||
try{
|
||||
musicData = (AudioData) loader.load(new AssetInfo(null, key) {
|
||||
@ -255,10 +263,10 @@ public class TestMusicPlayer extends javax.swing.JFrame {
|
||||
curTime = 0;
|
||||
|
||||
musicSource.setTimeOffset(curTime);
|
||||
if (musicSource.getStatus() == Status.Playing){
|
||||
musicSource.stop();
|
||||
musicSource.play();
|
||||
}
|
||||
// if (musicSource.getStatus() == Status.Playing){
|
||||
// musicSource.stop();
|
||||
// musicSource.play();
|
||||
// }
|
||||
updateTime();
|
||||
}
|
||||
}//GEN-LAST:event_sldBarStateChanged
|
||||
|
Loading…
x
Reference in New Issue
Block a user