From 9d95528e21871bee1614abd874971d669a5586bb Mon Sep 17 00:00:00 2001 From: "Sha..rd" Date: Thu, 19 Jul 2012 23:46:04 +0000 Subject: [PATCH] * 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 --- engine/src/core/com/jme3/audio/AudioNode.java | 6 +- .../jme3/audio/lwjgl/LwjglAudioRenderer.java | 538 +++++++++--------- 2 files changed, 285 insertions(+), 259 deletions(-) diff --git a/engine/src/core/com/jme3/audio/AudioNode.java b/engine/src/core/com/jme3/audio/AudioNode.java index fbc6c5d3f..24b2907c1 100644 --- a/engine/src/core/com/jme3/audio/AudioNode.java +++ b/engine/src/core/com/jme3/audio/AudioNode.java @@ -442,8 +442,9 @@ public class AudioNode extends Node { */ public void setReverbEnabled(boolean reverbEnabled) { this.reverbEnabled = reverbEnabled; - if (channel >= 0) + if (channel >= 0) { getRenderer().updateSourceParam(this, AudioParam.ReverbEnabled); + } } /** @@ -642,8 +643,9 @@ 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 diff --git a/engine/src/lwjgl/com/jme3/audio/lwjgl/LwjglAudioRenderer.java b/engine/src/lwjgl/com/jme3/audio/lwjgl/LwjglAudioRenderer.java index 41ee52f49..48e66909e 100644 --- a/engine/src/lwjgl/com/jme3/audio/lwjgl/LwjglAudioRenderer.java +++ b/engine/src/lwjgl/com/jme3/audio/lwjgl/LwjglAudioRenderer.java @@ -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,115 +44,110 @@ 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 freeChans = new ArrayList(); - 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); - public LwjglAudioRenderer(){ + public LwjglAudioRenderer() { } - public void initialize(){ - if (!audioThread.isAlive()){ + public void initialize() { + if (!audioThread.isAlive()) { audioThread.setDaemon(true); - audioThread.setPriority(Thread.NORM_PRIORITY+1); + audioThread.setPriority(Thread.NORM_PRIORITY + 1); audioThread.start(); - }else{ + } else { throw new IllegalStateException("Initialize already called"); } } - private void checkDead(){ - if (audioThread.getState() == Thread.State.TERMINATED) + private void checkDead() { + if (audioThread.getState() == Thread.State.TERMINATED) { throw new IllegalStateException("Audio thread is terminated"); + } } - public void run(){ + public void run() { initInThread(); - synchronized (threadLock){ + synchronized (threadLock) { threadLock.set(true); threadLock.notifyAll(); } - + 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){ + synchronized (threadLock) { updateInThread(UPDATE_RATE); } long endTime = System.nanoTime(); long diffTime = endTime - startTime; - if (diffTime < updateRateNanos){ + if (diffTime < updateRateNanos) { long desiredEndTime = startTime + updateRateNanos; - while (System.nanoTime() < desiredEndTime){ - try{ + while (System.nanoTime() < desiredEndTime) { + try { Thread.sleep(1); - }catch (InterruptedException ex){ + } catch (InterruptedException ex) { break mainloop; } } } } - synchronized (threadLock){ + synchronized (threadLock) { cleanupInThread(); } } - public void initInThread(){ - try{ - if (!AL.isCreated()){ + public void initInThread() { + try { + if (!AL.isCreated()) { AL.create(); } - }catch (OpenALException ex){ + } catch (OpenALException ex) { logger.log(Level.SEVERE, "Failed to load audio library", ex); audioDisabled = true; return; - }catch (LWJGLException ex){ + } catch (LWJGLException ex) { logger.log(Level.SEVERE, "Failed to load audio library", ex); audioDisabled = true; return; - } catch (UnsatisfiedLinkError ex){ + } catch (UnsatisfiedLinkError ex) { logger.log(Level.SEVERE, "Failed to load audio library", ex); audioDisabled = true; return; @@ -169,17 +163,17 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { // Find maximum # of sources supported by this implementation ArrayList channelList = new ArrayList(); - for (int i = 0; i < MAX_NUM_CHANNELS; i++){ + for (int i = 0; i < MAX_NUM_CHANNELS; i++) { int chan = alGenSources(); - if (alGetError() != 0){ + if (alGetError() != 0) { break; - }else{ + } else { channelList.add(chan); } } channels = new int[channelList.size()]; - for (int i = 0; i < channels.length; i++){ + for (int i = 0; i < channels.length; i++) { channels[i] = channelList.get(i); } @@ -189,7 +183,7 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length); supportEfx = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX"); - if (supportEfx){ + if (supportEfx) { ib.position(0).limit(1); ALC10.alcGetInteger(device, EFX10.ALC_EFX_MAJOR_VERSION, ib); int major = ib.get(0); @@ -215,34 +209,34 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { // attach reverb effect to effect slot EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); - }else{ + } else { logger.log(Level.WARNING, "OpenAL EFX not available! Audio effects won't work."); } } - public void cleanupInThread(){ - if (audioDisabled){ + public void cleanupInThread() { + if (audioDisabled) { AL.destroy(); return; } // stop any playing channels - for (int i = 0; i < chanSrcs.length; i++){ - if (chanSrcs[i] != null){ + for (int i = 0; i < chanSrcs.length; i++) { + if (chanSrcs[i] != null) { clearChannel(i); } } - + // delete channel-based sources ib.clear(); ib.put(channels); ib.flip(); alDeleteSources(ib); - + // delete audio buffers and filters objManager.deleteAllObjects(this); - if (supportEfx){ + if (supportEfx) { ib.position(0).limit(1); ib.put(0, reverbFx); EFX10.alDeleteEffects(ib); @@ -257,49 +251,50 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { AL.destroy(); } - public void cleanup(){ + public void cleanup() { // kill audio thread - if (audioThread.isAlive()){ + if (audioThread.isAlive()) { audioThread.interrupt(); } } - private void updateFilter(Filter f){ + private void updateFilter(Filter f) { int id = f.getId(); - if (id == -1){ + if (id == -1) { ib.position(0).limit(1); EFX10.alGenFilters(ib); id = ib.get(0); f.setId(id); - + objManager.registerForCleanup(f); } - if (f instanceof LowPassFilter){ + if (f instanceof LowPassFilter) { LowPassFilter lpf = (LowPassFilter) f; - EFX10.alFilteri(id, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); - EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAIN, lpf.getVolume()); + EFX10.alFilteri(id, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); + 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()); + } else { + throw new UnsupportedOperationException("Filter type unsupported: " + + f.getClass().getName()); } f.clearUpdateNeeded(); } - - public void updateSourceParam(AudioNode src, AudioParam param){ + + public void updateSourceParam(AudioNode src, AudioParam param) { checkDead(); - synchronized (threadLock){ - while (!threadLock.get()){ + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } 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 // detached from its channel. For example, setVolume() @@ -309,47 +304,53 @@ 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){ + 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){ + if (src.getReverbFilter() != null) { Filter f = src.getReverbFilter(); - if (f.isUpdateNeeded()){ + if (f.isUpdateNeeded()) { updateFilter(f); } filter = f.getId(); @@ -357,22 +358,26 @@ 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()){ + if (src.isReverbEnabled()) { updateSourceParam(src, AudioParam.ReverbFilter); - }else{ + } else { AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); } break; case IsPositional: - if (!src.isPositional()){ - // play in headspace + if (!src.isPositional()) { + // Play in headspace alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); - alSource3f(id, AL_POSITION, 0,0,0); - alSource3f(id, AL_VELOCITY, 0,0,0); - }else{ + 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); updateSourceParam(src, AudioParam.Velocity); @@ -382,58 +387,62 @@ 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; case IsDirectional: - if (src.isDirectional()){ + if (src.isDirectional()) { updateSourceParam(src, AudioParam.Direction); updateSourceParam(src, AudioParam.InnerAngle); updateSourceParam(src, AudioParam.OuterAngle); alSourcef(id, AL_CONE_OUTER_GAIN, 0); - }else{ + } else { alSourcef(id, AL_CONE_INNER_ANGLE, 360); alSourcef(id, AL_CONE_OUTER_ANGLE, 360); alSourcef(id, AL_CONE_OUTER_GAIN, 1f); } break; case DryFilter: - if (!supportEfx) + if (!supportEfx) { return; - - if (src.getDryFilter() != null){ + } + + if (src.getDryFilter() != null) { Filter f = src.getDryFilter(); - if (f.isUpdateNeeded()){ + if (f.isUpdateNeeded()) { updateFilter(f); // NOTE: must re-attach filter for changes to apply. alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); } - }else{ + } else { alSourcei(id, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); } break; case Looping: - if (src.isLooping()){ - if (!(src.getAudioData() instanceof AudioStream)){ + if (src.isLooping()) { + if (!(src.getAudioData() instanceof AudioStream)) { alSourcei(id, AL_LOOPING, AL_TRUE); } - }else{ + } else { alSourcei(id, AL_LOOPING, AL_FALSE); } break; @@ -447,8 +456,8 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { } } - private void setSourceParams(int id, AudioNode src, boolean forceNonLoop){ - if (src.isPositional()){ + private void setSourceParams(int id, AudioNode src, boolean forceNonLoop) { + if (src.isPositional()) { Vector3f pos = src.getWorldTranslation(); Vector3f vel = src.getVelocity(); alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); @@ -457,76 +466,77 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); - if (src.isReverbEnabled() && supportEfx){ + if (src.isReverbEnabled() && supportEfx) { int filter = EFX10.AL_FILTER_NULL; - if (src.getReverbFilter() != null){ + if (src.getReverbFilter() != null) { Filter f = src.getReverbFilter(); - if (f.isUpdateNeeded()){ + if (f.isUpdateNeeded()) { updateFilter(f); } filter = f.getId(); } AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); } - }else{ + } else { // play in headspace alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); - alSource3f(id, AL_POSITION, 0,0,0); - alSource3f(id, AL_VELOCITY, 0,0,0); + alSource3f(id, AL_POSITION, 0, 0, 0); + alSource3f(id, AL_VELOCITY, 0, 0, 0); } - if (src.getDryFilter() != null && supportEfx){ + if (src.getDryFilter() != null && supportEfx) { Filter f = src.getDryFilter(); - if (f.isUpdateNeeded()){ + if (f.isUpdateNeeded()) { updateFilter(f); - + // NOTE: must re-attach filter for changes to apply. alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); } } - if (forceNonLoop){ - alSourcei(id, AL_LOOPING, AL_FALSE); - }else{ - alSourcei(id, AL_LOOPING, src.isLooping() ? AL_TRUE : AL_FALSE); + if (forceNonLoop) { + alSourcei(id, AL_LOOPING, AL_FALSE); + } else { + alSourcei(id, AL_LOOPING, src.isLooping() ? AL_TRUE : AL_FALSE); } - alSourcef(id, AL_GAIN, src.getVolume()); - alSourcef(id, AL_PITCH, src.getPitch()); - alSourcef(id, AL11.AL_SEC_OFFSET, src.getTimeOffset()); + alSourcef(id, AL_GAIN, src.getVolume()); + alSourcef(id, AL_PITCH, src.getPitch()); + alSourcef(id, AL11.AL_SEC_OFFSET, src.getTimeOffset()); - if (src.isDirectional()){ + if (src.isDirectional()) { Vector3f dir = src.getDirection(); alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); - alSourcef(id, AL_CONE_OUTER_GAIN, 0); - }else{ + alSourcef(id, AL_CONE_OUTER_GAIN, 0); + } else { alSourcef(id, AL_CONE_INNER_ANGLE, 360); alSourcef(id, AL_CONE_OUTER_ANGLE, 360); alSourcef(id, AL_CONE_OUTER_GAIN, 1f); } } - public void updateListenerParam(Listener listener, ListenerParam param){ + public void updateListenerParam(Listener listener, ListenerParam param) { checkDead(); - synchronized (threadLock){ - while (!threadLock.get()){ + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } catch (InterruptedException ex) { } } - if (audioDisabled) + if (audioDisabled) { return; - - switch (param){ + } + + switch (param) { case Position: Vector3f pos = listener.getLocation(); alListener3f(AL_POSITION, pos.x, pos.y, pos.z); break; case Rotation: Vector3f dir = listener.getDirection(); - Vector3f up = listener.getUp(); + Vector3f up = listener.getUp(); fb.rewind(); fb.put(dir.x).put(dir.y).put(dir.z); fb.put(up.x).put(up.y).put(up.z); @@ -544,11 +554,11 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { } } - private void setListenerParams(Listener listener){ + private void setListenerParams(Listener listener) { Vector3f pos = listener.getLocation(); Vector3f vel = listener.getVelocity(); Vector3f dir = listener.getDirection(); - Vector3f up = listener.getUp(); + Vector3f up = listener.getUp(); alListener3f(AL_POSITION, pos.x, pos.y, pos.z); alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); @@ -560,46 +570,47 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { alListenerf(AL_GAIN, listener.getVolume()); } - private int newChannel(){ - if (freeChans.size() > 0) + private int newChannel() { + if (freeChans.size() > 0) { return freeChans.remove(0); - else if (nextChan < channels.length){ + } else if (nextChan < channels.length) { return nextChan++; - }else{ + } else { return -1; } } - private void freeChannel(int index){ - if (index == nextChan-1){ + private void freeChannel(int index) { + if (index == nextChan - 1) { nextChan--; - } else{ + } else { freeChans.add(index); } } - public void setEnvironment(Environment env){ + public void setEnvironment(Environment env) { checkDead(); - synchronized (threadLock){ - while (!threadLock.get()){ + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } 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()); - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAIN, env.getGain()); - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAINHF, env.getGainHf()); - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_TIME, env.getDecayTime()); - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_HFRATIO, env.getDecayHFRatio()); - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_GAIN, env.getReflectGain()); - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_DELAY, env.getReflectDelay()); - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_GAIN, env.getLateReverbGain()); - EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_DELAY, env.getLateReverbDelay()); + } + + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DENSITY, env.getDensity()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DIFFUSION, env.getDiffusion()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAIN, env.getGain()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAINHF, env.getGainHf()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_TIME, env.getDecayTime()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_HFRATIO, env.getDecayHFRatio()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_GAIN, env.getReflectGain()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_DELAY, env.getReflectDelay()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_GAIN, env.getLateReverbGain()); + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_DELAY, env.getLateReverbDelay()); EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_AIR_ABSORPTION_GAINHF, env.getAirAbsorbGainHf()); EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_ROOM_ROLLOFF_FACTOR, env.getRoomRolloffFactor()); @@ -608,22 +619,23 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { } } - private boolean fillBuffer(AudioStream stream, int id){ + private boolean fillBuffer(AudioStream stream, int id) { int size = 0; int result; - while (size < arrayBuf.length){ + while (size < arrayBuf.length) { result = stream.readSamples(arrayBuf, size, arrayBuf.length - size); - if(result > 0){ + if (result > 0) { size += result; - }else{ + } else { break; } } - if(size == 0) + if (size == 0) { return false; + } nativeBuf.clear(); nativeBuf.put(arrayBuf, 0, size); @@ -634,15 +646,16 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { return true; } - private boolean fillStreamingSource(int sourceId, AudioStream stream){ - if (!stream.isOpen()) + private boolean fillStreamingSource(int sourceId, AudioStream stream) { + if (!stream.isOpen()) { return false; + } boolean active = true; int processed = alGetSourcei(sourceId, AL_BUFFERS_PROCESSED); // while((processed--) != 0){ - if (processed > 0){ + if (processed > 0) { int buffer; ib.position(0).limit(1); @@ -656,15 +669,16 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { alSourceQueueBuffers(sourceId, ib); } - if (!active && stream.isOpen()) + if (!active && stream.isOpen()) { stream.close(); - + } + return active; } - private boolean attachStreamToSource(int sourceId, AudioStream stream){ + private boolean attachStreamToSource(int sourceId, AudioStream stream) { boolean active = true; - for (int id : stream.getIds()){ + for (int id : stream.getIds()) { active = fillBuffer(stream, id); ib.position(0).limit(1); ib.put(id).flip(); @@ -673,42 +687,42 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { return active; } - private boolean attachBufferToSource(int sourceId, AudioBuffer buffer){ + private boolean attachBufferToSource(int sourceId, AudioBuffer buffer) { alSourcei(sourceId, AL_BUFFER, buffer.getId()); return true; } - private boolean attachAudioToSource(int sourceId, AudioData data){ - if (data instanceof AudioBuffer){ + private boolean attachAudioToSource(int sourceId, AudioData data) { + if (data instanceof AudioBuffer) { return attachBufferToSource(sourceId, (AudioBuffer) data); - }else if (data instanceof AudioStream){ + } else if (data instanceof AudioStream) { return attachStreamToSource(sourceId, (AudioStream) data); } throw new UnsupportedOperationException(); } - private void clearChannel(int index){ + private void clearChannel(int index) { // make room at this channel - if (chanSrcs[index] != null){ + if (chanSrcs[index] != null) { AudioNode src = chanSrcs[index]; int sourceId = channels[index]; alSourceStop(sourceId); - if (src.getAudioData() instanceof AudioStream){ + if (src.getAudioData() instanceof AudioStream) { AudioStream str = (AudioStream) src.getAudioData(); ib.position(0).limit(STREAMING_BUFFER_COUNT); ib.put(str.getIds()).flip(); alSourceUnqueueBuffers(sourceId, ib); - }else if (src.getAudioData() instanceof AudioBuffer){ + } else if (src.getAudioData() instanceof AudioBuffer) { alSourcei(sourceId, AL_BUFFER, 0); } - if (src.getDryFilter() != null && supportEfx){ + if (src.getDryFilter() != null && supportEfx) { // detach filter alSourcei(sourceId, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); } - if (src.isPositional()){ + if (src.isPositional()) { AudioNode pas = (AudioNode) src; if (pas.isReverbEnabled() && supportEfx) { AL11.alSource3i(sourceId, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); @@ -719,18 +733,20 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { } } - public void update(float tpf){ + public void update(float tpf) { // does nothing } - public void updateInThread(float tpf){ - if (audioDisabled) + public void updateInThread(float tpf) { + if (audioDisabled) { return; + } - for (int i = 0; i < channels.length; i++){ + for (int i = 0; i < channels.length; i++) { AudioNode src = chanSrcs[i]; - if (src == null) + if (src == null) { continue; + } int sourceId = channels[i]; @@ -748,95 +764,100 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { boolean wantPlaying = src.getStatus() == Status.Playing; boolean stopped = state == AL_STOPPED; - if (streaming && wantPlaying){ + if (streaming && wantPlaying) { AudioStream stream = (AudioStream) src.getAudioData(); - if (stream.isOpen()){ + if (stream.isOpen()) { fillStreamingSource(sourceId, stream); - if (stopped) + if (stopped) { alSourcePlay(sourceId); - }else{ - if (stopped){ + } + } else { + if (stopped) { // became inactive src.setStatus(Status.Stopped); src.setChannel(-1); clearChannel(i); freeChannel(i); - + // And free the audio since it cannot be // played again anyway. deleteAudioData(stream); } } - }else if (!streaming){ + } else if (!streaming) { boolean paused = state == AL_PAUSED; // make sure OAL pause state & source state coincide assert (src.getStatus() == Status.Paused && paused) || (!paused); - if (stopped){ - if (boundSource){ + if (stopped) { + if (boundSource) { src.setStatus(Status.Stopped); src.setChannel(-1); } clearChannel(i); - freeChannel(i); + freeChannel(i); } } } - + // Delete any unused objects. objManager.deleteUnused(this); } public void setListener(Listener listener) { checkDead(); - synchronized (threadLock){ - while (!threadLock.get()){ + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } catch (InterruptedException ex) { } } - if (audioDisabled) + if (audioDisabled) { return; + } - if (this.listener != null){ + if (this.listener != null) { // previous listener no longer associated with current // renderer this.listener.setRenderer(null); } - + this.listener = listener; this.listener.setRenderer(this); setListenerParams(listener); } } - public void playSourceInstance(AudioNode src){ + public void playSourceInstance(AudioNode src) { checkDead(); - synchronized (threadLock){ - while (!threadLock.get()){ + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } 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()){ + if (src.getAudioData().isUpdateNeeded()) { updateAudioData(src.getAudioData()); } // create a new index for an audio-channel int index = newChannel(); - if (index == -1) + if (index == -1) { return; + } int sourceId = channels[index]; @@ -852,24 +873,24 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { } } - public void playSource(AudioNode src) { checkDead(); - synchronized (threadLock){ - while (!threadLock.get()){ + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } catch (InterruptedException ex) { } } - if (audioDisabled) + if (audioDisabled) { return; + } //assert src.getStatus() == Status.Stopped || src.getChannel() == -1; - if (src.getStatus() == Status.Playing){ + if (src.getStatus() == Status.Playing) { return; - }else if (src.getStatus() == Status.Stopped){ + } else if (src.getStatus() == Status.Stopped) { // allocate channel to this source int index = newChannel(); @@ -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,20 +916,20 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { } } - public void pauseSource(AudioNode src) { checkDead(); - synchronized (threadLock){ - while (!threadLock.get()){ + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } catch (InterruptedException ex) { } } - if (audioDisabled) + if (audioDisabled) { return; - - if (src.getStatus() == Status.Playing){ + } + + if (src.getStatus() == Status.Playing) { assert src.getChannel() != -1; alSourcePause(channels[src.getChannel()]); @@ -916,19 +938,19 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { } } - public void stopSource(AudioNode src) { - synchronized (threadLock){ - while (!threadLock.get()){ + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } catch (InterruptedException ex) { } } - if (audioDisabled) + if (audioDisabled) { return; - - if (src.getStatus() != Status.Stopped){ + } + + if (src.getStatus() != Status.Stopped) { int chan = src.getChannel(); assert chan != -1; // if it's not stopped, must have id @@ -936,48 +958,50 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { src.setChannel(-1); clearChannel(chan); freeChannel(chan); - + if (src.getAudioData() instanceof AudioStream) { - AudioStream stream = (AudioStream)src.getAudioData(); + AudioStream stream = (AudioStream) src.getAudioData(); if (stream.isOpen()) { stream.close(); } - + // And free the audio since it cannot be // played again anyway. deleteAudioData(src.getAudioData()); - } + } } } } - private int convertFormat(AudioData ad){ - switch (ad.getBitsPerSample()){ + 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){ + private void updateAudioBuffer(AudioBuffer ab) { int id = ab.getId(); - if (ab.getId() == -1){ + if (ab.getId() == -1) { ib.position(0).limit(1); alGenBuffers(ib); id = ib.get(0); ab.setId(id); - + objManager.registerForCleanup(ab); } @@ -986,71 +1010,71 @@ public class LwjglAudioRenderer implements AudioRenderer, Runnable { ab.clearUpdateNeeded(); } - private void updateAudioStream(AudioStream as){ - if (as.getIds() != null){ + private void updateAudioStream(AudioStream as) { + if (as.getIds() != null) { deleteAudioData(as); } int[] ids = new int[STREAMING_BUFFER_COUNT]; ib.position(0).limit(STREAMING_BUFFER_COUNT); alGenBuffers(ib); - ib.position(0).limit(STREAMING_BUFFER_COUNT); + ib.position(0).limit(STREAMING_BUFFER_COUNT); ib.get(ids); - + // Not registered with object manager. // AudioStreams can be handled without object manager // since their lifecycle is known to the audio renderer. - + as.setIds(ids); as.clearUpdateNeeded(); } - private void updateAudioData(AudioData ad){ - if (ad instanceof AudioBuffer){ + private void updateAudioData(AudioData ad) { + if (ad instanceof AudioBuffer) { updateAudioBuffer((AudioBuffer) ad); - }else if (ad instanceof AudioStream){ + } else if (ad instanceof AudioStream) { updateAudioStream((AudioStream) ad); } } - + public void deleteFilter(Filter filter) { int id = filter.getId(); - if (id != -1){ + if (id != -1) { EFX10.alDeleteFilters(id); } } - public void deleteAudioData(AudioData ad){ - synchronized (threadLock){ - while (!threadLock.get()){ + public void deleteAudioData(AudioData ad) { + synchronized (threadLock) { + while (!threadLock.get()) { try { threadLock.wait(); } catch (InterruptedException ex) { } } - if (audioDisabled) + if (audioDisabled) { return; - - if (ad instanceof AudioBuffer){ + } + + if (ad instanceof AudioBuffer) { AudioBuffer ab = (AudioBuffer) ad; int id = ab.getId(); - if (id != -1){ - ib.put(0,id); + if (id != -1) { + ib.put(0, id); ib.position(0).limit(1); alDeleteBuffers(ib); ab.resetObject(); } - }else if (ad instanceof AudioStream){ + } else if (ad instanceof AudioStream) { AudioStream as = (AudioStream) ad; int[] ids = as.getIds(); - if (ids != null){ + if (ids != null) { ib.clear(); ib.put(ids).flip(); alDeleteBuffers(ib); as.resetObject(); } } - } + } } - }