159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/* 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Copyright (c) 2009-2010 jMonkeyEngine 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * All rights reserved. 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Redistribution and use in source and binary forms, with or without 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * modification, are permitted provided that the following conditions are 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * met: 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions of source code must retain the above copyright 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer. 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Redistributions in binary form must reproduce the above copyright 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * notice, this list of conditions and the following disclaimer in the 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * documentation and/or other materials provided with the distribution. 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * may be used to endorse or promote products derived from this software 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * without specific prior written permission. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.audio.lwjgl; 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.audio.AudioNode.Status; 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.audio.*; 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.math.Vector3f; 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.BufferUtils; 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.util.NativeObjectManager; 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.ByteBuffer; 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.FloatBuffer; 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.nio.IntBuffer; 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.ArrayList; 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.concurrent.atomic.AtomicBoolean; 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Level; 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.logging.Logger; 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport org.lwjgl.LWJGLException; 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport static org.lwjgl.openal.AL10.*; 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport org.lwjgl.openal.*; 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class LwjglAudioRenderer implements AudioRenderer, Runnable { 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final Logger logger = Logger.getLogger(LwjglAudioRenderer.class.getName()); 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final NativeObjectManager objManager = new NativeObjectManager(); 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // When multiplied by STREAMING_BUFFER_COUNT, will equal 44100 * 2 * 2 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // which is exactly 1 second of audio. 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final int BUFFER_SIZE = 35280; 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final int STREAMING_BUFFER_COUNT = 5; 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final static int MAX_NUM_CHANNELS = 64; 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private IntBuffer ib = BufferUtils.createIntBuffer(1); 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final FloatBuffer fb = BufferUtils.createVector3Buffer(2); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE); 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final byte[] arrayBuf = new byte[BUFFER_SIZE]; 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int[] channels; 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private AudioNode[] chanSrcs; 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int nextChan = 0; 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private ArrayList<Integer> freeChans = new ArrayList<Integer>(); 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private Listener listener; 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean audioDisabled = false; 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean supportEfx = false; 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int auxSends = 0; 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int reverbFx = -1; 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int reverbFxSlot = -1; 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Update audio 20 times per second 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private static final float UPDATE_RATE = 0.05f; 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final Thread audioThread = new Thread(this, "jME3 Audio Thread"); 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private final AtomicBoolean threadLock = new AtomicBoolean(false); 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public LwjglAudioRenderer(){ 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void initialize(){ 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!audioThread.isAlive()){ 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta audioThread.setDaemon(true); 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta audioThread.setPriority(Thread.NORM_PRIORITY+1); 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta audioThread.start(); 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Initialize already called"); 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void checkDead(){ 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioThread.getState() == Thread.State.TERMINATED) 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Audio thread is terminated"); 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void run(){ 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta initInThread(); 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.set(true); 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.notifyAll(); 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta long updateRateNanos = (long) (UPDATE_RATE * 1000000000); 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta mainloop: while (true){ 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta long startTime = System.nanoTime(); 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (Thread.interrupted()) 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateInThread(UPDATE_RATE); 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta long endTime = System.nanoTime(); 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta long diffTime = endTime - startTime; 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (diffTime < updateRateNanos){ 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta long desiredEndTime = startTime + updateRateNanos; 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (System.nanoTime() < desiredEndTime){ 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try{ 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Thread.sleep(1); 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }catch (InterruptedException ex){ 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break mainloop; 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta cleanupInThread(); 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void initInThread(){ 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try{ 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!AL.isCreated()){ 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AL.create(); 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }catch (OpenALException ex){ 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.SEVERE, "Failed to load audio library", ex); 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta audioDisabled = true; 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }catch (LWJGLException ex){ 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.SEVERE, "Failed to load audio library", ex); 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta audioDisabled = true; 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (UnsatisfiedLinkError ex){ 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.SEVERE, "Failed to load audio library", ex); 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta audioDisabled = true; 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ALCdevice device = AL.getDevice(); 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String deviceName = ALC10.alcGetString(device, ALC10.ALC_DEVICE_SPECIFIER); 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Audio Device: {0}", deviceName); 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Audio Vendor: {0}", alGetString(AL_VENDOR)); 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Audio Renderer: {0}", alGetString(AL_RENDERER)); 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.FINER, "Audio Version: {0}", alGetString(AL_VERSION)); 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Find maximum # of sources supported by this implementation 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ArrayList<Integer> channelList = new ArrayList<Integer>(); 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < MAX_NUM_CHANNELS; i++){ 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int chan = alGenSources(); 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (alGetError() != 0){ 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta channelList.add(chan); 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta channels = new int[channelList.size()]; 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < channels.length; i++){ 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta channels[i] = channelList.get(i); 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib = BufferUtils.createIntBuffer(channels.length); 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta chanSrcs = new AudioNode[channels.length]; 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length); 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta supportEfx = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX"); 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (supportEfx){ 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ALC10.alcGetInteger(device, EFX10.ALC_EFX_MAJOR_VERSION, ib); 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int major = ib.get(0); 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ALC10.alcGetInteger(device, EFX10.ALC_EFX_MINOR_VERSION, ib); 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int minor = ib.get(0); 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "Audio effect extension version: {0}.{1}", new Object[]{major, minor}); 20059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ALC10.alcGetInteger(device, EFX10.ALC_MAX_AUXILIARY_SENDS, ib); 20259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta auxSends = ib.get(0); 20359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends); 20459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 20559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create slot 20659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 20759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alGenAuxiliaryEffectSlots(ib); 20859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta reverbFxSlot = ib.get(0); 20959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create effect 21159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 21259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alGenEffects(ib); 21359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta reverbFx = ib.get(0); 21459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffecti(reverbFx, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_REVERB); 21559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 21659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // attach reverb effect to effect slot 21759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); 21859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 21959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "OpenAL EFX not available! Audio effects won't work."); 22059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void cleanupInThread(){ 22459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled){ 22559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AL.destroy(); 22659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 22759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 22859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 22959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // stop any playing channels 23059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < chanSrcs.length; i++){ 23159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (chanSrcs[i] != null){ 23259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearChannel(i); 23359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 23559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 23659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // delete channel-based sources 23759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.clear(); 23859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.put(channels); 23959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.flip(); 24059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alDeleteSources(ib); 24159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // delete audio buffers and filters 24359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.deleteAllObjects(this); 24459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 24559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (supportEfx){ 24659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 24759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.put(0, reverbFx); 24859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alDeleteEffects(ib); 24959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // If this is not allocated, why is it deleted? 25159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Commented out to fix native crash in OpenAL. 25259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 25359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.put(0, reverbFxSlot); 25459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alDeleteAuxiliaryEffectSlots(ib); 25559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 25759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AL.destroy(); 25859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 25959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void cleanup(){ 26159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // kill audio thread 26259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioThread.isAlive()){ 26359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta audioThread.interrupt(); 26459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 26659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 26759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void updateFilter(Filter f){ 26859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = f.getId(); 26959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id == -1){ 27059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 27159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alGenFilters(ib); 27259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta id = ib.get(0); 27359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta f.setId(id); 27459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.registerForCleanup(f); 27659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 27759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 27859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (f instanceof LowPassFilter){ 27959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta LowPassFilter lpf = (LowPassFilter) f; 28059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alFilteri(id, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); 28159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAIN, lpf.getVolume()); 28259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAINHF, lpf.getHighFreqVolume()); 28359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 28459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Filter type unsupported: "+ 28559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta f.getClass().getName()); 28659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 28759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 28859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta f.clearUpdateNeeded(); 28959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 29159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateSourceParam(AudioNode src, AudioParam param){ 29259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDead(); 29359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 29459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 29559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 29659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 29759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 29859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 29959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 30059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 30159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 30259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 30359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // There is a race condition in AudioNode that can 30459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // cause this to be called for a node that has been 30559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // detached from its channel. For example, setVolume() 30659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // called from the render thread may see that that AudioNode 30759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // still has a channel value but the audio thread may 30859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // clear that channel before setVolume() gets to call 30959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // updateSourceParam() (because the audio stopped playing 31059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // on its own right as the volume was set). In this case, 31159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // it should be safe to just ignore the update 31259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getChannel() < 0) 31359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 31459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert src.getChannel() >= 0; 31659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 31759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = channels[src.getChannel()]; 31859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (param){ 31959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Position: 32059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!src.isPositional()) 32159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 32259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 32359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f pos = src.getWorldTranslation(); 32459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); 32559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 32659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Velocity: 32759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!src.isPositional()) 32859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 32959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f vel = src.getVelocity(); 33159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z); 33259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 33359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case MaxDistance: 33459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!src.isPositional()) 33559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 33659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 33759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance()); 33859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 33959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case RefDistance: 34059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!src.isPositional()) 34159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 34259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); 34459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 34559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case ReverbFilter: 34659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!supportEfx || !src.isPositional() || !src.isReverbEnabled()) 34759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 34859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 34959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int filter = EFX10.AL_FILTER_NULL; 35059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getReverbFilter() != null){ 35159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Filter f = src.getReverbFilter(); 35259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (f.isUpdateNeeded()){ 35359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFilter(f); 35459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta filter = f.getId(); 35659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 35759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); 35859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 35959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case ReverbEnabled: 36059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!supportEfx || !src.isPositional()) 36159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 36259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 36359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.isReverbEnabled()){ 36459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.ReverbFilter); 36559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 36659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); 36759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 36859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 36959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case IsPositional: 37059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!src.isPositional()){ 37159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // play in headspace 37259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); 37359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_POSITION, 0,0,0); 37459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_VELOCITY, 0,0,0); 37559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 37659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); 37759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.Position); 37859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.Velocity); 37959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.MaxDistance); 38059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.RefDistance); 38159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.ReverbEnabled); 38259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 38359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 38459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Direction: 38559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!src.isDirectional()) 38659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 38759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 38859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f dir = src.getDirection(); 38959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); 39059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 39159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case InnerAngle: 39259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!src.isDirectional()) 39359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 39459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 39559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); 39659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 39759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case OuterAngle: 39859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!src.isDirectional()) 39959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 40059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 40159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); 40259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 40359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case IsDirectional: 40459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.isDirectional()){ 40559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.Direction); 40659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.InnerAngle); 40759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateSourceParam(src, AudioParam.OuterAngle); 40859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_OUTER_GAIN, 0); 40959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 41059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_INNER_ANGLE, 360); 41159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_OUTER_ANGLE, 360); 41259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_OUTER_GAIN, 1f); 41359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 41459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 41559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case DryFilter: 41659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!supportEfx) 41759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 41859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 41959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getDryFilter() != null){ 42059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Filter f = src.getDryFilter(); 42159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (f.isUpdateNeeded()){ 42259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFilter(f); 42359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 42459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: must re-attach filter for changes to apply. 42559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); 42659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 42759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 42859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); 42959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 43059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 43159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Looping: 43259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.isLooping()){ 43359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!(src.getAudioData() instanceof AudioStream)){ 43459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, AL_LOOPING, AL_TRUE); 43559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 43659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 43759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, AL_LOOPING, AL_FALSE); 43859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 43959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 44059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Volume: 44159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_GAIN, src.getVolume()); 44259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 44359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Pitch: 44459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_PITCH, src.getPitch()); 44559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 44659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 44959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 45059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void setSourceParams(int id, AudioNode src, boolean forceNonLoop){ 45159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.isPositional()){ 45259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f pos = src.getWorldTranslation(); 45359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f vel = src.getVelocity(); 45459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); 45559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z); 45659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance()); 45759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); 45859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); 45959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 46059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.isReverbEnabled() && supportEfx){ 46159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int filter = EFX10.AL_FILTER_NULL; 46259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getReverbFilter() != null){ 46359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Filter f = src.getReverbFilter(); 46459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (f.isUpdateNeeded()){ 46559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFilter(f); 46659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta filter = f.getId(); 46859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 46959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); 47059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 47259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // play in headspace 47359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); 47459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_POSITION, 0,0,0); 47559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_VELOCITY, 0,0,0); 47659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 47759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 47859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getDryFilter() != null && supportEfx){ 47959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Filter f = src.getDryFilter(); 48059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (f.isUpdateNeeded()){ 48159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateFilter(f); 48259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 48359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // NOTE: must re-attach filter for changes to apply. 48459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); 48559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 48659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 48759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 48859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (forceNonLoop){ 48959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, AL_LOOPING, AL_FALSE); 49059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 49159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(id, AL_LOOPING, src.isLooping() ? AL_TRUE : AL_FALSE); 49259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 49359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_GAIN, src.getVolume()); 49459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_PITCH, src.getPitch()); 49559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL11.AL_SEC_OFFSET, src.getTimeOffset()); 49659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 49759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.isDirectional()){ 49859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f dir = src.getDirection(); 49959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); 50059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); 50159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); 50259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_OUTER_GAIN, 0); 50359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 50459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_INNER_ANGLE, 360); 50559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_OUTER_ANGLE, 360); 50659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcef(id, AL_CONE_OUTER_GAIN, 1f); 50759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 50959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 51059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateListenerParam(Listener listener, ListenerParam param){ 51159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDead(); 51259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 51359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 51459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 51559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 51659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 51759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 51959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 52059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 52159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 52259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (param){ 52359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Position: 52459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f pos = listener.getLocation(); 52559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alListener3f(AL_POSITION, pos.x, pos.y, pos.z); 52659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 52759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Rotation: 52859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f dir = listener.getDirection(); 52959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f up = listener.getUp(); 53059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.rewind(); 53159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.put(dir.x).put(dir.y).put(dir.z); 53259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.put(up.x).put(up.y).put(up.z); 53359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.flip(); 53459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alListener(AL_ORIENTATION, fb); 53559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 53659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Velocity: 53759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f vel = listener.getVelocity(); 53859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); 53959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 54059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case Volume: 54159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alListenerf(AL_GAIN, listener.getVolume()); 54259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 54359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 54459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 54559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 54659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 54759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void setListenerParams(Listener listener){ 54859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f pos = listener.getLocation(); 54959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f vel = listener.getVelocity(); 55059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f dir = listener.getDirection(); 55159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Vector3f up = listener.getUp(); 55259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 55359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alListener3f(AL_POSITION, pos.x, pos.y, pos.z); 55459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); 55559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.rewind(); 55659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.put(dir.x).put(dir.y).put(dir.z); 55759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.put(up.x).put(up.y).put(up.z); 55859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fb.flip(); 55959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alListener(AL_ORIENTATION, fb); 56059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alListenerf(AL_GAIN, listener.getVolume()); 56159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 56259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 56359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int newChannel(){ 56459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (freeChans.size() > 0) 56559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return freeChans.remove(0); 56659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta else if (nextChan < channels.length){ 56759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return nextChan++; 56859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 56959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return -1; 57059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 57159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 57259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 57359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void freeChannel(int index){ 57459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (index == nextChan-1){ 57559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nextChan--; 57659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } else{ 57759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta freeChans.add(index); 57859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 57959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 58059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 58159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setEnvironment(Environment env){ 58259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDead(); 58359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 58459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 58559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 58659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 58759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 58859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 58959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 59059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled || !supportEfx) 59159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 59259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 59359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DENSITY, env.getDensity()); 59459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DIFFUSION, env.getDiffusion()); 59559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAIN, env.getGain()); 59659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAINHF, env.getGainHf()); 59759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_TIME, env.getDecayTime()); 59859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_HFRATIO, env.getDecayHFRatio()); 59959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_GAIN, env.getReflectGain()); 60059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_DELAY, env.getReflectDelay()); 60159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_GAIN, env.getLateReverbGain()); 60259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_DELAY, env.getLateReverbDelay()); 60359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_AIR_ABSORPTION_GAINHF, env.getAirAbsorbGainHf()); 60459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_ROOM_ROLLOFF_FACTOR, env.getRoomRolloffFactor()); 60559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 60659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // attach effect to slot 60759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); 60859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 60959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 61059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 61159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean fillBuffer(AudioStream stream, int id){ 61259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int size = 0; 61359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int result; 61459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 61559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (size < arrayBuf.length){ 61659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta result = stream.readSamples(arrayBuf, size, arrayBuf.length - size); 61759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 61859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(result > 0){ 61959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta size += result; 62059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 62159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 62259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 62359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 62459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 62559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if(size == 0) 62659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 62759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 62859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nativeBuf.clear(); 62959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nativeBuf.put(arrayBuf, 0, size); 63059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta nativeBuf.flip(); 63159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 63259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alBufferData(id, convertFormat(stream), nativeBuf, stream.getSampleRate()); 63359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 63459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 63559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 63659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 63759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean fillStreamingSource(int sourceId, AudioStream stream){ 63859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!stream.isOpen()) 63959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return false; 64059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 64159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean active = true; 64259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int processed = alGetSourcei(sourceId, AL_BUFFERS_PROCESSED); 64359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 64459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta// while((processed--) != 0){ 64559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (processed > 0){ 64659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int buffer; 64759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 64859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 64959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourceUnqueueBuffers(sourceId, ib); 65059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta buffer = ib.get(0); 65159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 65259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta active = fillBuffer(stream, buffer); 65359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 65459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 65559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.put(0, buffer); 65659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourceQueueBuffers(sourceId, ib); 65759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 65859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 65959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (!active && stream.isOpen()) 66059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stream.close(); 66159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 66259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return active; 66359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 66459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 66559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean attachStreamToSource(int sourceId, AudioStream stream){ 66659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean active = true; 66759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int id : stream.getIds()){ 66859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta active = fillBuffer(stream, id); 66959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 67059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.put(id).flip(); 67159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourceQueueBuffers(sourceId, ib); 67259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 67359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return active; 67459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 67559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 67659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean attachBufferToSource(int sourceId, AudioBuffer buffer){ 67759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(sourceId, AL_BUFFER, buffer.getId()); 67859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 67959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 68059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 68159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private boolean attachAudioToSource(int sourceId, AudioData data){ 68259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (data instanceof AudioBuffer){ 68359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return attachBufferToSource(sourceId, (AudioBuffer) data); 68459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (data instanceof AudioStream){ 68559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return attachStreamToSource(sourceId, (AudioStream) data); 68659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 68759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException(); 68859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 68959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 69059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void clearChannel(int index){ 69159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // make room at this channel 69259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (chanSrcs[index] != null){ 69359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioNode src = chanSrcs[index]; 69459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 69559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int sourceId = channels[index]; 69659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourceStop(sourceId); 69759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 69859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getAudioData() instanceof AudioStream){ 69959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioStream str = (AudioStream) src.getAudioData(); 70059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(STREAMING_BUFFER_COUNT); 70159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.put(str.getIds()).flip(); 70259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourceUnqueueBuffers(sourceId, ib); 70359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (src.getAudioData() instanceof AudioBuffer){ 70459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(sourceId, AL_BUFFER, 0); 70559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 70659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 70759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getDryFilter() != null && supportEfx){ 70859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // detach filter 70959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcei(sourceId, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); 71059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 71159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.isPositional()){ 71259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioNode pas = (AudioNode) src; 71359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (pas.isReverbEnabled() && supportEfx) { 71459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AL11.alSource3i(sourceId, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); 71559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 71659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 71759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 71859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta chanSrcs[index] = null; 71959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 72059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 72159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 72259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void update(float tpf){ 72359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // does nothing 72459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 72559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 72659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void updateInThread(float tpf){ 72759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 72859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 72959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 73059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (int i = 0; i < channels.length; i++){ 73159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioNode src = chanSrcs[i]; 73259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src == null) 73359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta continue; 73459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 73559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int sourceId = channels[i]; 73659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 73759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // is the source bound to this channel 73859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // if false, it's an instanced playback 73959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean boundSource = i == src.getChannel(); 74059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 74159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // source's data is streaming 74259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean streaming = src.getAudioData() instanceof AudioStream; 74359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 74459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // only buffered sources can be bound 74559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert (boundSource && streaming) || (!streaming); 74659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 74759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int state = alGetSourcei(sourceId, AL_SOURCE_STATE); 74859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean wantPlaying = src.getStatus() == Status.Playing; 74959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean stopped = state == AL_STOPPED; 75059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 75159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (streaming && wantPlaying){ 75259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioStream stream = (AudioStream) src.getAudioData(); 75359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (stream.isOpen()){ 75459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta fillStreamingSource(sourceId, stream); 75559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (stopped) 75659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcePlay(sourceId); 75759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else{ 75859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (stopped){ 75959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // became inactive 76059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setStatus(Status.Stopped); 76159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setChannel(-1); 76259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearChannel(i); 76359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta freeChannel(i); 76459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 76559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // And free the audio since it cannot be 76659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // played again anyway. 76759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta deleteAudioData(stream); 76859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 76959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 77059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (!streaming){ 77159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta boolean paused = state == AL_PAUSED; 77259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 77359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // make sure OAL pause state & source state coincide 77459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert (src.getStatus() == Status.Paused && paused) || (!paused); 77559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 77659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (stopped){ 77759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (boundSource){ 77859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setStatus(Status.Stopped); 77959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setChannel(-1); 78059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 78159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearChannel(i); 78259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta freeChannel(i); 78359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 78459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 78559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 78659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 78759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Delete any unused objects. 78859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.deleteUnused(this); 78959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 79059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 79159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void setListener(Listener listener) { 79259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDead(); 79359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 79459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 79559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 79659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 79759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 79859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 79959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 80059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 80159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 80259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 80359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (this.listener != null){ 80459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // previous listener no longer associated with current 80559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // renderer 80659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.listener.setRenderer(null); 80759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 80859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 80959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.listener = listener; 81059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.listener.setRenderer(this); 81159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setListenerParams(listener); 81259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 81359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 81459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 81559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void playSourceInstance(AudioNode src){ 81659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDead(); 81759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 81859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 81959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 82059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 82159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 82259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 82359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 82459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 82559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 82659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 82759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getAudioData() instanceof AudioStream) 82859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException( 82959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "Cannot play instances " + 83059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "of audio streams. Use playSource() instead."); 83159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 83259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getAudioData().isUpdateNeeded()){ 83359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateAudioData(src.getAudioData()); 83459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 83559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 83659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // create a new index for an audio-channel 83759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int index = newChannel(); 83859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (index == -1) 83959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 84059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 84159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int sourceId = channels[index]; 84259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 84359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearChannel(index); 84459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 84559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // set parameters, like position and max distance 84659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setSourceParams(sourceId, src, true); 84759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attachAudioToSource(sourceId, src.getAudioData()); 84859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta chanSrcs[index] = src; 84959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 85059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // play the channel 85159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcePlay(sourceId); 85259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 85359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 85459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 85559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 85659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void playSource(AudioNode src) { 85759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDead(); 85859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 85959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 86059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 86159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 86259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 86359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 86459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 86559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 86659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 86759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 86859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta //assert src.getStatus() == Status.Stopped || src.getChannel() == -1; 86959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 87059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getStatus() == Status.Playing){ 87159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 87259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (src.getStatus() == Status.Stopped){ 87359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 87459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // allocate channel to this source 87559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int index = newChannel(); 87659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (index == -1) { 87759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta logger.log(Level.WARNING, "No channel available to play {0}", src); 87859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 87959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 88059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearChannel(index); 88159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setChannel(index); 88259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 88359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioData data = src.getAudioData(); 88459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (data.isUpdateNeeded()) 88559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateAudioData(data); 88659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 88759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta chanSrcs[index] = src; 88859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta setSourceParams(channels[index], src, false); 88959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta attachAudioToSource(channels[index], data); 89059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 89159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 89259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcePlay(channels[src.getChannel()]); 89359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setStatus(Status.Playing); 89459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 89559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 89659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 89759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 89859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void pauseSource(AudioNode src) { 89959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta checkDead(); 90059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 90159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 90259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 90359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 90459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 90559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 90659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 90759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 90859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 90959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 91059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getStatus() == Status.Playing){ 91159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert src.getChannel() != -1; 91259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 91359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alSourcePause(channels[src.getChannel()]); 91459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setStatus(Status.Paused); 91559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 91659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 91759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 91859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 91959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 92059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void stopSource(AudioNode src) { 92159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 92259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 92359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 92459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 92559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 92659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 92759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 92859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 92959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 93059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 93159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getStatus() != Status.Stopped){ 93259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int chan = src.getChannel(); 93359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta assert chan != -1; // if it's not stopped, must have id 93459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 93559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setStatus(Status.Stopped); 93659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta src.setChannel(-1); 93759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta clearChannel(chan); 93859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta freeChannel(chan); 93959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 94059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (src.getAudioData() instanceof AudioStream) { 94159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioStream stream = (AudioStream)src.getAudioData(); 94259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (stream.isOpen()) { 94359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta stream.close(); 94459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 94559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 94659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // And free the audio since it cannot be 94759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // played again anyway. 94859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta deleteAudioData(src.getAudioData()); 94959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 95059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 95159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 95259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 95359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 95459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private int convertFormat(AudioData ad){ 95559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta switch (ad.getBitsPerSample()){ 95659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 8: 95759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ad.getChannels() == 1) 95859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return AL_FORMAT_MONO8; 95959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta else if (ad.getChannels() == 2) 96059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return AL_FORMAT_STEREO8; 96159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 96259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta break; 96359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta case 16: 96459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ad.getChannels() == 1) 96559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return AL_FORMAT_MONO16; 96659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta else 96759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return AL_FORMAT_STEREO16; 96859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 96959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new UnsupportedOperationException("Unsupported channels/bits combination: "+ 97059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta "bits="+ad.getBitsPerSample()+", channels="+ad.getChannels()); 97159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 97259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 97359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void updateAudioBuffer(AudioBuffer ab){ 97459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = ab.getId(); 97559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ab.getId() == -1){ 97659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 97759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alGenBuffers(ib); 97859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta id = ib.get(0); 97959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ab.setId(id); 98059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 98159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta objManager.registerForCleanup(ab); 98259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 98359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 98459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ab.getData().clear(); 98559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alBufferData(id, convertFormat(ab), ab.getData(), ab.getSampleRate()); 98659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ab.clearUpdateNeeded(); 98759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 98859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 98959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void updateAudioStream(AudioStream as){ 99059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (as.getIds() != null){ 99159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta deleteAudioData(as); 99259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 99359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 99459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int[] ids = new int[STREAMING_BUFFER_COUNT]; 99559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(STREAMING_BUFFER_COUNT); 99659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alGenBuffers(ib); 99759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(STREAMING_BUFFER_COUNT); 99859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.get(ids); 99959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 100059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // Not registered with object manager. 100159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // AudioStreams can be handled without object manager 100259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // since their lifecycle is known to the audio renderer. 100359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 100459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta as.setIds(ids); 100559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta as.clearUpdateNeeded(); 100659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 100759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 100859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private void updateAudioData(AudioData ad){ 100959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ad instanceof AudioBuffer){ 101059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateAudioBuffer((AudioBuffer) ad); 101159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (ad instanceof AudioStream){ 101259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta updateAudioStream((AudioStream) ad); 101359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 101459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 101559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 101659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void deleteFilter(Filter filter) { 101759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = filter.getId(); 101859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id != -1){ 101959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta EFX10.alDeleteFilters(id); 102059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 102159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 102259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 102359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public void deleteAudioData(AudioData ad){ 102459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta synchronized (threadLock){ 102559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta while (!threadLock.get()){ 102659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta try { 102759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta threadLock.wait(); 102859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } catch (InterruptedException ex) { 102959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 103059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 103159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (audioDisabled) 103259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return; 103359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 103459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ad instanceof AudioBuffer){ 103559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioBuffer ab = (AudioBuffer) ad; 103659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int id = ab.getId(); 103759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (id != -1){ 103859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.put(0,id); 103959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.position(0).limit(1); 104059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alDeleteBuffers(ib); 104159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ab.resetObject(); 104259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 104359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta }else if (ad instanceof AudioStream){ 104459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta AudioStream as = (AudioStream) ad; 104559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int[] ids = as.getIds(); 104659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (ids != null){ 104759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.clear(); 104859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta ib.put(ids).flip(); 104959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta alDeleteBuffers(ib); 105059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta as.resetObject(); 105159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 105259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 105359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 105459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 105559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 105659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 1057