* Fixed issue where setReverbEnabled(false) after setPositional(false) did not actually remove reverb. Reverb is now removed automatically when setPositional(false) per contract of the method.

* Formatted the classes.

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@9569 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
Sha..rd 13 years ago
parent 5497fcc7e6
commit 9d95528e21
  1. 6
      engine/src/core/com/jme3/audio/AudioNode.java
  2. 144
      engine/src/lwjgl/com/jme3/audio/lwjgl/LwjglAudioRenderer.java

@ -442,9 +442,10 @@ public class AudioNode extends Node {
*/
public void setReverbEnabled(boolean reverbEnabled) {
this.reverbEnabled = reverbEnabled;
if (channel >= 0)
if (channel >= 0) {
getRenderer().updateSourceParam(this, AudioParam.ReverbEnabled);
}
}
/**
* @return Filter for the reverberations of this audio node.
@ -642,9 +643,10 @@ public class AudioNode extends Node {
*/
public void setPositional(boolean positional) {
this.positional = positional;
if (channel >= 0)
if (channel >= 0) {
getRenderer().updateSourceParam(this, AudioParam.IsPositional);
}
}
@Override
public void updateGeometricState(){

@ -29,11 +29,10 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.audio.lwjgl;
import com.jme3.audio.*;
import com.jme3.audio.AudioNode.Status;
import com.jme3.audio.*;
import com.jme3.math.Vector3f;
import com.jme3.util.BufferUtils;
import com.jme3.util.NativeObjectManager;
@ -45,42 +44,34 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.openal.*;
import static org.lwjgl.openal.AL10.*;
import org.lwjgl.openal.*;
public class LwjglAudioRenderer implements AudioRenderer, Runnable {
private static final Logger logger = Logger.getLogger(LwjglAudioRenderer.class.getName());
private final NativeObjectManager objManager = new NativeObjectManager();
// When multiplied by STREAMING_BUFFER_COUNT, will equal 44100 * 2 * 2
// which is exactly 1 second of audio.
private static final int BUFFER_SIZE = 35280;
private static final int STREAMING_BUFFER_COUNT = 5;
private final static int MAX_NUM_CHANNELS = 64;
private IntBuffer ib = BufferUtils.createIntBuffer(1);
private final FloatBuffer fb = BufferUtils.createVector3Buffer(2);
private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE);
private final byte[] arrayBuf = new byte[BUFFER_SIZE];
private int[] channels;
private AudioNode[] chanSrcs;
private int nextChan = 0;
private ArrayList<Integer> freeChans = new ArrayList<Integer>();
private Listener listener;
private boolean audioDisabled = false;
private boolean supportEfx = false;
private int auxSends = 0;
private int reverbFx = -1;
private int reverbFxSlot = -1;
// Update audio 20 times per second
private static final float UPDATE_RATE = 0.05f;
private final Thread audioThread = new Thread(this, "jME3 Audio Thread");
private final AtomicBoolean threadLock = new AtomicBoolean(false);
@ -98,9 +89,10 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
private void checkDead() {
if (audioThread.getState() == Thread.State.TERMINATED)
if (audioThread.getState() == Thread.State.TERMINATED) {
throw new IllegalStateException("Audio thread is terminated");
}
}
public void run() {
initInThread();
@ -110,11 +102,13 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
long updateRateNanos = (long) (UPDATE_RATE * 1000000000);
mainloop: while (true){
mainloop:
while (true) {
long startTime = System.nanoTime();
if (Thread.interrupted())
if (Thread.interrupted()) {
break;
}
synchronized (threadLock) {
updateInThread(UPDATE_RATE);
@ -281,8 +275,8 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAIN, lpf.getVolume());
EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAINHF, lpf.getHighFreqVolume());
} else {
throw new UnsupportedOperationException("Filter type unsupported: "+
f.getClass().getName());
throw new UnsupportedOperationException("Filter type unsupported: "
+ f.getClass().getName());
}
f.clearUpdateNeeded();
@ -297,8 +291,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled)
if (audioDisabled) {
return;
}
// There is a race condition in AudioNode that can
// cause this to be called for a node that has been
@ -309,42 +304,48 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
// 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)
if (src.getChannel() < 0) {
return;
}
assert src.getChannel() >= 0;
int id = channels[src.getChannel()];
switch (param) {
case Position:
if (!src.isPositional())
if (!src.isPositional()) {
return;
}
Vector3f pos = src.getWorldTranslation();
alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);
break;
case Velocity:
if (!src.isPositional())
if (!src.isPositional()) {
return;
}
Vector3f vel = src.getVelocity();
alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z);
break;
case MaxDistance:
if (!src.isPositional())
if (!src.isPositional()) {
return;
}
alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance());
break;
case RefDistance:
if (!src.isPositional())
if (!src.isPositional()) {
return;
}
alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance());
break;
case ReverbFilter:
if (!supportEfx || !src.isPositional() || !src.isReverbEnabled())
if (!supportEfx || !src.isPositional() || !src.isReverbEnabled()) {
return;
}
int filter = EFX10.AL_FILTER_NULL;
if (src.getReverbFilter() != null) {
@ -357,8 +358,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter);
break;
case ReverbEnabled:
if (!supportEfx || !src.isPositional())
if (!supportEfx || !src.isPositional()) {
return;
}
if (src.isReverbEnabled()) {
updateSourceParam(src, AudioParam.ReverbFilter);
@ -368,10 +370,13 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
break;
case IsPositional:
if (!src.isPositional()) {
// play in headspace
// Play in headspace
alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(id, AL_POSITION, 0, 0, 0);
alSource3f(id, AL_VELOCITY, 0, 0, 0);
// Disable reverb
AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL);
} else {
alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE);
updateSourceParam(src, AudioParam.Position);
@ -382,21 +387,24 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
break;
case Direction:
if (!src.isDirectional())
if (!src.isDirectional()) {
return;
}
Vector3f dir = src.getDirection();
alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z);
break;
case InnerAngle:
if (!src.isDirectional())
if (!src.isDirectional()) {
return;
}
alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle());
break;
case OuterAngle:
if (!src.isDirectional())
if (!src.isDirectional()) {
return;
}
alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle());
break;
@ -413,8 +421,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
break;
case DryFilter:
if (!supportEfx)
if (!supportEfx) {
return;
}
if (src.getDryFilter() != null) {
Filter f = src.getDryFilter();
@ -516,8 +525,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled)
if (audioDisabled) {
return;
}
switch (param) {
case Position:
@ -561,9 +571,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
private int newChannel() {
if (freeChans.size() > 0)
if (freeChans.size() > 0) {
return freeChans.remove(0);
else if (nextChan < channels.length){
} else if (nextChan < channels.length) {
return nextChan++;
} else {
return -1;
@ -587,8 +597,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled || !supportEfx)
if (audioDisabled || !supportEfx) {
return;
}
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DENSITY, env.getDensity());
EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DIFFUSION, env.getDiffusion());
@ -622,8 +633,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
}
if(size == 0)
if (size == 0) {
return false;
}
nativeBuf.clear();
nativeBuf.put(arrayBuf, 0, size);
@ -635,8 +647,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
private boolean fillStreamingSource(int sourceId, AudioStream stream) {
if (!stream.isOpen())
if (!stream.isOpen()) {
return false;
}
boolean active = true;
int processed = alGetSourcei(sourceId, AL_BUFFERS_PROCESSED);
@ -656,8 +669,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
alSourceQueueBuffers(sourceId, ib);
}
if (!active && stream.isOpen())
if (!active && stream.isOpen()) {
stream.close();
}
return active;
}
@ -724,13 +738,15 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
public void updateInThread(float tpf) {
if (audioDisabled)
if (audioDisabled) {
return;
}
for (int i = 0; i < channels.length; i++) {
AudioNode src = chanSrcs[i];
if (src == null)
if (src == null) {
continue;
}
int sourceId = channels[i];
@ -752,8 +768,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
AudioStream stream = (AudioStream) src.getAudioData();
if (stream.isOpen()) {
fillStreamingSource(sourceId, stream);
if (stopped)
if (stopped) {
alSourcePlay(sourceId);
}
} else {
if (stopped) {
// became inactive
@ -797,8 +814,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled)
if (audioDisabled) {
return;
}
if (this.listener != null) {
// previous listener no longer associated with current
@ -821,13 +839,15 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled)
if (audioDisabled) {
return;
}
if (src.getAudioData() instanceof AudioStream)
if (src.getAudioData() instanceof AudioStream) {
throw new UnsupportedOperationException(
"Cannot play instances " +
"of audio streams. Use playSource() instead.");
"Cannot play instances "
+ "of audio streams. Use playSource() instead.");
}
if (src.getAudioData().isUpdateNeeded()) {
updateAudioData(src.getAudioData());
@ -835,8 +855,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
// create a new index for an audio-channel
int index = newChannel();
if (index == -1)
if (index == -1) {
return;
}
int sourceId = channels[index];
@ -852,7 +873,6 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
}
public void playSource(AudioNode src) {
checkDead();
synchronized (threadLock) {
@ -862,8 +882,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled)
if (audioDisabled) {
return;
}
//assert src.getStatus() == Status.Stopped || src.getChannel() == -1;
@ -881,8 +902,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
src.setChannel(index);
AudioData data = src.getAudioData();
if (data.isUpdateNeeded())
if (data.isUpdateNeeded()) {
updateAudioData(data);
}
chanSrcs[index] = src;
setSourceParams(channels[index], src, false);
@ -894,7 +916,6 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
}
public void pauseSource(AudioNode src) {
checkDead();
synchronized (threadLock) {
@ -904,8 +925,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled)
if (audioDisabled) {
return;
}
if (src.getStatus() == Status.Playing) {
assert src.getChannel() != -1;
@ -916,7 +938,6 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
}
public void stopSource(AudioNode src) {
synchronized (threadLock) {
while (!threadLock.get()) {
@ -925,8 +946,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled)
if (audioDisabled) {
return;
}
if (src.getStatus() != Status.Stopped) {
int chan = src.getChannel();
@ -954,20 +976,22 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
private int convertFormat(AudioData ad) {
switch (ad.getBitsPerSample()) {
case 8:
if (ad.getChannels() == 1)
if (ad.getChannels() == 1) {
return AL_FORMAT_MONO8;
else if (ad.getChannels() == 2)
} else if (ad.getChannels() == 2) {
return AL_FORMAT_STEREO8;
}
break;
case 16:
if (ad.getChannels() == 1)
if (ad.getChannels() == 1) {
return AL_FORMAT_MONO16;
else
} else {
return AL_FORMAT_STEREO16;
}
throw new UnsupportedOperationException("Unsupported channels/bits combination: "+
"bits="+ad.getBitsPerSample()+", channels="+ad.getChannels());
}
throw new UnsupportedOperationException("Unsupported channels/bits combination: "
+ "bits=" + ad.getBitsPerSample() + ", channels=" + ad.getChannels());
}
private void updateAudioBuffer(AudioBuffer ab) {
@ -1028,8 +1052,9 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
} catch (InterruptedException ex) {
}
}
if (audioDisabled)
if (audioDisabled) {
return;
}
if (ad instanceof AudioBuffer) {
AudioBuffer ab = (AudioBuffer) ad;
@ -1052,5 +1077,4 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable {
}
}
}
}

Loading…
Cancel
Save