OSDN Git Service

Sort of fixed a streaming related memory leak. Well,
authorPSpeed42@gmail.com <PSpeed42@gmail.com@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Mon, 16 May 2011 22:59:49 +0000 (22:59 +0000)
committerPSpeed42@gmail.com <PSpeed42@gmail.com@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Mon, 16 May 2011 22:59:49 +0000 (22:59 +0000)
streams won't leak anymore but the buffered case
technically will if you create them and drop them because
that's a different level of fix.
Also made the deleteAudioData synchronized since it can
be called from another thread pretty trivially.
And fixed a race condition that caused an IndexOutOfBounds
exception if you happen to try adjusting an AudioNode's
parameters right as it was finishing playing.

git-svn-id: http://jmonkeyengine.googlecode.com/svn/trunk@7506 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

engine/src/lwjgl-oal/com/jme3/audio/lwjgl/LwjglAudioRenderer.java

index 1c69fa7..493e39d 100644 (file)
@@ -298,6 +298,18 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
             }\r
             if (audioDisabled)\r
                 return;\r
\r
+            // There is a race condition in AudioNode that can\r
+            // cause this to be called for a node that has been\r
+            // detached from its channel.  For example, setVolume()\r
+            // called from the render thread may see that that AudioNode\r
+            // still has a channel value but the audio thread may\r
+            // clear that channel before setVolume() gets to call\r
+            // updateSourceParam() (because the audio stopped playing\r
+            // on its own right as the volume was set).  In this case, \r
+            // it should be safe to just ignore the update\r
+            if (src.getChannel() < 0) \r
+                return;\r
            \r
             assert src.getChannel() >= 0;\r
 \r
@@ -745,6 +757,10 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
                         src.setChannel(-1);\r
                         clearChannel(i);\r
                         freeChannel(i);\r
\r
+                        // And free the audio since it cannot be\r
+                        // played again anyway.\r
+                        deleteAudioData(stream);\r
                     }\r
                 }\r
             }else if (!streaming){\r
@@ -913,6 +929,18 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
                 src.setChannel(-1);\r
                 clearChannel(chan);\r
                 freeChannel(chan);\r
+                \r
+                if (src.getAudioData() instanceof AudioStream) {\r
+                    \r
+                    AudioStream stream = (AudioStream)src.getAudioData();\r
+                    if (stream.isOpen()) {\r
+                        stream.close();\r
+                    }\r
+                \r
+                    // And free the audio since it cannot be\r
+                    // played again anyway.\r
+                    deleteAudioData(src.getAudioData());\r
+                }                    \r
             }\r
         }\r
     }\r
@@ -958,7 +986,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
         int[] ids = new int[STREAMING_BUFFER_COUNT];\r
         ib.position(0).limit(STREAMING_BUFFER_COUNT);\r
         alGenBuffers(ib);\r
-        ib.position(0).limit(STREAMING_BUFFER_COUNT);\r
+        ib.position(0).limit(STREAMING_BUFFER_COUNT);        \r
         ib.get(ids);\r
         \r
         as.setIds(ids);\r
@@ -974,28 +1002,36 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
     }\r
 \r
     public void deleteAudioData(AudioData ad){\r
-        if (audioDisabled)\r
-            return;\r
-        \r
-        if (ad instanceof AudioBuffer){\r
-            AudioBuffer ab = (AudioBuffer) ad;\r
-            int id = ab.getId();\r
-            if (id != -1){\r
-                ib.put(0,id);\r
-                ib.position(0).limit(1);\r
-                alDeleteBuffers(ib);\r
-                ab.resetObject();\r
+        synchronized (threadLock){\r
+            while (!threadLock.get()){\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
             }\r
-        }else if (ad instanceof AudioStream){\r
-            AudioStream as = (AudioStream) ad;\r
-            int[] ids = as.getIds();\r
-            if (ids != null){\r
-                ib.clear();\r
-                ib.put(ids).flip();\r
-                alDeleteBuffers(ib);\r
-                as.resetObject();\r
+            if (audioDisabled)\r
+                return;\r
+        \r
+            if (ad instanceof AudioBuffer){\r
+                AudioBuffer ab = (AudioBuffer) ad;\r
+                int id = ab.getId();\r
+                if (id != -1){\r
+                    ib.put(0,id);\r
+                    ib.position(0).limit(1);\r
+                    alDeleteBuffers(ib);\r
+                    ab.resetObject();\r
+                }\r
+            }else if (ad instanceof AudioStream){\r
+                AudioStream as = (AudioStream) ad;\r
+                int[] ids = as.getIds();\r
+                if (ids != null){\r
+                    ib.clear();\r
+                    ib.put(ids).flip();\r
+                    alDeleteBuffers(ib);\r
+                    as.resetObject();\r
+                }\r
             }\r
-        }\r
+        }            \r
     }\r
 \r
 }\r