Sort of fixed a streaming related memory leak. Well,

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: https://jmonkeyengine.googlecode.com/svn/trunk@7506 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
PSp..om 14 years ago
parent e73e97f753
commit c75f157cbb
  1. 74
      engine/src/lwjgl-oal/com/jme3/audio/lwjgl/LwjglAudioRenderer.java

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

Loading…
Cancel
Save