OSDN Git Service

Android: First commit of a new Audio system for Android that uses OpenAL Soft with...
authoriwgeric@gmail.com <iwgeric@gmail.com@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Sat, 11 May 2013 01:48:08 +0000 (01:48 +0000)
committeriwgeric@gmail.com <iwgeric@gmail.com@75d07b2b-3a1a-0410-a2c5-0572b91ccdca>
Sat, 11 May 2013 01:48:08 +0000 (01:48 +0000)
git-svn-id: http://jmonkeyengine.googlecode.com/svn/trunk@10606 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

engine/src/android/com/jme3/audio/android/AL.java [new file with mode: 0644]
engine/src/android/com/jme3/audio/android/AndroidOpenALSoftAudioRenderer.java [new file with mode: 0644]
engine/src/openal-soft-native/android/Android.mk [new file with mode: 0644]
engine/src/openal-soft-native/android/Application.mk [new file with mode: 0644]
engine/src/openal-soft-native/android/com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.cpp [new file with mode: 0644]
engine/src/openal-soft-native/android/com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.h [new file with mode: 0644]
engine/src/openal-soft-native/android/config.h [new file with mode: 0644]

diff --git a/engine/src/android/com/jme3/audio/android/AL.java b/engine/src/android/com/jme3/audio/android/AL.java
new file mode 100644 (file)
index 0000000..ccbc6f9
--- /dev/null
@@ -0,0 +1,384 @@
+package com.jme3.audio.android;\r
+\r
+/**\r
+ *\r
+ * @author iwgeric\r
+ */\r
+public class AL {\r
+\r
+\r
+\r
+    /* ********** */\r
+    /* FROM ALC.h */\r
+    /* ********** */\r
+\r
+//    typedef struct ALCdevice_struct ALCdevice;\r
+//    typedef struct ALCcontext_struct ALCcontext;\r
+\r
+\r
+    /**\r
+     * No error\r
+     */\r
+    static final int ALC_NO_ERROR = 0;\r
+\r
+    /**\r
+     * No device\r
+     */\r
+    static final int ALC_INVALID_DEVICE = 0xA001;\r
+\r
+    /**\r
+     * invalid context ID\r
+     */\r
+    static final int ALC_INVALID_CONTEXT = 0xA002;\r
+\r
+    /**\r
+     * bad enum\r
+     */\r
+    static final int ALC_INVALID_ENUM = 0xA003;\r
+\r
+    /**\r
+     * bad value\r
+     */\r
+    static final int ALC_INVALID_VALUE = 0xA004;\r
+\r
+    /**\r
+     * Out of memory.\r
+     */\r
+    static final int ALC_OUT_OF_MEMORY = 0xA005;\r
+\r
+\r
+    /**\r
+     * The Specifier string for default device\r
+     */\r
+    static final int ALC_DEFAULT_DEVICE_SPECIFIER = 0x1004;\r
+    static final int ALC_DEVICE_SPECIFIER = 0x1005;\r
+    static final int ALC_EXTENSIONS = 0x1006;\r
+\r
+    static final int ALC_MAJOR_VERSION = 0x1000;\r
+    static final int ALC_MINOR_VERSION = 0x1001;\r
+\r
+    static final int ALC_ATTRIBUTES_SIZE = 0x1002;\r
+    static final int ALC_ALL_ATTRIBUTES = 0x1003;\r
+\r
+\r
+    /**\r
+     * Capture extension\r
+     */\r
+    static final int ALC_EXT_CAPTURE = 1;\r
+    static final int ALC_CAPTURE_DEVICE_SPECIFIER = 0x310;\r
+    static final int ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER = 0x311;\r
+    static final int ALC_CAPTURE_SAMPLES = 0x312;\r
+\r
+\r
+    /**\r
+     * ALC_ENUMERATE_ALL_EXT enums\r
+     */\r
+    static final int ALC_ENUMERATE_ALL_EXT = 1;\r
+    static final int ALC_DEFAULT_ALL_DEVICES_SPECIFIER = 0x1012;\r
+    static final int ALC_ALL_DEVICES_SPECIFIER = 0x1013;\r
+\r
+\r
+    /* ********** */\r
+    /* FROM AL.h */\r
+    /* ********** */\r
+\r
+/** Boolean False. */\r
+    static final int AL_FALSE = 0;\r
+\r
+/** Boolean True. */\r
+    static final int AL_TRUE = 1;\r
+\r
+/* "no distance model" or "no buffer" */\r
+    static final int AL_NONE = 0;\r
+\r
+/** Indicate Source has relative coordinates. */\r
+    static final int AL_SOURCE_RELATIVE = 0x202;\r
+\r
+\r
+\r
+/**\r
+ * Directional source, inner cone angle, in degrees.\r
+ * Range:    [0-360]\r
+ * Default:  360\r
+ */\r
+    static final int AL_CONE_INNER_ANGLE = 0x1001;\r
+\r
+/**\r
+ * Directional source, outer cone angle, in degrees.\r
+ * Range:    [0-360]\r
+ * Default:  360\r
+ */\r
+    static final int AL_CONE_OUTER_ANGLE = 0x1002;\r
+\r
+/**\r
+ * Specify the pitch to be applied at source.\r
+ * Range:   [0.5-2.0]\r
+ * Default: 1.0\r
+ */\r
+    static final int AL_PITCH = 0x1003;\r
+\r
+/**\r
+ * Specify the current location in three dimensional space.\r
+ * OpenAL, like OpenGL, uses a right handed coordinate system,\r
+ *  where in a frontal default view X (thumb) points right,\r
+ *  Y points up (index finger), and Z points towards the\r
+ *  viewer/camera (middle finger).\r
+ * To switch from a left handed coordinate system, flip the\r
+ *  sign on the Z coordinate.\r
+ * Listener position is always in the world coordinate system.\r
+ */\r
+    static final int AL_POSITION = 0x1004;\r
+\r
+/** Specify the current direction. */\r
+    static final int AL_DIRECTION = 0x1005;\r
+\r
+/** Specify the current velocity in three dimensional space. */\r
+    static final int AL_VELOCITY = 0x1006;\r
+\r
+/**\r
+ * Indicate whether source is looping.\r
+ * Type: ALboolean?\r
+ * Range:   [AL_TRUE, AL_FALSE]\r
+ * Default: FALSE.\r
+ */\r
+    static final int AL_LOOPING = 0x1007;\r
+\r
+/**\r
+ * Indicate the buffer to provide sound samples.\r
+ * Type: ALuint.\r
+ * Range: any valid Buffer id.\r
+ */\r
+    static final int AL_BUFFER = 0x1009;\r
+\r
+/**\r
+ * Indicate the gain (volume amplification) applied.\r
+ * Type:   ALfloat.\r
+ * Range:  ]0.0-  ]\r
+ * A value of 1.0 means un-attenuated/unchanged.\r
+ * Each division by 2 equals an attenuation of -6dB.\r
+ * Each multiplicaton with 2 equals an amplification of +6dB.\r
+ * A value of 0.0 is meaningless with respect to a logarithmic\r
+ *  scale; it is interpreted as zero volume - the channel\r
+ *  is effectively disabled.\r
+ */\r
+    static final int AL_GAIN = 0x100A;\r
+\r
+/*\r
+ * Indicate minimum source attenuation\r
+ * Type: ALfloat\r
+ * Range:  [0.0 - 1.0]\r
+ *\r
+ * Logarthmic\r
+ */\r
+    static final int AL_MIN_GAIN = 0x100D;\r
+\r
+/**\r
+ * Indicate maximum source attenuation\r
+ * Type: ALfloat\r
+ * Range:  [0.0 - 1.0]\r
+ *\r
+ * Logarthmic\r
+ */\r
+    static final int AL_MAX_GAIN = 0x100E;\r
+\r
+/**\r
+ * Indicate listener orientation.\r
+ *\r
+ * at/up\r
+ */\r
+    static final int AL_ORIENTATION = 0x100F;\r
+\r
+/**\r
+ * Source state information.\r
+ */\r
+    static final int AL_SOURCE_STATE = 0x1010;\r
+    static final int AL_INITIAL = 0x1011;\r
+    static final int AL_PLAYING = 0x1012;\r
+    static final int AL_PAUSED = 0x1013;\r
+    static final int AL_STOPPED = 0x1014;\r
+\r
+/**\r
+ * Buffer Queue params\r
+ */\r
+    static final int AL_BUFFERS_QUEUED = 0x1015;\r
+    static final int AL_BUFFERS_PROCESSED = 0x1016;\r
+\r
+/**\r
+ * Source buffer position information\r
+ */\r
+    static final int AL_SEC_OFFSET = 0x1024;\r
+    static final int AL_SAMPLE_OFFSET = 0x1025;\r
+    static final int AL_BYTE_OFFSET = 0x1026;\r
+\r
+/*\r
+ * Source type (Static, Streaming or undetermined)\r
+ * Source is Static if a Buffer has been attached using AL_BUFFER\r
+ * Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers\r
+ * Source is undetermined when it has the NULL buffer attached\r
+ */\r
+    static final int AL_SOURCE_TYPE = 0x1027;\r
+    static final int AL_STATIC = 0x1028;\r
+    static final int AL_STREAMING = 0x1029;\r
+    static final int AL_UNDETERMINED = 0x1030;\r
+\r
+/** Sound samples: format specifier. */\r
+    static final int AL_FORMAT_MONO8 = 0x1100;\r
+    static final int AL_FORMAT_MONO16 = 0x1101;\r
+    static final int AL_FORMAT_STEREO8 = 0x1102;\r
+    static final int AL_FORMAT_STEREO16 = 0x1103;\r
+\r
+/**\r
+ * source specific reference distance\r
+ * Type: ALfloat\r
+ * Range:  0.0 - +inf\r
+ *\r
+ * At 0.0, no distance attenuation occurs.  Default is\r
+ * 1.0.\r
+ */\r
+    static final int AL_REFERENCE_DISTANCE = 0x1020;\r
+\r
+/**\r
+ * source specific rolloff factor\r
+ * Type: ALfloat\r
+ * Range:  0.0 - +inf\r
+ *\r
+ */\r
+    static final int AL_ROLLOFF_FACTOR = 0x1021;\r
+\r
+/**\r
+ * Directional source, outer cone gain.\r
+ *\r
+ * Default:  0.0\r
+ * Range:    [0.0 - 1.0]\r
+ * Logarithmic\r
+ */\r
+    static final int AL_CONE_OUTER_GAIN = 0x1022;\r
+\r
+/**\r
+ * Indicate distance above which sources are not\r
+ * attenuated using the inverse clamped distance model.\r
+ *\r
+ * Default: +inf\r
+ * Type: ALfloat\r
+ * Range:  0.0 - +inf\r
+ */\r
+    static final int AL_MAX_DISTANCE = 0x1023;\r
+\r
+/**\r
+ * Sound samples: frequency, in units of Hertz [Hz].\r
+ * This is the number of samples per second. Half of the\r
+ *  sample frequency marks the maximum significant\r
+ *  frequency component.\r
+ */\r
+    static final int AL_FREQUENCY = 0x2001;\r
+    static final int AL_BITS = 0x2002;\r
+    static final int AL_CHANNELS = 0x2003;\r
+    static final int AL_SIZE = 0x2004;\r
+\r
+/**\r
+ * Buffer state.\r
+ *\r
+ * Not supported for public use (yet).\r
+ */\r
+    static final int AL_UNUSED = 0x2010;\r
+    static final int AL_PENDING = 0x2011;\r
+    static final int AL_PROCESSED = 0x2012;\r
+\r
+\r
+/** Errors: No Error. */\r
+    static final int AL_NO_ERROR = 0;\r
+\r
+/**\r
+ * Invalid Name paramater passed to AL call.\r
+ */\r
+    static final int AL_INVALID_NAME = 0xA001;\r
+\r
+/**\r
+ * Invalid parameter passed to AL call.\r
+ */\r
+    static final int AL_INVALID_ENUM = 0xA002;\r
+\r
+/**\r
+ * Invalid enum parameter value.\r
+ */\r
+    static final int AL_INVALID_VALUE = 0xA003;\r
+\r
+/**\r
+ * Illegal call.\r
+ */\r
+    static final int AL_INVALID_OPERATION = 0xA004;\r
+\r
+\r
+/**\r
+ * No mojo.\r
+ */\r
+    static final int AL_OUT_OF_MEMORY = 0xA005;\r
+\r
+\r
+/** Context strings: Vendor Name. */\r
+    static final int AL_VENDOR = 0xB001;\r
+    static final int AL_VERSION = 0xB002;\r
+    static final int AL_RENDERER = 0xB003;\r
+    static final int AL_EXTENSIONS = 0xB004;\r
+\r
+/** Global tweakage. */\r
+\r
+/**\r
+ * Doppler scale.  Default 1.0\r
+ */\r
+    static final int AL_DOPPLER_FACTOR = 0xC000;\r
+\r
+/**\r
+ * Tweaks speed of propagation.\r
+ */\r
+    static final int AL_DOPPLER_VELOCITY = 0xC001;\r
+\r
+/**\r
+ * Speed of Sound in units per second\r
+ */\r
+    static final int AL_SPEED_OF_SOUND = 0xC003;\r
+\r
+/**\r
+ * Distance models\r
+ *\r
+ * used in conjunction with DistanceModel\r
+ *\r
+ * implicit: NONE, which disances distance attenuation.\r
+ */\r
+    static final int AL_DISTANCE_MODEL = 0xD000;\r
+    static final int AL_INVERSE_DISTANCE = 0xD001;\r
+    static final int AL_INVERSE_DISTANCE_CLAMPED = 0xD002;\r
+    static final int AL_LINEAR_DISTANCE = 0xD003;\r
+    static final int AL_LINEAR_DISTANCE_CLAMPED = 0xD004;\r
+    static final int AL_EXPONENT_DISTANCE = 0xD005;\r
+    static final int AL_EXPONENT_DISTANCE_CLAMPED = 0xD006;\r
+\r
+\r
+    public static String GetALErrorMsg(int errorCode) {\r
+        String errorText;\r
+        switch (errorCode) {\r
+            case AL_NO_ERROR:\r
+                errorText = "No Error";\r
+                break;\r
+            case AL_INVALID_NAME:\r
+                errorText = "Invalid Name";\r
+                break;\r
+            case AL_INVALID_ENUM:\r
+                errorText = "Invalid Enum";\r
+                break;\r
+            case AL_INVALID_VALUE:\r
+                errorText = "Invalid Value";\r
+                break;\r
+            case AL_INVALID_OPERATION:\r
+                errorText = "Invalid Operation";\r
+                break;\r
+            case AL_OUT_OF_MEMORY:\r
+                errorText = "Out of Memory";\r
+                break;\r
+            default:\r
+                errorText = "Unknown Error Code: " + String.valueOf(errorCode);\r
+        }\r
+        return errorText;\r
+    }\r
+}\r
+\r
diff --git a/engine/src/android/com/jme3/audio/android/AndroidOpenALSoftAudioRenderer.java b/engine/src/android/com/jme3/audio/android/AndroidOpenALSoftAudioRenderer.java
new file mode 100644 (file)
index 0000000..3fc4089
--- /dev/null
@@ -0,0 +1,1367 @@
+/*\r
+ * Copyright (c) 2009-2012 jMonkeyEngine\r
+ * All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or without\r
+ * modification, are permitted provided that the following conditions are\r
+ * met:\r
+ *\r
+ * * Redistributions of source code must retain the above copyright\r
+ *   notice, this list of conditions and the following disclaimer.\r
+ *\r
+ * * Redistributions in binary form must reproduce the above copyright\r
+ *   notice, this list of conditions and the following disclaimer in the\r
+ *   documentation and/or other materials provided with the distribution.\r
+ *\r
+ * * Neither the name of 'jMonkeyEngine' nor the names of its contributors\r
+ *   may be used to endorse or promote products derived from this software\r
+ *   without specific prior written permission.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED\r
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
+ */\r
+package com.jme3.audio.android;\r
+\r
+import com.jme3.audio.*;\r
+import com.jme3.audio.AudioSource.Status;\r
+import com.jme3.math.Vector3f;\r
+import com.jme3.util.BufferUtils;\r
+import com.jme3.util.NativeObjectManager;\r
+import java.nio.ByteBuffer;\r
+import java.nio.FloatBuffer;\r
+import java.nio.IntBuffer;\r
+import java.util.ArrayList;\r
+import java.util.concurrent.atomic.AtomicBoolean;\r
+import java.util.logging.Level;\r
+import java.util.logging.Logger;\r
+\r
+public class AndroidOpenALSoftAudioRenderer implements AudioRenderer, Runnable {\r
+\r
+    private static final Logger logger = Logger.getLogger(AndroidOpenALSoftAudioRenderer.class.getName());\r
+    private final NativeObjectManager objManager = new NativeObjectManager();\r
+    // When multiplied by STREAMING_BUFFER_COUNT, will equal 44100 * 2 * 2\r
+    // which is exactly 1 second of audio.\r
+    private static final int BUFFER_SIZE = 35280;\r
+    private static final int STREAMING_BUFFER_COUNT = 5;\r
+    private final static int MAX_NUM_CHANNELS = 64;\r
+    private IntBuffer ib = BufferUtils.createIntBuffer(1);\r
+    private final FloatBuffer fb = BufferUtils.createVector3Buffer(2);\r
+    private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE);\r
+    private final byte[] arrayBuf = new byte[BUFFER_SIZE];\r
+    private int[] channels;\r
+    private AudioSource[] chanSrcs;\r
+    private int nextChan = 0;\r
+    private ArrayList<Integer> freeChans = new ArrayList<Integer>();\r
+    private Listener listener;\r
+    private boolean audioDisabled = false;\r
+    private boolean supportEfx = false;\r
+    private int auxSends = 0;\r
+    private int reverbFx = -1;\r
+    private int reverbFxSlot = -1;\r
+    // Update audio 20 times per second\r
+    private static final float UPDATE_RATE = 0.05f;\r
+    private final Thread audioThread = new Thread(this, "jME3 Audio Thread");\r
+    private final AtomicBoolean threadLock = new AtomicBoolean(false);\r
+\r
+    public AndroidOpenALSoftAudioRenderer() {\r
+    }\r
+\r
+    public void initialize() {\r
+        if (!audioThread.isAlive()) {\r
+            audioThread.setDaemon(true);\r
+            audioThread.setPriority(Thread.NORM_PRIORITY + 1);\r
+            audioThread.start();\r
+        } else {\r
+            throw new IllegalStateException("Initialize already called");\r
+        }\r
+    }\r
+\r
+    private void checkDead() {\r
+        if (audioThread.getState() == Thread.State.TERMINATED) {\r
+            throw new IllegalStateException("Audio thread is terminated");\r
+        }\r
+    }\r
+\r
+    public void run() {\r
+        initInThread();\r
+        synchronized (threadLock) {\r
+            threadLock.set(true);\r
+            threadLock.notifyAll();\r
+        }\r
+\r
+        long updateRateNanos = (long) (UPDATE_RATE * 1000000000);\r
+        mainloop:\r
+        while (true) {\r
+            long startTime = System.nanoTime();\r
+\r
+            if (Thread.interrupted()) {\r
+                break;\r
+            }\r
+\r
+            synchronized (threadLock) {\r
+                updateInThread(UPDATE_RATE);\r
+            }\r
+\r
+            long endTime = System.nanoTime();\r
+            long diffTime = endTime - startTime;\r
+\r
+            if (diffTime < updateRateNanos) {\r
+                long desiredEndTime = startTime + updateRateNanos;\r
+                while (System.nanoTime() < desiredEndTime) {\r
+                    try {\r
+                        Thread.sleep(1);\r
+                    } catch (InterruptedException ex) {\r
+                        break mainloop;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+\r
+        logger.log(Level.INFO, "Exiting audioThread run loop");\r
+        synchronized (threadLock) {\r
+            cleanupInThread();\r
+        }\r
+    }\r
+\r
+    public void initInThread() {\r
+        try {\r
+            if (!alIsCreated()) {\r
+                //AL.create();\r
+                logger.log(Level.INFO, "Creating OpenAL Soft Renderer");\r
+                alCreate();\r
+                checkError(false);\r
+            }\r
+//        } catch (OpenALException ex) {\r
+//            logger.log(Level.SEVERE, "Failed to load audio library", ex);\r
+//            audioDisabled = true;\r
+//            return;\r
+//        } catch (LWJGLException ex) {\r
+//            logger.log(Level.SEVERE, "Failed to load audio library", ex);\r
+//            audioDisabled = true;\r
+//            return;\r
+        } catch (UnsatisfiedLinkError ex) {\r
+            logger.log(Level.SEVERE, "Failed to load audio library", ex);\r
+            audioDisabled = true;\r
+            return;\r
+        }\r
+\r
+        //ALCdevice device = AL.getDevice(); /* device maintained in jni */\r
+        //String deviceName = ALC10.alcGetString(device, ALC10.ALC_DEVICE_SPECIFIER);\r
+        String deviceName = alcGetString(AL.ALC_DEVICE_SPECIFIER);\r
+\r
+        logger.log(Level.INFO, "Audio Device: {0}", deviceName);\r
+        //logger.log(Level.INFO, "Audio Vendor: {0}", alGetString(AL_VENDOR));\r
+        //logger.log(Level.INFO, "Audio Renderer: {0}", alGetString(AL_RENDERER));\r
+        //logger.log(Level.INFO, "Audio Version: {0}", alGetString(AL_VERSION));\r
+        logger.log(Level.INFO, "Audio Vendor: {0}", alGetString(AL.AL_VENDOR));\r
+        logger.log(Level.INFO, "Audio Renderer: {0}", alGetString(AL.AL_RENDERER));\r
+        logger.log(Level.INFO, "Audio Version: {0}", alGetString(AL.AL_VERSION));\r
+\r
+        // Find maximum # of sources supported by this implementation\r
+        ArrayList<Integer> channelList = new ArrayList<Integer>();\r
+        for (int i = 0; i < MAX_NUM_CHANNELS; i++) {\r
+//            logger.log(Level.INFO, "Generating Source for index: {0}", i);\r
+            int chan = alGenSources();\r
+//            logger.log(Level.INFO, "chan: {0}", chan);\r
+            //if (alGetError() != 0) {\r
+            if (checkError(false) != 0) {\r
+//                logger.log(Level.INFO, "alGetError detected an error");\r
+                break;\r
+            } else {\r
+                channelList.add(chan);\r
+            }\r
+        }\r
+\r
+        channels = new int[channelList.size()];\r
+        for (int i = 0; i < channels.length; i++) {\r
+            channels[i] = channelList.get(i);\r
+        }\r
+\r
+        ib = BufferUtils.createIntBuffer(channels.length);\r
+        chanSrcs = new AudioSource[channels.length];\r
+\r
+        logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length);\r
+\r
+//        supportEfx = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX");\r
+//        if (supportEfx) {\r
+//            ib.position(0).limit(1);\r
+//            ALC10.alcGetInteger(device, EFX10.ALC_EFX_MAJOR_VERSION, ib);\r
+//            int major = ib.get(0);\r
+//            ib.position(0).limit(1);\r
+//            ALC10.alcGetInteger(device, EFX10.ALC_EFX_MINOR_VERSION, ib);\r
+//            int minor = ib.get(0);\r
+//            logger.log(Level.INFO, "Audio effect extension version: {0}.{1}", new Object[]{major, minor});\r
+//\r
+//            ALC10.alcGetInteger(device, EFX10.ALC_MAX_AUXILIARY_SENDS, ib);\r
+//            auxSends = ib.get(0);\r
+//            logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends);\r
+//\r
+//            // create slot\r
+//            ib.position(0).limit(1);\r
+//            EFX10.alGenAuxiliaryEffectSlots(ib);\r
+//            reverbFxSlot = ib.get(0);\r
+//\r
+//            // create effect\r
+//            ib.position(0).limit(1);\r
+//            EFX10.alGenEffects(ib);\r
+//            reverbFx = ib.get(0);\r
+//            EFX10.alEffecti(reverbFx, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_REVERB);\r
+//\r
+//            // attach reverb effect to effect slot\r
+//            EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx);\r
+//        } else {\r
+//            logger.log(Level.WARNING, "OpenAL EFX not available! Audio effects won't work.");\r
+//        }\r
+    }\r
+\r
+    public void cleanupInThread() {\r
+        logger.log(Level.INFO, "cleanupInThread");\r
+        if (audioDisabled) {\r
+            //AL.destroy();\r
+            logger.log(Level.INFO, "Destroying OpenAL Soft Renderer with audioDisabled");\r
+            alDestroy();\r
+            checkError(true);\r
+            return;\r
+        }\r
+\r
+        // stop any playing channels\r
+        for (int i = 0; i < chanSrcs.length; i++) {\r
+            if (chanSrcs[i] != null) {\r
+                clearChannel(i);\r
+            }\r
+        }\r
+\r
+        // delete channel-based sources\r
+        ib.clear();\r
+        ib.put(channels);\r
+        ib.flip();\r
+        //alDeleteSources(ib);\r
+        alDeleteSources(channels.length, ib);\r
+        checkError(true);\r
+\r
+        // delete audio buffers and filters\r
+        objManager.deleteAllObjects(this);\r
+\r
+//        if (supportEfx) {\r
+//            ib.position(0).limit(1);\r
+//            ib.put(0, reverbFx);\r
+//            EFX10.alDeleteEffects(ib);\r
+//\r
+//            // If this is not allocated, why is it deleted?\r
+//            // Commented out to fix native crash in OpenAL.\r
+//            ib.position(0).limit(1);\r
+//            ib.put(0, reverbFxSlot);\r
+//            EFX10.alDeleteAuxiliaryEffectSlots(ib);\r
+//        }\r
+//\r
+        //AL.destroy();\r
+        logger.log(Level.INFO, "Destroying OpenAL Soft Renderer");\r
+        alDestroy();\r
+//        checkError(true);\r
+    }\r
+\r
+    public void cleanup() {\r
+        logger.log(Level.INFO, "cleanup");\r
+        // kill audio thread\r
+        if (audioThread.isAlive()) {\r
+            logger.log(Level.INFO, "Interrupting audioThread");\r
+            audioThread.interrupt();\r
+        }\r
+    }\r
+\r
+    private void updateFilter(Filter f) {\r
+//        int id = f.getId();\r
+//        if (id == -1) {\r
+//            ib.position(0).limit(1);\r
+//            EFX10.alGenFilters(ib);\r
+//            id = ib.get(0);\r
+//            f.setId(id);\r
+//\r
+//            objManager.registerForCleanup(f);\r
+//        }\r
+//\r
+//        if (f instanceof LowPassFilter) {\r
+//            LowPassFilter lpf = (LowPassFilter) f;\r
+//            EFX10.alFilteri(id, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS);\r
+//            EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAIN, lpf.getVolume());\r
+//            EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAINHF, lpf.getHighFreqVolume());\r
+//        } else {\r
+//            throw new UnsupportedOperationException("Filter type unsupported: "\r
+//                    + f.getClass().getName());\r
+//        }\r
+//\r
+//        f.clearUpdateNeeded();\r
+    }\r
+\r
+    public void updateSourceParam(AudioSource src, AudioParam param) {\r
+        checkDead();\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled) {\r
+                return;\r
+            }\r
+\r
+            // There is a race condition in AudioSource that can\r
+            // cause this to be called for a node that has been\r
+            // detached from its channel.  For example, setVolume()\r
+            // called from the render thread may see that that AudioSource\r
+            // still has a channel value but the audio thread may\r
+            // clear that channel before setVolume() gets to call\r
+            // updateSourceParam() (because the audio stopped playing\r
+            // on its own right as the volume was set).  In this case,\r
+            // it should be safe to just ignore the update\r
+            if (src.getChannel() < 0) {\r
+                return;\r
+            }\r
+\r
+            assert src.getChannel() >= 0;\r
+\r
+            int id = channels[src.getChannel()];\r
+            switch (param) {\r
+                case Position:\r
+                    if (!src.isPositional()) {\r
+                        return;\r
+                    }\r
+\r
+                    Vector3f pos = src.getPosition();\r
+                    //alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);\r
+                    alSource3f(id, AL.AL_POSITION, pos.x, pos.y, pos.z);\r
+                    checkError(true);\r
+                    break;\r
+                case Velocity:\r
+                    if (!src.isPositional()) {\r
+                        return;\r
+                    }\r
+\r
+                    Vector3f vel = src.getVelocity();\r
+                    //alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z);\r
+                    alSource3f(id, AL.AL_VELOCITY, vel.x, vel.y, vel.z);\r
+                    checkError(true);\r
+                    break;\r
+                case MaxDistance:\r
+                    if (!src.isPositional()) {\r
+                        return;\r
+                    }\r
+\r
+                    //alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance());\r
+                    alSourcef(id, AL.AL_MAX_DISTANCE, src.getMaxDistance());\r
+                    checkError(true);\r
+                    break;\r
+                case RefDistance:\r
+                    if (!src.isPositional()) {\r
+                        return;\r
+                    }\r
+\r
+                    //alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance());\r
+                    alSourcef(id, AL.AL_REFERENCE_DISTANCE, src.getRefDistance());\r
+                    checkError(true);\r
+                    break;\r
+                case ReverbFilter:\r
+                    if (!supportEfx || !src.isPositional() || !src.isReverbEnabled()) {\r
+                        return;\r
+                    }\r
+\r
+//                    int filter = EFX10.AL_FILTER_NULL;\r
+//                    if (src.getReverbFilter() != null) {\r
+//                        Filter f = src.getReverbFilter();\r
+//                        if (f.isUpdateNeeded()) {\r
+//                            updateFilter(f);\r
+//                        }\r
+//                        filter = f.getId();\r
+//                    }\r
+//                    AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter);\r
+                    break;\r
+                case ReverbEnabled:\r
+                    if (!supportEfx || !src.isPositional()) {\r
+                        return;\r
+                    }\r
+\r
+                    if (src.isReverbEnabled()) {\r
+                        updateSourceParam(src, AudioParam.ReverbFilter);\r
+                    } else {\r
+//                        AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL);\r
+                    }\r
+                    break;\r
+                case IsPositional:\r
+                    if (!src.isPositional()) {\r
+                        // Play in headspace\r
+                        //alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE);\r
+                        alSourcei(id, AL.AL_SOURCE_RELATIVE, AL.AL_TRUE);\r
+                        checkError(true);\r
+                        //alSource3f(id, AL_POSITION, 0, 0, 0);\r
+                        alSource3f(id, AL.AL_POSITION, 0, 0, 0);\r
+                        checkError(true);\r
+                        //alSource3f(id, AL_VELOCITY, 0, 0, 0);\r
+                        alSource3f(id, AL.AL_VELOCITY, 0, 0, 0);\r
+                        checkError(true);\r
+\r
+                        // Disable reverb\r
+//                        AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL);\r
+                    } else {\r
+                        //alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE);\r
+                        alSourcei(id, AL.AL_SOURCE_RELATIVE, AL.AL_FALSE);\r
+                        checkError(true);\r
+                        updateSourceParam(src, AudioParam.Position);\r
+                        updateSourceParam(src, AudioParam.Velocity);\r
+                        updateSourceParam(src, AudioParam.MaxDistance);\r
+                        updateSourceParam(src, AudioParam.RefDistance);\r
+                        updateSourceParam(src, AudioParam.ReverbEnabled);\r
+                    }\r
+                    break;\r
+                case Direction:\r
+                    if (!src.isDirectional()) {\r
+                        return;\r
+                    }\r
+\r
+                    Vector3f dir = src.getDirection();\r
+                    //alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z);\r
+                    alSource3f(id, AL.AL_DIRECTION, dir.x, dir.y, dir.z);\r
+                    checkError(true);\r
+                    break;\r
+                case InnerAngle:\r
+                    if (!src.isDirectional()) {\r
+                        return;\r
+                    }\r
+\r
+                    //alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle());\r
+                    alSourcef(id, AL.AL_CONE_INNER_ANGLE, src.getInnerAngle());\r
+                    checkError(true);\r
+                    break;\r
+                case OuterAngle:\r
+                    if (!src.isDirectional()) {\r
+                        return;\r
+                    }\r
+\r
+                    //alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle());\r
+                    alSourcef(id, AL.AL_CONE_OUTER_ANGLE, src.getOuterAngle());\r
+                    checkError(true);\r
+                    break;\r
+                case IsDirectional:\r
+                    if (src.isDirectional()) {\r
+                        updateSourceParam(src, AudioParam.Direction);\r
+                        updateSourceParam(src, AudioParam.InnerAngle);\r
+                        updateSourceParam(src, AudioParam.OuterAngle);\r
+                        //alSourcef(id, AL_CONE_OUTER_GAIN, 0);\r
+                        alSourcef(id, AL.AL_CONE_OUTER_GAIN, 0);\r
+                        checkError(true);\r
+                    } else {\r
+                        //alSourcef(id, AL_CONE_INNER_ANGLE, 360);\r
+                        alSourcef(id, AL.AL_CONE_INNER_ANGLE, 360);\r
+                        checkError(true);\r
+                        //alSourcef(id, AL_CONE_OUTER_ANGLE, 360);\r
+                        alSourcef(id, AL.AL_CONE_OUTER_ANGLE, 360);\r
+                        checkError(true);\r
+                        //alSourcef(id, AL_CONE_OUTER_GAIN, 1f);\r
+                        alSourcef(id, AL.AL_CONE_OUTER_GAIN, 1f);\r
+                        checkError(true);\r
+                    }\r
+                    break;\r
+//                case DryFilter:\r
+//                    if (!supportEfx) {\r
+//                        return;\r
+//                    }\r
+//\r
+//                    if (src.getDryFilter() != null) {\r
+//                        Filter f = src.getDryFilter();\r
+//                        if (f.isUpdateNeeded()) {\r
+//                            updateFilter(f);\r
+//\r
+//                            // NOTE: must re-attach filter for changes to apply.\r
+//                            alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId());\r
+//                        }\r
+//                    } else {\r
+//                        alSourcei(id, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL);\r
+//                    }\r
+//                    break;\r
+                case Looping:\r
+                    if (src.isLooping()) {\r
+                        if (!(src.getAudioData() instanceof AudioStream)) {\r
+                            //alSourcei(id, AL_LOOPING, AL_TRUE);\r
+                            alSourcei(id, AL.AL_LOOPING, AL.AL_TRUE);\r
+                            checkError(true);\r
+                        }\r
+                    } else {\r
+                        //alSourcei(id, AL_LOOPING, AL_FALSE);\r
+                        alSourcei(id, AL.AL_LOOPING, AL.AL_FALSE);\r
+                        checkError(true);\r
+                    }\r
+                    break;\r
+                case Volume:\r
+                    //alSourcef(id, AL_GAIN, src.getVolume());\r
+                    alSourcef(id, AL.AL_GAIN, src.getVolume());\r
+                    checkError(true);\r
+                    break;\r
+                case Pitch:\r
+                    //alSourcef(id, AL_PITCH, src.getPitch());\r
+                    alSourcef(id, AL.AL_PITCH, src.getPitch());\r
+                    checkError(true);\r
+                    break;\r
+            }\r
+        }\r
+    }\r
+\r
+    private void setSourceParams(int id, AudioSource src, boolean forceNonLoop) {\r
+        if (src.isPositional()) {\r
+            Vector3f pos = src.getPosition();\r
+            Vector3f vel = src.getVelocity();\r
+            //alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z);\r
+            alSource3f(id, AL.AL_POSITION, pos.x, pos.y, pos.z);\r
+            checkError(true);\r
+            //alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z);\r
+            alSource3f(id, AL.AL_VELOCITY, vel.x, vel.y, vel.z);\r
+            checkError(true);\r
+            //alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance());\r
+            alSourcef(id, AL.AL_MAX_DISTANCE, src.getMaxDistance());\r
+            checkError(true);\r
+            //alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance());\r
+            alSourcef(id, AL.AL_REFERENCE_DISTANCE, src.getRefDistance());\r
+            checkError(true);\r
+            //alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE);\r
+            alSourcei(id, AL.AL_SOURCE_RELATIVE, AL.AL_FALSE);\r
+            checkError(true);\r
+\r
+//            if (src.isReverbEnabled() && supportEfx) {\r
+//                int filter = EFX10.AL_FILTER_NULL;\r
+//                if (src.getReverbFilter() != null) {\r
+//                    Filter f = src.getReverbFilter();\r
+//                    if (f.isUpdateNeeded()) {\r
+//                        updateFilter(f);\r
+//                    }\r
+//                    filter = f.getId();\r
+//                }\r
+//                AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter);\r
+//            }\r
+        } else {\r
+            // play in headspace\r
+            //alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE);\r
+            alSourcei(id, AL.AL_SOURCE_RELATIVE, AL.AL_TRUE);\r
+            checkError(true);\r
+            //alSource3f(id, AL_POSITION, 0, 0, 0);\r
+            alSource3f(id, AL.AL_POSITION, 0, 0, 0);\r
+            checkError(true);\r
+            //alSource3f(id, AL_VELOCITY, 0, 0, 0);\r
+            alSource3f(id, AL.AL_VELOCITY, 0, 0, 0);\r
+            checkError(true);\r
+        }\r
+\r
+//        if (src.getDryFilter() != null && supportEfx) {\r
+//            Filter f = src.getDryFilter();\r
+//            if (f.isUpdateNeeded()) {\r
+//                updateFilter(f);\r
+//\r
+//                // NOTE: must re-attach filter for changes to apply.\r
+//                alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId());\r
+//            }\r
+//        }\r
+//\r
+        if (forceNonLoop) {\r
+            //alSourcei(id, AL_LOOPING, AL_FALSE);\r
+            alSourcei(id, AL.AL_LOOPING, AL.AL_FALSE);\r
+            checkError(true);\r
+        } else {\r
+            //alSourcei(id, AL_LOOPING, src.isLooping() ? AL_TRUE : AL_FALSE);\r
+            alSourcei(id, AL.AL_LOOPING, src.isLooping() ? AL.AL_TRUE : AL.AL_FALSE);\r
+            checkError(true);\r
+        }\r
+        //alSourcef(id, AL_GAIN, src.getVolume());\r
+        alSourcef(id, AL.AL_GAIN, src.getVolume());\r
+        checkError(true);\r
+        //alSourcef(id, AL_PITCH, src.getPitch());\r
+        alSourcef(id, AL.AL_PITCH, src.getPitch());\r
+        checkError(true);\r
+        //alSourcef(id, AL11.AL_SEC_OFFSET, src.getTimeOffset());\r
+        alSourcef(id, AL.AL_SEC_OFFSET, src.getTimeOffset());\r
+        checkError(true);\r
+\r
+        if (src.isDirectional()) {\r
+            Vector3f dir = src.getDirection();\r
+            //alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z);\r
+            alSource3f(id, AL.AL_DIRECTION, dir.x, dir.y, dir.z);\r
+            checkError(true);\r
+            //alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle());\r
+            alSourcef(id, AL.AL_CONE_INNER_ANGLE, src.getInnerAngle());\r
+            checkError(true);\r
+            //alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle());\r
+            alSourcef(id, AL.AL_CONE_OUTER_ANGLE, src.getOuterAngle());\r
+            checkError(true);\r
+            //alSourcef(id, AL_CONE_OUTER_GAIN, 0);\r
+            alSourcef(id, AL.AL_CONE_OUTER_GAIN, 0);\r
+            checkError(true);\r
+        } else {\r
+            //alSourcef(id, AL_CONE_INNER_ANGLE, 360);\r
+            alSourcef(id, AL.AL_CONE_INNER_ANGLE, 360);\r
+            checkError(true);\r
+            //alSourcef(id, AL_CONE_OUTER_ANGLE, 360);\r
+            alSourcef(id, AL.AL_CONE_OUTER_ANGLE, 360);\r
+            checkError(true);\r
+            //alSourcef(id, AL_CONE_OUTER_GAIN, 1f);\r
+            alSourcef(id, AL.AL_CONE_OUTER_GAIN, 1f);\r
+            checkError(true);\r
+        }\r
+    }\r
+\r
+    public void updateListenerParam(Listener listener, ListenerParam param) {\r
+        checkDead();\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled) {\r
+                return;\r
+            }\r
+\r
+            switch (param) {\r
+                case Position:\r
+                    Vector3f pos = listener.getLocation();\r
+                    //alListener3f(AL_POSITION, pos.x, pos.y, pos.z);\r
+                    alListener3f(AL.AL_POSITION, pos.x, pos.y, pos.z);\r
+                    checkError(true);\r
+                    break;\r
+                case Rotation:\r
+                    Vector3f dir = listener.getDirection();\r
+                    Vector3f up = listener.getUp();\r
+                    fb.rewind();\r
+                    fb.put(dir.x).put(dir.y).put(dir.z);\r
+                    fb.put(up.x).put(up.y).put(up.z);\r
+                    fb.flip();\r
+                    //alListener(AL_ORIENTATION, fb);\r
+                    alListener(AL.AL_ORIENTATION, fb);\r
+                    checkError(true);\r
+                    break;\r
+                case Velocity:\r
+                    Vector3f vel = listener.getVelocity();\r
+                    //alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z);\r
+                    alListener3f(AL.AL_VELOCITY, vel.x, vel.y, vel.z);\r
+                    checkError(true);\r
+                    break;\r
+                case Volume:\r
+                    //alListenerf(AL_GAIN, listener.getVolume());\r
+                    alListenerf(AL.AL_GAIN, listener.getVolume());\r
+                    checkError(true);\r
+                    break;\r
+            }\r
+        }\r
+    }\r
+\r
+    private void setListenerParams(Listener listener) {\r
+        Vector3f pos = listener.getLocation();\r
+        Vector3f vel = listener.getVelocity();\r
+        Vector3f dir = listener.getDirection();\r
+        Vector3f up = listener.getUp();\r
+\r
+        //alListener3f(AL_POSITION, pos.x, pos.y, pos.z);\r
+        alListener3f(AL.AL_POSITION, pos.x, pos.y, pos.z);\r
+        checkError(true);\r
+        //alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z);\r
+        alListener3f(AL.AL_VELOCITY, vel.x, vel.y, vel.z);\r
+        checkError(true);\r
+        fb.rewind();\r
+        fb.put(dir.x).put(dir.y).put(dir.z);\r
+        fb.put(up.x).put(up.y).put(up.z);\r
+        fb.flip();\r
+        //alListener(AL_ORIENTATION, fb);\r
+        alListener(AL.AL_ORIENTATION, fb);\r
+        checkError(true);\r
+        //alListenerf(AL_GAIN, listener.getVolume());\r
+        alListenerf(AL.AL_GAIN, listener.getVolume());\r
+        checkError(true);\r
+    }\r
+\r
+    private int newChannel() {\r
+        if (freeChans.size() > 0) {\r
+            return freeChans.remove(0);\r
+        } else if (nextChan < channels.length) {\r
+            return nextChan++;\r
+        } else {\r
+            return -1;\r
+        }\r
+    }\r
+\r
+    private void freeChannel(int index) {\r
+        if (index == nextChan - 1) {\r
+            nextChan--;\r
+        } else {\r
+            freeChans.add(index);\r
+        }\r
+    }\r
+\r
+    public void setEnvironment(Environment env) {\r
+        checkDead();\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled || !supportEfx) {\r
+                return;\r
+            }\r
+\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DENSITY, env.getDensity());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DIFFUSION, env.getDiffusion());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAIN, env.getGain());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAINHF, env.getGainHf());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_TIME, env.getDecayTime());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_HFRATIO, env.getDecayHFRatio());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_GAIN, env.getReflectGain());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_DELAY, env.getReflectDelay());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_GAIN, env.getLateReverbGain());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_DELAY, env.getLateReverbDelay());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_AIR_ABSORPTION_GAINHF, env.getAirAbsorbGainHf());\r
+//            EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_ROOM_ROLLOFF_FACTOR, env.getRoomRolloffFactor());\r
+//\r
+//            // attach effect to slot\r
+//            EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx);\r
+        }\r
+    }\r
+\r
+    private boolean fillBuffer(AudioStream stream, int id) {\r
+//        logger.log(Level.INFO, "fillBuffer for id: {0}", id);\r
+        int size = 0;\r
+        int result;\r
+\r
+        while (size < arrayBuf.length) {\r
+            result = stream.readSamples(arrayBuf, size, arrayBuf.length - size);\r
+\r
+            if (result > 0) {\r
+                size += result;\r
+            } else {\r
+                break;\r
+            }\r
+        }\r
+\r
+//        logger.log(Level.INFO, "data for buffer: {0} is size: {1}",\r
+//                new Object[]{id, size});\r
+\r
+        if (size == 0) {\r
+            return false;\r
+        }\r
+\r
+        nativeBuf.clear();\r
+        nativeBuf.put(arrayBuf, 0, size);\r
+        nativeBuf.flip();\r
+\r
+        //alBufferData(id, convertFormat(stream), nativeBuf, stream.getSampleRate());\r
+        alBufferData(id, convertFormat(stream), nativeBuf, size, stream.getSampleRate());\r
+        checkError(true);\r
+\r
+        return true;\r
+    }\r
+\r
+    private boolean fillStreamingSource(int sourceId, AudioStream stream) {\r
+//        logger.log(Level.INFO, "fillStreamingSource for source: {0}", sourceId);\r
+        if (!stream.isOpen()) {\r
+            return false;\r
+        }\r
+\r
+        boolean active = true;\r
+        //int processed = alGetSourcei(sourceId, AL_BUFFERS_PROCESSED);\r
+        int processed = alGetSourcei(sourceId, AL.AL_BUFFERS_PROCESSED);\r
+//        logger.log(Level.INFO, "fillStreamingSource buffers processed: {0}", processed);\r
+        checkError(true);\r
+\r
+        //while((processed--) != 0){\r
+        if (processed > 0) {\r
+            int buffer;\r
+\r
+            ib.position(0).limit(1);\r
+//            logger.log(Level.INFO, "fillStreamingSource alSourceUnqueueBuffers for source: {0}", sourceId);\r
+            //alSourceUnqueueBuffers(sourceId, ib);\r
+            alSourceUnqueueBuffers(sourceId, 1, ib);\r
+            checkError(true);\r
+            buffer = ib.get(0);\r
+//            logger.log(Level.INFO, "fillStreamingSource bufferID: {0}", buffer);\r
+\r
+            active = fillBuffer(stream, buffer);\r
+\r
+            ib.position(0).limit(1);\r
+            ib.put(0, buffer);\r
+//            logger.log(Level.INFO, "fillStreamingSource alSourceQueueBuffers for source: {0}, buffer: {1}",\r
+//                    new Object[]{sourceId, buffer});\r
+            //alSourceQueueBuffers(sourceId, ib);\r
+            alSourceQueueBuffers(sourceId, 1, ib);\r
+            checkError(true);\r
+        }\r
+\r
+        if (!active && stream.isOpen()) {\r
+            stream.close();\r
+        }\r
+\r
+        return active;\r
+    }\r
+\r
+    private boolean attachStreamToSource(int sourceId, AudioStream stream) {\r
+//        logger.log(Level.INFO, "attachStreamToSource for source: {0}", sourceId);\r
+        boolean active = true;\r
+        int activeBufferCount = 0;\r
+        for (int id : stream.getIds()) {\r
+            active = fillBuffer(stream, id);\r
+            ib.position(0).limit(1);\r
+            ib.put(id).flip();\r
+            //alSourceQueueBuffers(sourceId, ib);\r
+            // OpenAL Soft does not like 0 size buffer data in alSourceQueueBuffers\r
+            //  Produces error code 40964 (0xA004) = AL_INVALID_OPERATION and\r
+            //  does not return (crashes) so that the error code can be checked.\r
+            // active is FALSE when the data size is 0\r
+            if (active) {\r
+//                logger.log(Level.INFO, "attachStreamToSource alSourceQueueBuffers for source: {0}, buffer: {1}",\r
+//                        new Object[]{sourceId, id});\r
+                alSourceQueueBuffers(sourceId, 1, ib);\r
+                checkError(true);\r
+                activeBufferCount++;\r
+            }\r
+        }\r
+        // adjust the steam id array if the audio data is smaller than STREAMING_BUFFER_COUNT\r
+        // this is to avoid an error with OpenAL Soft when alSourceUnenqueueBuffers\r
+        //   is called with more buffers than were originally used with alSourceQueueBuffers\r
+        if (activeBufferCount < STREAMING_BUFFER_COUNT) {\r
+            int[] newIds = new int[activeBufferCount];\r
+            for (int i=0; i<STREAMING_BUFFER_COUNT; i++) {\r
+                if (i < activeBufferCount) {\r
+                    newIds[i] = stream.getIds()[i];\r
+//                    logger.log(Level.INFO, "newIds[{0}] = {1}",\r
+//                            new Object[]{i, newIds[i]});\r
+                } else {\r
+                    ib.clear();\r
+                    ib.put(stream.getIds()[i]).limit(1).flip();\r
+                    alDeleteBuffers(1, ib);\r
+                    checkError(true);\r
+//                    logger.log(Level.INFO, "deleting buffer at index[{0}] = {1}",\r
+//                            new Object[]{i, stream.getIds()[i]});\r
+                }\r
+\r
+            }\r
+            stream.setIds(newIds);\r
+        }\r
+\r
+        return active;\r
+    }\r
+\r
+    private boolean attachBufferToSource(int sourceId, AudioBuffer buffer) {\r
+        //alSourcei(sourceId, AL_BUFFER, buffer.getId());\r
+        alSourcei(sourceId, AL.AL_BUFFER, buffer.getId());\r
+        checkError(true);\r
+        return true;\r
+    }\r
+\r
+    private boolean attachAudioToSource(int sourceId, AudioData data) {\r
+//        logger.log(Level.INFO, "attachAudioToSource for data type: {0}", data.getClass().getName());\r
+        if (data instanceof AudioBuffer) {\r
+            return attachBufferToSource(sourceId, (AudioBuffer) data);\r
+        } else if (data instanceof AudioStream) {\r
+            return attachStreamToSource(sourceId, (AudioStream) data);\r
+        }\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    private void clearChannel(int index) {\r
+//        logger.log(Level.INFO, "Clearing channel for index: {0}", index);\r
+        // make room at this channel\r
+        if (chanSrcs[index] != null) {\r
+            AudioSource src = chanSrcs[index];\r
+\r
+            int sourceId = channels[index];\r
+//            logger.log(Level.INFO, "Stopping source: {0} in clearChannel", sourceId);\r
+            alSourceStop(sourceId);\r
+\r
+            if (src.getAudioData() instanceof AudioStream) {\r
+                AudioStream str = (AudioStream) src.getAudioData();\r
+//                logger.log(Level.INFO, "source is a stream with numBuffers: {0}", str.getIds().length);\r
+                for (int i=0; i<str.getIds().length; i++) {\r
+//                    logger.log(Level.INFO, "id[{0}]: {1}",\r
+//                            new Object[]{i, str.getIds()[i]});\r
+                }\r
+                //ib.position(0).limit(STREAMING_BUFFER_COUNT);\r
+                ib.position(0).limit(str.getIds().length);\r
+                ib.put(str.getIds()).flip();\r
+//                logger.log(Level.INFO, "clearChannel alSourceUnqueueBuffers for source: {0}", sourceId);\r
+                int processed = alGetSourcei(sourceId, AL.AL_BUFFERS_PROCESSED);\r
+//                logger.log(Level.INFO, "clearChannels buffers processed: {0}", processed);\r
+                //alSourceUnqueueBuffers(sourceId, ib);\r
+                alSourceUnqueueBuffers(sourceId, processed, ib);\r
+                checkError(true);\r
+            } else if (src.getAudioData() instanceof AudioBuffer) {\r
+                //alSourcei(sourceId, AL_BUFFER, 0);\r
+                alSourcei(sourceId, AL.AL_BUFFER, 0);\r
+                checkError(true);\r
+            }\r
+\r
+            if (src.getDryFilter() != null && supportEfx) {\r
+                // detach filter\r
+//                alSourcei(sourceId, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL);\r
+            }\r
+            if (src.isPositional()) {\r
+                AudioSource pas = (AudioSource) src;\r
+                if (pas.isReverbEnabled() && supportEfx) {\r
+//                    AL11.alSource3i(sourceId, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL);\r
+                }\r
+            }\r
+\r
+            chanSrcs[index] = null;\r
+        }\r
+    }\r
+\r
+    public void update(float tpf) {\r
+        // does nothing\r
+    }\r
+\r
+    public void updateInThread(float tpf) {\r
+        if (audioDisabled) {\r
+            return;\r
+        }\r
+\r
+        for (int i = 0; i < channels.length; i++) {\r
+            AudioSource src = chanSrcs[i];\r
+            if (src == null) {\r
+                continue;\r
+            }\r
+\r
+            int sourceId = channels[i];\r
+\r
+            // is the source bound to this channel\r
+            // if false, it's an instanced playback\r
+            boolean boundSource = i == src.getChannel();\r
+\r
+            // source's data is streaming\r
+            boolean streaming = src.getAudioData() instanceof AudioStream;\r
+\r
+            // only buffered sources can be bound\r
+            assert (boundSource && streaming) || (!streaming);\r
+\r
+            //int state = alGetSourcei(sourceId, AL_SOURCE_STATE);\r
+            int state = alGetSourcei(sourceId, AL.AL_SOURCE_STATE);\r
+            checkError(true);\r
+//            logger.log(Level.INFO, "source: {0}, state: {1}",\r
+//                    new Object[]{sourceId, state});\r
+            boolean wantPlaying = src.getStatus() == Status.Playing;\r
+//            logger.log(Level.INFO, "sourceId: {0}, wantPlaying: {1}",\r
+//                    new Object[]{sourceId, wantPlaying});\r
+            //boolean stopped = state == AL_STOPPED;\r
+            boolean stopped = state == AL.AL_STOPPED;\r
+//            logger.log(Level.INFO, "sourceId: {0}, stopped: {1}",\r
+//                    new Object[]{sourceId, stopped});\r
+\r
+            if (streaming && wantPlaying) {\r
+                AudioStream stream = (AudioStream) src.getAudioData();\r
+                if (stream.isOpen()) {\r
+//                    logger.log(Level.INFO, "stream is open && want playing for source: {0}", sourceId);\r
+                    fillStreamingSource(sourceId, stream);\r
+                    if (stopped) {\r
+//                        logger.log(Level.INFO, "source: {0} stopped, set playstate", sourceId);\r
+                        alSourcePlay(sourceId);\r
+                        checkError(true);\r
+                    }\r
+                } else {\r
+                    if (stopped) {\r
+//                        logger.log(Level.INFO, "stream is not open && want playing for source: {0}", sourceId);\r
+                        // became inactive\r
+                        src.setStatus(Status.Stopped);\r
+                        src.setChannel(-1);\r
+                        clearChannel(i);\r
+                        freeChannel(i);\r
+\r
+                        // And free the audio since it cannot be\r
+                        // played again anyway.\r
+                        deleteAudioData(stream);\r
+                    }\r
+                }\r
+            } else if (!streaming) {\r
+                //boolean paused = state == AL_PAUSED;\r
+                boolean paused = state == AL.AL_PAUSED;\r
+//                logger.log(Level.INFO, "source: {0}, pause: {1}",\r
+//                        new Object[]{sourceId, paused});\r
+\r
+                // make sure OAL pause state & source state coincide\r
+                assert (src.getStatus() == Status.Paused && paused) || (!paused);\r
+\r
+                if (stopped) {\r
+                    if (boundSource) {\r
+                        src.setStatus(Status.Stopped);\r
+                        src.setChannel(-1);\r
+                    }\r
+                    clearChannel(i);\r
+                    freeChannel(i);\r
+                }\r
+            }\r
+        }\r
+\r
+        // Delete any unused objects.\r
+        objManager.deleteUnused(this);\r
+    }\r
+\r
+    public void setListener(Listener listener) {\r
+        checkDead();\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled) {\r
+                return;\r
+            }\r
+\r
+            if (this.listener != null) {\r
+                // previous listener no longer associated with current\r
+                // renderer\r
+                this.listener.setRenderer(null);\r
+            }\r
+\r
+            this.listener = listener;\r
+            this.listener.setRenderer(this);\r
+            setListenerParams(listener);\r
+        }\r
+    }\r
+\r
+    public void playSourceInstance(AudioSource src) {\r
+        checkDead();\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled) {\r
+                return;\r
+            }\r
+\r
+            if (src.getAudioData() instanceof AudioStream) {\r
+                throw new UnsupportedOperationException(\r
+                        "Cannot play instances "\r
+                        + "of audio streams. Use playSource() instead.");\r
+            }\r
+\r
+            if (src.getAudioData().isUpdateNeeded()) {\r
+//                logger.log(Level.INFO, "Calling updateAudioData from playSourceInstance");\r
+                updateAudioData(src.getAudioData());\r
+            }\r
+\r
+            // create a new index for an audio-channel\r
+            int index = newChannel();\r
+            if (index == -1) {\r
+                return;\r
+            }\r
+\r
+            int sourceId = channels[index];\r
+\r
+//            logger.log(Level.INFO, "Calling clearChannel for index[{0}] from playSourceInstance", index);\r
+            clearChannel(index);\r
+\r
+            // set parameters, like position and max distance\r
+//            logger.log(Level.INFO, "Calling setSourceParams for sourceID: {0} from playSourceInstance", index);\r
+            setSourceParams(sourceId, src, true);\r
+//            logger.log(Level.INFO, "Calling attachAudioToSource for sourceID: {0} and data audiodata id: {1} from playSourceInstance",\r
+//                    new Object[]{sourceId, src.getAudioData().getId()});\r
+            attachAudioToSource(sourceId, src.getAudioData());\r
+            chanSrcs[index] = src;\r
+\r
+            // play the channel\r
+            alSourcePlay(sourceId);\r
+            checkError(true);\r
+        }\r
+    }\r
+\r
+    public void playSource(AudioSource src) {\r
+        checkDead();\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled) {\r
+                return;\r
+            }\r
+\r
+            //assert src.getStatus() == Status.Stopped || src.getChannel() == -1;\r
+\r
+            if (src.getStatus() == Status.Playing) {\r
+                return;\r
+            } else if (src.getStatus() == Status.Stopped) {\r
+\r
+                // allocate channel to this source\r
+                int index = newChannel();\r
+                if (index == -1) {\r
+                    logger.log(Level.WARNING, "No channel available to play {0}", src);\r
+                    return;\r
+                }\r
+                clearChannel(index);\r
+                src.setChannel(index);\r
+\r
+                AudioData data = src.getAudioData();\r
+                if (data.isUpdateNeeded()) {\r
+                    updateAudioData(data);\r
+                }\r
+\r
+                chanSrcs[index] = src;\r
+                setSourceParams(channels[index], src, false);\r
+                attachAudioToSource(channels[index], data);\r
+            }\r
+\r
+            alSourcePlay(channels[src.getChannel()]);\r
+            checkError(true);\r
+            src.setStatus(Status.Playing);\r
+        }\r
+    }\r
+\r
+    public void pauseSource(AudioSource src) {\r
+//        logger.log(Level.INFO, "pauseSource");\r
+        checkDead();\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled) {\r
+                return;\r
+            }\r
+\r
+//            logger.log(Level.INFO, "source is playing: {0}", src.getStatus() == Status.Playing);\r
+            if (src.getStatus() == Status.Playing) {\r
+                assert src.getChannel() != -1;\r
+\r
+                alSourcePause(channels[src.getChannel()]);\r
+                checkError(true);\r
+                src.setStatus(Status.Paused);\r
+            }\r
+        }\r
+    }\r
+\r
+    public void stopSource(AudioSource src) {\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled) {\r
+                return;\r
+            }\r
+\r
+            if (src.getStatus() != Status.Stopped) {\r
+                int chan = src.getChannel();\r
+                assert chan != -1; // if it's not stopped, must have id\r
+\r
+                src.setStatus(Status.Stopped);\r
+                src.setChannel(-1);\r
+                clearChannel(chan);\r
+                freeChannel(chan);\r
+\r
+                if (src.getAudioData() instanceof AudioStream) {\r
+                    AudioStream stream = (AudioStream) src.getAudioData();\r
+                    if (stream.isOpen()) {\r
+                        stream.close();\r
+                    }\r
+\r
+                    // And free the audio since it cannot be\r
+                    // played again anyway.\r
+                    deleteAudioData(src.getAudioData());\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    private int convertFormat(AudioData ad) {\r
+        switch (ad.getBitsPerSample()) {\r
+            case 8:\r
+                if (ad.getChannels() == 1) {\r
+                    //return AL_FORMAT_MONO8;\r
+                    return AL.AL_FORMAT_MONO8;\r
+                } else if (ad.getChannels() == 2) {\r
+                    //return AL_FORMAT_STEREO8;\r
+                    return AL.AL_FORMAT_STEREO8;\r
+                }\r
+\r
+                break;\r
+            case 16:\r
+                if (ad.getChannels() == 1) {\r
+                    //return AL_FORMAT_MONO16;\r
+                    return AL.AL_FORMAT_MONO16;\r
+                } else {\r
+                    //return AL_FORMAT_STEREO16;\r
+                    return AL.AL_FORMAT_STEREO16;\r
+                }\r
+        }\r
+        throw new UnsupportedOperationException("Unsupported channels/bits combination: "\r
+                + "bits=" + ad.getBitsPerSample() + ", channels=" + ad.getChannels());\r
+    }\r
+\r
+    private void updateAudioBuffer(AudioBuffer ab) {\r
+        int id = ab.getId();\r
+//        logger.log(Level.INFO, "updateAudioBuffer for buffer id: {0}", id);\r
+        if (ab.getId() == -1) {\r
+            ib.position(0).limit(1);\r
+            alGenBuffers(1, ib);\r
+            checkError(true);\r
+            id = ib.get(0);\r
+            ab.setId(id);\r
+//            logger.log(Level.INFO, "Generated Buffer: {0}", id);\r
+\r
+            objManager.registerForCleanup(ab);\r
+        }\r
+//        logger.log(Level.INFO, "updateAudioBuffer new buffer id: {0}", id);\r
+\r
+        ab.getData().clear();\r
+        //alBufferData(id, convertFormat(ab), ab.getData(), ab.getSampleRate());\r
+        alBufferData(id, convertFormat(ab), ab.getData(), ab.getData().limit(), ab.getSampleRate());\r
+        checkError(true);\r
+        ab.clearUpdateNeeded();\r
+    }\r
+\r
+    private void updateAudioStream(AudioStream as) {\r
+//        logger.log(Level.INFO, "updateAudioStream");\r
+        if (as.getIds() != null) {\r
+            deleteAudioData(as);\r
+        }\r
+\r
+        int[] ids = new int[STREAMING_BUFFER_COUNT];\r
+        ib.position(0).limit(STREAMING_BUFFER_COUNT);\r
+        //alGenBuffers(ib);\r
+        alGenBuffers(STREAMING_BUFFER_COUNT, ib);\r
+        checkError(true);\r
+        ib.position(0).limit(STREAMING_BUFFER_COUNT);\r
+        ib.get(ids);\r
+//        for (int i=0; i<ids.length; i++) {\r
+//            logger.log(Level.INFO, "Generated Streaming Buffer: {0}", ids[i]);\r
+//        }\r
+\r
+        // Not registered with object manager.\r
+        // AudioStreams can be handled without object manager\r
+        // since their lifecycle is known to the audio renderer.\r
+\r
+        as.setIds(ids);\r
+        as.clearUpdateNeeded();\r
+    }\r
+\r
+    private void updateAudioData(AudioData ad) {\r
+        if (ad instanceof AudioBuffer) {\r
+            updateAudioBuffer((AudioBuffer) ad);\r
+        } else if (ad instanceof AudioStream) {\r
+            updateAudioStream((AudioStream) ad);\r
+        }\r
+    }\r
+\r
+    public void deleteFilter(Filter filter) {\r
+        int id = filter.getId();\r
+        if (id != -1) {\r
+//            EFX10.alDeleteFilters(id);\r
+        }\r
+    }\r
+\r
+    public void deleteAudioData(AudioData ad) {\r
+//        if (ad instanceof AudioStream) {\r
+//            AudioStream as = (AudioStream) ad;\r
+//            int[] ids = as.getIds();\r
+//            for (int i=0; i<ids.length; i++) {\r
+//                logger.log(Level.INFO, "deleteAudioData for stream buffer: {0}", ids[i]);\r
+//            }\r
+//        } else if (ad instanceof AudioBuffer) {\r
+//            logger.log(Level.INFO, "deleteAudioData for buffer: {0}", ad.getId());\r
+//        }\r
+        synchronized (threadLock) {\r
+            while (!threadLock.get()) {\r
+                try {\r
+                    threadLock.wait();\r
+                } catch (InterruptedException ex) {\r
+                }\r
+            }\r
+            if (audioDisabled) {\r
+                return;\r
+            }\r
+\r
+            if (ad instanceof AudioBuffer) {\r
+                AudioBuffer ab = (AudioBuffer) ad;\r
+                int id = ab.getId();\r
+                if (id != -1) {\r
+                    ib.put(0, id);\r
+                    ib.position(0).limit(1);\r
+                    //alDeleteBuffers(ib);\r
+                    alDeleteBuffers(1, ib);\r
+                    checkError(true);\r
+                    ab.resetObject();\r
+                }\r
+            } else if (ad instanceof AudioStream) {\r
+                AudioStream as = (AudioStream) ad;\r
+                int[] ids = as.getIds();\r
+                if (ids != null) {\r
+                    ib.clear();\r
+                    ib.put(ids).flip();\r
+                    //alDeleteBuffers(ib);\r
+                    alDeleteBuffers(ids.length, ib);\r
+                    checkError(true);\r
+                    as.resetObject();\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    private int checkError(boolean stopOnError) {\r
+        int errorCode = alGetError();\r
+        String errorText = AL.GetALErrorMsg(errorCode);\r
+//        logger.log(Level.INFO, "alError Code: {0}, Description: {1}",\r
+//                new Object[]{errorCode, errorText});\r
+\r
+        if (errorCode != AL.AL_NO_ERROR && stopOnError) {\r
+            throw new IllegalStateException("AL Error Detected.  Error Code: " + errorCode + ": " + errorText);\r
+        }\r
+\r
+        return errorCode;\r
+    }\r
+\r
+    /** Native methods, implemented in jni folder */\r
+    public static native boolean alIsCreated();\r
+    public static native boolean alCreate();\r
+    public static native boolean alDestroy();\r
+    public static native String alcGetString(int parameter);\r
+    public static native String alGetString(int parameter);\r
+    public static native int alGenSources();\r
+    public static native int alGetError();\r
+    public static native void alDeleteSources(int numSources, IntBuffer sources);\r
+    public static native void alGenBuffers(int numBuffers, IntBuffer buffers);\r
+    public static native void alDeleteBuffers(int numBuffers, IntBuffer buffers);\r
+    public static native void alSourceStop(int source);\r
+    public static native void alSourcei(int source, int param, int value);\r
+    public static native void alBufferData(int buffer, int format, ByteBuffer data, int size, int frequency);\r
+    public static native void alSourcePlay(int source);\r
+    public static native void alSourcePause(int source);\r
+    public static native void alSourcef(int source, int param, float value);\r
+    public static native void alSource3f(int source, int param, float value1, float value2, float value3);\r
+    public static native int alGetSourcei(int source, int param);\r
+    public static native void alSourceUnqueueBuffers(int source, int numBuffers, IntBuffer buffers);\r
+    public static native void alSourceQueueBuffers(int source, int numBuffers, IntBuffer buffers);\r
+    public static native void alListener(int param, FloatBuffer data);\r
+    public static native void alListenerf(int param, float value);\r
+    public static native void alListener3f(int param, float value1, float value2, float value3);\r
+\r
+\r
+    /** Load jni .so on initialization */\r
+    static {\r
+         System.loadLibrary("openalsoftjme");\r
+    }\r
+\r
+\r
+}\r
diff --git a/engine/src/openal-soft-native/android/Android.mk b/engine/src/openal-soft-native/android/Android.mk
new file mode 100644 (file)
index 0000000..936bf3d
--- /dev/null
@@ -0,0 +1,55 @@
+TARGET_PLATFORM := android-9
+
+ROOT_PATH := $(call my-dir)
+
+########################################################################################################
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE     := openalsoftjme
+LOCAL_ARM_MODE   := arm
+LOCAL_PATH       := $(ROOT_PATH)
+LOCAL_C_INCLUDES := $(LOCAL_PATH) $(LOCAL_PATH)/include $(LOCAL_PATH)/OpenAL32/Include
+
+LOCAL_CFLAGS     := -ffast-math -DAL_BUILD_LIBRARY -DAL_ALEXT_PROTOTYPES
+LOCAL_LDLIBS     := -llog -Wl,-s
+LOCAL_LDLIBS    += -lOpenSLES
+#  LOCAL_CFLAGS +=   -DPOST_FROYO #-I$(ANDROID_NDK_ROOT)/platforms/android-9/arch-arm/usr/include/
+#  LOCAL_LDLIBS += -ldl -L$(ANDROID_NDK_ROOT)/platforms/android-9/arch-arm/usr/lib/
+
+LOCAL_SRC_FILES  := OpenAL32/alAuxEffectSlot.c \
+                    OpenAL32/alBuffer.c        \
+                    OpenAL32/alEffect.c        \
+                    OpenAL32/alError.c         \
+                    OpenAL32/alExtension.c     \
+                    OpenAL32/alFilter.c        \
+                    OpenAL32/alListener.c      \
+                    OpenAL32/alSource.c        \
+                    OpenAL32/alState.c         \
+                    OpenAL32/alThunk.c         \
+                    Alc/ALc.c                  \
+                    Alc/ALu.c                  \
+                    Alc/alcChorus.c            \
+                    Alc/alcConfig.c            \
+                    Alc/alcDedicated.c         \
+                    Alc/alcEcho.c              \
+                    Alc/alcFlanger.c           \
+                    Alc/alcModulator.c         \
+                    Alc/alcReverb.c            \
+                    Alc/alcRing.c              \
+                    Alc/alcThread.c            \
+                    Alc/bs2b.c                 \
+                    Alc/helpers.c              \
+                    Alc/panning.c              \
+                    Alc/hrtf.c                 \
+                    Alc/mixer.c                \
+                    Alc/mixer_c.c              \
+                    Alc/backends/loopback.c    \
+                    Alc/backends/null.c        \
+                    Alc/backends/opensl.c      \
+                    com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.cpp
+#                    Alc/backends/alsa.c        \
+#                    Alc/backends/android.c     \
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/engine/src/openal-soft-native/android/Application.mk b/engine/src/openal-soft-native/android/Application.mk
new file mode 100644 (file)
index 0000000..3deb526
--- /dev/null
@@ -0,0 +1,4 @@
+APP_OPTIM := release
+APP_ABI := all
+#APP_ABI := armeabi-v7a
+#APP_ABI += armeabi
diff --git a/engine/src/openal-soft-native/android/com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.cpp b/engine/src/openal-soft-native/android/com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.cpp
new file mode 100644 (file)
index 0000000..09fbd1d
--- /dev/null
@@ -0,0 +1,333 @@
+#include "com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.h"\r
+#include "AL/alc.h"\r
+#include "AL/al.h"\r
+#include "AL/alext.h"\r
+// for __android_log_print(ANDROID_LOG_INFO, "YourApp", "formatted message");\r
+#include <android/log.h>\r
+#include <jni.h>\r
+#include <stddef.h>\r
+#include <stdio.h>\r
+#include <assert.h>\r
+#include <string.h>\r
+#include <time.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+static jboolean created = JNI_FALSE;\r
+\r
+#define BUFFER_COUNT 1\r
+ALuint* buffers[BUFFER_COUNT] = { 0 };\r
+ALuint* source = 0;\r
+\r
+int getError() {\r
+    int errorcode = alGetError();\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "getError: %d", errorcode);\r
+    return errorcode;\r
+}\r
+\r
+/* InitAL opens the default device and sets up a context using default\r
+ * attributes, making the program ready to call OpenAL functions. */\r
+int InitAL()\r
+{\r
+    ALCdevice *device;\r
+    ALCcontext *ctx;\r
+\r
+    /* Open and initialize a device with default settings */\r
+    device = alcOpenDevice(NULL);\r
+    if(!device)\r
+    {\r
+        fprintf(stderr, "Could not open a device!\n");\r
+        return 1;\r
+    }\r
+\r
+    ctx = alcCreateContext(device, NULL);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "NULL: %d", NULL);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Created context: %d", ctx);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Created context addr: %d", &ctx);\r
+    if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)\r
+    {\r
+        if(ctx != NULL)\r
+            alcDestroyContext(ctx);\r
+        alcCloseDevice(device);\r
+        fprintf(stderr, "Could not set a context!\n");\r
+        return 1;\r
+    }\r
+\r
+    printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));\r
+    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Opened %s", alcGetString(device, ALC_DEVICE_SPECIFIER));\r
+    return 0;\r
+}\r
+\r
+/* CloseAL closes the device belonging to the current context, and destroys the\r
+ * context. */\r
+void CloseAL()\r
+{\r
+    ALCdevice *device;\r
+    ALCcontext *ctx;\r
+    ALCboolean result;\r
+\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Getting current context");\r
+    ctx = alcGetCurrentContext();\r
+//    getError();\r
+    if(ctx == NULL){\r
+        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "No context found");\r
+        return;\r
+    }\r
+\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Getting current context device");\r
+    device = alcGetContextsDevice(ctx);\r
+    if(device == NULL) {\r
+        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "No device found");\r
+        return;\r
+    } else {\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetContextsDevice device: %d", device);\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetContextsDevice device addr: %d", &device);\r
+    }\r
+//    getError();\r
+\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Setting context to NULL");\r
+    result = alcMakeContextCurrent(NULL);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcMakeContextCurrent returned");\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcMakeContextCurrent returned with result: %d", result);\r
+    if(!result) {\r
+        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcMakeContextCurrent failed");\r
+        return;\r
+    }\r
+\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Destroying context: %d", ctx);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Destroying context addr: %d", &ctx);\r
+    alcDestroyContext(ctx);\r
+\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Closing device");\r
+    result = alcCloseDevice(device);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcCloseDevice result: %d", result);\r
+}\r
+\r
+\r
+JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alIsCreated\r
+  (JNIEnv* env, jclass)\r
+{\r
+    return created;\r
+}\r
+\r
+\r
+JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alCreate\r
+  (JNIEnv* env, jclass)\r
+{\r
+    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "Starting Audio Engine");\r
+\r
+    InitAL();\r
+    created = JNI_TRUE;\r
+    return created;\r
+\r
+}\r
+\r
+JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDestroy\r
+  (JNIEnv* env, jclass)\r
+{\r
+\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDestroy");\r
+    CloseAL();\r
+    created = JNI_FALSE;\r
+    return created;\r
+\r
+}\r
+\r
+JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alcGetString\r
+  (JNIEnv* env, jclass, jint param)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetString for param: %d", param);\r
+\r
+    ALCdevice *device;\r
+    ALCcontext *ctx;\r
+\r
+    ctx = alcGetCurrentContext();\r
+    if(ctx != NULL) {\r
+        device = alcGetContextsDevice(ctx);\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alcGetString param value: %s", alcGetString(device, param));\r
+        return env->NewStringUTF(alcGetString(device, param));\r
+    }\r
+}\r
+\r
+JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetString\r
+  (JNIEnv* env, jclass, jint param)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGetString for param: %d", param);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGetString param value: %s", alGetString(param));\r
+    return env->NewStringUTF(alGetString(param));\r
+}\r
+\r
+JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenSources\r
+  (JNIEnv *, jclass)\r
+{\r
+    ALuint source;\r
+    alGenSources(1, &source);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGenSources: %d", source);\r
+    return source;\r
+}\r
+\r
+JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetError\r
+  (JNIEnv *, jclass)\r
+{\r
+    return getError();\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteSources\r
+  (JNIEnv* env, jclass, jint numSources, jobject intbufSources)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteSources numSources: %d", numSources);\r
+\r
+    ALuint* pIntBufSources = (ALuint*) env->GetDirectBufferAddress(intbufSources);\r
+    alDeleteSources((ALsizei)numSources, pIntBufSources);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenBuffers\r
+  (JNIEnv* env, jclass, jint numBuffers, jobject intbufBuffers)\r
+{\r
+    ALuint* pIntBufBuffers = (ALuint*) env->GetDirectBufferAddress(intbufBuffers);\r
+    alGenBuffers((ALsizei)numBuffers, pIntBufBuffers);\r
+//    for (int i=0; i<numBuffers; i++) {\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGenBuffers[%d]: %d", i, *(pIntBufBuffers+i));\r
+//    }\r
+\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteBuffers\r
+  (JNIEnv* env, jclass, jint numBuffers, jobject intbufBuffers)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteBuffers numBuffers: %d", numBuffers);\r
+\r
+    ALuint* pIntBufBuffers = (ALuint*) env->GetDirectBufferAddress(intbufBuffers);\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteBuffers Buffers: %d", *pIntBufBuffers);\r
+//    for (int i=0; i<numBuffers; i++) {\r
+//        if(alIsBuffer(*(pIntBufBuffers+i)) == AL_TRUE) {\r
+//            __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteBuffers[%d]: %d", i, *(pIntBufBuffers+i));\r
+//            __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alDeleteBuffers buffer is a known buffer");\r
+//        }\r
+//    }\r
+    alDeleteBuffers((ALsizei)numBuffers, pIntBufBuffers);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceStop\r
+  (JNIEnv *, jclass, jint source)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceStop for source: %d", source);\r
+    alSourceStop((ALuint)source);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcei\r
+  (JNIEnv *, jclass, jint source, jint param, jint value)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourcei for source: %d, param: %d, value: %d", source, param, value);\r
+    alSourcei((ALuint)source, (ALenum)param, (ALint)value);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alBufferData\r
+  (JNIEnv* env, jclass, jint buffer, jint format, jobject bufferData, jint bufferSize, jint frequency)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alBufferData for source: %d, format: %d, size: %d, frequency: %d", buffer, format, bufferSize, frequency);\r
+    ALuint* pBufferData = (ALuint*) env->GetDirectBufferAddress(bufferData);\r
+    alBufferData((ALuint)buffer, (ALenum)format, pBufferData, (ALsizei)bufferSize, (ALsizei)frequency);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcePlay\r
+  (JNIEnv *, jclass, jint source)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourcePlay for source: %d", source);\r
+    alSourcePlay((ALuint)source);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcePause\r
+  (JNIEnv *, jclass, jint source)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourcePause for source: %d", source);\r
+    alSourcePause((ALuint)source);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcef\r
+  (JNIEnv *, jclass, jint source, jint param, jfloat value)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourcef for source: %d, param: %d, value: %f", source, param, value);\r
+    alSourcef((ALuint)source, (ALenum)param, (ALfloat)value);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSource3f\r
+  (JNIEnv *, jclass, jint source, jint param, jfloat value1, jfloat value2, jfloat value3)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSource3f for source: %d, param: %d, value1: %f, value2: %f, value3: %f", source, param, value1, value2, value3);\r
+    alSource3f((ALuint)source, (ALenum)param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);\r
+}\r
+\r
+JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetSourcei\r
+  (JNIEnv *, jclass, jint source, jint param)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alGetSourcei for source: %d, param: %d", source, param);\r
+    ALint result;\r
+    alGetSourcei((ALuint)source, (ALenum)param, &result);\r
+    return (jint)result;\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceUnqueueBuffers\r
+  (JNIEnv* env, jclass, jint source, jint numBuffers, jobject buffers)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceUnqueueBuffers for source: %d, numBuffers: %d", source, numBuffers);\r
+    ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffers);\r
+\r
+//    for (ALuint i=0; i<numBuffers; i++) {\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceUnqueueBuffers, checking buffer[%d]: %d", i, *(pBuffers+i));\r
+//        ALboolean isBuffer = alIsBuffer(*(pBuffers+i));\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "buffer check result: %d", isBuffer);\r
+//    }\r
+    alSourceUnqueueBuffers((ALuint)source, (ALsizei)numBuffers, pBuffers);\r
+//    for (ALuint i=0; i<numBuffers; i++) {\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceUnqueueBuffers[%d]: %d", i, *(pBuffers+i));\r
+//    }\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceQueueBuffers\r
+  (JNIEnv* env, jclass, jint source, jint numBuffers, jobject buffers)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceQueueBuffers for source: %d, numBuffers: %d", source, numBuffers);\r
+    ALuint* pBuffers = (ALuint*) env->GetDirectBufferAddress(buffers);\r
+    alSourceQueueBuffers((ALuint)source, (ALsizei)numBuffers, pBuffers);\r
+//    for (ALuint i=0; i<numBuffers; i++) {\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alSourceQueueBuffers[%d]: %d", i, *(pBuffers+i));\r
+//    }\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListener\r
+  (JNIEnv* env, jclass, jint param, jobject bufferData)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alListener for param: %d", param);\r
+    ALfloat* pBufferData = (ALfloat*) env->GetDirectBufferAddress(bufferData);\r
+    alListenerfv((ALenum)param, pBufferData);\r
+//    getError();\r
+//    for (int i=0; i<4; i++) {\r
+//        __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alListener[%d]: %f", i, *(pBufferData+(i*sizeof(ALfloat))));\r
+//    }\r
+\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListenerf\r
+  (JNIEnv *, jclass, jint param, jfloat value)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alListenerf for param: %d, value: %f", param, value);\r
+    alListenerf((ALenum)param, (ALfloat)value);\r
+}\r
+\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListener3f\r
+  (JNIEnv *, jclass, jint param, jfloat value1, jfloat value2, jfloat value3)\r
+{\r
+//    __android_log_print(ANDROID_LOG_INFO, "OpenAL Soft", "alListener3f for param: %d, value1: %f, value2: %f, value3: %f", param, value1, value2, value3);\r
+    alListener3f((ALenum)param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3);\r
+}\r
+\r
+\r
+\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
diff --git a/engine/src/openal-soft-native/android/com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.h b/engine/src/openal-soft-native/android/com_jme3_audio_android_AndroidOpenALSoftAudioRenderer.h
new file mode 100644 (file)
index 0000000..3469f1d
--- /dev/null
@@ -0,0 +1,207 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>\r
+/* Header for class com_jme3_audio_android_AndroidOpenALSoftAudioRenderer */
+
+#ifndef _Included_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer
+#define _Included_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+#ifdef __cplusplus
+extern "C" {
+#endif\r
+/* Inaccessible static: logger */\r
+#undef com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_BUFFER_SIZE
+#define com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_BUFFER_SIZE 35280L\r
+#undef com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_STREAMING_BUFFER_COUNT
+#define com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_STREAMING_BUFFER_COUNT 5L\r
+#undef com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_MAX_NUM_CHANNELS
+#define com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_MAX_NUM_CHANNELS 64L\r
+#undef com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_UPDATE_RATE
+#define com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_UPDATE_RATE 0.05f\r
+/* Inaccessible static: _00024assertionsDisabled */\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alIsCreated\r
+ * Signature: ()Z\r
+ */\r
+JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alIsCreated\r
+  (JNIEnv *, jclass);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alCreate\r
+ * Signature: ()Z\r
+ */\r
+JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alCreate\r
+  (JNIEnv *, jclass);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alDestroy\r
+ * Signature: ()Z\r
+ */\r
+JNIEXPORT jboolean JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDestroy\r
+  (JNIEnv *, jclass);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alcGetString\r
+ * Signature: (I)Ljava/lang/String;\r
+ */\r
+JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alcGetString\r
+  (JNIEnv *, jclass, jint);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alGetString\r
+ * Signature: (I)Ljava/lang/String;\r
+ */\r
+JNIEXPORT jstring JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetString\r
+  (JNIEnv *, jclass, jint);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alGenSources\r
+ * Signature: ()I\r
+ */\r
+JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenSources\r
+  (JNIEnv *, jclass);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alGetError\r
+ * Signature: ()I\r
+ */\r
+JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetError\r
+  (JNIEnv *, jclass);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alDeleteSources\r
+ * Signature: (ILjava/nio/IntBuffer;)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteSources\r
+  (JNIEnv *, jclass, jint, jobject);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alGenBuffers\r
+ * Signature: (ILjava/nio/IntBuffer;)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGenBuffers\r
+  (JNIEnv *, jclass, jint, jobject);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alDeleteBuffers\r
+ * Signature: (ILjava/nio/IntBuffer;)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alDeleteBuffers\r
+  (JNIEnv *, jclass, jint, jobject);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alSourceStop\r
+ * Signature: (I)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceStop\r
+  (JNIEnv *, jclass, jint);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alSourcei\r
+ * Signature: (III)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcei\r
+  (JNIEnv *, jclass, jint, jint, jint);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alBufferData\r
+ * Signature: (IILjava/nio/ByteBuffer;II)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alBufferData\r
+  (JNIEnv *, jclass, jint, jint, jobject, jint, jint);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alSourcePlay\r
+ * Signature: (I)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcePlay\r
+  (JNIEnv *, jclass, jint);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alSourcePause\r
+ * Signature: (I)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcePause\r
+  (JNIEnv *, jclass, jint);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alSourcef\r
+ * Signature: (IIF)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourcef\r
+  (JNIEnv *, jclass, jint, jint, jfloat);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alSource3f\r
+ * Signature: (IIFFF)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSource3f\r
+  (JNIEnv *, jclass, jint, jint, jfloat, jfloat, jfloat);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alGetSourcei\r
+ * Signature: (II)I\r
+ */\r
+JNIEXPORT jint JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alGetSourcei\r
+  (JNIEnv *, jclass, jint, jint);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alSourceUnqueueBuffers\r
+ * Signature: (IILjava/nio/IntBuffer;)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceUnqueueBuffers\r
+  (JNIEnv *, jclass, jint, jint, jobject);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alSourceQueueBuffers\r
+ * Signature: (IILjava/nio/IntBuffer;)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alSourceQueueBuffers\r
+  (JNIEnv *, jclass, jint, jint, jobject);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alListener\r
+ * Signature: (ILjava/nio/FloatBuffer;)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListener\r
+  (JNIEnv *, jclass, jint, jobject);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alListenerf\r
+ * Signature: (IF)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListenerf\r
+  (JNIEnv *, jclass, jint, jfloat);
+\r
+/*\r
+ * Class:     com_jme3_audio_android_AndroidOpenALSoftAudioRenderer\r
+ * Method:    alListener3f\r
+ * Signature: (IFFF)V\r
+ */\r
+JNIEXPORT void JNICALL Java_com_jme3_audio_android_AndroidOpenALSoftAudioRenderer_alListener3f\r
+  (JNIEnv *, jclass, jint, jfloat, jfloat, jfloat);
+\r
+#ifdef __cplusplus
+}
+#endif\r
+#endif\r
diff --git a/engine/src/openal-soft-native/android/config.h b/engine/src/openal-soft-native/android/config.h
new file mode 100644 (file)
index 0000000..bf3ee85
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef CONFIG_H
+#define CONFIG_H
+
+/* Define to the library version */
+#define ALSOFT_VERSION "1.15.1"
+
+#define ALIGN(x) __attribute__  ((aligned(x)))
+
+/* Define if we have the Android backend */
+/* #define HAVE_ANDROID 1 */
+
+/* Define if we have the ALSA backend */
+/* #define HAVE_ALSA */
+
+/* Define if we have the OSS backend */
+/* #cmakedefine HAVE_OSS */
+
+/* Define if we have the Solaris backend */
+/* #cmakedefine HAVE_SOLARIS */
+
+/* Define if we have the SndIO backend */
+/* #cmakedefine HAVE_SNDIO */
+
+/* Define if we have the MMDevApi backend */
+/* #cmakedefine HAVE_MMDEVAPI */
+
+/* Define if we have the DSound backend */
+/* #cmakedefine HAVE_DSOUND */
+
+/* Define if we have the Windows Multimedia backend */
+/* #cmakedefine HAVE_WINMM */
+
+/* Define if we have the PortAudio backend */
+/* #cmakedefine HAVE_PORTAUDIO */
+
+/* Define if we have the PulseAudio backend */
+/* #cmakedefine HAVE_PULSEAUDIO */
+
+/* Define if we have the CoreAudio backend */
+/* #cmakedefine HAVE_COREAUDIO */
+
+/* Define if we have the OpenSL backend */
+#define HAVE_OPENSL /* THIS BACKEND WORKS ON >=2.3 Android!! */
+
+/* Define if we have the Wave Writer backend */
+/* #cmakedefine HAVE_WAVE */
+
+/* Define if we have dlfcn.h */
+#define HAVE_DLFCN_H
+
+/* Define if we have the stat function */
+#define HAVE_STAT
+
+/* Define if we have the powf function */
+/* #define HAVE_POWF 1 */
+
+/* Define if we have the sqrtf function */
+/* #define HAVE_SQRTF 1 */
+
+/* Define if we have the cosf function */
+/* #define HAVE_COSF 1 */
+
+/* Define if we have the sinf function */
+/* #define HAVE_SINF 1 */
+
+/* Define if we have the acosf function */
+/* #define HAVE_ACOSF 1 */
+
+/* Define if we have the asinf function */
+/* #define  HAVE_ASINF 1 */
+
+/* Define if we have the atanf function */
+/* #define HAVE_ATANF 1 */
+
+/* Define if we have the atan2f function */
+/* #define HAVE_ATAN2F 1 */
+
+/* Define if we have the fabsf function */
+/* #define HAVE_FABSF 1 */
+
+/* Define if we have the log10f function */
+/* #define HAVE_LOG10F 1 */
+
+/* Define if we have the floorf function */
+/* #define HAVE_FLOORF 1 */
+
+/* Define if we have the strtof function */
+#define HAVE_STRTOF
+
+/* Define if we have stdint.h */
+#define HAVE_STDINT_H
+
+/* Define if we have the __int64 type */
+/* #cmakedefine HAVE___INT64 */
+
+/* Define to the size of a long int type */
+#define SIZEOF_LONG 4
+
+/* Define to the size of a long long int type */
+#define SIZEOF_LONG_LONG 8
+
+/* Define if we have GCC's destructor attribute */
+#define HAVE_GCC_DESTRUCTOR
+
+/* Define if we have GCC's format attribute */
+#define HAVE_GCC_FORMAT
+
+/* Define if we have pthread_np.h */
+/* #cmakedefine HAVE_PTHREAD_NP_H */
+
+/* Define if we have arm_neon.h */
+/* #cmakedefine HAVE_ARM_NEON_H */
+
+/* Define if we have guiddef.h */
+/* #cmakedefine HAVE_GUIDDEF_H */
+
+/* Define if we have guiddef.h */
+/* #cmakedefine HAVE_INITGUID_H */
+
+/* Define if we have ieeefp.h */
+/* #cmakedefine HAVE_IEEEFP_H */
+
+/* Define if we have float.h */
+/* #cmakedefine HAVE_FLOAT_H */
+
+/* Define if we have fpu_control.h */
+/* #cmakedefine HAVE_FPU_CONTROL_H */
+
+/* Define if we have fenv.h */
+#define HAVE_FENV_H
+
+/* Define if we have fesetround() */
+/* #cmakedefine HAVE_FESETROUND */
+
+/* Define if we have _controlfp() */
+/* #cmakedefine HAVE__CONTROLFP */
+
+/* Define if we have pthread_setschedparam() */
+#define HAVE_PTHREAD_SETSCHEDPARAM
+
+/* Define if we have the restrict keyword */
+/* #cmakedefine  HAVE_RESTRICT 1 */
+
+/* Define if we have the __restrict keyword */
+#define RESTRICT __restrict
+
+#endif