Browse Source

updated OpenAL-Soft to version 1.16.0

fysx 11 years ago
parent
commit
70eef137ae
100 changed files with 10012 additions and 4154 deletions
  1. 4 3
      jni/love/Android.mk
  2. 428 282
      jni/openal-soft-1.16.0/Alc/ALc.c
  3. 370 309
      jni/openal-soft-1.16.0/Alc/ALu.c
  4. 174 45
      jni/openal-soft-1.16.0/Alc/alcConfig.c
  5. 10 9
      jni/openal-soft-1.16.0/Alc/alcRing.c
  6. 45 0
      jni/openal-soft-1.16.0/Alc/alstring.h
  7. 116 147
      jni/openal-soft-1.16.0/Alc/backends/alsa.c
  8. 40 38
      jni/openal-soft-1.16.0/Alc/backends/base.c
  9. 9 9
      jni/openal-soft-1.16.0/Alc/backends/base.h
  10. 4 1
      jni/openal-soft-1.16.0/Alc/backends/coreaudio.c
  11. 388 370
      jni/openal-soft-1.16.0/Alc/backends/dsound.c
  12. 12 14
      jni/openal-soft-1.16.0/Alc/backends/loopback.c
  13. 615 337
      jni/openal-soft-1.16.0/Alc/backends/mmdevapi.c
  14. 48 42
      jni/openal-soft-1.16.0/Alc/backends/null.c
  15. 21 74
      jni/openal-soft-1.16.0/Alc/backends/opensl.c
  16. 29 35
      jni/openal-soft-1.16.0/Alc/backends/oss.c
  17. 6 3
      jni/openal-soft-1.16.0/Alc/backends/portaudio.c
  18. 175 186
      jni/openal-soft-1.16.0/Alc/backends/pulseaudio.c
  19. 26 34
      jni/openal-soft-1.16.0/Alc/backends/qsa.c
  20. 9 9
      jni/openal-soft-1.16.0/Alc/backends/sndio.c
  21. 10 10
      jni/openal-soft-1.16.0/Alc/backends/solaris.c
  22. 44 39
      jni/openal-soft-1.16.0/Alc/backends/wave.c
  23. 138 191
      jni/openal-soft-1.16.0/Alc/backends/winmm.c
  24. 37 79
      jni/openal-soft-1.16.0/Alc/bs2b.c
  25. 32 0
      jni/openal-soft-1.16.0/Alc/compat.h
  26. 12 15
      jni/openal-soft-1.16.0/Alc/effects/autowah.c
  27. 29 13
      jni/openal-soft-1.16.0/Alc/effects/chorus.c
  28. 4 7
      jni/openal-soft-1.16.0/Alc/effects/compressor.c
  29. 2 5
      jni/openal-soft-1.16.0/Alc/effects/dedicated.c
  30. 2 5
      jni/openal-soft-1.16.0/Alc/effects/distortion.c
  31. 3 6
      jni/openal-soft-1.16.0/Alc/effects/echo.c
  32. 2 5
      jni/openal-soft-1.16.0/Alc/effects/equalizer.c
  33. 29 13
      jni/openal-soft-1.16.0/Alc/effects/flanger.c
  34. 2 5
      jni/openal-soft-1.16.0/Alc/effects/modulator.c
  35. 14 4
      jni/openal-soft-1.16.0/Alc/effects/null.c
  36. 3 6
      jni/openal-soft-1.16.0/Alc/effects/reverb.c
  37. 0 0
      jni/openal-soft-1.16.0/Alc/evtqueue.h
  38. 814 0
      jni/openal-soft-1.16.0/Alc/helpers.c
  39. 138 146
      jni/openal-soft-1.16.0/Alc/hrtf.c
  40. 28 0
      jni/openal-soft-1.16.0/Alc/hrtf.h
  41. 19 53
      jni/openal-soft-1.16.0/Alc/midi/base.c
  42. 20 15
      jni/openal-soft-1.16.0/Alc/midi/base.h
  43. 9 28
      jni/openal-soft-1.16.0/Alc/midi/dummy.c
  44. 167 80
      jni/openal-soft-1.16.0/Alc/midi/fluidsynth.c
  45. 234 301
      jni/openal-soft-1.16.0/Alc/midi/sf2load.c
  46. 140 0
      jni/openal-soft-1.16.0/Alc/midi/soft.c
  47. 188 99
      jni/openal-soft-1.16.0/Alc/mixer.c
  48. 52 51
      jni/openal-soft-1.16.0/Alc/mixer_c.c
  49. 65 0
      jni/openal-soft-1.16.0/Alc/mixer_defs.h
  50. 93 0
      jni/openal-soft-1.16.0/Alc/mixer_inc.c
  51. 118 0
      jni/openal-soft-1.16.0/Alc/mixer_neon.c
  52. 202 0
      jni/openal-soft-1.16.0/Alc/mixer_sse.c
  53. 78 0
      jni/openal-soft-1.16.0/Alc/mixer_sse2.c
  54. 82 0
      jni/openal-soft-1.16.0/Alc/mixer_sse41.c
  55. 0 0
      jni/openal-soft-1.16.0/Alc/panning.c
  56. 87 0
      jni/openal-soft-1.16.0/Alc/vector.h
  57. 4 1
      jni/openal-soft-1.16.0/Android.mk
  58. 451 239
      jni/openal-soft-1.16.0/CMakeLists.txt
  59. 0 0
      jni/openal-soft-1.16.0/COPYING
  60. 7 7
      jni/openal-soft-1.16.0/OpenAL32/Include/alAuxEffectSlot.h
  61. 14 4
      jni/openal-soft-1.16.0/OpenAL32/Include/alBuffer.h
  62. 0 0
      jni/openal-soft-1.16.0/OpenAL32/Include/alEffect.h
  63. 0 0
      jni/openal-soft-1.16.0/OpenAL32/Include/alError.h
  64. 16 10
      jni/openal-soft-1.16.0/OpenAL32/Include/alFilter.h
  65. 0 0
      jni/openal-soft-1.16.0/OpenAL32/Include/alListener.h
  66. 155 113
      jni/openal-soft-1.16.0/OpenAL32/Include/alMain.h
  67. 22 16
      jni/openal-soft-1.16.0/OpenAL32/Include/alMidi.h
  68. 32 78
      jni/openal-soft-1.16.0/OpenAL32/Include/alSource.h
  69. 0 0
      jni/openal-soft-1.16.0/OpenAL32/Include/alThunk.h
  70. 99 20
      jni/openal-soft-1.16.0/OpenAL32/Include/alu.h
  71. 36 14
      jni/openal-soft-1.16.0/OpenAL32/Include/bs2b.h
  72. 9 0
      jni/openal-soft-1.16.0/OpenAL32/Include/sample_cvt.h
  73. 35 51
      jni/openal-soft-1.16.0/OpenAL32/alAuxEffectSlot.c
  74. 1329 0
      jni/openal-soft-1.16.0/OpenAL32/alBuffer.c
  75. 0 0
      jni/openal-soft-1.16.0/OpenAL32/alEffect.c
  76. 3 2
      jni/openal-soft-1.16.0/OpenAL32/alError.c
  77. 2 0
      jni/openal-soft-1.16.0/OpenAL32/alExtension.c
  78. 183 40
      jni/openal-soft-1.16.0/OpenAL32/alFilter.c
  79. 70 34
      jni/openal-soft-1.16.0/OpenAL32/alFontsound.c
  80. 5 5
      jni/openal-soft-1.16.0/OpenAL32/alListener.c
  81. 7 11
      jni/openal-soft-1.16.0/OpenAL32/alMidi.c
  82. 10 11
      jni/openal-soft-1.16.0/OpenAL32/alPreset.c
  83. 62 171
      jni/openal-soft-1.16.0/OpenAL32/alSoundfont.c
  84. 321 155
      jni/openal-soft-1.16.0/OpenAL32/alSource.c
  85. 24 16
      jni/openal-soft-1.16.0/OpenAL32/alState.c
  86. 0 0
      jni/openal-soft-1.16.0/OpenAL32/alThunk.c
  87. 1269 0
      jni/openal-soft-1.16.0/OpenAL32/sample_cvt.c
  88. 0 0
      jni/openal-soft-1.16.0/README
  89. 0 0
      jni/openal-soft-1.16.0/XCompile.txt
  90. 50 27
      jni/openal-soft-1.16.0/alsoftrc.sample
  91. 0 0
      jni/openal-soft-1.16.0/build/.empty
  92. 9 0
      jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.c
  93. 39 0
      jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.cmake
  94. 0 0
      jni/openal-soft-1.16.0/cmake/CheckSharedFunctionExists.cmake
  95. 73 0
      jni/openal-soft-1.16.0/cmake/FindALSA.cmake
  96. 21 0
      jni/openal-soft-1.16.0/cmake/FindAudioIO.cmake
  97. 33 0
      jni/openal-soft-1.16.0/cmake/FindDSound.cmake
  98. 173 0
      jni/openal-soft-1.16.0/cmake/FindFFmpeg.cmake
  99. 2 6
      jni/openal-soft-1.16.0/cmake/FindFluidSynth.cmake
  100. 21 0
      jni/openal-soft-1.16.0/cmake/FindOSS.cmake

+ 4 - 3
jni/love/Android.mk

@@ -6,7 +6,8 @@ include $(CLEAR_VARS)
 LOCAL_MODULE    := liblove
 LOCAL_CFLAGS    := -fexceptions -g -Dlinux -Dunix \
 	-DHAVE_GCC_DESTRUCTOR=1 -DOPT_GENERIC -DREAL_IS_FLOAT \
-	-DGL_GLEXT_PROTOTYPES -DLOVE_TURBO_JPEG -DLOVE_NO_DEVIL
+	-DGL_GLEXT_PROTOTYPES -DLOVE_TURBO_JPEG -DLOVE_NO_DEVIL \
+	-DAL_ALEXT_PROTOTYPES
 
 LOCAL_CPPFLAGS  := ${LOCAL_CFLAGS} 
 
@@ -21,8 +22,8 @@ LOCAL_C_INCLUDES  :=  \
 	${LOCAL_PATH}/../libjpeg-turbo-1.3.1/ \
 	${LOCAL_PATH}/../lcms2-2.5/include \
 	${LOCAL_PATH}/../tiff-3.9.5/libtiff \
-	${LOCAL_PATH}/../openal-soft-android/include \
-	${LOCAL_PATH}/../openal-soft-android/OpenAL32/Include \
+	${LOCAL_PATH}/../openal-soft-1.16.0/include \
+	${LOCAL_PATH}/../openal-soft-1.16.0/OpenAL32/Include \
 	${LOCAL_PATH}/../freetype2-android/include \
 	${LOCAL_PATH}/../freetype2-android/src \
 	${LOCAL_PATH}/../physfs-2.1.0/src \

File diff suppressed because it is too large
+ 428 - 282
jni/openal-soft-1.16.0/Alc/ALc.c


File diff suppressed because it is too large
+ 370 - 309
jni/openal-soft-1.16.0/Alc/ALu.c


+ 174 - 45
jni/openal-soft-android/Alc/alcConfig.c → jni/openal-soft-1.16.0/Alc/alcConfig.c

@@ -32,13 +32,14 @@
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
-
-#include "alMain.h"
-
 #ifdef _WIN32_IE
 #include <shlobj.h>
 #endif
 
+#include "alMain.h"
+#include "compat.h"
+
+
 typedef struct ConfigEntry {
     char *key;
     char *value;
@@ -48,10 +49,8 @@ typedef struct ConfigBlock {
     ConfigEntry *entries;
     unsigned int entryCount;
 } ConfigBlock;
-
 static ConfigBlock cfgBlock;
 
-static char buffer[1024];
 
 static char *lstrip(char *line)
 {
@@ -69,23 +68,132 @@ static char *rstrip(char *line)
     return line;
 }
 
+static int readline(FILE *f, char **output, size_t *maxlen)
+{
+    size_t len = 0;
+    int c;
+
+    while((c=fgetc(f)) != EOF && (c == '\r' || c == '\n'))
+        ;
+    if(c == EOF)
+        return 0;
+
+    do {
+        if(len+1 >= *maxlen)
+        {
+            void *temp = NULL;
+            size_t newmax;
+
+            newmax = (*maxlen ? (*maxlen)<<1 : 32);
+            if(newmax > *maxlen)
+                temp = realloc(*output, newmax);
+            if(!temp)
+            {
+                ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, *maxlen);
+                return 0;
+            }
+
+            *output = temp;
+            *maxlen = newmax;
+        }
+        (*output)[len++] = c;
+        (*output)[len] = '\0';
+    } while((c=fgetc(f)) != EOF && c != '\r' && c != '\n');
+
+    return 1;
+}
+
+
+static char *expdup(const char *str)
+{
+    char *output = NULL;
+    size_t maxlen = 0;
+    size_t len = 0;
+
+    while(*str != '\0')
+    {
+        const char *addstr;
+        size_t addstrlen;
+        size_t i;
+
+        if(str[0] != '$')
+        {
+            const char *next = strchr(str, '$');
+            addstr = str;
+            addstrlen = next ? (size_t)(next-str) : strlen(str);
+
+            str += addstrlen;
+        }
+        else
+        {
+            str++;
+            if(*str == '$')
+            {
+                const char *next = strchr(str+1, '$');
+                addstr = str;
+                addstrlen = next ? (size_t)(next-str) : strlen(str);
+
+                str += addstrlen;
+            }
+            else
+            {
+                char envname[1024];
+                size_t k = 0;
+
+                while((isalnum(*str) || *str == '_') && k < sizeof(envname)-1)
+                    envname[k++] = *(str++);
+                envname[k++] = '\0';
+
+                if((addstr=getenv(envname)) == NULL)
+                    continue;
+                addstrlen = strlen(addstr);
+            }
+        }
+        if(addstrlen == 0)
+            continue;
+
+        if(addstrlen >= maxlen-len)
+        {
+            void *temp = NULL;
+            size_t newmax;
+
+            newmax = len+addstrlen+1;
+            if(newmax > maxlen)
+                temp = realloc(output, newmax);
+            if(!temp)
+            {
+                ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, maxlen);
+                return output;
+            }
+
+            output = temp;
+            maxlen = newmax;
+        }
+
+        for(i = 0;i < addstrlen;i++)
+            output[len++] = addstr[i];
+        output[len] = '\0';
+    }
+
+    return output ? output : calloc(1, 1);
+}
+
+
 static void LoadConfigFromFile(FILE *f)
 {
     char curSection[128] = "";
+    char *buffer = NULL;
+    size_t maxlen = 0;
     ConfigEntry *ent;
 
-    while(fgets(buffer, sizeof(buffer), f))
+    while(readline(f, &buffer, &maxlen))
     {
         char *line, *comment;
         char key[256] = "";
         char value[256] = "";
 
         comment = strchr(buffer, '#');
-        if(comment)
-        {
-            *(comment++) = 0;
-            comment = rstrip(lstrip(comment));
-        }
+        if(comment) *(comment++) = 0;
 
         line = rstrip(lstrip(buffer));
         if(!line[0])
@@ -123,26 +231,26 @@ static void LoadConfigFromFile(FILE *f)
              * manually. */
             if(strcmp(value, "\"\"") == 0 || strcmp(value, "''") == 0)
                 value[0] = 0;
-         }
-         else if(sscanf(line, "%255[^=] %255[=]", key, value) == 2)
-         {
-             /* Special case for 'key =' */
-             value[0] = 0;
-         }
-         else
-         {
-             ERR("config parse error: malformed option line: \"%s\"\n\n", line);
-             continue;
-         }
-         rstrip(key);
-
-         if(curSection[0] != 0)
-         {
-             size_t len = strlen(curSection);
-             memmove(&key[len+1], key, sizeof(key)-1-len);
-             key[len] = '/';
-             memcpy(key, curSection, len);
-         }
+        }
+        else if(sscanf(line, "%255[^=] %255[=]", key, value) == 2)
+        {
+            /* Special case for 'key =' */
+            value[0] = 0;
+        }
+        else
+        {
+            ERR("config parse error: malformed option line: \"%s\"\n\n", line);
+            continue;
+        }
+        rstrip(key);
+
+        if(curSection[0] != 0)
+        {
+            size_t len = strlen(curSection);
+            memmove(&key[len+1], key, sizeof(key)-1-len);
+            key[len] = '/';
+            memcpy(key, curSection, len);
+        }
 
         /* Check if we already have this option set */
         ent = cfgBlock.entries;
@@ -171,36 +279,57 @@ static void LoadConfigFromFile(FILE *f)
         }
 
         free(ent->value);
-        ent->value = strdup(value);
+        ent->value = expdup(value);
 
         TRACE("found '%s' = '%s'\n", ent->key, ent->value);
     }
+
+    free(buffer);
 }
 
+#ifdef _WIN32
 void ReadALConfig(void)
 {
-    const char *str;
+    WCHAR buffer[PATH_MAX];
+    const WCHAR *str;
     FILE *f;
 
-#ifdef _WIN32
-    if(SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE)
+    if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE)
     {
-        size_t p = strlen(buffer);
-        snprintf(buffer+p, sizeof(buffer)-p, "\\alsoft.ini");
+        size_t p = lstrlenW(buffer);
+        _snwprintf(buffer+p, PATH_MAX-p, L"\\alsoft.ini");
 
-        TRACE("Loading config %s...\n", buffer);
-        f = fopen(buffer, "rt");
+        TRACE("Loading config %ls...\n", buffer);
+        f = _wfopen(buffer, L"rt");
         if(f)
         {
             LoadConfigFromFile(f);
             fclose(f);
         }
     }
+
+    if((str=_wgetenv(L"ALSOFT_CONF")) != NULL && *str)
+    {
+        TRACE("Loading config %ls...\n", str);
+        f = _wfopen(str, L"rt");
+        if(f)
+        {
+            LoadConfigFromFile(f);
+            fclose(f);
+        }
+    }
+}
 #else
+void ReadALConfig(void)
+{
+    char buffer[PATH_MAX];
+    const char *str;
+    FILE *f;
+
     str = "/etc/openal/alsoft.conf";
 
     TRACE("Loading config %s...\n", str);
-    f = fopen(str, "r");
+    f = al_fopen(str, "r");
     if(f)
     {
         LoadConfigFromFile(f);
@@ -231,7 +360,7 @@ void ReadALConfig(void)
             buffer[sizeof(buffer)-1] = 0;
 
             TRACE("Loading config %s...\n", next);
-            f = fopen(next, "r");
+            f = al_fopen(next, "r");
             if(f)
             {
                 LoadConfigFromFile(f);
@@ -247,7 +376,7 @@ void ReadALConfig(void)
         snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str);
 
         TRACE("Loading config %s...\n", buffer);
-        f = fopen(buffer, "r");
+        f = al_fopen(buffer, "r");
         if(f)
         {
             LoadConfigFromFile(f);
@@ -266,19 +395,18 @@ void ReadALConfig(void)
     if(buffer[0] != 0)
     {
         TRACE("Loading config %s...\n", buffer);
-        f = fopen(buffer, "r");
+        f = al_fopen(buffer, "r");
         if(f)
         {
             LoadConfigFromFile(f);
             fclose(f);
         }
     }
-#endif
 
     if((str=getenv("ALSOFT_CONF")) != NULL && *str)
     {
         TRACE("Loading config %s...\n", str);
-        f = fopen(str, "r");
+        f = al_fopen(str, "r");
         if(f)
         {
             LoadConfigFromFile(f);
@@ -286,6 +414,7 @@ void ReadALConfig(void)
         }
     }
 }
+#endif
 
 void FreeALConfig(void)
 {

+ 10 - 9
jni/openal-soft-android/Alc/alcRing.c → jni/openal-soft-1.16.0/Alc/alcRing.c

@@ -24,6 +24,7 @@
 #include <stdlib.h>
 
 #include "alMain.h"
+#include "threads.h"
 #include "compat.h"
 
 
@@ -35,7 +36,7 @@ struct RingBuffer {
     ALint read_pos;
     ALint write_pos;
 
-    CRITICAL_SECTION cs;
+    almtx_t mtx;
 };
 
 
@@ -51,7 +52,7 @@ RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length)
         ring->read_pos = 0;
         ring->write_pos = 0;
 
-        InitializeCriticalSection(&ring->cs);
+        almtx_init(&ring->mtx, almtx_plain);
     }
     return ring;
 }
@@ -60,7 +61,7 @@ void DestroyRingBuffer(RingBuffer *ring)
 {
     if(ring)
     {
-        DeleteCriticalSection(&ring->cs);
+        almtx_destroy(&ring->mtx);
         free(ring);
     }
 }
@@ -69,9 +70,9 @@ ALsizei RingBufferSize(RingBuffer *ring)
 {
     ALsizei s;
 
-    EnterCriticalSection(&ring->cs);
+    almtx_lock(&ring->mtx);
     s = (ring->write_pos-ring->read_pos+ring->length) % ring->length;
-    LeaveCriticalSection(&ring->cs);
+    almtx_unlock(&ring->mtx);
 
     return s;
 }
@@ -80,7 +81,7 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
 {
     int remain;
 
-    EnterCriticalSection(&ring->cs);
+    almtx_lock(&ring->mtx);
 
     remain = (ring->read_pos-ring->write_pos-1+ring->length) % ring->length;
     if(remain < len) len = remain;
@@ -103,14 +104,14 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
         ring->write_pos %= ring->length;
     }
 
-    LeaveCriticalSection(&ring->cs);
+    almtx_unlock(&ring->mtx);
 }
 
 void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
 {
     int remain;
 
-    EnterCriticalSection(&ring->cs);
+    almtx_lock(&ring->mtx);
 
     remain = ring->length - ring->read_pos;
     if(remain < len)
@@ -124,5 +125,5 @@ void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
     ring->read_pos += len;
     ring->read_pos %= ring->length;
 
-    LeaveCriticalSection(&ring->cs);
+    almtx_unlock(&ring->mtx);
 }

+ 45 - 0
jni/openal-soft-1.16.0/Alc/alstring.h

@@ -0,0 +1,45 @@
+#ifndef ALSTRING_H
+#define ALSTRING_H
+
+#include <string.h>
+
+#include "vector.h"
+
+
+typedef char al_string_char_type;
+TYPEDEF_VECTOR(al_string_char_type, al_string)
+
+inline void al_string_deinit(al_string *str)
+{ VECTOR_DEINIT(*str); }
+#define AL_STRING_INIT(_x)       do { (_x) = (al_string)NULL; } while(0)
+#define AL_STRING_INIT_STATIC()  ((al_string)NULL)
+#define AL_STRING_DEINIT(_x)     al_string_deinit(&(_x))
+
+inline ALsizei al_string_length(const_al_string str)
+{ return VECTOR_SIZE(str); }
+
+inline ALboolean al_string_empty(const_al_string str)
+{ return al_string_length(str) == 0; }
+
+inline const al_string_char_type *al_string_get_cstr(const_al_string str)
+{ return str ? &VECTOR_FRONT(str) : ""; }
+
+void al_string_clear(al_string *str);
+
+int al_string_cmp(const_al_string str1, const_al_string str2);
+int al_string_cmp_cstr(const_al_string str1, const al_string_char_type *str2);
+
+void al_string_copy(al_string *str, const_al_string from);
+void al_string_copy_cstr(al_string *str, const al_string_char_type *from);
+
+void al_string_append_char(al_string *str, const al_string_char_type c);
+void al_string_append_cstr(al_string *str, const al_string_char_type *from);
+void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to);
+
+#ifdef _WIN32
+#include <wchar.h>
+/* Windows-only methods to deal with WideChar strings. */
+void al_string_copy_wcstr(al_string *str, const wchar_t *from);
+#endif
+
+#endif /* ALSTRING_H */

+ 116 - 147
jni/openal-soft-android/Alc/backends/alsa.c → jni/openal-soft-1.16.0/Alc/backends/alsa.c

@@ -227,14 +227,27 @@ static ALCboolean alsa_load(void)
 
 
 typedef struct {
-    ALCchar *name;
-    char *device;
+    al_string name;
+    al_string device_name;
 } DevMap;
+TYPEDEF_VECTOR(DevMap, vector_DevMap)
 
-static DevMap *allDevNameMap;
-static ALuint numDevNames;
-static DevMap *allCaptureDevNameMap;
-static ALuint numCaptureDevNames;
+static vector_DevMap PlaybackDevices;
+static vector_DevMap CaptureDevices;
+
+static void clear_devlist(vector_DevMap *devlist)
+{
+    DevMap *iter, *end;
+
+    iter = VECTOR_ITER_BEGIN(*devlist);
+    end = VECTOR_ITER_END(*devlist);
+    for(;iter != end;iter++)
+    {
+        AL_STRING_DEINIT(iter->name);
+        AL_STRING_DEINIT(iter->device_name);
+    }
+    VECTOR_RESIZE(*devlist, 0);
+}
 
 
 static const char *prefix_name(snd_pcm_stream_t stream)
@@ -243,23 +256,26 @@ static const char *prefix_name(snd_pcm_stream_t stream)
     return (stream==SND_PCM_STREAM_PLAYBACK) ? "device-prefix" : "capture-prefix";
 }
 
-static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count)
+static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
 {
     const char *main_prefix = "plughw:";
     snd_ctl_t *handle;
-    int card, err, dev, idx;
     snd_ctl_card_info_t *info;
     snd_pcm_info_t *pcminfo;
-    DevMap *DevList;
+    int card, err, dev;
+    DevMap entry;
+
+    clear_devlist(DeviceList);
 
     snd_ctl_card_info_malloc(&info);
     snd_pcm_info_malloc(&pcminfo);
 
-    DevList = malloc(sizeof(DevMap) * 1);
-    DevList[0].name = strdup(alsaDevice);
-    DevList[0].device = strdup(GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
-                                                      "device" : "capture", "default"));
-    idx = 1;
+    AL_STRING_INIT(entry.name);
+    AL_STRING_INIT(entry.device_name);
+    al_string_copy_cstr(&entry.name, alsaDevice);
+    al_string_copy_cstr(&entry.device_name, GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
+                                                           "device" : "capture", "default"));
+    VECTOR_PUSH_BACK(*DeviceList, entry);
 
     card = -1;
     if((err=snd_card_next(&card)) < 0)
@@ -293,8 +309,9 @@ static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count)
         dev = -1;
         while(1)
         {
+            const char *device_prefix = card_prefix;
             const char *devname;
-            void *temp;
+            char device[128];
 
             if(snd_ctl_pcm_next_device(handle, &dev) < 0)
                 ERR("snd_ctl_pcm_next_device failed\n");
@@ -310,28 +327,22 @@ static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count)
                 continue;
             }
 
-            temp = realloc(DevList, sizeof(DevMap) * (idx+1));
-            if(temp)
-            {
-                const char *device_prefix = card_prefix;
-                char device[128];
+            devname = snd_pcm_info_get_name(pcminfo);
 
-                DevList = temp;
-                devname = snd_pcm_info_get_name(pcminfo);
+            snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
+            ConfigValueStr("alsa", name, &device_prefix);
 
-                snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
-                ConfigValueStr("alsa", name, &device_prefix);
+            snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
+                        cardname, devname, cardid, dev);
+            snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d",
+                        device_prefix, cardid, dev);
 
-                snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
-                         cardname, devname, cardid, dev);
-                snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d",
-                         device_prefix, cardid, dev);
-
-                TRACE("Got device \"%s\", \"%s\"\n", name, device);
-                DevList[idx].name = strdup(name);
-                DevList[idx].device = strdup(device);
-                idx++;
-            }
+            TRACE("Got device \"%s\", \"%s\"\n", name, device);
+            AL_STRING_INIT(entry.name);
+            AL_STRING_INIT(entry.device_name);
+            al_string_copy_cstr(&entry.name, name);
+            al_string_copy_cstr(&entry.device_name, device);
+            VECTOR_PUSH_BACK(*DeviceList, entry);
         }
         snd_ctl_close(handle);
     next_card:
@@ -343,9 +354,6 @@ static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count)
 
     snd_pcm_info_free(pcminfo);
     snd_ctl_card_info_free(info);
-
-    *count = idx;
-    return DevList;
 }
 
 
@@ -390,12 +398,11 @@ typedef struct ALCplaybackAlsa {
     ALsizei size;
 
     volatile int killNow;
-    althread_t thread;
+    althrd_t thread;
 } ALCplaybackAlsa;
-DECLARE_ALCBACKEND_VTABLE(ALCplaybackAlsa);
 
-static ALuint ALCplaybackAlsa_mixerProc(ALvoid *ptr);
-static ALuint ALCplaybackAlsa_mixerNoMMapProc(ALvoid *ptr);
+static int ALCplaybackAlsa_mixerProc(void *ptr);
+static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr);
 
 static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device);
 static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, Destruct)
@@ -406,8 +413,12 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self);
 static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self);
 static DECLARE_FORWARD2(ALCplaybackAlsa, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
 static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, ALCuint, availableSamples)
+static ALint64 ALCplaybackAlsa_getLatency(ALCplaybackAlsa *self);
 static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCplaybackAlsa)
+
+DEFINE_ALCBACKEND_VTABLE(ALCplaybackAlsa);
 
 
 static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device)
@@ -417,7 +428,7 @@ static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device)
 }
 
 
-static ALuint ALCplaybackAlsa_mixerProc(ALvoid *ptr)
+static int ALCplaybackAlsa_mixerProc(void *ptr)
 {
     ALCplaybackAlsa *self = (ALCplaybackAlsa*)ptr;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -429,7 +440,7 @@ static ALuint ALCplaybackAlsa_mixerProc(ALvoid *ptr)
     int err;
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     update_size = device->UpdateSize;
     num_updates = device->NumUpdates;
@@ -509,7 +520,7 @@ static ALuint ALCplaybackAlsa_mixerProc(ALvoid *ptr)
     return 0;
 }
 
-static ALuint ALCplaybackAlsa_mixerNoMMapProc(ALvoid *ptr)
+static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr)
 {
     ALCplaybackAlsa *self = (ALCplaybackAlsa*)ptr;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -519,7 +530,7 @@ static ALuint ALCplaybackAlsa_mixerNoMMapProc(ALvoid *ptr)
     int err;
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     update_size = device->UpdateSize;
     num_updates = device->NumUpdates;
@@ -614,21 +625,17 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name)
 
     if(name)
     {
-        size_t idx;
+        const DevMap *iter;
 
-        if(!allDevNameMap)
-            allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames);
+        if(VECTOR_SIZE(PlaybackDevices) == 0)
+            probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices);
 
-        for(idx = 0;idx < numDevNames;idx++)
-        {
-            if(strcmp(name, allDevNameMap[idx].name) == 0)
-            {
-                driver = allDevNameMap[idx].device;
-                break;
-            }
-        }
-        if(idx == numDevNames)
+#define MATCH_NAME(i)  (al_string_cmp_cstr((i)->name, name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
+#undef MATCH_NAME
+        if(iter == VECTOR_ITER_END(PlaybackDevices))
             return ALC_INVALID_VALUE;
+        driver = al_string_get_cstr(iter->device_name);
     }
     else
     {
@@ -636,6 +643,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name)
         driver = GetConfigValue("alsa", "device", "default");
     }
 
+    TRACE("Opening device \"%s\"\n", driver);
     err = snd_pcm_open(&self->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
     if(err < 0)
     {
@@ -646,7 +654,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name)
     /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */
     snd_config_update_free_global();
 
-    device->DeviceName = strdup(name);
+    al_string_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 }
@@ -663,15 +671,14 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
     unsigned int periodLen, bufferLen;
     snd_pcm_sw_params_t *sp = NULL;
     snd_pcm_hw_params_t *hp = NULL;
+    snd_pcm_format_t format = -1;
     snd_pcm_access_t access;
-    snd_pcm_format_t format;
     unsigned int periods;
     unsigned int rate;
     const char *funcerr;
     int allowmmap;
     int err;
 
-    format = -1;
     switch(device->FmtType)
     {
         case DevFmtByte:
@@ -809,7 +816,7 @@ error:
 static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    ALuint (*thread_func)(ALvoid*) = NULL;
+    int (*thread_func)(void*) = NULL;
     snd_pcm_hw_params_t *hp = NULL;
     snd_pcm_access_t access;
     const char *funcerr;
@@ -845,7 +852,8 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self)
         }
         thread_func = ALCplaybackAlsa_mixerProc;
     }
-    if(!StartThread(&self->thread, thread_func, self))
+    self->killNow = 0;
+    if(althrd_create(&self->thread, thread_func, self) != althrd_success)
     {
         ERR("Could not create playback thread\n");
         free(self->buffer);
@@ -863,13 +871,14 @@ error:
 
 static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self)
 {
-    if(self->thread)
-    {
-        self->killNow = 1;
-        StopThread(self->thread);
-        self->thread = NULL;
-    }
-    self->killNow = 0;
+    int res;
+
+    if(self->killNow)
+        return;
+
+    self->killNow = 1;
+    althrd_join(self->thread, &res);
+
     free(self->buffer);
     self->buffer = NULL;
 }
@@ -889,14 +898,6 @@ static ALint64 ALCplaybackAlsa_getLatency(ALCplaybackAlsa *self)
 }
 
 
-static void ALCplaybackAlsa_Delete(ALCplaybackAlsa *self)
-{
-    free(self);
-}
-
-DEFINE_ALCBACKEND_VTABLE(ALCplaybackAlsa);
-
-
 typedef struct ALCcaptureAlsa {
     DERIVE_FROM_TYPE(ALCbackend);
 
@@ -910,7 +911,6 @@ typedef struct ALCcaptureAlsa {
 
     snd_pcm_sframes_t last_avail;
 } ALCcaptureAlsa;
-DECLARE_ALCBACKEND_VTABLE(ALCcaptureAlsa);
 
 static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device);
 static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, Destruct)
@@ -921,8 +921,12 @@ static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self);
 static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self);
 static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buffer, ALCuint samples);
 static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self);
+static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self);
 static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCcaptureAlsa)
+
+DEFINE_ALCBACKEND_VTABLE(ALCcaptureAlsa);
 
 
 static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device)
@@ -940,27 +944,23 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
     snd_pcm_uframes_t bufferSizeInFrames;
     snd_pcm_uframes_t periodSizeInFrames;
     ALboolean needring = AL_FALSE;
-    snd_pcm_format_t format;
+    snd_pcm_format_t format = -1;
     const char *funcerr;
     int err;
 
     if(name)
     {
-        size_t idx;
+        const DevMap *iter;
 
-        if(!allCaptureDevNameMap)
-            allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames);
+        if(VECTOR_SIZE(CaptureDevices) == 0)
+            probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices);
 
-        for(idx = 0;idx < numCaptureDevNames;idx++)
-        {
-            if(strcmp(name, allCaptureDevNameMap[idx].name) == 0)
-            {
-                driver = allCaptureDevNameMap[idx].device;
-                break;
-            }
-        }
-        if(idx == numCaptureDevNames)
+#define MATCH_NAME(i)  (al_string_cmp_cstr((i)->name, name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
+#undef MATCH_NAME
+        if(iter == VECTOR_ITER_END(CaptureDevices))
             return ALC_INVALID_VALUE;
+        driver = al_string_get_cstr(iter->device_name);
     }
     else
     {
@@ -968,6 +968,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
         driver = GetConfigValue("alsa", "capture", "default");
     }
 
+    TRACE("Opening device \"%s\"\n", driver);
     err = snd_pcm_open(&self->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
     if(err < 0)
     {
@@ -978,7 +979,6 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
     /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */
     snd_config_update_free_global();
 
-    format = -1;
     switch(device->FmtType)
     {
         case DevFmtByte:
@@ -1056,7 +1056,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
         }
     }
 
-    device->DeviceName = strdup(name);
+    al_string_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 
@@ -1114,11 +1114,12 @@ static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self)
         void *ptr;
 
         size = snd_pcm_frames_to_bytes(self->pcmHandle, avail);
-        ptr = realloc(self->buffer, size);
+        ptr = malloc(size);
         if(ptr)
         {
+            ALCcaptureAlsa_captureSamples(self, ptr, avail);
+            free(self->buffer);
             self->buffer = ptr;
-            ALCcaptureAlsa_captureSamples(self, self->buffer, avail);
             self->size = size;
         }
     }
@@ -1150,7 +1151,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff
             if((snd_pcm_uframes_t)amt > samples) amt = samples;
 
             amt = snd_pcm_frames_to_bytes(self->pcmHandle, amt);
-            memmove(buffer, self->buffer, amt);
+            memcpy(buffer, self->buffer, amt);
 
             if(self->size > amt)
             {
@@ -1287,14 +1288,11 @@ static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self)
     return maxi64((ALint64)delay*1000000000/device->Frequency, 0);
 }
 
-static void ALCcaptureAlsa_Delete(ALCcaptureAlsa *self)
-{
-    free(self);
-}
-
-DEFINE_ALCBACKEND_VTABLE(ALCcaptureAlsa);
-
 
+static inline void AppendAllDevicesList2(const DevMap *entry)
+{ AppendAllDevicesList(al_string_get_cstr(entry->name)); }
+static inline void AppendCaptureDeviceList2(const DevMap *entry)
+{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); }
 
 typedef struct ALCalsaBackendFactory {
     DERIVE_FROM_TYPE(ALCbackendFactory);
@@ -1303,6 +1301,9 @@ typedef struct ALCalsaBackendFactory {
 
 static ALCboolean ALCalsaBackendFactory_init(ALCalsaBackendFactory* UNUSED(self))
 {
+    VECTOR_INIT(PlaybackDevices);
+    VECTOR_INIT(CaptureDevices);
+
     if(!alsa_load())
         return ALC_FALSE;
     return ALC_TRUE;
@@ -1310,25 +1311,11 @@ static ALCboolean ALCalsaBackendFactory_init(ALCalsaBackendFactory* UNUSED(self)
 
 static void ALCalsaBackendFactory_deinit(ALCalsaBackendFactory* UNUSED(self))
 {
-    ALuint i;
+    clear_devlist(&PlaybackDevices);
+    VECTOR_DEINIT(PlaybackDevices);
 
-    for(i = 0;i < numDevNames;++i)
-    {
-        free(allDevNameMap[i].name);
-        free(allDevNameMap[i].device);
-    }
-    free(allDevNameMap);
-    allDevNameMap = NULL;
-    numDevNames = 0;
-
-    for(i = 0;i < numCaptureDevNames;++i)
-    {
-        free(allCaptureDevNameMap[i].name);
-        free(allCaptureDevNameMap[i].device);
-    }
-    free(allCaptureDevNameMap);
-    allCaptureDevNameMap = NULL;
-    numCaptureDevNames = 0;
+    clear_devlist(&CaptureDevices);
+    VECTOR_DEINIT(CaptureDevices);
 
 #ifdef HAVE_DYNLOAD
     if(alsa_handle)
@@ -1346,36 +1333,16 @@ static ALCboolean ALCalsaBackendFactory_querySupport(ALCalsaBackendFactory* UNUS
 
 static void ALCalsaBackendFactory_probe(ALCalsaBackendFactory* UNUSED(self), enum DevProbe type)
 {
-    ALuint i;
-
     switch(type)
     {
         case ALL_DEVICE_PROBE:
-            for(i = 0;i < numDevNames;++i)
-            {
-                free(allDevNameMap[i].name);
-                free(allDevNameMap[i].device);
-            }
-
-            free(allDevNameMap);
-            allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames);
-
-            for(i = 0;i < numDevNames;++i)
-                AppendAllDevicesList(allDevNameMap[i].name);
+            probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices);
+            VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2);
             break;
 
         case CAPTURE_DEVICE_PROBE:
-            for(i = 0;i < numCaptureDevNames;++i)
-            {
-                free(allCaptureDevNameMap[i].name);
-                free(allCaptureDevNameMap[i].device);
-            }
-
-            free(allCaptureDevNameMap);
-            allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames);
-
-            for(i = 0;i < numCaptureDevNames;++i)
-                AppendCaptureDeviceList(allCaptureDevNameMap[i].name);
+            probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices);
+            VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2);
             break;
     }
 }
@@ -1386,8 +1353,9 @@ static ALCbackend* ALCalsaBackendFactory_createBackend(ALCalsaBackendFactory* UN
     {
         ALCplaybackAlsa *backend;
 
-        backend = calloc(1, sizeof(*backend));
+        backend = ALCplaybackAlsa_New(sizeof(*backend));
         if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
 
         ALCplaybackAlsa_Construct(backend, device);
 
@@ -1397,8 +1365,9 @@ static ALCbackend* ALCalsaBackendFactory_createBackend(ALCalsaBackendFactory* UN
     {
         ALCcaptureAlsa *backend;
 
-        backend = calloc(1, sizeof(*backend));
+        backend = ALCcaptureAlsa_New(sizeof(*backend));
         if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
 
         ALCcaptureAlsa_Construct(backend, device);
 

+ 40 - 38
jni/openal-soft-android/Alc/backends/base.c → jni/openal-soft-1.16.0/Alc/backends/base.c

@@ -11,13 +11,15 @@
 /* Base ALCbackend method implementations. */
 void ALCbackend_Construct(ALCbackend *self, ALCdevice *device)
 {
+    int ret;
     self->mDevice = device;
-    InitializeCriticalSection(&self->mMutex);
+    ret = almtx_init(&self->mMutex, almtx_recursive);
+    assert(ret == althrd_success);
 }
 
 void ALCbackend_Destruct(ALCbackend *self)
 {
-    DeleteCriticalSection(&self->mMutex);
+    almtx_destroy(&self->mMutex);
 }
 
 ALCboolean ALCbackend_reset(ALCbackend* UNUSED(self))
@@ -42,12 +44,14 @@ ALint64 ALCbackend_getLatency(ALCbackend* UNUSED(self))
 
 void ALCbackend_lock(ALCbackend *self)
 {
-    EnterCriticalSection(&self->mMutex);
+    int ret = almtx_lock(&self->mMutex);
+    assert(ret == althrd_success);
 }
 
 void ALCbackend_unlock(ALCbackend *self)
 {
-    LeaveCriticalSection(&self->mMutex);
+    int ret = almtx_unlock(&self->mMutex);
+    assert(ret == althrd_success);
 }
 
 
@@ -60,9 +64,11 @@ void ALCbackendFactory_deinit(ALCbackendFactory* UNUSED(self))
 /* Wrappers to use an old-style backend with the new interface. */
 typedef struct PlaybackWrapper {
     DERIVE_FROM_TYPE(ALCbackend);
+
+    const BackendFuncs *Funcs;
 } PlaybackWrapper;
 
-static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device);
+static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs);
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct)
 static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name);
 static void PlaybackWrapper_close(PlaybackWrapper *self);
@@ -74,62 +80,61 @@ static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples)
 static ALint64 PlaybackWrapper_getLatency(PlaybackWrapper *self);
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock)
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock)
-static void PlaybackWrapper_Delete(PlaybackWrapper *self);
+DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper)
 DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper);
 
-static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device)
+static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(PlaybackWrapper, ALCbackend, self);
+
+    self->Funcs = funcs;
 }
 
 static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return device->Funcs->OpenPlayback(device, name);
+    return self->Funcs->OpenPlayback(device, name);
 }
 
 static void PlaybackWrapper_close(PlaybackWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    device->Funcs->ClosePlayback(device);
+    self->Funcs->ClosePlayback(device);
 }
 
 static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return device->Funcs->ResetPlayback(device);
+    return self->Funcs->ResetPlayback(device);
 }
 
 static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return device->Funcs->StartPlayback(device);
+    return self->Funcs->StartPlayback(device);
 }
 
 static void PlaybackWrapper_stop(PlaybackWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    device->Funcs->StopPlayback(device);
+    self->Funcs->StopPlayback(device);
 }
 
 static ALint64 PlaybackWrapper_getLatency(PlaybackWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return device->Funcs->GetLatency(device);
-}
-
-static void PlaybackWrapper_Delete(PlaybackWrapper *self)
-{
-    free(self);
+    return self->Funcs->GetLatency(device);
 }
 
 
 typedef struct CaptureWrapper {
     DERIVE_FROM_TYPE(ALCbackend);
+
+    const BackendFuncs *Funcs;
 } CaptureWrapper;
 
-static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device);
+static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs);
 static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct)
 static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name);
 static void CaptureWrapper_close(CaptureWrapper *self);
@@ -141,75 +146,72 @@ static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self);
 static ALint64 CaptureWrapper_getLatency(CaptureWrapper *self);
 static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock)
 static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock)
-static void CaptureWrapper_Delete(CaptureWrapper *self);
+DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper)
 DEFINE_ALCBACKEND_VTABLE(CaptureWrapper);
 
 
-static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device)
+static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(CaptureWrapper, ALCbackend, self);
+
+    self->Funcs = funcs;
 }
 
 static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return device->Funcs->OpenCapture(device, name);
+    return self->Funcs->OpenCapture(device, name);
 }
 
 static void CaptureWrapper_close(CaptureWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    device->Funcs->CloseCapture(device);
+    self->Funcs->CloseCapture(device);
 }
 
 static ALCboolean CaptureWrapper_start(CaptureWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    device->Funcs->StartCapture(device);
+    self->Funcs->StartCapture(device);
     return ALC_TRUE;
 }
 
 static void CaptureWrapper_stop(CaptureWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    device->Funcs->StopCapture(device);
+    self->Funcs->StopCapture(device);
 }
 
 static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return device->Funcs->CaptureSamples(device, buffer, samples);
+    return self->Funcs->CaptureSamples(device, buffer, samples);
 }
 
 static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return device->Funcs->AvailableSamples(device);
+    return self->Funcs->AvailableSamples(device);
 }
 
 static ALint64 CaptureWrapper_getLatency(CaptureWrapper *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return device->Funcs->GetLatency(device);
-}
-
-static void CaptureWrapper_Delete(CaptureWrapper *self)
-{
-    free(self);
+    return self->Funcs->GetLatency(device);
 }
 
 
-ALCbackend *create_backend_wrapper(ALCdevice *device, ALCbackend_Type type)
+ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type)
 {
     if(type == ALCbackend_Playback)
     {
         PlaybackWrapper *backend;
 
-        backend = malloc(sizeof(*backend));
+        backend = PlaybackWrapper_New(sizeof(*backend));
         if(!backend) return NULL;
 
-        PlaybackWrapper_Construct(backend, device);
+        PlaybackWrapper_Construct(backend, device, funcs);
 
         return STATIC_CAST(ALCbackend, backend);
     }
@@ -218,10 +220,10 @@ ALCbackend *create_backend_wrapper(ALCdevice *device, ALCbackend_Type type)
     {
         CaptureWrapper *backend;
 
-        backend = malloc(sizeof(*backend));
+        backend = CaptureWrapper_New(sizeof(*backend));
         if(!backend) return NULL;
 
-        CaptureWrapper_Construct(backend, device);
+        CaptureWrapper_Construct(backend, device, funcs);
 
         return STATIC_CAST(ALCbackend, backend);
     }

+ 9 - 9
jni/openal-soft-android/Alc/backends/base.h → jni/openal-soft-1.16.0/Alc/backends/base.h

@@ -2,7 +2,7 @@
 #define AL_BACKENDS_BASE_H
 
 #include "alMain.h"
-#include "compat.h"
+#include "threads.h"
 
 
 struct ALCbackendVtable;
@@ -12,7 +12,7 @@ typedef struct ALCbackend {
 
     ALCdevice *mDevice;
 
-    CRITICAL_SECTION mMutex;
+    almtx_t mMutex;
 } ALCbackend;
 
 void ALCbackend_Construct(ALCbackend *self, ALCdevice *device);
@@ -42,12 +42,9 @@ struct ALCbackendVtable {
     void (*const lock)(ALCbackend*);
     void (*const unlock)(ALCbackend*);
 
-    void (*const Delete)(ALCbackend*);
+    void (*const Delete)(void*);
 };
 
-#define DECLARE_ALCBACKEND_VTABLE(T)                                          \
-static const struct ALCbackendVtable T##_ALCbackend_vtable
-
 #define DEFINE_ALCBACKEND_VTABLE(T)                                           \
 DECLARE_THUNK(T, ALCbackend, void, Destruct)                                  \
 DECLARE_THUNK1(T, ALCbackend, ALCenum, open, const ALCchar*)                  \
@@ -60,9 +57,10 @@ DECLARE_THUNK(T, ALCbackend, ALCuint, availableSamples)                       \
 DECLARE_THUNK(T, ALCbackend, ALint64, getLatency)                             \
 DECLARE_THUNK(T, ALCbackend, void, lock)                                      \
 DECLARE_THUNK(T, ALCbackend, void, unlock)                                    \
-DECLARE_THUNK(T, ALCbackend, void, Delete)                                    \
+static void T##_ALCbackend_Delete(void *ptr)                                  \
+{ T##_Delete(STATIC_UPCAST(T, ALCbackend, (ALCbackend*)ptr)); }               \
                                                                               \
-DECLARE_ALCBACKEND_VTABLE(T) = {                                              \
+static const struct ALCbackendVtable T##_ALCbackend_vtable = {                \
     T##_ALCbackend_Destruct,                                                  \
                                                                               \
     T##_ALCbackend_open,                                                      \
@@ -125,9 +123,11 @@ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = {  \
 ALCbackendFactory *ALCpulseBackendFactory_getFactory(void);
 ALCbackendFactory *ALCalsaBackendFactory_getFactory(void);
 ALCbackendFactory *ALCossBackendFactory_getFactory(void);
+ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void);
+ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void);
 ALCbackendFactory *ALCnullBackendFactory_getFactory(void);
 ALCbackendFactory *ALCloopbackFactory_getFactory(void);
 
-ALCbackend *create_backend_wrapper(ALCdevice *device, ALCbackend_Type type);
+ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type);
 
 #endif /* AL_BACKENDS_BASE_H */

+ 4 - 1
jni/openal-soft-android/Alc/backends/coreaudio.c → jni/openal-soft-1.16.0/Alc/backends/coreaudio.c

@@ -23,6 +23,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <alloca.h>
 
 #include "alMain.h"
 #include "alu.h"
@@ -180,7 +181,7 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
         return ALC_INVALID_VALUE;
     }
 
-    device->DeviceName = strdup(deviceName);
+    al_string_copy_cstr(&device->DeviceName, deviceName);
     device->ExtraData = data;
     return ALC_NO_ERROR;
 }
@@ -577,6 +578,8 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     if(data->ring == NULL)
         goto error;
 
+    al_string_copy_cstr(&device->DeviceName, deviceName);
+
     return ALC_NO_ERROR;
 
 error:

+ 388 - 370
jni/openal-soft-android/Alc/backends/dsound.c → jni/openal-soft-1.16.0/Alc/backends/dsound.c

@@ -36,6 +36,9 @@
 #include "alu.h"
 #include "threads.h"
 #include "compat.h"
+#include "alstring.h"
+
+#include "backends/base.h"
 
 #ifndef DSSPEAKER_5POINT1
 #   define DSSPEAKER_5POINT1          0x00000006
@@ -55,54 +58,23 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x
 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 
 
+#ifdef HAVE_DYNLOAD
 static void *ds_handle;
-static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter);
-static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext);
-static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID pcGuidDevice, IDirectSoundCapture **ppDSC, IUnknown *pUnkOuter);
-static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext);
+static HRESULT (WINAPI *pDirectSoundCreate)(const GUID *pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter);
+static HRESULT (WINAPI *pDirectSoundEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext);
+static HRESULT (WINAPI *pDirectSoundCaptureCreate)(const GUID *pcGuidDevice, IDirectSoundCapture **ppDSC, IUnknown *pUnkOuter);
+static HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext);
 
 #define DirectSoundCreate            pDirectSoundCreate
-#define DirectSoundEnumerateA        pDirectSoundEnumerateA
+#define DirectSoundEnumerateW        pDirectSoundEnumerateW
 #define DirectSoundCaptureCreate     pDirectSoundCaptureCreate
-#define DirectSoundCaptureEnumerateA pDirectSoundCaptureEnumerateA
-
-
-typedef struct {
-    // DirectSound Playback Device
-    IDirectSound       *DS;
-    IDirectSoundBuffer *PrimaryBuffer;
-    IDirectSoundBuffer *Buffer;
-    IDirectSoundNotify *Notifies;
-    HANDLE             NotifyEvent;
-
-    volatile int killNow;
-    althread_t thread;
-} DSoundPlaybackData;
-
-typedef struct {
-    // DirectSound Capture Device
-    IDirectSoundCapture *DSC;
-    IDirectSoundCaptureBuffer *DSCbuffer;
-    DWORD BufferBytes;
-    DWORD Cursor;
-    RingBuffer *Ring;
-} DSoundCaptureData;
-
-
-typedef struct {
-    ALCchar *name;
-    GUID guid;
-} DevMap;
-
-static DevMap *PlaybackDeviceList;
-static ALuint NumPlaybackDevices;
-static DevMap *CaptureDeviceList;
-static ALuint NumCaptureDevices;
+#define DirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW
+#endif
 
-#define MAX_UPDATES 128
 
 static ALCboolean DSoundLoad(void)
 {
+#ifdef HAVE_DYNLOAD
     if(!ds_handle)
     {
         ds_handle = LoadLib("dsound.dll");
@@ -121,117 +93,130 @@ static ALCboolean DSoundLoad(void)
     }                                                                         \
 } while(0)
         LOAD_FUNC(DirectSoundCreate);
-        LOAD_FUNC(DirectSoundEnumerateA);
+        LOAD_FUNC(DirectSoundEnumerateW);
         LOAD_FUNC(DirectSoundCaptureCreate);
-        LOAD_FUNC(DirectSoundCaptureEnumerateA);
+        LOAD_FUNC(DirectSoundCaptureEnumerateW);
 #undef LOAD_FUNC
     }
+#endif
     return ALC_TRUE;
 }
 
 
-static BOOL CALLBACK DSoundEnumPlaybackDevices(LPGUID guid, LPCSTR desc, LPCSTR UNUSED(drvname), LPVOID UNUSED(data))
+#define MAX_UPDATES 128
+
+typedef struct {
+    al_string name;
+    GUID guid;
+} DevMap;
+TYPEDEF_VECTOR(DevMap, vector_DevMap)
+
+static vector_DevMap PlaybackDevices;
+static vector_DevMap CaptureDevices;
+
+static void clear_devlist(vector_DevMap *list)
 {
-    LPOLESTR guidstr = NULL;
-    char str[1024];
+#define DEINIT_STR(i) AL_STRING_DEINIT((i)->name)
+    VECTOR_FOR_EACH(DevMap, *list, DEINIT_STR);
+#undef DEINIT_STR
+    VECTOR_RESIZE(*list, 0);
+}
+
+static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data)
+{
+    vector_DevMap *devices = data;
+    OLECHAR *guidstr = NULL;
+    DevMap *iter, *end;
+    DevMap entry;
     HRESULT hr;
-    void *temp;
     int count;
-    ALuint i;
 
     if(!guid)
         return TRUE;
 
+    AL_STRING_INIT(entry.name);
+
     count = 0;
     do {
-        if(count == 0)
-            snprintf(str, sizeof(str), "%s", desc);
-        else
-            snprintf(str, sizeof(str), "%s #%d", desc, count+1);
+        al_string_copy_wcstr(&entry.name, desc);
+        if(count != 0)
+        {
+            char str[64];
+            snprintf(str, sizeof(str), " #%d", count+1);
+            al_string_append_cstr(&entry.name, str);
+        }
         count++;
 
-        for(i = 0;i < NumPlaybackDevices;i++)
+        iter = VECTOR_ITER_BEGIN(*devices);
+        end = VECTOR_ITER_END(*devices);
+        for(;iter != end;++iter)
         {
-            if(strcmp(str, PlaybackDeviceList[i].name) == 0)
+            if(al_string_cmp(entry.name, iter->name) == 0)
                 break;
         }
-    } while(i != NumPlaybackDevices);
+    } while(iter != end);
+    entry.guid = *guid;
 
     hr = StringFromCLSID(guid, &guidstr);
     if(SUCCEEDED(hr))
     {
-        TRACE("Got device \"%s\", GUID \"%ls\"\n", str, guidstr);
+        TRACE("Got device \"%s\", GUID \"%ls\"\n", al_string_get_cstr(entry.name), guidstr);
         CoTaskMemFree(guidstr);
     }
 
-    temp = realloc(PlaybackDeviceList, sizeof(DevMap) * (NumPlaybackDevices+1));
-    if(temp)
-    {
-        PlaybackDeviceList = temp;
-        PlaybackDeviceList[NumPlaybackDevices].name = strdup(str);
-        PlaybackDeviceList[NumPlaybackDevices].guid = *guid;
-        NumPlaybackDevices++;
-    }
+    VECTOR_PUSH_BACK(*devices, entry);
 
     return TRUE;
 }
 
 
-static BOOL CALLBACK DSoundEnumCaptureDevices(LPGUID guid, LPCSTR desc, LPCSTR UNUSED(drvname), LPVOID UNUSED(data))
-{
-    LPOLESTR guidstr = NULL;
-    char str[1024];
-    HRESULT hr;
-    void *temp;
-    int count;
-    ALuint i;
+typedef struct ALCdsoundPlayback {
+    DERIVE_FROM_TYPE(ALCbackend);
 
-    if(!guid)
-        return TRUE;
+    IDirectSound       *DS;
+    IDirectSoundBuffer *PrimaryBuffer;
+    IDirectSoundBuffer *Buffer;
+    IDirectSoundNotify *Notifies;
+    HANDLE             NotifyEvent;
 
-    count = 0;
-    do {
-        if(count == 0)
-            snprintf(str, sizeof(str), "%s", desc);
-        else
-            snprintf(str, sizeof(str), "%s #%d", desc, count+1);
-        count++;
+    volatile int killNow;
+    althrd_t thread;
+} ALCdsoundPlayback;
 
-        for(i = 0;i < NumCaptureDevices;i++)
-        {
-            if(strcmp(str, CaptureDeviceList[i].name) == 0)
-                break;
-        }
-    } while(i != NumCaptureDevices);
+static int ALCdsoundPlayback_mixerProc(void *ptr);
 
-    hr = StringFromCLSID(guid, &guidstr);
-    if(SUCCEEDED(hr))
-    {
-        TRACE("Got device \"%s\", GUID \"%ls\"\n", str, guidstr);
-        CoTaskMemFree(guidstr);
-    }
+static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device);
+static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, Destruct)
+static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *name);
+static void ALCdsoundPlayback_close(ALCdsoundPlayback *self);
+static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self);
+static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self);
+static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self);
+static DECLARE_FORWARD2(ALCdsoundPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCdsoundPlayback)
 
-    temp = realloc(CaptureDeviceList, sizeof(DevMap) * (NumCaptureDevices+1));
-    if(temp)
-    {
-        CaptureDeviceList = temp;
-        CaptureDeviceList[NumCaptureDevices].name = strdup(str);
-        CaptureDeviceList[NumCaptureDevices].guid = *guid;
-        NumCaptureDevices++;
-    }
+DEFINE_ALCBACKEND_VTABLE(ALCdsoundPlayback);
 
-    return TRUE;
+
+static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCdsoundPlayback, ALCbackend, self);
 }
 
 
-FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr)
+FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
 {
-    ALCdevice *Device = (ALCdevice*)ptr;
-    DSoundPlaybackData *data = (DSoundPlaybackData*)Device->ExtraData;
+    ALCdsoundPlayback *self = ptr;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     DSBCAPS DSBCaps;
     DWORD LastCursor = 0;
     DWORD PlayCursor;
-    VOID *WritePtr1, *WritePtr2;
+    void *WritePtr1, *WritePtr2;
     DWORD WriteCnt1,  WriteCnt2;
     BOOL Playing = FALSE;
     DWORD FrameSize;
@@ -240,47 +225,47 @@ FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr)
     HRESULT err;
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     memset(&DSBCaps, 0, sizeof(DSBCaps));
     DSBCaps.dwSize = sizeof(DSBCaps);
-    err = IDirectSoundBuffer_GetCaps(data->Buffer, &DSBCaps);
+    err = IDirectSoundBuffer_GetCaps(self->Buffer, &DSBCaps);
     if(FAILED(err))
     {
         ERR("Failed to get buffer caps: 0x%lx\n", err);
-        ALCdevice_Lock(Device);
-        aluHandleDisconnect(Device);
-        ALCdevice_Unlock(Device);
+        ALCdevice_Lock(device);
+        aluHandleDisconnect(device);
+        ALCdevice_Unlock(device);
         return 1;
     }
 
-    FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
-    FragSize = Device->UpdateSize * FrameSize;
+    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    FragSize = device->UpdateSize * FrameSize;
 
-    IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &LastCursor, NULL);
-    while(!data->killNow)
+    IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL);
+    while(!self->killNow)
     {
         // Get current play cursor
-        IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &PlayCursor, NULL);
+        IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &PlayCursor, NULL);
         avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes;
 
         if(avail < FragSize)
         {
             if(!Playing)
             {
-                err = IDirectSoundBuffer_Play(data->Buffer, 0, 0, DSBPLAY_LOOPING);
+                err = IDirectSoundBuffer_Play(self->Buffer, 0, 0, DSBPLAY_LOOPING);
                 if(FAILED(err))
                 {
                     ERR("Failed to play buffer: 0x%lx\n", err);
-                    ALCdevice_Lock(Device);
-                    aluHandleDisconnect(Device);
-                    ALCdevice_Unlock(Device);
+                    ALCdevice_Lock(device);
+                    aluHandleDisconnect(device);
+                    ALCdevice_Unlock(device);
                     return 1;
                 }
                 Playing = TRUE;
             }
 
-            avail = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE);
+            avail = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE);
             if(avail != WAIT_OBJECT_0)
                 ERR("WaitForSingleObjectEx error: 0x%lx\n", avail);
             continue;
@@ -290,18 +275,18 @@ FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr)
         // Lock output buffer
         WriteCnt1 = 0;
         WriteCnt2 = 0;
-        err = IDirectSoundBuffer_Lock(data->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
+        err = IDirectSoundBuffer_Lock(self->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
 
         // If the buffer is lost, restore it and lock
         if(err == DSERR_BUFFERLOST)
         {
             WARN("Buffer lost, restoring...\n");
-            err = IDirectSoundBuffer_Restore(data->Buffer);
+            err = IDirectSoundBuffer_Restore(self->Buffer);
             if(SUCCEEDED(err))
             {
                 Playing = FALSE;
                 LastCursor = 0;
-                err = IDirectSoundBuffer_Lock(data->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
+                err = IDirectSoundBuffer_Lock(self->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0);
             }
         }
 
@@ -309,18 +294,18 @@ FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr)
         if(SUCCEEDED(err))
         {
             // If we have an active context, mix data directly into output buffer otherwise fill with silence
-            aluMixData(Device, WritePtr1, WriteCnt1/FrameSize);
-            aluMixData(Device, WritePtr2, WriteCnt2/FrameSize);
+            aluMixData(device, WritePtr1, WriteCnt1/FrameSize);
+            aluMixData(device, WritePtr2, WriteCnt2/FrameSize);
 
             // Unlock output buffer only when successfully locked
-            IDirectSoundBuffer_Unlock(data->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
+            IDirectSoundBuffer_Unlock(self->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
         }
         else
         {
             ERR("Buffer lock error: %#lx\n", err);
-            ALCdevice_Lock(Device);
-            aluHandleDisconnect(Device);
-            ALCdevice_Unlock(Device);
+            ALCdevice_Lock(device);
+            aluHandleDisconnect(device);
+            ALCdevice_Unlock(device);
             return 1;
         }
 
@@ -332,94 +317,89 @@ FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr)
     return 0;
 }
 
-static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
+static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *deviceName)
 {
-    DSoundPlaybackData *data = NULL;
-    LPGUID guid = NULL;
-    HRESULT hr;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    const GUID *guid = NULL;
+    HRESULT hr, hrcom;
 
-    if(!PlaybackDeviceList)
+    if(VECTOR_SIZE(PlaybackDevices) == 0)
     {
-        hr = DirectSoundEnumerateA(DSoundEnumPlaybackDevices, NULL);
+        /* Initialize COM to prevent name truncation */
+        hrcom = CoInitialize(NULL);
+        hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices);
         if(FAILED(hr))
-            ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
+            ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr);
+        if(SUCCEEDED(hrcom))
+            CoUninitialize();
     }
 
-    if(!deviceName && NumPlaybackDevices > 0)
+    if(!deviceName && VECTOR_SIZE(PlaybackDevices) > 0)
     {
-        deviceName = PlaybackDeviceList[0].name;
-        guid = &PlaybackDeviceList[0].guid;
+        deviceName = al_string_get_cstr(VECTOR_FRONT(PlaybackDevices).name);
+        guid = &VECTOR_FRONT(PlaybackDevices).guid;
     }
     else
     {
-        ALuint i;
+        const DevMap *iter;
 
-        for(i = 0;i < NumPlaybackDevices;i++)
-        {
-            if(strcmp(deviceName, PlaybackDeviceList[i].name) == 0)
-            {
-                guid = &PlaybackDeviceList[i].guid;
-                break;
-            }
-        }
-        if(i == NumPlaybackDevices)
+#define MATCH_NAME(i)  (al_string_cmp_cstr((i)->name, deviceName) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
+#undef MATCH_NAME
+        if(iter == VECTOR_ITER_END(PlaybackDevices))
             return ALC_INVALID_VALUE;
+        guid = &iter->guid;
     }
 
-    //Initialise requested device
-    data = calloc(1, sizeof(DSoundPlaybackData));
-    if(!data)
-        return ALC_OUT_OF_MEMORY;
-
     hr = DS_OK;
-    data->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if(data->NotifyEvent == NULL)
+    self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if(self->NotifyEvent == NULL)
         hr = E_FAIL;
 
     //DirectSound Init code
     if(SUCCEEDED(hr))
-        hr = DirectSoundCreate(guid, &data->DS, NULL);
+        hr = DirectSoundCreate(guid, &self->DS, NULL);
     if(SUCCEEDED(hr))
-        hr = IDirectSound_SetCooperativeLevel(data->DS, GetForegroundWindow(), DSSCL_PRIORITY);
+        hr = IDirectSound_SetCooperativeLevel(self->DS, GetForegroundWindow(), DSSCL_PRIORITY);
     if(FAILED(hr))
     {
-        if(data->DS)
-            IDirectSound_Release(data->DS);
-        if(data->NotifyEvent)
-            CloseHandle(data->NotifyEvent);
-        free(data);
+        if(self->DS)
+            IDirectSound_Release(self->DS);
+        self->DS = NULL;
+        if(self->NotifyEvent)
+            CloseHandle(self->NotifyEvent);
+        self->NotifyEvent = NULL;
+
         ERR("Device init failed: 0x%08lx\n", hr);
         return ALC_INVALID_VALUE;
     }
 
-    device->DeviceName = strdup(deviceName);
-    device->ExtraData = data;
+    al_string_copy_cstr(&device->DeviceName, deviceName);
+
     return ALC_NO_ERROR;
 }
 
-static void DSoundClosePlayback(ALCdevice *device)
+static void ALCdsoundPlayback_close(ALCdsoundPlayback *self)
 {
-    DSoundPlaybackData *data = device->ExtraData;
-
-    if(data->Notifies)
-        IDirectSoundNotify_Release(data->Notifies);
-    data->Notifies = NULL;
-    if(data->Buffer)
-        IDirectSoundBuffer_Release(data->Buffer);
-    data->Buffer = NULL;
-    if(data->PrimaryBuffer != NULL)
-        IDirectSoundBuffer_Release(data->PrimaryBuffer);
-    data->PrimaryBuffer = NULL;
-
-    IDirectSound_Release(data->DS);
-    CloseHandle(data->NotifyEvent);
-    free(data);
-    device->ExtraData = NULL;
+    if(self->Notifies)
+        IDirectSoundNotify_Release(self->Notifies);
+    self->Notifies = NULL;
+    if(self->Buffer)
+        IDirectSoundBuffer_Release(self->Buffer);
+    self->Buffer = NULL;
+    if(self->PrimaryBuffer != NULL)
+        IDirectSoundBuffer_Release(self->PrimaryBuffer);
+    self->PrimaryBuffer = NULL;
+
+    IDirectSound_Release(self->DS);
+    self->DS = NULL;
+    CloseHandle(self->NotifyEvent);
+    self->NotifyEvent = NULL;
 }
 
-static ALCboolean DSoundResetPlayback(ALCdevice *device)
+static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
 {
-    DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     DSBUFFERDESC DSBDescription;
     WAVEFORMATEXTENSIBLE OutputType;
     DWORD speakers;
@@ -427,15 +407,15 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
 
     memset(&OutputType, 0, sizeof(OutputType));
 
-    if(data->Notifies)
-        IDirectSoundNotify_Release(data->Notifies);
-    data->Notifies = NULL;
-    if(data->Buffer)
-        IDirectSoundBuffer_Release(data->Buffer);
-    data->Buffer = NULL;
-    if(data->PrimaryBuffer != NULL)
-        IDirectSoundBuffer_Release(data->PrimaryBuffer);
-    data->PrimaryBuffer = NULL;
+    if(self->Notifies)
+        IDirectSoundNotify_Release(self->Notifies);
+    self->Notifies = NULL;
+    if(self->Buffer)
+        IDirectSoundBuffer_Release(self->Buffer);
+    self->Buffer = NULL;
+    if(self->PrimaryBuffer != NULL)
+        IDirectSoundBuffer_Release(self->PrimaryBuffer);
+    self->PrimaryBuffer = NULL;
 
     switch(device->FmtType)
     {
@@ -458,7 +438,7 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
             break;
     }
 
-    hr = IDirectSound_GetSpeakerConfig(data->DS, &speakers);
+    hr = IDirectSound_GetSpeakerConfig(self->DS, &speakers);
     if(SUCCEEDED(hr))
     {
         if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
@@ -551,21 +531,21 @@ retry_open:
         else
             OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
 
-        if(data->PrimaryBuffer)
-            IDirectSoundBuffer_Release(data->PrimaryBuffer);
-        data->PrimaryBuffer = NULL;
+        if(self->PrimaryBuffer)
+            IDirectSoundBuffer_Release(self->PrimaryBuffer);
+        self->PrimaryBuffer = NULL;
     }
     else
     {
-        if(SUCCEEDED(hr) && !data->PrimaryBuffer)
+        if(SUCCEEDED(hr) && !self->PrimaryBuffer)
         {
             memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
             DSBDescription.dwSize=sizeof(DSBUFFERDESC);
             DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER;
-            hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->PrimaryBuffer, NULL);
+            hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->PrimaryBuffer, NULL);
         }
         if(SUCCEEDED(hr))
-            hr = IDirectSoundBuffer_SetFormat(data->PrimaryBuffer,&OutputType.Format);
+            hr = IDirectSoundBuffer_SetFormat(self->PrimaryBuffer,&OutputType.Format);
     }
 
     if(SUCCEEDED(hr))
@@ -583,7 +563,7 @@ retry_open:
         DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates *
                                      OutputType.Format.nBlockAlign;
         DSBDescription.lpwfxFormat=&OutputType.Format;
-        hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->Buffer, NULL);
+        hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->Buffer, NULL);
         if(FAILED(hr) && device->FmtType == DevFmtFloat)
         {
             device->FmtType = DevFmtShort;
@@ -593,7 +573,7 @@ retry_open:
 
     if(SUCCEEDED(hr))
     {
-        hr = IDirectSoundBuffer_QueryInterface(data->Buffer, &IID_IDirectSoundNotify, (LPVOID *)&data->Notifies);
+        hr = IDirectSoundBuffer_QueryInterface(self->Buffer, &IID_IDirectSoundNotify, (void**)&self->Notifies);
         if(SUCCEEDED(hr))
         {
             DSBPOSITIONNOTIFY notifies[MAX_UPDATES];
@@ -603,98 +583,125 @@ retry_open:
             {
                 notifies[i].dwOffset = i * device->UpdateSize *
                                        OutputType.Format.nBlockAlign;
-                notifies[i].hEventNotify = data->NotifyEvent;
+                notifies[i].hEventNotify = self->NotifyEvent;
             }
-            if(IDirectSoundNotify_SetNotificationPositions(data->Notifies, device->NumUpdates, notifies) != DS_OK)
+            if(IDirectSoundNotify_SetNotificationPositions(self->Notifies, device->NumUpdates, notifies) != DS_OK)
                 hr = E_FAIL;
         }
     }
 
     if(FAILED(hr))
     {
-        if(data->Notifies != NULL)
-            IDirectSoundNotify_Release(data->Notifies);
-        data->Notifies = NULL;
-        if(data->Buffer != NULL)
-            IDirectSoundBuffer_Release(data->Buffer);
-        data->Buffer = NULL;
-        if(data->PrimaryBuffer != NULL)
-            IDirectSoundBuffer_Release(data->PrimaryBuffer);
-        data->PrimaryBuffer = NULL;
+        if(self->Notifies != NULL)
+            IDirectSoundNotify_Release(self->Notifies);
+        self->Notifies = NULL;
+        if(self->Buffer != NULL)
+            IDirectSoundBuffer_Release(self->Buffer);
+        self->Buffer = NULL;
+        if(self->PrimaryBuffer != NULL)
+            IDirectSoundBuffer_Release(self->PrimaryBuffer);
+        self->PrimaryBuffer = NULL;
         return ALC_FALSE;
     }
 
-    ResetEvent(data->NotifyEvent);
+    ResetEvent(self->NotifyEvent);
     SetDefaultWFXChannelOrder(device);
 
     return ALC_TRUE;
 }
 
-static ALCboolean DSoundStartPlayback(ALCdevice *device)
+static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self)
 {
-    DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData;
-
-    if(!StartThread(&data->thread, DSoundPlaybackProc, device))
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCdsoundPlayback_mixerProc, self) != althrd_success)
         return ALC_FALSE;
 
     return ALC_TRUE;
 }
 
-static void DSoundStopPlayback(ALCdevice *device)
+static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self)
 {
-    DSoundPlaybackData *data = device->ExtraData;
+    int res;
 
-    if(!data->thread)
+    if(self->killNow)
         return;
 
-    data->killNow = 1;
-    StopThread(data->thread);
-    data->thread = NULL;
+    self->killNow = 1;
+    althrd_join(self->thread, &res);
+
+    IDirectSoundBuffer_Stop(self->Buffer);
+}
+
 
-    data->killNow = 0;
-    IDirectSoundBuffer_Stop(data->Buffer);
+
+typedef struct ALCdsoundCapture {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    IDirectSoundCapture *DSC;
+    IDirectSoundCaptureBuffer *DSCbuffer;
+    DWORD BufferBytes;
+    DWORD Cursor;
+    RingBuffer *Ring;
+} ALCdsoundCapture;
+
+static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device);
+static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, Destruct)
+static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *name);
+static void ALCdsoundCapture_close(ALCdsoundCapture *self);
+static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALCboolean, reset)
+static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self);
+static void ALCdsoundCapture_stop(ALCdsoundCapture *self);
+static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self);
+static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCdsoundCapture)
+
+DEFINE_ALCBACKEND_VTABLE(ALCdsoundCapture);
+
+static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCdsoundCapture, ALCbackend, self);
 }
 
 
-static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
+static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *deviceName)
 {
-    DSoundCaptureData *data = NULL;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     WAVEFORMATEXTENSIBLE InputType;
     DSCBUFFERDESC DSCBDescription;
-    LPGUID guid = NULL;
+    const GUID *guid = NULL;
     HRESULT hr, hrcom;
     ALuint samples;
 
-    if(!CaptureDeviceList)
+    if(VECTOR_SIZE(CaptureDevices) == 0)
     {
         /* Initialize COM to prevent name truncation */
         hrcom = CoInitialize(NULL);
-        hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL);
+        hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices);
         if(FAILED(hr))
-            ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr);
+            ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr);
         if(SUCCEEDED(hrcom))
             CoUninitialize();
     }
 
-    if(!deviceName && NumCaptureDevices > 0)
+    if(!deviceName && VECTOR_SIZE(CaptureDevices) > 0)
     {
-        deviceName = CaptureDeviceList[0].name;
-        guid = &CaptureDeviceList[0].guid;
+        deviceName = al_string_get_cstr(VECTOR_FRONT(CaptureDevices).name);
+        guid = &VECTOR_FRONT(CaptureDevices).guid;
     }
     else
     {
-        ALuint i;
+        const DevMap *iter;
 
-        for(i = 0;i < NumCaptureDevices;i++)
-        {
-            if(strcmp(deviceName, CaptureDeviceList[i].name) == 0)
-            {
-                guid = &CaptureDeviceList[i].guid;
-                break;
-            }
-        }
-        if(i == NumCaptureDevices)
+#define MATCH_NAME(i)  (al_string_cmp_cstr((i)->name, deviceName) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
+#undef MATCH_NAME
+        if(iter == VECTOR_ITER_END(CaptureDevices))
             return ALC_INVALID_VALUE;
+        guid = &iter->guid;
     }
 
     switch(device->FmtType)
@@ -712,16 +719,8 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
             break;
     }
 
-    //Initialise requested device
-    data = calloc(1, sizeof(DSoundCaptureData));
-    if(!data)
-        return ALC_OUT_OF_MEMORY;
-
-    hr = DS_OK;
-
     //DirectSoundCapture Init code
-    if(SUCCEEDED(hr))
-        hr = DirectSoundCaptureCreate(guid, &data->DSC, NULL);
+    hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL);
     if(SUCCEEDED(hr))
     {
         memset(&InputType, 0, sizeof(InputType));
@@ -806,12 +805,12 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
         DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign;
         DSCBDescription.lpwfxFormat = &InputType.Format;
 
-        hr = IDirectSoundCapture_CreateCaptureBuffer(data->DSC, &DSCBDescription, &data->DSCbuffer, NULL);
+        hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL);
     }
     if(SUCCEEDED(hr))
     {
-         data->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates);
-         if(data->Ring == NULL)
+         self->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates);
+         if(self->Ring == NULL)
              hr = DSERR_OUTOFMEMORY;
     }
 
@@ -819,218 +818,237 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName)
     {
         ERR("Device init failed: 0x%08lx\n", hr);
 
-        DestroyRingBuffer(data->Ring);
-        data->Ring = NULL;
-        if(data->DSCbuffer != NULL)
-            IDirectSoundCaptureBuffer_Release(data->DSCbuffer);
-        data->DSCbuffer = NULL;
-        if(data->DSC)
-            IDirectSoundCapture_Release(data->DSC);
-        data->DSC = NULL;
+        DestroyRingBuffer(self->Ring);
+        self->Ring = NULL;
+        if(self->DSCbuffer != NULL)
+            IDirectSoundCaptureBuffer_Release(self->DSCbuffer);
+        self->DSCbuffer = NULL;
+        if(self->DSC)
+            IDirectSoundCapture_Release(self->DSC);
+        self->DSC = NULL;
 
-        free(data);
         return ALC_INVALID_VALUE;
     }
 
-    data->BufferBytes = DSCBDescription.dwBufferBytes;
+    self->BufferBytes = DSCBDescription.dwBufferBytes;
     SetDefaultWFXChannelOrder(device);
 
-    device->DeviceName = strdup(deviceName);
-    device->ExtraData = data;
+    al_string_copy_cstr(&device->DeviceName, deviceName);
 
     return ALC_NO_ERROR;
 }
 
-static void DSoundCloseCapture(ALCdevice *device)
+static void ALCdsoundCapture_close(ALCdsoundCapture *self)
 {
-    DSoundCaptureData *data = device->ExtraData;
+    DestroyRingBuffer(self->Ring);
+    self->Ring = NULL;
 
-    DestroyRingBuffer(data->Ring);
-    data->Ring = NULL;
-
-    if(data->DSCbuffer != NULL)
+    if(self->DSCbuffer != NULL)
     {
-        IDirectSoundCaptureBuffer_Stop(data->DSCbuffer);
-        IDirectSoundCaptureBuffer_Release(data->DSCbuffer);
-        data->DSCbuffer = NULL;
+        IDirectSoundCaptureBuffer_Stop(self->DSCbuffer);
+        IDirectSoundCaptureBuffer_Release(self->DSCbuffer);
+        self->DSCbuffer = NULL;
     }
 
-    IDirectSoundCapture_Release(data->DSC);
-    data->DSC = NULL;
-
-    free(data);
-    device->ExtraData = NULL;
+    IDirectSoundCapture_Release(self->DSC);
+    self->DSC = NULL;
 }
 
-static void DSoundStartCapture(ALCdevice *device)
+static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self)
 {
-    DSoundCaptureData *data = device->ExtraData;
     HRESULT hr;
 
-    hr = IDirectSoundCaptureBuffer_Start(data->DSCbuffer, DSCBSTART_LOOPING);
+    hr = IDirectSoundCaptureBuffer_Start(self->DSCbuffer, DSCBSTART_LOOPING);
     if(FAILED(hr))
     {
         ERR("start failed: 0x%08lx\n", hr);
-        aluHandleDisconnect(device);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice);
+        return ALC_FALSE;
     }
+
+    return ALC_TRUE;
 }
 
-static void DSoundStopCapture(ALCdevice *device)
+static void ALCdsoundCapture_stop(ALCdsoundCapture *self)
 {
-    DSoundCaptureData *data = device->ExtraData;
     HRESULT hr;
 
-    hr = IDirectSoundCaptureBuffer_Stop(data->DSCbuffer);
+    hr = IDirectSoundCaptureBuffer_Stop(self->DSCbuffer);
     if(FAILED(hr))
     {
         ERR("stop failed: 0x%08lx\n", hr);
-        aluHandleDisconnect(device);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice);
     }
 }
 
-static ALCenum DSoundCaptureSamples(ALCdevice *Device, ALCvoid *pBuffer, ALCuint lSamples)
+static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples)
 {
-    DSoundCaptureData *data = Device->ExtraData;
-    ReadRingBuffer(data->Ring, pBuffer, lSamples);
+    ReadRingBuffer(self->Ring, buffer, samples);
     return ALC_NO_ERROR;
 }
 
-static ALCuint DSoundAvailableSamples(ALCdevice *Device)
+static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
 {
-    DSoundCaptureData *data = Device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     DWORD ReadCursor, LastCursor, BufferBytes, NumBytes;
-    VOID *ReadPtr1, *ReadPtr2;
+    void *ReadPtr1, *ReadPtr2;
     DWORD ReadCnt1,  ReadCnt2;
     DWORD FrameSize;
     HRESULT hr;
 
-    if(!Device->Connected)
+    if(!device->Connected)
         goto done;
 
-    FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
-    BufferBytes = data->BufferBytes;
-    LastCursor = data->Cursor;
+    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    BufferBytes = self->BufferBytes;
+    LastCursor = self->Cursor;
 
-    hr = IDirectSoundCaptureBuffer_GetCurrentPosition(data->DSCbuffer, NULL, &ReadCursor);
+    hr = IDirectSoundCaptureBuffer_GetCurrentPosition(self->DSCbuffer, NULL, &ReadCursor);
     if(SUCCEEDED(hr))
     {
         NumBytes = (ReadCursor-LastCursor + BufferBytes) % BufferBytes;
         if(NumBytes == 0)
             goto done;
-        hr = IDirectSoundCaptureBuffer_Lock(data->DSCbuffer, LastCursor, NumBytes,
+        hr = IDirectSoundCaptureBuffer_Lock(self->DSCbuffer, LastCursor, NumBytes,
                                             &ReadPtr1, &ReadCnt1,
                                             &ReadPtr2, &ReadCnt2, 0);
     }
     if(SUCCEEDED(hr))
     {
-        WriteRingBuffer(data->Ring, ReadPtr1, ReadCnt1/FrameSize);
+        WriteRingBuffer(self->Ring, ReadPtr1, ReadCnt1/FrameSize);
         if(ReadPtr2 != NULL)
-            WriteRingBuffer(data->Ring, ReadPtr2, ReadCnt2/FrameSize);
-        hr = IDirectSoundCaptureBuffer_Unlock(data->DSCbuffer,
+            WriteRingBuffer(self->Ring, ReadPtr2, ReadCnt2/FrameSize);
+        hr = IDirectSoundCaptureBuffer_Unlock(self->DSCbuffer,
                                               ReadPtr1, ReadCnt1,
                                               ReadPtr2, ReadCnt2);
-        data->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes;
+        self->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes;
     }
 
     if(FAILED(hr))
     {
         ERR("update failed: 0x%08lx\n", hr);
-        aluHandleDisconnect(Device);
+        aluHandleDisconnect(device);
     }
 
 done:
-    return RingBufferSize(data->Ring);
+    return RingBufferSize(self->Ring);
 }
 
 
-static const BackendFuncs DSoundFuncs = {
-    DSoundOpenPlayback,
-    DSoundClosePlayback,
-    DSoundResetPlayback,
-    DSoundStartPlayback,
-    DSoundStopPlayback,
-    DSoundOpenCapture,
-    DSoundCloseCapture,
-    DSoundStartCapture,
-    DSoundStopCapture,
-    DSoundCaptureSamples,
-    DSoundAvailableSamples,
-    ALCdevice_GetLatencyDefault
-};
+static inline void AppendAllDevicesList2(const DevMap *entry)
+{ AppendAllDevicesList(al_string_get_cstr(entry->name)); }
+static inline void AppendCaptureDeviceList2(const DevMap *entry)
+{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); }
+
+typedef struct ALCdsoundBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCdsoundBackendFactory;
+#define ALCDSOUNDBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCdsoundBackendFactory, ALCbackendFactory) } }
+
+ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void);
+
+static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory *self);
+static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory *self);
+static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory *self, ALCbackend_Type type);
+static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCdsoundBackendFactory);
 
 
-ALCboolean alcDSoundInit(BackendFuncs *FuncList)
+ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void)
 {
+    static ALCdsoundBackendFactory factory = ALCDSOUNDBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}
+
+
+static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory* UNUSED(self))
+{
+    VECTOR_INIT(PlaybackDevices);
+    VECTOR_INIT(CaptureDevices);
+
     if(!DSoundLoad())
         return ALC_FALSE;
-    *FuncList = DSoundFuncs;
     return ALC_TRUE;
 }
 
-void alcDSoundDeinit(void)
+static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory* UNUSED(self))
 {
-    ALuint i;
+    clear_devlist(&PlaybackDevices);
+    VECTOR_DEINIT(PlaybackDevices);
 
-    for(i = 0;i < NumPlaybackDevices;++i)
-        free(PlaybackDeviceList[i].name);
-    free(PlaybackDeviceList);
-    PlaybackDeviceList = NULL;
-    NumPlaybackDevices = 0;
-
-    for(i = 0;i < NumCaptureDevices;++i)
-        free(CaptureDeviceList[i].name);
-    free(CaptureDeviceList);
-    CaptureDeviceList = NULL;
-    NumCaptureDevices = 0;
+    clear_devlist(&CaptureDevices);
+    VECTOR_DEINIT(CaptureDevices);
 
+#ifdef HAVE_DYNLOAD
     if(ds_handle)
         CloseLib(ds_handle);
     ds_handle = NULL;
+#endif
+}
+
+static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback || type == ALCbackend_Capture)
+        return ALC_TRUE;
+    return ALC_FALSE;
 }
 
-void alcDSoundProbe(enum DevProbe type)
+static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), enum DevProbe type)
 {
     HRESULT hr, hrcom;
-    ALuint i;
 
+    /* Initialize COM to prevent name truncation */
+    hrcom = CoInitialize(NULL);
     switch(type)
     {
         case ALL_DEVICE_PROBE:
-            for(i = 0;i < NumPlaybackDevices;++i)
-                free(PlaybackDeviceList[i].name);
-            free(PlaybackDeviceList);
-            PlaybackDeviceList = NULL;
-            NumPlaybackDevices = 0;
-
-            hr = DirectSoundEnumerateA(DSoundEnumPlaybackDevices, NULL);
+            clear_devlist(&PlaybackDevices);
+            hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices);
             if(FAILED(hr))
-                ERR("Error enumerating DirectSound playback devices (%#x)!\n", (unsigned int)hr);
-            else
-            {
-                for(i = 0;i < NumPlaybackDevices;i++)
-                    AppendAllDevicesList(PlaybackDeviceList[i].name);
-            }
+                ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr);
+            VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2);
             break;
 
         case CAPTURE_DEVICE_PROBE:
-            for(i = 0;i < NumCaptureDevices;++i)
-                free(CaptureDeviceList[i].name);
-            free(CaptureDeviceList);
-            CaptureDeviceList = NULL;
-            NumCaptureDevices = 0;
-
-            /* Initialize COM to prevent name truncation */
-            hrcom = CoInitialize(NULL);
-            hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL);
+            clear_devlist(&CaptureDevices);
+            hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices);
             if(FAILED(hr))
-                ERR("Error enumerating DirectSound capture devices (%#x)!\n", (unsigned int)hr);
-            else
-            {
-                for(i = 0;i < NumCaptureDevices;i++)
-                    AppendCaptureDeviceList(CaptureDeviceList[i].name);
-            }
-            if(SUCCEEDED(hrcom))
-                CoUninitialize();
+                ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr);
+            VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2);
             break;
     }
+    if(SUCCEEDED(hrcom))
+        CoUninitialize();
+}
+
+static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCdsoundPlayback *backend;
+
+        backend = ALCdsoundPlayback_New(sizeof(*backend));
+        if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
+
+        ALCdsoundPlayback_Construct(backend, device);
+
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    if(type == ALCbackend_Capture)
+    {
+        ALCdsoundCapture *backend;
+
+        backend = ALCdsoundCapture_New(sizeof(*backend));
+        if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
+
+        ALCdsoundCapture_Construct(backend, device);
+
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
 }

+ 12 - 14
jni/openal-soft-android/Alc/backends/loopback.c → jni/openal-soft-1.16.0/Alc/backends/loopback.c

@@ -44,7 +44,7 @@ static DECLARE_FORWARD(ALCloopback, ALCbackend, ALCuint, availableSamples)
 static DECLARE_FORWARD(ALCloopback, ALCbackend, ALint64, getLatency)
 static DECLARE_FORWARD(ALCloopback, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCloopback, ALCbackend, void, unlock)
-static void ALCloopback_Delete(ALCloopback *self);
+DECLARE_DEFAULT_ALLOCATORS(ALCloopback)
 DEFINE_ALCBACKEND_VTABLE(ALCloopback);
 
 
@@ -59,7 +59,7 @@ static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
 
-    device->DeviceName = strdup(name);
+    al_string_copy_cstr(&device->DeviceName, name);
     return ALC_NO_ERROR;
 }
 
@@ -83,12 +83,6 @@ static void ALCloopback_stop(ALCloopback* UNUSED(self))
 }
 
 
-static void ALCloopback_Delete(ALCloopback *self)
-{
-    free(self);
-}
-
-
 typedef struct ALCloopbackFactory {
     DERIVE_FROM_TYPE(ALCbackendFactory);
 } ALCloopbackFactory;
@@ -127,14 +121,18 @@ static void ALCloopbackFactory_probe(ALCloopbackFactory* UNUSED(self), enum DevP
 
 static ALCbackend* ALCloopbackFactory_createBackend(ALCloopbackFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
 {
-    ALCloopback *backend;
+    if(type == ALCbackend_Loopback)
+    {
+        ALCloopback *backend;
 
-    assert(type == ALCbackend_Loopback);
+        backend = ALCloopback_New(sizeof(*backend));
+        if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
 
-    backend = calloc(1, sizeof(*backend));
-    if(!backend) return NULL;
+        ALCloopback_Construct(backend, device);
 
-    ALCloopback_Construct(backend, device);
+        return STATIC_CAST(ALCbackend, backend);
+    }
 
-    return STATIC_CAST(ALCbackend, backend);
+    return NULL;
 }

File diff suppressed because it is too large
+ 615 - 337
jni/openal-soft-1.16.0/Alc/backends/mmdevapi.c


+ 48 - 42
jni/openal-soft-android/Alc/backends/null.c → jni/openal-soft-1.16.0/Alc/backends/null.c

@@ -37,11 +37,10 @@ typedef struct ALCnullBackend {
     DERIVE_FROM_TYPE(ALCbackend);
 
     volatile int killNow;
-    althread_t thread;
+    althrd_t thread;
 } ALCnullBackend;
-DECLARE_ALCBACKEND_VTABLE(ALCnullBackend);
 
-static ALuint ALCnullBackend_mixerProc(ALvoid *ptr);
+static int ALCnullBackend_mixerProc(void *ptr);
 
 static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device);
 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, Destruct)
@@ -55,6 +54,10 @@ static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALCuint, availableSamples)
 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALint64, getLatency)
 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCnullBackend)
+
+DEFINE_ALCBACKEND_VTABLE(ALCnullBackend);
+
 
 static const ALCchar nullDevice[] = "No Output";
 
@@ -66,42 +69,49 @@ static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device)
 }
 
 
-static ALuint ALCnullBackend_mixerProc(ALvoid *ptr)
+static int ALCnullBackend_mixerProc(void *ptr)
 {
     ALCnullBackend *self = (ALCnullBackend*)ptr;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    ALuint now, start;
+    struct timespec now, start;
     ALuint64 avail, done;
+    const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 /
+                                 device->Frequency / 2);
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     done = 0;
-    start = timeGetTime();
+    if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC)
+    {
+        ERR("Failed to get starting time\n");
+        return 1;
+    }
     while(!self->killNow && device->Connected)
     {
-        now = timeGetTime();
+        if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
+        {
+            ERR("Failed to get current time\n");
+            return 1;
+        }
 
-        avail = (ALuint64)(now-start) * device->Frequency / 1000;
+        avail  = (now.tv_sec - start.tv_sec) * device->Frequency;
+        avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000;
         if(avail < done)
         {
-            /* Timer wrapped (50 days???). Add the remainder of the cycle to
-             * the available count and reset the number of samples done */
-            avail += (U64(1)<<32)*device->Frequency/1000 - done;
-            done = 0;
+            /* Oops, time skipped backwards. Reset the number of samples done
+             * with one update available since we (likely) just came back from
+             * sleeping. */
+            done = avail - device->UpdateSize;
         }
+
         if(avail-done < device->UpdateSize)
+            al_nssleep(0, restTime);
+        else while(avail-done >= device->UpdateSize)
         {
-            ALuint restTime = (ALuint)((device->UpdateSize - (avail-done)) * 1000 /
-                                       device->Frequency);
-            Sleep(restTime);
-            continue;
-        }
-
-        do {
             aluMixData(device, NULL, device->UpdateSize);
             done += device->UpdateSize;
-        } while(avail-done >= device->UpdateSize);
+        }
     }
 
     return 0;
@@ -118,7 +128,7 @@ static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name)
         return ALC_INVALID_VALUE;
 
     device = STATIC_CAST(ALCbackend, self)->mDevice;
-    device->DeviceName = strdup(name);
+    al_string_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 }
@@ -135,31 +145,23 @@ static ALCboolean ALCnullBackend_reset(ALCnullBackend *self)
 
 static ALCboolean ALCnullBackend_start(ALCnullBackend *self)
 {
-    if(!StartThread(&self->thread, ALCnullBackend_mixerProc, self))
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCnullBackend_mixerProc, self) != althrd_success)
         return ALC_FALSE;
     return ALC_TRUE;
 }
 
 static void ALCnullBackend_stop(ALCnullBackend *self)
 {
-    if(!self->thread)
+    int res;
+
+    if(self->killNow)
         return;
 
     self->killNow = 1;
-    StopThread(self->thread);
-    self->thread = NULL;
-
-    self->killNow = 0;
-}
-
-
-static void ALCnullBackend_Delete(ALCnullBackend *self)
-{
-    free(self);
+    althrd_join(self->thread, &res);
 }
 
-DEFINE_ALCBACKEND_VTABLE(ALCnullBackend);
-
 
 typedef struct ALCnullBackendFactory {
     DERIVE_FROM_TYPE(ALCbackendFactory);
@@ -209,14 +211,18 @@ static void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enu
 
 static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
 {
-    ALCnullBackend *backend;
+    if(type == ALCbackend_Playback)
+    {
+        ALCnullBackend *backend;
 
-    assert(type == ALCbackend_Playback);
+        backend = ALCnullBackend_New(sizeof(*backend));
+        if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
 
-    backend = calloc(1, sizeof(*backend));
-    if(!backend) return NULL;
+        ALCnullBackend_Construct(backend, device);
 
-    ALCnullBackend_Construct(backend, device);
+        return STATIC_CAST(ALCbackend, backend);
+    }
 
-    return STATIC_CAST(ALCbackend, backend);
+    return NULL;
 }

+ 21 - 74
jni/openal-soft-android/Alc/backends/opensl.c → jni/openal-soft-1.16.0/Alc/backends/opensl.c

@@ -28,62 +28,9 @@
 
 
 #include <SLES/OpenSLES.h>
-#if 1
 #include <SLES/OpenSLES_Android.h>
-#else
-extern SLAPIENTRY const SLInterfaceID SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
-
-struct SLAndroidSimpleBufferQueueItf_;
-typedef const struct SLAndroidSimpleBufferQueueItf_ * const * SLAndroidSimpleBufferQueueItf;
-
-typedef void (*slAndroidSimpleBufferQueueCallback)(SLAndroidSimpleBufferQueueItf caller, void *pContext);
-
-typedef struct SLAndroidSimpleBufferQueueState_ {
-    SLuint32 count;
-    SLuint32 index;
-} SLAndroidSimpleBufferQueueState;
-
-
-struct SLAndroidSimpleBufferQueueItf_ {
-    SLresult (*Enqueue) (
-        SLAndroidSimpleBufferQueueItf self,
-        const void *pBuffer,
-        SLuint32 size
-    );
-    SLresult (*Clear) (
-        SLAndroidSimpleBufferQueueItf self
-    );
-    SLresult (*GetState) (
-        SLAndroidSimpleBufferQueueItf self,
-        SLAndroidSimpleBufferQueueState *pState
-    );
-    SLresult (*RegisterCallback) (
-        SLAndroidSimpleBufferQueueItf self,
-        slAndroidSimpleBufferQueueCallback callback,
-        void* pContext
-    );
-};
-
-#define SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE ((SLuint32) 0x800007BD)
-
-typedef struct SLDataLocator_AndroidSimpleBufferQueue {
-    SLuint32 locatorType;
-    SLuint32 numBuffers;
-} SLDataLocator_AndroidSimpleBufferQueue;
-
-#endif
 
 /* Helper macros */
-#define SLObjectItf_Realize(a,b)        ((*(a))->Realize((a),(b)))
-#define SLObjectItf_GetInterface(a,b,c) ((*(a))->GetInterface((a),(b),(c)))
-#define SLObjectItf_Destroy(a)          ((*(a))->Destroy((a)))
-
-#define SLEngineItf_CreateOutputMix(a,b,c,d,e)       ((*(a))->CreateOutputMix((a),(b),(c),(d),(e)))
-#define SLEngineItf_CreateAudioPlayer(a,b,c,d,e,f,g) ((*(a))->CreateAudioPlayer((a),(b),(c),(d),(e),(f),(g)))
-
-#define SLPlayItf_SetPlayState(a,b) ((*(a))->SetPlayState((a),(b)))
-
-/* Should start using these generic callers instead of the name-specific ones above. */
 #define VCALL(obj, func)  ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
 #define VCALL0(obj, func)  ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
 
@@ -186,7 +133,7 @@ static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *context)
     buf = (ALbyte*)data->buffer + data->curBuffer*data->bufferSize;
     aluMixData(Device, buf, data->bufferSize/data->frameSize);
 
-    result = (*bq)->Enqueue(bq, buf, data->bufferSize);
+    result = VCALL(bq,Enqueue)(buf, data->bufferSize);
     PRINTERR(result, "bq->Enqueue");
 
     data->curBuffer = (data->curBuffer+1) % Device->NumUpdates;
@@ -212,33 +159,33 @@ static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName
     PRINTERR(result, "slCreateEngine");
     if(SL_RESULT_SUCCESS == result)
     {
-        result = SLObjectItf_Realize(data->engineObject, SL_BOOLEAN_FALSE);
+        result = VCALL(data->engineObject,Realize)(SL_BOOLEAN_FALSE);
         PRINTERR(result, "engine->Realize");
     }
     if(SL_RESULT_SUCCESS == result)
     {
-        result = SLObjectItf_GetInterface(data->engineObject, SL_IID_ENGINE, &data->engine);
+        result = VCALL(data->engineObject,GetInterface)(SL_IID_ENGINE, &data->engine);
         PRINTERR(result, "engine->GetInterface");
     }
     if(SL_RESULT_SUCCESS == result)
     {
-        result = SLEngineItf_CreateOutputMix(data->engine, &data->outputMix, 0, NULL, NULL);
+        result = VCALL(data->engine,CreateOutputMix)(&data->outputMix, 0, NULL, NULL);
         PRINTERR(result, "engine->CreateOutputMix");
     }
     if(SL_RESULT_SUCCESS == result)
     {
-        result = SLObjectItf_Realize(data->outputMix, SL_BOOLEAN_FALSE);
+        result = VCALL(data->outputMix,Realize)(SL_BOOLEAN_FALSE);
         PRINTERR(result, "outputMix->Realize");
     }
 
     if(SL_RESULT_SUCCESS != result)
     {
         if(data->outputMix != NULL)
-            SLObjectItf_Destroy(data->outputMix);
+            VCALL0(data->outputMix,Destroy)();
         data->outputMix = NULL;
 
         if(data->engineObject != NULL)
-            SLObjectItf_Destroy(data->engineObject);
+            VCALL0(data->engineObject,Destroy)();
         data->engineObject = NULL;
         data->engine = NULL;
 
@@ -246,7 +193,7 @@ static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName
         return ALC_INVALID_VALUE;
     }
 
-    Device->DeviceName = strdup(deviceName);
+    al_string_copy_cstr(&Device->DeviceName, deviceName);
     Device->ExtraData = data;
 
     return ALC_NO_ERROR;
@@ -258,13 +205,13 @@ static void opensl_close_playback(ALCdevice *Device)
     osl_data *data = Device->ExtraData;
 
     if(data->bufferQueueObject != NULL)
-        SLObjectItf_Destroy(data->bufferQueueObject);
+        VCALL0(data->bufferQueueObject,Destroy)();
     data->bufferQueueObject = NULL;
 
-    SLObjectItf_Destroy(data->outputMix);
+    VCALL0(data->outputMix,Destroy)();
     data->outputMix = NULL;
 
-    SLObjectItf_Destroy(data->engineObject);
+    VCALL0(data->engineObject,Destroy)();
     data->engineObject = NULL;
     data->engine = NULL;
 
@@ -321,21 +268,21 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device)
 
 
     if(data->bufferQueueObject != NULL)
-        SLObjectItf_Destroy(data->bufferQueueObject);
+        VCALL0(data->bufferQueueObject,Destroy)();
     data->bufferQueueObject = NULL;
 
-    result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req);
+    result = VCALL(data->engine,CreateAudioPlayer)(&data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req);
     PRINTERR(result, "engine->CreateAudioPlayer");
     if(SL_RESULT_SUCCESS == result)
     {
-        result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE);
+        result = VCALL(data->bufferQueueObject,Realize)(SL_BOOLEAN_FALSE);
         PRINTERR(result, "bufferQueue->Realize");
     }
 
     if(SL_RESULT_SUCCESS != result)
     {
         if(data->bufferQueueObject != NULL)
-            SLObjectItf_Destroy(data->bufferQueueObject);
+            VCALL0(data->bufferQueueObject,Destroy)();
         data->bufferQueueObject = NULL;
 
         return ALC_FALSE;
@@ -352,11 +299,11 @@ static ALCboolean opensl_start_playback(ALCdevice *Device)
     SLresult result;
     ALuint i;
 
-    result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue);
+    result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue);
     PRINTERR(result, "bufferQueue->GetInterface");
     if(SL_RESULT_SUCCESS == result)
     {
-        result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device);
+        result = VCALL(bufferQueue,RegisterCallback)(opensl_callback, Device);
         PRINTERR(result, "bufferQueue->RegisterCallback");
     }
     if(SL_RESULT_SUCCESS == result)
@@ -376,26 +323,26 @@ static ALCboolean opensl_start_playback(ALCdevice *Device)
         if(SL_RESULT_SUCCESS == result)
         {
             ALvoid *buf = (ALbyte*)data->buffer + i*data->bufferSize;
-            result = (*bufferQueue)->Enqueue(bufferQueue, buf, data->bufferSize);
+            result = VCALL(bufferQueue,Enqueue)(buf, data->bufferSize);
             PRINTERR(result, "bufferQueue->Enqueue");
         }
     }
     data->curBuffer = 0;
     if(SL_RESULT_SUCCESS == result)
     {
-        result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player);
+        result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_PLAY, &player);
         PRINTERR(result, "bufferQueue->GetInterface");
     }
     if(SL_RESULT_SUCCESS == result)
     {
-        result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING);
+        result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING);
         PRINTERR(result, "player->SetPlayState");
     }
 
     if(SL_RESULT_SUCCESS != result)
     {
         if(data->bufferQueueObject != NULL)
-            SLObjectItf_Destroy(data->bufferQueueObject);
+            VCALL0(data->bufferQueueObject,Destroy)();
         data->bufferQueueObject = NULL;
 
         free(data->buffer);

+ 29 - 35
jni/openal-soft-android/Alc/backends/oss.c → jni/openal-soft-1.16.0/Alc/backends/oss.c

@@ -78,10 +78,10 @@ typedef struct ALCplaybackOSS {
     int data_size;
 
     volatile int killNow;
-    althread_t thread;
+    althrd_t thread;
 } ALCplaybackOSS;
 
-static ALuint ALCplaybackOSS_mixerProc(ALvoid *ptr);
+static int ALCplaybackOSS_mixerProc(void *ptr);
 
 static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device);
 static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, Destruct)
@@ -95,11 +95,11 @@ static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALCuint, availableSamples)
 static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALint64, getLatency)
 static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, unlock)
-static void ALCplaybackOSS_Delete(ALCplaybackOSS *self);
+DECLARE_DEFAULT_ALLOCATORS(ALCplaybackOSS)
 DEFINE_ALCBACKEND_VTABLE(ALCplaybackOSS);
 
 
-static ALuint ALCplaybackOSS_mixerProc(ALvoid *ptr)
+static int ALCplaybackOSS_mixerProc(void *ptr)
 {
     ALCplaybackOSS *self = (ALCplaybackOSS*)ptr;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -107,7 +107,7 @@ static ALuint ALCplaybackOSS_mixerProc(ALvoid *ptr)
     ssize_t wrote;
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
 
@@ -131,7 +131,7 @@ static ALuint ALCplaybackOSS_mixerProc(ALvoid *ptr)
                     break;
                 }
 
-                Sleep(1);
+                al_nssleep(0, 1000000);
                 continue;
             }
 
@@ -168,7 +168,7 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name)
         return ALC_INVALID_VALUE;
     }
 
-    device->DeviceName = strdup(name);
+    al_string_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 }
@@ -275,7 +275,8 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self)
     self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
     self->mix_data = calloc(1, self->data_size);
 
-    if(!StartThread(&self->thread, ALCplaybackOSS_mixerProc, self))
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCplaybackOSS_mixerProc, self) != althrd_success)
     {
         free(self->mix_data);
         self->mix_data = NULL;
@@ -287,14 +288,14 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self)
 
 static void ALCplaybackOSS_stop(ALCplaybackOSS *self)
 {
-    if(!self->thread)
+    int res;
+
+    if(self->killNow)
         return;
 
     self->killNow = 1;
-    StopThread(self->thread);
-    self->thread = NULL;
+    althrd_join(self->thread, &res);
 
-    self->killNow = 0;
     if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0)
         ERR("Error resetting device: %s\n", strerror(errno));
 
@@ -302,11 +303,6 @@ static void ALCplaybackOSS_stop(ALCplaybackOSS *self)
     self->mix_data = NULL;
 }
 
-static void ALCplaybackOSS_Delete(ALCplaybackOSS *self)
-{
-    free(self);
-}
-
 
 typedef struct ALCcaptureOSS {
     DERIVE_FROM_TYPE(ALCbackend);
@@ -320,10 +316,10 @@ typedef struct ALCcaptureOSS {
     int doCapture;
 
     volatile int killNow;
-    althread_t thread;
+    althrd_t thread;
 } ALCcaptureOSS;
 
-static ALuint ALCcaptureOSS_recordProc(ALvoid *ptr);
+static int ALCcaptureOSS_recordProc(void *ptr);
 
 static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device);
 static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, Destruct)
@@ -337,11 +333,11 @@ static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self);
 static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALint64, getLatency)
 static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, unlock)
-static void ALCcaptureOSS_Delete(ALCcaptureOSS *self);
+DECLARE_DEFAULT_ALLOCATORS(ALCcaptureOSS)
 DEFINE_ALCBACKEND_VTABLE(ALCcaptureOSS);
 
 
-static ALuint ALCcaptureOSS_recordProc(ALvoid *ptr)
+static int ALCcaptureOSS_recordProc(void *ptr)
 {
     ALCcaptureOSS *self = (ALCcaptureOSS*)ptr;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -349,7 +345,7 @@ static ALuint ALCcaptureOSS_recordProc(ALvoid *ptr)
     int amt;
 
     SetRTPriority();
-    SetThreadName("alsoft-record");
+    althrd_setname(althrd_current(), "alsoft-record");
 
     frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
 
@@ -366,7 +362,7 @@ static ALuint ALCcaptureOSS_recordProc(ALvoid *ptr)
         }
         if(amt == 0)
         {
-            Sleep(1);
+            al_nssleep(0, 1000000);
             continue;
         }
         if(self->doCapture)
@@ -488,7 +484,8 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
     self->data_size = info.fragsize;
     self->read_data = calloc(1, self->data_size);
 
-    if(!StartThread(&self->thread, ALCcaptureOSS_recordProc, self))
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success)
     {
         device->ExtraData = NULL;
         close(self->fd);
@@ -496,16 +493,17 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
         return ALC_OUT_OF_MEMORY;
     }
 
-    device->DeviceName = strdup(name);
+    al_string_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 }
 
 static void ALCcaptureOSS_close(ALCcaptureOSS *self)
 {
+    int res;
+
     self->killNow = 1;
-    StopThread(self->thread);
-    self->killNow = 0;
+    althrd_join(self->thread, &res);
 
     close(self->fd);
     self->fd = -1;
@@ -539,12 +537,6 @@ static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self)
     return RingBufferSize(self->ring);
 }
 
-void ALCcaptureOSS_Delete(ALCcaptureOSS *self)
-{
-    free(self);
-}
-
-
 
 typedef struct ALCossBackendFactory {
     DERIVE_FROM_TYPE(ALCbackendFactory);
@@ -615,8 +607,9 @@ ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory* UNUSED(self
     {
         ALCplaybackOSS *backend;
 
-        backend = calloc(1, sizeof(*backend));
+        backend = ALCplaybackOSS_New(sizeof(*backend));
         if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
 
         ALCplaybackOSS_Construct(backend, device);
 
@@ -626,8 +619,9 @@ ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory* UNUSED(self
     {
         ALCcaptureOSS *backend;
 
-        backend = calloc(1, sizeof(*backend));
+        backend = ALCcaptureOSS_New(sizeof(*backend));
         if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
 
         ALCcaptureOSS_Construct(backend, device);
 

+ 6 - 3
jni/openal-soft-android/Alc/backends/portaudio.c → jni/openal-soft-1.16.0/Alc/backends/portaudio.c

@@ -45,6 +45,7 @@ MAKE_FUNC(Pa_StopStream);
 MAKE_FUNC(Pa_OpenStream);
 MAKE_FUNC(Pa_CloseStream);
 MAKE_FUNC(Pa_GetDefaultOutputDevice);
+MAKE_FUNC(Pa_GetDefaultInputDevice);
 MAKE_FUNC(Pa_GetStreamInfo);
 #undef MAKE_FUNC
 
@@ -56,6 +57,7 @@ MAKE_FUNC(Pa_GetStreamInfo);
 #define Pa_OpenStream                  pPa_OpenStream
 #define Pa_CloseStream                 pPa_CloseStream
 #define Pa_GetDefaultOutputDevice      pPa_GetDefaultOutputDevice
+#define Pa_GetDefaultInputDevice       pPa_GetDefaultInputDevice
 #define Pa_GetStreamInfo               pPa_GetStreamInfo
 #endif
 
@@ -97,6 +99,7 @@ static ALCboolean pa_load(void)
         LOAD_FUNC(Pa_OpenStream);
         LOAD_FUNC(Pa_CloseStream);
         LOAD_FUNC(Pa_GetDefaultOutputDevice);
+        LOAD_FUNC(Pa_GetDefaultInputDevice);
         LOAD_FUNC(Pa_GetStreamInfo);
 #undef LOAD_FUNC
 
@@ -212,7 +215,7 @@ retry_open:
     }
 
     device->ExtraData = data;
-    device->DeviceName = strdup(deviceName);
+    al_string_copy_cstr(&device->DeviceName, deviceName);
 
     return ALC_NO_ERROR;
 }
@@ -318,7 +321,7 @@ static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
     data->params.device = -1;
     if(!ConfigValueInt("port", "capture", &data->params.device) ||
        data->params.device < 0)
-        data->params.device = Pa_GetDefaultOutputDevice();
+        data->params.device = Pa_GetDefaultInputDevice();
     data->params.suggestedLatency = 0.0f;
     data->params.hostApiSpecificStreamInfo = NULL;
 
@@ -354,7 +357,7 @@ static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
         goto error;
     }
 
-    device->DeviceName = strdup(deviceName);
+    al_string_copy_cstr(&device->DeviceName, deviceName);
 
     device->ExtraData = data;
     return ALC_NO_ERROR;

+ 175 - 186
jni/openal-soft-android/Alc/backends/pulseaudio.c → jni/openal-soft-1.16.0/Alc/backends/pulseaudio.c

@@ -306,9 +306,6 @@ static ALCboolean pulse_load(void)
 static pa_context_flags_t pulse_ctx_flags;
 static pa_proplist *prop_filter;
 
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
 
 /* PulseAudio Event Callbacks */
 static void context_state_callback(pa_context *context, void *pdata)
@@ -438,7 +435,9 @@ static void pulse_close(pa_threaded_mainloop *loop, pa_context *context,
 
     if(stream)
     {
+        pa_stream_set_state_callback(stream, NULL, NULL);
         pa_stream_set_moved_callback(stream, NULL, NULL);
+        pa_stream_set_write_callback(stream, NULL, NULL);
 #if PA_CHECK_VERSION(0,9,15)
         if(pa_stream_set_buffer_attr_callback)
             pa_stream_set_buffer_attr_callback(stream, NULL, NULL);
@@ -458,20 +457,27 @@ static void pulse_close(pa_threaded_mainloop *loop, pa_context *context,
 
 
 typedef struct {
-    char *name;
-    char *device_name;
+    al_string name;
+    al_string device_name;
 } DevMap;
+TYPEDEF_VECTOR(DevMap, vector_DevMap)
+
+static vector_DevMap PlaybackDevices;
+static vector_DevMap CaptureDevices;
 
-static DevMap *allDevNameMap;
-static ALuint numDevNames;
-static DevMap *allCaptureDevNameMap;
-static ALuint numCaptureDevNames;
+static void clear_devlist(vector_DevMap *list)
+{
+#define DEINIT_STRS(i)  (AL_STRING_DEINIT((i)->name),AL_STRING_DEINIT((i)->device_name))
+    VECTOR_FOR_EACH(DevMap, *list, DEINIT_STRS);
+#undef DEINIT_STRS
+    VECTOR_RESIZE(*list, 0);
+}
 
 
 typedef struct ALCpulsePlayback {
     DERIVE_FROM_TYPE(ALCbackend);
 
-    char *device_name;
+    al_string device_name;
 
     pa_buffer_attr attr;
     pa_sample_spec spec;
@@ -482,9 +488,8 @@ typedef struct ALCpulsePlayback {
     pa_context *context;
 
     volatile ALboolean killNow;
-    althread_t thread;
+    althrd_t thread;
 } ALCpulsePlayback;
-DECLARE_ALCBACKEND_VTABLE(ALCpulsePlayback);
 
 static void ALCpulsePlayback_deviceCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
 static void ALCpulsePlayback_probeDevices(void);
@@ -492,6 +497,7 @@ static void ALCpulsePlayback_probeDevices(void);
 static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata);
 static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata);
 static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata);
+static void ALCpulsePlayback_streamWriteCallback(pa_stream *p, size_t nbytes, void *userdata);
 static void ALCpulsePlayback_sinkInfoCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
 static void ALCpulsePlayback_sinkNameCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata);
 static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata);
@@ -499,10 +505,10 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, pa_thr
                                                  pa_context *context, pa_stream_flags_t flags,
                                                  pa_buffer_attr *attr, pa_sample_spec *spec,
                                                  pa_channel_map *chanmap);
-static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr);
+static int ALCpulsePlayback_mixerProc(void *ptr);
 
 static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, void, Destruct)
+static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self);
 static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name);
 static void ALCpulsePlayback_close(ALCpulsePlayback *self);
 static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self);
@@ -510,22 +516,34 @@ static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self);
 static void ALCpulsePlayback_stop(ALCpulsePlayback *self);
 static DECLARE_FORWARD2(ALCpulsePlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
 static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, ALCuint, availableSamples)
+static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self);
 static void ALCpulsePlayback_lock(ALCpulsePlayback *self);
 static void ALCpulsePlayback_unlock(ALCpulsePlayback *self);
+DECLARE_DEFAULT_ALLOCATORS(ALCpulsePlayback)
+
+DEFINE_ALCBACKEND_VTABLE(ALCpulsePlayback);
 
 
 static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCpulsePlayback, ALCbackend, self);
+
+    AL_STRING_INIT(self->device_name);
+}
+
+static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self)
+{
+    AL_STRING_DEINIT(self->device_name);
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
 
 static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
 {
     pa_threaded_mainloop *loop = pdata;
-    void *temp;
-    ALuint i;
+    const DevMap *iter;
+    DevMap entry;
 
     if(eol)
     {
@@ -533,29 +551,29 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p
         return;
     }
 
-    for(i = 0;i < numDevNames;i++)
-    {
-        if(strcmp(info->name, allDevNameMap[i].device_name) == 0)
-            return;
-    }
+#define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0)
+    VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_INFO_NAME);
+#undef MATCH_INFO_NAME
+    if(iter != VECTOR_ITER_END(PlaybackDevices))
+        return;
 
     TRACE("Got device \"%s\", \"%s\"\n", info->description, info->name);
 
-    temp = realloc(allDevNameMap, (numDevNames+1) * sizeof(*allDevNameMap));
-    if(temp)
-    {
-        allDevNameMap = temp;
-        allDevNameMap[numDevNames].name = strdup(info->description);
-        allDevNameMap[numDevNames].device_name = strdup(info->name);
-        numDevNames++;
-    }
+    AL_STRING_INIT(entry.name);
+    AL_STRING_INIT(entry.device_name);
+
+    al_string_copy_cstr(&entry.name, info->description);
+    al_string_copy_cstr(&entry.device_name, info->name);
+
+    VECTOR_PUSH_BACK(PlaybackDevices, entry);
 }
 
 static void ALCpulsePlayback_probeDevices(void)
 {
     pa_threaded_mainloop *loop;
 
-    allDevNameMap = malloc(sizeof(DevMap) * 1);
+    clear_devlist(&PlaybackDevices);
+
     if((loop=pa_threaded_mainloop_new()) &&
        pa_threaded_mainloop_start(loop) >= 0)
     {
@@ -634,6 +652,12 @@ static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata)
     pa_threaded_mainloop_signal(self->loop, 0);
 }
 
+static void ALCpulsePlayback_streamWriteCallback(pa_stream* UNUSED(p), size_t UNUSED(nbytes), void *pdata)
+{
+    ALCpulsePlayback *self = pdata;
+    pa_threaded_mainloop_signal(self->loop, 0);
+}
+
 static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
 {
     ALCpulsePlayback *self = pdata;
@@ -697,8 +721,7 @@ static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const
         return;
     }
 
-    free(device->DeviceName);
-    device->DeviceName = strdup(info->description);
+    al_string_copy_cstr(&device->DeviceName, info->description);
 }
 
 
@@ -706,10 +729,9 @@ static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata)
 {
     ALCpulsePlayback *self = pdata;
 
-    free(self->device_name);
-    self->device_name = strdup(pa_stream_get_device_name(stream));
+    al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(stream));
 
-    TRACE("Stream moved to %s\n", self->device_name);
+    TRACE("Stream moved to %s\n", al_string_get_cstr(self->device_name));
 }
 
 
@@ -754,7 +776,7 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name,
 }
 
 
-static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr)
+static int ALCpulsePlayback_mixerProc(void *ptr)
 {
     ALCpulsePlayback *self = ptr;
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
@@ -764,7 +786,7 @@ static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr)
     ssize_t len;
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     pa_threaded_mainloop_lock(self->loop);
     frame_size = pa_frame_size(&self->spec);
@@ -785,9 +807,7 @@ static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr)
                 o = pa_stream_cork(self->stream, 0, NULL, NULL);
                 if(o) pa_operation_unref(o);
             }
-            pa_threaded_mainloop_unlock(self->loop);
-            Sleep(1);
-            pa_threaded_mainloop_lock(self->loop);
+            pa_threaded_mainloop_wait(self->loop);
             continue;
         }
         len -= len%update_size;
@@ -828,21 +848,17 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name
 
     if(name)
     {
-        ALuint i;
+        const DevMap *iter;
 
-        if(!allDevNameMap)
+        if(VECTOR_SIZE(PlaybackDevices) == 0)
             ALCpulsePlayback_probeDevices();
 
-        for(i = 0;i < numDevNames;i++)
-        {
-            if(strcmp(name, allDevNameMap[i].name) == 0)
-            {
-                pulse_name = allDevNameMap[i].device_name;
-                break;
-            }
-        }
-        if(i == numDevNames)
+#define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
+#undef MATCH_NAME
+        if(iter == VECTOR_ITER_END(PlaybackDevices))
             return ALC_INVALID_VALUE;
+        pulse_name = al_string_get_cstr(iter->device_name);
     }
 
     if(!pulse_open(&self->loop, &self->context, ALCpulsePlayback_contextStateCallback, self))
@@ -859,6 +875,7 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name
     spec.rate = 44100;
     spec.channels = 2;
 
+    TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)");
     self->stream = ALCpulsePlayback_connectStream(pulse_name, self->loop, self->context,
                                                   flags, NULL, &spec, NULL);
     if(!self->stream)
@@ -871,8 +888,9 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name
     }
     pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self);
 
-    self->device_name = strdup(pa_stream_get_device_name(self->stream));
-    o = pa_context_get_sink_info_by_name(self->context, self->device_name,
+    al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream));
+    o = pa_context_get_sink_info_by_name(self->context,
+                                         al_string_get_cstr(self->device_name),
                                          ALCpulsePlayback_sinkNameCallback, self);
     wait_for_operation(o, self->loop);
 
@@ -888,16 +906,15 @@ static void ALCpulsePlayback_close(ALCpulsePlayback *self)
     self->context = NULL;
     self->stream = NULL;
 
-    free(self->device_name);
-    self->device_name = NULL;
+    al_string_clear(&self->device_name);
 }
 
 static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
     pa_stream_flags_t flags = 0;
+    const char *mapname = NULL;
     pa_channel_map chanmap;
-    const char *mapname;
     ALuint len;
 
     pa_threaded_mainloop_lock(self->loop);
@@ -917,7 +934,8 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
     if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
     {
         pa_operation *o;
-        o = pa_context_get_sink_info_by_name(self->context, self->device_name,
+        o = pa_context_get_sink_info_by_name(self->context,
+                                             al_string_get_cstr(self->device_name),
                                              ALCpulsePlayback_sinkInfoCallback, self);
         wait_for_operation(o, self->loop);
     }
@@ -964,7 +982,6 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
         return ALC_FALSE;
     }
 
-    mapname = "(invalid)";
     switch(device->FmtChans)
     {
         case DevFmtMono:
@@ -1003,9 +1020,9 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
     self->attr.tlength = self->attr.minreq * maxu(device->NumUpdates, 2);
     self->attr.maxlength = -1;
 
-    self->stream = ALCpulsePlayback_connectStream(self->device_name, self->loop,
-                                                  self->context, flags, &self->attr,
-                                                  &self->spec, &chanmap);
+    self->stream = ALCpulsePlayback_connectStream(al_string_get_cstr(self->device_name),
+                                                  self->loop, self->context, flags,
+                                                  &self->attr, &self->spec, &chanmap);
     if(!self->stream)
     {
         pa_threaded_mainloop_unlock(self->loop);
@@ -1013,6 +1030,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
     }
     pa_stream_set_state_callback(self->stream, ALCpulsePlayback_streamStateCallback, self);
     pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self);
+    pa_stream_set_write_callback(self->stream, ALCpulsePlayback_streamWriteCallback, self);
 
     self->spec = *(pa_stream_get_sample_spec(self->stream));
     if(device->Frequency != self->spec.rate)
@@ -1054,7 +1072,8 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
 
 static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self)
 {
-    if(!StartThread(&self->thread, ALCpulsePlayback_mixerProc, self))
+    self->killNow = AL_FALSE;
+    if(althrd_create(&self->thread, ALCpulsePlayback_mixerProc, self) != althrd_success)
         return ALC_FALSE;
     return ALC_TRUE;
 }
@@ -1062,17 +1081,13 @@ static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self)
 static void ALCpulsePlayback_stop(ALCpulsePlayback *self)
 {
     pa_operation *o;
+    int res;
 
     if(!self->stream)
         return;
 
     self->killNow = AL_TRUE;
-    if(self->thread)
-    {
-        StopThread(self->thread);
-        self->thread = NULL;
-    }
-    self->killNow = AL_FALSE;
+    althrd_join(self->thread, &res);
 
     pa_threaded_mainloop_lock(self->loop);
 
@@ -1083,25 +1098,19 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self)
 }
 
 
-static void ALCpulsePlayback_lock(ALCpulsePlayback *self)
-{
-    pa_threaded_mainloop_lock(self->loop);
-}
-
-static void ALCpulsePlayback_unlock(ALCpulsePlayback *self)
-{
-    pa_threaded_mainloop_unlock(self->loop);
-}
-
-
 static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self)
 {
     pa_usec_t latency = 0;
-    int neg;
+    int neg, err;
 
-    if(pa_stream_get_latency(self->stream, &latency, &neg) != 0)
+    if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0)
     {
-        ERR("Failed to get stream latency!\n");
+        /* FIXME: if err = -PA_ERR_NODATA, it means we were called too soon
+         * after starting the stream and no timing info has been received from
+         * the server yet. Should we wait, possibly stalling the app, or give a
+         * dummy value? Either way, it shouldn't be 0. */
+        if(err != -PA_ERR_NODATA)
+            ERR("Failed to get stream latency: 0x%x\n", err);
         return 0;
     }
 
@@ -1110,18 +1119,21 @@ static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self)
 }
 
 
-static void ALCpulsePlayback_Delete(ALCpulsePlayback *self)
+static void ALCpulsePlayback_lock(ALCpulsePlayback *self)
 {
-    free(self);
+    pa_threaded_mainloop_lock(self->loop);
 }
 
-DEFINE_ALCBACKEND_VTABLE(ALCpulsePlayback);
+static void ALCpulsePlayback_unlock(ALCpulsePlayback *self)
+{
+    pa_threaded_mainloop_unlock(self->loop);
+}
 
 
 typedef struct ALCpulseCapture {
     DERIVE_FROM_TYPE(ALCbackend);
 
-    char *device_name;
+    al_string device_name;
 
     const void *cap_store;
     size_t cap_len;
@@ -1137,7 +1149,6 @@ typedef struct ALCpulseCapture {
     pa_stream *stream;
     pa_context *context;
 } ALCpulseCapture;
-DECLARE_ALCBACKEND_VTABLE(ALCpulseCapture);
 
 static void ALCpulseCapture_deviceCallback(pa_context *context, const pa_source_info *info, int eol, void *pdata);
 static void ALCpulseCapture_probeDevices(void);
@@ -1152,7 +1163,7 @@ static pa_stream *ALCpulseCapture_connectStream(const char *device_name,
                                                 pa_sample_spec *spec, pa_channel_map *chanmap);
 
 static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCpulseCapture, ALCbackend, void, Destruct)
+static void ALCpulseCapture_Destruct(ALCpulseCapture *self);
 static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name);
 static void ALCpulseCapture_close(ALCpulseCapture *self);
 static DECLARE_FORWARD(ALCpulseCapture, ALCbackend, ALCboolean, reset)
@@ -1160,22 +1171,34 @@ static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self);
 static void ALCpulseCapture_stop(ALCpulseCapture *self);
 static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *buffer, ALCuint samples);
 static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self);
+static ALint64 ALCpulseCapture_getLatency(ALCpulseCapture *self);
 static void ALCpulseCapture_lock(ALCpulseCapture *self);
 static void ALCpulseCapture_unlock(ALCpulseCapture *self);
+DECLARE_DEFAULT_ALLOCATORS(ALCpulseCapture)
+
+DEFINE_ALCBACKEND_VTABLE(ALCpulseCapture);
 
 
 static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCpulseCapture, ALCbackend, self);
+
+    AL_STRING_INIT(self->device_name);
+}
+
+static void ALCpulseCapture_Destruct(ALCpulseCapture *self)
+{
+    AL_STRING_DEINIT(self->device_name);
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
 
 static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa_source_info *info, int eol, void *pdata)
 {
     pa_threaded_mainloop *loop = pdata;
-    void *temp;
-    ALuint i;
+    const DevMap *iter;
+    DevMap entry;
 
     if(eol)
     {
@@ -1183,29 +1206,29 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa
         return;
     }
 
-    for(i = 0;i < numCaptureDevNames;i++)
-    {
-        if(strcmp(info->name, allCaptureDevNameMap[i].device_name) == 0)
-            return;
-    }
+#define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0)
+    VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_INFO_NAME);
+#undef MATCH_INFO_NAME
+    if(iter != VECTOR_ITER_END(CaptureDevices))
+        return;
 
     TRACE("Got device \"%s\", \"%s\"\n", info->description, info->name);
 
-    temp = realloc(allCaptureDevNameMap, (numCaptureDevNames+1) * sizeof(*allCaptureDevNameMap));
-    if(temp)
-    {
-        allCaptureDevNameMap = temp;
-        allCaptureDevNameMap[numCaptureDevNames].name = strdup(info->description);
-        allCaptureDevNameMap[numCaptureDevNames].device_name = strdup(info->name);
-        numCaptureDevNames++;
-    }
+    AL_STRING_INIT(entry.name);
+    AL_STRING_INIT(entry.device_name);
+
+    al_string_copy_cstr(&entry.name, info->description);
+    al_string_copy_cstr(&entry.device_name, info->name);
+
+    VECTOR_PUSH_BACK(CaptureDevices, entry);
 }
 
 static void ALCpulseCapture_probeDevices(void)
 {
     pa_threaded_mainloop *loop;
 
-    allCaptureDevNameMap = malloc(sizeof(DevMap) * 1);
+    clear_devlist(&CaptureDevices);
+
     if((loop=pa_threaded_mainloop_new()) &&
        pa_threaded_mainloop_start(loop) >= 0)
     {
@@ -1288,8 +1311,7 @@ static void ALCpulseCapture_sourceNameCallback(pa_context *UNUSED(context), cons
         return;
     }
 
-    free(device->DeviceName);
-    device->DeviceName = strdup(info->description);
+    al_string_copy_cstr(&device->DeviceName, info->description);
 }
 
 
@@ -1297,10 +1319,9 @@ static void ALCpulseCapture_streamMovedCallback(pa_stream *stream, void *pdata)
 {
     ALCpulseCapture *self = pdata;
 
-    free(self->device_name);
-    self->device_name = strdup(pa_stream_get_device_name(stream));
+    al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(stream));
 
-    TRACE("Stream moved to %s\n", self->device_name);
+    TRACE("Stream moved to %s\n", al_string_get_cstr(self->device_name));
 }
 
 
@@ -1356,21 +1377,17 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
 
     if(name)
     {
-        ALuint i;
+        const DevMap *iter;
 
-        if(!allCaptureDevNameMap)
+        if(VECTOR_SIZE(CaptureDevices) == 0)
             ALCpulseCapture_probeDevices();
 
-        for(i = 0;i < numCaptureDevNames;i++)
-        {
-            if(strcmp(name, allCaptureDevNameMap[i].name) == 0)
-            {
-                pulse_name = allCaptureDevNameMap[i].device_name;
-                break;
-            }
-        }
-        if(i == numCaptureDevNames)
+#define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
+#undef MATCH_NAME
+        if(iter == VECTOR_ITER_END(CaptureDevices))
             return ALC_INVALID_VALUE;
+        pulse_name = al_string_get_cstr(iter->device_name);
     }
 
     if(!pulse_open(&self->loop, &self->context, ALCpulseCapture_contextStateCallback, self))
@@ -1431,6 +1448,7 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
     if(!GetConfigValueBool("pulse", "allow-moves", 0))
         flags |= PA_STREAM_DONT_MOVE;
 
+    TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)");
     self->stream = ALCpulseCapture_connectStream(pulse_name, self->loop, self->context,
                                                  flags, &self->attr, &self->spec,
                                                  &chanmap);
@@ -1442,8 +1460,9 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
     pa_stream_set_moved_callback(self->stream, ALCpulseCapture_streamMovedCallback, self);
     pa_stream_set_state_callback(self->stream, ALCpulseCapture_streamStateCallback, self);
 
-    self->device_name = strdup(pa_stream_get_device_name(self->stream));
-    o = pa_context_get_source_info_by_name(self->context, self->device_name,
+    al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream));
+    o = pa_context_get_source_info_by_name(self->context,
+                                           al_string_get_cstr(self->device_name),
                                            ALCpulseCapture_sourceNameCallback, self);
     wait_for_operation(o, self->loop);
 
@@ -1466,8 +1485,7 @@ static void ALCpulseCapture_close(ALCpulseCapture *self)
     self->context = NULL;
     self->stream = NULL;
 
-    free(self->device_name);
-    self->device_name = NULL;
+    al_string_clear(&self->device_name);
 }
 
 static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self)
@@ -1562,17 +1580,6 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self)
 }
 
 
-static void ALCpulseCapture_lock(ALCpulseCapture *self)
-{
-    pa_threaded_mainloop_lock(self->loop);
-}
-
-static void ALCpulseCapture_unlock(ALCpulseCapture *self)
-{
-    pa_threaded_mainloop_unlock(self->loop);
-}
-
-
 static ALint64 ALCpulseCapture_getLatency(ALCpulseCapture *self)
 {
     pa_usec_t latency = 0;
@@ -1589,23 +1596,43 @@ static ALint64 ALCpulseCapture_getLatency(ALCpulseCapture *self)
 }
 
 
-static void ALCpulseCapture_Delete(ALCpulseCapture *self)
+static void ALCpulseCapture_lock(ALCpulseCapture *self)
 {
-    free(self);
+    pa_threaded_mainloop_lock(self->loop);
+}
+
+static void ALCpulseCapture_unlock(ALCpulseCapture *self)
+{
+    pa_threaded_mainloop_unlock(self->loop);
 }
 
-DEFINE_ALCBACKEND_VTABLE(ALCpulseCapture);
 
+static inline void AppendAllDevicesList2(const DevMap *entry)
+{ AppendAllDevicesList(al_string_get_cstr(entry->name)); }
+static inline void AppendCaptureDeviceList2(const DevMap *entry)
+{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); }
 
 typedef struct ALCpulseBackendFactory {
     DERIVE_FROM_TYPE(ALCbackendFactory);
 } ALCpulseBackendFactory;
 #define ALCPULSEBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCpulseBackendFactory, ALCbackendFactory) } }
 
+static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory *self);
+static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory *self);
+static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory *self, ALCbackend_Type type);
+static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory);
+
+
 static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(self))
 {
     ALCboolean ret = ALC_FALSE;
 
+    VECTOR_INIT(PlaybackDevices);
+    VECTOR_INIT(CaptureDevices);
+
     if(pulse_load())
     {
         pa_threaded_mainloop *loop;
@@ -1648,25 +1675,11 @@ static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(sel
 
 static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory* UNUSED(self))
 {
-    ALuint i;
-
-    for(i = 0;i < numDevNames;++i)
-    {
-        free(allDevNameMap[i].name);
-        free(allDevNameMap[i].device_name);
-    }
-    free(allDevNameMap);
-    allDevNameMap = NULL;
-    numDevNames = 0;
+    clear_devlist(&PlaybackDevices);
+    VECTOR_DEINIT(PlaybackDevices);
 
-    for(i = 0;i < numCaptureDevNames;++i)
-    {
-        free(allCaptureDevNameMap[i].name);
-        free(allCaptureDevNameMap[i].device_name);
-    }
-    free(allCaptureDevNameMap);
-    allCaptureDevNameMap = NULL;
-    numCaptureDevNames = 0;
+    clear_devlist(&CaptureDevices);
+    VECTOR_DEINIT(CaptureDevices);
 
     if(prop_filter)
         pa_proplist_free(prop_filter);
@@ -1684,40 +1697,16 @@ static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UN
 
 static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe type)
 {
-    ALuint i;
-
     switch(type)
     {
         case ALL_DEVICE_PROBE:
-            for(i = 0;i < numDevNames;++i)
-            {
-                free(allDevNameMap[i].name);
-                free(allDevNameMap[i].device_name);
-            }
-            free(allDevNameMap);
-            allDevNameMap = NULL;
-            numDevNames = 0;
-
             ALCpulsePlayback_probeDevices();
-
-            for(i = 0;i < numDevNames;i++)
-                AppendAllDevicesList(allDevNameMap[i].name);
+            VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2);
             break;
 
         case CAPTURE_DEVICE_PROBE:
-            for(i = 0;i < numCaptureDevNames;++i)
-            {
-                free(allCaptureDevNameMap[i].name);
-                free(allCaptureDevNameMap[i].device_name);
-            }
-            free(allCaptureDevNameMap);
-            allCaptureDevNameMap = NULL;
-            numCaptureDevNames = 0;
-
             ALCpulseCapture_probeDevices();
-
-            for(i = 0;i < numCaptureDevNames;i++)
-                AppendCaptureDeviceList(allCaptureDevNameMap[i].name);
+            VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2);
             break;
     }
 }
@@ -1728,8 +1717,9 @@ static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory*
     {
         ALCpulsePlayback *backend;
 
-        backend = calloc(1, sizeof(*backend));
+        backend = ALCpulsePlayback_New(sizeof(*backend));
         if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
 
         ALCpulsePlayback_Construct(backend, device);
 
@@ -1739,8 +1729,9 @@ static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory*
     {
         ALCpulseCapture *backend;
 
-        backend = calloc(1, sizeof(*backend));
+        backend = ALCpulseCapture_New(sizeof(*backend));
         if(!backend) return NULL;
+        memset(backend, 0, sizeof(*backend));
 
         ALCpulseCapture_Construct(backend, device);
 
@@ -1750,8 +1741,6 @@ static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory*
     return NULL;
 }
 
-DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory);
-
 
 #else /* PA_API_VERSION == 12 */
 

+ 26 - 34
jni/openal-soft-android/Alc/backends/qsa.c → jni/openal-soft-1.16.0/Alc/backends/qsa.c

@@ -34,8 +34,7 @@
 #include "threads.h"
 
 
-typedef struct
-{
+typedef struct {
     snd_pcm_t* pcmHandle;
     int audio_fd;
 
@@ -46,27 +45,24 @@ typedef struct
     ALsizei size;
 
     volatile int killNow;
-    althread_t thread;
+    althrd_t thread;
 } qsa_data;
 
-typedef struct
-{
+typedef struct {
     ALCchar* name;
     int card;
     int dev;
 } DevMap;
 
-static const ALCchar qsaDevice[]="QSA Default";
+static const ALCchar qsaDevice[] = "QSA Default";
 static DevMap* allDevNameMap;
 static ALuint numDevNames;
 static DevMap* allCaptureDevNameMap;
 static ALuint numCaptureDevNames;
 
-static const struct
-{
+static const struct {
     int32_t format;
-} formatlist[]=
-{
+} formatlist[] = {
     {SND_PCM_SFMT_FLOAT_LE},
     {SND_PCM_SFMT_S32_LE},
     {SND_PCM_SFMT_U32_LE},
@@ -77,11 +73,9 @@ static const struct
     {0},
 };
 
-static const struct
-{
+static const struct {
     int32_t rate;
-} ratelist[]=
-{
+} ratelist[] = {
     {192000},
     {176400},
     {96000},
@@ -98,11 +92,9 @@ static const struct
     {0},
 };
 
-static const struct
-{
+static const struct {
     int32_t channels;
-} channellist[]=
-{
+} channellist[] = {
     {8},
     {7},
     {6},
@@ -112,7 +104,7 @@ static const struct
     {0},
 };
 
-static DevMap* deviceList(int type, ALuint* count)
+static DevMap *deviceList(int type, ALuint *count)
 {
     snd_ctl_t* handle;
     snd_pcm_info_t pcminfo;
@@ -178,7 +170,7 @@ static DevMap* deviceList(int type, ALuint* count)
 }
 
 
-FORCE_ALIGN static ALuint qsa_proc_playback(ALvoid* ptr)
+FORCE_ALIGN static int qsa_proc_playback(void* ptr)
 {
     ALCdevice* device=(ALCdevice*)ptr;
     qsa_data* data=(qsa_data*)device->ExtraData;
@@ -191,7 +183,7 @@ FORCE_ALIGN static ALuint qsa_proc_playback(ALvoid* ptr)
     struct timeval timeout;
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     /* Increase default 10 priority to 11 to avoid jerky sound */
     SchedGet(0, 0, &param);
@@ -343,8 +335,8 @@ static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName)
         return ALC_INVALID_DEVICE;
     }
 
-    device->DeviceName=strdup(deviceName);
-    device->ExtraData=data;
+    al_string_copy_cstr(&device->DeviceName, deviceName);
+    device->ExtraData = data;
 
     return ALC_NO_ERROR;
 }
@@ -616,7 +608,8 @@ static ALCboolean qsa_start_playback(ALCdevice* device)
 {
     qsa_data *data = (qsa_data*)device->ExtraData;
 
-    if(!StartThread(&data->thread, qsa_proc_playback, device))
+    data->killNow = 0;
+    if(althrd_create(&data->thread, qsa_proc_playback, device) != althrd_success)
         return ALC_FALSE;
 
     return ALC_TRUE;
@@ -624,15 +617,14 @@ static ALCboolean qsa_start_playback(ALCdevice* device)
 
 static void qsa_stop_playback(ALCdevice* device)
 {
-    qsa_data* data=(qsa_data*)device->ExtraData;
+    qsa_data *data = (qsa_data*)device->ExtraData;
+    int res;
 
-    if (data->thread)
-    {
-        data->killNow=1;
-        StopThread(data->thread);
-        data->thread=NULL;
-    }
-    data->killNow=0;
+    if(data->killNow)
+        return;
+
+    data->killNow = 1;
+    althrd_join(data->thread, &res);
 }
 
 /***********/
@@ -711,8 +703,8 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
         return ALC_INVALID_DEVICE;
     }
 
-    device->DeviceName=strdup(deviceName);
-    device->ExtraData=data;
+    al_string_copy_cstr(&device->DeviceName, deviceName);
+    device->ExtraData = data;
 
     switch (device->FmtType)
     {

+ 9 - 9
jni/openal-soft-android/Alc/backends/sndio.c → jni/openal-soft-1.16.0/Alc/backends/sndio.c

@@ -47,11 +47,11 @@ typedef struct {
     ALsizei data_size;
 
     volatile int killNow;
-    althread_t thread;
+    althrd_t thread;
 } sndio_data;
 
 
-static ALuint sndio_proc(ALvoid *ptr)
+static int sndio_proc(void *ptr)
 {
     ALCdevice *device = ptr;
     sndio_data *data = device->ExtraData;
@@ -59,7 +59,7 @@ static ALuint sndio_proc(ALvoid *ptr)
     size_t wrote;
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
 
@@ -111,7 +111,7 @@ static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
         return ALC_INVALID_VALUE;
     }
 
-    device->DeviceName = strdup(deviceName);
+    al_string_copy_cstr(&device->DeviceName, deviceName);
     device->ExtraData = data;
 
     return ALC_NO_ERROR;
@@ -224,7 +224,8 @@ static ALCboolean sndio_start_playback(ALCdevice *device)
     data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
     data->mix_data = calloc(1, data->data_size);
 
-    if(!StartThread(&data->thread, sndio_proc, device))
+    data->killNow = 0;
+    if(althrd_create(&data->thread, sndio_proc, device) != althrd_success)
     {
         sio_stop(data->sndHandle);
         free(data->mix_data);
@@ -238,15 +239,14 @@ static ALCboolean sndio_start_playback(ALCdevice *device)
 static void sndio_stop_playback(ALCdevice *device)
 {
     sndio_data *data = device->ExtraData;
+    int res;
 
-    if(!data->thread)
+    if(data->killNow)
         return;
 
     data->killNow = 1;
-    StopThread(data->thread);
-    data->thread = NULL;
+    althrd_join(data->thread, &res);
 
-    data->killNow = 0;
     if(!sio_stop(data->sndHandle))
         ERR("Error stopping device\n");
 

+ 10 - 10
jni/openal-soft-android/Alc/backends/solaris.c → jni/openal-soft-1.16.0/Alc/backends/solaris.c

@@ -50,11 +50,11 @@ typedef struct {
     int data_size;
 
     volatile int killNow;
-    althread_t thread;
+    althrd_t thread;
 } solaris_data;
 
 
-static ALuint SolarisProc(ALvoid *ptr)
+static int SolarisProc(void *ptr)
 {
     ALCdevice *Device = (ALCdevice*)ptr;
     solaris_data *data = (solaris_data*)Device->ExtraData;
@@ -62,7 +62,7 @@ static ALuint SolarisProc(ALvoid *ptr)
     int wrote;
 
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
 
@@ -86,7 +86,7 @@ static ALuint SolarisProc(ALvoid *ptr)
                     break;
                 }
 
-                Sleep(1);
+                al_nssleep(0, 1000000);
                 continue;
             }
 
@@ -119,7 +119,7 @@ static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceNam
         return ALC_INVALID_VALUE;
     }
 
-    device->DeviceName = strdup(deviceName);
+    al_string_copy_cstr(&device->DeviceName, deviceName);
     device->ExtraData = data;
     return ALC_NO_ERROR;
 }
@@ -211,7 +211,8 @@ static ALCboolean solaris_start_playback(ALCdevice *device)
     data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
     data->mix_data = calloc(1, data->data_size);
 
-    if(!StartThread(&data->thread, SolarisProc, device))
+    data->killNow = 0;
+    if(althrd_create(&data->thread, SolarisProc, device) != althrd_success)
     {
         free(data->mix_data);
         data->mix_data = NULL;
@@ -224,15 +225,14 @@ static ALCboolean solaris_start_playback(ALCdevice *device)
 static void solaris_stop_playback(ALCdevice *device)
 {
     solaris_data *data = (solaris_data*)device->ExtraData;
+    int res;
 
-    if(!data->thread)
+    if(data->killNow)
         return;
 
     data->killNow = 1;
-    StopThread(data->thread);
-    data->thread = NULL;
+    althrd_join(data->thread, &res);
 
-    data->killNow = 0;
     if(ioctl(data->fd, AUDIO_DRAIN) < 0)
         ERR("Error draining device: %s\n", strerror(errno));
 

+ 44 - 39
jni/openal-soft-android/Alc/backends/wave.c → jni/openal-soft-1.16.0/Alc/backends/wave.c

@@ -42,7 +42,7 @@ typedef struct {
     ALuint size;
 
     volatile int killNow;
-    althread_t thread;
+    althrd_t thread;
 } wave_data;
 
 
@@ -85,49 +85,55 @@ static void fwrite32le(ALuint val, FILE *f)
 }
 
 
-static ALuint WaveProc(ALvoid *ptr)
+static int WaveProc(void *ptr)
 {
-    ALCdevice *Device = (ALCdevice*)ptr;
-    wave_data *data = (wave_data*)Device->ExtraData;
+    ALCdevice *device = (ALCdevice*)ptr;
+    wave_data *data = (wave_data*)device->ExtraData;
+    struct timespec now, start;
+    ALint64 avail, done;
     ALuint frameSize;
-    ALuint now, start;
-    ALuint64 avail, done;
     size_t fs;
-    const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 /
-                            Device->Frequency / 2;
+    const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 /
+                                 device->Frequency / 2);
 
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
-    frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
+    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
 
     done = 0;
-    start = timeGetTime();
-    while(!data->killNow && Device->Connected)
+    if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC)
     {
-        now = timeGetTime();
-
-        avail = (ALuint64)(now-start) * Device->Frequency / 1000;
-        if(avail < done)
+        ERR("Failed to get starting time\n");
+        return 1;
+    }
+    while(!data->killNow && device->Connected)
+    {
+        if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
         {
-            /* Timer wrapped (50 days???). Add the remainder of the cycle to
-             * the available count and reset the number of samples done */
-            avail += ((ALuint64)1<<32)*Device->Frequency/1000 - done;
-            done = 0;
+            ERR("Failed to get current time\n");
+            return 1;
         }
-        if(avail-done < Device->UpdateSize)
+
+        avail  = (now.tv_sec - start.tv_sec) * device->Frequency;
+        avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000;
+        if(avail < done)
         {
-            Sleep(restTime);
-            continue;
+            /* Oops, time skipped backwards. Reset the number of samples done
+             * with one update available since we (likely) just came back from
+             * sleeping. */
+            done = avail - device->UpdateSize;
         }
 
-        while(avail-done >= Device->UpdateSize)
+        if(avail-done < device->UpdateSize)
+            al_nssleep(0, restTime);
+        else while(avail-done >= device->UpdateSize)
         {
-            aluMixData(Device, data->buffer, Device->UpdateSize);
-            done += Device->UpdateSize;
+            aluMixData(device, data->buffer, device->UpdateSize);
+            done += device->UpdateSize;
 
             if(!IS_LITTLE_ENDIAN)
             {
-                ALuint bytesize = BytesFromDevFmt(Device->FmtType);
+                ALuint bytesize = BytesFromDevFmt(device->FmtType);
                 ALubyte *bytes = data->buffer;
                 ALuint i;
 
@@ -149,16 +155,16 @@ static ALuint WaveProc(ALvoid *ptr)
             }
             else
             {
-                fs = fwrite(data->buffer, frameSize, Device->UpdateSize,
+                fs = fwrite(data->buffer, frameSize, device->UpdateSize,
                             data->f);
                 (void)fs;
             }
             if(ferror(data->f))
             {
                 ERR("Error writing to file\n");
-                ALCdevice_Lock(Device);
-                aluHandleDisconnect(Device);
-                ALCdevice_Unlock(Device);
+                ALCdevice_Lock(device);
+                aluHandleDisconnect(device);
+                ALCdevice_Unlock(device);
                 break;
             }
         }
@@ -183,7 +189,7 @@ static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
 
     data = (wave_data*)calloc(1, sizeof(wave_data));
 
-    data->f = fopen(fname, "wb");
+    data->f = al_fopen(fname, "wb");
     if(!data->f)
     {
         free(data);
@@ -191,7 +197,7 @@ static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
         return ALC_INVALID_VALUE;
     }
 
-    device->DeviceName = strdup(deviceName);
+    al_string_copy_cstr(&device->DeviceName, deviceName);
     device->ExtraData = data;
     return ALC_NO_ERROR;
 }
@@ -291,7 +297,8 @@ static ALCboolean wave_start_playback(ALCdevice *device)
         return ALC_FALSE;
     }
 
-    if(!StartThread(&data->thread, WaveProc, device))
+    data->killNow = 0;
+    if(althrd_create(&data->thread, WaveProc, device) != althrd_success)
     {
         free(data->buffer);
         data->buffer = NULL;
@@ -306,15 +313,13 @@ static void wave_stop_playback(ALCdevice *device)
     wave_data *data = (wave_data*)device->ExtraData;
     ALuint dataLen;
     long size;
+    int res;
 
-    if(!data->thread)
+    if(data->killNow)
         return;
 
     data->killNow = 1;
-    StopThread(data->thread);
-    data->thread = NULL;
-
-    data->killNow = 0;
+    althrd_join(data->thread, &res);
 
     free(data->buffer);
     data->buffer = NULL;

+ 138 - 191
jni/openal-soft-android/Alc/backends/winmm.c → jni/openal-soft-1.16.0/Alc/backends/winmm.c

@@ -39,10 +39,9 @@
 typedef struct {
     // MMSYSTEM Device
     volatile ALboolean killNow;
-    HANDLE  WaveThreadEvent;
-    HANDLE  WaveThread;
-    DWORD   WaveThreadID;
-    volatile LONG WaveBuffersCommitted;
+    althrd_t thread;
+
+    RefCount WaveBuffersCommitted;
     WAVEHDR WaveBuffer[4];
 
     union {
@@ -56,87 +55,102 @@ typedef struct {
 } WinMMData;
 
 
-static ALCchar **PlaybackDeviceList;
-static ALuint  NumPlaybackDevices;
-static ALCchar **CaptureDeviceList;
-static ALuint  NumCaptureDevices;
+TYPEDEF_VECTOR(al_string, vector_al_string)
+static vector_al_string PlaybackDevices;
+static vector_al_string CaptureDevices;
+
+static void clear_devlist(vector_al_string *list)
+{
+    VECTOR_FOR_EACH(al_string, *list, al_string_deinit);
+    VECTOR_RESIZE(*list, 0);
+}
 
 
 static void ProbePlaybackDevices(void)
 {
+    al_string *iter, *end;
+    ALuint numdevs;
     ALuint i;
 
-    for(i = 0;i < NumPlaybackDevices;i++)
-        free(PlaybackDeviceList[i]);
+    clear_devlist(&PlaybackDevices);
 
-    NumPlaybackDevices = waveOutGetNumDevs();
-    PlaybackDeviceList = realloc(PlaybackDeviceList, sizeof(ALCchar*) * NumPlaybackDevices);
-    for(i = 0;i < NumPlaybackDevices;i++)
+    numdevs = waveOutGetNumDevs();
+    VECTOR_RESERVE(PlaybackDevices, numdevs);
+    for(i = 0;i < numdevs;i++)
     {
-        WAVEOUTCAPS WaveCaps;
+        WAVEOUTCAPSW WaveCaps;
+        al_string dname;
 
-        PlaybackDeviceList[i] = NULL;
-        if(waveOutGetDevCaps(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
+        AL_STRING_INIT(dname);
+        if(waveOutGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
         {
-            char name[1024];
-            ALuint count, j;
-
-            count = 0;
+            ALuint count = 0;
             do {
-                if(count == 0)
-                    snprintf(name, sizeof(name), "%s", WaveCaps.szPname);
-                else
-                    snprintf(name, sizeof(name), "%s #%d", WaveCaps.szPname, count+1);
+                al_string_copy_wcstr(&dname, WaveCaps.szPname);
+                if(count != 0)
+                {
+                    char str[64];
+                    snprintf(str, sizeof(str), " #%d", count+1);
+                    al_string_append_cstr(&dname, str);
+                }
                 count++;
 
-                for(j = 0;j < i;j++)
+                iter = VECTOR_ITER_BEGIN(PlaybackDevices);
+                end = VECTOR_ITER_END(PlaybackDevices);
+                for(;iter != end;iter++)
                 {
-                    if(strcmp(name, PlaybackDeviceList[j]) == 0)
+                    if(al_string_cmp(*iter, dname) == 0)
                         break;
                 }
-            } while(j != i);
+            } while(iter != end);
 
-            PlaybackDeviceList[i] = strdup(name);
+            TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i);
         }
+        VECTOR_PUSH_BACK(PlaybackDevices, dname);
     }
 }
 
 static void ProbeCaptureDevices(void)
 {
+    al_string *iter, *end;
+    ALuint numdevs;
     ALuint i;
 
-    for(i = 0;i < NumCaptureDevices;i++)
-        free(CaptureDeviceList[i]);
+    clear_devlist(&CaptureDevices);
 
-    NumCaptureDevices = waveInGetNumDevs();
-    CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices);
-    for(i = 0;i < NumCaptureDevices;i++)
+    numdevs = waveInGetNumDevs();
+    VECTOR_RESERVE(CaptureDevices, numdevs);
+    for(i = 0;i < numdevs;i++)
     {
-        WAVEINCAPS WaveInCaps;
+        WAVEINCAPSW WaveCaps;
+        al_string dname;
 
-        CaptureDeviceList[i] = NULL;
-        if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR)
+        AL_STRING_INIT(dname);
+        if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
         {
-            char name[1024];
-            ALuint count, j;
-
-            count = 0;
+            ALuint count = 0;
             do {
-                if(count == 0)
-                    snprintf(name, sizeof(name), "%s", WaveInCaps.szPname);
-                else
-                    snprintf(name, sizeof(name), "%s #%d", WaveInCaps.szPname, count+1);
+                al_string_copy_wcstr(&dname, WaveCaps.szPname);
+                if(count != 0)
+                {
+                    char str[64];
+                    snprintf(str, sizeof(str), " #%d", count+1);
+                    al_string_append_cstr(&dname, str);
+                }
                 count++;
 
-                for(j = 0;j < i;j++)
+                iter = VECTOR_ITER_BEGIN(CaptureDevices);
+                end = VECTOR_ITER_END(CaptureDevices);
+                for(;iter != end;iter++)
                 {
-                    if(strcmp(name, CaptureDeviceList[j]) == 0)
+                    if(al_string_cmp(*iter, dname) == 0)
                         break;
                 }
-            } while(j != i);
+            } while(iter != end);
 
-            CaptureDeviceList[i] = strdup(name);
+            TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i);
         }
+        VECTOR_PUSH_BACK(CaptureDevices, dname);
     }
 }
 
@@ -155,28 +169,19 @@ static void CALLBACK WaveOutProc(HWAVEOUT UNUSED(device), UINT msg, DWORD_PTR in
     if(msg != WOM_DONE)
         return;
 
-    InterlockedDecrement(&data->WaveBuffersCommitted);
-    PostThreadMessage(data->WaveThreadID, msg, 0, param1);
+    DecrementRef(&data->WaveBuffersCommitted);
+    PostThreadMessage(data->thread, msg, 0, param1);
 }
 
-/*
-    PlaybackThreadProc
-
-    Used by "MMSYSTEM" Device.  Called when a WaveOut buffer has used up its
-    audio data.
-*/
-FORCE_ALIGN static DWORD WINAPI PlaybackThreadProc(LPVOID param)
+FORCE_ALIGN static int PlaybackThreadProc(void *arg)
 {
-    ALCdevice *Device = (ALCdevice*)param;
+    ALCdevice *Device = (ALCdevice*)arg;
     WinMMData *data = Device->ExtraData;
-    LPWAVEHDR WaveHdr;
-    ALuint FrameSize;
+    WAVEHDR *WaveHdr;
     MSG msg;
 
-    FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
-
     SetRTPriority();
-    SetThreadName(MIXER_THREAD_NAME);
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     while(GetMessage(&msg, NULL, 0, 0))
     {
@@ -185,24 +190,20 @@ FORCE_ALIGN static DWORD WINAPI PlaybackThreadProc(LPVOID param)
 
         if(data->killNow)
         {
-            if(data->WaveBuffersCommitted == 0)
+            if(ReadRef(&data->WaveBuffersCommitted) == 0)
                 break;
             continue;
         }
 
-        WaveHdr = ((LPWAVEHDR)msg.lParam);
-        aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength/FrameSize);
+        WaveHdr = ((WAVEHDR*)msg.lParam);
+        aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength /
+                                            data->Format.nBlockAlign);
 
         // Send buffer back to play more data
         waveOutWrite(data->WaveHandle.Out, WaveHdr, sizeof(WAVEHDR));
-        InterlockedIncrement(&data->WaveBuffersCommitted);
+        IncrementRef(&data->WaveBuffersCommitted);
     }
 
-    // Signal Wave Thread completed event
-    if(data->WaveThreadEvent)
-        SetEvent(data->WaveThreadEvent);
-
-    ExitThread(0);
     return 0;
 }
 
@@ -220,26 +221,18 @@ static void CALLBACK WaveInProc(HWAVEIN UNUSED(device), UINT msg, DWORD_PTR inst
     if(msg != WIM_DATA)
         return;
 
-    InterlockedDecrement(&data->WaveBuffersCommitted);
-    PostThreadMessage(data->WaveThreadID, msg, 0, param1);
+    DecrementRef(&data->WaveBuffersCommitted);
+    PostThreadMessage(data->thread, msg, 0, param1);
 }
 
-/*
-    CaptureThreadProc
-
-    Used by "MMSYSTEM" Device.  Called when a WaveIn buffer had been filled with new
-    audio data.
-*/
-static DWORD WINAPI CaptureThreadProc(LPVOID param)
+static int CaptureThreadProc(void *arg)
 {
-    ALCdevice *Device = (ALCdevice*)param;
+    ALCdevice *Device = (ALCdevice*)arg;
     WinMMData *data = Device->ExtraData;
-    LPWAVEHDR WaveHdr;
-    ALuint FrameSize;
+    WAVEHDR *WaveHdr;
     MSG msg;
 
-    FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
-    SetThreadName("alsoft-record");
+    althrd_setname(althrd_current(), "alsoft-record");
 
     while(GetMessage(&msg, NULL, 0, 0))
     {
@@ -250,19 +243,15 @@ static DWORD WINAPI CaptureThreadProc(LPVOID param)
         if(data->killNow)
             break;
 
-        WaveHdr = ((LPWAVEHDR)msg.lParam);
-        WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData, WaveHdr->dwBytesRecorded/FrameSize);
+        WaveHdr = ((WAVEHDR*)msg.lParam);
+        WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData,
+                        WaveHdr->dwBytesRecorded/data->Format.nBlockAlign);
 
         // Send buffer back to capture more data
         waveInAddBuffer(data->WaveHandle.In, WaveHdr, sizeof(WAVEHDR));
-        InterlockedIncrement(&data->WaveBuffersCommitted);
+        IncrementRef(&data->WaveBuffersCommitted);
     }
 
-    // Signal Wave Thread completed event
-    if(data->WaveThreadEvent)
-        SetEvent(data->WaveThreadEvent);
-
-    ExitThread(0);
     return 0;
 }
 
@@ -270,24 +259,26 @@ static DWORD WINAPI CaptureThreadProc(LPVOID param)
 static ALCenum WinMMOpenPlayback(ALCdevice *Device, const ALCchar *deviceName)
 {
     WinMMData *data = NULL;
-    UINT DeviceID = 0;
+    const al_string *iter, *end;
+    UINT DeviceID;
     MMRESULT res;
-    ALuint i = 0;
 
-    if(!PlaybackDeviceList)
+    if(VECTOR_SIZE(PlaybackDevices) == 0)
         ProbePlaybackDevices();
 
     // Find the Device ID matching the deviceName if valid
-    for(i = 0;i < NumPlaybackDevices;i++)
+    iter = VECTOR_ITER_BEGIN(PlaybackDevices);
+    end = VECTOR_ITER_END(PlaybackDevices);
+    for(;iter != end;iter++)
     {
-        if(PlaybackDeviceList[i] &&
-           (!deviceName || strcmp(deviceName, PlaybackDeviceList[i]) == 0))
+        if(!al_string_empty(*iter) &&
+           (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0))
         {
-            DeviceID = i;
+            DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(PlaybackDevices));
             break;
         }
     }
-    if(i == NumPlaybackDevices)
+    if(iter == end)
         return ALC_INVALID_VALUE;
 
     data = calloc(1, sizeof(*data));
@@ -329,20 +320,10 @@ retry_open:
         goto failure;
     }
 
-    data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if(data->WaveThreadEvent == NULL)
-    {
-        ERR("CreateEvent failed: %lu\n", GetLastError());
-        goto failure;
-    }
-
-    Device->DeviceName = strdup(PlaybackDeviceList[DeviceID]);
+    al_string_copy(&Device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID));
     return ALC_NO_ERROR;
 
 failure:
-    if(data->WaveThreadEvent)
-        CloseHandle(data->WaveThreadEvent);
-
     if(data->WaveHandle.Out)
         waveOutClose(data->WaveHandle.Out);
 
@@ -356,9 +337,6 @@ static void WinMMClosePlayback(ALCdevice *device)
     WinMMData *data = (WinMMData*)device->ExtraData;
 
     // Close the Wave device
-    CloseHandle(data->WaveThreadEvent);
-    data->WaveThreadEvent = 0;
-
     waveOutClose(data->WaveHandle.Out);
     data->WaveHandle.Out = 0;
 
@@ -426,11 +404,11 @@ static ALCboolean WinMMStartPlayback(ALCdevice *device)
     ALint BufferSize;
     ALuint i;
 
-    data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &data->WaveThreadID);
-    if(data->WaveThread == NULL)
+    data->killNow = AL_FALSE;
+    if(althrd_create(&data->thread, PlaybackThreadProc, device) != althrd_success)
         return ALC_FALSE;
 
-    data->WaveBuffersCommitted = 0;
+    InitRef(&data->WaveBuffersCommitted, 0);
 
     // Create 4 Buffers
     BufferSize  = device->UpdateSize*device->NumUpdates / 4;
@@ -441,12 +419,12 @@ static ALCboolean WinMMStartPlayback(ALCdevice *device)
     {
         memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
         data->WaveBuffer[i].dwBufferLength = BufferSize;
-        data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
+        data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData :
                                       (data->WaveBuffer[i-1].lpData +
                                        data->WaveBuffer[i-1].dwBufferLength));
         waveOutPrepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
         waveOutWrite(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        InterlockedIncrement(&data->WaveBuffersCommitted);
+        IncrementRef(&data->WaveBuffersCommitted);
     }
 
     return ALC_TRUE;
@@ -458,19 +436,12 @@ static void WinMMStopPlayback(ALCdevice *device)
     void *buffer = NULL;
     int i;
 
-    if(data->WaveThread == NULL)
+    if(data->killNow)
         return;
 
     // Set flag to stop processing headers
     data->killNow = AL_TRUE;
-
-    // Wait for signal that Wave Thread has been destroyed
-    WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE);
-
-    CloseHandle(data->WaveThread);
-    data->WaveThread = 0;
-
-    data->killNow = AL_FALSE;
+    althrd_join(data->thread, &i);
 
     // Release the wave buffers
     for(i = 0;i < 4;i++)
@@ -485,28 +456,31 @@ static void WinMMStopPlayback(ALCdevice *device)
 
 static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName)
 {
+    const al_string *iter, *end;
     ALbyte *BufferData = NULL;
     DWORD CapturedDataSize;
     WinMMData *data = NULL;
-    UINT DeviceID = 0;
     ALint BufferSize;
+    UINT DeviceID;
     MMRESULT res;
     ALuint i;
 
-    if(!CaptureDeviceList)
+    if(VECTOR_SIZE(CaptureDevices) == 0)
         ProbeCaptureDevices();
 
     // Find the Device ID matching the deviceName if valid
-    for(i = 0;i < NumCaptureDevices;i++)
+    iter = VECTOR_ITER_BEGIN(CaptureDevices);
+    end = VECTOR_ITER_END(CaptureDevices);
+    for(;iter != end;iter++)
     {
-        if(CaptureDeviceList[i] &&
-           (!deviceName || strcmp(deviceName, CaptureDeviceList[i]) == 0))
+        if(!al_string_empty(*iter) &&
+           (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0))
         {
-            DeviceID = i;
+            DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(CaptureDevices));
             break;
         }
     }
-    if(i == NumCaptureDevices)
+    if(iter == end)
         return ALC_INVALID_VALUE;
 
     switch(Device->FmtChans)
@@ -560,13 +534,6 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName)
         goto failure;
     }
 
-    data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if(data->WaveThreadEvent == NULL)
-    {
-        ERR("CreateEvent failed: %lu\n", GetLastError());
-        goto failure;
-    }
-
     // Allocate circular memory buffer for the captured audio
     CapturedDataSize = Device->UpdateSize*Device->NumUpdates;
 
@@ -578,7 +545,7 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName)
     if(!data->Ring)
         goto failure;
 
-    data->WaveBuffersCommitted = 0;
+    InitRef(&data->WaveBuffersCommitted, 0);
 
     // Create 4 Buffers of 50ms each
     BufferSize = data->Format.nAvgBytesPerSec / 20;
@@ -592,27 +559,23 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName)
     {
         memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
         data->WaveBuffer[i].dwBufferLength = BufferSize;
-        data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData :
+        data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData :
                                       (data->WaveBuffer[i-1].lpData +
                                        data->WaveBuffer[i-1].dwBufferLength));
         data->WaveBuffer[i].dwFlags = 0;
         data->WaveBuffer[i].dwLoops = 0;
         waveInPrepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
         waveInAddBuffer(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        InterlockedIncrement(&data->WaveBuffersCommitted);
+        IncrementRef(&data->WaveBuffersCommitted);
     }
 
-    data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)Device, 0, &data->WaveThreadID);
-    if (data->WaveThread == NULL)
+    if(althrd_create(&data->thread, CaptureThreadProc, Device) != althrd_success)
         goto failure;
 
-    Device->DeviceName = strdup(CaptureDeviceList[DeviceID]);
+    al_string_copy(&Device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID));
     return ALC_NO_ERROR;
 
 failure:
-    if(data->WaveThread)
-        CloseHandle(data->WaveThread);
-
     if(BufferData)
     {
         for(i = 0;i < 4;i++)
@@ -623,9 +586,6 @@ failure:
     if(data->Ring)
         DestroyRingBuffer(data->Ring);
 
-    if(data->WaveThreadEvent)
-        CloseHandle(data->WaveThreadEvent);
-
     if(data->WaveHandle.In)
         waveInClose(data->WaveHandle.In);
 
@@ -642,16 +602,13 @@ static void WinMMCloseCapture(ALCdevice *Device)
 
     /* Tell the processing thread to quit and wait for it to do so. */
     data->killNow = AL_TRUE;
-    PostThreadMessage(data->WaveThreadID, WM_QUIT, 0, 0);
+    PostThreadMessage(data->thread, WM_QUIT, 0, 0);
 
-    WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE);
+    althrd_join(data->thread, &i);
 
     /* Make sure capture is stopped and all pending buffers are flushed. */
     waveInReset(data->WaveHandle.In);
 
-    CloseHandle(data->WaveThread);
-    data->WaveThread = 0;
-
     // Release the wave buffers
     for(i = 0;i < 4;i++)
     {
@@ -665,9 +622,6 @@ static void WinMMCloseCapture(ALCdevice *Device)
     data->Ring = NULL;
 
     // Close the Wave device
-    CloseHandle(data->WaveThreadEvent);
-    data->WaveThreadEvent = 0;
-
     waveInClose(data->WaveHandle.In);
     data->WaveHandle.In = 0;
 
@@ -701,6 +655,17 @@ static ALCuint WinMMAvailableSamples(ALCdevice *Device)
 }
 
 
+static inline void AppendAllDevicesList2(const al_string *name)
+{
+    if(!al_string_empty(*name))
+        AppendAllDevicesList(al_string_get_cstr(*name));
+}
+static inline void AppendCaptureDeviceList2(const al_string *name)
+{
+    if(!al_string_empty(*name))
+        AppendCaptureDeviceList(al_string_get_cstr(*name));
+}
+
 static const BackendFuncs WinMMFuncs = {
     WinMMOpenPlayback,
     WinMMClosePlayback,
@@ -718,52 +683,34 @@ static const BackendFuncs WinMMFuncs = {
 
 ALCboolean alcWinMMInit(BackendFuncs *FuncList)
 {
+    VECTOR_INIT(PlaybackDevices);
+    VECTOR_INIT(CaptureDevices);
+
     *FuncList = WinMMFuncs;
     return ALC_TRUE;
 }
 
 void alcWinMMDeinit()
 {
-    ALuint i;
+    clear_devlist(&PlaybackDevices);
+    VECTOR_DEINIT(PlaybackDevices);
 
-    for(i = 0;i < NumPlaybackDevices;i++)
-        free(PlaybackDeviceList[i]);
-    free(PlaybackDeviceList);
-    PlaybackDeviceList = NULL;
-
-    NumPlaybackDevices = 0;
-
-
-    for(i = 0;i < NumCaptureDevices;i++)
-        free(CaptureDeviceList[i]);
-    free(CaptureDeviceList);
-    CaptureDeviceList = NULL;
-
-    NumCaptureDevices = 0;
+    clear_devlist(&CaptureDevices);
+    VECTOR_DEINIT(CaptureDevices);
 }
 
 void alcWinMMProbe(enum DevProbe type)
 {
-    ALuint i;
-
     switch(type)
     {
         case ALL_DEVICE_PROBE:
             ProbePlaybackDevices();
-            for(i = 0;i < NumPlaybackDevices;i++)
-            {
-                if(PlaybackDeviceList[i])
-                    AppendAllDevicesList(PlaybackDeviceList[i]);
-            }
+            VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2);
             break;
 
         case CAPTURE_DEVICE_PROBE:
             ProbeCaptureDevices();
-            for(i = 0;i < NumCaptureDevices;i++)
-            {
-                if(CaptureDeviceList[i])
-                    AppendCaptureDeviceList(CaptureDeviceList[i]);
-            }
+            VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2);
             break;
     }
 }

+ 37 - 79
jni/openal-soft-android/Alc/bs2b.c → jni/openal-soft-1.16.0/Alc/bs2b.c

@@ -27,93 +27,82 @@
 #include <string.h>
 
 #include "bs2b.h"
+#include "alu.h"
 
 #ifndef M_PI
 #define M_PI  3.14159265358979323846
 #endif
 
-/* Single pole IIR filter.
- * O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1]
- */
-
-/* Lowpass filter */
-#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1))
-
-/* Highboost filter */
-#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1))
-
 /* Set up all data. */
 static void init(struct bs2b *bs2b)
 {
-    double Fc_lo, Fc_hi;
-    double G_lo,  G_hi;
-    double x;
+    float Fc_lo, Fc_hi;
+    float G_lo,  G_hi;
+    float x, g;
 
-    if ((bs2b->srate > 192000) || (bs2b->srate < 2000))
-        bs2b->srate = BS2B_DEFAULT_SRATE;
+    bs2b->srate = clampi(bs2b->srate, 2000, 192000);
 
     switch(bs2b->level)
     {
     case BS2B_LOW_CLEVEL: /* Low crossfeed level */
-        Fc_lo = 360.0;
-        Fc_hi = 501.0;
-        G_lo  = 0.398107170553497;
-        G_hi  = 0.205671765275719;
+        Fc_lo = 360.0f;
+        Fc_hi = 501.0f;
+        G_lo  = 0.398107170553497f;
+        G_hi  = 0.205671765275719f;
         break;
 
     case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */
-        Fc_lo = 500.0;
-        Fc_hi = 711.0;
-        G_lo  = 0.459726988530872;
-        G_hi  = 0.228208484414988;
+        Fc_lo = 500.0f;
+        Fc_hi = 711.0f;
+        G_lo  = 0.459726988530872f;
+        G_hi  = 0.228208484414988f;
         break;
 
     case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */
-        Fc_lo = 700.0;
-        Fc_hi = 1021.0;
-        G_lo  = 0.530884444230988;
-        G_hi  = 0.250105790667544;
+        Fc_lo = 700.0f;
+        Fc_hi = 1021.0f;
+        G_lo  = 0.530884444230988f;
+        G_hi  = 0.250105790667544f;
         break;
 
     case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */
-        Fc_lo = 360.0;
-        Fc_hi = 494.0;
-        G_lo  = 0.316227766016838;
-        G_hi  = 0.168236228897329;
+        Fc_lo = 360.0f;
+        Fc_hi = 494.0f;
+        G_lo  = 0.316227766016838f;
+        G_hi  = 0.168236228897329f;
         break;
 
     case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */
-        Fc_lo = 500.0;
-        Fc_hi = 689.0;
-        G_lo  = 0.354813389233575;
-        G_hi  = 0.187169483835901;
+        Fc_lo = 500.0f;
+        Fc_hi = 689.0f;
+        G_lo  = 0.354813389233575f;
+        G_hi  = 0.187169483835901f;
         break;
 
     default: /* High easy crossfeed level */
         bs2b->level = BS2B_HIGH_ECLEVEL;
 
-        Fc_lo = 700.0;
-        Fc_hi = 975.0;
-        G_lo  = 0.398107170553497;
-        G_hi  = 0.205671765275719;
+        Fc_lo = 700.0f;
+        Fc_hi = 975.0f;
+        G_lo  = 0.398107170553497f;
+        G_hi  = 0.205671765275719f;
         break;
     } /* switch */
 
+    g = 1.0f / (1.0f - G_hi + G_lo);
+
     /* $fc = $Fc / $s;
      * $d  = 1 / 2 / pi / $fc;
      * $x  = exp(-1 / $d);
      */
-
-    x           = exp(-2.0 * M_PI * Fc_lo / bs2b->srate);
+    x           = expf(-2.0f * F_PI * Fc_lo / bs2b->srate);
     bs2b->b1_lo = x;
-    bs2b->a0_lo = G_lo * (1.0 - x);
+    bs2b->a0_lo = G_lo * (1.0f - x) * g;
 
-    x           = exp(-2.0 * M_PI * Fc_hi / bs2b->srate);
+    x           = expf(-2.0f * F_PI * Fc_hi / bs2b->srate);
     bs2b->b1_hi = x;
-    bs2b->a0_hi = 1.0 - G_hi * (1.0 - x);
-    bs2b->a1_hi = -x;
-
-    bs2b->gain  = 1.0f / (float)(1.0 - G_hi + G_lo);
+    bs2b->a0_hi = (1.0f - G_hi * (1.0f - x)) * g;
+    bs2b->a1_hi = -x * g;
 } /* init */
 
 /* Exported functions.
@@ -151,35 +140,4 @@ void bs2b_clear(struct bs2b *bs2b)
     memset(&bs2b->last_sample, 0, sizeof(bs2b->last_sample));
 } /* bs2b_clear */
 
-void bs2b_cross_feed(struct bs2b *bs2b, float *sample)
-{
-    /* Lowpass filter */
-    bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]);
-    bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]);
-
-    /* Highboost filter */
-    bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]);
-    bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]);
-    bs2b->last_sample.asis[0] = sample[0];
-    bs2b->last_sample.asis[1] = sample[1];
-
-    /* Crossfeed */
-    sample[0] = (float)(bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1]);
-    sample[1] = (float)(bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0]);
-
-    /* Bass boost cause allpass attenuation */
-    sample[0] *= bs2b->gain;
-    sample[1] *= bs2b->gain;
-
-    /* Clipping of overloaded samples */
-#if 0
-    if (sample[0] > 1.0)
-        sample[0] = 1.0;
-    if (sample[0] < -1.0)
-        sample[0] = -1.0;
-    if (sample[1] > 1.0)
-        sample[1] = 1.0;
-    if (sample[1] < -1.0)
-        sample[1] = -1.0;
-#endif
-} /* bs2b_cross_feed */
+extern inline void bs2b_cross_feed(struct bs2b *bs2b, float *restrict samples);

+ 32 - 0
jni/openal-soft-1.16.0/Alc/compat.h

@@ -0,0 +1,32 @@
+#ifndef AL_COMPAT_H
+#define AL_COMPAT_H
+
+#ifdef _WIN32
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+WCHAR *strdupW(const WCHAR *str);
+
+/* Opens a file with standard I/O. The filename is expected to be UTF-8. */
+FILE *al_fopen(const char *fname, const char *mode);
+
+#define HAVE_DYNLOAD 1
+
+#else
+
+#define al_fopen fopen
+
+#if defined(HAVE_DLFCN_H) && !defined(IN_IDE_PARSER)
+#define HAVE_DYNLOAD 1
+#endif
+
+#endif
+
+#ifdef HAVE_DYNLOAD
+void *LoadLib(const char *name);
+void CloseLib(void *handle);
+void *GetSymbol(void *handle, const char *name);
+#endif
+
+#endif /* AL_COMPAT_H */

+ 12 - 15
jni/openal-soft-android/Alc/effects/autowah.c → jni/openal-soft-1.16.0/Alc/effects/autowah.c

@@ -59,7 +59,7 @@ static ALvoid ALautowahState_Destruct(ALautowahState *UNUSED(state))
 
 static ALboolean ALautowahState_deviceUpdate(ALautowahState *state, ALCdevice *device)
 {
-    state->Frequency = device->Frequency;
+    state->Frequency = (ALfloat)device->Frequency;
     return AL_TRUE;
 }
 
@@ -71,8 +71,8 @@ static ALvoid ALautowahState_update(ALautowahState *state, ALCdevice *device, co
     attackTime = slot->EffectProps.Autowah.AttackTime * state->Frequency;
     releaseTime = slot->EffectProps.Autowah.ReleaseTime * state->Frequency;
 
-    state->AttackRate = 1.0f / attackTime;
-    state->ReleaseRate = 1.0f / releaseTime;
+    state->AttackRate = powf(1.0f/GAIN_SILENCE_THRESHOLD, 1.0f/attackTime);
+    state->ReleaseRate = powf(GAIN_SILENCE_THRESHOLD/1.0f, 1.0f/releaseTime);
     state->PeakGain = slot->EffectProps.Autowah.PeakGain;
     state->Resonance = slot->EffectProps.Autowah.Resonance;
 
@@ -100,15 +100,15 @@ static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo,
 
             /* Similar to compressor, we get the current amplitude of the
              * incoming signal, and attack or release to reach it. */
-            amplitude = fabs(smp);
+            amplitude = fabsf(smp);
             if(amplitude > gain)
-                gain = minf(gain+state->AttackRate, amplitude);
+                gain = minf(gain*state->AttackRate, amplitude);
             else if(amplitude < gain)
-                gain = maxf(gain-state->ReleaseRate, amplitude);
+                gain = maxf(gain*state->ReleaseRate, amplitude);
             gain = maxf(gain, GAIN_SILENCE_THRESHOLD);
 
             /* FIXME: What range does the filter cover? */
-            cutoff = lerp(1000.0f, (ALfloat)LOWPASSFREQREF, minf(gain/state->PeakGain, 1.0f));
+            cutoff = lerp(20.0f, 20000.0f, minf(gain/state->PeakGain, 1.0f));
 
             /* The code below is like calling ALfilterState_setParams with
              * ALfilterType_LowPass. However, instead of passing a bandwidth,
@@ -151,10 +151,7 @@ static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo,
     }
 }
 
-static void ALautowahState_Delete(ALautowahState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALautowahState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALautowahState);
 
@@ -167,13 +164,13 @@ static ALeffectState *ALautowahStateFactory_create(ALautowahStateFactory *UNUSED
 {
     ALautowahState *state;
 
-    state = malloc(sizeof(*state));
+    state = ALautowahState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALautowahState, ALeffectState, state);
 
-    state->AttackRate = 0.0f;
-    state->ReleaseRate = 0.0f;
-    state->Resonance = 0.0f;
+    state->AttackRate = 1.0f;
+    state->ReleaseRate = 1.0f;
+    state->Resonance = 2.0f;
     state->PeakGain = 1.0f;
     state->GainCtrl = 1.0f;
 

+ 29 - 13
jni/openal-soft-android/Alc/effects/chorus.c → jni/openal-soft-1.16.0/Alc/effects/chorus.c

@@ -30,6 +30,11 @@
 #include "alu.h"
 
 
+enum ChorusWaveForm {
+    CWF_Triangle = AL_CHORUS_WAVEFORM_TRIANGLE,
+    CWF_Sinusoid = AL_CHORUS_WAVEFORM_SINUSOID
+};
+
 typedef struct ALchorusState {
     DERIVE_FROM_TYPE(ALeffectState);
 
@@ -44,7 +49,7 @@ typedef struct ALchorusState {
     ALfloat Gain[2][MaxChannels];
 
     /* effect parameters */
-    ALint waveform;
+    enum ChorusWaveForm waveform;
     ALint delay;
     ALfloat depth;
     ALfloat feedback;
@@ -92,7 +97,15 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons
     ALfloat rate;
     ALint phase;
 
-    state->waveform = Slot->EffectProps.Chorus.Waveform;
+    switch(Slot->EffectProps.Chorus.Waveform)
+    {
+        case AL_CHORUS_WAVEFORM_TRIANGLE:
+            state->waveform = CWF_Triangle;
+            break;
+        case AL_CHORUS_WAVEFORM_SINUSOID:
+            state->waveform = CWF_Sinusoid;
+            break;
+    }
     state->depth = Slot->EffectProps.Chorus.Depth;
     state->feedback = Slot->EffectProps.Chorus.Feedback;
     state->delay = fastf2i(Slot->EffectProps.Chorus.Delay * frequency);
@@ -115,10 +128,10 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons
         state->lfo_range = fastf2u(frequency/rate + 0.5f);
         switch(state->waveform)
         {
-            case AL_CHORUS_WAVEFORM_TRIANGLE:
+            case CWF_Triangle:
                 state->lfo_scale = 4.0f / state->lfo_range;
                 break;
-            case AL_CHORUS_WAVEFORM_SINUSOID:
+            case CWF_Sinusoid:
                 state->lfo_scale = F_2PI / state->lfo_range;
                 break;
         }
@@ -198,10 +211,15 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, co
         ALfloat temps[64][2];
         ALuint td = minu(SamplesToDo-base, 64);
 
-        if(state->waveform == AL_CHORUS_WAVEFORM_TRIANGLE)
-            ProcessTriangle(state, td, SamplesIn+base, temps);
-        else if(state->waveform == AL_CHORUS_WAVEFORM_SINUSOID)
-            ProcessSinusoid(state, td, SamplesIn+base, temps);
+        switch(state->waveform)
+        {
+            case CWF_Triangle:
+                ProcessTriangle(state, td, SamplesIn+base, temps);
+                break;
+            case CWF_Sinusoid:
+                ProcessSinusoid(state, td, SamplesIn+base, temps);
+                break;
+        }
 
         for(kt = 0;kt < MaxChannels;kt++)
         {
@@ -224,10 +242,7 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, co
     }
 }
 
-static void ALchorusState_Delete(ALchorusState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALchorusState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALchorusState);
 
@@ -240,7 +255,7 @@ static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(f
 {
     ALchorusState *state;
 
-    state = malloc(sizeof(*state));
+    state = ALchorusState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALchorusState, ALeffectState, state);
 
@@ -249,6 +264,7 @@ static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(f
     state->SampleBuffer[1] = NULL;
     state->offset = 0;
     state->lfo_range = 1;
+    state->waveform = CWF_Triangle;
 
     return STATIC_CAST(ALeffectState, state);
 }

+ 4 - 7
jni/openal-soft-android/Alc/effects/compressor.c → jni/openal-soft-1.16.0/Alc/effects/compressor.c

@@ -84,12 +84,12 @@ static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint Samples
             {
                 smp = SamplesIn[it+base];
 
-                amplitude = fabs(smp);
+                amplitude = fabsf(smp);
                 if(amplitude > gain)
                     gain = minf(gain+state->AttackRate, amplitude);
                 else if(amplitude < gain)
                     gain = maxf(gain-state->ReleaseRate, amplitude);
-                output = 1.0 / clampf(gain, 0.5f, 2.0f);
+                output = 1.0f / clampf(gain, 0.5f, 2.0f);
 
                 temps[it] = smp * output;
             }
@@ -133,10 +133,7 @@ static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint Samples
     }
 }
 
-static void ALcompressorState_Delete(ALcompressorState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALcompressorState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALcompressorState);
 
@@ -149,7 +146,7 @@ static ALeffectState *ALcompressorStateFactory_create(ALcompressorStateFactory *
 {
     ALcompressorState *state;
 
-    state = malloc(sizeof(*state));
+    state = ALcompressorState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALcompressorState, ALeffectState, state);
 

+ 2 - 5
jni/openal-soft-android/Alc/effects/dedicated.c → jni/openal-soft-1.16.0/Alc/effects/dedicated.c

@@ -76,10 +76,7 @@ static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALuint SamplesTo
     }
 }
 
-static void ALdedicatedState_Delete(ALdedicatedState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALdedicatedState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALdedicatedState);
 
@@ -93,7 +90,7 @@ ALeffectState *ALdedicatedStateFactory_create(ALdedicatedStateFactory *UNUSED(fa
     ALdedicatedState *state;
     ALsizei s;
 
-    state = malloc(sizeof(*state));
+    state = ALdedicatedState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALdedicatedState, ALeffectState, state);
 

+ 2 - 5
jni/openal-soft-android/Alc/effects/distortion.c → jni/openal-soft-1.16.0/Alc/effects/distortion.c

@@ -170,10 +170,7 @@ static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint Samples
     }
 }
 
-static void ALdistortionState_Delete(ALdistortionState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALdistortionState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALdistortionState);
 
@@ -186,7 +183,7 @@ static ALeffectState *ALdistortionStateFactory_create(ALdistortionStateFactory *
 {
     ALdistortionState *state;
 
-    state = malloc(sizeof(*state));
+    state = ALdistortionState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALdistortionState, ALeffectState, state);
 

+ 3 - 6
jni/openal-soft-android/Alc/effects/echo.c → jni/openal-soft-1.16.0/Alc/effects/echo.c

@@ -97,7 +97,7 @@ static ALvoid ALechoState_update(ALechoState *state, ALCdevice *Device, const AL
 
     ALfilterState_setParams(&state->Filter, ALfilterType_HighShelf,
                             1.0f - Slot->EffectProps.Echo.Damping,
-                            (ALfloat)LOWPASSFREQREF/frequency, 0.0f);
+                            LOWPASSFREQREF/frequency, 0.0f);
 
     gain = Slot->Gain;
     dirGain = fabsf(lrpan);
@@ -161,10 +161,7 @@ static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const
     state->Offset = offset;
 }
 
-static void ALechoState_Delete(ALechoState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALechoState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALechoState);
 
@@ -177,7 +174,7 @@ ALeffectState *ALechoStateFactory_create(ALechoStateFactory *UNUSED(factory))
 {
     ALechoState *state;
 
-    state = malloc(sizeof(*state));
+    state = ALechoState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALechoState, ALeffectState, state);
 

+ 2 - 5
jni/openal-soft-android/Alc/effects/equalizer.c → jni/openal-soft-1.16.0/Alc/effects/equalizer.c

@@ -155,10 +155,7 @@ static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesTo
     }
 }
 
-static void ALequalizerState_Delete(ALequalizerState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALequalizerState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALequalizerState);
 
@@ -172,7 +169,7 @@ ALeffectState *ALequalizerStateFactory_create(ALequalizerStateFactory *UNUSED(fa
     ALequalizerState *state;
     int it;
 
-    state = malloc(sizeof(*state));
+    state = ALequalizerState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALequalizerState, ALeffectState, state);
 

+ 29 - 13
jni/openal-soft-android/Alc/effects/flanger.c → jni/openal-soft-1.16.0/Alc/effects/flanger.c

@@ -30,6 +30,11 @@
 #include "alu.h"
 
 
+enum FlangerWaveForm {
+    FWF_Triangle = AL_FLANGER_WAVEFORM_TRIANGLE,
+    FWF_Sinusoid = AL_FLANGER_WAVEFORM_SINUSOID
+};
+
 typedef struct ALflangerState {
     DERIVE_FROM_TYPE(ALeffectState);
 
@@ -44,7 +49,7 @@ typedef struct ALflangerState {
     ALfloat Gain[2][MaxChannels];
 
     /* effect parameters */
-    ALint waveform;
+    enum FlangerWaveForm waveform;
     ALint delay;
     ALfloat depth;
     ALfloat feedback;
@@ -92,7 +97,15 @@ static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, co
     ALfloat rate;
     ALint phase;
 
-    state->waveform = Slot->EffectProps.Flanger.Waveform;
+    switch(Slot->EffectProps.Flanger.Waveform)
+    {
+        case AL_FLANGER_WAVEFORM_TRIANGLE:
+            state->waveform = FWF_Triangle;
+            break;
+        case AL_FLANGER_WAVEFORM_SINUSOID:
+            state->waveform = FWF_Sinusoid;
+            break;
+    }
     state->depth = Slot->EffectProps.Flanger.Depth;
     state->feedback = Slot->EffectProps.Flanger.Feedback;
     state->delay = fastf2i(Slot->EffectProps.Flanger.Delay * frequency);
@@ -115,10 +128,10 @@ static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, co
         state->lfo_range = fastf2u(frequency/rate + 0.5f);
         switch(state->waveform)
         {
-            case AL_FLANGER_WAVEFORM_TRIANGLE:
+            case FWF_Triangle:
                 state->lfo_scale = 4.0f / state->lfo_range;
                 break;
-            case AL_FLANGER_WAVEFORM_SINUSOID:
+            case FWF_Sinusoid:
                 state->lfo_scale = F_2PI / state->lfo_range;
                 break;
         }
@@ -198,10 +211,15 @@ static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo,
         ALfloat temps[64][2];
         ALuint td = minu(SamplesToDo-base, 64);
 
-        if(state->waveform == AL_FLANGER_WAVEFORM_TRIANGLE)
-            ProcessTriangle(state, td, SamplesIn+base, temps);
-        else if(state->waveform == AL_FLANGER_WAVEFORM_SINUSOID)
-            ProcessSinusoid(state, td, SamplesIn+base, temps);
+        switch(state->waveform)
+        {
+            case FWF_Triangle:
+                ProcessTriangle(state, td, SamplesIn+base, temps);
+                break;
+            case FWF_Sinusoid:
+                ProcessSinusoid(state, td, SamplesIn+base, temps);
+                break;
+        }
 
         for(kt = 0;kt < MaxChannels;kt++)
         {
@@ -224,10 +242,7 @@ static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo,
     }
 }
 
-static void ALflangerState_Delete(ALflangerState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALflangerState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALflangerState);
 
@@ -240,7 +255,7 @@ ALeffectState *ALflangerStateFactory_create(ALflangerStateFactory *UNUSED(factor
 {
     ALflangerState *state;
 
-    state = malloc(sizeof(*state));
+    state = ALflangerState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALflangerState, ALeffectState, state);
 
@@ -249,6 +264,7 @@ ALeffectState *ALflangerStateFactory_create(ALflangerStateFactory *UNUSED(factor
     state->SampleBuffer[1] = NULL;
     state->offset = 0;
     state->lfo_range = 1;
+    state->waveform = FWF_Triangle;
 
     return STATIC_CAST(ALeffectState, state);
 }

+ 2 - 5
jni/openal-soft-android/Alc/effects/modulator.c → jni/openal-soft-1.16.0/Alc/effects/modulator.c

@@ -171,10 +171,7 @@ static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALuint SamplesTo
     }
 }
 
-static void ALmodulatorState_Delete(ALmodulatorState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState);
 
@@ -187,7 +184,7 @@ static ALeffectState *ALmodulatorStateFactory_create(ALmodulatorStateFactory *UN
 {
     ALmodulatorState *state;
 
-    state = malloc(sizeof(*state));
+    state = ALmodulatorState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALmodulatorState, ALeffectState, state);
 

+ 14 - 4
jni/openal-soft-android/Alc/effects/null.c → jni/openal-soft-1.16.0/Alc/effects/null.c

@@ -48,10 +48,20 @@ static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALuint UNUSED(samp
     (void)samplesOut;
 }
 
-/* This frees the memory used by the object, after it has been destructed. */
-static void ALnullState_Delete(ALnullState *state)
+/* This allocates memory to store the object, before it gets constructed.
+ * DECLARE_DEFAULT_ALLOCATORS can be used to declate a default method.
+ */
+static void *ALnullState_New(size_t size)
+{
+    return malloc(size);
+}
+
+/* This frees the memory used by the object, after it has been destructed.
+ * DECLARE_DEFAULT_ALLOCATORS can be used to declate a default method.
+ */
+static void ALnullState_Delete(void *ptr)
 {
-    free(state);
+    free(ptr);
 }
 
 /* Define the forwards and the ALeffectState vtable for this type. */
@@ -67,7 +77,7 @@ ALeffectState *ALnullStateFactory_create(ALnullStateFactory *UNUSED(factory))
 {
     ALnullState *state;
 
-    state = calloc(1, sizeof(*state));
+    state = ALnullState_New(sizeof(*state));
     if(!state) return NULL;
     /* Set vtables for inherited types. */
     SET_VTABLE2(ALnullState, ALeffectState, state);

+ 3 - 6
jni/openal-soft-android/Alc/effects/reverb.c → jni/openal-soft-1.16.0/Alc/effects/reverb.c

@@ -1096,7 +1096,7 @@ static ALvoid ALreverbState_update(ALreverbState *State, ALCdevice *Device, cons
     }
     else
     {
-        hfscale = (ALfloat)LOWPASSFREQREF / frequency;
+        hfscale = LOWPASSFREQREF / frequency;
         ALfilterState_setParams(&State->LpFilter, ALfilterType_HighShelf,
                                 Slot->EffectProps.Reverb.GainHF,
                                 hfscale, 0.0f);
@@ -1170,10 +1170,7 @@ static ALvoid ALreverbState_Destruct(ALreverbState *State)
     State->SampleBuffer = NULL;
 }
 
-static void ALreverbState_Delete(ALreverbState *state)
-{
-    free(state);
-}
+DECLARE_DEFAULT_ALLOCATORS(ALreverbState)
 
 DEFINE_ALEFFECTSTATE_VTABLE(ALreverbState);
 
@@ -1187,7 +1184,7 @@ static ALeffectState *ALreverbStateFactory_create(ALreverbStateFactory* UNUSED(f
     ALreverbState *state;
     ALuint index;
 
-    state = malloc(sizeof(ALreverbState));
+    state = ALreverbState_New(sizeof(*state));
     if(!state) return NULL;
     SET_VTABLE2(ALreverbState, ALeffectState, state);
 

+ 0 - 0
jni/openal-soft-android/Alc/evtqueue.h → jni/openal-soft-1.16.0/Alc/evtqueue.h


+ 814 - 0
jni/openal-soft-1.16.0/Alc/helpers.c

@@ -0,0 +1,814 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 2011 by authors.
+ * This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the
+ *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ *  Boston, MA  02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#ifdef _WIN32
+#ifdef __MINGW32__
+#define _WIN32_IE 0x501
+#else
+#define _WIN32_IE 0x400
+#endif
+#endif
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <time.h>
+#include <errno.h>
+#include <stdarg.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#ifndef AL_NO_UID_DEFS
+#if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H)
+#define INITGUID
+#include <windows.h>
+#ifdef HAVE_GUIDDEF_H
+#include <guiddef.h>
+#else
+#include <initguid.h>
+#endif
+
+DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM,        0x00000001, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71);
+DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71);
+
+DEFINE_GUID(IID_IDirectSoundNotify,   0xb0210783, 0x89cd, 0x11d0, 0xaf,0x08, 0x00,0xa0,0xc9,0x25,0xcd,0x16);
+
+DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e);
+DEFINE_GUID(IID_IMMDeviceEnumerator,  0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6);
+DEFINE_GUID(IID_IAudioClient,         0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2);
+DEFINE_GUID(IID_IAudioRenderClient,   0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2);
+
+#ifdef HAVE_MMDEVAPI
+#include <devpropdef.h>
+DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
+#endif
+#endif
+#endif /* AL_NO_UID_DEFS */
+
+#ifdef HAVE_DLFCN_H
+#include <dlfcn.h>
+#endif
+#ifdef HAVE_INTRIN_H
+#include <intrin.h>
+#endif
+#ifdef HAVE_CPUID_H
+#include <cpuid.h>
+#endif
+#ifdef HAVE_SYS_SYSCONF_H
+#include <sys/sysconf.h>
+#endif
+#ifdef HAVE_FLOAT_H
+#include <float.h>
+#endif
+#ifdef HAVE_IEEEFP_H
+#include <ieeefp.h>
+#endif
+
+#ifdef _WIN32_IE
+#include <shlobj.h>
+#endif
+
+#include "alMain.h"
+#include "alu.h"
+#include "atomic.h"
+#include "uintmap.h"
+#include "vector.h"
+#include "alstring.h"
+#include "compat.h"
+#include "threads.h"
+
+
+extern inline ALuint NextPowerOf2(ALuint value);
+extern inline ALint fastf2i(ALfloat f);
+extern inline ALuint fastf2u(ALfloat f);
+
+
+ALuint CPUCapFlags = 0;
+
+
+void FillCPUCaps(ALuint capfilter)
+{
+    ALuint caps = 0;
+
+/* FIXME: We really should get this for all available CPUs in case different
+ * CPUs have different caps (is that possible on one machine?). */
+#if defined(HAVE_GCC_GET_CPUID) && (defined(__i386__) || defined(__x86_64__) || \
+                                    defined(_M_IX86) || defined(_M_X64))
+    union {
+        unsigned int regs[4];
+        char str[sizeof(unsigned int[4])];
+    } cpuinf[3];
+
+    if(!__get_cpuid(0, &cpuinf[0].regs[0], &cpuinf[0].regs[1], &cpuinf[0].regs[2], &cpuinf[0].regs[3]))
+        ERR("Failed to get CPUID\n");
+    else
+    {
+        unsigned int maxfunc = cpuinf[0].regs[0];
+        unsigned int maxextfunc = 0;
+
+        if(__get_cpuid(0x80000000, &cpuinf[0].regs[0], &cpuinf[0].regs[1], &cpuinf[0].regs[2], &cpuinf[0].regs[3]))
+            maxextfunc = cpuinf[0].regs[0];
+        TRACE("Detected max CPUID function: 0x%x (ext. 0x%x)\n", maxfunc, maxextfunc);
+
+        TRACE("Vendor ID: \"%.4s%.4s%.4s\"\n", cpuinf[0].str+4, cpuinf[0].str+12, cpuinf[0].str+8);
+        if(maxextfunc >= 0x80000004 &&
+           __get_cpuid(0x80000002, &cpuinf[0].regs[0], &cpuinf[0].regs[1], &cpuinf[0].regs[2], &cpuinf[0].regs[3]) &&
+           __get_cpuid(0x80000003, &cpuinf[1].regs[0], &cpuinf[1].regs[1], &cpuinf[1].regs[2], &cpuinf[1].regs[3]) &&
+           __get_cpuid(0x80000004, &cpuinf[2].regs[0], &cpuinf[2].regs[1], &cpuinf[2].regs[2], &cpuinf[2].regs[3]))
+            TRACE("Name: \"%.16s%.16s%.16s\"\n", cpuinf[0].str, cpuinf[1].str, cpuinf[2].str);
+
+        if(maxfunc >= 1 &&
+           __get_cpuid(1, &cpuinf[0].regs[0], &cpuinf[0].regs[1], &cpuinf[0].regs[2], &cpuinf[0].regs[3]))
+        {
+            if((cpuinf[0].regs[3]&(1<<25)))
+            {
+                caps |= CPU_CAP_SSE;
+                if((cpuinf[0].regs[3]&(1<<26)))
+                {
+                    caps |= CPU_CAP_SSE2;
+                    if((cpuinf[0].regs[2]&(1<<19)))
+                        caps |= CPU_CAP_SSE4_1;
+                }
+            }
+        }
+    }
+#elif defined(HAVE_CPUID_INTRINSIC) && (defined(__i386__) || defined(__x86_64__) || \
+                                        defined(_M_IX86) || defined(_M_X64))
+    union {
+        int regs[4];
+        char str[sizeof(int[4])];
+    } cpuinf[3];
+
+    (__cpuid)(cpuinf[0].regs, 0);
+    if(cpuinf[0].regs[0] == 0)
+        ERR("Failed to get CPUID\n");
+    else
+    {
+        unsigned int maxfunc = cpuinf[0].regs[0];
+        unsigned int maxextfunc;
+
+        (__cpuid)(cpuinf[0].regs, 0x80000000);
+        maxextfunc = cpuinf[0].regs[0];
+
+        TRACE("Detected max CPUID function: 0x%x (ext. 0x%x)\n", maxfunc, maxextfunc);
+
+        TRACE("Vendor ID: \"%.4s%.4s%.4s\"\n", cpuinf[0].str+4, cpuinf[0].str+12, cpuinf[0].str+8);
+        if(maxextfunc >= 0x80000004)
+        {
+            (__cpuid)(cpuinf[0].regs, 0x80000002);
+            (__cpuid)(cpuinf[1].regs, 0x80000003);
+            (__cpuid)(cpuinf[2].regs, 0x80000004);
+            TRACE("Name: \"%.16s%.16s%.16s\"\n", cpuinf[0].str, cpuinf[1].str, cpuinf[2].str);
+        }
+
+        if(maxfunc >= 1)
+        {
+            (__cpuid)(cpuinf[0].regs, 1);
+            if((cpuinf[0].regs[3]&(1<<25)))
+            {
+                caps |= CPU_CAP_SSE;
+                if((cpuinf[0].regs[3]&(1<<26)))
+                {
+                    caps |= CPU_CAP_SSE2;
+                    if((cpuinf[0].regs[2]&(1<<19)))
+                        caps |= CPU_CAP_SSE4_1;
+                }
+            }
+        }
+    }
+#else
+    /* Assume support for whatever's supported if we can't check for it */
+#if defined(HAVE_SSE4_1)
+#warning "Assuming SSE 4.1 run-time support!"
+    capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
+#elif defined(HAVE_SSE2)
+#warning "Assuming SSE 2 run-time support!"
+    capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
+#elif defined(HAVE_SSE)
+#warning "Assuming SSE run-time support!"
+    capfilter |= CPU_CAP_SSE;
+#endif
+#endif
+#ifdef HAVE_NEON
+    /* Assume Neon support if compiled with it */
+    caps |= CPU_CAP_NEON;
+#endif
+
+    TRACE("Extensions:%s%s%s%s%s\n",
+        ((capfilter&CPU_CAP_SSE)    ? ((caps&CPU_CAP_SSE)    ? " +SSE"    : " -SSE")    : ""),
+        ((capfilter&CPU_CAP_SSE2)   ? ((caps&CPU_CAP_SSE2)   ? " +SSE2"   : " -SSE2")   : ""),
+        ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""),
+        ((capfilter&CPU_CAP_NEON)   ? ((caps&CPU_CAP_NEON)   ? " +Neon"   : " -Neon")   : ""),
+        ((!capfilter) ? " -none-" : "")
+    );
+    CPUCapFlags = caps & capfilter;
+}
+
+
+void *al_malloc(size_t alignment, size_t size)
+{
+#if defined(HAVE_ALIGNED_ALLOC)
+    size = (size+(alignment-1))&~(alignment-1);
+    return aligned_alloc(alignment, size);
+#elif defined(HAVE_POSIX_MEMALIGN)
+    void *ret;
+    if(posix_memalign(&ret, alignment, size) == 0)
+        return ret;
+    return NULL;
+#elif defined(HAVE__ALIGNED_MALLOC)
+    return _aligned_malloc(size, alignment);
+#else
+    char *ret = malloc(size+alignment);
+    if(ret != NULL)
+    {
+        *(ret++) = 0x00;
+        while(((ALintptrEXT)ret&(alignment-1)) != 0)
+            *(ret++) = 0x55;
+    }
+    return ret;
+#endif
+}
+
+void *al_calloc(size_t alignment, size_t size)
+{
+    void *ret = al_malloc(alignment, size);
+    if(ret) memset(ret, 0, size);
+    return ret;
+}
+
+void al_free(void *ptr)
+{
+#if defined(HAVE_ALIGNED_ALLOC) || defined(HAVE_POSIX_MEMALIGN)
+    free(ptr);
+#elif defined(HAVE__ALIGNED_MALLOC)
+    _aligned_free(ptr);
+#else
+    if(ptr != NULL)
+    {
+        char *finder = ptr;
+        do {
+            --finder;
+        } while(*finder == 0x55);
+        free(finder);
+    }
+#endif
+}
+
+
+void SetMixerFPUMode(FPUCtl *ctl)
+{
+#ifdef HAVE_FENV_H
+    fegetenv(STATIC_CAST(fenv_t, ctl));
+#if defined(__GNUC__) && defined(HAVE_SSE)
+    if((CPUCapFlags&CPU_CAP_SSE))
+        __asm__ __volatile__("stmxcsr %0" : "=m" (*&ctl->sse_state));
+#endif
+
+#ifdef FE_TOWARDZERO
+    fesetround(FE_TOWARDZERO);
+#endif
+#if defined(__GNUC__) && defined(HAVE_SSE)
+    if((CPUCapFlags&CPU_CAP_SSE))
+    {
+        int sseState = ctl->sse_state;
+        sseState |= 0x6000; /* set round-to-zero */
+        sseState |= 0x8000; /* set flush-to-zero */
+        if((CPUCapFlags&CPU_CAP_SSE2))
+            sseState |= 0x0040; /* set denormals-are-zero */
+        __asm__ __volatile__("ldmxcsr %0" : : "m" (*&sseState));
+    }
+#endif
+
+#elif defined(HAVE___CONTROL87_2)
+
+    int mode;
+    __control87_2(0, 0, &ctl->state, NULL);
+    __control87_2(_RC_CHOP, _MCW_RC, &mode, NULL);
+#ifdef HAVE_SSE
+    if((CPUCapFlags&CPU_CAP_SSE))
+    {
+        __control87_2(0, 0, NULL, &ctl->sse_state);
+        __control87_2(_RC_CHOP|_DN_FLUSH, _MCW_RC|_MCW_DN, NULL, &mode);
+    }
+#endif
+
+#elif defined(HAVE__CONTROLFP)
+
+    ctl->state = _controlfp(0, 0);
+    (void)_controlfp(_RC_CHOP, _MCW_RC);
+#endif
+}
+
+void RestoreFPUMode(const FPUCtl *ctl)
+{
+#ifdef HAVE_FENV_H
+    fesetenv(STATIC_CAST(fenv_t, ctl));
+#if defined(__GNUC__) && defined(HAVE_SSE)
+    if((CPUCapFlags&CPU_CAP_SSE))
+        __asm__ __volatile__("ldmxcsr %0" : : "m" (*&ctl->sse_state));
+#endif
+
+#elif defined(HAVE___CONTROL87_2)
+
+    int mode;
+    __control87_2(ctl->state, _MCW_RC, &mode, NULL);
+#ifdef HAVE_SSE
+    if((CPUCapFlags&CPU_CAP_SSE))
+        __control87_2(ctl->sse_state, _MCW_RC|_MCW_DN, NULL, &mode);
+#endif
+
+#elif defined(HAVE__CONTROLFP)
+
+    _controlfp(ctl->state, _MCW_RC);
+#endif
+}
+
+
+#ifdef _WIN32
+
+static WCHAR *FromUTF8(const char *str)
+{
+    WCHAR *out = NULL;
+    int len;
+
+    if((len=MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)) > 0)
+    {
+        out = calloc(sizeof(WCHAR), len);
+        MultiByteToWideChar(CP_UTF8, 0, str, -1, out, len);
+    }
+    return out;
+}
+
+
+void *LoadLib(const char *name)
+{
+    HANDLE hdl = NULL;
+    WCHAR *wname;
+
+    wname = FromUTF8(name);
+    if(!wname)
+        ERR("Failed to convert UTF-8 filename: \"%s\"\n", name);
+    else
+    {
+        hdl = LoadLibraryW(wname);
+        free(wname);
+    }
+    return hdl;
+}
+void CloseLib(void *handle)
+{ FreeLibrary((HANDLE)handle); }
+void *GetSymbol(void *handle, const char *name)
+{
+    void *ret;
+
+    ret = (void*)GetProcAddress((HANDLE)handle, name);
+    if(ret == NULL)
+        ERR("Failed to load %s\n", name);
+    return ret;
+}
+
+WCHAR *strdupW(const WCHAR *str)
+{
+    const WCHAR *n;
+    WCHAR *ret;
+    size_t len;
+
+    n = str;
+    while(*n) n++;
+    len = n - str;
+
+    ret = calloc(sizeof(WCHAR), len+1);
+    if(ret != NULL)
+        memcpy(ret, str, sizeof(WCHAR)*len);
+    return ret;
+}
+
+FILE *al_fopen(const char *fname, const char *mode)
+{
+    WCHAR *wname=NULL, *wmode=NULL;
+    FILE *file = NULL;
+
+    wname = FromUTF8(fname);
+    wmode = FromUTF8(mode);
+    if(!wname)
+        ERR("Failed to convert UTF-8 filename: \"%s\"\n", fname);
+    else if(!wmode)
+        ERR("Failed to convert UTF-8 mode: \"%s\"\n", mode);
+    else
+        file = _wfopen(wname, wmode);
+
+    free(wname);
+    free(wmode);
+
+    return file;
+}
+
+#else
+
+#ifdef HAVE_DLFCN_H
+
+void *LoadLib(const char *name)
+{
+    const char *err;
+    void *handle;
+
+    dlerror();
+    handle = dlopen(name, RTLD_NOW);
+    if((err=dlerror()) != NULL)
+        handle = NULL;
+    return handle;
+}
+void CloseLib(void *handle)
+{ dlclose(handle); }
+void *GetSymbol(void *handle, const char *name)
+{
+    const char *err;
+    void *sym;
+
+    dlerror();
+    sym = dlsym(handle, name);
+    if((err=dlerror()) != NULL)
+    {
+        WARN("Failed to load %s: %s\n", name, err);
+        sym = NULL;
+    }
+    return sym;
+}
+
+#endif
+#endif
+
+
+void al_print(const char *type, const char *func, const char *fmt, ...)
+{
+    va_list ap;
+
+    va_start(ap, fmt);
+    fprintf(LogFile, "AL lib: %s %s: ", type, func);
+    vfprintf(LogFile, fmt, ap);
+    va_end(ap);
+
+    fflush(LogFile);
+}
+
+#ifdef _WIN32
+static inline int is_slash(int c)
+{ return (c == '\\' || c == '/'); }
+
+FILE *OpenDataFile(const char *fname, const char *subdir)
+{
+    static const int ids[2] = { CSIDL_APPDATA, CSIDL_COMMON_APPDATA };
+    WCHAR *wname=NULL, *wsubdir=NULL;
+    FILE *f;
+    int i;
+
+    /* If the path is absolute, open it directly. */
+    if(fname[0] != '\0' && fname[1] == ':' && is_slash(fname[2]))
+    {
+        if((f=al_fopen(fname, "rb")) != NULL)
+        {
+            TRACE("Opened %s\n", fname);
+            return f;
+        }
+        WARN("Could not open %s\n", fname);
+        return NULL;
+    }
+
+    /* If it's relative, try the current directory first before the data directories. */
+    if((f=al_fopen(fname, "rb")) != NULL)
+    {
+        TRACE("Opened %s\n", fname);
+        return f;
+    }
+    WARN("Could not open %s\n", fname);
+
+    wname = FromUTF8(fname);
+    wsubdir = FromUTF8(subdir);
+    if(!wname)
+        ERR("Failed to convert UTF-8 filename: \"%s\"\n", fname);
+    else if(!wsubdir)
+        ERR("Failed to convert UTF-8 subdir: \"%s\"\n", subdir);
+    else for(i = 0;i < 2;i++)
+    {
+        WCHAR buffer[PATH_MAX];
+        size_t len;
+
+        if(SHGetSpecialFolderPathW(NULL, buffer, ids[i], FALSE) == FALSE)
+            continue;
+
+        len = lstrlenW(buffer);
+        if(len > 0 && is_slash(buffer[len-1]))
+            buffer[--len] = '\0';
+        _snwprintf(buffer+len, PATH_MAX-len, L"/%ls/%ls", wsubdir, wname);
+        len = lstrlenW(buffer);
+        while(len > 0)
+        {
+            --len;
+            if(buffer[len] == '/')
+                buffer[len] = '\\';
+        }
+
+        if((f=_wfopen(buffer, L"rb")) != NULL)
+        {
+            TRACE("Opened %ls\n", buffer);
+            return f;
+        }
+        WARN("Could not open %ls\n", buffer);
+    }
+    free(wname);
+    free(wsubdir);
+
+    return NULL;
+}
+#else
+FILE *OpenDataFile(const char *fname, const char *subdir)
+{
+    char buffer[PATH_MAX] = "";
+    const char *str, *next;
+    FILE *f;
+
+    if(fname[0] == '/')
+    {
+        if((f=al_fopen(fname, "rb")) != NULL)
+        {
+            TRACE("Opened %s\n", fname);
+            return f;
+        }
+        WARN("Could not open %s\n", fname);
+        return NULL;
+    }
+
+    if((f=al_fopen(fname, "rb")) != NULL)
+    {
+        TRACE("Opened %s\n", fname);
+        return f;
+    }
+    WARN("Could not open %s\n", fname);
+
+    if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0')
+        snprintf(buffer, sizeof(buffer), "%s/%s/%s", str, subdir, fname);
+    else if((str=getenv("HOME")) != NULL && str[0] != '\0')
+        snprintf(buffer, sizeof(buffer), "%s/.local/share/%s/%s", str, subdir, fname);
+    if(buffer[0])
+    {
+        if((f=al_fopen(buffer, "rb")) != NULL)
+        {
+            TRACE("Opened %s\n", buffer);
+            return f;
+        }
+        WARN("Could not open %s\n", buffer);
+    }
+
+    if((str=getenv("XDG_DATA_DIRS")) == NULL || str[0] == '\0')
+        str = "/usr/local/share/:/usr/share/";
+
+    next = str;
+    while((str=next) != NULL && str[0] != '\0')
+    {
+        size_t len;
+        next = strchr(str, ':');
+
+        if(!next)
+            len = strlen(str);
+        else
+        {
+            len = next - str;
+            next++;
+        }
+
+        if(len > sizeof(buffer)-1)
+            len = sizeof(buffer)-1;
+        strncpy(buffer, str, len);
+        buffer[len] = '\0';
+        snprintf(buffer+len, sizeof(buffer)-len, "/%s/%s", subdir, fname);
+
+        if((f=al_fopen(buffer, "rb")) != NULL)
+        {
+            TRACE("Opened %s\n", buffer);
+            return f;
+        }
+        WARN("Could not open %s\n", buffer);
+    }
+
+    return NULL;
+}
+#endif
+
+
+void SetRTPriority(void)
+{
+    ALboolean failed = AL_FALSE;
+
+#ifdef _WIN32
+    if(RTPrioLevel > 0)
+        failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
+#elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__)
+    if(RTPrioLevel > 0)
+    {
+        struct sched_param param;
+        /* Use the minimum real-time priority possible for now (on Linux this
+         * should be 1 for SCHED_RR) */
+        param.sched_priority = sched_get_priority_min(SCHED_RR);
+        failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, &param);
+    }
+#else
+    /* Real-time priority not available */
+    failed = (RTPrioLevel>0);
+#endif
+    if(failed)
+        ERR("Failed to set priority level for thread\n");
+}
+
+
+ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count, ALboolean exact)
+{
+    vector_ *vecptr = (vector_*)ptr;
+    if(obj_count < 0)
+        return AL_FALSE;
+    if((*vecptr ? (*vecptr)->Capacity : 0) < obj_count)
+    {
+        ALsizei old_size = (*vecptr ? (*vecptr)->Size : 0);
+        void *temp;
+
+        /* Use the next power-of-2 size if we don't need to allocate the exact
+         * amount. This is preferred when regularly increasing the vector since
+         * it means fewer reallocations. Though it means it also wastes some
+         * memory. */
+        if(exact == AL_FALSE)
+        {
+            obj_count = NextPowerOf2((ALuint)obj_count);
+            if(obj_count < 0) return AL_FALSE;
+        }
+
+        /* Need to be explicit with the caller type's base size, because it
+         * could have extra padding before the start of the array (that is,
+         * sizeof(*vector_) may not equal base_size). */
+        temp = realloc(*vecptr, base_size + obj_size*obj_count);
+        if(temp == NULL) return AL_FALSE;
+
+        *vecptr = temp;
+        (*vecptr)->Capacity = obj_count;
+        (*vecptr)->Size = old_size;
+    }
+    return AL_TRUE;
+}
+
+ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count)
+{
+    vector_ *vecptr = (vector_*)ptr;
+    if(obj_count < 0)
+        return AL_FALSE;
+    if(*vecptr || obj_count > 0)
+    {
+        if(!vector_reserve((char*)vecptr, base_size, obj_size, obj_count, AL_TRUE))
+            return AL_FALSE;
+        (*vecptr)->Size = obj_count;
+    }
+    return AL_TRUE;
+}
+
+ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_pos, const void *datstart, const void *datend)
+{
+    vector_ *vecptr = (vector_*)ptr;
+    if(datstart != datend)
+    {
+        ptrdiff_t ins_elem = (*vecptr ? ((char*)ins_pos - ((char*)(*vecptr) + base_size)) :
+                                        ((char*)ins_pos - (char*)NULL)) /
+                             obj_size;
+        ptrdiff_t numins = ((const char*)datend - (const char*)datstart) / obj_size;
+
+        assert(numins > 0);
+        if(INT_MAX-VECTOR_SIZE(*vecptr) <= numins ||
+           !vector_reserve((char*)vecptr, base_size, obj_size, VECTOR_SIZE(*vecptr)+numins, AL_TRUE))
+            return AL_FALSE;
+
+        /* NOTE: ins_pos may have been invalidated if *vecptr moved. Use ins_elem instead. */
+        if(ins_elem < (*vecptr)->Size)
+        {
+            memmove((char*)(*vecptr) + base_size + ((ins_elem+numins)*obj_size),
+                    (char*)(*vecptr) + base_size + ((ins_elem       )*obj_size),
+                    ((*vecptr)->Size-ins_elem)*obj_size);
+        }
+        memcpy((char*)(*vecptr) + base_size + (ins_elem*obj_size),
+               datstart, numins*obj_size);
+        (*vecptr)->Size += (ALsizei)numins;
+    }
+    return AL_TRUE;
+}
+
+
+extern inline void al_string_deinit(al_string *str);
+extern inline ALsizei al_string_length(const_al_string str);
+extern inline ALboolean al_string_empty(const_al_string str);
+extern inline const al_string_char_type *al_string_get_cstr(const_al_string str);
+
+void al_string_clear(al_string *str)
+{
+    /* Reserve one more character than the total size of the string. This is to
+     * ensure we have space to add a null terminator in the string data so it
+     * can be used as a C-style string. */
+    VECTOR_RESERVE(*str, 1);
+    VECTOR_RESIZE(*str, 0);
+    *VECTOR_ITER_END(*str) = 0;
+}
+
+static inline int al_string_compare(const al_string_char_type *str1, ALsizei str1len,
+                                    const al_string_char_type *str2, ALsizei str2len)
+{
+    ALsizei complen = mini(str1len, str2len);
+    int ret = memcmp(str1, str2, complen);
+    if(ret == 0)
+    {
+        if(str1len > str2len) return  1;
+        if(str1len < str2len) return -1;
+    }
+    return ret;
+}
+int al_string_cmp(const_al_string str1, const_al_string str2)
+{
+    return al_string_compare(&VECTOR_FRONT(str1), al_string_length(str1),
+                             &VECTOR_FRONT(str2), al_string_length(str2));
+}
+int al_string_cmp_cstr(const_al_string str1, const al_string_char_type *str2)
+{
+    return al_string_compare(&VECTOR_FRONT(str1), al_string_length(str1),
+                             str2, (ALsizei)strlen(str2));
+}
+
+void al_string_copy(al_string *str, const_al_string from)
+{
+    ALsizei len = VECTOR_SIZE(from);
+    VECTOR_RESERVE(*str, len+1);
+    VECTOR_RESIZE(*str, 0);
+    VECTOR_INSERT(*str, VECTOR_ITER_END(*str), VECTOR_ITER_BEGIN(from), VECTOR_ITER_BEGIN(from)+len);
+    *VECTOR_ITER_END(*str) = 0;
+}
+
+void al_string_copy_cstr(al_string *str, const al_string_char_type *from)
+{
+    size_t len = strlen(from);
+    VECTOR_RESERVE(*str, len+1);
+    VECTOR_RESIZE(*str, 0);
+    VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, from+len);
+    *VECTOR_ITER_END(*str) = 0;
+}
+
+void al_string_append_char(al_string *str, const al_string_char_type c)
+{
+    VECTOR_RESERVE(*str, al_string_length(*str)+2);
+    VECTOR_PUSH_BACK(*str, c);
+    *VECTOR_ITER_END(*str) = 0;
+}
+
+void al_string_append_cstr(al_string *str, const al_string_char_type *from)
+{
+    size_t len = strlen(from);
+    if(len != 0)
+    {
+        VECTOR_RESERVE(*str, al_string_length(*str)+len+1);
+        VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, from+len);
+        *VECTOR_ITER_END(*str) = 0;
+    }
+}
+
+void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to)
+{
+    if(to != from)
+    {
+        VECTOR_RESERVE(*str, al_string_length(*str)+(to-from)+1);
+        VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, to);
+        *VECTOR_ITER_END(*str) = 0;
+    }
+}
+
+#ifdef _WIN32
+void al_string_copy_wcstr(al_string *str, const wchar_t *from)
+{
+    int len;
+    if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0)
+    {
+        VECTOR_RESERVE(*str, len);
+        VECTOR_RESIZE(*str, len-1);
+        WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str), len, NULL, NULL);
+        *VECTOR_ITER_END(*str) = 0;
+    }
+}
+#endif

+ 138 - 146
jni/openal-soft-android/Alc/hrtf.c → jni/openal-soft-1.16.0/Alc/hrtf.c

@@ -28,11 +28,7 @@
 #include "alMain.h"
 #include "alSource.h"
 #include "alu.h"
-
-
-#ifndef PATH_MAX
-#define PATH_MAX 4096
-#endif
+#include "hrtf.h"
 
 
 /* Current data set limits defined by the makehrtf utility. */
@@ -62,39 +58,33 @@ struct Hrtf {
 static const ALchar magicMarker00[8] = "MinPHR00";
 static const ALchar magicMarker01[8] = "MinPHR01";
 
-/* Define the default HRTF:
- *  ALubyte  defaultAzCount  [DefaultHrtf.evCount]
- *  ALushort defaultEvOffset [DefaultHrtf.evCount]
- *  ALshort  defaultCoeffs   [DefaultHrtf.irCount * defaultHrtf.irSize]
- *  ALubyte  defaultDelays   [DefaultHrtf.irCount]
- *
- *  struct Hrtf DefaultHrtf
- */
-#include "hrtf_tables.inc"
+/* First value for pass-through coefficients (remaining are 0), used for omni-
+ * directional sounds. */
+static const ALfloat PassthruCoeff = 32767.0f * 0.707106781187f/*sqrt(0.5)*/;
 
 static struct Hrtf *LoadedHrtfs = NULL;
 
 /* Calculate the elevation indices given the polar elevation in radians.
- * This will return two indices between 0 and (Hrtf->evCount - 1) and an
+ * This will return two indices between 0 and (evcount - 1) and an
  * interpolation factor between 0.0 and 1.0.
  */
-static void CalcEvIndices(const struct Hrtf *Hrtf, ALfloat ev, ALuint *evidx, ALfloat *evmu)
+static void CalcEvIndices(ALuint evcount, ALfloat ev, ALuint *evidx, ALfloat *evmu)
 {
-    ev = (F_PI_2 + ev) * (Hrtf->evCount-1) / F_PI;
+    ev = (F_PI_2 + ev) * (evcount-1) / F_PI;
     evidx[0] = fastf2u(ev);
-    evidx[1] = minu(evidx[0] + 1, Hrtf->evCount-1);
+    evidx[1] = minu(evidx[0] + 1, evcount-1);
     *evmu = ev - evidx[0];
 }
 
 /* Calculate the azimuth indices given the polar azimuth in radians.  This
- * will return two indices between 0 and (Hrtf->azCount[ei] - 1) and an
- * interpolation factor between 0.0 and 1.0.
+ * will return two indices between 0 and (azcount - 1) and an interpolation
+ * factor between 0.0 and 1.0.
  */
-static void CalcAzIndices(const struct Hrtf *Hrtf, ALuint evidx, ALfloat az, ALuint *azidx, ALfloat *azmu)
+static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *azmu)
 {
-    az = (F_2PI + az) * Hrtf->azCount[evidx] / (F_2PI);
-    azidx[0] = fastf2u(az) % Hrtf->azCount[evidx];
-    azidx[1] = (azidx[0] + 1) % Hrtf->azCount[evidx];
+    az = (F_2PI + az) * azcount / (F_2PI);
+    azidx[0] = fastf2u(az) % azcount;
+    azidx[1] = (azidx[0] + 1) % azcount;
     *azmu = az - floorf(az);
 }
 
@@ -112,18 +102,17 @@ ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3],
     oldGain = maxf(oldGain, 0.0001f);
     gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f));
 
-    // Calculate the normalized listener to source angle change when there is
-    // enough gain to notice it.
+    // Calculate the angle change only when there is enough gain to notice it.
     angleChange = 0.0f;
     if(gainChange > 0.0001f || newGain > 0.0001f)
     {
         // No angle change when the directions are equal or degenerate (when
         // both have zero length).
-        if(newdir[0]-olddir[0] || newdir[1]-olddir[1] || newdir[2]-olddir[2])
-            angleChange = acosf(olddir[0]*newdir[0] +
-                                olddir[1]*newdir[1] +
-                                olddir[2]*newdir[2]) / F_PI;
-
+        if(newdir[0] != olddir[0] || newdir[1] != olddir[1] || newdir[2] != olddir[2])
+        {
+            ALfloat dotp = olddir[0]*newdir[0] + olddir[1]*newdir[1] + olddir[2]*newdir[2];
+            angleChange = acosf(clampf(dotp, -1.0f, 1.0f)) / F_PI;
+        }
     }
 
     // Use the largest of the two changes for the delta factor, and apply a
@@ -137,37 +126,30 @@ ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3],
  * increase the apparent resolution of the HRIR data set.  The coefficients
  * are also normalized and attenuated by the specified gain.
  */
-void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
+void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
 {
-    ALuint evidx[2], azidx[2];
-    ALuint lidx[4], ridx[4];
+    ALuint evidx[2], lidx[4], ridx[4];
     ALfloat mu[3], blend[4];
     ALuint i;
 
-    // Claculate elevation indices and interpolation factor.
-    CalcEvIndices(Hrtf, elevation, evidx, &mu[2]);
-
-    // Calculate azimuth indices and interpolation factor for the first
-    // elevation.
-    CalcAzIndices(Hrtf, evidx[0], azimuth, azidx, &mu[0]);
-
-    // Calculate the first set of linear HRIR indices for left and right
-    // channels.
-    lidx[0] = Hrtf->evOffset[evidx[0]] + azidx[0];
-    lidx[1] = Hrtf->evOffset[evidx[0]] + azidx[1];
-    ridx[0] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[0]) % Hrtf->azCount[evidx[0]]);
-    ridx[1] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[1]) % Hrtf->azCount[evidx[0]]);
+    /* Claculate elevation indices and interpolation factor. */
+    CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]);
 
-    // Calculate azimuth indices and interpolation factor for the second
-    // elevation.
-    CalcAzIndices(Hrtf, evidx[1], azimuth, azidx, &mu[1]);
-
-    // Calculate the second set of linear HRIR indices for left and right
-    // channels.
-    lidx[2] = Hrtf->evOffset[evidx[1]] + azidx[0];
-    lidx[3] = Hrtf->evOffset[evidx[1]] + azidx[1];
-    ridx[2] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[0]) % Hrtf->azCount[evidx[1]]);
-    ridx[3] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[1]) % Hrtf->azCount[evidx[1]]);
+    for(i = 0;i < 2;i++)
+    {
+        ALuint azcount = Hrtf->azCount[evidx[i]];
+        ALuint evoffset = Hrtf->evOffset[evidx[i]];
+        ALuint azidx[2];
+
+        /* Calculate azimuth indices and interpolation factor for this elevation. */
+        CalcAzIndices(azcount, azimuth, azidx, &mu[i]);
+
+        /* Calculate a set of linear HRIR indices for left and right channels. */
+        lidx[i*2 + 0] = evoffset + azidx[0];
+        lidx[i*2 + 1] = evoffset + azidx[1];
+        ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount);
+        ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount);
+    }
 
     /* Calculate 4 blending weights for 2D bilinear interpolation. */
     blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
@@ -176,12 +158,12 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi
     blend[3] = (     mu[1]) * (     mu[2]);
 
     /* Calculate the HRIR delays using linear interpolation. */
-    delays[0] = fastf2u(Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
-                        Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3] +
-                        0.5f) << HRTFDELAY_BITS;
-    delays[1] = fastf2u(Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
-                        Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3] +
-                        0.5f) << HRTFDELAY_BITS;
+    delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
+                         Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) *
+                        dirfact + 0.5f) << HRTFDELAY_BITS;
+    delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
+                         Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
+                        dirfact + 0.5f) << HRTFDELAY_BITS;
 
     /* Calculate the sample offsets for the HRIR indices. */
     lidx[0] *= Hrtf->irSize;
@@ -199,17 +181,26 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi
      */
     if(gain > 0.0001f)
     {
+        ALfloat c;
+
         gain *= 1.0f/32767.0f;
-        for(i = 0;i < Hrtf->irSize;i++)
+
+        i = 0;
+        c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
+             Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
+        coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain;
+        c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
+             Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
+        coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain;
+
+        for(i = 1;i < Hrtf->irSize;i++)
         {
-            coeffs[i][0] = (Hrtf->coeffs[lidx[0]+i]*blend[0] +
-                            Hrtf->coeffs[lidx[1]+i]*blend[1] +
-                            Hrtf->coeffs[lidx[2]+i]*blend[2] +
-                            Hrtf->coeffs[lidx[3]+i]*blend[3]) * gain;
-            coeffs[i][1] = (Hrtf->coeffs[ridx[0]+i]*blend[0] +
-                            Hrtf->coeffs[ridx[1]+i]*blend[1] +
-                            Hrtf->coeffs[ridx[2]+i]*blend[2] +
-                            Hrtf->coeffs[ridx[3]+i]*blend[3]) * gain;
+            c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
+                 Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
+            coeffs[i][0] = lerp(0.0f, c, dirfact) * gain;
+            c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
+                 Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
+            coeffs[i][1] = lerp(0.0f, c, dirfact) * gain;
         }
     }
     else
@@ -229,39 +220,32 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi
  * specified gain.  Stepping resolution and count is determined using the
  * given delta factor between 0.0 and 1.0.
  */
-ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep)
+ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep)
 {
-    ALuint evidx[2], azidx[2];
-    ALuint lidx[4], ridx[4];
+    ALuint evidx[2], lidx[4], ridx[4];
     ALfloat mu[3], blend[4];
     ALfloat left, right;
     ALfloat step;
     ALuint i;
 
-    // Claculate elevation indices and interpolation factor.
-    CalcEvIndices(Hrtf, elevation, evidx, &mu[2]);
-
-    // Calculate azimuth indices and interpolation factor for the first
-    // elevation.
-    CalcAzIndices(Hrtf, evidx[0], azimuth, azidx, &mu[0]);
-
-    // Calculate the first set of linear HRIR indices for left and right
-    // channels.
-    lidx[0] = Hrtf->evOffset[evidx[0]] + azidx[0];
-    lidx[1] = Hrtf->evOffset[evidx[0]] + azidx[1];
-    ridx[0] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[0]) % Hrtf->azCount[evidx[0]]);
-    ridx[1] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[1]) % Hrtf->azCount[evidx[0]]);
-
-    // Calculate azimuth indices and interpolation factor for the second
-    // elevation.
-    CalcAzIndices(Hrtf, evidx[1], azimuth, azidx, &mu[1]);
+    /* Claculate elevation indices and interpolation factor. */
+    CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]);
 
-    // Calculate the second set of linear HRIR indices for left and right
-    // channels.
-    lidx[2] = Hrtf->evOffset[evidx[1]] + azidx[0];
-    lidx[3] = Hrtf->evOffset[evidx[1]] + azidx[1];
-    ridx[2] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[0]) % Hrtf->azCount[evidx[1]]);
-    ridx[3] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[1]) % Hrtf->azCount[evidx[1]]);
+    for(i = 0;i < 2;i++)
+    {
+        ALuint azcount = Hrtf->azCount[evidx[i]];
+        ALuint evoffset = Hrtf->evOffset[evidx[i]];
+        ALuint azidx[2];
+
+        /* Calculate azimuth indices and interpolation factor for this elevation. */
+        CalcAzIndices(azcount, azimuth, azidx, &mu[i]);
+
+        /* Calculate a set of linear HRIR indices for left and right channels. */
+        lidx[i*2 + 0] = evoffset + azidx[0];
+        lidx[i*2 + 1] = evoffset + azidx[1];
+        ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount);
+        ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount);
+    }
 
     // Calculate the stepping parameters.
     delta = maxf(floorf(delta*(Hrtf->sampleRate*0.015f) + 0.5f), 1.0f);
@@ -280,12 +264,12 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
     left = (ALfloat)(delays[0] - (delayStep[0] * counter));
     right = (ALfloat)(delays[1] - (delayStep[1] * counter));
 
-    delays[0] = fastf2u(Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
-                        Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3] +
-                        0.5f) << HRTFDELAY_BITS;
-    delays[1] = fastf2u(Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
-                        Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3] +
-                        0.5f) << HRTFDELAY_BITS;
+    delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
+                         Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) *
+                        dirfact + 0.5f) << HRTFDELAY_BITS;
+    delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
+                         Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
+                        dirfact + 0.5f) << HRTFDELAY_BITS;
 
     delayStep[0] = fastf2i(step * (delays[0] - left));
     delayStep[1] = fastf2i(step * (delays[1] - right));
@@ -308,20 +292,35 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
      */
     if(gain > 0.0001f)
     {
+        ALfloat c;
+
         gain *= 1.0f/32767.0f;
-        for(i = 0;i < HRIR_LENGTH;i++)
+
+        i = 0;
+        left = coeffs[i][0] - (coeffStep[i][0] * counter);
+        right = coeffs[i][1] - (coeffStep[i][1] * counter);
+
+        c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
+             Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
+        coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain;
+        c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
+             Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
+        coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain;
+
+        coeffStep[i][0] = step * (coeffs[i][0] - left);
+        coeffStep[i][1] = step * (coeffs[i][1] - right);
+
+        for(i = 1;i < Hrtf->irSize;i++)
         {
             left = coeffs[i][0] - (coeffStep[i][0] * counter);
             right = coeffs[i][1] - (coeffStep[i][1] * counter);
 
-            coeffs[i][0] = (Hrtf->coeffs[lidx[0]+i]*blend[0] +
-                            Hrtf->coeffs[lidx[1]+i]*blend[1] +
-                            Hrtf->coeffs[lidx[2]+i]*blend[2] +
-                            Hrtf->coeffs[lidx[3]+i]*blend[3]) * gain;
-            coeffs[i][1] = (Hrtf->coeffs[ridx[0]+i]*blend[0] +
-                            Hrtf->coeffs[ridx[1]+i]*blend[1] +
-                            Hrtf->coeffs[ridx[2]+i]*blend[2] +
-                            Hrtf->coeffs[ridx[3]+i]*blend[3]) * gain;
+            c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
+                 Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
+            coeffs[i][0] = lerp(0.0f, c, dirfact) * gain;
+            c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
+                 Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
+            coeffs[i][1] = lerp(0.0f, c, dirfact) * gain;
 
             coeffStep[i][0] = step * (coeffs[i][0] - left);
             coeffStep[i][1] = step * (coeffs[i][1] - right);
@@ -329,7 +328,7 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
     }
     else
     {
-        for(i = 0;i < HRIR_LENGTH;i++)
+        for(i = 0;i < Hrtf->irSize;i++)
         {
             left = coeffs[i][0] - (coeffStep[i][0] * counter);
             right = coeffs[i][1] - (coeffStep[i][1] * counter);
@@ -664,24 +663,25 @@ static struct Hrtf *LoadHrtf01(FILE *f, ALuint deviceRate)
 
 static struct Hrtf *LoadHrtf(ALuint deviceRate)
 {
-    const char *fnamelist = NULL;
+    const char *fnamelist = "default-%r.mhr";
 
-    if(!ConfigValueStr(NULL, "hrtf_tables", &fnamelist))
-        return NULL;
+    ConfigValueStr(NULL, "hrtf_tables", &fnamelist);
     while(*fnamelist != '\0')
     {
         struct Hrtf *Hrtf = NULL;
         char fname[PATH_MAX];
+        const char *next;
         ALchar magic[8];
         ALuint i;
         FILE *f;
 
+        i = 0;
         while(isspace(*fnamelist) || *fnamelist == ',')
             fnamelist++;
-        i = 0;
-        while(*fnamelist != '\0' && *fnamelist != ',')
+        next = fnamelist;
+        while(*(fnamelist=next) != '\0' && *fnamelist != ',')
         {
-            const char *next = strpbrk(fnamelist, "%,");
+            next = strpbrk(fnamelist, "%,");
             while(fnamelist != next && *fnamelist && i < sizeof(fname))
                 fname[i++] = *(fnamelist++);
 
@@ -704,7 +704,6 @@ static struct Hrtf *LoadHrtf(ALuint deviceRate)
             }
             else
                 ERR("Invalid marker '%%%c'\n", *next);
-            fnamelist = next;
         }
         i = minu(i, sizeof(fname)-1);
         fname[i] = '\0';
@@ -716,7 +715,7 @@ static struct Hrtf *LoadHrtf(ALuint deviceRate)
             continue;
 
         TRACE("Loading %s...\n", fname);
-        f = fopen(fname, "rb");
+        f = OpenDataFile(fname, "openal/hrtf");
         if(f == NULL)
         {
             ERR("Could not open %s\n", fname);
@@ -759,52 +758,45 @@ static struct Hrtf *LoadHrtf(ALuint deviceRate)
     return NULL;
 }
 
-const struct Hrtf *GetHrtf(ALCdevice *device)
+const struct Hrtf *GetHrtf(enum DevFmtChannels chans, ALCuint srate)
 {
-    if(device->FmtChans == DevFmtStereo)
+    if(chans == DevFmtStereo)
     {
         struct Hrtf *Hrtf = LoadedHrtfs;
         while(Hrtf != NULL)
         {
-            if(device->Frequency == Hrtf->sampleRate)
+            if(srate == Hrtf->sampleRate)
                 return Hrtf;
             Hrtf = Hrtf->next;
         }
 
-        Hrtf = LoadHrtf(device->Frequency);
+        Hrtf = LoadHrtf(srate);
         if(Hrtf != NULL)
             return Hrtf;
-
-        if(device->Frequency == DefaultHrtf.sampleRate)
-            return &DefaultHrtf;
     }
-    ERR("Incompatible format: %s %uhz\n",
-        DevFmtChannelsString(device->FmtChans), device->Frequency);
+    ERR("Incompatible format: %s %uhz\n", DevFmtChannelsString(chans), srate);
     return NULL;
 }
 
-void FindHrtfFormat(const ALCdevice *device, enum DevFmtChannels *chans, ALCuint *srate)
+ALCboolean FindHrtfFormat(enum DevFmtChannels *chans, ALCuint *srate)
 {
-    const struct Hrtf *hrtf = &DefaultHrtf;
-
-    if(device->Frequency != DefaultHrtf.sampleRate)
+    const struct Hrtf *hrtf = LoadedHrtfs;
+    while(hrtf != NULL)
     {
-        hrtf = LoadedHrtfs;
-        while(hrtf != NULL)
-        {
-            if(device->Frequency == hrtf->sampleRate)
-                break;
-            hrtf = hrtf->next;
-        }
+        if(*srate == hrtf->sampleRate)
+            break;
+        hrtf = hrtf->next;
+    }
 
-        if(hrtf == NULL)
-            hrtf = LoadHrtf(device->Frequency);
-        if(hrtf == NULL)
-            hrtf = &DefaultHrtf;
+    if(hrtf == NULL)
+    {
+        hrtf = LoadHrtf(*srate);
+        if(hrtf == NULL) return ALC_FALSE;
     }
 
     *chans = DevFmtStereo;
     *srate = hrtf->sampleRate;
+    return ALC_TRUE;
 }
 
 void FreeHrtfs(void)

+ 28 - 0
jni/openal-soft-1.16.0/Alc/hrtf.h

@@ -0,0 +1,28 @@
+#ifndef ALC_HRTF_H
+#define ALC_HRTF_H
+
+#include "AL/al.h"
+#include "AL/alc.h"
+
+enum DevFmtChannels;
+
+struct Hrtf;
+
+#define HRIR_BITS        (7)
+#define HRIR_LENGTH      (1<<HRIR_BITS)
+#define HRIR_MASK        (HRIR_LENGTH-1)
+#define HRTFDELAY_BITS    (20)
+#define HRTFDELAY_FRACONE (1<<HRTFDELAY_BITS)
+#define HRTFDELAY_MASK    (HRTFDELAY_FRACONE-1)
+
+const struct Hrtf *GetHrtf(enum DevFmtChannels chans, ALCuint srate);
+ALCboolean FindHrtfFormat(enum DevFmtChannels *chans, ALCuint *srate);
+
+void FreeHrtfs(void);
+
+ALuint GetHrtfIrSize(const struct Hrtf *Hrtf);
+ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]);
+void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays);
+ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep);
+
+#endif /* ALC_HRTF_H */

+ 19 - 53
jni/openal-soft-android/Alc/midi/base.c → jni/openal-soft-1.16.0/Alc/midi/base.c

@@ -16,8 +16,10 @@
 #include "alu.h"
 
 
-/* Microsecond resolution */
-#define TICKS_PER_SECOND (1000000)
+extern inline ALboolean IsValidCtrlInput(int cc);
+
+extern inline size_t Reader_read(Reader *self, void *buf, size_t len);
+
 
 /* MIDI events */
 #define SYSEX_EVENT  (0xF0)
@@ -129,12 +131,9 @@ void MidiSynth_Construct(MidiSynth *self, ALCdevice *device)
     self->Gain = 1.0f;
     self->State = AL_INITIAL;
 
-    self->LastEvtTime = 0;
-    self->NextEvtTime = UINT64_MAX;
-    self->SamplesSinceLast = 0.0;
-    self->SamplesToNext = 0.0;
-
-    self->SamplesPerTick = (ALdouble)device->Frequency / TICKS_PER_SECOND;
+    self->ClockBase = 0;
+    self->SamplesDone = 0;
+    self->SampleRate = device->Frequency;
 }
 
 void MidiSynth_Destruct(MidiSynth *self)
@@ -195,29 +194,22 @@ void MidiSynth_stop(MidiSynth *self)
 {
     ResetEvtQueue(&self->EventQueue);
 
-    self->LastEvtTime = 0;
-    self->NextEvtTime = UINT64_MAX;
-    self->SamplesSinceLast = 0.0;
-    self->SamplesToNext = 0.0;
+    self->ClockBase = 0;
+    self->SamplesDone = 0;
 }
 
 extern inline void MidiSynth_reset(MidiSynth *self);
-
-ALuint64 MidiSynth_getTime(const MidiSynth *self)
-{
-    ALuint64 time = self->LastEvtTime + (self->SamplesSinceLast/self->SamplesPerTick);
-    return clampu64(time, self->LastEvtTime, self->NextEvtTime);
-}
-
+extern inline ALuint64 MidiSynth_getTime(const MidiSynth *self);
 extern inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self);
 
-void MidiSynth_setSampleRate(MidiSynth *self, ALdouble srate)
+void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate)
 {
-    ALdouble sampletickrate = srate / TICKS_PER_SECOND;
-
-    self->SamplesSinceLast = self->SamplesSinceLast * sampletickrate / self->SamplesPerTick;
-    self->SamplesToNext = self->SamplesToNext * sampletickrate / self->SamplesPerTick;
-    self->SamplesPerTick = sampletickrate;
+    if(self->SampleRate != srate)
+    {
+        self->ClockBase += self->SamplesDone * MIDI_CLOCK_RES / self->SampleRate;
+        self->SamplesDone = 0;
+        self->SampleRate = srate;
+    }
 }
 
 extern inline void MidiSynth_update(MidiSynth *self, ALCdevice *device);
@@ -225,25 +217,11 @@ extern inline void MidiSynth_update(MidiSynth *self, ALCdevice *device);
 ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2)
 {
     MidiEvent entry;
-    ALenum err;
-
     entry.time = time;
     entry.event = event;
     entry.param.val[0] = param1;
     entry.param.val[1] = param2;
-
-    err = InsertEvtQueue(&self->EventQueue, &entry);
-    if(err != AL_NO_ERROR) return err;
-
-    if(entry.time < self->NextEvtTime)
-    {
-        self->NextEvtTime = entry.time;
-
-        self->SamplesToNext  = (self->NextEvtTime - self->LastEvtTime) * self->SamplesPerTick;
-        self->SamplesToNext -= self->SamplesSinceLast;
-    }
-
-    return AL_NO_ERROR;
+    return InsertEvtQueue(&self->EventQueue, &entry);
 }
 
 ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *data, ALsizei size)
@@ -261,18 +239,6 @@ ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *
 
     err = InsertEvtQueue(&self->EventQueue, &entry);
     if(err != AL_NO_ERROR)
-    {
         free(entry.param.sysex.data);
-        return err;
-    }
-
-    if(entry.time < self->NextEvtTime)
-    {
-        self->NextEvtTime = entry.time;
-
-        self->SamplesToNext  = (self->NextEvtTime - self->LastEvtTime) * self->SamplesPerTick;
-        self->SamplesToNext -= self->SamplesSinceLast;
-    }
-
-    return AL_NO_ERROR;
+    return err;
 }

+ 20 - 15
jni/openal-soft-android/Alc/midi/base.h → jni/openal-soft-1.16.0/Alc/midi/base.h

@@ -17,23 +17,28 @@ typedef struct Reader {
     void *ptr;
     int error;
 } Reader;
-#define READ(x_, buf_, len_) ((x_)->cb((buf_), (len_), (x_)->ptr))
-#define READERR(x_)          ((x_)->error)
+inline size_t Reader_read(Reader *self, void *buf, size_t len)
+{
+    size_t got = (!self->error) ? self->cb(buf, len, self->ptr) : 0;
+    if(got < len) self->error = 1;
+    return got;
+}
+#define READERR(x_) ((x_)->error)
 
 ALboolean loadSf2(Reader *stream, struct ALsoundfont *sfont, ALCcontext *context);
 
 
+#define MIDI_CLOCK_RES  U64(1000000000)
+
+
 struct MidiSynthVtable;
 
 typedef struct MidiSynth {
     EvtQueue EventQueue;
 
-    ALuint64 LastEvtTime;
-    ALuint64 NextEvtTime;
-    ALdouble SamplesSinceLast;
-    ALdouble SamplesToNext;
-
-    ALdouble SamplesPerTick;
+    ALuint64 ClockBase;
+    ALuint SamplesDone;
+    ALuint SampleRate;
 
     /* NOTE: This rwlock is for the state and soundfont. The EventQueue and
      * related must instead use the device lock as they're used in the mixer
@@ -59,14 +64,15 @@ inline void MidiSynth_setState(MidiSynth *self, ALenum state) { ExchangeInt(&sel
 inline ALenum MidiSynth_getState(const MidiSynth *self) { return self->State; }
 void MidiSynth_stop(MidiSynth *self);
 inline void MidiSynth_reset(MidiSynth *self) { MidiSynth_stop(self); }
-ALuint64 MidiSynth_getTime(const MidiSynth *self);
+inline ALuint64 MidiSynth_getTime(const MidiSynth *self)
+{ return self->ClockBase + (self->SamplesDone*MIDI_CLOCK_RES/self->SampleRate); }
 inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self)
 {
     if(self->EventQueue.pos == self->EventQueue.size)
         return UINT64_MAX;
     return self->EventQueue.events[self->EventQueue.pos].time;
 }
-void MidiSynth_setSampleRate(MidiSynth *self, ALdouble srate);
+void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate);
 inline void MidiSynth_update(MidiSynth *self, ALCdevice *device)
 { MidiSynth_setSampleRate(self, device->Frequency); }
 ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2);
@@ -79,7 +85,6 @@ struct MidiSynthVtable {
     ALenum (*const selectSoundfonts)(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
 
     void (*const setGain)(MidiSynth *self, ALfloat gain);
-    void (*const setState)(MidiSynth *self, ALenum state);
 
     void (*const stop)(MidiSynth *self);
     void (*const reset)(MidiSynth *self);
@@ -87,26 +92,25 @@ struct MidiSynthVtable {
     void (*const update)(MidiSynth *self, ALCdevice *device);
     void (*const process)(MidiSynth *self, ALuint samples, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
 
-    void (*const Delete)(MidiSynth *self);
+    void (*const Delete)(void *ptr);
 };
 
 #define DEFINE_MIDISYNTH_VTABLE(T)                                            \
 DECLARE_THUNK(T, MidiSynth, void, Destruct)                                   \
 DECLARE_THUNK3(T, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*) \
 DECLARE_THUNK1(T, MidiSynth, void, setGain, ALfloat)                          \
-DECLARE_THUNK1(T, MidiSynth, void, setState, ALenum)                          \
 DECLARE_THUNK(T, MidiSynth, void, stop)                                       \
 DECLARE_THUNK(T, MidiSynth, void, reset)                                      \
 DECLARE_THUNK1(T, MidiSynth, void, update, ALCdevice*)                        \
 DECLARE_THUNK2(T, MidiSynth, void, process, ALuint, ALfloatBUFFERSIZE*restrict) \
-DECLARE_THUNK(T, MidiSynth, void, Delete)                                     \
+static void T##_MidiSynth_Delete(void *ptr)                                   \
+{ T##_Delete(STATIC_UPCAST(T, MidiSynth, (MidiSynth*)ptr)); }                 \
                                                                               \
 static const struct MidiSynthVtable T##_MidiSynth_vtable = {                  \
     T##_MidiSynth_Destruct,                                                   \
                                                                               \
     T##_MidiSynth_selectSoundfonts,                                           \
     T##_MidiSynth_setGain,                                                    \
-    T##_MidiSynth_setState,                                                   \
     T##_MidiSynth_stop,                                                       \
     T##_MidiSynth_reset,                                                      \
     T##_MidiSynth_update,                                                     \
@@ -116,6 +120,7 @@ static const struct MidiSynthVtable T##_MidiSynth_vtable = {                  \
 }
 
 
+MidiSynth *SSynth_create(ALCdevice *device);
 MidiSynth *FSynth_create(ALCdevice *device);
 MidiSynth *DSynth_create(ALCdevice *device);
 

+ 9 - 28
jni/openal-soft-android/Alc/midi/dummy.c → jni/openal-soft-1.16.0/Alc/midi/dummy.c

@@ -22,12 +22,11 @@ static void DSynth_Construct(DSynth *self, ALCdevice *device);
 static DECLARE_FORWARD(DSynth, MidiSynth, void, Destruct)
 static DECLARE_FORWARD3(DSynth, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*)
 static DECLARE_FORWARD1(DSynth, MidiSynth, void, setGain, ALfloat)
-static DECLARE_FORWARD1(DSynth, MidiSynth, void, setState, ALenum)
 static DECLARE_FORWARD(DSynth, MidiSynth, void, stop)
 static DECLARE_FORWARD(DSynth, MidiSynth, void, reset)
 static DECLARE_FORWARD1(DSynth, MidiSynth, void, update, ALCdevice*)
 static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
-static void DSynth_Delete(DSynth *self);
+DECLARE_DEFAULT_ALLOCATORS(DSynth)
 DEFINE_MIDISYNTH_VTABLE(DSynth);
 
 
@@ -49,47 +48,29 @@ static void DSynth_processQueue(DSynth *self, ALuint64 time)
 static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloatBUFFERSIZE*restrict UNUSED(DryBuffer))
 {
     MidiSynth *synth = STATIC_CAST(MidiSynth, self);
+    ALuint64 curtime;
 
     if(synth->State != AL_PLAYING)
         return;
 
-    synth->SamplesSinceLast += SamplesToDo;
-    synth->SamplesToNext -= SamplesToDo;
-    while(synth->SamplesToNext < 1.0f)
-    {
-        ALuint64 time = synth->NextEvtTime;
-        if(time == UINT64_MAX)
-        {
-            synth->SamplesToNext = 0.0;
-            break;
-        }
-
-        synth->SamplesSinceLast -= (time - synth->LastEvtTime) * synth->SamplesPerTick;
-        synth->SamplesSinceLast  = maxd(synth->SamplesSinceLast, 0.0);
-        synth->LastEvtTime = time;
-        DSynth_processQueue(self, time);
-
-        synth->NextEvtTime = MidiSynth_getNextEvtTime(synth);
-        if(synth->NextEvtTime != UINT64_MAX)
-            synth->SamplesToNext += (synth->NextEvtTime - synth->LastEvtTime) * synth->SamplesPerTick;
-    }
-}
+    synth->SamplesDone += SamplesToDo;
+    synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
+    synth->SamplesDone %= synth->SampleRate;
 
-
-static void DSynth_Delete(DSynth *self)
-{
-    free(self);
+    curtime = MidiSynth_getTime(synth);
+    DSynth_processQueue(self, maxi64(curtime-1, 0));
 }
 
 
 MidiSynth *DSynth_create(ALCdevice *device)
 {
-    DSynth *synth = calloc(1, sizeof(*synth));
+    DSynth *synth = DSynth_New(sizeof(*synth));
     if(!synth)
     {
         ERR("Failed to allocate DSynth\n");
         return NULL;
     }
+    memset(synth, 0, sizeof(*synth));
     DSynth_Construct(synth, device);
     return STATIC_CAST(MidiSynth, synth);
 }

+ 167 - 80
jni/openal-soft-android/Alc/midi/fluidsynth.c → jni/openal-soft-1.16.0/Alc/midi/fluidsynth.c

@@ -10,15 +10,115 @@
 #include "alMain.h"
 #include "alError.h"
 #include "alMidi.h"
+#include "alu.h"
+#include "compat.h"
 #include "evtqueue.h"
 #include "rwlock.h"
-#include "alu.h"
 
 #ifdef HAVE_FLUIDSYNTH
 
 #include <fluidsynth.h>
 
 
+#ifdef HAVE_DYNLOAD
+#define FLUID_FUNCS(MAGIC)                                                    \
+    MAGIC(new_fluid_synth);                                                   \
+    MAGIC(delete_fluid_synth);                                                \
+    MAGIC(new_fluid_settings);                                                \
+    MAGIC(delete_fluid_settings);                                             \
+    MAGIC(fluid_settings_setint);                                             \
+    MAGIC(fluid_settings_setnum);                                             \
+    MAGIC(fluid_synth_noteon);                                                \
+    MAGIC(fluid_synth_noteoff);                                               \
+    MAGIC(fluid_synth_program_change);                                        \
+    MAGIC(fluid_synth_pitch_bend);                                            \
+    MAGIC(fluid_synth_channel_pressure);                                      \
+    MAGIC(fluid_synth_cc);                                                    \
+    MAGIC(fluid_synth_sysex);                                                 \
+    MAGIC(fluid_synth_bank_select);                                           \
+    MAGIC(fluid_synth_set_channel_type);                                      \
+    MAGIC(fluid_synth_all_sounds_off);                                        \
+    MAGIC(fluid_synth_system_reset);                                          \
+    MAGIC(fluid_synth_set_gain);                                              \
+    MAGIC(fluid_synth_set_sample_rate);                                       \
+    MAGIC(fluid_synth_write_float);                                           \
+    MAGIC(fluid_synth_add_sfloader);                                          \
+    MAGIC(fluid_synth_sfload);                                                \
+    MAGIC(fluid_synth_sfunload);                                              \
+    MAGIC(fluid_synth_alloc_voice);                                           \
+    MAGIC(fluid_synth_start_voice);                                           \
+    MAGIC(fluid_voice_gen_set);                                               \
+    MAGIC(fluid_voice_add_mod);                                               \
+    MAGIC(fluid_mod_set_source1);                                             \
+    MAGIC(fluid_mod_set_source2);                                             \
+    MAGIC(fluid_mod_set_amount);                                              \
+    MAGIC(fluid_mod_set_dest);
+
+void *fsynth_handle = NULL;
+#define DECL_FUNC(x) __typeof(x) *p##x
+FLUID_FUNCS(DECL_FUNC)
+#undef DECL_FUNC
+
+#define new_fluid_synth pnew_fluid_synth
+#define delete_fluid_synth pdelete_fluid_synth
+#define new_fluid_settings pnew_fluid_settings
+#define delete_fluid_settings pdelete_fluid_settings
+#define fluid_settings_setint pfluid_settings_setint
+#define fluid_settings_setnum pfluid_settings_setnum
+#define fluid_synth_noteon pfluid_synth_noteon
+#define fluid_synth_noteoff pfluid_synth_noteoff
+#define fluid_synth_program_change pfluid_synth_program_change
+#define fluid_synth_pitch_bend pfluid_synth_pitch_bend
+#define fluid_synth_channel_pressure pfluid_synth_channel_pressure
+#define fluid_synth_cc pfluid_synth_cc
+#define fluid_synth_sysex pfluid_synth_sysex
+#define fluid_synth_bank_select pfluid_synth_bank_select
+#define fluid_synth_set_channel_type pfluid_synth_set_channel_type
+#define fluid_synth_all_sounds_off pfluid_synth_all_sounds_off
+#define fluid_synth_system_reset pfluid_synth_system_reset
+#define fluid_synth_set_gain pfluid_synth_set_gain
+#define fluid_synth_set_sample_rate pfluid_synth_set_sample_rate
+#define fluid_synth_write_float pfluid_synth_write_float
+#define fluid_synth_add_sfloader pfluid_synth_add_sfloader
+#define fluid_synth_sfload pfluid_synth_sfload
+#define fluid_synth_sfunload pfluid_synth_sfunload
+#define fluid_synth_alloc_voice pfluid_synth_alloc_voice
+#define fluid_synth_start_voice pfluid_synth_start_voice
+#define fluid_voice_gen_set pfluid_voice_gen_set
+#define fluid_voice_add_mod pfluid_voice_add_mod
+#define fluid_mod_set_source1 pfluid_mod_set_source1
+#define fluid_mod_set_source2 pfluid_mod_set_source2
+#define fluid_mod_set_amount pfluid_mod_set_amount
+#define fluid_mod_set_dest pfluid_mod_set_dest
+
+static ALboolean LoadFSynth(void)
+{
+    ALboolean ret = AL_TRUE;
+    if(!fsynth_handle)
+    {
+        fsynth_handle = LoadLib("libfluidsynth.so.1");
+        if(!fsynth_handle) return AL_FALSE;
+
+#define LOAD_FUNC(x) do {                                                     \
+     p##x = GetSymbol(fsynth_handle, #x);                                     \
+     if(!p##x) ret = AL_FALSE;                                                \
+} while(0)
+        FLUID_FUNCS(LOAD_FUNC)
+#undef LOAD_FUNC
+
+        if(ret == AL_FALSE)
+        {
+            CloseLib(fsynth_handle);
+            fsynth_handle = NULL;
+        }
+    }
+    return ret;
+}
+#else
+static inline ALboolean LoadFSynth(void) { return AL_TRUE; }
+#endif
+
+
 /* MIDI events */
 #define SYSEX_EVENT  (0xF0)
 
@@ -28,7 +128,7 @@
 #define CTRL_ALLNOTESOFF     (123)
 
 
-static int getGenInput(ALenum input)
+static int getModInput(ALenum input)
 {
     switch(input)
     {
@@ -43,7 +143,7 @@ static int getGenInput(ALenum input)
     return input&0x7F;
 }
 
-static int getGenFlags(ALenum input, ALenum type, ALenum form)
+static int getModFlags(ALenum input, ALenum type, ALenum form)
 {
     int ret = 0;
 
@@ -69,7 +169,7 @@ static int getGenFlags(ALenum input, ALenum type, ALenum form)
     return ret;
 }
 
-static enum fluid_gen_type getSf2Gen(ALenum gen)
+static enum fluid_gen_type getModDest(ALenum gen)
 {
     switch(gen)
     {
@@ -144,7 +244,7 @@ typedef struct FSample {
     ALsizei NumMods;
 } FSample;
 
-static void FSample_Construct(FSample *self, ALfontsound *sound, ALsoundfont *sfont)
+static void FSample_Construct(FSample *self, ALfontsound *sound)
 {
     fluid_sample_t *sample = STATIC_CAST(fluid_sample_t, self);
     memset(sample->name, 0, sizeof(sample->name));
@@ -156,8 +256,8 @@ static void FSample_Construct(FSample *self, ALfontsound *sound, ALsoundfont *sf
     sample->origpitch = sound->PitchKey;
     sample->pitchadj = sound->PitchCorrection;
     sample->sampletype = getSampleType(sound->SampleType);
-    sample->valid = 1;
-    sample->data = sfont->Samples;
+    sample->valid = !!sound->Buffer;
+    sample->data = sound->Buffer ? sound->Buffer->data : NULL;
 
     sample->amplitude_that_reaches_noise_floor_is_valid = 0;
     sample->amplitude_that_reaches_noise_floor = 0.0;
@@ -171,25 +271,30 @@ static void FSample_Construct(FSample *self, ALfontsound *sound, ALsoundfont *sf
     self->Sound = sound;
 
     self->NumMods = 0;
-    self->Mods = calloc(sound->ModulatorMap.size, sizeof(self->Mods[0]));
+    self->Mods = calloc(sound->ModulatorMap.size*4, sizeof(fluid_mod_t[4]));
     if(self->Mods)
     {
-        ALsizei i;
+        ALsizei i, j, k;
 
-        self->NumMods = sound->ModulatorMap.size;
-        for(i = 0;i < self->NumMods;i++)
+        for(i = j = 0;i < sound->ModulatorMap.size;i++)
         {
             ALsfmodulator *mod = sound->ModulatorMap.array[i].value;
-            fluid_mod_set_source1(&self->Mods[i], getGenInput(mod->Source[0].Input),
-                                  getGenFlags(mod->Source[0].Input, mod->Source[0].Type,
-                                              mod->Source[0].Form));
-            fluid_mod_set_source2(&self->Mods[i], getGenInput(mod->Source[1].Input),
-                                  getGenFlags(mod->Source[1].Input, mod->Source[1].Type,
-                                              mod->Source[1].Form));
-            fluid_mod_set_amount(&self->Mods[i], mod->Amount);
-            fluid_mod_set_dest(&self->Mods[i], getSf2Gen(mod->Dest));
-            self->Mods[i].next = NULL;
+            for(k = 0;k < 4;k++,mod++)
+            {
+                if(mod->Dest == AL_NONE)
+                    continue;
+                fluid_mod_set_source1(&self->Mods[j], getModInput(mod->Source[0].Input),
+                                      getModFlags(mod->Source[0].Input, mod->Source[0].Type,
+                                                  mod->Source[0].Form));
+                fluid_mod_set_source2(&self->Mods[j], getModInput(mod->Source[1].Input),
+                                      getModFlags(mod->Source[1].Input, mod->Source[1].Type,
+                                                  mod->Source[1].Form));
+                fluid_mod_set_amount(&self->Mods[j], mod->Amount);
+                fluid_mod_set_dest(&self->Mods[j], getModDest(mod->Dest));
+                self->Mods[j++].next = NULL;
+            }
         }
+        self->NumMods = j;
     }
 }
 
@@ -218,7 +323,7 @@ static int FPreset_getPreset(fluid_preset_t *preset);
 static int FPreset_getBank(fluid_preset_t *preset);
 static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int channel, int key, int velocity);
 
-static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t *parent, ALsoundfont *sfont)
+static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t *parent)
 {
     STATIC_CAST(fluid_preset_t, self)->data = self;
     STATIC_CAST(fluid_preset_t, self)->sfont = parent;
@@ -240,7 +345,7 @@ static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t *
         ALsizei i;
         self->NumSamples = preset->NumSounds;
         for(i = 0;i < self->NumSamples;i++)
-            FSample_Construct(&self->Samples[i], preset->Sounds[i], sfont);
+            FSample_Construct(&self->Samples[i], preset->Sounds[i]);
     }
 }
 
@@ -258,7 +363,6 @@ static void FPreset_Destruct(FPreset *self)
 static ALboolean FPreset_canDelete(FPreset *self)
 {
     ALsizei i;
-
     for(i = 0;i < self->NumSamples;i++)
     {
         if(fluid_sample_refcount(STATIC_CAST(fluid_sample_t, &self->Samples[i])) != 0)
@@ -298,8 +402,7 @@ static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int chan
             continue;
 
         voice = fluid_synth_alloc_voice(synth, STATIC_CAST(fluid_sample_t, sample), channel, key, vel);
-        if(voice == NULL)
-            return FLUID_FAILED;
+        if(voice == NULL) return FLUID_FAILED;
 
         fluid_voice_gen_set(voice, GEN_MODLFOTOPITCH, sound->ModLfoToPitch);
         fluid_voice_gen_set(voice, GEN_VIBLFOTOPITCH, sound->VibratoLfoToPitch);
@@ -384,7 +487,7 @@ static void FSfont_Construct(FSfont *self, ALsoundfont *sfont)
         ALsizei i;
         self->NumPresets = sfont->NumPresets;
         for(i = 0;i < self->NumPresets;i++)
-            FPreset_Construct(&self->Presets[i], sfont->Presets[i], STATIC_CAST(fluid_sfont_t, self), sfont);
+            FPreset_Construct(&self->Presets[i], sfont->Presets[i], STATIC_CAST(fluid_sfont_t, self));
     }
 }
 
@@ -470,13 +573,12 @@ static void FSynth_Destruct(FSynth *self);
 static ALboolean FSynth_init(FSynth *self, ALCdevice *device);
 static ALenum FSynth_selectSoundfonts(FSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
 static void FSynth_setGain(FSynth *self, ALfloat gain);
-static void FSynth_setState(FSynth *self, ALenum state);
 static void FSynth_stop(FSynth *self);
 static void FSynth_reset(FSynth *self);
 static void FSynth_update(FSynth *self, ALCdevice *device);
 static void FSynth_processQueue(FSynth *self, ALuint64 time);
 static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
-static void FSynth_Delete(FSynth *self);
+DECLARE_DEFAULT_ALLOCATORS(FSynth)
 DEFINE_MIDISYNTH_VTABLE(FSynth);
 
 static fluid_sfont_t *FSynth_loadSfont(fluid_sfloader_t *loader, const char *filename);
@@ -632,32 +734,15 @@ static void FSynth_setGain(FSynth *self, ALfloat gain)
 }
 
 
-static void FSynth_setState(FSynth *self, ALenum state)
-{
-    MidiSynth_setState(STATIC_CAST(MidiSynth, self), state);
-}
-
 static void FSynth_stop(FSynth *self)
 {
     MidiSynth *synth = STATIC_CAST(MidiSynth, self);
+    ALuint64 curtime;
     ALsizei chan;
 
     /* Make sure all pending events are processed. */
-    while(!(synth->SamplesToNext >= 1.0))
-    {
-        ALuint64 time = synth->NextEvtTime;
-        if(time == UINT64_MAX)
-            break;
-
-        synth->SamplesSinceLast -= (time - synth->LastEvtTime) * synth->SamplesPerTick;
-        synth->SamplesSinceLast = maxd(synth->SamplesSinceLast, 0.0);
-        synth->LastEvtTime = time;
-        FSynth_processQueue(self, time);
-
-        synth->NextEvtTime = MidiSynth_getNextEvtTime(synth);
-        if(synth->NextEvtTime != UINT64_MAX)
-            synth->SamplesToNext += (synth->NextEvtTime - synth->LastEvtTime) * synth->SamplesPerTick;
-    }
+    curtime = MidiSynth_getTime(synth);
+    FSynth_processQueue(self, curtime);
 
     /* All notes off */
     for(chan = 0;chan < 16;chan++)
@@ -759,6 +844,7 @@ static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict
 {
     MidiSynth *synth = STATIC_CAST(MidiSynth, self);
     ALenum state = synth->State;
+    ALuint64 curtime;
     ALuint total = 0;
 
     if(state == AL_INITIAL)
@@ -770,58 +856,59 @@ static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict
         return;
     }
 
+    curtime = MidiSynth_getTime(synth);
     while(total < SamplesToDo)
     {
-        if(synth->SamplesToNext >= 1.0)
-        {
-            ALuint todo = minu(SamplesToDo - total, fastf2u(synth->SamplesToNext));
+        ALuint64 time, diff;
+        ALint tonext;
 
-            fluid_synth_write_float(self->Synth, todo,
-                                    &DryBuffer[FrontLeft][total], 0, 1,
-                                    &DryBuffer[FrontRight][total], 0, 1);
-            total += todo;
-            synth->SamplesSinceLast += todo;
-            synth->SamplesToNext -= todo;
+        time = MidiSynth_getNextEvtTime(synth);
+        diff = maxu64(time, curtime) - curtime;
+        if(diff >= MIDI_CLOCK_RES || time == UINT64_MAX)
+        {
+            /* If there's no pending event, or if it's more than 1 second
+             * away, do as many samples as we can. */
+            tonext = INT_MAX;
         }
         else
         {
-            ALuint64 time = synth->NextEvtTime;
-            if(time == UINT64_MAX)
-            {
-                synth->SamplesSinceLast += SamplesToDo-total;
-                fluid_synth_write_float(self->Synth, SamplesToDo-total,
-                                        &DryBuffer[FrontLeft][total], 0, 1,
-                                        &DryBuffer[FrontRight][total], 0, 1);
-                break;
-            }
-
-            synth->SamplesSinceLast -= (time - synth->LastEvtTime) * synth->SamplesPerTick;
-            synth->SamplesSinceLast = maxd(synth->SamplesSinceLast, 0.0);
-            synth->LastEvtTime = time;
-            FSynth_processQueue(self, time);
+            /* Figure out how many samples until the next event. */
+            tonext  = (ALint)((diff*synth->SampleRate + (MIDI_CLOCK_RES-1)) / MIDI_CLOCK_RES);
+            tonext -= total;
+        }
 
-            synth->NextEvtTime = MidiSynth_getNextEvtTime(synth);
-            if(synth->NextEvtTime != UINT64_MAX)
-                synth->SamplesToNext += (synth->NextEvtTime - synth->LastEvtTime) * synth->SamplesPerTick;
+        if(tonext > 0)
+        {
+            ALuint todo = minu(tonext, SamplesToDo-total);
+            fluid_synth_write_float(self->Synth, todo, DryBuffer[FrontLeft], total, 1,
+                                                       DryBuffer[FrontRight], total, 1);
+            total += todo;
+            tonext -= todo;
         }
+        if(total < SamplesToDo && tonext <= 0)
+            FSynth_processQueue(self, time);
     }
-}
-
 
-static void FSynth_Delete(FSynth *self)
-{
-    free(self);
+    synth->SamplesDone += SamplesToDo;
+    synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
+    synth->SamplesDone %= synth->SampleRate;
 }
 
 
 MidiSynth *FSynth_create(ALCdevice *device)
 {
-    FSynth *synth = calloc(1, sizeof(*synth));
+    FSynth *synth;
+
+    if(!LoadFSynth())
+        return NULL;
+
+    synth = FSynth_New(sizeof(*synth));
     if(!synth)
     {
         ERR("Failed to allocate FSynth\n");
         return NULL;
     }
+    memset(synth, 0, sizeof(*synth));
     FSynth_Construct(synth, device);
 
     if(FSynth_init(synth, device) == AL_FALSE)

File diff suppressed because it is too large
+ 234 - 301
jni/openal-soft-1.16.0/Alc/midi/sf2load.c


+ 140 - 0
jni/openal-soft-1.16.0/Alc/midi/soft.c

@@ -0,0 +1,140 @@
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "alMain.h"
+#include "alError.h"
+#include "evtqueue.h"
+#include "alu.h"
+
+#include "midi/base.h"
+
+
+typedef struct SSynth {
+    DERIVE_FROM_TYPE(MidiSynth);
+} SSynth;
+
+static void SSynth_mixSamples(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
+
+static void SSynth_Construct(SSynth *self, ALCdevice *device);
+static void SSynth_Destruct(SSynth *self);
+static DECLARE_FORWARD3(SSynth, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*)
+static DECLARE_FORWARD1(SSynth, MidiSynth, void, setGain, ALfloat)
+static DECLARE_FORWARD(SSynth, MidiSynth, void, stop)
+static DECLARE_FORWARD(SSynth, MidiSynth, void, reset)
+static void SSynth_update(SSynth *self, ALCdevice *device);
+static void SSynth_process(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
+DECLARE_DEFAULT_ALLOCATORS(SSynth)
+DEFINE_MIDISYNTH_VTABLE(SSynth);
+
+
+static void SSynth_Construct(SSynth *self, ALCdevice *device)
+{
+    MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device);
+    SET_VTABLE2(SSynth, MidiSynth, self);
+}
+
+static void SSynth_Destruct(SSynth* UNUSED(self))
+{
+}
+
+
+static void SSynth_update(SSynth* UNUSED(self), ALCdevice* UNUSED(device))
+{
+}
+
+
+static void SSynth_mixSamples(SSynth* UNUSED(self), ALuint UNUSED(SamplesToDo), ALfloatBUFFERSIZE *restrict UNUSED(DryBuffer))
+{
+}
+
+
+static void SSynth_processQueue(SSynth *self, ALuint64 time)
+{
+    EvtQueue *queue = &STATIC_CAST(MidiSynth, self)->EventQueue;
+
+    while(queue->pos < queue->size && queue->events[queue->pos].time <= time)
+        queue->pos++;
+}
+
+static void SSynth_process(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE])
+{
+    MidiSynth *synth = STATIC_CAST(MidiSynth, self);
+    ALenum state = synth->State;
+    ALuint64 curtime;
+    ALuint total = 0;
+
+    if(state == AL_INITIAL)
+        return;
+    if(state != AL_PLAYING)
+    {
+        SSynth_mixSamples(self, SamplesToDo, DryBuffer);
+        return;
+    }
+
+    curtime = MidiSynth_getTime(synth);
+    while(total < SamplesToDo)
+    {
+        ALuint64 time, diff;
+        ALint tonext;
+
+        time = MidiSynth_getNextEvtTime(synth);
+        diff = maxu64(time, curtime) - curtime;
+        if(diff >= MIDI_CLOCK_RES || time == UINT64_MAX)
+        {
+            /* If there's no pending event, or if it's more than 1 second
+             * away, do as many samples as we can. */
+            tonext = INT_MAX;
+        }
+        else
+        {
+            /* Figure out how many samples until the next event. */
+            tonext  = (ALint)((diff*synth->SampleRate + (MIDI_CLOCK_RES-1)) / MIDI_CLOCK_RES);
+            tonext -= total;
+            /* For efficiency reasons, try to mix a multiple of 64 samples
+             * (~1ms @ 44.1khz) before processing the next event. */
+            tonext = (tonext+63) & ~63;
+        }
+
+        if(tonext > 0)
+        {
+            ALuint todo = mini(tonext, SamplesToDo-total);
+            SSynth_mixSamples(self, todo, DryBuffer);
+            total += todo;
+            tonext -= todo;
+        }
+        if(total < SamplesToDo && tonext <= 0)
+            SSynth_processQueue(self, time);
+    }
+
+    synth->SamplesDone += SamplesToDo;
+    synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
+    synth->SamplesDone %= synth->SampleRate;
+}
+
+
+MidiSynth *SSynth_create(ALCdevice *device)
+{
+    SSynth *synth;
+
+    /* This option is temporary. Once this synth is in a more usable state, a
+     * more generic selector should be used. */
+    if(!GetConfigValueBool("midi", "internal-synth", 0))
+    {
+        TRACE("Not using internal MIDI synth\n");
+        return NULL;
+    }
+
+    synth = SSynth_New(sizeof(*synth));
+    if(!synth)
+    {
+        ERR("Failed to allocate SSynth\n");
+        return NULL;
+    }
+    SSynth_Construct(synth, device);
+    return STATIC_CAST(MidiSynth, synth);
+}

+ 188 - 99
jni/openal-soft-android/Alc/mixer.c → jni/openal-soft-1.16.0/Alc/mixer.c

@@ -34,7 +34,68 @@
 #include "alListener.h"
 #include "alAuxEffectSlot.h"
 #include "alu.h"
-#include "bs2b.h"
+
+#include "mixer_defs.h"
+
+
+extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
+
+
+static inline HrtfMixerFunc SelectHrtfMixer(void)
+{
+#ifdef HAVE_SSE
+    if((CPUCapFlags&CPU_CAP_SSE))
+        return MixHrtf_SSE;
+#endif
+#ifdef HAVE_NEON
+    if((CPUCapFlags&CPU_CAP_NEON))
+        return MixHrtf_Neon;
+#endif
+
+    return MixHrtf_C;
+}
+
+static inline MixerFunc SelectMixer(void)
+{
+#ifdef HAVE_SSE
+    if((CPUCapFlags&CPU_CAP_SSE))
+        return Mix_SSE;
+#endif
+#ifdef HAVE_NEON
+    if((CPUCapFlags&CPU_CAP_NEON))
+        return Mix_Neon;
+#endif
+
+    return Mix_C;
+}
+
+static inline ResamplerFunc SelectResampler(enum Resampler Resampler, ALuint increment)
+{
+    if(increment == FRACTIONONE)
+        return Resample_copy32_C;
+    switch(Resampler)
+    {
+        case PointResampler:
+            return Resample_point32_C;
+        case LinearResampler:
+#ifdef HAVE_SSE4_1
+            if((CPUCapFlags&CPU_CAP_SSE4_1))
+                return Resample_lerp32_SSE41;
+#endif
+#ifdef HAVE_SSE2
+            if((CPUCapFlags&CPU_CAP_SSE2))
+                return Resample_lerp32_SSE2;
+#endif
+            return Resample_lerp32_C;
+        case CubicResampler:
+            return Resample_cubic32_C;
+        case ResamplerMax:
+            /* Shouldn't happen */
+            break;
+    }
+
+    return Resample_point32_C;
+}
 
 
 static inline ALfloat Sample_ALbyte(ALbyte val)
@@ -60,7 +121,7 @@ DECL_TEMPLATE(ALfloat)
 
 #undef DECL_TEMPLATE
 
-static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
+static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
 {
     switch(srctype)
     {
@@ -76,7 +137,7 @@ static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtTy
     }
 }
 
-static void SilenceData(ALfloat *dst, ALuint samples)
+static void SilenceSamples(ALfloat *dst, ALuint samples)
 {
     ALuint i;
     for(i = 0;i < samples;i++)
@@ -84,21 +145,47 @@ static void SilenceData(ALfloat *dst, ALuint samples)
 }
 
 
-static void DoFilter(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *restrict src,
-                     ALuint numsamples)
+static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter,
+                                ALfloat *restrict dst, const ALfloat *restrict src,
+                                ALuint numsamples, enum ActiveFilters type)
 {
     ALuint i;
-    for(i = 0;i < numsamples;i++)
-        dst[i] = ALfilterState_processSingle(filter, src[i]);
-    dst[i] = ALfilterState_processSingleC(filter, src[i]);
+    switch(type)
+    {
+        case AF_None:
+            break;
+
+        case AF_LowPass:
+            ALfilterState_process(lpfilter, dst, src, numsamples);
+            return dst;
+        case AF_HighPass:
+            ALfilterState_process(hpfilter, dst, src, numsamples);
+            return dst;
+
+        case AF_BandPass:
+            for(i = 0;i < numsamples;)
+            {
+                ALfloat temp[64];
+                ALuint todo = minu(64, numsamples-i);
+
+                ALfilterState_process(lpfilter, temp, src+i, todo);
+                ALfilterState_process(hpfilter, dst+i, temp, todo);
+                i += todo;
+            }
+            return dst;
+    }
+    return src;
 }
 
 
-ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
+ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
 {
+    MixerFunc Mix;
+    HrtfMixerFunc HrtfMix;
+    ResamplerFunc Resample;
+    ALsource *Source = src->Source;
     ALbufferlistitem *BufferListItem;
     ALuint DataPosInt, DataPosFrac;
-    ALuint BuffersPlayed;
     ALboolean Looping;
     ALuint increment;
     enum Resampler Resampler;
@@ -110,20 +197,19 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
     ALuint chan, j;
 
     /* Get source info */
-    State         = Source->state;
-    BuffersPlayed = Source->BuffersPlayed;
-    DataPosInt    = Source->position;
-    DataPosFrac   = Source->position_fraction;
-    Looping       = Source->Looping;
-    increment     = Source->Params.Step;
-    Resampler     = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
-    NumChannels   = Source->NumChannels;
-    SampleSize    = Source->SampleSize;
-
-    /* Get current buffer queue item */
-    BufferListItem = Source->queue;
-    for(j = 0;j < BuffersPlayed;j++)
-        BufferListItem = BufferListItem->next;
+    State          = Source->state;
+    BufferListItem = ATOMIC_LOAD(&Source->current_buffer);
+    DataPosInt     = Source->position;
+    DataPosFrac    = Source->position_fraction;
+    Looping        = Source->Looping;
+    increment      = src->Step;
+    Resampler      = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
+    NumChannels    = Source->NumChannels;
+    SampleSize     = Source->SampleSize;
+
+    Mix = SelectMixer();
+    HrtfMix = SelectHrtfMixer();
+    Resample = SelectResampler(Resampler, increment);
 
     OutPos = 0;
     do {
@@ -132,7 +218,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
         ALuint SrcBufferSize, DstBufferSize;
 
         /* Figure out how many buffer samples will be needed */
-        DataSize64  = SamplesToDo-OutPos+1;
+        DataSize64  = SamplesToDo-OutPos;
         DataSize64 *= increment;
         DataSize64 += DataPosFrac+FRACTIONMASK;
         DataSize64 >>= FRACTIONBITS;
@@ -144,7 +230,6 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
         DataSize64  = SrcBufferSize;
         DataSize64 -= BufferPadding+BufferPrePadding;
         DataSize64 <<= FRACTIONBITS;
-        DataSize64 -= increment;
         DataSize64 -= DataPosFrac;
 
         DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
@@ -157,13 +242,13 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
 
         for(chan = 0;chan < NumChannels;chan++)
         {
-            ALfloat *SrcData = Device->SampleData1;
-            ALfloat *ResampledData = Device->SampleData2;
+            const ALfloat *ResampledData;
+            ALfloat *SrcData = Device->SourceData;
             ALuint SrcDataSize = 0;
 
             if(Source->SourceType == AL_STATIC)
             {
-                const ALbuffer *ALBuffer = Source->queue->buffer;
+                const ALbuffer *ALBuffer = BufferListItem->buffer;
                 const ALubyte *Data = ALBuffer->data;
                 ALuint DataSize;
                 ALuint pos;
@@ -180,7 +265,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
                         DataSize = BufferPrePadding - DataPosInt;
                         DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
 
-                        SilenceData(&SrcData[SrcDataSize], DataSize);
+                        SilenceSamples(&SrcData[SrcDataSize], DataSize);
                         SrcDataSize += DataSize;
 
                         pos = 0;
@@ -190,11 +275,11 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
                      * rest of the temp buffer */
                     DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
 
-                    LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
-                             NumChannels, ALBuffer->FmtType, DataSize);
+                    LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
+                                NumChannels, ALBuffer->FmtType, DataSize);
                     SrcDataSize += DataSize;
 
-                    SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
+                    SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
                     SrcDataSize += SrcBufferSize - SrcDataSize;
                 }
                 else
@@ -217,7 +302,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
                         DataSize = BufferPrePadding - DataPosInt;
                         DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
 
-                        SilenceData(&SrcData[SrcDataSize], DataSize);
+                        SilenceSamples(&SrcData[SrcDataSize], DataSize);
                         SrcDataSize += DataSize;
 
                         pos = 0;
@@ -228,8 +313,8 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
                     DataSize = LoopEnd - pos;
                     DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
 
-                    LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
-                             NumChannels, ALBuffer->FmtType, DataSize);
+                    LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
+                                NumChannels, ALBuffer->FmtType, DataSize);
                     SrcDataSize += DataSize;
 
                     DataSize = LoopEnd-LoopStart;
@@ -237,8 +322,8 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
                     {
                         DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
 
-                        LoadData(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
-                                 NumChannels, ALBuffer->FmtType, DataSize);
+                        LoadSamples(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
+                                    NumChannels, ALBuffer->FmtType, DataSize);
                         SrcDataSize += DataSize;
                     }
                 }
@@ -256,25 +341,25 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
                     pos = BufferPrePadding - DataPosInt;
                     while(pos > 0)
                     {
-                        if(!tmpiter->prev && !Looping)
+                        ALbufferlistitem *prev;
+                        if((prev=tmpiter->prev) != NULL)
+                            tmpiter = prev;
+                        else if(Looping)
+                        {
+                            while(tmpiter->next)
+                                tmpiter = tmpiter->next;
+                        }
+                        else
                         {
                             ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
 
-                            SilenceData(&SrcData[SrcDataSize], DataSize);
+                            SilenceSamples(&SrcData[SrcDataSize], DataSize);
                             SrcDataSize += DataSize;
 
                             pos = 0;
                             break;
                         }
 
-                        if(tmpiter->prev)
-                            tmpiter = tmpiter->prev;
-                        else
-                        {
-                            while(tmpiter->next)
-                                tmpiter = tmpiter->next;
-                        }
-
                         if(tmpiter->buffer)
                         {
                             if((ALuint)tmpiter->buffer->SampleLen > pos)
@@ -305,55 +390,72 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
                             pos -= pos;
 
                             DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-                            LoadData(&SrcData[SrcDataSize], Data, NumChannels,
-                                     ALBuffer->FmtType, DataSize);
+                            LoadSamples(&SrcData[SrcDataSize], Data, NumChannels,
+                                        ALBuffer->FmtType, DataSize);
                             SrcDataSize += DataSize;
                         }
                     }
                     tmpiter = tmpiter->next;
                     if(!tmpiter && Looping)
-                        tmpiter = Source->queue;
+                        tmpiter = ATOMIC_LOAD(&Source->queue);
                     else if(!tmpiter)
                     {
-                        SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
+                        SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
                         SrcDataSize += SrcBufferSize - SrcDataSize;
                     }
                 }
             }
 
             /* Now resample, then filter and mix to the appropriate outputs. */
-            Source->Params.Resample(&SrcData[BufferPrePadding], DataPosFrac,
-                                    increment, ResampledData, DstBufferSize);
-
+            ResampledData = Resample(
+                &SrcData[BufferPrePadding], DataPosFrac, increment,
+                Device->ResampledData, DstBufferSize
+            );
             {
-                DirectParams *directparms = &Source->Params.Direct;
-
-                DoFilter(&directparms->LpFilter[chan], SrcData, ResampledData,
-                         DstBufferSize);
-                Source->Params.DryMix(directparms, SrcData, chan, OutPos,
-                                      SamplesToDo, DstBufferSize);
+                DirectParams *parms = &src->Direct;
+                const ALfloat *samples;
+
+                samples = DoFilters(
+                    &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
+                    Device->FilteredData, ResampledData, DstBufferSize,
+                    parms->Filters[chan].ActiveType
+                );
+                if(!src->IsHrtf)
+                    Mix(samples, MaxChannels, parms->OutBuffer, parms->Mix.Gains[chan],
+                        parms->Counter, OutPos, DstBufferSize);
+                else
+                    HrtfMix(parms->OutBuffer, samples, parms->Counter, src->Offset,
+                            OutPos, parms->Mix.Hrtf.IrSize, &parms->Mix.Hrtf.Params[chan],
+                            &parms->Mix.Hrtf.State[chan], DstBufferSize);
             }
 
             for(j = 0;j < Device->NumAuxSends;j++)
             {
-                SendParams *sendparms = &Source->Params.Send[j];
-                if(!sendparms->OutBuffer)
+                SendParams *parms = &src->Send[j];
+                const ALfloat *samples;
+
+                if(!parms->OutBuffer)
                     continue;
 
-                DoFilter(&sendparms->LpFilter[chan], SrcData, ResampledData,
-                         DstBufferSize);
-                Source->Params.WetMix(sendparms, SrcData, OutPos,
-                                      SamplesToDo, DstBufferSize);
+                samples = DoFilters(
+                    &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
+                    Device->FilteredData, ResampledData, DstBufferSize,
+                    parms->Filters[chan].ActiveType
+                );
+                Mix(samples, 1, parms->OutBuffer, &parms->Gain,
+                    parms->Counter, OutPos, DstBufferSize);
             }
         }
         /* Update positions */
-        for(j = 0;j < DstBufferSize;j++)
-        {
-            DataPosFrac += increment;
-            DataPosInt  += DataPosFrac>>FRACTIONBITS;
-            DataPosFrac &= FRACTIONMASK;
-        }
+        DataPosFrac += increment*DstBufferSize;
+        DataPosInt  += DataPosFrac>>FRACTIONBITS;
+        DataPosFrac &= FRACTIONMASK;
+
         OutPos += DstBufferSize;
+        src->Offset += DstBufferSize;
+        src->Direct.Counter = maxu(src->Direct.Counter, DstBufferSize) - DstBufferSize;
+        for(j = 0;j < Device->NumAuxSends;j++)
+            src->Send[j].Counter = maxu(src->Send[j].Counter, DstBufferSize) - DstBufferSize;
 
         /* Handle looping sources */
         while(1)
@@ -374,6 +476,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
 
             if(Looping && Source->SourceType == AL_STATIC)
             {
+                assert(LoopEnd > LoopStart);
                 DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
                 break;
             }
@@ -381,24 +484,18 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
             if(DataSize > DataPosInt)
                 break;
 
-            if(BufferListItem->next)
-            {
-                BufferListItem = BufferListItem->next;
-                BuffersPlayed++;
-            }
-            else if(Looping)
+            if(!(BufferListItem=BufferListItem->next))
             {
-                BufferListItem = Source->queue;
-                BuffersPlayed = 0;
-            }
-            else
-            {
-                State = AL_STOPPED;
-                BufferListItem = Source->queue;
-                BuffersPlayed = Source->BuffersInQueue;
-                DataPosInt = 0;
-                DataPosFrac = 0;
-                break;
+                if(Looping)
+                    BufferListItem = ATOMIC_LOAD(&Source->queue);
+                else
+                {
+                    State = AL_STOPPED;
+                    BufferListItem = NULL;
+                    DataPosInt = 0;
+                    DataPosFrac = 0;
+                    break;
+                }
             }
 
             DataPosInt -= DataSize;
@@ -407,15 +504,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
 
     /* Update source info */
     Source->state             = State;
-    Source->BuffersPlayed     = BuffersPlayed;
+    ATOMIC_STORE(&Source->current_buffer, BufferListItem);
     Source->position          = DataPosInt;
     Source->position_fraction = DataPosFrac;
-    Source->Hrtf.Offset      += OutPos;
-    if(State == AL_PLAYING)
-        Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos;
-    else
-    {
-        Source->Hrtf.Counter = 0;
-        Source->Hrtf.Moving  = AL_FALSE;
-    }
 }

+ 52 - 51
jni/openal-soft-android/Alc/mixer_c.c → jni/openal-soft-1.16.0/Alc/mixer_c.c

@@ -15,28 +15,33 @@ static inline ALfloat lerp32(const ALfloat *vals, ALuint frac)
 static inline ALfloat cubic32(const ALfloat *vals, ALuint frac)
 { return cubic(vals[-1], vals[0], vals[1], vals[2], frac * (1.0f/FRACTIONONE)); }
 
-void Resample_copy32_C(const ALfloat *data, ALuint UNUSED(frac),
-  ALuint increment, ALfloat *restrict OutBuffer, ALuint BufferSize)
+const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint UNUSED(frac),
+  ALuint increment, ALfloat *restrict dst, ALuint numsamples)
 {
     assert(increment==FRACTIONONE);
-    memcpy(OutBuffer, data, (BufferSize+1)*sizeof(ALfloat));
+#if defined(HAVE_SSE) || defined(HAVE_NEON)
+    /* Avoid copying the source data if it's aligned like the destination. */
+    if((((intptr_t)src)&15) == (((intptr_t)dst)&15))
+        return src;
+#endif
+    memcpy(dst, src, numsamples*sizeof(ALfloat));
+    return dst;
 }
 
 #define DECL_TEMPLATE(Sampler)                                                \
-void Resample_##Sampler##_C(const ALfloat *data, ALuint frac,                 \
-  ALuint increment, ALfloat *restrict OutBuffer, ALuint BufferSize)           \
+const ALfloat *Resample_##Sampler##_C(const ALfloat *src, ALuint frac,        \
+  ALuint increment, ALfloat *restrict dst, ALuint numsamples)                 \
 {                                                                             \
-    ALuint pos = 0;                                                           \
     ALuint i;                                                                 \
-                                                                              \
-    for(i = 0;i < BufferSize+1;i++)                                           \
+    for(i = 0;i < numsamples;i++)                                             \
     {                                                                         \
-        OutBuffer[i] = Sampler(data + pos, frac);                             \
+        dst[i] = Sampler(src, frac);                                          \
                                                                               \
         frac += increment;                                                    \
-        pos  += frac>>FRACTIONBITS;                                           \
+        src  += frac>>FRACTIONBITS;                                           \
         frac &= FRACTIONMASK;                                                 \
     }                                                                         \
+    return dst;                                                               \
 }
 
 DECL_TEMPLATE(point32)
@@ -46,13 +51,26 @@ DECL_TEMPLATE(cubic32)
 #undef DECL_TEMPLATE
 
 
-static inline void ApplyCoeffsStep(const ALuint IrSize,
+void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples)
+{
+    ALuint i;
+    for(i = 0;i < numsamples;i++)
+        *(dst++) = ALfilterState_processSingle(filter, *(src++));
+}
+
+
+static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
+                                   const ALuint IrSize,
                                    ALfloat (*restrict Coeffs)[2],
-                                   const ALfloat (*restrict CoeffStep)[2])
+                                   const ALfloat (*restrict CoeffStep)[2],
+                                   ALfloat left, ALfloat right)
 {
     ALuint c;
     for(c = 0;c < IrSize;c++)
     {
+        const ALuint off = (Offset+c)&HRIR_MASK;
+        Values[off][0] += Coeffs[c][0] * left;
+        Values[off][1] += Coeffs[c][1] * right;
         Coeffs[c][0] += CoeffStep[c][0];
         Coeffs[c][1] += CoeffStep[c][1];
     }
@@ -77,49 +95,32 @@ static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
 #undef SUFFIX
 
 
-void MixDirect_C(const DirectParams *params, const ALfloat *restrict data, ALuint srcchan,
-  ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
+void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+           MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize)
 {
-    ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer;
-    ALfloat *restrict ClickRemoval = params->ClickRemoval;
-    ALfloat *restrict PendingClicks = params->PendingClicks;
-    ALfloat DrySend;
-    ALuint pos;
+    ALfloat gain, step;
     ALuint c;
 
-    for(c = 0;c < MaxChannels;c++)
+    for(c = 0;c < OutChans;c++)
     {
-        DrySend = params->Gains[srcchan][c];
-        if(!(DrySend > GAIN_SILENCE_THRESHOLD))
+        ALuint pos = 0;
+        gain = Gains[c].Current;
+        step = Gains[c].Step;
+        if(step != 1.0f && Counter > 0)
+        {
+            for(;pos < BufferSize && pos < Counter;pos++)
+            {
+                OutBuffer[c][OutPos+pos] += data[pos]*gain;
+                gain *= step;
+            }
+            if(pos == Counter)
+                gain = Gains[c].Target;
+            Gains[c].Current = gain;
+        }
+
+        if(!(gain > GAIN_SILENCE_THRESHOLD))
             continue;
-
-        if(OutPos == 0)
-            ClickRemoval[c] -= data[0]*DrySend;
-        for(pos = 0;pos < BufferSize;pos++)
-            OutBuffer[c][OutPos+pos] += data[pos]*DrySend;
-        if(OutPos+pos == SamplesToDo)
-            PendingClicks[c] += data[pos]*DrySend;
+        for(;pos < BufferSize;pos++)
+            OutBuffer[c][OutPos+pos] += data[pos]*gain;
     }
 }
-
-
-void MixSend_C(const SendParams *params, const ALfloat *restrict data,
-  ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize)
-{
-    ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer;
-    ALfloat *restrict ClickRemoval = params->ClickRemoval;
-    ALfloat *restrict PendingClicks = params->PendingClicks;
-    ALfloat WetSend;
-    ALuint pos;
-
-    WetSend = params->Gain;
-    if(!(WetSend > GAIN_SILENCE_THRESHOLD))
-        return;
-
-    if(OutPos == 0)
-        ClickRemoval[0] -= data[0] * WetSend;
-    for(pos = 0;pos < BufferSize;pos++)
-        OutBuffer[0][OutPos+pos] += data[pos] * WetSend;
-    if(OutPos+pos == SamplesToDo)
-        PendingClicks[0] += data[pos] * WetSend;
-}

+ 65 - 0
jni/openal-soft-1.16.0/Alc/mixer_defs.h

@@ -0,0 +1,65 @@
+#ifndef MIXER_DEFS_H
+#define MIXER_DEFS_H
+
+#include "AL/alc.h"
+#include "AL/al.h"
+#include "alMain.h"
+#include "alu.h"
+
+struct MixGains;
+
+struct HrtfParams;
+struct HrtfState;
+
+/* C resamplers */
+const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_point32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_lerp32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_cubic32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+
+
+/* C mixers */
+void MixHrtf_C(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
+               ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize,
+               const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate,
+               ALuint BufferSize);
+void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+                 struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize);
+
+/* SSE mixers */
+void MixHrtf_SSE(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
+                 ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize,
+                 const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate,
+                 ALuint BufferSize);
+void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+             struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize);
+
+/* SSE resamplers */
+inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size)
+{
+    ALuint i;
+
+    pos_arr[0] = 0;
+    frac_arr[0] = frac;
+    for(i = 1;i < size;i++)
+    {
+        ALuint frac_tmp = frac_arr[i-1] + increment;
+        pos_arr[i] = pos_arr[i-1] + (frac_tmp>>FRACTIONBITS);
+        frac_arr[i] = frac_tmp&FRACTIONMASK;
+    }
+}
+
+const ALfloat *Resample_lerp32_SSE2(const ALfloat *src, ALuint frac, ALuint increment,
+                                    ALfloat *restrict dst, ALuint numsamples);
+const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint increment,
+                                     ALfloat *restrict dst, ALuint numsamples);
+
+/* Neon mixers */
+void MixHrtf_Neon(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
+                  ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize,
+                  const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate,
+                  ALuint BufferSize);
+void Mix_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+              struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize);
+
+#endif /* MIXER_DEFS_H */

+ 93 - 0
jni/openal-soft-1.16.0/Alc/mixer_inc.c

@@ -0,0 +1,93 @@
+#include "config.h"
+
+#include "alMain.h"
+#include "alSource.h"
+
+#include "hrtf.h"
+#include "mixer_defs.h"
+#include "align.h"
+
+
+#define REAL_MERGE(a,b) a##b
+#define MERGE(a,b) REAL_MERGE(a,b)
+
+#define MixHrtf MERGE(MixHrtf_,SUFFIX)
+
+
+static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
+                                   const ALuint irSize,
+                                   ALfloat (*restrict Coeffs)[2],
+                                   const ALfloat (*restrict CoeffStep)[2],
+                                   ALfloat left, ALfloat right);
+static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
+                               const ALuint irSize,
+                               ALfloat (*restrict Coeffs)[2],
+                               ALfloat left, ALfloat right);
+
+
+void MixHrtf(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
+             ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize,
+             const HrtfParams *hrtfparams, HrtfState *hrtfstate, ALuint BufferSize)
+{
+    alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
+    ALuint Delay[2];
+    ALfloat left, right;
+    ALuint pos;
+    ALuint c;
+
+    for(c = 0;c < IrSize;c++)
+    {
+        Coeffs[c][0] = hrtfparams->Coeffs[c][0] - (hrtfparams->CoeffStep[c][0]*Counter);
+        Coeffs[c][1] = hrtfparams->Coeffs[c][1] - (hrtfparams->CoeffStep[c][1]*Counter);
+    }
+    Delay[0] = hrtfparams->Delay[0] - (hrtfparams->DelayStep[0]*Counter);
+    Delay[1] = hrtfparams->Delay[1] - (hrtfparams->DelayStep[1]*Counter);
+
+    for(pos = 0;pos < BufferSize && pos < Counter;pos++)
+    {
+        hrtfstate->History[Offset&SRC_HISTORY_MASK] = data[pos];
+        left  = lerp(hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
+                     hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
+                     (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
+        right = lerp(hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
+                     hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
+                     (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
+
+        Delay[0] += hrtfparams->DelayStep[0];
+        Delay[1] += hrtfparams->DelayStep[1];
+
+        hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
+        hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
+        Offset++;
+
+        ApplyCoeffsStep(Offset, hrtfstate->Values, IrSize, Coeffs, hrtfparams->CoeffStep, left, right);
+        OutBuffer[FrontLeft][OutPos]  += hrtfstate->Values[Offset&HRIR_MASK][0];
+        OutBuffer[FrontRight][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][1];
+        OutPos++;
+    }
+
+    Delay[0] >>= HRTFDELAY_BITS;
+    Delay[1] >>= HRTFDELAY_BITS;
+    for(;pos < BufferSize;pos++)
+    {
+        hrtfstate->History[Offset&SRC_HISTORY_MASK] = data[pos];
+        left = hrtfstate->History[(Offset-Delay[0])&SRC_HISTORY_MASK];
+        right = hrtfstate->History[(Offset-Delay[1])&SRC_HISTORY_MASK];
+
+        hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
+        hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
+        Offset++;
+
+        ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right);
+        OutBuffer[FrontLeft][OutPos]  += hrtfstate->Values[Offset&HRIR_MASK][0];
+        OutBuffer[FrontRight][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][1];
+
+        OutPos++;
+    }
+}
+
+
+#undef MixHrtf
+
+#undef MERGE
+#undef REAL_MERGE

+ 118 - 0
jni/openal-soft-1.16.0/Alc/mixer_neon.c

@@ -0,0 +1,118 @@
+#include "config.h"
+
+#include <arm_neon.h>
+
+#include "AL/al.h"
+#include "AL/alc.h"
+#include "alMain.h"
+#include "alu.h"
+#include "hrtf.h"
+
+
+static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
+                                   const ALuint IrSize,
+                                   ALfloat (*restrict Coeffs)[2],
+                                   const ALfloat (*restrict CoeffStep)[2],
+                                   ALfloat left, ALfloat right)
+{
+    ALuint c;
+    float32x4_t leftright4;
+    {
+        float32x2_t leftright2 = vdup_n_f32(0.0);
+        leftright2 = vset_lane_f32(left, leftright2, 0);
+        leftright2 = vset_lane_f32(right, leftright2, 1);
+        leftright4 = vcombine_f32(leftright2, leftright2);
+    }
+    for(c = 0;c < IrSize;c += 2)
+    {
+        const ALuint o0 = (Offset+c)&HRIR_MASK;
+        const ALuint o1 = (o0+1)&HRIR_MASK;
+        float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
+                                        vld1_f32((float32_t*)&Values[o1][0]));
+        float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
+        float32x4_t deltas = vld1q_f32(&CoeffStep[c][0]);
+
+        vals = vmlaq_f32(vals, coefs, leftright4);
+        coefs = vaddq_f32(coefs, deltas);
+
+        vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
+        vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
+        vst1q_f32(&Coeffs[c][0], coefs);
+    }
+}
+
+static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
+                               const ALuint IrSize,
+                               ALfloat (*restrict Coeffs)[2],
+                               ALfloat left, ALfloat right)
+{
+    ALuint c;
+    float32x4_t leftright4;
+    {
+        float32x2_t leftright2 = vdup_n_f32(0.0);
+        leftright2 = vset_lane_f32(left, leftright2, 0);
+        leftright2 = vset_lane_f32(right, leftright2, 1);
+        leftright4 = vcombine_f32(leftright2, leftright2);
+    }
+    for(c = 0;c < IrSize;c += 2)
+    {
+        const ALuint o0 = (Offset+c)&HRIR_MASK;
+        const ALuint o1 = (o0+1)&HRIR_MASK;
+        float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
+                                        vld1_f32((float32_t*)&Values[o1][0]));
+        float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
+
+        vals = vmlaq_f32(vals, coefs, leftright4);
+
+        vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
+        vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
+    }
+}
+
+
+#define SUFFIX Neon
+#include "mixer_inc.c"
+#undef SUFFIX
+
+
+void MixDirect_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+                    MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize)
+{
+    ALfloat gain, step;
+    float32x4_t gain4;
+    ALuint c;
+
+    for(c = 0;c < OutChans;c++)
+    {
+        ALuint pos = 0;
+        gain = Gains[c].Current;
+        step = Gains[c].Step;
+        if(step != 1.0f && Counter > 0)
+        {
+            for(;pos < BufferSize && pos < Counter;pos++)
+            {
+                OutBuffer[c][OutPos+pos] += data[pos]*gain;
+                gain *= step;
+            }
+            if(pos == Counter)
+                gain = Gains[c].Target;
+            Gains[c].Current = gain;
+            /* Mix until pos is aligned with 4 or the mix is done. */
+            for(;pos < BufferSize && (pos&3) != 0;pos++)
+                OutBuffer[c][OutPos+pos] += data[pos]*gain;
+        }
+
+        if(!(gain > GAIN_SILENCE_THRESHOLD))
+            continue;
+        gain4 = vdupq_n_f32(gain);
+        for(;BufferSize-pos > 3;pos += 4)
+        {
+            const float32x4_t val4 = vld1q_f32(&data[pos]);
+            float32x4_t dry4 = vld1q_f32(&OutBuffer[c][OutPos+pos]);
+            dry4 = vaddq_f32(dry4, vmulq_f32(val4, gain4));
+            vst1q_f32(&OutBuffer[c][OutPos+pos], dry4);
+        }
+        for(;pos < BufferSize;pos++)
+            OutBuffer[c][OutPos+pos] += data[pos]*gain;
+    }
+}

+ 202 - 0
jni/openal-soft-1.16.0/Alc/mixer_sse.c

@@ -0,0 +1,202 @@
+#include "config.h"
+
+#ifdef IN_IDE_PARSER
+/* KDevelop's parser won't recognize these defines that get added by the -msse
+ * switch used to compile this source. Without them, xmmintrin.h fails to
+ * declare anything. */
+#define __MMX__
+#define __SSE__
+#endif
+#include <xmmintrin.h>
+
+#include "AL/al.h"
+#include "AL/alc.h"
+#include "alMain.h"
+#include "alu.h"
+
+#include "alSource.h"
+#include "alAuxEffectSlot.h"
+#include "mixer_defs.h"
+
+
+static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
+                                   const ALuint IrSize,
+                                   ALfloat (*restrict Coeffs)[2],
+                                   const ALfloat (*restrict CoeffStep)[2],
+                                   ALfloat left, ALfloat right)
+{
+    const __m128 lrlr = _mm_setr_ps(left, right, left, right);
+    __m128 coeffs, deltas, imp0, imp1;
+    __m128 vals = _mm_setzero_ps();
+    ALuint i;
+
+    if((Offset&1))
+    {
+        const ALuint o0 = Offset&HRIR_MASK;
+        const ALuint o1 = (Offset+IrSize-1)&HRIR_MASK;
+
+        coeffs = _mm_load_ps(&Coeffs[0][0]);
+        deltas = _mm_load_ps(&CoeffStep[0][0]);
+        vals = _mm_loadl_pi(vals, (__m64*)&Values[o0][0]);
+        imp0 = _mm_mul_ps(lrlr, coeffs);
+        coeffs = _mm_add_ps(coeffs, deltas);
+        vals = _mm_add_ps(imp0, vals);
+        _mm_store_ps(&Coeffs[0][0], coeffs);
+        _mm_storel_pi((__m64*)&Values[o0][0], vals);
+        for(i = 1;i < IrSize-1;i += 2)
+        {
+            const ALuint o2 = (Offset+i)&HRIR_MASK;
+
+            coeffs = _mm_load_ps(&Coeffs[i+1][0]);
+            deltas = _mm_load_ps(&CoeffStep[i+1][0]);
+            vals = _mm_load_ps(&Values[o2][0]);
+            imp1 = _mm_mul_ps(lrlr, coeffs);
+            coeffs = _mm_add_ps(coeffs, deltas);
+            imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2));
+            vals = _mm_add_ps(imp0, vals);
+            _mm_store_ps(&Coeffs[i+1][0], coeffs);
+            _mm_store_ps(&Values[o2][0], vals);
+            imp0 = imp1;
+        }
+        vals = _mm_loadl_pi(vals, (__m64*)&Values[o1][0]);
+        imp0 = _mm_movehl_ps(imp0, imp0);
+        vals = _mm_add_ps(imp0, vals);
+        _mm_storel_pi((__m64*)&Values[o1][0], vals);
+    }
+    else
+    {
+        for(i = 0;i < IrSize;i += 2)
+        {
+            const ALuint o = (Offset + i)&HRIR_MASK;
+
+            coeffs = _mm_load_ps(&Coeffs[i][0]);
+            deltas = _mm_load_ps(&CoeffStep[i][0]);
+            vals = _mm_load_ps(&Values[o][0]);
+            imp0 = _mm_mul_ps(lrlr, coeffs);
+            coeffs = _mm_add_ps(coeffs, deltas);
+            vals = _mm_add_ps(imp0, vals);
+            _mm_store_ps(&Coeffs[i][0], coeffs);
+            _mm_store_ps(&Values[o][0], vals);
+        }
+    }
+}
+
+static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
+                               const ALuint IrSize,
+                               ALfloat (*restrict Coeffs)[2],
+                               ALfloat left, ALfloat right)
+{
+    const __m128 lrlr = _mm_setr_ps(left, right, left, right);
+    __m128 vals = _mm_setzero_ps();
+    __m128 coeffs;
+    ALuint i;
+
+    if((Offset&1))
+    {
+        const ALuint o0 = Offset&HRIR_MASK;
+        const ALuint o1 = (Offset+IrSize-1)&HRIR_MASK;
+        __m128 imp0, imp1;
+
+        coeffs = _mm_load_ps(&Coeffs[0][0]);
+        vals = _mm_loadl_pi(vals, (__m64*)&Values[o0][0]);
+        imp0 = _mm_mul_ps(lrlr, coeffs);
+        vals = _mm_add_ps(imp0, vals);
+        _mm_storel_pi((__m64*)&Values[o0][0], vals);
+        for(i = 1;i < IrSize-1;i += 2)
+        {
+            const ALuint o2 = (Offset+i)&HRIR_MASK;
+
+            coeffs = _mm_load_ps(&Coeffs[i+1][0]);
+            vals = _mm_load_ps(&Values[o2][0]);
+            imp1 = _mm_mul_ps(lrlr, coeffs);
+            imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2));
+            vals = _mm_add_ps(imp0, vals);
+            _mm_store_ps(&Values[o2][0], vals);
+            imp0 = imp1;
+        }
+        vals = _mm_loadl_pi(vals, (__m64*)&Values[o1][0]);
+        imp0 = _mm_movehl_ps(imp0, imp0);
+        vals = _mm_add_ps(imp0, vals);
+        _mm_storel_pi((__m64*)&Values[o1][0], vals);
+    }
+    else
+    {
+        for(i = 0;i < IrSize;i += 2)
+        {
+            const ALuint o = (Offset + i)&HRIR_MASK;
+
+            coeffs = _mm_load_ps(&Coeffs[i][0]);
+            vals = _mm_load_ps(&Values[o][0]);
+            vals = _mm_add_ps(vals, _mm_mul_ps(lrlr, coeffs));
+            _mm_store_ps(&Values[o][0], vals);
+        }
+    }
+}
+
+#define SUFFIX SSE
+#include "mixer_inc.c"
+#undef SUFFIX
+
+
+void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+             MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize)
+{
+    ALfloat gain, step;
+    __m128 gain4, step4;
+    ALuint c;
+
+    for(c = 0;c < OutChans;c++)
+    {
+        ALuint pos = 0;
+        gain = Gains[c].Current;
+        step = Gains[c].Step;
+        if(step != 1.0f && Counter > 0)
+        {
+            /* Mix with applying gain steps in aligned multiples of 4. */
+            if(BufferSize-pos > 3 && Counter-pos > 3)
+            {
+                gain4 = _mm_setr_ps(
+                    gain,
+                    gain * step,
+                    gain * step * step,
+                    gain * step * step * step
+                );
+                step4 = _mm_set1_ps(step * step * step * step);
+                do {
+                    const __m128 val4 = _mm_load_ps(&data[pos]);
+                    __m128 dry4 = _mm_load_ps(&OutBuffer[c][OutPos+pos]);
+                    dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4));
+                    gain4 = _mm_mul_ps(gain4, step4);
+                    _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4);
+                    pos += 4;
+                } while(BufferSize-pos > 3 && Counter-pos > 3);
+                gain = _mm_cvtss_f32(gain4);
+            }
+            /* Mix with applying left over gain steps that aren't aligned multiples of 4. */
+            for(;pos < BufferSize && pos < Counter;pos++)
+            {
+                OutBuffer[c][OutPos+pos] += data[pos]*gain;
+                gain *= step;
+            }
+            if(pos == Counter)
+                gain = Gains[c].Target;
+            Gains[c].Current = gain;
+            /* Mix until pos is aligned with 4 or the mix is done. */
+            for(;pos < BufferSize && (pos&3) != 0;pos++)
+                OutBuffer[c][OutPos+pos] += data[pos]*gain;
+        }
+
+        if(!(gain > GAIN_SILENCE_THRESHOLD))
+            continue;
+        gain4 = _mm_set1_ps(gain);
+        for(;BufferSize-pos > 3;pos += 4)
+        {
+            const __m128 val4 = _mm_load_ps(&data[pos]);
+            __m128 dry4 = _mm_load_ps(&OutBuffer[c][OutPos+pos]);
+            dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4));
+            _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4);
+        }
+        for(;pos < BufferSize;pos++)
+            OutBuffer[c][OutPos+pos] += data[pos]*gain;
+    }
+}

+ 78 - 0
jni/openal-soft-1.16.0/Alc/mixer_sse2.c

@@ -0,0 +1,78 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 2014 by Timothy Arceri <[email protected]>.
+ * This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the
+ *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ *  Boston, MA  02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "config.h"
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+
+#include "alu.h"
+#include "mixer_defs.h"
+
+
+const ALfloat *Resample_lerp32_SSE2(const ALfloat *src, ALuint frac, ALuint increment,
+                                    ALfloat *restrict dst, ALuint numsamples)
+{
+    const __m128i increment4 = _mm_set1_epi32(increment*4);
+    const __m128 fracOne4 = _mm_set1_ps(1.0f/FRACTIONONE);
+    const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK);
+    alignas(16) union { ALuint i[4]; float f[4]; } pos_;
+    alignas(16) union { ALuint i[4]; float f[4]; } frac_;
+    __m128i frac4, pos4;
+    ALuint pos;
+    ALuint i;
+
+    InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4);
+
+    frac4 = _mm_castps_si128(_mm_load_ps(frac_.f));
+    pos4 = _mm_castps_si128(_mm_load_ps(pos_.f));
+
+    for(i = 0;numsamples-i > 3;i += 4)
+    {
+        const __m128 val1 = _mm_setr_ps(src[pos_.i[0]], src[pos_.i[1]], src[pos_.i[2]], src[pos_.i[3]]);
+        const __m128 val2 = _mm_setr_ps(src[pos_.i[0]+1], src[pos_.i[1]+1], src[pos_.i[2]+1], src[pos_.i[3]+1]);
+
+        /* val1 + (val2-val1)*mu */
+        const __m128 r0 = _mm_sub_ps(val2, val1);
+        const __m128 mu = _mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4);
+        const __m128 out = _mm_add_ps(val1, _mm_mul_ps(mu, r0));
+
+        _mm_store_ps(&dst[i], out);
+
+        frac4 = _mm_add_epi32(frac4, increment4);
+        pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS));
+        frac4 = _mm_and_si128(frac4, fracMask4);
+
+        _mm_store_ps(pos_.f, _mm_castsi128_ps(pos4));
+    }
+
+    pos = pos_.i[0];
+    frac = _mm_cvtsi128_si32(frac4);
+
+    for(;i < numsamples;i++)
+    {
+        dst[i] = lerp(src[pos], src[pos+1], frac * (1.0f/FRACTIONONE));
+
+        frac += increment;
+        pos  += frac>>FRACTIONBITS;
+        frac &= FRACTIONMASK;
+    }
+    return dst;
+}

+ 82 - 0
jni/openal-soft-1.16.0/Alc/mixer_sse41.c

@@ -0,0 +1,82 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 2014 by Timothy Arceri <[email protected]>.
+ * This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the
+ *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ *  Boston, MA  02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "config.h"
+
+#include <xmmintrin.h>
+#include <emmintrin.h>
+#include <smmintrin.h>
+
+#include "alu.h"
+#include "mixer_defs.h"
+
+
+const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint increment,
+                                     ALfloat *restrict dst, ALuint numsamples)
+{
+    const __m128i increment4 = _mm_set1_epi32(increment*4);
+    const __m128 fracOne4 = _mm_set1_ps(1.0f/FRACTIONONE);
+    const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK);
+    alignas(16) union { ALuint i[4]; float f[4]; } pos_;
+    alignas(16) union { ALuint i[4]; float f[4]; } frac_;
+    __m128i frac4, pos4;
+    ALuint pos;
+    ALuint i;
+
+    InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4);
+
+    frac4 = _mm_castps_si128(_mm_load_ps(frac_.f));
+    pos4 = _mm_castps_si128(_mm_load_ps(pos_.f));
+
+    for(i = 0;numsamples-i > 3;i += 4)
+    {
+        const __m128 val1 = _mm_setr_ps(src[pos_.i[0]], src[pos_.i[1]], src[pos_.i[2]], src[pos_.i[3]]);
+        const __m128 val2 = _mm_setr_ps(src[pos_.i[0]+1], src[pos_.i[1]+1], src[pos_.i[2]+1], src[pos_.i[3]+1]);
+
+        /* val1 + (val2-val1)*mu */
+        const __m128 r0 = _mm_sub_ps(val2, val1);
+        const __m128 mu = _mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4);
+        const __m128 out = _mm_add_ps(val1, _mm_mul_ps(mu, r0));
+
+        _mm_store_ps(&dst[i], out);
+
+        frac4 = _mm_add_epi32(frac4, increment4);
+        pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS));
+        frac4 = _mm_and_si128(frac4, fracMask4);
+
+        pos_.i[0] = _mm_extract_epi32(pos4, 0);
+        pos_.i[1] = _mm_extract_epi32(pos4, 1);
+        pos_.i[2] = _mm_extract_epi32(pos4, 2);
+        pos_.i[3] = _mm_extract_epi32(pos4, 3);
+    }
+
+    pos = pos_.i[0];
+    frac = _mm_cvtsi128_si32(frac4);
+
+    for(;i < numsamples;i++)
+    {
+        dst[i] = lerp(src[pos], src[pos+1], frac * (1.0f/FRACTIONONE));
+
+        frac += increment;
+        pos  += frac>>FRACTIONBITS;
+        frac &= FRACTIONMASK;
+    }
+    return dst;
+}

+ 0 - 0
jni/openal-soft-android/Alc/panning.c → jni/openal-soft-1.16.0/Alc/panning.c


+ 87 - 0
jni/openal-soft-1.16.0/Alc/vector.h

@@ -0,0 +1,87 @@
+#ifndef AL_VECTOR_H
+#define AL_VECTOR_H
+
+#include <stdlib.h>
+
+#include <AL/al.h>
+
+/* "Base" vector type, designed to alias with the actual vector types. */
+typedef struct vector__s {
+    ALsizei Capacity;
+    ALsizei Size;
+} *vector_;
+
+#define TYPEDEF_VECTOR(T, N) typedef struct {                                 \
+    ALsizei Capacity;                                                         \
+    ALsizei Size;                                                             \
+    T Data[];                                                                 \
+} _##N;                                                                       \
+typedef _##N* N;                                                              \
+typedef const _##N* const_##N;
+
+#define VECTOR(T) struct {                                                    \
+    ALsizei Capacity;                                                         \
+    ALsizei Size;                                                             \
+    T Data[];                                                                 \
+}*
+
+#define VECTOR_INIT(_x)       do { (_x) = NULL; } while(0)
+#define VECTOR_INIT_STATIC()  NULL
+#define VECTOR_DEINIT(_x)     do { free((_x)); (_x) = NULL; } while(0)
+
+/* Helper to increase a vector's reserve. Do not call directly. */
+ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count, ALboolean exact);
+#define VECTOR_RESERVE(_x, _c) (vector_reserve((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_c), AL_TRUE))
+
+ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count);
+#define VECTOR_RESIZE(_x, _c) (vector_resize((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_c)))
+
+#define VECTOR_CAPACITY(_x) ((_x) ? (_x)->Capacity : 0)
+#define VECTOR_SIZE(_x)     ((_x) ? (_x)->Size : 0)
+
+#define VECTOR_ITER_BEGIN(_x) ((_x) ? (_x)->Data + 0 : NULL)
+#define VECTOR_ITER_END(_x)   ((_x) ? (_x)->Data + (_x)->Size : NULL)
+
+ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_pos, const void *datstart, const void *datend);
+#ifdef __GNUC__
+#define TYPE_CHECK(T1, T2) __builtin_types_compatible_p(T1, T2)
+#define VECTOR_INSERT(_x, _i, _s, _e) __extension__({                         \
+    ALboolean _r;                                                             \
+    static_assert(TYPE_CHECK(__typeof((_x)->Data[0]), __typeof(*(_i))), "Incompatible insertion iterator"); \
+    static_assert(TYPE_CHECK(__typeof((_x)->Data[0]), __typeof(*(_s))), "Incompatible insertion source type"); \
+    static_assert(TYPE_CHECK(__typeof(*(_s)), __typeof(*(_e))), "Incompatible iterator sources"); \
+    _r = vector_insert((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_i), (_s), (_e)); \
+    _r;                                                                       \
+})
+#else
+#define VECTOR_INSERT(_x, _i, _s, _e) (vector_insert((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_i), (_s), (_e)))
+#endif
+
+#define VECTOR_PUSH_BACK(_x, _obj) (vector_reserve((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), VECTOR_SIZE(_x)+1, AL_FALSE) && \
+                                    (((_x)->Data[(_x)->Size++] = (_obj)),AL_TRUE))
+#define VECTOR_POP_BACK(_x) ((void)((_x)->Size--))
+
+#define VECTOR_BACK(_x)  ((_x)->Data[(_x)->Size-1])
+#define VECTOR_FRONT(_x) ((_x)->Data[0])
+
+#define VECTOR_ELEM(_x, _o) ((_x)->Data[(_o)])
+
+#define VECTOR_FOR_EACH(_t, _x, _f)  do {                                     \
+    _t *_iter = VECTOR_ITER_BEGIN((_x));                                      \
+    _t *_end = VECTOR_ITER_END((_x));                                         \
+    for(;_iter != _end;++_iter)                                               \
+        _f(_iter);                                                            \
+} while(0)
+
+#define VECTOR_FIND_IF(_i, _t, _x, _f)  do {                                  \
+    _t *_iter = VECTOR_ITER_BEGIN((_x));                                      \
+    _t *_end = VECTOR_ITER_END((_x));                                         \
+    for(;_iter != _end;++_iter)                                               \
+    {                                                                         \
+        if(_f(_iter))                                                         \
+            break;                                                            \
+    }                                                                         \
+    (_i) = _iter;                                                             \
+} while(0)
+
+#endif /* AL_VECTOR_H */

+ 4 - 1
jni/openal-soft-android/Android.mk → jni/openal-soft-1.16.0/Android.mk

@@ -4,7 +4,7 @@ LOCAL_PATH:= $(call my-dir)
 include $(CLEAR_VARS)
 
 LOCAL_MODULE    := libopenal
-LOCAL_CFLAGS    := -DAL_ALEXT_PROTOTYPES -DAL_BUILD_LIBRARY -DAL_LIBTYPE_STATIC -D_GNU_SOURCE=1 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -std=c99 -Drestrict=__restrict
+LOCAL_CFLAGS    := -DAL_ALEXT_PROTOTYPES -DAL_BUILD_LIBRARY -D_GNU_SOURCE=1 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -std=c99 -Drestrict=__restrict
 
 LOCAL_CPPFLAGS  := ${LOCAL_CFLAGS}
 
@@ -18,12 +18,15 @@ LOCAL_SRC_FILES := \
 	 Alc/mixer_neon.c \
 	 Alc/mixer_inc.c \
 	 Alc/mixer_sse.c \
+	 Alc/mixer_sse2.c \
+	 Alc/mixer_sse41.c \
 	, $(subst $(LOCAL_PATH)/,,\
 		${LOCAL_PATH}/Alc/backends/base.c \
 		${LOCAL_PATH}/Alc/backends/loopback.c \
 		${LOCAL_PATH}/Alc/backends/null.c \
 		${LOCAL_PATH}/Alc/backends/opensl.c \
 		${LOCAL_PATH}/Alc/backends/wave.c \
+		$(wildcard ${LOCAL_PATH}/common/*.c) \
 		$(wildcard ${LOCAL_PATH}/Alc/midi/*.c) \
 		$(wildcard ${LOCAL_PATH}/Alc/effects/*.c) \
 		$(wildcard ${LOCAL_PATH}/Alc/*.c) \

File diff suppressed because it is too large
+ 451 - 239
jni/openal-soft-1.16.0/CMakeLists.txt


+ 0 - 0
jni/openal-soft-android/COPYING → jni/openal-soft-1.16.0/COPYING


+ 7 - 7
jni/openal-soft-android/OpenAL32/Include/alAuxEffectSlot.h → jni/openal-soft-1.16.0/OpenAL32/Include/alAuxEffectSlot.h

@@ -4,6 +4,8 @@
 #include "alMain.h"
 #include "alEffect.h"
 
+#include "align.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -22,7 +24,7 @@ struct ALeffectStateVtable {
     void (*const update)(ALeffectState *state, ALCdevice *device, const struct ALeffectslot *slot);
     void (*const process)(ALeffectState *state, ALuint samplesToDo, const ALfloat *restrict samplesIn, ALfloat (*restrict samplesOut)[BUFFERSIZE]);
 
-    void (*const Delete)(struct ALeffectState *state);
+    void (*const Delete)(void *ptr);
 };
 
 #define DEFINE_ALEFFECTSTATE_VTABLE(T)                                        \
@@ -30,7 +32,8 @@ DECLARE_THUNK(T, ALeffectState, void, Destruct)                               \
 DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*)         \
 DECLARE_THUNK2(T, ALeffectState, void, update, ALCdevice*, const ALeffectslot*) \
 DECLARE_THUNK3(T, ALeffectState, void, process, ALuint, const ALfloat*restrict, ALfloatBUFFERSIZE*restrict) \
-DECLARE_THUNK(T, ALeffectState, void, Delete)                                 \
+static void T##_ALeffectState_Delete(void *ptr)                               \
+{ return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); }  \
                                                                               \
 static const struct ALeffectStateVtable T##_ALeffectState_vtable = {          \
     T##_ALeffectState_Destruct,                                               \
@@ -68,13 +71,10 @@ typedef struct ALeffectslot {
     volatile ALfloat   Gain;
     volatile ALboolean AuxSendAuto;
 
-    volatile ALenum NeedsUpdate;
+    ATOMIC(ALenum) NeedsUpdate;
     ALeffectState *EffectState;
 
-    ALIGN(16) ALfloat WetBuffer[1][BUFFERSIZE];
-
-    ALfloat ClickRemoval[1];
-    ALfloat PendingClicks[1];
+    alignas(16) ALfloat WetBuffer[1][BUFFERSIZE];
 
     RefCount ref;
 

+ 14 - 4
jni/openal-soft-android/OpenAL32/Include/alBuffer.h → jni/openal-soft-1.16.0/OpenAL32/Include/alBuffer.h

@@ -22,6 +22,7 @@ enum UserFmtType {
     UserFmtMulaw,
     UserFmtAlaw,
     UserFmtIMA4,
+    UserFmtMSADPCM,
 };
 enum UserFmtChannels {
     UserFmtMono   = AL_MONO_SOFT,
@@ -33,8 +34,8 @@ enum UserFmtChannels {
     UserFmtX71    = AL_7POINT1_SOFT, /* (WFX order) */
 };
 
-ALuint BytesFromUserFmt(enum UserFmtType type);
-ALuint ChannelsFromUserFmt(enum UserFmtChannels chans);
+ALuint BytesFromUserFmt(enum UserFmtType type) DECL_CONST;
+ALuint ChannelsFromUserFmt(enum UserFmtChannels chans) DECL_CONST;
 inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type)
 {
     return ChannelsFromUserFmt(chans) * BytesFromUserFmt(type);
@@ -58,8 +59,8 @@ enum FmtChannels {
 };
 #define MAX_INPUT_CHANNELS  (8)
 
-ALuint BytesFromFmt(enum FmtType type);
-ALuint ChannelsFromFmt(enum FmtChannels chans);
+ALuint BytesFromFmt(enum FmtType type) DECL_CONST;
+ALuint ChannelsFromFmt(enum FmtChannels chans) DECL_CONST;
 inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type)
 {
     return ChannelsFromFmt(chans) * BytesFromFmt(type);
@@ -79,10 +80,14 @@ typedef struct ALbuffer {
     enum UserFmtChannels OriginalChannels;
     enum UserFmtType     OriginalType;
     ALsizei              OriginalSize;
+    ALsizei              OriginalAlign;
 
     ALsizei  LoopStart;
     ALsizei  LoopEnd;
 
+    ALsizei UnpackAlign;
+    ALsizei PackAlign;
+
     /* Number of times buffer was attached to a source (deletion can only occur when 0) */
     RefCount ref;
 
@@ -92,6 +97,11 @@ typedef struct ALbuffer {
     ALuint id;
 } ALbuffer;
 
+ALbuffer *NewBuffer(ALCcontext *context);
+void DeleteBuffer(ALCdevice *device, ALbuffer *buffer);
+
+ALenum LoadData(ALbuffer *buffer, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc);
+
 inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
 { return (struct ALbuffer*)LookupUIntMapKey(&device->BufferMap, id); }
 inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id)

+ 0 - 0
jni/openal-soft-android/OpenAL32/Include/alEffect.h → jni/openal-soft-1.16.0/OpenAL32/Include/alEffect.h


+ 0 - 0
jni/openal-soft-android/OpenAL32/Include/alError.h → jni/openal-soft-1.16.0/OpenAL32/Include/alError.h


+ 16 - 10
jni/openal-soft-android/OpenAL32/Include/alFilter.h → jni/openal-soft-1.16.0/OpenAL32/Include/alFilter.h

@@ -7,7 +7,8 @@
 extern "C" {
 #endif
 
-#define LOWPASSFREQREF  (5000)
+#define LOWPASSFREQREF  (5000.0f)
+#define HIGHPASSFREQREF  (250.0f)
 
 
 /* Filters implementation is based on the "Cookbook formulae for audio   *
@@ -15,12 +16,18 @@ extern "C" {
  * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt                   */
 
 typedef enum ALfilterType {
+    /** EFX-style low-pass filter, specifying a gain and reference frequency. */
     ALfilterType_HighShelf,
+    /** EFX-style high-pass filter, specifying a gain and reference frequency. */
     ALfilterType_LowShelf,
+    /** Peaking filter, specifying a gain, reference frequency, and bandwidth. */
     ALfilterType_Peaking,
 
+    /** Low-pass cut-off filter, specifying a cut-off frequency and bandwidth. */
     ALfilterType_LowPass,
+    /** High-pass cut-off filter, specifying a cut-off frequency and bandwidth. */
     ALfilterType_HighPass,
+    /** Band-pass filter, specifying a center frequency and bandwidth. */
     ALfilterType_BandPass,
 } ALfilterType;
 
@@ -29,10 +36,13 @@ typedef struct ALfilterState {
     ALfloat y[2]; /* History of two last output samples */
     ALfloat a[3]; /* Transfer function coefficients "a" */
     ALfloat b[3]; /* Transfer function coefficients "b" */
+
+    void (*process)(struct ALfilterState *self, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples);
 } ALfilterState;
+#define ALfilterState_process(a, ...) ((a)->process((a), __VA_ARGS__))
 
 void ALfilterState_clear(ALfilterState *filter);
-void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_scale, ALfloat bandwidth);
+void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat bandwidth);
 
 inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample)
 {
@@ -51,14 +61,7 @@ inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample
     return outsmp;
 }
 
-inline ALfloat ALfilterState_processSingleC(const ALfilterState *filter, ALfloat sample)
-{
-    return filter->b[0] * sample +
-           filter->b[1] * filter->x[0] +
-           filter->b[2] * filter->x[1] -
-           filter->a[1] * filter->y[0] -
-           filter->a[2] * filter->y[1];
-}
+void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples);
 
 
 typedef struct ALfilter {
@@ -67,6 +70,9 @@ typedef struct ALfilter {
 
     ALfloat Gain;
     ALfloat GainHF;
+    ALfloat HFReference;
+    ALfloat GainLF;
+    ALfloat LFReference;
 
     void (*SetParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint val);
     void (*SetParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals);

+ 0 - 0
jni/openal-soft-android/OpenAL32/Include/alListener.h → jni/openal-soft-1.16.0/OpenAL32/Include/alListener.h


+ 155 - 113
jni/openal-soft-android/OpenAL32/Include/alMain.h → jni/openal-soft-1.16.0/OpenAL32/Include/alMain.h

@@ -6,6 +6,7 @@
 #include <stdarg.h>
 #include <assert.h>
 #include <math.h>
+#include <limits.h>
 
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
@@ -19,8 +20,22 @@
 #include "AL/alc.h"
 #include "AL/alext.h"
 
+
+#if defined(_WIN64)
+#define SZFMT "%I64u"
+#elif defined(_WIN32)
+#define SZFMT "%u"
+#else
+#define SZFMT "%zu"
+#endif
+
+
+#include "static_assert.h"
+#include "align.h"
 #include "atomic.h"
 #include "uintmap.h"
+#include "vector.h"
+#include "alstring.h"
 
 #ifndef ALC_SOFT_HRTF
 #define ALC_SOFT_HRTF 1
@@ -29,54 +44,25 @@
 
 #ifndef ALC_SOFT_midi_interface
 #define ALC_SOFT_midi_interface 1
+/* Global properties */
 #define AL_MIDI_CLOCK_SOFT                       0x9999
 #define AL_MIDI_STATE_SOFT                       0x9986
 #define AL_MIDI_GAIN_SOFT                        0x9998
-#define AL_MIDI_PRESET_SOFT                      0x9997
-#define AL_MIDI_BANK_SOFT                        0x9996
 #define AL_SOUNDFONTS_SIZE_SOFT                  0x9995
 #define AL_SOUNDFONTS_SOFT                       0x9994
+
+/* Soundfont properties */
 #define AL_PRESETS_SIZE_SOFT                     0x9993
 #define AL_PRESETS_SOFT                          0x9992
+
+/* Preset properties */
+#define AL_MIDI_PRESET_SOFT                      0x9997
+#define AL_MIDI_BANK_SOFT                        0x9996
 #define AL_FONTSOUNDS_SIZE_SOFT                  0x9991
 #define AL_FONTSOUNDS_SOFT                       0x9990
 
-#define AL_SOURCE0_INPUT_SOFT                    0x998F
-#define AL_SOURCE0_TYPE_SOFT                     0x998E
-#define AL_SOURCE0_FORM_SOFT                     0x998D
-#define AL_SOURCE1_INPUT_SOFT                    0x998C
-#define AL_SOURCE1_TYPE_SOFT                     0x998B
-#define AL_SOURCE1_FORM_SOFT                     0x998A
-#define AL_AMOUNT_SOFT                           0x9989
-#define AL_TRANSFORM_OP_SOFT                     0x9988
-#define AL_DESTINATION_SOFT                      0x9987
-
-/* Sounce Input */
-#define AL_ONE_SOFT                              0x0080
-#define AL_NOTEON_VELOCITY_SOFT                  0x0082
-#define AL_NOTEON_KEY_SOFT                       0x0083
-/* AL_KEYPRESSURE_SOFT */
-/* AL_CHANNELPRESSURE_SOFT */
-/* AL_PITCHBEND_SOFT */
-#define AL_PITCHBEND_SENSITIVITY_SOFT            0x0090
-/* CC 0...127 */
-
-/* Source Type */
-#define AL_UNORM_SOFT                            0x0000
-#define AL_UNORM_REV_SOFT                        0x0100
-#define AL_SNORM_SOFT                            0x0200
-#define AL_SNORM_REV_SOFT                        0x0300
-
-/* Source Form */
-#define AL_LINEAR_SOFT                           0x0000
-#define AL_CONCAVE_SOFT                          0x0400
-#define AL_CONVEX_SOFT                           0x0800
-#define AL_SWITCH_SOFT                           0x0C00
-
-/* Transform op */
-/* AL_LINEAR_SOFT */
-#define AL_ABSOLUTE_SOFT                         0x0002
-
+/* Fontsound properties */
+/* AL_BUFFER */
 #define AL_SAMPLE_START_SOFT                     0x2000
 #define AL_SAMPLE_END_SOFT                       0x2001
 #define AL_SAMPLE_LOOP_START_SOFT                0x2002
@@ -125,11 +111,55 @@
 #define AL_LOOP_MODE_SOFT                        0x0036
 #define AL_TUNING_SCALE_SOFT                     0x0038
 #define AL_EXCLUSIVE_CLASS_SOFT                  0x0039
-#define AL_LOOP_CONTINUOUS_SOFT                  0x0001
-#define AL_LOOP_UNTIL_RELEASE_SOFT               0x0003
+
+/* Sample Types */
+/* AL_MONO_SOFT */
 #define AL_RIGHT_SOFT                            0x0002
 #define AL_LEFT_SOFT                             0x0004
-#define AL_FORMAT_TYPE_SOFT                      0x1991
+
+/* Loop Modes */
+/* AL_NONE */
+#define AL_LOOP_CONTINUOUS_SOFT                  0x0001
+#define AL_LOOP_UNTIL_RELEASE_SOFT               0x0003
+
+/* Fontsound modulator stage properties */
+#define AL_SOURCE0_INPUT_SOFT                    0x998F
+#define AL_SOURCE0_TYPE_SOFT                     0x998E
+#define AL_SOURCE0_FORM_SOFT                     0x998D
+#define AL_SOURCE1_INPUT_SOFT                    0x998C
+#define AL_SOURCE1_TYPE_SOFT                     0x998B
+#define AL_SOURCE1_FORM_SOFT                     0x998A
+#define AL_AMOUNT_SOFT                           0x9989
+#define AL_TRANSFORM_OP_SOFT                     0x9988
+#define AL_DESTINATION_SOFT                      0x9987
+
+/* Sounce Inputs */
+#define AL_ONE_SOFT                              0x0080
+#define AL_NOTEON_VELOCITY_SOFT                  0x0082
+#define AL_NOTEON_KEY_SOFT                       0x0083
+/* AL_KEYPRESSURE_SOFT */
+/* AL_CHANNELPRESSURE_SOFT */
+/* AL_PITCHBEND_SOFT */
+#define AL_PITCHBEND_SENSITIVITY_SOFT            0x0090
+/* CC 0...127 */
+
+/* Source Types */
+#define AL_UNORM_SOFT                            0x0000
+#define AL_UNORM_REV_SOFT                        0x0100
+#define AL_SNORM_SOFT                            0x0200
+#define AL_SNORM_REV_SOFT                        0x0300
+
+/* Source Forms */
+#define AL_LINEAR_SOFT                           0x0000
+#define AL_CONCAVE_SOFT                          0x0400
+#define AL_CONVEX_SOFT                           0x0800
+#define AL_SWITCH_SOFT                           0x0C00
+
+/* Transform Ops */
+/* AL_LINEAR_SOFT */
+#define AL_ABSOLUTE_SOFT                         0x0002
+
+/* Events */
 #define AL_NOTEOFF_SOFT                          0x0080
 #define AL_NOTEON_SOFT                           0x0090
 #define AL_KEYPRESSURE_SOFT                      0x00A0
@@ -137,13 +167,10 @@
 #define AL_PROGRAMCHANGE_SOFT                    0x00C0
 #define AL_CHANNELPRESSURE_SOFT                  0x00D0
 #define AL_PITCHBEND_SOFT                        0x00E0
+
 typedef void (AL_APIENTRY*LPALGENSOUNDFONTSSOFT)(ALsizei n, ALuint *ids);
 typedef void (AL_APIENTRY*LPALDELETESOUNDFONTSSOFT)(ALsizei n, const ALuint *ids);
 typedef ALboolean (AL_APIENTRY*LPALISSOUNDFONTSOFT)(ALuint id);
-typedef void (AL_APIENTRY*LPALSOUNDFONTSAMPLESSOFT)(ALuint sfid, ALenum type, ALsizei count, const ALvoid *samples);
-typedef void (AL_APIENTRY*LPALGETSOUNDFONTSAMPLESSOFT)(ALuint id, ALsizei offset, ALsizei count, ALenum type, ALvoid *samples);
-typedef ALvoid* (AL_APIENTRY*LPALSOUNDFONTMAPSAMPLESSOFT)(ALuint sfid, ALsizei offset, ALsizei length);
-typedef void (AL_APIENTRY*LPALSOUNDFONTUNMAPSAMPLESSOFT)(ALuint sfid);
 typedef void (AL_APIENTRY*LPALGETSOUNDFONTIVSOFT)(ALuint id, ALenum param, ALint *values);
 typedef void (AL_APIENTRY*LPALSOUNDFONTPRESETSSOFT)(ALuint id, ALsizei count, const ALuint *pids);
 typedef void (AL_APIENTRY*LPALGENPRESETSSOFT)(ALsizei n, ALuint *ids);
@@ -178,10 +205,6 @@ typedef void (AL_APIENTRY*LPALLOADSOUNDFONTSOFT)(ALuint id, size_t(*cb)(ALvoid*,
 AL_API void AL_APIENTRY alGenSoundfontsSOFT(ALsizei n, ALuint *ids);
 AL_API void AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids);
 AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(ALuint id);
-AL_API void AL_APIENTRY alSoundfontSamplesSOFT(ALuint sfid, ALenum type, ALsizei count, const ALvoid *samples);
-AL_API void AL_APIENTRY alGetSoundfontSamplesSOFT(ALuint id, ALsizei offset, ALsizei count, ALenum type, ALvoid *samples);
-AL_API ALvoid* AL_APIENTRY alSoundfontMapSamplesSOFT(ALuint sfid, ALsizei offset, ALsizei length);
-AL_API void AL_APIENTRY alSoundfontUnmapSamplesSOFT(ALuint sfid);
 AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *values);
 AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const ALuint *pids);
 
@@ -218,13 +241,14 @@ AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_
 #endif
 #endif
 
-#ifndef ALC_SOFT_pause_device
-#define ALC_SOFT_pause_device 1
-typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device);
-typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device);
+#ifndef ALC_SOFT_device_clock
+#define ALC_SOFT_device_clock 1
+typedef int64_t ALCint64SOFT;
+typedef uint64_t ALCuint64SOFT;
+#define ALC_DEVICE_CLOCK_SOFT                    0x1600
+typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
 #ifdef AL_ALEXT_PROTOTYPES
-ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device);
-ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device);
+ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
 #endif
 #endif
 
@@ -233,11 +257,6 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device);
 /* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but
  * recent versions (at least 4.5.1) do recognize GCC's __restrict. */
 #define restrict __restrict
-/* KDevelop won't see the ALIGN macro from config.h when viewing files that
- * don't include it directly (e.g. headers). */
-#ifndef ALIGN
-#define ALIGN(x)
-#endif
 #endif
 
 
@@ -273,10 +292,12 @@ typedef ptrdiff_t ALsizeiptrEXT;
 #endif
 #endif
 
-#ifdef HAVE_GCC_FORMAT
-#define PRINTF_STYLE(x, y) __attribute__((format(printf, (x), (y))))
+#ifdef __GNUC__
+#define DECL_CONST __attribute__((const))
+#define DECL_FORMAT(x, y, z) __attribute__((format(x, (y), (z))))
 #else
-#define PRINTF_STYLE(x, y)
+#define DECL_CONST
+#define DECL_FORMAT(x, y, z)
 #endif
 
 #if defined(__GNUC__) && defined(__i386__)
@@ -289,6 +310,20 @@ typedef ptrdiff_t ALsizeiptrEXT;
 #define FORCE_ALIGN
 #endif
 
+#ifdef HAVE_C99_VLA
+#define DECL_VLA(T, _name, _size)  T _name[(_size)]
+#else
+#define DECL_VLA(T, _name, _size)  T *_name = alloca((_size) * sizeof(T))
+#endif
+
+#ifndef PATH_MAX
+#ifdef MAX_PATH
+#define PATH_MAX MAX_PATH
+#else
+#define PATH_MAX 4096
+#endif
+#endif
+
 
 static const union {
     ALuint u;
@@ -301,8 +336,15 @@ static const union {
 
 #define DERIVE_FROM_TYPE(t)          t t##_parent
 #define STATIC_CAST(to, obj)         (&(obj)->to##_parent)
+#ifdef __GNUC__
+#define STATIC_UPCAST(to, from, obj) __extension__({                          \
+    static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))),       \
+                  "Invalid upcast object from type");                         \
+    (to*)((char*)(obj) - offsetof(to, from##_parent));                        \
+})
+#else
 #define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent)))
-
+#endif
 
 #define DECLARE_FORWARD(T1, T2, rettype, func)                                \
 rettype T1##_##func(T1 *obj)                                                  \
@@ -343,6 +385,9 @@ static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b)            \
 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \
 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); }
 
+#define DECLARE_DEFAULT_ALLOCATORS(T)                                         \
+static void* T##_New(size_t size) { return malloc(size); }                    \
+static void T##_Delete(void *ptr) { free(ptr); }
 
 /* Helper to extract an argument list for VCALL. Not used directly. */
 #define EXTRACT_VCALL_ARGS(...)  __VA_ARGS__))
@@ -437,12 +482,6 @@ void alc_solaris_probe(enum DevProbe type);
 ALCboolean alc_sndio_init(BackendFuncs *func_list);
 void alc_sndio_deinit(void);
 void alc_sndio_probe(enum DevProbe type);
-ALCboolean alcMMDevApiInit(BackendFuncs *func_list);
-void alcMMDevApiDeinit(void);
-void alcMMDevApiProbe(enum DevProbe type);
-ALCboolean alcDSoundInit(BackendFuncs *func_list);
-void alcDSoundDeinit(void);
-void alcDSoundProbe(enum DevProbe type);
 ALCboolean alcWinMMInit(BackendFuncs *FuncList);
 void alcWinMMDeinit(void);
 void alcWinMMProbe(enum DevProbe type);
@@ -526,8 +565,8 @@ enum DevFmtChannels {
     DevFmtChannelsDefault = DevFmtStereo
 };
 
-ALuint BytesFromDevFmt(enum DevFmtType type);
-ALuint ChannelsFromDevFmt(enum DevFmtChannels chans);
+ALuint BytesFromDevFmt(enum DevFmtType type) DECL_CONST;
+ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) DECL_CONST;
 inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type)
 {
     return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type);
@@ -559,7 +598,7 @@ enum DeviceType {
 
 struct ALCdevice_struct
 {
-    volatile RefCount ref;
+    RefCount ref;
 
     ALCboolean Connected;
     enum DeviceType Type;
@@ -570,9 +609,9 @@ struct ALCdevice_struct
     enum DevFmtChannels FmtChans;
     enum DevFmtType     FmtType;
 
-    ALCchar      *DeviceName;
+    al_string DeviceName;
 
-    volatile ALCenum LastError;
+    ATOMIC(ALCenum) LastError;
 
     // Maximum number of sources that can be created
     ALuint       MaxNoOfSources;
@@ -623,28 +662,38 @@ struct ALCdevice_struct
     ALfloat SpeakerAngle[MaxChannels];
     ALuint  NumChan;
 
-    /* Temp storage used for mixing. +1 for the predictive sample. */
-    ALIGN(16) ALfloat SampleData1[BUFFERSIZE+1];
-    ALIGN(16) ALfloat SampleData2[BUFFERSIZE+1];
+    ALuint64 ClockBase;
+    ALuint SamplesDone;
+
+    /* Temp storage used for each source when mixing. */
+    alignas(16) ALfloat SourceData[BUFFERSIZE];
+    alignas(16) ALfloat ResampledData[BUFFERSIZE];
+    alignas(16) ALfloat FilteredData[BUFFERSIZE];
 
     // Dry path buffer mix
-    ALIGN(16) ALfloat DryBuffer[MaxChannels][BUFFERSIZE];
+    alignas(16) ALfloat DryBuffer[MaxChannels][BUFFERSIZE];
 
-    ALIGN(16) ALfloat ClickRemoval[MaxChannels];
-    ALIGN(16) ALfloat PendingClicks[MaxChannels];
+    /* Running count of the mixer invocations, in 31.1 fixed point. This
+     * actually increments *twice* when mixing, first at the start and then at
+     * the end, so the bottom bit indicates if the device is currently mixing
+     * and the upper bits indicates how many mixes have been done.
+     */
+    RefCount MixCount;
 
     /* Default effect slot */
     struct ALeffectslot *DefaultSlot;
 
     // Contexts created on this device
-    ALCcontext *volatile ContextList;
+    ATOMIC(ALCcontext*) ContextList;
 
     struct ALCbackend *Backend;
 
-    BackendFuncs *Funcs;
-    void         *ExtraData; // For the backend's use
+    void *ExtraData; // For the backend's use
 
     ALCdevice *volatile next;
+
+    /* Memory space used by the default slot (Playback devices only) */
+    alignas(16) ALCbyte _slot_mem[];
 };
 
 // Frequency was requested by the app or config file
@@ -669,6 +718,10 @@ struct ALCdevice_struct
 #define INVALID_OFFSET                           (~0u)
 
 
+/* Nanosecond resolution for the device clock time. */
+#define DEVICE_CLOCK_RES  U64(1000000000)
+
+
 /* Must be less than 15 characters (16 including terminating null) for
  * compatibility with pthread_setname_np limitations. */
 #define MIXER_THREAD_NAME "alsoft-mixer"
@@ -676,16 +729,16 @@ struct ALCdevice_struct
 
 struct ALCcontext_struct
 {
-    volatile RefCount ref;
+    RefCount ref;
 
     struct ALlistener *Listener;
 
     UIntMap SourceMap;
     UIntMap EffectSlotMap;
 
-    volatile ALenum LastError;
+    ATOMIC(ALenum) LastError;
 
-    volatile ALenum UpdateSources;
+    ATOMIC(ALenum) UpdateSources;
 
     volatile enum DistanceModel DistanceModel;
     volatile ALboolean SourceDistanceModel;
@@ -695,18 +748,19 @@ struct ALCcontext_struct
     volatile ALfloat SpeedOfSound;
     volatile ALenum  DeferUpdates;
 
-    struct ALsource **ActiveSources;
-    ALsizei           ActiveSourceCount;
-    ALsizei           MaxActiveSources;
+    struct ALactivesource **ActiveSources;
+    ALsizei ActiveSourceCount;
+    ALsizei MaxActiveSources;
 
-    struct ALeffectslot **ActiveEffectSlots;
-    ALsizei               ActiveEffectSlotCount;
-    ALsizei               MaxActiveEffectSlots;
+    VECTOR(struct ALeffectslot*) ActiveAuxSlots;
 
     ALCdevice  *Device;
     const ALCchar *ExtensionList;
 
     ALCcontext *volatile next;
+
+    /* Memory space used by the listener */
+    alignas(16) ALCbyte _listener_mem[];
 };
 
 ALCcontext *GetContextRef(void);
@@ -771,31 +825,17 @@ void SetRTPriority(void);
 void SetDefaultChannelOrder(ALCdevice *device);
 void SetDefaultWFXChannelOrder(ALCdevice *device);
 
-const ALCchar *DevFmtTypeString(enum DevFmtType type);
-const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
-
-#define HRIR_BITS        (7)
-#define HRIR_LENGTH      (1<<HRIR_BITS)
-#define HRIR_MASK        (HRIR_LENGTH-1)
-#define HRTFDELAY_BITS    (20)
-#define HRTFDELAY_FRACONE (1<<HRTFDELAY_BITS)
-#define HRTFDELAY_MASK    (HRTFDELAY_FRACONE-1)
-const struct Hrtf *GetHrtf(ALCdevice *device);
-void FindHrtfFormat(const ALCdevice *device, enum DevFmtChannels *chans, ALCuint *srate);
-void FreeHrtfs(void);
-ALuint GetHrtfIrSize(const struct Hrtf *Hrtf);
-ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]);
-void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays);
-ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep);
+const ALCchar *DevFmtTypeString(enum DevFmtType type) DECL_CONST;
+const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) DECL_CONST;
 
 
 extern FILE *LogFile;
 
-#ifdef __GNUC__
+#if defined(__GNUC__) && !defined(IN_IDE_PARSER)
 #define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: "MSG, T, __FUNCTION__ , ## __VA_ARGS__)
 #else
-void al_print(const char *type, const char *func, const char *fmt, ...) PRINTF_STYLE(3,4);
-#define AL_PRINT(T, MSG, ...) al_print((T), __FUNCTION__, MSG, __VA_ARGS__)
+void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4);
+#define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__)
 #endif
 
 enum LogLevel {
@@ -835,11 +875,13 @@ extern ALuint CPUCapFlags;
 enum {
     CPU_CAP_SSE    = 1<<0,
     CPU_CAP_SSE2   = 1<<1,
-    CPU_CAP_NEON   = 1<<2,
+    CPU_CAP_SSE4_1 = 1<<2,
+    CPU_CAP_NEON   = 1<<3,
 };
 
 void FillCPUCaps(ALuint capfilter);
 
+FILE *OpenDataFile(const char *fname, const char *subdir);
 
 /* Small hack to use a pointer-to-array type as a normal argument type.
  * Shouldn't be used directly. */

+ 22 - 16
jni/openal-soft-android/OpenAL32/Include/alMidi.h → jni/openal-soft-1.16.0/OpenAL32/Include/alMidi.h

@@ -32,7 +32,9 @@ typedef struct ALenvelope {
 
 
 typedef struct ALfontsound {
-    volatile RefCount ref;
+    RefCount ref;
+
+    struct ALbuffer *Buffer;
 
     ALint MinKey, MaxKey;
     ALint MinVelocity, MaxVelocity;
@@ -85,32 +87,28 @@ typedef struct ALfontsound {
     ALenum SampleType;
     struct ALfontsound *Link;
 
+    /* NOTE: Each map entry contains *four* (4) ALsfmodulator objects. */
     UIntMap ModulatorMap;
 
     ALuint id;
 } ALfontsound;
 
-void ALfontsound_Destruct(ALfontsound *self);
 void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value);
 void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value);
 
 ALfontsound *NewFontsound(ALCcontext *context);
+void DeleteFontsound(ALCdevice *device, ALfontsound *sound);
 
 inline struct ALfontsound *LookupFontsound(ALCdevice *device, ALuint id)
 { return (struct ALfontsound*)LookupUIntMapKey(&device->FontsoundMap, id); }
 inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id)
 { return (struct ALfontsound*)RemoveUIntMapKey(&device->FontsoundMap, id); }
 
-inline struct ALsfmodulator *LookupModulator(ALfontsound *sound, ALuint id)
-{ return (struct ALsfmodulator*)LookupUIntMapKey(&sound->ModulatorMap, id); }
-inline struct ALsfmodulator *RemoveModulator(ALfontsound *sound, ALuint id)
-{ return (struct ALsfmodulator*)RemoveUIntMapKey(&sound->ModulatorMap, id); }
-
 void ReleaseALFontsounds(ALCdevice *device);
 
 
 typedef struct ALsfpreset {
-    volatile RefCount ref;
+    RefCount ref;
 
     ALint Preset; /* a.k.a. MIDI program number */
     ALint Bank; /* MIDI bank 0...127, or percussion (bank 128) */
@@ -122,7 +120,7 @@ typedef struct ALsfpreset {
 } ALsfpreset;
 
 ALsfpreset *NewPreset(ALCcontext *context);
-void DeletePreset(ALsfpreset *preset, ALCdevice *device);
+void DeletePreset(ALCdevice *device, ALsfpreset *preset);
 
 inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id)
 { return (struct ALsfpreset*)LookupUIntMapKey(&device->PresetMap, id); }
@@ -133,22 +131,16 @@ void ReleaseALPresets(ALCdevice *device);
 
 
 typedef struct ALsoundfont {
-    volatile RefCount ref;
+    RefCount ref;
 
     ALsfpreset **Presets;
     ALsizei NumPresets;
 
-    ALshort *Samples;
-    ALint NumSamples;
-
     RWLock Lock;
-    volatile ALenum Mapped;
 
     ALuint id;
 } ALsoundfont;
 
-void ALsoundfont_Construct(ALsoundfont *self);
-void ALsoundfont_Destruct(ALsoundfont *self);
 ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context);
 void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device);
 
@@ -159,6 +151,20 @@ inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id)
 
 void ReleaseALSoundfonts(ALCdevice *device);
 
+
+inline ALboolean IsValidCtrlInput(int cc)
+{
+    /* These correspond to MIDI functions, not real controller values. */
+    if(cc == 0 || cc == 6 || cc == 32 || cc == 38 || (cc >= 98 && cc <= 101) || cc >= 120)
+        return AL_FALSE;
+    /* These are the LSB components of CC0...CC31, which are automatically used when
+     * reading the MSB controller value. */
+    if(cc >= 32 && cc <= 63)
+        return AL_FALSE;
+    /* All the rest are okay! */
+    return AL_TRUE;
+}
+
 #ifdef __cplusplus
 }
 #endif

+ 32 - 78
jni/openal-soft-android/OpenAL32/Include/alSource.h → jni/openal-soft-1.16.0/OpenAL32/Include/alSource.h

@@ -5,17 +5,12 @@
 
 #include "alMain.h"
 #include "alu.h"
-#include "alFilter.h"
-#include "alBuffer.h"
+#include "hrtf.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#define SRC_HISTORY_BITS   (6)
-#define SRC_HISTORY_LENGTH (1<<SRC_HISTORY_BITS)
-#define SRC_HISTORY_MASK   (SRC_HISTORY_LENGTH-1)
-
 extern enum Resampler DefaultResampler;
 
 extern const ALsizei ResamplerPadding[ResamplerMax];
@@ -23,62 +18,31 @@ extern const ALsizei ResamplerPrePadding[ResamplerMax];
 
 
 typedef struct ALbufferlistitem {
-    struct ALbuffer         *buffer;
-    struct ALbufferlistitem *next;
-    struct ALbufferlistitem *prev;
+    struct ALbuffer *buffer;
+    struct ALbufferlistitem *volatile next;
+    struct ALbufferlistitem *volatile prev;
 } ALbufferlistitem;
 
-typedef struct HrtfState {
-    ALboolean Moving;
-    ALuint Counter;
-    ALIGN(16) ALfloat History[MAX_INPUT_CHANNELS][SRC_HISTORY_LENGTH];
-    ALIGN(16) ALfloat Values[MAX_INPUT_CHANNELS][HRIR_LENGTH][2];
-    ALuint Offset;
-} HrtfState;
-
-typedef struct HrtfParams {
-    ALfloat Gain;
-    ALfloat Dir[3];
-    ALIGN(16) ALfloat Coeffs[MAX_INPUT_CHANNELS][HRIR_LENGTH][2];
-    ALIGN(16) ALfloat CoeffStep[HRIR_LENGTH][2];
-    ALuint Delay[MAX_INPUT_CHANNELS][2];
-    ALint DelayStep[2];
-    ALuint IrSize;
-} HrtfParams;
-
-typedef struct DirectParams {
-    ALfloat (*OutBuffer)[BUFFERSIZE];
-    ALfloat *ClickRemoval;
-    ALfloat *PendingClicks;
 
-    struct {
-        HrtfParams Params;
-        HrtfState *State;
-    } Hrtf;
+typedef struct ALactivesource {
+    struct ALsource *Source;
 
-    /* A mixing matrix. First subscript is the channel number of the input data
-     * (regardless of channel configuration) and the second is the channel
-     * target (eg. FrontLeft). Not used with HRTF. */
-    ALfloat Gains[MAX_INPUT_CHANNELS][MaxChannels];
+    /** Method to update mixing parameters. */
+    ALvoid (*Update)(struct ALactivesource *self, const ALCcontext *context);
 
-    ALfilterState LpFilter[MAX_INPUT_CHANNELS];
-} DirectParams;
+    /** Current target parameters used for mixing. */
+    ALint Step;
 
-typedef struct SendParams {
-    ALfloat (*OutBuffer)[BUFFERSIZE];
-    ALfloat *ClickRemoval;
-    ALfloat *PendingClicks;
+    ALboolean IsHrtf;
 
-    /* Gain control, which applies to all input channels to a single (mono)
-     * output buffer. */
-    ALfloat Gain;
+    ALuint Offset; /* Number of output samples mixed since starting. */
 
-    ALfilterState LpFilter[MAX_INPUT_CHANNELS];
-} SendParams;
+    DirectParams Direct;
+    SendParams Send[MAX_SENDS];
+} ALactivesource;
 
 
-typedef struct ALsource
-{
+typedef struct ALsource {
     /** Source properties. */
     volatile ALfloat   Pitch;
     volatile ALfloat   Gain;
@@ -107,6 +71,8 @@ typedef struct ALsource
     volatile ALfloat RoomRolloffFactor;
     volatile ALfloat DopplerFactor;
 
+    volatile ALfloat Radius;
+
     enum Resampler Resampler;
 
     /**
@@ -132,49 +98,37 @@ typedef struct ALsource
     ALuint position_fraction;
 
     /** Source Buffer Queue info. */
-    ALbufferlistitem *queue;
-    ALuint BuffersInQueue;
-    ALuint BuffersPlayed;
+    ATOMIC(ALbufferlistitem*) queue;
+    ATOMIC(ALbufferlistitem*) current_buffer;
+    RWLock queue_lock;
 
     /** Current buffer sample info. */
     ALuint NumChannels;
     ALuint SampleSize;
 
     /** Direct filter and auxiliary send info. */
-    ALfloat DirectGain;
-    ALfloat DirectGainHF;
-
+    struct {
+        ALfloat Gain;
+        ALfloat GainHF;
+        ALfloat HFReference;
+        ALfloat GainLF;
+        ALfloat LFReference;
+    } Direct;
     struct {
         struct ALeffectslot *Slot;
         ALfloat Gain;
         ALfloat GainHF;
+        ALfloat HFReference;
+        ALfloat GainLF;
+        ALfloat LFReference;
     } Send[MAX_SENDS];
 
-    /** HRTF info. */
-    HrtfState Hrtf;
-
-    /** Current target parameters used for mixing. */
-    struct {
-        ResamplerFunc Resample;
-        DryMixerFunc DryMix;
-        WetMixerFunc WetMix;
-
-        ALint Step;
-
-        DirectParams Direct;
-
-        SendParams Send[MAX_SENDS];
-    } Params;
     /** Source needs to update its mixing parameters. */
-    volatile ALenum NeedsUpdate;
-
-    /** Method to update mixing parameters. */
-    ALvoid (*Update)(struct ALsource *self, const ALCcontext *context);
+    ATOMIC(ALenum) NeedsUpdate;
 
     /** Self ID */
     ALuint id;
 } ALsource;
-#define ALsource_Update(s,a)                 ((s)->Update(s,a))
 
 inline struct ALsource *LookupSource(ALCcontext *context, ALuint id)
 { return (struct ALsource*)LookupUIntMapKey(&context->SourceMap, id); }

+ 0 - 0
jni/openal-soft-android/OpenAL32/Include/alThunk.h → jni/openal-soft-1.16.0/OpenAL32/Include/alThunk.h


+ 99 - 20
jni/openal-soft-android/OpenAL32/Include/alu.h → jni/openal-soft-1.16.0/OpenAL32/Include/alu.h

@@ -1,8 +1,6 @@
 #ifndef _ALU_H_
 #define _ALU_H_
 
-#include "alMain.h"
-
 #include <limits.h>
 #include <math.h>
 #ifdef HAVE_FLOAT_H
@@ -12,6 +10,13 @@
 #include <ieeefp.h>
 #endif
 
+#include "alMain.h"
+#include "alBuffer.h"
+#include "alFilter.h"
+
+#include "hrtf.h"
+#include "align.h"
+
 
 #define F_PI    (3.14159265358979323846f)
 #define F_PI_2  (1.57079632679489661923f)
@@ -25,29 +30,103 @@
 #define RAD2DEG(x)  ((ALfloat)(x) * (180.0f/F_PI))
 
 
+#define SRC_HISTORY_BITS   (6)
+#define SRC_HISTORY_LENGTH (1<<SRC_HISTORY_BITS)
+#define SRC_HISTORY_MASK   (SRC_HISTORY_LENGTH-1)
+
+#define MAX_PITCH  (10)
+
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-struct ALsource;
-struct ALbuffer;
-struct DirectParams;
-struct SendParams;
+enum ActiveFilters {
+    AF_None = 0,
+    AF_LowPass = 1,
+    AF_HighPass = 2,
+    AF_BandPass = AF_LowPass | AF_HighPass
+};
+
+
+typedef struct HrtfState {
+    alignas(16) ALfloat History[SRC_HISTORY_LENGTH];
+    alignas(16) ALfloat Values[HRIR_LENGTH][2];
+} HrtfState;
+
+typedef struct HrtfParams {
+    alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
+    alignas(16) ALfloat CoeffStep[HRIR_LENGTH][2];
+    ALuint Delay[2];
+    ALint DelayStep[2];
+} HrtfParams;
+
+
+typedef struct MixGains {
+    ALfloat Current;
+    ALfloat Step;
+    ALfloat Target;
+} MixGains;
+
+
+typedef struct DirectParams {
+    ALfloat (*OutBuffer)[BUFFERSIZE];
+
+    /* If not 'moving', gain/coefficients are set directly without fading. */
+    ALboolean Moving;
+    /* Stepping counter for gain/coefficient fading. */
+    ALuint Counter;
+
+    struct {
+        enum ActiveFilters ActiveType;
+        ALfilterState LowPass;
+        ALfilterState HighPass;
+    } Filters[MAX_INPUT_CHANNELS];
+
+    union {
+        struct {
+            HrtfParams Params[MAX_INPUT_CHANNELS];
+            HrtfState State[MAX_INPUT_CHANNELS];
+            ALuint IrSize;
+            ALfloat Gain;
+            ALfloat Dir[3];
+        } Hrtf;
+
+        MixGains Gains[MAX_INPUT_CHANNELS][MaxChannels];
+    } Mix;
+} DirectParams;
+
+typedef struct SendParams {
+    ALfloat (*OutBuffer)[BUFFERSIZE];
+
+    ALboolean Moving;
+    ALuint Counter;
+
+    struct {
+        enum ActiveFilters ActiveType;
+        ALfilterState LowPass;
+        ALfilterState HighPass;
+    } Filters[MAX_INPUT_CHANNELS];
+
+    /* Gain control, which applies to all input channels to a single (mono)
+     * output buffer. */
+    MixGains Gain;
+} SendParams;
+
 
-typedef void (*ResamplerFunc)(const ALfloat *src, ALuint frac, ALuint increment,
-                              ALfloat *restrict dst, ALuint dstlen);
+typedef const ALfloat* (*ResamplerFunc)(const ALfloat *src, ALuint frac, ALuint increment,
+                                        ALfloat *restrict dst, ALuint dstlen);
 
-typedef ALvoid (*DryMixerFunc)(const struct DirectParams *params,
-                               const ALfloat *restrict data, ALuint srcchan,
-                               ALuint OutPos, ALuint SamplesToDo,
-                               ALuint BufferSize);
-typedef ALvoid (*WetMixerFunc)(const struct SendParams *params,
-                               const ALfloat *restrict data,
-                               ALuint OutPos, ALuint SamplesToDo,
-                               ALuint BufferSize);
+typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
+                          ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
+                          ALuint Counter, ALuint OutPos, ALuint BufferSize);
+typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
+                              ALuint Counter, ALuint Offset, ALuint OutPos,
+                              const ALuint IrSize, const HrtfParams *hrtfparams,
+                              HrtfState *hrtfstate, ALuint BufferSize);
 
 
-#define GAIN_SILENCE_THRESHOLD  (0.00001f)
+#define GAIN_SILENCE_THRESHOLD  (0.00001f) /* -100dB */
 
 #define SPEEDOFSOUNDMETRESPERSEC  (343.3f)
 #define AIRABSORBGAINHF           (0.99426f) /* -0.05dB */
@@ -137,10 +216,10 @@ inline void SetGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MaxC
 }
 
 
-ALvoid CalcSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
-ALvoid CalcNonAttnSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext);
+ALvoid CalcSourceParams(struct ALactivesource *src, const ALCcontext *ALContext);
+ALvoid CalcNonAttnSourceParams(struct ALactivesource *src, const ALCcontext *ALContext);
 
-ALvoid MixSource(struct ALsource *Source, ALCdevice *Device, ALuint SamplesToDo);
+ALvoid MixSource(struct ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo);
 
 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
 /* Caller must lock the device. */

+ 36 - 14
jni/openal-soft-android/OpenAL32/Include/bs2b.h → jni/openal-soft-1.16.0/OpenAL32/Include/bs2b.h

@@ -51,24 +51,21 @@ struct bs2b {
     int srate;   /* Sample rate (Hz) */
 
     /* Lowpass IIR filter coefficients */
-    double a0_lo;
-    double b1_lo;
+    float a0_lo;
+    float b1_lo;
 
     /* Highboost IIR filter coefficients */
-    double a0_hi;
-    double a1_hi;
-    double b1_hi;
-
-    /* Global gain against overloading */
-    float gain;
+    float a0_hi;
+    float a1_hi;
+    float b1_hi;
 
     /* Buffer of last filtered sample.
      * [0] - first channel, [1] - second channel
      */
     struct t_last_sample {
-        double asis[2];
-        double lo[2];
-        double hi[2];
+        float asis[2];
+        float lo[2];
+        float hi[2];
     } last_sample;
 };
 
@@ -93,11 +90,36 @@ void bs2b_clear(struct bs2b *bs2b);
 
 /* Crossfeeds one stereo sample that are pointed by sample.
  * [0] - first channel, [1] - second channel.
- * Returns crossfided samle by sample pointer.
+ * Returns crossfided sample by sample pointer.
+ */
+inline void bs2b_cross_feed(struct bs2b *bs2b, float *restrict sample)
+{
+/* Single pole IIR filter.
+ * O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1]
  */
 
-/* sample poits to floats */
-void bs2b_cross_feed(struct bs2b *bs2b, float *sample);
+/* Lowpass filter */
+#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1))
+
+/* Highboost filter */
+#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1))
+
+    /* Lowpass filter */
+    bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]);
+    bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]);
+
+    /* Highboost filter */
+    bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]);
+    bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]);
+    bs2b->last_sample.asis[0] = sample[0];
+    bs2b->last_sample.asis[1] = sample[1];
+
+    /* Crossfeed */
+    sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1];
+    sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0];
+#undef hi_filter
+#undef lo_filter
+} /* bs2b_cross_feed */
 
 #ifdef __cplusplus
 }    /* extern "C" */

+ 9 - 0
jni/openal-soft-1.16.0/OpenAL32/Include/sample_cvt.h

@@ -0,0 +1,9 @@
+#ifndef SAMPLE_CVT_H
+#define SAMPLE_CVT_H
+
+#include "AL/al.h"
+#include "alBuffer.h"
+
+void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align);
+
+#endif /* SAMPLE_CVT_H */

+ 35 - 51
jni/openal-soft-android/OpenAL32/alAuxEffectSlot.c → jni/openal-soft-1.16.0/OpenAL32/alAuxEffectSlot.c

@@ -35,8 +35,8 @@
 extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id);
 extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id);
 
-static ALenum AddEffectSlotArray(ALCcontext *Context, ALsizei count, const ALuint *slots);
-static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *slot);
+static ALenum AddEffectSlotArray(ALCcontext *Context, ALeffectslot **start, ALsizei count);
+static void RemoveEffectSlotArray(ALCcontext *Context, const ALeffectslot *slot);
 
 
 static UIntMap EffectStateFactoryMap;
@@ -52,14 +52,20 @@ static inline ALeffectStateFactory *getFactoryByType(ALenum type)
 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
 {
     ALCcontext *context;
+    VECTOR(ALeffectslot*) slotvec;
     ALsizei cur;
     ALenum err;
 
     context = GetContextRef();
     if(!context) return;
 
+    VECTOR_INIT(slotvec);
+
     if(!(n >= 0))
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(!VECTOR_RESERVE(slotvec, n))
+        SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
+
     for(cur = 0;cur < n;cur++)
     {
         ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
@@ -84,9 +90,11 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
             SET_ERROR_AND_GOTO(context, err, done);
         }
 
+        VECTOR_PUSH_BACK(slotvec, slot);
+
         effectslots[cur] = slot->id;
     }
-    err = AddEffectSlotArray(context, n, effectslots);
+    err = AddEffectSlotArray(context, VECTOR_ITER_BEGIN(slotvec), n);
     if(err != AL_NO_ERROR)
     {
         alDeleteAuxiliaryEffectSlots(cur, effectslots);
@@ -94,6 +102,8 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
     }
 
 done:
+    VECTOR_DEINIT(slotvec);
+
     ALCcontext_DecRef(context);
 }
 
@@ -112,7 +122,7 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *
     {
         if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
             SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-        if(slot->ref != 0)
+        if(ReadRef(&slot->ref) != 0)
             SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
     }
 
@@ -173,7 +183,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
         err = InitializeEffect(device, slot, effect);
         if(err != AL_NO_ERROR)
             SET_ERROR_AND_GOTO(context, err, done);
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         break;
 
     case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
@@ -181,7 +191,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
         slot->AuxSendAuto = value;
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         break;
 
     default:
@@ -236,7 +246,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
         slot->Gain = value;
-        slot->NeedsUpdate = AL_TRUE;
+        ATOMIC_STORE(&slot->NeedsUpdate, AL_TRUE);
         break;
 
     default:
@@ -375,56 +385,32 @@ done:
 }
 
 
-static ALvoid RemoveEffectSlotArray(ALCcontext *context, ALeffectslot *slot)
+static ALenum AddEffectSlotArray(ALCcontext *context, ALeffectslot **start, ALsizei count)
 {
-    ALeffectslot **slotlist, **slotlistend;
+    ALenum err = AL_NO_ERROR;
 
     LockContext(context);
-    slotlist = context->ActiveEffectSlots;
-    slotlistend = slotlist + context->ActiveEffectSlotCount;
-    while(slotlist != slotlistend)
-    {
-        if(*slotlist == slot)
-        {
-            *slotlist = *(--slotlistend);
-            context->ActiveEffectSlotCount--;
-            break;
-        }
-        slotlist++;
-    }
+    if(!VECTOR_INSERT(context->ActiveAuxSlots, VECTOR_ITER_END(context->ActiveAuxSlots), start, start+count))
+        err = AL_OUT_OF_MEMORY;
     UnlockContext(context);
+
+    return err;
 }
 
-static ALenum AddEffectSlotArray(ALCcontext *context, ALsizei count, const ALuint *slots)
+static void RemoveEffectSlotArray(ALCcontext *context, const ALeffectslot *slot)
 {
-    ALsizei i;
+    ALeffectslot **iter;
 
     LockContext(context);
-    if(count > context->MaxActiveEffectSlots-context->ActiveEffectSlotCount)
-    {
-        ALsizei newcount;
-        void *temp = NULL;
-
-        newcount = context->MaxActiveEffectSlots ? (context->MaxActiveEffectSlots<<1) : 1;
-        if(newcount > context->MaxActiveEffectSlots)
-            temp = realloc(context->ActiveEffectSlots,
-                           newcount * sizeof(*context->ActiveEffectSlots));
-        if(!temp)
-        {
-            UnlockContext(context);
-            return AL_OUT_OF_MEMORY;
-        }
-        context->ActiveEffectSlots = temp;
-        context->MaxActiveEffectSlots = newcount;
-    }
-    for(i = 0;i < count;i++)
+#define MATCH_SLOT(_i)  (slot == *(_i))
+    VECTOR_FIND_IF(iter, ALeffectslot*, context->ActiveAuxSlots, MATCH_SLOT);
+    if(iter != VECTOR_ITER_END(context->ActiveAuxSlots))
     {
-        ALeffectslot *slot = LookupEffectSlot(context, slots[i]);
-        assert(slot != NULL);
-        context->ActiveEffectSlots[context->ActiveEffectSlotCount++] = slot;
+        *iter = VECTOR_BACK(context->ActiveAuxSlots);
+        VECTOR_POP_BACK(context->ActiveAuxSlots);
     }
+#undef MATCH_SLOT
     UnlockContext(context);
-    return AL_NO_ERROR;
 }
 
 
@@ -499,7 +485,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
         /* FIXME: This should be done asynchronously, but since the EffectState
          * object was changed, it needs an update before its Process method can
          * be called. */
-        EffectSlot->NeedsUpdate = AL_FALSE;
+        ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_FALSE);
         V(EffectSlot->EffectState,update)(Device, EffectSlot);
         ALCdevice_Unlock(Device);
 
@@ -515,7 +501,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
             ALCdevice_Lock(Device);
             memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props));
             ALCdevice_Unlock(Device);
-            EffectSlot->NeedsUpdate = AL_TRUE;
+            ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_TRUE);
         }
     }
 
@@ -536,15 +522,13 @@ ALenum InitEffectSlot(ALeffectslot *slot)
 
     slot->Gain = 1.0;
     slot->AuxSendAuto = AL_TRUE;
-    slot->NeedsUpdate = AL_FALSE;
+    ATOMIC_INIT(&slot->NeedsUpdate, AL_FALSE);
     for(c = 0;c < 1;c++)
     {
         for(i = 0;i < BUFFERSIZE;i++)
             slot->WetBuffer[c][i] = 0.0f;
-        slot->ClickRemoval[c] = 0.0f;
-        slot->PendingClicks[c] = 0.0f;
     }
-    slot->ref = 0;
+    InitRef(&slot->ref, 0);
 
     return AL_NO_ERROR;
 }

+ 1329 - 0
jni/openal-soft-1.16.0/OpenAL32/alBuffer.c

@@ -0,0 +1,1329 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 1999-2007 by authors.
+ * This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the
+ *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ *  Boston, MA  02111-1307, USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <limits.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "alMain.h"
+#include "alu.h"
+#include "alError.h"
+#include "alBuffer.h"
+#include "alThunk.h"
+#include "sample_cvt.h"
+
+
+extern inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id);
+extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id);
+extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type);
+extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type);
+
+static ALboolean IsValidType(ALenum type) DECL_CONST;
+static ALboolean IsValidChannels(ALenum channels) DECL_CONST;
+static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type) DECL_CONST;
+static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) DECL_CONST;
+static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align);
+
+
+AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers)
+{
+    ALCcontext *context;
+    ALsizei cur = 0;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    if(!(n >= 0))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+    for(cur = 0;cur < n;cur++)
+    {
+        ALbuffer *buffer = NewBuffer(context);
+        if(!buffer)
+        {
+            alDeleteBuffers(cur, buffers);
+            break;
+        }
+
+        buffers[cur] = buffer->id;
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *ALBuf;
+    ALsizei i;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    if(!(n >= 0))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+    device = context->Device;
+    for(i = 0;i < n;i++)
+    {
+        if(!buffers[i])
+            continue;
+
+        /* Check for valid Buffer ID */
+        if((ALBuf=LookupBuffer(device, buffers[i])) == NULL)
+            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        if(ReadRef(&ALBuf->ref) != 0)
+            SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
+    }
+
+    for(i = 0;i < n;i++)
+    {
+        if((ALBuf=LookupBuffer(device, buffers[i])) != NULL)
+            DeleteBuffer(device, ALBuf);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer)
+{
+    ALCcontext *context;
+    ALboolean ret;
+
+    context = GetContextRef();
+    if(!context) return AL_FALSE;
+
+    ret = ((!buffer || LookupBuffer(context->Device, buffer)) ?
+           AL_TRUE : AL_FALSE);
+
+    ALCcontext_DecRef(context);
+
+    return ret;
+}
+
+
+AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq)
+{
+    enum UserFmtChannels srcchannels;
+    enum UserFmtType srctype;
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+    ALenum newformat = AL_NONE;
+    ALuint framesize;
+    ALsizei align;
+    ALenum err;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+    if(!(size >= 0 && freq > 0))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+
+    align = albuf->UnpackAlign;
+    if(SanitizeAlignment(srctype, &align) == AL_FALSE)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(srctype)
+    {
+        case UserFmtByte:
+        case UserFmtUByte:
+        case UserFmtShort:
+        case UserFmtUShort:
+        case UserFmtFloat:
+            framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
+            if((size%framesize) != 0)
+                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+            err = LoadData(albuf, freq, format, size/framesize*align,
+                           srcchannels, srctype, data, align, AL_TRUE);
+            if(err != AL_NO_ERROR)
+                SET_ERROR_AND_GOTO(context, err, done);
+            break;
+
+        case UserFmtInt:
+        case UserFmtUInt:
+        case UserFmtByte3:
+        case UserFmtUByte3:
+        case UserFmtDouble:
+            framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
+            if((size%framesize) != 0)
+                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+            switch(srcchannels)
+            {
+                case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break;
+                case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break;
+                case UserFmtRear: newformat = AL_FORMAT_REAR32; break;
+                case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break;
+                case UserFmtX51: newformat = AL_FORMAT_51CHN32; break;
+                case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
+                case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
+            }
+            err = LoadData(albuf, freq, newformat, size/framesize*align,
+                           srcchannels, srctype, data, align, AL_TRUE);
+            if(err != AL_NO_ERROR)
+                SET_ERROR_AND_GOTO(context, err, done);
+            break;
+
+        case UserFmtMulaw:
+        case UserFmtAlaw:
+            framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align;
+            if((size%framesize) != 0)
+                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+            switch(srcchannels)
+            {
+                case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
+                case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
+                case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
+                case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
+                case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
+                case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
+                case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
+            }
+            err = LoadData(albuf, freq, newformat, size/framesize*align,
+                           srcchannels, srctype, data, align, AL_TRUE);
+            if(err != AL_NO_ERROR)
+                SET_ERROR_AND_GOTO(context, err, done);
+            break;
+
+        case UserFmtIMA4:
+            framesize  = (align-1)/2 + 4;
+            framesize *= ChannelsFromUserFmt(srcchannels);
+            if((size%framesize) != 0)
+                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+            switch(srcchannels)
+            {
+                case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
+                case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
+                case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
+                case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
+                case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
+                case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
+                case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
+            }
+            err = LoadData(albuf, freq, newformat, size/framesize*align,
+                           srcchannels, srctype, data, align, AL_TRUE);
+            if(err != AL_NO_ERROR)
+                SET_ERROR_AND_GOTO(context, err, done);
+            break;
+
+        case UserFmtMSADPCM:
+            framesize  = (align-2)/2 + 7;
+            framesize *= ChannelsFromUserFmt(srcchannels);
+            if((size%framesize) != 0)
+                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+            switch(srcchannels)
+            {
+                case UserFmtMono: newformat = AL_FORMAT_MONO16; break;
+                case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break;
+                case UserFmtRear: newformat = AL_FORMAT_REAR16; break;
+                case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break;
+                case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
+                case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
+                case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
+            }
+            err = LoadData(albuf, freq, newformat, size/framesize*align,
+                           srcchannels, srctype, data, align, AL_TRUE);
+            if(err != AL_NO_ERROR)
+                SET_ERROR_AND_GOTO(context, err, done);
+            break;
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length)
+{
+    enum UserFmtChannels srcchannels;
+    enum UserFmtType srctype;
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+    ALuint byte_align;
+    ALuint channels;
+    ALuint bytes;
+    ALsizei align;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+    if(!(length >= 0 && offset >= 0))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+
+    WriteLock(&albuf->lock);
+    align = albuf->UnpackAlign;
+    if(SanitizeAlignment(srctype, &align) == AL_FALSE)
+    {
+        WriteUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    }
+    if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType)
+    {
+        WriteUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+    if(align != albuf->OriginalAlign)
+    {
+        WriteUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+    if(albuf->OriginalType == UserFmtIMA4)
+    {
+        byte_align  = (albuf->OriginalAlign-1)/2 + 4;
+        byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
+    }
+    else if(albuf->OriginalType == UserFmtMSADPCM)
+    {
+        byte_align  = (albuf->OriginalAlign-2)/2 + 7;
+        byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels);
+    }
+    else
+    {
+        byte_align  = albuf->OriginalAlign;
+        byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels,
+                                           albuf->OriginalType);
+    }
+
+    if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset ||
+       (offset%byte_align) != 0 || (length%byte_align) != 0)
+    {
+        WriteUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    }
+
+    channels = ChannelsFromFmt(albuf->FmtChannels);
+    bytes = BytesFromFmt(albuf->FmtType);
+    /* offset -> byte offset, length -> sample count */
+    offset = offset/byte_align * channels*bytes;
+    length = length/byte_align * albuf->OriginalAlign;
+
+    ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
+                data, srctype, channels, length, align);
+    WriteUnlock(&albuf->lock);
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
+  ALuint samplerate, ALenum internalformat, ALsizei samples,
+  ALenum channels, ALenum type, const ALvoid *data)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+    ALsizei align;
+    ALenum err;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+    if(!(samples >= 0 && samplerate != 0))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+
+    align = albuf->UnpackAlign;
+    if(SanitizeAlignment(type, &align) == AL_FALSE)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if((samples%align) != 0)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+
+    err = LoadData(albuf, samplerate, internalformat, samples,
+                   channels, type, data, align, AL_FALSE);
+    if(err != AL_NO_ERROR)
+        SET_ERROR_AND_GOTO(context, err, done);
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
+  ALsizei offset, ALsizei samples,
+  ALenum channels, ALenum type, const ALvoid *data)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+    ALsizei align;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+    if(!(samples >= 0 && offset >= 0))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(IsValidType(type) == AL_FALSE)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+
+    WriteLock(&albuf->lock);
+    align = albuf->UnpackAlign;
+    if(SanitizeAlignment(type, &align) == AL_FALSE)
+    {
+        WriteUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    }
+    if(channels != (ALenum)albuf->FmtChannels)
+    {
+        WriteUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+    if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
+    {
+        WriteUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    }
+    if((samples%align) != 0)
+    {
+        WriteUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    }
+
+    /* offset -> byte offset */
+    offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
+    ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
+                data, type, ChannelsFromFmt(albuf->FmtChannels), samples, align);
+    WriteUnlock(&albuf->lock);
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
+  ALsizei offset, ALsizei samples,
+  ALenum channels, ALenum type, ALvoid *data)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+    ALsizei align;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+    if(!(samples >= 0 && offset >= 0))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(IsValidType(type) == AL_FALSE)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+
+    ReadLock(&albuf->lock);
+    align = albuf->PackAlign;
+    if(SanitizeAlignment(type, &align) == AL_FALSE)
+    {
+        ReadUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    }
+    if(channels != (ALenum)albuf->FmtChannels)
+    {
+        ReadUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+    if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset)
+    {
+        ReadUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    }
+    if((samples%align) != 0)
+    {
+        ReadUnlock(&albuf->lock);
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    }
+
+    /* offset -> byte offset */
+    offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType);
+    ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType,
+                ChannelsFromFmt(albuf->FmtChannels), samples, align);
+    ReadUnlock(&albuf->lock);
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format)
+{
+    enum FmtChannels dstchannels;
+    enum FmtType dsttype;
+    ALCcontext *context;
+    ALboolean ret;
+
+    context = GetContextRef();
+    if(!context) return AL_FALSE;
+
+    ret = DecomposeFormat(format, &dstchannels, &dsttype);
+
+    ALCcontext_DecRef(context);
+
+    return ret;
+}
+
+
+AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value))
+{
+    ALCdevice *device;
+    ALCcontext *context;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if(LookupBuffer(device, buffer) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    switch(param)
+    {
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3))
+{
+    ALCdevice *device;
+    ALCcontext *context;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if(LookupBuffer(device, buffer) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    switch(param)
+    {
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if(LookupBuffer(device, buffer) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    if(!(values))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(param)
+    {
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    switch(param)
+    {
+    case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+        if(!(value >= 0))
+            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+        ExchangeInt(&albuf->UnpackAlign, value);
+        break;
+
+    case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+        if(!(value >= 0))
+            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+        ExchangeInt(&albuf->PackAlign, value);
+        break;
+
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3))
+{
+    ALCdevice *device;
+    ALCcontext *context;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if(LookupBuffer(device, buffer) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    switch(param)
+    {
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+
+    if(values)
+    {
+        switch(param)
+        {
+            case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+            case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+                alBufferi(buffer, param, values[0]);
+                return;
+        }
+    }
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    if(!(values))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(param)
+    {
+    case AL_LOOP_POINTS_SOFT:
+        WriteLock(&albuf->lock);
+        if(ReadRef(&albuf->ref) != 0)
+        {
+            WriteUnlock(&albuf->lock);
+            SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
+        }
+        if(values[0] >= values[1] || values[0] < 0 ||
+           values[1] > albuf->SampleLen)
+        {
+            WriteUnlock(&albuf->lock);
+            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+        }
+
+        albuf->LoopStart = values[0];
+        albuf->LoopEnd = values[1];
+        WriteUnlock(&albuf->lock);
+        break;
+
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    if(!(value))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(param)
+    {
+    case AL_SEC_LENGTH_SOFT:
+        ReadLock(&albuf->lock);
+        if(albuf->SampleLen != 0)
+            *value = albuf->SampleLen / (ALfloat)albuf->Frequency;
+        else
+            *value = 0.0f;
+        ReadUnlock(&albuf->lock);
+        break;
+
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if(LookupBuffer(device, buffer) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    if(!(value1 && value2 && value3))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(param)
+    {
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+
+    switch(param)
+    {
+    case AL_SEC_LENGTH_SOFT:
+        alGetBufferf(buffer, param, values);
+        return;
+    }
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if(LookupBuffer(device, buffer) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    if(!(values))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(param)
+    {
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer *albuf;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    if(!(value))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(param)
+    {
+    case AL_FREQUENCY:
+        *value = albuf->Frequency;
+        break;
+
+    case AL_BITS:
+        *value = BytesFromFmt(albuf->FmtType) * 8;
+        break;
+
+    case AL_CHANNELS:
+        *value = ChannelsFromFmt(albuf->FmtChannels);
+        break;
+
+    case AL_SIZE:
+        ReadLock(&albuf->lock);
+        *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels,
+                                                     albuf->FmtType);
+        ReadUnlock(&albuf->lock);
+        break;
+
+    case AL_INTERNAL_FORMAT_SOFT:
+        *value = albuf->Format;
+        break;
+
+    case AL_BYTE_LENGTH_SOFT:
+        *value = albuf->OriginalSize;
+        break;
+
+    case AL_SAMPLE_LENGTH_SOFT:
+        *value = albuf->SampleLen;
+        break;
+
+    case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+        *value = albuf->UnpackAlign;
+        break;
+
+    case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+        *value = albuf->PackAlign;
+        break;
+
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if(LookupBuffer(device, buffer) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    if(!(value1 && value2 && value3))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(param)
+    {
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values)
+{
+    ALCdevice *device;
+    ALCcontext *context;
+    ALbuffer   *albuf;
+
+    switch(param)
+    {
+    case AL_FREQUENCY:
+    case AL_BITS:
+    case AL_CHANNELS:
+    case AL_SIZE:
+    case AL_INTERNAL_FORMAT_SOFT:
+    case AL_BYTE_LENGTH_SOFT:
+    case AL_SAMPLE_LENGTH_SOFT:
+    case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
+    case AL_PACK_BLOCK_ALIGNMENT_SOFT:
+        alGetBufferi(buffer, param, values);
+        return;
+    }
+
+    context = GetContextRef();
+    if(!context) return;
+
+    device = context->Device;
+    if((albuf=LookupBuffer(device, buffer)) == NULL)
+        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+
+    if(!(values))
+        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    switch(param)
+    {
+    case AL_LOOP_POINTS_SOFT:
+        ReadLock(&albuf->lock);
+        values[0] = albuf->LoopStart;
+        values[1] = albuf->LoopEnd;
+        ReadUnlock(&albuf->lock);
+        break;
+
+    default:
+        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+    }
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+
+/*
+ * LoadData
+ *
+ * Loads the specified data into the buffer, using the specified formats.
+ * Currently, the new format must have the same channel configuration as the
+ * original format.
+ */
+ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc)
+{
+    ALuint NewChannels, NewBytes;
+    enum FmtChannels DstChannels;
+    enum FmtType DstType;
+    ALuint64 newsize;
+    ALvoid *temp;
+
+    if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE ||
+       (long)SrcChannels != (long)DstChannels)
+        return AL_INVALID_ENUM;
+
+    NewChannels = ChannelsFromFmt(DstChannels);
+    NewBytes = BytesFromFmt(DstType);
+
+    newsize = frames;
+    newsize *= NewBytes;
+    newsize *= NewChannels;
+    if(newsize > INT_MAX)
+        return AL_OUT_OF_MEMORY;
+
+    WriteLock(&ALBuf->lock);
+    if(ReadRef(&ALBuf->ref) != 0)
+    {
+        WriteUnlock(&ALBuf->lock);
+        return AL_INVALID_OPERATION;
+    }
+
+    temp = realloc(ALBuf->data, (size_t)newsize);
+    if(!temp && newsize)
+    {
+        WriteUnlock(&ALBuf->lock);
+        return AL_OUT_OF_MEMORY;
+    }
+    ALBuf->data = temp;
+
+    if(data != NULL)
+        ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align);
+
+    if(storesrc)
+    {
+        ALBuf->OriginalChannels = SrcChannels;
+        ALBuf->OriginalType     = SrcType;
+        if(SrcType == UserFmtIMA4)
+        {
+            ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels);
+            ALBuf->OriginalSize  = frames / align * byte_align;
+            ALBuf->OriginalAlign = align;
+        }
+        else if(SrcType == UserFmtMSADPCM)
+        {
+            ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels);
+            ALBuf->OriginalSize  = frames / align * byte_align;
+            ALBuf->OriginalAlign = align;
+        }
+        else
+        {
+            ALBuf->OriginalSize  = frames * FrameSizeFromUserFmt(SrcChannels, SrcType);
+            ALBuf->OriginalAlign = 1;
+        }
+    }
+    else
+    {
+        ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels;
+        ALBuf->OriginalType     = (enum UserFmtType)DstType;
+        ALBuf->OriginalSize     = frames * NewBytes * NewChannels;
+        ALBuf->OriginalAlign    = 1;
+    }
+
+    ALBuf->Frequency = freq;
+    ALBuf->FmtChannels = DstChannels;
+    ALBuf->FmtType = DstType;
+    ALBuf->Format = NewFormat;
+
+    ALBuf->SampleLen = frames;
+    ALBuf->LoopStart = 0;
+    ALBuf->LoopEnd = ALBuf->SampleLen;
+
+    WriteUnlock(&ALBuf->lock);
+    return AL_NO_ERROR;
+}
+
+
+ALuint BytesFromUserFmt(enum UserFmtType type)
+{
+    switch(type)
+    {
+    case UserFmtByte: return sizeof(ALbyte);
+    case UserFmtUByte: return sizeof(ALubyte);
+    case UserFmtShort: return sizeof(ALshort);
+    case UserFmtUShort: return sizeof(ALushort);
+    case UserFmtInt: return sizeof(ALint);
+    case UserFmtUInt: return sizeof(ALuint);
+    case UserFmtFloat: return sizeof(ALfloat);
+    case UserFmtDouble: return sizeof(ALdouble);
+    case UserFmtByte3: return sizeof(ALbyte[3]);
+    case UserFmtUByte3: return sizeof(ALubyte[3]);
+    case UserFmtMulaw: return sizeof(ALubyte);
+    case UserFmtAlaw: return sizeof(ALubyte);
+    case UserFmtIMA4: break; /* not handled here */
+    case UserFmtMSADPCM: break; /* not handled here */
+    }
+    return 0;
+}
+ALuint ChannelsFromUserFmt(enum UserFmtChannels chans)
+{
+    switch(chans)
+    {
+    case UserFmtMono: return 1;
+    case UserFmtStereo: return 2;
+    case UserFmtRear: return 2;
+    case UserFmtQuad: return 4;
+    case UserFmtX51: return 6;
+    case UserFmtX61: return 7;
+    case UserFmtX71: return 8;
+    }
+    return 0;
+}
+static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
+                                     enum UserFmtType *type)
+{
+    static const struct {
+        ALenum format;
+        enum UserFmtChannels channels;
+        enum UserFmtType type;
+    } list[] = {
+        { AL_FORMAT_MONO8,             UserFmtMono, UserFmtUByte   },
+        { AL_FORMAT_MONO16,            UserFmtMono, UserFmtShort   },
+        { AL_FORMAT_MONO_FLOAT32,      UserFmtMono, UserFmtFloat   },
+        { AL_FORMAT_MONO_DOUBLE_EXT,   UserFmtMono, UserFmtDouble  },
+        { AL_FORMAT_MONO_IMA4,         UserFmtMono, UserFmtIMA4    },
+        { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM },
+        { AL_FORMAT_MONO_MULAW,        UserFmtMono, UserFmtMulaw   },
+        { AL_FORMAT_MONO_ALAW_EXT,     UserFmtMono, UserFmtAlaw    },
+
+        { AL_FORMAT_STEREO8,             UserFmtStereo, UserFmtUByte   },
+        { AL_FORMAT_STEREO16,            UserFmtStereo, UserFmtShort   },
+        { AL_FORMAT_STEREO_FLOAT32,      UserFmtStereo, UserFmtFloat   },
+        { AL_FORMAT_STEREO_DOUBLE_EXT,   UserFmtStereo, UserFmtDouble  },
+        { AL_FORMAT_STEREO_IMA4,         UserFmtStereo, UserFmtIMA4    },
+        { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM },
+        { AL_FORMAT_STEREO_MULAW,        UserFmtStereo, UserFmtMulaw   },
+        { AL_FORMAT_STEREO_ALAW_EXT,     UserFmtStereo, UserFmtAlaw    },
+
+        { AL_FORMAT_REAR8,      UserFmtRear, UserFmtUByte },
+        { AL_FORMAT_REAR16,     UserFmtRear, UserFmtShort },
+        { AL_FORMAT_REAR32,     UserFmtRear, UserFmtFloat },
+        { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw },
+
+        { AL_FORMAT_QUAD8_LOKI,  UserFmtQuad, UserFmtUByte },
+        { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort },
+
+        { AL_FORMAT_QUAD8,      UserFmtQuad, UserFmtUByte },
+        { AL_FORMAT_QUAD16,     UserFmtQuad, UserFmtShort },
+        { AL_FORMAT_QUAD32,     UserFmtQuad, UserFmtFloat },
+        { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw },
+
+        { AL_FORMAT_51CHN8,      UserFmtX51, UserFmtUByte },
+        { AL_FORMAT_51CHN16,     UserFmtX51, UserFmtShort },
+        { AL_FORMAT_51CHN32,     UserFmtX51, UserFmtFloat },
+        { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw },
+
+        { AL_FORMAT_61CHN8,      UserFmtX61, UserFmtUByte },
+        { AL_FORMAT_61CHN16,     UserFmtX61, UserFmtShort },
+        { AL_FORMAT_61CHN32,     UserFmtX61, UserFmtFloat },
+        { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw },
+
+        { AL_FORMAT_71CHN8,      UserFmtX71, UserFmtUByte },
+        { AL_FORMAT_71CHN16,     UserFmtX71, UserFmtShort },
+        { AL_FORMAT_71CHN32,     UserFmtX71, UserFmtFloat },
+        { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
+    };
+    ALuint i;
+
+    for(i = 0;i < COUNTOF(list);i++)
+    {
+        if(list[i].format == format)
+        {
+            *chans = list[i].channels;
+            *type  = list[i].type;
+            return AL_TRUE;
+        }
+    }
+
+    return AL_FALSE;
+}
+
+ALuint BytesFromFmt(enum FmtType type)
+{
+    switch(type)
+    {
+    case FmtByte: return sizeof(ALbyte);
+    case FmtShort: return sizeof(ALshort);
+    case FmtFloat: return sizeof(ALfloat);
+    }
+    return 0;
+}
+ALuint ChannelsFromFmt(enum FmtChannels chans)
+{
+    switch(chans)
+    {
+    case FmtMono: return 1;
+    case FmtStereo: return 2;
+    case FmtRear: return 2;
+    case FmtQuad: return 4;
+    case FmtX51: return 6;
+    case FmtX61: return 7;
+    case FmtX71: return 8;
+    }
+    return 0;
+}
+static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type)
+{
+    static const struct {
+        ALenum format;
+        enum FmtChannels channels;
+        enum FmtType type;
+    } list[] = {
+        { AL_MONO8_SOFT,   FmtMono, FmtByte  },
+        { AL_MONO16_SOFT,  FmtMono, FmtShort },
+        { AL_MONO32F_SOFT, FmtMono, FmtFloat },
+
+        { AL_STEREO8_SOFT,   FmtStereo, FmtByte  },
+        { AL_STEREO16_SOFT,  FmtStereo, FmtShort },
+        { AL_STEREO32F_SOFT, FmtStereo, FmtFloat },
+
+        { AL_REAR8_SOFT,   FmtRear, FmtByte  },
+        { AL_REAR16_SOFT,  FmtRear, FmtShort },
+        { AL_REAR32F_SOFT, FmtRear, FmtFloat },
+
+        { AL_FORMAT_QUAD8_LOKI,  FmtQuad, FmtByte  },
+        { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort },
+
+        { AL_QUAD8_SOFT,   FmtQuad, FmtByte  },
+        { AL_QUAD16_SOFT,  FmtQuad, FmtShort },
+        { AL_QUAD32F_SOFT, FmtQuad, FmtFloat },
+
+        { AL_5POINT1_8_SOFT,   FmtX51, FmtByte  },
+        { AL_5POINT1_16_SOFT,  FmtX51, FmtShort },
+        { AL_5POINT1_32F_SOFT, FmtX51, FmtFloat },
+
+        { AL_6POINT1_8_SOFT,   FmtX61, FmtByte  },
+        { AL_6POINT1_16_SOFT,  FmtX61, FmtShort },
+        { AL_6POINT1_32F_SOFT, FmtX61, FmtFloat },
+
+        { AL_7POINT1_8_SOFT,   FmtX71, FmtByte  },
+        { AL_7POINT1_16_SOFT,  FmtX71, FmtShort },
+        { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
+    };
+    ALuint i;
+
+    for(i = 0;i < COUNTOF(list);i++)
+    {
+        if(list[i].format == format)
+        {
+            *chans = list[i].channels;
+            *type  = list[i].type;
+            return AL_TRUE;
+        }
+    }
+
+    return AL_FALSE;
+}
+
+static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align)
+{
+    if(*align < 0)
+        return AL_FALSE;
+
+    if(*align == 0)
+    {
+        if(type == UserFmtIMA4)
+        {
+            /* Here is where things vary:
+             * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel
+             * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel
+             */
+            *align = 65;
+        }
+        else if(type == UserFmtMSADPCM)
+            *align = 64;
+        else
+            *align = 1;
+        return AL_TRUE;
+    }
+
+    if(type == UserFmtIMA4)
+    {
+        /* IMA4 block alignment must be a multiple of 8, plus 1. */
+        return ((*align)&7) == 1;
+    }
+    if(type == UserFmtMSADPCM)
+    {
+        /* MSADPCM block alignment must be a multiple of 2. */
+        /* FIXME: Too strict? Might only require align*channels to be a
+         * multiple of 2. */
+        return ((*align)&1) == 0;
+    }
+
+    return AL_TRUE;
+}
+
+
+static ALboolean IsValidType(ALenum type)
+{
+    switch(type)
+    {
+        case AL_BYTE_SOFT:
+        case AL_UNSIGNED_BYTE_SOFT:
+        case AL_SHORT_SOFT:
+        case AL_UNSIGNED_SHORT_SOFT:
+        case AL_INT_SOFT:
+        case AL_UNSIGNED_INT_SOFT:
+        case AL_FLOAT_SOFT:
+        case AL_DOUBLE_SOFT:
+        case AL_BYTE3_SOFT:
+        case AL_UNSIGNED_BYTE3_SOFT:
+            return AL_TRUE;
+    }
+    return AL_FALSE;
+}
+
+static ALboolean IsValidChannels(ALenum channels)
+{
+    switch(channels)
+    {
+        case AL_MONO_SOFT:
+        case AL_STEREO_SOFT:
+        case AL_REAR_SOFT:
+        case AL_QUAD_SOFT:
+        case AL_5POINT1_SOFT:
+        case AL_6POINT1_SOFT:
+        case AL_7POINT1_SOFT:
+            return AL_TRUE;
+    }
+    return AL_FALSE;
+}
+
+
+ALbuffer *NewBuffer(ALCcontext *context)
+{
+    ALCdevice *device = context->Device;
+    ALbuffer *buffer;
+    ALenum err;
+
+    buffer = calloc(1, sizeof(ALbuffer));
+    if(!buffer)
+        SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
+    RWLockInit(&buffer->lock);
+
+    err = NewThunkEntry(&buffer->id);
+    if(err == AL_NO_ERROR)
+        err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer);
+    if(err != AL_NO_ERROR)
+    {
+        FreeThunkEntry(buffer->id);
+        memset(buffer, 0, sizeof(ALbuffer));
+        free(buffer);
+
+        SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
+    }
+
+    return buffer;
+}
+
+void DeleteBuffer(ALCdevice *device, ALbuffer *buffer)
+{
+    RemoveBuffer(device, buffer->id);
+    FreeThunkEntry(buffer->id);
+
+    free(buffer->data);
+
+    memset(buffer, 0, sizeof(*buffer));
+    free(buffer);
+}
+
+
+/*
+ *    ReleaseALBuffers()
+ *
+ *    INTERNAL: Called to destroy any buffers that still exist on the device
+ */
+ALvoid ReleaseALBuffers(ALCdevice *device)
+{
+    ALsizei i;
+    for(i = 0;i < device->BufferMap.size;i++)
+    {
+        ALbuffer *temp = device->BufferMap.array[i].value;
+        device->BufferMap.array[i].value = NULL;
+
+        free(temp->data);
+
+        FreeThunkEntry(temp->id);
+        memset(temp, 0, sizeof(ALbuffer));
+        free(temp);
+    }
+}

+ 0 - 0
jni/openal-soft-android/OpenAL32/alEffect.c → jni/openal-soft-1.16.0/OpenAL32/alEffect.c


+ 3 - 2
jni/openal-soft-android/OpenAL32/alError.c → jni/openal-soft-1.16.0/OpenAL32/alError.c

@@ -35,6 +35,7 @@ ALboolean TrapALError = AL_FALSE;
 
 ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
 {
+    ALenum curerr = AL_NO_ERROR;
     if(TrapALError)
     {
 #ifdef _WIN32
@@ -45,7 +46,7 @@ ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
         raise(SIGTRAP);
 #endif
     }
-    CompExchangeInt(&Context->LastError, AL_NO_ERROR, errorCode);
+    ATOMIC_COMPARE_EXCHANGE_STRONG(ALenum, &Context->LastError, &curerr, errorCode);
 }
 
 AL_API ALenum AL_APIENTRY alGetError(void)
@@ -68,7 +69,7 @@ AL_API ALenum AL_APIENTRY alGetError(void)
         return AL_INVALID_OPERATION;
     }
 
-    errorCode = ExchangeInt(&Context->LastError, AL_NO_ERROR);
+    errorCode = ATOMIC_EXCHANGE(ALenum, &Context->LastError, AL_NO_ERROR);
 
     ALCcontext_DecRef(Context);
 

+ 2 - 0
jni/openal-soft-android/OpenAL32/alExtension.c → jni/openal-soft-1.16.0/OpenAL32/alExtension.c

@@ -38,7 +38,9 @@
 const struct EffectList EffectList[] = {
     { "eaxreverb",  EAXREVERB,  "AL_EFFECT_EAXREVERB",      AL_EFFECT_EAXREVERB },
     { "reverb",     REVERB,     "AL_EFFECT_REVERB",         AL_EFFECT_REVERB },
+#if 0
     { "autowah",    AUTOWAH,    "AL_EFFECT_AUTOWAH",        AL_EFFECT_AUTOWAH },
+#endif
     { "chorus",     CHORUS,     "AL_EFFECT_CHORUS",         AL_EFFECT_CHORUS },
     { "compressor", COMPRESSOR, "AL_EFFECT_COMPRESSOR",     AL_EFFECT_COMPRESSOR },
     { "distortion", DISTORTION, "AL_EFFECT_DISTORTION",     AL_EFFECT_DISTORTION },

+ 183 - 40
jni/openal-soft-android/OpenAL32/alFilter.c → jni/openal-soft-1.16.0/OpenAL32/alFilter.c

@@ -32,7 +32,6 @@
 extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id);
 extern inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id);
 extern inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample);
-extern inline ALfloat ALfilterState_processSingleC(const ALfilterState *filter, ALfloat sample);
 
 static void InitFilterParams(ALfilter *filter, ALenum type);
 
@@ -146,7 +145,8 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
     {
         if(param == AL_FILTER_TYPE)
         {
-            if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS)
+            if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS ||
+               value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS)
                 InitFilterParams(ALFilter, value);
             else
                 alSetError(Context, AL_INVALID_VALUE);
@@ -336,7 +336,7 @@ void ALfilterState_clear(ALfilterState *filter)
     filter->y[1] = 0.0f;
 }
 
-void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_scale, ALfloat bandwidth)
+void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat bandwidth)
 {
     ALfloat alpha;
     ALfloat w0;
@@ -344,50 +344,28 @@ void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat g
     // Limit gain to -100dB
     gain = maxf(gain, 0.00001f);
 
-    w0 = F_2PI * freq_scale;
+    w0 = F_2PI * freq_mult;
 
     /* Calculate filter coefficients depending on filter type */
     switch(type)
     {
         case ALfilterType_HighShelf:
-            alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f/gain) *
-                                            (1.0f/0.75f - 1.0f) + 2.0f);
-            filter->b[0] = gain * ((gain + 1.0f) +
-                                   (gain - 1.0f) * cosf(w0) +
-                                   2.0f * sqrtf(gain) * alpha);
-            filter->b[1] = -2.0f * gain * ((gain - 1.0f) +
-                                           (gain + 1.0f) * cosf(w0));
-            filter->b[2] = gain * ((gain + 1.0f) +
-                                   (gain - 1.0f) * cosf(w0) -
-                                   2.0f * sqrtf(gain) * alpha);
-            filter->a[0] = (gain + 1.0f) -
-                           (gain - 1.0f) * cosf(w0) +
-                           2.0f * sqrtf(gain) * alpha;
-            filter->a[1] = 2.0f * ((gain - 1.0f) -
-                           (gain + 1.0f) * cosf(w0));
-            filter->a[2] = (gain + 1.0f) -
-                           (gain - 1.0f) * cosf(w0) -
-                           2.0f * sqrtf(gain) * alpha;
+            alpha = sinf(w0)/2.0f*sqrtf((gain + 1.0f/gain)*(1.0f/0.75f - 1.0f) + 2.0f);
+            filter->b[0] =       gain*((gain+1.0f) + (gain-1.0f)*cosf(w0) + 2.0f*sqrtf(gain)*alpha);
+            filter->b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cosf(w0)                         );
+            filter->b[2] =       gain*((gain+1.0f) + (gain-1.0f)*cosf(w0) - 2.0f*sqrtf(gain)*alpha);
+            filter->a[0] =             (gain+1.0f) - (gain-1.0f)*cosf(w0) + 2.0f*sqrtf(gain)*alpha;
+            filter->a[1] =  2.0f*     ((gain-1.0f) - (gain+1.0f)*cosf(w0)                         );
+            filter->a[2] =             (gain+1.0f) - (gain-1.0f)*cosf(w0) - 2.0f*sqrtf(gain)*alpha;
             break;
         case ALfilterType_LowShelf:
-            alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f / gain) *
-                                            (1.0f / 0.75f - 1.0f) + 2.0f);
-            filter->b[0] = gain * ((gain + 1.0f) -
-                                   (gain - 1.0f) * cosf(w0) +
-                                   2.0f * sqrtf(gain) * alpha);
-            filter->b[1] = 2.0f * gain * ((gain - 1.0f) -
-                                          (gain + 1.0f) * cosf(w0));
-            filter->b[2] = gain * ((gain + 1.0f) -
-                                   (gain - 1.0f) * cosf(w0) -
-                                   2.0f * sqrtf(gain) * alpha);
-            filter->a[0] = (gain + 1.0f) +
-                           (gain - 1.0f) * cosf(w0) +
-                           2.0f * sqrtf(gain) * alpha;
-            filter->a[1] = -2.0f * ((gain - 1.0f) +
-                           (gain + 1.0f) * cosf(w0));
-            filter->a[2] = (gain + 1.0f) +
-                           (gain - 1.0f) * cosf(w0) -
-                           2.0f * sqrtf(gain) * alpha;
+            alpha = sinf(w0)/2.0f*sqrtf((gain + 1.0f/gain)*(1.0f/0.75f - 1.0f) + 2.0f);
+            filter->b[0] =       gain*((gain+1.0f) - (gain-1.0f)*cosf(w0) + 2.0f*sqrtf(gain)*alpha);
+            filter->b[1] =  2.0f*gain*((gain-1.0f) - (gain+1.0f)*cosf(w0)                         );
+            filter->b[2] =       gain*((gain+1.0f) - (gain-1.0f)*cosf(w0) - 2.0f*sqrtf(gain)*alpha);
+            filter->a[0] =             (gain+1.0f) + (gain-1.0f)*cosf(w0) + 2.0f*sqrtf(gain)*alpha;
+            filter->a[1] = -2.0f*     ((gain-1.0f) + (gain+1.0f)*cosf(w0)                         );
+            filter->a[2] =             (gain+1.0f) + (gain-1.0f)*cosf(w0) - 2.0f*sqrtf(gain)*alpha;
             break;
         case ALfilterType_Peaking:
             alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
@@ -434,6 +412,8 @@ void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat g
     filter->a[2] /= filter->a[0];
     filter->a[1] /= filter->a[0];
     filter->a[0] /= filter->a[0];
+
+    filter->process = ALfilterState_processC;
 }
 
 
@@ -492,6 +472,126 @@ static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, A
 }
 
 
+static void hp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void hp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void hp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
+{
+    switch(param)
+    {
+        case AL_HIGHPASS_GAIN:
+            if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN))
+                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+            filter->Gain = val;
+            break;
+
+        case AL_HIGHPASS_GAINLF:
+            if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF))
+                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+            filter->GainLF = val;
+            break;
+
+        default:
+            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    }
+}
+static void hp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
+{
+    hp_SetParamf(filter, context, param, vals[0]);
+}
+
+static void hp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void hp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void hp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
+{
+    switch(param)
+    {
+        case AL_HIGHPASS_GAIN:
+            *val = filter->Gain;
+            break;
+
+        case AL_HIGHPASS_GAINLF:
+            *val = filter->GainLF;
+            break;
+
+        default:
+            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    }
+}
+static void hp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
+{
+    hp_GetParamf(filter, context, param, vals);
+}
+
+
+static void bp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void bp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void bp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
+{
+    switch(param)
+    {
+        case AL_BANDPASS_GAIN:
+            if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN))
+                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+            filter->Gain = val;
+            break;
+
+        case AL_BANDPASS_GAINHF:
+            if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF))
+                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+            filter->GainHF = val;
+            break;
+
+        case AL_BANDPASS_GAINLF:
+            if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF))
+                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+            filter->GainLF = val;
+            break;
+
+        default:
+            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    }
+}
+static void bp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
+{
+    bp_SetParamf(filter, context, param, vals[0]);
+}
+
+static void bp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void bp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
+{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+static void bp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
+{
+    switch(param)
+    {
+        case AL_BANDPASS_GAIN:
+            *val = filter->Gain;
+            break;
+
+        case AL_BANDPASS_GAINHF:
+            *val = filter->GainHF;
+            break;
+
+        case AL_BANDPASS_GAINLF:
+            *val = filter->GainLF;
+            break;
+
+        default:
+            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    }
+}
+static void bp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
+{
+    bp_GetParamf(filter, context, param, vals);
+}
+
+
 static void null_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
 static void null_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
@@ -533,6 +633,9 @@ static void InitFilterParams(ALfilter *filter, ALenum type)
     {
         filter->Gain = AL_LOWPASS_DEFAULT_GAIN;
         filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF;
+        filter->HFReference = LOWPASSFREQREF;
+        filter->GainLF = 1.0f;
+        filter->LFReference = HIGHPASSFREQREF;
 
         filter->SetParami  = lp_SetParami;
         filter->SetParamiv = lp_SetParamiv;
@@ -543,8 +646,48 @@ static void InitFilterParams(ALfilter *filter, ALenum type)
         filter->GetParamf  = lp_GetParamf;
         filter->GetParamfv = lp_GetParamfv;
     }
+    else if(type == AL_FILTER_HIGHPASS)
+    {
+        filter->Gain = AL_HIGHPASS_DEFAULT_GAIN;
+        filter->GainHF = 1.0f;
+        filter->HFReference = LOWPASSFREQREF;
+        filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF;
+        filter->LFReference = HIGHPASSFREQREF;
+
+        filter->SetParami  = hp_SetParami;
+        filter->SetParamiv = hp_SetParamiv;
+        filter->SetParamf  = hp_SetParamf;
+        filter->SetParamfv = hp_SetParamfv;
+        filter->GetParami  = hp_GetParami;
+        filter->GetParamiv = hp_GetParamiv;
+        filter->GetParamf  = hp_GetParamf;
+        filter->GetParamfv = hp_GetParamfv;
+    }
+    else if(type == AL_FILTER_BANDPASS)
+    {
+        filter->Gain = AL_BANDPASS_DEFAULT_GAIN;
+        filter->GainHF = AL_BANDPASS_DEFAULT_GAINHF;
+        filter->HFReference = LOWPASSFREQREF;
+        filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF;
+        filter->LFReference = HIGHPASSFREQREF;
+
+        filter->SetParami  = bp_SetParami;
+        filter->SetParamiv = bp_SetParamiv;
+        filter->SetParamf  = bp_SetParamf;
+        filter->SetParamfv = bp_SetParamfv;
+        filter->GetParami  = bp_GetParami;
+        filter->GetParamiv = bp_GetParamiv;
+        filter->GetParamf  = bp_GetParamf;
+        filter->GetParamfv = bp_GetParamfv;
+    }
     else
     {
+        filter->Gain = 1.0f;
+        filter->GainHF = 1.0f;
+        filter->HFReference = LOWPASSFREQREF;
+        filter->GainLF = 1.0f;
+        filter->LFReference = HIGHPASSFREQREF;
+
         filter->SetParami  = null_SetParami;
         filter->SetParamiv = null_SetParamiv;
         filter->SetParamf  = null_SetParamf;

+ 70 - 34
jni/openal-soft-android/OpenAL32/alFontsound.c → jni/openal-soft-1.16.0/OpenAL32/alFontsound.c

@@ -8,6 +8,7 @@
 #include "alMidi.h"
 #include "alError.h"
 #include "alThunk.h"
+#include "alBuffer.h"
 
 #include "midi/base.h"
 
@@ -15,13 +16,21 @@
 extern inline struct ALfontsound *LookupFontsound(ALCdevice *device, ALuint id);
 extern inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id);
 
+
 static void ALfontsound_Construct(ALfontsound *self);
-void ALfontsound_Destruct(ALfontsound *self);
+static void ALfontsound_Destruct(ALfontsound *self);
 void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value);
 static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage);
 void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value);
 static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values);
 
+static inline struct ALsfmodulator *LookupModulator(ALfontsound *sound, ALuint id)
+{
+    ALsfmodulator *mod = LookupUIntMapKey(&sound->ModulatorMap, id>>2);
+    if(mod) mod += id&3;
+    return mod;
+}
+
 
 AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids)
 {
@@ -69,19 +78,14 @@ AL_API ALvoid AL_APIENTRY alDeleteFontsoundsSOFT(ALsizei n, const ALuint *ids)
         /* Check for valid ID */
         if((inst=LookupFontsound(device, ids[i])) == NULL)
             SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-        if(inst->ref != 0)
+        if(ReadRef(&inst->ref) != 0)
             SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
     }
 
     for(i = 0;i < n;i++)
     {
-        if((inst=RemoveFontsound(device, ids[i])) == NULL)
-            continue;
-
-        ALfontsound_Destruct(inst);
-
-        memset(inst, 0, sizeof(*inst));
-        free(inst);
+        if((inst=LookupFontsound(device, ids[i])) != NULL)
+            DeleteFontsound(device, inst);
     }
 
 done:
@@ -115,7 +119,7 @@ AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value)
     device = context->Device;
     if(!(sound=LookupFontsound(device, id)))
         SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(sound->ref != 0)
+    if(ReadRef(&sound->ref) != 0)
         SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
 
     ALfontsound_setPropi(sound, context, param, value);
@@ -136,7 +140,7 @@ AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1,
     device = context->Device;
     if(!(sound=LookupFontsound(device, id)))
         SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(sound->ref != 0)
+    if(ReadRef(&sound->ref) != 0)
         SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
     switch(param)
     {
@@ -231,7 +235,7 @@ AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint *
     device = context->Device;
     if(!(sound=LookupFontsound(device, id)))
         SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(sound->ref != 0)
+    if(ReadRef(&sound->ref) != 0)
         SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
     switch(param)
     {
@@ -257,6 +261,10 @@ AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *val
         SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
     switch(param)
     {
+        case AL_BUFFER:
+            values[0] = (sound->Buffer ? sound->Buffer->id : 0);
+            break;
+
         case AL_MOD_LFO_TO_PITCH_SOFT:
             values[0] = sound->ModLfoToPitch;
             break;
@@ -505,10 +513,22 @@ ALfontsound *NewFontsound(ALCcontext *context)
     return sound;
 }
 
+void DeleteFontsound(ALCdevice *device, ALfontsound *sound)
+{
+    RemoveFontsound(device, sound->id);
+
+    ALfontsound_Destruct(sound);
+
+    memset(sound, 0, sizeof(*sound));
+    free(sound);
+}
+
 
 static void ALfontsound_Construct(ALfontsound *self)
 {
-    self->ref = 0;
+    InitRef(&self->ref, 0);
+
+    self->Buffer = NULL;
 
     self->MinKey = 0;
     self->MaxKey = 127;
@@ -580,13 +600,16 @@ static void ALfontsound_Construct(ALfontsound *self)
     self->id = 0;
 }
 
-void ALfontsound_Destruct(ALfontsound *self)
+static void ALfontsound_Destruct(ALfontsound *self)
 {
     ALsizei i;
 
     FreeThunkEntry(self->id);
     self->id = 0;
 
+    if(self->Buffer)
+        DecrementRef(&self->Buffer->ref);
+    self->Buffer = NULL;
     if(self->Link)
         DecrementRef(&self->Link->ref);
     self->Link = NULL;
@@ -602,9 +625,26 @@ void ALfontsound_Destruct(ALfontsound *self)
 void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value)
 {
     ALfontsound *link;
+    ALbuffer *buffer;
 
     switch(param)
     {
+        case AL_BUFFER:
+            buffer = value ? LookupBuffer(context->Device, value) : NULL;
+            if(value && !buffer)
+                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+            else if(buffer)
+            {
+                /* Buffer must have a non-0 length, and must be mono. */
+                if(buffer->SampleLen <= 0 || buffer->FmtChannels != FmtMono)
+                    SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+            }
+
+            if(buffer) IncrementRef(&buffer->ref);
+            if((buffer=ExchangePtr((XchgPtr*)&self->Buffer, buffer)) != NULL)
+                DecrementRef(&buffer->ref);
+            break;
+
         case AL_MOD_LFO_TO_PITCH_SOFT:
             self->ModLfoToPitch = value;
             break;
@@ -787,17 +827,13 @@ void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param,
             break;
 
         case AL_FONTSOUND_LINK_SOFT:
-            if(!value)
-                link = NULL;
-            else
-            {
-                link = LookupFontsound(context->Device, value);
-                if(!link)
-                    SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            }
+            link = value ? LookupFontsound(context->Device, value) : NULL;
+            if(value && !link)
+                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+
             if(link) IncrementRef(&link->ref);
-            link = ExchangePtr((XchgPtr*)&self->Link, link);
-            if(link) DecrementRef(&link->ref);
+            if((link=ExchangePtr((XchgPtr*)&self->Link, link)) != NULL)
+                DecrementRef(&link->ref);
             break;
 
         default:
@@ -812,15 +848,18 @@ static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage)
     {
         static const ALsfmodulator moddef = {
             { { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT },
-              { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT }
-            },
+              { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT } },
             0,
             AL_LINEAR_SOFT,
             AL_NONE
         };
-        ret = malloc(sizeof(*ret));
-        *ret = moddef;
-        InsertUIntMapEntry(&self->ModulatorMap, stage, ret);
+        ret = malloc(sizeof(ALsfmodulator[4]));
+        ret[0] = moddef;
+        ret[1] = moddef;
+        ret[2] = moddef;
+        ret[3] = moddef;
+        InsertUIntMapEntry(&self->ModulatorMap, stage>>2, ret);
+        ret += stage&3;
     }
     return ret;
 }
@@ -829,7 +868,7 @@ void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei st
 {
     ALint srcidx = 0;
 
-    if(self->ref != 0)
+    if(ReadRef(&self->ref) != 0)
         SET_ERROR_AND_RETURN(context, AL_INVALID_OPERATION);
     switch(param)
     {
@@ -841,10 +880,7 @@ void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei st
                  value == AL_NOTEON_KEY_SOFT || value == AL_KEYPRESSURE_SOFT ||
                  value == AL_CHANNELPRESSURE_SOFT || value == AL_PITCHBEND_SOFT ||
                  value == AL_PITCHBEND_SENSITIVITY_SOFT ||
-                 (value > 0 && value < 120 && !(value == 6 || (value >= 32 && value <= 63) ||
-                                                (value >= 98 && value <= 101))
-                 )
-              ))
+                 IsValidCtrlInput(value)))
                 SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
             ALfontsound_getModStage(self, stage)->Source[srcidx].Input = value;
             break;

+ 5 - 5
jni/openal-soft-android/OpenAL32/alListener.c → jni/openal-soft-1.16.0/OpenAL32/alListener.c

@@ -40,7 +40,7 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
         context->Listener->Gain = value;
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         break;
 
     case AL_METERS_PER_UNIT:
@@ -48,7 +48,7 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
         context->Listener->MetersPerUnit = value;
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         break;
 
     default:
@@ -77,7 +77,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val
         context->Listener->Position[0] = value1;
         context->Listener->Position[1] = value2;
         context->Listener->Position[2] = value3;
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         UnlockContext(context);
         break;
 
@@ -89,7 +89,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val
         context->Listener->Velocity[0] = value1;
         context->Listener->Velocity[1] = value2;
         context->Listener->Velocity[2] = value3;
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         UnlockContext(context);
         break;
 
@@ -142,7 +142,7 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
         context->Listener->Up[0] = values[3];
         context->Listener->Up[1] = values[4];
         context->Listener->Up[2] = values[5];
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         UnlockContext(context);
         break;
 

+ 7 - 11
jni/openal-soft-android/OpenAL32/alMidi.c → jni/openal-soft-1.16.0/OpenAL32/alMidi.c

@@ -19,7 +19,9 @@
 
 MidiSynth *SynthCreate(ALCdevice *device)
 {
-    MidiSynth *synth = FSynth_create(device);
+    MidiSynth *synth = NULL;
+    if(!synth) synth = SSynth_create(device);
+    if(!synth) synth = FSynth_create(device);
     if(!synth) synth = DSynth_create(device);
     return synth;
 }
@@ -99,18 +101,12 @@ AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, A
     ALCdevice *device;
     ALCcontext *context;
     ALenum err;
-    ALsizei i;
 
     context = GetContextRef();
     if(!context) return;
 
     if(!data || size < 0)
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    for(i = 0;i < size;i++)
-    {
-        if((data[i]&0x80))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    }
 
     device = context->Device;
     ALCdevice_Lock(device);
@@ -133,7 +129,7 @@ AL_API void AL_APIENTRY alMidiPlaySOFT(void)
 
     synth = context->Device->Synth;
     WriteLock(&synth->Lock);
-    V(synth,setState)(AL_PLAYING);
+    MidiSynth_setState(synth, AL_PLAYING);
     WriteUnlock(&synth->Lock);
 
     ALCcontext_DecRef(context);
@@ -149,7 +145,7 @@ AL_API void AL_APIENTRY alMidiPauseSOFT(void)
 
     synth = context->Device->Synth;
     WriteLock(&synth->Lock);
-    V(synth,setState)(AL_PAUSED);
+    MidiSynth_setState(synth, AL_PAUSED);
     WriteUnlock(&synth->Lock);
 
     ALCcontext_DecRef(context);
@@ -168,7 +164,7 @@ AL_API void AL_APIENTRY alMidiStopSOFT(void)
     synth = device->Synth;
 
     WriteLock(&synth->Lock);
-    V(synth,setState)(AL_STOPPED);
+    MidiSynth_setState(synth, AL_STOPPED);
 
     ALCdevice_Lock(device);
     V0(synth,stop)();
@@ -191,7 +187,7 @@ AL_API void AL_APIENTRY alMidiResetSOFT(void)
     synth = device->Synth;
 
     WriteLock(&synth->Lock);
-    V(synth,setState)(AL_INITIAL);
+    MidiSynth_setState(synth, AL_INITIAL);
 
     ALCdevice_Lock(device);
     V0(synth,reset)();

+ 10 - 11
jni/openal-soft-android/OpenAL32/alPreset.c → jni/openal-soft-1.16.0/OpenAL32/alPreset.c

@@ -16,7 +16,7 @@ extern inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id);
 extern inline struct ALsfpreset *RemovePreset(ALCdevice *device, ALuint id);
 
 static void ALsfpreset_Construct(ALsfpreset *self);
-void ALsfpreset_Destruct(ALsfpreset *self);
+static void ALsfpreset_Destruct(ALsfpreset *self);
 
 
 AL_API void AL_APIENTRY alGenPresetsSOFT(ALsizei n, ALuint *ids)
@@ -65,15 +65,14 @@ AL_API ALvoid AL_APIENTRY alDeletePresetsSOFT(ALsizei n, const ALuint *ids)
         /* Check for valid ID */
         if((preset=LookupPreset(device, ids[i])) == NULL)
             SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-        if(preset->ref != 0)
+        if(ReadRef(&preset->ref) != 0)
             SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
     }
 
     for(i = 0;i < n;i++)
     {
-        if((preset=LookupPreset(device, ids[i])) == NULL)
-            continue;
-        DeletePreset(preset, device);
+        if((preset=LookupPreset(device, ids[i])) != NULL)
+            DeletePreset(device, preset);
     }
 
 done:
@@ -107,7 +106,7 @@ AL_API void AL_APIENTRY alPresetiSOFT(ALuint id, ALenum param, ALint value)
     device = context->Device;
     if((preset=LookupPreset(device, id)) == NULL)
         SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(preset->ref != 0)
+    if(ReadRef(&preset->ref) != 0)
         SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
     switch(param)
     {
@@ -151,7 +150,7 @@ AL_API void AL_APIENTRY alPresetivSOFT(ALuint id, ALenum param, const ALint *val
     device = context->Device;
     if((preset=LookupPreset(device, id)) == NULL)
         SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(preset->ref != 0)
+    if(ReadRef(&preset->ref) != 0)
         SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
     switch(param)
     {
@@ -220,7 +219,7 @@ AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const A
     if(count < 0)
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
-    if(preset->ref != 0)
+    if(ReadRef(&preset->ref) != 0)
         SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
 
     if(count == 0)
@@ -282,7 +281,7 @@ ALsfpreset *NewPreset(ALCcontext *context)
     return preset;
 }
 
-void DeletePreset(ALsfpreset *preset, ALCdevice *device)
+void DeletePreset(ALCdevice *device, ALsfpreset *preset)
 {
     RemovePreset(device, preset->id);
 
@@ -294,7 +293,7 @@ void DeletePreset(ALsfpreset *preset, ALCdevice *device)
 
 static void ALsfpreset_Construct(ALsfpreset *self)
 {
-    self->ref = 0;
+    InitRef(&self->ref, 0);
 
     self->Preset = 0;
     self->Bank = 0;
@@ -305,7 +304,7 @@ static void ALsfpreset_Construct(ALsfpreset *self)
     self->id = 0;
 }
 
-void ALsfpreset_Destruct(ALsfpreset *self)
+static void ALsfpreset_Destruct(ALsfpreset *self)
 {
     ALsizei i;
 

+ 62 - 171
jni/openal-soft-android/OpenAL32/alSoundfont.c → jni/openal-soft-1.16.0/OpenAL32/alSoundfont.c

@@ -4,11 +4,13 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "alMain.h"
 #include "alMidi.h"
 #include "alThunk.h"
 #include "alError.h"
+#include <alBuffer.h>
 
 #include "midi/base.h"
 
@@ -16,8 +18,8 @@
 extern inline struct ALsoundfont *LookupSfont(ALCdevice *device, ALuint id);
 extern inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id);
 
-void ALsoundfont_Construct(ALsoundfont *self);
-void ALsoundfont_Destruct(ALsoundfont *self);
+static void ALsoundfont_Construct(ALsoundfont *self);
+static void ALsoundfont_Destruct(ALsoundfont *self);
 void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device);
 ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context);
 static size_t ALsoundfont_read(ALvoid *buf, size_t bytes, ALvoid *ptr);
@@ -91,7 +93,7 @@ AL_API ALvoid AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids)
         }
         else if((sfont=LookupSfont(device, ids[i])) == NULL)
             SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-        if(sfont->Mapped != AL_FALSE || sfont->ref != 0)
+        if(ReadRef(&sfont->ref) != 0)
             SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
     }
 
@@ -136,137 +138,6 @@ AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(ALuint id)
     return ret;
 }
 
-AL_API ALvoid AL_APIENTRY alSoundfontSamplesSOFT(ALuint id, ALenum type, ALsizei count, const ALvoid *samples)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsoundfont *sfont;
-    void *ptr;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(id == 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    if(!(sfont=LookupSfont(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(type != AL_SHORT_SOFT)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    if(count <= 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    WriteLock(&sfont->Lock);
-    if(sfont->ref != 0)
-        alSetError(context, AL_INVALID_OPERATION);
-    else if(sfont->Mapped)
-        alSetError(context, AL_INVALID_OPERATION);
-    else if(!(ptr=realloc(sfont->Samples, count * sizeof(ALshort))))
-        alSetError(context, AL_OUT_OF_MEMORY);
-    else
-    {
-        sfont->Samples = ptr;
-        sfont->NumSamples = count;
-        if(samples != NULL)
-            memcpy(sfont->Samples, samples, count * sizeof(ALshort));
-    }
-    WriteUnlock(&sfont->Lock);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alGetSoundfontSamplesSOFT(ALuint id, ALsizei offset, ALsizei count, ALenum type, ALvoid *samples)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsoundfont *sfont;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(id == 0)
-        sfont = ALsoundfont_getDefSoundfont(context);
-    else if(!(sfont=LookupSfont(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(type != AL_SHORT_SOFT)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    if(offset < 0 || count <= 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    ReadLock(&sfont->Lock);
-    if(offset >= sfont->NumSamples || count > (sfont->NumSamples-offset))
-        alSetError(context, AL_INVALID_VALUE);
-    else if(sfont->Mapped)
-        alSetError(context, AL_INVALID_OPERATION);
-    else
-    {
-        /* TODO: Allow conversion. */
-        memcpy(samples, sfont->Samples + offset*sizeof(ALshort), count * sizeof(ALshort));
-    }
-    ReadUnlock(&sfont->Lock);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALvoid* AL_APIENTRY alSoundfontMapSamplesSOFT(ALuint id, ALsizei offset, ALsizei length)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsoundfont *sfont;
-    ALvoid *ptr = NULL;
-
-    context = GetContextRef();
-    if(!context) return NULL;
-
-    device = context->Device;
-    if(id == 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    if(!(sfont=LookupSfont(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(offset < 0 || (ALuint)offset > sfont->NumSamples*sizeof(ALshort))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    if(length <= 0 || (ALuint)length > (sfont->NumSamples*sizeof(ALshort) - offset))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    ReadLock(&sfont->Lock);
-    if(sfont->ref != 0)
-        alSetError(context, AL_INVALID_OPERATION);
-    else if(ExchangeInt(&sfont->Mapped, AL_TRUE) == AL_TRUE)
-        alSetError(context, AL_INVALID_OPERATION);
-    else
-        ptr = (ALbyte*)sfont->Samples + offset;
-    ReadUnlock(&sfont->Lock);
-
-done:
-    ALCcontext_DecRef(context);
-
-    return ptr;
-}
-
-AL_API ALvoid AL_APIENTRY alSoundfontUnmapSamplesSOFT(ALuint id)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsoundfont *sfont;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(id == 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    if(!(sfont=LookupSfont(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(ExchangeInt(&sfont->Mapped, AL_FALSE) == AL_FALSE)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
 AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *values)
 {
     ALCdevice *device;
@@ -293,14 +164,6 @@ AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *val
                 values[i] = sfont->Presets[i]->id;
             break;
 
-        case AL_SAMPLE_LENGTH_SOFT:
-            values[0] = sfont->NumSamples;
-            break;
-
-        case AL_FORMAT_TYPE_SOFT:
-            values[0] = AL_SHORT_SOFT;
-            break;
-
         default:
             SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
     }
@@ -329,7 +192,7 @@ AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const A
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
     WriteLock(&sfont->Lock);
-    if(sfont->ref != 0)
+    if(ReadRef(&sfont->ref) != 0)
     {
         WriteUnlock(&sfont->Lock);
         SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
@@ -350,6 +213,7 @@ AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const A
         {
             if(!(presets[i]=LookupPreset(device, pids[i])))
             {
+                free(presets);
                 WriteUnlock(&sfont->Lock);
                 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
             }
@@ -389,12 +253,7 @@ AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_
         SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
 
     WriteLock(&sfont->Lock);
-    if(sfont->ref != 0)
-    {
-        WriteUnlock(&sfont->Lock);
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    }
-    if(sfont->Mapped)
+    if(ReadRef(&sfont->ref) != 0)
     {
         WriteUnlock(&sfont->Lock);
         SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
@@ -416,23 +275,19 @@ done:
 }
 
 
-void ALsoundfont_Construct(ALsoundfont *self)
+static void ALsoundfont_Construct(ALsoundfont *self)
 {
-    self->ref = 0;
+    InitRef(&self->ref, 0);
 
     self->Presets = NULL;
     self->NumPresets = 0;
 
-    self->Samples = NULL;
-    self->NumSamples = 0;
-
     RWLockInit(&self->Lock);
-    self->Mapped = AL_FALSE;
 
     self->id = 0;
 }
 
-void ALsoundfont_Destruct(ALsoundfont *self)
+static void ALsoundfont_Destruct(ALsoundfont *self)
 {
     ALsizei i;
 
@@ -447,16 +302,13 @@ void ALsoundfont_Destruct(ALsoundfont *self)
     free(self->Presets);
     self->Presets = NULL;
     self->NumPresets = 0;
-
-    free(self->Samples);
-    self->Samples = NULL;
-    self->NumSamples = 0;
 }
 
 ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context)
 {
     ALCdevice *device = context->Device;
-    const char *fname;
+    al_string fname = AL_STRING_INIT_STATIC();
+    const char *namelist;
 
     if(device->DefaultSfont)
         return device->DefaultSfont;
@@ -464,25 +316,44 @@ ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context)
     device->DefaultSfont = calloc(1, sizeof(device->DefaultSfont[0]));
     ALsoundfont_Construct(device->DefaultSfont);
 
-    fname = getenv("ALSOFT_SOUNDFONT");
-    if((fname && fname[0]) || ConfigValueStr("midi", "soundfont", &fname))
+    namelist = getenv("ALSOFT_SOUNDFONT");
+    if(!namelist || !namelist[0])
+        ConfigValueStr("midi", "soundfont", &namelist);
+    while(namelist && namelist[0])
     {
+        const char *next, *end;
         FILE *f;
 
-        f = fopen(fname, "rb");
+        while(*namelist && (isspace(*namelist) || *namelist == ','))
+            namelist++;
+        if(!*namelist)
+            break;
+        next = strchr(namelist, ',');
+        end = next ? next++ : (namelist+strlen(namelist));
+        while(--end != namelist && isspace(*end)) {
+        }
+        if(end == namelist)
+            continue;
+        al_string_append_range(&fname, namelist, end+1);
+        namelist = next;
+
+        f = OpenDataFile(al_string_get_cstr(fname), "openal/soundfonts");
         if(f == NULL)
-            ERR("Failed to open %s\n", fname);
+            ERR("Failed to open %s\n", al_string_get_cstr(fname));
         else
         {
             Reader reader;
             reader.cb = ALsoundfont_read;
             reader.ptr = f;
             reader.error = 0;
-            TRACE("Loading %s\n", fname);
+            TRACE("Loading %s\n", al_string_get_cstr(fname));
             loadSf2(&reader, device->DefaultSfont, context);
             fclose(f);
         }
+
+        al_string_clear(&fname);
     }
+    AL_STRING_DEINIT(fname);
 
     return device->DefaultSfont;
 }
@@ -491,8 +362,10 @@ void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device)
 {
     ALsfpreset **presets;
     ALsizei num_presets;
+    VECTOR(ALbuffer*) buffers;
     ALsizei i;
 
+    VECTOR_INIT(buffers);
     presets = ExchangePtr((XchgPtr*)&self->Presets, NULL);
     num_presets = ExchangeInt(&self->NumPresets, 0);
 
@@ -506,7 +379,8 @@ void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device)
 
         sounds = ExchangePtr((XchgPtr*)&preset->Sounds, NULL);
         num_sounds = ExchangeInt(&preset->NumSounds, 0);
-        DeletePreset(preset, device);
+
+        DeletePreset(device, preset);
         preset = NULL;
 
         for(j = 0;j < num_sounds;j++)
@@ -519,12 +393,21 @@ void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device)
             deleting = AL_FALSE;
             for(j = 0;j < num_sounds;j++)
             {
-                if(sounds[j] && sounds[j]->ref == 0)
+                if(sounds[j] && ReadRef(&sounds[j]->ref) == 0)
                 {
                     deleting = AL_TRUE;
-                    RemoveFontsound(device, sounds[j]->id);
-                    ALfontsound_Destruct(sounds[j]);
-                    free(sounds[j]);
+                    if(sounds[j]->Buffer)
+                    {
+                        ALbuffer *buffer = sounds[j]->Buffer;
+                        ALbuffer **iter;
+
+#define MATCH_BUFFER(_i) (buffer == *(_i))
+                        VECTOR_FIND_IF(iter, ALbuffer*, buffers, MATCH_BUFFER);
+                        if(iter == VECTOR_ITER_END(buffers))
+                            VECTOR_PUSH_BACK(buffers, buffer);
+#undef MATCH_BUFFER
+                    }
+                    DeleteFontsound(device, sounds[j]);
                     sounds[j] = NULL;
                 }
             }
@@ -534,6 +417,14 @@ void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device)
 
     ALsoundfont_Destruct(self);
     free(self);
+
+#define DELETE_BUFFER(iter) do {           \
+    assert(ReadRef(&(*(iter))->ref) == 0); \
+    DeleteBuffer(device, *(iter));         \
+} while(0)
+    VECTOR_FOR_EACH(ALbuffer*, buffers, DELETE_BUFFER);
+    VECTOR_DEINIT(buffers);
+#undef DELETE_BUFFER
 }
 
 

File diff suppressed because it is too large
+ 321 - 155
jni/openal-soft-1.16.0/OpenAL32/alSource.c


+ 24 - 16
jni/openal-soft-android/OpenAL32/alState.c → jni/openal-soft-1.16.0/OpenAL32/alState.c

@@ -56,7 +56,7 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
     {
     case AL_SOURCE_DISTANCE_MODEL:
         context->SourceDistanceModel = AL_TRUE;
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         break;
 
     default:
@@ -78,7 +78,7 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
     {
     case AL_SOURCE_DISTANCE_MODEL:
         context->SourceDistanceModel = AL_FALSE;
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         break;
 
     default:
@@ -643,7 +643,7 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
     context->DopplerFactor = value;
-    context->UpdateSources = AL_TRUE;
+    ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
 
 done:
     ALCcontext_DecRef(context);
@@ -660,7 +660,7 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
     context->DopplerVelocity = value;
-    context->UpdateSources = AL_TRUE;
+    ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
 
 done:
     ALCcontext_DecRef(context);
@@ -677,7 +677,7 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
     context->SpeedOfSound = value;
-    context->UpdateSources = AL_TRUE;
+    ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
 
 done:
     ALCcontext_DecRef(context);
@@ -698,7 +698,7 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
 
     context->DistanceModel = value;
     if(!context->SourceDistanceModel)
-        context->UpdateSources = AL_TRUE;
+        ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
 
 done:
     ALCcontext_DecRef(context);
@@ -715,7 +715,7 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
     if(!context->DeferUpdates)
     {
         ALboolean UpdateSources;
-        ALsource **src, **src_end;
+        ALactivesource **src, **src_end;
         ALeffectslot **slot, **slot_end;
         FPUCtl oldMode;
 
@@ -725,30 +725,34 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
         context->DeferUpdates = AL_TRUE;
 
         /* Make sure all pending updates are performed */
-        UpdateSources = ExchangeInt(&context->UpdateSources, AL_FALSE);
+        UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE);
 
         src = context->ActiveSources;
         src_end = src + context->ActiveSourceCount;
         while(src != src_end)
         {
-            if((*src)->state != AL_PLAYING)
+            ALsource *source = (*src)->Source;
+
+            if(source->state != AL_PLAYING && source->state != AL_PAUSED)
             {
-                context->ActiveSourceCount--;
-                *src = *(--src_end);
+                ALactivesource *temp = *(--src_end);
+                *src_end = *src;
+                *src = temp;
+                --(context->ActiveSourceCount);
                 continue;
             }
 
-            if(ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) || UpdateSources)
-                ALsource_Update(*src, context);
+            if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)
+                (*src)->Update(*src, context);
 
             src++;
         }
 
-        slot = context->ActiveEffectSlots;
-        slot_end = slot + context->ActiveEffectSlotCount;
+        slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots);
+        slot_end = VECTOR_ITER_END(context->ActiveAuxSlots);
         while(slot != slot_end)
         {
-            if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE))
+            if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
                 V((*slot)->EffectState,update)(context->Device, *slot);
             slot++;
         }
@@ -780,7 +784,11 @@ AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
 
             if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
                Source->Offset >= 0.0)
+            {
+                ReadLock(&Source->queue_lock);
                 ApplyOffset(Source);
+                ReadUnlock(&Source->queue_lock);
+            }
 
             new_state = ExchangeInt(&Source->new_state, AL_NONE);
             if(new_state)

+ 0 - 0
jni/openal-soft-android/OpenAL32/alThunk.c → jni/openal-soft-1.16.0/OpenAL32/alThunk.c


+ 1269 - 0
jni/openal-soft-1.16.0/OpenAL32/sample_cvt.c

@@ -0,0 +1,1269 @@
+
+#include "config.h"
+
+#include "sample_cvt.h"
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "AL/al.h"
+#include "alu.h"
+#include "alBuffer.h"
+
+
+/* IMA ADPCM Stepsize table */
+static const int IMAStep_size[89] = {
+       7,    8,    9,   10,   11,   12,   13,   14,   16,   17,   19,
+      21,   23,   25,   28,   31,   34,   37,   41,   45,   50,   55,
+      60,   66,   73,   80,   88,   97,  107,  118,  130,  143,  157,
+     173,  190,  209,  230,  253,  279,  307,  337,  371,  408,  449,
+     494,  544,  598,  658,  724,  796,  876,  963, 1060, 1166, 1282,
+    1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660,
+    4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442,
+   11487,12635,13899,15289,16818,18500,20350,22358,24633,27086,29794,
+   32767
+};
+
+/* IMA4 ADPCM Codeword decode table */
+static const int IMA4Codeword[16] = {
+    1, 3, 5, 7, 9, 11, 13, 15,
+   -1,-3,-5,-7,-9,-11,-13,-15,
+};
+
+/* IMA4 ADPCM Step index adjust decode table */
+static const int IMA4Index_adjust[16] = {
+   -1,-1,-1,-1, 2, 4, 6, 8,
+   -1,-1,-1,-1, 2, 4, 6, 8
+};
+
+
+/* MSADPCM Adaption table */
+static const int MSADPCMAdaption[16] = {
+    230, 230, 230, 230, 307, 409, 512, 614,
+    768, 614, 512, 409, 307, 230, 230, 230
+};
+
+/* MSADPCM Adaption Coefficient tables */
+static const int MSADPCMAdaptionCoeff[7][2] = {
+    { 256,    0 },
+    { 512, -256 },
+    {   0,    0 },
+    { 192,   64 },
+    { 240,    0 },
+    { 460, -208 },
+    { 392, -232 }
+};
+
+
+/* A quick'n'dirty lookup table to decode a muLaw-encoded byte sample into a
+ * signed 16-bit sample */
+static const ALshort muLawDecompressionTable[256] = {
+    -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
+    -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
+    -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
+    -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316,
+     -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
+     -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
+     -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
+     -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
+     -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
+     -1372, -1308, -1244, -1180, -1116, -1052,  -988,  -924,
+      -876,  -844,  -812,  -780,  -748,  -716,  -684,  -652,
+      -620,  -588,  -556,  -524,  -492,  -460,  -428,  -396,
+      -372,  -356,  -340,  -324,  -308,  -292,  -276,  -260,
+      -244,  -228,  -212,  -196,  -180,  -164,  -148,  -132,
+      -120,  -112,  -104,   -96,   -88,   -80,   -72,   -64,
+       -56,   -48,   -40,   -32,   -24,   -16,    -8,     0,
+     32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
+     23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
+     15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
+     11900, 11388, 10876, 10364,  9852,  9340,  8828,  8316,
+      7932,  7676,  7420,  7164,  6908,  6652,  6396,  6140,
+      5884,  5628,  5372,  5116,  4860,  4604,  4348,  4092,
+      3900,  3772,  3644,  3516,  3388,  3260,  3132,  3004,
+      2876,  2748,  2620,  2492,  2364,  2236,  2108,  1980,
+      1884,  1820,  1756,  1692,  1628,  1564,  1500,  1436,
+      1372,  1308,  1244,  1180,  1116,  1052,   988,   924,
+       876,   844,   812,   780,   748,   716,   684,   652,
+       620,   588,   556,   524,   492,   460,   428,   396,
+       372,   356,   340,   324,   308,   292,   276,   260,
+       244,   228,   212,   196,   180,   164,   148,   132,
+       120,   112,   104,    96,    88,    80,    72,    64,
+        56,    48,    40,    32,    24,    16,     8,     0
+};
+
+/* Values used when encoding a muLaw sample */
+static const int muLawBias = 0x84;
+static const int muLawClip = 32635;
+static const char muLawCompressTable[256] = {
+     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+
+
+/* A quick'n'dirty lookup table to decode an aLaw-encoded byte sample into a
+ * signed 16-bit sample */
+static const ALshort aLawDecompressionTable[256] = {
+     -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
+     -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
+     -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
+     -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
+    -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944,
+    -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136,
+    -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472,
+    -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568,
+      -344,  -328,  -376,  -360,  -280,  -264,  -312,  -296,
+      -472,  -456,  -504,  -488,  -408,  -392,  -440,  -424,
+       -88,   -72,  -120,  -104,   -24,    -8,   -56,   -40,
+      -216,  -200,  -248,  -232,  -152,  -136,  -184,  -168,
+     -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
+     -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
+      -688,  -656,  -752,  -720,  -560,  -528,  -624,  -592,
+      -944,  -912, -1008,  -976,  -816,  -784,  -880,  -848,
+      5504,  5248,  6016,  5760,  4480,  4224,  4992,  4736,
+      7552,  7296,  8064,  7808,  6528,  6272,  7040,  6784,
+      2752,  2624,  3008,  2880,  2240,  2112,  2496,  2368,
+      3776,  3648,  4032,  3904,  3264,  3136,  3520,  3392,
+     22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
+     30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
+     11008, 10496, 12032, 11520,  8960,  8448,  9984,  9472,
+     15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
+       344,   328,   376,   360,   280,   264,   312,   296,
+       472,   456,   504,   488,   408,   392,   440,   424,
+        88,    72,   120,   104,    24,     8,    56,    40,
+       216,   200,   248,   232,   152,   136,   184,   168,
+      1376,  1312,  1504,  1440,  1120,  1056,  1248,  1184,
+      1888,  1824,  2016,  1952,  1632,  1568,  1760,  1696,
+       688,   656,   752,   720,   560,   528,   624,   592,
+       944,   912,  1008,   976,   816,   784,   880,   848
+};
+
+/* Values used when encoding an aLaw sample */
+static const int aLawClip = 32635;
+static const char aLawCompressTable[128] = {
+    1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,
+    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+
+
+typedef ALubyte ALmulaw;
+typedef ALubyte ALalaw;
+typedef ALubyte ALima4;
+typedef ALubyte ALmsadpcm;
+typedef struct {
+    ALbyte b[3];
+} ALbyte3;
+static_assert(sizeof(ALbyte3)==sizeof(ALbyte[3]), "ALbyte3 size is not 3");
+typedef struct {
+    ALubyte b[3];
+} ALubyte3;
+static_assert(sizeof(ALubyte3)==sizeof(ALubyte[3]), "ALubyte3 size is not 3");
+
+static inline ALshort DecodeMuLaw(ALmulaw val)
+{ return muLawDecompressionTable[val]; }
+
+static ALmulaw EncodeMuLaw(ALshort val)
+{
+    ALint mant, exp, sign;
+
+    sign = (val>>8) & 0x80;
+    if(sign)
+    {
+        /* -32768 doesn't properly negate on a short; it results in itself.
+         * So clamp to -32767 */
+        val = maxi(val, -32767);
+        val = -val;
+    }
+
+    val = mini(val, muLawClip);
+    val += muLawBias;
+
+    exp = muLawCompressTable[(val>>7) & 0xff];
+    mant = (val >> (exp+3)) & 0x0f;
+
+    return ~(sign | (exp<<4) | mant);
+}
+
+static inline ALshort DecodeALaw(ALalaw val)
+{ return aLawDecompressionTable[val]; }
+
+static ALalaw EncodeALaw(ALshort val)
+{
+    ALint mant, exp, sign;
+
+    sign = ((~val) >> 8) & 0x80;
+    if(!sign)
+    {
+        val = maxi(val, -32767);
+        val = -val;
+    }
+    val = mini(val, aLawClip);
+
+    if(val >= 256)
+    {
+        exp = aLawCompressTable[(val>>8) & 0x7f];
+        mant = (val >> (exp+3)) & 0x0f;
+    }
+    else
+    {
+        exp = 0;
+        mant = val >> 4;
+    }
+
+    return ((exp<<4) | mant) ^ (sign^0x55);
+}
+
+static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans, ALsizei align)
+{
+    ALint sample[MAX_INPUT_CHANNELS], index[MAX_INPUT_CHANNELS];
+    ALuint code[MAX_INPUT_CHANNELS];
+    ALsizei j,k,c;
+
+    for(c = 0;c < numchans;c++)
+    {
+        sample[c]  = *(src++);
+        sample[c] |= *(src++) << 8;
+        sample[c]  = (sample[c]^0x8000) - 32768;
+        index[c]  = *(src++);
+        index[c] |= *(src++) << 8;
+        index[c]  = (index[c]^0x8000) - 32768;
+
+        index[c] = clampi(index[c], 0, 88);
+
+        dst[c] = sample[c];
+    }
+
+    for(j = 1;j < align;j += 8)
+    {
+        for(c = 0;c < numchans;c++)
+        {
+            code[c]  = *(src++);
+            code[c] |= *(src++) << 8;
+            code[c] |= *(src++) << 16;
+            code[c] |= *(src++) << 24;
+        }
+
+        for(k = 0;k < 8;k++)
+        {
+            for(c = 0;c < numchans;c++)
+            {
+                int nibble = code[c]&0xf;
+                code[c] >>= 4;
+
+                sample[c] += IMA4Codeword[nibble] * IMAStep_size[index[c]] / 8;
+                sample[c] = clampi(sample[c], -32768, 32767);
+
+                index[c] += IMA4Index_adjust[nibble];
+                index[c] = clampi(index[c], 0, 88);
+
+                dst[(j+k)*numchans + c] = sample[c];
+            }
+        }
+    }
+}
+
+static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALint *index, ALint numchans, ALsizei align)
+{
+    ALsizei j,k,c;
+
+    for(c = 0;c < numchans;c++)
+    {
+        int diff = src[c] - sample[c];
+        int step = IMAStep_size[index[c]];
+        int nibble;
+
+        nibble = 0;
+        if(diff < 0)
+        {
+            nibble = 0x8;
+            diff = -diff;
+        }
+
+        diff = mini(step*2, diff);
+        nibble |= (diff*8/step - 1) / 2;
+
+        sample[c] += IMA4Codeword[nibble] * step / 8;
+        sample[c] = clampi(sample[c], -32768, 32767);
+
+        index[c] += IMA4Index_adjust[nibble];
+        index[c] = clampi(index[c], 0, 88);
+
+        *(dst++) = sample[c] & 0xff;
+        *(dst++) = (sample[c]>>8) & 0xff;
+        *(dst++) = index[c] & 0xff;
+        *(dst++) = (index[c]>>8) & 0xff;
+    }
+
+    for(j = 1;j < align;j += 8)
+    {
+        for(c = 0;c < numchans;c++)
+        {
+            for(k = 0;k < 8;k++)
+            {
+                int diff = src[(j+k)*numchans + c] - sample[c];
+                int step = IMAStep_size[index[c]];
+                int nibble;
+
+                nibble = 0;
+                if(diff < 0)
+                {
+                    nibble = 0x8;
+                    diff = -diff;
+                }
+
+                diff = mini(step*2, diff);
+                nibble |= (diff*8/step - 1) / 2;
+
+                sample[c] += IMA4Codeword[nibble] * step / 8;
+                sample[c] = clampi(sample[c], -32768, 32767);
+
+                index[c] += IMA4Index_adjust[nibble];
+                index[c] = clampi(index[c], 0, 88);
+
+                if(!(k&1)) *dst = nibble;
+                else *(dst++) |= nibble<<4;
+            }
+        }
+    }
+}
+
+
+static void DecodeMSADPCMBlock(ALshort *dst, const ALmsadpcm *src, ALint numchans, ALsizei align)
+{
+    ALubyte blockpred[MAX_INPUT_CHANNELS];
+    ALint delta[MAX_INPUT_CHANNELS];
+    ALshort samples[MAX_INPUT_CHANNELS][2];
+    ALint i, j;
+
+    for(i = 0;i < numchans;i++)
+    {
+        blockpred[i] = *(src++);
+        blockpred[i] = minu(blockpred[i], 6);
+    }
+    for(i = 0;i < numchans;i++)
+    {
+        delta[i]  = *(src++);
+        delta[i] |= *(src++) << 8;
+        delta[i]  = (delta[i]^0x8000) - 0x8000;
+    }
+    for(i = 0;i < numchans;i++)
+    {
+        samples[i][0]  = *(src++);
+        samples[i][0] |= *(src++) << 8;
+        samples[i][0]  = (samples[i][0]^0x8000) - 0x8000;
+    }
+    for(i = 0;i < numchans;i++)
+    {
+        samples[i][1]  = *(src++);
+        samples[i][1] |= *(src++) << 8;
+        samples[i][1]  = (samples[i][1]^0x8000) - 0x8000;
+    }
+
+    /* Second sample is written first. */
+    for(i = 0;i < numchans;i++)
+        *(dst++) = samples[i][1];
+    for(i = 0;i < numchans;i++)
+        *(dst++) = samples[i][0];
+
+    for(j = 2;j < align;j++)
+    {
+        for(i = 0;i < numchans;i++)
+        {
+            const ALint num = (j*numchans) + i;
+            ALint nibble, pred;
+
+            /* Read the nibble (first is in the upper bits). */
+            if(!(num&1))
+                nibble = (*src>>4)&0x0f;
+            else
+                nibble = (*(src++))&0x0f;
+
+            pred  = (samples[i][0]*MSADPCMAdaptionCoeff[blockpred[i]][0] +
+                     samples[i][1]*MSADPCMAdaptionCoeff[blockpred[i]][1]) / 256;
+            pred += ((nibble^0x08) - 0x08) * delta[i];
+            pred  = clampi(pred, -32768, 32767);
+
+            samples[i][1] = samples[i][0];
+            samples[i][0] = pred;
+
+            delta[i] = (MSADPCMAdaption[nibble] * delta[i]) / 256;
+            delta[i] = maxi(16, delta[i]);
+
+            *(dst++) = pred;
+        }
+    }
+}
+
+/* NOTE: This encoder is pretty dumb/simplistic. Some kind of pre-processing
+ * that tries to find the optimal block predictors would be nice, at least. A
+ * multi-pass method that can generate better deltas would be good, too. */
+static void EncodeMSADPCMBlock(ALmsadpcm *dst, const ALshort *src, ALint *sample, ALint numchans, ALsizei align)
+{
+    ALubyte blockpred[MAX_INPUT_CHANNELS];
+    ALint delta[MAX_INPUT_CHANNELS];
+    ALshort samples[MAX_INPUT_CHANNELS][2];
+    ALint i, j;
+
+    /* Block predictor */
+    for(i = 0;i < numchans;i++)
+    {
+        /* FIXME: Calculate something better. */
+        blockpred[i] = 0;
+        *(dst++) = blockpred[i];
+    }
+    /* Initial delta */
+    for(i = 0;i < numchans;i++)
+    {
+        delta[i] = 16;
+        *(dst++) = (delta[i]   ) & 0xff;
+        *(dst++) = (delta[i]>>8) & 0xff;
+    }
+    /* Initial sample 1 */
+    for(i = 0;i < numchans;i++)
+    {
+        samples[i][0] = src[1*numchans + i];
+        *(dst++) = (samples[i][0]   ) & 0xff;
+        *(dst++) = (samples[i][0]>>8) & 0xff;
+    }
+    /* Initial sample 2 */
+    for(i = 0;i < numchans;i++)
+    {
+        samples[i][1] = src[i];
+        *(dst++) = (samples[i][1]   ) & 0xff;
+        *(dst++) = (samples[i][1]>>8) & 0xff;
+    }
+
+    for(j = 2;j < align;j++)
+    {
+        for(i = 0;i < numchans;i++)
+        {
+            const ALint num = (j*numchans) + i;
+            ALint nibble = 0;
+            ALint bias;
+
+            sample[i] = (samples[i][0]*MSADPCMAdaptionCoeff[blockpred[i]][0] +
+                         samples[i][1]*MSADPCMAdaptionCoeff[blockpred[i]][1]) / 256;
+
+            nibble = src[num] - sample[i];
+            if(nibble >= 0)
+                bias = delta[i] / 2;
+            else
+                bias = -delta[i] / 2;
+
+            nibble = (nibble + bias) / delta[i];
+            nibble = clampi(nibble, -8, 7)&0x0f;
+
+            sample[i] += ((nibble^0x08)-0x08) * delta[i];
+            sample[i]  = clampi(sample[i], -32768, 32767);
+
+            samples[i][1] = samples[i][0];
+            samples[i][0] = sample[i];
+
+            delta[i] = (MSADPCMAdaption[nibble] * delta[i]) / 256;
+            delta[i] = maxi(16, delta[i]);
+
+            if(!(num&1))
+                *dst = nibble << 4;
+            else
+            {
+                *dst |= nibble;
+                dst++;
+            }
+        }
+    }
+}
+
+
+static inline ALint DecodeByte3(ALbyte3 val)
+{
+    if(IS_LITTLE_ENDIAN)
+        return (val.b[2]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[0]);
+    return (val.b[0]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[2]);
+}
+
+static inline ALbyte3 EncodeByte3(ALint val)
+{
+    if(IS_LITTLE_ENDIAN)
+    {
+        ALbyte3 ret = {{ val, val>>8, val>>16 }};
+        return ret;
+    }
+    else
+    {
+        ALbyte3 ret = {{ val>>16, val>>8, val }};
+        return ret;
+    }
+}
+
+static inline ALint DecodeUByte3(ALubyte3 val)
+{
+    if(IS_LITTLE_ENDIAN)
+        return (val.b[2]<<16) | (val.b[1]<<8) | (val.b[0]);
+    return (val.b[0]<<16) | (val.b[1]<<8) | val.b[2];
+}
+
+static inline ALubyte3 EncodeUByte3(ALint val)
+{
+    if(IS_LITTLE_ENDIAN)
+    {
+        ALubyte3 ret = {{ val, val>>8, val>>16 }};
+        return ret;
+    }
+    else
+    {
+        ALubyte3 ret = {{ val>>16, val>>8, val }};
+        return ret;
+    }
+}
+
+
+static inline ALbyte Conv_ALbyte_ALbyte(ALbyte val)
+{ return val; }
+static inline ALbyte Conv_ALbyte_ALubyte(ALubyte val)
+{ return val-128; }
+static inline ALbyte Conv_ALbyte_ALshort(ALshort val)
+{ return val>>8; }
+static inline ALbyte Conv_ALbyte_ALushort(ALushort val)
+{ return (val>>8)-128; }
+static inline ALbyte Conv_ALbyte_ALint(ALint val)
+{ return val>>24; }
+static inline ALbyte Conv_ALbyte_ALuint(ALuint val)
+{ return (val>>24)-128; }
+static inline ALbyte Conv_ALbyte_ALfloat(ALfloat val)
+{
+    if(val > 1.0f) return 127;
+    if(val < -1.0f) return -128;
+    return (ALint)(val * 127.0f);
+}
+static inline ALbyte Conv_ALbyte_ALdouble(ALdouble val)
+{
+    if(val > 1.0) return 127;
+    if(val < -1.0) return -128;
+    return (ALint)(val * 127.0);
+}
+static inline ALbyte Conv_ALbyte_ALmulaw(ALmulaw val)
+{ return Conv_ALbyte_ALshort(DecodeMuLaw(val)); }
+static inline ALbyte Conv_ALbyte_ALalaw(ALalaw val)
+{ return Conv_ALbyte_ALshort(DecodeALaw(val)); }
+static inline ALbyte Conv_ALbyte_ALbyte3(ALbyte3 val)
+{ return DecodeByte3(val)>>16; }
+static inline ALbyte Conv_ALbyte_ALubyte3(ALubyte3 val)
+{ return (DecodeUByte3(val)>>16)-128; }
+
+static inline ALubyte Conv_ALubyte_ALbyte(ALbyte val)
+{ return val+128; }
+static inline ALubyte Conv_ALubyte_ALubyte(ALubyte val)
+{ return val; }
+static inline ALubyte Conv_ALubyte_ALshort(ALshort val)
+{ return (val>>8)+128; }
+static inline ALubyte Conv_ALubyte_ALushort(ALushort val)
+{ return val>>8; }
+static inline ALubyte Conv_ALubyte_ALint(ALint val)
+{ return (val>>24)+128; }
+static inline ALubyte Conv_ALubyte_ALuint(ALuint val)
+{ return val>>24; }
+static inline ALubyte Conv_ALubyte_ALfloat(ALfloat val)
+{
+    if(val > 1.0f) return 255;
+    if(val < -1.0f) return 0;
+    return (ALint)(val * 127.0f) + 128;
+}
+static inline ALubyte Conv_ALubyte_ALdouble(ALdouble val)
+{
+    if(val > 1.0) return 255;
+    if(val < -1.0) return 0;
+    return (ALint)(val * 127.0) + 128;
+}
+static inline ALubyte Conv_ALubyte_ALmulaw(ALmulaw val)
+{ return Conv_ALubyte_ALshort(DecodeMuLaw(val)); }
+static inline ALubyte Conv_ALubyte_ALalaw(ALalaw val)
+{ return Conv_ALubyte_ALshort(DecodeALaw(val)); }
+static inline ALubyte Conv_ALubyte_ALbyte3(ALbyte3 val)
+{ return (DecodeByte3(val)>>16)+128; }
+static inline ALubyte Conv_ALubyte_ALubyte3(ALubyte3 val)
+{ return DecodeUByte3(val)>>16; }
+
+static inline ALshort Conv_ALshort_ALbyte(ALbyte val)
+{ return val<<8; }
+static inline ALshort Conv_ALshort_ALubyte(ALubyte val)
+{ return (val-128)<<8; }
+static inline ALshort Conv_ALshort_ALshort(ALshort val)
+{ return val; }
+static inline ALshort Conv_ALshort_ALushort(ALushort val)
+{ return val-32768; }
+static inline ALshort Conv_ALshort_ALint(ALint val)
+{ return val>>16; }
+static inline ALshort Conv_ALshort_ALuint(ALuint val)
+{ return (val>>16)-32768; }
+static inline ALshort Conv_ALshort_ALfloat(ALfloat val)
+{
+    if(val > 1.0f) return 32767;
+    if(val < -1.0f) return -32768;
+    return (ALint)(val * 32767.0f);
+}
+static inline ALshort Conv_ALshort_ALdouble(ALdouble val)
+{
+    if(val > 1.0) return 32767;
+    if(val < -1.0) return -32768;
+    return (ALint)(val * 32767.0);
+}
+static inline ALshort Conv_ALshort_ALmulaw(ALmulaw val)
+{ return Conv_ALshort_ALshort(DecodeMuLaw(val)); }
+static inline ALshort Conv_ALshort_ALalaw(ALalaw val)
+{ return Conv_ALshort_ALshort(DecodeALaw(val)); }
+static inline ALshort Conv_ALshort_ALbyte3(ALbyte3 val)
+{ return DecodeByte3(val)>>8; }
+static inline ALshort Conv_ALshort_ALubyte3(ALubyte3 val)
+{ return (DecodeUByte3(val)>>8)-32768; }
+
+static inline ALushort Conv_ALushort_ALbyte(ALbyte val)
+{ return (val+128)<<8; }
+static inline ALushort Conv_ALushort_ALubyte(ALubyte val)
+{ return val<<8; }
+static inline ALushort Conv_ALushort_ALshort(ALshort val)
+{ return val+32768; }
+static inline ALushort Conv_ALushort_ALushort(ALushort val)
+{ return val; }
+static inline ALushort Conv_ALushort_ALint(ALint val)
+{ return (val>>16)+32768; }
+static inline ALushort Conv_ALushort_ALuint(ALuint val)
+{ return val>>16; }
+static inline ALushort Conv_ALushort_ALfloat(ALfloat val)
+{
+    if(val > 1.0f) return 65535;
+    if(val < -1.0f) return 0;
+    return (ALint)(val * 32767.0f) + 32768;
+}
+static inline ALushort Conv_ALushort_ALdouble(ALdouble val)
+{
+    if(val > 1.0) return 65535;
+    if(val < -1.0) return 0;
+    return (ALint)(val * 32767.0) + 32768;
+}
+static inline ALushort Conv_ALushort_ALmulaw(ALmulaw val)
+{ return Conv_ALushort_ALshort(DecodeMuLaw(val)); }
+static inline ALushort Conv_ALushort_ALalaw(ALalaw val)
+{ return Conv_ALushort_ALshort(DecodeALaw(val)); }
+static inline ALushort Conv_ALushort_ALbyte3(ALbyte3 val)
+{ return (DecodeByte3(val)>>8)+32768; }
+static inline ALushort Conv_ALushort_ALubyte3(ALubyte3 val)
+{ return DecodeUByte3(val)>>8; }
+
+static inline ALint Conv_ALint_ALbyte(ALbyte val)
+{ return val<<24; }
+static inline ALint Conv_ALint_ALubyte(ALubyte val)
+{ return (val-128)<<24; }
+static inline ALint Conv_ALint_ALshort(ALshort val)
+{ return val<<16; }
+static inline ALint Conv_ALint_ALushort(ALushort val)
+{ return (val-32768)<<16; }
+static inline ALint Conv_ALint_ALint(ALint val)
+{ return val; }
+static inline ALint Conv_ALint_ALuint(ALuint val)
+{ return val-2147483648u; }
+static inline ALint Conv_ALint_ALfloat(ALfloat val)
+{
+    if(val > 1.0f) return 2147483647;
+    if(val < -1.0f) return -2147483647-1;
+    return (ALint)(val*16777215.0f) << 7;
+}
+static inline ALint Conv_ALint_ALdouble(ALdouble val)
+{
+    if(val > 1.0) return 2147483647;
+    if(val < -1.0) return -2147483647-1;
+    return (ALint)(val * 2147483647.0);
+}
+static inline ALint Conv_ALint_ALmulaw(ALmulaw val)
+{ return Conv_ALint_ALshort(DecodeMuLaw(val)); }
+static inline ALint Conv_ALint_ALalaw(ALalaw val)
+{ return Conv_ALint_ALshort(DecodeALaw(val)); }
+static inline ALint Conv_ALint_ALbyte3(ALbyte3 val)
+{ return DecodeByte3(val)<<8; }
+static inline ALint Conv_ALint_ALubyte3(ALubyte3 val)
+{ return (DecodeUByte3(val)-8388608)<<8; }
+
+static inline ALuint Conv_ALuint_ALbyte(ALbyte val)
+{ return (val+128)<<24; }
+static inline ALuint Conv_ALuint_ALubyte(ALubyte val)
+{ return val<<24; }
+static inline ALuint Conv_ALuint_ALshort(ALshort val)
+{ return (val+32768)<<16; }
+static inline ALuint Conv_ALuint_ALushort(ALushort val)
+{ return val<<16; }
+static inline ALuint Conv_ALuint_ALint(ALint val)
+{ return val+2147483648u; }
+static inline ALuint Conv_ALuint_ALuint(ALuint val)
+{ return val; }
+static inline ALuint Conv_ALuint_ALfloat(ALfloat val)
+{
+    if(val > 1.0f) return 4294967295u;
+    if(val < -1.0f) return 0;
+    return ((ALint)(val*16777215.0f)<<7) + 2147483648u;
+}
+static inline ALuint Conv_ALuint_ALdouble(ALdouble val)
+{
+    if(val > 1.0) return 4294967295u;
+    if(val < -1.0) return 0;
+    return (ALint)(val * 2147483647.0) + 2147483648u;
+}
+static inline ALuint Conv_ALuint_ALmulaw(ALmulaw val)
+{ return Conv_ALuint_ALshort(DecodeMuLaw(val)); }
+static inline ALuint Conv_ALuint_ALalaw(ALalaw val)
+{ return Conv_ALuint_ALshort(DecodeALaw(val)); }
+static inline ALuint Conv_ALuint_ALbyte3(ALbyte3 val)
+{ return (DecodeByte3(val)+8388608)<<8; }
+static inline ALuint Conv_ALuint_ALubyte3(ALubyte3 val)
+{ return DecodeUByte3(val)<<8; }
+
+static inline ALfloat Conv_ALfloat_ALbyte(ALbyte val)
+{ return val * (1.0f/127.0f); }
+static inline ALfloat Conv_ALfloat_ALubyte(ALubyte val)
+{ return (val-128) * (1.0f/127.0f); }
+static inline ALfloat Conv_ALfloat_ALshort(ALshort val)
+{ return val * (1.0f/32767.0f); }
+static inline ALfloat Conv_ALfloat_ALushort(ALushort val)
+{ return (val-32768) * (1.0f/32767.0f); }
+static inline ALfloat Conv_ALfloat_ALint(ALint val)
+{ return (ALfloat)(val>>7) * (1.0f/16777215.0f); }
+static inline ALfloat Conv_ALfloat_ALuint(ALuint val)
+{ return (ALfloat)((ALint)(val>>7)-16777216) * (1.0f/16777215.0f); }
+static inline ALfloat Conv_ALfloat_ALfloat(ALfloat val)
+{ return (val==val) ? val : 0.0f; }
+static inline ALfloat Conv_ALfloat_ALdouble(ALdouble val)
+{ return (val==val) ? (ALfloat)val : 0.0f; }
+static inline ALfloat Conv_ALfloat_ALmulaw(ALmulaw val)
+{ return Conv_ALfloat_ALshort(DecodeMuLaw(val)); }
+static inline ALfloat Conv_ALfloat_ALalaw(ALalaw val)
+{ return Conv_ALfloat_ALshort(DecodeALaw(val)); }
+static inline ALfloat Conv_ALfloat_ALbyte3(ALbyte3 val)
+{ return (ALfloat)(DecodeByte3(val) * (1.0/8388607.0)); }
+static inline ALfloat Conv_ALfloat_ALubyte3(ALubyte3 val)
+{ return (ALfloat)((DecodeUByte3(val)-8388608) * (1.0/8388607.0)); }
+
+static inline ALdouble Conv_ALdouble_ALbyte(ALbyte val)
+{ return val * (1.0/127.0); }
+static inline ALdouble Conv_ALdouble_ALubyte(ALubyte val)
+{ return (val-128) * (1.0/127.0); }
+static inline ALdouble Conv_ALdouble_ALshort(ALshort val)
+{ return val * (1.0/32767.0); }
+static inline ALdouble Conv_ALdouble_ALushort(ALushort val)
+{ return (val-32768) * (1.0/32767.0); }
+static inline ALdouble Conv_ALdouble_ALint(ALint val)
+{ return val * (1.0/2147483647.0); }
+static inline ALdouble Conv_ALdouble_ALuint(ALuint val)
+{ return (ALint)(val-2147483648u) * (1.0/2147483647.0); }
+static inline ALdouble Conv_ALdouble_ALfloat(ALfloat val)
+{ return (val==val) ? val : 0.0f; }
+static inline ALdouble Conv_ALdouble_ALdouble(ALdouble val)
+{ return (val==val) ? val : 0.0; }
+static inline ALdouble Conv_ALdouble_ALmulaw(ALmulaw val)
+{ return Conv_ALdouble_ALshort(DecodeMuLaw(val)); }
+static inline ALdouble Conv_ALdouble_ALalaw(ALalaw val)
+{ return Conv_ALdouble_ALshort(DecodeALaw(val)); }
+static inline ALdouble Conv_ALdouble_ALbyte3(ALbyte3 val)
+{ return DecodeByte3(val) * (1.0/8388607.0); }
+static inline ALdouble Conv_ALdouble_ALubyte3(ALubyte3 val)
+{ return (DecodeUByte3(val)-8388608) * (1.0/8388607.0); }
+
+#define DECL_TEMPLATE(T)                                                      \
+static inline ALmulaw Conv_ALmulaw_##T(T val)                                 \
+{ return EncodeMuLaw(Conv_ALshort_##T(val)); }
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+DECL_TEMPLATE(ALshort)
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+static inline ALmulaw Conv_ALmulaw_ALmulaw(ALmulaw val)
+{ return val; }
+DECL_TEMPLATE(ALalaw)
+DECL_TEMPLATE(ALbyte3)
+DECL_TEMPLATE(ALubyte3)
+
+#undef DECL_TEMPLATE
+
+#define DECL_TEMPLATE(T)                                                      \
+static inline ALalaw Conv_ALalaw_##T(T val)                                   \
+{ return EncodeALaw(Conv_ALshort_##T(val)); }
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+DECL_TEMPLATE(ALshort)
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+static inline ALalaw Conv_ALalaw_ALalaw(ALalaw val)
+{ return val; }
+DECL_TEMPLATE(ALbyte3)
+DECL_TEMPLATE(ALubyte3)
+
+#undef DECL_TEMPLATE
+
+#define DECL_TEMPLATE(T)                                                      \
+static inline ALbyte3 Conv_ALbyte3_##T(T val)                                 \
+{ return EncodeByte3(Conv_ALint_##T(val)>>8); }
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+DECL_TEMPLATE(ALshort)
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+DECL_TEMPLATE(ALalaw)
+static inline ALbyte3 Conv_ALbyte3_ALbyte3(ALbyte3 val)
+{ return val; }
+DECL_TEMPLATE(ALubyte3)
+
+#undef DECL_TEMPLATE
+
+#define DECL_TEMPLATE(T)                                                      \
+static inline ALubyte3 Conv_ALubyte3_##T(T val)                               \
+{ return EncodeUByte3(Conv_ALuint_##T(val)>>8); }
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+DECL_TEMPLATE(ALshort)
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+DECL_TEMPLATE(ALalaw)
+DECL_TEMPLATE(ALbyte3)
+static inline ALubyte3 Conv_ALubyte3_ALubyte3(ALubyte3 val)
+{ return val; }
+
+#undef DECL_TEMPLATE
+
+
+#define DECL_TEMPLATE(T1, T2)                                                 \
+static void Convert_##T1##_##T2(T1 *dst, const T2 *src, ALuint numchans,      \
+                                ALuint len, ALsizei UNUSED(align))            \
+{                                                                             \
+    ALuint i, j;                                                              \
+    for(i = 0;i < len;i++)                                                    \
+    {                                                                         \
+        for(j = 0;j < numchans;j++)                                           \
+            *(dst++) = Conv_##T1##_##T2(*(src++));                            \
+    }                                                                         \
+}
+
+#define DECL_TEMPLATE2(T)  \
+DECL_TEMPLATE(T, ALbyte)   \
+DECL_TEMPLATE(T, ALubyte)  \
+DECL_TEMPLATE(T, ALshort)  \
+DECL_TEMPLATE(T, ALushort) \
+DECL_TEMPLATE(T, ALint)    \
+DECL_TEMPLATE(T, ALuint)   \
+DECL_TEMPLATE(T, ALfloat)  \
+DECL_TEMPLATE(T, ALdouble) \
+DECL_TEMPLATE(T, ALmulaw)  \
+DECL_TEMPLATE(T, ALalaw)   \
+DECL_TEMPLATE(T, ALbyte3)  \
+DECL_TEMPLATE(T, ALubyte3)
+
+DECL_TEMPLATE2(ALbyte)
+DECL_TEMPLATE2(ALubyte)
+DECL_TEMPLATE2(ALshort)
+DECL_TEMPLATE2(ALushort)
+DECL_TEMPLATE2(ALint)
+DECL_TEMPLATE2(ALuint)
+DECL_TEMPLATE2(ALfloat)
+DECL_TEMPLATE2(ALdouble)
+DECL_TEMPLATE2(ALmulaw)
+DECL_TEMPLATE2(ALalaw)
+DECL_TEMPLATE2(ALbyte3)
+DECL_TEMPLATE2(ALubyte3)
+
+#undef DECL_TEMPLATE2
+#undef DECL_TEMPLATE
+
+#define DECL_TEMPLATE(T)                                                      \
+static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans,  \
+                                 ALuint len, ALuint align)                    \
+{                                                                             \
+    ALsizei byte_align = ((align-1)/2 + 4) * numchans;                        \
+    DECL_VLA(ALshort, tmp, align*numchans);                                   \
+    ALuint i, j, k;                                                           \
+                                                                              \
+    assert(align > 0 && (len%align) == 0);                                    \
+    for(i = 0;i < len;i += align)                                             \
+    {                                                                         \
+        DecodeIMA4Block(tmp, src, numchans, align);                           \
+        src += byte_align;                                                    \
+                                                                              \
+        for(j = 0;j < align;j++)                                              \
+        {                                                                     \
+            for(k = 0;k < numchans;k++)                                       \
+                *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]);           \
+        }                                                                     \
+    }                                                                         \
+}
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+static void Convert_ALshort_ALima4(ALshort *dst, const ALima4 *src, ALuint numchans,
+                                   ALuint len, ALuint align)
+{
+    ALsizei byte_align = ((align-1)/2 + 4) * numchans;
+    ALuint i;
+
+    assert(align > 0 && (len%align) == 0);
+    for(i = 0;i < len;i += align)
+    {
+        DecodeIMA4Block(dst, src, numchans, align);
+        src += byte_align;
+        dst += align*numchans;
+    }
+}
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+DECL_TEMPLATE(ALalaw)
+DECL_TEMPLATE(ALbyte3)
+DECL_TEMPLATE(ALubyte3)
+
+#undef DECL_TEMPLATE
+
+#define DECL_TEMPLATE(T)                                                      \
+static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans,    \
+                               ALuint len, ALuint align)                      \
+{                                                                             \
+    ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};                     \
+    ALint index[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};                      \
+    ALsizei byte_align = ((align-1)/2 + 4) * numchans;                        \
+    DECL_VLA(ALshort, tmp, align*numchans);                                   \
+    ALuint i, j, k;                                                           \
+                                                                              \
+    assert(align > 0 && (len%align) == 0);                                    \
+    for(i = 0;i < len;i += align)                                             \
+    {                                                                         \
+        for(j = 0;j < align;j++)                                              \
+        {                                                                     \
+            for(k = 0;k < numchans;k++)                                       \
+                tmp[j*numchans + k] = Conv_ALshort_##T(*(src++));             \
+        }                                                                     \
+        EncodeIMA4Block(dst, tmp, sample, index, numchans, align);            \
+        dst += byte_align;                                                    \
+    }                                                                         \
+}
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+static void Convert_ALima4_ALshort(ALima4 *dst, const ALshort *src,
+                                   ALuint numchans, ALuint len, ALuint align)
+{
+    ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};
+    ALint index[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};
+    ALsizei byte_align = ((align-1)/2 + 4) * numchans;
+    ALuint i;
+
+    assert(align > 0 && (len%align) == 0);
+    for(i = 0;i < len;i += align)
+    {
+        EncodeIMA4Block(dst, src, sample, index, numchans, align);
+        src += align*numchans;
+        dst += byte_align;
+    }
+}
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+DECL_TEMPLATE(ALalaw)
+DECL_TEMPLATE(ALbyte3)
+DECL_TEMPLATE(ALubyte3)
+
+#undef DECL_TEMPLATE
+
+
+#define DECL_TEMPLATE(T)                                                      \
+static void Convert_##T##_ALmsadpcm(T *dst, const ALmsadpcm *src,             \
+                                    ALuint numchans, ALuint len,              \
+                                    ALuint align)                             \
+{                                                                             \
+    ALsizei byte_align = ((align-2)/2 + 7) * numchans;                        \
+    DECL_VLA(ALshort, tmp, align*numchans);                                   \
+    ALuint i, j, k;                                                           \
+                                                                              \
+    assert(align > 1 && (len%align) == 0);                                    \
+    for(i = 0;i < len;i += align)                                             \
+    {                                                                         \
+        DecodeMSADPCMBlock(tmp, src, numchans, align);                        \
+        src += byte_align;                                                    \
+                                                                              \
+        for(j = 0;j < align;j++)                                              \
+        {                                                                     \
+            for(k = 0;k < numchans;k++)                                       \
+                *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]);           \
+        }                                                                     \
+    }                                                                         \
+}
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+static void Convert_ALshort_ALmsadpcm(ALshort *dst, const ALmsadpcm *src,
+                                      ALuint numchans, ALuint len,
+                                      ALuint align)
+{
+    ALsizei byte_align = ((align-2)/2 + 7) * numchans;
+    ALuint i;
+
+    assert(align > 1 && (len%align) == 0);
+    for(i = 0;i < len;i += align)
+    {
+        DecodeMSADPCMBlock(dst, src, numchans, align);
+        src += byte_align;
+        dst += align*numchans;
+    }
+}
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+DECL_TEMPLATE(ALalaw)
+DECL_TEMPLATE(ALbyte3)
+DECL_TEMPLATE(ALubyte3)
+
+#undef DECL_TEMPLATE
+
+#define DECL_TEMPLATE(T)                                                      \
+static void Convert_ALmsadpcm_##T(ALmsadpcm *dst, const T *src,               \
+                                  ALuint numchans, ALuint len, ALuint align)  \
+{                                                                             \
+    ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};                     \
+    ALsizei byte_align = ((align-2)/2 + 7) * numchans;                        \
+    DECL_VLA(ALshort, tmp, align*numchans);                                   \
+    ALuint i, j, k;                                                           \
+                                                                              \
+    assert(align > 1 && (len%align) == 0);                                    \
+    for(i = 0;i < len;i += align)                                             \
+    {                                                                         \
+        for(j = 0;j < align;j++)                                              \
+        {                                                                     \
+            for(k = 0;k < numchans;k++)                                       \
+                tmp[j*numchans + k] = Conv_ALshort_##T(*(src++));             \
+        }                                                                     \
+        EncodeMSADPCMBlock(dst, tmp, sample, numchans, align);                \
+        dst += byte_align;                                                    \
+    }                                                                         \
+}
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+static void Convert_ALmsadpcm_ALshort(ALmsadpcm *dst, const ALshort *src,
+                                      ALuint numchans, ALuint len, ALuint align)
+{
+    ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};
+    ALsizei byte_align = ((align-2)/2 + 7) * numchans;
+    ALuint i;
+
+    assert(align > 1 && (len%align) == 0);
+    for(i = 0;i < len;i += align)
+    {
+        EncodeMSADPCMBlock(dst, src, sample, numchans, align);
+        src += align*numchans;
+        dst += byte_align;
+    }
+}
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+DECL_TEMPLATE(ALalaw)
+DECL_TEMPLATE(ALbyte3)
+DECL_TEMPLATE(ALubyte3)
+
+#undef DECL_TEMPLATE
+
+/* NOTE: We don't store compressed samples internally, so these conversions
+ * should never happen. */
+static void Convert_ALima4_ALima4(ALima4* UNUSED(dst), const ALima4* UNUSED(src),
+                                  ALuint UNUSED(numchans), ALuint UNUSED(len),
+                                  ALuint UNUSED(align))
+{
+    ERR("Unexpected IMA4-to-IMA4 conversion!\n");
+}
+
+static void Convert_ALmsadpcm_ALmsadpcm(ALmsadpcm* UNUSED(dst), const ALmsadpcm* UNUSED(src),
+                                        ALuint UNUSED(numchans), ALuint UNUSED(len),
+                                        ALuint UNUSED(align))
+{
+    ERR("Unexpected MSADPCM-to-MSADPCM conversion!\n");
+}
+
+static void Convert_ALmsadpcm_ALima4(ALmsadpcm* UNUSED(dst), const ALima4* UNUSED(src),
+                                     ALuint UNUSED(numchans), ALuint UNUSED(len),
+                                     ALuint UNUSED(align))
+{
+    ERR("Unexpected IMA4-to-MSADPCM conversion!\n");
+}
+
+static void Convert_ALima4_ALmsadpcm(ALima4* UNUSED(dst), const ALmsadpcm* UNUSED(src),
+                                     ALuint UNUSED(numchans), ALuint UNUSED(len),
+                                     ALuint UNUSED(align))
+{
+    ERR("Unexpected MSADPCM-to-IMA4 conversion!\n");
+}
+
+
+#define DECL_TEMPLATE(T)                                                      \
+static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType,  \
+                        ALsizei numchans, ALsizei len, ALsizei align)         \
+{                                                                             \
+    switch(srcType)                                                           \
+    {                                                                         \
+        case UserFmtByte:                                                     \
+            Convert_##T##_ALbyte(dst, src, numchans, len, align);             \
+            break;                                                            \
+        case UserFmtUByte:                                                    \
+            Convert_##T##_ALubyte(dst, src, numchans, len, align);            \
+            break;                                                            \
+        case UserFmtShort:                                                    \
+            Convert_##T##_ALshort(dst, src, numchans, len, align);            \
+            break;                                                            \
+        case UserFmtUShort:                                                   \
+            Convert_##T##_ALushort(dst, src, numchans, len, align);           \
+            break;                                                            \
+        case UserFmtInt:                                                      \
+            Convert_##T##_ALint(dst, src, numchans, len, align);              \
+            break;                                                            \
+        case UserFmtUInt:                                                     \
+            Convert_##T##_ALuint(dst, src, numchans, len, align);             \
+            break;                                                            \
+        case UserFmtFloat:                                                    \
+            Convert_##T##_ALfloat(dst, src, numchans, len, align);            \
+            break;                                                            \
+        case UserFmtDouble:                                                   \
+            Convert_##T##_ALdouble(dst, src, numchans, len, align);           \
+            break;                                                            \
+        case UserFmtMulaw:                                                    \
+            Convert_##T##_ALmulaw(dst, src, numchans, len, align);            \
+            break;                                                            \
+        case UserFmtAlaw:                                                     \
+            Convert_##T##_ALalaw(dst, src, numchans, len, align);             \
+            break;                                                            \
+        case UserFmtIMA4:                                                     \
+            Convert_##T##_ALima4(dst, src, numchans, len, align);             \
+            break;                                                            \
+        case UserFmtMSADPCM:                                                  \
+            Convert_##T##_ALmsadpcm(dst, src, numchans, len, align);          \
+            break;                                                            \
+        case UserFmtByte3:                                                    \
+            Convert_##T##_ALbyte3(dst, src, numchans, len, align);            \
+            break;                                                            \
+        case UserFmtUByte3:                                                   \
+            Convert_##T##_ALubyte3(dst, src, numchans, len, align);           \
+            break;                                                            \
+    }                                                                         \
+}
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+DECL_TEMPLATE(ALshort)
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+DECL_TEMPLATE(ALalaw)
+DECL_TEMPLATE(ALima4)
+DECL_TEMPLATE(ALmsadpcm)
+DECL_TEMPLATE(ALbyte3)
+DECL_TEMPLATE(ALubyte3)
+
+#undef DECL_TEMPLATE
+
+
+void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align)
+{
+    switch(dstType)
+    {
+        case UserFmtByte:
+            Convert_ALbyte(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtUByte:
+            Convert_ALubyte(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtShort:
+            Convert_ALshort(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtUShort:
+            Convert_ALushort(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtInt:
+            Convert_ALint(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtUInt:
+            Convert_ALuint(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtFloat:
+            Convert_ALfloat(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtDouble:
+            Convert_ALdouble(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtMulaw:
+            Convert_ALmulaw(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtAlaw:
+            Convert_ALalaw(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtIMA4:
+            Convert_ALima4(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtMSADPCM:
+            Convert_ALmsadpcm(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtByte3:
+            Convert_ALbyte3(dst, src, srcType, numchans, len, align);
+            break;
+        case UserFmtUByte3:
+            Convert_ALubyte3(dst, src, srcType, numchans, len, align);
+            break;
+    }
+}

+ 0 - 0
jni/openal-soft-android/README → jni/openal-soft-1.16.0/README


+ 0 - 0
jni/openal-soft-android/XCompile.txt → jni/openal-soft-1.16.0/XCompile.txt


+ 50 - 27
jni/openal-soft-android/alsoftrc.sample → jni/openal-soft-1.16.0/alsoftrc.sample

@@ -1,28 +1,40 @@
-# OpenAL config file. Options that are not under a block or are under the
-# [general] block are for general, non-backend-specific options. Blocks may
-# appear multiple times, and duplicated options will take the last value
-# specified.
+# OpenAL config file.
+#
+# Option blocks may appear multiple times, and duplicated options will take the
+# last value specified. Environment variables may be specified within option
+# values, and are automatically substituted when the config file is loaded.
+# Environment variable names may only contain alpha-numeric characters (a-z,
+# A-Z, 0-9) and underscores (_), and are prefixed with $. For example,
+# specifying "$HOME/file.ext" would typically result in something like
+# "/home/user/file.ext". To specify an actual "$" character, use "$$".
+#
 # The system-wide settings can be put in /etc/openal/alsoft.conf and user-
-# specific override settings in ~/.alsoftrc.
-# For Windows, these settings should go into %AppData%\alsoft.ini
-
+# specific override settings in $HOME/.alsoftrc.
+# For Windows, these settings should go into $AppData\alsoft.ini
+#
 # Option and block names are case-insenstive. The supplied values are only
 # hints and may not be honored (though generally it'll try to get as close as
 # possible). Note: options that are left unset may default to app- or system-
 # specified values. These are the current available settings:
 
+##
+## General stuff
+##
+[general]
+
 ## disable-cpu-exts:
-#  Disables use of the listed CPU extensions. Certain methods may utilize CPU
-#  extensions when detected, and this option is useful for preventing those
-#  extensions from being used. The available extensions are: sse, sse2, neon.
-#  Specifying 'all' disables use of all extensions.
+#  Disables use of specialized methods that use specific CPU intrinsics.
+#  Certain methods may utilize CPU extensions for improved performance, and
+#  this option is useful for preventing some or all of those methods from being
+#  used. The available extensions are: sse, sse2, sse4.1, and neon. Specifying
+#  'all' disables use of all such specialized methods.
 #disable-cpu-exts =
 
 ## channels:
 #  Sets the output channel configuration. If left unspecified, one will try to
 #  be detected from the system, and defaulting to stereo. The available values
 #  are: mono, stereo, quad, surround51, surround61, surround71
-#channels = stereo
+#channels =
 
 ## sample-type:
 #  Sets the output sample type. Currently, all mixing is done with 32-bit float
@@ -45,15 +57,19 @@
 
 ## hrtf_tables
 #  Specifies a comma-separated list of files containing HRTF data sets. The
-#  listed data sets can be used in place of or in addiiton to the the built-in
-#  set. The format of the files are described in hrtf.txt. The filenames may
-#  contain these markers, which will be replaced as needed:
+#  format of the files are described in hrtf.txt. The filenames may contain
+#  these markers, which will be replaced as needed:
 #  %r - Device sampling rate
 #  %% - Percent sign (%)
-#  So if this is set to "kemar-%r-diffuse.mhr", it will try to open
-#  "kemar-44100-diffuse.mhr" if the device is using 44100hz output, or
-#  "kemar-48000-diffuse.mhr" if the device is using 48000hz output, etc.
-#hrtf_tables =
+#  The listed files are relative to system-dependant data directories. On
+#  Windows this is:
+#  $AppData\openal\hrtf
+#  And on other systems, it's (in order):
+#  $XDG_DATA_HOME/openal/hrtf  (defaults to $HOME/.local/share/openal/hrtf)
+#  $XDG_DATA_DIRS/openal/hrtf  (defaults to /usr/local/share/openal/hrtf and
+#                               /usr/share/openal/hrtf)
+#  An absolute path may also be specified, if the given file is elsewhere.
+#hrtf_tables = default-%r.mhr
 
 ## cf_level:
 #  Sets the crossfeed level for stereo output. Valid values are:
@@ -77,8 +93,9 @@
 #wide-stereo = false
 
 ## frequency:
-#  Sets the output frequency.
-#frequency = 44100
+#  Sets the output frequency. If left unspecified it will try to detect a
+#  default from the system, otherwise it will default to 44100.
+#frequency =
 
 ## resampler:
 #  Selects the resampler used when mixing sources. Valid values are:
@@ -117,11 +134,11 @@
 ## drivers:
 #  Sets the backend driver list order, comma-seperated. Unknown backends and
 #  duplicated names are ignored. Unlisted backends won't be considered for use
-#  unless the list is ended with a comma (eg. 'oss,' will list OSS first
-#  followed by all other available backends, while 'oss' will list OSS only).
-#  Backends prepended with - won't be available for use (eg. '-oss,' will allow
-#  all available backends except OSS). An empty list means the default.
-#drivers = pulse,alsa,core,oss,solaris,sndio,qsa,mmdevapi,dsound,winmm,port,opensl,null,wave
+#  unless the list is ended with a comma (e.g. 'oss,' will try OSS first before
+#  other backends, while 'oss' will try OSS only). Backends prepended with -
+#  won't be considered for use (e.g. '-oss,' will try all available backends
+#  except OSS). An empty list means to try all backends.
+#drivers =
 
 ## excludefx:
 #  Sets which effects to exclude, preventing apps from using them. This can
@@ -190,7 +207,13 @@
 
 ## soundfont:
 #  A default soundfont (sf2 format). Used when an app requests the system
-#  default.
+#  default. The listed file is relative to system-dependant data directories.
+#  On Windows this is:
+#  $AppData\openal\soundfonts
+#  And on other systems, it's (in order):
+#  $XDG_DATA_HOME/openal/soundfonts
+#  $XDG_DATA_DIRS/openal/soundfonts
+#  An absolute path may also be specified, if the given file is elsewhere.
 #soundfont =
 
 ## volume:

+ 0 - 0
jni/openal-soft-1.16.0/build/.empty


+ 9 - 0
jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.c

@@ -0,0 +1,9 @@
+#include <sys/types.h>
+
+#define KB ((off_t)(1024))
+#define MB ((off_t)(KB*1024))
+#define GB ((off_t)(MB*1024))
+int tb[((GB+GB+GB) > GB) ? 1 : -1];
+
+int main()
+{ return 0; }

+ 39 - 0
jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.cmake

@@ -0,0 +1,39 @@
+# - Check if the _FILE_OFFSET_BITS macro is needed for large files
+# CHECK_FILE_OFFSET_BITS()
+#
+# The following variables may be set before calling this macro to
+# modify the way the check is run:
+#
+#  CMAKE_REQUIRED_FLAGS = string of compile command line flags
+#  CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
+#  CMAKE_REQUIRED_INCLUDES = list of include directories
+# Copyright (c) 2009, Chris Robinson
+#
+# Redistribution and use is allowed according to the terms of the LGPL license.
+
+
+MACRO(CHECK_FILE_OFFSET_BITS)
+
+  IF(NOT DEFINED _FILE_OFFSET_BITS)
+    MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files")
+    TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64
+      ${CMAKE_BINARY_DIR}
+      ${CMAKE_SOURCE_DIR}/cmake/CheckFileOffsetBits.c
+      COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
+    IF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
+      TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64
+        ${CMAKE_BINARY_DIR}
+        ${CMAKE_SOURCE_DIR}/cmake/CheckFileOffsetBits.c
+        COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64)
+    ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
+
+    IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+      SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
+      MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - 64")
+    ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+      SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files")
+      MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - not needed")
+    ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64)
+  ENDIF(NOT DEFINED _FILE_OFFSET_BITS)
+
+ENDMACRO(CHECK_FILE_OFFSET_BITS)

+ 0 - 0
jni/openal-soft-android/cmake/CheckSharedFunctionExists.cmake → jni/openal-soft-1.16.0/cmake/CheckSharedFunctionExists.cmake


+ 73 - 0
jni/openal-soft-1.16.0/cmake/FindALSA.cmake

@@ -0,0 +1,73 @@
+# - Find alsa
+# Find the alsa libraries (asound)
+#
+#  This module defines the following variables:
+#     ALSA_FOUND       - True if ALSA_INCLUDE_DIR & ALSA_LIBRARY are found
+#     ALSA_LIBRARIES   - Set when ALSA_LIBRARY is found
+#     ALSA_INCLUDE_DIRS - Set when ALSA_INCLUDE_DIR is found
+#
+#     ALSA_INCLUDE_DIR - where to find asoundlib.h, etc.
+#     ALSA_LIBRARY     - the asound library
+#     ALSA_VERSION_STRING - the version of alsa found (since CMake 2.8.8)
+#
+
+#=============================================================================
+# Copyright 2009-2011 Kitware, Inc.
+# Copyright 2009-2011 Philip Lowman <[email protected]>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#  * Redistributions of source code must retain the above copyright notice,
+#    this list of conditions and the following disclaimer.
+#
+#  * Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+#  * The names of Kitware, Inc., the Insight Consortium, or the names of
+#    any consortium members, or of any contributors, may not be used to
+#    endorse or promote products derived from this software without
+#    specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS''
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
+# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#=============================================================================
+
+find_path(ALSA_INCLUDE_DIR NAMES alsa/asoundlib.h
+          DOC "The ALSA (asound) include directory"
+)
+
+find_library(ALSA_LIBRARY NAMES asound
+             DOC "The ALSA (asound) library"
+)
+
+if(ALSA_INCLUDE_DIR AND EXISTS "${ALSA_INCLUDE_DIR}/alsa/version.h")
+  file(STRINGS "${ALSA_INCLUDE_DIR}/alsa/version.h" alsa_version_str REGEX "^#define[\t ]+SND_LIB_VERSION_STR[\t ]+\".*\"")
+
+  string(REGEX REPLACE "^.*SND_LIB_VERSION_STR[\t ]+\"([^\"]*)\".*$" "\\1" ALSA_VERSION_STRING "${alsa_version_str}")
+  unset(alsa_version_str)
+endif()
+
+# handle the QUIETLY and REQUIRED arguments and set ALSA_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(ALSA
+                                  REQUIRED_VARS ALSA_LIBRARY ALSA_INCLUDE_DIR
+                                  VERSION_VAR ALSA_VERSION_STRING)
+
+if(ALSA_FOUND)
+  set( ALSA_LIBRARIES ${ALSA_LIBRARY} )
+  set( ALSA_INCLUDE_DIRS ${ALSA_INCLUDE_DIR} )
+endif()
+
+mark_as_advanced(ALSA_INCLUDE_DIR ALSA_LIBRARY)

+ 21 - 0
jni/openal-soft-1.16.0/cmake/FindAudioIO.cmake

@@ -0,0 +1,21 @@
+# - Find AudioIO includes and libraries
+#
+#   AUDIOIO_FOUND        - True if AUDIOIO_INCLUDE_DIR is found
+#   AUDIOIO_INCLUDE_DIRS - Set when AUDIOIO_INCLUDE_DIR is found
+#
+#   AUDIOIO_INCLUDE_DIR - where to find sys/audioio.h, etc.
+#
+
+find_path(AUDIOIO_INCLUDE_DIR
+          NAMES sys/audioio.h
+          DOC "The AudioIO include directory"
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(AudioIO  REQUIRED_VARS AUDIOIO_INCLUDE_DIR)
+
+if(AUDIOIO_FOUND)
+    set(AUDIOIO_INCLUDE_DIRS ${AUDIOIO_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(AUDIOIO_INCLUDE_DIR)

+ 33 - 0
jni/openal-soft-1.16.0/cmake/FindDSound.cmake

@@ -0,0 +1,33 @@
+# - Find DirectSound includes and libraries
+#
+#   DSOUND_FOUND        - True if DSOUND_INCLUDE_DIR & DSOUND_LIBRARY are found
+#   DSOUND_LIBRARIES    - Set when DSOUND_LIBRARY is found
+#   DSOUND_INCLUDE_DIRS - Set when DSOUND_INCLUDE_DIR is found
+#
+#   DSOUND_INCLUDE_DIR - where to find dsound.h, etc.
+#   DSOUND_LIBRARY     - the dsound library
+#
+
+find_path(DSOUND_INCLUDE_DIR
+          PATHS "${DXSDK_DIR}/include"
+          NAMES dsound.h
+          DOC "The DirectSound include directory"
+)
+
+find_library(DSOUND_LIBRARY
+             PATHS "${DXSDK_DIR}/lib"
+             NAMES dsound
+             DOC "The DirectSound library"
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(DSound
+    REQUIRED_VARS DSOUND_LIBRARY DSOUND_INCLUDE_DIR
+)
+
+if(DSOUND_FOUND)
+    set(DSOUND_LIBRARIES ${DSOUND_LIBRARY})
+    set(DSOUND_INCLUDE_DIRS ${DSOUND_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(DSOUND_INCLUDE_DIR DSOUND_LIBRARY)

+ 173 - 0
jni/openal-soft-1.16.0/cmake/FindFFmpeg.cmake

@@ -0,0 +1,173 @@
+# vim: ts=2 sw=2
+# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC)
+#
+# Once done this will define
+#  FFMPEG_FOUND         - System has the all required components.
+#  FFMPEG_INCLUDE_DIRS  - Include directory necessary for using the required components headers.
+#  FFMPEG_LIBRARIES     - Link these to use the required ffmpeg components.
+#  FFMPEG_DEFINITIONS   - Compiler switches required for using the required ffmpeg components.
+#
+# For each of the components it will additionaly set.
+#   - AVCODEC
+#   - AVDEVICE
+#   - AVFORMAT
+#   - AVUTIL
+#   - POSTPROC
+#   - SWSCALE
+#   - SWRESAMPLE
+# the following variables will be defined
+#  <component>_FOUND        - System has <component>
+#  <component>_INCLUDE_DIRS - Include directory necessary for using the <component> headers
+#  <component>_LIBRARIES    - Link these to use <component>
+#  <component>_DEFINITIONS  - Compiler switches required for using <component>
+#  <component>_VERSION      - The components version
+#
+# Copyright (c) 2006, Matthias Kretz, <[email protected]>
+# Copyright (c) 2008, Alexander Neundorf, <[email protected]>
+# Copyright (c) 2011, Michael Jansen, <[email protected]>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+
+include(FindPackageHandleStandardArgs)
+
+if(NOT FFmpeg_FIND_COMPONENTS)
+    set(FFmpeg_FIND_COMPONENTS AVFORMAT AVCODEC AVUTIL)
+endif()
+
+#
+### Macro: set_component_found
+#
+# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present.
+#
+macro(set_component_found _component)
+    if(${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS)
+        # message(STATUS "  - ${_component} found.")
+        set(${_component}_FOUND TRUE)
+    else()
+        # message(STATUS "  - ${_component} not found.")
+    endif()
+endmacro()
+
+#
+### Macro: find_component
+#
+# Checks for the given component by invoking pkgconfig and then looking up the libraries and
+# include directories.
+#
+macro(find_component _component _pkgconfig _library _header)
+    if(NOT WIN32)
+        # use pkg-config to get the directories and then use these values
+        # in the FIND_PATH() and FIND_LIBRARY() calls
+        find_package(PkgConfig)
+        if(PKG_CONFIG_FOUND)
+            pkg_check_modules(PC_${_component} ${_pkgconfig})
+        endif()
+    endif()
+
+    find_path(${_component}_INCLUDE_DIRS ${_header}
+        HINTS
+            ${FFMPEGSDK_INC}
+            ${PC_LIB${_component}_INCLUDEDIR}
+            ${PC_LIB${_component}_INCLUDE_DIRS}
+        PATH_SUFFIXES
+            ffmpeg
+    )
+
+    find_library(${_component}_LIBRARIES NAMES ${_library}
+        HINTS
+            ${FFMPEGSDK_LIB}
+            ${PC_LIB${_component}_LIBDIR}
+            ${PC_LIB${_component}_LIBRARY_DIRS}
+    )
+
+    STRING(REGEX REPLACE "/.*" "/version.h" _ver_header ${_header})
+    if(EXISTS "${${_component}_INCLUDE_DIRS}/${_ver_header}")
+        file(STRINGS "${${_component}_INCLUDE_DIRS}/${_ver_header}" version_str REGEX "^#define[\t ]+LIB${_component}_VERSION_M.*")
+
+        foreach(_str "${version_str}")
+            if(NOT version_maj)
+                string(REGEX REPLACE "^.*LIB${_component}_VERSION_MAJOR[\t ]+([0-9]*).*$" "\\1" version_maj "${_str}")
+            endif()
+            if(NOT version_min)
+                string(REGEX REPLACE "^.*LIB${_component}_VERSION_MINOR[\t ]+([0-9]*).*$" "\\1" version_min "${_str}")
+            endif()
+            if(NOT version_mic)
+                string(REGEX REPLACE "^.*LIB${_component}_VERSION_MICRO[\t ]+([0-9]*).*$" "\\1" version_mic "${_str}")
+            endif()
+        endforeach()
+        unset(version_str)
+
+        set(${_component}_VERSION "${version_maj}.${version_min}.${version_mic}" CACHE STRING "The ${_component} version number.")
+        unset(version_maj)
+        unset(version_min)
+        unset(version_mic)
+    endif(EXISTS "${${_component}_INCLUDE_DIRS}/${_ver_header}")
+    set(${_component}_VERSION     ${PC_${_component}_VERSION}      CACHE STRING "The ${_component} version number.")
+    set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.")
+
+    set_component_found(${_component})
+
+    mark_as_advanced(
+        ${_component}_INCLUDE_DIRS
+        ${_component}_LIBRARIES
+        ${_component}_DEFINITIONS
+        ${_component}_VERSION)
+endmacro()
+
+
+set(FFMPEGSDK $ENV{FFMPEG_HOME})
+if(FFMPEGSDK)
+    set(FFMPEGSDK_INC "${FFMPEGSDK}/include")
+    set(FFMPEGSDK_LIB "${FFMPEGSDK}/lib")
+endif()
+
+# Check for all possible components.
+find_component(AVCODEC    libavcodec    avcodec    libavcodec/avcodec.h)
+find_component(AVFORMAT   libavformat   avformat   libavformat/avformat.h)
+find_component(AVDEVICE   libavdevice   avdevice   libavdevice/avdevice.h)
+find_component(AVUTIL     libavutil     avutil     libavutil/avutil.h)
+find_component(SWSCALE    libswscale    swscale    libswscale/swscale.h)
+find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)
+find_component(POSTPROC   libpostproc   postproc   libpostproc/postprocess.h)
+
+# Check if the required components were found and add their stuff to the FFMPEG_* vars.
+foreach(_component ${FFmpeg_FIND_COMPONENTS})
+    if(${_component}_FOUND)
+        # message(STATUS "Required component ${_component} present.")
+        set(FFMPEG_LIBRARIES   ${FFMPEG_LIBRARIES}   ${${_component}_LIBRARIES})
+        set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS})
+        list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS})
+    else()
+        # message(STATUS "Required component ${_component} missing.")
+    endif()
+endforeach()
+
+# Build the include path and library list with duplicates removed.
+if(FFMPEG_INCLUDE_DIRS)
+    list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)
+endif()
+
+if(FFMPEG_LIBRARIES)
+    list(REMOVE_DUPLICATES FFMPEG_LIBRARIES)
+endif()
+
+# cache the vars.
+set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE)
+set(FFMPEG_LIBRARIES    ${FFMPEG_LIBRARIES}    CACHE STRING "The FFmpeg libraries." FORCE)
+set(FFMPEG_DEFINITIONS  ${FFMPEG_DEFINITIONS}  CACHE STRING "The FFmpeg cflags." FORCE)
+
+mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES FFMPEG_DEFINITIONS)
+
+# Now set the noncached _FOUND vars for the components.
+foreach(_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWRESAMPLE SWSCALE)
+    set_component_found(${_component})
+endforeach ()
+
+# Compile the list of required vars
+set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)
+foreach(_component ${FFmpeg_FIND_COMPONENTS})
+    list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS)
+endforeach()
+
+# Give a nice error message if some of the required vars are missing.
+find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS})

+ 2 - 6
jni/openal-soft-android/cmake/FindFluidSynth.cmake → jni/openal-soft-1.16.0/cmake/FindFluidSynth.cmake

@@ -6,11 +6,6 @@
 #  FLUIDSYNTH_FOUND       - True if fluidsynth found.
 
 
-IF (FLUIDSYNTH_INCLUDE_DIR AND FLUIDSYNTH_LIBRARIES)
-  # Already in cache, be silent
-  SET(FluidSynth_FIND_QUIETLY TRUE)
-ENDIF (FLUIDSYNTH_INCLUDE_DIR AND FLUIDSYNTH_LIBRARIES)
-
 FIND_PATH(FLUIDSYNTH_INCLUDE_DIR fluidsynth.h)
 
 FIND_LIBRARY(FLUIDSYNTH_LIBRARIES NAMES fluidsynth )
@@ -19,5 +14,6 @@ MARK_AS_ADVANCED( FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR )
 # handle the QUIETLY and REQUIRED arguments and set FLUIDSYNTH_FOUND to TRUE if 
 # all listed variables are TRUE
 INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(FluidSynth DEFAULT_MSG FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(FluidSynth
+                                  REQUIRED_VARS FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR)
 

+ 21 - 0
jni/openal-soft-1.16.0/cmake/FindOSS.cmake

@@ -0,0 +1,21 @@
+# - Find OSS includes
+#
+#   OSS_FOUND        - True if OSS_INCLUDE_DIR is found
+#   OSS_INCLUDE_DIRS - Set when OSS_INCLUDE_DIR is found
+#
+#   OSS_INCLUDE_DIR - where to find sys/soundcard.h, etc.
+#
+
+find_path(OSS_INCLUDE_DIR
+          NAMES sys/soundcard.h
+          DOC "The OSS include directory"
+)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(OSS  REQUIRED_VARS OSS_INCLUDE_DIR)
+
+if(OSS_FOUND)
+    set(OSS_INCLUDE_DIRS ${OSS_INCLUDE_DIR})
+endif()
+
+mark_as_advanced(OSS_INCLUDE_DIR)

Some files were not shown because too many files changed in this diff