Browse Source

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
rem..om 14 years ago
parent
commit
1f2193a2b9

+ 7 - 0
engine/src/core/com/jme3/audio/AudioNode.java

@@ -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();
+        }
     }
 
     /**

+ 16 - 4
engine/src/core/com/jme3/audio/AudioStream.java

@@ -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 - 0
engine/src/core/com/jme3/audio/SeekableStream.java

@@ -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);
+    
+}

+ 61 - 13
engine/src/jogg/com/jme3/audio/plugins/OGGLoader.java

@@ -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;
         }
     }

+ 13 - 5
engine/src/test/jme3test/audio/TestMusicPlayer.java

@@ -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