Browse Source

Added missing changes to the OpenAL-Soft update.

Alex Szpakowski 10 years ago
parent
commit
e9d77ef766
94 changed files with 8302 additions and 5351 deletions
  1. 1 1
      CMakeLists.txt
  2. 491 262
      libs/openal-soft/Alc/ALc.c
  3. 546 286
      libs/openal-soft/Alc/ALu.c
  4. 86 35
      libs/openal-soft/Alc/alcConfig.c
  5. 274 2
      libs/openal-soft/Alc/alcRing.c
  6. 4 1
      libs/openal-soft/Alc/alstring.h
  7. 16 23
      libs/openal-soft/Alc/backends/alsa.c
  8. 4 21
      libs/openal-soft/Alc/backends/base.c
  9. 5 0
      libs/openal-soft/Alc/backends/base.h
  10. 10 5
      libs/openal-soft/Alc/backends/coreaudio.c
  11. 45 40
      libs/openal-soft/Alc/backends/dsound.c
  12. 3 8
      libs/openal-soft/Alc/backends/loopback.c
  13. 733 70
      libs/openal-soft/Alc/backends/mmdevapi.c
  14. 4 9
      libs/openal-soft/Alc/backends/null.c
  15. 16 7
      libs/openal-soft/Alc/backends/opensl.c
  16. 9 19
      libs/openal-soft/Alc/backends/oss.c
  17. 259 155
      libs/openal-soft/Alc/backends/portaudio.c
  18. 165 140
      libs/openal-soft/Alc/backends/pulseaudio.c
  19. 108 352
      libs/openal-soft/Alc/backends/qsa.c
  20. 3 4
      libs/openal-soft/Alc/backends/sndio.c
  21. 132 82
      libs/openal-soft/Alc/backends/solaris.c
  22. 195 130
      libs/openal-soft/Alc/backends/wave.c
  23. 365 311
      libs/openal-soft/Alc/backends/winmm.c
  24. 6 17
      libs/openal-soft/Alc/bs2b.c
  25. 12 14
      libs/openal-soft/Alc/effects/autowah.c
  26. 14 12
      libs/openal-soft/Alc/effects/chorus.c
  27. 11 14
      libs/openal-soft/Alc/effects/compressor.c
  28. 28 14
      libs/openal-soft/Alc/effects/dedicated.c
  29. 18 20
      libs/openal-soft/Alc/effects/distortion.c
  30. 18 16
      libs/openal-soft/Alc/effects/echo.c
  31. 30 23
      libs/openal-soft/Alc/effects/equalizer.c
  32. 14 12
      libs/openal-soft/Alc/effects/flanger.c
  33. 16 17
      libs/openal-soft/Alc/effects/modulator.c
  34. 1 4
      libs/openal-soft/Alc/effects/null.c
  35. 417 395
      libs/openal-soft/Alc/effects/reverb.c
  36. 655 93
      libs/openal-soft/Alc/helpers.c
  37. 255 175
      libs/openal-soft/Alc/hrtf.c
  38. 16 4
      libs/openal-soft/Alc/hrtf.h
  39. 253 125
      libs/openal-soft/Alc/mixer.c
  40. 69 14
      libs/openal-soft/Alc/mixer_c.c
  41. 22 7
      libs/openal-soft/Alc/mixer_defs.h
  42. 18 32
      libs/openal-soft/Alc/mixer_inc.c
  43. 32 11
      libs/openal-soft/Alc/mixer_neon.c
  44. 99 22
      libs/openal-soft/Alc/mixer_sse.c
  45. 6 3
      libs/openal-soft/Alc/mixer_sse2.c
  46. 145 3
      libs/openal-soft/Alc/mixer_sse41.c
  47. 452 345
      libs/openal-soft/Alc/panning.c
  48. 26 8
      libs/openal-soft/Alc/vector.h
  49. 167 117
      libs/openal-soft/CMakeLists.txt
  50. 10 13
      libs/openal-soft/COPYING
  51. 58 0
      libs/openal-soft/ChangeLog
  52. 2 2
      libs/openal-soft/OpenAL32/Include/alAuxEffectSlot.h
  53. 6 2
      libs/openal-soft/OpenAL32/Include/alBuffer.h
  54. 0 1
      libs/openal-soft/OpenAL32/Include/alEffect.h
  55. 37 8
      libs/openal-soft/OpenAL32/Include/alFilter.h
  56. 5 4
      libs/openal-soft/OpenAL32/Include/alListener.h
  57. 135 289
      libs/openal-soft/OpenAL32/Include/alMain.h
  58. 14 13
      libs/openal-soft/OpenAL32/Include/alSource.h
  59. 158 64
      libs/openal-soft/OpenAL32/Include/alu.h
  60. 4 7
      libs/openal-soft/OpenAL32/Include/bs2b.h
  61. 2 2
      libs/openal-soft/OpenAL32/alAuxEffectSlot.c
  62. 41 11
      libs/openal-soft/OpenAL32/alBuffer.c
  63. 16 2
      libs/openal-soft/OpenAL32/alEffect.c
  64. 2 2
      libs/openal-soft/OpenAL32/alError.c
  65. 2 2
      libs/openal-soft/OpenAL32/alExtension.c
  66. 57 37
      libs/openal-soft/OpenAL32/alFilter.c
  67. 16 20
      libs/openal-soft/OpenAL32/alListener.c
  68. 410 345
      libs/openal-soft/OpenAL32/alSource.c
  69. 5 172
      libs/openal-soft/OpenAL32/alState.c
  70. 28 14
      libs/openal-soft/OpenAL32/alThunk.c
  71. 6 4
      libs/openal-soft/README
  72. 12 5
      libs/openal-soft/XCompile.txt
  73. 123 125
      libs/openal-soft/alsoftrc.sample
  74. 2 2
      libs/openal-soft/cmake/CheckFileOffsetBits.cmake
  75. 7 7
      libs/openal-soft/cmake/CheckSharedFunctionExists.cmake
  76. 4 2
      libs/openal-soft/cmake/FindDSound.cmake
  77. 218 169
      libs/openal-soft/cmake/FindSDL_sound.cmake
  78. 5 5
      libs/openal-soft/common/threads.c
  79. 10 12
      libs/openal-soft/config.h.in
  80. 10 0
      libs/openal-soft/env-vars.txt
  81. 64 10
      libs/openal-soft/examples/alffplay.c
  82. 3 3
      libs/openal-soft/examples/alloopback.c
  83. 1 1
      libs/openal-soft/hrtf.txt
  84. 40 2
      libs/openal-soft/include/AL/alext.h
  85. 1 1
      libs/openal-soft/include/AL/efx-presets.h
  86. 4 4
      libs/openal-soft/include/align.h
  87. 99 78
      libs/openal-soft/include/atomic.h
  88. 4 0
      libs/openal-soft/include/static_assert.h
  89. 1 1
      libs/openal-soft/include/threads.h
  90. 237 70
      libs/openal-soft/utils/alsoft-config/mainwindow.cpp
  91. 0 4
      libs/openal-soft/utils/alsoft-config/mainwindow.h
  92. 138 263
      libs/openal-soft/utils/alsoft-config/mainwindow.ui
  93. 1 93
      libs/openal-soft/utils/makehrtf.c
  94. 30 0
      libs/openal-soft/utils/openal-info.c

+ 1 - 1
CMakeLists.txt

@@ -138,7 +138,7 @@ set(MEGA_LIBTHEORA_VER "1.1")
 set(MEGA_MPG123_VER "1.15.3")
 set(MEGA_MPG123_VER "1.15.3")
 set(MEGA_FREETYPE_VER "2.5.0.1")
 set(MEGA_FREETYPE_VER "2.5.0.1")
 set(MEGA_SDL2_VER "2.0.3-dba168c67bea")
 set(MEGA_SDL2_VER "2.0.3-dba168c67bea")
-set(MEGA_OPENAL_VER "1.16.0")
+set(MEGA_OPENAL_VER "1.17.0")
 set(MEGA_MODPLUG_VER "0.8.8.4")
 set(MEGA_MODPLUG_VER "0.8.8.4")
 
 
 set(SKIP_INSTALL_ALL TRUE)
 set(SKIP_INSTALL_ALL TRUE)

File diff suppressed because it is too large
+ 491 - 262
libs/openal-soft/Alc/ALc.c


File diff suppressed because it is too large
+ 546 - 286
libs/openal-soft/Alc/ALu.c


+ 86 - 35
libs/openal-soft/Alc/alcConfig.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -33,11 +33,13 @@
 #include <ctype.h>
 #include <ctype.h>
 #include <string.h>
 #include <string.h>
 #ifdef _WIN32_IE
 #ifdef _WIN32_IE
+#include <windows.h>
 #include <shlobj.h>
 #include <shlobj.h>
 #endif
 #endif
 
 
 #include "alMain.h"
 #include "alMain.h"
 #include "compat.h"
 #include "compat.h"
+#include "bool.h"
 
 
 
 
 typedef struct ConfigEntry {
 typedef struct ConfigEntry {
@@ -137,13 +139,21 @@ static char *expdup(const char *str)
             }
             }
             else
             else
             {
             {
+                bool hasbraces;
                 char envname[1024];
                 char envname[1024];
                 size_t k = 0;
                 size_t k = 0;
 
 
+                hasbraces = (*str == '{');
+                if(hasbraces) str++;
+
                 while((isalnum(*str) || *str == '_') && k < sizeof(envname)-1)
                 while((isalnum(*str) || *str == '_') && k < sizeof(envname)-1)
                     envname[k++] = *(str++);
                     envname[k++] = *(str++);
                 envname[k++] = '\0';
                 envname[k++] = '\0';
 
 
+                if(hasbraces && *str != '}')
+                    continue;
+
+                if(hasbraces) str++;
                 if((addstr=getenv(envname)) == NULL)
                 if((addstr=getenv(envname)) == NULL)
                     continue;
                     continue;
                 addstrlen = strlen(addstr);
                 addstrlen = strlen(addstr);
@@ -192,12 +202,8 @@ static void LoadConfigFromFile(FILE *f)
         char key[256] = "";
         char key[256] = "";
         char value[256] = "";
         char value[256] = "";
 
 
-        comment = strchr(buffer, '#');
-        if(comment) *(comment++) = 0;
-
         line = rstrip(lstrip(buffer));
         line = rstrip(lstrip(buffer));
-        if(!line[0])
-            continue;
+        if(!line[0]) continue;
 
 
         if(line[0] == '[')
         if(line[0] == '[')
         {
         {
@@ -205,10 +211,21 @@ static void LoadConfigFromFile(FILE *f)
             char *endsection;
             char *endsection;
 
 
             endsection = strchr(section, ']');
             endsection = strchr(section, ']');
-            if(!endsection || section == endsection || endsection[1] != 0)
+            if(!endsection || section == endsection)
             {
             {
-                 ERR("config parse error: bad line \"%s\"\n", line);
-                 continue;
+                ERR("config parse error: bad line \"%s\"\n", line);
+                continue;
+            }
+            if(endsection[1] != 0)
+            {
+                char *end = endsection+1;
+                while(isspace(*end))
+                    ++end;
+                if(*end != 0 && *end != '#')
+                {
+                    ERR("config parse error: bad line \"%s\"\n", line);
+                    continue;
+                }
             }
             }
             *endsection = 0;
             *endsection = 0;
 
 
@@ -223,6 +240,10 @@ static void LoadConfigFromFile(FILE *f)
             continue;
             continue;
         }
         }
 
 
+        comment = strchr(line, '#');
+        if(comment) *(comment++) = 0;
+        if(!line[0]) continue;
+
         if(sscanf(line, "%255[^=] = \"%255[^\"]\"", key, value) == 2 ||
         if(sscanf(line, "%255[^=] = \"%255[^\"]\"", key, value) == 2 ||
            sscanf(line, "%255[^=] = '%255[^\']'", key, value) == 2 ||
            sscanf(line, "%255[^=] = '%255[^\']'", key, value) == 2 ||
            sscanf(line, "%255[^=] = %255[^\n]", key, value) == 2)
            sscanf(line, "%255[^=] = %255[^\n]", key, value) == 2)
@@ -296,27 +317,33 @@ void ReadALConfig(void)
 
 
     if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE)
     if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE)
     {
     {
-        size_t p = lstrlenW(buffer);
-        _snwprintf(buffer+p, PATH_MAX-p, L"\\alsoft.ini");
+        al_string filepath = AL_STRING_INIT_STATIC();
+        al_string_copy_wcstr(&filepath, buffer);
+        al_string_append_cstr(&filepath, "\\alsoft.ini");
 
 
-        TRACE("Loading config %ls...\n", buffer);
-        f = _wfopen(buffer, L"rt");
+        TRACE("Loading config %s...\n", al_string_get_cstr(filepath));
+        f = al_fopen(al_string_get_cstr(filepath), "rt");
         if(f)
         if(f)
         {
         {
             LoadConfigFromFile(f);
             LoadConfigFromFile(f);
             fclose(f);
             fclose(f);
         }
         }
+        al_string_deinit(&filepath);
     }
     }
 
 
     if((str=_wgetenv(L"ALSOFT_CONF")) != NULL && *str)
     if((str=_wgetenv(L"ALSOFT_CONF")) != NULL && *str)
     {
     {
-        TRACE("Loading config %ls...\n", str);
-        f = _wfopen(str, L"rt");
+        al_string filepath = AL_STRING_INIT_STATIC();
+        al_string_copy_wcstr(&filepath, str);
+
+        TRACE("Loading config %s...\n", al_string_get_cstr(filepath));
+        f = al_fopen(al_string_get_cstr(filepath), "rt");
         if(f)
         if(f)
         {
         {
             LoadConfigFromFile(f);
             LoadConfigFromFile(f);
             fclose(f);
             fclose(f);
         }
         }
+        al_string_deinit(&filepath);
     }
     }
 }
 }
 #else
 #else
@@ -428,7 +455,7 @@ void FreeALConfig(void)
     free(cfgBlock.entries);
     free(cfgBlock.entries);
 }
 }
 
 
-const char *GetConfigValue(const char *blockName, const char *keyName, const char *def)
+const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def)
 {
 {
     unsigned int i;
     unsigned int i;
     char key[256];
     char key[256];
@@ -437,16 +464,26 @@ const char *GetConfigValue(const char *blockName, const char *keyName, const cha
         return def;
         return def;
 
 
     if(blockName && strcasecmp(blockName, "general") != 0)
     if(blockName && strcasecmp(blockName, "general") != 0)
-        snprintf(key, sizeof(key), "%s/%s", blockName, keyName);
+    {
+        if(devName)
+            snprintf(key, sizeof(key), "%s/%s/%s", blockName, devName, keyName);
+        else
+            snprintf(key, sizeof(key), "%s/%s", blockName, keyName);
+    }
     else
     else
     {
     {
-        strncpy(key, keyName, sizeof(key)-1);
-        key[sizeof(key)-1] = 0;
+        if(devName)
+            snprintf(key, sizeof(key), "%s/%s", devName, keyName);
+        else
+        {
+            strncpy(key, keyName, sizeof(key)-1);
+            key[sizeof(key)-1] = 0;
+        }
     }
     }
 
 
     for(i = 0;i < cfgBlock.entryCount;i++)
     for(i = 0;i < cfgBlock.entryCount;i++)
     {
     {
-        if(strcasecmp(cfgBlock.entries[i].key, key) == 0)
+        if(strcmp(cfgBlock.entries[i].key, key) == 0)
         {
         {
             TRACE("Found %s = \"%s\"\n", key, cfgBlock.entries[i].value);
             TRACE("Found %s = \"%s\"\n", key, cfgBlock.entries[i].value);
             if(cfgBlock.entries[i].value[0])
             if(cfgBlock.entries[i].value[0])
@@ -455,46 +492,50 @@ const char *GetConfigValue(const char *blockName, const char *keyName, const cha
         }
         }
     }
     }
 
 
-    TRACE("Key %s not found\n", key);
-    return def;
+    if(!devName)
+    {
+        TRACE("Key %s not found\n", key);
+        return def;
+    }
+    return GetConfigValue(NULL, blockName, keyName, def);
 }
 }
 
 
-int ConfigValueExists(const char *blockName, const char *keyName)
+int ConfigValueExists(const char *devName, const char *blockName, const char *keyName)
 {
 {
-    const char *val = GetConfigValue(blockName, keyName, "");
+    const char *val = GetConfigValue(devName, blockName, keyName, "");
     return !!val[0];
     return !!val[0];
 }
 }
 
 
-int ConfigValueStr(const char *blockName, const char *keyName, const char **ret)
+int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret)
 {
 {
-    const char *val = GetConfigValue(blockName, keyName, "");
+    const char *val = GetConfigValue(devName, blockName, keyName, "");
     if(!val[0]) return 0;
     if(!val[0]) return 0;
 
 
     *ret = val;
     *ret = val;
     return 1;
     return 1;
 }
 }
 
 
-int ConfigValueInt(const char *blockName, const char *keyName, int *ret)
+int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret)
 {
 {
-    const char *val = GetConfigValue(blockName, keyName, "");
+    const char *val = GetConfigValue(devName, blockName, keyName, "");
     if(!val[0]) return 0;
     if(!val[0]) return 0;
 
 
     *ret = strtol(val, NULL, 0);
     *ret = strtol(val, NULL, 0);
     return 1;
     return 1;
 }
 }
 
 
-int ConfigValueUInt(const char *blockName, const char *keyName, unsigned int *ret)
+int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret)
 {
 {
-    const char *val = GetConfigValue(blockName, keyName, "");
+    const char *val = GetConfigValue(devName, blockName, keyName, "");
     if(!val[0]) return 0;
     if(!val[0]) return 0;
 
 
     *ret = strtoul(val, NULL, 0);
     *ret = strtoul(val, NULL, 0);
     return 1;
     return 1;
 }
 }
 
 
-int ConfigValueFloat(const char *blockName, const char *keyName, float *ret)
+int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret)
 {
 {
-    const char *val = GetConfigValue(blockName, keyName, "");
+    const char *val = GetConfigValue(devName, blockName, keyName, "");
     if(!val[0]) return 0;
     if(!val[0]) return 0;
 
 
 #ifdef HAVE_STRTOF
 #ifdef HAVE_STRTOF
@@ -505,9 +546,19 @@ int ConfigValueFloat(const char *blockName, const char *keyName, float *ret)
     return 1;
     return 1;
 }
 }
 
 
-int GetConfigValueBool(const char *blockName, const char *keyName, int def)
+int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret)
+{
+    const char *val = GetConfigValue(devName, blockName, keyName, "");
+    if(!val[0]) return 0;
+
+    *ret = (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 ||
+            strcasecmp(val, "on") == 0 || atoi(val) != 0);
+    return 1;
+}
+
+int GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, int def)
 {
 {
-    const char *val = GetConfigValue(blockName, keyName, "");
+    const char *val = GetConfigValue(devName, blockName, keyName, "");
 
 
     if(!val[0]) return !!def;
     if(!val[0]) return !!def;
     return (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 ||
     return (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 ||

+ 274 - 2
libs/openal-soft/Alc/alcRing.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -127,3 +127,275 @@ void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
 
 
     almtx_unlock(&ring->mtx);
     almtx_unlock(&ring->mtx);
 }
 }
+
+
+/* NOTE: This lockless ringbuffer implementation is copied from JACK, extended
+ * to include an element size. Consequently, parameters and return values for a
+ * size or count is in 'elements', not bytes. Additionally, it only supports
+ * single-consumer/single-provider operation. */
+struct ll_ringbuffer {
+    volatile size_t write_ptr;
+    volatile size_t read_ptr;
+    size_t size;
+    size_t size_mask;
+    size_t elem_size;
+    int mlocked;
+
+    alignas(16) char buf[];
+};
+
+/* Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes.
+ * The number of elements is rounded up to the next power of two. */
+ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz)
+{
+    ll_ringbuffer_t *rb;
+    ALuint power_of_two;
+
+    power_of_two = NextPowerOf2(sz);
+    if(power_of_two < sz)
+        return NULL;
+
+    rb = al_malloc(16, sizeof(*rb) + power_of_two*elem_sz);
+    if(!rb) return NULL;
+
+    rb->size = power_of_two;
+    rb->size_mask = rb->size - 1;
+    rb->elem_size = elem_sz;
+    rb->write_ptr = 0;
+    rb->read_ptr = 0;
+    rb->mlocked = 0;
+    return rb;
+}
+
+/* Free all data associated with the ringbuffer `rb'. */
+void ll_ringbuffer_free(ll_ringbuffer_t *rb)
+{
+    if(rb)
+    {
+#ifdef USE_MLOCK
+        if(rb->mlocked)
+            munlock(rb, sizeof(*rb) + rb->size*rb->elem_size);
+#endif /* USE_MLOCK */
+        al_free(rb);
+    }
+}
+
+/* Lock the data block of `rb' using the system call 'mlock'. */
+int ll_ringbuffer_mlock(ll_ringbuffer_t *rb)
+{
+#ifdef USE_MLOCK
+    if(!rb->locked && mlock(rb, sizeof(*rb) + rb->size*rb->elem_size))
+        return -1;
+#endif /* USE_MLOCK */
+    rb->mlocked = 1;
+    return 0;
+}
+
+/* Reset the read and write pointers to zero. This is not thread safe. */
+void ll_ringbuffer_reset(ll_ringbuffer_t *rb)
+{
+    rb->read_ptr = 0;
+    rb->write_ptr = 0;
+    memset(rb->buf, 0, rb->size*rb->elem_size);
+}
+
+/* Return the number of elements available for reading. This is the number of
+ * elements in front of the read pointer and behind the write pointer. */
+size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb)
+{
+    size_t w = rb->write_ptr;
+    size_t r = rb->read_ptr;
+    return (rb->size+w-r) & rb->size_mask;
+}
+/* Return the number of elements available for writing. This is the number of
+ * elements in front of the write pointer and behind the read pointer. */
+size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb)
+{
+    size_t w = rb->write_ptr;
+    size_t r = rb->read_ptr;
+    return (rb->size+r-w-1) & rb->size_mask;
+}
+
+/* The copying data reader. Copy at most `cnt' elements from `rb' to `dest'.
+ * Returns the actual number of elements copied. */
+size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt)
+{
+    size_t free_cnt;
+    size_t cnt2;
+    size_t to_read;
+    size_t n1, n2;
+
+    free_cnt = ll_ringbuffer_read_space(rb);
+    if(free_cnt == 0) return 0;
+
+    to_read = (cnt > free_cnt) ? free_cnt : cnt;
+    cnt2 = rb->read_ptr + to_read;
+    if(cnt2 > rb->size)
+    {
+        n1 = rb->size - rb->read_ptr;
+        n2 = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        n1 = to_read;
+        n2 = 0;
+    }
+
+    memcpy(dest, &(rb->buf[rb->read_ptr*rb->elem_size]), n1*rb->elem_size);
+    rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
+    if(n2)
+    {
+        memcpy(dest + n1*rb->elem_size, &(rb->buf[rb->read_ptr*rb->elem_size]), n2*rb->elem_size);
+        rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
+    }
+    return to_read;
+}
+
+/* The copying data reader w/o read pointer advance. Copy at most `cnt'
+ * elements from `rb' to `dest'. Returns the actual number of elements copied.
+ */
+size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt)
+{
+    size_t free_cnt;
+    size_t cnt2;
+    size_t to_read;
+    size_t n1, n2;
+    size_t tmp_read_ptr;
+
+    tmp_read_ptr = rb->read_ptr;
+    free_cnt = ll_ringbuffer_read_space(rb);
+    if(free_cnt == 0) return 0;
+
+    to_read = (cnt > free_cnt) ? free_cnt : cnt;
+    cnt2 = tmp_read_ptr + to_read;
+    if(cnt2 > rb->size)
+    {
+        n1 = rb->size - tmp_read_ptr;
+        n2 = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        n1 = to_read;
+        n2 = 0;
+    }
+
+    memcpy(dest, &(rb->buf[tmp_read_ptr*rb->elem_size]), n1*rb->elem_size);
+    tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
+    if(n2)
+        memcpy(dest + n1*rb->elem_size, &(rb->buf[tmp_read_ptr*rb->elem_size]), n2*rb->elem_size);
+    return to_read;
+}
+
+/* The copying data writer. Copy at most `cnt' elements to `rb' from `src'.
+ * Returns the actual number of elements copied. */
+size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt)
+{
+    size_t free_cnt;
+    size_t cnt2;
+    size_t to_write;
+    size_t n1, n2;
+
+    free_cnt = ll_ringbuffer_write_space(rb);
+    if(free_cnt == 0) return 0;
+
+    to_write = (cnt > free_cnt) ? free_cnt : cnt;
+    cnt2 = rb->write_ptr + to_write;
+    if(cnt2 > rb->size)
+    {
+        n1 = rb->size - rb->write_ptr;
+        n2 = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        n1 = to_write;
+        n2 = 0;
+    }
+
+    memcpy(&(rb->buf[rb->write_ptr*rb->elem_size]), src, n1*rb->elem_size);
+    rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
+    if(n2)
+    {
+        memcpy(&(rb->buf[rb->write_ptr*rb->elem_size]), src + n1*rb->elem_size, n2*rb->elem_size);
+        rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
+    }
+    return to_write;
+}
+
+/* Advance the read pointer `cnt' places. */
+void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt)
+{
+    size_t tmp = (rb->read_ptr + cnt) & rb->size_mask;
+    rb->read_ptr = tmp;
+}
+
+/* Advance the write pointer `cnt' places. */
+void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt)
+{
+    size_t tmp = (rb->write_ptr + cnt) & rb->size_mask;
+    rb->write_ptr = tmp;
+}
+
+/* The non-copying data reader. `vec' is an array of two places. Set the values
+ * at `vec' to hold the current readable data at `rb'. If the readable data is
+ * in one segment the second segment has zero length. */
+void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t * vec)
+{
+    size_t free_cnt;
+    size_t cnt2;
+    size_t w, r;
+
+    w = rb->write_ptr;
+    r = rb->read_ptr;
+    free_cnt = (rb->size+w-r) & rb->size_mask;
+
+    cnt2 = r + free_cnt;
+    if(cnt2 > rb->size)
+    {
+        /* Two part vector: the rest of the buffer after the current write ptr,
+         * plus some from the start of the buffer. */
+        vec[0].buf = (char*)&(rb->buf[r*rb->elem_size]);
+        vec[0].len = rb->size - r;
+        vec[1].buf = (char*)rb->buf;
+        vec[1].len = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        /* Single part vector: just the rest of the buffer */
+        vec[0].buf = (char*)&(rb->buf[r*rb->elem_size]);
+        vec[0].len = free_cnt;
+        vec[1].buf = NULL;
+        vec[1].len = 0;
+    }
+}
+
+/* The non-copying data writer. `vec' is an array of two places. Set the values
+ * at `vec' to hold the current writeable data at `rb'. If the writeable data
+ * is in one segment the second segment has zero length. */
+void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec)
+{
+    size_t free_cnt;
+    size_t cnt2;
+    size_t w, r;
+
+    w = rb->write_ptr;
+    r = rb->read_ptr;
+    free_cnt = (rb->size+r-w-1) & rb->size_mask;
+
+    cnt2 = w + free_cnt;
+    if(cnt2 > rb->size)
+    {
+        /* Two part vector: the rest of the buffer after the current write ptr,
+         * plus some from the start of the buffer. */
+        vec[0].buf = (char*)&(rb->buf[w*rb->elem_size]);
+        vec[0].len = rb->size - w;
+        vec[1].buf = (char*)rb->buf;
+        vec[1].len = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        vec[0].buf = (char*)&(rb->buf[w*rb->elem_size]);
+        vec[0].len = free_cnt;
+        vec[1].buf = NULL;
+        vec[1].len = 0;
+    }
+}

+ 4 - 1
libs/openal-soft/Alc/alstring.h

@@ -8,6 +8,7 @@
 
 
 typedef char al_string_char_type;
 typedef char al_string_char_type;
 TYPEDEF_VECTOR(al_string_char_type, al_string)
 TYPEDEF_VECTOR(al_string_char_type, al_string)
+TYPEDEF_VECTOR(al_string, vector_al_string)
 
 
 inline void al_string_deinit(al_string *str)
 inline void al_string_deinit(al_string *str)
 { VECTOR_DEINIT(*str); }
 { VECTOR_DEINIT(*str); }
@@ -15,7 +16,7 @@ inline void al_string_deinit(al_string *str)
 #define AL_STRING_INIT_STATIC()  ((al_string)NULL)
 #define AL_STRING_INIT_STATIC()  ((al_string)NULL)
 #define AL_STRING_DEINIT(_x)     al_string_deinit(&(_x))
 #define AL_STRING_DEINIT(_x)     al_string_deinit(&(_x))
 
 
-inline ALsizei al_string_length(const_al_string str)
+inline size_t al_string_length(const_al_string str)
 { return VECTOR_SIZE(str); }
 { return VECTOR_SIZE(str); }
 
 
 inline ALboolean al_string_empty(const_al_string str)
 inline ALboolean al_string_empty(const_al_string str)
@@ -40,6 +41,8 @@ void al_string_append_range(al_string *str, const al_string_char_type *from, con
 #include <wchar.h>
 #include <wchar.h>
 /* Windows-only methods to deal with WideChar strings. */
 /* Windows-only methods to deal with WideChar strings. */
 void al_string_copy_wcstr(al_string *str, const wchar_t *from);
 void al_string_copy_wcstr(al_string *str, const wchar_t *from);
+void al_string_append_wcstr(al_string *str, const wchar_t *from);
+void al_string_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to);
 #endif
 #endif
 
 
 #endif /* ALSTRING_H */
 #endif /* ALSTRING_H */

+ 16 - 23
libs/openal-soft/Alc/backends/alsa.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -273,14 +273,14 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
     AL_STRING_INIT(entry.name);
     AL_STRING_INIT(entry.name);
     AL_STRING_INIT(entry.device_name);
     AL_STRING_INIT(entry.device_name);
     al_string_copy_cstr(&entry.name, alsaDevice);
     al_string_copy_cstr(&entry.name, alsaDevice);
-    al_string_copy_cstr(&entry.device_name, GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
+    al_string_copy_cstr(&entry.device_name, GetConfigValue(NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
                                                            "device" : "capture", "default"));
                                                            "device" : "capture", "default"));
     VECTOR_PUSH_BACK(*DeviceList, entry);
     VECTOR_PUSH_BACK(*DeviceList, entry);
 
 
     card = -1;
     card = -1;
     if((err=snd_card_next(&card)) < 0)
     if((err=snd_card_next(&card)) < 0)
         ERR("Failed to find a card: %s\n", snd_strerror(err));
         ERR("Failed to find a card: %s\n", snd_strerror(err));
-    ConfigValueStr("alsa", prefix_name(stream), &main_prefix);
+    ConfigValueStr(NULL, "alsa", prefix_name(stream), &main_prefix);
     while(card >= 0)
     while(card >= 0)
     {
     {
         const char *card_prefix = main_prefix;
         const char *card_prefix = main_prefix;
@@ -304,7 +304,7 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
         cardid = snd_ctl_card_info_get_id(info);
         cardid = snd_ctl_card_info_get_id(info);
 
 
         snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid);
         snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid);
-        ConfigValueStr("alsa", name, &card_prefix);
+        ConfigValueStr(NULL, "alsa", name, &card_prefix);
 
 
         dev = -1;
         dev = -1;
         while(1)
         while(1)
@@ -330,7 +330,7 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
             devname = snd_pcm_info_get_name(pcminfo);
             devname = snd_pcm_info_get_name(pcminfo);
 
 
             snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
             snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
-            ConfigValueStr("alsa", name, &device_prefix);
+            ConfigValueStr(NULL, "alsa", name, &device_prefix);
 
 
             snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
             snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
                         cardname, devname, cardid, dev);
                         cardname, devname, cardid, dev);
@@ -640,7 +640,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name)
     else
     else
     {
     {
         name = alsaDevice;
         name = alsaDevice;
-        driver = GetConfigValue("alsa", "device", "default");
+        driver = GetConfigValue(NULL, "alsa", "device", "default");
     }
     }
 
 
     TRACE("Opening device \"%s\"\n", driver);
     TRACE("Opening device \"%s\"\n", driver);
@@ -704,7 +704,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
             break;
             break;
     }
     }
 
 
-    allowmmap = GetConfigValueBool("alsa", "mmap", 1);
+    allowmmap = GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "mmap", 1);
     periods = device->NumUpdates;
     periods = device->NumUpdates;
     periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency;
     periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency;
     bufferLen = periodLen * periods;
     bufferLen = periodLen * periods;
@@ -770,8 +770,11 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
     }
     }
     CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)));
     CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)));
     /* set rate (implicitly constrains period/buffer parameters) */
     /* set rate (implicitly constrains period/buffer parameters) */
-    if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 0) < 0)
-        ERR("Failed to disable ALSA resampler\n");
+    if(GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0))
+    {
+        if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 0) < 0)
+            ERR("Failed to disable ALSA resampler\n");
+    }
     CHECK(snd_pcm_hw_params_set_rate_near(self->pcmHandle, hp, &rate, NULL));
     CHECK(snd_pcm_hw_params_set_rate_near(self->pcmHandle, hp, &rate, NULL));
     /* set buffer time (implicitly constrains period/buffer parameters) */
     /* set buffer time (implicitly constrains period/buffer parameters) */
     if((err=snd_pcm_hw_params_set_buffer_time_near(self->pcmHandle, hp, &bufferLen, NULL)) < 0)
     if((err=snd_pcm_hw_params_set_buffer_time_near(self->pcmHandle, hp, &bufferLen, NULL)) < 0)
@@ -965,7 +968,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
     else
     else
     {
     {
         name = alsaDevice;
         name = alsaDevice;
-        driver = GetConfigValue("alsa", "capture", "default");
+        driver = GetConfigValue(NULL, "alsa", "capture", "default");
     }
     }
 
 
     TRACE("Opening device \"%s\"\n", driver);
     TRACE("Opening device \"%s\"\n", driver);
@@ -1352,25 +1355,15 @@ static ALCbackend* ALCalsaBackendFactory_createBackend(ALCalsaBackendFactory* UN
     if(type == ALCbackend_Playback)
     if(type == ALCbackend_Playback)
     {
     {
         ALCplaybackAlsa *backend;
         ALCplaybackAlsa *backend;
-
-        backend = ALCplaybackAlsa_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCplaybackAlsa)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCplaybackAlsa_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
     if(type == ALCbackend_Capture)
     if(type == ALCbackend_Capture)
     {
     {
         ALCcaptureAlsa *backend;
         ALCcaptureAlsa *backend;
-
-        backend = ALCcaptureAlsa_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCcaptureAlsa)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCcaptureAlsa_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 

+ 4 - 21
libs/openal-soft/Alc/backends/base.c

@@ -77,7 +77,7 @@ static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self);
 static void PlaybackWrapper_stop(PlaybackWrapper *self);
 static void PlaybackWrapper_stop(PlaybackWrapper *self);
 static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
 static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples)
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples)
-static ALint64 PlaybackWrapper_getLatency(PlaybackWrapper *self);
+static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALint64, getLatency)
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock)
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock)
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock)
 static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper)
 DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper)
@@ -121,12 +121,6 @@ static void PlaybackWrapper_stop(PlaybackWrapper *self)
     self->Funcs->StopPlayback(device);
     self->Funcs->StopPlayback(device);
 }
 }
 
 
-static ALint64 PlaybackWrapper_getLatency(PlaybackWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->GetLatency(device);
-}
-
 
 
 typedef struct CaptureWrapper {
 typedef struct CaptureWrapper {
     DERIVE_FROM_TYPE(ALCbackend);
     DERIVE_FROM_TYPE(ALCbackend);
@@ -143,13 +137,12 @@ static ALCboolean CaptureWrapper_start(CaptureWrapper *self);
 static void CaptureWrapper_stop(CaptureWrapper *self);
 static void CaptureWrapper_stop(CaptureWrapper *self);
 static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples);
 static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples);
 static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self);
 static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self);
-static ALint64 CaptureWrapper_getLatency(CaptureWrapper *self);
+static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALint64, getLatency)
 static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock)
 static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock)
 static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock)
 static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper)
 DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper)
 DEFINE_ALCBACKEND_VTABLE(CaptureWrapper);
 DEFINE_ALCBACKEND_VTABLE(CaptureWrapper);
 
 
-
 static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs)
 static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs)
 {
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
@@ -195,12 +188,6 @@ static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self)
     return self->Funcs->AvailableSamples(device);
     return self->Funcs->AvailableSamples(device);
 }
 }
 
 
-static ALint64 CaptureWrapper_getLatency(CaptureWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->GetLatency(device);
-}
-
 
 
 ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type)
 ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type)
 {
 {
@@ -208,11 +195,9 @@ ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs,
     {
     {
         PlaybackWrapper *backend;
         PlaybackWrapper *backend;
 
 
-        backend = PlaybackWrapper_New(sizeof(*backend));
+        NEW_OBJ(backend, PlaybackWrapper)(device, funcs);
         if(!backend) return NULL;
         if(!backend) return NULL;
 
 
-        PlaybackWrapper_Construct(backend, device, funcs);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 
@@ -220,11 +205,9 @@ ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs,
     {
     {
         CaptureWrapper *backend;
         CaptureWrapper *backend;
 
 
-        backend = CaptureWrapper_New(sizeof(*backend));
+        NEW_OBJ(backend, CaptureWrapper)(device, funcs);
         if(!backend) return NULL;
         if(!backend) return NULL;
 
 
-        CaptureWrapper_Construct(backend, device, funcs);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 

+ 5 - 0
libs/openal-soft/Alc/backends/base.h

@@ -123,9 +123,14 @@ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = {  \
 ALCbackendFactory *ALCpulseBackendFactory_getFactory(void);
 ALCbackendFactory *ALCpulseBackendFactory_getFactory(void);
 ALCbackendFactory *ALCalsaBackendFactory_getFactory(void);
 ALCbackendFactory *ALCalsaBackendFactory_getFactory(void);
 ALCbackendFactory *ALCossBackendFactory_getFactory(void);
 ALCbackendFactory *ALCossBackendFactory_getFactory(void);
+ALCbackendFactory *ALCjackBackendFactory_getFactory(void);
+ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void);
 ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void);
 ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void);
 ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void);
 ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void);
+ALCbackendFactory *ALCwinmmBackendFactory_getFactory(void);
+ALCbackendFactory *ALCportBackendFactory_getFactory(void);
 ALCbackendFactory *ALCnullBackendFactory_getFactory(void);
 ALCbackendFactory *ALCnullBackendFactory_getFactory(void);
+ALCbackendFactory *ALCwaveBackendFactory_getFactory(void);
 ALCbackendFactory *ALCloopbackFactory_getFactory(void);
 ALCbackendFactory *ALCloopbackFactory_getFactory(void);
 
 
 ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type);
 ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type);

+ 10 - 5
libs/openal-soft/Alc/backends/coreaudio.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -383,6 +383,11 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     ca_data *data;
     ca_data *data;
     OSStatus err;
     OSStatus err;
 
 
+    if(!deviceName)
+        deviceName = ca_device;
+    else if(strcmp(deviceName, ca_device) != 0)
+        return ALC_INVALID_VALUE;
+
     desc.componentType = kAudioUnitType_Output;
     desc.componentType = kAudioUnitType_Output;
     desc.componentSubType = kAudioUnitSubType_HALOutput;
     desc.componentSubType = kAudioUnitSubType_HALOutput;
     desc.componentManufacturer = kAudioUnitManufacturer_Apple;
     desc.componentManufacturer = kAudioUnitManufacturer_Apple;
@@ -514,9 +519,10 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
 
 
         case DevFmtQuad:
         case DevFmtQuad:
         case DevFmtX51:
         case DevFmtX51:
-        case DevFmtX51Side:
+        case DevFmtX51Rear:
         case DevFmtX61:
         case DevFmtX61:
         case DevFmtX71:
         case DevFmtX71:
+        case DevFmtBFormat3D:
             ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
             ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
             goto error;
             goto error;
     }
     }
@@ -679,8 +685,7 @@ static const BackendFuncs ca_funcs = {
     ca_start_capture,
     ca_start_capture,
     ca_stop_capture,
     ca_stop_capture,
     ca_capture_samples,
     ca_capture_samples,
-    ca_available_samples,
-    ALCdevice_GetLatencyDefault
+    ca_available_samples
 };
 };
 
 
 ALCboolean alc_ca_init(BackendFuncs *func_list)
 ALCboolean alc_ca_init(BackendFuncs *func_list)

+ 45 - 40
libs/openal-soft/Alc/backends/dsound.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -43,6 +43,9 @@
 #ifndef DSSPEAKER_5POINT1
 #ifndef DSSPEAKER_5POINT1
 #   define DSSPEAKER_5POINT1          0x00000006
 #   define DSSPEAKER_5POINT1          0x00000006
 #endif
 #endif
+#ifndef DSSPEAKER_5POINT1_BACK
+#   define DSSPEAKER_5POINT1_BACK     0x00000006
+#endif
 #ifndef DSSPEAKER_7POINT1
 #ifndef DSSPEAKER_7POINT1
 #   define DSSPEAKER_7POINT1          0x00000007
 #   define DSSPEAKER_7POINT1          0x00000007
 #endif
 #endif
@@ -57,6 +60,8 @@
 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 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(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 
 
+#define DEVNAME_TAIL " on OpenAL Soft"
+
 
 
 #ifdef HAVE_DYNLOAD
 #ifdef HAVE_DYNLOAD
 static void *ds_handle;
 static void *ds_handle;
@@ -118,15 +123,14 @@ static void clear_devlist(vector_DevMap *list)
 {
 {
 #define DEINIT_STR(i) AL_STRING_DEINIT((i)->name)
 #define DEINIT_STR(i) AL_STRING_DEINIT((i)->name)
     VECTOR_FOR_EACH(DevMap, *list, DEINIT_STR);
     VECTOR_FOR_EACH(DevMap, *list, DEINIT_STR);
-#undef DEINIT_STR
     VECTOR_RESIZE(*list, 0);
     VECTOR_RESIZE(*list, 0);
+#undef DEINIT_STR
 }
 }
 
 
 static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data)
 static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data)
 {
 {
     vector_DevMap *devices = data;
     vector_DevMap *devices = data;
     OLECHAR *guidstr = NULL;
     OLECHAR *guidstr = NULL;
-    DevMap *iter, *end;
     DevMap entry;
     DevMap entry;
     HRESULT hr;
     HRESULT hr;
     int count;
     int count;
@@ -137,24 +141,26 @@ static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHA
     AL_STRING_INIT(entry.name);
     AL_STRING_INIT(entry.name);
 
 
     count = 0;
     count = 0;
-    do {
+    while(1)
+    {
+        const DevMap *iter;
+
         al_string_copy_wcstr(&entry.name, desc);
         al_string_copy_wcstr(&entry.name, desc);
-        if(count != 0)
+        if(count == 0)
+            al_string_append_cstr(&entry.name, DEVNAME_TAIL);
+        else
         {
         {
             char str[64];
             char str[64];
-            snprintf(str, sizeof(str), " #%d", count+1);
+            snprintf(str, sizeof(str), " #%d"DEVNAME_TAIL, count+1);
             al_string_append_cstr(&entry.name, str);
             al_string_append_cstr(&entry.name, str);
         }
         }
-        count++;
 
 
-        iter = VECTOR_ITER_BEGIN(*devices);
-        end = VECTOR_ITER_END(*devices);
-        for(;iter != end;++iter)
-        {
-            if(al_string_cmp(entry.name, iter->name) == 0)
-                break;
-        }
-    } while(iter != end);
+#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, *devices, MATCH_ENTRY);
+        if(iter == VECTOR_ITER_END(*devices)) break;
+#undef MATCH_ENTRY
+        count++;
+    }
     entry.guid = *guid;
     entry.guid = *guid;
 
 
     hr = StringFromCLSID(guid, &guidstr);
     hr = StringFromCLSID(guid, &guidstr);
@@ -441,28 +447,35 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
     hr = IDirectSound_GetSpeakerConfig(self->DS, &speakers);
     hr = IDirectSound_GetSpeakerConfig(self->DS, &speakers);
     if(SUCCEEDED(hr))
     if(SUCCEEDED(hr))
     {
     {
+        speakers = DSSPEAKER_CONFIG(speakers);
         if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
         if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
         {
         {
-            speakers = DSSPEAKER_CONFIG(speakers);
             if(speakers == DSSPEAKER_MONO)
             if(speakers == DSSPEAKER_MONO)
                 device->FmtChans = DevFmtMono;
                 device->FmtChans = DevFmtMono;
             else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE)
             else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE)
                 device->FmtChans = DevFmtStereo;
                 device->FmtChans = DevFmtStereo;
             else if(speakers == DSSPEAKER_QUAD)
             else if(speakers == DSSPEAKER_QUAD)
                 device->FmtChans = DevFmtQuad;
                 device->FmtChans = DevFmtQuad;
-            else if(speakers == DSSPEAKER_5POINT1 || speakers == DSSPEAKER_5POINT1_SURROUND)
+            else if(speakers == DSSPEAKER_5POINT1_SURROUND)
                 device->FmtChans = DevFmtX51;
                 device->FmtChans = DevFmtX51;
+            else if(speakers == DSSPEAKER_5POINT1_BACK)
+                device->FmtChans = DevFmtX51Rear;
             else if(speakers == DSSPEAKER_7POINT1 || speakers == DSSPEAKER_7POINT1_SURROUND)
             else if(speakers == DSSPEAKER_7POINT1 || speakers == DSSPEAKER_7POINT1_SURROUND)
                 device->FmtChans = DevFmtX71;
                 device->FmtChans = DevFmtX71;
             else
             else
                 ERR("Unknown system speaker config: 0x%lx\n", speakers);
                 ERR("Unknown system speaker config: 0x%lx\n", speakers);
         }
         }
+        device->IsHeadphones = (device->FmtChans == DevFmtStereo &&
+                                speakers == DSSPEAKER_HEADPHONE);
 
 
         switch(device->FmtChans)
         switch(device->FmtChans)
         {
         {
             case DevFmtMono:
             case DevFmtMono:
                 OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
                 OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
                 break;
                 break;
+            case DevFmtBFormat3D:
+                device->FmtChans = DevFmtStereo;
+                /*fall-through*/
             case DevFmtStereo:
             case DevFmtStereo:
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                            SPEAKER_FRONT_RIGHT;
                                            SPEAKER_FRONT_RIGHT;
@@ -478,16 +491,16 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
                                            SPEAKER_FRONT_RIGHT |
                                            SPEAKER_FRONT_RIGHT |
                                            SPEAKER_FRONT_CENTER |
                                            SPEAKER_FRONT_CENTER |
                                            SPEAKER_LOW_FREQUENCY |
                                            SPEAKER_LOW_FREQUENCY |
-                                           SPEAKER_BACK_LEFT |
-                                           SPEAKER_BACK_RIGHT;
+                                           SPEAKER_SIDE_LEFT |
+                                           SPEAKER_SIDE_RIGHT;
                 break;
                 break;
-            case DevFmtX51Side:
+            case DevFmtX51Rear:
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                            SPEAKER_FRONT_RIGHT |
                                            SPEAKER_FRONT_RIGHT |
                                            SPEAKER_FRONT_CENTER |
                                            SPEAKER_FRONT_CENTER |
                                            SPEAKER_LOW_FREQUENCY |
                                            SPEAKER_LOW_FREQUENCY |
-                                           SPEAKER_SIDE_LEFT |
-                                           SPEAKER_SIDE_RIGHT;
+                                           SPEAKER_BACK_LEFT |
+                                           SPEAKER_BACK_RIGHT;
                 break;
                 break;
             case DevFmtX61:
             case DevFmtX61:
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
@@ -745,16 +758,16 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_FRONT_CENTER |
                                           SPEAKER_FRONT_CENTER |
                                           SPEAKER_LOW_FREQUENCY |
                                           SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_BACK_LEFT |
-                                          SPEAKER_BACK_RIGHT;
+                                          SPEAKER_SIDE_LEFT |
+                                          SPEAKER_SIDE_RIGHT;
                 break;
                 break;
-            case DevFmtX51Side:
+            case DevFmtX51Rear:
                 InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                 InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_FRONT_RIGHT |
                                           SPEAKER_FRONT_CENTER |
                                           SPEAKER_FRONT_CENTER |
                                           SPEAKER_LOW_FREQUENCY |
                                           SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_SIDE_LEFT |
-                                          SPEAKER_SIDE_RIGHT;
+                                          SPEAKER_BACK_LEFT |
+                                          SPEAKER_BACK_RIGHT;
                 break;
                 break;
             case DevFmtX61:
             case DevFmtX61:
                 InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                 InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
@@ -775,6 +788,8 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
                                           SPEAKER_SIDE_LEFT |
                                           SPEAKER_SIDE_LEFT |
                                           SPEAKER_SIDE_RIGHT;
                                           SPEAKER_SIDE_RIGHT;
                 break;
                 break;
+            case DevFmtBFormat3D:
+                break;
         }
         }
 
 
         InputType.Format.wFormatTag = WAVE_FORMAT_PCM;
         InputType.Format.wFormatTag = WAVE_FORMAT_PCM;
@@ -1027,26 +1042,16 @@ static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory
     if(type == ALCbackend_Playback)
     if(type == ALCbackend_Playback)
     {
     {
         ALCdsoundPlayback *backend;
         ALCdsoundPlayback *backend;
-
-        backend = ALCdsoundPlayback_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCdsoundPlayback)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCdsoundPlayback_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 
     if(type == ALCbackend_Capture)
     if(type == ALCbackend_Capture)
     {
     {
         ALCdsoundCapture *backend;
         ALCdsoundCapture *backend;
-
-        backend = ALCdsoundCapture_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCdsoundCapture)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCdsoundCapture_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 

+ 3 - 8
libs/openal-soft/Alc/backends/loopback.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -124,13 +124,8 @@ static ALCbackend* ALCloopbackFactory_createBackend(ALCloopbackFactory* UNUSED(s
     if(type == ALCbackend_Loopback)
     if(type == ALCbackend_Loopback)
     {
     {
         ALCloopback *backend;
         ALCloopback *backend;
-
-        backend = ALCloopback_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCloopback)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCloopback_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 

+ 733 - 70
libs/openal-soft/Alc/backends/mmdevapi.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -51,14 +51,18 @@ 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);
 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 
 
 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
+DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0);
 
 
 #define MONO SPEAKER_FRONT_CENTER
 #define MONO SPEAKER_FRONT_CENTER
 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
-#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
-#define X5DOT1SIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X5DOT1REAR (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
 #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
 #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X7DOT1_WIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_FRONT_LEFT_OF_CENTER|SPEAKER_FRONT_RIGHT_OF_CENTER)
+
+#define DEVNAME_TAIL " on OpenAL Soft"
 
 
 
 
 typedef struct {
 typedef struct {
@@ -69,16 +73,14 @@ TYPEDEF_VECTOR(DevMap, vector_DevMap)
 
 
 static void clear_devlist(vector_DevMap *list)
 static void clear_devlist(vector_DevMap *list)
 {
 {
-    DevMap *iter, *end;
-
-    iter = VECTOR_ITER_BEGIN(*list);
-    end = VECTOR_ITER_END(*list);
-    for(;iter != end;iter++)
-    {
-        AL_STRING_DEINIT(iter->name);
-        free(iter->devid);
-    }
+#define CLEAR_DEVMAP(i) do {     \
+    AL_STRING_DEINIT((i)->name); \
+    free((i)->devid);            \
+    (i)->devid = NULL;           \
+} while(0)
+    VECTOR_FOR_EACH(DevMap, *list, CLEAR_DEVMAP);
     VECTOR_RESIZE(*list, 0);
     VECTOR_RESIZE(*list, 0);
+#undef CLEAR_DEVMAP
 }
 }
 
 
 static vector_DevMap PlaybackDevices;
 static vector_DevMap PlaybackDevices;
@@ -134,39 +136,105 @@ static void get_device_name(IMMDevice *device, al_string *name)
 
 
     hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname);
     hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname);
     if(FAILED(hr))
     if(FAILED(hr))
-        WARN("GetValue failed: 0x%08lx\n", hr);
-    else
+        WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr);
+    else if(pvname.vt == VT_LPWSTR)
         al_string_copy_wcstr(name, pvname.pwszVal);
         al_string_copy_wcstr(name, pvname.pwszVal);
+    else
+        WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt);
 
 
     PropVariantClear(&pvname);
     PropVariantClear(&pvname);
     IPropertyStore_Release(ps);
     IPropertyStore_Release(ps);
 }
 }
 
 
-static void add_device(IMMDevice *device, vector_DevMap *list)
+static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfactor)
 {
 {
-    LPWSTR devid;
+    IPropertyStore *ps;
+    PROPVARIANT pvform;
     HRESULT hr;
     HRESULT hr;
 
 
-    hr = IMMDevice_GetId(device, &devid);
-    if(SUCCEEDED(hr))
+    hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
+    if(FAILED(hr))
     {
     {
-        DevMap entry;
-        AL_STRING_INIT(entry.name);
+        WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
+        return;
+    }
+
+    PropVariantInit(&pvform);
+
+    hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_FormFactor, &pvform);
+    if(FAILED(hr))
+        WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr);
+    else if(pvform.vt == VT_UI4)
+        *formfactor = pvform.ulVal;
+    else if(pvform.vt == VT_EMPTY)
+        *formfactor = UnknownFormFactor;
+    else
+        WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform.vt);
+
+    PropVariantClear(&pvform);
+    IPropertyStore_Release(ps);
+}
+
+
+static void add_device(IMMDevice *device, LPCWSTR devid, vector_DevMap *list)
+{
+    int count = 0;
+    al_string tmpname;
+    DevMap entry;
+
+    AL_STRING_INIT(tmpname);
+    AL_STRING_INIT(entry.name);
+
+    entry.devid = strdupW(devid);
+    get_device_name(device, &tmpname);
+
+    while(1)
+    {
+        const DevMap *iter;
+
+        al_string_copy(&entry.name, tmpname);
+        if(count == 0)
+            al_string_append_cstr(&entry.name, DEVNAME_TAIL);
+        else
+        {
+            char str[64];
+            snprintf(str, sizeof(str), " #%d"DEVNAME_TAIL, count+1);
+            al_string_append_cstr(&entry.name, str);
+        }
+
+#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY);
+        if(iter == VECTOR_ITER_END(*list)) break;
+#undef MATCH_ENTRY
+        count++;
+    }
 
 
-        entry.devid = strdupW(devid);
-        get_device_name(device, &entry.name);
+    TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), entry.devid);
+    VECTOR_PUSH_BACK(*list, entry);
 
 
-        CoTaskMemFree(devid);
+    AL_STRING_DEINIT(tmpname);
+}
+
+static LPWSTR get_device_id(IMMDevice *device)
+{
+    LPWSTR devid;
+    HRESULT hr;
 
 
-        TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), entry.devid);
-        VECTOR_PUSH_BACK(*list, entry);
+    hr = IMMDevice_GetId(device, &devid);
+    if(FAILED(hr))
+    {
+        ERR("Failed to get device id: %lx\n", hr);
+        return NULL;
     }
     }
+
+    return devid;
 }
 }
 
 
 static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list)
 static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list)
 {
 {
     IMMDeviceCollection *coll;
     IMMDeviceCollection *coll;
     IMMDevice *defdev = NULL;
     IMMDevice *defdev = NULL;
+    LPWSTR defdevid = NULL;
     HRESULT hr;
     HRESULT hr;
     UINT count;
     UINT count;
     UINT i;
     UINT i;
@@ -183,7 +251,7 @@ static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ve
     if(SUCCEEDED(hr) && count > 0)
     if(SUCCEEDED(hr) && count > 0)
     {
     {
         clear_devlist(list);
         clear_devlist(list);
-        if(!VECTOR_RESERVE(*list, count+1))
+        if(!VECTOR_RESERVE(*list, count))
         {
         {
             IMMDeviceCollection_Release(coll);
             IMMDeviceCollection_Release(coll);
             return E_OUTOFMEMORY;
             return E_OUTOFMEMORY;
@@ -193,22 +261,32 @@ static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ve
                                                          eMultimedia, &defdev);
                                                          eMultimedia, &defdev);
     }
     }
     if(SUCCEEDED(hr) && defdev != NULL)
     if(SUCCEEDED(hr) && defdev != NULL)
-        add_device(defdev, list);
+    {
+        defdevid = get_device_id(defdev);
+        if(defdevid)
+            add_device(defdev, defdevid, list);
+    }
 
 
     for(i = 0;i < count;++i)
     for(i = 0;i < count;++i)
     {
     {
         IMMDevice *device;
         IMMDevice *device;
+        LPWSTR devid;
 
 
-        if(FAILED(IMMDeviceCollection_Item(coll, i, &device)))
-            continue;
-
-        if(device != defdev)
-            add_device(device, list);
+        hr = IMMDeviceCollection_Item(coll, i, &device);
+        if(FAILED(hr)) continue;
 
 
+        devid = get_device_id(device);
+        if(devid)
+        {
+            if(wcscmp(devid, defdevid) != 0)
+                add_device(device, devid, list);
+            CoTaskMemFree(devid);
+        }
         IMMDevice_Release(device);
         IMMDevice_Release(device);
     }
     }
 
 
     if(defdev) IMMDevice_Release(defdev);
     if(defdev) IMMDevice_Release(defdev);
+    if(defdevid) CoTaskMemFree(defdevid);
     IMMDeviceCollection_Release(coll);
     IMMDeviceCollection_Release(coll);
 
 
     return S_OK;
     return S_OK;
@@ -294,7 +372,7 @@ static DWORD CALLBACK ALCmmdevProxy_messageHandler(void *ptr)
     TRACE("Starting message loop\n");
     TRACE("Starting message loop\n");
     while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last))
     while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last))
     {
     {
-        TRACE("Got message %u\n", msg.message);
+        TRACE("Got message %u (lparam=%p, wparam=%p)\n", msg.message, (void*)msg.lParam, (void*)msg.wParam);
         switch(msg.message)
         switch(msg.message)
         {
         {
         case WM_USER_OpenDevice:
         case WM_USER_OpenDevice:
@@ -483,9 +561,9 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg)
     if(FAILED(hr))
     if(FAILED(hr))
     {
     {
         ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr);
         ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr);
-        ALCdevice_Lock(device);
+        V0(device->Backend,lock)();
         aluHandleDisconnect(device);
         aluHandleDisconnect(device);
-        ALCdevice_Unlock(device);
+        V0(device->Backend,unlock)();
         return 1;
         return 1;
     }
     }
 
 
@@ -500,9 +578,9 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg)
         if(FAILED(hr))
         if(FAILED(hr))
         {
         {
             ERR("Failed to get padding: 0x%08lx\n", hr);
             ERR("Failed to get padding: 0x%08lx\n", hr);
-            ALCdevice_Lock(device);
+            V0(device->Backend,lock)();
             aluHandleDisconnect(device);
             aluHandleDisconnect(device);
-            ALCdevice_Unlock(device);
+            V0(device->Backend,unlock)();
             break;
             break;
         }
         }
         self->Padding = written;
         self->Padding = written;
@@ -521,18 +599,18 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg)
         hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer);
         hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer);
         if(SUCCEEDED(hr))
         if(SUCCEEDED(hr))
         {
         {
-            ALCdevice_Lock(device);
+            V0(device->Backend,lock)();
             aluMixData(device, buffer, len);
             aluMixData(device, buffer, len);
             self->Padding = written + len;
             self->Padding = written + len;
-            ALCdevice_Unlock(device);
+            V0(device->Backend,unlock)();
             hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0);
             hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0);
         }
         }
         if(FAILED(hr))
         if(FAILED(hr))
         {
         {
             ERR("Failed to buffer data: 0x%08lx\n", hr);
             ERR("Failed to buffer data: 0x%08lx\n", hr);
-            ALCdevice_Lock(device);
+            V0(device->Backend,lock)();
             aluHandleDisconnect(device);
             aluHandleDisconnect(device);
-            ALCdevice_Unlock(device);
+            V0(device->Backend,unlock)();
             break;
             break;
         }
         }
     }
     }
@@ -599,7 +677,7 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi
     {
     {
         if(deviceName)
         if(deviceName)
         {
         {
-            const DevMap *iter, *end;
+            const DevMap *iter;
 
 
             if(VECTOR_SIZE(PlaybackDevices) == 0)
             if(VECTOR_SIZE(PlaybackDevices) == 0)
             {
             {
@@ -609,19 +687,18 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi
             }
             }
 
 
             hr = E_FAIL;
             hr = E_FAIL;
-            iter = VECTOR_ITER_BEGIN(PlaybackDevices);
-            end = VECTOR_ITER_END(PlaybackDevices);
-            for(;iter != end;iter++)
+#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0)
+            VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
+            if(iter == VECTOR_ITER_END(PlaybackDevices))
+                WARN("Failed to find device name matching \"%s\"\n", deviceName);
+            else
             {
             {
-                if(al_string_cmp_cstr(iter->name, deviceName) == 0)
-                {
-                    self->devid = strdupW(iter->devid);
-                    hr = S_OK;
-                    break;
-                }
+                ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+                self->devid = strdupW(iter->devid);
+                al_string_copy(&device->DeviceName, iter->name);
+                hr = S_OK;
             }
             }
-            if(FAILED(hr))
-                WARN("Failed to find device name matching \"%s\"\n", deviceName);
+#undef MATCH_NAME
         }
         }
     }
     }
 
 
@@ -677,7 +754,11 @@ static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self)
     if(SUCCEEDED(hr))
     if(SUCCEEDED(hr))
     {
     {
         self->client = ptr;
         self->client = ptr;
-        get_device_name(self->mmdev, &device->DeviceName);
+        if(al_string_empty(device->DeviceName))
+        {
+            get_device_name(self->mmdev, &device->DeviceName);
+            al_string_append_cstr(&device->DeviceName, DEVNAME_TAIL);
+        }
     }
     }
 
 
     if(FAILED(hr))
     if(FAILED(hr))
@@ -734,6 +815,7 @@ static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self)
 static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
 static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
 {
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    EndpointFormFactor formfactor = UnknownFormFactor;
     WAVEFORMATEXTENSIBLE OutputType;
     WAVEFORMATEXTENSIBLE OutputType;
     WAVEFORMATEX *wfx = NULL;
     WAVEFORMATEX *wfx = NULL;
     REFERENCE_TIME min_per, buf_time;
     REFERENCE_TIME min_per, buf_time;
@@ -783,11 +865,11 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             device->FmtChans = DevFmtQuad;
             device->FmtChans = DevFmtQuad;
         else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1)
         else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1)
             device->FmtChans = DevFmtX51;
             device->FmtChans = DevFmtX51;
-        else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE)
-            device->FmtChans = DevFmtX51Side;
+        else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1REAR)
+            device->FmtChans = DevFmtX51Rear;
         else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1)
         else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1)
             device->FmtChans = DevFmtX61;
             device->FmtChans = DevFmtX61;
-        else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1)
+        else if(OutputType.Format.nChannels == 8 && (OutputType.dwChannelMask == X7DOT1 || OutputType.dwChannelMask == X7DOT1_WIDE))
             device->FmtChans = DevFmtX71;
             device->FmtChans = DevFmtX71;
         else
         else
             ERR("Unhandled channel config: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask);
             ERR("Unhandled channel config: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask);
@@ -799,6 +881,9 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             OutputType.Format.nChannels = 1;
             OutputType.Format.nChannels = 1;
             OutputType.dwChannelMask = MONO;
             OutputType.dwChannelMask = MONO;
             break;
             break;
+        case DevFmtBFormat3D:
+            device->FmtChans = DevFmtStereo;
+            /*fall-through*/
         case DevFmtStereo:
         case DevFmtStereo:
             OutputType.Format.nChannels = 2;
             OutputType.Format.nChannels = 2;
             OutputType.dwChannelMask = STEREO;
             OutputType.dwChannelMask = STEREO;
@@ -811,9 +896,9 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             OutputType.Format.nChannels = 6;
             OutputType.Format.nChannels = 6;
             OutputType.dwChannelMask = X5DOT1;
             OutputType.dwChannelMask = X5DOT1;
             break;
             break;
-        case DevFmtX51Side:
+        case DevFmtX51Rear:
             OutputType.Format.nChannels = 6;
             OutputType.Format.nChannels = 6;
-            OutputType.dwChannelMask = X5DOT1SIDE;
+            OutputType.dwChannelMask = X5DOT1REAR;
             break;
             break;
         case DevFmtX61:
         case DevFmtX61:
             OutputType.Format.nChannels = 7;
             OutputType.Format.nChannels = 7;
@@ -894,11 +979,11 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             device->FmtChans = DevFmtQuad;
             device->FmtChans = DevFmtQuad;
         else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1)
         else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1)
             device->FmtChans = DevFmtX51;
             device->FmtChans = DevFmtX51;
-        else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE)
-            device->FmtChans = DevFmtX51Side;
+        else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1REAR)
+            device->FmtChans = DevFmtX51Rear;
         else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1)
         else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1)
             device->FmtChans = DevFmtX61;
             device->FmtChans = DevFmtX61;
-        else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1)
+        else if(OutputType.Format.nChannels == 8 && (OutputType.dwChannelMask == X7DOT1 || OutputType.dwChannelMask == X7DOT1_WIDE))
             device->FmtChans = DevFmtX71;
             device->FmtChans = DevFmtX71;
         else
         else
         {
         {
@@ -936,6 +1021,8 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
         }
         }
         OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
         OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
     }
     }
+    get_device_formfactor(self->mmdev, &formfactor);
+    device->IsHeadphones = (device->FmtChans == DevFmtStereo && formfactor == Headphones);
 
 
     SetDefaultWFXChannelOrder(device);
     SetDefaultWFXChannelOrder(device);
 
 
@@ -1055,6 +1142,575 @@ static ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self)
 }
 }
 
 
 
 
+typedef struct ALCmmdevCapture {
+    DERIVE_FROM_TYPE(ALCbackend);
+    DERIVE_FROM_TYPE(ALCmmdevProxy);
+
+    WCHAR *devid;
+
+    IMMDevice *mmdev;
+    IAudioClient *client;
+    IAudioCaptureClient *capture;
+    HANDLE NotifyEvent;
+
+    HANDLE MsgEvent;
+
+    ll_ringbuffer_t *Ring;
+
+    volatile int killNow;
+    althrd_t thread;
+} ALCmmdevCapture;
+
+static int ALCmmdevCapture_recordProc(void *arg);
+
+static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device);
+static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self);
+static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *name);
+static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self);
+static void ALCmmdevCapture_close(ALCmmdevCapture *self);
+static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self);
+static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ALCboolean, reset)
+static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self);
+static ALCboolean ALCmmdevCapture_start(ALCmmdevCapture *self);
+static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self);
+static void ALCmmdevCapture_stop(ALCmmdevCapture *self);
+static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self);
+static ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self);
+static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCmmdevCapture)
+
+DEFINE_ALCMMDEVPROXY_VTABLE(ALCmmdevCapture);
+DEFINE_ALCBACKEND_VTABLE(ALCmmdevCapture);
+
+
+static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device)
+{
+    SET_VTABLE2(ALCmmdevCapture, ALCbackend, self);
+    SET_VTABLE2(ALCmmdevCapture, ALCmmdevProxy, self);
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    ALCmmdevProxy_Construct(STATIC_CAST(ALCmmdevProxy, self));
+
+    self->devid = NULL;
+
+    self->mmdev = NULL;
+    self->client = NULL;
+    self->capture = NULL;
+    self->NotifyEvent = NULL;
+
+    self->MsgEvent = NULL;
+
+    self->Ring = NULL;
+
+    self->killNow = 0;
+}
+
+static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self)
+{
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = NULL;
+
+    if(self->NotifyEvent != NULL)
+        CloseHandle(self->NotifyEvent);
+    self->NotifyEvent = NULL;
+    if(self->MsgEvent != NULL)
+        CloseHandle(self->MsgEvent);
+    self->MsgEvent = NULL;
+
+    free(self->devid);
+    self->devid = NULL;
+
+    ALCmmdevProxy_Destruct(STATIC_CAST(ALCmmdevProxy, self));
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg)
+{
+    ALCmmdevCapture *self = arg;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    HRESULT hr;
+
+    hr = CoInitialize(NULL);
+    if(FAILED(hr))
+    {
+        ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr);
+        V0(device->Backend,lock)();
+        aluHandleDisconnect(device);
+        V0(device->Backend,unlock)();
+        return 1;
+    }
+
+    althrd_setname(althrd_current(), RECORD_THREAD_NAME);
+
+    while(!self->killNow)
+    {
+        UINT32 avail;
+        DWORD res;
+
+        hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail);
+        if(FAILED(hr))
+            ERR("Failed to get next packet size: 0x%08lx\n", hr);
+        else while(avail > 0 && SUCCEEDED(hr))
+        {
+            UINT32 numsamples;
+            DWORD flags;
+            BYTE *data;
+
+            hr = IAudioCaptureClient_GetBuffer(self->capture,
+                &data, &numsamples, &flags, NULL, NULL
+            );
+            if(FAILED(hr))
+            {
+                ERR("Failed to get capture buffer: 0x%08lx\n", hr);
+                break;
+            }
+
+            ll_ringbuffer_write(self->Ring, (char*)data, numsamples);
+
+            hr = IAudioCaptureClient_ReleaseBuffer(self->capture, numsamples);
+            if(FAILED(hr))
+            {
+                ERR("Failed to release capture buffer: 0x%08lx\n", hr);
+                break;
+            }
+
+            hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail);
+            if(FAILED(hr))
+                ERR("Failed to get next packet size: 0x%08lx\n", hr);
+        }
+
+        if(FAILED(hr))
+        {
+            V0(device->Backend,lock)();
+            aluHandleDisconnect(device);
+            V0(device->Backend,unlock)();
+            break;
+        }
+
+        res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE);
+        if(res != WAIT_OBJECT_0)
+            ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
+    }
+
+    CoUninitialize();
+    return 0;
+}
+
+
+static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *deviceName)
+{
+    HRESULT hr = S_OK;
+
+    self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    self->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    if(self->NotifyEvent == NULL || self->MsgEvent == NULL)
+    {
+        ERR("Failed to create message events: %lu\n", GetLastError());
+        hr = E_FAIL;
+    }
+
+    if(SUCCEEDED(hr))
+    {
+        if(deviceName)
+        {
+            const DevMap *iter;
+
+            if(VECTOR_SIZE(CaptureDevices) == 0)
+            {
+                ThreadRequest req = { self->MsgEvent, 0 };
+                if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, CAPTURE_DEVICE_PROBE))
+                    (void)WaitForResponse(&req);
+            }
+
+            hr = E_FAIL;
+#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0)
+            VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
+            if(iter == VECTOR_ITER_END(CaptureDevices))
+                WARN("Failed to find device name matching \"%s\"\n", deviceName);
+            else
+            {
+                ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+                self->devid = strdupW(iter->devid);
+                al_string_copy(&device->DeviceName, iter->name);
+                hr = S_OK;
+            }
+#undef MATCH_NAME
+        }
+    }
+
+    if(SUCCEEDED(hr))
+    {
+        ThreadRequest req = { self->MsgEvent, 0 };
+
+        hr = E_FAIL;
+        if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+            hr = WaitForResponse(&req);
+        else
+            ERR("Failed to post thread message: %lu\n", GetLastError());
+    }
+
+    if(FAILED(hr))
+    {
+        if(self->NotifyEvent != NULL)
+            CloseHandle(self->NotifyEvent);
+        self->NotifyEvent = NULL;
+        if(self->MsgEvent != NULL)
+            CloseHandle(self->MsgEvent);
+        self->MsgEvent = NULL;
+
+        free(self->devid);
+        self->devid = NULL;
+
+        ERR("Device init failed: 0x%08lx\n", hr);
+        return ALC_INVALID_VALUE;
+    }
+    else
+    {
+        ThreadRequest req = { self->MsgEvent, 0 };
+
+        hr = E_FAIL;
+        if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+            hr = WaitForResponse(&req);
+        else
+            ERR("Failed to post thread message: %lu\n", GetLastError());
+
+        if(FAILED(hr))
+        {
+            ALCmmdevCapture_close(self);
+            if(hr == E_OUTOFMEMORY)
+               return ALC_OUT_OF_MEMORY;
+            return ALC_INVALID_VALUE;
+        }
+    }
+
+    return ALC_NO_ERROR;
+}
+
+static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    void *ptr;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
+    if(SUCCEEDED(hr))
+    {
+        IMMDeviceEnumerator *Enumerator = ptr;
+        if(!self->devid)
+            hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eCapture, eMultimedia, &self->mmdev);
+        else
+            hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev);
+        IMMDeviceEnumerator_Release(Enumerator);
+        Enumerator = NULL;
+    }
+    if(SUCCEEDED(hr))
+        hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
+    if(SUCCEEDED(hr))
+    {
+        self->client = ptr;
+        if(al_string_empty(device->DeviceName))
+        {
+            get_device_name(self->mmdev, &device->DeviceName);
+            al_string_append_cstr(&device->DeviceName, DEVNAME_TAIL);
+        }
+    }
+
+    if(FAILED(hr))
+    {
+        if(self->mmdev)
+            IMMDevice_Release(self->mmdev);
+        self->mmdev = NULL;
+    }
+
+    return hr;
+}
+
+
+static void ALCmmdevCapture_close(ALCmmdevCapture *self)
+{
+    ThreadRequest req = { self->MsgEvent, 0 };
+
+    if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+        (void)WaitForResponse(&req);
+
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = NULL;
+
+    CloseHandle(self->MsgEvent);
+    self->MsgEvent = NULL;
+
+    CloseHandle(self->NotifyEvent);
+    self->NotifyEvent = NULL;
+
+    free(self->devid);
+    self->devid = NULL;
+}
+
+static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self)
+{
+    if(self->client)
+        IAudioClient_Release(self->client);
+    self->client = NULL;
+
+    if(self->mmdev)
+        IMMDevice_Release(self->mmdev);
+    self->mmdev = NULL;
+}
+
+
+static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    WAVEFORMATEXTENSIBLE OutputType;
+    WAVEFORMATEX *wfx = NULL;
+    REFERENCE_TIME buf_time;
+    UINT32 buffer_len;
+    void *ptr = NULL;
+    HRESULT hr;
+
+    if(self->client)
+        IAudioClient_Release(self->client);
+    self->client = NULL;
+
+    hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
+    if(FAILED(hr))
+    {
+        ERR("Failed to reactivate audio client: 0x%08lx\n", hr);
+        return hr;
+    }
+    self->client = ptr;
+
+    buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 +
+                                device->Frequency-1) / device->Frequency;
+
+    OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+    switch(device->FmtChans)
+    {
+        case DevFmtMono:
+            OutputType.Format.nChannels = 1;
+            OutputType.dwChannelMask = MONO;
+            break;
+        case DevFmtStereo:
+            OutputType.Format.nChannels = 2;
+            OutputType.dwChannelMask = STEREO;
+            break;
+        case DevFmtQuad:
+            OutputType.Format.nChannels = 4;
+            OutputType.dwChannelMask = QUAD;
+            break;
+        case DevFmtX51:
+            OutputType.Format.nChannels = 6;
+            OutputType.dwChannelMask = X5DOT1;
+            break;
+        case DevFmtX51Rear:
+            OutputType.Format.nChannels = 6;
+            OutputType.dwChannelMask = X5DOT1REAR;
+            break;
+        case DevFmtX61:
+            OutputType.Format.nChannels = 7;
+            OutputType.dwChannelMask = X6DOT1;
+            break;
+        case DevFmtX71:
+            OutputType.Format.nChannels = 8;
+            OutputType.dwChannelMask = X7DOT1;
+            break;
+
+        case DevFmtBFormat3D:
+            return E_FAIL;
+    }
+    switch(device->FmtType)
+    {
+        case DevFmtUByte:
+            OutputType.Format.wBitsPerSample = 8;
+            OutputType.Samples.wValidBitsPerSample = 8;
+            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+            break;
+        case DevFmtShort:
+            OutputType.Format.wBitsPerSample = 16;
+            OutputType.Samples.wValidBitsPerSample = 16;
+            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+            break;
+        case DevFmtInt:
+            OutputType.Format.wBitsPerSample = 32;
+            OutputType.Samples.wValidBitsPerSample = 32;
+            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+            break;
+        case DevFmtFloat:
+            OutputType.Format.wBitsPerSample = 32;
+            OutputType.Samples.wValidBitsPerSample = 32;
+            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+            break;
+
+        case DevFmtByte:
+        case DevFmtUShort:
+        case DevFmtUInt:
+            WARN("%s capture samples not supported\n", DevFmtTypeString(device->FmtType));
+            return E_FAIL;
+    }
+    OutputType.Format.nSamplesPerSec = device->Frequency;
+
+    OutputType.Format.nBlockAlign = OutputType.Format.nChannels *
+                                    OutputType.Format.wBitsPerSample / 8;
+    OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec *
+                                        OutputType.Format.nBlockAlign;
+    OutputType.Format.cbSize = sizeof(OutputType) - sizeof(OutputType.Format);
+
+    hr = IAudioClient_IsFormatSupported(self->client,
+        AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx
+    );
+    if(FAILED(hr))
+    {
+        ERR("Failed to check format support: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    /* FIXME: We should do conversion/resampling if we didn't get a matching format. */
+    if(wfx->nSamplesPerSec != OutputType.Format.nSamplesPerSec ||
+       wfx->wBitsPerSample != OutputType.Format.wBitsPerSample ||
+       wfx->nChannels != OutputType.Format.nChannels ||
+       wfx->nBlockAlign != OutputType.Format.nBlockAlign)
+    {
+        ERR("Did not get matching format, wanted: %s %s %uhz, got: %d channel(s) %d-bit %luhz\n",
+            DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), device->Frequency,
+            wfx->nChannels, wfx->wBitsPerSample, wfx->nSamplesPerSec);
+        CoTaskMemFree(wfx);
+        return E_FAIL;
+    }
+
+    if(!MakeExtensible(&OutputType, wfx))
+    {
+        CoTaskMemFree(wfx);
+        return E_FAIL;
+    }
+    CoTaskMemFree(wfx);
+    wfx = NULL;
+
+    hr = IAudioClient_Initialize(self->client,
+        AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+        buf_time, 0, &OutputType.Format, NULL
+    );
+    if(FAILED(hr))
+    {
+        ERR("Failed to initialize audio client: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    hr = IAudioClient_GetBufferSize(self->client, &buffer_len);
+    if(FAILED(hr))
+    {
+        ERR("Failed to get buffer size: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    buffer_len = maxu(device->UpdateSize*device->NumUpdates + 1, buffer_len);
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = ll_ringbuffer_create(buffer_len, OutputType.Format.nBlockAlign);
+    if(!self->Ring)
+    {
+        ERR("Failed to allocate capture ring buffer\n");
+        return E_OUTOFMEMORY;
+    }
+
+    hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent);
+    if(FAILED(hr))
+    {
+        ERR("Failed to set event handle: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    return hr;
+}
+
+
+static ALCboolean ALCmmdevCapture_start(ALCmmdevCapture *self)
+{
+    ThreadRequest req = { self->MsgEvent, 0 };
+    HRESULT hr = E_FAIL;
+
+    if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+        hr = WaitForResponse(&req);
+
+    return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
+}
+
+static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self)
+{
+    HRESULT hr;
+    void *ptr;
+
+    ResetEvent(self->NotifyEvent);
+    hr = IAudioClient_Start(self->client);
+    if(FAILED(hr))
+    {
+        ERR("Failed to start audio client: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    hr = IAudioClient_GetService(self->client, &IID_IAudioCaptureClient, &ptr);
+    if(SUCCEEDED(hr))
+    {
+        self->capture = ptr;
+        self->killNow = 0;
+        if(althrd_create(&self->thread, ALCmmdevCapture_recordProc, self) != althrd_success)
+        {
+            ERR("Failed to start thread\n");
+            IAudioCaptureClient_Release(self->capture);
+            self->capture = NULL;
+            hr = E_FAIL;
+        }
+    }
+
+    if(FAILED(hr))
+    {
+        IAudioClient_Stop(self->client);
+        IAudioClient_Reset(self->client);
+    }
+
+    return hr;
+}
+
+
+static void ALCmmdevCapture_stop(ALCmmdevCapture *self)
+{
+    ThreadRequest req = { self->MsgEvent, 0 };
+    if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+        (void)WaitForResponse(&req);
+}
+
+static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self)
+{
+    int res;
+
+    if(!self->capture)
+        return;
+
+    self->killNow = 1;
+    althrd_join(self->thread, &res);
+
+    IAudioCaptureClient_Release(self->capture);
+    self->capture = NULL;
+    IAudioClient_Stop(self->client);
+    IAudioClient_Reset(self->client);
+}
+
+
+ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self)
+{
+    return (ALuint)ll_ringbuffer_read_space(self->Ring);
+}
+
+ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples)
+{
+    if(ALCmmdevCapture_availableSamples(self) < samples)
+        return ALC_INVALID_VALUE;
+    ll_ringbuffer_read(self->Ring, buffer, samples);
+    return ALC_NO_ERROR;
+}
+
+
 static inline void AppendAllDevicesList2(const DevMap *entry)
 static inline void AppendAllDevicesList2(const DevMap *entry)
 { AppendAllDevicesList(al_string_get_cstr(entry->name)); }
 { AppendAllDevicesList(al_string_get_cstr(entry->name)); }
 static inline void AppendCaptureDeviceList2(const DevMap *entry)
 static inline void AppendCaptureDeviceList2(const DevMap *entry)
@@ -1125,7 +1781,12 @@ static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory* UNUSED(self))
 
 
 static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UNUSED(self), ALCbackend_Type type)
 static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UNUSED(self), ALCbackend_Type type)
 {
 {
-    if(type == ALCbackend_Playback)
+    /* TODO: Disable capture with mmdevapi for now, since it doesn't do any
+     * rechanneling or resampling; if the device is configured for 48000hz
+     * stereo input, for example, and the app asks for 22050hz mono,
+     * initialization will fail.
+     */
+    if(type == ALCbackend_Playback /*|| type == ALCbackend_Capture*/)
         return ALC_TRUE;
         return ALC_TRUE;
     return ALC_FALSE;
     return ALC_FALSE;
 }
 }
@@ -1162,13 +1823,15 @@ static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory*
     if(type == ALCbackend_Playback)
     if(type == ALCbackend_Playback)
     {
     {
         ALCmmdevPlayback *backend;
         ALCmmdevPlayback *backend;
-
-        backend = ALCmmdevPlayback_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCmmdevPlayback)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+    if(type == ALCbackend_Capture)
+    {
+        ALCmmdevCapture *backend;
+        NEW_OBJ(backend, ALCmmdevCapture)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCmmdevPlayback_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 

+ 4 - 9
libs/openal-soft/Alc/backends/null.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -106,7 +106,7 @@ static int ALCnullBackend_mixerProc(void *ptr)
         }
         }
 
 
         if(avail-done < device->UpdateSize)
         if(avail-done < device->UpdateSize)
-            al_nssleep(0, restTime);
+            al_nssleep(restTime);
         else while(avail-done >= device->UpdateSize)
         else while(avail-done >= device->UpdateSize)
         {
         {
             aluMixData(device, NULL, device->UpdateSize);
             aluMixData(device, NULL, device->UpdateSize);
@@ -214,13 +214,8 @@ static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UN
     if(type == ALCbackend_Playback)
     if(type == ALCbackend_Playback)
     {
     {
         ALCnullBackend *backend;
         ALCnullBackend *backend;
-
-        backend = ALCnullBackend_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCnullBackend)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCnullBackend_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 

+ 16 - 7
libs/openal-soft/Alc/backends/opensl.c

@@ -25,7 +25,7 @@
 
 
 #include "alMain.h"
 #include "alMain.h"
 #include "alu.h"
 #include "alu.h"
-
+#include "threads.h"
 
 
 #include <SLES/OpenSLES.h>
 #include <SLES/OpenSLES.h>
 #include <SLES/OpenSLES_Android.h>
 #include <SLES/OpenSLES_Android.h>
@@ -67,7 +67,10 @@ static SLuint32 GetChannelMask(enum DevFmtChannels chans)
                                 SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
                                 SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
         case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
         case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
                                SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
                                SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
-                               SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
+                               SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
+        case DevFmtX51Rear: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
+                                   SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
+                                   SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
         case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
         case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
                                SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
                                SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
                                SL_SPEAKER_BACK_CENTER|
                                SL_SPEAKER_BACK_CENTER|
@@ -76,9 +79,7 @@ static SLuint32 GetChannelMask(enum DevFmtChannels chans)
                                SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
                                SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
                                SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
                                SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
                                SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
                                SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
-        case DevFmtX51Side: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
-                                   SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
-                                   SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
+        case DevFmtBFormat3D: break;
     }
     }
     return 0;
     return 0;
 }
 }
@@ -378,6 +379,15 @@ static void opensl_stop_playback(ALCdevice *Device)
         result = VCALL0(bufferQueue,Clear)();
         result = VCALL0(bufferQueue,Clear)();
         PRINTERR(result, "bufferQueue->Clear");
         PRINTERR(result, "bufferQueue->Clear");
     }
     }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        SLAndroidSimpleBufferQueueState state;
+        do {
+            althrd_yield();
+            result = VCALL(bufferQueue,GetState)(&state);
+        } while(SL_RESULT_SUCCESS == result && state.count > 0);
+        PRINTERR(result, "bufferQueue->GetState");
+    }
 
 
     free(data->buffer);
     free(data->buffer);
     data->buffer = NULL;
     data->buffer = NULL;
@@ -396,8 +406,7 @@ static const BackendFuncs opensl_funcs = {
     NULL,
     NULL,
     NULL,
     NULL,
     NULL,
     NULL,
-    NULL,
-    ALCdevice_GetLatencyDefault
+    NULL
 };
 };
 
 
 
 

+ 9 - 19
libs/openal-soft/Alc/backends/oss.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -131,7 +131,7 @@ static int ALCplaybackOSS_mixerProc(void *ptr)
                     break;
                     break;
                 }
                 }
 
 
-                al_nssleep(0, 1000000);
+                al_nssleep(1000000);
                 continue;
                 continue;
             }
             }
 
 
@@ -345,7 +345,7 @@ static int ALCcaptureOSS_recordProc(void *ptr)
     int amt;
     int amt;
 
 
     SetRTPriority();
     SetRTPriority();
-    althrd_setname(althrd_current(), "alsoft-record");
+    althrd_setname(althrd_current(), RECORD_THREAD_NAME);
 
 
     frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
     frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
 
 
@@ -362,7 +362,7 @@ static int ALCcaptureOSS_recordProc(void *ptr)
         }
         }
         if(amt == 0)
         if(amt == 0)
         {
         {
-            al_nssleep(0, 1000000);
+            al_nssleep(1000000);
             continue;
             continue;
         }
         }
         if(self->doCapture)
         if(self->doCapture)
@@ -562,8 +562,8 @@ ALCbackendFactory *ALCossBackendFactory_getFactory(void)
 
 
 ALCboolean ALCossBackendFactory_init(ALCossBackendFactory* UNUSED(self))
 ALCboolean ALCossBackendFactory_init(ALCossBackendFactory* UNUSED(self))
 {
 {
-    ConfigValueStr("oss", "device", &oss_driver);
-    ConfigValueStr("oss", "capture", &oss_capture);
+    ConfigValueStr(NULL, "oss", "device", &oss_driver);
+    ConfigValueStr(NULL, "oss", "capture", &oss_capture);
 
 
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
@@ -606,25 +606,15 @@ ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory* UNUSED(self
     if(type == ALCbackend_Playback)
     if(type == ALCbackend_Playback)
     {
     {
         ALCplaybackOSS *backend;
         ALCplaybackOSS *backend;
-
-        backend = ALCplaybackOSS_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCplaybackOSS)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCplaybackOSS_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
     if(type == ALCbackend_Capture)
     if(type == ALCbackend_Capture)
     {
     {
         ALCcaptureOSS *backend;
         ALCcaptureOSS *backend;
-
-        backend = ALCcaptureOSS_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCcaptureOSS)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCcaptureOSS_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 

+ 259 - 155
libs/openal-soft/Alc/backends/portaudio.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -28,6 +28,8 @@
 #include "alu.h"
 #include "alu.h"
 #include "compat.h"
 #include "compat.h"
 
 
+#include "backends/base.h"
+
 #include <portaudio.h>
 #include <portaudio.h>
 
 
 
 
@@ -122,149 +124,171 @@ static ALCboolean pa_load(void)
 }
 }
 
 
 
 
-typedef struct {
+typedef struct ALCportPlayback {
+    DERIVE_FROM_TYPE(ALCbackend);
+
     PaStream *stream;
     PaStream *stream;
     PaStreamParameters params;
     PaStreamParameters params;
     ALuint update_size;
     ALuint update_size;
+} ALCportPlayback;
+
+static int ALCportPlayback_WriteCallback(const void *inputBuffer, void *outputBuffer,
+    unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
+    const PaStreamCallbackFlags statusFlags, void *userData);
+
+static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device);
+static void ALCportPlayback_Destruct(ALCportPlayback *self);
+static ALCenum ALCportPlayback_open(ALCportPlayback *self, const ALCchar *name);
+static void ALCportPlayback_close(ALCportPlayback *self);
+static ALCboolean ALCportPlayback_reset(ALCportPlayback *self);
+static ALCboolean ALCportPlayback_start(ALCportPlayback *self);
+static void ALCportPlayback_stop(ALCportPlayback *self);
+static DECLARE_FORWARD2(ALCportPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
+static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCportPlayback, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCportPlayback, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCportPlayback)
+
+DEFINE_ALCBACKEND_VTABLE(ALCportPlayback);
+
+
+static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCportPlayback, ALCbackend, self);
 
 
-    RingBuffer *ring;
-} pa_data;
-
+    self->stream = NULL;
+}
 
 
-static int pa_callback(const void *UNUSED(inputBuffer), void *outputBuffer,
-                       unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
-                       const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
+static void ALCportPlayback_Destruct(ALCportPlayback *self)
 {
 {
-    ALCdevice *device = (ALCdevice*)userData;
+    if(self->stream)
+        Pa_CloseStream(self->stream);
+    self->stream = NULL;
 
 
-    aluMixData(device, outputBuffer, framesPerBuffer);
-    return 0;
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 }
 
 
-static int pa_capture_cb(const void *inputBuffer, void *UNUSED(outputBuffer),
-                         unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
-                         const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
+
+static int ALCportPlayback_WriteCallback(const void *UNUSED(inputBuffer), void *outputBuffer,
+    unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
+    const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
 {
 {
-    ALCdevice *device = (ALCdevice*)userData;
-    pa_data *data = (pa_data*)device->ExtraData;
+    ALCportPlayback *self = userData;
 
 
-    WriteRingBuffer(data->ring, inputBuffer, framesPerBuffer);
+    aluMixData(STATIC_CAST(ALCbackend, self)->mDevice, outputBuffer, framesPerBuffer);
     return 0;
     return 0;
 }
 }
 
 
 
 
-static ALCenum pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
+static ALCenum ALCportPlayback_open(ALCportPlayback *self, const ALCchar *name)
 {
 {
-    pa_data *data;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     PaError err;
     PaError err;
 
 
-    if(!deviceName)
-        deviceName = pa_device;
-    else if(strcmp(deviceName, pa_device) != 0)
+    if(!name)
+        name = pa_device;
+    else if(strcmp(name, pa_device) != 0)
         return ALC_INVALID_VALUE;
         return ALC_INVALID_VALUE;
 
 
-    data = (pa_data*)calloc(1, sizeof(pa_data));
-    data->update_size = device->UpdateSize;
+    self->update_size = device->UpdateSize;
 
 
-    data->params.device = -1;
-    if(!ConfigValueInt("port", "device", &data->params.device) ||
-       data->params.device < 0)
-        data->params.device = Pa_GetDefaultOutputDevice();
-    data->params.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
+    self->params.device = -1;
+    if(!ConfigValueInt(NULL, "port", "device", &self->params.device) ||
+       self->params.device < 0)
+        self->params.device = Pa_GetDefaultOutputDevice();
+    self->params.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
                                     (float)device->Frequency;
                                     (float)device->Frequency;
-    data->params.hostApiSpecificStreamInfo = NULL;
+    self->params.hostApiSpecificStreamInfo = NULL;
 
 
-    data->params.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);
+    self->params.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);
 
 
     switch(device->FmtType)
     switch(device->FmtType)
     {
     {
         case DevFmtByte:
         case DevFmtByte:
-            data->params.sampleFormat = paInt8;
+            self->params.sampleFormat = paInt8;
             break;
             break;
         case DevFmtUByte:
         case DevFmtUByte:
-            data->params.sampleFormat = paUInt8;
+            self->params.sampleFormat = paUInt8;
             break;
             break;
         case DevFmtUShort:
         case DevFmtUShort:
             /* fall-through */
             /* fall-through */
         case DevFmtShort:
         case DevFmtShort:
-            data->params.sampleFormat = paInt16;
+            self->params.sampleFormat = paInt16;
             break;
             break;
         case DevFmtUInt:
         case DevFmtUInt:
             /* fall-through */
             /* fall-through */
         case DevFmtInt:
         case DevFmtInt:
-            data->params.sampleFormat = paInt32;
+            self->params.sampleFormat = paInt32;
             break;
             break;
         case DevFmtFloat:
         case DevFmtFloat:
-            data->params.sampleFormat = paFloat32;
+            self->params.sampleFormat = paFloat32;
             break;
             break;
     }
     }
 
 
 retry_open:
 retry_open:
-    err = Pa_OpenStream(&data->stream, NULL, &data->params, device->Frequency,
-                        device->UpdateSize, paNoFlag, pa_callback, device);
+    err = Pa_OpenStream(&self->stream, NULL, &self->params,
+        device->Frequency, device->UpdateSize, paNoFlag,
+        ALCportPlayback_WriteCallback, self
+    );
     if(err != paNoError)
     if(err != paNoError)
     {
     {
-        if(data->params.sampleFormat == paFloat32)
+        if(self->params.sampleFormat == paFloat32)
         {
         {
-            data->params.sampleFormat = paInt16;
+            self->params.sampleFormat = paInt16;
             goto retry_open;
             goto retry_open;
         }
         }
         ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
         ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
-        free(data);
         return ALC_INVALID_VALUE;
         return ALC_INVALID_VALUE;
     }
     }
 
 
-    device->ExtraData = data;
-    al_string_copy_cstr(&device->DeviceName, deviceName);
+    al_string_copy_cstr(&device->DeviceName, name);
 
 
     return ALC_NO_ERROR;
     return ALC_NO_ERROR;
+
 }
 }
 
 
-static void pa_close_playback(ALCdevice *device)
+static void ALCportPlayback_close(ALCportPlayback *self)
 {
 {
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_CloseStream(data->stream);
+    PaError err = Pa_CloseStream(self->stream);
     if(err != paNoError)
     if(err != paNoError)
         ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
         ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
-
-    free(data);
-    device->ExtraData = NULL;
+    self->stream = NULL;
 }
 }
 
 
-static ALCboolean pa_reset_playback(ALCdevice *device)
+static ALCboolean ALCportPlayback_reset(ALCportPlayback *self)
 {
 {
-    pa_data *data = (pa_data*)device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     const PaStreamInfo *streamInfo;
     const PaStreamInfo *streamInfo;
 
 
-    streamInfo = Pa_GetStreamInfo(data->stream);
+    streamInfo = Pa_GetStreamInfo(self->stream);
     device->Frequency = streamInfo->sampleRate;
     device->Frequency = streamInfo->sampleRate;
-    device->UpdateSize = data->update_size;
+    device->UpdateSize = self->update_size;
 
 
-    if(data->params.sampleFormat == paInt8)
+    if(self->params.sampleFormat == paInt8)
         device->FmtType = DevFmtByte;
         device->FmtType = DevFmtByte;
-    else if(data->params.sampleFormat == paUInt8)
+    else if(self->params.sampleFormat == paUInt8)
         device->FmtType = DevFmtUByte;
         device->FmtType = DevFmtUByte;
-    else if(data->params.sampleFormat == paInt16)
+    else if(self->params.sampleFormat == paInt16)
         device->FmtType = DevFmtShort;
         device->FmtType = DevFmtShort;
-    else if(data->params.sampleFormat == paInt32)
+    else if(self->params.sampleFormat == paInt32)
         device->FmtType = DevFmtInt;
         device->FmtType = DevFmtInt;
-    else if(data->params.sampleFormat == paFloat32)
+    else if(self->params.sampleFormat == paFloat32)
         device->FmtType = DevFmtFloat;
         device->FmtType = DevFmtFloat;
     else
     else
     {
     {
-        ERR("Unexpected sample format: 0x%lx\n", data->params.sampleFormat);
+        ERR("Unexpected sample format: 0x%lx\n", self->params.sampleFormat);
         return ALC_FALSE;
         return ALC_FALSE;
     }
     }
 
 
-    if(data->params.channelCount == 2)
+    if(self->params.channelCount == 2)
         device->FmtChans = DevFmtStereo;
         device->FmtChans = DevFmtStereo;
-    else if(data->params.channelCount == 1)
+    else if(self->params.channelCount == 1)
         device->FmtChans = DevFmtMono;
         device->FmtChans = DevFmtMono;
     else
     else
     {
     {
-        ERR("Unexpected channel count: %u\n", data->params.channelCount);
+        ERR("Unexpected channel count: %u\n", self->params.channelCount);
         return ALC_FALSE;
         return ALC_FALSE;
     }
     }
     SetDefaultChannelOrder(device);
     SetDefaultChannelOrder(device);
@@ -272,12 +296,11 @@ static ALCboolean pa_reset_playback(ALCdevice *device)
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
-static ALCboolean pa_start_playback(ALCdevice *device)
+static ALCboolean ALCportPlayback_start(ALCportPlayback *self)
 {
 {
-    pa_data *data = (pa_data*)device->ExtraData;
     PaError err;
     PaError err;
 
 
-    err = Pa_StartStream(data->stream);
+    err = Pa_StartStream(self->stream);
     if(err != paNoError)
     if(err != paNoError)
     {
     {
         ERR("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err));
         ERR("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err));
@@ -287,161 +310,209 @@ static ALCboolean pa_start_playback(ALCdevice *device)
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
-static void pa_stop_playback(ALCdevice *device)
+static void ALCportPlayback_stop(ALCportPlayback *self)
 {
 {
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_StopStream(data->stream);
+    PaError err = Pa_StopStream(self->stream);
     if(err != paNoError)
     if(err != paNoError)
         ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
         ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
 }
 }
 
 
 
 
-static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
+typedef struct ALCportCapture {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    PaStream *stream;
+    PaStreamParameters params;
+
+    ll_ringbuffer_t *ring;
+} ALCportCapture;
+
+static int ALCportCapture_ReadCallback(const void *inputBuffer, void *outputBuffer,
+    unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
+    const PaStreamCallbackFlags statusFlags, void *userData);
+
+static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device);
+static void ALCportCapture_Destruct(ALCportCapture *self);
+static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name);
+static void ALCportCapture_close(ALCportCapture *self);
+static DECLARE_FORWARD(ALCportCapture, ALCbackend, ALCboolean, reset)
+static ALCboolean ALCportCapture_start(ALCportCapture *self);
+static void ALCportCapture_stop(ALCportCapture *self);
+static ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALCuint ALCportCapture_availableSamples(ALCportCapture *self);
+static DECLARE_FORWARD(ALCportCapture, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCportCapture, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCportCapture, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCportCapture)
+
+DEFINE_ALCBACKEND_VTABLE(ALCportCapture);
+
+
+static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCportCapture, ALCbackend, self);
+
+    self->stream = NULL;
+}
+
+static void ALCportCapture_Destruct(ALCportCapture *self)
+{
+    if(self->stream)
+        Pa_CloseStream(self->stream);
+    self->stream = NULL;
+
+    if(self->ring)
+        ll_ringbuffer_free(self->ring);
+    self->ring = NULL;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static int ALCportCapture_ReadCallback(const void *inputBuffer, void *UNUSED(outputBuffer),
+    unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
+    const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
+{
+    ALCportCapture *self = userData;
+    size_t writable = ll_ringbuffer_write_space(self->ring);
+
+    if(framesPerBuffer > writable)
+        framesPerBuffer = writable;
+    ll_ringbuffer_write(self->ring, inputBuffer, framesPerBuffer);
+    return 0;
+}
+
+
+static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name)
 {
 {
-    ALuint frame_size;
-    pa_data *data;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ALuint samples, frame_size;
     PaError err;
     PaError err;
 
 
-    if(!deviceName)
-        deviceName = pa_device;
-    else if(strcmp(deviceName, pa_device) != 0)
+    if(!name)
+        name = pa_device;
+    else if(strcmp(name, pa_device) != 0)
         return ALC_INVALID_VALUE;
         return ALC_INVALID_VALUE;
 
 
-    data = (pa_data*)calloc(1, sizeof(pa_data));
-    if(data == NULL)
-        return ALC_OUT_OF_MEMORY;
-
+    samples = device->UpdateSize * device->NumUpdates;
+    samples = maxu(samples, 100 * device->Frequency / 1000);
     frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
     frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-    data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates);
-    if(data->ring == NULL)
-        goto error;
 
 
-    data->params.device = -1;
-    if(!ConfigValueInt("port", "capture", &data->params.device) ||
-       data->params.device < 0)
-        data->params.device = Pa_GetDefaultInputDevice();
-    data->params.suggestedLatency = 0.0f;
-    data->params.hostApiSpecificStreamInfo = NULL;
+    self->ring = ll_ringbuffer_create(samples, frame_size);
+    if(self->ring == NULL) return ALC_INVALID_VALUE;
+
+    self->params.device = -1;
+    if(!ConfigValueInt(NULL, "port", "capture", &self->params.device) ||
+       self->params.device < 0)
+        self->params.device = Pa_GetDefaultInputDevice();
+    self->params.suggestedLatency = 0.0f;
+    self->params.hostApiSpecificStreamInfo = NULL;
 
 
     switch(device->FmtType)
     switch(device->FmtType)
     {
     {
         case DevFmtByte:
         case DevFmtByte:
-            data->params.sampleFormat = paInt8;
+            self->params.sampleFormat = paInt8;
             break;
             break;
         case DevFmtUByte:
         case DevFmtUByte:
-            data->params.sampleFormat = paUInt8;
+            self->params.sampleFormat = paUInt8;
             break;
             break;
         case DevFmtShort:
         case DevFmtShort:
-            data->params.sampleFormat = paInt16;
+            self->params.sampleFormat = paInt16;
             break;
             break;
         case DevFmtInt:
         case DevFmtInt:
-            data->params.sampleFormat = paInt32;
+            self->params.sampleFormat = paInt32;
             break;
             break;
         case DevFmtFloat:
         case DevFmtFloat:
-            data->params.sampleFormat = paFloat32;
+            self->params.sampleFormat = paFloat32;
             break;
             break;
         case DevFmtUInt:
         case DevFmtUInt:
         case DevFmtUShort:
         case DevFmtUShort:
             ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
             ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
-            goto error;
+            return ALC_INVALID_VALUE;
     }
     }
-    data->params.channelCount = ChannelsFromDevFmt(device->FmtChans);
+    self->params.channelCount = ChannelsFromDevFmt(device->FmtChans);
 
 
-    err = Pa_OpenStream(&data->stream, &data->params, NULL, device->Frequency,
-                        paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device);
+    err = Pa_OpenStream(&self->stream, &self->params, NULL,
+        device->Frequency, paFramesPerBufferUnspecified, paNoFlag,
+        ALCportCapture_ReadCallback, self
+    );
     if(err != paNoError)
     if(err != paNoError)
     {
     {
         ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
         ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
-        goto error;
+        return ALC_INVALID_VALUE;
     }
     }
 
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
+    al_string_copy_cstr(&device->DeviceName, name);
 
 
-    device->ExtraData = data;
     return ALC_NO_ERROR;
     return ALC_NO_ERROR;
-
-error:
-    DestroyRingBuffer(data->ring);
-    free(data);
-    return ALC_INVALID_VALUE;
 }
 }
 
 
-static void pa_close_capture(ALCdevice *device)
+static void ALCportCapture_close(ALCportCapture *self)
 {
 {
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_CloseStream(data->stream);
+    PaError err = Pa_CloseStream(self->stream);
     if(err != paNoError)
     if(err != paNoError)
         ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
         ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
+    self->stream = NULL;
 
 
-    DestroyRingBuffer(data->ring);
-    data->ring = NULL;
-
-    free(data);
-    device->ExtraData = NULL;
+    ll_ringbuffer_free(self->ring);
+    self->ring = NULL;
 }
 }
 
 
-static void pa_start_capture(ALCdevice *device)
-{
-    pa_data *data = device->ExtraData;
-    PaError err;
 
 
-    err = Pa_StartStream(data->stream);
+static ALCboolean ALCportCapture_start(ALCportCapture *self)
+{
+    PaError err = Pa_StartStream(self->stream);
     if(err != paNoError)
     if(err != paNoError)
+    {
         ERR("Error starting stream: %s\n", Pa_GetErrorText(err));
         ERR("Error starting stream: %s\n", Pa_GetErrorText(err));
+        return ALC_FALSE;
+    }
+    return ALC_TRUE;
 }
 }
 
 
-static void pa_stop_capture(ALCdevice *device)
+static void ALCportCapture_stop(ALCportCapture *self)
 {
 {
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_StopStream(data->stream);
+    PaError err = Pa_StopStream(self->stream);
     if(err != paNoError)
     if(err != paNoError)
         ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
         ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
 }
 }
 
 
-static ALCenum pa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
+
+static ALCuint ALCportCapture_availableSamples(ALCportCapture *self)
 {
 {
-    pa_data *data = device->ExtraData;
-    ReadRingBuffer(data->ring, buffer, samples);
-    return ALC_NO_ERROR;
+    return ll_ringbuffer_read_space(self->ring);
 }
 }
 
 
-static ALCuint pa_available_samples(ALCdevice *device)
+static ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples)
 {
 {
-    pa_data *data = device->ExtraData;
-    return RingBufferSize(data->ring);
+    ll_ringbuffer_read(self->ring, buffer, samples);
+    return ALC_NO_ERROR;
 }
 }
 
 
 
 
-static const BackendFuncs pa_funcs = {
-    pa_open_playback,
-    pa_close_playback,
-    pa_reset_playback,
-    pa_start_playback,
-    pa_stop_playback,
-    pa_open_capture,
-    pa_close_capture,
-    pa_start_capture,
-    pa_stop_capture,
-    pa_capture_samples,
-    pa_available_samples,
-    ALCdevice_GetLatencyDefault
-};
-
-ALCboolean alc_pa_init(BackendFuncs *func_list)
+typedef struct ALCportBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCportBackendFactory;
+#define ALCPORTBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCportBackendFactory, ALCbackendFactory) } }
+
+static ALCboolean ALCportBackendFactory_init(ALCportBackendFactory *self);
+static void ALCportBackendFactory_deinit(ALCportBackendFactory *self);
+static ALCboolean ALCportBackendFactory_querySupport(ALCportBackendFactory *self, ALCbackend_Type type);
+static void ALCportBackendFactory_probe(ALCportBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCportBackendFactory_createBackend(ALCportBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCportBackendFactory);
+
+
+static ALCboolean ALCportBackendFactory_init(ALCportBackendFactory* UNUSED(self))
 {
 {
     if(!pa_load())
     if(!pa_load())
         return ALC_FALSE;
         return ALC_FALSE;
-    *func_list = pa_funcs;
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
-void alc_pa_deinit(void)
+static void ALCportBackendFactory_deinit(ALCportBackendFactory* UNUSED(self))
 {
 {
 #ifdef HAVE_DYNLOAD
 #ifdef HAVE_DYNLOAD
     if(pa_handle)
     if(pa_handle)
@@ -455,7 +526,14 @@ void alc_pa_deinit(void)
 #endif
 #endif
 }
 }
 
 
-void alc_pa_probe(enum DevProbe type)
+static ALCboolean ALCportBackendFactory_querySupport(ALCportBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback || type == ALCbackend_Capture)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCportBackendFactory_probe(ALCportBackendFactory* UNUSED(self), enum DevProbe type)
 {
 {
     switch(type)
     switch(type)
     {
     {
@@ -467,3 +545,29 @@ void alc_pa_probe(enum DevProbe type)
             break;
             break;
     }
     }
 }
 }
+
+static ALCbackend* ALCportBackendFactory_createBackend(ALCportBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCportPlayback *backend;
+        NEW_OBJ(backend, ALCportPlayback)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+    if(type == ALCbackend_Capture)
+    {
+        ALCportCapture *backend;
+        NEW_OBJ(backend, ALCportCapture)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}
+
+ALCbackendFactory *ALCportBackendFactory_getFactory(void)
+{
+    static ALCportBackendFactory factory = ALCPORTBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}

+ 165 - 140
libs/openal-soft/Alc/backends/pulseaudio.c

@@ -14,8 +14,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -34,13 +34,6 @@
 
 
 #if PA_API_VERSION == 12
 #if PA_API_VERSION == 12
 
 
-#ifndef PA_CHECK_VERSION
-#define PA_CHECK_VERSION(major,minor,micro)                             \
-    ((PA_MAJOR > (major)) ||                                            \
-     (PA_MAJOR == (major) && PA_MINOR > (minor)) ||                     \
-     (PA_MAJOR == (major) && PA_MINOR == (minor) && PA_MICRO >= (micro)))
-#endif
-
 #ifdef HAVE_DYNLOAD
 #ifdef HAVE_DYNLOAD
 static void *pa_handle;
 static void *pa_handle;
 #define MAKE_FUNC(x) static __typeof(x) * p##x
 #define MAKE_FUNC(x) static __typeof(x) * p##x
@@ -108,13 +101,9 @@ MAKE_FUNC(pa_operation_unref);
 MAKE_FUNC(pa_proplist_new);
 MAKE_FUNC(pa_proplist_new);
 MAKE_FUNC(pa_proplist_free);
 MAKE_FUNC(pa_proplist_free);
 MAKE_FUNC(pa_proplist_set);
 MAKE_FUNC(pa_proplist_set);
-#if PA_CHECK_VERSION(0,9,15)
 MAKE_FUNC(pa_channel_map_superset);
 MAKE_FUNC(pa_channel_map_superset);
 MAKE_FUNC(pa_stream_set_buffer_attr_callback);
 MAKE_FUNC(pa_stream_set_buffer_attr_callback);
-#endif
-#if PA_CHECK_VERSION(0,9,16)
 MAKE_FUNC(pa_stream_begin_write);
 MAKE_FUNC(pa_stream_begin_write);
-#endif
 #undef MAKE_FUNC
 #undef MAKE_FUNC
 
 
 #define pa_context_unref ppa_context_unref
 #define pa_context_unref ppa_context_unref
@@ -181,13 +170,9 @@ MAKE_FUNC(pa_stream_begin_write);
 #define pa_proplist_new ppa_proplist_new
 #define pa_proplist_new ppa_proplist_new
 #define pa_proplist_free ppa_proplist_free
 #define pa_proplist_free ppa_proplist_free
 #define pa_proplist_set ppa_proplist_set
 #define pa_proplist_set ppa_proplist_set
-#if PA_CHECK_VERSION(0,9,15)
 #define pa_channel_map_superset ppa_channel_map_superset
 #define pa_channel_map_superset ppa_channel_map_superset
 #define pa_stream_set_buffer_attr_callback ppa_stream_set_buffer_attr_callback
 #define pa_stream_set_buffer_attr_callback ppa_stream_set_buffer_attr_callback
-#endif
-#if PA_CHECK_VERSION(0,9,16)
 #define pa_stream_begin_write ppa_stream_begin_write
 #define pa_stream_begin_write ppa_stream_begin_write
-#endif
 
 
 #endif
 #endif
 
 
@@ -278,18 +263,10 @@ static ALCboolean pulse_load(void)
         LOAD_FUNC(pa_proplist_new);
         LOAD_FUNC(pa_proplist_new);
         LOAD_FUNC(pa_proplist_free);
         LOAD_FUNC(pa_proplist_free);
         LOAD_FUNC(pa_proplist_set);
         LOAD_FUNC(pa_proplist_set);
+        LOAD_FUNC(pa_channel_map_superset);
+        LOAD_FUNC(pa_stream_set_buffer_attr_callback);
+        LOAD_FUNC(pa_stream_begin_write);
 #undef LOAD_FUNC
 #undef LOAD_FUNC
-#define LOAD_OPTIONAL_FUNC(x) do {                                            \
-    p##x = GetSymbol(pa_handle, #x);                                          \
-} while(0)
-#if PA_CHECK_VERSION(0,9,15)
-        LOAD_OPTIONAL_FUNC(pa_channel_map_superset);
-        LOAD_OPTIONAL_FUNC(pa_stream_set_buffer_attr_callback);
-#endif
-#if PA_CHECK_VERSION(0,9,16)
-        LOAD_OPTIONAL_FUNC(pa_stream_begin_write);
-#endif
-#undef LOAD_OPTIONAL_FUNC
 
 
         if(ret == ALC_FALSE)
         if(ret == ALC_FALSE)
         {
         {
@@ -428,8 +405,7 @@ error:
     return ALC_FALSE;
     return ALC_FALSE;
 }
 }
 
 
-static void pulse_close(pa_threaded_mainloop *loop, pa_context *context,
-                        pa_stream *stream)
+static void pulse_close(pa_threaded_mainloop *loop, pa_context *context, pa_stream *stream)
 {
 {
     pa_threaded_mainloop_lock(loop);
     pa_threaded_mainloop_lock(loop);
 
 
@@ -438,10 +414,7 @@ static void pulse_close(pa_threaded_mainloop *loop, pa_context *context,
         pa_stream_set_state_callback(stream, NULL, NULL);
         pa_stream_set_state_callback(stream, NULL, NULL);
         pa_stream_set_moved_callback(stream, NULL, NULL);
         pa_stream_set_moved_callback(stream, NULL, NULL);
         pa_stream_set_write_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);
-#endif
+        pa_stream_set_buffer_attr_callback(stream, NULL, NULL);
         pa_stream_disconnect(stream);
         pa_stream_disconnect(stream);
         pa_stream_unref(stream);
         pa_stream_unref(stream);
     }
     }
@@ -544,6 +517,7 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p
     pa_threaded_mainloop *loop = pdata;
     pa_threaded_mainloop *loop = pdata;
     const DevMap *iter;
     const DevMap *iter;
     DevMap entry;
     DevMap entry;
+    int count;
 
 
     if(eol)
     if(eol)
     {
     {
@@ -553,18 +527,34 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p
 
 
 #define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0)
 #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);
     VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_INFO_NAME);
+    if(iter != VECTOR_ITER_END(PlaybackDevices)) return;
 #undef MATCH_INFO_NAME
 #undef MATCH_INFO_NAME
-    if(iter != VECTOR_ITER_END(PlaybackDevices))
-        return;
-
-    TRACE("Got device \"%s\", \"%s\"\n", info->description, info->name);
 
 
     AL_STRING_INIT(entry.name);
     AL_STRING_INIT(entry.name);
     AL_STRING_INIT(entry.device_name);
     AL_STRING_INIT(entry.device_name);
 
 
-    al_string_copy_cstr(&entry.name, info->description);
     al_string_copy_cstr(&entry.device_name, info->name);
     al_string_copy_cstr(&entry.device_name, info->name);
 
 
+    count = 0;
+    while(1)
+    {
+        al_string_copy_cstr(&entry.name, info->description);
+        if(count != 0)
+        {
+            char str[64];
+            snprintf(str, sizeof(str), " #%d", count+1);
+            al_string_append_cstr(&entry.name, str);
+        }
+
+#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_ENTRY);
+        if(iter == VECTOR_ITER_END(PlaybackDevices)) break;
+#undef MATCH_ENTRY
+        count++;
+    }
+
+    TRACE("Got device \"%s\", \"%s\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.device_name));
+
     VECTOR_PUSH_BACK(PlaybackDevices, entry);
     VECTOR_PUSH_BACK(PlaybackDevices, entry);
 }
 }
 
 
@@ -660,27 +650,44 @@ static void ALCpulsePlayback_streamWriteCallback(pa_stream* UNUSED(p), size_t UN
 
 
 static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
 static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
 {
 {
-    ALCpulsePlayback *self = pdata;
-    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
-    char chanmap_str[256] = "";
-    const struct {
-        const char *str;
+    static const struct {
         enum DevFmtChannels chans;
         enum DevFmtChannels chans;
+        pa_channel_map map;
     } chanmaps[] = {
     } chanmaps[] = {
-        { "front-left,front-right,front-center,lfe,rear-left,rear-right,side-left,side-right",
-          DevFmtX71 },
-        { "front-left,front-right,front-center,lfe,rear-center,side-left,side-right",
-          DevFmtX61 },
-        { "front-left,front-right,front-center,lfe,rear-left,rear-right",
-          DevFmtX51 },
-        { "front-left,front-right,front-center,lfe,side-left,side-right",
-          DevFmtX51Side },
-        { "front-left,front-right,rear-left,rear-right", DevFmtQuad },
-        { "front-left,front-right", DevFmtStereo },
-        { "mono", DevFmtMono },
-        { NULL, 0 }
+        { DevFmtX71, { 8, {
+            PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
+            PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
+            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
+            PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT
+        } } },
+        { DevFmtX61, { 7, {
+            PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
+            PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
+            PA_CHANNEL_POSITION_REAR_CENTER,
+            PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT
+        } } },
+        { DevFmtX51, { 6, {
+            PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
+            PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
+            PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT
+        } } },
+        { DevFmtX51Rear, { 6, {
+            PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
+            PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
+            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT
+        } } },
+        { DevFmtQuad, { 4, {
+            PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
+            PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT
+        } } },
+        { DevFmtStereo, { 2, {
+            PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT
+        } } },
+        { DevFmtMono, { 1, {PA_CHANNEL_POSITION_MONO} } }
     };
     };
-    int i;
+    ALCpulsePlayback *self = pdata;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    size_t i;
 
 
     if(eol)
     if(eol)
     {
     {
@@ -688,26 +695,27 @@ static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const
         return;
         return;
     }
     }
 
 
-    for(i = 0;chanmaps[i].str;i++)
+    for(i = 0;i < COUNTOF(chanmaps);i++)
     {
     {
-        pa_channel_map map;
-        if(!pa_channel_map_parse(&map, chanmaps[i].str))
-            continue;
-
-        if(pa_channel_map_equal(&info->channel_map, &map)
-#if PA_CHECK_VERSION(0,9,15)
-           || (pa_channel_map_superset &&
-               pa_channel_map_superset(&info->channel_map, &map))
-#endif
-            )
+        if(pa_channel_map_superset(&info->channel_map, &chanmaps[i].map))
         {
         {
-            device->FmtChans = chanmaps[i].chans;
-            return;
+            if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
+                device->FmtChans = chanmaps[i].chans;
+            break;
         }
         }
     }
     }
+    if(i == COUNTOF(chanmaps))
+    {
+        char chanmap_str[PA_CHANNEL_MAP_SNPRINT_MAX] = "";
+        pa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map);
+        WARN("Failed to find format for channel map:\n    %s\n", chanmap_str);
+    }
 
 
-    pa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map);
-    ERR("Failed to find format for channel map:\n    %s\n", chanmap_str);
+    if(info->active_port)
+        TRACE("Active port: %s (%s)\n", info->active_port->name, info->active_port->description);
+    device->IsHeadphones = (info->active_port &&
+                            strcmp(info->active_port->name, "analog-output-headphones") == 0 &&
+                            device->FmtChans == DevFmtStereo);
 }
 }
 
 
 static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
 static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata)
@@ -818,10 +826,7 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
             void *buf;
             void *buf;
             pa_free_cb_t free_func = NULL;
             pa_free_cb_t free_func = NULL;
 
 
-#if PA_CHECK_VERSION(0,9,16)
-            if(!pa_stream_begin_write ||
-               pa_stream_begin_write(self->stream, &buf, &newlen) < 0)
-#endif
+            if(pa_stream_begin_write(self->stream, &buf, &newlen) < 0)
             {
             {
                 buf = pa_xmalloc(newlen);
                 buf = pa_xmalloc(newlen);
                 free_func = pa_xfree;
                 free_func = pa_xfree;
@@ -841,10 +846,10 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
 
 
 static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name)
 static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name)
 {
 {
+    const_al_string dev_name = AL_STRING_INIT_STATIC();
     const char *pulse_name = NULL;
     const char *pulse_name = NULL;
     pa_stream_flags_t flags;
     pa_stream_flags_t flags;
     pa_sample_spec spec;
     pa_sample_spec spec;
-    pa_operation *o;
 
 
     if(name)
     if(name)
     {
     {
@@ -859,6 +864,7 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name
         if(iter == VECTOR_ITER_END(PlaybackDevices))
         if(iter == VECTOR_ITER_END(PlaybackDevices))
             return ALC_INVALID_VALUE;
             return ALC_INVALID_VALUE;
         pulse_name = al_string_get_cstr(iter->device_name);
         pulse_name = al_string_get_cstr(iter->device_name);
+        dev_name = iter->name;
     }
     }
 
 
     if(!pulse_open(&self->loop, &self->context, ALCpulsePlayback_contextStateCallback, self))
     if(!pulse_open(&self->loop, &self->context, ALCpulsePlayback_contextStateCallback, self))
@@ -868,7 +874,7 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name
 
 
     flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
     flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE |
             PA_STREAM_FIX_CHANNELS;
             PA_STREAM_FIX_CHANNELS;
-    if(!GetConfigValueBool("pulse", "allow-moves", 0))
+    if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0))
         flags |= PA_STREAM_DONT_MOVE;
         flags |= PA_STREAM_DONT_MOVE;
 
 
     spec.format = PA_SAMPLE_S16NE;
     spec.format = PA_SAMPLE_S16NE;
@@ -889,10 +895,19 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name
     pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self);
     pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self);
 
 
     al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream));
     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);
+    if(al_string_empty(dev_name))
+    {
+        pa_operation *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);
+    }
+    else
+    {
+        ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+        al_string_copy(&device->DeviceName, dev_name);
+    }
 
 
     pa_threaded_mainloop_unlock(self->loop);
     pa_threaded_mainloop_unlock(self->loop);
 
 
@@ -915,37 +930,33 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
     pa_stream_flags_t flags = 0;
     pa_stream_flags_t flags = 0;
     const char *mapname = NULL;
     const char *mapname = NULL;
     pa_channel_map chanmap;
     pa_channel_map chanmap;
+    pa_operation *o;
     ALuint len;
     ALuint len;
 
 
     pa_threaded_mainloop_lock(self->loop);
     pa_threaded_mainloop_lock(self->loop);
 
 
     if(self->stream)
     if(self->stream)
     {
     {
+        pa_stream_set_state_callback(self->stream, NULL, NULL);
         pa_stream_set_moved_callback(self->stream, NULL, NULL);
         pa_stream_set_moved_callback(self->stream, NULL, NULL);
-#if PA_CHECK_VERSION(0,9,15)
-        if(pa_stream_set_buffer_attr_callback)
-            pa_stream_set_buffer_attr_callback(self->stream, NULL, NULL);
-#endif
+        pa_stream_set_write_callback(self->stream, NULL, NULL);
+        pa_stream_set_buffer_attr_callback(self->stream, NULL, NULL);
         pa_stream_disconnect(self->stream);
         pa_stream_disconnect(self->stream);
         pa_stream_unref(self->stream);
         pa_stream_unref(self->stream);
         self->stream = NULL;
         self->stream = NULL;
     }
     }
 
 
-    if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
-    {
-        pa_operation *o;
-        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);
-    }
-    if(!(device->Flags&DEVICE_FREQUENCY_REQUEST))
-        flags |= PA_STREAM_FIX_RATE;
+    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);
 
 
+    if(GetConfigValueBool(al_string_get_cstr(device->DeviceName), "pulse", "fix-rate", 0) ||
+       !(device->Flags&DEVICE_FREQUENCY_REQUEST))
+        flags |= PA_STREAM_FIX_RATE;
     flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
     flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE;
     flags |= PA_STREAM_ADJUST_LATENCY;
     flags |= PA_STREAM_ADJUST_LATENCY;
     flags |= PA_STREAM_START_CORKED;
     flags |= PA_STREAM_START_CORKED;
-    if(!GetConfigValueBool("pulse", "allow-moves", 0))
+    if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0))
         flags |= PA_STREAM_DONT_MOVE;
         flags |= PA_STREAM_DONT_MOVE;
 
 
     switch(device->FmtType)
     switch(device->FmtType)
@@ -987,6 +998,9 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
         case DevFmtMono:
         case DevFmtMono:
             mapname = "mono";
             mapname = "mono";
             break;
             break;
+        case DevFmtBFormat3D:
+            device->FmtChans = DevFmtStereo;
+            /*fall-through*/
         case DevFmtStereo:
         case DevFmtStereo:
             mapname = "front-left,front-right";
             mapname = "front-left,front-right";
             break;
             break;
@@ -994,11 +1008,11 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
             mapname = "front-left,front-right,rear-left,rear-right";
             mapname = "front-left,front-right,rear-left,rear-right";
             break;
             break;
         case DevFmtX51:
         case DevFmtX51:
-            mapname = "front-left,front-right,front-center,lfe,rear-left,rear-right";
-            break;
-        case DevFmtX51Side:
             mapname = "front-left,front-right,front-center,lfe,side-left,side-right";
             mapname = "front-left,front-right,front-center,lfe,side-left,side-right";
             break;
             break;
+        case DevFmtX51Rear:
+            mapname = "front-left,front-right,front-center,lfe,rear-left,rear-right";
+            break;
         case DevFmtX61:
         case DevFmtX61:
             mapname = "front-left,front-right,front-center,lfe,rear-center,side-left,side-right";
             mapname = "front-left,front-right,front-center,lfe,rear-center,side-left,side-right";
             break;
             break;
@@ -1035,8 +1049,6 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
     self->spec = *(pa_stream_get_sample_spec(self->stream));
     self->spec = *(pa_stream_get_sample_spec(self->stream));
     if(device->Frequency != self->spec.rate)
     if(device->Frequency != self->spec.rate)
     {
     {
-        pa_operation *o;
-
         /* Server updated our playback rate, so modify the buffer attribs
         /* Server updated our playback rate, so modify the buffer attribs
          * accordingly. */
          * accordingly. */
         device->NumUpdates = (ALuint)((ALdouble)device->NumUpdates / device->Frequency *
         device->NumUpdates = (ALuint)((ALdouble)device->NumUpdates / device->Frequency *
@@ -1053,15 +1065,10 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
         device->Frequency = self->spec.rate;
         device->Frequency = self->spec.rate;
     }
     }
 
 
-#if PA_CHECK_VERSION(0,9,15)
-    if(pa_stream_set_buffer_attr_callback)
-        pa_stream_set_buffer_attr_callback(self->stream, ALCpulsePlayback_bufferAttrCallback, self);
-#endif
+    pa_stream_set_buffer_attr_callback(self->stream, ALCpulsePlayback_bufferAttrCallback, self);
     ALCpulsePlayback_bufferAttrCallback(self->stream, self);
     ALCpulsePlayback_bufferAttrCallback(self->stream, self);
 
 
     len = self->attr.minreq / pa_frame_size(&self->spec);
     len = self->attr.minreq / pa_frame_size(&self->spec);
-    if((CPUCapFlags&CPU_CAP_SSE))
-        len = (len+3)&~3;
     device->NumUpdates = (ALuint)((ALdouble)device->NumUpdates/len*device->UpdateSize + 0.5);
     device->NumUpdates = (ALuint)((ALdouble)device->NumUpdates/len*device->UpdateSize + 0.5);
     device->NumUpdates = clampu(device->NumUpdates, 2, 16);
     device->NumUpdates = clampu(device->NumUpdates, 2, 16);
     device->UpdateSize = len;
     device->UpdateSize = len;
@@ -1083,10 +1090,18 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self)
     pa_operation *o;
     pa_operation *o;
     int res;
     int res;
 
 
-    if(!self->stream)
+    if(!self->stream || self->killNow)
         return;
         return;
 
 
     self->killNow = AL_TRUE;
     self->killNow = AL_TRUE;
+    /* Signal the main loop in case PulseAudio isn't sending us audio requests
+     * (e.g. if the device is suspended). We need to lock the mainloop in case
+     * the mixer is between checking the killNow flag but before waiting for
+     * the signal.
+     */
+    pa_threaded_mainloop_lock(self->loop);
+    pa_threaded_mainloop_unlock(self->loop);
+    pa_threaded_mainloop_signal(self->loop, 0);
     althrd_join(self->thread, &res);
     althrd_join(self->thread, &res);
 
 
     pa_threaded_mainloop_lock(self->loop);
     pa_threaded_mainloop_lock(self->loop);
@@ -1199,6 +1214,7 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa
     pa_threaded_mainloop *loop = pdata;
     pa_threaded_mainloop *loop = pdata;
     const DevMap *iter;
     const DevMap *iter;
     DevMap entry;
     DevMap entry;
+    int count;
 
 
     if(eol)
     if(eol)
     {
     {
@@ -1208,18 +1224,34 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa
 
 
 #define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0)
 #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);
     VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_INFO_NAME);
+    if(iter != VECTOR_ITER_END(CaptureDevices)) return;
 #undef MATCH_INFO_NAME
 #undef MATCH_INFO_NAME
-    if(iter != VECTOR_ITER_END(CaptureDevices))
-        return;
-
-    TRACE("Got device \"%s\", \"%s\"\n", info->description, info->name);
 
 
     AL_STRING_INIT(entry.name);
     AL_STRING_INIT(entry.name);
     AL_STRING_INIT(entry.device_name);
     AL_STRING_INIT(entry.device_name);
 
 
-    al_string_copy_cstr(&entry.name, info->description);
     al_string_copy_cstr(&entry.device_name, info->name);
     al_string_copy_cstr(&entry.device_name, info->name);
 
 
+    count = 0;
+    while(1)
+    {
+        al_string_copy_cstr(&entry.name, info->description);
+        if(count != 0)
+        {
+            char str[64];
+            snprintf(str, sizeof(str), " #%d", count+1);
+            al_string_append_cstr(&entry.name, str);
+        }
+
+#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_ENTRY);
+        if(iter == VECTOR_ITER_END(CaptureDevices)) break;
+#undef MATCH_ENTRY
+        count++;
+    }
+
+    TRACE("Got device \"%s\", \"%s\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.device_name));
+
     VECTOR_PUSH_BACK(CaptureDevices, entry);
     VECTOR_PUSH_BACK(CaptureDevices, entry);
 }
 }
 
 
@@ -1372,7 +1404,6 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
     const char *pulse_name = NULL;
     const char *pulse_name = NULL;
     pa_stream_flags_t flags = 0;
     pa_stream_flags_t flags = 0;
     pa_channel_map chanmap;
     pa_channel_map chanmap;
-    pa_operation *o;
     ALuint samples;
     ALuint samples;
 
 
     if(name)
     if(name)
@@ -1388,6 +1419,7 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
         if(iter == VECTOR_ITER_END(CaptureDevices))
         if(iter == VECTOR_ITER_END(CaptureDevices))
             return ALC_INVALID_VALUE;
             return ALC_INVALID_VALUE;
         pulse_name = al_string_get_cstr(iter->device_name);
         pulse_name = al_string_get_cstr(iter->device_name);
+        al_string_copy(&device->DeviceName, iter->name);
     }
     }
 
 
     if(!pulse_open(&self->loop, &self->context, ALCpulseCapture_contextStateCallback, self))
     if(!pulse_open(&self->loop, &self->context, ALCpulseCapture_contextStateCallback, self))
@@ -1445,7 +1477,7 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
                           pa_frame_size(&self->spec);
                           pa_frame_size(&self->spec);
 
 
     flags |= PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY;
     flags |= PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY;
-    if(!GetConfigValueBool("pulse", "allow-moves", 0))
+    if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0))
         flags |= PA_STREAM_DONT_MOVE;
         flags |= PA_STREAM_DONT_MOVE;
 
 
     TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)");
     TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)");
@@ -1461,10 +1493,14 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name)
     pa_stream_set_state_callback(self->stream, ALCpulseCapture_streamStateCallback, self);
     pa_stream_set_state_callback(self->stream, ALCpulseCapture_streamStateCallback, self);
 
 
     al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream));
     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);
+    if(al_string_empty(device->DeviceName))
+    {
+        pa_operation *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);
+    }
 
 
     pa_threaded_mainloop_unlock(self->loop);
     pa_threaded_mainloop_unlock(self->loop);
     return ALC_NO_ERROR;
     return ALC_NO_ERROR;
@@ -1607,11 +1643,6 @@ static void ALCpulseCapture_unlock(ALCpulseCapture *self)
 }
 }
 
 
 
 
-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 {
 typedef struct ALCpulseBackendFactory {
     DERIVE_FROM_TYPE(ALCbackendFactory);
     DERIVE_FROM_TYPE(ALCbackendFactory);
 } ALCpulseBackendFactory;
 } ALCpulseBackendFactory;
@@ -1638,7 +1669,7 @@ static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(sel
         pa_threaded_mainloop *loop;
         pa_threaded_mainloop *loop;
 
 
         pulse_ctx_flags = 0;
         pulse_ctx_flags = 0;
-        if(!GetConfigValueBool("pulse", "spawn-server", 1))
+        if(!GetConfigValueBool(NULL, "pulse", "spawn-server", 1))
             pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN;
             pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN;
 
 
         if((loop=pa_threaded_mainloop_new()) &&
         if((loop=pa_threaded_mainloop_new()) &&
@@ -1701,12 +1732,16 @@ static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), e
     {
     {
         case ALL_DEVICE_PROBE:
         case ALL_DEVICE_PROBE:
             ALCpulsePlayback_probeDevices();
             ALCpulsePlayback_probeDevices();
-            VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2);
+#define APPEND_ALL_DEVICES_LIST(e)  AppendAllDevicesList(al_string_get_cstr((e)->name))
+            VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_ALL_DEVICES_LIST);
+#undef APPEND_ALL_DEVICES_LIST
             break;
             break;
 
 
         case CAPTURE_DEVICE_PROBE:
         case CAPTURE_DEVICE_PROBE:
             ALCpulseCapture_probeDevices();
             ALCpulseCapture_probeDevices();
-            VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2);
+#define APPEND_CAPTURE_DEVICE_LIST(e) AppendCaptureDeviceList(al_string_get_cstr((e)->name))
+            VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_CAPTURE_DEVICE_LIST);
+#undef APPEND_CAPTURE_DEVICE_LIST
             break;
             break;
     }
     }
 }
 }
@@ -1716,25 +1751,15 @@ static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory*
     if(type == ALCbackend_Playback)
     if(type == ALCbackend_Playback)
     {
     {
         ALCpulsePlayback *backend;
         ALCpulsePlayback *backend;
-
-        backend = ALCpulsePlayback_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCpulsePlayback)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCpulsePlayback_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
     if(type == ALCbackend_Capture)
     if(type == ALCbackend_Capture)
     {
     {
         ALCpulseCapture *backend;
         ALCpulseCapture *backend;
-
-        backend = ALCpulseCapture_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCpulseCapture)(device);
         if(!backend) return NULL;
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCpulseCapture_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
         return STATIC_CAST(ALCbackend, backend);
     }
     }
 
 

+ 108 - 352
libs/openal-soft/Alc/backends/qsa.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -53,12 +53,12 @@ typedef struct {
     int card;
     int card;
     int dev;
     int dev;
 } DevMap;
 } DevMap;
+TYPEDEF_VECTOR(DevMap, vector_DevMap)
+
+static vector_DevMap DeviceNameMap;
+static vector_DevMap CaptureNameMap;
 
 
 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;
     int32_t format;
@@ -104,69 +104,57 @@ static const struct {
     {0},
     {0},
 };
 };
 
 
-static DevMap *deviceList(int type, ALuint *count)
+static void deviceList(int type, vector_DevMap *devmap)
 {
 {
     snd_ctl_t* handle;
     snd_ctl_t* handle;
     snd_pcm_info_t pcminfo;
     snd_pcm_info_t pcminfo;
-    int max_cards, card, err, dev, num_devices, idx;
-    DevMap* dev_list;
+    int max_cards, card, err, dev;
+    DevMap entry;
     char name[1024];
     char name[1024];
     struct snd_ctl_hw_info info;
     struct snd_ctl_hw_info info;
-    void* temp;
 
 
-    idx=0;
-    num_devices=0;
-    max_cards=snd_cards();
+    max_cards = snd_cards();
+    if(max_cards < 0)
+        return;
 
 
-    if (max_cards<=0)
-    {
-        return 0;
-    }
+    VECTOR_RESERVE(*devmap, max_cards+1);
+    VECTOR_RESIZE(*devmap, 0);
 
 
-    dev_list=malloc(sizeof(DevMap)*1);
-    dev_list[0].name=strdup(qsaDevice);
-    num_devices=1;
+    entry.name = strdup(qsaDevice);
+    entry.card = 0;
+    entry.dev = 0;
+    VECTOR_PUSH_BACK(*devmap, entry);
 
 
-    for (card=0; card<max_cards; card++)
+    for(card = 0;card < max_cards;card++)
     {
     {
-        if ((err=snd_ctl_open(&handle, card))<0)
-        {
+        if((err=snd_ctl_open(&handle, card)) < 0)
             continue;
             continue;
-        }
-        if ((err=snd_ctl_hw_info(handle, &info))<0)
+
+        if((err=snd_ctl_hw_info(handle, &info)) < 0)
         {
         {
             snd_ctl_close(handle);
             snd_ctl_close(handle);
             continue;
             continue;
         }
         }
 
 
-        for (dev=0; dev<(int)info.pcmdevs; dev++)
+        for(dev = 0;dev < (int)info.pcmdevs;dev++)
         {
         {
-            if ((err=snd_ctl_pcm_info(handle, dev, &pcminfo)) < 0)
-            {
+            if((err=snd_ctl_pcm_info(handle, dev, &pcminfo)) < 0)
                 continue;
                 continue;
-            }
 
 
-            if ((type==SND_PCM_CHANNEL_PLAYBACK && (pcminfo.flags&SND_PCM_INFO_PLAYBACK)) ||
-                (type==SND_PCM_CHANNEL_CAPTURE && (pcminfo.flags&SND_PCM_INFO_CAPTURE)))
+            if((type==SND_PCM_CHANNEL_PLAYBACK && (pcminfo.flags&SND_PCM_INFO_PLAYBACK)) ||
+               (type==SND_PCM_CHANNEL_CAPTURE && (pcminfo.flags&SND_PCM_INFO_CAPTURE)))
             {
             {
-                temp=realloc(dev_list, sizeof(DevMap)*(num_devices+1));
-                if (temp)
-                {
-                    dev_list=temp;
-                    snprintf(name, sizeof(name), "%s [%s] (hw:%d,%d)", info.name, pcminfo.name, card, dev);
-                    dev_list[num_devices].name=strdup(name);
-                    dev_list[num_devices].card=card;
-                    dev_list[num_devices].dev=dev;
-                    num_devices++;
-                }
+                snprintf(name, sizeof(name), "%s [%s] (hw:%d,%d)", info.name, pcminfo.name, card, dev);
+                entry.name = strdup(name);
+                entry.card = card;
+                entry.dev = dev;
+
+                VECTOR_PUSH_BACK(*devmap, entry);
+                TRACE("Got device \"%s\", card %d, dev %d\n", name, card, dev);
             }
             }
         }
         }
-        snd_ctl_close (handle);
+        snd_ctl_close(handle);
     }
     }
-
-    *count=num_devices;
-
-    return dev_list;
 }
 }
 
 
 
 
@@ -266,71 +254,48 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr)
 
 
 static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName)
 static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName)
 {
 {
-    qsa_data* data;
-    char driver[64];
-    int status;
+    qsa_data *data;
     int card, dev;
     int card, dev;
+    int status;
 
 
-    strncpy(driver, GetConfigValue("qsa", "device", qsaDevice), sizeof(driver)-1);
-    driver[sizeof(driver)-1]=0;
-
-    data=(qsa_data*)calloc(1, sizeof(qsa_data));
-    if (data==NULL)
-    {
+    data = (qsa_data*)calloc(1, sizeof(qsa_data));
+    if(data == NULL)
         return ALC_OUT_OF_MEMORY;
         return ALC_OUT_OF_MEMORY;
-    }
 
 
-    if (!deviceName)
-    {
-        deviceName=driver;
-    }
+    if(!deviceName)
+        deviceName = qsaDevice;
 
 
-    if (strcmp(deviceName, qsaDevice)==0)
-    {
-        if (!deviceName)
-        {
-            deviceName=qsaDevice;
-        }
-
-        status=snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK);
-    }
+    if(strcmp(deviceName, qsaDevice) == 0)
+        status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK);
     else
     else
     {
     {
-        size_t idx;
+        const DevMap *iter;
 
 
-        if (!allDevNameMap)
-        {
-            allDevNameMap=deviceList(SND_PCM_CHANNEL_PLAYBACK, &numDevNames);
-        }
+        if(VECTOR_SIZE(DeviceNameMap) == 0)
+            deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap);
 
 
-        for (idx=0; idx<numDevNames; idx++)
-        {
-            if (allDevNameMap[idx].name && strcmp(deviceName, allDevNameMap[idx].name)==0)
-            {
-                if (idx>0)
-                {
-                    break;
-                }
-            }
-        }
-        if (idx==numDevNames)
+#define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0)
+        VECTOR_FIND_IF(iter, const DevMap, DeviceNameMap, MATCH_DEVNAME);
+#undef MATCH_DEVNAME
+        if(iter == VECTOR_ITER_END(DeviceNameMap))
         {
         {
             free(data);
             free(data);
             return ALC_INVALID_DEVICE;
             return ALC_INVALID_DEVICE;
         }
         }
 
 
-        status=snd_pcm_open(&data->pcmHandle, allDevNameMap[idx].card, allDevNameMap[idx].dev, SND_PCM_OPEN_PLAYBACK);
+        status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_PLAYBACK);
     }
     }
 
 
-    if (status<0)
+    if(status < 0)
     {
     {
         free(data);
         free(data);
         return ALC_INVALID_DEVICE;
         return ALC_INVALID_DEVICE;
     }
     }
 
 
-    data->audio_fd=snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
-    if (data->audio_fd<0)
+    data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
+    if(data->audio_fd < 0)
     {
     {
+        snd_pcm_close(data->pcmHandle);
         free(data);
         free(data);
         return ALC_INVALID_DEVICE;
         return ALC_INVALID_DEVICE;
     }
     }
@@ -633,72 +598,51 @@ static void qsa_stop_playback(ALCdevice* device)
 
 
 static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
 static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
 {
 {
-    qsa_data* data;
-    int format=-1;
-    char driver[64];
+    qsa_data *data;
     int card, dev;
     int card, dev;
+    int format=-1;
     int status;
     int status;
 
 
-    strncpy(driver, GetConfigValue("qsa", "capture", qsaDevice), sizeof(driver)-1);
-    driver[sizeof(driver)-1]=0;
-
     data=(qsa_data*)calloc(1, sizeof(qsa_data));
     data=(qsa_data*)calloc(1, sizeof(qsa_data));
     if (data==NULL)
     if (data==NULL)
     {
     {
         return ALC_OUT_OF_MEMORY;
         return ALC_OUT_OF_MEMORY;
     }
     }
 
 
-    if (!deviceName)
-    {
-        deviceName=driver;
-    }
+    if(!deviceName)
+        deviceName = qsaDevice;
 
 
-    if (strcmp(deviceName, qsaDevice)==0)
-    {
-        if (!deviceName)
-        {
-            deviceName=qsaDevice;
-        }
-
-        status=snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE);
-    }
+    if(strcmp(deviceName, qsaDevice) == 0)
+        status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE);
     else
     else
     {
     {
-        size_t idx;
+        const DevMap *iter;
 
 
-        if (!allCaptureDevNameMap)
-        {
-            allCaptureDevNameMap=deviceList(SND_PCM_CHANNEL_CAPTURE, &numDevNames);
-        }
+        if(VECTOR_SIZE(CaptureNameMap) == 0)
+            deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap);
 
 
-        for (idx=0; idx<numDevNames; idx++)
-        {
-            if (allCaptureDevNameMap[idx].name && strcmp(deviceName, allCaptureDevNameMap[idx].name)==0)
-            {
-                if (idx>0)
-                {
-                    break;
-                }
-            }
-        }
-        if (idx==numDevNames)
+#define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0)
+        VECTOR_FIND_IF(iter, const DevMap, CaptureNameMap, MATCH_DEVNAME);
+#undef MATCH_DEVNAME
+        if(iter == VECTOR_ITER_END(CaptureNameMap))
         {
         {
             free(data);
             free(data);
             return ALC_INVALID_DEVICE;
             return ALC_INVALID_DEVICE;
         }
         }
 
 
-        status=snd_pcm_open(&data->pcmHandle, allCaptureDevNameMap[idx].card, allCaptureDevNameMap[idx].dev, SND_PCM_OPEN_CAPTURE);
+        status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_CAPTURE);
     }
     }
 
 
-    if (status<0)
+    if(status < 0)
     {
     {
         free(data);
         free(data);
         return ALC_INVALID_DEVICE;
         return ALC_INVALID_DEVICE;
     }
     }
 
 
-    data->audio_fd=snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE);
-    if (data->audio_fd<0)
+    data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE);
+    if(data->audio_fd < 0)
     {
     {
+        snd_pcm_close(data->pcmHandle);
         free(data);
         free(data);
         return ALC_INVALID_DEVICE;
         return ALC_INVALID_DEVICE;
     }
     }
@@ -753,170 +697,13 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
     data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
     data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
     data->cparams.format.format=format;
     data->cparams.format.format=format;
 
 
-    if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
-    {
-        int original_rate=data->cparams.format.rate;
-        int original_voices=data->cparams.format.voices;
-        int original_format=data->cparams.format.format;
-        int it;
-        int jt;
-
-        for (it=0; it<1; it++)
-        {
-            /* Check for second pass */
-            if (it==1)
-            {
-                original_rate=ratelist[0].rate;
-                original_voices=channellist[0].channels;
-                original_format=formatlist[0].format;
-            }
-
-            do {
-                /* At first downgrade sample format */
-                jt=0;
-                do {
-                    if (formatlist[jt].format==data->cparams.format.format)
-                    {
-                        data->cparams.format.format=formatlist[jt+1].format;
-                        break;
-                    }
-                    if (formatlist[jt].format==0)
-                    {
-                        data->cparams.format.format=0;
-                        break;
-                    }
-                    jt++;
-                } while(1);
-
-                if (data->cparams.format.format==0)
-                {
-                    data->cparams.format.format=original_format;
-
-                    /* At secod downgrade sample rate */
-                    jt=0;
-                    do {
-                        if (ratelist[jt].rate==data->cparams.format.rate)
-                        {
-                            data->cparams.format.rate=ratelist[jt+1].rate;
-                            break;
-                        }
-                        if (ratelist[jt].rate==0)
-                        {
-                            data->cparams.format.rate=0;
-                            break;
-                        }
-                        jt++;
-                    } while(1);
-
-                    if (data->cparams.format.rate==0)
-                    {
-                        data->cparams.format.rate=original_rate;
-                        data->cparams.format.format=original_format;
-
-                        /* At third downgrade channels number */
-                        jt=0;
-                        do {
-                            if(channellist[jt].channels==data->cparams.format.voices)
-                            {
-                                data->cparams.format.voices=channellist[jt+1].channels;
-                                break;
-                            }
-                            if (channellist[jt].channels==0)
-                            {
-                                data->cparams.format.voices=0;
-                                break;
-                            }
-                           jt++;
-                        } while(1);
-                    }
-
-                    if (data->cparams.format.voices==0)
-                    {
-                        break;
-                    }
-                }
-
-                data->cparams.buf.block.frag_size=device->UpdateSize*
-                    data->cparams.format.voices*
-                    snd_pcm_format_width(data->cparams.format.format)/8;
-                data->cparams.buf.block.frags_max=device->NumUpdates;
-                data->cparams.buf.block.frags_min=device->NumUpdates;
-                if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
-                {
-                    continue;
-                }
-                else
-                {
-                    break;
-                }
-            } while(1);
-
-            if (data->cparams.format.voices!=0)
-            {
-                break;
-            }
-        }
-
-        if (data->cparams.format.voices==0)
-        {
-            return ALC_INVALID_VALUE;
-        }
-    }
-
-    /* now fill back to the our AL device */
-    device->Frequency=data->cparams.format.rate;
-
-    switch (data->cparams.format.voices)
+    if(snd_pcm_plugin_params(data->pcmHandle, &data->cparams) < 0)
     {
     {
-        case 1:
-             device->FmtChans=DevFmtMono;
-             break;
-        case 2:
-             device->FmtChans=DevFmtStereo;
-             break;
-        case 4:
-             device->FmtChans=DevFmtQuad;
-             break;
-        case 6:
-             device->FmtChans=DevFmtX51;
-             break;
-        case 7:
-             device->FmtChans=DevFmtX61;
-             break;
-        case 8:
-             device->FmtChans=DevFmtX71;
-             break;
-        default:
-             device->FmtChans=DevFmtMono;
-             break;
-    }
+        snd_pcm_close(data->pcmHandle);
+        free(data);
+        device->ExtraData=NULL;
 
 
-    switch (data->cparams.format.format)
-    {
-        case SND_PCM_SFMT_S8:
-             device->FmtType=DevFmtByte;
-             break;
-        case SND_PCM_SFMT_U8:
-             device->FmtType=DevFmtUByte;
-             break;
-        case SND_PCM_SFMT_S16_LE:
-             device->FmtType=DevFmtShort;
-             break;
-        case SND_PCM_SFMT_U16_LE:
-             device->FmtType=DevFmtUShort;
-             break;
-        case SND_PCM_SFMT_S32_LE:
-             device->FmtType=DevFmtInt;
-             break;
-        case SND_PCM_SFMT_U32_LE:
-             device->FmtType=DevFmtUInt;
-             break;
-        case SND_PCM_SFMT_FLOAT_LE:
-             device->FmtType=DevFmtFloat;
-             break;
-        default:
-             device->FmtType=DevFmtShort;
-             break;
+        return ALC_INVALID_VALUE;
     }
     }
 
 
     return ALC_NO_ERROR;
     return ALC_NO_ERROR;
@@ -927,9 +714,8 @@ static void qsa_close_capture(ALCdevice* device)
     qsa_data* data=(qsa_data*)device->ExtraData;
     qsa_data* data=(qsa_data*)device->ExtraData;
 
 
     if (data->pcmHandle!=NULL)
     if (data->pcmHandle!=NULL)
-    {
         snd_pcm_close(data->pcmHandle);
         snd_pcm_close(data->pcmHandle);
-    }
+
     free(data);
     free(data);
     device->ExtraData=NULL;
     device->ExtraData=NULL;
 }
 }
@@ -954,10 +740,6 @@ static void qsa_start_capture(ALCdevice* device)
     }
     }
 
 
     snd_pcm_capture_go(data->pcmHandle);
     snd_pcm_capture_go(data->pcmHandle);
-
-    device->UpdateSize=data->csetup.buf.block.frag_size/
-        (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType));
-    device->NumUpdates=data->csetup.buf.block.frags;
 }
 }
 
 
 static void qsa_stop_capture(ALCdevice* device)
 static void qsa_stop_capture(ALCdevice* device)
@@ -1073,16 +855,7 @@ static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint s
     return ALC_NO_ERROR;
     return ALC_NO_ERROR;
 }
 }
 
 
-static ALint64 qsa_get_latency(ALCdevice* device)
-{
-    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-
-    return (ALint64)(device->UpdateSize*device->NumUpdates/frame_size)*
-        1000000000/device->Frequency;
-}
-
-BackendFuncs qsa_funcs=
-{
+static const BackendFuncs qsa_funcs= {
     qsa_open_playback,
     qsa_open_playback,
     qsa_close_playback,
     qsa_close_playback,
     qsa_reset_playback,
     qsa_reset_playback,
@@ -1093,69 +866,52 @@ BackendFuncs qsa_funcs=
     qsa_start_capture,
     qsa_start_capture,
     qsa_stop_capture,
     qsa_stop_capture,
     qsa_capture_samples,
     qsa_capture_samples,
-    qsa_available_samples,
-    qsa_get_latency,
+    qsa_available_samples
 };
 };
 
 
 ALCboolean alc_qsa_init(BackendFuncs* func_list)
 ALCboolean alc_qsa_init(BackendFuncs* func_list)
 {
 {
-    *func_list=qsa_funcs;
-
+    *func_list = qsa_funcs;
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
 void alc_qsa_deinit(void)
 void alc_qsa_deinit(void)
 {
 {
-    ALuint i;
-
-    for (i=0; i<numDevNames; ++i)
-    {
-        free(allDevNameMap[i].name);
-    }
-    free(allDevNameMap);
-    allDevNameMap=NULL;
-    numDevNames=0;
+#define FREE_NAME(iter) free((iter)->name)
+    VECTOR_FOR_EACH(DevMap, DeviceNameMap, FREE_NAME);
+    VECTOR_DEINIT(DeviceNameMap);
 
 
-    for (i=0; i<numCaptureDevNames; ++i)
-    {
-        free(allCaptureDevNameMap[i].name);
-    }
-    free(allCaptureDevNameMap);
-    allCaptureDevNameMap=NULL;
-    numCaptureDevNames=0;
+    VECTOR_FOR_EACH(DevMap, CaptureNameMap, FREE_NAME);
+    VECTOR_DEINIT(CaptureNameMap);
+#undef FREE_NAME
 }
 }
 
 
 void alc_qsa_probe(enum DevProbe type)
 void alc_qsa_probe(enum DevProbe type)
 {
 {
-    ALuint i;
-
     switch (type)
     switch (type)
     {
     {
         case ALL_DEVICE_PROBE:
         case ALL_DEVICE_PROBE:
-             for (i=0; i<numDevNames; ++i)
-             {
-                 free(allDevNameMap[i].name);
-             }
-             free(allDevNameMap);
-
-             allDevNameMap=deviceList(SND_PCM_CHANNEL_PLAYBACK, &numDevNames);
-             for (i=0; i<numDevNames; ++i)
-             {
-                 AppendAllDevicesList(allDevNameMap[i].name);
-             }
-             break;
+#define FREE_NAME(iter) free((iter)->name)
+            VECTOR_FOR_EACH(DevMap, DeviceNameMap, FREE_NAME);
+#undef FREE_NAME
+            VECTOR_RESIZE(DeviceNameMap, 0);
+
+            deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap);
+#define APPEND_DEVICE(iter) AppendAllDevicesList((iter)->name)
+            VECTOR_FOR_EACH(const DevMap, DeviceNameMap, APPEND_DEVICE);
+#undef APPEND_DEVICE
+            break;
+
         case CAPTURE_DEVICE_PROBE:
         case CAPTURE_DEVICE_PROBE:
-             for (i=0; i<numCaptureDevNames; ++i)
-             {
-                 free(allCaptureDevNameMap[i].name);
-             }
-             free(allCaptureDevNameMap);
-
-             allCaptureDevNameMap=deviceList(SND_PCM_CHANNEL_CAPTURE, &numCaptureDevNames);
-             for (i=0; i<numCaptureDevNames; ++i)
-             {
-                 AppendCaptureDeviceList(allCaptureDevNameMap[i].name);
-             }
-             break;
+#define FREE_NAME(iter) free((iter)->name)
+            VECTOR_FOR_EACH(DevMap, CaptureNameMap, FREE_NAME);
+#undef FREE_NAME
+            VECTOR_RESIZE(CaptureNameMap, 0);
+
+            deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap);
+#define APPEND_DEVICE(iter) AppendCaptureDeviceList((iter)->name)
+            VECTOR_FOR_EACH(const DevMap, CaptureNameMap, APPEND_DEVICE);
+#undef APPEND_DEVICE
+            break;
     }
     }
 }
 }

+ 3 - 4
libs/openal-soft/Alc/backends/sndio.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -266,8 +266,7 @@ static const BackendFuncs sndio_funcs = {
     NULL,
     NULL,
     NULL,
     NULL,
     NULL,
     NULL,
-    NULL,
-    ALCdevice_GetLatencyDefault
+    NULL
 };
 };
 
 
 ALCboolean alc_sndio_init(BackendFuncs *func_list)
 ALCboolean alc_sndio_init(BackendFuncs *func_list)

+ 132 - 82
libs/openal-soft/Alc/backends/solaris.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -36,14 +36,14 @@
 #include "threads.h"
 #include "threads.h"
 #include "compat.h"
 #include "compat.h"
 
 
-#include <sys/audioio.h>
+#include "backends/base.h"
 
 
+#include <sys/audioio.h>
 
 
-static const ALCchar solaris_device[] = "Solaris Default";
 
 
-static const char *solaris_driver = "/dev/audio";
+typedef struct ALCsolarisBackend {
+    DERIVE_FROM_TYPE(ALCbackend);
 
 
-typedef struct {
     int fd;
     int fd;
 
 
     ALubyte *mix_data;
     ALubyte *mix_data;
@@ -51,13 +51,58 @@ typedef struct {
 
 
     volatile int killNow;
     volatile int killNow;
     althrd_t thread;
     althrd_t thread;
-} solaris_data;
+} ALCsolarisBackend;
+
+static int ALCsolarisBackend_mixerProc(void *ptr);
+
+static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *device);
+static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self);
+static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name);
+static void ALCsolarisBackend_close(ALCsolarisBackend *self);
+static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self);
+static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self);
+static void ALCsolarisBackend_stop(ALCsolarisBackend *self);
+static DECLARE_FORWARD2(ALCsolarisBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCsolarisBackend)
+
+DEFINE_ALCBACKEND_VTABLE(ALCsolarisBackend);
+
+
+static const ALCchar solaris_device[] = "Solaris Default";
+
+static const char *solaris_driver = "/dev/audio";
 
 
 
 
-static int SolarisProc(void *ptr)
+static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *device)
 {
 {
-    ALCdevice *Device = (ALCdevice*)ptr;
-    solaris_data *data = (solaris_data*)Device->ExtraData;
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCsolarisBackend, ALCbackend, self);
+
+    self->fd = -1;
+}
+
+static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self)
+{
+    if(self->fd != -1)
+        close(self->fd);
+    self->fd = -1;
+
+    free(self->mix_data);
+    self->mix_data = NULL;
+    self->data_size = 0;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static int ALCsolarisBackend_mixerProc(void *ptr)
+{
+    ALCsolarisBackend *self = ptr;
+    ALCdevice *Device = STATIC_CAST(ALCbackend,self)->mDevice;
     ALint frameSize;
     ALint frameSize;
     int wrote;
     int wrote;
 
 
@@ -66,27 +111,27 @@ static int SolarisProc(void *ptr)
 
 
     frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
     frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
 
 
-    while(!data->killNow && Device->Connected)
+    while(!self->killNow && Device->Connected)
     {
     {
-        ALint len = data->data_size;
-        ALubyte *WritePtr = data->mix_data;
+        ALint len = self->data_size;
+        ALubyte *WritePtr = self->mix_data;
 
 
         aluMixData(Device, WritePtr, len/frameSize);
         aluMixData(Device, WritePtr, len/frameSize);
-        while(len > 0 && !data->killNow)
+        while(len > 0 && !self->killNow)
         {
         {
-            wrote = write(data->fd, WritePtr, len);
+            wrote = write(self->fd, WritePtr, len);
             if(wrote < 0)
             if(wrote < 0)
             {
             {
                 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
                 if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
                 {
                 {
                     ERR("write failed: %s\n", strerror(errno));
                     ERR("write failed: %s\n", strerror(errno));
-                    ALCdevice_Lock(Device);
+                    ALCsolarisBackend_lock(self);
                     aluHandleDisconnect(Device);
                     aluHandleDisconnect(Device);
-                    ALCdevice_Unlock(Device);
+                    ALCsolarisBackend_unlock(self);
                     break;
                     break;
                 }
                 }
 
 
-                al_nssleep(0, 1000000);
+                al_nssleep(1000000);
                 continue;
                 continue;
             }
             }
 
 
@@ -99,43 +144,37 @@ static int SolarisProc(void *ptr)
 }
 }
 
 
 
 
-static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceName)
+static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name)
 {
 {
-    solaris_data *data;
+    ALCdevice *device;
 
 
-    if(!deviceName)
-        deviceName = solaris_device;
-    else if(strcmp(deviceName, solaris_device) != 0)
+    if(!name)
+        name = solaris_device;
+    else if(strcmp(name, solaris_device) != 0)
         return ALC_INVALID_VALUE;
         return ALC_INVALID_VALUE;
 
 
-    data = (solaris_data*)calloc(1, sizeof(solaris_data));
-    data->killNow = 0;
-
-    data->fd = open(solaris_driver, O_WRONLY);
-    if(data->fd == -1)
+    self->fd = open(solaris_driver, O_WRONLY);
+    if(self->fd == -1)
     {
     {
-        free(data);
         ERR("Could not open %s: %s\n", solaris_driver, strerror(errno));
         ERR("Could not open %s: %s\n", solaris_driver, strerror(errno));
         return ALC_INVALID_VALUE;
         return ALC_INVALID_VALUE;
     }
     }
 
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-    device->ExtraData = data;
+    device = STATIC_CAST(ALCbackend,self)->mDevice;
+    al_string_copy_cstr(&device->DeviceName, name);
+
     return ALC_NO_ERROR;
     return ALC_NO_ERROR;
 }
 }
 
 
-static void solaris_close_playback(ALCdevice *device)
+static void ALCsolarisBackend_close(ALCsolarisBackend *self)
 {
 {
-    solaris_data *data = (solaris_data*)device->ExtraData;
-
-    close(data->fd);
-    free(data);
-    device->ExtraData = NULL;
+    close(self->fd);
+    self->fd = -1;
 }
 }
 
 
-static ALCboolean solaris_reset_playback(ALCdevice *device)
+static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
 {
 {
-    solaris_data *data = (solaris_data*)device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
     audio_info_t info;
     audio_info_t info;
     ALuint frameSize;
     ALuint frameSize;
     int numChannels;
     int numChannels;
@@ -174,7 +213,7 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
     frameSize = numChannels * BytesFromDevFmt(device->FmtType);
     frameSize = numChannels * BytesFromDevFmt(device->FmtType);
     info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize;
     info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize;
 
 
-    if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0)
+    if(ioctl(self->fd, AUDIO_SETINFO, &info) < 0)
     {
     {
         ERR("ioctl failed: %s\n", strerror(errno));
         ERR("ioctl failed: %s\n", strerror(errno));
         return ALC_FALSE;
         return ALC_FALSE;
@@ -201,74 +240,72 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
 
 
     SetDefaultChannelOrder(device);
     SetDefaultChannelOrder(device);
 
 
+    free(self->mix_data);
+    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->mix_data = calloc(1, self->data_size);
+
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
-static ALCboolean solaris_start_playback(ALCdevice *device)
+static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self)
 {
 {
-    solaris_data *data = (solaris_data*)device->ExtraData;
-
-    data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-    data->mix_data = calloc(1, data->data_size);
-
-    data->killNow = 0;
-    if(althrd_create(&data->thread, SolarisProc, device) != althrd_success)
-    {
-        free(data->mix_data);
-        data->mix_data = NULL;
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCsolarisBackend_mixerProc, self) != althrd_success)
         return ALC_FALSE;
         return ALC_FALSE;
-    }
-
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
-static void solaris_stop_playback(ALCdevice *device)
+static void ALCsolarisBackend_stop(ALCsolarisBackend *self)
 {
 {
-    solaris_data *data = (solaris_data*)device->ExtraData;
     int res;
     int res;
 
 
-    if(data->killNow)
+    if(self->killNow)
         return;
         return;
 
 
-    data->killNow = 1;
-    althrd_join(data->thread, &res);
+    self->killNow = 1;
+    althrd_join(self->thread, &res);
 
 
-    if(ioctl(data->fd, AUDIO_DRAIN) < 0)
+    if(ioctl(self->fd, AUDIO_DRAIN) < 0)
         ERR("Error draining device: %s\n", strerror(errno));
         ERR("Error draining device: %s\n", strerror(errno));
-
-    free(data->mix_data);
-    data->mix_data = NULL;
 }
 }
 
 
 
 
-static const BackendFuncs solaris_funcs = {
-    solaris_open_playback,
-    solaris_close_playback,
-    solaris_reset_playback,
-    solaris_start_playback,
-    solaris_stop_playback,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    ALCdevice_GetLatencyDefault
-};
-
-ALCboolean alc_solaris_init(BackendFuncs *func_list)
+typedef struct ALCsolarisBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCsolarisBackendFactory;
+#define ALCSOLARISBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCsolarisBackendFactory, ALCbackendFactory) } }
+
+ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void);
+
+static ALCboolean ALCsolarisBackendFactory_init(ALCsolarisBackendFactory *self);
+static DECLARE_FORWARD(ALCsolarisBackendFactory, ALCbackendFactory, void, deinit)
+static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory *self, ALCbackend_Type type);
+static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsolarisBackendFactory);
+
+
+ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void)
 {
 {
-    ConfigValueStr("solaris", "device", &solaris_driver);
+    static ALCsolarisBackendFactory factory = ALCSOLARISBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}
 
 
-    *func_list = solaris_funcs;
+
+static ALCboolean ALCsolarisBackendFactory_init(ALCsolarisBackendFactory* UNUSED(self))
+{
+    ConfigValueStr(NULL, "solaris", "device", &solaris_driver);
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
-void alc_solaris_deinit(void)
+static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory* UNUSED(self), ALCbackend_Type type)
 {
 {
+    if(type == ALCbackend_Playback)
+        return ALC_TRUE;
+    return ALC_FALSE;
 }
 }
 
 
-void alc_solaris_probe(enum DevProbe type)
+static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self), enum DevProbe type)
 {
 {
     switch(type)
     switch(type)
     {
     {
@@ -286,3 +323,16 @@ void alc_solaris_probe(enum DevProbe type)
             break;
             break;
     }
     }
 }
 }
+
+ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCsolarisBackend *backend;
+        NEW_OBJ(backend, ALCsolarisBackend)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}

+ 195 - 130
libs/openal-soft/Alc/backends/wave.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -24,26 +24,13 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <memory.h>
 #include <memory.h>
 #include <errno.h>
 #include <errno.h>
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
 
 
 #include "alMain.h"
 #include "alMain.h"
 #include "alu.h"
 #include "alu.h"
 #include "threads.h"
 #include "threads.h"
 #include "compat.h"
 #include "compat.h"
 
 
-
-typedef struct {
-    FILE *f;
-    long DataStart;
-
-    ALvoid *buffer;
-    ALuint size;
-
-    volatile int killNow;
-    althrd_t thread;
-} wave_data;
+#include "backends/base.h"
 
 
 
 
 static const ALCchar waveDevice[] = "Wave File Writer";
 static const ALCchar waveDevice[] = "Wave File Writer";
@@ -57,18 +44,15 @@ static const ALubyte SUBTYPE_FLOAT[] = {
     0x00, 0x38, 0x9b, 0x71
     0x00, 0x38, 0x9b, 0x71
 };
 };
 
 
-static const ALuint channel_masks[] = {
-    0, /* invalid */
-    0x4, /* Mono */
-    0x1 | 0x2, /* Stereo */
-    0, /* 3 channel */
-    0x1 | 0x2 | 0x10 | 0x20, /* Quad */
-    0, /* 5 channel */
-    0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20, /* 5.1 */
-    0x1 | 0x2 | 0x4 | 0x8 | 0x100 | 0x200 | 0x400, /* 6.1 */
-    0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x200 | 0x400, /* 7.1 */
+static const ALubyte SUBTYPE_BFORMAT_PCM[] = {
+    0x01, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
+    0xca, 0x00, 0x00, 0x00
 };
 };
 
 
+static const ALubyte SUBTYPE_BFORMAT_FLOAT[] = {
+    0x03, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
+    0xca, 0x00, 0x00, 0x00
+};
 
 
 static void fwrite16le(ALushort val, FILE *f)
 static void fwrite16le(ALushort val, FILE *f)
 {
 {
@@ -85,10 +69,57 @@ static void fwrite32le(ALuint val, FILE *f)
 }
 }
 
 
 
 
-static int WaveProc(void *ptr)
+typedef struct ALCwaveBackend {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    FILE *mFile;
+    long mDataStart;
+
+    ALvoid *mBuffer;
+    ALuint mSize;
+
+    volatile int killNow;
+    althrd_t thread;
+} ALCwaveBackend;
+
+static int ALCwaveBackend_mixerProc(void *ptr);
+
+static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device);
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, Destruct)
+static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name);
+static void ALCwaveBackend_close(ALCwaveBackend *self);
+static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self);
+static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self);
+static void ALCwaveBackend_stop(ALCwaveBackend *self);
+static DECLARE_FORWARD2(ALCwaveBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCwaveBackend)
+
+DEFINE_ALCBACKEND_VTABLE(ALCwaveBackend);
+
+
+static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCwaveBackend, ALCbackend, self);
+
+    self->mFile = NULL;
+    self->mDataStart = -1;
+
+    self->mBuffer = NULL;
+    self->mSize = 0;
+
+    self->killNow = 1;
+}
+
+
+static int ALCwaveBackend_mixerProc(void *ptr)
 {
 {
-    ALCdevice *device = (ALCdevice*)ptr;
-    wave_data *data = (wave_data*)device->ExtraData;
+    ALCwaveBackend *self = (ALCwaveBackend*)ptr;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     struct timespec now, start;
     struct timespec now, start;
     ALint64 avail, done;
     ALint64 avail, done;
     ALuint frameSize;
     ALuint frameSize;
@@ -106,7 +137,7 @@ static int WaveProc(void *ptr)
         ERR("Failed to get starting time\n");
         ERR("Failed to get starting time\n");
         return 1;
         return 1;
     }
     }
-    while(!data->killNow && device->Connected)
+    while(!self->killNow && device->Connected)
     {
     {
         if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
         if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
         {
         {
@@ -125,41 +156,41 @@ static int WaveProc(void *ptr)
         }
         }
 
 
         if(avail-done < device->UpdateSize)
         if(avail-done < device->UpdateSize)
-            al_nssleep(0, restTime);
+            al_nssleep(restTime);
         else while(avail-done >= device->UpdateSize)
         else while(avail-done >= device->UpdateSize)
         {
         {
-            aluMixData(device, data->buffer, device->UpdateSize);
+            aluMixData(device, self->mBuffer, device->UpdateSize);
             done += device->UpdateSize;
             done += device->UpdateSize;
 
 
             if(!IS_LITTLE_ENDIAN)
             if(!IS_LITTLE_ENDIAN)
             {
             {
                 ALuint bytesize = BytesFromDevFmt(device->FmtType);
                 ALuint bytesize = BytesFromDevFmt(device->FmtType);
-                ALubyte *bytes = data->buffer;
+                ALubyte *bytes = self->mBuffer;
                 ALuint i;
                 ALuint i;
 
 
                 if(bytesize == 1)
                 if(bytesize == 1)
                 {
                 {
-                    for(i = 0;i < data->size;i++)
-                        fputc(bytes[i], data->f);
+                    for(i = 0;i < self->mSize;i++)
+                        fputc(bytes[i], self->mFile);
                 }
                 }
                 else if(bytesize == 2)
                 else if(bytesize == 2)
                 {
                 {
-                    for(i = 0;i < data->size;i++)
-                        fputc(bytes[i^1], data->f);
+                    for(i = 0;i < self->mSize;i++)
+                        fputc(bytes[i^1], self->mFile);
                 }
                 }
                 else if(bytesize == 4)
                 else if(bytesize == 4)
                 {
                 {
-                    for(i = 0;i < data->size;i++)
-                        fputc(bytes[i^3], data->f);
+                    for(i = 0;i < self->mSize;i++)
+                        fputc(bytes[i^3], self->mFile);
                 }
                 }
             }
             }
             else
             else
             {
             {
-                fs = fwrite(data->buffer, frameSize, device->UpdateSize,
-                            data->f);
+                fs = fwrite(self->mBuffer, frameSize, device->UpdateSize,
+                            self->mFile);
                 (void)fs;
                 (void)fs;
             }
             }
-            if(ferror(data->f))
+            if(ferror(self->mFile))
             {
             {
                 ERR("Error writing to file\n");
                 ERR("Error writing to file\n");
                 ALCdevice_Lock(device);
                 ALCdevice_Lock(device);
@@ -173,52 +204,52 @@ static int WaveProc(void *ptr)
     return 0;
     return 0;
 }
 }
 
 
-static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
+
+static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name)
 {
 {
-    wave_data *data;
+    ALCdevice *device;
     const char *fname;
     const char *fname;
 
 
-    fname = GetConfigValue("wave", "file", "");
-    if(!fname[0])
-        return ALC_INVALID_VALUE;
+    fname = GetConfigValue(NULL, "wave", "file", "");
+    if(!fname[0]) return ALC_INVALID_VALUE;
 
 
-    if(!deviceName)
-        deviceName = waveDevice;
-    else if(strcmp(deviceName, waveDevice) != 0)
+    if(!name)
+        name = waveDevice;
+    else if(strcmp(name, waveDevice) != 0)
         return ALC_INVALID_VALUE;
         return ALC_INVALID_VALUE;
 
 
-    data = (wave_data*)calloc(1, sizeof(wave_data));
-
-    data->f = al_fopen(fname, "wb");
-    if(!data->f)
+    self->mFile = al_fopen(fname, "wb");
+    if(!self->mFile)
     {
     {
-        free(data);
         ERR("Could not open file '%s': %s\n", fname, strerror(errno));
         ERR("Could not open file '%s': %s\n", fname, strerror(errno));
         return ALC_INVALID_VALUE;
         return ALC_INVALID_VALUE;
     }
     }
 
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-    device->ExtraData = data;
+    device = STATIC_CAST(ALCbackend, self)->mDevice;
+    al_string_copy_cstr(&device->DeviceName, name);
+
     return ALC_NO_ERROR;
     return ALC_NO_ERROR;
 }
 }
 
 
-static void wave_close_playback(ALCdevice *device)
+static void ALCwaveBackend_close(ALCwaveBackend *self)
 {
 {
-    wave_data *data = (wave_data*)device->ExtraData;
-
-    fclose(data->f);
-    free(data);
-    device->ExtraData = NULL;
+    if(self->mFile)
+        fclose(self->mFile);
+    self->mFile = NULL;
 }
 }
 
 
-static ALCboolean wave_reset_playback(ALCdevice *device)
+static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
 {
 {
-    wave_data *data = (wave_data*)device->ExtraData;
-    ALuint channels=0, bits=0;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ALuint channels=0, bits=0, chanmask=0;
+    int isbformat = 0;
     size_t val;
     size_t val;
 
 
-    fseek(data->f, 0, SEEK_SET);
-    clearerr(data->f);
+    fseek(self->mFile, 0, SEEK_SET);
+    clearerr(self->mFile);
+
+    if(GetConfigValueBool(NULL, "wave", "bformat", 0))
+        device->FmtChans = DevFmtBFormat3D;
 
 
     switch(device->FmtType)
     switch(device->FmtType)
     {
     {
@@ -237,135 +268,156 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
         case DevFmtFloat:
         case DevFmtFloat:
             break;
             break;
     }
     }
+    switch(device->FmtChans)
+    {
+        case DevFmtMono:   chanmask = 0x04; break;
+        case DevFmtStereo: chanmask = 0x01 | 0x02; break;
+        case DevFmtQuad:   chanmask = 0x01 | 0x02 | 0x10 | 0x20; break;
+        case DevFmtX51: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x200 | 0x400; break;
+        case DevFmtX51Rear: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020; break;
+        case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break;
+        case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break;
+        case DevFmtBFormat3D:
+            isbformat = 1;
+            chanmask = 0;
+            break;
+    }
     bits = BytesFromDevFmt(device->FmtType) * 8;
     bits = BytesFromDevFmt(device->FmtType) * 8;
     channels = ChannelsFromDevFmt(device->FmtChans);
     channels = ChannelsFromDevFmt(device->FmtChans);
 
 
-    fprintf(data->f, "RIFF");
-    fwrite32le(0xFFFFFFFF, data->f); // 'RIFF' header len; filled in at close
+    fprintf(self->mFile, "RIFF");
+    fwrite32le(0xFFFFFFFF, self->mFile); // 'RIFF' header len; filled in at close
 
 
-    fprintf(data->f, "WAVE");
+    fprintf(self->mFile, "WAVE");
 
 
-    fprintf(data->f, "fmt ");
-    fwrite32le(40, data->f); // 'fmt ' header len; 40 bytes for EXTENSIBLE
+    fprintf(self->mFile, "fmt ");
+    fwrite32le(40, self->mFile); // 'fmt ' header len; 40 bytes for EXTENSIBLE
 
 
     // 16-bit val, format type id (extensible: 0xFFFE)
     // 16-bit val, format type id (extensible: 0xFFFE)
-    fwrite16le(0xFFFE, data->f);
+    fwrite16le(0xFFFE, self->mFile);
     // 16-bit val, channel count
     // 16-bit val, channel count
-    fwrite16le(channels, data->f);
+    fwrite16le(channels, self->mFile);
     // 32-bit val, frequency
     // 32-bit val, frequency
-    fwrite32le(device->Frequency, data->f);
+    fwrite32le(device->Frequency, self->mFile);
     // 32-bit val, bytes per second
     // 32-bit val, bytes per second
-    fwrite32le(device->Frequency * channels * bits / 8, data->f);
+    fwrite32le(device->Frequency * channels * bits / 8, self->mFile);
     // 16-bit val, frame size
     // 16-bit val, frame size
-    fwrite16le(channels * bits / 8, data->f);
+    fwrite16le(channels * bits / 8, self->mFile);
     // 16-bit val, bits per sample
     // 16-bit val, bits per sample
-    fwrite16le(bits, data->f);
+    fwrite16le(bits, self->mFile);
     // 16-bit val, extra byte count
     // 16-bit val, extra byte count
-    fwrite16le(22, data->f);
+    fwrite16le(22, self->mFile);
     // 16-bit val, valid bits per sample
     // 16-bit val, valid bits per sample
-    fwrite16le(bits, data->f);
+    fwrite16le(bits, self->mFile);
     // 32-bit val, channel mask
     // 32-bit val, channel mask
-    fwrite32le(channel_masks[channels], data->f);
+    fwrite32le(chanmask, self->mFile);
     // 16 byte GUID, sub-type format
     // 16 byte GUID, sub-type format
-    val = fwrite(((bits==32) ? SUBTYPE_FLOAT : SUBTYPE_PCM), 1, 16, data->f);
+    val = fwrite(((bits==32) ? (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) :
+                               (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM)), 1, 16, self->mFile);
     (void)val;
     (void)val;
 
 
-    fprintf(data->f, "data");
-    fwrite32le(0xFFFFFFFF, data->f); // 'data' header len; filled in at close
+    fprintf(self->mFile, "data");
+    fwrite32le(0xFFFFFFFF, self->mFile); // 'data' header len; filled in at close
 
 
-    if(ferror(data->f))
+    if(ferror(self->mFile))
     {
     {
         ERR("Error writing header: %s\n", strerror(errno));
         ERR("Error writing header: %s\n", strerror(errno));
         return ALC_FALSE;
         return ALC_FALSE;
     }
     }
-    data->DataStart = ftell(data->f);
+    self->mDataStart = ftell(self->mFile);
 
 
     SetDefaultWFXChannelOrder(device);
     SetDefaultWFXChannelOrder(device);
 
 
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
-static ALCboolean wave_start_playback(ALCdevice *device)
+static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self)
 {
 {
-    wave_data *data = (wave_data*)device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
 
 
-    data->size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-    data->buffer = malloc(data->size);
-    if(!data->buffer)
+    self->mSize = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->mBuffer = malloc(self->mSize);
+    if(!self->mBuffer)
     {
     {
         ERR("Buffer malloc failed\n");
         ERR("Buffer malloc failed\n");
         return ALC_FALSE;
         return ALC_FALSE;
     }
     }
 
 
-    data->killNow = 0;
-    if(althrd_create(&data->thread, WaveProc, device) != althrd_success)
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCwaveBackend_mixerProc, self) != althrd_success)
     {
     {
-        free(data->buffer);
-        data->buffer = NULL;
+        free(self->mBuffer);
+        self->mBuffer = NULL;
+        self->mSize = 0;
         return ALC_FALSE;
         return ALC_FALSE;
     }
     }
 
 
     return ALC_TRUE;
     return ALC_TRUE;
 }
 }
 
 
-static void wave_stop_playback(ALCdevice *device)
+static void ALCwaveBackend_stop(ALCwaveBackend *self)
 {
 {
-    wave_data *data = (wave_data*)device->ExtraData;
     ALuint dataLen;
     ALuint dataLen;
     long size;
     long size;
     int res;
     int res;
 
 
-    if(data->killNow)
+    if(self->killNow)
         return;
         return;
 
 
-    data->killNow = 1;
-    althrd_join(data->thread, &res);
+    self->killNow = 1;
+    althrd_join(self->thread, &res);
 
 
-    free(data->buffer);
-    data->buffer = NULL;
+    free(self->mBuffer);
+    self->mBuffer = NULL;
 
 
-    size = ftell(data->f);
+    size = ftell(self->mFile);
     if(size > 0)
     if(size > 0)
     {
     {
-        dataLen = size - data->DataStart;
-        if(fseek(data->f, data->DataStart-4, SEEK_SET) == 0)
-            fwrite32le(dataLen, data->f); // 'data' header len
-        if(fseek(data->f, 4, SEEK_SET) == 0)
-            fwrite32le(size-8, data->f); // 'WAVE' header len
+        dataLen = size - self->mDataStart;
+        if(fseek(self->mFile, self->mDataStart-4, SEEK_SET) == 0)
+            fwrite32le(dataLen, self->mFile); // 'data' header len
+        if(fseek(self->mFile, 4, SEEK_SET) == 0)
+            fwrite32le(size-8, self->mFile); // 'WAVE' header len
     }
     }
 }
 }
 
 
 
 
-static const BackendFuncs wave_funcs = {
-    wave_open_playback,
-    wave_close_playback,
-    wave_reset_playback,
-    wave_start_playback,
-    wave_stop_playback,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    ALCdevice_GetLatencyDefault
-};
+typedef struct ALCwaveBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCwaveBackendFactory;
+#define ALCWAVEBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCwaveBackendFactory, ALCbackendFactory) } }
+
+ALCbackendFactory *ALCwaveBackendFactory_getFactory(void);
+
+static ALCboolean ALCwaveBackendFactory_init(ALCwaveBackendFactory *self);
+static DECLARE_FORWARD(ALCwaveBackendFactory, ALCbackendFactory, void, deinit)
+static ALCboolean ALCwaveBackendFactory_querySupport(ALCwaveBackendFactory *self, ALCbackend_Type type);
+static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCwaveBackendFactory_createBackend(ALCwaveBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwaveBackendFactory);
+
 
 
-ALCboolean alc_wave_init(BackendFuncs *func_list)
+ALCbackendFactory *ALCwaveBackendFactory_getFactory(void)
 {
 {
-    *func_list = wave_funcs;
-    return ALC_TRUE;
+    static ALCwaveBackendFactory factory = ALCWAVEBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
 }
 }
 
 
-void alc_wave_deinit(void)
+
+static ALCboolean ALCwaveBackendFactory_init(ALCwaveBackendFactory* UNUSED(self))
 {
 {
+    return ALC_TRUE;
 }
 }
 
 
-void alc_wave_probe(enum DevProbe type)
+static ALCboolean ALCwaveBackendFactory_querySupport(ALCwaveBackendFactory* UNUSED(self), ALCbackend_Type type)
 {
 {
-    if(!ConfigValueExists("wave", "file"))
-        return;
+    if(type == ALCbackend_Playback)
+        return !!ConfigValueExists(NULL, "wave", "file");
+    return ALC_FALSE;
+}
 
 
+static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory* UNUSED(self), enum DevProbe type)
+{
     switch(type)
     switch(type)
     {
     {
         case ALL_DEVICE_PROBE:
         case ALL_DEVICE_PROBE:
@@ -375,3 +427,16 @@ void alc_wave_probe(enum DevProbe type)
             break;
             break;
     }
     }
 }
 }
+
+static ALCbackend* ALCwaveBackendFactory_createBackend(ALCwaveBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCwaveBackend *backend;
+        NEW_OBJ(backend, ALCwaveBackend)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}

File diff suppressed because it is too large
+ 365 - 311
libs/openal-soft/Alc/backends/winmm.c


+ 6 - 17
libs/openal-soft/Alc/bs2b.c

@@ -29,9 +29,6 @@
 #include "bs2b.h"
 #include "bs2b.h"
 #include "alu.h"
 #include "alu.h"
 
 
-#ifndef M_PI
-#define M_PI  3.14159265358979323846
-#endif
 
 
 /* Set up all data. */
 /* Set up all data. */
 static void init(struct bs2b *bs2b)
 static void init(struct bs2b *bs2b)
@@ -40,8 +37,6 @@ static void init(struct bs2b *bs2b)
     float G_lo,  G_hi;
     float G_lo,  G_hi;
     float x, g;
     float x, g;
 
 
-    bs2b->srate = clampi(bs2b->srate, 2000, 192000);
-
     switch(bs2b->level)
     switch(bs2b->level)
     {
     {
     case BS2B_LOW_CLEVEL: /* Low crossfeed level */
     case BS2B_LOW_CLEVEL: /* Low crossfeed level */
@@ -105,31 +100,25 @@ static void init(struct bs2b *bs2b)
     bs2b->a1_hi = -x * g;
     bs2b->a1_hi = -x * g;
 } /* init */
 } /* init */
 
 
+
 /* Exported functions.
 /* Exported functions.
  * See descriptions in "bs2b.h"
  * See descriptions in "bs2b.h"
  */
  */
 
 
-void bs2b_set_level(struct bs2b *bs2b, int level)
+void bs2b_set_params(struct bs2b *bs2b, int level, int srate)
 {
 {
-    if(level == bs2b->level)
-        return;
+    if(srate <= 0) srate = 1;
+
     bs2b->level = level;
     bs2b->level = level;
+    bs2b->srate = srate;
     init(bs2b);
     init(bs2b);
-} /* bs2b_set_level */
+} /* bs2b_set_params */
 
 
 int bs2b_get_level(struct bs2b *bs2b)
 int bs2b_get_level(struct bs2b *bs2b)
 {
 {
     return bs2b->level;
     return bs2b->level;
 } /* bs2b_get_level */
 } /* bs2b_get_level */
 
 
-void bs2b_set_srate(struct bs2b *bs2b, int srate)
-{
-    if (srate == bs2b->srate)
-        return;
-    bs2b->srate = srate;
-    init(bs2b);
-} /* bs2b_set_srate */
-
 int bs2b_get_srate(struct bs2b *bs2b)
 int bs2b_get_srate(struct bs2b *bs2b)
 {
 {
     return bs2b->srate;
     return bs2b->srate;

+ 12 - 14
libs/openal-soft/Alc/effects/autowah.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -31,15 +31,15 @@
 /* Auto-wah is simply a low-pass filter with a cutoff frequency that shifts up
 /* Auto-wah is simply a low-pass filter with a cutoff frequency that shifts up
  * or down depending on the input signal, and a resonant peak at the cutoff.
  * or down depending on the input signal, and a resonant peak at the cutoff.
  *
  *
- * Currently, we assume a cutoff frequency range of 500hz (no amplitude) to
- * 3khz (peak gain). Peak gain is assumed to be in normalized scale.
+ * Currently, we assume a cutoff frequency range of 20hz (no amplitude) to
+ * 20khz (peak gain). Peak gain is assumed to be in normalized scale.
  */
  */
 
 
 typedef struct ALautowahState {
 typedef struct ALautowahState {
     DERIVE_FROM_TYPE(ALeffectState);
     DERIVE_FROM_TYPE(ALeffectState);
 
 
     /* Effect gains for each channel */
     /* Effect gains for each channel */
-    ALfloat Gain[MaxChannels];
+    ALfloat Gain[MAX_OUTPUT_CHANNELS];
 
 
     /* Effect parameters */
     /* Effect parameters */
     ALfloat AttackRate;
     ALfloat AttackRate;
@@ -66,7 +66,6 @@ static ALboolean ALautowahState_deviceUpdate(ALautowahState *state, ALCdevice *d
 static ALvoid ALautowahState_update(ALautowahState *state, ALCdevice *device, const ALeffectslot *slot)
 static ALvoid ALautowahState_update(ALautowahState *state, ALCdevice *device, const ALeffectslot *slot)
 {
 {
     ALfloat attackTime, releaseTime;
     ALfloat attackTime, releaseTime;
-    ALfloat gain;
 
 
     attackTime = slot->EffectProps.Autowah.AttackTime * state->Frequency;
     attackTime = slot->EffectProps.Autowah.AttackTime * state->Frequency;
     releaseTime = slot->EffectProps.Autowah.ReleaseTime * state->Frequency;
     releaseTime = slot->EffectProps.Autowah.ReleaseTime * state->Frequency;
@@ -76,19 +75,18 @@ static ALvoid ALautowahState_update(ALautowahState *state, ALCdevice *device, co
     state->PeakGain = slot->EffectProps.Autowah.PeakGain;
     state->PeakGain = slot->EffectProps.Autowah.PeakGain;
     state->Resonance = slot->EffectProps.Autowah.Resonance;
     state->Resonance = slot->EffectProps.Autowah.Resonance;
 
 
-    gain = sqrtf(1.0f / device->NumChan) * slot->Gain;
-    SetGains(device, gain, state->Gain);
+    ComputeAmbientGains(device, slot->Gain, state->Gain);
 }
 }
 
 
-static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE])
+static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     ALuint it, kt;
     ALuint it, kt;
     ALuint base;
     ALuint base;
 
 
     for(base = 0;base < SamplesToDo;)
     for(base = 0;base < SamplesToDo;)
     {
     {
-        ALfloat temps[64];
-        ALuint td = minu(SamplesToDo-base, 64);
+        ALfloat temps[256];
+        ALuint td = minu(256, SamplesToDo-base);
         ALfloat gain = state->GainCtrl;
         ALfloat gain = state->GainCtrl;
 
 
         for(it = 0;it < td;it++)
         for(it = 0;it < td;it++)
@@ -114,7 +112,7 @@ static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo,
              * ALfilterType_LowPass. However, instead of passing a bandwidth,
              * ALfilterType_LowPass. However, instead of passing a bandwidth,
              * we use the resonance property for Q. This also inlines the call.
              * we use the resonance property for Q. This also inlines the call.
              */
              */
-            w0 = F_2PI * cutoff / state->Frequency;
+            w0 = F_TAU * cutoff / state->Frequency;
 
 
             /* FIXME: Resonance controls the resonant peak, or Q. How? Not sure
             /* FIXME: Resonance controls the resonant peak, or Q. How? Not sure
              * that Q = resonance*0.1. */
              * that Q = resonance*0.1. */
@@ -137,10 +135,10 @@ static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo,
         }
         }
         state->GainCtrl = gain;
         state->GainCtrl = gain;
 
 
-        for(kt = 0;kt < MaxChannels;kt++)
+        for(kt = 0;kt < NumChannels;kt++)
         {
         {
             ALfloat gain = state->Gain[kt];
             ALfloat gain = state->Gain[kt];
-            if(!(gain > GAIN_SILENCE_THRESHOLD))
+            if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
                 continue;
                 continue;
 
 
             for(it = 0;it < td;it++)
             for(it = 0;it < td;it++)

+ 14 - 12
libs/openal-soft/Alc/effects/chorus.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -46,7 +46,7 @@ typedef struct ALchorusState {
     ALint lfo_disp;
     ALint lfo_disp;
 
 
     /* Gains for left and right sides */
     /* Gains for left and right sides */
-    ALfloat Gain[2][MaxChannels];
+    ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
 
 
     /* effect parameters */
     /* effect parameters */
     enum ChorusWaveForm waveform;
     enum ChorusWaveForm waveform;
@@ -93,6 +93,8 @@ static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Dev
 
 
 static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, const ALeffectslot *Slot)
 static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, const ALeffectslot *Slot)
 {
 {
+    static const ALfloat left_dir[3] = { -1.0f, 0.0f, 0.0f };
+    static const ALfloat right_dir[3] = { 1.0f, 0.0f, 0.0f };
     ALfloat frequency = (ALfloat)Device->Frequency;
     ALfloat frequency = (ALfloat)Device->Frequency;
     ALfloat rate;
     ALfloat rate;
     ALint phase;
     ALint phase;
@@ -111,8 +113,8 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons
     state->delay = fastf2i(Slot->EffectProps.Chorus.Delay * frequency);
     state->delay = fastf2i(Slot->EffectProps.Chorus.Delay * frequency);
 
 
     /* Gains for left and right sides */
     /* Gains for left and right sides */
-    ComputeAngleGains(Device, atan2f(-1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[0]);
-    ComputeAngleGains(Device, atan2f(+1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[1]);
+    ComputeDirectionalGains(Device, left_dir, Slot->Gain, state->Gain[0]);
+    ComputeDirectionalGains(Device, right_dir, Slot->Gain, state->Gain[1]);
 
 
     phase = Slot->EffectProps.Chorus.Phase;
     phase = Slot->EffectProps.Chorus.Phase;
     rate = Slot->EffectProps.Chorus.Rate;
     rate = Slot->EffectProps.Chorus.Rate;
@@ -132,7 +134,7 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons
                 state->lfo_scale = 4.0f / state->lfo_range;
                 state->lfo_scale = 4.0f / state->lfo_range;
                 break;
                 break;
             case CWF_Sinusoid:
             case CWF_Sinusoid:
-                state->lfo_scale = F_2PI / state->lfo_range;
+                state->lfo_scale = F_TAU / state->lfo_range;
                 break;
                 break;
         }
         }
 
 
@@ -201,15 +203,15 @@ DECL_TEMPLATE(Sinusoid)
 
 
 #undef DECL_TEMPLATE
 #undef DECL_TEMPLATE
 
 
-static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     ALuint it, kt;
     ALuint it, kt;
     ALuint base;
     ALuint base;
 
 
     for(base = 0;base < SamplesToDo;)
     for(base = 0;base < SamplesToDo;)
     {
     {
-        ALfloat temps[64][2];
-        ALuint td = minu(SamplesToDo-base, 64);
+        ALfloat temps[128][2];
+        ALuint td = minu(128, SamplesToDo-base);
 
 
         switch(state->waveform)
         switch(state->waveform)
         {
         {
@@ -221,17 +223,17 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, co
                 break;
                 break;
         }
         }
 
 
-        for(kt = 0;kt < MaxChannels;kt++)
+        for(kt = 0;kt < NumChannels;kt++)
         {
         {
             ALfloat gain = state->Gain[0][kt];
             ALfloat gain = state->Gain[0][kt];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
             {
             {
                 for(it = 0;it < td;it++)
                 for(it = 0;it < td;it++)
                     SamplesOut[kt][it+base] += temps[it][0] * gain;
                     SamplesOut[kt][it+base] += temps[it][0] * gain;
             }
             }
 
 
             gain = state->Gain[1][kt];
             gain = state->Gain[1][kt];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
             {
             {
                 for(it = 0;it < td;it++)
                 for(it = 0;it < td;it++)
                     SamplesOut[kt][it+base] += temps[it][1] * gain;
                     SamplesOut[kt][it+base] += temps[it][1] * gain;

+ 11 - 14
libs/openal-soft/Alc/effects/compressor.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -31,7 +31,7 @@ typedef struct ALcompressorState {
     DERIVE_FROM_TYPE(ALeffectState);
     DERIVE_FROM_TYPE(ALeffectState);
 
 
     /* Effect gains for each channel */
     /* Effect gains for each channel */
-    ALfloat Gain[MaxChannels];
+    ALfloat Gain[MAX_OUTPUT_CHANNELS];
 
 
     /* Effect parameters */
     /* Effect parameters */
     ALboolean Enabled;
     ALboolean Enabled;
@@ -55,25 +55,22 @@ static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdev
     return AL_TRUE;
     return AL_TRUE;
 }
 }
 
 
-static ALvoid ALcompressorState_update(ALcompressorState *state, ALCdevice *Device, const ALeffectslot *Slot)
+static ALvoid ALcompressorState_update(ALcompressorState *state, ALCdevice *device, const ALeffectslot *slot)
 {
 {
-    ALfloat gain;
+    state->Enabled = slot->EffectProps.Compressor.OnOff;
 
 
-    state->Enabled = Slot->EffectProps.Compressor.OnOff;
-
-    gain = sqrtf(1.0f / Device->NumChan) * Slot->Gain;
-    SetGains(Device, gain, state->Gain);
+    ComputeAmbientGains(device, slot->Gain, state->Gain);
 }
 }
 
 
-static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE])
+static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     ALuint it, kt;
     ALuint it, kt;
     ALuint base;
     ALuint base;
 
 
     for(base = 0;base < SamplesToDo;)
     for(base = 0;base < SamplesToDo;)
     {
     {
-        ALfloat temps[64];
-        ALuint td = minu(SamplesToDo-base, 64);
+        ALfloat temps[256];
+        ALuint td = minu(256, SamplesToDo-base);
 
 
         if(state->Enabled)
         if(state->Enabled)
         {
         {
@@ -119,10 +116,10 @@ static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint Samples
         }
         }
 
 
 
 
-        for(kt = 0;kt < MaxChannels;kt++)
+        for(kt = 0;kt < NumChannels;kt++)
         {
         {
             ALfloat gain = state->Gain[kt];
             ALfloat gain = state->Gain[kt];
-            if(!(gain > GAIN_SILENCE_THRESHOLD))
+            if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
                 continue;
                 continue;
 
 
             for(it = 0;it < td;it++)
             for(it = 0;it < td;it++)

+ 28 - 14
libs/openal-soft/Alc/effects/dedicated.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -32,7 +32,7 @@
 typedef struct ALdedicatedState {
 typedef struct ALdedicatedState {
     DERIVE_FROM_TYPE(ALeffectState);
     DERIVE_FROM_TYPE(ALeffectState);
 
 
-    ALfloat gains[MaxChannels];
+    ALfloat gains[MAX_OUTPUT_CHANNELS];
 } ALdedicatedState;
 } ALdedicatedState;
 
 
 
 
@@ -48,27 +48,41 @@ static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *UNUSED(state),
 static ALvoid ALdedicatedState_update(ALdedicatedState *state, ALCdevice *device, const ALeffectslot *Slot)
 static ALvoid ALdedicatedState_update(ALdedicatedState *state, ALCdevice *device, const ALeffectslot *Slot)
 {
 {
     ALfloat Gain;
     ALfloat Gain;
-    ALsizei s;
+    ALuint i;
+
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+        state->gains[i] = 0.0f;
 
 
     Gain = Slot->Gain * Slot->EffectProps.Dedicated.Gain;
     Gain = Slot->Gain * Slot->EffectProps.Dedicated.Gain;
-    if(Slot->EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
-        ComputeAngleGains(device, atan2f(0.0f, 1.0f), 0.0f, Gain, state->gains);
-    else if(Slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
+    if(Slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
+    {
+        int idx;
+        if((idx=GetChannelIdxByName(device, LFE)) != -1)
+            state->gains[idx] = Gain;
+    }
+    else if(Slot->EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
     {
     {
-        for(s = 0;s < MaxChannels;s++)
-            state->gains[s] = 0.0f;
-        state->gains[LFE] = Gain;
+        int idx;
+        /* Dialog goes to the front-center speaker if it exists, otherwise it
+         * plays from the front-center location. */
+        if((idx=GetChannelIdxByName(device, FrontCenter)) != -1)
+            state->gains[idx] = Gain;
+        else
+        {
+            static const ALfloat front_dir[3] = { 0.0f, 0.0f, -1.0f };
+            ComputeDirectionalGains(device, front_dir, Gain, state->gains);
+        }
     }
     }
 }
 }
 
 
-static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     const ALfloat *gains = state->gains;
     const ALfloat *gains = state->gains;
     ALuint i, c;
     ALuint i, c;
 
 
-    for(c = 0;c < MaxChannels;c++)
+    for(c = 0;c < NumChannels;c++)
     {
     {
-        if(!(gains[c] > GAIN_SILENCE_THRESHOLD))
+        if(!(fabsf(gains[c]) > GAIN_SILENCE_THRESHOLD))
             continue;
             continue;
 
 
         for(i = 0;i < SamplesToDo;i++)
         for(i = 0;i < SamplesToDo;i++)
@@ -94,7 +108,7 @@ ALeffectState *ALdedicatedStateFactory_create(ALdedicatedStateFactory *UNUSED(fa
     if(!state) return NULL;
     if(!state) return NULL;
     SET_VTABLE2(ALdedicatedState, ALeffectState, state);
     SET_VTABLE2(ALdedicatedState, ALeffectState, state);
 
 
-    for(s = 0;s < MaxChannels;s++)
+    for(s = 0;s < MAX_OUTPUT_CHANNELS;s++)
         state->gains[s] = 0.0f;
         state->gains[s] = 0.0f;
 
 
     return STATIC_CAST(ALeffectState, state);
     return STATIC_CAST(ALeffectState, state);

+ 18 - 20
libs/openal-soft/Alc/effects/distortion.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -34,7 +34,7 @@ typedef struct ALdistortionState {
     DERIVE_FROM_TYPE(ALeffectState);
     DERIVE_FROM_TYPE(ALeffectState);
 
 
     /* Effect gains for each channel */
     /* Effect gains for each channel */
-    ALfloat Gain[MaxChannels];
+    ALfloat Gain[MAX_OUTPUT_CHANNELS];
 
 
     /* Effect parameters */
     /* Effect parameters */
     ALfilterState lowpass;
     ALfilterState lowpass;
@@ -58,7 +58,6 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, ALCdevice *Devi
     ALfloat bandwidth;
     ALfloat bandwidth;
     ALfloat cutoff;
     ALfloat cutoff;
     ALfloat edge;
     ALfloat edge;
-    ALfloat gain;
 
 
     /* Store distorted signal attenuation settings */
     /* Store distorted signal attenuation settings */
     state->attenuation = Slot->EffectProps.Distortion.Gain;
     state->attenuation = Slot->EffectProps.Distortion.Gain;
@@ -73,23 +72,23 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, ALCdevice *Devi
     /* Bandwidth value is constant in octaves */
     /* Bandwidth value is constant in octaves */
     bandwidth = (cutoff / 2.0f) / (cutoff * 0.67f);
     bandwidth = (cutoff / 2.0f) / (cutoff * 0.67f);
     ALfilterState_setParams(&state->lowpass, ALfilterType_LowPass, 1.0f,
     ALfilterState_setParams(&state->lowpass, ALfilterType_LowPass, 1.0f,
-                            cutoff / (frequency*4.0f), bandwidth);
+        cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
+    );
 
 
     /* Bandpass filter */
     /* Bandpass filter */
     cutoff = Slot->EffectProps.Distortion.EQCenter;
     cutoff = Slot->EffectProps.Distortion.EQCenter;
     /* Convert bandwidth in Hz to octaves */
     /* Convert bandwidth in Hz to octaves */
     bandwidth = Slot->EffectProps.Distortion.EQBandwidth / (cutoff * 0.67f);
     bandwidth = Slot->EffectProps.Distortion.EQBandwidth / (cutoff * 0.67f);
     ALfilterState_setParams(&state->bandpass, ALfilterType_BandPass, 1.0f,
     ALfilterState_setParams(&state->bandpass, ALfilterType_BandPass, 1.0f,
-                            cutoff / (frequency*4.0f), bandwidth);
+        cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
+    );
 
 
-    gain = sqrtf(1.0f / Device->NumChan) * Slot->Gain;
-    SetGains(Device, gain, state->Gain);
+    ComputeAmbientGains(Device, Slot->Gain, state->Gain);
 }
 }
 
 
-static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     const ALfloat fc = state->edge_coeff;
     const ALfloat fc = state->edge_coeff;
-    float oversample_buffer[64][4];
     ALuint base;
     ALuint base;
     ALuint it;
     ALuint it;
     ALuint ot;
     ALuint ot;
@@ -97,8 +96,8 @@ static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint Samples
 
 
     for(base = 0;base < SamplesToDo;)
     for(base = 0;base < SamplesToDo;)
     {
     {
-        ALfloat temps[64];
-        ALuint td = minu(SamplesToDo-base, 64);
+        float oversample_buffer[64][4];
+        ALuint td = minu(64, SamplesToDo-base);
 
 
         /* Perform 4x oversampling to avoid aliasing.   */
         /* Perform 4x oversampling to avoid aliasing.   */
         /* Oversampling greatly improves distortion     */
         /* Oversampling greatly improves distortion     */
@@ -150,20 +149,19 @@ static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint Samples
                 smp = ALfilterState_processSingle(&state->bandpass, smp);
                 smp = ALfilterState_processSingle(&state->bandpass, smp);
                 oversample_buffer[it][ot] = smp;
                 oversample_buffer[it][ot] = smp;
             }
             }
-
-            /* Fourth step, final, do attenuation and perform decimation, */
-            /* store only one sample out of 4.                            */
-            temps[it] = oversample_buffer[it][0] * state->attenuation;
         }
         }
 
 
-        for(kt = 0;kt < MaxChannels;kt++)
+        for(kt = 0;kt < NumChannels;kt++)
         {
         {
-            ALfloat gain = state->Gain[kt];
-            if(!(gain > GAIN_SILENCE_THRESHOLD))
+            /* Fourth step, final, do attenuation and perform decimation,
+             * store only one sample out of 4.
+             */
+            ALfloat gain = state->Gain[kt] * state->attenuation;
+            if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
                 continue;
                 continue;
 
 
             for(it = 0;it < td;it++)
             for(it = 0;it < td;it++)
-                SamplesOut[kt][base+it] += gain * temps[it];
+                SamplesOut[kt][base+it] += gain * oversample_buffer[it][0];
         }
         }
 
 
         base += td;
         base += td;

+ 18 - 16
libs/openal-soft/Alc/effects/echo.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -43,7 +43,7 @@ typedef struct ALechoState {
     } Tap[2];
     } Tap[2];
     ALuint Offset;
     ALuint Offset;
     /* The panning gains for the two taps */
     /* The panning gains for the two taps */
-    ALfloat Gain[2][MaxChannels];
+    ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
 
 
     ALfloat FeedGain;
     ALfloat FeedGain;
 
 
@@ -83,9 +83,9 @@ static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device)
 
 
 static ALvoid ALechoState_update(ALechoState *state, ALCdevice *Device, const ALeffectslot *Slot)
 static ALvoid ALechoState_update(ALechoState *state, ALCdevice *Device, const ALeffectslot *Slot)
 {
 {
+    ALfloat pandir[3] = { 0.0f, 0.0f, 0.0f };
     ALuint frequency = Device->Frequency;
     ALuint frequency = Device->Frequency;
-    ALfloat lrpan, gain;
-    ALfloat dirGain;
+    ALfloat gain, lrpan;
 
 
     state->Tap[0].delay = fastf2u(Slot->EffectProps.Echo.Delay * frequency) + 1;
     state->Tap[0].delay = fastf2u(Slot->EffectProps.Echo.Delay * frequency) + 1;
     state->Tap[1].delay = fastf2u(Slot->EffectProps.Echo.LRDelay * frequency);
     state->Tap[1].delay = fastf2u(Slot->EffectProps.Echo.LRDelay * frequency);
@@ -95,21 +95,23 @@ static ALvoid ALechoState_update(ALechoState *state, ALCdevice *Device, const AL
 
 
     state->FeedGain = Slot->EffectProps.Echo.Feedback;
     state->FeedGain = Slot->EffectProps.Echo.Feedback;
 
 
+    gain = minf(1.0f - Slot->EffectProps.Echo.Damping, 0.01f);
     ALfilterState_setParams(&state->Filter, ALfilterType_HighShelf,
     ALfilterState_setParams(&state->Filter, ALfilterType_HighShelf,
-                            1.0f - Slot->EffectProps.Echo.Damping,
-                            LOWPASSFREQREF/frequency, 0.0f);
+                            gain, LOWPASSFREQREF/frequency,
+                            calc_rcpQ_from_slope(gain, 0.75f));
 
 
     gain = Slot->Gain;
     gain = Slot->Gain;
-    dirGain = fabsf(lrpan);
 
 
     /* First tap panning */
     /* First tap panning */
-    ComputeAngleGains(Device, atan2f(-lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[0]);
+    pandir[0] = -lrpan;
+    ComputeDirectionalGains(Device, pandir, gain, state->Gain[0]);
 
 
     /* Second tap panning */
     /* Second tap panning */
-    ComputeAngleGains(Device, atan2f(+lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[1]);
+    pandir[0] = +lrpan;
+    ComputeDirectionalGains(Device, pandir, gain, state->Gain[1]);
 }
 }
 
 
-static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     const ALuint mask = state->BufferLength-1;
     const ALuint mask = state->BufferLength-1;
     const ALuint tap1 = state->Tap[0].delay;
     const ALuint tap1 = state->Tap[0].delay;
@@ -121,8 +123,8 @@ static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const
 
 
     for(base = 0;base < SamplesToDo;)
     for(base = 0;base < SamplesToDo;)
     {
     {
-        ALfloat temps[64][2];
-        ALuint td = minu(SamplesToDo-base, 64);
+        ALfloat temps[128][2];
+        ALuint td = minu(128, SamplesToDo-base);
 
 
         for(i = 0;i < td;i++)
         for(i = 0;i < td;i++)
         {
         {
@@ -138,17 +140,17 @@ static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const
             offset++;
             offset++;
         }
         }
 
 
-        for(k = 0;k < MaxChannels;k++)
+        for(k = 0;k < NumChannels;k++)
         {
         {
             ALfloat gain = state->Gain[0][k];
             ALfloat gain = state->Gain[0][k];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
             {
             {
                 for(i = 0;i < td;i++)
                 for(i = 0;i < td;i++)
                     SamplesOut[k][i+base] += temps[i][0] * gain;
                     SamplesOut[k][i+base] += temps[i][0] * gain;
             }
             }
 
 
             gain = state->Gain[1][k];
             gain = state->Gain[1][k];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
             {
             {
                 for(i = 0;i < td;i++)
                 for(i = 0;i < td;i++)
                     SamplesOut[k][i+base] += temps[i][1] * gain;
                     SamplesOut[k][i+base] += temps[i][1] * gain;

+ 30 - 23
libs/openal-soft/Alc/effects/equalizer.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -75,7 +75,7 @@ typedef struct ALequalizerState {
     DERIVE_FROM_TYPE(ALeffectState);
     DERIVE_FROM_TYPE(ALeffectState);
 
 
     /* Effect gains for each channel */
     /* Effect gains for each channel */
-    ALfloat Gain[MaxChannels];
+    ALfloat Gain[MAX_OUTPUT_CHANNELS];
 
 
     /* Effect parameters */
     /* Effect parameters */
     ALfilterState filter[4];
     ALfilterState filter[4];
@@ -93,33 +93,40 @@ static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *UNUSED(state),
 static ALvoid ALequalizerState_update(ALequalizerState *state, ALCdevice *device, const ALeffectslot *slot)
 static ALvoid ALequalizerState_update(ALequalizerState *state, ALCdevice *device, const ALeffectslot *slot)
 {
 {
     ALfloat frequency = (ALfloat)device->Frequency;
     ALfloat frequency = (ALfloat)device->Frequency;
-    ALfloat gain = sqrtf(1.0f / device->NumChan) * slot->Gain;
+    ALfloat gain, freq_mult;
 
 
-    SetGains(device, gain, state->Gain);
+    ComputeAmbientGains(device, slot->Gain, state->Gain);
 
 
-    /* Calculate coefficients for the each type of filter */
+    /* Calculate coefficients for the each type of filter. Note that the shelf
+     * filters' gain is for the reference frequency, which is the centerpoint
+     * of the transition band.
+     */
+    gain = sqrtf(slot->EffectProps.Equalizer.LowGain);
+    freq_mult = slot->EffectProps.Equalizer.LowCutoff/frequency;
     ALfilterState_setParams(&state->filter[0], ALfilterType_LowShelf,
     ALfilterState_setParams(&state->filter[0], ALfilterType_LowShelf,
-                            sqrtf(slot->EffectProps.Equalizer.LowGain),
-                            slot->EffectProps.Equalizer.LowCutoff/frequency,
-                            0.0f);
+        gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
+    );
 
 
+    gain = slot->EffectProps.Equalizer.Mid1Gain;
+    freq_mult = slot->EffectProps.Equalizer.Mid1Center/frequency;
     ALfilterState_setParams(&state->filter[1], ALfilterType_Peaking,
     ALfilterState_setParams(&state->filter[1], ALfilterType_Peaking,
-                            sqrtf(slot->EffectProps.Equalizer.Mid1Gain),
-                            slot->EffectProps.Equalizer.Mid1Center/frequency,
-                            slot->EffectProps.Equalizer.Mid1Width);
+        gain, freq_mult, calc_rcpQ_from_bandwidth(freq_mult, slot->EffectProps.Equalizer.Mid1Width)
+    );
 
 
+    gain = slot->EffectProps.Equalizer.Mid2Gain;
+    freq_mult = slot->EffectProps.Equalizer.Mid2Center/frequency;
     ALfilterState_setParams(&state->filter[2], ALfilterType_Peaking,
     ALfilterState_setParams(&state->filter[2], ALfilterType_Peaking,
-                            sqrtf(slot->EffectProps.Equalizer.Mid2Gain),
-                            slot->EffectProps.Equalizer.Mid2Center/frequency,
-                            slot->EffectProps.Equalizer.Mid2Width);
+        gain, freq_mult, calc_rcpQ_from_bandwidth(freq_mult, slot->EffectProps.Equalizer.Mid2Width)
+    );
 
 
+    gain = sqrtf(slot->EffectProps.Equalizer.HighGain);
+    freq_mult = slot->EffectProps.Equalizer.HighCutoff/frequency;
     ALfilterState_setParams(&state->filter[3], ALfilterType_HighShelf,
     ALfilterState_setParams(&state->filter[3], ALfilterType_HighShelf,
-                            sqrtf(slot->EffectProps.Equalizer.HighGain),
-                            slot->EffectProps.Equalizer.HighCutoff/frequency,
-                            0.0f);
+        gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
+    );
 }
 }
 
 
-static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     ALuint base;
     ALuint base;
     ALuint it;
     ALuint it;
@@ -128,8 +135,8 @@ static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesTo
 
 
     for(base = 0;base < SamplesToDo;)
     for(base = 0;base < SamplesToDo;)
     {
     {
-        ALfloat temps[64];
-        ALuint td = minu(SamplesToDo-base, 64);
+        ALfloat temps[256];
+        ALuint td = minu(256, SamplesToDo-base);
 
 
         for(it = 0;it < td;it++)
         for(it = 0;it < td;it++)
         {
         {
@@ -141,10 +148,10 @@ static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesTo
             temps[it] = smp;
             temps[it] = smp;
         }
         }
 
 
-        for(kt = 0;kt < MaxChannels;kt++)
+        for(kt = 0;kt < NumChannels;kt++)
         {
         {
             ALfloat gain = state->Gain[kt];
             ALfloat gain = state->Gain[kt];
-            if(!(gain > GAIN_SILENCE_THRESHOLD))
+            if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
                 continue;
                 continue;
 
 
             for(it = 0;it < td;it++)
             for(it = 0;it < td;it++)

+ 14 - 12
libs/openal-soft/Alc/effects/flanger.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -46,7 +46,7 @@ typedef struct ALflangerState {
     ALint lfo_disp;
     ALint lfo_disp;
 
 
     /* Gains for left and right sides */
     /* Gains for left and right sides */
-    ALfloat Gain[2][MaxChannels];
+    ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
 
 
     /* effect parameters */
     /* effect parameters */
     enum FlangerWaveForm waveform;
     enum FlangerWaveForm waveform;
@@ -93,6 +93,8 @@ static ALboolean ALflangerState_deviceUpdate(ALflangerState *state, ALCdevice *D
 
 
 static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, const ALeffectslot *Slot)
 static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, const ALeffectslot *Slot)
 {
 {
+    static const ALfloat left_dir[3] = { -1.0f, 0.0f, 0.0f };
+    static const ALfloat right_dir[3] = { 1.0f, 0.0f, 0.0f };
     ALfloat frequency = (ALfloat)Device->Frequency;
     ALfloat frequency = (ALfloat)Device->Frequency;
     ALfloat rate;
     ALfloat rate;
     ALint phase;
     ALint phase;
@@ -111,8 +113,8 @@ static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, co
     state->delay = fastf2i(Slot->EffectProps.Flanger.Delay * frequency);
     state->delay = fastf2i(Slot->EffectProps.Flanger.Delay * frequency);
 
 
     /* Gains for left and right sides */
     /* Gains for left and right sides */
-    ComputeAngleGains(Device, atan2f(-1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[0]);
-    ComputeAngleGains(Device, atan2f(+1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[1]);
+    ComputeDirectionalGains(Device, left_dir, Slot->Gain, state->Gain[0]);
+    ComputeDirectionalGains(Device, right_dir, Slot->Gain, state->Gain[1]);
 
 
     phase = Slot->EffectProps.Flanger.Phase;
     phase = Slot->EffectProps.Flanger.Phase;
     rate = Slot->EffectProps.Flanger.Rate;
     rate = Slot->EffectProps.Flanger.Rate;
@@ -132,7 +134,7 @@ static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, co
                 state->lfo_scale = 4.0f / state->lfo_range;
                 state->lfo_scale = 4.0f / state->lfo_range;
                 break;
                 break;
             case FWF_Sinusoid:
             case FWF_Sinusoid:
-                state->lfo_scale = F_2PI / state->lfo_range;
+                state->lfo_scale = F_TAU / state->lfo_range;
                 break;
                 break;
         }
         }
 
 
@@ -201,15 +203,15 @@ DECL_TEMPLATE(Sinusoid)
 
 
 #undef DECL_TEMPLATE
 #undef DECL_TEMPLATE
 
 
-static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     ALuint it, kt;
     ALuint it, kt;
     ALuint base;
     ALuint base;
 
 
     for(base = 0;base < SamplesToDo;)
     for(base = 0;base < SamplesToDo;)
     {
     {
-        ALfloat temps[64][2];
-        ALuint td = minu(SamplesToDo-base, 64);
+        ALfloat temps[128][2];
+        ALuint td = minu(128, SamplesToDo-base);
 
 
         switch(state->waveform)
         switch(state->waveform)
         {
         {
@@ -221,17 +223,17 @@ static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo,
                 break;
                 break;
         }
         }
 
 
-        for(kt = 0;kt < MaxChannels;kt++)
+        for(kt = 0;kt < NumChannels;kt++)
         {
         {
             ALfloat gain = state->Gain[0][kt];
             ALfloat gain = state->Gain[0][kt];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
             {
             {
                 for(it = 0;it < td;it++)
                 for(it = 0;it < td;it++)
                     SamplesOut[kt][it+base] += temps[it][0] * gain;
                     SamplesOut[kt][it+base] += temps[it][0] * gain;
             }
             }
 
 
             gain = state->Gain[1][kt];
             gain = state->Gain[1][kt];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
             {
             {
                 for(it = 0;it < td;it++)
                 for(it = 0;it < td;it++)
                     SamplesOut[kt][it+base] += temps[it][1] * gain;
                     SamplesOut[kt][it+base] += temps[it][1] * gain;

+ 16 - 17
libs/openal-soft/Alc/effects/modulator.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -42,7 +42,7 @@ typedef struct ALmodulatorState {
     ALuint index;
     ALuint index;
     ALuint step;
     ALuint step;
 
 
-    ALfloat Gain[MaxChannels];
+    ALfloat Gain[MAX_OUTPUT_CHANNELS];
 
 
     ALfilterState Filter;
     ALfilterState Filter;
 } ALmodulatorState;
 } ALmodulatorState;
@@ -53,7 +53,7 @@ typedef struct ALmodulatorState {
 
 
 static inline ALfloat Sin(ALuint index)
 static inline ALfloat Sin(ALuint index)
 {
 {
-    return sinf(index*(F_2PI/WAVEFORM_FRACONE) - F_PI)*0.5f + 0.5f;
+    return sinf(index*(F_TAU/WAVEFORM_FRACONE) - F_PI)*0.5f + 0.5f;
 }
 }
 
 
 static inline ALfloat Saw(ALuint index)
 static inline ALfloat Saw(ALuint index)
@@ -69,7 +69,7 @@ static inline ALfloat Square(ALuint index)
 #define DECL_TEMPLATE(func)                                                   \
 #define DECL_TEMPLATE(func)                                                   \
 static void Process##func(ALmodulatorState *state, ALuint SamplesToDo,        \
 static void Process##func(ALmodulatorState *state, ALuint SamplesToDo,        \
   const ALfloat *restrict SamplesIn,                                          \
   const ALfloat *restrict SamplesIn,                                          \
-  ALfloat (*restrict SamplesOut)[BUFFERSIZE])                                 \
+  ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)             \
 {                                                                             \
 {                                                                             \
     const ALuint step = state->step;                                          \
     const ALuint step = state->step;                                          \
     ALuint index = state->index;                                              \
     ALuint index = state->index;                                              \
@@ -77,8 +77,8 @@ static void Process##func(ALmodulatorState *state, ALuint SamplesToDo,        \
                                                                               \
                                                                               \
     for(base = 0;base < SamplesToDo;)                                         \
     for(base = 0;base < SamplesToDo;)                                         \
     {                                                                         \
     {                                                                         \
-        ALfloat temps[64];                                                    \
-        ALuint td = minu(SamplesToDo-base, 64);                               \
+        ALfloat temps[256];                                                   \
+        ALuint td = minu(256, SamplesToDo-base);                              \
         ALuint i, k;                                                          \
         ALuint i, k;                                                          \
                                                                               \
                                                                               \
         for(i = 0;i < td;i++)                                                 \
         for(i = 0;i < td;i++)                                                 \
@@ -92,10 +92,10 @@ static void Process##func(ALmodulatorState *state, ALuint SamplesToDo,        \
             temps[i] = samp * func(index);                                    \
             temps[i] = samp * func(index);                                    \
         }                                                                     \
         }                                                                     \
                                                                               \
                                                                               \
-        for(k = 0;k < MaxChannels;k++)                                        \
+        for(k = 0;k < NumChannels;k++)                                        \
         {                                                                     \
         {                                                                     \
             ALfloat gain = state->Gain[k];                                    \
             ALfloat gain = state->Gain[k];                                    \
-            if(!(gain > GAIN_SILENCE_THRESHOLD))                              \
+            if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))                       \
                 continue;                                                     \
                 continue;                                                     \
                                                                               \
                                                                               \
             for(i = 0;i < td;i++)                                             \
             for(i = 0;i < td;i++)                                             \
@@ -125,7 +125,7 @@ static ALboolean ALmodulatorState_deviceUpdate(ALmodulatorState *UNUSED(state),
 
 
 static ALvoid ALmodulatorState_update(ALmodulatorState *state, ALCdevice *Device, const ALeffectslot *Slot)
 static ALvoid ALmodulatorState_update(ALmodulatorState *state, ALCdevice *Device, const ALeffectslot *Slot)
 {
 {
-    ALfloat gain, cw, a;
+    ALfloat cw, a;
 
 
     if(Slot->EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
     if(Slot->EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
         state->Waveform = SINUSOID;
         state->Waveform = SINUSOID;
@@ -139,7 +139,7 @@ static ALvoid ALmodulatorState_update(ALmodulatorState *state, ALCdevice *Device
     if(state->step == 0) state->step = 1;
     if(state->step == 0) state->step = 1;
 
 
     /* Custom filter coeffs, which match the old version instead of a low-shelf. */
     /* Custom filter coeffs, which match the old version instead of a low-shelf. */
-    cw = cosf(F_2PI * Slot->EffectProps.Modulator.HighPassCutoff / Device->Frequency);
+    cw = cosf(F_TAU * Slot->EffectProps.Modulator.HighPassCutoff / Device->Frequency);
     a = (2.0f-cw) - sqrtf(powf(2.0f-cw, 2.0f) - 1.0f);
     a = (2.0f-cw) - sqrtf(powf(2.0f-cw, 2.0f) - 1.0f);
 
 
     state->Filter.b[0] = a;
     state->Filter.b[0] = a;
@@ -149,24 +149,23 @@ static ALvoid ALmodulatorState_update(ALmodulatorState *state, ALCdevice *Device
     state->Filter.a[1] = -a;
     state->Filter.a[1] = -a;
     state->Filter.a[2] = 0.0f;
     state->Filter.a[2] = 0.0f;
 
 
-    gain = sqrtf(1.0f/Device->NumChan) * Slot->Gain;
-    SetGains(Device, gain, state->Gain);
+    ComputeAmbientGains(Device, Slot->Gain, state->Gain);
 }
 }
 
 
-static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels)
 {
 {
     switch(state->Waveform)
     switch(state->Waveform)
     {
     {
         case SINUSOID:
         case SINUSOID:
-            ProcessSin(state, SamplesToDo, SamplesIn, SamplesOut);
+            ProcessSin(state, SamplesToDo, SamplesIn, SamplesOut, NumChannels);
             break;
             break;
 
 
         case SAWTOOTH:
         case SAWTOOTH:
-            ProcessSaw(state, SamplesToDo, SamplesIn, SamplesOut);
+            ProcessSaw(state, SamplesToDo, SamplesIn, SamplesOut, NumChannels);
             break;
             break;
 
 
         case SQUARE:
         case SQUARE:
-            ProcessSquare(state, SamplesToDo, SamplesIn, SamplesOut);
+            ProcessSquare(state, SamplesToDo, SamplesIn, SamplesOut, NumChannels);
             break;
             break;
     }
     }
 }
 }

+ 1 - 4
libs/openal-soft/Alc/effects/null.c

@@ -41,11 +41,8 @@ static ALvoid ALnullState_update(ALnullState* UNUSED(state), ALCdevice* UNUSED(d
  * input to the output buffer. The result should be added to the output buffer,
  * input to the output buffer. The result should be added to the output buffer,
  * not replace it.
  * not replace it.
  */
  */
-static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALuint UNUSED(samplesToDo), const ALfloat *restrict UNUSED(samplesIn), ALfloat (*restrict samplesOut)[BUFFERSIZE])
+static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALuint UNUSED(samplesToDo), const ALfloat *restrict UNUSED(samplesIn), ALfloatBUFFERSIZE*restrict UNUSED(samplesOut), ALuint UNUSED(NumChannels))
 {
 {
-    /* NOTE: Couldn't use the UNUSED macro on samplesOut due to the way GCC's
-     * __attribute__ declaration interacts with the parenthesis. */
-    (void)samplesOut;
 }
 }
 
 
 /* This allocates memory to store the object, before it gets constructed.
 /* This allocates memory to store the object, before it gets constructed.

File diff suppressed because it is too large
+ 417 - 395
libs/openal-soft/Alc/effects/reverb.c


+ 655 - 93
libs/openal-soft/Alc/helpers.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -35,6 +35,9 @@
 #ifdef HAVE_MALLOC_H
 #ifdef HAVE_MALLOC_H
 #include <malloc.h>
 #include <malloc.h>
 #endif
 #endif
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
 
 
 #ifndef AL_NO_UID_DEFS
 #ifndef AL_NO_UID_DEFS
 #if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H)
 #if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H)
@@ -55,10 +58,13 @@ DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc
 DEFINE_GUID(IID_IMMDeviceEnumerator,  0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6);
 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_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);
 DEFINE_GUID(IID_IAudioRenderClient,   0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2);
+DEFINE_GUID(IID_IAudioCaptureClient,  0xc8adbd64, 0xe71e, 0x48a0, 0xa4,0xde, 0x18,0x5c,0x39,0x5c,0xd3,0x17);
 
 
 #ifdef HAVE_MMDEVAPI
 #ifdef HAVE_MMDEVAPI
 #include <devpropdef.h>
 #include <devpropdef.h>
+#include <propkeydef.h>
 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
+DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0);
 #endif
 #endif
 #endif
 #endif
 #endif /* AL_NO_UID_DEFS */
 #endif /* AL_NO_UID_DEFS */
@@ -82,7 +88,9 @@ DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,
 #include <ieeefp.h>
 #include <ieeefp.h>
 #endif
 #endif
 
 
-#ifdef _WIN32_IE
+#ifndef _WIN32
+#include <unistd.h>
+#elif defined(_WIN32_IE)
 #include <shlobj.h>
 #include <shlobj.h>
 #endif
 #endif
 
 
@@ -144,8 +152,12 @@ void FillCPUCaps(ALuint capfilter)
                 if((cpuinf[0].regs[3]&(1<<26)))
                 if((cpuinf[0].regs[3]&(1<<26)))
                 {
                 {
                     caps |= CPU_CAP_SSE2;
                     caps |= CPU_CAP_SSE2;
-                    if((cpuinf[0].regs[2]&(1<<19)))
-                        caps |= CPU_CAP_SSE4_1;
+                    if((cpuinf[0].regs[2]&(1<<0)))
+                    {
+                        caps |= CPU_CAP_SSE3;
+                        if((cpuinf[0].regs[2]&(1<<19)))
+                            caps |= CPU_CAP_SSE4_1;
+                    }
                 }
                 }
             }
             }
         }
         }
@@ -188,8 +200,12 @@ void FillCPUCaps(ALuint capfilter)
                 if((cpuinf[0].regs[3]&(1<<26)))
                 if((cpuinf[0].regs[3]&(1<<26)))
                 {
                 {
                     caps |= CPU_CAP_SSE2;
                     caps |= CPU_CAP_SSE2;
-                    if((cpuinf[0].regs[2]&(1<<19)))
-                        caps |= CPU_CAP_SSE4_1;
+                    if((cpuinf[0].regs[2]&(1<<0)))
+                    {
+                        caps |= CPU_CAP_SSE3;
+                        if((cpuinf[0].regs[2]&(1<<19)))
+                            caps |= CPU_CAP_SSE4_1;
+                    }
                 }
                 }
             }
             }
         }
         }
@@ -198,13 +214,16 @@ void FillCPUCaps(ALuint capfilter)
     /* Assume support for whatever's supported if we can't check for it */
     /* Assume support for whatever's supported if we can't check for it */
 #if defined(HAVE_SSE4_1)
 #if defined(HAVE_SSE4_1)
 #warning "Assuming SSE 4.1 run-time support!"
 #warning "Assuming SSE 4.1 run-time support!"
-    capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1;
+    caps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1;
+#elif defined(HAVE_SSE3)
+#warning "Assuming SSE 3 run-time support!"
+    caps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3;
 #elif defined(HAVE_SSE2)
 #elif defined(HAVE_SSE2)
 #warning "Assuming SSE 2 run-time support!"
 #warning "Assuming SSE 2 run-time support!"
-    capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2;
+    caps |= CPU_CAP_SSE | CPU_CAP_SSE2;
 #elif defined(HAVE_SSE)
 #elif defined(HAVE_SSE)
 #warning "Assuming SSE run-time support!"
 #warning "Assuming SSE run-time support!"
-    capfilter |= CPU_CAP_SSE;
+    caps |= CPU_CAP_SSE;
 #endif
 #endif
 #endif
 #endif
 #ifdef HAVE_NEON
 #ifdef HAVE_NEON
@@ -212,9 +231,10 @@ void FillCPUCaps(ALuint capfilter)
     caps |= CPU_CAP_NEON;
     caps |= CPU_CAP_NEON;
 #endif
 #endif
 
 
-    TRACE("Extensions:%s%s%s%s%s\n",
+    TRACE("Extensions:%s%s%s%s%s%s\n",
         ((capfilter&CPU_CAP_SSE)    ? ((caps&CPU_CAP_SSE)    ? " +SSE"    : " -SSE")    : ""),
         ((capfilter&CPU_CAP_SSE)    ? ((caps&CPU_CAP_SSE)    ? " +SSE"    : " -SSE")    : ""),
         ((capfilter&CPU_CAP_SSE2)   ? ((caps&CPU_CAP_SSE2)   ? " +SSE2"   : " -SSE2")   : ""),
         ((capfilter&CPU_CAP_SSE2)   ? ((caps&CPU_CAP_SSE2)   ? " +SSE2"   : " -SSE2")   : ""),
+        ((capfilter&CPU_CAP_SSE3)   ? ((caps&CPU_CAP_SSE3)   ? " +SSE3"   : " -SSE3")   : ""),
         ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""),
         ((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&CPU_CAP_NEON)   ? ((caps&CPU_CAP_NEON)   ? " +Neon"   : " -Neon")   : ""),
         ((!capfilter) ? " -none-" : "")
         ((!capfilter) ? " -none-" : "")
@@ -240,7 +260,7 @@ void *al_malloc(size_t alignment, size_t size)
     if(ret != NULL)
     if(ret != NULL)
     {
     {
         *(ret++) = 0x00;
         *(ret++) = 0x00;
-        while(((ALintptrEXT)ret&(alignment-1)) != 0)
+        while(((ptrdiff_t)ret&(alignment-1)) != 0)
             *(ret++) = 0x55;
             *(ret++) = 0x55;
     }
     }
     return ret;
     return ret;
@@ -278,6 +298,8 @@ void SetMixerFPUMode(FPUCtl *ctl)
 #ifdef HAVE_FENV_H
 #ifdef HAVE_FENV_H
     fegetenv(STATIC_CAST(fenv_t, ctl));
     fegetenv(STATIC_CAST(fenv_t, ctl));
 #if defined(__GNUC__) && defined(HAVE_SSE)
 #if defined(__GNUC__) && defined(HAVE_SSE)
+    /* FIXME: Some fegetenv implementations can get the SSE environment too?
+     * How to tell when it does? */
     if((CPUCapFlags&CPU_CAP_SSE))
     if((CPUCapFlags&CPU_CAP_SSE))
         __asm__ __volatile__("stmxcsr %0" : "=m" (*&ctl->sse_state));
         __asm__ __volatile__("stmxcsr %0" : "=m" (*&ctl->sse_state));
 #endif
 #endif
@@ -421,55 +443,31 @@ FILE *al_fopen(const char *fname, const char *mode)
     return file;
     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, ...)
 void al_print(const char *type, const char *func, const char *fmt, ...)
 {
 {
+    char str[1024];
+    WCHAR *wstr;
     va_list ap;
     va_list ap;
 
 
     va_start(ap, fmt);
     va_start(ap, fmt);
-    fprintf(LogFile, "AL lib: %s %s: ", type, func);
-    vfprintf(LogFile, fmt, ap);
+    vsnprintf(str, sizeof(str), fmt, ap);
     va_end(ap);
     va_end(ap);
 
 
+    str[sizeof(str)-1] = 0;
+    wstr = FromUTF8(str);
+    if(!wstr)
+        fprintf(LogFile, "AL lib: %s %s: <UTF-8 error> %s", type, func, str);
+    else
+    {
+        fprintf(LogFile, "AL lib: %s %s: %ls", type, func, wstr);
+        free(wstr);
+        wstr = NULL;
+    }
     fflush(LogFile);
     fflush(LogFile);
 }
 }
 
 
-#ifdef _WIN32
+
 static inline int is_slash(int c)
 static inline int is_slash(int c)
 { return (c == '\\' || c == '/'); }
 { return (c == '\\' || c == '/'); }
 
 
@@ -478,35 +476,42 @@ FILE *OpenDataFile(const char *fname, const char *subdir)
     static const int ids[2] = { CSIDL_APPDATA, CSIDL_COMMON_APPDATA };
     static const int ids[2] = { CSIDL_APPDATA, CSIDL_COMMON_APPDATA };
     WCHAR *wname=NULL, *wsubdir=NULL;
     WCHAR *wname=NULL, *wsubdir=NULL;
     FILE *f;
     FILE *f;
-    int i;
+    size_t i;
 
 
-    /* If the path is absolute, open it directly. */
-    if(fname[0] != '\0' && fname[1] == ':' && is_slash(fname[2]))
+    wname = FromUTF8(fname);
+    if(!wname)
     {
     {
-        if((f=al_fopen(fname, "rb")) != NULL)
-        {
-            TRACE("Opened %s\n", fname);
-            return f;
-        }
-        WARN("Could not open %s\n", fname);
+        ERR("Failed to convert UTF-8 filename: \"%s\"\n", fname);
         return NULL;
         return NULL;
     }
     }
 
 
-    /* If it's relative, try the current directory first before the data directories. */
-    if((f=al_fopen(fname, "rb")) != NULL)
+    /* If the path is absolute, open it directly. */
+    if(wname[0] != '\0' && wname[1] == ':' && is_slash(wname[2]))
+    {
+        f = _wfopen(wname, L"rb");
+        if(f) TRACE("Opened %s\n", fname);
+        else WARN("Could not open %s\n", fname);
+        free(wname);
+        return f;
+    }
+
+    /* Try the current directory first before the data directories. */
+    if((f=_wfopen(wname, L"rb")) != NULL)
     {
     {
         TRACE("Opened %s\n", fname);
         TRACE("Opened %s\n", fname);
+        free(wname);
         return f;
         return f;
     }
     }
-    WARN("Could not open %s\n", fname);
 
 
-    wname = FromUTF8(fname);
     wsubdir = FromUTF8(subdir);
     wsubdir = FromUTF8(subdir);
-    if(!wname)
-        ERR("Failed to convert UTF-8 filename: \"%s\"\n", fname);
-    else if(!wsubdir)
+    if(!wsubdir)
+    {
         ERR("Failed to convert UTF-8 subdir: \"%s\"\n", subdir);
         ERR("Failed to convert UTF-8 subdir: \"%s\"\n", subdir);
-    else for(i = 0;i < 2;i++)
+        free(wname);
+        return NULL;
+    }
+
+    for(i = 0;i < COUNTOF(ids);i++)
     {
     {
         WCHAR buffer[PATH_MAX];
         WCHAR buffer[PATH_MAX];
         size_t len;
         size_t len;
@@ -528,17 +533,347 @@ FILE *OpenDataFile(const char *fname, const char *subdir)
 
 
         if((f=_wfopen(buffer, L"rb")) != NULL)
         if((f=_wfopen(buffer, L"rb")) != NULL)
         {
         {
-            TRACE("Opened %ls\n", buffer);
-            return f;
+            al_string filepath = AL_STRING_INIT_STATIC();
+            al_string_copy_wcstr(&filepath, buffer);
+            TRACE("Opened %s\n", al_string_get_cstr(filepath));
+            al_string_deinit(&filepath);
+            break;
         }
         }
-        WARN("Could not open %ls\n", buffer);
     }
     }
     free(wname);
     free(wname);
     free(wsubdir);
     free(wsubdir);
 
 
+    if(f == NULL)
+        WARN("Could not open %s\\%s\n", subdir, fname);
+    return f;
+}
+
+
+static const WCHAR *strchrW(const WCHAR *str, WCHAR ch)
+{
+    for(;*str != 0;++str)
+    {
+        if(*str == ch)
+            return str;
+    }
     return NULL;
     return NULL;
 }
 }
+
+static const WCHAR *strrchrW(const WCHAR *str, WCHAR ch)
+{
+    const WCHAR *ret = NULL;
+    for(;*str != 0;++str)
+    {
+        if(*str == ch)
+            ret = str;
+    }
+    return ret;
+}
+
+/* Compares the filename in the find data with the match string. The match
+ * string may contain the "%r" marker to signifiy a sample rate (really any
+ * positive integer), or "%%" to signify a single '%'.
+ */
+static int MatchFilter(const WCHAR *match, const WIN32_FIND_DATAW *fdata)
+{
+    const WCHAR *name = fdata->cFileName;
+    int ret = 1;
+
+    do {
+        const WCHAR *p = strchrW(match, '%');
+        if(!p)
+            ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE,
+                                 match, -1, name, -1) == CSTR_EQUAL;
+        else
+        {
+            int len = p-match;
+            ret = lstrlenW(name) >= len;
+            if(ret)
+                ret = CompareStringW(GetThreadLocale(), NORM_IGNORECASE,
+                                     match, len, name, len) == CSTR_EQUAL;
+            if(ret)
+            {
+                match += len;
+                name += len;
+
+                ++p;
+                if(*p == 'r')
+                {
+                    unsigned long l = 0;
+                    while(*name >= '0' && *name <= '9')
+                    {
+                        l = l*10 + (*name-'0');
+                        ++name;
+                    }
+                    ret = l > 0;
+                    ++p;
+                }
+            }
+        }
+
+        match = p;
+    } while(ret && match && *match);
+
+    return ret;
+}
+
+static void RecurseDirectorySearch(const char *path, const WCHAR *match, vector_al_string *results)
+{
+    WIN32_FIND_DATAW fdata;
+    const WCHAR *sep, *p;
+    HANDLE hdl;
+
+    if(!match[0])
+        return;
+
+    /* Find the last directory separator and the next '%' marker in the match
+     * string. */
+    sep = strrchrW(match, '\\');
+    p = strchrW(match, '%');
+
+    /* If there's no separator, test the files in the specified path against
+     * the match string, and add the results. */
+    if(!sep)
+    {
+        al_string pathstr = AL_STRING_INIT_STATIC();
+        WCHAR *wpath;
+
+        TRACE("Searching %s for %ls\n", path, match);
+
+        al_string_append_cstr(&pathstr, path);
+        al_string_append_cstr(&pathstr, "\\*.*");
+        wpath = FromUTF8(al_string_get_cstr(pathstr));
+
+        hdl = FindFirstFileW(wpath, &fdata);
+        if(hdl != INVALID_HANDLE_VALUE)
+        {
+            do {
+                if(MatchFilter(match, &fdata))
+                {
+                    al_string str = AL_STRING_INIT_STATIC();
+                    al_string_copy_cstr(&str, path);
+                    al_string_append_char(&str, '\\');
+                    al_string_append_wcstr(&str, fdata.cFileName);
+                    TRACE("Got result %s\n", al_string_get_cstr(str));
+                    VECTOR_PUSH_BACK(*results, str);
+                }
+            } while(FindNextFileW(hdl, &fdata));
+            FindClose(hdl);
+        }
+
+        free(wpath);
+        al_string_deinit(&pathstr);
+
+        return;
+    }
+
+    /* If there's no '%' marker, or it's after the final separator, append the
+     * remaining directories to the path and recurse into it with the remaining
+     * filename portion. */
+    if(!p || p-sep >= 0)
+    {
+        al_string npath = AL_STRING_INIT_STATIC();
+        al_string_append_cstr(&npath, path);
+        al_string_append_char(&npath, '\\');
+        al_string_append_wrange(&npath, match, sep);
+
+        TRACE("Recursing into %s with %ls\n", al_string_get_cstr(npath), sep+1);
+        RecurseDirectorySearch(al_string_get_cstr(npath), sep+1, results);
+
+        al_string_deinit(&npath);
+        return;
+    }
+
+    /* Look for the last separator before the '%' marker, and the first
+     * separator after it. */
+    sep = strchrW(match, '\\');
+    if(sep-p >= 0) sep = NULL;
+    for(;;)
+    {
+        const WCHAR *next = strchrW(sep?sep+1:match, '\\');
+        if(next-p < 0)
+        {
+            al_string npath = AL_STRING_INIT_STATIC();
+            WCHAR *nwpath, *nwmatch;
+
+            /* Append up to the last directory before the one with a '%'. */
+            al_string_copy_cstr(&npath, path);
+            if(sep)
+            {
+                al_string_append_char(&npath, '\\');
+                al_string_append_wrange(&npath, match, sep);
+            }
+            al_string_append_cstr(&npath, "\\*.*");
+            nwpath = FromUTF8(al_string_get_cstr(npath));
+
+            /* Take the directory name containing a '%' as a new string to
+             * match against. */
+            if(!sep)
+            {
+                nwmatch = calloc(2, next-match+1);
+                memcpy(nwmatch, match, (next-match)*2);
+            }
+            else
+            {
+                nwmatch = calloc(2, next-(sep+1)+1);
+                memcpy(nwmatch, sep+1, (next-(sep+1))*2);
+            }
+
+            /* For each matching directory name, recurse into it with the
+             * remaining string. */
+            TRACE("Searching %s for %ls\n", al_string_get_cstr(npath), nwmatch);
+            hdl = FindFirstFileW(nwpath, &fdata);
+            if(hdl != INVALID_HANDLE_VALUE)
+            {
+                do {
+                    if(MatchFilter(nwmatch, &fdata))
+                    {
+                        al_string ndir = AL_STRING_INIT_STATIC();
+                        al_string_copy(&ndir, npath);
+                        al_string_append_char(&ndir, '\\');
+                        al_string_append_wcstr(&ndir, fdata.cFileName);
+                        TRACE("Recursing %s with %ls\n", al_string_get_cstr(ndir), next+1);
+                        RecurseDirectorySearch(al_string_get_cstr(ndir), next+1, results);
+                        al_string_deinit(&ndir);
+                    }
+                } while(FindNextFileW(hdl, &fdata));
+                FindClose(hdl);
+            }
+
+            free(nwmatch);
+            free(nwpath);
+            al_string_deinit(&npath);
+            break;
+        }
+        sep = next;
+    }
+}
+
+vector_al_string SearchDataFiles(const char *match, const char *subdir)
+{
+    static const int ids[2] = { CSIDL_APPDATA, CSIDL_COMMON_APPDATA };
+    static RefCount search_lock;
+    vector_al_string results = VECTOR_INIT_STATIC();
+    WCHAR *wmatch;
+    size_t i;
+
+    while(ATOMIC_EXCHANGE(uint, &search_lock, 1) == 1)
+        althrd_yield();
+
+    wmatch = FromUTF8(match);
+    if(!wmatch)
+    {
+        ERR("Failed to convert UTF-8 filename: \"%s\"\n", match);
+        return results;
+    }
+    for(i = 0;wmatch[i];++i)
+    {
+        if(wmatch[i] == '/')
+            wmatch[i] = '\\';
+    }
+
+    /* If the path is absolute, use it directly. */
+    if(isalpha(wmatch[0]) && wmatch[1] == ':' && is_slash(wmatch[2]))
+    {
+        char drv[3] = { (char)wmatch[0], ':', 0 };
+        RecurseDirectorySearch(drv, wmatch+3, &results);
+    }
+    else if(wmatch[0] == '\\' && wmatch[1] == '\\' && wmatch[2] == '?' && wmatch[3] == '\\')
+        RecurseDirectorySearch("\\\\?", wmatch+4, &results);
+    else
+    {
+        al_string path = AL_STRING_INIT_STATIC();
+        WCHAR *cwdbuf;
+
+        /* Search the CWD. */
+        if(!(cwdbuf=_wgetcwd(NULL, 0)))
+            al_string_copy_cstr(&path, ".");
+        else
+        {
+            al_string_copy_wcstr(&path, cwdbuf);
+            if(is_slash(VECTOR_BACK(path)))
+            {
+                VECTOR_POP_BACK(path);
+                *VECTOR_ITER_END(path) = 0;
+            }
+            free(cwdbuf);
+        }
+        RecurseDirectorySearch(al_string_get_cstr(path), wmatch, &results);
+
+        /* Search the local and global data dirs. */
+        for(i = 0;i < COUNTOF(ids);i++)
+        {
+            WCHAR buffer[PATH_MAX];
+            if(SHGetSpecialFolderPathW(NULL, buffer, ids[i], FALSE) != FALSE)
+            {
+                al_string_copy_wcstr(&path, buffer);
+                if(!is_slash(VECTOR_BACK(path)))
+                    al_string_append_char(&path, '\\');
+                al_string_append_cstr(&path, subdir);
+#define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0)
+                VECTOR_FOR_EACH(char, path, FIX_SLASH);
+#undef FIX_SLASH
+
+                RecurseDirectorySearch(al_string_get_cstr(path), wmatch, &results);
+            }
+        }
+
+        al_string_deinit(&path);
+    }
+
+    free(wmatch);
+    ATOMIC_STORE(&search_lock, 0);
+
+    return results;
+}
+
 #else
 #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 /* HAVE_DLFCN_H */
+
+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);
+}
+
+
 FILE *OpenDataFile(const char *fname, const char *subdir)
 FILE *OpenDataFile(const char *fname, const char *subdir)
 {
 {
     char buffer[PATH_MAX] = "";
     char buffer[PATH_MAX] = "";
@@ -561,7 +896,6 @@ FILE *OpenDataFile(const char *fname, const char *subdir)
         TRACE("Opened %s\n", fname);
         TRACE("Opened %s\n", fname);
         return f;
         return f;
     }
     }
-    WARN("Could not open %s\n", fname);
 
 
     if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0')
     if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0')
         snprintf(buffer, sizeof(buffer), "%s/%s/%s", str, subdir, fname);
         snprintf(buffer, sizeof(buffer), "%s/%s/%s", str, subdir, fname);
@@ -574,7 +908,6 @@ FILE *OpenDataFile(const char *fname, const char *subdir)
             TRACE("Opened %s\n", buffer);
             TRACE("Opened %s\n", buffer);
             return f;
             return f;
         }
         }
-        WARN("Could not open %s\n", buffer);
     }
     }
 
 
     if((str=getenv("XDG_DATA_DIRS")) == NULL || str[0] == '\0')
     if((str=getenv("XDG_DATA_DIRS")) == NULL || str[0] == '\0')
@@ -605,11 +938,221 @@ FILE *OpenDataFile(const char *fname, const char *subdir)
             TRACE("Opened %s\n", buffer);
             TRACE("Opened %s\n", buffer);
             return f;
             return f;
         }
         }
-        WARN("Could not open %s\n", buffer);
     }
     }
+    WARN("Could not open %s/%s\n", subdir, fname);
 
 
     return NULL;
     return NULL;
 }
 }
+
+
+static const char *MatchString;
+static int MatchFilter(const struct dirent *dir)
+{
+    const char *match = MatchString;
+    const char *name = dir->d_name;
+    int ret = 1;
+
+    do {
+        const char *p = strchr(match, '%');
+        if(!p)
+            ret = strcmp(match, name) == 0;
+        else
+        {
+            size_t len = p-match;
+            ret = strncmp(match, name, len) == 0;
+            if(ret)
+            {
+                match += len;
+                name += len;
+
+                ++p;
+                if(*p == 'r')
+                {
+                    char *end;
+                    ret = strtoul(name, &end, 10) > 0;
+                    if(ret) name = end;
+                    ++p;
+                }
+            }
+        }
+
+        match = p;
+    } while(ret && match && *match);
+
+    return ret;
+}
+
+static void RecurseDirectorySearch(const char *path, const char *match, vector_al_string *results)
+{
+    struct dirent **namelist;
+    char *sep, *p;
+    int n, i;
+
+    if(!match[0])
+        return;
+
+    sep = strrchr(match, '/');
+    p = strchr(match, '%');
+
+    if(!sep)
+    {
+        MatchString = match;
+        TRACE("Searching %s for %s\n", path?path:"/", match);
+        n = scandir(path?path:"/", &namelist, MatchFilter, alphasort);
+        if(n >= 0)
+        {
+            for(i = 0;i < n;++i)
+            {
+                al_string str = AL_STRING_INIT_STATIC();
+                if(path) al_string_copy_cstr(&str, path);
+                al_string_append_char(&str, '/');
+                al_string_append_cstr(&str, namelist[i]->d_name);
+                TRACE("Got result %s\n", al_string_get_cstr(str));
+                VECTOR_PUSH_BACK(*results, str);
+                free(namelist[i]);
+            }
+            free(namelist);
+        }
+
+        return;
+    }
+
+    if(!p || p-sep >= 0)
+    {
+        al_string npath = AL_STRING_INIT_STATIC();
+        if(path) al_string_append_cstr(&npath, path);
+        al_string_append_char(&npath, '/');
+        al_string_append_range(&npath, match, sep);
+
+        TRACE("Recursing into %s with %s\n", al_string_get_cstr(npath), sep+1);
+        RecurseDirectorySearch(al_string_get_cstr(npath), sep+1, results);
+
+        al_string_deinit(&npath);
+        return;
+    }
+
+    sep = strchr(match, '/');
+    if(sep-p >= 0) sep = NULL;
+    for(;;)
+    {
+        char *next = strchr(sep?sep+1:match, '/');
+        if(next-p < 0)
+        {
+            al_string npath = AL_STRING_INIT_STATIC();
+            al_string nmatch = AL_STRING_INIT_STATIC();
+
+            if(!sep)
+            {
+                al_string_append_cstr(&npath, path?path:"/.");
+                MatchString = match;
+            }
+            else
+            {
+                if(path) al_string_append_cstr(&npath, path);
+                al_string_append_char(&npath, '/');
+                al_string_append_range(&npath, match, sep);
+
+                al_string_append_range(&nmatch, sep+1, next);
+                MatchString = al_string_get_cstr(nmatch);
+            }
+
+            TRACE("Searching %s for %s\n", al_string_get_cstr(npath), MatchString);
+            n = scandir(al_string_get_cstr(npath), &namelist, MatchFilter, alphasort);
+            if(n >= 0)
+            {
+                al_string ndir = AL_STRING_INIT_STATIC();
+                for(i = 0;i < n;++i)
+                {
+                    al_string_copy(&ndir, npath);
+                    al_string_append_char(&ndir, '/');
+                    al_string_append_cstr(&ndir, namelist[i]->d_name);
+                    free(namelist[i]);
+                    TRACE("Recursing %s with %s\n", al_string_get_cstr(ndir), next+1);
+                    RecurseDirectorySearch(al_string_get_cstr(ndir), next+1, results);
+                }
+                al_string_deinit(&ndir);
+                free(namelist);
+            }
+
+            al_string_deinit(&nmatch);
+            al_string_deinit(&npath);
+            break;
+        }
+
+        sep = next;
+    }
+}
+
+vector_al_string SearchDataFiles(const char *match, const char *subdir)
+{
+    static RefCount search_lock;
+    vector_al_string results = VECTOR_INIT_STATIC();
+
+    while(ATOMIC_EXCHANGE(uint, &search_lock, 1) == 1)
+        althrd_yield();
+
+    if(match[0] == '/')
+        RecurseDirectorySearch(NULL, match+1, &results);
+    else
+    {
+        al_string path = AL_STRING_INIT_STATIC();
+        const char *str, *next;
+        char cwdbuf[PATH_MAX];
+
+        // Search CWD
+        if(!getcwd(cwdbuf, sizeof(cwdbuf)))
+            strcpy(cwdbuf, ".");
+        RecurseDirectorySearch(cwdbuf, match, &results);
+
+        // Search local data dir
+        if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0')
+        {
+            al_string_append_cstr(&path, str);
+            al_string_append_char(&path, '/');
+            al_string_append_cstr(&path, subdir);
+        }
+        else if((str=getenv("HOME")) != NULL && str[0] != '\0')
+        {
+            al_string_append_cstr(&path, str);
+            al_string_append_cstr(&path, "/.local/share/");
+            al_string_append_cstr(&path, subdir);
+        }
+        if(!al_string_empty(path))
+            RecurseDirectorySearch(al_string_get_cstr(path), match, &results);
+
+        // Search global data dirs
+        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')
+        {
+            next = strchr(str, ':');
+            if(!next)
+                al_string_copy_cstr(&path, str);
+            else
+            {
+                al_string_clear(&path);
+                al_string_append_range(&path, str, next);
+                ++next;
+            }
+            if(!al_string_empty(path))
+            {
+                al_string_append_char(&path, '/');
+                al_string_append_cstr(&path, subdir);
+
+                RecurseDirectorySearch(al_string_get_cstr(path), match, &results);
+            }
+        }
+
+        al_string_deinit(&path);
+    }
+
+    ATOMIC_STORE(&search_lock, 0);
+
+    return results;
+}
+
 #endif
 #endif
 
 
 
 
@@ -638,25 +1181,20 @@ void SetRTPriority(void)
 }
 }
 
 
 
 
-ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count, ALboolean exact)
+ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, size_t obj_count, ALboolean exact)
 {
 {
     vector_ *vecptr = (vector_*)ptr;
     vector_ *vecptr = (vector_*)ptr;
-    if(obj_count < 0)
-        return AL_FALSE;
     if((*vecptr ? (*vecptr)->Capacity : 0) < obj_count)
     if((*vecptr ? (*vecptr)->Capacity : 0) < obj_count)
     {
     {
-        ALsizei old_size = (*vecptr ? (*vecptr)->Size : 0);
+        size_t old_size = (*vecptr ? (*vecptr)->Size : 0);
         void *temp;
         void *temp;
 
 
         /* Use the next power-of-2 size if we don't need to allocate the exact
         /* 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
          * amount. This is preferred when regularly increasing the vector since
          * it means fewer reallocations. Though it means it also wastes some
          * it means fewer reallocations. Though it means it also wastes some
          * memory. */
          * memory. */
-        if(exact == AL_FALSE)
-        {
+        if(exact == AL_FALSE && obj_count < INT_MAX)
             obj_count = NextPowerOf2((ALuint)obj_count);
             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
         /* 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,
          * could have extra padding before the start of the array (that is,
@@ -671,11 +1209,9 @@ ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, ALsizei o
     return AL_TRUE;
     return AL_TRUE;
 }
 }
 
 
-ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count)
+ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, size_t obj_count)
 {
 {
     vector_ *vecptr = (vector_*)ptr;
     vector_ *vecptr = (vector_*)ptr;
-    if(obj_count < 0)
-        return AL_FALSE;
     if(*vecptr || obj_count > 0)
     if(*vecptr || obj_count > 0)
     {
     {
         if(!vector_reserve((char*)vecptr, base_size, obj_size, obj_count, AL_TRUE))
         if(!vector_reserve((char*)vecptr, base_size, obj_size, obj_count, AL_TRUE))
@@ -696,12 +1232,12 @@ ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_
         ptrdiff_t numins = ((const char*)datend - (const char*)datstart) / obj_size;
         ptrdiff_t numins = ((const char*)datend - (const char*)datstart) / obj_size;
 
 
         assert(numins > 0);
         assert(numins > 0);
-        if(INT_MAX-VECTOR_SIZE(*vecptr) <= numins ||
+        if((size_t)numins + VECTOR_SIZE(*vecptr) < (size_t)numins ||
            !vector_reserve((char*)vecptr, base_size, obj_size, VECTOR_SIZE(*vecptr)+numins, AL_TRUE))
            !vector_reserve((char*)vecptr, base_size, obj_size, VECTOR_SIZE(*vecptr)+numins, AL_TRUE))
             return AL_FALSE;
             return AL_FALSE;
 
 
         /* NOTE: ins_pos may have been invalidated if *vecptr moved. Use ins_elem instead. */
         /* NOTE: ins_pos may have been invalidated if *vecptr moved. Use ins_elem instead. */
-        if(ins_elem < (*vecptr)->Size)
+        if((size_t)ins_elem < (*vecptr)->Size)
         {
         {
             memmove((char*)(*vecptr) + base_size + ((ins_elem+numins)*obj_size),
             memmove((char*)(*vecptr) + base_size + ((ins_elem+numins)*obj_size),
                     (char*)(*vecptr) + base_size + ((ins_elem       )*obj_size),
                     (char*)(*vecptr) + base_size + ((ins_elem       )*obj_size),
@@ -709,14 +1245,14 @@ ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_
         }
         }
         memcpy((char*)(*vecptr) + base_size + (ins_elem*obj_size),
         memcpy((char*)(*vecptr) + base_size + (ins_elem*obj_size),
                datstart, numins*obj_size);
                datstart, numins*obj_size);
-        (*vecptr)->Size += (ALsizei)numins;
+        (*vecptr)->Size += numins;
     }
     }
     return AL_TRUE;
     return AL_TRUE;
 }
 }
 
 
 
 
 extern inline void al_string_deinit(al_string *str);
 extern inline void al_string_deinit(al_string *str);
-extern inline ALsizei al_string_length(const_al_string str);
+extern inline size_t al_string_length(const_al_string str);
 extern inline ALboolean al_string_empty(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);
 extern inline const al_string_char_type *al_string_get_cstr(const_al_string str);
 
 
@@ -730,10 +1266,10 @@ void al_string_clear(al_string *str)
     *VECTOR_ITER_END(*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)
+static inline int al_string_compare(const al_string_char_type *str1, size_t str1len,
+                                    const al_string_char_type *str2, size_t str2len)
 {
 {
-    ALsizei complen = mini(str1len, str2len);
+    size_t complen = (str1len < str2len) ? str1len : str2len;
     int ret = memcmp(str1, str2, complen);
     int ret = memcmp(str1, str2, complen);
     if(ret == 0)
     if(ret == 0)
     {
     {
@@ -750,12 +1286,12 @@ 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)
 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),
     return al_string_compare(&VECTOR_FRONT(str1), al_string_length(str1),
-                             str2, (ALsizei)strlen(str2));
+                             str2, strlen(str2));
 }
 }
 
 
 void al_string_copy(al_string *str, const_al_string from)
 void al_string_copy(al_string *str, const_al_string from)
 {
 {
-    ALsizei len = VECTOR_SIZE(from);
+    size_t len = al_string_length(from);
     VECTOR_RESERVE(*str, len+1);
     VECTOR_RESERVE(*str, len+1);
     VECTOR_RESIZE(*str, 0);
     VECTOR_RESIZE(*str, 0);
     VECTOR_INSERT(*str, VECTOR_ITER_END(*str), VECTOR_ITER_BEGIN(from), VECTOR_ITER_BEGIN(from)+len);
     VECTOR_INSERT(*str, VECTOR_ITER_END(*str), VECTOR_ITER_BEGIN(from), VECTOR_ITER_BEGIN(from)+len);
@@ -811,4 +1347,30 @@ void al_string_copy_wcstr(al_string *str, const wchar_t *from)
         *VECTOR_ITER_END(*str) = 0;
         *VECTOR_ITER_END(*str) = 0;
     }
     }
 }
 }
+
+void al_string_append_wcstr(al_string *str, const wchar_t *from)
+{
+    int len;
+    if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0)
+    {
+        size_t strlen = al_string_length(*str);
+        VECTOR_RESERVE(*str, strlen+len);
+        VECTOR_RESIZE(*str, strlen+len-1);
+        WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str) + strlen, len, NULL, NULL);
+        *VECTOR_ITER_END(*str) = 0;
+    }
+}
+
+void al_string_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to)
+{
+    int len;
+    if((len=WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), NULL, 0, NULL, NULL)) > 0)
+    {
+        size_t strlen = al_string_length(*str);
+        VECTOR_RESERVE(*str, strlen+len+1);
+        VECTOR_RESIZE(*str, strlen+len);
+        WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), &VECTOR_FRONT(*str) + strlen, len+1, NULL, NULL);
+        *VECTOR_ITER_END(*str) = 0;
+    }
+}
 #endif
 #endif

+ 255 - 175
libs/openal-soft/Alc/hrtf.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -30,6 +30,8 @@
 #include "alu.h"
 #include "alu.h"
 #include "hrtf.h"
 #include "hrtf.h"
 
 
+#include "compat.h"
+
 
 
 /* Current data set limits defined by the makehrtf utility. */
 /* Current data set limits defined by the makehrtf utility. */
 #define MIN_IR_SIZE                  (8)
 #define MIN_IR_SIZE                  (8)
@@ -52,6 +54,7 @@ struct Hrtf {
     const ALshort *coeffs;
     const ALshort *coeffs;
     const ALubyte *delays;
     const ALubyte *delays;
 
 
+    al_string filename;
     struct Hrtf *next;
     struct Hrtf *next;
 };
 };
 
 
@@ -82,45 +85,12 @@ static void CalcEvIndices(ALuint evcount, ALfloat ev, ALuint *evidx, ALfloat *ev
  */
  */
 static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *azmu)
 static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *azmu)
 {
 {
-    az = (F_2PI + az) * azcount / (F_2PI);
+    az = (F_TAU + az) * azcount / F_TAU;
     azidx[0] = fastf2u(az) % azcount;
     azidx[0] = fastf2u(az) % azcount;
     azidx[1] = (azidx[0] + 1) % azcount;
     azidx[1] = (azidx[0] + 1) % azcount;
     *azmu = az - floorf(az);
     *azmu = az - floorf(az);
 }
 }
 
 
-/* Calculates the normalized HRTF transition factor (delta) from the changes
- * in gain and listener to source angle between updates.  The result is a
- * normalized delta factor that can be used to calculate moving HRIR stepping
- * values.
- */
-ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3])
-{
-    ALfloat gainChange, angleChange, change;
-
-    // Calculate the normalized dB gain change.
-    newGain = maxf(newGain, 0.0001f);
-    oldGain = maxf(oldGain, 0.0001f);
-    gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f));
-
-    // 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])
-        {
-            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
-    // significance shaping function to it.
-    change = maxf(angleChange * 25.0f, gainChange) * 2.0f;
-    return minf(change, 1.0f);
-}
-
 /* Calculates static HRIR coefficients and delays for the given polar
 /* Calculates static HRIR coefficients and delays for the given polar
  * elevation and azimuth in radians.  Linear interpolation is used to
  * elevation and azimuth in radians.  Linear interpolation is used to
  * increase the apparent resolution of the HRIR data set.  The coefficients
  * increase the apparent resolution of the HRIR data set.  The coefficients
@@ -183,24 +153,22 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi
     {
     {
         ALfloat c;
         ALfloat c;
 
 
-        gain *= 1.0f/32767.0f;
-
         i = 0;
         i = 0;
         c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
         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]);
              Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
-        coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain;
+        coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain * (1.0f/32767.0f);
         c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
         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]);
              Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
-        coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain;
+        coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain * (1.0f/32767.0f);
 
 
         for(i = 1;i < Hrtf->irSize;i++)
         for(i = 1;i < Hrtf->irSize;i++)
         {
         {
             c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
             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]);
                  Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
-            coeffs[i][0] = lerp(0.0f, c, dirfact) * gain;
+            coeffs[i][0] = lerp(0.0f, c, dirfact) * gain * (1.0f/32767.0f);
             c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
             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]);
                  Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
-            coeffs[i][1] = lerp(0.0f, c, dirfact) * gain;
+            coeffs[i][1] = lerp(0.0f, c, dirfact) * gain * (1.0f/32767.0f);
         }
         }
     }
     }
     else
     else
@@ -225,7 +193,7 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
     ALuint evidx[2], lidx[4], ridx[4];
     ALuint evidx[2], lidx[4], ridx[4];
     ALfloat mu[3], blend[4];
     ALfloat mu[3], blend[4];
     ALfloat left, right;
     ALfloat left, right;
-    ALfloat step;
+    ALfloat steps;
     ALuint i;
     ALuint i;
 
 
     /* Claculate elevation indices and interpolation factor. */
     /* Claculate elevation indices and interpolation factor. */
@@ -248,8 +216,8 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
     }
     }
 
 
     // Calculate the stepping parameters.
     // Calculate the stepping parameters.
-    delta = maxf(floorf(delta*(Hrtf->sampleRate*0.015f) + 0.5f), 1.0f);
-    step = 1.0f / delta;
+    steps = maxf(floorf(delta*Hrtf->sampleRate + 0.5f), 1.0f);
+    delta = 1.0f / steps;
 
 
     /* Calculate 4 blending weights for 2D bilinear interpolation. */
     /* Calculate 4 blending weights for 2D bilinear interpolation. */
     blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
     blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
@@ -271,8 +239,8 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
                          Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
                          Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
                         dirfact + 0.5f) << HRTFDELAY_BITS;
                         dirfact + 0.5f) << HRTFDELAY_BITS;
 
 
-    delayStep[0] = fastf2i(step * (delays[0] - left));
-    delayStep[1] = fastf2i(step * (delays[1] - right));
+    delayStep[0] = fastf2i(delta * (delays[0] - left));
+    delayStep[1] = fastf2i(delta * (delays[1] - right));
 
 
     /* Calculate the sample offsets for the HRIR indices. */
     /* Calculate the sample offsets for the HRIR indices. */
     lidx[0] *= Hrtf->irSize;
     lidx[0] *= Hrtf->irSize;
@@ -294,21 +262,19 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
     {
     {
         ALfloat c;
         ALfloat c;
 
 
-        gain *= 1.0f/32767.0f;
-
         i = 0;
         i = 0;
         left = coeffs[i][0] - (coeffStep[i][0] * counter);
         left = coeffs[i][0] - (coeffStep[i][0] * counter);
         right = coeffs[i][1] - (coeffStep[i][1] * counter);
         right = coeffs[i][1] - (coeffStep[i][1] * counter);
 
 
         c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
         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]);
              Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
-        coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain;
+        coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain * (1.0f/32767.0f);
         c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
         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]);
              Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
-        coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain;
+        coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain * (1.0f/32767.0f);
 
 
-        coeffStep[i][0] = step * (coeffs[i][0] - left);
-        coeffStep[i][1] = step * (coeffs[i][1] - right);
+        coeffStep[i][0] = delta * (coeffs[i][0] - left);
+        coeffStep[i][1] = delta * (coeffs[i][1] - right);
 
 
         for(i = 1;i < Hrtf->irSize;i++)
         for(i = 1;i < Hrtf->irSize;i++)
         {
         {
@@ -317,13 +283,13 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
 
 
             c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
             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]);
                  Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
-            coeffs[i][0] = lerp(0.0f, c, dirfact) * gain;
+            coeffs[i][0] = lerp(0.0f, c, dirfact) * gain * (1.0f/32767.0f);
             c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
             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]);
                  Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
-            coeffs[i][1] = lerp(0.0f, c, dirfact) * gain;
+            coeffs[i][1] = lerp(0.0f, c, dirfact) * gain * (1.0f/32767.0f);
 
 
-            coeffStep[i][0] = step * (coeffs[i][0] - left);
-            coeffStep[i][1] = step * (coeffs[i][1] - right);
+            coeffStep[i][0] = delta * (coeffs[i][0] - left);
+            coeffStep[i][1] = delta * (coeffs[i][1] - right);
         }
         }
     }
     }
     else
     else
@@ -336,8 +302,8 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
             coeffs[i][0] = 0.0f;
             coeffs[i][0] = 0.0f;
             coeffs[i][1] = 0.0f;
             coeffs[i][1] = 0.0f;
 
 
-            coeffStep[i][0] = step * -left;
-            coeffStep[i][1] = step * -right;
+            coeffStep[i][0] = delta * -left;
+            coeffStep[i][1] = delta * -right;
         }
         }
     }
     }
 
 
@@ -345,13 +311,118 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
      * complete its transition.  The mixer will only apply stepping for this
      * complete its transition.  The mixer will only apply stepping for this
      * many samples.
      * many samples.
      */
      */
-    return fastf2u(delta);
+    return fastf2u(steps);
+}
+
+
+/* Calculates HRTF coefficients for B-Format channels (only up to first-order).
+ * Note that these will decode a B-Format output mix, which uses FuMa ordering
+ * and scaling, not N3D!
+ */
+void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, const ALuint num_chans, ALfloat (**coeffs_list)[2], ALuint **delay_list)
+{
+    ALuint elev_idx, azi_idx;
+    ALfloat scale;
+    ALuint i, c;
+
+    assert(num_chans <= 4);
+
+    for(c = 0;c < num_chans;c++)
+    {
+        ALfloat (*coeffs)[2] = coeffs_list[c];
+        ALuint *delay = delay_list[c];
+
+        for(i = 0;i < Hrtf->irSize;i++)
+        {
+            coeffs[i][0] = 0.0f;
+            coeffs[i][1] = 0.0f;
+        }
+        delay[0] = 0;
+        delay[1] = 0;
+    }
+
+    /* NOTE: HRTF coefficients are generated by combining all the HRIRs in the
+     * dataset, with each entry scaled according to how much it contributes to
+     * the given B-Format channel based on its direction (including negative
+     * contributions!).
+     */
+    scale = 0.0f;
+    for(elev_idx = 0;elev_idx < Hrtf->evCount;elev_idx++)
+    {
+        ALfloat elev = (ALfloat)elev_idx/(ALfloat)(Hrtf->evCount-1)*F_PI - F_PI_2;
+        ALuint evoffset = Hrtf->evOffset[elev_idx];
+        ALuint azcount = Hrtf->azCount[elev_idx];
+
+        scale += (ALfloat)azcount;
+
+        for(azi_idx = 0;azi_idx < azcount;azi_idx++)
+        {
+            ALuint lidx, ridx;
+            ALfloat ambi_coeffs[4];
+            ALfloat az, gain;
+            ALfloat x, y, z;
+
+            lidx = evoffset + azi_idx;
+            ridx = evoffset + ((azcount-azi_idx) % azcount);
+
+            az = (ALfloat)azi_idx / (ALfloat)azcount * F_TAU;
+            if(az > F_PI) az -= F_TAU;
+
+            x = cosf(-az) * cosf(elev);
+            y = sinf(-az) * cosf(elev);
+            z = sinf(elev);
+
+            ambi_coeffs[0] = 1.414213562f;
+            ambi_coeffs[1] = x;
+            ambi_coeffs[2] = y;
+            ambi_coeffs[3] = z;
+
+            for(c = 0;c < num_chans;c++)
+            {
+                ALfloat (*coeffs)[2] = coeffs_list[c];
+                ALuint *delay = delay_list[c];
+
+                /* NOTE: Always include the total delay average since the
+                 * channels need to have matching delays. */
+                delay[0] += Hrtf->delays[lidx];
+                delay[1] += Hrtf->delays[ridx];
+
+                gain = ambi_coeffs[c];
+                if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
+                    continue;
+
+                for(i = 0;i < Hrtf->irSize;i++)
+                {
+                    coeffs[i][0] += Hrtf->coeffs[lidx*Hrtf->irSize + i]*(1.0f/32767.0f) * gain;
+                    coeffs[i][1] += Hrtf->coeffs[ridx*Hrtf->irSize + i]*(1.0f/32767.0f) * gain;
+                }
+            }
+        }
+    }
+
+    scale = 1.0f/scale;
+
+    for(c = 0;c < num_chans;c++)
+    {
+        ALfloat (*coeffs)[2] = coeffs_list[c];
+        ALuint *delay = delay_list[c];
+
+        for(i = 0;i < Hrtf->irSize;i++)
+        {
+            coeffs[i][0] *= scale;
+            coeffs[i][1] *= scale;
+        }
+        delay[0] = minu((ALuint)((ALfloat)delay[0] * scale), HRTF_HISTORY_LENGTH-1);
+        delay[0] <<= HRTFDELAY_BITS;
+        delay[1] = minu((ALuint)((ALfloat)delay[1] * scale), HRTF_HISTORY_LENGTH-1);
+        delay[1] <<= HRTFDELAY_BITS;
+    }
 }
 }
 
 
 
 
-static struct Hrtf *LoadHrtf00(FILE *f, ALuint deviceRate)
+static struct Hrtf *LoadHrtf00(FILE *f)
 {
 {
-    const ALubyte maxDelay = SRC_HISTORY_LENGTH-1;
+    const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
     struct Hrtf *Hrtf = NULL;
     struct Hrtf *Hrtf = NULL;
     ALboolean failed = AL_FALSE;
     ALboolean failed = AL_FALSE;
     ALuint rate = 0, irCount = 0;
     ALuint rate = 0, irCount = 0;
@@ -376,12 +447,6 @@ static struct Hrtf *LoadHrtf00(FILE *f, ALuint deviceRate)
 
 
     evCount = fgetc(f);
     evCount = fgetc(f);
 
 
-    if(rate != deviceRate)
-    {
-        ERR("HRIR rate does not match device rate: rate=%d (%d)\n",
-            rate, deviceRate);
-        failed = AL_TRUE;
-    }
     if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
     if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
     {
     {
         ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
         ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
@@ -504,6 +569,7 @@ static struct Hrtf *LoadHrtf00(FILE *f, ALuint deviceRate)
         Hrtf->evOffset = evOffset;
         Hrtf->evOffset = evOffset;
         Hrtf->coeffs = coeffs;
         Hrtf->coeffs = coeffs;
         Hrtf->delays = delays;
         Hrtf->delays = delays;
+        AL_STRING_INIT(Hrtf->filename);
         Hrtf->next = NULL;
         Hrtf->next = NULL;
         return Hrtf;
         return Hrtf;
     }
     }
@@ -516,9 +582,9 @@ static struct Hrtf *LoadHrtf00(FILE *f, ALuint deviceRate)
 }
 }
 
 
 
 
-static struct Hrtf *LoadHrtf01(FILE *f, ALuint deviceRate)
+static struct Hrtf *LoadHrtf01(FILE *f)
 {
 {
-    const ALubyte maxDelay = SRC_HISTORY_LENGTH-1;
+    const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
     struct Hrtf *Hrtf = NULL;
     struct Hrtf *Hrtf = NULL;
     ALboolean failed = AL_FALSE;
     ALboolean failed = AL_FALSE;
     ALuint rate = 0, irCount = 0;
     ALuint rate = 0, irCount = 0;
@@ -538,12 +604,6 @@ static struct Hrtf *LoadHrtf01(FILE *f, ALuint deviceRate)
 
 
     evCount = fgetc(f);
     evCount = fgetc(f);
 
 
-    if(rate != deviceRate)
-    {
-        ERR("HRIR rate does not match device rate: rate=%d (%d)\n",
-                rate, deviceRate);
-        failed = AL_TRUE;
-    }
     if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
     if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
     {
     {
         ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
         ERR("Unsupported HRIR size: irSize=%d (%d to %d by %d)\n",
@@ -649,6 +709,7 @@ static struct Hrtf *LoadHrtf01(FILE *f, ALuint deviceRate)
         Hrtf->evOffset = evOffset;
         Hrtf->evOffset = evOffset;
         Hrtf->coeffs = coeffs;
         Hrtf->coeffs = coeffs;
         Hrtf->delays = delays;
         Hrtf->delays = delays;
+        AL_STRING_INIT(Hrtf->filename);
         Hrtf->next = NULL;
         Hrtf->next = NULL;
         return Hrtf;
         return Hrtf;
     }
     }
@@ -661,144 +722,167 @@ static struct Hrtf *LoadHrtf01(FILE *f, ALuint deviceRate)
 }
 }
 
 
 
 
-static struct Hrtf *LoadHrtf(ALuint deviceRate)
+static void AddFileEntry(vector_HrtfEntry *list, al_string *filename)
 {
 {
-    const char *fnamelist = "default-%r.mhr";
+    HrtfEntry entry = { AL_STRING_INIT_STATIC(), *filename, NULL };
+    HrtfEntry *iter;
+    const char *name;
+    int i;
+
+    name = strrchr(al_string_get_cstr(entry.filename), '/');
+    if(!name) name = strrchr(al_string_get_cstr(entry.filename), '\\');
+    if(!name) name = al_string_get_cstr(entry.filename);
+    else ++name;
+
+    entry.hrtf = LoadedHrtfs;
+    while(entry.hrtf)
+    {
+        if(al_string_cmp(entry.filename, entry.hrtf->filename) == 0)
+            break;
+        entry.hrtf = entry.hrtf->next;
+    }
 
 
-    ConfigValueStr(NULL, "hrtf_tables", &fnamelist);
-    while(*fnamelist != '\0')
+    if(!entry.hrtf)
     {
     {
-        struct Hrtf *Hrtf = NULL;
-        char fname[PATH_MAX];
-        const char *next;
+        struct Hrtf *hrtf = NULL;
         ALchar magic[8];
         ALchar magic[8];
-        ALuint i;
         FILE *f;
         FILE *f;
 
 
-        i = 0;
-        while(isspace(*fnamelist) || *fnamelist == ',')
-            fnamelist++;
-        next = fnamelist;
-        while(*(fnamelist=next) != '\0' && *fnamelist != ',')
-        {
-            next = strpbrk(fnamelist, "%,");
-            while(fnamelist != next && *fnamelist && i < sizeof(fname))
-                fname[i++] = *(fnamelist++);
-
-            if(!next || *next == ',')
-                break;
-
-            /* *next == '%' */
-            next++;
-            if(*next == 'r')
-            {
-                int wrote = snprintf(&fname[i], sizeof(fname)-i, "%u", deviceRate);
-                i += minu(wrote, sizeof(fname)-i);
-                next++;
-            }
-            else if(*next == '%')
-            {
-                if(i < sizeof(fname))
-                    fname[i++] = '%';
-                next++;
-            }
-            else
-                ERR("Invalid marker '%%%c'\n", *next);
-        }
-        i = minu(i, sizeof(fname)-1);
-        fname[i] = '\0';
-        while(i > 0 && isspace(fname[i-1]))
-            i--;
-        fname[i] = '\0';
-
-        if(fname[0] == '\0')
-            continue;
-
-        TRACE("Loading %s...\n", fname);
-        f = OpenDataFile(fname, "openal/hrtf");
+        TRACE("Loading %s...\n", al_string_get_cstr(entry.filename));
+        f = al_fopen(al_string_get_cstr(entry.filename), "rb");
         if(f == NULL)
         if(f == NULL)
         {
         {
-            ERR("Could not open %s\n", fname);
-            continue;
+            ERR("Could not open %s\n", al_string_get_cstr(entry.filename));
+            goto error;
         }
         }
 
 
         if(fread(magic, 1, sizeof(magic), f) != sizeof(magic))
         if(fread(magic, 1, sizeof(magic), f) != sizeof(magic))
-            ERR("Failed to read header from %s\n", fname);
+            ERR("Failed to read header from %s\n", al_string_get_cstr(entry.filename));
         else
         else
         {
         {
             if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0)
             if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0)
             {
             {
                 TRACE("Detected data set format v0\n");
                 TRACE("Detected data set format v0\n");
-                Hrtf = LoadHrtf00(f, deviceRate);
+                hrtf = LoadHrtf00(f);
             }
             }
             else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0)
             else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0)
             {
             {
                 TRACE("Detected data set format v1\n");
                 TRACE("Detected data set format v1\n");
-                Hrtf = LoadHrtf01(f, deviceRate);
+                hrtf = LoadHrtf01(f);
             }
             }
             else
             else
-                ERR("Invalid header in %s: \"%.8s\"\n", fname, magic);
+                ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(entry.filename), magic);
         }
         }
-
         fclose(f);
         fclose(f);
-        f = NULL;
 
 
-        if(Hrtf)
+        if(!hrtf)
         {
         {
-            Hrtf->next = LoadedHrtfs;
-            LoadedHrtfs = Hrtf;
-            TRACE("Loaded HRTF support for format: %s %uhz\n",
-                  DevFmtChannelsString(DevFmtStereo), Hrtf->sampleRate);
-            return Hrtf;
+            ERR("Failed to load %s\n", al_string_get_cstr(entry.filename));
+            goto error;
         }
         }
 
 
-        ERR("Failed to load %s\n", fname);
+        al_string_copy(&hrtf->filename, entry.filename);
+        hrtf->next = LoadedHrtfs;
+        LoadedHrtfs = hrtf;
+        TRACE("Loaded HRTF support for format: %s %uhz\n",
+                DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate);
+        entry.hrtf = hrtf;
     }
     }
 
 
-    return NULL;
+    /* TODO: Get a human-readable name from the HRTF data (possibly coming in a
+     * format update). */
+
+    i = 0;
+    do {
+        al_string_copy_cstr(&entry.name, name);
+        if(i != 0)
+        {
+            char str[64];
+            snprintf(str, sizeof(str), " #%d", i+1);
+            al_string_append_cstr(&entry.name, str);
+        }
+        ++i;
+
+#define MATCH_NAME(i)  (al_string_cmp(entry.name, (i)->name) == 0)
+        VECTOR_FIND_IF(iter, HrtfEntry, *list, MATCH_NAME);
+#undef MATCH_NAME
+    } while(iter != VECTOR_ITER_END(*list));
+
+    TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name),
+          al_string_get_cstr(entry.filename));
+    VECTOR_PUSH_BACK(*list, entry);
+    return;
+
+error:
+    al_string_deinit(&entry.filename);
 }
 }
 
 
-const struct Hrtf *GetHrtf(enum DevFmtChannels chans, ALCuint srate)
+vector_HrtfEntry EnumerateHrtf(const_al_string devname)
 {
 {
-    if(chans == DevFmtStereo)
+    vector_HrtfEntry list = VECTOR_INIT_STATIC();
+    const char *fnamelist = "default-%r.mhr";
+
+    ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf_tables", &fnamelist);
+    while(fnamelist && *fnamelist)
     {
     {
-        struct Hrtf *Hrtf = LoadedHrtfs;
-        while(Hrtf != NULL)
+        while(isspace(*fnamelist) || *fnamelist == ',')
+            fnamelist++;
+        if(*fnamelist != '\0')
         {
         {
-            if(srate == Hrtf->sampleRate)
-                return Hrtf;
-            Hrtf = Hrtf->next;
-        }
+            const char *next, *end;
+
+            next = strchr(fnamelist, ',');
+            if(!next)
+                end = fnamelist + strlen(fnamelist);
+            else
+                end = next++;
+
+            while(end != fnamelist && isspace(*(end-1)))
+                --end;
+            if(end != fnamelist)
+            {
+                al_string fname = AL_STRING_INIT_STATIC();
+                vector_al_string flist;
+
+                al_string_append_range(&fname, fnamelist, end);
+
+                flist = SearchDataFiles(al_string_get_cstr(fname), "openal/hrtf");
+                VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list);
+                VECTOR_DEINIT(flist);
 
 
-        Hrtf = LoadHrtf(srate);
-        if(Hrtf != NULL)
-            return Hrtf;
+                al_string_deinit(&fname);
+            }
+
+            fnamelist = next;
+        }
     }
     }
-    ERR("Incompatible format: %s %uhz\n", DevFmtChannelsString(chans), srate);
-    return NULL;
+
+    return list;
 }
 }
 
 
-ALCboolean FindHrtfFormat(enum DevFmtChannels *chans, ALCuint *srate)
+void FreeHrtfList(vector_HrtfEntry *list)
 {
 {
-    const struct Hrtf *hrtf = LoadedHrtfs;
-    while(hrtf != NULL)
-    {
-        if(*srate == hrtf->sampleRate)
-            break;
-        hrtf = hrtf->next;
-    }
+#define CLEAR_ENTRY(i) do {           \
+    al_string_deinit(&(i)->name);     \
+    al_string_deinit(&(i)->filename); \
+} while(0)
+    VECTOR_FOR_EACH(HrtfEntry, *list, CLEAR_ENTRY);
+    VECTOR_DEINIT(*list);
+#undef CLEAR_ENTRY
+}
 
 
-    if(hrtf == NULL)
-    {
-        hrtf = LoadHrtf(*srate);
-        if(hrtf == NULL) return ALC_FALSE;
-    }
 
 
-    *chans = DevFmtStereo;
-    *srate = hrtf->sampleRate;
-    return ALC_TRUE;
+ALuint GetHrtfSampleRate(const struct Hrtf *Hrtf)
+{
+    return Hrtf->sampleRate;
+}
+
+ALuint GetHrtfIrSize(const struct Hrtf *Hrtf)
+{
+    return Hrtf->irSize;
 }
 }
 
 
+
 void FreeHrtfs(void)
 void FreeHrtfs(void)
 {
 {
     struct Hrtf *Hrtf = NULL;
     struct Hrtf *Hrtf = NULL;
@@ -810,11 +894,7 @@ void FreeHrtfs(void)
         free((void*)Hrtf->evOffset);
         free((void*)Hrtf->evOffset);
         free((void*)Hrtf->coeffs);
         free((void*)Hrtf->coeffs);
         free((void*)Hrtf->delays);
         free((void*)Hrtf->delays);
+        al_string_deinit(&Hrtf->filename);
         free(Hrtf);
         free(Hrtf);
     }
     }
 }
 }
-
-ALuint GetHrtfIrSize (const struct Hrtf *Hrtf)
-{
-    return Hrtf->irSize;
-}

+ 16 - 4
libs/openal-soft/Alc/hrtf.h

@@ -4,10 +4,20 @@
 #include "AL/al.h"
 #include "AL/al.h"
 #include "AL/alc.h"
 #include "AL/alc.h"
 
 
+#include "alstring.h"
+
 enum DevFmtChannels;
 enum DevFmtChannels;
 
 
 struct Hrtf;
 struct Hrtf;
 
 
+typedef struct HrtfEntry {
+    al_string name;
+    al_string filename;
+
+    const struct Hrtf *hrtf;
+} HrtfEntry;
+TYPEDEF_VECTOR(HrtfEntry, vector_HrtfEntry)
+
 #define HRIR_BITS        (7)
 #define HRIR_BITS        (7)
 #define HRIR_LENGTH      (1<<HRIR_BITS)
 #define HRIR_LENGTH      (1<<HRIR_BITS)
 #define HRIR_MASK        (HRIR_LENGTH-1)
 #define HRIR_MASK        (HRIR_LENGTH-1)
@@ -15,14 +25,16 @@ struct Hrtf;
 #define HRTFDELAY_FRACONE (1<<HRTFDELAY_BITS)
 #define HRTFDELAY_FRACONE (1<<HRTFDELAY_BITS)
 #define HRTFDELAY_MASK    (HRTFDELAY_FRACONE-1)
 #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);
 void FreeHrtfs(void);
 
 
+vector_HrtfEntry EnumerateHrtf(const_al_string devname);
+void FreeHrtfList(vector_HrtfEntry *list);
+
+ALuint GetHrtfSampleRate(const struct Hrtf *Hrtf);
 ALuint GetHrtfIrSize(const struct Hrtf *Hrtf);
 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);
 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);
 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);
+void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, const ALuint num_chans, ALfloat (**coeffs_list)[2], ALuint **delay_list);
 
 
 #endif /* ALC_HRTF_H */
 #endif /* ALC_HRTF_H */

+ 253 - 125
libs/openal-soft/Alc/mixer.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -38,8 +38,32 @@
 #include "mixer_defs.h"
 #include "mixer_defs.h"
 
 
 
 
+static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
+              "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
+
 extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
 extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
 
 
+alignas(16) union ResamplerCoeffs ResampleCoeffs;
+
+
+enum Resampler {
+    PointResampler,
+    LinearResampler,
+    FIR4Resampler,
+    FIR8Resampler,
+    BSincResampler,
+
+    ResamplerDefault = LinearResampler
+};
+
+/* FIR8 requires 3 extra samples before the current position, and 4 after. */
+static_assert(MAX_PRE_SAMPLES >= 3, "MAX_PRE_SAMPLES must be at least 3!");
+static_assert(MAX_POST_SAMPLES >= 4, "MAX_POST_SAMPLES must be at least 4!");
+
+
+static HrtfMixerFunc MixHrtfSamples = MixHrtf_C;
+static MixerFunc MixSamples = Mix_C;
+static ResamplerFunc ResampleSamples = Resample_point32_C;
 
 
 static inline HrtfMixerFunc SelectHrtfMixer(void)
 static inline HrtfMixerFunc SelectHrtfMixer(void)
 {
 {
@@ -69,11 +93,9 @@ static inline MixerFunc SelectMixer(void)
     return Mix_C;
     return Mix_C;
 }
 }
 
 
-static inline ResamplerFunc SelectResampler(enum Resampler Resampler, ALuint increment)
+static inline ResamplerFunc SelectResampler(enum Resampler resampler)
 {
 {
-    if(increment == FRACTIONONE)
-        return Resample_copy32_C;
-    switch(Resampler)
+    switch(resampler)
     {
     {
         case PointResampler:
         case PointResampler:
             return Resample_point32_C;
             return Resample_point32_C;
@@ -87,17 +109,181 @@ static inline ResamplerFunc SelectResampler(enum Resampler Resampler, ALuint inc
                 return Resample_lerp32_SSE2;
                 return Resample_lerp32_SSE2;
 #endif
 #endif
             return Resample_lerp32_C;
             return Resample_lerp32_C;
-        case CubicResampler:
-            return Resample_cubic32_C;
-        case ResamplerMax:
-            /* Shouldn't happen */
-            break;
+        case FIR4Resampler:
+#ifdef HAVE_SSE4_1
+            if((CPUCapFlags&CPU_CAP_SSE4_1))
+                return Resample_fir4_32_SSE41;
+#endif
+#ifdef HAVE_SSE3
+            if((CPUCapFlags&CPU_CAP_SSE3))
+                return Resample_fir4_32_SSE3;
+#endif
+            return Resample_fir4_32_C;
+        case FIR8Resampler:
+#ifdef HAVE_SSE4_1
+            if((CPUCapFlags&CPU_CAP_SSE4_1))
+                return Resample_fir8_32_SSE41;
+#endif
+#ifdef HAVE_SSE3
+            if((CPUCapFlags&CPU_CAP_SSE3))
+                return Resample_fir8_32_SSE3;
+#endif
+            return Resample_fir8_32_C;
+        case BSincResampler:
+#ifdef HAVE_SSE
+            if((CPUCapFlags&CPU_CAP_SSE))
+                return Resample_bsinc32_SSE;
+#endif
+            return Resample_bsinc32_C;
     }
     }
 
 
     return Resample_point32_C;
     return Resample_point32_C;
 }
 }
 
 
 
 
+/* The sinc resampler makes use of a Kaiser window to limit the needed sample
+ * points to 4 and 8, respectively.
+ */
+
+#ifndef M_PI
+#define M_PI                         (3.14159265358979323846)
+#endif
+static inline double Sinc(double x)
+{
+    if(x == 0.0) return 1.0;
+    return sin(x*M_PI) / (x*M_PI);
+}
+
+/* The zero-order modified Bessel function of the first kind, used for the
+ * Kaiser window.
+ *
+ *   I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
+ *          = sum_{k=0}^inf ((x / 2)^k / k!)^2
+ */
+static double BesselI_0(double x)
+{
+    double term, sum, x2, y, last_sum;
+    int k;
+
+    /* Start at k=1 since k=0 is trivial. */
+    term = 1.0;
+    sum = 1.0;
+    x2 = x / 2.0;
+    k = 1;
+
+    /* Let the integration converge until the term of the sum is no longer
+     * significant.
+     */
+    do {
+        y = x2 / k;
+        k ++;
+        last_sum = sum;
+        term *= y * y;
+        sum += term;
+    } while(sum != last_sum);
+    return sum;
+}
+
+/* Calculate a Kaiser window from the given beta value and a normalized k
+ * [-1, 1].
+ *
+ *   w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B),  -1 <= k <= 1
+ *          { 0,                              elsewhere.
+ *
+ * Where k can be calculated as:
+ *
+ *   k = i / l,         where -l <= i <= l.
+ *
+ * or:
+ *
+ *   k = 2 i / M - 1,   where 0 <= i <= M.
+ */
+static inline double Kaiser(double b, double k)
+{
+    if(k <= -1.0 || k >= 1.0) return 0.0;
+    return BesselI_0(b * sqrt(1.0 - (k*k))) / BesselI_0(b);
+}
+
+static inline double CalcKaiserBeta(double rejection)
+{
+    if(rejection > 50.0)
+        return 0.1102 * (rejection - 8.7);
+    if(rejection >= 21.0)
+        return (0.5842 * pow(rejection - 21.0, 0.4)) +
+               (0.07886 * (rejection - 21.0));
+    return 0.0;
+}
+
+static float SincKaiser(double r, double x)
+{
+    /* Limit rippling to -60dB. */
+    return (float)(Kaiser(CalcKaiserBeta(60.0), x / r) * Sinc(x));
+}
+
+
+void aluInitMixer(void)
+{
+    enum Resampler resampler = ResamplerDefault;
+    const char *str;
+    ALuint i;
+
+    if(ConfigValueStr(NULL, NULL, "resampler", &str))
+    {
+        if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
+            resampler = PointResampler;
+        else if(strcasecmp(str, "linear") == 0)
+            resampler = LinearResampler;
+        else if(strcasecmp(str, "sinc4") == 0)
+            resampler = FIR4Resampler;
+        else if(strcasecmp(str, "sinc8") == 0)
+            resampler = FIR8Resampler;
+        else if(strcasecmp(str, "bsinc") == 0)
+            resampler = BSincResampler;
+        else if(strcasecmp(str, "cubic") == 0)
+        {
+            WARN("Resampler option \"cubic\" is deprecated, using sinc4\n");
+            resampler = FIR4Resampler;
+        }
+        else
+        {
+            char *end;
+            long n = strtol(str, &end, 0);
+            if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == FIR4Resampler))
+                resampler = n;
+            else
+                WARN("Invalid resampler: %s\n", str);
+        }
+    }
+
+    if(resampler == FIR8Resampler)
+        for(i = 0;i < FRACTIONONE;i++)
+        {
+            ALdouble mu = (ALdouble)i / FRACTIONONE;
+            ResampleCoeffs.FIR8[i][0] = SincKaiser(4.0, mu - -3.0);
+            ResampleCoeffs.FIR8[i][1] = SincKaiser(4.0, mu - -2.0);
+            ResampleCoeffs.FIR8[i][2] = SincKaiser(4.0, mu - -1.0);
+            ResampleCoeffs.FIR8[i][3] = SincKaiser(4.0, mu -  0.0);
+            ResampleCoeffs.FIR8[i][4] = SincKaiser(4.0, mu -  1.0);
+            ResampleCoeffs.FIR8[i][5] = SincKaiser(4.0, mu -  2.0);
+            ResampleCoeffs.FIR8[i][6] = SincKaiser(4.0, mu -  3.0);
+            ResampleCoeffs.FIR8[i][7] = SincKaiser(4.0, mu -  4.0);
+        }
+    else if(resampler == FIR4Resampler)
+        for(i = 0;i < FRACTIONONE;i++)
+        {
+            ALdouble mu = (ALdouble)i / FRACTIONONE;
+            ResampleCoeffs.FIR4[i][0] = SincKaiser(2.0, mu - -1.0);
+            ResampleCoeffs.FIR4[i][1] = SincKaiser(2.0, mu -  0.0);
+            ResampleCoeffs.FIR4[i][2] = SincKaiser(2.0, mu -  1.0);
+            ResampleCoeffs.FIR4[i][3] = SincKaiser(2.0, mu -  2.0);
+        }
+
+    MixHrtfSamples = SelectHrtfMixer();
+    MixSamples = SelectMixer();
+    ResampleSamples = SelectResampler(resampler);
+}
+
+
 static inline ALfloat Sample_ALbyte(ALbyte val)
 static inline ALfloat Sample_ALbyte(ALbyte val)
 { return val * (1.0f/127.0f); }
 { return val * (1.0f/127.0f); }
 
 
@@ -108,7 +294,7 @@ static inline ALfloat Sample_ALfloat(ALfloat val)
 { return val; }
 { return val; }
 
 
 #define DECL_TEMPLATE(T)                                                      \
 #define DECL_TEMPLATE(T)                                                      \
-static void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
+static inline void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
 {                                                                             \
 {                                                                             \
     ALuint i;                                                                 \
     ALuint i;                                                                 \
     for(i = 0;i < samples;i++)                                                \
     for(i = 0;i < samples;i++)                                                \
@@ -137,7 +323,7 @@ static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum Fm
     }
     }
 }
 }
 
 
-static void SilenceSamples(ALfloat *dst, ALuint samples)
+static inline void SilenceSamples(ALfloat *dst, ALuint samples)
 {
 {
     ALuint i;
     ALuint i;
     for(i = 0;i < samples;i++)
     for(i = 0;i < samples;i++)
@@ -153,20 +339,24 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
     switch(type)
     switch(type)
     {
     {
         case AF_None:
         case AF_None:
+            ALfilterState_processPassthru(lpfilter, src, numsamples);
+            ALfilterState_processPassthru(hpfilter, src, numsamples);
             break;
             break;
 
 
         case AF_LowPass:
         case AF_LowPass:
             ALfilterState_process(lpfilter, dst, src, numsamples);
             ALfilterState_process(lpfilter, dst, src, numsamples);
+            ALfilterState_processPassthru(hpfilter, dst, numsamples);
             return dst;
             return dst;
         case AF_HighPass:
         case AF_HighPass:
+            ALfilterState_processPassthru(lpfilter, src, numsamples);
             ALfilterState_process(hpfilter, dst, src, numsamples);
             ALfilterState_process(hpfilter, dst, src, numsamples);
             return dst;
             return dst;
 
 
         case AF_BandPass:
         case AF_BandPass:
             for(i = 0;i < numsamples;)
             for(i = 0;i < numsamples;)
             {
             {
-                ALfloat temp[64];
-                ALuint todo = minu(64, numsamples-i);
+                ALfloat temp[256];
+                ALuint todo = minu(256, numsamples-i);
 
 
                 ALfilterState_process(lpfilter, temp, src+i, todo);
                 ALfilterState_process(lpfilter, temp, src+i, todo);
                 ALfilterState_process(hpfilter, dst+i, temp, todo);
                 ALfilterState_process(hpfilter, dst+i, temp, todo);
@@ -178,22 +368,19 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
 }
 }
 
 
 
 
-ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
+ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
 {
 {
-    MixerFunc Mix;
-    HrtfMixerFunc HrtfMix;
     ResamplerFunc Resample;
     ResamplerFunc Resample;
-    ALsource *Source = src->Source;
     ALbufferlistitem *BufferListItem;
     ALbufferlistitem *BufferListItem;
     ALuint DataPosInt, DataPosFrac;
     ALuint DataPosInt, DataPosFrac;
     ALboolean Looping;
     ALboolean Looping;
     ALuint increment;
     ALuint increment;
-    enum Resampler Resampler;
     ALenum State;
     ALenum State;
     ALuint OutPos;
     ALuint OutPos;
     ALuint NumChannels;
     ALuint NumChannels;
     ALuint SampleSize;
     ALuint SampleSize;
     ALint64 DataSize64;
     ALint64 DataSize64;
+    ALuint IrSize;
     ALuint chan, j;
     ALuint chan, j;
 
 
     /* Get source info */
     /* Get source info */
@@ -202,19 +389,17 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
     DataPosInt     = Source->position;
     DataPosInt     = Source->position;
     DataPosFrac    = Source->position_fraction;
     DataPosFrac    = Source->position_fraction;
     Looping        = Source->Looping;
     Looping        = Source->Looping;
-    increment      = src->Step;
-    Resampler      = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
     NumChannels    = Source->NumChannels;
     NumChannels    = Source->NumChannels;
     SampleSize     = Source->SampleSize;
     SampleSize     = Source->SampleSize;
+    increment      = voice->Step;
 
 
-    Mix = SelectMixer();
-    HrtfMix = SelectHrtfMixer();
-    Resample = SelectResampler(Resampler, increment);
+    IrSize = (Device->Hrtf ? GetHrtfIrSize(Device->Hrtf) : 0);
+
+    Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
+                Resample_copy32_C : ResampleSamples);
 
 
     OutPos = 0;
     OutPos = 0;
     do {
     do {
-        const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
-        const ALuint BufferPadding = ResamplerPadding[Resampler];
         ALuint SrcBufferSize, DstBufferSize;
         ALuint SrcBufferSize, DstBufferSize;
 
 
         /* Figure out how many buffer samples will be needed */
         /* Figure out how many buffer samples will be needed */
@@ -222,13 +407,13 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
         DataSize64 *= increment;
         DataSize64 *= increment;
         DataSize64 += DataPosFrac+FRACTIONMASK;
         DataSize64 += DataPosFrac+FRACTIONMASK;
         DataSize64 >>= FRACTIONBITS;
         DataSize64 >>= FRACTIONBITS;
-        DataSize64 += BufferPadding+BufferPrePadding;
+        DataSize64 += MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
 
 
         SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
         SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
 
 
         /* Figure out how many samples we can actually mix from this. */
         /* Figure out how many samples we can actually mix from this. */
         DataSize64  = SrcBufferSize;
         DataSize64  = SrcBufferSize;
-        DataSize64 -= BufferPadding+BufferPrePadding;
+        DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
         DataSize64 <<= FRACTIONBITS;
         DataSize64 <<= FRACTIONBITS;
         DataSize64 -= DataPosFrac;
         DataSize64 -= DataPosFrac;
 
 
@@ -244,7 +429,11 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
         {
         {
             const ALfloat *ResampledData;
             const ALfloat *ResampledData;
             ALfloat *SrcData = Device->SourceData;
             ALfloat *SrcData = Device->SourceData;
-            ALuint SrcDataSize = 0;
+            ALuint SrcDataSize;
+
+            /* Load the previous samples into the source data first. */
+            memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat));
+            SrcDataSize = MAX_PRE_SAMPLES;
 
 
             if(Source->SourceType == AL_STATIC)
             if(Source->SourceType == AL_STATIC)
             {
             {
@@ -253,29 +442,20 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
                 ALuint DataSize;
                 ALuint DataSize;
                 ALuint pos;
                 ALuint pos;
 
 
+                /* Offset buffer data to current channel */
+                Data += chan*SampleSize;
+
                 /* If current pos is beyond the loop range, do not loop */
                 /* If current pos is beyond the loop range, do not loop */
                 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
                 if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
                 {
                 {
                     Looping = AL_FALSE;
                     Looping = AL_FALSE;
 
 
-                    if(DataPosInt >= BufferPrePadding)
-                        pos = DataPosInt - BufferPrePadding;
-                    else
-                    {
-                        DataSize = BufferPrePadding - DataPosInt;
-                        DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-
-                        SilenceSamples(&SrcData[SrcDataSize], DataSize);
-                        SrcDataSize += DataSize;
-
-                        pos = 0;
-                    }
-
-                    /* Copy what's left to play in the source buffer, and clear the
-                     * rest of the temp buffer */
+                    /* Load what's left to play from the source buffer, and
+                     * clear the rest of the temp buffer */
+                    pos = DataPosInt;
                     DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
                     DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
 
 
-                    LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
+                    LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize],
                                 NumChannels, ALBuffer->FmtType, DataSize);
                                 NumChannels, ALBuffer->FmtType, DataSize);
                     SrcDataSize += DataSize;
                     SrcDataSize += DataSize;
 
 
@@ -287,33 +467,13 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
                     ALuint LoopStart = ALBuffer->LoopStart;
                     ALuint LoopStart = ALBuffer->LoopStart;
                     ALuint LoopEnd   = ALBuffer->LoopEnd;
                     ALuint LoopEnd   = ALBuffer->LoopEnd;
 
 
-                    if(DataPosInt >= LoopStart)
-                    {
-                        pos = DataPosInt-LoopStart;
-                        while(pos < BufferPrePadding)
-                            pos += LoopEnd-LoopStart;
-                        pos -= BufferPrePadding;
-                        pos += LoopStart;
-                    }
-                    else if(DataPosInt >= BufferPrePadding)
-                        pos = DataPosInt - BufferPrePadding;
-                    else
-                    {
-                        DataSize = BufferPrePadding - DataPosInt;
-                        DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-
-                        SilenceSamples(&SrcData[SrcDataSize], DataSize);
-                        SrcDataSize += DataSize;
-
-                        pos = 0;
-                    }
-
-                    /* Copy what's left of this loop iteration, then copy repeats
-                     * of the loop section */
+                    /* Load what's left of this loop iteration, then load
+                     * repeats of the loop section */
+                    pos = DataPosInt;
                     DataSize = LoopEnd - pos;
                     DataSize = LoopEnd - pos;
                     DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
                     DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
 
 
-                    LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
+                    LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize],
                                 NumChannels, ALBuffer->FmtType, DataSize);
                                 NumChannels, ALBuffer->FmtType, DataSize);
                     SrcDataSize += DataSize;
                     SrcDataSize += DataSize;
 
 
@@ -322,7 +482,7 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
                     {
                     {
                         DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
                         DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
 
 
-                        LoadSamples(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
+                        LoadSamples(&SrcData[SrcDataSize], &Data[LoopStart * NumChannels*SampleSize],
                                     NumChannels, ALBuffer->FmtType, DataSize);
                                     NumChannels, ALBuffer->FmtType, DataSize);
                         SrcDataSize += DataSize;
                         SrcDataSize += DataSize;
                     }
                     }
@@ -332,45 +492,7 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
             {
             {
                 /* Crawl the buffer queue to fill in the temp buffer */
                 /* Crawl the buffer queue to fill in the temp buffer */
                 ALbufferlistitem *tmpiter = BufferListItem;
                 ALbufferlistitem *tmpiter = BufferListItem;
-                ALuint pos;
-
-                if(DataPosInt >= BufferPrePadding)
-                    pos = DataPosInt - BufferPrePadding;
-                else
-                {
-                    pos = BufferPrePadding - DataPosInt;
-                    while(pos > 0)
-                    {
-                        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);
-
-                            SilenceSamples(&SrcData[SrcDataSize], DataSize);
-                            SrcDataSize += DataSize;
-
-                            pos = 0;
-                            break;
-                        }
-
-                        if(tmpiter->buffer)
-                        {
-                            if((ALuint)tmpiter->buffer->SampleLen > pos)
-                            {
-                                pos = tmpiter->buffer->SampleLen - pos;
-                                break;
-                            }
-                            pos -= tmpiter->buffer->SampleLen;
-                        }
-                    }
-                }
+                ALuint pos = DataPosInt;
 
 
                 while(tmpiter && SrcBufferSize > SrcDataSize)
                 while(tmpiter && SrcBufferSize > SrcDataSize)
                 {
                 {
@@ -406,13 +528,19 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
                 }
                 }
             }
             }
 
 
+            /* Store the last source samples used for next time. */
+            memcpy(voice->PrevSamples[chan],
+                &SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
+                MAX_PRE_SAMPLES*sizeof(ALfloat)
+            );
+
             /* Now resample, then filter and mix to the appropriate outputs. */
             /* Now resample, then filter and mix to the appropriate outputs. */
-            ResampledData = Resample(
-                &SrcData[BufferPrePadding], DataPosFrac, increment,
+            ResampledData = Resample(&voice->SincState,
+                &SrcData[MAX_PRE_SAMPLES], DataPosFrac, increment,
                 Device->ResampledData, DstBufferSize
                 Device->ResampledData, DstBufferSize
             );
             );
             {
             {
-                DirectParams *parms = &src->Direct;
+                DirectParams *parms = &voice->Direct;
                 const ALfloat *samples;
                 const ALfloat *samples;
 
 
                 samples = DoFilters(
                 samples = DoFilters(
@@ -420,18 +548,18 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
                     Device->FilteredData, ResampledData, DstBufferSize,
                     Device->FilteredData, ResampledData, DstBufferSize,
                     parms->Filters[chan].ActiveType
                     parms->Filters[chan].ActiveType
                 );
                 );
-                if(!src->IsHrtf)
-                    Mix(samples, MaxChannels, parms->OutBuffer, parms->Mix.Gains[chan],
-                        parms->Counter, OutPos, DstBufferSize);
+                if(!voice->IsHrtf)
+                    MixSamples(samples, parms->OutChannels, parms->OutBuffer, parms->Gains[chan],
+                               parms->Counter, OutPos, DstBufferSize);
                 else
                 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);
+                    MixHrtfSamples(parms->OutBuffer, samples, parms->Counter, voice->Offset,
+                                   OutPos, IrSize, &parms->Hrtf[chan].Params,
+                                   &parms->Hrtf[chan].State, DstBufferSize);
             }
             }
 
 
             for(j = 0;j < Device->NumAuxSends;j++)
             for(j = 0;j < Device->NumAuxSends;j++)
             {
             {
-                SendParams *parms = &src->Send[j];
+                SendParams *parms = &voice->Send[j];
                 const ALfloat *samples;
                 const ALfloat *samples;
 
 
                 if(!parms->OutBuffer)
                 if(!parms->OutBuffer)
@@ -442,8 +570,8 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
                     Device->FilteredData, ResampledData, DstBufferSize,
                     Device->FilteredData, ResampledData, DstBufferSize,
                     parms->Filters[chan].ActiveType
                     parms->Filters[chan].ActiveType
                 );
                 );
-                Mix(samples, 1, parms->OutBuffer, &parms->Gain,
-                    parms->Counter, OutPos, DstBufferSize);
+                MixSamples(samples, 1, parms->OutBuffer, &parms->Gains[chan],
+                           parms->Counter, OutPos, DstBufferSize);
             }
             }
         }
         }
         /* Update positions */
         /* Update positions */
@@ -452,10 +580,10 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
         DataPosFrac &= FRACTIONMASK;
         DataPosFrac &= FRACTIONMASK;
 
 
         OutPos += DstBufferSize;
         OutPos += DstBufferSize;
-        src->Offset += DstBufferSize;
-        src->Direct.Counter = maxu(src->Direct.Counter, DstBufferSize) - DstBufferSize;
+        voice->Offset += DstBufferSize;
+        voice->Direct.Counter = maxu(voice->Direct.Counter, DstBufferSize) - DstBufferSize;
         for(j = 0;j < Device->NumAuxSends;j++)
         for(j = 0;j < Device->NumAuxSends;j++)
-            src->Send[j].Counter = maxu(src->Send[j].Counter, DstBufferSize) - DstBufferSize;
+            voice->Send[j].Counter = maxu(voice->Send[j].Counter, DstBufferSize) - DstBufferSize;
 
 
         /* Handle looping sources */
         /* Handle looping sources */
         while(1)
         while(1)

+ 69 - 14
libs/openal-soft/Alc/mixer_c.c

@@ -12,13 +12,15 @@ static inline ALfloat point32(const ALfloat *vals, ALuint UNUSED(frac))
 { return vals[0]; }
 { return vals[0]; }
 static inline ALfloat lerp32(const ALfloat *vals, ALuint frac)
 static inline ALfloat lerp32(const ALfloat *vals, ALuint frac)
 { return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); }
 { return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); }
-static inline ALfloat cubic32(const ALfloat *vals, ALuint frac)
-{ return cubic(vals[-1], vals[0], vals[1], vals[2], frac * (1.0f/FRACTIONONE)); }
+static inline ALfloat fir4_32(const ALfloat *vals, ALuint frac)
+{ return resample_fir4(vals[-1], vals[0], vals[1], vals[2], frac); }
+static inline ALfloat fir8_32(const ALfloat *vals, ALuint frac)
+{ return resample_fir8(vals[-3], vals[-2], vals[-1], vals[0], vals[1], vals[2], vals[3], vals[4], frac); }
 
 
-const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint UNUSED(frac),
-  ALuint increment, ALfloat *restrict dst, ALuint numsamples)
+
+const ALfloat *Resample_copy32_C(const BsincState* UNUSED(state), const ALfloat *src, ALuint UNUSED(frac),
+  ALuint UNUSED(increment), ALfloat *restrict dst, ALuint numsamples)
 {
 {
-    assert(increment==FRACTIONONE);
 #if defined(HAVE_SSE) || defined(HAVE_NEON)
 #if defined(HAVE_SSE) || defined(HAVE_NEON)
     /* Avoid copying the source data if it's aligned like the destination. */
     /* Avoid copying the source data if it's aligned like the destination. */
     if((((intptr_t)src)&15) == (((intptr_t)dst)&15))
     if((((intptr_t)src)&15) == (((intptr_t)dst)&15))
@@ -29,8 +31,9 @@ const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint UNUSED(frac),
 }
 }
 
 
 #define DECL_TEMPLATE(Sampler)                                                \
 #define DECL_TEMPLATE(Sampler)                                                \
-const ALfloat *Resample_##Sampler##_C(const ALfloat *src, ALuint frac,        \
-  ALuint increment, ALfloat *restrict dst, ALuint numsamples)                 \
+const ALfloat *Resample_##Sampler##_C(const BsincState* UNUSED(state),        \
+  const ALfloat *src, ALuint frac, ALuint increment,                          \
+  ALfloat *restrict dst, ALuint numsamples)                                   \
 {                                                                             \
 {                                                                             \
     ALuint i;                                                                 \
     ALuint i;                                                                 \
     for(i = 0;i < numsamples;i++)                                             \
     for(i = 0;i < numsamples;i++)                                             \
@@ -46,10 +49,49 @@ const ALfloat *Resample_##Sampler##_C(const ALfloat *src, ALuint frac,        \
 
 
 DECL_TEMPLATE(point32)
 DECL_TEMPLATE(point32)
 DECL_TEMPLATE(lerp32)
 DECL_TEMPLATE(lerp32)
-DECL_TEMPLATE(cubic32)
+DECL_TEMPLATE(fir4_32)
+DECL_TEMPLATE(fir8_32)
 
 
 #undef DECL_TEMPLATE
 #undef DECL_TEMPLATE
 
 
+const ALfloat *Resample_bsinc32_C(const BsincState *state, const ALfloat *src, ALuint frac,
+                                  ALuint increment, ALfloat *restrict dst, ALuint dstlen)
+{
+    const ALfloat *fil, *scd, *phd, *spd;
+    const ALfloat sf = state->sf;
+    const ALuint m = state->m;
+    const ALint l = state->l;
+    ALuint j_f, pi, i;
+    ALfloat pf, r;
+    ALint j_s;
+
+    for(i = 0;i < dstlen;i++)
+    {
+        // Calculate the phase index and factor.
+#define FRAC_PHASE_BITDIFF (FRACTIONBITS-BSINC_PHASE_BITS)
+        pi = frac >> FRAC_PHASE_BITDIFF;
+        pf = (frac & ((1<<FRAC_PHASE_BITDIFF)-1)) * (1.0f/(1<<FRAC_PHASE_BITDIFF));
+#undef FRAC_PHASE_BITDIFF
+
+        fil = state->coeffs[pi].filter;
+        scd = state->coeffs[pi].scDelta;
+        phd = state->coeffs[pi].phDelta;
+        spd = state->coeffs[pi].spDelta;
+
+        // Apply the scale and phase interpolated filter.
+        r = 0.0f;
+        for(j_f = 0,j_s = l;j_f < m;j_f++,j_s++)
+            r += (fil[j_f] + sf*scd[j_f] + pf*(phd[j_f] + sf*spd[j_f])) *
+                    src[j_s];
+        dst[i] = r;
+
+        frac += increment;
+        src  += frac>>FRACTIONBITS;
+        frac &= FRACTIONMASK;
+    }
+    return dst;
+}
+
 
 
 void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples)
 void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples)
 {
 {
@@ -59,6 +101,18 @@ void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const
 }
 }
 
 
 
 
+static inline void SetupCoeffs(ALfloat (*restrict OutCoeffs)[2],
+                               const HrtfParams *hrtfparams,
+                               ALuint IrSize, ALuint Counter)
+{
+    ALuint c;
+    for(c = 0;c < IrSize;c++)
+    {
+        OutCoeffs[c][0] = hrtfparams->Coeffs[c][0] - (hrtfparams->CoeffStep[c][0]*Counter);
+        OutCoeffs[c][1] = hrtfparams->Coeffs[c][1] - (hrtfparams->CoeffStep[c][1]*Counter);
+    }
+}
+
 static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
 static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
                                    const ALuint IrSize,
                                    const ALuint IrSize,
                                    ALfloat (*restrict Coeffs)[2],
                                    ALfloat (*restrict Coeffs)[2],
@@ -90,9 +144,9 @@ static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
     }
     }
 }
 }
 
 
-#define SUFFIX C
+#define MixHrtf MixHrtf_C
 #include "mixer_inc.c"
 #include "mixer_inc.c"
-#undef SUFFIX
+#undef MixHrtf
 
 
 
 
 void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
 void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
@@ -106,19 +160,20 @@ void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[B
         ALuint pos = 0;
         ALuint pos = 0;
         gain = Gains[c].Current;
         gain = Gains[c].Current;
         step = Gains[c].Step;
         step = Gains[c].Step;
-        if(step != 1.0f && Counter > 0)
+        if(step != 0.0f && Counter > 0)
         {
         {
-            for(;pos < BufferSize && pos < Counter;pos++)
+            ALuint minsize = minu(BufferSize, Counter);
+            for(;pos < minsize;pos++)
             {
             {
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
-                gain *= step;
+                gain += step;
             }
             }
             if(pos == Counter)
             if(pos == Counter)
                 gain = Gains[c].Target;
                 gain = Gains[c].Target;
             Gains[c].Current = gain;
             Gains[c].Current = gain;
         }
         }
 
 
-        if(!(gain > GAIN_SILENCE_THRESHOLD))
+        if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
             continue;
             continue;
         for(;pos < BufferSize;pos++)
         for(;pos < BufferSize;pos++)
             OutBuffer[c][OutPos+pos] += data[pos]*gain;
             OutBuffer[c][OutPos+pos] += data[pos]*gain;

+ 22 - 7
libs/openal-soft/Alc/mixer_defs.h

@@ -12,10 +12,12 @@ struct HrtfParams;
 struct HrtfState;
 struct HrtfState;
 
 
 /* C resamplers */
 /* 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);
+const ALfloat *Resample_copy32_C(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_point32_C(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_lerp32_C(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_fir4_32_C(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_fir8_32_C(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+const ALfloat *Resample_bsinc32_C(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen);
 
 
 
 
 /* C mixers */
 /* C mixers */
@@ -24,7 +26,7 @@ void MixHrtf_C(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
                const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate,
                const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate,
                ALuint BufferSize);
                ALuint BufferSize);
 void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
 void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
-                 struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize);
+           struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize);
 
 
 /* SSE mixers */
 /* SSE mixers */
 void MixHrtf_SSE(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
 void MixHrtf_SSE(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
@@ -49,10 +51,23 @@ inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_a
     }
     }
 }
 }
 
 
-const ALfloat *Resample_lerp32_SSE2(const ALfloat *src, ALuint frac, ALuint increment,
+const ALfloat *Resample_bsinc32_SSE(const BsincState *state, const ALfloat *src, ALuint frac,
+                                    ALuint increment, ALfloat *restrict dst, ALuint dstlen);
+
+const ALfloat *Resample_lerp32_SSE2(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment,
                                     ALfloat *restrict dst, ALuint numsamples);
                                     ALfloat *restrict dst, ALuint numsamples);
-const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint increment,
+const ALfloat *Resample_lerp32_SSE41(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment,
+                                     ALfloat *restrict dst, ALuint numsamples);
+
+const ALfloat *Resample_fir4_32_SSE3(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment,
+                                     ALfloat *restrict dst, ALuint numsamples);
+const ALfloat *Resample_fir4_32_SSE41(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment,
+                                      ALfloat *restrict dst, ALuint numsamples);
+
+const ALfloat *Resample_fir8_32_SSE3(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment,
                                      ALfloat *restrict dst, ALuint numsamples);
                                      ALfloat *restrict dst, ALuint numsamples);
+const ALfloat *Resample_fir8_32_SSE41(const BsincState *state, const ALfloat *src, ALuint frac, ALuint increment,
+                                      ALfloat *restrict dst, ALuint numsamples);
 
 
 /* Neon mixers */
 /* Neon mixers */
 void MixHrtf_Neon(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
 void MixHrtf_Neon(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,

+ 18 - 32
libs/openal-soft/Alc/mixer_inc.c

@@ -8,12 +8,9 @@
 #include "align.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 SetupCoeffs(ALfloat (*restrict OutCoeffs)[2],
+                               const HrtfParams *hrtfparams,
+                               ALuint IrSize, ALuint Counter);
 static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
 static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
                                    const ALuint irSize,
                                    const ALuint irSize,
                                    ALfloat (*restrict Coeffs)[2],
                                    ALfloat (*restrict Coeffs)[2],
@@ -33,24 +30,20 @@ void MixHrtf(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
     ALuint Delay[2];
     ALuint Delay[2];
     ALfloat left, right;
     ALfloat left, right;
     ALuint pos;
     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);
-    }
+    SetupCoeffs(Coeffs, hrtfparams, IrSize, Counter);
     Delay[0] = hrtfparams->Delay[0] - (hrtfparams->DelayStep[0]*Counter);
     Delay[0] = hrtfparams->Delay[0] - (hrtfparams->DelayStep[0]*Counter);
     Delay[1] = hrtfparams->Delay[1] - (hrtfparams->DelayStep[1]*Counter);
     Delay[1] = hrtfparams->Delay[1] - (hrtfparams->DelayStep[1]*Counter);
 
 
-    for(pos = 0;pos < BufferSize && pos < Counter;pos++)
+    pos = 0;
+    for(;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],
+        hrtfstate->History[Offset&HRTF_HISTORY_MASK] = data[pos];
+        left  = lerp(hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&HRTF_HISTORY_MASK],
+                     hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&HRTF_HISTORY_MASK],
                      (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
                      (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],
+        right = lerp(hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&HRTF_HISTORY_MASK],
+                     hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&HRTF_HISTORY_MASK],
                      (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
                      (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
 
 
         Delay[0] += hrtfparams->DelayStep[0];
         Delay[0] += hrtfparams->DelayStep[0];
@@ -61,8 +54,8 @@ void MixHrtf(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
         Offset++;
         Offset++;
 
 
         ApplyCoeffsStep(Offset, hrtfstate->Values, IrSize, Coeffs, hrtfparams->CoeffStep, left, right);
         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];
+        OutBuffer[0][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][0];
+        OutBuffer[1][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][1];
         OutPos++;
         OutPos++;
     }
     }
 
 
@@ -70,24 +63,17 @@ void MixHrtf(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
     Delay[1] >>= HRTFDELAY_BITS;
     Delay[1] >>= HRTFDELAY_BITS;
     for(;pos < BufferSize;pos++)
     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->History[Offset&HRTF_HISTORY_MASK] = data[pos];
+        left = hrtfstate->History[(Offset-Delay[0])&HRTF_HISTORY_MASK];
+        right = hrtfstate->History[(Offset-Delay[1])&HRTF_HISTORY_MASK];
 
 
         hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
         hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
         hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
         hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
         Offset++;
         Offset++;
 
 
         ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right);
         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];
-
+        OutBuffer[0][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][0];
+        OutBuffer[1][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][1];
         OutPos++;
         OutPos++;
     }
     }
 }
 }
-
-
-#undef MixHrtf
-
-#undef MERGE
-#undef REAL_MERGE

+ 32 - 11
libs/openal-soft/Alc/mixer_neon.c

@@ -9,6 +9,25 @@
 #include "hrtf.h"
 #include "hrtf.h"
 
 
 
 
+static inline void SetupCoeffs(ALfloat (*restrict OutCoeffs)[2],
+                               const HrtfParams *hrtfparams,
+                               ALuint IrSize, ALuint Counter)
+{
+    ALuint c;
+    float32x4_t counter4;
+    {
+        float32x2_t counter2 = vdup_n_f32(-(float)Counter);
+        counter4 = vcombine_f32(counter2, counter2);
+    }
+    for(c = 0;c < IrSize;c += 2)
+    {
+        float32x4_t step4 = vld1q_f32((float32_t*)hrtfparams->CoeffStep[c]);
+        float32x4_t coeffs = vld1q_f32((float32_t*)hrtfparams->Coeffs[c]);
+        coeffs = vmlaq_f32(coeffs, step4, counter4);
+        vst1q_f32((float32_t*)OutCoeffs[c], coeffs);
+    }
+}
+
 static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
 static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
                                    const ALuint IrSize,
                                    const ALuint IrSize,
                                    ALfloat (*restrict Coeffs)[2],
                                    ALfloat (*restrict Coeffs)[2],
@@ -69,14 +88,13 @@ static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
     }
     }
 }
 }
 
 
-
-#define SUFFIX Neon
+#define MixHrtf MixHrtf_Neon
 #include "mixer_inc.c"
 #include "mixer_inc.c"
-#undef SUFFIX
+#undef MixHrtf
 
 
 
 
-void MixDirect_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
-                    MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize)
+void Mix_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
+              MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize)
 {
 {
     ALfloat gain, step;
     ALfloat gain, step;
     float32x4_t gain4;
     float32x4_t gain4;
@@ -87,29 +105,32 @@ void MixDirect_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict Out
         ALuint pos = 0;
         ALuint pos = 0;
         gain = Gains[c].Current;
         gain = Gains[c].Current;
         step = Gains[c].Step;
         step = Gains[c].Step;
-        if(step != 1.0f && Counter > 0)
+        if(step != 0.0f && Counter > 0)
         {
         {
-            for(;pos < BufferSize && pos < Counter;pos++)
+            ALuint minsize = minu(BufferSize, Counter);
+            for(;pos < minsize;pos++)
             {
             {
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
-                gain *= step;
+                gain += step;
             }
             }
             if(pos == Counter)
             if(pos == Counter)
                 gain = Gains[c].Target;
                 gain = Gains[c].Target;
             Gains[c].Current = gain;
             Gains[c].Current = gain;
+
             /* Mix until pos is aligned with 4 or the mix is done. */
             /* Mix until pos is aligned with 4 or the mix is done. */
-            for(;pos < BufferSize && (pos&3) != 0;pos++)
+            minsize = minu(BufferSize, (pos+3)&~3);
+            for(;pos < minsize;pos++)
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
         }
         }
 
 
-        if(!(gain > GAIN_SILENCE_THRESHOLD))
+        if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
             continue;
             continue;
         gain4 = vdupq_n_f32(gain);
         gain4 = vdupq_n_f32(gain);
         for(;BufferSize-pos > 3;pos += 4)
         for(;BufferSize-pos > 3;pos += 4)
         {
         {
             const float32x4_t val4 = vld1q_f32(&data[pos]);
             const float32x4_t val4 = vld1q_f32(&data[pos]);
             float32x4_t dry4 = vld1q_f32(&OutBuffer[c][OutPos+pos]);
             float32x4_t dry4 = vld1q_f32(&OutBuffer[c][OutPos+pos]);
-            dry4 = vaddq_f32(dry4, vmulq_f32(val4, gain4));
+            dry4 = vmlaq_f32(dry4, val4, gain4);
             vst1q_f32(&OutBuffer[c][OutPos+pos], dry4);
             vst1q_f32(&OutBuffer[c][OutPos+pos], dry4);
         }
         }
         for(;pos < BufferSize;pos++)
         for(;pos < BufferSize;pos++)

+ 99 - 22
libs/openal-soft/Alc/mixer_sse.c

@@ -1,12 +1,5 @@
 #include "config.h"
 #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 <xmmintrin.h>
 
 
 #include "AL/al.h"
 #include "AL/al.h"
@@ -19,6 +12,82 @@
 #include "mixer_defs.h"
 #include "mixer_defs.h"
 
 
 
 
+const ALfloat *Resample_bsinc32_SSE(const BsincState *state, const ALfloat *src, ALuint frac,
+                                    ALuint increment, ALfloat *restrict dst, ALuint dstlen)
+{
+    const __m128 sf4 = _mm_set1_ps(state->sf);
+    const ALuint m = state->m;
+    const ALint l = state->l;
+    const ALfloat *fil, *scd, *phd, *spd;
+    ALuint pi, j_f, i;
+    ALfloat pf;
+    ALint j_s;
+    __m128 r4;
+
+    for(i = 0;i < dstlen;i++)
+    {
+        // Calculate the phase index and factor.
+#define FRAC_PHASE_BITDIFF (FRACTIONBITS-BSINC_PHASE_BITS)
+        pi = frac >> FRAC_PHASE_BITDIFF;
+        pf = (frac & ((1<<FRAC_PHASE_BITDIFF)-1)) * (1.0f/(1<<FRAC_PHASE_BITDIFF));
+#undef FRAC_PHASE_BITDIFF
+
+        fil = state->coeffs[pi].filter;
+        scd = state->coeffs[pi].scDelta;
+        phd = state->coeffs[pi].phDelta;
+        spd = state->coeffs[pi].spDelta;
+
+        // Apply the scale and phase interpolated filter.
+        r4 = _mm_setzero_ps();
+        {
+            const __m128 pf4 = _mm_set1_ps(pf);
+            for(j_f = 0,j_s = l;j_f < m;j_f+=4,j_s+=4)
+            {
+                const __m128 f4 = _mm_add_ps(
+                    _mm_add_ps(
+                        _mm_load_ps(&fil[j_f]),
+                        _mm_mul_ps(sf4, _mm_load_ps(&scd[j_f]))
+                    ),
+                    _mm_mul_ps(
+                        pf4,
+                        _mm_add_ps(
+                            _mm_load_ps(&phd[j_f]),
+                            _mm_mul_ps(sf4, _mm_load_ps(&spd[j_f]))
+                        )
+                    )
+                );
+                r4 = _mm_add_ps(r4, _mm_mul_ps(f4, _mm_loadu_ps(&src[j_s])));
+            }
+        }
+        r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3)));
+        r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4));
+        dst[i] = _mm_cvtss_f32(r4);
+
+        frac += increment;
+        src  += frac>>FRACTIONBITS;
+        frac &= FRACTIONMASK;
+    }
+    return dst;
+}
+
+
+static inline void SetupCoeffs(ALfloat (*restrict OutCoeffs)[2],
+                               const HrtfParams *hrtfparams,
+                               ALuint IrSize, ALuint Counter)
+{
+    const __m128 counter4 = _mm_set1_ps((float)Counter);
+    __m128 coeffs, step4;
+    ALuint i;
+
+    for(i = 0;i < IrSize;i += 2)
+    {
+        step4  = _mm_load_ps(&hrtfparams->CoeffStep[i][0]);
+        coeffs = _mm_load_ps(&hrtfparams->Coeffs[i][0]);
+        coeffs = _mm_sub_ps(coeffs, _mm_mul_ps(step4, counter4));
+        _mm_store_ps(&OutCoeffs[i][0], coeffs);
+    }
+}
+
 static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
 static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
                                    const ALuint IrSize,
                                    const ALuint IrSize,
                                    ALfloat (*restrict Coeffs)[2],
                                    ALfloat (*restrict Coeffs)[2],
@@ -133,16 +202,16 @@ static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
     }
     }
 }
 }
 
 
-#define SUFFIX SSE
+#define MixHrtf MixHrtf_SSE
 #include "mixer_inc.c"
 #include "mixer_inc.c"
-#undef SUFFIX
+#undef MixHrtf
 
 
 
 
 void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
 void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
              MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize)
              MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize)
 {
 {
     ALfloat gain, step;
     ALfloat gain, step;
-    __m128 gain4, step4;
+    __m128 gain4;
     ALuint c;
     ALuint c;
 
 
     for(c = 0;c < OutChans;c++)
     for(c = 0;c < OutChans;c++)
@@ -150,43 +219,51 @@ void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)
         ALuint pos = 0;
         ALuint pos = 0;
         gain = Gains[c].Current;
         gain = Gains[c].Current;
         step = Gains[c].Step;
         step = Gains[c].Step;
-        if(step != 1.0f && Counter > 0)
+        if(step != 0.0f && Counter > 0)
         {
         {
+            ALuint minsize = minu(BufferSize, Counter);
             /* Mix with applying gain steps in aligned multiples of 4. */
             /* Mix with applying gain steps in aligned multiples of 4. */
-            if(BufferSize-pos > 3 && Counter-pos > 3)
+            if(minsize-pos > 3)
             {
             {
+                __m128 step4;
                 gain4 = _mm_setr_ps(
                 gain4 = _mm_setr_ps(
                     gain,
                     gain,
-                    gain * step,
-                    gain * step * step,
-                    gain * step * step * step
+                    gain + step,
+                    gain + step + step,
+                    gain + step + step + step
                 );
                 );
-                step4 = _mm_set1_ps(step * step * step * step);
+                step4 = _mm_set1_ps(step + step + step + step);
                 do {
                 do {
                     const __m128 val4 = _mm_load_ps(&data[pos]);
                     const __m128 val4 = _mm_load_ps(&data[pos]);
                     __m128 dry4 = _mm_load_ps(&OutBuffer[c][OutPos+pos]);
                     __m128 dry4 = _mm_load_ps(&OutBuffer[c][OutPos+pos]);
                     dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4));
                     dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4));
-                    gain4 = _mm_mul_ps(gain4, step4);
+                    gain4 = _mm_add_ps(gain4, step4);
                     _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4);
                     _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4);
                     pos += 4;
                     pos += 4;
-                } while(BufferSize-pos > 3 && Counter-pos > 3);
+                } while(minsize-pos > 3);
+                /* NOTE: gain4 now represents the next four gains after the
+                 * last four mixed samples, so the lowest element represents
+                 * the next gain to apply.
+                 */
                 gain = _mm_cvtss_f32(gain4);
                 gain = _mm_cvtss_f32(gain4);
             }
             }
             /* Mix with applying left over gain steps that aren't aligned multiples of 4. */
             /* Mix with applying left over gain steps that aren't aligned multiples of 4. */
-            for(;pos < BufferSize && pos < Counter;pos++)
+            for(;pos < minsize;pos++)
             {
             {
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
-                gain *= step;
+                gain += step;
             }
             }
             if(pos == Counter)
             if(pos == Counter)
                 gain = Gains[c].Target;
                 gain = Gains[c].Target;
             Gains[c].Current = gain;
             Gains[c].Current = gain;
+
             /* Mix until pos is aligned with 4 or the mix is done. */
             /* Mix until pos is aligned with 4 or the mix is done. */
-            for(;pos < BufferSize && (pos&3) != 0;pos++)
+            minsize = minu(BufferSize, (pos+3)&~3);
+            for(;pos < minsize;pos++)
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
                 OutBuffer[c][OutPos+pos] += data[pos]*gain;
         }
         }
 
 
-        if(!(gain > GAIN_SILENCE_THRESHOLD))
+        if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
             continue;
             continue;
         gain4 = _mm_set1_ps(gain);
         gain4 = _mm_set1_ps(gain);
         for(;BufferSize-pos > 3;pos += 4)
         for(;BufferSize-pos > 3;pos += 4)

+ 6 - 3
libs/openal-soft/Alc/mixer_sse2.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -27,7 +27,7 @@
 #include "mixer_defs.h"
 #include "mixer_defs.h"
 
 
 
 
-const ALfloat *Resample_lerp32_SSE2(const ALfloat *src, ALuint frac, ALuint increment,
+const ALfloat *Resample_lerp32_SSE2(const BsincState* UNUSED(state), const ALfloat *src, ALuint frac, ALuint increment,
                                     ALfloat *restrict dst, ALuint numsamples)
                                     ALfloat *restrict dst, ALuint numsamples)
 {
 {
     const __m128i increment4 = _mm_set1_epi32(increment*4);
     const __m128i increment4 = _mm_set1_epi32(increment*4);
@@ -63,6 +63,9 @@ const ALfloat *Resample_lerp32_SSE2(const ALfloat *src, ALuint frac, ALuint incr
         _mm_store_ps(pos_.f, _mm_castsi128_ps(pos4));
         _mm_store_ps(pos_.f, _mm_castsi128_ps(pos4));
     }
     }
 
 
+    /* NOTE: These four elements represent the position *after* the last four
+     * samples, so the lowest element is the next position to resample.
+     */
     pos = pos_.i[0];
     pos = pos_.i[0];
     frac = _mm_cvtsi128_si32(frac4);
     frac = _mm_cvtsi128_si32(frac4);
 
 

+ 145 - 3
libs/openal-soft/Alc/mixer_sse41.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -28,7 +28,7 @@
 #include "mixer_defs.h"
 #include "mixer_defs.h"
 
 
 
 
-const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint increment,
+const ALfloat *Resample_lerp32_SSE41(const BsincState* UNUSED(state), const ALfloat *src, ALuint frac, ALuint increment,
                                      ALfloat *restrict dst, ALuint numsamples)
                                      ALfloat *restrict dst, ALuint numsamples)
 {
 {
     const __m128i increment4 = _mm_set1_epi32(increment*4);
     const __m128i increment4 = _mm_set1_epi32(increment*4);
@@ -67,6 +67,9 @@ const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint inc
         pos_.i[3] = _mm_extract_epi32(pos4, 3);
         pos_.i[3] = _mm_extract_epi32(pos4, 3);
     }
     }
 
 
+    /* NOTE: These four elements represent the position *after* the last four
+     * samples, so the lowest element is the next position to resample.
+     */
     pos = pos_.i[0];
     pos = pos_.i[0];
     frac = _mm_cvtsi128_si32(frac4);
     frac = _mm_cvtsi128_si32(frac4);
 
 
@@ -80,3 +83,142 @@ const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint inc
     }
     }
     return dst;
     return dst;
 }
 }
+
+const ALfloat *Resample_fir4_32_SSE41(const BsincState* UNUSED(state), const ALfloat *src, ALuint frac, ALuint increment,
+                                      ALfloat *restrict dst, ALuint numsamples)
+{
+    const __m128i increment4 = _mm_set1_epi32(increment*4);
+    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));
+
+    --src;
+    for(i = 0;numsamples-i > 3;i += 4)
+    {
+        const __m128 val0 = _mm_loadu_ps(&src[pos_.i[0]]);
+        const __m128 val1 = _mm_loadu_ps(&src[pos_.i[1]]);
+        const __m128 val2 = _mm_loadu_ps(&src[pos_.i[2]]);
+        const __m128 val3 = _mm_loadu_ps(&src[pos_.i[3]]);
+        __m128 k0 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[0]]);
+        __m128 k1 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[1]]);
+        __m128 k2 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[2]]);
+        __m128 k3 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[3]]);
+        __m128 out;
+
+        k0 = _mm_mul_ps(k0, val0);
+        k1 = _mm_mul_ps(k1, val1);
+        k2 = _mm_mul_ps(k2, val2);
+        k3 = _mm_mul_ps(k3, val3);
+        k0 = _mm_hadd_ps(k0, k1);
+        k2 = _mm_hadd_ps(k2, k3);
+        out = _mm_hadd_ps(k0, k2);
+
+        _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);
+        frac_.i[0] = _mm_extract_epi32(frac4, 0);
+        frac_.i[1] = _mm_extract_epi32(frac4, 1);
+        frac_.i[2] = _mm_extract_epi32(frac4, 2);
+        frac_.i[3] = _mm_extract_epi32(frac4, 3);
+    }
+
+    pos = pos_.i[0];
+    frac = frac_.i[0];
+
+    for(;i < numsamples;i++)
+    {
+        dst[i] = resample_fir4(src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
+
+        frac += increment;
+        pos  += frac>>FRACTIONBITS;
+        frac &= FRACTIONMASK;
+    }
+    return dst;
+}
+
+const ALfloat *Resample_fir8_32_SSE41(const BsincState* UNUSED(state), const ALfloat *src, ALuint frac, ALuint increment,
+                                      ALfloat *restrict dst, ALuint numsamples)
+{
+    const __m128i increment4 = _mm_set1_epi32(increment*4);
+    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, j;
+
+    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));
+
+    src -= 3;
+    for(i = 0;numsamples-i > 3;i += 4)
+    {
+        __m128 out[2];
+        for(j = 0;j < 8;j+=4)
+        {
+            const __m128 val0 = _mm_loadu_ps(&src[pos_.i[0]+j]);
+            const __m128 val1 = _mm_loadu_ps(&src[pos_.i[1]+j]);
+            const __m128 val2 = _mm_loadu_ps(&src[pos_.i[2]+j]);
+            const __m128 val3 = _mm_loadu_ps(&src[pos_.i[3]+j]);
+            __m128 k0 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[0]][j]);
+            __m128 k1 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[1]][j]);
+            __m128 k2 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[2]][j]);
+            __m128 k3 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[3]][j]);
+
+            k0 = _mm_mul_ps(k0, val0);
+            k1 = _mm_mul_ps(k1, val1);
+            k2 = _mm_mul_ps(k2, val2);
+            k3 = _mm_mul_ps(k3, val3);
+            k0 = _mm_hadd_ps(k0, k1);
+            k2 = _mm_hadd_ps(k2, k3);
+            out[j>>2] = _mm_hadd_ps(k0, k2);
+        }
+
+        out[0] = _mm_add_ps(out[0], out[1]);
+        _mm_store_ps(&dst[i], out[0]);
+
+        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);
+        frac_.i[0] = _mm_extract_epi32(frac4, 0);
+        frac_.i[1] = _mm_extract_epi32(frac4, 1);
+        frac_.i[2] = _mm_extract_epi32(frac4, 2);
+        frac_.i[3] = _mm_extract_epi32(frac4, 3);
+    }
+
+    pos = pos_.i[0];
+    frac = frac_.i[0];
+
+    for(;i < numsamples;i++)
+    {
+        dst[i] = resample_fir8(src[pos  ], src[pos+1], src[pos+2], src[pos+3],
+                               src[pos+4], src[pos+5], src[pos+6], src[pos+7], frac);
+
+        frac += increment;
+        pos  += frac>>FRACTIONBITS;
+        frac &= FRACTIONMASK;
+    }
+    return dst;
+}

+ 452 - 345
libs/openal-soft/Alc/panning.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -30,421 +30,528 @@
 #include "AL/al.h"
 #include "AL/al.h"
 #include "AL/alc.h"
 #include "AL/alc.h"
 #include "alu.h"
 #include "alu.h"
-
-extern inline void SetGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MaxChannels]);
-
-static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MaxChannels],
-                                  enum Channel Speaker2Chan[MaxChannels], ALint chans)
+#include "bool.h"
+
+
+#define ZERO_ORDER_SCALE    0.0f
+#define FIRST_ORDER_SCALE   1.0f
+#define SECOND_ORDER_SCALE  (1.0f / 1.22474f)
+#define THIRD_ORDER_SCALE   (1.0f / 1.30657f)
+
+
+static const ALuint FuMa2ACN[MAX_AMBI_COEFFS] = {
+    0,  /* W */
+    3,  /* X */
+    1,  /* Y */
+    2,  /* Z */
+    6,  /* R */
+    7,  /* S */
+    5,  /* T */
+    8,  /* U */
+    4,  /* V */
+    12, /* K */
+    13, /* L */
+    11, /* M */
+    14, /* N */
+    10, /* O */
+    15, /* P */
+    9,  /* Q */
+};
+
+/* NOTE: These are scale factors as applied to Ambisonics content. FuMa
+ * decoder coefficients should be divided by these values to get N3D decoder
+ * coefficients.
+ */
+static const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
+    1.414213562f, /* ACN  0 (W), sqrt(2) */
+    1.732050808f, /* ACN  1 (Y), sqrt(3) */
+    1.732050808f, /* ACN  2 (Z), sqrt(3) */
+    1.732050808f, /* ACN  3 (X), sqrt(3) */
+    1.936491673f, /* ACN  4 (V), sqrt(15)/2 */
+    1.936491673f, /* ACN  5 (T), sqrt(15)/2 */
+    2.236067978f, /* ACN  6 (R), sqrt(5) */
+    1.936491673f, /* ACN  7 (S), sqrt(15)/2 */
+    1.936491673f, /* ACN  8 (U), sqrt(15)/2 */
+    2.091650066f, /* ACN  9 (Q), sqrt(35/8) */
+    1.972026594f, /* ACN 10 (O), sqrt(35)/3 */
+    2.231093404f, /* ACN 11 (M), sqrt(224/45) */
+    2.645751311f, /* ACN 12 (K), sqrt(7) */
+    2.231093404f, /* ACN 13 (L), sqrt(224/45) */
+    1.972026594f, /* ACN 14 (N), sqrt(35)/3 */
+    2.091650066f, /* ACN 15 (P), sqrt(35/8) */
+};
+
+
+void ComputeAmbientGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
 {
 {
-    char *confkey, *next;
-    char *layout_str;
-    char *sep, *end;
-    enum Channel val;
-    const char *str;
-    int i;
-
-    if(!ConfigValueStr(NULL, name, &str) && !ConfigValueStr(NULL, "layout", &str))
-        return;
+    ALuint i;
 
 
-    layout_str = strdup(str);
-    next = confkey = layout_str;
-    while(next && *next)
+    for(i = 0;i < device->NumChannels;i++)
     {
     {
-        confkey = next;
-        next = strchr(confkey, ',');
-        if(next)
-        {
-            *next = 0;
-            do {
-                next++;
-            } while(isspace(*next) || *next == ',');
-        }
-
-        sep = strchr(confkey, '=');
-        if(!sep || confkey == sep)
-        {
-            ERR("Malformed speaker key: %s\n", confkey);
-            continue;
-        }
-
-        end = sep - 1;
-        while(isspace(*end) && end != confkey)
-            end--;
-        *(++end) = 0;
-
-        if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0)
-            val = FrontLeft;
-        else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0)
-            val = FrontRight;
-        else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0)
-            val = FrontCenter;
-        else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0)
-            val = BackLeft;
-        else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0)
-            val = BackRight;
-        else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0)
-            val = BackCenter;
-        else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0)
-            val = SideLeft;
-        else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0)
-            val = SideRight;
-        else
-        {
-            ERR("Unknown speaker for %s: \"%s\"\n", name, confkey);
-            continue;
-        }
-
-        *(sep++) = 0;
-        while(isspace(*sep))
-            sep++;
-
-        for(i = 0;i < chans;i++)
-        {
-            if(Speaker2Chan[i] == val)
-            {
-                long angle = strtol(sep, NULL, 10);
-                if(angle >= -180 && angle <= 180)
-                    SpeakerAngle[i] = DEG2RAD(angle);
-                else
-                    ERR("Invalid angle for speaker \"%s\": %ld\n", confkey, angle);
-                break;
-            }
-        }
+        // The W coefficients are based on a mathematical average of the
+        // output. The square root of the base average provides for a more
+        // perceptual average volume, better suited to non-directional gains.
+        gains[i] = sqrtf(device->AmbiCoeffs[i][0]) * ingain;
     }
     }
-    free(layout_str);
-    layout_str = NULL;
+    for(;i < MAX_OUTPUT_CHANNELS;i++)
+        gains[i] = 0.0f;
+}
 
 
-    for(i = 0;i < chans;i++)
+void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat elevation, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+{
+    ALfloat dir[3] = {
+        sinf(angle) * cosf(elevation),
+        sinf(elevation),
+        -cosf(angle) * cosf(elevation)
+    };
+    ComputeDirectionalGains(device, dir, ingain, gains);
+}
+
+void ComputeDirectionalGains(const ALCdevice *device, const ALfloat dir[3], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+{
+    ALfloat coeffs[MAX_AMBI_COEFFS];
+    ALuint i, j;
+    /* Convert from OpenAL coords to Ambisonics. */
+    ALfloat x = -dir[2];
+    ALfloat y = -dir[0];
+    ALfloat z =  dir[1];
+
+    /* Zeroth-order */
+    coeffs[0]  = 1.0f; /* ACN 0 = 1 */
+    /* First-order */
+    coeffs[1]  = 1.732050808f * y; /* ACN 1 = sqrt(3) * Y */
+    coeffs[2]  = 1.732050808f * z; /* ACN 2 = sqrt(3) * Z */
+    coeffs[3]  = 1.732050808f * x; /* ACN 3 = sqrt(3) * X */
+    /* Second-order */
+    coeffs[4]  = 3.872983346f * x * y;             /* ACN 4 = sqrt(15) * X * Y */
+    coeffs[5]  = 3.872983346f * y * z;             /* ACN 5 = sqrt(15) * Y * Z */
+    coeffs[6]  = 1.118033989f * (3.0f*z*z - 1.0f); /* ACN 6 = sqrt(5)/2 * (3*Z*Z - 1) */
+    coeffs[7]  = 3.872983346f * x * z;             /* ACN 7 = sqrt(15) * X * Z */
+    coeffs[8]  = 1.936491673f * (x*x - y*y);       /* ACN 8 = sqrt(15)/2 * (X*X - Y*Y) */
+    /* Third-order */
+    coeffs[9]  =  2.091650066f * y * (3.0f*x*x - y*y);  /* ACN  9 = sqrt(35/8) * Y * (3*X*X - Y*Y) */
+    coeffs[10] = 10.246950766f * z * x * y;             /* ACN 10 = sqrt(105) * Z * X * Y */
+    coeffs[11] =  1.620185175f * y * (5.0f*z*z - 1.0f); /* ACN 11 = sqrt(21/8) * Y * (5*Z*Z - 1) */
+    coeffs[12] =  1.322875656f * z * (5.0f*z*z - 3.0f); /* ACN 12 = sqrt(7)/2 * Z * (5*Z*Z - 3) */
+    coeffs[13] =  1.620185175f * x * (5.0f*z*z - 1.0f); /* ACN 13 = sqrt(21/8) * X * (5*Z*Z - 1) */
+    coeffs[14] =  5.123475383f * z * (x*x - y*y);       /* ACN 14 = sqrt(105)/2 * Z * (X*X - Y*Y) */
+    coeffs[15] =  2.091650066f * x * (x*x - 3.0f*y*y);  /* ACN 15 = sqrt(35/8) * X * (X*X - 3*Y*Y) */
+
+    for(i = 0;i < device->NumChannels;i++)
     {
     {
-        int min = i;
-        int i2;
+        float gain = 0.0f;
+        for(j = 0;j < MAX_AMBI_COEFFS;j++)
+            gain += device->AmbiCoeffs[i][j]*coeffs[j];
+        gains[i] = gain * ingain;
+    }
+    for(;i < MAX_OUTPUT_CHANNELS;i++)
+        gains[i] = 0.0f;
+}
 
 
-        for(i2 = i+1;i2 < chans;i2++)
-        {
-            if(SpeakerAngle[i2] < SpeakerAngle[min])
-                min = i2;
-        }
+void ComputeBFormatGains(const ALCdevice *device, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+{
+    ALuint i, j;
 
 
-        if(min != i)
-        {
-            ALfloat tmpf;
-            enum Channel tmpc;
+    for(i = 0;i < device->NumChannels;i++)
+    {
+        float gain = 0.0f;
+        for(j = 0;j < 4;j++)
+            gain += device->AmbiCoeffs[i][j] * mtx[j];
+        gains[i] = gain * ingain;
+    }
+    for(;i < MAX_OUTPUT_CHANNELS;i++)
+        gains[i] = 0.0f;
+}
 
 
-            tmpf = SpeakerAngle[i];
-            SpeakerAngle[i] = SpeakerAngle[min];
-            SpeakerAngle[min] = tmpf;
 
 
-            tmpc = Speaker2Chan[i];
-            Speaker2Chan[i] = Speaker2Chan[min];
-            Speaker2Chan[min] = tmpc;
-        }
+DECL_CONST static inline const char *GetLabelFromChannel(enum Channel channel)
+{
+    switch(channel)
+    {
+        case FrontLeft: return "front-left";
+        case FrontRight: return "front-right";
+        case FrontCenter: return "front-center";
+        case LFE: return "lfe";
+        case BackLeft: return "back-left";
+        case BackRight: return "back-right";
+        case BackCenter: return "back-center";
+        case SideLeft: return "side-left";
+        case SideRight: return "side-right";
+
+        case BFormatW: return "bformat-w";
+        case BFormatX: return "bformat-x";
+        case BFormatY: return "bformat-y";
+        case BFormatZ: return "bformat-z";
+
+        case InvalidChannel: break;
     }
     }
+    return "(unknown)";
 }
 }
 
 
 
 
-void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat gains[MaxChannels])
+typedef struct ChannelMap {
+    enum Channel ChanName;
+    ChannelConfig Config;
+} ChannelMap;
+
+static void SetChannelMap(ALCdevice *device, const ChannelMap *chanmap, size_t count, ALfloat ambiscale, ALboolean isfuma)
 {
 {
-    ALfloat tmpgains[MaxChannels] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
-    enum Channel Speaker2Chan[MaxChannels];
-    ALfloat SpeakerAngle[MaxChannels];
-    ALfloat langle, rangle;
-    ALfloat a;
+    size_t j, k;
     ALuint i;
     ALuint i;
 
 
-    for(i = 0;i < device->NumChan;i++)
-        Speaker2Chan[i] = device->Speaker2Chan[i];
-    for(i = 0;i < device->NumChan;i++)
-        SpeakerAngle[i] = device->SpeakerAngle[i];
-
-    /* Some easy special-cases first... */
-    if(device->NumChan <= 1 || hwidth >= F_PI)
+    device->AmbiScale = ambiscale;
+    for(i = 0;i < MAX_OUTPUT_CHANNELS && device->ChannelName[i] != InvalidChannel;i++)
     {
     {
-        /* Full coverage for all speakers. */
-        for(i = 0;i < MaxChannels;i++)
-            gains[i] = 0.0f;
-        for(i = 0;i < device->NumChan;i++)
+        if(device->ChannelName[i] == LFE)
         {
         {
-            enum Channel chan = Speaker2Chan[i];
-            gains[chan] = ingain;
+            for(j = 0;j < MAX_AMBI_COEFFS;j++)
+                device->AmbiCoeffs[i][j] = 0.0f;
+            continue;
         }
         }
-        return;
-    }
-    if(hwidth <= 0.0f)
-    {
-        /* Infinitely small sound point. */
-        for(i = 0;i < MaxChannels;i++)
-            gains[i] = 0.0f;
-        for(i = 0;i < device->NumChan-1;i++)
+
+        for(j = 0;j < count;j++)
         {
         {
-            if(angle >= SpeakerAngle[i] && angle < SpeakerAngle[i+1])
+            if(device->ChannelName[i] == chanmap[j].ChanName)
             {
             {
-                /* Sound is between speakers i and i+1 */
-                a =             (angle-SpeakerAngle[i]) /
-                    (SpeakerAngle[i+1]-SpeakerAngle[i]);
-                gains[Speaker2Chan[i]]   = sqrtf(1.0f-a) * ingain;
-                gains[Speaker2Chan[i+1]] = sqrtf(     a) * ingain;
-                return;
+                if(isfuma)
+                {
+                    /* Reformat FuMa -> ACN/N3D */
+                    for(k = 0;k < MAX_AMBI_COEFFS;++k)
+                    {
+                        ALuint acn = FuMa2ACN[k];
+                        device->AmbiCoeffs[i][acn] = chanmap[j].Config[k] / FuMa2N3DScale[acn];
+                    }
+                }
+                else
+                {
+                    for(k = 0;k < MAX_AMBI_COEFFS;++k)
+                        device->AmbiCoeffs[i][k] = chanmap[j].Config[k];
+                }
+                break;
             }
             }
         }
         }
-        /* Sound is between last and first speakers */
-        if(angle < SpeakerAngle[0])
-            angle += F_2PI;
-        a =                   (angle-SpeakerAngle[i]) /
-            (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
-        gains[Speaker2Chan[i]] = sqrtf(1.0f-a) * ingain;
-        gains[Speaker2Chan[0]] = sqrtf(     a) * ingain;
-        return;
+        if(j == count)
+            ERR("Failed to match %s channel (%u) in config\n", GetLabelFromChannel(device->ChannelName[i]), i);
     }
     }
+    device->NumChannels = i;
+}
 
 
-    if(fabsf(angle)+hwidth > F_PI)
+static bool LoadChannelSetup(ALCdevice *device)
+{
+    static const enum Channel mono_chans[1] = {
+        FrontCenter
+    }, stereo_chans[2] = {
+        FrontLeft, FrontRight
+    }, quad_chans[4] = {
+        FrontLeft, FrontRight,
+        BackLeft, BackRight
+    }, surround51_chans[5] = {
+        FrontLeft, FrontRight, FrontCenter,
+        SideLeft, SideRight
+    }, surround51rear_chans[5] = {
+        FrontLeft, FrontRight, FrontCenter,
+        BackLeft, BackRight
+    }, surround61_chans[6] = {
+        FrontLeft, FrontRight,
+        FrontCenter, BackCenter,
+        SideLeft, SideRight
+    }, surround71_chans[7] = {
+        FrontLeft, FrontRight, FrontCenter,
+        BackLeft, BackRight,
+        SideLeft, SideRight
+    };
+    ChannelMap chanmap[MAX_OUTPUT_CHANNELS];
+    const enum Channel *channels = NULL;
+    const char *layout = NULL;
+    ALfloat ambiscale = 1.0f;
+    size_t count = 0;
+    int isfuma;
+    int order;
+    size_t i;
+
+    switch(device->FmtChans)
     {
     {
-        /* The coverage area would go outside of -pi...+pi. Instead, rotate the
-         * speaker angles so it would be as if angle=0, and keep them wrapped
-         * within -pi...+pi. */
-        if(angle > 0.0f)
-        {
-            ALuint done;
-            ALuint i = 0;
-            while(i < device->NumChan && device->SpeakerAngle[i]-angle < -F_PI)
-                i++;
-            for(done = 0;i < device->NumChan;done++)
-            {
-                SpeakerAngle[done] = device->SpeakerAngle[i]-angle;
-                Speaker2Chan[done] = device->Speaker2Chan[i];
-                i++;
-            }
-            for(i = 0;done < device->NumChan;i++)
-            {
-                SpeakerAngle[done] = device->SpeakerAngle[i]-angle + F_2PI;
-                Speaker2Chan[done] = device->Speaker2Chan[i];
-                done++;
-            }
-        }
-        else
-        {
-            /* NOTE: '< device->NumChan' on the iterators is correct here since
-             * we need to handle index 0. Because the iterators are unsigned,
-             * they'll underflow and wrap to become 0xFFFFFFFF, which will
-             * break as expected. */
-            ALuint done;
-            ALuint i = device->NumChan-1;
-            while(i < device->NumChan && device->SpeakerAngle[i]-angle > F_PI)
-                i--;
-            for(done = device->NumChan-1;i < device->NumChan;done--)
-            {
-                SpeakerAngle[done] = device->SpeakerAngle[i]-angle;
-                Speaker2Chan[done] = device->Speaker2Chan[i];
-                i--;
-            }
-            for(i = device->NumChan-1;done < device->NumChan;i--)
-            {
-                SpeakerAngle[done] = device->SpeakerAngle[i]-angle - F_2PI;
-                Speaker2Chan[done] = device->Speaker2Chan[i];
-                done--;
-            }
-        }
-        angle = 0.0f;
+        case DevFmtMono:
+            layout = "mono";
+            channels = mono_chans;
+            count = COUNTOF(mono_chans);
+            break;
+        case DevFmtStereo:
+            layout = "stereo";
+            channels = stereo_chans;
+            count = COUNTOF(stereo_chans);
+            break;
+        case DevFmtQuad:
+            layout = "quad";
+            channels = quad_chans;
+            count = COUNTOF(quad_chans);
+            break;
+        case DevFmtX51:
+            layout = "surround51";
+            channels = surround51_chans;
+            count = COUNTOF(surround51_chans);
+            break;
+        case DevFmtX51Rear:
+            layout = "surround51rear";
+            channels = surround51rear_chans;
+            count = COUNTOF(surround51rear_chans);
+            break;
+        case DevFmtX61:
+            layout = "surround61";
+            channels = surround61_chans;
+            count = COUNTOF(surround61_chans);
+            break;
+        case DevFmtX71:
+            layout = "surround71";
+            channels = surround71_chans;
+            count = COUNTOF(surround71_chans);
+            break;
+        case DevFmtBFormat3D:
+            break;
     }
     }
-    langle = angle - hwidth;
-    rangle = angle + hwidth;
 
 
-    /* First speaker */
-    i = 0;
-    do {
-        ALuint last = device->NumChan-1;
-        enum Channel chan = Speaker2Chan[i];
+    if(!layout)
+        return false;
+    else
+    {
+        char name[32] = {0};
+        const char *type;
+        char eol;
 
 
-        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
-        {
-            tmpgains[chan] = 1.0f;
-            continue;
-        }
+        snprintf(name, sizeof(name), "%s/type", layout);
+        if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", name, &type))
+            return false;
 
 
-        if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
+        if(sscanf(type, " %31[^: ] : %d%c", name, &order, &eol) != 2)
         {
         {
-            a =            (langle-SpeakerAngle[i]) /
-                (SpeakerAngle[i+1]-SpeakerAngle[i]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
+            ERR("Invalid type value '%s' (expected name:order) for layout %s\n", type, layout);
+            return false;
         }
         }
-        if(SpeakerAngle[i] > rangle)
-        {
-            a =          (F_2PI + rangle-SpeakerAngle[last]) /
-                (F_2PI + SpeakerAngle[i]-SpeakerAngle[last]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
-        }
-        else if(SpeakerAngle[last] < rangle)
-        {
-            a =                  (rangle-SpeakerAngle[last]) /
-                (F_2PI + SpeakerAngle[i]-SpeakerAngle[last]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
-        }
-    } while(0);
 
 
-    for(i = 1;i < device->NumChan-1;i++)
-    {
-        enum Channel chan = Speaker2Chan[i];
-        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
+        if(strcasecmp(name, "fuma") == 0)
+            isfuma = 1;
+        else if(strcasecmp(name, "n3d") == 0)
+            isfuma = 0;
+        else
         {
         {
-            tmpgains[chan] = 1.0f;
-            continue;
+            ERR("Unhandled type name '%s' (expected FuMa or N3D) for layout %s\n", name, layout);
+            return false;
         }
         }
 
 
-        if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
-        {
-            a =            (langle-SpeakerAngle[i]) /
-                (SpeakerAngle[i+1]-SpeakerAngle[i]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
-        }
-        if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
+        if(order == 3)
+            ambiscale = THIRD_ORDER_SCALE;
+        else if(order == 2)
+            ambiscale = SECOND_ORDER_SCALE;
+        else if(order == 1)
+            ambiscale = FIRST_ORDER_SCALE;
+        else if(order == 0)
+            ambiscale = ZERO_ORDER_SCALE;
+        else
         {
         {
-            a =          (rangle-SpeakerAngle[i-1]) /
-                (SpeakerAngle[i]-SpeakerAngle[i-1]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
+            ERR("Unhandled type order %d (expected 0, 1, 2, or 3) for layout %s\n", order, layout);
+            return false;
         }
         }
     }
     }
 
 
-    /* Last speaker */
-    i = device->NumChan-1;
-    do {
-        enum Channel chan = Speaker2Chan[i];
-        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
-        {
-            tmpgains[Speaker2Chan[i]] = 1.0f;
-            continue;
-        }
-        if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
+    for(i = 0;i < count;i++)
+    {
+        float coeffs[MAX_AMBI_COEFFS] = {0.0f};
+        const char *channame;
+        char chanlayout[32];
+        const char *value;
+        int props = 0;
+        char eol = 0;
+        int j;
+
+        chanmap[i].ChanName = channels[i];
+        channame = GetLabelFromChannel(channels[i]);
+
+        snprintf(chanlayout, sizeof(chanlayout), "%s/%s", layout, channame);
+        if(!ConfigValueStr(al_string_get_cstr(device->DeviceName), "layouts", chanlayout, &value))
         {
         {
-            a =          (rangle-SpeakerAngle[i-1]) /
-                (SpeakerAngle[i]-SpeakerAngle[i-1]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
+            ERR("Missing channel %s\n", channame);
+            return false;
         }
         }
-        if(SpeakerAngle[i] < langle)
+        if(order == 3)
+            props = sscanf(value, " %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %c",
+                &coeffs[0],  &coeffs[1],  &coeffs[2],  &coeffs[3],
+                &coeffs[4],  &coeffs[5],  &coeffs[6],  &coeffs[7],
+                &coeffs[8],  &coeffs[9],  &coeffs[10], &coeffs[11],
+                &coeffs[12], &coeffs[13], &coeffs[14], &coeffs[15],
+                &eol
+            );
+        else if(order == 2)
+            props = sscanf(value, " %f %f %f %f %f %f %f %f %f %c",
+                &coeffs[0], &coeffs[1], &coeffs[2],
+                &coeffs[3], &coeffs[4], &coeffs[5],
+                &coeffs[6], &coeffs[7], &coeffs[8],
+                &eol
+            );
+        else if(order == 1)
+            props = sscanf(value, " %f %f %f %f %c",
+                &coeffs[0], &coeffs[1],
+                &coeffs[2], &coeffs[3],
+                &eol
+            );
+        else if(order == 0)
+            props = sscanf(value, " %f %c", &coeffs[0], &eol);
+        if(props == 0)
         {
         {
-            a =                  (langle-SpeakerAngle[i]) /
-                (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
+            ERR("Failed to parse option %s properties\n", chanlayout);
+            return false;
         }
         }
-        else if(SpeakerAngle[0] > langle)
+
+        if(props > (order+1)*(order+1))
         {
         {
-            a =          (F_2PI + langle-SpeakerAngle[i]) /
-                (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
+            ERR("Excess elements in option %s (expected %d)\n", chanlayout, (order+1)*(order+1));
+            return false;
         }
         }
-    } while(0);
 
 
-    for(i = 0;i < device->NumChan;i++)
-    {
-        enum Channel chan = device->Speaker2Chan[i];
-        gains[chan] = sqrtf(tmpgains[chan]) * ingain;
+        for(j = 0;j < MAX_AMBI_COEFFS;++j)
+            chanmap[i].Config[j] = coeffs[j];
     }
     }
+    SetChannelMap(device, chanmap, count, ambiscale, isfuma);
+    return true;
 }
 }
 
 
-
-ALvoid aluInitPanning(ALCdevice *Device)
+ALvoid aluInitPanning(ALCdevice *device)
 {
 {
-    const char *layoutname = NULL;
-    enum Channel *Speaker2Chan;
-    ALfloat *SpeakerAngle;
+    /* NOTE: These decoder coefficients are using FuMa channel ordering and
+     * normalization, since that's what was produced by the Ambisonic Decoder
+     * Toolbox. SetChannelMap will convert them to N3D.
+     */
+    static const ChannelMap MonoCfg[1] = {
+        { FrontCenter, { 1.414213562f } },
+    }, StereoCfg[2] = {
+        { FrontLeft,   { 0.707106781f, 0.0f,  0.5f, 0.0f } },
+        { FrontRight,  { 0.707106781f, 0.0f, -0.5f, 0.0f } },
+    }, QuadCfg[4] = {
+        { FrontLeft,   { 0.353553f,  0.306184f,  0.306184f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f,  0.117186f } },
+        { FrontRight,  { 0.353553f,  0.306184f, -0.306184f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f, -0.117186f } },
+        { BackLeft,    { 0.353553f, -0.306184f,  0.306184f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f, -0.117186f } },
+        { BackRight,   { 0.353553f, -0.306184f, -0.306184f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f,  0.117186f } },
+    }, X51SideCfg[5] = {
+        { FrontLeft,   { 0.208954f,  0.212846f,  0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f,  0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f,  0.047490f } },
+        { FrontRight,  { 0.208954f,  0.212846f, -0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f, -0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f, -0.047490f } },
+        { FrontCenter, { 0.109403f,  0.179490f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f,  0.142031f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.072024f,  0.000000f } },
+        { SideLeft,    { 0.470936f, -0.369626f,  0.349386f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031375f, -0.058144f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007119f, -0.043968f } },
+        { SideRight,   { 0.470936f, -0.369626f, -0.349386f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031375f,  0.058144f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007119f,  0.043968f } },
+    }, X51RearCfg[5] = {
+        { FrontLeft,   { 0.208954f,  0.212846f,  0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f,  0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f,  0.047490f } },
+        { FrontRight,  { 0.208954f,  0.212846f, -0.238350f, 0.0f, 0.0f, 0.0f, 0.0f, -0.017738f, -0.204014f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.051023f, -0.047490f } },
+        { FrontCenter, { 0.109403f,  0.179490f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f,  0.142031f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.072024f,  0.000000f } },
+        { BackLeft,    { 0.470936f, -0.369626f,  0.349386f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031375f, -0.058144f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007119f, -0.043968f } },
+        { BackRight,   { 0.470936f, -0.369626f, -0.349386f, 0.0f, 0.0f, 0.0f, 0.0f, -0.031375f,  0.058144f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.007119f,  0.043968f } },
+    }, X61Cfg[6] = {
+        { FrontLeft,   { 0.167065f,  0.200583f,  0.172695f, 0.0f, 0.0f, 0.0f, 0.0f,  0.029855f,  0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f,  0.068910f } },
+        { FrontRight,  { 0.167065f,  0.200583f, -0.172695f, 0.0f, 0.0f, 0.0f, 0.0f,  0.029855f, -0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, -0.068910f } },
+        { FrontCenter, { 0.109403f,  0.179490f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f,  0.142031f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.072024f,  0.000000f } },
+        { BackCenter,  { 0.353556f, -0.461940f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f,  0.165723f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f,  0.000000f } },
+        { SideLeft,    { 0.289151f, -0.081301f,  0.401292f, 0.0f, 0.0f, 0.0f, 0.0f, -0.188208f, -0.071420f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.010099f, -0.032897f } },
+        { SideRight,   { 0.289151f, -0.081301f, -0.401292f, 0.0f, 0.0f, 0.0f, 0.0f, -0.188208f,  0.071420f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.010099f,  0.032897f } },
+    }, X71Cfg[7] = {
+        { FrontLeft,   { 0.167065f,  0.200583f,  0.172695f, 0.0f, 0.0f, 0.0f, 0.0f,  0.029855f,  0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f,  0.068910f } },
+        { FrontRight,  { 0.167065f,  0.200583f, -0.172695f, 0.0f, 0.0f, 0.0f, 0.0f,  0.029855f, -0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, -0.068910f } },
+        { FrontCenter, { 0.109403f,  0.179490f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f,  0.142031f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.072024f,  0.000000f } },
+        { BackLeft,    { 0.224752f, -0.295009f,  0.170325f, 0.0f, 0.0f, 0.0f, 0.0f,  0.105349f, -0.182473f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f,  0.065799f } },
+        { BackRight,   { 0.224752f, -0.295009f, -0.170325f, 0.0f, 0.0f, 0.0f, 0.0f,  0.105349f,  0.182473f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f, -0.065799f } },
+        { SideLeft,    { 0.224739f,  0.000000f,  0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f, -0.065795f } },
+        { SideRight,   { 0.224739f,  0.000000f, -0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f,  0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.000000f,  0.065795f } },
+    }, BFormat3D[4] = {
+        { BFormatW, { 1.0f, 0.0f, 0.0f, 0.0f } },
+        { BFormatX, { 0.0f, 1.0f, 0.0f, 0.0f } },
+        { BFormatY, { 0.0f, 0.0f, 1.0f, 0.0f } },
+        { BFormatZ, { 0.0f, 0.0f, 0.0f, 1.0f } },
+    };
+    const ChannelMap *chanmap = NULL;
+    ALfloat ambiscale = 1.0f;
+    size_t count = 0;
+
+    device->AmbiScale = 1.0f;
+    memset(device->AmbiCoeffs, 0, sizeof(device->AmbiCoeffs));
+    device->NumChannels = 0;
+
+    if(device->Hrtf)
+    {
+        ALfloat (*coeffs_list[4])[2];
+        ALuint *delay_list[4];
+        ALuint i;
+
+        count = COUNTOF(BFormat3D);
+        chanmap = BFormat3D;
+        ambiscale = 1.0f;
+
+        for(i = 0;i < count;i++)
+            device->ChannelName[i] = chanmap[i].ChanName;
+        for(;i < MAX_OUTPUT_CHANNELS;i++)
+            device->ChannelName[i] = InvalidChannel;
+        SetChannelMap(device, chanmap, count, ambiscale, AL_TRUE);
+
+        for(i = 0;i < 4;++i)
+        {
+            static const enum Channel inputs[4] = { BFormatW, BFormatX, BFormatY, BFormatZ };
+            int chan = GetChannelIdxByName(device, inputs[i]);
+            coeffs_list[i] = device->Hrtf_Params[chan].Coeffs;
+            delay_list[i] = device->Hrtf_Params[chan].Delay;
+        }
+        GetBFormatHrtfCoeffs(device->Hrtf, 4, coeffs_list, delay_list);
+
+        return;
+    }
+
+    if(LoadChannelSetup(device))
+        return;
 
 
-    Speaker2Chan = Device->Speaker2Chan;
-    SpeakerAngle = Device->SpeakerAngle;
-    switch(Device->FmtChans)
+    switch(device->FmtChans)
     {
     {
         case DevFmtMono:
         case DevFmtMono:
-            Device->NumChan = 1;
-            Speaker2Chan[0] = FrontCenter;
-            SpeakerAngle[0] = DEG2RAD(0.0f);
-            layoutname = NULL;
+            count = COUNTOF(MonoCfg);
+            chanmap = MonoCfg;
+            ambiscale = ZERO_ORDER_SCALE;
             break;
             break;
 
 
         case DevFmtStereo:
         case DevFmtStereo:
-            Device->NumChan = 2;
-            Speaker2Chan[0] = FrontLeft;
-            Speaker2Chan[1] = FrontRight;
-            SpeakerAngle[0] = DEG2RAD(-90.0f);
-            SpeakerAngle[1] = DEG2RAD( 90.0f);
-            layoutname = "layout_stereo";
+            count = COUNTOF(StereoCfg);
+            chanmap = StereoCfg;
+            ambiscale = FIRST_ORDER_SCALE;
             break;
             break;
 
 
         case DevFmtQuad:
         case DevFmtQuad:
-            Device->NumChan = 4;
-            Speaker2Chan[0] = BackLeft;
-            Speaker2Chan[1] = FrontLeft;
-            Speaker2Chan[2] = FrontRight;
-            Speaker2Chan[3] = BackRight;
-            SpeakerAngle[0] = DEG2RAD(-135.0f);
-            SpeakerAngle[1] = DEG2RAD( -45.0f);
-            SpeakerAngle[2] = DEG2RAD(  45.0f);
-            SpeakerAngle[3] = DEG2RAD( 135.0f);
-            layoutname = "layout_quad";
+            count = COUNTOF(QuadCfg);
+            chanmap = QuadCfg;
+            ambiscale = SECOND_ORDER_SCALE;
             break;
             break;
 
 
         case DevFmtX51:
         case DevFmtX51:
-            Device->NumChan = 5;
-            Speaker2Chan[0] = BackLeft;
-            Speaker2Chan[1] = FrontLeft;
-            Speaker2Chan[2] = FrontCenter;
-            Speaker2Chan[3] = FrontRight;
-            Speaker2Chan[4] = BackRight;
-            SpeakerAngle[0] = DEG2RAD(-110.0f);
-            SpeakerAngle[1] = DEG2RAD( -30.0f);
-            SpeakerAngle[2] = DEG2RAD(   0.0f);
-            SpeakerAngle[3] = DEG2RAD(  30.0f);
-            SpeakerAngle[4] = DEG2RAD( 110.0f);
-            layoutname = "layout_surround51";
+            count = COUNTOF(X51SideCfg);
+            chanmap = X51SideCfg;
+            ambiscale = THIRD_ORDER_SCALE;
             break;
             break;
 
 
-        case DevFmtX51Side:
-            Device->NumChan = 5;
-            Speaker2Chan[0] = SideLeft;
-            Speaker2Chan[1] = FrontLeft;
-            Speaker2Chan[2] = FrontCenter;
-            Speaker2Chan[3] = FrontRight;
-            Speaker2Chan[4] = SideRight;
-            SpeakerAngle[0] = DEG2RAD(-90.0f);
-            SpeakerAngle[1] = DEG2RAD(-30.0f);
-            SpeakerAngle[2] = DEG2RAD(  0.0f);
-            SpeakerAngle[3] = DEG2RAD( 30.0f);
-            SpeakerAngle[4] = DEG2RAD( 90.0f);
-            layoutname = "layout_side51";
+        case DevFmtX51Rear:
+            count = COUNTOF(X51RearCfg);
+            chanmap = X51RearCfg;
+            ambiscale = THIRD_ORDER_SCALE;
             break;
             break;
 
 
         case DevFmtX61:
         case DevFmtX61:
-            Device->NumChan = 6;
-            Speaker2Chan[0] = SideLeft;
-            Speaker2Chan[1] = FrontLeft;
-            Speaker2Chan[2] = FrontCenter;
-            Speaker2Chan[3] = FrontRight;
-            Speaker2Chan[4] = SideRight;
-            Speaker2Chan[5] = BackCenter;
-            SpeakerAngle[0] = DEG2RAD(-90.0f);
-            SpeakerAngle[1] = DEG2RAD(-30.0f);
-            SpeakerAngle[2] = DEG2RAD(  0.0f);
-            SpeakerAngle[3] = DEG2RAD( 30.0f);
-            SpeakerAngle[4] = DEG2RAD( 90.0f);
-            SpeakerAngle[5] = DEG2RAD(180.0f);
-            layoutname = "layout_surround61";
+            count = COUNTOF(X61Cfg);
+            chanmap = X61Cfg;
+            ambiscale = THIRD_ORDER_SCALE;
             break;
             break;
 
 
         case DevFmtX71:
         case DevFmtX71:
-            Device->NumChan = 7;
-            Speaker2Chan[0] = BackLeft;
-            Speaker2Chan[1] = SideLeft;
-            Speaker2Chan[2] = FrontLeft;
-            Speaker2Chan[3] = FrontCenter;
-            Speaker2Chan[4] = FrontRight;
-            Speaker2Chan[5] = SideRight;
-            Speaker2Chan[6] = BackRight;
-            SpeakerAngle[0] = DEG2RAD(-150.0f);
-            SpeakerAngle[1] = DEG2RAD( -90.0f);
-            SpeakerAngle[2] = DEG2RAD( -30.0f);
-            SpeakerAngle[3] = DEG2RAD(   0.0f);
-            SpeakerAngle[4] = DEG2RAD(  30.0f);
-            SpeakerAngle[5] = DEG2RAD(  90.0f);
-            SpeakerAngle[6] = DEG2RAD( 150.0f);
-            layoutname = "layout_surround71";
+            count = COUNTOF(X71Cfg);
+            chanmap = X71Cfg;
+            ambiscale = THIRD_ORDER_SCALE;
+            break;
+
+        case DevFmtBFormat3D:
+            count = COUNTOF(BFormat3D);
+            chanmap = BFormat3D;
+            ambiscale = 1.0f;
             break;
             break;
     }
     }
-    if(layoutname && Device->Type != Loopback)
-        SetSpeakerArrangement(layoutname, SpeakerAngle, Speaker2Chan, Device->NumChan);
+
+    SetChannelMap(device, chanmap, count, ambiscale, AL_TRUE);
 }
 }

+ 26 - 8
libs/openal-soft/Alc/vector.h

@@ -7,21 +7,21 @@
 
 
 /* "Base" vector type, designed to alias with the actual vector types. */
 /* "Base" vector type, designed to alias with the actual vector types. */
 typedef struct vector__s {
 typedef struct vector__s {
-    ALsizei Capacity;
-    ALsizei Size;
+    size_t Capacity;
+    size_t Size;
 } *vector_;
 } *vector_;
 
 
 #define TYPEDEF_VECTOR(T, N) typedef struct {                                 \
 #define TYPEDEF_VECTOR(T, N) typedef struct {                                 \
-    ALsizei Capacity;                                                         \
-    ALsizei Size;                                                             \
+    size_t Capacity;                                                          \
+    size_t Size;                                                              \
     T Data[];                                                                 \
     T Data[];                                                                 \
 } _##N;                                                                       \
 } _##N;                                                                       \
 typedef _##N* N;                                                              \
 typedef _##N* N;                                                              \
 typedef const _##N* const_##N;
 typedef const _##N* const_##N;
 
 
 #define VECTOR(T) struct {                                                    \
 #define VECTOR(T) struct {                                                    \
-    ALsizei Capacity;                                                         \
-    ALsizei Size;                                                             \
+    size_t Capacity;                                                          \
+    size_t Size;                                                              \
     T Data[];                                                                 \
     T Data[];                                                                 \
 }*
 }*
 
 
@@ -30,10 +30,10 @@ typedef const _##N* const_##N;
 #define VECTOR_DEINIT(_x)     do { free((_x)); (_x) = NULL; } while(0)
 #define VECTOR_DEINIT(_x)     do { free((_x)); (_x) = NULL; } while(0)
 
 
 /* Helper to increase a vector's reserve. Do not call directly. */
 /* 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);
+ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, size_t obj_count, ALboolean exact);
 #define VECTOR_RESERVE(_x, _c) (vector_reserve((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_c), AL_TRUE))
 #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);
+ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, size_t obj_count);
 #define VECTOR_RESIZE(_x, _c) (vector_resize((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_c)))
 #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_CAPACITY(_x) ((_x) ? (_x)->Capacity : 0)
@@ -73,6 +73,13 @@ ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_
         _f(_iter);                                                            \
         _f(_iter);                                                            \
 } while(0)
 } while(0)
 
 
+#define VECTOR_FOR_EACH_PARAMS(_t, _x, _f, ...)  do {                         \
+    _t *_iter = VECTOR_ITER_BEGIN((_x));                                      \
+    _t *_end = VECTOR_ITER_END((_x));                                         \
+    for(;_iter != _end;++_iter)                                               \
+        _f(__VA_ARGS__, _iter);                                               \
+} while(0)
+
 #define VECTOR_FIND_IF(_i, _t, _x, _f)  do {                                  \
 #define VECTOR_FIND_IF(_i, _t, _x, _f)  do {                                  \
     _t *_iter = VECTOR_ITER_BEGIN((_x));                                      \
     _t *_iter = VECTOR_ITER_BEGIN((_x));                                      \
     _t *_end = VECTOR_ITER_END((_x));                                         \
     _t *_end = VECTOR_ITER_END((_x));                                         \
@@ -84,4 +91,15 @@ ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_
     (_i) = _iter;                                                             \
     (_i) = _iter;                                                             \
 } while(0)
 } while(0)
 
 
+#define VECTOR_FIND_IF_PARMS(_i, _t, _x, _f, ...)  do {                       \
+    _t *_iter = VECTOR_ITER_BEGIN((_x));                                      \
+    _t *_end = VECTOR_ITER_END((_x));                                         \
+    for(;_iter != _end;++_iter)                                               \
+    {                                                                         \
+        if(_f(__VA_ARGS__, _iter))                                            \
+            break;                                                            \
+    }                                                                         \
+    (_i) = _iter;                                                             \
+} while(0)
+
 #endif /* AL_VECTOR_H */
 #endif /* AL_VECTOR_H */

+ 167 - 117
libs/openal-soft/CMakeLists.txt

@@ -34,9 +34,11 @@ OPTION(ALSOFT_UTILS          "Build and install utility programs"         OFF)
 OPTION(ALSOFT_NO_CONFIG_UTIL "Disable building the alsoft-config utility" OFF)
 OPTION(ALSOFT_NO_CONFIG_UTIL "Disable building the alsoft-config utility" OFF)
 
 
 OPTION(ALSOFT_EXAMPLES  "Build and install example programs"  OFF)
 OPTION(ALSOFT_EXAMPLES  "Build and install example programs"  OFF)
+OPTION(ALSOFT_TESTS     "Build and install test programs"     OFF)
 
 
 OPTION(ALSOFT_CONFIG "Install alsoft.conf sample configuration file" OFF)
 OPTION(ALSOFT_CONFIG "Install alsoft.conf sample configuration file" OFF)
-OPTION(ALSOFT_HRTF_DEFS "Install HRTF definition files" ON)
+OPTION(ALSOFT_HRTF_DEFS "Install HRTF definition files" OFF)
+OPTION(ALSOFT_INSTALL "Install headers and libraries" ON)
 
 
 
 
 IF(WIN32)
 IF(WIN32)
@@ -89,7 +91,7 @@ IF(NOT LIBTYPE)
 ENDIF()
 ENDIF()
 
 
 SET(LIB_MAJOR_VERSION "1")
 SET(LIB_MAJOR_VERSION "1")
-SET(LIB_MINOR_VERSION "16")
+SET(LIB_MINOR_VERSION "17")
 SET(LIB_REVISION "0")
 SET(LIB_REVISION "0")
 SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}")
 SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}")
 
 
@@ -101,9 +103,14 @@ CHECK_TYPE_SIZE("long" SIZEOF_LONG)
 CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
 CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG)
 
 
 
 
-CHECK_C_COMPILER_FLAG(-std=c99 HAVE_STD_C99)
-IF(HAVE_STD_C99)
-    SET(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}")
+CHECK_C_COMPILER_FLAG(-std=c11 HAVE_STD_C11)
+IF(HAVE_STD_C11)
+    SET(CMAKE_C_FLAGS "-std=c11 ${CMAKE_C_FLAGS}")
+ELSE()
+    CHECK_C_COMPILER_FLAG(-std=c99 HAVE_STD_C99)
+    IF(HAVE_STD_C99)
+        SET(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}")
+    ENDIF()
 ENDIF()
 ENDIF()
 
 
 # MSVC may need workarounds for C99 restrict and inline
 # MSVC may need workarounds for C99 restrict and inline
@@ -188,7 +195,7 @@ HAVE_C11_ALIGNAS)
 # Check if we have C11 _Atomic
 # Check if we have C11 _Atomic
 CHECK_C_SOURCE_COMPILES(
 CHECK_C_SOURCE_COMPILES(
 "#include <stdatomic.h>
 "#include <stdatomic.h>
- int _Atomic foo;
+ const int _Atomic foo = ATOMIC_VAR_INIT(~0);
  int main()
  int main()
  {
  {
      return atomic_load(&foo);
      return atomic_load(&foo);
@@ -216,11 +223,6 @@ IF(NOT CMAKE_DEBUG_POSTFIX)
 ENDIF()
 ENDIF()
 
 
 IF(MSVC)
 IF(MSVC)
-    # ???
-    SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -D_DEBUG")
-    SET(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DNDEBUG")
-    SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG")
-    SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG")
     ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
     ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
     ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
     ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE)
     ADD_DEFINITIONS("/wd4098")
     ADD_DEFINITIONS("/wd4098")
@@ -232,9 +234,6 @@ IF(MSVC)
     ENDIF()
     ENDIF()
     IF(DXSDK_DIR)
     IF(DXSDK_DIR)
         MESSAGE(STATUS "Using DirectX SDK directory: ${DXSDK_DIR}")
         MESSAGE(STATUS "Using DirectX SDK directory: ${DXSDK_DIR}")
-        SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} "${DXSDK_DIR}/Include")
-        INCLUDE_DIRECTORIES("${DXSDK_DIR}/Include")
-        LINK_DIRECTORIES("${DXSDK_DIR}/Lib")
     ENDIF()
     ENDIF()
 
 
     OPTION(FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF)
     OPTION(FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF)
@@ -258,27 +257,24 @@ ELSE()
         ADD_DEFINITIONS(-Werror)
         ADD_DEFINITIONS(-Werror)
     ENDIF()
     ENDIF()
 
 
-    # Force enable PIC if available. The static common library will be linked
-    # into the dynamic openal library, which requires all its code to be
-    # position-independent, and CMake doesn't automatically enable PIC for
-    # static library targets (Windows code is always position-independent).
-    CHECK_C_COMPILER_FLAG(-fPIC HAVE_FPIC_SWITCH)
-    IF(HAVE_FPIC_SWITCH AND NOT WIN32)
-        ADD_DEFINITIONS(-fPIC)
+    # Force enable -fPIC for CMake versions before 2.8.9 (later versions have
+    # the POSITION_INDEPENDENT_CODE target property). The static common library
+    # will be linked into the dynamic openal library, which requires all its
+    # code to be position-independent.
+    IF(CMAKE_VERSION VERSION_LESS "2.8.9" AND NOT WIN32)
+        CHECK_C_COMPILER_FLAG(-fPIC HAVE_FPIC_SWITCH)
+        IF(HAVE_FPIC_SWITCH)
+            ADD_DEFINITIONS(-fPIC)
+        ENDIF()
     ENDIF()
     ENDIF()
 
 
-    SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -D_DEBUG" CACHE STRING
-        "Flags used by the compiler during Release with Debug Info builds."
-        FORCE)
-    SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING
-        "Flags used by the compiler during release minsize builds."
-        FORCE)
-    SET(CMAKE_C_FLAGS_RELEASE "-O2 -fomit-frame-pointer -DNDEBUG" CACHE STRING
-        "Flags used by the compiler during release builds"
-        FORCE)
-    SET(CMAKE_C_FLAGS_DEBUG "-g3 -D_DEBUG" CACHE STRING
-        "Flags used by the compiler during debug builds."
-        FORCE)
+    # We want RelWithDebInfo to actually include debug stuff (define _DEBUG
+    # instead of NDEBUG)
+    FOREACH(flag_var  CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+        IF(${flag_var} MATCHES "-DNDEBUG")
+            STRING(REGEX REPLACE "-DNDEBUG" "-D_DEBUG" ${flag_var} "${${flag_var}}")
+        ENDIF()
+    ENDFOREACH()
 
 
     CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
     CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor));
                              int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
                              int main() {return 0;}" HAVE_GCC_DESTRUCTOR)
@@ -337,6 +333,10 @@ IF(NOT MSVC)
     IF(HAVE_MSSE2_SWITCH)
     IF(HAVE_MSSE2_SWITCH)
         SET(SSE2_SWITCH "-msse2")
         SET(SSE2_SWITCH "-msse2")
     ENDIF()
     ENDIF()
+    CHECK_C_COMPILER_FLAG(-msse3 HAVE_MSSE3_SWITCH)
+    IF(HAVE_MSSE3_SWITCH)
+        SET(SSE3_SWITCH "-msse3")
+    ENDIF()
     CHECK_C_COMPILER_FLAG(-msse4.1 HAVE_MSSE4_1_SWITCH)
     CHECK_C_COMPILER_FLAG(-msse4.1 HAVE_MSSE4_1_SWITCH)
     IF(HAVE_MSSE4_1_SWITCH)
     IF(HAVE_MSSE4_1_SWITCH)
         SET(SSE4_1_SWITCH "-msse4.1")
         SET(SSE4_1_SWITCH "-msse4.1")
@@ -349,7 +349,7 @@ CHECK_C_SOURCE_COMPILES("int foo(const char *str, ...) __attribute__((format(pri
 CHECK_INCLUDE_FILE(stdbool.h HAVE_STDBOOL_H)
 CHECK_INCLUDE_FILE(stdbool.h HAVE_STDBOOL_H)
 CHECK_INCLUDE_FILE(stdalign.h HAVE_STDALIGN_H)
 CHECK_INCLUDE_FILE(stdalign.h HAVE_STDALIGN_H)
 CHECK_INCLUDE_FILE(malloc.h HAVE_MALLOC_H)
 CHECK_INCLUDE_FILE(malloc.h HAVE_MALLOC_H)
-CHECK_INCLUDE_FILE(ftw.h HAVE_FTW_H)
+CHECK_INCLUDE_FILE(dirent.h HAVE_DIRENT_H)
 CHECK_INCLUDE_FILE(io.h HAVE_IO_H)
 CHECK_INCLUDE_FILE(io.h HAVE_IO_H)
 CHECK_INCLUDE_FILE(strings.h HAVE_STRINGS_H)
 CHECK_INCLUDE_FILE(strings.h HAVE_STRINGS_H)
 CHECK_INCLUDE_FILE(cpuid.h HAVE_CPUID_H)
 CHECK_INCLUDE_FILE(cpuid.h HAVE_CPUID_H)
@@ -368,7 +368,7 @@ IF(HAVE_CPUID_H)
         int main()
         int main()
         {
         {
             unsigned int eax, ebx, ecx, edx;
             unsigned int eax, ebx, ecx, edx;
-            return __get_cpuid(0, eax, ebx, ecx, edx);
+            return __get_cpuid(0, &eax, &ebx, &ecx, &edx);
         }" HAVE_GCC_GET_CPUID)
         }" HAVE_GCC_GET_CPUID)
 ENDIF()
 ENDIF()
 
 
@@ -394,6 +394,7 @@ CHECK_SYMBOL_EXISTS(aligned_alloc    stdlib.h HAVE_ALIGNED_ALLOC)
 CHECK_SYMBOL_EXISTS(posix_memalign   stdlib.h HAVE_POSIX_MEMALIGN)
 CHECK_SYMBOL_EXISTS(posix_memalign   stdlib.h HAVE_POSIX_MEMALIGN)
 CHECK_SYMBOL_EXISTS(_aligned_malloc  malloc.h HAVE__ALIGNED_MALLOC)
 CHECK_SYMBOL_EXISTS(_aligned_malloc  malloc.h HAVE__ALIGNED_MALLOC)
 CHECK_SYMBOL_EXISTS(lrintf math.h HAVE_LRINTF)
 CHECK_SYMBOL_EXISTS(lrintf math.h HAVE_LRINTF)
+CHECK_SYMBOL_EXISTS(modff  math.h HAVE_MODFF)
 IF(NOT HAVE_C99_VLA)
 IF(NOT HAVE_C99_VLA)
     CHECK_SYMBOL_EXISTS(alloca malloc.h HAVE_ALLOCA)
     CHECK_SYMBOL_EXISTS(alloca malloc.h HAVE_ALLOCA)
     IF(NOT HAVE_ALLOCA)
     IF(NOT HAVE_ALLOCA)
@@ -405,12 +406,6 @@ IF(HAVE_FLOAT_H)
     CHECK_SYMBOL_EXISTS(_controlfp float.h HAVE__CONTROLFP)
     CHECK_SYMBOL_EXISTS(_controlfp float.h HAVE__CONTROLFP)
     CHECK_SYMBOL_EXISTS(__control87_2 float.h HAVE___CONTROL87_2)
     CHECK_SYMBOL_EXISTS(__control87_2 float.h HAVE___CONTROL87_2)
 ENDIF()
 ENDIF()
-IF(HAVE_FTW_H)
-    CHECK_SYMBOL_EXISTS(ftw ftw.h HAVE_FTW)
-ENDIF()
-IF(HAVE_IO_H)
-    CHECK_SYMBOL_EXISTS(_wfindfirst io.h HAVE__WFINDFIRST)
-ENDIF()
 
 
 CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
 CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF)
 CHECK_FUNCTION_EXISTS(stat HAVE_STAT)
 CHECK_FUNCTION_EXISTS(stat HAVE_STAT)
@@ -515,12 +510,18 @@ IF(NOT HAVE_WINDOWS_H)
 
 
     CHECK_SYMBOL_EXISTS(pthread_setschedparam pthread.h HAVE_PTHREAD_SETSCHEDPARAM)
     CHECK_SYMBOL_EXISTS(pthread_setschedparam pthread.h HAVE_PTHREAD_SETSCHEDPARAM)
 
 
-    CHECK_SYMBOL_EXISTS(pthread_setname_np pthread.h HAVE_PTHREAD_SETNAME_NP)
-    IF(NOT HAVE_PTHREAD_SETNAME_NP)
-        CHECK_SYMBOL_EXISTS(pthread_set_name_np pthread.h HAVE_PTHREAD_SET_NAME_NP)
-    ENDIF()
     IF(HAVE_PTHREAD_NP_H)
     IF(HAVE_PTHREAD_NP_H)
+        CHECK_SYMBOL_EXISTS(pthread_setname_np "pthread.h;pthread_np.h" HAVE_PTHREAD_SETNAME_NP)
+        IF(NOT HAVE_PTHREAD_SETNAME_NP)
+            CHECK_SYMBOL_EXISTS(pthread_set_name_np "pthread.h;pthread_np.h" HAVE_PTHREAD_SET_NAME_NP)
+        ENDIF()
         CHECK_SYMBOL_EXISTS(pthread_mutexattr_setkind_np "pthread.h;pthread_np.h" HAVE_PTHREAD_MUTEXATTR_SETKIND_NP)
         CHECK_SYMBOL_EXISTS(pthread_mutexattr_setkind_np "pthread.h;pthread_np.h" HAVE_PTHREAD_MUTEXATTR_SETKIND_NP)
+    ELSE()
+        CHECK_SYMBOL_EXISTS(pthread_setname_np pthread.h HAVE_PTHREAD_SETNAME_NP)
+        IF(NOT HAVE_PTHREAD_SETNAME_NP)
+            CHECK_SYMBOL_EXISTS(pthread_set_name_np pthread.h HAVE_PTHREAD_SET_NAME_NP)
+        ENDIF()
+        CHECK_SYMBOL_EXISTS(pthread_mutexattr_setkind_np pthread.h HAVE_PTHREAD_MUTEXATTR_SETKIND_NP)
     ENDIF()
     ENDIF()
 
 
     CHECK_SYMBOL_EXISTS(pthread_mutex_timedlock pthread.h HAVE_PTHREAD_MUTEX_TIMEDLOCK)
     CHECK_SYMBOL_EXISTS(pthread_mutex_timedlock pthread.h HAVE_PTHREAD_MUTEX_TIMEDLOCK)
@@ -561,11 +562,7 @@ SET(OPENAL_OBJS  OpenAL32/alAuxEffectSlot.c
                  OpenAL32/alError.c
                  OpenAL32/alError.c
                  OpenAL32/alExtension.c
                  OpenAL32/alExtension.c
                  OpenAL32/alFilter.c
                  OpenAL32/alFilter.c
-                 OpenAL32/alFontsound.c
                  OpenAL32/alListener.c
                  OpenAL32/alListener.c
-                 OpenAL32/alMidi.c
-                 OpenAL32/alPreset.c
-                 OpenAL32/alSoundfont.c
                  OpenAL32/alSource.c
                  OpenAL32/alSource.c
                  OpenAL32/alState.c
                  OpenAL32/alState.c
                  OpenAL32/alThunk.c
                  OpenAL32/alThunk.c
@@ -588,6 +585,7 @@ SET(ALC_OBJS  Alc/ALc.c
               Alc/effects/null.c
               Alc/effects/null.c
               Alc/effects/reverb.c
               Alc/effects/reverb.c
               Alc/helpers.c
               Alc/helpers.c
+              Alc/bsinc.c
               Alc/hrtf.c
               Alc/hrtf.c
               Alc/panning.c
               Alc/panning.c
               Alc/mixer.c
               Alc/mixer.c
@@ -598,11 +596,10 @@ SET(ALC_OBJS  Alc/ALc.c
 SET(CPU_EXTS "Default")
 SET(CPU_EXTS "Default")
 SET(HAVE_SSE        0)
 SET(HAVE_SSE        0)
 SET(HAVE_SSE2       0)
 SET(HAVE_SSE2       0)
+SET(HAVE_SSE3       0)
 SET(HAVE_SSE4_1     0)
 SET(HAVE_SSE4_1     0)
 SET(HAVE_NEON       0)
 SET(HAVE_NEON       0)
 
 
-SET(HAVE_FLUIDSYNTH 0)
-
 SET(HAVE_ALSA       0)
 SET(HAVE_ALSA       0)
 SET(HAVE_OSS        0)
 SET(HAVE_OSS        0)
 SET(HAVE_SOLARIS    0)
 SET(HAVE_SOLARIS    0)
@@ -658,6 +655,26 @@ IF(ALSOFT_REQUIRE_SSE2 AND NOT HAVE_SSE2)
     MESSAGE(FATAL_ERROR "Failed to enable required SSE2 CPU extensions")
     MESSAGE(FATAL_ERROR "Failed to enable required SSE2 CPU extensions")
 ENDIF()
 ENDIF()
 
 
+OPTION(ALSOFT_REQUIRE_SSE2 "Require SSE3 support" OFF)
+CHECK_INCLUDE_FILE(pmmintrin.h HAVE_PMMINTRIN_H "${SSE3_SWITCH}")
+IF(HAVE_EMMINTRIN_H)
+    OPTION(ALSOFT_CPUEXT_SSE3 "Enable SSE3 support" ON)
+    IF(HAVE_SSE2 AND ALSOFT_CPUEXT_SSE3)
+        IF(ALIGN_DECL OR HAVE_C11_ALIGNAS)
+            SET(HAVE_SSE3 1)
+            SET(ALC_OBJS  ${ALC_OBJS} Alc/mixer_sse3.c)
+            IF(SSE2_SWITCH)
+                SET_SOURCE_FILES_PROPERTIES(Alc/mixer_sse3.c PROPERTIES
+                                            COMPILE_FLAGS "${SSE3_SWITCH}")
+            ENDIF()
+            SET(CPU_EXTS "${CPU_EXTS}, SSE3")
+        ENDIF()
+    ENDIF()
+ENDIF()
+IF(ALSOFT_REQUIRE_SSE3 AND NOT HAVE_SSE3)
+    MESSAGE(FATAL_ERROR "Failed to enable required SSE3 CPU extensions")
+ENDIF()
+
 OPTION(ALSOFT_REQUIRE_SSE4_1 "Require SSE4.1 support" OFF)
 OPTION(ALSOFT_REQUIRE_SSE4_1 "Require SSE4.1 support" OFF)
 CHECK_INCLUDE_FILE(smmintrin.h HAVE_SMMINTRIN_H "${SSE4_1_SWITCH}")
 CHECK_INCLUDE_FILE(smmintrin.h HAVE_SMMINTRIN_H "${SSE4_1_SWITCH}")
 IF(HAVE_SMMINTRIN_H)
 IF(HAVE_SMMINTRIN_H)
@@ -705,32 +722,6 @@ ELSE()
     ENDMACRO()
     ENDMACRO()
 ENDIF()
 ENDIF()
 
 
-SET(ALC_OBJS  ${ALC_OBJS}
-              Alc/midi/base.c
-              Alc/midi/sf2load.c
-              Alc/midi/dummy.c
-              Alc/midi/fluidsynth.c
-              Alc/midi/soft.c
-)
-
-# Check for FluidSynth support
-OPTION(ALSOFT_REQUIRE_FLUIDSYNTH "Require FluidSynth MIDI" OFF)
-FIND_PACKAGE(FluidSynth)
-IF(FLUIDSYNTH_FOUND)
-    OPTION(ALSOFT_MIDI_FLUIDSYNTH "Enable FluidSynth MIDI" ON)
-    IF(ALSOFT_MIDI_FLUIDSYNTH)
-        SET(HAVE_FLUIDSYNTH 1)
-        ADD_BACKEND_LIBS(${FLUIDSYNTH_LIBRARIES})
-        IF(CMAKE_VERSION VERSION_LESS "2.8.8")
-            INCLUDE_DIRECTORIES(${FLUIDSYNTH_INCLUDE_DIR})
-        ENDIF()
-    ENDIF()
-ENDIF()
-IF(ALSOFT_REQUIRE_FLUIDSYNTH AND NOT HAVE_FLUIDSYNTH)
-    MESSAGE(FATAL_ERROR "Failed to enabled required FluidSynth support")
-ENDIF()
-
-
 SET(BACKENDS "")
 SET(BACKENDS "")
 SET(ALC_OBJS  ${ALC_OBJS}
 SET(ALC_OBJS  ${ALC_OBJS}
               Alc/backends/base.c
               Alc/backends/base.c
@@ -926,6 +917,25 @@ IF(ALSOFT_REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO)
     MESSAGE(FATAL_ERROR "Failed to enabled required PulseAudio backend")
     MESSAGE(FATAL_ERROR "Failed to enabled required PulseAudio backend")
 ENDIF()
 ENDIF()
 
 
+# Check JACK backend
+OPTION(ALSOFT_REQUIRE_JACK "Require JACK backend" OFF)
+FIND_PACKAGE(JACK)
+IF(JACK_FOUND)
+    OPTION(ALSOFT_BACKEND_JACK "Enable JACK backend" ON)
+    IF(ALSOFT_BACKEND_JACK)
+        SET(HAVE_JACK 1)
+        SET(BACKENDS  "${BACKENDS} JACK${IS_LINKED},")
+        SET(ALC_OBJS  ${ALC_OBJS} Alc/backends/jack.c)
+        ADD_BACKEND_LIBS(${PULSEAUDIO_LIBRARIES})
+        IF(CMAKE_VERSION VERSION_LESS "2.8.8")
+            INCLUDE_DIRECTORIES(${JACK_INCLUDE_DIRS})
+        ENDIF()
+    ENDIF()
+ENDIF()
+IF(ALSOFT_REQUIRE_JACK AND NOT HAVE_JACK)
+    MESSAGE(FATAL_ERROR "Failed to enabled required JACK backend")
+ENDIF()
+
 # Check CoreAudio backend
 # Check CoreAudio backend
 OPTION(ALSOFT_REQUIRE_COREAUDIO "Require CoreAudio backend" OFF)
 OPTION(ALSOFT_REQUIRE_COREAUDIO "Require CoreAudio backend" OFF)
 FIND_LIBRARY(COREAUDIO_FRAMEWORK
 FIND_LIBRARY(COREAUDIO_FRAMEWORK
@@ -1030,17 +1040,21 @@ CONFIGURE_FILE(
 
 
 # Build a common library with reusable helpers
 # Build a common library with reusable helpers
 ADD_LIBRARY(common STATIC ${COMMON_OBJS})
 ADD_LIBRARY(common STATIC ${COMMON_OBJS})
+IF(NOT LIBTYPE STREQUAL "STATIC")
+    SET_PROPERTY(TARGET common PROPERTY POSITION_INDEPENDENT_CODE TRUE)
+ENDIF()
 
 
 # Build main library
 # Build main library
-ADD_LIBRARY(${LIBNAME} ${LIBTYPE} ${OPENAL_OBJS} ${ALC_OBJS})
+IF(LIBTYPE STREQUAL "STATIC")
+    ADD_LIBRARY(${LIBNAME} STATIC ${COMMON_OBJS} ${OPENAL_OBJS} ${ALC_OBJS})
+ELSE()
+    ADD_LIBRARY(${LIBNAME} SHARED ${OPENAL_OBJS} ${ALC_OBJS})
+ENDIF()
 SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY COMPILE_DEFINITIONS AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES)
 SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY COMPILE_DEFINITIONS AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES)
 IF(WIN32 AND ALSOFT_NO_UID_DEFS)
 IF(WIN32 AND ALSOFT_NO_UID_DEFS)
     SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY COMPILE_DEFINITIONS AL_NO_UID_DEFS)
     SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY COMPILE_DEFINITIONS AL_NO_UID_DEFS)
 ENDIF()
 ENDIF()
 SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES "${OpenAL_SOURCE_DIR}/OpenAL32/Include" "${OpenAL_SOURCE_DIR}/Alc")
 SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES "${OpenAL_SOURCE_DIR}/OpenAL32/Include" "${OpenAL_SOURCE_DIR}/Alc")
-IF(FLUIDSYNTH_FOUND)
-    SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${FLUIDSYNTH_INCLUDE_DIR})
-ENDIF()
 IF(HAVE_ALSA)
 IF(HAVE_ALSA)
     SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${ALSA_INCLUDE_DIRS})
     SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${ALSA_INCLUDE_DIRS})
 ENDIF()
 ENDIF()
@@ -1065,6 +1079,9 @@ ENDIF()
 IF(HAVE_PULSEAUDIO)
 IF(HAVE_PULSEAUDIO)
     SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${PULSEAUDIO_INCLUDE_DIRS})
     SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${PULSEAUDIO_INCLUDE_DIRS})
 ENDIF()
 ENDIF()
+IF(HAVE_JACK)
+    SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${JACK_INCLUDE_DIRS})
+ENDIF()
 SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION}
 SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION}
                                             SOVERSION ${LIB_MAJOR_VERSION})
                                             SOVERSION ${LIB_MAJOR_VERSION})
 IF(WIN32 AND NOT LIBTYPE STREQUAL "STATIC")
 IF(WIN32 AND NOT LIBTYPE STREQUAL "STATIC")
@@ -1096,25 +1113,28 @@ ENDIF()
 TARGET_LINK_LIBRARIES(${LIBNAME} common ${EXTRA_LIBS})
 TARGET_LINK_LIBRARIES(${LIBNAME} common ${EXTRA_LIBS})
 TARGET_INCLUDE_DIRECTORIES(${LIBNAME} PUBLIC include)
 TARGET_INCLUDE_DIRECTORIES(${LIBNAME} PUBLIC include)
 
 
-# Add an install target here
-IF(NOT MEGA)
-INSTALL(TARGETS ${LIBNAME}
-        RUNTIME DESTINATION bin
-        LIBRARY DESTINATION "lib${LIB_SUFFIX}"
-        ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
-)
-INSTALL(FILES include/AL/al.h
-              include/AL/alc.h
-              include/AL/alext.h
-              include/AL/efx.h
-              include/AL/efx-creative.h
-              include/AL/efx-presets.h
-        DESTINATION include/AL
-)
-INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc"
-        DESTINATION "lib${LIB_SUFFIX}/pkgconfig")
+IF(ALSOFT_INSTALL)
+    # Add an install target here
+    IF(NOT MEGA)
+    INSTALL(TARGETS ${LIBNAME}
+            RUNTIME DESTINATION bin
+            LIBRARY DESTINATION "lib${LIB_SUFFIX}"
+            ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
+    )
+    INSTALL(FILES include/AL/al.h
+                  include/AL/alc.h
+                  include/AL/alext.h
+                  include/AL/efx.h
+                  include/AL/efx-creative.h
+                  include/AL/efx-presets.h
+            DESTINATION include/AL
+    )
+    INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc"
+            DESTINATION "lib${LIB_SUFFIX}/pkgconfig")
+    ENDIF()
 ENDIF()
 ENDIF()
 
 
+
 MESSAGE(STATUS "")
 MESSAGE(STATUS "")
 MESSAGE(STATUS "Building OpenAL with support for the following backends:")
 MESSAGE(STATUS "Building OpenAL with support for the following backends:")
 MESSAGE(STATUS "    ${BACKENDS}")
 MESSAGE(STATUS "    ${BACKENDS}")
@@ -1122,10 +1142,6 @@ MESSAGE(STATUS "")
 MESSAGE(STATUS "Building with support for CPU extensions:")
 MESSAGE(STATUS "Building with support for CPU extensions:")
 MESSAGE(STATUS "    ${CPU_EXTS}")
 MESSAGE(STATUS "    ${CPU_EXTS}")
 MESSAGE(STATUS "")
 MESSAGE(STATUS "")
-IF(HAVE_FLUIDSYNTH)
-    MESSAGE(STATUS "FluidSynth support for ALC_SOFT_midi_interface enabled")
-    MESSAGE(STATUS "")
-ENDIF()
 
 
 IF(WIN32)
 IF(WIN32)
     IF(NOT HAVE_DSOUND)
     IF(NOT HAVE_DSOUND)
@@ -1163,11 +1179,18 @@ IF(ALSOFT_UTILS)
         TARGET_LINK_LIBRARIES(makehrtf m)
         TARGET_LINK_LIBRARIES(makehrtf m)
     ENDIF()
     ENDIF()
 
 
-    INSTALL(TARGETS openal-info makehrtf
-            RUNTIME DESTINATION bin
-            LIBRARY DESTINATION "lib${LIB_SUFFIX}"
-            ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
-    )
+    ADD_EXECUTABLE(bsincgen utils/bsincgen.c)
+    IF(HAVE_LIBM)
+        TARGET_LINK_LIBRARIES(bsincgen m)
+    ENDIF()
+
+    IF(ALSOFT_INSTALL)
+        INSTALL(TARGETS openal-info makehrtf bsincgen
+                RUNTIME DESTINATION bin
+                LIBRARY DESTINATION "lib${LIB_SUFFIX}"
+                ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
+        )
+    ENDIF()
 
 
     MESSAGE(STATUS "Building utility programs")
     MESSAGE(STATUS "Building utility programs")
     IF(TARGET alsoft-config)
     IF(TARGET alsoft-config)
@@ -1176,6 +1199,24 @@ IF(ALSOFT_UTILS)
     MESSAGE(STATUS "")
     MESSAGE(STATUS "")
 ENDIF()
 ENDIF()
 
 
+IF(ALSOFT_TESTS)
+        ADD_LIBRARY(test-common STATIC examples/common/alhelpers.c)
+
+        ADD_EXECUTABLE(altonegen examples/altonegen.c)
+        TARGET_LINK_LIBRARIES(altonegen test-common ${LIBNAME})
+
+        IF(ALSOFT_INSTALL)
+            INSTALL(TARGETS altonegen
+                    RUNTIME DESTINATION bin
+                    LIBRARY DESTINATION "lib${LIB_SUFFIX}"
+                    ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
+            )
+        ENDIF()
+
+        MESSAGE(STATUS "Building test programs")
+        MESSAGE(STATUS "")
+ENDIF()
+
 IF(ALSOFT_EXAMPLES)
 IF(ALSOFT_EXAMPLES)
     IF(SDL2_FOUND AND SDL_SOUND_FOUND)
     IF(SDL2_FOUND AND SDL_SOUND_FOUND)
         ADD_LIBRARY(ex-common STATIC examples/common/alhelpers.c
         ADD_LIBRARY(ex-common STATIC examples/common/alhelpers.c
@@ -1203,11 +1244,18 @@ IF(ALSOFT_EXAMPLES)
         SET_PROPERTY(TARGET alloopback APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR}
         SET_PROPERTY(TARGET alloopback APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR}
                                                                            ${SDL_SOUND_INCLUDE_DIR})
                                                                            ${SDL_SOUND_INCLUDE_DIR})
 
 
-        INSTALL(TARGETS alstream alreverb allatency alloopback
-                RUNTIME DESTINATION bin
-                LIBRARY DESTINATION "lib${LIB_SUFFIX}"
-                ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
-        )
+        ADD_EXECUTABLE(alhrtf examples/alhrtf.c)
+        TARGET_LINK_LIBRARIES(alhrtf ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} ${LIBNAME})
+        SET_PROPERTY(TARGET alhrtf APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR}
+                                                                       ${SDL_SOUND_INCLUDE_DIR})
+
+        IF(ALSOFT_INSTALL)
+            INSTALL(TARGETS alstream alreverb allatency alloopback
+                    RUNTIME DESTINATION bin
+                    LIBRARY DESTINATION "lib${LIB_SUFFIX}"
+                    ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
+            )
+        ENDIF()
 
 
         SET(FFVER_OK FALSE)
         SET(FFVER_OK FALSE)
         IF(FFMPEG_FOUND)
         IF(FFMPEG_FOUND)
@@ -1239,11 +1287,13 @@ IF(ALSOFT_EXAMPLES)
             SET_PROPERTY(TARGET alffplay APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR}
             SET_PROPERTY(TARGET alffplay APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR}
                                                                              ${FFMPEG_INCLUDE_DIRS})
                                                                              ${FFMPEG_INCLUDE_DIRS})
 
 
-            INSTALL(TARGETS alffplay
-                    RUNTIME DESTINATION bin
-                    LIBRARY DESTINATION "lib${LIB_SUFFIX}"
-                    ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
-            )
+            IF(ALSOFT_INSTALL)
+                INSTALL(TARGETS alffplay
+                        RUNTIME DESTINATION bin
+                        LIBRARY DESTINATION "lib${LIB_SUFFIX}"
+                        ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
+                )
+            ENDIF()
             MESSAGE(STATUS "Building SDL and FFmpeg example programs")
             MESSAGE(STATUS "Building SDL and FFmpeg example programs")
         ELSE()
         ELSE()
             MESSAGE(STATUS "Building SDL example programs")
             MESSAGE(STATUS "Building SDL example programs")

+ 10 - 13
libs/openal-soft/COPYING

@@ -1,17 +1,15 @@
- 
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
+                  GNU LIBRARY GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
 
 
  Copyright (C) 1991 Free Software Foundation, Inc.
  Copyright (C) 1991 Free Software Foundation, Inc.
-                    675 Mass Ave, Cambridge, MA 02139, USA
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Everyone is permitted to copy and distribute verbatim copies
  Everyone is permitted to copy and distribute verbatim copies
  of this license document, but changing it is not allowed.
  of this license document, but changing it is not allowed.
 
 
 [This is the first released version of the library GPL.  It is
 [This is the first released version of the library GPL.  It is
  numbered 2 because it goes with version 2 of the ordinary GPL.]
  numbered 2 because it goes with version 2 of the ordinary GPL.]
 
 
-			    Preamble
+                            Preamble
 
 
   The licenses for most software are designed to take away your
   The licenses for most software are designed to take away your
 freedom to share and change it.  By contrast, the GNU General Public
 freedom to share and change it.  By contrast, the GNU General Public
@@ -101,7 +99,7 @@ works together with the library.
   Note that it is possible for a library to be covered by the ordinary
   Note that it is possible for a library to be covered by the ordinary
 General Public License rather than by this special one.
 General Public License rather than by this special one.
 
 
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
+                  GNU LIBRARY GENERAL PUBLIC LICENSE
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
 
 
   0. This License Agreement applies to any software library which
   0. This License Agreement applies to any software library which
@@ -413,7 +411,7 @@ decision will be guided by the two goals of preserving the free status
 of all derivatives of our free software and of promoting the sharing
 of all derivatives of our free software and of promoting the sharing
 and reuse of software generally.
 and reuse of software generally.
 
 
-			    NO WARRANTY
+                            NO WARRANTY
 
 
   15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
   15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
 WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
 WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
@@ -436,9 +434,9 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
 DAMAGES.
 DAMAGES.
 
 
-		     END OF TERMS AND CONDITIONS
+                     END OF TERMS AND CONDITIONS
 
 
-     Appendix: How to Apply These Terms to Your New Libraries
+           How to Apply These Terms to Your New Libraries
 
 
   If you develop a new library, and you want it to be of the greatest
   If you develop a new library, and you want it to be of the greatest
 possible use to the public, we recommend making it free software that
 possible use to the public, we recommend making it free software that
@@ -465,8 +463,8 @@ convey the exclusion of warranty; and each file should have at least the
     Library General Public License for more details.
     Library General Public License for more details.
 
 
     You should have received a copy of the GNU Library General Public
     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., 675 Mass Ave, Cambridge, MA 02139, USA.
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 
 
 Also add information on how to contact you by electronic and paper mail.
 Also add information on how to contact you by electronic and paper mail.
 
 
@@ -481,4 +479,3 @@ necessary.  Here is a sample; alter the names:
   Ty Coon, President of Vice
   Ty Coon, President of Vice
 
 
 That's all there is to it!
 That's all there is to it!
-

+ 58 - 0
libs/openal-soft/ChangeLog

@@ -1,3 +1,61 @@
+openal-soft-1.17.0:
+
+    Implemented a JACK playback backend.
+
+    Implemented the AL_EXT_BFORMAT and AL_EXT_MULAW_BFORMAT extensions.
+
+    Implemented the ALC_SOFT_HRTF extension.
+
+    Implemented C, SSE3, and SSE4.1 based 4- and 8-point Sinc resamplers.
+
+    Implemented a C and SSE based band-limited Sinc resampler. This does 12- to
+    24-point Sinc resampling, and performs anti-aliasing.
+
+    Implemented B-Format output support for the wave file writer. This creates
+    FuMa-style first-order Ambisonics wave files (AMB format).
+
+    Implemented a stereo-mode config option for treating stereo modes as either
+    speakers or headphones.
+
+    Implemented per-device configuration options.
+
+    Fixed handling of PulseAudio and MMDevAPI devices that have identical
+    descriptions.
+
+    Fixed a potential lockup when stopping playback of suspended PulseAudio devices.
+
+    Fixed logging of Unicode characters on Windows.
+
+    Fixed 5.1 surround sound channels. By default it will now use the side
+    channels for the surround output. A configuration using rear channels is
+    still available.
+
+    Fixed the QSA backend potentially altering the capture format.
+
+    Fixed detecting MMDevAPI's default device.
+
+    Fixed returning the default capture device name.
+
+    Fixed mixing property calculations when deferring context updates.
+
+    Altered the behavior of alcSuspendContext and alcProcessContext to better
+    match certain Windows drivers.
+
+    Altered the panning algorithm, utilizing Ambisonics for better side and
+    back positioning cues with surround sound output.
+
+    Improved support for certain older Windows apps.
+
+    Improved the alffplay example to support surround sound streams.
+
+    Improved support for building as a sub-project.
+
+    Added an HRTF playback example.
+
+    Added a tone generator output test.
+
+    Added a toolchain to help with cross-compiling to Android.
+
 openal-soft-1.16.0:
 openal-soft-1.16.0:
 
 
     Implemented EFX Chorus, Flanger, Distortion, Equalizer, and Compressor
     Implemented EFX Chorus, Flanger, Distortion, Equalizer, and Compressor

+ 2 - 2
libs/openal-soft/OpenAL32/Include/alAuxEffectSlot.h

@@ -22,7 +22,7 @@ struct ALeffectStateVtable {
 
 
     ALboolean (*const deviceUpdate)(ALeffectState *state, ALCdevice *device);
     ALboolean (*const deviceUpdate)(ALeffectState *state, ALCdevice *device);
     void (*const update)(ALeffectState *state, ALCdevice *device, const struct ALeffectslot *slot);
     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 process)(ALeffectState *state, ALuint samplesToDo, const ALfloat *restrict samplesIn, ALfloat (*restrict samplesOut)[BUFFERSIZE], ALuint numChannels);
 
 
     void (*const Delete)(void *ptr);
     void (*const Delete)(void *ptr);
 };
 };
@@ -31,7 +31,7 @@ struct ALeffectStateVtable {
 DECLARE_THUNK(T, ALeffectState, void, Destruct)                               \
 DECLARE_THUNK(T, ALeffectState, void, Destruct)                               \
 DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*)         \
 DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*)         \
 DECLARE_THUNK2(T, ALeffectState, void, update, ALCdevice*, const ALeffectslot*) \
 DECLARE_THUNK2(T, ALeffectState, void, update, ALCdevice*, const ALeffectslot*) \
-DECLARE_THUNK3(T, ALeffectState, void, process, ALuint, const ALfloat*restrict, ALfloatBUFFERSIZE*restrict) \
+DECLARE_THUNK4(T, ALeffectState, void, process, ALuint, const ALfloat*restrict, ALfloatBUFFERSIZE*restrict, ALuint) \
 static void T##_ALeffectState_Delete(void *ptr)                               \
 static void T##_ALeffectState_Delete(void *ptr)                               \
 { return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); }  \
 { return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); }  \
                                                                               \
                                                                               \

+ 6 - 2
libs/openal-soft/OpenAL32/Include/alBuffer.h

@@ -32,6 +32,8 @@ enum UserFmtChannels {
     UserFmtX51    = AL_5POINT1_SOFT, /* (WFX order) */
     UserFmtX51    = AL_5POINT1_SOFT, /* (WFX order) */
     UserFmtX61    = AL_6POINT1_SOFT, /* (WFX order) */
     UserFmtX61    = AL_6POINT1_SOFT, /* (WFX order) */
     UserFmtX71    = AL_7POINT1_SOFT, /* (WFX order) */
     UserFmtX71    = AL_7POINT1_SOFT, /* (WFX order) */
+    UserFmtBFormat2D = 0x10000000, /* WXY */
+    UserFmtBFormat3D, /* WXYZ */
 };
 };
 
 
 ALuint BytesFromUserFmt(enum UserFmtType type) DECL_CONST;
 ALuint BytesFromUserFmt(enum UserFmtType type) DECL_CONST;
@@ -56,6 +58,8 @@ enum FmtChannels {
     FmtX51    = UserFmtX51,
     FmtX51    = UserFmtX51,
     FmtX61    = UserFmtX61,
     FmtX61    = UserFmtX61,
     FmtX71    = UserFmtX71,
     FmtX71    = UserFmtX71,
+    FmtBFormat2D = UserFmtBFormat2D,
+    FmtBFormat3D = UserFmtBFormat3D,
 };
 };
 #define MAX_INPUT_CHANNELS  (8)
 #define MAX_INPUT_CHANNELS  (8)
 
 
@@ -85,8 +89,8 @@ typedef struct ALbuffer {
     ALsizei  LoopStart;
     ALsizei  LoopStart;
     ALsizei  LoopEnd;
     ALsizei  LoopEnd;
 
 
-    ALsizei UnpackAlign;
-    ALsizei PackAlign;
+    ATOMIC(ALsizei) UnpackAlign;
+    ATOMIC(ALsizei) PackAlign;
 
 
     /* Number of times buffer was attached to a source (deletion can only occur when 0) */
     /* Number of times buffer was attached to a source (deletion can only occur when 0) */
     RefCount ref;
     RefCount ref;

+ 0 - 1
libs/openal-soft/OpenAL32/Include/alEffect.h

@@ -132,7 +132,6 @@ typedef union ALeffectProps {
     } Echo;
     } Echo;
 
 
     struct {
     struct {
-        ALfloat Delay;
         ALfloat LowCutoff;
         ALfloat LowCutoff;
         ALfloat LowGain;
         ALfloat LowGain;
         ALfloat Mid1Center;
         ALfloat Mid1Center;

+ 37 - 8
libs/openal-soft/OpenAL32/Include/alFilter.h

@@ -3,6 +3,8 @@
 
 
 #include "alMain.h"
 #include "alMain.h"
 
 
+#include "math_defs.h"
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
@@ -11,23 +13,29 @@ extern "C" {
 #define HIGHPASSFREQREF  (250.0f)
 #define HIGHPASSFREQREF  (250.0f)
 
 
 
 
-/* Filters implementation is based on the "Cookbook formulae for audio   *
- * EQ biquad filter coefficients" by Robert Bristow-Johnson              *
- * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt                   */
+/* Filters implementation is based on the "Cookbook formulae for audio
+ * EQ biquad filter coefficients" by Robert Bristow-Johnson
+ * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
+ */
+/* Implementation note: For the shelf filters, the specified gain is for the
+ * reference frequency, which is the centerpoint of the transition band. This
+ * better matches EFX filter design. To set the gain for the shelf itself, use
+ * the square root of the desired linear gain (or halve the dB gain).
+ */
 
 
 typedef enum ALfilterType {
 typedef enum ALfilterType {
     /** EFX-style low-pass filter, specifying a gain and reference frequency. */
     /** EFX-style low-pass filter, specifying a gain and reference frequency. */
     ALfilterType_HighShelf,
     ALfilterType_HighShelf,
     /** EFX-style high-pass filter, specifying a gain and reference frequency. */
     /** EFX-style high-pass filter, specifying a gain and reference frequency. */
     ALfilterType_LowShelf,
     ALfilterType_LowShelf,
-    /** Peaking filter, specifying a gain, reference frequency, and bandwidth. */
+    /** Peaking filter, specifying a gain and reference frequency. */
     ALfilterType_Peaking,
     ALfilterType_Peaking,
 
 
-    /** Low-pass cut-off filter, specifying a cut-off frequency and bandwidth. */
+    /** Low-pass cut-off filter, specifying a cut-off frequency. */
     ALfilterType_LowPass,
     ALfilterType_LowPass,
-    /** High-pass cut-off filter, specifying a cut-off frequency and bandwidth. */
+    /** High-pass cut-off filter, specifying a cut-off frequency. */
     ALfilterType_HighPass,
     ALfilterType_HighPass,
-    /** Band-pass filter, specifying a center frequency and bandwidth. */
+    /** Band-pass filter, specifying a center frequency. */
     ALfilterType_BandPass,
     ALfilterType_BandPass,
 } ALfilterType;
 } ALfilterType;
 
 
@@ -41,8 +49,27 @@ typedef struct ALfilterState {
 } ALfilterState;
 } ALfilterState;
 #define ALfilterState_process(a, ...) ((a)->process((a), __VA_ARGS__))
 #define ALfilterState_process(a, ...) ((a)->process((a), __VA_ARGS__))
 
 
+/* Calculates the rcpQ (i.e. 1/Q) coefficient for shelving filters, using the
+ * reference gain and shelf slope parameter.
+ * 0 < gain
+ * 0 < slope <= 1
+ */
+inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope)
+{
+    return sqrtf((gain + 1.0f/gain)*(1.0f/slope - 1.0f) + 2.0f);
+}
+/* Calculates the rcpQ (i.e. 1/Q) coefficient for filters, using the frequency
+ * multiple (i.e. ref_freq / sampling_freq) and bandwidth.
+ * 0 < freq_mult < 0.5.
+ */
+inline ALfloat calc_rcpQ_from_bandwidth(ALfloat freq_mult, ALfloat bandwidth)
+{
+    ALfloat w0 = F_TAU * freq_mult;
+    return 2.0f*sinhf(logf(2.0f)/2.0f*bandwidth*w0/sinf(w0));
+}
+
 void ALfilterState_clear(ALfilterState *filter);
 void ALfilterState_clear(ALfilterState *filter);
-void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat bandwidth);
+void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat rcpQ);
 
 
 inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample)
 inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample)
 {
 {
@@ -63,6 +90,8 @@ inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample
 
 
 void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples);
 void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples);
 
 
+void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *src, ALuint numsamples);
+
 
 
 typedef struct ALfilter {
 typedef struct ALfilter {
     // Filter type (AL_FILTER_NULL, ...)
     // Filter type (AL_FILTER_NULL, ...)

+ 5 - 4
libs/openal-soft/OpenAL32/Include/alListener.h

@@ -2,22 +2,23 @@
 #define _AL_LISTENER_H_
 #define _AL_LISTENER_H_
 
 
 #include "alMain.h"
 #include "alMain.h"
+#include "alu.h"
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
 typedef struct ALlistener {
 typedef struct ALlistener {
-    volatile ALfloat Position[3];
-    volatile ALfloat Velocity[3];
+    aluVector Position;
+    aluVector Velocity;
     volatile ALfloat Forward[3];
     volatile ALfloat Forward[3];
     volatile ALfloat Up[3];
     volatile ALfloat Up[3];
     volatile ALfloat Gain;
     volatile ALfloat Gain;
     volatile ALfloat MetersPerUnit;
     volatile ALfloat MetersPerUnit;
 
 
     struct {
     struct {
-        ALfloat Matrix[4][4];
-        ALfloat Velocity[3];
+        aluMatrixd Matrix;
+        aluVector  Velocity;
     } Params;
     } Params;
 } ALlistener;
 } ALlistener;
 
 

+ 135 - 289
libs/openal-soft/OpenAL32/Include/alMain.h

@@ -37,209 +37,7 @@
 #include "vector.h"
 #include "vector.h"
 #include "alstring.h"
 #include "alstring.h"
 
 
-#ifndef ALC_SOFT_HRTF
-#define ALC_SOFT_HRTF 1
-#define ALC_HRTF_SOFT                            0x1992
-#endif
-
-#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_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
-
-/* Fontsound properties */
-/* AL_BUFFER */
-#define AL_SAMPLE_START_SOFT                     0x2000
-#define AL_SAMPLE_END_SOFT                       0x2001
-#define AL_SAMPLE_LOOP_START_SOFT                0x2002
-#define AL_SAMPLE_LOOP_END_SOFT                  0x2003
-#define AL_SAMPLE_RATE_SOFT                      0x2004
-#define AL_BASE_KEY_SOFT                         0x2005
-#define AL_KEY_CORRECTION_SOFT                   0x2006
-#define AL_SAMPLE_TYPE_SOFT                      0x2007
-#define AL_FONTSOUND_LINK_SOFT                   0x2008
-#define AL_MOD_LFO_TO_PITCH_SOFT                 0x0005
-#define AL_VIBRATO_LFO_TO_PITCH_SOFT             0x0006
-#define AL_MOD_ENV_TO_PITCH_SOFT                 0x0007
-#define AL_FILTER_CUTOFF_SOFT                    0x0008
-#define AL_FILTER_RESONANCE_SOFT                 0x0009
-#define AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT         0x000A
-#define AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT         0x000B
-#define AL_MOD_LFO_TO_VOLUME_SOFT                0x000D
-#define AL_CHORUS_SEND_SOFT                      0x000F
-#define AL_REVERB_SEND_SOFT                      0x0010
-#define AL_PAN_SOFT                              0x0011
-#define AL_MOD_LFO_DELAY_SOFT                    0x0015
-#define AL_MOD_LFO_FREQUENCY_SOFT                0x0016
-#define AL_VIBRATO_LFO_DELAY_SOFT                0x0017
-#define AL_VIBRATO_LFO_FREQUENCY_SOFT            0x0018
-#define AL_MOD_ENV_DELAYTIME_SOFT                0x0019
-#define AL_MOD_ENV_ATTACKTIME_SOFT               0x001A
-#define AL_MOD_ENV_HOLDTIME_SOFT                 0x001B
-#define AL_MOD_ENV_DECAYTIME_SOFT                0x001C
-#define AL_MOD_ENV_SUSTAINVOLUME_SOFT            0x001D
-#define AL_MOD_ENV_RELEASETIME_SOFT              0x002E
-#define AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT          0x001F
-#define AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT         0x0020
-#define AL_VOLUME_ENV_DELAYTIME_SOFT             0x0021
-#define AL_VOLUME_ENV_ATTACKTIME_SOFT            0x0022
-#define AL_VOLUME_ENV_HOLDTIME_SOFT              0x0023
-#define AL_VOLUME_ENV_DECAYTIME_SOFT             0x0024
-#define AL_VOLUME_ENV_SUSTAINVOLUME_SOFT         0x0025
-#define AL_VOLUME_ENV_RELEASETIME_SOFT           0x0026
-#define AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT       0x0027
-#define AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT      0x0028
-#define AL_KEY_RANGE_SOFT                        0x002B
-#define AL_VELOCITY_RANGE_SOFT                   0x002C
-#define AL_ATTENUATION_SOFT                      0x0030
-#define AL_TUNING_COARSE_SOFT                    0x0033
-#define AL_TUNING_FINE_SOFT                      0x0034
-#define AL_LOOP_MODE_SOFT                        0x0036
-#define AL_TUNING_SCALE_SOFT                     0x0038
-#define AL_EXCLUSIVE_CLASS_SOFT                  0x0039
-
-/* Sample Types */
-/* AL_MONO_SOFT */
-#define AL_RIGHT_SOFT                            0x0002
-#define AL_LEFT_SOFT                             0x0004
-
-/* 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
-#define AL_CONTROLLERCHANGE_SOFT                 0x00B0
-#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*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);
-typedef void (AL_APIENTRY*LPALDELETEPRESETSSOFT)(ALsizei n, const ALuint *ids);
-typedef ALboolean (AL_APIENTRY*LPALISPRESETSOFT)(ALuint id);
-typedef void (AL_APIENTRY*LPALPRESETISOFT)(ALuint id, ALenum param, ALint value);
-typedef void (AL_APIENTRY*LPALPRESETIVSOFT)(ALuint id, ALenum param, const ALint *values);
-typedef void (AL_APIENTRY*LPALPRESETFONTSOUNDSSOFT)(ALuint id, ALsizei count, const ALuint *fsids);
-typedef void (AL_APIENTRY*LPALGETPRESETIVSOFT)(ALuint id, ALenum param, ALint *values);
-typedef void (AL_APIENTRY*LPALGENFONTSOUNDSSOFT)(ALsizei n, ALuint *ids);
-typedef void (AL_APIENTRY*LPALDELETEFONTSOUNDSSOFT)(ALsizei n, const ALuint *ids);
-typedef ALboolean (AL_APIENTRY*LPALISFONTSOUNDSOFT)(ALuint id);
-typedef void (AL_APIENTRY*LPALFONTSOUNDISOFT)(ALuint id, ALenum param, ALint value);
-typedef void (AL_APIENTRY*LPALFONTSOUND2ISOFT)(ALuint id, ALenum param, ALint value1, ALint value2);
-typedef void (AL_APIENTRY*LPALFONTSOUNDIVSOFT)(ALuint id, ALenum param, const ALint *values);
-typedef void (AL_APIENTRY*LPALGETFONTSOUNDIVSOFT)(ALuint id, ALenum param, ALint *values);
-typedef void (AL_APIENTRY*LPALFONTSOUNDMOFULATORISOFT)(ALuint id, ALsizei stage, ALenum param, ALint value);
-typedef void (AL_APIENTRY*LPALGETFONTSOUNDMODULATORIVSOFT)(ALuint id, ALsizei stage, ALenum param, ALint *values);
-typedef void (AL_APIENTRY*LPALMIDISOUNDFONTSOFT)(ALuint id);
-typedef void (AL_APIENTRY*LPALMIDISOUNDFONTVSOFT)(ALsizei count, const ALuint *ids);
-typedef void (AL_APIENTRY*LPALMIDIEVENTSOFT)(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2);
-typedef void (AL_APIENTRY*LPALMIDISYSEXSOFT)(ALuint64SOFT time, const ALbyte *data, ALsizei size);
-typedef void (AL_APIENTRY*LPALMIDIPLAYSOFT)(void);
-typedef void (AL_APIENTRY*LPALMIDIPAUSESOFT)(void);
-typedef void (AL_APIENTRY*LPALMIDISTOPSOFT)(void);
-typedef void (AL_APIENTRY*LPALMIDIRESETSOFT)(void);
-typedef void (AL_APIENTRY*LPALMIDIGAINSOFT)(ALfloat value);
-typedef ALint64SOFT (AL_APIENTRY*LPALGETINTEGER64SOFT)(ALenum pname);
-typedef void (AL_APIENTRY*LPALGETINTEGER64VSOFT)(ALenum pname, ALint64SOFT *values);
-typedef void (AL_APIENTRY*LPALLOADSOUNDFONTSOFT)(ALuint id, size_t(*cb)(ALvoid*,size_t,ALvoid*), ALvoid *user);
-#ifdef AL_ALEXT_PROTOTYPES
-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 alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *values);
-AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const ALuint *pids);
-
-AL_API void AL_APIENTRY alGenPresetsSOFT(ALsizei n, ALuint *ids);
-AL_API void AL_APIENTRY alDeletePresetsSOFT(ALsizei n, const ALuint *ids);
-AL_API ALboolean AL_APIENTRY alIsPresetSOFT(ALuint id);
-AL_API void AL_APIENTRY alPresetiSOFT(ALuint id, ALenum param, ALint value);
-AL_API void AL_APIENTRY alPresetivSOFT(ALuint id, ALenum param, const ALint *values);
-AL_API void AL_APIENTRY alGetPresetivSOFT(ALuint id, ALenum param, ALint *values);
-AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const ALuint *fsids);
-
-AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids);
-AL_API void AL_APIENTRY alDeleteFontsoundsSOFT(ALsizei n, const ALuint *ids);
-AL_API ALboolean AL_APIENTRY alIsFontsoundSOFT(ALuint id);
-AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value);
-AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1, ALint value2);
-AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint *values);
-AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *values);
-AL_API void AL_APIENTRY alFontsoundModulatoriSOFT(ALuint id, ALsizei stage, ALenum param, ALint value);
-AL_API void AL_APIENTRY alGetFontsoundModulatorivSOFT(ALuint id, ALsizei stage, ALenum param, ALint *values);
-
-AL_API void AL_APIENTRY alMidiSoundfontSOFT(ALuint id);
-AL_API void AL_APIENTRY alMidiSoundfontvSOFT(ALsizei count, const ALuint *ids);
-AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2);
-AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, ALsizei size);
-AL_API void AL_APIENTRY alMidiPlaySOFT(void);
-AL_API void AL_APIENTRY alMidiPauseSOFT(void);
-AL_API void AL_APIENTRY alMidiStopSOFT(void);
-AL_API void AL_APIENTRY alMidiResetSOFT(void);
-AL_API void AL_APIENTRY alMidiGainSOFT(ALfloat value);
-AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname);
-AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values);
-AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_t,ALvoid*), ALvoid *user);
-#endif
-#endif
+#include "hrtf.h"
 
 
 #ifndef ALC_SOFT_device_clock
 #ifndef ALC_SOFT_device_clock
 #define ALC_SOFT_device_clock 1
 #define ALC_SOFT_device_clock 1
@@ -253,19 +51,9 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname,
 #endif
 #endif
 
 
 
 
-#ifdef IN_IDE_PARSER
-/* 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
-#endif
-
-
 typedef ALint64SOFT ALint64;
 typedef ALint64SOFT ALint64;
 typedef ALuint64SOFT ALuint64;
 typedef ALuint64SOFT ALuint64;
 
 
-typedef ptrdiff_t ALintptrEXT;
-typedef ptrdiff_t ALsizeiptrEXT;
-
 #ifndef U64
 #ifndef U64
 #if defined(_MSC_VER)
 #if defined(_MSC_VER)
 #define U64(x) ((ALuint64)(x##ui64))
 #define U64(x) ((ALuint64)(x##ui64))
@@ -385,9 +173,13 @@ static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b)            \
 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \
 static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \
 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); }
 { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); }
 
 
+#define DECLARE_THUNK4(T1, T2, rettype, func, argtype1, argtype2, argtype3, argtype4) \
+static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c, argtype4 d) \
+{ return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c, d); }
+
 #define DECLARE_DEFAULT_ALLOCATORS(T)                                         \
 #define DECLARE_DEFAULT_ALLOCATORS(T)                                         \
-static void* T##_New(size_t size) { return malloc(size); }                    \
-static void T##_Delete(void *ptr) { free(ptr); }
+static void* T##_New(size_t size) { return al_malloc(16, size); }             \
+static void T##_Delete(void *ptr) { al_free(ptr); }
 
 
 /* Helper to extract an argument list for VCALL. Not used directly. */
 /* Helper to extract an argument list for VCALL. Not used directly. */
 #define EXTRACT_VCALL_ARGS(...)  __VA_ARGS__))
 #define EXTRACT_VCALL_ARGS(...)  __VA_ARGS__))
@@ -406,6 +198,18 @@ static void T##_Delete(void *ptr) { free(ptr); }
 } while(0)
 } while(0)
 
 
 
 
+#define EXTRACT_NEW_ARGS(...)  __VA_ARGS__);                                  \
+    }                                                                         \
+} while(0)
+
+#define NEW_OBJ(_res, T) do {                                                 \
+    _res = T##_New(sizeof(T));                                                \
+    if(_res)                                                                  \
+    {                                                                         \
+        memset(_res, 0, sizeof(T));                                           \
+        T##_Construct(_res, EXTRACT_NEW_ARGS
+
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
@@ -472,25 +276,11 @@ typedef struct {
     void (*StopCapture)(ALCdevice*);
     void (*StopCapture)(ALCdevice*);
     ALCenum (*CaptureSamples)(ALCdevice*, void*, ALCuint);
     ALCenum (*CaptureSamples)(ALCdevice*, void*, ALCuint);
     ALCuint (*AvailableSamples)(ALCdevice*);
     ALCuint (*AvailableSamples)(ALCdevice*);
-
-    ALint64 (*GetLatency)(ALCdevice*);
 } BackendFuncs;
 } BackendFuncs;
 
 
-ALCboolean alc_solaris_init(BackendFuncs *func_list);
-void alc_solaris_deinit(void);
-void alc_solaris_probe(enum DevProbe type);
 ALCboolean alc_sndio_init(BackendFuncs *func_list);
 ALCboolean alc_sndio_init(BackendFuncs *func_list);
 void alc_sndio_deinit(void);
 void alc_sndio_deinit(void);
 void alc_sndio_probe(enum DevProbe type);
 void alc_sndio_probe(enum DevProbe type);
-ALCboolean alcWinMMInit(BackendFuncs *FuncList);
-void alcWinMMDeinit(void);
-void alcWinMMProbe(enum DevProbe type);
-ALCboolean alc_pa_init(BackendFuncs *func_list);
-void alc_pa_deinit(void);
-void alc_pa_probe(enum DevProbe type);
-ALCboolean alc_wave_init(BackendFuncs *func_list);
-void alc_wave_deinit(void);
-void alc_wave_probe(enum DevProbe type);
 ALCboolean alc_ca_init(BackendFuncs *func_list);
 ALCboolean alc_ca_init(BackendFuncs *func_list);
 void alc_ca_deinit(void);
 void alc_ca_deinit(void);
 void alc_ca_probe(enum DevProbe type);
 void alc_ca_probe(enum DevProbe type);
@@ -516,14 +306,6 @@ enum DistanceModel {
     DefaultDistanceModel = InverseDistanceClamped
     DefaultDistanceModel = InverseDistanceClamped
 };
 };
 
 
-enum Resampler {
-    PointResampler,
-    LinearResampler,
-    CubicResampler,
-
-    ResamplerMax,
-};
-
 enum Channel {
 enum Channel {
     FrontLeft = 0,
     FrontLeft = 0,
     FrontRight,
     FrontRight,
@@ -535,7 +317,12 @@ enum Channel {
     SideLeft,
     SideLeft,
     SideRight,
     SideRight,
 
 
-    MaxChannels,
+    BFormatW,
+    BFormatX,
+    BFormatY,
+    BFormatZ,
+
+    InvalidChannel
 };
 };
 
 
 
 
@@ -559,11 +346,14 @@ enum DevFmtChannels {
     DevFmtX61    = ALC_6POINT1_SOFT,
     DevFmtX61    = ALC_6POINT1_SOFT,
     DevFmtX71    = ALC_7POINT1_SOFT,
     DevFmtX71    = ALC_7POINT1_SOFT,
 
 
-    /* Similar to 5.1, except using the side channels instead of back */
-    DevFmtX51Side = 0x80000000,
+    /* Similar to 5.1, except using rear channels instead of sides */
+    DevFmtX51Rear = 0x80000000,
+
+    DevFmtBFormat3D,
 
 
     DevFmtChannelsDefault = DevFmtStereo
     DevFmtChannelsDefault = DevFmtStereo
 };
 };
+#define MAX_OUTPUT_CHANNELS  (8)
 
 
 ALuint BytesFromDevFmt(enum DevFmtType type) DECL_CONST;
 ALuint BytesFromDevFmt(enum DevFmtType type) DECL_CONST;
 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) DECL_CONST;
 ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) DECL_CONST;
@@ -588,6 +378,38 @@ enum DeviceType {
 };
 };
 
 
 
 
+enum HrtfMode {
+    DisabledHrtf,
+    BasicHrtf,
+    FullHrtf
+};
+
+
+/* The maximum number of Ambisonics coefficients. For a given order (o), the
+ * size needed will be (o+1)**2, thus zero-order has 1, first-order has 4,
+ * second-order has 9, and third-order has 16. */
+#define MAX_AMBI_COEFFS 16
+
+typedef ALfloat ChannelConfig[MAX_AMBI_COEFFS];
+
+
+#define HRTF_HISTORY_BITS   (6)
+#define HRTF_HISTORY_LENGTH (1<<HRTF_HISTORY_BITS)
+#define HRTF_HISTORY_MASK   (HRTF_HISTORY_LENGTH-1)
+
+typedef struct HrtfState {
+    alignas(16) ALfloat History[HRTF_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;
+
+
 /* Size for temporary storage of buffer data, in ALfloats. Larger values need
 /* Size for temporary storage of buffer data, in ALfloats. Larger values need
  * more memory, while smaller values may need more iterations. The value needs
  * more memory, while smaller values may need more iterations. The value needs
  * to be a sensible size, however, as it constrains the max stepping value used
  * to be a sensible size, however, as it constrains the max stepping value used
@@ -595,7 +417,6 @@ enum DeviceType {
  */
  */
 #define BUFFERSIZE (2048u)
 #define BUFFERSIZE (2048u)
 
 
-
 struct ALCdevice_struct
 struct ALCdevice_struct
 {
 {
     RefCount ref;
     RefCount ref;
@@ -608,6 +429,7 @@ struct ALCdevice_struct
     ALuint       NumUpdates;
     ALuint       NumUpdates;
     enum DevFmtChannels FmtChans;
     enum DevFmtChannels FmtChans;
     enum DevFmtType     FmtType;
     enum DevFmtType     FmtType;
+    ALboolean    IsHeadphones;
 
 
     al_string DeviceName;
     al_string DeviceName;
 
 
@@ -631,36 +453,26 @@ struct ALCdevice_struct
     // Map of Filters for this device
     // Map of Filters for this device
     UIntMap FilterMap;
     UIntMap FilterMap;
 
 
-    // Map of Soundfonts for this device
-    UIntMap SfontMap;
-
-    // Map of Presets for this device
-    UIntMap PresetMap;
-
-    // Map of Fontsounds for this device
-    UIntMap FontsoundMap;
-
-    /* Default soundfont (accessible as ID 0) */
-    struct ALsoundfont *DefaultSfont;
-
-    /* MIDI synth engine */
-    struct MidiSynth *Synth;
-
     /* HRTF filter tables */
     /* HRTF filter tables */
+    vector_HrtfEntry Hrtf_List;
+    al_string Hrtf_Name;
     const struct Hrtf *Hrtf;
     const struct Hrtf *Hrtf;
+    ALCenum Hrtf_Status;
+    enum HrtfMode Hrtf_Mode;
+    HrtfState Hrtf_State[MAX_OUTPUT_CHANNELS];
+    HrtfParams Hrtf_Params[MAX_OUTPUT_CHANNELS];
+    ALuint Hrtf_Offset;
 
 
     // Stereo-to-binaural filter
     // Stereo-to-binaural filter
     struct bs2b *Bs2b;
     struct bs2b *Bs2b;
-    ALCint       Bs2bLevel;
 
 
     // Device flags
     // Device flags
-    ALuint       Flags;
-
-    ALuint ChannelOffsets[MaxChannels];
+    ALuint Flags;
 
 
-    enum Channel Speaker2Chan[MaxChannels];
-    ALfloat SpeakerAngle[MaxChannels];
-    ALuint  NumChan;
+    enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
+    ChannelConfig AmbiCoeffs[MAX_OUTPUT_CHANNELS];
+    ALfloat AmbiScale; /* Scale for first-order XYZ inputs using AmbCoeffs. */
+    ALuint NumChannels;
 
 
     ALuint64 ClockBase;
     ALuint64 ClockBase;
     ALuint SamplesDone;
     ALuint SamplesDone;
@@ -670,8 +482,8 @@ struct ALCdevice_struct
     alignas(16) ALfloat ResampledData[BUFFERSIZE];
     alignas(16) ALfloat ResampledData[BUFFERSIZE];
     alignas(16) ALfloat FilteredData[BUFFERSIZE];
     alignas(16) ALfloat FilteredData[BUFFERSIZE];
 
 
-    // Dry path buffer mix
-    alignas(16) ALfloat DryBuffer[MaxChannels][BUFFERSIZE];
+    /* Dry path buffer mix. */
+    alignas(16) ALfloat (*DryBuffer)[BUFFERSIZE];
 
 
     /* Running count of the mixer invocations, in 31.1 fixed point. This
     /* Running count of the mixer invocations, in 31.1 fixed point. This
      * actually increments *twice* when mixing, first at the start and then at
      * actually increments *twice* when mixing, first at the start and then at
@@ -702,11 +514,6 @@ struct ALCdevice_struct
 #define DEVICE_CHANNELS_REQUEST                  (1<<2)
 #define DEVICE_CHANNELS_REQUEST                  (1<<2)
 // Sample type was requested by the config file
 // Sample type was requested by the config file
 #define DEVICE_SAMPLE_TYPE_REQUEST               (1<<3)
 #define DEVICE_SAMPLE_TYPE_REQUEST               (1<<3)
-// HRTF was requested by the app
-#define DEVICE_HRTF_REQUEST                      (1<<4)
-
-// Stereo sources cover 120-degree angles around +/-90
-#define DEVICE_WIDE_STEREO                       (1<<16)
 
 
 // Specifies if the DSP is paused at user request
 // Specifies if the DSP is paused at user request
 #define DEVICE_PAUSED                            (1<<30)
 #define DEVICE_PAUSED                            (1<<30)
@@ -714,9 +521,6 @@ struct ALCdevice_struct
 // Specifies if the device is currently running
 // Specifies if the device is currently running
 #define DEVICE_RUNNING                           (1<<31)
 #define DEVICE_RUNNING                           (1<<31)
 
 
-/* Invalid channel offset */
-#define INVALID_OFFSET                           (~0u)
-
 
 
 /* Nanosecond resolution for the device clock time. */
 /* Nanosecond resolution for the device clock time. */
 #define DEVICE_CLOCK_RES  U64(1000000000)
 #define DEVICE_CLOCK_RES  U64(1000000000)
@@ -726,6 +530,8 @@ struct ALCdevice_struct
  * compatibility with pthread_setname_np limitations. */
  * compatibility with pthread_setname_np limitations. */
 #define MIXER_THREAD_NAME "alsoft-mixer"
 #define MIXER_THREAD_NAME "alsoft-mixer"
 
 
+#define RECORD_THREAD_NAME "alsoft-record"
+
 
 
 struct ALCcontext_struct
 struct ALCcontext_struct
 {
 {
@@ -748,9 +554,9 @@ struct ALCcontext_struct
     volatile ALfloat SpeedOfSound;
     volatile ALfloat SpeedOfSound;
     volatile ALenum  DeferUpdates;
     volatile ALenum  DeferUpdates;
 
 
-    struct ALactivesource **ActiveSources;
-    ALsizei ActiveSourceCount;
-    ALsizei MaxActiveSources;
+    struct ALvoice *Voices;
+    ALsizei VoiceCount;
+    ALsizei MaxVoices;
 
 
     VECTOR(struct ALeffectslot*) ActiveAuxSlots;
     VECTOR(struct ALeffectslot*) ActiveAuxSlots;
 
 
@@ -771,11 +577,11 @@ void ALCcontext_DecRef(ALCcontext *context);
 void AppendAllDevicesList(const ALCchar *name);
 void AppendAllDevicesList(const ALCchar *name);
 void AppendCaptureDeviceList(const ALCchar *name);
 void AppendCaptureDeviceList(const ALCchar *name);
 
 
-ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device);
-
 void ALCdevice_Lock(ALCdevice *device);
 void ALCdevice_Lock(ALCdevice *device);
 void ALCdevice_Unlock(ALCdevice *device);
 void ALCdevice_Unlock(ALCdevice *device);
-ALint64 ALCdevice_GetLatency(ALCdevice *device);
+
+void ALCcontext_DeferUpdates(ALCcontext *context);
+void ALCcontext_ProcessUpdates(ALCcontext *context);
 
 
 inline void LockContext(ALCcontext *context)
 inline void LockContext(ALCcontext *context)
 { ALCdevice_Lock(context->Device); }
 { ALCdevice_Lock(context->Device); }
@@ -810,15 +616,35 @@ ALsizei RingBufferSize(RingBuffer *ring);
 void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len);
 void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len);
 void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len);
 void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len);
 
 
+typedef struct ll_ringbuffer ll_ringbuffer_t;
+typedef struct ll_ringbuffer_data {
+    char *buf;
+    size_t len;
+} ll_ringbuffer_data_t;
+ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz);
+void ll_ringbuffer_free(ll_ringbuffer_t *rb);
+void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec);
+void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec);
+size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt);
+size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt);
+void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt);
+size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb);
+int ll_ringbuffer_mlock(ll_ringbuffer_t *rb);
+void ll_ringbuffer_reset(ll_ringbuffer_t *rb);
+size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt);
+void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt);
+size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb);
+
 void ReadALConfig(void);
 void ReadALConfig(void);
 void FreeALConfig(void);
 void FreeALConfig(void);
-int ConfigValueExists(const char *blockName, const char *keyName);
-const char *GetConfigValue(const char *blockName, const char *keyName, const char *def);
-int GetConfigValueBool(const char *blockName, const char *keyName, int def);
-int ConfigValueStr(const char *blockName, const char *keyName, const char **ret);
-int ConfigValueInt(const char *blockName, const char *keyName, int *ret);
-int ConfigValueUInt(const char *blockName, const char *keyName, unsigned int *ret);
-int ConfigValueFloat(const char *blockName, const char *keyName, float *ret);
+int ConfigValueExists(const char *devName, const char *blockName, const char *keyName);
+const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def);
+int GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, int def);
+int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret);
+int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret);
+int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret);
+int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret);
+int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret);
 
 
 void SetRTPriority(void);
 void SetRTPriority(void);
 
 
@@ -828,10 +654,27 @@ void SetDefaultWFXChannelOrder(ALCdevice *device);
 const ALCchar *DevFmtTypeString(enum DevFmtType type) DECL_CONST;
 const ALCchar *DevFmtTypeString(enum DevFmtType type) DECL_CONST;
 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) DECL_CONST;
 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) DECL_CONST;
 
 
+/**
+ * GetChannelIdxByName
+ *
+ * Returns the device's channel index given a channel name (e.g. FrontCenter),
+ * or -1 if it doesn't exist.
+ */
+inline ALint GetChannelIdxByName(const ALCdevice *device, enum Channel chan)
+{
+    ALint i = 0;
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+    {
+        if(device->ChannelName[i] == chan)
+            return i;
+    }
+    return -1;
+}
+
 
 
 extern FILE *LogFile;
 extern FILE *LogFile;
 
 
-#if defined(__GNUC__) && !defined(IN_IDE_PARSER)
+#if defined(__GNUC__) && !defined(_WIN32) && !defined(IN_IDE_PARSER)
 #define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: "MSG, T, __FUNCTION__ , ## __VA_ARGS__)
 #define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: "MSG, T, __FUNCTION__ , ## __VA_ARGS__)
 #else
 #else
 void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4);
 void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4);
@@ -875,14 +718,17 @@ extern ALuint CPUCapFlags;
 enum {
 enum {
     CPU_CAP_SSE    = 1<<0,
     CPU_CAP_SSE    = 1<<0,
     CPU_CAP_SSE2   = 1<<1,
     CPU_CAP_SSE2   = 1<<1,
-    CPU_CAP_SSE4_1 = 1<<2,
-    CPU_CAP_NEON   = 1<<3,
+    CPU_CAP_SSE3   = 1<<2,
+    CPU_CAP_SSE4_1 = 1<<3,
+    CPU_CAP_NEON   = 1<<4,
 };
 };
 
 
 void FillCPUCaps(ALuint capfilter);
 void FillCPUCaps(ALuint capfilter);
 
 
 FILE *OpenDataFile(const char *fname, const char *subdir);
 FILE *OpenDataFile(const char *fname, const char *subdir);
 
 
+vector_al_string SearchDataFiles(const char *match, const char *subdir);
+
 /* Small hack to use a pointer-to-array type as a normal argument type.
 /* Small hack to use a pointer-to-array type as a normal argument type.
  * Shouldn't be used directly. */
  * Shouldn't be used directly. */
 typedef ALfloat ALfloatBUFFERSIZE[BUFFERSIZE];
 typedef ALfloat ALfloatBUFFERSIZE[BUFFERSIZE];

+ 14 - 13
libs/openal-soft/OpenAL32/Include/alSource.h

@@ -11,10 +11,8 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-extern enum Resampler DefaultResampler;
-
-extern const ALsizei ResamplerPadding[ResamplerMax];
-extern const ALsizei ResamplerPrePadding[ResamplerMax];
+struct ALbuffer;
+struct ALsource;
 
 
 
 
 typedef struct ALbufferlistitem {
 typedef struct ALbufferlistitem {
@@ -24,11 +22,11 @@ typedef struct ALbufferlistitem {
 } ALbufferlistitem;
 } ALbufferlistitem;
 
 
 
 
-typedef struct ALactivesource {
-    struct ALsource *Source;
+typedef struct ALvoice {
+    struct ALsource *volatile Source;
 
 
     /** Method to update mixing parameters. */
     /** Method to update mixing parameters. */
-    ALvoid (*Update)(struct ALactivesource *self, const ALCcontext *context);
+    ALvoid (*Update)(struct ALvoice *self, const struct ALsource *source, const ALCcontext *context);
 
 
     /** Current target parameters used for mixing. */
     /** Current target parameters used for mixing. */
     ALint Step;
     ALint Step;
@@ -37,9 +35,13 @@ typedef struct ALactivesource {
 
 
     ALuint Offset; /* Number of output samples mixed since starting. */
     ALuint Offset; /* Number of output samples mixed since starting. */
 
 
+    alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
+
+    BsincState SincState;
+
     DirectParams Direct;
     DirectParams Direct;
     SendParams Send[MAX_SENDS];
     SendParams Send[MAX_SENDS];
-} ALactivesource;
+} ALvoice;
 
 
 
 
 typedef struct ALsource {
 typedef struct ALsource {
@@ -54,9 +56,10 @@ typedef struct ALsource {
     volatile ALfloat   RefDistance;
     volatile ALfloat   RefDistance;
     volatile ALfloat   MaxDistance;
     volatile ALfloat   MaxDistance;
     volatile ALfloat   RollOffFactor;
     volatile ALfloat   RollOffFactor;
-    volatile ALfloat   Position[3];
-    volatile ALfloat   Velocity[3];
-    volatile ALfloat   Orientation[3];
+    aluVector Position;
+    aluVector Velocity;
+    aluVector Direction;
+    volatile ALfloat   Orientation[2][3];
     volatile ALboolean HeadRelative;
     volatile ALboolean HeadRelative;
     volatile ALboolean Looping;
     volatile ALboolean Looping;
     volatile enum DistanceModel DistanceModel;
     volatile enum DistanceModel DistanceModel;
@@ -73,8 +76,6 @@ typedef struct ALsource {
 
 
     volatile ALfloat Radius;
     volatile ALfloat Radius;
 
 
-    enum Resampler Resampler;
-
     /**
     /**
      * Last user-specified offset, and the offset type (bytes, samples, or
      * Last user-specified offset, and the offset type (bytes, samples, or
      * seconds).
      * seconds).

+ 158 - 64
libs/openal-soft/OpenAL32/Include/alu.h

@@ -16,30 +16,111 @@
 
 
 #include "hrtf.h"
 #include "hrtf.h"
 #include "align.h"
 #include "align.h"
+#include "math_defs.h"
 
 
 
 
-#define F_PI    (3.14159265358979323846f)
-#define F_PI_2  (1.57079632679489661923f)
-#define F_2PI   (6.28318530717958647692f)
+#define MAX_PITCH  (255)
 
 
-#ifndef FLT_EPSILON
-#define FLT_EPSILON (1.19209290e-07f)
+/* Maximum number of buffer samples before the current pos needed for resampling. */
+#define MAX_PRE_SAMPLES 12
+
+/* Maximum number of buffer samples after the current pos needed for resampling. */
+#define MAX_POST_SAMPLES 12
+
+
+#ifdef __cplusplus
+extern "C" {
 #endif
 #endif
 
 
-#define DEG2RAD(x)  ((ALfloat)(x) * (F_PI/180.0f))
-#define RAD2DEG(x)  ((ALfloat)(x) * (180.0f/F_PI))
+struct ALsource;
+struct ALvoice;
+
+
+/* The number of distinct scale and phase intervals within the filter table. */
+#define BSINC_SCALE_BITS  4
+#define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
+#define BSINC_PHASE_BITS  4
+#define BSINC_PHASE_COUNT (1<<BSINC_PHASE_BITS)
 
 
+/* Interpolator state.  Kind of a misnomer since the interpolator itself is
+ * stateless.  This just keeps it from having to recompute scale-related
+ * mappings for every sample.
+ */
+typedef struct BsincState {
+    ALfloat sf; /* Scale interpolation factor. */
+    ALuint m;   /* Coefficient count. */
+    ALint l;    /* Left coefficient offset. */
+    struct {
+        const ALfloat *filter;   /* Filter coefficients. */
+        const ALfloat *scDelta;  /* Scale deltas. */
+        const ALfloat *phDelta;  /* Phase deltas. */
+        const ALfloat *spDelta;  /* Scale-phase deltas. */
+    } coeffs[BSINC_PHASE_COUNT];
+} BsincState;
 
 
-#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)
+typedef union aluVector {
+    alignas(16) ALfloat v[4];
+} aluVector;
 
 
+inline void aluVectorSet(aluVector *vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w)
+{
+    vector->v[0] = x;
+    vector->v[1] = y;
+    vector->v[2] = z;
+    vector->v[3] = w;
+}
+
+
+typedef union aluMatrixf {
+    alignas(16) ALfloat m[4][4];
+} aluMatrixf;
+
+inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
+                             ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3)
+{
+    matrix->m[row][0] = m0;
+    matrix->m[row][1] = m1;
+    matrix->m[row][2] = m2;
+    matrix->m[row][3] = m3;
+}
+
+inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
+                                              ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
+                                              ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
+                                              ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33)
+{
+    aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03);
+    aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13);
+    aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23);
+    aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33);
+}
+
+
+typedef union aluMatrixd {
+    alignas(16) ALdouble m[4][4];
+} aluMatrixd;
+
+inline void aluMatrixdSetRow(aluMatrixd *matrix, ALuint row,
+                             ALdouble m0, ALdouble m1, ALdouble m2, ALdouble m3)
+{
+    matrix->m[row][0] = m0;
+    matrix->m[row][1] = m1;
+    matrix->m[row][2] = m2;
+    matrix->m[row][3] = m3;
+}
+
+inline void aluMatrixdSet(aluMatrixd *matrix, ALdouble m00, ALdouble m01, ALdouble m02, ALdouble m03,
+                                              ALdouble m10, ALdouble m11, ALdouble m12, ALdouble m13,
+                                              ALdouble m20, ALdouble m21, ALdouble m22, ALdouble m23,
+                                              ALdouble m30, ALdouble m31, ALdouble m32, ALdouble m33)
+{
+    aluMatrixdSetRow(matrix, 0, m00, m01, m02, m03);
+    aluMatrixdSetRow(matrix, 1, m10, m11, m12, m13);
+    aluMatrixdSetRow(matrix, 2, m20, m21, m22, m23);
+    aluMatrixdSetRow(matrix, 3, m30, m31, m32, m33);
+}
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
 
 enum ActiveFilters {
 enum ActiveFilters {
     AF_None = 0,
     AF_None = 0,
@@ -49,19 +130,6 @@ enum ActiveFilters {
 };
 };
 
 
 
 
-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 {
 typedef struct MixGains {
     ALfloat Current;
     ALfloat Current;
     ALfloat Step;
     ALfloat Step;
@@ -71,11 +139,15 @@ typedef struct MixGains {
 
 
 typedef struct DirectParams {
 typedef struct DirectParams {
     ALfloat (*OutBuffer)[BUFFERSIZE];
     ALfloat (*OutBuffer)[BUFFERSIZE];
+    ALuint OutChannels;
 
 
     /* If not 'moving', gain/coefficients are set directly without fading. */
     /* If not 'moving', gain/coefficients are set directly without fading. */
     ALboolean Moving;
     ALboolean Moving;
     /* Stepping counter for gain/coefficient fading. */
     /* Stepping counter for gain/coefficient fading. */
     ALuint Counter;
     ALuint Counter;
+    /* Last direction (relative to listener) and gain of a moving source. */
+    aluVector LastDir;
+    ALfloat LastGain;
 
 
     struct {
     struct {
         enum ActiveFilters ActiveType;
         enum ActiveFilters ActiveType;
@@ -83,17 +155,11 @@ typedef struct DirectParams {
         ALfilterState HighPass;
         ALfilterState HighPass;
     } Filters[MAX_INPUT_CHANNELS];
     } 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;
+    struct {
+        HrtfParams Params;
+        HrtfState State;
+    } Hrtf[MAX_INPUT_CHANNELS];
+    MixGains Gains[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
 } DirectParams;
 } DirectParams;
 
 
 typedef struct SendParams {
 typedef struct SendParams {
@@ -108,14 +174,15 @@ typedef struct SendParams {
         ALfilterState HighPass;
         ALfilterState HighPass;
     } Filters[MAX_INPUT_CHANNELS];
     } Filters[MAX_INPUT_CHANNELS];
 
 
-    /* Gain control, which applies to all input channels to a single (mono)
+    /* Gain control, which applies to each input channel to a single (mono)
      * output buffer. */
      * output buffer. */
-    MixGains Gain;
+    MixGains Gains[MAX_INPUT_CHANNELS];
 } SendParams;
 } SendParams;
 
 
 
 
-typedef const ALfloat* (*ResamplerFunc)(const ALfloat *src, ALuint frac, ALuint increment,
-                                        ALfloat *restrict dst, ALuint dstlen);
+typedef const ALfloat* (*ResamplerFunc)(const BsincState *state,
+    const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen
+);
 
 
 typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
 typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
                           ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
                           ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
@@ -131,7 +198,7 @@ typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const A
 #define SPEEDOFSOUNDMETRESPERSEC  (343.3f)
 #define SPEEDOFSOUNDMETRESPERSEC  (343.3f)
 #define AIRABSORBGAINHF           (0.99426f) /* -0.05dB */
 #define AIRABSORBGAINHF           (0.99426f) /* -0.05dB */
 
 
-#define FRACTIONBITS (14)
+#define FRACTIONBITS (12)
 #define FRACTIONONE  (1<<FRACTIONBITS)
 #define FRACTIONONE  (1<<FRACTIONBITS)
 #define FRACTIONMASK (FRACTIONONE-1)
 #define FRACTIONMASK (FRACTIONONE-1)
 
 
@@ -179,47 +246,75 @@ inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
 { return minu64(max, maxu64(min, val)); }
 { return minu64(max, maxu64(min, val)); }
 
 
 
 
+union ResamplerCoeffs {
+    ALfloat FIR4[FRACTIONONE][4];
+    ALfloat FIR8[FRACTIONONE][8];
+};
+extern alignas(16) union ResamplerCoeffs ResampleCoeffs;
+
+extern alignas(16) const ALfloat bsincTab[18840];
+
+
 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
 {
 {
     return val1 + (val2-val1)*mu;
     return val1 + (val2-val1)*mu;
 }
 }
-inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat mu)
+inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac)
 {
 {
-    ALfloat mu2 = mu*mu;
-    ALfloat a0 = -0.5f*val0 +  1.5f*val1 + -1.5f*val2 +  0.5f*val3;
-    ALfloat a1 =       val0 + -2.5f*val1 +  2.0f*val2 + -0.5f*val3;
-    ALfloat a2 = -0.5f*val0              +  0.5f*val2;
-    ALfloat a3 =                    val1;
-
-    return a0*mu*mu2 + a1*mu2 + a2*mu + a3;
+    const ALfloat *k = ResampleCoeffs.FIR4[frac];
+    return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3;
+}
+inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac)
+{
+    const ALfloat *k = ResampleCoeffs.FIR8[frac];
+    return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 +
+           k[4]*val4 + k[5]*val5 + k[6]*val6 + k[7]*val7;
 }
 }
 
 
 
 
+void aluInitMixer(void);
+
 ALvoid aluInitPanning(ALCdevice *Device);
 ALvoid aluInitPanning(ALCdevice *Device);
 
 
+/**
+ * ComputeDirectionalGains
+ *
+ * Sets channel gains based on a direction. The direction must be a 3-component
+ * vector no longer than 1 unit.
+ */
+void ComputeDirectionalGains(const ALCdevice *device, const ALfloat dir[3], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+
 /**
 /**
  * ComputeAngleGains
  * ComputeAngleGains
  *
  *
- * Sets channel gains based on a given source's angle and its half-width. The
- * angle and hwidth parameters are in radians.
+ * Sets channel gains based on angle and elevation. The angle and elevation
+ * parameters are in radians, going right and up respectively.
  */
  */
-void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat gains[MaxChannels]);
+void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat elevation, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
 
 
 /**
 /**
- * SetGains
+ * ComputeAmbientGains
  *
  *
- * Helper to set the appropriate channels to the specified gain.
+ * Sets channel gains for ambient, omni-directional sounds.
  */
  */
-inline void SetGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MaxChannels])
-{
-    ComputeAngleGains(device, 0.0f, F_PI, ingain, gains);
-}
+void ComputeAmbientGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
 
 
+/**
+ * ComputeBFormatGains
+ *
+ * Sets channel gains for a given (first-order) B-Format channel. The matrix is
+ * a 1x4 'slice' of the rotation matrix for a given channel used to orient the
+ * coefficients.
+ */
+void ComputeBFormatGains(const ALCdevice *device, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
 
 
-ALvoid CalcSourceParams(struct ALactivesource *src, const ALCcontext *ALContext);
-ALvoid CalcNonAttnSourceParams(struct ALactivesource *src, const ALCcontext *ALContext);
 
 
-ALvoid MixSource(struct ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo);
+ALvoid UpdateContextSources(ALCcontext *context);
+
+ALvoid CalcSourceParams(struct ALvoice *voice, const struct ALsource *source, const ALCcontext *ALContext);
+ALvoid CalcNonAttnSourceParams(struct ALvoice *voice, const struct ALsource *source, const ALCcontext *ALContext);
+
+ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, ALCdevice *Device, ALuint SamplesToDo);
 
 
 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
 ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
 /* Caller must lock the device. */
 /* Caller must lock the device. */
@@ -233,4 +328,3 @@ extern ALfloat ZScale;
 #endif
 #endif
 
 
 #endif
 #endif
-

+ 4 - 7
libs/openal-soft/OpenAL32/Include/bs2b.h

@@ -69,19 +69,16 @@ struct bs2b {
     } last_sample;
     } last_sample;
 };
 };
 
 
-/* Clear buffers and set new coefficients with new crossfeed level value.
+/* Clear buffers and set new coefficients with new crossfeed level and sample
+ * rate values.
  * level - crossfeed level of *LEVEL values.
  * level - crossfeed level of *LEVEL values.
+ * srate - sample rate by Hz.
  */
  */
-void bs2b_set_level(struct bs2b *bs2b, int level);
+void bs2b_set_params(struct bs2b *bs2b, int level, int srate);
 
 
 /* Return current crossfeed level value */
 /* Return current crossfeed level value */
 int bs2b_get_level(struct bs2b *bs2b);
 int bs2b_get_level(struct bs2b *bs2b);
 
 
-/* Clear buffers and set new coefficients with new sample rate value.
- * srate - sample rate by Hz.
- */
-void bs2b_set_srate(struct bs2b *bs2b, int srate);
-
 /* Return current sample rate value */
 /* Return current sample rate value */
 int bs2b_get_srate(struct bs2b *bs2b);
 int bs2b_get_srate(struct bs2b *bs2b);
 
 

+ 2 - 2
libs/openal-soft/OpenAL32/alAuxEffectSlot.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 

+ 41 - 11
libs/openal-soft/OpenAL32/alBuffer.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -151,7 +151,7 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
     if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
     if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE)
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
 
 
-    align = albuf->UnpackAlign;
+    align = ATOMIC_LOAD(&albuf->UnpackAlign);
     if(SanitizeAlignment(srctype, &align) == AL_FALSE)
     if(SanitizeAlignment(srctype, &align) == AL_FALSE)
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
     switch(srctype)
     switch(srctype)
@@ -189,6 +189,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
                 case UserFmtX51: newformat = AL_FORMAT_51CHN32; break;
                 case UserFmtX51: newformat = AL_FORMAT_51CHN32; break;
                 case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
                 case UserFmtX61: newformat = AL_FORMAT_61CHN32; break;
                 case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
                 case UserFmtX71: newformat = AL_FORMAT_71CHN32; break;
+                case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_FLOAT32; break;
+                case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_FLOAT32; break;
             }
             }
             err = LoadData(albuf, freq, newformat, size/framesize*align,
             err = LoadData(albuf, freq, newformat, size/framesize*align,
                            srcchannels, srctype, data, align, AL_TRUE);
                            srcchannels, srctype, data, align, AL_TRUE);
@@ -211,6 +213,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
                 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
                 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
+                case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
+                case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
             }
             }
             err = LoadData(albuf, freq, newformat, size/framesize*align,
             err = LoadData(albuf, freq, newformat, size/framesize*align,
                            srcchannels, srctype, data, align, AL_TRUE);
                            srcchannels, srctype, data, align, AL_TRUE);
@@ -233,6 +237,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
                 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
                 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
+                case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
+                case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
             }
             }
             err = LoadData(albuf, freq, newformat, size/framesize*align,
             err = LoadData(albuf, freq, newformat, size/framesize*align,
                            srcchannels, srctype, data, align, AL_TRUE);
                            srcchannels, srctype, data, align, AL_TRUE);
@@ -255,6 +261,8 @@ AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoi
                 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                 case UserFmtX51: newformat = AL_FORMAT_51CHN16; break;
                 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                 case UserFmtX61: newformat = AL_FORMAT_61CHN16; break;
                 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
                 case UserFmtX71: newformat = AL_FORMAT_71CHN16; break;
+                case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break;
+                case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break;
             }
             }
             err = LoadData(albuf, freq, newformat, size/framesize*align,
             err = LoadData(albuf, freq, newformat, size/framesize*align,
                            srcchannels, srctype, data, align, AL_TRUE);
                            srcchannels, srctype, data, align, AL_TRUE);
@@ -291,7 +299,7 @@ AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, cons
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
 
 
     WriteLock(&albuf->lock);
     WriteLock(&albuf->lock);
-    align = albuf->UnpackAlign;
+    align = ATOMIC_LOAD(&albuf->UnpackAlign);
     if(SanitizeAlignment(srctype, &align) == AL_FALSE)
     if(SanitizeAlignment(srctype, &align) == AL_FALSE)
     {
     {
         WriteUnlock(&albuf->lock);
         WriteUnlock(&albuf->lock);
@@ -368,7 +376,7 @@ AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer,
     if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
     if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE)
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
 
 
-    align = albuf->UnpackAlign;
+    align = ATOMIC_LOAD(&albuf->UnpackAlign);
     if(SanitizeAlignment(type, &align) == AL_FALSE)
     if(SanitizeAlignment(type, &align) == AL_FALSE)
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
     if((samples%align) != 0)
     if((samples%align) != 0)
@@ -404,7 +412,7 @@ AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer,
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
 
 
     WriteLock(&albuf->lock);
     WriteLock(&albuf->lock);
-    align = albuf->UnpackAlign;
+    align = ATOMIC_LOAD(&albuf->UnpackAlign);
     if(SanitizeAlignment(type, &align) == AL_FALSE)
     if(SanitizeAlignment(type, &align) == AL_FALSE)
     {
     {
         WriteUnlock(&albuf->lock);
         WriteUnlock(&albuf->lock);
@@ -457,7 +465,7 @@ AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer,
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
 
 
     ReadLock(&albuf->lock);
     ReadLock(&albuf->lock);
-    align = albuf->PackAlign;
+    align = ATOMIC_LOAD(&albuf->PackAlign);
     if(SanitizeAlignment(type, &align) == AL_FALSE)
     if(SanitizeAlignment(type, &align) == AL_FALSE)
     {
     {
         ReadUnlock(&albuf->lock);
         ReadUnlock(&albuf->lock);
@@ -596,13 +604,13 @@ AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value)
     case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
     case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
         if(!(value >= 0))
         if(!(value >= 0))
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-        ExchangeInt(&albuf->UnpackAlign, value);
+        ATOMIC_STORE(&albuf->UnpackAlign, value);
         break;
         break;
 
 
     case AL_PACK_BLOCK_ALIGNMENT_SOFT:
     case AL_PACK_BLOCK_ALIGNMENT_SOFT:
         if(!(value >= 0))
         if(!(value >= 0))
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-        ExchangeInt(&albuf->PackAlign, value);
+        ATOMIC_STORE(&albuf->PackAlign, value);
         break;
         break;
 
 
     default:
     default:
@@ -834,11 +842,11 @@ AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value
         break;
         break;
 
 
     case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
     case AL_UNPACK_BLOCK_ALIGNMENT_SOFT:
-        *value = albuf->UnpackAlign;
+        *value = ATOMIC_LOAD(&albuf->UnpackAlign);
         break;
         break;
 
 
     case AL_PACK_BLOCK_ALIGNMENT_SOFT:
     case AL_PACK_BLOCK_ALIGNMENT_SOFT:
-        *value = albuf->PackAlign;
+        *value = ATOMIC_LOAD(&albuf->PackAlign);
         break;
         break;
 
 
     default:
     default:
@@ -1045,6 +1053,8 @@ ALuint ChannelsFromUserFmt(enum UserFmtChannels chans)
     case UserFmtX51: return 6;
     case UserFmtX51: return 6;
     case UserFmtX61: return 7;
     case UserFmtX61: return 7;
     case UserFmtX71: return 8;
     case UserFmtX71: return 8;
+    case UserFmtBFormat2D: return 3;
+    case UserFmtBFormat3D: return 4;
     }
     }
     return 0;
     return 0;
 }
 }
@@ -1101,6 +1111,16 @@ static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans,
         { AL_FORMAT_71CHN16,     UserFmtX71, UserFmtShort },
         { AL_FORMAT_71CHN16,     UserFmtX71, UserFmtShort },
         { AL_FORMAT_71CHN32,     UserFmtX71, UserFmtFloat },
         { AL_FORMAT_71CHN32,     UserFmtX71, UserFmtFloat },
         { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
         { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw },
+
+        { AL_FORMAT_BFORMAT2D_8,       UserFmtBFormat2D, UserFmtUByte },
+        { AL_FORMAT_BFORMAT2D_16,      UserFmtBFormat2D, UserFmtShort },
+        { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat },
+        { AL_FORMAT_BFORMAT2D_MULAW,   UserFmtBFormat2D, UserFmtMulaw },
+
+        { AL_FORMAT_BFORMAT3D_8,       UserFmtBFormat3D, UserFmtUByte },
+        { AL_FORMAT_BFORMAT3D_16,      UserFmtBFormat3D, UserFmtShort },
+        { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat },
+        { AL_FORMAT_BFORMAT3D_MULAW,   UserFmtBFormat3D, UserFmtMulaw },
     };
     };
     ALuint i;
     ALuint i;
 
 
@@ -1138,6 +1158,8 @@ ALuint ChannelsFromFmt(enum FmtChannels chans)
     case FmtX51: return 6;
     case FmtX51: return 6;
     case FmtX61: return 7;
     case FmtX61: return 7;
     case FmtX71: return 8;
     case FmtX71: return 8;
+    case FmtBFormat2D: return 3;
+    case FmtBFormat3D: return 4;
     }
     }
     return 0;
     return 0;
 }
 }
@@ -1178,6 +1200,14 @@ static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum Fm
         { AL_7POINT1_8_SOFT,   FmtX71, FmtByte  },
         { AL_7POINT1_8_SOFT,   FmtX71, FmtByte  },
         { AL_7POINT1_16_SOFT,  FmtX71, FmtShort },
         { AL_7POINT1_16_SOFT,  FmtX71, FmtShort },
         { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
         { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat },
+
+        { AL_FORMAT_BFORMAT2D_8,       FmtBFormat2D, FmtByte },
+        { AL_FORMAT_BFORMAT2D_16,      FmtBFormat2D, FmtShort },
+        { AL_FORMAT_BFORMAT2D_FLOAT32, FmtBFormat2D, FmtFloat },
+
+        { AL_FORMAT_BFORMAT3D_8,       FmtBFormat3D, FmtByte },
+        { AL_FORMAT_BFORMAT3D_16,      FmtBFormat3D, FmtShort },
+        { AL_FORMAT_BFORMAT3D_FLOAT32, FmtBFormat3D, FmtFloat },
     };
     };
     ALuint i;
     ALuint i;
 
 

+ 16 - 2
libs/openal-soft/OpenAL32/alEffect.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -402,13 +402,27 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
         effect->Props.Reverb.Diffusion = AL_REVERB_DEFAULT_DIFFUSION;
         effect->Props.Reverb.Diffusion = AL_REVERB_DEFAULT_DIFFUSION;
         effect->Props.Reverb.Gain   = AL_REVERB_DEFAULT_GAIN;
         effect->Props.Reverb.Gain   = AL_REVERB_DEFAULT_GAIN;
         effect->Props.Reverb.GainHF = AL_REVERB_DEFAULT_GAINHF;
         effect->Props.Reverb.GainHF = AL_REVERB_DEFAULT_GAINHF;
+        effect->Props.Reverb.GainLF = 1.0f;
         effect->Props.Reverb.DecayTime    = AL_REVERB_DEFAULT_DECAY_TIME;
         effect->Props.Reverb.DecayTime    = AL_REVERB_DEFAULT_DECAY_TIME;
         effect->Props.Reverb.DecayHFRatio = AL_REVERB_DEFAULT_DECAY_HFRATIO;
         effect->Props.Reverb.DecayHFRatio = AL_REVERB_DEFAULT_DECAY_HFRATIO;
+        effect->Props.Reverb.DecayLFRatio = 1.0f;
         effect->Props.Reverb.ReflectionsGain   = AL_REVERB_DEFAULT_REFLECTIONS_GAIN;
         effect->Props.Reverb.ReflectionsGain   = AL_REVERB_DEFAULT_REFLECTIONS_GAIN;
         effect->Props.Reverb.ReflectionsDelay  = AL_REVERB_DEFAULT_REFLECTIONS_DELAY;
         effect->Props.Reverb.ReflectionsDelay  = AL_REVERB_DEFAULT_REFLECTIONS_DELAY;
+        effect->Props.Reverb.ReflectionsPan[0] = 0.0f;
+        effect->Props.Reverb.ReflectionsPan[1] = 0.0f;
+        effect->Props.Reverb.ReflectionsPan[2] = 0.0f;
         effect->Props.Reverb.LateReverbGain   = AL_REVERB_DEFAULT_LATE_REVERB_GAIN;
         effect->Props.Reverb.LateReverbGain   = AL_REVERB_DEFAULT_LATE_REVERB_GAIN;
         effect->Props.Reverb.LateReverbDelay  = AL_REVERB_DEFAULT_LATE_REVERB_DELAY;
         effect->Props.Reverb.LateReverbDelay  = AL_REVERB_DEFAULT_LATE_REVERB_DELAY;
+        effect->Props.Reverb.LateReverbPan[0] = 0.0f;
+        effect->Props.Reverb.LateReverbPan[1] = 0.0f;
+        effect->Props.Reverb.LateReverbPan[2] = 0.0f;
+        effect->Props.Reverb.EchoTime  = 0.25f;
+        effect->Props.Reverb.EchoDepth = 0.0f;
+        effect->Props.Reverb.ModulationTime  = 0.25f;
+        effect->Props.Reverb.ModulationDepth = 0.0f;
         effect->Props.Reverb.AirAbsorptionGainHF = AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF;
         effect->Props.Reverb.AirAbsorptionGainHF = AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF;
+        effect->Props.Reverb.HFReference = 5000.0f;
+        effect->Props.Reverb.LFReference = 250.0f;
         effect->Props.Reverb.RoomRolloffFactor = AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR;
         effect->Props.Reverb.RoomRolloffFactor = AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR;
         effect->Props.Reverb.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT;
         effect->Props.Reverb.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT;
         SET_VTABLE1(ALreverb, effect);
         SET_VTABLE1(ALreverb, effect);

+ 2 - 2
libs/openal-soft/OpenAL32/alError.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 

+ 2 - 2
libs/openal-soft/OpenAL32/alExtension.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 

+ 57 - 37
libs/openal-soft/OpenAL32/alFilter.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -32,6 +32,8 @@
 extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id);
 extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id);
 extern inline struct ALfilter *RemoveFilter(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_processSingle(ALfilterState *filter, ALfloat sample);
+extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope);
+extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat freq_mult, ALfloat bandwidth);
 
 
 static void InitFilterParams(ALfilter *filter, ALenum type);
 static void InitFilterParams(ALfilter *filter, ALenum type);
 
 
@@ -336,72 +338,72 @@ void ALfilterState_clear(ALfilterState *filter)
     filter->y[1] = 0.0f;
     filter->y[1] = 0.0f;
 }
 }
 
 
-void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat bandwidth)
+void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat rcpQ)
 {
 {
-    ALfloat alpha;
-    ALfloat w0;
+    ALfloat alpha, sqrtgain_alpha_2;
+    ALfloat w0, sin_w0, cos_w0;
 
 
     // Limit gain to -100dB
     // Limit gain to -100dB
     gain = maxf(gain, 0.00001f);
     gain = maxf(gain, 0.00001f);
 
 
-    w0 = F_2PI * freq_mult;
+    w0 = F_TAU * freq_mult;
+    sin_w0 = sinf(w0);
+    cos_w0 = cosf(w0);
+    alpha = sin_w0/2.0f * rcpQ;
 
 
     /* Calculate filter coefficients depending on filter type */
     /* Calculate filter coefficients depending on filter type */
     switch(type)
     switch(type)
     {
     {
         case ALfilterType_HighShelf:
         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;
+            sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
+            filter->b[0] =       gain*((gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
+            filter->b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cos_w0                   );
+            filter->b[2] =       gain*((gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
+            filter->a[0] =             (gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2;
+            filter->a[1] =  2.0f*     ((gain-1.0f) - (gain+1.0f)*cos_w0                   );
+            filter->a[2] =             (gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
             break;
             break;
         case ALfilterType_LowShelf:
         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;
+            sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
+            filter->b[0] =       gain*((gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
+            filter->b[1] =  2.0f*gain*((gain-1.0f) - (gain+1.0f)*cos_w0                   );
+            filter->b[2] =       gain*((gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
+            filter->a[0] =             (gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2;
+            filter->a[1] = -2.0f*     ((gain-1.0f) + (gain+1.0f)*cos_w0                   );
+            filter->a[2] =             (gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
             break;
             break;
         case ALfilterType_Peaking:
         case ALfilterType_Peaking:
-            alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
+            gain = sqrtf(gain);
             filter->b[0] =  1.0f + alpha * gain;
             filter->b[0] =  1.0f + alpha * gain;
-            filter->b[1] = -2.0f * cosf(w0);
+            filter->b[1] = -2.0f * cos_w0;
             filter->b[2] =  1.0f - alpha * gain;
             filter->b[2] =  1.0f - alpha * gain;
             filter->a[0] =  1.0f + alpha / gain;
             filter->a[0] =  1.0f + alpha / gain;
-            filter->a[1] = -2.0f * cosf(w0);
+            filter->a[1] = -2.0f * cos_w0;
             filter->a[2] =  1.0f - alpha / gain;
             filter->a[2] =  1.0f - alpha / gain;
             break;
             break;
 
 
         case ALfilterType_LowPass:
         case ALfilterType_LowPass:
-            alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
-            filter->b[0] = (1.0f - cosf(w0)) / 2.0f;
-            filter->b[1] =  1.0f - cosf(w0);
-            filter->b[2] = (1.0f - cosf(w0)) / 2.0f;
+            filter->b[0] = (1.0f - cos_w0) / 2.0f;
+            filter->b[1] =  1.0f - cos_w0;
+            filter->b[2] = (1.0f - cos_w0) / 2.0f;
             filter->a[0] =  1.0f + alpha;
             filter->a[0] =  1.0f + alpha;
-            filter->a[1] = -2.0f * cosf(w0);
+            filter->a[1] = -2.0f * cos_w0;
             filter->a[2] =  1.0f - alpha;
             filter->a[2] =  1.0f - alpha;
             break;
             break;
         case ALfilterType_HighPass:
         case ALfilterType_HighPass:
-            alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
-            filter->b[0] = (1.0f + cosf(w0)) / 2.0f;
-            filter->b[1] =  1.0f + cosf(w0);
-            filter->b[2] = (1.0f + cosf(w0)) / 2.0f;
-            filter->a[0] =  1.0f + alpha;
-            filter->a[1] = -2.0f * cosf(w0);
-            filter->a[2] =  1.0f - alpha;
+            filter->b[0] =  (1.0f + cos_w0) / 2.0f;
+            filter->b[1] = -(1.0f + cos_w0);
+            filter->b[2] =  (1.0f + cos_w0) / 2.0f;
+            filter->a[0] =   1.0f + alpha;
+            filter->a[1] =  -2.0f * cos_w0;
+            filter->a[2] =   1.0f - alpha;
             break;
             break;
         case ALfilterType_BandPass:
         case ALfilterType_BandPass:
-            alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0));
             filter->b[0] =  alpha;
             filter->b[0] =  alpha;
             filter->b[1] =  0;
             filter->b[1] =  0;
             filter->b[2] = -alpha;
             filter->b[2] = -alpha;
             filter->a[0] =  1.0f + alpha;
             filter->a[0] =  1.0f + alpha;
-            filter->a[1] = -2.0f * cosf(w0);
+            filter->a[1] = -2.0f * cos_w0;
             filter->a[2] =  1.0f - alpha;
             filter->a[2] =  1.0f - alpha;
             break;
             break;
     }
     }
@@ -416,6 +418,24 @@ void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat g
     filter->process = ALfilterState_processC;
     filter->process = ALfilterState_processC;
 }
 }
 
 
+void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *src, ALuint numsamples)
+{
+    if(numsamples >= 2)
+    {
+        filter->x[1] = src[numsamples-2];
+        filter->x[0] = src[numsamples-1];
+        filter->y[1] = src[numsamples-2];
+        filter->y[0] = src[numsamples-1];
+    }
+    else if(numsamples == 1)
+    {
+        filter->x[1] = filter->x[0];
+        filter->x[0] = src[0];
+        filter->y[1] = filter->y[0];
+        filter->y[0] = src[0];
+    }
+}
+
 
 
 static void lp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
 static void lp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
 { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }

+ 16 - 20
libs/openal-soft/OpenAL32/alListener.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -74,9 +74,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
 
         LockContext(context);
         LockContext(context);
-        context->Listener->Position[0] = value1;
-        context->Listener->Position[1] = value2;
-        context->Listener->Position[2] = value3;
+        aluVectorSet(&context->Listener->Position, value1, value2, value3, 1.0f);
         ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         UnlockContext(context);
         UnlockContext(context);
         break;
         break;
@@ -86,9 +84,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
             SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
 
 
         LockContext(context);
         LockContext(context);
-        context->Listener->Velocity[0] = value1;
-        context->Listener->Velocity[1] = value2;
-        context->Listener->Velocity[2] = value3;
+        aluVectorSet(&context->Listener->Velocity, value1, value2, value3, 0.0f);
         ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         ATOMIC_STORE(&context->UpdateSources, AL_TRUE);
         UnlockContext(context);
         UnlockContext(context);
         break;
         break;
@@ -282,17 +278,17 @@ AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat
     {
     {
     case AL_POSITION:
     case AL_POSITION:
         LockContext(context);
         LockContext(context);
-        *value1 = context->Listener->Position[0];
-        *value2 = context->Listener->Position[1];
-        *value3 = context->Listener->Position[2];
+        *value1 = context->Listener->Position.v[0];
+        *value2 = context->Listener->Position.v[1];
+        *value3 = context->Listener->Position.v[2];
         UnlockContext(context);
         UnlockContext(context);
         break;
         break;
 
 
     case AL_VELOCITY:
     case AL_VELOCITY:
         LockContext(context);
         LockContext(context);
-        *value1 = context->Listener->Velocity[0];
-        *value2 = context->Listener->Velocity[1];
-        *value3 = context->Listener->Velocity[2];
+        *value1 = context->Listener->Velocity.v[0];
+        *value2 = context->Listener->Velocity.v[1];
+        *value3 = context->Listener->Velocity.v[2];
         UnlockContext(context);
         UnlockContext(context);
         break;
         break;
 
 
@@ -383,17 +379,17 @@ AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *valu
     {
     {
     case AL_POSITION:
     case AL_POSITION:
         LockContext(context);
         LockContext(context);
-        *value1 = (ALint)context->Listener->Position[0];
-        *value2 = (ALint)context->Listener->Position[1];
-        *value3 = (ALint)context->Listener->Position[2];
+        *value1 = (ALint)context->Listener->Position.v[0];
+        *value2 = (ALint)context->Listener->Position.v[1];
+        *value3 = (ALint)context->Listener->Position.v[2];
         UnlockContext(context);
         UnlockContext(context);
         break;
         break;
 
 
     case AL_VELOCITY:
     case AL_VELOCITY:
         LockContext(context);
         LockContext(context);
-        *value1 = (ALint)context->Listener->Velocity[0];
-        *value2 = (ALint)context->Listener->Velocity[1];
-        *value3 = (ALint)context->Listener->Velocity[2];
+        *value1 = (ALint)context->Listener->Velocity.v[0];
+        *value2 = (ALint)context->Listener->Velocity.v[1];
+        *value3 = (ALint)context->Listener->Velocity.v[2];
         UnlockContext(context);
         UnlockContext(context);
         break;
         break;
 
 

File diff suppressed because it is too large
+ 410 - 345
libs/openal-soft/OpenAL32/alSource.c


+ 5 - 172
libs/openal-soft/OpenAL32/alState.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -28,9 +28,8 @@
 #include "alError.h"
 #include "alError.h"
 #include "alSource.h"
 #include "alSource.h"
 #include "alAuxEffectSlot.h"
 #include "alAuxEffectSlot.h"
-#include "alMidi.h"
 
 
-#include "midi/base.h"
+#include "backends/base.h"
 
 
 
 
 static const ALchar alVendor[] = "OpenAL Community";
 static const ALchar alVendor[] = "OpenAL Community";
@@ -159,7 +158,6 @@ done:
 
 
 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
 {
 {
-    ALCdevice *device;
     ALCcontext *context;
     ALCcontext *context;
     ALdouble value = 0.0;
     ALdouble value = 0.0;
 
 
@@ -188,16 +186,6 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
         value = (ALdouble)context->DeferUpdates;
         value = (ALdouble)context->DeferUpdates;
         break;
         break;
 
 
-    case AL_MIDI_GAIN_SOFT:
-        device = context->Device;
-        value = (ALdouble)MidiSynth_getGain(device->Synth);
-        break;
-
-    case AL_MIDI_STATE_SOFT:
-        device = context->Device;
-        value = (ALdouble)MidiSynth_getState(device->Synth);
-        break;
-
     default:
     default:
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
     }
     }
@@ -210,7 +198,6 @@ done:
 
 
 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
 {
 {
-    ALCdevice *device;
     ALCcontext *context;
     ALCcontext *context;
     ALfloat value = 0.0f;
     ALfloat value = 0.0f;
 
 
@@ -239,16 +226,6 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
         value = (ALfloat)context->DeferUpdates;
         value = (ALfloat)context->DeferUpdates;
         break;
         break;
 
 
-    case AL_MIDI_GAIN_SOFT:
-        device = context->Device;
-        value = MidiSynth_getGain(device->Synth);
-        break;
-
-    case AL_MIDI_STATE_SOFT:
-        device = context->Device;
-        value = (ALfloat)MidiSynth_getState(device->Synth);
-        break;
-
     default:
     default:
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
     }
     }
@@ -262,8 +239,6 @@ done:
 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
 {
 {
     ALCcontext *context;
     ALCcontext *context;
-    ALCdevice *device;
-    MidiSynth *synth;
     ALint value = 0;
     ALint value = 0;
 
 
     context = GetContextRef();
     context = GetContextRef();
@@ -291,17 +266,6 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
         value = (ALint)context->DeferUpdates;
         value = (ALint)context->DeferUpdates;
         break;
         break;
 
 
-    case AL_SOUNDFONTS_SIZE_SOFT:
-        device = context->Device;
-        synth = device->Synth;
-        value = synth->NumSoundfonts;
-        break;
-
-    case AL_MIDI_STATE_SOFT:
-        device = context->Device;
-        value = MidiSynth_getState(device->Synth);
-        break;
-
     default:
     default:
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
     }
     }
@@ -315,8 +279,6 @@ done:
 AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
 AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
 {
 {
     ALCcontext *context;
     ALCcontext *context;
-    ALCdevice *device;
-    MidiSynth *synth;
     ALint64SOFT value = 0;
     ALint64SOFT value = 0;
 
 
     context = GetContextRef();
     context = GetContextRef();
@@ -344,24 +306,6 @@ AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
         value = (ALint64SOFT)context->DeferUpdates;
         value = (ALint64SOFT)context->DeferUpdates;
         break;
         break;
 
 
-    case AL_MIDI_CLOCK_SOFT:
-        device = context->Device;
-        ALCdevice_Lock(device);
-        value = MidiSynth_getTime(device->Synth);
-        ALCdevice_Unlock(device);
-        break;
-
-    case AL_SOUNDFONTS_SIZE_SOFT:
-        device = context->Device;
-        synth = device->Synth;
-        value = (ALint64SOFT)synth->NumSoundfonts;
-        break;
-
-    case AL_MIDI_STATE_SOFT:
-        device = context->Device;
-        value = (ALint64SOFT)MidiSynth_getState(device->Synth);
-        break;
-
     default:
     default:
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
     }
     }
@@ -418,8 +362,6 @@ AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
             case AL_DISTANCE_MODEL:
             case AL_DISTANCE_MODEL:
             case AL_SPEED_OF_SOUND:
             case AL_SPEED_OF_SOUND:
             case AL_DEFERRED_UPDATES_SOFT:
             case AL_DEFERRED_UPDATES_SOFT:
-            case AL_MIDI_GAIN_SOFT:
-            case AL_MIDI_STATE_SOFT:
                 values[0] = alGetDouble(pname);
                 values[0] = alGetDouble(pname);
                 return;
                 return;
         }
         }
@@ -453,8 +395,6 @@ AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
             case AL_DISTANCE_MODEL:
             case AL_DISTANCE_MODEL:
             case AL_SPEED_OF_SOUND:
             case AL_SPEED_OF_SOUND:
             case AL_DEFERRED_UPDATES_SOFT:
             case AL_DEFERRED_UPDATES_SOFT:
-            case AL_MIDI_GAIN_SOFT:
-            case AL_MIDI_STATE_SOFT:
                 values[0] = alGetFloat(pname);
                 values[0] = alGetFloat(pname);
                 return;
                 return;
         }
         }
@@ -478,9 +418,6 @@ done:
 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
 {
 {
     ALCcontext *context;
     ALCcontext *context;
-    ALCdevice *device;
-    MidiSynth *synth;
-    ALsizei i;
 
 
     if(values)
     if(values)
     {
     {
@@ -491,8 +428,6 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
             case AL_DISTANCE_MODEL:
             case AL_DISTANCE_MODEL:
             case AL_SPEED_OF_SOUND:
             case AL_SPEED_OF_SOUND:
             case AL_DEFERRED_UPDATES_SOFT:
             case AL_DEFERRED_UPDATES_SOFT:
-            case AL_SOUNDFONTS_SIZE_SOFT:
-            case AL_MIDI_STATE_SOFT:
                 values[0] = alGetInteger(pname);
                 values[0] = alGetInteger(pname);
                 return;
                 return;
         }
         }
@@ -503,18 +438,6 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
 
 
     switch(pname)
     switch(pname)
     {
     {
-    case AL_SOUNDFONTS_SOFT:
-        device = context->Device;
-        synth = device->Synth;
-        if(synth->NumSoundfonts > 0)
-        {
-            if(!(values))
-                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-            for(i = 0;i < synth->NumSoundfonts;i++)
-                values[i] = synth->Soundfonts[i]->id;
-        }
-        break;
-
     default:
     default:
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
     }
     }
@@ -526,9 +449,6 @@ done:
 AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
 AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
 {
 {
     ALCcontext *context;
     ALCcontext *context;
-    ALCdevice *device;
-    MidiSynth *synth;
-    ALsizei i;
 
 
     if(values)
     if(values)
     {
     {
@@ -539,9 +459,6 @@ AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
             case AL_DISTANCE_MODEL:
             case AL_DISTANCE_MODEL:
             case AL_SPEED_OF_SOUND:
             case AL_SPEED_OF_SOUND:
             case AL_DEFERRED_UPDATES_SOFT:
             case AL_DEFERRED_UPDATES_SOFT:
-            case AL_MIDI_CLOCK_SOFT:
-            case AL_SOUNDFONTS_SIZE_SOFT:
-            case AL_MIDI_STATE_SOFT:
                 values[0] = alGetInteger64SOFT(pname);
                 values[0] = alGetInteger64SOFT(pname);
                 return;
                 return;
         }
         }
@@ -552,18 +469,6 @@ AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
 
 
     switch(pname)
     switch(pname)
     {
     {
-    case AL_SOUNDFONTS_SOFT:
-        device = context->Device;
-        synth = device->Synth;
-        if(synth->NumSoundfonts > 0)
-        {
-            if(!(values))
-                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-            for(i = 0;i < synth->NumSoundfonts;i++)
-                values[i] = (ALint64SOFT)synth->Soundfonts[i]->id;
-        }
-        break;
-
     default:
     default:
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
         SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
     }
     }
@@ -712,54 +617,7 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
     context = GetContextRef();
     context = GetContextRef();
     if(!context) return;
     if(!context) return;
 
 
-    if(!context->DeferUpdates)
-    {
-        ALboolean UpdateSources;
-        ALactivesource **src, **src_end;
-        ALeffectslot **slot, **slot_end;
-        FPUCtl oldMode;
-
-        SetMixerFPUMode(&oldMode);
-
-        LockContext(context);
-        context->DeferUpdates = AL_TRUE;
-
-        /* Make sure all pending updates are performed */
-        UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE);
-
-        src = context->ActiveSources;
-        src_end = src + context->ActiveSourceCount;
-        while(src != src_end)
-        {
-            ALsource *source = (*src)->Source;
-
-            if(source->state != AL_PLAYING && source->state != AL_PAUSED)
-            {
-                ALactivesource *temp = *(--src_end);
-                *src_end = *src;
-                *src = temp;
-                --(context->ActiveSourceCount);
-                continue;
-            }
-
-            if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)
-                (*src)->Update(*src, context);
-
-            src++;
-        }
-
-        slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots);
-        slot_end = VECTOR_ITER_END(context->ActiveAuxSlots);
-        while(slot != slot_end)
-        {
-            if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
-                V((*slot)->EffectState,update)(context->Device, *slot);
-            slot++;
-        }
-
-        UnlockContext(context);
-        RestoreFPUMode(&oldMode);
-    }
+    ALCcontext_DeferUpdates(context);
 
 
     ALCcontext_DecRef(context);
     ALCcontext_DecRef(context);
 }
 }
@@ -771,32 +629,7 @@ AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
     context = GetContextRef();
     context = GetContextRef();
     if(!context) return;
     if(!context) return;
 
 
-    if(ExchangeInt(&context->DeferUpdates, AL_FALSE))
-    {
-        ALsizei pos;
-
-        LockContext(context);
-        LockUIntMapRead(&context->SourceMap);
-        for(pos = 0;pos < context->SourceMap.size;pos++)
-        {
-            ALsource *Source = context->SourceMap.array[pos].value;
-            ALenum new_state;
-
-            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)
-                SetSourceState(Source, context, new_state);
-        }
-        UnlockUIntMapRead(&context->SourceMap);
-        UnlockContext(context);
-    }
+    ALCcontext_ProcessUpdates(context);
 
 
     ALCcontext_DecRef(context);
     ALCcontext_DecRef(context);
 }
 }

+ 28 - 14
libs/openal-soft/OpenAL32/alThunk.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -26,33 +26,33 @@
 #include "alThunk.h"
 #include "alThunk.h"
 
 
 
 
-static ALenum *ThunkArray;
-static ALuint  ThunkArraySize;
-static RWLock  ThunkLock;
+static ATOMIC(ALenum) *ThunkArray;
+static ALuint          ThunkArraySize;
+static RWLock ThunkLock;
 
 
 void ThunkInit(void)
 void ThunkInit(void)
 {
 {
     RWLockInit(&ThunkLock);
     RWLockInit(&ThunkLock);
     ThunkArraySize = 1;
     ThunkArraySize = 1;
-    ThunkArray = calloc(1, ThunkArraySize * sizeof(*ThunkArray));
+    ThunkArray = al_calloc(16, ThunkArraySize * sizeof(*ThunkArray));
 }
 }
 
 
 void ThunkExit(void)
 void ThunkExit(void)
 {
 {
-    free(ThunkArray);
+    al_free(ThunkArray);
     ThunkArray = NULL;
     ThunkArray = NULL;
     ThunkArraySize = 0;
     ThunkArraySize = 0;
 }
 }
 
 
 ALenum NewThunkEntry(ALuint *index)
 ALenum NewThunkEntry(ALuint *index)
 {
 {
-    ALenum *NewList;
+    void *NewList;
     ALuint i;
     ALuint i;
 
 
     ReadLock(&ThunkLock);
     ReadLock(&ThunkLock);
     for(i = 0;i < ThunkArraySize;i++)
     for(i = 0;i < ThunkArraySize;i++)
     {
     {
-        if(ExchangeInt(&ThunkArray[i], AL_TRUE) == AL_FALSE)
+        if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE) == AL_FALSE)
         {
         {
             ReadUnlock(&ThunkLock);
             ReadUnlock(&ThunkLock);
             *index = i+1;
             *index = i+1;
@@ -62,18 +62,32 @@ ALenum NewThunkEntry(ALuint *index)
     ReadUnlock(&ThunkLock);
     ReadUnlock(&ThunkLock);
 
 
     WriteLock(&ThunkLock);
     WriteLock(&ThunkLock);
-    NewList = realloc(ThunkArray, ThunkArraySize*2 * sizeof(*ThunkArray));
+    /* Double-check that there's still no free entries, in case another
+     * invocation just came through and increased the size of the array.
+     */
+    for(;i < ThunkArraySize;i++)
+    {
+        if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE) == AL_FALSE)
+        {
+            WriteUnlock(&ThunkLock);
+            *index = i+1;
+            return AL_NO_ERROR;
+        }
+    }
+
+    NewList = al_calloc(16, ThunkArraySize*2 * sizeof(*ThunkArray));
     if(!NewList)
     if(!NewList)
     {
     {
         WriteUnlock(&ThunkLock);
         WriteUnlock(&ThunkLock);
         ERR("Realloc failed to increase to %u entries!\n", ThunkArraySize*2);
         ERR("Realloc failed to increase to %u entries!\n", ThunkArraySize*2);
         return AL_OUT_OF_MEMORY;
         return AL_OUT_OF_MEMORY;
     }
     }
-    memset(&NewList[ThunkArraySize], 0, ThunkArraySize*sizeof(*ThunkArray));
-    ThunkArraySize *= 2;
+    memcpy(NewList, ThunkArray, ThunkArraySize*sizeof(*ThunkArray));
+    al_free(ThunkArray);
     ThunkArray = NewList;
     ThunkArray = NewList;
+    ThunkArraySize *= 2;
 
 
-    ThunkArray[i] = AL_TRUE;
+    ATOMIC_STORE(&ThunkArray[i], AL_TRUE);
     WriteUnlock(&ThunkLock);
     WriteUnlock(&ThunkLock);
 
 
     *index = i+1;
     *index = i+1;
@@ -84,6 +98,6 @@ void FreeThunkEntry(ALuint index)
 {
 {
     ReadLock(&ThunkLock);
     ReadLock(&ThunkLock);
     if(index > 0 && index <= ThunkArraySize)
     if(index > 0 && index <= ThunkArraySize)
-        ExchangeInt(&ThunkArray[index-1], AL_FALSE);
+        ATOMIC_STORE(&ThunkArray[index-1], AL_FALSE);
     ReadUnlock(&ThunkLock);
     ReadUnlock(&ThunkLock);
 }
 }

+ 6 - 4
libs/openal-soft/README

@@ -45,9 +45,11 @@ Special thanks go to:
 Creative Labs for the original source code this is based off of.
 Creative Labs for the original source code this is based off of.
 
 
 Christopher Fitzgerald for the current reverb effect implementation, and
 Christopher Fitzgerald for the current reverb effect implementation, and
-helping with the low-pass filter.
+helping with the low-pass and HRTF filters.
 
 
-Christian Borss for the 3D panning code the current implementation is heavilly
-based on.
+Christian Borss for the 3D panning code previous versions used as a base.
 
 
-Ben Davis for the idea behind the current click-removal code.
+Ben Davis for the idea behind a previous version of the click-removal code.
+
+Richard Furse for helping with my understanding of Ambisonics that is used by
+the various parts of the library.

+ 12 - 5
libs/openal-soft/XCompile.txt

@@ -1,7 +1,6 @@
-# Cross-compiling requires CMake 2.6 or newer. To use it from build/, call it
-# like this:
-# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt -DHOST=i686-pc-mingw32
-# Where 'i686-pc-mingw32' is the host prefix for your cross-compiler. If you
+# Cross-compiling requires CMake 2.6 or newer. Example:
+# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt -DHOST=i686-w64-mingw32
+# Where 'i686-w64-mingw32' is the host prefix for your cross-compiler. If you
 # already have a toolchain file setup, you may use that instead of this file.
 # already have a toolchain file setup, you may use that instead of this file.
 
 
 # the name of the target operating system
 # the name of the target operating system
@@ -10,12 +9,13 @@ SET(CMAKE_SYSTEM_NAME Windows)
 # which compilers to use for C and C++
 # which compilers to use for C and C++
 SET(CMAKE_C_COMPILER "${HOST}-gcc")
 SET(CMAKE_C_COMPILER "${HOST}-gcc")
 SET(CMAKE_CXX_COMPILER "${HOST}-g++")
 SET(CMAKE_CXX_COMPILER "${HOST}-g++")
+SET(CMAKE_RC_COMPILER "${HOST}-windres")
 
 
 # here is the target environment located
 # here is the target environment located
 SET(CMAKE_FIND_ROOT_PATH "/usr/${HOST}")
 SET(CMAKE_FIND_ROOT_PATH "/usr/${HOST}")
 
 
 # here is where stuff gets installed to
 # here is where stuff gets installed to
-SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}/usr" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
+SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
 
 
 # adjust the default behaviour of the FIND_XXX() commands:
 # adjust the default behaviour of the FIND_XXX() commands:
 # search headers and libraries in the target environment, search 
 # search headers and libraries in the target environment, search 
@@ -28,3 +28,10 @@ set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
 # .pc files (as there seems to be no way to force using ${HOST}-pkg-config)
 # .pc files (as there seems to be no way to force using ${HOST}-pkg-config)
 set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
 set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
 set(ENV{PKG_CONFIG_PATH} "")
 set(ENV{PKG_CONFIG_PATH} "")
+
+# Qt4 tools
+SET(QT_QMAKE_EXECUTABLE ${HOST}-qmake)
+SET(QT_MOC_EXECUTABLE ${HOST}-moc)
+SET(QT_RCC_EXECUTABLE ${HOST}-rcc)
+SET(QT_UIC_EXECUTABLE ${HOST}-uic)
+SET(QT_LRELEASE_EXECUTABLE ${HOST}-lrelease)

+ 123 - 125
libs/openal-soft/alsoftrc.sample

@@ -8,12 +8,18 @@
 # specifying "$HOME/file.ext" would typically result in something like
 # specifying "$HOME/file.ext" would typically result in something like
 # "/home/user/file.ext". To specify an actual "$" character, use "$$".
 # "/home/user/file.ext". To specify an actual "$" character, use "$$".
 #
 #
+# Device-specific values may be specified by including the device name in the
+# block name, with "general" replaced by the device name. That is, general
+# options for the device "Name of Device" would be in the [Name of Device]
+# block, while ALSA options would be in the [alsa/Name of Device] block.
+# Options marked as "(global)" are not influenced by the device.
+#
 # The system-wide settings can be put in /etc/openal/alsoft.conf and user-
 # The system-wide settings can be put in /etc/openal/alsoft.conf and user-
 # specific override settings in $HOME/.alsoftrc.
 # specific override settings in $HOME/.alsoftrc.
 # For Windows, these settings should go into $AppData\alsoft.ini
 # 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
+# Option and block names are case-senstive. 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-
 # possible). Note: options that are left unset may default to app- or system-
 # specified values. These are the current available settings:
 # specified values. These are the current available settings:
 
 
@@ -22,18 +28,27 @@
 ##
 ##
 [general]
 [general]
 
 
-## disable-cpu-exts:
+## disable-cpu-exts: (global)
 #  Disables use of specialized methods that use specific CPU intrinsics.
 #  Disables use of specialized methods that use specific CPU intrinsics.
 #  Certain methods may utilize CPU extensions for improved performance, and
 #  Certain methods may utilize CPU extensions for improved performance, and
 #  this option is useful for preventing some or all of those methods from being
 #  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.
+#  used. The available extensions are: sse, sse2, sse3, sse4.1, and neon.
+#  Specifying 'all' disables use of all such specialized methods.
 #disable-cpu-exts =
 #disable-cpu-exts =
 
 
+## drivers: (global)
+#  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 (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 =
+
 ## channels:
 ## channels:
 #  Sets the output channel configuration. If left unspecified, one will try to
 #  Sets the output channel configuration. If left unspecified, one will try to
 #  be detected from the system, and defaulting to stereo. The available values
 #  be detected from the system, and defaulting to stereo. The available values
-#  are: mono, stereo, quad, surround51, surround61, surround71
+#  are: mono, stereo, quad, surround51, surround51rear, surround61, surround71
 #channels =
 #channels =
 
 
 ## sample-type:
 ## sample-type:
@@ -48,14 +63,40 @@
 #  float32 - 32-bit float
 #  float32 - 32-bit float
 #sample-type = float32
 #sample-type = float32
 
 
-## hrtf:
-#  Enables HRTF filters. These filters provide for better sound spatialization
-#  while using headphones. The default filter will only work when output is
-#  44100hz stereo. While HRTF is active, the cf_level option is disabled.
-#  Default is disabled since stereo speaker output quality may suffer.
-#hrtf = false
+## frequency:
+#  Sets the output frequency. If left unspecified it will try to detect a
+#  default from the system, otherwise it will default to 44100.
+#frequency =
+
+## period_size:
+#  Sets the update period size, in frames. This is the number of frames needed
+#  for each mixing update. Acceptable values range between 64 and 8192.
+#period_size = 1024
+
+## periods:
+#  Sets the number of update periods. Higher values create a larger mix ahead,
+#  which helps protect against skips when the CPU is under load, but increases
+#  the delay between a sound getting mixed and being heard. Acceptable values
+#  range between 2 and 16.
+#periods = 4
+
+## stereo-mode:
+#  Specifies if stereo output is treated as being headphones or speakers. With
+#  headphones, HRTF or crossfeed filters may be used for better audio quality.
+#  Valid settings are auto, speakers, and headphones.
+#stereo-mode = auto
 
 
-## hrtf_tables
+## hrtf:
+#  Controls HRTF processing. These filters provide better spatialization of
+#  sounds while using headphones, but do require a bit more CPU power. The
+#  default filters will only work with 44100hz or 48000hz stereo output. While
+#  HRTF is used, the cf_level option is ignored. Setting this to auto (default)
+#  will allow HRTF to be used when headphones are detected or the app requests
+#  it, while setting true or false will forcefully enable or disable HRTF
+#  respectively.
+#hrtf = auto
+
+## hrtf_tables:
 #  Specifies a comma-separated list of files containing HRTF data sets. The
 #  Specifies a comma-separated list of files containing HRTF data sets. The
 #  format of the files are described in hrtf.txt. The filenames may contain
 #  format of the files are described in hrtf.txt. The filenames may contain
 #  these markers, which will be replaced as needed:
 #  these markers, which will be replaced as needed:
@@ -84,28 +125,18 @@
 #  stereo modes.
 #  stereo modes.
 #cf_level = 0
 #cf_level = 0
 
 
-## wide-stereo:
-#  Specifies that stereo sources are given a width of about 120 degrees on each
-#  channel, centering on -90 (left) and +90 (right), as opposed to being points
-#  placed at -30 (left) and +30 (right). This can be useful for surround-sound
-#  to give stereo sources a more encompassing sound. Note that the sound's
-#  overall volume will be slightly reduced to account for the extra output.
-#wide-stereo = false
-
-## frequency:
-#  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:
+## resampler: (global)
 #  Selects the resampler used when mixing sources. Valid values are:
 #  Selects the resampler used when mixing sources. Valid values are:
 #  point - nearest sample, no interpolation
 #  point - nearest sample, no interpolation
 #  linear - extrapolates samples using a linear slope between samples
 #  linear - extrapolates samples using a linear slope between samples
-#  cubic - extrapolates samples using a Catmull-Rom spline
+#  sinc4 - extrapolates samples using a 4-point Sinc filter
+#  sinc8 - extrapolates samples using an 8-point Sinc filter
+#  bsinc - extrapolates samples using a band-limited Sinc filter (varying
+#          between 12 and 24 points, with anti-aliasing)
 #  Specifying other values will result in using the default (linear).
 #  Specifying other values will result in using the default (linear).
 #resampler = linear
 #resampler = linear
 
 
-## rt-prio:
+## rt-prio: (global)
 #  Sets real-time priority for the mixing thread. Not all drivers may use this
 #  Sets real-time priority for the mixing thread. Not all drivers may use this
 #  (eg. PortAudio) as they already control the priority of the mixing thread.
 #  (eg. PortAudio) as they already control the priority of the mixing thread.
 #  0 and negative values will disable it. Note that this may constitute a
 #  0 and negative values will disable it. Note that this may constitute a
@@ -114,39 +145,11 @@
 #  disabled.
 #  disabled.
 #rt-prio = 0
 #rt-prio = 0
 
 
-## period_size:
-#  Sets the update period size, in frames. This is the number of frames needed
-#  for each mixing update. Acceptable values range between 64 and 8192.
-#period_size = 1024
-
-## periods:
-#  Sets the number of update periods. Higher values create a larger mix ahead,
-#  which helps protect against skips when the CPU is under load, but increases
-#  the delay between a sound getting mixed and being heard. Acceptable values
-#  range between 2 and 16.
-#periods = 4
-
 ## sources:
 ## sources:
 #  Sets the maximum number of allocatable sources. Lower values may help for
 #  Sets the maximum number of allocatable sources. Lower values may help for
 #  systems with apps that try to play more sounds than the CPU can handle.
 #  systems with apps that try to play more sounds than the CPU can handle.
 #sources = 256
 #sources = 256
 
 
-## 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 (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
-#  help for apps that try to use effects which are too CPU intensive for the
-#  system to handle. Available effects are: eaxreverb,reverb,autowah,chorus,
-#  compressor,distortion,echo,equalizer,flanger,modulator,dedicated
-#excludefx =
-
 ## slots:
 ## slots:
 #  Sets the maximum number of Auxiliary Effect Slots an app can create. A slot
 #  Sets the maximum number of Auxiliary Effect Slots an app can create. A slot
 #  can use a non-negligible amount of CPU time if an effect is set on it even
 #  can use a non-negligible amount of CPU time if an effect is set on it even
@@ -160,26 +163,14 @@
 #  possible is 4.
 #  possible is 4.
 #sends =
 #sends =
 
 
-## layout:
-#  Sets the virtual speaker layout. Values are specified in degrees, where 0 is
-#  straight in front, negative goes left, and positive goes right. Unspecified
-#  speakers will remain at their default positions (which are dependant on the
-#  output format). Available speakers are back-left(bl), side-left(sl), front-
-#  left(fl), front-center(fc), front-right(fr), side-right(sr), back-right(br),
-#  and back-center(bc).
-#layout =
-
-## layout_*:
-#  Channel-specific layouts may be specified to override the layout option. The
-#  same speakers as the layout option are available, and the default settings
-#  are shown below.
-#layout_stereo     = fl=-90, fr=90
-#layout_quad       = fl=-45, fr=45, bl=-135, br=135
-#layout_surround51 = fl=-30, fr=30, fc=0, bl=-110, br=110
-#layout_surround61 = fl=-30, fr=30, fc=0, sl=-90, sr=90, bc=180
-#layout_surround71 = fl=-30, fr=30, fc=0, sl=-90, sr=90, bl=-150, br=150
-
-## default-reverb:
+## excludefx: (global)
+#  Sets which effects to exclude, preventing apps from using them. This can
+#  help for apps that try to use effects which are too CPU intensive for the
+#  system to handle. Available effects are: eaxreverb,reverb,chorus,compressor,
+#  distortion,echo,equalizer,flanger,modulator,dedicated
+#excludefx =
+
+## default-reverb: (global)
 #  A reverb preset that applies by default to all sources on send 0
 #  A reverb preset that applies by default to all sources on send 0
 #  (applications that set their own slots on send 0 will override this).
 #  (applications that set their own slots on send 0 will override this).
 #  Available presets are: None, Generic, PaddedCell, Room, Bathroom,
 #  Available presets are: None, Generic, PaddedCell, Room, Bathroom,
@@ -188,54 +179,31 @@
 #  Quarry, Plain, ParkingLot, SewerPipe, Underwater, Drugged, Dizzy, Psychotic.
 #  Quarry, Plain, ParkingLot, SewerPipe, Underwater, Drugged, Dizzy, Psychotic.
 #default-reverb =
 #default-reverb =
 
 
-## trap-alc-error:
+## trap-alc-error: (global)
 #  Generates a SIGTRAP signal when an ALC device error is generated, on systems
 #  Generates a SIGTRAP signal when an ALC device error is generated, on systems
 #  that support it. This helps when debugging, while trying to find the cause
 #  that support it. This helps when debugging, while trying to find the cause
 #  of a device error. On Windows, a breakpoint exception is generated.
 #  of a device error. On Windows, a breakpoint exception is generated.
 #trap-alc-error = false
 #trap-alc-error = false
 
 
-## trap-al-error:
+## trap-al-error: (global)
 #  Generates a SIGTRAP signal when an AL context error is generated, on systems
 #  Generates a SIGTRAP signal when an AL context error is generated, on systems
 #  that support it. This helps when debugging, while trying to find the cause
 #  that support it. This helps when debugging, while trying to find the cause
 #  of a context error. On Windows, a breakpoint exception is generated.
 #  of a context error. On Windows, a breakpoint exception is generated.
 #trap-al-error = false
 #trap-al-error = false
 
 
-##
-## MIDI stuff (EXPERIMENTAL)
-##
-[midi]
-
-## soundfont:
-#  A default soundfont (sf2 format). Used when an app requests the system
-#  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:
-#  Additional attenuation applied to MIDI output, expressed in decibels. This
-#  is used to help keep the mix from clipping, and so must be 0 or less. The
-#  value is logarithmic, so -6 will be about half amplitude, and -12 about
-#  1/4th. The default is roughly -13.9794 (0.2, or 1/5th).
-#volume =
-
 ##
 ##
 ## Reverb effect stuff (includes EAX reverb)
 ## Reverb effect stuff (includes EAX reverb)
 ##
 ##
 [reverb]
 [reverb]
 
 
-## boost:
+## boost: (global)
 #  A global amplification for reverb output, expressed in decibels. The value
 #  A global amplification for reverb output, expressed in decibels. The value
 #  is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will be a
 #  is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will be a
 #  scale of 4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A
 #  scale of 4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A
 #  value of 0 means no change.
 #  value of 0 means no change.
 #boost = 0
 #boost = 0
 
 
-## emulate-eax:
+## emulate-eax: (global)
 #  Allows the standard reverb effect to be used in place of EAX reverb. EAX
 #  Allows the standard reverb effect to be used in place of EAX reverb. EAX
 #  reverb processing is a bit more CPU intensive than standard, so this option
 #  reverb processing is a bit more CPU intensive than standard, so this option
 #  allows a simpler effect to be used at the loss of some quality.
 #  allows a simpler effect to be used at the loss of some quality.
@@ -246,52 +214,59 @@
 ##
 ##
 [pulse]
 [pulse]
 
 
-## spawn-server:
+## spawn-server: (global)
 #  Attempts to autospawn a PulseAudio server whenever needed (initializing the
 #  Attempts to autospawn a PulseAudio server whenever needed (initializing the
 #  backend, enumerating devices, etc). Setting autospawn to false in Pulse's
 #  backend, enumerating devices, etc). Setting autospawn to false in Pulse's
 #  client.conf will still prevent autospawning even if this is set to true.
 #  client.conf will still prevent autospawning even if this is set to true.
 #spawn-server = true
 #spawn-server = true
 
 
-## allow-moves:
+## allow-moves: (global)
 #  Allows PulseAudio to move active streams to different devices. Note that the
 #  Allows PulseAudio to move active streams to different devices. Note that the
 #  device specifier (seen by applications) will not be updated when this
 #  device specifier (seen by applications) will not be updated when this
 #  occurs, and neither will the AL device configuration (sample rate, format,
 #  occurs, and neither will the AL device configuration (sample rate, format,
 #  etc).
 #  etc).
 #allow-moves = false
 #allow-moves = false
 
 
+## fix-rate:
+#  Specifies whether to match the playback stream's sample rate to the device's
+#  sample rate. Enabling this forces OpenAL Soft to mix sources and effects
+#  directly to the actual output rate, avoiding a second resample pass by the
+#  PulseAudio server.
+#fix-rate = false
+
 ##
 ##
 ## ALSA backend stuff
 ## ALSA backend stuff
 ##
 ##
 [alsa]
 [alsa]
 
 
-## device:
+## device: (global)
 #  Sets the device name for the default playback device.
 #  Sets the device name for the default playback device.
 #device = default
 #device = default
 
 
-## device-prefix:
+## device-prefix: (global)
 #  Sets the prefix used by the discovered (non-default) playback devices. This
 #  Sets the prefix used by the discovered (non-default) playback devices. This
 #  will be appended with "CARD=c,DEV=d", where c is the card id and d is the
 #  will be appended with "CARD=c,DEV=d", where c is the card id and d is the
 #  device index for the requested device name.
 #  device index for the requested device name.
 #device-prefix = plughw:
 #device-prefix = plughw:
 
 
-## device-prefix-*:
+## device-prefix-*: (global)
 #  Card- and device-specific prefixes may be used to override the device-prefix
 #  Card- and device-specific prefixes may be used to override the device-prefix
 #  option. The option may specify the card id (eg, device-prefix-NVidia), or
 #  option. The option may specify the card id (eg, device-prefix-NVidia), or
 #  the card id and device index (eg, device-prefix-NVidia-0). The card id is
 #  the card id and device index (eg, device-prefix-NVidia-0). The card id is
 #  case-sensitive.
 #  case-sensitive.
 #device-prefix- =
 #device-prefix- =
 
 
-## capture:
+## capture: (global)
 #  Sets the device name for the default capture device.
 #  Sets the device name for the default capture device.
 #capture = default
 #capture = default
 
 
-## capture-prefix:
+## capture-prefix: (global)
 #  Sets the prefix used by the discovered (non-default) capture devices. This
 #  Sets the prefix used by the discovered (non-default) capture devices. This
 #  will be appended with "CARD=c,DEV=d", where c is the card id and d is the
 #  will be appended with "CARD=c,DEV=d", where c is the card id and d is the
 #  device number for the requested device name.
 #  device number for the requested device name.
 #capture-prefix = plughw:
 #capture-prefix = plughw:
 
 
-## capture-prefix-*:
+## capture-prefix-*: (global)
 #  Card- and device-specific prefixes may be used to override the
 #  Card- and device-specific prefixes may be used to override the
 #  capture-prefix option. The option may specify the card id (eg,
 #  capture-prefix option. The option may specify the card id (eg,
 #  capture-prefix-NVidia), or the card id and device index (eg,
 #  capture-prefix-NVidia), or the card id and device index (eg,
@@ -305,16 +280,23 @@
 #  and anything else will force mmap off.
 #  and anything else will force mmap off.
 #mmap = true
 #mmap = true
 
 
+## allow-resampler:
+#  Specifies whether to allow ALSA's built-in resampler. Enabling this will
+#  allow the playback device to be set to a different sample rate than the
+#  actual output, causing ALSA to apply its own resampling pass after OpenAL
+#  Soft resamples and mixes the sources and effects for output.
+#allow-resampler = false
+
 ##
 ##
 ## OSS backend stuff
 ## OSS backend stuff
 ##
 ##
 [oss]
 [oss]
 
 
-## device:
+## device: (global)
 #  Sets the device name for OSS output.
 #  Sets the device name for OSS output.
 #device = /dev/dsp
 #device = /dev/dsp
 
 
-## capture:
+## capture: (global)
 #  Sets the device name for OSS capture.
 #  Sets the device name for OSS capture.
 #capture = /dev/dsp
 #capture = /dev/dsp
 
 
@@ -323,7 +305,7 @@
 ##
 ##
 [solaris]
 [solaris]
 
 
-## device:
+## device: (global)
 #  Sets the device name for Solaris output.
 #  Sets the device name for Solaris output.
 #device = /dev/audio
 #device = /dev/audio
 
 
@@ -332,13 +314,24 @@
 ##
 ##
 [qsa]
 [qsa]
 
 
-## device:
-#  Sets the device name for the default playback device.
-#device = default
-
-## capture:
-#  Sets the device name for the default capture device.
-#capture = default
+##
+## JACK backend stuff
+##
+[jack]
+
+## spawn-server: (global)
+#  Attempts to autospawn a JACK server whenever needed (initializing the
+#  backend, opening devices, etc).
+#spawn-server = false
+
+## buffer-size:
+#  Sets the update buffer size, in samples, that the backend will keep buffered
+#  to handle the server's real-time processing requests. This value must be a
+#  power of 2, or else it will be rounded up to the next power of 2. If it is
+#  less than JACK's buffer update size, it will be clamped. This option may
+#  be useful in case the server's update size is too small and doesn't give the
+#  mixer time to keep enough audio available for the processing requests.
+#buffer-size = 0
 
 
 ##
 ##
 ## MMDevApi backend stuff
 ## MMDevApi backend stuff
@@ -360,12 +353,12 @@
 ##
 ##
 [port]
 [port]
 
 
-## device:
+## device: (global)
 #  Sets the device index for output. Negative values will use the default as
 #  Sets the device index for output. Negative values will use the default as
 #  given by PortAudio itself.
 #  given by PortAudio itself.
 #device = -1
 #device = -1
 
 
-## capture:
+## capture: (global)
 #  Sets the device index for capture. Negative values will use the default as
 #  Sets the device index for capture. Negative values will use the default as
 #  given by PortAudio itself.
 #  given by PortAudio itself.
 #capture = -1
 #capture = -1
@@ -375,8 +368,13 @@
 ##
 ##
 [wave]
 [wave]
 
 
-## file:
+## file: (global)
 #  Sets the filename of the wave file to write to. An empty name prevents the
 #  Sets the filename of the wave file to write to. An empty name prevents the
 #  backend from opening, even when explicitly requested.
 #  backend from opening, even when explicitly requested.
 #  THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION!
 #  THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION!
 #file =
 #file =
+
+## bformat: (global)
+#  Creates AMB format files using first-order ambisonics instead of a standard
+#  single- or multi-channel .wav file.
+#bformat = false

+ 2 - 2
libs/openal-soft/cmake/CheckFileOffsetBits.cmake

@@ -17,12 +17,12 @@ MACRO(CHECK_FILE_OFFSET_BITS)
   IF(NOT DEFINED _FILE_OFFSET_BITS)
   IF(NOT DEFINED _FILE_OFFSET_BITS)
     MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files")
     MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files")
     TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64
     TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64
-      ${CMAKE_BINARY_DIR}
+      ${CMAKE_CURRENT_BINARY_DIR}
       ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckFileOffsetBits.c
       ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckFileOffsetBits.c
       COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
       COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS})
     IF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
     IF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
       TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64
       TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64
-        ${CMAKE_BINARY_DIR}
+        ${CMAKE_CURRENT_BINARY_DIR}
         ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckFileOffsetBits.c
         ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckFileOffsetBits.c
         COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64)
         COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64)
     ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64)
     ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64)

+ 7 - 7
libs/openal-soft/cmake/CheckSharedFunctionExists.cmake

@@ -58,12 +58,12 @@ MACRO(CHECK_SHARED_FUNCTION_EXISTS SYMBOL FILES LIBRARY LOCATION VARIABLE)
       "${CMAKE_CONFIGURABLE_FILE_CONTENT}\nvoid cmakeRequireSymbol(int dummy,...){(void)dummy;}\nint main()\n{\n  cmakeRequireSymbol(0,&${SYMBOL});\n  return 0;\n}\n")
       "${CMAKE_CONFIGURABLE_FILE_CONTENT}\nvoid cmakeRequireSymbol(int dummy,...){(void)dummy;}\nint main()\n{\n  cmakeRequireSymbol(0,&${SYMBOL});\n  return 0;\n}\n")
 
 
     CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
     CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in"
-      "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" @ONLY)
+      "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" @ONLY)
 
 
     MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY}")
     MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY}")
     TRY_COMPILE(${VARIABLE}
     TRY_COMPILE(${VARIABLE}
-      ${CMAKE_BINARY_DIR}
-      ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c
+      ${CMAKE_CURRENT_BINARY_DIR}
+      ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c
       COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
       COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
       CMAKE_FLAGS 
       CMAKE_FLAGS 
       -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS}
       -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS}
@@ -74,18 +74,18 @@ MACRO(CHECK_SHARED_FUNCTION_EXISTS SYMBOL FILES LIBRARY LOCATION VARIABLE)
     IF(${VARIABLE})
     IF(${VARIABLE})
       MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - found")
       MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - found")
       SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}")
       SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}")
-      FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log 
+      FILE(APPEND ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
         "Determining if the ${SYMBOL} "
         "Determining if the ${SYMBOL} "
         "exist in ${LIBRARY} passed with the following output:\n"
         "exist in ${LIBRARY} passed with the following output:\n"
-        "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n"
+        "${OUTPUT}\nFile ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n"
         "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
         "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
     ELSE(${VARIABLE})
     ELSE(${VARIABLE})
       MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - not found.")
       MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - not found.")
       SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}")
       SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}")
-      FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 
+      FILE(APPEND ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
         "Determining if the ${SYMBOL} "
         "Determining if the ${SYMBOL} "
         "exist in ${LIBRARY} failed with the following output:\n"
         "exist in ${LIBRARY} failed with the following output:\n"
-        "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n"
+        "${OUTPUT}\nFile ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n"
         "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
         "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
     ENDIF(${VARIABLE})
     ENDIF(${VARIABLE})
   ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")
   ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$")

+ 4 - 2
libs/openal-soft/cmake/FindDSound.cmake

@@ -9,14 +9,16 @@
 #
 #
 
 
 find_path(DSOUND_INCLUDE_DIR
 find_path(DSOUND_INCLUDE_DIR
-          PATHS "${DXSDK_DIR}/include"
           NAMES dsound.h
           NAMES dsound.h
+          PATHS "${DXSDK_DIR}"
+          PATH_SUFFIXES include
           DOC "The DirectSound include directory"
           DOC "The DirectSound include directory"
 )
 )
 
 
 find_library(DSOUND_LIBRARY
 find_library(DSOUND_LIBRARY
-             PATHS "${DXSDK_DIR}/lib"
              NAMES dsound
              NAMES dsound
+             PATHS "${DXSDK_DIR}"
+             PATH_SUFFIXES lib lib/x86 lib/x64
              DOC "The DirectSound library"
              DOC "The DirectSound library"
 )
 )
 
 

+ 218 - 169
libs/openal-soft/cmake/FindSDL_sound.cmake

@@ -146,196 +146,219 @@ if(SDL2_FOUND OR SDL_FOUND)
         # The ;-framework Cocoa seems to be confusing CMake once the OS X
         # The ;-framework Cocoa seems to be confusing CMake once the OS X
         # framework support was added. I was told that breaking up the list
         # framework support was added. I was told that breaking up the list
         # would fix the problem.
         # would fix the problem.
-        set(TMP_TRY_LIBS)
+        set(TMP_LIBS "")
         if(SDL2_FOUND)
         if(SDL2_FOUND)
+            set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY})
             foreach(lib ${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY})
             foreach(lib ${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY})
-                set(TMP_TRY_LIBS "${TMP_TRY_LIBS} \"${lib}\"")
+                set(TMP_LIBS "${TMP_LIBS} \"${lib}\"")
             endforeach()
             endforeach()
             set(TMP_INCLUDE_DIRS ${SDL2_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR})
             set(TMP_INCLUDE_DIRS ${SDL2_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR})
         else()
         else()
+            set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY})
             foreach(lib ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY})
             foreach(lib ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY})
-                set(TMP_TRY_LIBS "${TMP_TRY_LIBS} \"${lib}\"")
+                set(TMP_LIBS "${TMP_LIBS} \"${lib}\"")
             endforeach()
             endforeach()
             set(TMP_INCLUDE_DIRS ${SDL_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR})
             set(TMP_INCLUDE_DIRS ${SDL_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR})
         endif()
         endif()
 
 
-        # message("TMP_TRY_LIBS ${TMP_TRY_LIBS}")
+        # Keep trying to build a temp project until we find all missing libs.
+        set(TRY_AGAIN TRUE)
+        WHILE(TRY_AGAIN)
+            set(TRY_AGAIN FALSE)
+            # message("TMP_TRY_LIBS ${TMP_TRY_LIBS}")
 
 
-        # Write the CMakeLists.txt and test project
-        # Weird, this is still sketchy. If I don't quote the variables
-        # in the TARGET_LINK_LIBRARIES, I seem to loose everything
-        # in the SDL2_LIBRARY string after the "-framework".
-        # But if I quote the stuff in INCLUDE_DIRECTORIES, it doesn't work.
-        file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/CMakeLists.txt
-            "cmake_minimum_required(VERSION 2.8)
-            project(DetermineSoundLibs C)
-            include_directories(${TMP_INCLUDE_DIRS})
-            add_executable(DetermineSoundLibs DetermineSoundLibs.c)
-            target_link_libraries(DetermineSoundLibs ${TMP_TRY_LIBS})"
-        )
-        unset(TMP_INCLUDE_DIRS)
-        unset(TMP_TRY_LIBS)
+            # Write the CMakeLists.txt and test project
+            # Weird, this is still sketchy. If I don't quote the variables
+            # in the TARGET_LINK_LIBRARIES, I seem to loose everything
+            # in the SDL2_LIBRARY string after the "-framework".
+            # But if I quote the stuff in INCLUDE_DIRECTORIES, it doesn't work.
+            file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/CMakeLists.txt
+                "cmake_minimum_required(VERSION 2.8)
+                project(DetermineSoundLibs C)
+                include_directories(${TMP_INCLUDE_DIRS})
+                add_executable(DetermineSoundLibs DetermineSoundLibs.c)
+                target_link_libraries(DetermineSoundLibs ${TMP_LIBS})"
+            )
 
 
-        try_compile(
-            MY_RESULT
-            ${PROJECT_BINARY_DIR}/CMakeTmp
-            ${PROJECT_BINARY_DIR}/CMakeTmp
-            DetermineSoundLibs
-            OUTPUT_VARIABLE MY_OUTPUT
-        )
-        # message("${MY_RESULT}")
-        # message(${MY_OUTPUT})
+            try_compile(
+                MY_RESULT
+                ${PROJECT_BINARY_DIR}/CMakeTmp
+                ${PROJECT_BINARY_DIR}/CMakeTmp
+                DetermineSoundLibs
+                OUTPUT_VARIABLE MY_OUTPUT
+            )
+            # message("${MY_RESULT}")
+            # message(${MY_OUTPUT})
 
 
-        if(NOT MY_RESULT)
-            # I expect that MPGLIB, VOC, WAV, AIFF, and SHN are compiled in statically.
-            # I think Timidity is also compiled in statically.
-            # I've never had to explcitly link against Quicktime, so I'll skip that for now.
+            if(NOT MY_RESULT)
+                # I expect that MPGLIB, VOC, WAV, AIFF, and SHN are compiled in statically.
+                # I think Timidity is also compiled in statically.
+                # I've never had to explcitly link against Quicktime, so I'll skip that for now.
 
 
-            set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY})
+                # Find libmath
+                if("${MY_OUTPUT}" MATCHES "cos@@GLIBC")
+                    find_library(MATH_LIBRARY NAMES m)
+                    if(MATH_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MATH_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${MATH_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif(MATH_LIBRARY)
+                endif("${MY_OUTPUT}" MATCHES "cos@@GLIBC")
 
 
-            # Find MikMod
-            if("${MY_OUTPUT}" MATCHES "MikMod_")
-                find_library(MIKMOD_LIBRARY
-                    NAMES libmikmod-coreaudio mikmod
-                    PATHS
-                        ENV MIKMODDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(MIKMOD_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MIKMOD_LIBRARY})
-                endif(MIKMOD_LIBRARY)
-            endif("${MY_OUTPUT}" MATCHES "MikMod_")
+                # Find MikMod
+                if("${MY_OUTPUT}" MATCHES "MikMod_")
+                    find_library(MIKMOD_LIBRARY
+                        NAMES libmikmod-coreaudio mikmod
+                        PATHS
+                            ENV MIKMODDIR
+                            ENV SDLSOUNDDIR
+                            ENV SDLDIR
+                            /sw
+                            /opt/local
+                            /opt/csw
+                            /opt
+                        PATH_SUFFIXES lib
+                    )
+                    if(MIKMOD_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MIKMOD_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${MIKMOD_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif(MIKMOD_LIBRARY)
+                endif("${MY_OUTPUT}" MATCHES "MikMod_")
 
 
-            # Find ModPlug
-            if("${MY_OUTPUT}" MATCHES "MODPLUG_")
-                find_library(MODPLUG_LIBRARY
-                    NAMES modplug
-                    PATHS
-                        ENV MODPLUGDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(MODPLUG_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MODPLUG_LIBRARY})
+                # Find ModPlug
+                if("${MY_OUTPUT}" MATCHES "MODPLUG_")
+                    find_library(MODPLUG_LIBRARY
+                        NAMES modplug
+                        PATHS
+                            ENV MODPLUGDIR
+                            ENV SDLSOUNDDIR
+                            ENV SDLDIR
+                            /sw
+                            /opt/local
+                            /opt/csw
+                            /opt
+                        PATH_SUFFIXES lib
+                    )
+                    if(MODPLUG_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MODPLUG_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${MODPLUG_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif()
                 endif()
                 endif()
-            endif()
 
 
-            # Find Ogg and Vorbis
-            if("${MY_OUTPUT}" MATCHES "ov_")
-                find_library(VORBIS_LIBRARY
-                    NAMES vorbis Vorbis VORBIS
-                    PATHS
-                        ENV VORBISDIR
-                        ENV OGGDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(VORBIS_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBIS_LIBRARY})
-                endif()
-                find_library(OGG_LIBRARY
-                    NAMES ogg Ogg OGG
-                    PATHS
-                        ENV OGGDIR
-                        ENV VORBISDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(OGG_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY})
-                endif()
-            endif()
+                # Find Ogg and Vorbis
+                if("${MY_OUTPUT}" MATCHES "ov_")
+                    find_library(VORBISFILE_LIBRARY
+                        NAMES vorbisfile VorbisFile VORBISFILE
+                        PATHS
+                            ENV VORBISDIR
+                            ENV OGGDIR
+                            ENV SDLSOUNDDIR
+                            ENV SDLDIR
+                            /sw
+                            /opt/local
+                            /opt/csw
+                            /opt
+                        PATH_SUFFIXES lib
+                    )
+                    if(VORBISFILE_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBISFILE_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${VORBISFILE_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif()
 
 
-            # Find SMPEG
-            if("${MY_OUTPUT}" MATCHES "SMPEG_")
-                find_library(SMPEG_LIBRARY
-                    NAMES smpeg SMPEG Smpeg SMpeg
-                    PATHS
-                        ENV SMPEGDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(SMPEG_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SMPEG_LIBRARY})
-                endif()
-            endif()
+                    find_library(VORBIS_LIBRARY
+                        NAMES vorbis Vorbis VORBIS
+                        PATHS
+                            ENV OGGDIR
+                            ENV VORBISDIR
+                            ENV SDLSOUNDDIR
+                            ENV SDLDIR
+                            /sw
+                            /opt/local
+                            /opt/csw
+                            /opt
+                        PATH_SUFFIXES lib
+                    )
+                    if(VORBIS_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBIS_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${VORBIS_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif()
 
 
+                    find_library(OGG_LIBRARY
+                        NAMES ogg Ogg OGG
+                        PATHS
+                            ENV OGGDIR
+                            ENV VORBISDIR
+                            ENV SDLSOUNDDIR
+                            ENV SDLDIR
+                            /sw
+                            /opt/local
+                            /opt/csw
+                            /opt
+                        PATH_SUFFIXES lib
+                    )
+                    if(OGG_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${OGG_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif()
+                endif()
 
 
-            # Find FLAC
-            if("${MY_OUTPUT}" MATCHES "FLAC_")
-                find_library(FLAC_LIBRARY
-                    NAMES flac FLAC
-                    PATHS
-                        ENV FLACDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(FLAC_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${FLAC_LIBRARY})
+                # Find SMPEG
+                if("${MY_OUTPUT}" MATCHES "SMPEG_")
+                    find_library(SMPEG_LIBRARY
+                        NAMES smpeg SMPEG Smpeg SMpeg
+                        PATHS
+                            ENV SMPEGDIR
+                            ENV SDLSOUNDDIR
+                            ENV SDLDIR
+                            /sw
+                            /opt/local
+                            /opt/csw
+                            /opt
+                        PATH_SUFFIXES lib
+                    )
+                    if(SMPEG_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SMPEG_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${SMPEG_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif()
                 endif()
                 endif()
-            endif()
 
 
 
 
-            # Hmmm...Speex seems to depend on Ogg. This might be a problem if
-            # the TRY_COMPILE attempt gets blocked at SPEEX before it can pull
-            # in the Ogg symbols. I'm not sure if I should duplicate the ogg stuff
-            # above for here or if two ogg entries will screw up things.
-            if("${MY_OUTPUT}" MATCHES "speex_")
-                find_library(SPEEX_LIBRARY
-                    NAMES speex SPEEX
-                    PATHS
-                        ENV SPEEXDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(SPEEX_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SPEEX_LIBRARY})
+                # Find FLAC
+                if("${MY_OUTPUT}" MATCHES "FLAC_")
+                    find_library(FLAC_LIBRARY
+                        NAMES flac FLAC
+                        PATHS
+                            ENV FLACDIR
+                            ENV SDLSOUNDDIR
+                            ENV SDLDIR
+                            /sw
+                            /opt/local
+                            /opt/csw
+                            /opt
+                        PATH_SUFFIXES lib
+                    )
+                    if(FLAC_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${FLAC_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${FLAC_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif()
                 endif()
                 endif()
 
 
-                # Find OGG (needed for Speex)
-                # We might have already found Ogg for Vorbis, so skip it if so.
-                if(NOT OGG_LIBRARY)
-                    find_library(OGG_LIBRARY
-                        NAMES ogg Ogg OGG
+
+                # Hmmm...Speex seems to depend on Ogg. This might be a problem if
+                # the TRY_COMPILE attempt gets blocked at SPEEX before it can pull
+                # in the Ogg symbols. I'm not sure if I should duplicate the ogg stuff
+                # above for here or if two ogg entries will screw up things.
+                if("${MY_OUTPUT}" MATCHES "speex_")
+                    find_library(SPEEX_LIBRARY
+                        NAMES speex SPEEX
                         PATHS
                         PATHS
-                            ENV OGGDIR
-                            ENV VORBISDIR
                             ENV SPEEXDIR
                             ENV SPEEXDIR
                             ENV SDLSOUNDDIR
                             ENV SDLSOUNDDIR
                             ENV SDLDIR
                             ENV SDLDIR
@@ -345,16 +368,42 @@ if(SDL2_FOUND OR SDL_FOUND)
                             /opt
                             /opt
                         PATH_SUFFIXES lib
                         PATH_SUFFIXES lib
                     )
                     )
-                    if(OGG_LIBRARY)
-                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY})
+                    if(SPEEX_LIBRARY)
+                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SPEEX_LIBRARY})
+                        set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${SPEEX_LIBRARY}\"")
+                        set(TRY_AGAIN TRUE)
+                    endif()
+
+                    # Find OGG (needed for Speex)
+                    # We might have already found Ogg for Vorbis, so skip it if so.
+                    if(NOT OGG_LIBRARY)
+                        find_library(OGG_LIBRARY
+                            NAMES ogg Ogg OGG
+                            PATHS
+                                ENV OGGDIR
+                                ENV VORBISDIR
+                                ENV SPEEXDIR
+                                ENV SDLSOUNDDIR
+                                ENV SDLDIR
+                                /sw
+                                /opt/local
+                                /opt/csw
+                                /opt
+                            PATH_SUFFIXES lib
+                        )
+                        if(OGG_LIBRARY)
+                            set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY})
+                            set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${OGG_LIBRARY}\"")
+                            set(TRY_AGAIN TRUE)
+                        endif()
                     endif()
                     endif()
                 endif()
                 endif()
             endif()
             endif()
+        ENDWHILE()
+        unset(TMP_INCLUDE_DIRS)
+        unset(TMP_LIBS)
 
 
-            set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARIES_TMP} CACHE INTERNAL "SDL_sound and dependent libraries")
-        else()
-            set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARY} CACHE INTERNAL "SDL_sound and dependent libraries")
-        endif()
+        set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARIES_TMP} CACHE INTERNAL "SDL_sound and dependent libraries")
     endif()
     endif()
 endif()
 endif()
 
 

+ 5 - 5
libs/openal-soft/common/threads.c

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -733,11 +733,11 @@ int altimespec_get(struct timespec *ts, int base)
 #endif
 #endif
 
 
 
 
-void al_nssleep(time_t sec, long nsec)
+void al_nssleep(unsigned long nsec)
 {
 {
     struct timespec ts, rem;
     struct timespec ts, rem;
-    ts.tv_sec = sec;
-    ts.tv_nsec = nsec;
+    ts.tv_sec = nsec / 1000000000ul;
+    ts.tv_nsec = nsec % 1000000000ul;
 
 
     while(althrd_sleep(&ts, &rem) == -1)
     while(althrd_sleep(&ts, &rem) == -1)
         ts = rem;
         ts = rem;

+ 10 - 12
libs/openal-soft/config.h.in

@@ -9,7 +9,7 @@
 /* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but
 /* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but
  * recent versions (at least 4.5.1) do recognize GCC's __restrict. */
  * recent versions (at least 4.5.1) do recognize GCC's __restrict. */
 #define restrict __restrict
 #define restrict __restrict
-#endif 
+#endif
 
 
 /* Define any available alignment declaration */
 /* Define any available alignment declaration */
 #define ALIGN(x) ${ALIGN_DECL}
 #define ALIGN(x) ${ALIGN_DECL}
@@ -26,14 +26,12 @@
 /* Define if we have SSE CPU extensions */
 /* Define if we have SSE CPU extensions */
 #cmakedefine HAVE_SSE
 #cmakedefine HAVE_SSE
 #cmakedefine HAVE_SSE2
 #cmakedefine HAVE_SSE2
+#cmakedefine HAVE_SSE3
 #cmakedefine HAVE_SSE4_1
 #cmakedefine HAVE_SSE4_1
 
 
 /* Define if we have ARM Neon CPU extensions */
 /* Define if we have ARM Neon CPU extensions */
 #cmakedefine HAVE_NEON
 #cmakedefine HAVE_NEON
 
 
-/* Define if we have FluidSynth support */
-#cmakedefine HAVE_FLUIDSYNTH
-
 /* Define if we have the ALSA backend */
 /* Define if we have the ALSA backend */
 #cmakedefine HAVE_ALSA
 #cmakedefine HAVE_ALSA
 
 
@@ -64,6 +62,9 @@
 /* Define if we have the PulseAudio backend */
 /* Define if we have the PulseAudio backend */
 #cmakedefine HAVE_PULSEAUDIO
 #cmakedefine HAVE_PULSEAUDIO
 
 
+/* Define if we have the JACK backend */
+#cmakedefine HAVE_JACK
+
 /* Define if we have the CoreAudio backend */
 /* Define if we have the CoreAudio backend */
 #cmakedefine HAVE_COREAUDIO
 #cmakedefine HAVE_COREAUDIO
 
 
@@ -79,6 +80,9 @@
 /* Define if we have the lrintf function */
 /* Define if we have the lrintf function */
 #cmakedefine HAVE_LRINTF
 #cmakedefine HAVE_LRINTF
 
 
+/* Define if we have the modff function */
+#cmakedefine HAVE_MODFF
+
 /* Define if we have the strtof function */
 /* Define if we have the strtof function */
 #cmakedefine HAVE_STRTOF
 #cmakedefine HAVE_STRTOF
 
 
@@ -136,8 +140,8 @@
 /* Define if we have malloc.h */
 /* Define if we have malloc.h */
 #cmakedefine HAVE_MALLOC_H
 #cmakedefine HAVE_MALLOC_H
 
 
-/* Define if we have ftw.h */
-#cmakedefine HAVE_FTW_H
+/* Define if we have dirent.h */
+#cmakedefine HAVE_DIRENT_H
 
 
 /* Define if we have io.h */
 /* Define if we have io.h */
 #cmakedefine HAVE_IO_H
 #cmakedefine HAVE_IO_H
@@ -181,12 +185,6 @@
 /* Define if we have __control87_2() */
 /* Define if we have __control87_2() */
 #cmakedefine HAVE___CONTROL87_2
 #cmakedefine HAVE___CONTROL87_2
 
 
-/* Define if we have ftw() */
-#cmakedefine HAVE_FTW
-
-/* Define if we have _wfindfirst() */
-#cmakedefine HAVE__WFINDFIRST
-
 /* Define if we have pthread_setschedparam() */
 /* Define if we have pthread_setschedparam() */
 #cmakedefine HAVE_PTHREAD_SETSCHEDPARAM
 #cmakedefine HAVE_PTHREAD_SETSCHEDPARAM
 
 

+ 10 - 0
libs/openal-soft/env-vars.txt

@@ -69,3 +69,13 @@ sound (i.e., sounds that are supposed to be behind you sound like they're in
 front, and vice-versa). Setting this to "true" or "1" will negate the localized
 front, and vice-versa). Setting this to "true" or "1" will negate the localized
 Z coordinate to attempt to fix output for apps that have incorrect front/back
 Z coordinate to attempt to fix output for apps that have incorrect front/back
 panning.
 panning.
+
+__ALSOFT_SUSPEND_CONTEXT
+Due to the OpenAL spec not being very clear about them, behavior of the
+alcSuspendContext and alcProcessContext methods has varied, and because of
+that, previous versions of OpenAL Soft had them no-op. Creative's hardware
+drivers and the Rapture3D driver, however, use these methods to batch changes,
+which some applications make use of to protect against partial updates. In an
+attempt to standardize on that behavior, OpenAL Soft has changed those methods
+accordingly. Setting this to "ignore" restores the previous no-op behavior for
+applications that interact poorly with the new behavior.

+ 64 - 10
libs/openal-soft/examples/alffplay.c

@@ -548,6 +548,7 @@ static int audio_thread(void *userdata)
     MovieState *movState = (MovieState*)userdata;
     MovieState *movState = (MovieState*)userdata;
     uint8_t *samples = NULL;
     uint8_t *samples = NULL;
     ALsizei buffer_len;
     ALsizei buffer_len;
+    ALenum fmt;
 
 
     alGenBuffers(AUDIO_BUFFER_QUEUE_SIZE, movState->audio.buffer);
     alGenBuffers(AUDIO_BUFFER_QUEUE_SIZE, movState->audio.buffer);
     alGenSources(1, &movState->audio.source);
     alGenSources(1, &movState->audio.source);
@@ -557,56 +558,107 @@ static int audio_thread(void *userdata)
 
 
     av_new_packet(&movState->audio.pkt, 0);
     av_new_packet(&movState->audio.pkt, 0);
 
 
-    /* Find a suitable format for OpenAL. Currently does not handle surround
-     * sound (everything non-mono becomes stereo). */
+    /* Find a suitable format for OpenAL. */
+    movState->audio.format = AL_NONE;
     if(movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_U8 ||
     if(movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_U8 ||
        movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_U8P)
        movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_U8P)
     {
     {
         movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_U8;
         movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_U8;
         movState->audio.frame_size = 1;
         movState->audio.frame_size = 1;
+        if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_7POINT1 &&
+           alIsExtensionPresent("AL_EXT_MCFORMATS") &&
+           (fmt=alGetEnumValue("AL_FORMAT_71CHN8")) != AL_NONE && fmt != -1)
+        {
+            movState->audio.dst_ch_layout = movState->audio.st->codec->channel_layout;
+            movState->audio.frame_size *= 8;
+            movState->audio.format = fmt;
+        }
+        if((movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_5POINT1 ||
+            movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) &&
+           alIsExtensionPresent("AL_EXT_MCFORMATS") &&
+           (fmt=alGetEnumValue("AL_FORMAT_51CHN8")) != AL_NONE && fmt != -1)
+        {
+            movState->audio.dst_ch_layout = movState->audio.st->codec->channel_layout;
+            movState->audio.frame_size *= 6;
+            movState->audio.format = fmt;
+        }
         if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
         if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
         {
         {
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
             movState->audio.frame_size *= 1;
             movState->audio.frame_size *= 1;
             movState->audio.format = AL_FORMAT_MONO8;
             movState->audio.format = AL_FORMAT_MONO8;
         }
         }
-        else
+        if(movState->audio.format == AL_NONE)
         {
         {
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
             movState->audio.frame_size *= 2;
             movState->audio.frame_size *= 2;
             movState->audio.format = AL_FORMAT_STEREO8;
             movState->audio.format = AL_FORMAT_STEREO8;
         }
         }
     }
     }
-    else if((movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_FLT ||
-             movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) &&
-            alIsExtensionPresent("AL_EXT_FLOAT32"))
+    if((movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_FLT ||
+        movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) &&
+       alIsExtensionPresent("AL_EXT_FLOAT32"))
     {
     {
         movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_FLT;
         movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_FLT;
         movState->audio.frame_size = 4;
         movState->audio.frame_size = 4;
+        if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_7POINT1 &&
+           alIsExtensionPresent("AL_EXT_MCFORMATS") &&
+           (fmt=alGetEnumValue("AL_FORMAT_71CHN32")) != AL_NONE && fmt != -1)
+        {
+            movState->audio.dst_ch_layout = movState->audio.st->codec->channel_layout;
+            movState->audio.frame_size *= 8;
+            movState->audio.format = fmt;
+        }
+        if((movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_5POINT1 ||
+            movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) &&
+           alIsExtensionPresent("AL_EXT_MCFORMATS") &&
+           (fmt=alGetEnumValue("AL_FORMAT_51CHN32")) != AL_NONE && fmt != -1)
+        {
+            movState->audio.dst_ch_layout = movState->audio.st->codec->channel_layout;
+            movState->audio.frame_size *= 6;
+            movState->audio.format = fmt;
+        }
         if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
         if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
         {
         {
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
             movState->audio.frame_size *= 1;
             movState->audio.frame_size *= 1;
             movState->audio.format = AL_FORMAT_MONO_FLOAT32;
             movState->audio.format = AL_FORMAT_MONO_FLOAT32;
         }
         }
-        else
+        if(movState->audio.format == AL_NONE)
         {
         {
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
             movState->audio.frame_size *= 2;
             movState->audio.frame_size *= 2;
             movState->audio.format = AL_FORMAT_STEREO_FLOAT32;
             movState->audio.format = AL_FORMAT_STEREO_FLOAT32;
         }
         }
     }
     }
-    else
+    if(movState->audio.format == AL_NONE)
     {
     {
         movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_S16;
         movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_S16;
         movState->audio.frame_size = 2;
         movState->audio.frame_size = 2;
+        if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_7POINT1 &&
+           alIsExtensionPresent("AL_EXT_MCFORMATS") &&
+           (fmt=alGetEnumValue("AL_FORMAT_71CHN16")) != AL_NONE && fmt != -1)
+        {
+            movState->audio.dst_ch_layout = movState->audio.st->codec->channel_layout;
+            movState->audio.frame_size *= 8;
+            movState->audio.format = fmt;
+        }
+        if((movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_5POINT1 ||
+            movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_5POINT1_BACK) &&
+           alIsExtensionPresent("AL_EXT_MCFORMATS") &&
+           (fmt=alGetEnumValue("AL_FORMAT_51CHN16")) != AL_NONE && fmt != -1)
+        {
+            movState->audio.dst_ch_layout = movState->audio.st->codec->channel_layout;
+            movState->audio.frame_size *= 6;
+            movState->audio.format = fmt;
+        }
         if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
         if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
         {
         {
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
             movState->audio.frame_size *= 1;
             movState->audio.frame_size *= 1;
             movState->audio.format = AL_FORMAT_MONO16;
             movState->audio.format = AL_FORMAT_MONO16;
         }
         }
-        else
+        if(movState->audio.format == AL_NONE)
         {
         {
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
             movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
             movState->audio.frame_size *= 2;
             movState->audio.frame_size *= 2;
@@ -632,7 +684,9 @@ static int audio_thread(void *userdata)
         movState->audio.dst_ch_layout,
         movState->audio.dst_ch_layout,
         movState->audio.dst_sample_fmt,
         movState->audio.dst_sample_fmt,
         movState->audio.st->codec->sample_rate,
         movState->audio.st->codec->sample_rate,
-        movState->audio.st->codec->channel_layout,
+        movState->audio.st->codec->channel_layout ?
+            movState->audio.st->codec->channel_layout :
+            av_get_default_channel_layout(movState->audio.st->codec->channels),
         movState->audio.st->codec->sample_fmt,
         movState->audio.st->codec->sample_fmt,
         movState->audio.st->codec->sample_rate,
         movState->audio.st->codec->sample_rate,
         0, NULL
         0, NULL

+ 3 - 3
libs/openal-soft/examples/alloopback.c

@@ -65,13 +65,13 @@ void SDLCALL RenderSDLSamples(void *userdata, Uint8 *stream, int len)
  * buffer ID. */
  * buffer ID. */
 static ALuint CreateSineWave(void)
 static ALuint CreateSineWave(void)
 {
 {
-    ALshort data[44100];
+    ALshort data[44100*4];
     ALuint buffer;
     ALuint buffer;
     ALenum err;
     ALenum err;
     ALuint i;
     ALuint i;
 
 
-    for(i = 0;i < 44100;i++)
-        data[i] = (ALshort)(sin(i * 441.0 / 44100.0 * 2.0*M_PI)*32767.0);
+    for(i = 0;i < 44100*4;i++)
+        data[i] = (ALshort)(sin(i/44100.0 * 1000.0 * 2.0*M_PI) * 32767.0);
 
 
     /* Buffer the audio data into a new buffer object. */
     /* Buffer the audio data into a new buffer object. */
     buffer = 0;
     buffer = 0;

+ 1 - 1
libs/openal-soft/hrtf.txt

@@ -14,7 +14,7 @@ sides.
 
 
 The default data set is based on the KEMAR HRTF data provided by MIT, which can
 The default data set is based on the KEMAR HRTF data provided by MIT, which can
 be found at <http://sound.media.mit.edu/resources/KEMAR.html>. It's only
 be found at <http://sound.media.mit.edu/resources/KEMAR.html>. It's only
-available when using 44100hz playback.
+available when using 44100hz or 48000hz playback.
 
 
 
 
 Custom HRTF Data Sets
 Custom HRTF Data Sets

+ 40 - 2
libs/openal-soft/include/AL/alext.h

@@ -13,8 +13,8 @@
  *
  *
  * You should have received a copy of the GNU Library General Public
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
  */
 
 
@@ -393,6 +393,44 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device);
 #endif
 #endif
 #endif
 #endif
 
 
+#ifndef AL_EXT_BFORMAT
+#define AL_EXT_BFORMAT 1
+#define AL_FORMAT_BFORMAT2D_8                    0x20021
+#define AL_FORMAT_BFORMAT2D_16                   0x20022
+#define AL_FORMAT_BFORMAT2D_FLOAT32              0x20023
+#define AL_FORMAT_BFORMAT3D_8                    0x20031
+#define AL_FORMAT_BFORMAT3D_16                   0x20032
+#define AL_FORMAT_BFORMAT3D_FLOAT32              0x20033
+#endif
+
+#ifndef AL_EXT_MULAW_BFORMAT
+#define AL_EXT_MULAW_BFORMAT 1
+#define AL_FORMAT_BFORMAT2D_MULAW                0x10031
+#define AL_FORMAT_BFORMAT3D_MULAW                0x10032
+#endif
+
+#ifndef ALC_SOFT_HRTF
+#define ALC_SOFT_HRTF 1
+#define ALC_HRTF_SOFT                            0x1992
+#define ALC_DONT_CARE_SOFT                       0x0002
+#define ALC_HRTF_STATUS_SOFT                     0x1993
+#define ALC_HRTF_DISABLED_SOFT                   0x0000
+#define ALC_HRTF_ENABLED_SOFT                    0x0001
+#define ALC_HRTF_DENIED_SOFT                     0x0002
+#define ALC_HRTF_REQUIRED_SOFT                   0x0003
+#define ALC_HRTF_HEADPHONES_DETECTED_SOFT        0x0004
+#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT         0x0005
+#define ALC_NUM_HRTF_SPECIFIERS_SOFT             0x1994
+#define ALC_HRTF_SPECIFIER_SOFT                  0x1995
+#define ALC_HRTF_ID_SOFT                         0x1996
+typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index);
+typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs);
+#ifdef AL_ALEXT_PROTOTYPES
+ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index);
+ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs);
+#endif
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 1 - 1
libs/openal-soft/include/AL/efx-presets.h

@@ -345,7 +345,7 @@ typedef struct {
 /* Driving Presets */
 /* Driving Presets */
 
 
 #define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \
 #define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \
-    { 1.0000f, 0.0000f, 3.1623f, 0.5623f, 0.5012f, 2.4200f, 0.8800f, 0.6800f, 0.1995f, 0.0930f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
+    { 1.0000f, 0.0000f, 0.3162f, 0.5623f, 0.5012f, 2.4200f, 0.8800f, 0.6800f, 0.1995f, 0.0930f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x1 }
 
 
 #define EFX_REVERB_PRESET_DRIVING_PITGARAGE \
 #define EFX_REVERB_PRESET_DRIVING_PITGARAGE \
     { 0.4287f, 0.5900f, 0.3162f, 0.7079f, 0.5623f, 1.7200f, 0.9300f, 0.8700f, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }
     { 0.4287f, 0.5900f, 0.3162f, 0.7079f, 0.5623f, 1.7200f, 0.9300f, 0.8700f, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 }

+ 4 - 4
libs/openal-soft/include/align.h

@@ -1,16 +1,16 @@
 #ifndef AL_ALIGN_H
 #ifndef AL_ALIGN_H
 #define AL_ALIGN_H
 #define AL_ALIGN_H
 
 
-#ifdef HAVE_STDALIGN_H
+#if defined(HAVE_STDALIGN_H) && defined(HAVE_C11_ALIGNAS)
 #include <stdalign.h>
 #include <stdalign.h>
 #endif
 #endif
 
 
 #ifndef alignas
 #ifndef alignas
-#ifdef HAVE_C11_ALIGNAS
-#define alignas _Alignas
-#elif defined(IN_IDE_PARSER)
+#if defined(IN_IDE_PARSER)
 /* KDevelop has problems with our align macro, so just use nothing for parsing. */
 /* KDevelop has problems with our align macro, so just use nothing for parsing. */
 #define alignas(x)
 #define alignas(x)
+#elif defined(HAVE_C11_ALIGNAS)
+#define alignas _Alignas
 #else
 #else
 /* NOTE: Our custom ALIGN macro can't take a type name like alignas can. For
 /* NOTE: Our custom ALIGN macro can't take a type name like alignas can. For
  * maximum compatibility, only provide constant integer values to alignas. */
  * maximum compatibility, only provide constant integer values to alignas. */

+ 99 - 78
libs/openal-soft/include/atomic.h

@@ -8,74 +8,81 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-typedef void *volatile XchgPtr;
-
 /* Atomics using C11 */
 /* Atomics using C11 */
 #ifdef HAVE_C11_ATOMIC
 #ifdef HAVE_C11_ATOMIC
 
 
 #include <stdatomic.h>
 #include <stdatomic.h>
 
 
-inline int ExchangeInt(volatile int *ptr, int newval)
-{ return atomic_exchange(ptr, newval); }
-inline void *ExchangePtr(XchgPtr *ptr, void *newval)
-{ return atomic_exchange(ptr, newval); }
+#define almemory_order memory_order
+#define almemory_order_relaxed memory_order_relaxed
+#define almemory_order_consume memory_order_consume
+#define almemory_order_acquire memory_order_acquire
+#define almemory_order_release memory_order_release
+#define almemory_order_acq_rel memory_order_acq_rel
+#define almemory_order_seq_cst memory_order_seq_cst
 
 
+#define ATOMIC(T)  T _Atomic
 
 
-#define ATOMIC(T)  struct { T _Atomic value; }
+#define ATOMIC_INIT(_val, _newval)  atomic_init((_val), (_newval))
+#define ATOMIC_INIT_STATIC(_newval) ATOMIC_VAR_INIT(_newval)
 
 
-#define ATOMIC_INIT(_val, _newval) atomic_init(&(_val)->value, (_newval))
-#define ATOMIC_INIT_STATIC(_newval) {ATOMIC_VAR_INIT(_newval)}
+#define PARAM2(f, a, b, ...)           (f((a), (b)))
+#define PARAM3(f, a, b, c, ...)        (f((a), (b), (c)))
+#define PARAM5(f, a, b, c, d, e, ...)  (f((a), (b), (c), (d), (e)))
 
 
-#define ATOMIC_LOAD(_val)            atomic_load(&(_val)->value)
-#define ATOMIC_STORE(_val, _newval)  atomic_store(&(_val)->value, (_newval))
+#define ATOMIC_LOAD(...)   PARAM2(atomic_load_explicit, __VA_ARGS__, memory_order_seq_cst)
+#define ATOMIC_STORE(...)  PARAM3(atomic_store_explicit, __VA_ARGS__, memory_order_seq_cst)
 
 
-#define ATOMIC_ADD(T, _val, _incr) atomic_fetch_add(&(_val)->value, (_incr))
-#define ATOMIC_SUB(T, _val, _decr) atomic_fetch_sub(&(_val)->value, (_decr))
+#define ATOMIC_ADD(T, ...) PARAM3(atomic_fetch_add_explicit, __VA_ARGS__, memory_order_seq_cst)
+#define ATOMIC_SUB(T, ...) PARAM3(atomic_fetch_sub_explicit, __VA_ARGS__, memory_order_seq_cst)
 
 
-#define ATOMIC_EXCHANGE(T, _val, _newval) atomic_exchange(&(_val)->value, (_newval))
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval)             \
-    atomic_compare_exchange_strong(&(_val)->value, (_oldval), (_newval))
-#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, _val, _oldval, _newval)               \
-    atomic_compare_exchange_weak(&(_val)->value, (_oldval), (_newval))
+#define ATOMIC_EXCHANGE(T, ...) PARAM3(atomic_exchange_explicit, __VA_ARGS__, memory_order_seq_cst)
+#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, ...)                                \
+    PARAM5(atomic_compare_exchange_strong_explicit, __VA_ARGS__, memory_order_seq_cst, memory_order_seq_cst)
+#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, ...)                                  \
+    PARAM5(atomic_compare_exchange_weak_explicit, __VA_ARGS__, memory_order_seq_cst, memory_order_seq_cst)
 
 
 /* Atomics using GCC intrinsics */
 /* Atomics using GCC intrinsics */
 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__QNXNTO__)
 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__QNXNTO__)
 
 
-inline int ExchangeInt(volatile int *ptr, int newval)
-{ return __sync_lock_test_and_set(ptr, newval); }
-inline void *ExchangePtr(XchgPtr *ptr, void *newval)
-{ return __sync_lock_test_and_set(ptr, newval); }
-
+enum almemory_order {
+    almemory_order_relaxed,
+    almemory_order_consume,
+    almemory_order_acquire,
+    almemory_order_release,
+    almemory_order_acq_rel,
+    almemory_order_seq_cst
+};
 
 
 #define ATOMIC(T)  struct { T volatile value; }
 #define ATOMIC(T)  struct { T volatile value; }
 
 
 #define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
 #define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
 #define ATOMIC_INIT_STATIC(_newval) {(_newval)}
 #define ATOMIC_INIT_STATIC(_newval) {(_newval)}
 
 
-#define ATOMIC_LOAD(_val)  __extension__({      \
+#define ATOMIC_LOAD(_val, ...)  __extension__({ \
     __typeof((_val)->value) _r = (_val)->value; \
     __typeof((_val)->value) _r = (_val)->value; \
     __asm__ __volatile__("" ::: "memory");      \
     __asm__ __volatile__("" ::: "memory");      \
     _r;                                         \
     _r;                                         \
 })
 })
-#define ATOMIC_STORE(_val, _newval)  do {  \
-    __asm__ __volatile__("" ::: "memory"); \
-    (_val)->value = (_newval);             \
+#define ATOMIC_STORE(_val, _newval, ...)  do { \
+    __asm__ __volatile__("" ::: "memory");     \
+    (_val)->value = (_newval);                 \
 } while(0)
 } while(0)
 
 
-#define ATOMIC_ADD(T, _val, _incr)  __extension__({                           \
+#define ATOMIC_ADD(T, _val, _incr, ...)  __extension__({                      \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     __sync_fetch_and_add(&(_val)->value, (_incr));                            \
     __sync_fetch_and_add(&(_val)->value, (_incr));                            \
 })
 })
-#define ATOMIC_SUB(T, _val, _decr)  __extension__({                           \
+#define ATOMIC_SUB(T, _val, _decr, ...)  __extension__({                      \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     __sync_fetch_and_sub(&(_val)->value, (_decr));                            \
     __sync_fetch_and_sub(&(_val)->value, (_decr));                            \
 })
 })
 
 
-#define ATOMIC_EXCHANGE(T, _val, _newval)  __extension__({                    \
+#define ATOMIC_EXCHANGE(T, _val, _newval, ...)  __extension__({               \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     __sync_lock_test_and_set(&(_val)->value, (_newval));                      \
     __sync_lock_test_and_set(&(_val)->value, (_newval));                      \
 })
 })
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) __extension__({ \
+#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, ...) __extension__({ \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     T _o = *(_oldval);                                                        \
     T _o = *(_oldval);                                                        \
     *(_oldval) = __sync_val_compare_and_swap(&(_val)->value, _o, (_newval));  \
     *(_oldval) = __sync_val_compare_and_swap(&(_val)->value, _o, (_newval));  \
@@ -112,41 +119,38 @@ inline void *ExchangePtr(XchgPtr *ptr, void *newval)
 )
 )
 
 
 
 
-inline int ExchangeInt(volatile int *dest, int newval)
-{ int ret; WRAP_XCHG("l", ret, dest, newval); return ret; }
-
-#ifdef __i386__
-inline void *ExchangePtr(XchgPtr *dest, void *newval)
-{ void *ret; WRAP_XCHG("l", ret, dest, newval); return ret; }
-#else
-inline void *ExchangePtr(XchgPtr *dest, void *newval)
-{ void *ret; WRAP_XCHG("q", ret, dest, newval); return ret; }
-#endif
-
+enum almemory_order {
+    almemory_order_relaxed,
+    almemory_order_consume,
+    almemory_order_acquire,
+    almemory_order_release,
+    almemory_order_acq_rel,
+    almemory_order_seq_cst
+};
 
 
 #define ATOMIC(T)  struct { T volatile value; }
 #define ATOMIC(T)  struct { T volatile value; }
 
 
 #define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
 #define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
 #define ATOMIC_INIT_STATIC(_newval) {(_newval)}
 #define ATOMIC_INIT_STATIC(_newval) {(_newval)}
 
 
-#define ATOMIC_LOAD(_val)  __extension__({      \
+#define ATOMIC_LOAD(_val, ...)  __extension__({ \
     __typeof((_val)->value) _r = (_val)->value; \
     __typeof((_val)->value) _r = (_val)->value; \
     __asm__ __volatile__("" ::: "memory");      \
     __asm__ __volatile__("" ::: "memory");      \
     _r;                                         \
     _r;                                         \
 })
 })
-#define ATOMIC_STORE(_val, _newval)  do {  \
-    __asm__ __volatile__("" ::: "memory"); \
-    (_val)->value = (_newval);             \
+#define ATOMIC_STORE(_val, _newval, ...)  do { \
+    __asm__ __volatile__("" ::: "memory");     \
+    (_val)->value = (_newval);                 \
 } while(0)
 } while(0)
 
 
-#define ATOMIC_ADD(T, _val, _incr)  __extension__({                           \
+#define ATOMIC_ADD(T, _val, _incr, ...)  __extension__({                      \
     static_assert(sizeof(T)==4, "Type "#T" has incorrect size!");             \
     static_assert(sizeof(T)==4, "Type "#T" has incorrect size!");             \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     T _r;                                                                     \
     T _r;                                                                     \
     WRAP_ADD(_r, &(_val)->value, (T)(_incr));                                 \
     WRAP_ADD(_r, &(_val)->value, (T)(_incr));                                 \
     _r;                                                                       \
     _r;                                                                       \
 })
 })
-#define ATOMIC_SUB(T, _val, _decr)  __extension__({                           \
+#define ATOMIC_SUB(T, _val, _decr, ...)  __extension__({                      \
     static_assert(sizeof(T)==4, "Type "#T" has incorrect size!");             \
     static_assert(sizeof(T)==4, "Type "#T" has incorrect size!");             \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     T _r;                                                                     \
     T _r;                                                                     \
@@ -154,7 +158,7 @@ inline void *ExchangePtr(XchgPtr *dest, void *newval)
     _r;                                                                       \
     _r;                                                                       \
 })
 })
 
 
-#define ATOMIC_EXCHANGE(T, _val, _newval)  __extension__({                    \
+#define ATOMIC_EXCHANGE(T, _val, _newval, ...)  __extension__({               \
     static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     T _r;                                                                     \
     T _r;                                                                     \
@@ -162,7 +166,7 @@ inline void *ExchangePtr(XchgPtr *dest, void *newval)
     else if(sizeof(T) == 8) WRAP_XCHG("q", _r, &(_val)->value, (T)(_newval)); \
     else if(sizeof(T) == 8) WRAP_XCHG("q", _r, &(_val)->value, (T)(_newval)); \
     _r;                                                                       \
     _r;                                                                       \
 })
 })
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) __extension__({ \
+#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, ...) __extension__({ \
     static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
     T _old = *(_oldval);                                                      \
     T _old = *(_oldval);                                                      \
@@ -222,42 +226,40 @@ inline bool CompareAndSwap64(volatile LONGLONG *dest, LONGLONG newval, LONGLONG
 #define WRAP_XCHG(T, _func, _ptr, _newval)  ((T(*)(T volatile*,T))_func)((_ptr), (_newval))
 #define WRAP_XCHG(T, _func, _ptr, _newval)  ((T(*)(T volatile*,T))_func)((_ptr), (_newval))
 #define WRAP_CMPXCHG(T, _func, _ptr, _newval, _oldval) ((bool(*)(T volatile*,T,T*))_func)((_ptr), (_newval), (_oldval))
 #define WRAP_CMPXCHG(T, _func, _ptr, _newval, _oldval) ((bool(*)(T volatile*,T,T*))_func)((_ptr), (_newval), (_oldval))
 
 
-inline int ExchangeInt(volatile int *ptr, int newval)
-{ return WRAP_XCHG(int,AtomicSwap32,ptr,newval); }
-
-#ifdef _WIN64
-inline void *ExchangePtr(XchgPtr *ptr, void *newval)
-{ return WRAP_XCHG(void*,AtomicSwap64,ptr,newval); }
-#else
-inline void *ExchangePtr(XchgPtr *ptr, void *newval)
-{ return WRAP_XCHG(void*,AtomicSwap32,ptr,newval); }
-#endif
 
 
+enum almemory_order {
+    almemory_order_relaxed,
+    almemory_order_consume,
+    almemory_order_acquire,
+    almemory_order_release,
+    almemory_order_acq_rel,
+    almemory_order_seq_cst
+};
 
 
 #define ATOMIC(T)  struct { T volatile value; }
 #define ATOMIC(T)  struct { T volatile value; }
 
 
 #define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
 #define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
 #define ATOMIC_INIT_STATIC(_newval) {(_newval)}
 #define ATOMIC_INIT_STATIC(_newval) {(_newval)}
 
 
-#define ATOMIC_LOAD(_val)  ((_val)->value)
-#define ATOMIC_STORE(_val, _newval)  do {  \
-    (_val)->value = (_newval);             \
+#define ATOMIC_LOAD(_val, ...)  ((_val)->value)
+#define ATOMIC_STORE(_val, _newval, ...)  do {  \
+    (_val)->value = (_newval);                  \
 } while(0)
 } while(0)
 
 
 int _al_invalid_atomic_size(); /* not defined */
 int _al_invalid_atomic_size(); /* not defined */
 
 
-#define ATOMIC_ADD(T, _val, _incr)                                            \
+#define ATOMIC_ADD(T, _val, _incr, ...)                                       \
     ((sizeof(T)==4) ? WRAP_ADDSUB(T, AtomicAdd32, &(_val)->value, (_incr)) :  \
     ((sizeof(T)==4) ? WRAP_ADDSUB(T, AtomicAdd32, &(_val)->value, (_incr)) :  \
      (T)_al_invalid_atomic_size())
      (T)_al_invalid_atomic_size())
-#define ATOMIC_SUB(T, _val, _decr)                                            \
+#define ATOMIC_SUB(T, _val, _decr, ...)                                       \
     ((sizeof(T)==4) ? WRAP_ADDSUB(T, AtomicSub32, &(_val)->value, (_decr)) :  \
     ((sizeof(T)==4) ? WRAP_ADDSUB(T, AtomicSub32, &(_val)->value, (_decr)) :  \
      (T)_al_invalid_atomic_size())
      (T)_al_invalid_atomic_size())
 
 
-#define ATOMIC_EXCHANGE(T, _val, _newval)                                     \
+#define ATOMIC_EXCHANGE(T, _val, _newval, ...)                                \
     ((sizeof(T)==4) ? WRAP_XCHG(T, AtomicSwap32, &(_val)->value, (_newval)) : \
     ((sizeof(T)==4) ? WRAP_XCHG(T, AtomicSwap32, &(_val)->value, (_newval)) : \
      (sizeof(T)==8) ? WRAP_XCHG(T, AtomicSwap64, &(_val)->value, (_newval)) : \
      (sizeof(T)==8) ? WRAP_XCHG(T, AtomicSwap64, &(_val)->value, (_newval)) : \
      (T)_al_invalid_atomic_size())
      (T)_al_invalid_atomic_size())
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval)             \
+#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, ...)        \
     ((sizeof(T)==4) ? WRAP_CMPXCHG(T, CompareAndSwap32, &(_val)->value, (_newval), (_oldval)) : \
     ((sizeof(T)==4) ? WRAP_CMPXCHG(T, CompareAndSwap32, &(_val)->value, (_newval), (_oldval)) : \
      (sizeof(T)==8) ? WRAP_CMPXCHG(T, CompareAndSwap64, &(_val)->value, (_newval), (_oldval)) : \
      (sizeof(T)==8) ? WRAP_CMPXCHG(T, CompareAndSwap64, &(_val)->value, (_newval), (_oldval)) : \
      (bool)_al_invalid_atomic_size())
      (bool)_al_invalid_atomic_size())
@@ -273,26 +275,22 @@ int _al_invalid_atomic_size(); /* not defined */
 #define ATOMIC_LOAD_UNSAFE(_val)  (0)
 #define ATOMIC_LOAD_UNSAFE(_val)  (0)
 #define ATOMIC_STORE_UNSAFE(_val, _newval)  ((void)0)
 #define ATOMIC_STORE_UNSAFE(_val, _newval)  ((void)0)
 
 
-#define ATOMIC_LOAD(_val)  (0)
-#define ATOMIC_STORE(_val, _newval)  ((void)0)
+#define ATOMIC_LOAD(_val, ...)  (0)
+#define ATOMIC_STORE(_val, _newval, ...)  ((void)0)
 
 
-#define ATOMIC_ADD(T, _val, _incr)  (0)
-#define ATOMIC_SUB(T, _val, _decr)  (0)
+#define ATOMIC_ADD(T, _val, _incr, ...)  (0)
+#define ATOMIC_SUB(T, _val, _decr, ...)  (0)
 
 
-#define ATOMIC_EXCHANGE(T, _val, _newval)  (0)
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) (0)
+#define ATOMIC_EXCHANGE(T, _val, _newval, ...)  (0)
+#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval, ...) (0)
 #endif
 #endif
 
 
 /* If no weak cmpxchg is provided (not all systems will have one), substitute a
 /* If no weak cmpxchg is provided (not all systems will have one), substitute a
  * strong cmpxchg. */
  * strong cmpxchg. */
 #ifndef ATOMIC_COMPARE_EXCHANGE_WEAK
 #ifndef ATOMIC_COMPARE_EXCHANGE_WEAK
-#define ATOMIC_COMPARE_EXCHANGE_WEAK(a, b, c, d) ATOMIC_COMPARE_EXCHANGE_STRONG(a, b, c, d)
+#define ATOMIC_COMPARE_EXCHANGE_WEAK ATOMIC_COMPARE_EXCHANGE_STRONG
 #endif
 #endif
 
 
-/* This is *NOT* atomic, but is a handy utility macro to compare-and-swap non-
- * atomic variables. */
-#define COMPARE_EXCHANGE(_val, _oldval, _newval)  ((*(_val) == *(_oldval)) ? ((*(_val)=(_newval)),true) : ((*(_oldval)=*(_val)),false))
-
 
 
 typedef unsigned int uint;
 typedef unsigned int uint;
 typedef ATOMIC(uint) RefCount;
 typedef ATOMIC(uint) RefCount;
@@ -306,6 +304,29 @@ inline uint IncrementRef(RefCount *ptr)
 inline uint DecrementRef(RefCount *ptr)
 inline uint DecrementRef(RefCount *ptr)
 { return ATOMIC_SUB(uint, ptr, 1)-1; }
 { return ATOMIC_SUB(uint, ptr, 1)-1; }
 
 
+
+/* NOTE: Not atomic! */
+inline int ExchangeInt(volatile int *ptr, int newval)
+{
+    int old = *ptr;
+    *ptr = newval;
+    return old;
+}
+
+typedef void *volatile XchgPtr;
+/* NOTE: Not atomic! */
+inline void *ExchangePtr(XchgPtr *ptr, void *newval)
+{
+    void *old = *ptr;
+    *ptr = newval;
+    return old;
+}
+
+/* This is *NOT* atomic, but is a handy utility macro to compare-and-swap non-
+ * atomic variables. */
+#define COMPARE_EXCHANGE(_val, _oldval, _newval)  ((*(_val) == *(_oldval)) ? ((*(_val)=(_newval)),true) : ((*(_oldval)=*(_val)),false))
+
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 4 - 0
libs/openal-soft/include/static_assert.h

@@ -10,7 +10,11 @@
 #else
 #else
 #define CTASTR2(_pre,_post) _pre##_post
 #define CTASTR2(_pre,_post) _pre##_post
 #define CTASTR(_pre,_post) CTASTR2(_pre,_post)
 #define CTASTR(_pre,_post) CTASTR2(_pre,_post)
+#if defined(__COUNTER__)
 #define static_assert(_cond, _msg) typedef struct { int CTASTR(static_assert_failed_at_line_,__LINE__) : !!(_cond); } CTASTR(static_assertion_,__COUNTER__)
 #define static_assert(_cond, _msg) typedef struct { int CTASTR(static_assert_failed_at_line_,__LINE__) : !!(_cond); } CTASTR(static_assertion_,__COUNTER__)
+#else
+#define static_assert(_cond, _msg) struct { int CTASTR(static_assert_failed_at_line_,__LINE__) : !!(_cond); }
+#endif
 #endif
 #endif
 #endif
 #endif
 
 

+ 1 - 1
libs/openal-soft/include/threads.h

@@ -234,7 +234,7 @@ void altss_delete(altss_t tss_id);
 
 
 int altimespec_get(struct timespec *ts, int base);
 int altimespec_get(struct timespec *ts, int base);
 
 
-void al_nssleep(time_t sec, long nsec);
+void al_nssleep(unsigned long nsec);
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 237 - 70
libs/openal-soft/utils/alsoft-config/mainwindow.cpp

@@ -1,3 +1,6 @@
+
+#include "config.h"
+
 #include <QFileDialog>
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QMessageBox>
 #include <QSettings>
 #include <QSettings>
@@ -10,26 +13,92 @@ static const struct {
     char backend_name[16];
     char backend_name[16];
     char menu_string[32];
     char menu_string[32];
 } backendMenuList[] = {
 } backendMenuList[] = {
-#ifdef Q_OS_WIN32
-    { "mmdevapi", "Add MMDevAPI" },
-    { "dsound", "Add DirectSound" },
-    { "winmm", "Add Windows Multimedia" },
-#endif
-#ifdef Q_OS_MAC
-    { "core", "Add CoreAudio" },
+#ifdef HAVE_JACK
+    { "jack", "Add JACK" },
 #endif
 #endif
+#ifdef HAVE_PULSEAUDIO
     { "pulse", "Add PulseAudio" },
     { "pulse", "Add PulseAudio" },
-#ifdef Q_OS_UNIX
+#endif
+#ifdef HAVE_ALSA
     { "alsa", "Add ALSA" },
     { "alsa", "Add ALSA" },
+#endif
+#ifdef HAVE_COREAUDIO
+    { "core", "Add CoreAudio" },
+#endif
+#ifdef HAVE_OSS
     { "oss", "Add OSS" },
     { "oss", "Add OSS" },
+#endif
+#ifdef HAVE_SOLARIS
     { "solaris", "Add Solaris" },
     { "solaris", "Add Solaris" },
+#endif
+#ifdef HAVE_SNDIO
     { "sndio", "Add SndIO" },
     { "sndio", "Add SndIO" },
+#endif
+#ifdef HAVE_QSA
     { "qsa", "Add QSA" },
     { "qsa", "Add QSA" },
 #endif
 #endif
+#ifdef HAVE_MMDEVAPI
+    { "mmdevapi", "Add MMDevAPI" },
+#endif
+#ifdef HAVE_DSOUND
+    { "dsound", "Add DirectSound" },
+#endif
+#ifdef HAVE_WINMM
+    { "winmm", "Add Windows Multimedia" },
+#endif
+#ifdef HAVE_PORTAUDIO
     { "port", "Add PortAudio" },
     { "port", "Add PortAudio" },
+#endif
+#ifdef HAVE_OPENSL
     { "opensl", "Add OpenSL" },
     { "opensl", "Add OpenSL" },
+#endif
+
     { "null", "Add Null Output" },
     { "null", "Add Null Output" },
+#ifdef HAVE_WAVE
     { "wave", "Add Wave Writer" },
     { "wave", "Add Wave Writer" },
+#endif
+    { "", "" }
+};
+
+static const struct {
+    const char name[64];
+    const char value[16];
+} speakerModeList[] = {
+    { "Autodetect", "" },
+    { "Mono", "mono" },
+    { "Stereo", "stereo" },
+    { "Quadrophonic", "quad" },
+    { "5.1 Surround (Side)", "surround51" },
+    { "5.1 Surround (Rear)", "surround51rear" },
+    { "6.1 Surround", "surround61" },
+    { "7.1 Surround", "surround71" },
+
+    { "", "" }
+}, sampleTypeList[] = {
+    { "Autodetect", "" },
+    { "8-bit int", "int8" },
+    { "8-bit uint", "uint8" },
+    { "16-bit int", "int16" },
+    { "16-bit uint", "uint16" },
+    { "32-bit int", "int32" },
+    { "32-bit uint", "uint32" },
+    { "32-bit float", "float32" },
+
+    { "", "" }
+}, resamplerList[] = {
+    { "Default", "" },
+    { "Point (low quality, very fast)", "point" },
+    { "Linear (basic quality, fast)", "linear" },
+    { "4-Point Sinc (good quality)", "sinc4" },
+    { "8-Point Sinc (high quality, slow)", "sinc8" },
+    { "Band-limited Sinc (very high quality, very slow)", "bsinc" },
+
+    { "", "" }
+}, stereoModeList[] = {
+    { "Autodetect", "" },
+    { "Speakers", "speakers" },
+    { "Headphones", "headphones" },
+
     { "", "" }
     { "", "" }
 };
 };
 
 
@@ -104,11 +173,65 @@ MainWindow::MainWindow(QWidget *parent) :
     mSourceCountValidator(NULL),
     mSourceCountValidator(NULL),
     mEffectSlotValidator(NULL),
     mEffectSlotValidator(NULL),
     mSourceSendValidator(NULL),
     mSourceSendValidator(NULL),
-    mSampleRateValidator(NULL),
-    mReverbBoostValidator(NULL)
+    mSampleRateValidator(NULL)
 {
 {
     ui->setupUi(this);
     ui->setupUi(this);
 
 
+    for(int i = 0;speakerModeList[i].name[0];i++)
+        ui->channelConfigCombo->addItem(speakerModeList[i].name);
+    ui->channelConfigCombo->adjustSize();
+    for(int i = 0;sampleTypeList[i].name[0];i++)
+        ui->sampleFormatCombo->addItem(sampleTypeList[i].name);
+    ui->sampleFormatCombo->adjustSize();
+    for(int i = 0;resamplerList[i].name[0];i++)
+        ui->resamplerComboBox->addItem(resamplerList[i].name);
+    ui->resamplerComboBox->adjustSize();
+    for(int i = 0;stereoModeList[i].name[0];i++)
+        ui->stereoModeCombo->addItem(stereoModeList[i].name);
+    ui->stereoModeCombo->adjustSize();
+
+    ui->hrtfStateComboBox->adjustSize();
+
+#if !defined(HAVE_NEON) && !defined(HAVE_SSE)
+    ui->cpuExtDisabledLabel->move(ui->cpuExtDisabledLabel->x(), ui->cpuExtDisabledLabel->y() - 60);
+#else
+    ui->cpuExtDisabledLabel->setVisible(false);
+#endif
+
+#ifndef HAVE_NEON
+
+#ifndef HAVE_SSE4_1
+#ifndef HAVE_SSE3
+#ifndef HAVE_SSE2
+#ifndef HAVE_SSE
+    ui->enableSSECheckBox->setVisible(false);
+#endif /* !SSE */
+    ui->enableSSE2CheckBox->setVisible(false);
+#endif /* !SSE2 */
+    ui->enableSSE3CheckBox->setVisible(false);
+#endif /* !SSE3 */
+    ui->enableSSE41CheckBox->setVisible(false);
+#endif /* !SSE4.1 */
+    ui->enableNeonCheckBox->setVisible(false);
+
+#else /* !Neon */
+
+#ifndef HAVE_SSE4_1
+#ifndef HAVE_SSE3
+#ifndef HAVE_SSE2
+#ifndef HAVE_SSE
+    ui->enableNeonCheckBox->move(ui->enableNeonCheckBox->x(), ui->enableNeonCheckBox->y() - 30);
+    ui->enableSSECheckBox->setVisible(false);
+#endif /* !SSE */
+    ui->enableSSE2CheckBox->setVisible(false);
+#endif /* !SSE2 */
+    ui->enableSSE3CheckBox->setVisible(false);
+#endif /* !SSE3 */
+    ui->enableSSE41CheckBox->setVisible(false);
+#endif /* !SSE4.1 */
+
+#endif
+
     mPeriodSizeValidator = new QIntValidator(64, 8192, this);
     mPeriodSizeValidator = new QIntValidator(64, 8192, this);
     ui->periodSizeEdit->setValidator(mPeriodSizeValidator);
     ui->periodSizeEdit->setValidator(mPeriodSizeValidator);
     mPeriodCountValidator = new QIntValidator(2, 16, this);
     mPeriodCountValidator = new QIntValidator(2, 16, this);
@@ -123,9 +246,6 @@ MainWindow::MainWindow(QWidget *parent) :
     mSampleRateValidator = new QIntValidator(8000, 192000, this);
     mSampleRateValidator = new QIntValidator(8000, 192000, this);
     ui->sampleRateCombo->lineEdit()->setValidator(mSampleRateValidator);
     ui->sampleRateCombo->lineEdit()->setValidator(mSampleRateValidator);
 
 
-    mReverbBoostValidator = new QDoubleValidator(-12.0, +12.0, 1, this);
-    ui->reverbBoostEdit->setValidator(mReverbBoostValidator);
-
     connect(ui->actionLoad, SIGNAL(triggered()), this, SLOT(loadConfigFromFile()));
     connect(ui->actionLoad, SIGNAL(triggered()), this, SLOT(loadConfigFromFile()));
     connect(ui->actionSave_As, SIGNAL(triggered()), this, SLOT(saveConfigAsFile()));
     connect(ui->actionSave_As, SIGNAL(triggered()), this, SLOT(saveConfigAsFile()));
 
 
@@ -146,9 +266,6 @@ MainWindow::MainWindow(QWidget *parent) :
     ui->disabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu);
     ui->disabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu);
     connect(ui->disabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDisabledBackendMenu(QPoint)));
     connect(ui->disabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDisabledBackendMenu(QPoint)));
 
 
-    connect(ui->reverbBoostSlider, SIGNAL(valueChanged(int)), this, SLOT(updateReverbBoostEdit(int)));
-    connect(ui->reverbBoostEdit, SIGNAL(textEdited(QString)), this, SLOT(updateReverbBoostSlider(QString)));
-
     loadConfig(getDefaultConfigName());
     loadConfig(getDefaultConfigName());
 }
 }
 
 
@@ -161,7 +278,6 @@ MainWindow::~MainWindow()
     delete mEffectSlotValidator;
     delete mEffectSlotValidator;
     delete mSourceSendValidator;
     delete mSourceSendValidator;
     delete mSampleRateValidator;
     delete mSampleRateValidator;
-    delete mReverbBoostValidator;
 }
 }
 
 
 void MainWindow::loadConfigFromFile()
 void MainWindow::loadConfigFromFile()
@@ -179,12 +295,19 @@ void MainWindow::loadConfig(const QString &fname)
     ui->sampleFormatCombo->setCurrentIndex(0);
     ui->sampleFormatCombo->setCurrentIndex(0);
     if(sampletype.isEmpty() == false)
     if(sampletype.isEmpty() == false)
     {
     {
-        for(int i = 1;i < ui->sampleFormatCombo->count();i++)
+        for(int i = 0;sampleTypeList[i].name[i];i++)
         {
         {
-            QString item = ui->sampleFormatCombo->itemText(i);
-            if(item.startsWith(sampletype))
+            if(sampletype == sampleTypeList[i].value)
             {
             {
-                ui->sampleFormatCombo->setCurrentIndex(i);
+                for(int j = 1;j < ui->sampleFormatCombo->count();j++)
+                {
+                    QString item = ui->sampleFormatCombo->itemText(j);
+                    if(item == sampleTypeList[i].name)
+                    {
+                        ui->sampleFormatCombo->setCurrentIndex(j);
+                        break;
+                    }
+                }
                 break;
                 break;
             }
             }
         }
         }
@@ -194,12 +317,19 @@ void MainWindow::loadConfig(const QString &fname)
     ui->channelConfigCombo->setCurrentIndex(0);
     ui->channelConfigCombo->setCurrentIndex(0);
     if(channelconfig.isEmpty() == false)
     if(channelconfig.isEmpty() == false)
     {
     {
-        for(int i = 1;i < ui->channelConfigCombo->count();i++)
+        for(int i = 0;speakerModeList[i].name[i];i++)
         {
         {
-            QString item = ui->channelConfigCombo->itemText(i);
-            if(item.startsWith(channelconfig))
+            if(channelconfig == speakerModeList[i].value)
             {
             {
-                ui->channelConfigCombo->setCurrentIndex(i);
+                for(int j = 1;j < ui->channelConfigCombo->count();j++)
+                {
+                    QString item = ui->channelConfigCombo->itemText(j);
+                    if(item == speakerModeList[i].name)
+                    {
+                        ui->channelConfigCombo->setCurrentIndex(j);
+                        break;
+                    }
+                }
                 break;
                 break;
             }
             }
         }
         }
@@ -222,18 +352,49 @@ void MainWindow::loadConfig(const QString &fname)
     ui->srcSendLineEdit->insert(settings.value("sends").toString());
     ui->srcSendLineEdit->insert(settings.value("sends").toString());
 
 
     QString resampler = settings.value("resampler").toString().trimmed();
     QString resampler = settings.value("resampler").toString().trimmed();
-    if(resampler.isEmpty())
-        ui->resamplerComboBox->setCurrentIndex(0);
-    else
+    ui->resamplerComboBox->setCurrentIndex(0);
+    if(resampler.isEmpty() == false)
+    {
+        /* The "cubic" resampler is no longer supported. It's been replaced by
+         * "sinc4". */
+        if(resampler == "cubic")
+            resampler = "sinc4";
+
+        for(int i = 0;resamplerList[i].name[i];i++)
+        {
+            if(resampler == resamplerList[i].value)
+            {
+                for(int j = 1;j < ui->resamplerComboBox->count();j++)
+                {
+                    QString item = ui->resamplerComboBox->itemText(j);
+                    if(item == resamplerList[i].name)
+                    {
+                        ui->resamplerComboBox->setCurrentIndex(j);
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    QString stereomode = settings.value("stereo-mode").toString().trimmed();
+    ui->stereoModeCombo->setCurrentIndex(0);
+    if(stereomode.isEmpty() == false)
     {
     {
-        for(int i = 1;i < ui->resamplerComboBox->count();i++)
+        for(int i = 0;stereoModeList[i].name[i];i++)
         {
         {
-            QString item = ui->resamplerComboBox->itemText(i);
-            int end = item.indexOf(' ');
-            if(end < 0) end = item.size();
-            if(resampler.size() == end && resampler.compare(item.leftRef(end), Qt::CaseInsensitive) == 0)
+            if(stereomode == stereoModeList[i].value)
             {
             {
-                ui->resamplerComboBox->setCurrentIndex(i);
+                for(int j = 1;j < ui->stereoModeCombo->count();j++)
+                {
+                    QString item = ui->stereoModeCombo->itemText(j);
+                    if(item == stereoModeList[i].name)
+                    {
+                        ui->stereoModeCombo->setCurrentIndex(j);
+                        break;
+                    }
+                }
                 break;
                 break;
             }
             }
         }
         }
@@ -262,17 +423,18 @@ void MainWindow::loadConfig(const QString &fname)
                    disabledCpuExts.begin(), std::mem_fun_ref(&QString::trimmed));
                    disabledCpuExts.begin(), std::mem_fun_ref(&QString::trimmed));
     ui->enableSSECheckBox->setChecked(!disabledCpuExts.contains("sse", Qt::CaseInsensitive));
     ui->enableSSECheckBox->setChecked(!disabledCpuExts.contains("sse", Qt::CaseInsensitive));
     ui->enableSSE2CheckBox->setChecked(!disabledCpuExts.contains("sse2", Qt::CaseInsensitive));
     ui->enableSSE2CheckBox->setChecked(!disabledCpuExts.contains("sse2", Qt::CaseInsensitive));
+    ui->enableSSE3CheckBox->setChecked(!disabledCpuExts.contains("sse3", Qt::CaseInsensitive));
     ui->enableSSE41CheckBox->setChecked(!disabledCpuExts.contains("sse4.1", Qt::CaseInsensitive));
     ui->enableSSE41CheckBox->setChecked(!disabledCpuExts.contains("sse4.1", Qt::CaseInsensitive));
     ui->enableNeonCheckBox->setChecked(!disabledCpuExts.contains("neon", Qt::CaseInsensitive));
     ui->enableNeonCheckBox->setChecked(!disabledCpuExts.contains("neon", Qt::CaseInsensitive));
 
 
     if(settings.value("hrtf").toString() == QString())
     if(settings.value("hrtf").toString() == QString())
-        ui->hrtfEnableButton->setChecked(true);
+        ui->hrtfStateComboBox->setCurrentIndex(0);
     else
     else
     {
     {
         if(settings.value("hrtf", true).toBool())
         if(settings.value("hrtf", true).toBool())
-            ui->hrtfForceButton->setChecked(true);
+            ui->hrtfStateComboBox->setCurrentIndex(1);
         else
         else
-            ui->hrtfDisableButton->setChecked(true);
+            ui->hrtfStateComboBox->setCurrentIndex(2);
     }
     }
 
 
     QStringList hrtf_tables = settings.value("hrtf_tables").toStringList();
     QStringList hrtf_tables = settings.value("hrtf_tables").toStringList();
@@ -323,8 +485,6 @@ void MainWindow::loadConfig(const QString &fname)
     }
     }
 
 
     ui->emulateEaxCheckBox->setChecked(settings.value("reverb/emulate-eax", false).toBool());
     ui->emulateEaxCheckBox->setChecked(settings.value("reverb/emulate-eax", false).toBool());
-    ui->reverbBoostEdit->clear();
-    ui->reverbBoostEdit->insert(settings.value("reverb/boost").toString());
 
 
     QStringList excludefx = settings.value("excludefx").toStringList();
     QStringList excludefx = settings.value("excludefx").toStringList();
     if(excludefx.size() == 1)
     if(excludefx.size() == 1)
@@ -371,15 +531,27 @@ void MainWindow::saveConfig(const QString &fname) const
     }
     }
 
 
     QString str = ui->sampleFormatCombo->currentText();
     QString str = ui->sampleFormatCombo->currentText();
-    str.truncate(str.indexOf('-'));
-    settings.setValue("sample-type", str.trimmed());
+    for(int i = 0;sampleTypeList[i].name[0];i++)
+    {
+        if(str == sampleTypeList[i].name)
+        {
+            settings.setValue("sample-type", sampleTypeList[i].value);
+            break;
+        }
+    }
 
 
     str = ui->channelConfigCombo->currentText();
     str = ui->channelConfigCombo->currentText();
-    str.truncate(str.indexOf('-'));
-    settings.setValue("channels", str.trimmed());
+    for(int i = 0;speakerModeList[i].name[0];i++)
+    {
+        if(str == speakerModeList[i].name)
+        {
+            settings.setValue("channels", speakerModeList[i].value);
+            break;
+        }
+    }
 
 
     uint rate = ui->sampleRateCombo->currentText().toUInt();
     uint rate = ui->sampleRateCombo->currentText().toUInt();
-    if(rate == 0)
+    if(!(rate > 0))
         settings.setValue("frequency", QString());
         settings.setValue("frequency", QString());
     else
     else
         settings.setValue("frequency", rate);
         settings.setValue("frequency", rate);
@@ -390,12 +562,24 @@ void MainWindow::saveConfig(const QString &fname) const
     settings.setValue("sources", ui->srcCountLineEdit->text());
     settings.setValue("sources", ui->srcCountLineEdit->text());
     settings.setValue("slots", ui->effectSlotLineEdit->text());
     settings.setValue("slots", ui->effectSlotLineEdit->text());
 
 
-    if(ui->resamplerComboBox->currentIndex() == 0)
-        settings.setValue("resampler", QString());
-    else
+    str = ui->resamplerComboBox->currentText();
+    for(int i = 0;resamplerList[i].name[0];i++)
     {
     {
-        str = ui->resamplerComboBox->currentText();
-        settings.setValue("resampler", str.split(' ').first().toLower());
+        if(str == resamplerList[i].name)
+        {
+            settings.setValue("resampler", resamplerList[i].value);
+            break;
+        }
+    }
+
+    str = ui->stereoModeCombo->currentText();
+    for(int i = 0;stereoModeList[i].name[0];i++)
+    {
+        if(str == stereoModeList[i].name)
+        {
+            settings.setValue("stereo-mode", stereoModeList[i].value);
+            break;
+        }
     }
     }
 
 
     QStringList strlist;
     QStringList strlist;
@@ -403,15 +587,17 @@ void MainWindow::saveConfig(const QString &fname) const
         strlist.append("sse");
         strlist.append("sse");
     if(!ui->enableSSE2CheckBox->isChecked())
     if(!ui->enableSSE2CheckBox->isChecked())
         strlist.append("sse2");
         strlist.append("sse2");
+    if(!ui->enableSSE3CheckBox->isChecked())
+        strlist.append("sse3");
     if(!ui->enableSSE41CheckBox->isChecked())
     if(!ui->enableSSE41CheckBox->isChecked())
         strlist.append("sse4.1");
         strlist.append("sse4.1");
     if(!ui->enableNeonCheckBox->isChecked())
     if(!ui->enableNeonCheckBox->isChecked())
         strlist.append("neon");
         strlist.append("neon");
     settings.setValue("disable-cpu-exts", strlist.join(QChar(',')));
     settings.setValue("disable-cpu-exts", strlist.join(QChar(',')));
 
 
-    if(ui->hrtfForceButton->isChecked())
+    if(ui->hrtfStateComboBox->currentIndex() == 1)
         settings.setValue("hrtf", "true");
         settings.setValue("hrtf", "true");
-    else if(ui->hrtfDisableButton->isChecked())
+    else if(ui->hrtfStateComboBox->currentIndex() == 2)
         settings.setValue("hrtf", "false");
         settings.setValue("hrtf", "false");
     else
     else
         settings.setValue("hrtf", QString());
         settings.setValue("hrtf", QString());
@@ -449,12 +635,6 @@ void MainWindow::saveConfig(const QString &fname) const
     else
     else
         settings.setValue("reverb/emulate-eax", QString()/*"false"*/);
         settings.setValue("reverb/emulate-eax", QString()/*"false"*/);
 
 
-    // TODO: Remove check when we can properly match global values.
-    if(ui->reverbBoostSlider->sliderPosition() == 0)
-        settings.setValue("reverb/boost", QString());
-    else
-        settings.setValue("reverb/boost", ui->reverbBoostEdit->text());
-
     strlist.clear();
     strlist.clear();
     if(!ui->enableEaxReverbCheck->isChecked())
     if(!ui->enableEaxReverbCheck->isChecked())
         strlist.append("eaxreverb");
         strlist.append("eaxreverb");
@@ -645,16 +825,3 @@ void MainWindow::showDisabledBackendMenu(QPoint pt)
             ui->disabledBackendList->addItem(iter.value());
             ui->disabledBackendList->addItem(iter.value());
     }
     }
 }
 }
-
-void MainWindow::updateReverbBoostEdit(int value)
-{
-    ui->reverbBoostEdit->clear();
-    if(value != 0)
-        ui->reverbBoostEdit->insert(QString::number(value/10.0, 'f', 1));
-}
-
-void MainWindow::updateReverbBoostSlider(QString value)
-{
-    int pos = int(value.toFloat()*10.0f);
-    ui->reverbBoostSlider->setSliderPosition(pos);
-}

+ 0 - 4
libs/openal-soft/utils/alsoft-config/mainwindow.h

@@ -35,9 +35,6 @@ private slots:
     void showEnabledBackendMenu(QPoint pt);
     void showEnabledBackendMenu(QPoint pt);
     void showDisabledBackendMenu(QPoint pt);
     void showDisabledBackendMenu(QPoint pt);
 
 
-    void updateReverbBoostEdit(int size);
-    void updateReverbBoostSlider(QString value);
-
 private:
 private:
     Ui::MainWindow *ui;
     Ui::MainWindow *ui;
 
 
@@ -47,7 +44,6 @@ private:
     QValidator *mEffectSlotValidator;
     QValidator *mEffectSlotValidator;
     QValidator *mSourceSendValidator;
     QValidator *mSourceSendValidator;
     QValidator *mSampleRateValidator;
     QValidator *mSampleRateValidator;
-    QValidator *mReverbBoostValidator;
 
 
     void loadConfig(const QString &fname);
     void loadConfig(const QString &fname);
     void saveConfig(const QString &fname) const;
     void saveConfig(const QString &fname) const;

+ 138 - 263
libs/openal-soft/utils/alsoft-config/mainwindow.ui

@@ -57,8 +57,8 @@
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
         <x>120</x>
         <x>120</x>
-        <y>20</y>
-        <width>188</width>
+        <y>50</y>
+        <width>78</width>
         <height>22</height>
         <height>22</height>
        </rect>
        </rect>
       </property>
       </property>
@@ -69,52 +69,12 @@ float and converted to the output sample type as needed.</string>
       <property name="sizeAdjustPolicy">
       <property name="sizeAdjustPolicy">
        <enum>QComboBox::AdjustToContents</enum>
        <enum>QComboBox::AdjustToContents</enum>
       </property>
       </property>
-      <item>
-       <property name="text">
-        <string>- Autodetect -</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>int8 - signed 8-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>uint8 - unsigned 8-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>int16 - signed 16-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>uint16 - unsigned 16-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>int32 - signed 32-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>uint32 - unsigned 32-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>float32 - 32-bit float</string>
-       </property>
-      </item>
      </widget>
      </widget>
      <widget class="QLabel" name="label_5">
      <widget class="QLabel" name="label_5">
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
         <x>10</x>
         <x>10</x>
-        <y>20</y>
+        <y>50</y>
         <width>101</width>
         <width>101</width>
         <height>21</height>
         <height>21</height>
        </rect>
        </rect>
@@ -130,7 +90,7 @@ float and converted to the output sample type as needed.</string>
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
         <x>10</x>
         <x>10</x>
-        <y>50</y>
+        <y>20</y>
         <width>101</width>
         <width>101</width>
         <height>21</height>
         <height>21</height>
        </rect>
        </rect>
@@ -146,8 +106,8 @@ float and converted to the output sample type as needed.</string>
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
         <x>120</x>
         <x>120</x>
-        <y>50</y>
-        <width>227</width>
+        <y>20</y>
+        <width>78</width>
         <height>22</height>
         <height>22</height>
        </rect>
        </rect>
       </property>
       </property>
@@ -159,48 +119,13 @@ to stereo output.</string>
       <property name="sizeAdjustPolicy">
       <property name="sizeAdjustPolicy">
        <enum>QComboBox::AdjustToContents</enum>
        <enum>QComboBox::AdjustToContents</enum>
       </property>
       </property>
-      <item>
-       <property name="text">
-        <string>- Autodetect -</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>mono - 1-channel Mono</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>stereo - 2-channel Stereo</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>quad - 4-channel Quadraphonic</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>surround51 - 5.1 Surround Sound</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>surround61 - 6.1 Surround Sound</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>surround71 - 7.1 Surround Sound</string>
-       </property>
-      </item>
      </widget>
      </widget>
      <widget class="QComboBox" name="sampleRateCombo">
      <widget class="QComboBox" name="sampleRateCombo">
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
-        <x>120</x>
-        <y>80</y>
-        <width>111</width>
+        <x>370</x>
+        <y>20</y>
+        <width>96</width>
         <height>22</height>
         <height>22</height>
        </rect>
        </rect>
       </property>
       </property>
@@ -218,27 +143,22 @@ to stereo output.</string>
       </property>
       </property>
       <item>
       <item>
        <property name="text">
        <property name="text">
-        <string>- Autodetect -</string>
+        <string>Autodetect</string>
        </property>
        </property>
       </item>
       </item>
       <item>
       <item>
        <property name="text">
        <property name="text">
-        <string>96000</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>48000</string>
+        <string>8000</string>
        </property>
        </property>
       </item>
       </item>
       <item>
       <item>
        <property name="text">
        <property name="text">
-        <string>44100</string>
+        <string>11025</string>
        </property>
        </property>
       </item>
       </item>
       <item>
       <item>
        <property name="text">
        <property name="text">
-        <string>32000</string>
+        <string>16000</string>
        </property>
        </property>
       </item>
       </item>
       <item>
       <item>
@@ -248,26 +168,26 @@ to stereo output.</string>
       </item>
       </item>
       <item>
       <item>
        <property name="text">
        <property name="text">
-        <string>16000</string>
+        <string>32000</string>
        </property>
        </property>
       </item>
       </item>
       <item>
       <item>
        <property name="text">
        <property name="text">
-        <string>11025</string>
+        <string>44100</string>
        </property>
        </property>
       </item>
       </item>
       <item>
       <item>
        <property name="text">
        <property name="text">
-        <string>8000</string>
+        <string>48000</string>
        </property>
        </property>
       </item>
       </item>
      </widget>
      </widget>
      <widget class="QLabel" name="label_7">
      <widget class="QLabel" name="label_7">
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
-        <x>10</x>
-        <y>80</y>
-        <width>101</width>
+        <x>280</x>
+        <y>20</y>
+        <width>81</width>
         <height>21</height>
         <height>21</height>
        </rect>
        </rect>
       </property>
       </property>
@@ -282,73 +202,20 @@ to stereo output.</string>
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
         <x>10</x>
         <x>10</x>
-        <y>200</y>
+        <y>180</y>
         <width>511</width>
         <width>511</width>
-        <height>161</height>
+        <height>191</height>
        </rect>
        </rect>
       </property>
       </property>
       <property name="title">
       <property name="title">
        <string>HRTF (Stereo only)</string>
        <string>HRTF (Stereo only)</string>
       </property>
       </property>
-      <widget class="QRadioButton" name="hrtfEnableButton">
-       <property name="geometry">
-        <rect>
-         <x>20</x>
-         <y>30</y>
-         <width>71</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>Allows applications to request HRTF mixing.</string>
-       </property>
-       <property name="text">
-        <string>Enable</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QRadioButton" name="hrtfDisableButton">
-       <property name="geometry">
-        <rect>
-         <x>20</x>
-         <y>50</y>
-         <width>71</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>Does not allow HRTF mixing, even when requested.</string>
-       </property>
-       <property name="text">
-        <string>Disable</string>
-       </property>
-      </widget>
-      <widget class="QRadioButton" name="hrtfForceButton">
-       <property name="geometry">
-        <rect>
-         <x>20</x>
-         <y>70</y>
-         <width>71</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>Attempts to force HRTF mixing, even if applications request not
-to do it. This may override the channel configuration and
-sample rate.</string>
-       </property>
-       <property name="text">
-        <string>Force</string>
-       </property>
-      </widget>
       <widget class="QListWidget" name="hrtfFileList">
       <widget class="QListWidget" name="hrtfFileList">
        <property name="geometry">
        <property name="geometry">
         <rect>
         <rect>
-         <x>110</x>
+         <x>20</x>
          <y>30</y>
          <y>30</y>
-         <width>301</width>
+         <width>391</width>
          <height>121</height>
          <height>121</height>
         </rect>
         </rect>
        </property>
        </property>
@@ -378,7 +245,7 @@ contain these markers, which will be replaced as needed:
       <widget class="QPushButton" name="hrtfAddButton">
       <widget class="QPushButton" name="hrtfAddButton">
        <property name="geometry">
        <property name="geometry">
         <rect>
         <rect>
-         <x>419</x>
+         <x>420</x>
          <y>30</y>
          <y>30</y>
          <width>81</width>
          <width>81</width>
          <height>25</height>
          <height>25</height>
@@ -399,7 +266,7 @@ contain these markers, which will be replaced as needed:
       <widget class="QPushButton" name="hrtfRemoveButton">
       <widget class="QPushButton" name="hrtfRemoveButton">
        <property name="geometry">
        <property name="geometry">
         <rect>
         <rect>
-         <x>419</x>
+         <x>420</x>
          <y>60</y>
          <y>60</y>
          <width>81</width>
          <width>81</width>
          <height>25</height>
          <height>25</height>
@@ -414,12 +281,56 @@ contain these markers, which will be replaced as needed:
         </iconset>
         </iconset>
        </property>
        </property>
       </widget>
       </widget>
+      <widget class="QComboBox" name="hrtfStateComboBox">
+       <property name="geometry">
+        <rect>
+         <x>110</x>
+         <y>160</y>
+         <width>161</width>
+         <height>22</height>
+        </rect>
+       </property>
+       <property name="sizeAdjustPolicy">
+        <enum>QComboBox::AdjustToContentsOnFirstShow</enum>
+       </property>
+       <item>
+        <property name="text">
+         <string>Application preference</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>Force on</string>
+        </property>
+       </item>
+       <item>
+        <property name="text">
+         <string>Force off</string>
+        </property>
+       </item>
+      </widget>
+      <widget class="QLabel" name="label_15">
+       <property name="geometry">
+        <rect>
+         <x>30</x>
+         <y>160</y>
+         <width>71</width>
+         <height>21</height>
+        </rect>
+       </property>
+       <property name="text">
+        <string>HRTF Mode:</string>
+       </property>
+       <property name="alignment">
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+      </widget>
      </widget>
      </widget>
      <widget class="QGroupBox" name="groupBox_3">
      <widget class="QGroupBox" name="groupBox_3">
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
         <x>10</x>
         <x>10</x>
-        <y>110</y>
+        <y>90</y>
         <width>511</width>
         <width>511</width>
         <height>91</height>
         <height>91</height>
        </rect>
        </rect>
@@ -590,6 +501,37 @@ frames needed for each mixing update.</string>
        </widget>
        </widget>
       </widget>
       </widget>
      </widget>
      </widget>
+     <widget class="QLabel" name="label_14">
+      <property name="geometry">
+       <rect>
+        <x>280</x>
+        <y>50</y>
+        <width>81</width>
+        <height>21</height>
+       </rect>
+      </property>
+      <property name="text">
+       <string>Stereo Mode:</string>
+      </property>
+      <property name="alignment">
+       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+      </property>
+     </widget>
+     <widget class="QComboBox" name="stereoModeCombo">
+      <property name="geometry">
+       <rect>
+        <x>370</x>
+        <y>50</y>
+        <width>78</width>
+        <height>22</height>
+       </rect>
+      </property>
+      <property name="toolTip">
+       <string>How to treat stereo output. As headphones, HRTF or crossfeed
+filters may be used to improve binaural quality, which may not
+otherwise be suitable for speakers.</string>
+      </property>
+     </widget>
     </widget>
     </widget>
     <widget class="QWidget" name="tab_2">
     <widget class="QWidget" name="tab_2">
      <attribute name="title">
      <attribute name="title">
@@ -737,7 +679,7 @@ value currently possible is 4.</string>
        <rect>
        <rect>
         <x>110</x>
         <x>110</x>
         <y>120</y>
         <y>120</y>
-        <width>185</width>
+        <width>78</width>
         <height>22</height>
         <height>22</height>
        </rect>
        </rect>
       </property>
       </property>
@@ -747,34 +689,14 @@ value currently possible is 4.</string>
       <property name="sizeAdjustPolicy">
       <property name="sizeAdjustPolicy">
        <enum>QComboBox::AdjustToContents</enum>
        <enum>QComboBox::AdjustToContents</enum>
       </property>
       </property>
-      <item>
-       <property name="text">
-        <string>- Default -</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Point (low quality, fast)</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Linear (basic quality, fast)</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Cubic Spline (good quality)</string>
-       </property>
-      </item>
      </widget>
      </widget>
-     <widget class="QGroupBox" name="groupBox_2">
+     <widget class="QGroupBox" name="cpuExtGroupBox">
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
         <x>10</x>
         <x>10</x>
         <y>150</y>
         <y>150</y>
         <width>511</width>
         <width>511</width>
-        <height>91</height>
+        <height>121</height>
        </rect>
        </rect>
       </property>
       </property>
       <property name="toolTip">
       <property name="toolTip">
@@ -788,7 +710,7 @@ be useful for preventing those extensions from being used.</string>
       <widget class="QCheckBox" name="enableSSECheckBox">
       <widget class="QCheckBox" name="enableSSECheckBox">
        <property name="geometry">
        <property name="geometry">
         <rect>
         <rect>
-         <x>180</x>
+         <x>100</x>
          <y>20</y>
          <y>20</y>
          <width>71</width>
          <width>71</width>
          <height>31</height>
          <height>31</height>
@@ -805,7 +727,7 @@ be useful for preventing those extensions from being used.</string>
        <property name="geometry">
        <property name="geometry">
         <rect>
         <rect>
          <x>180</x>
          <x>180</x>
-         <y>50</y>
+         <y>20</y>
          <width>71</width>
          <width>71</width>
          <height>31</height>
          <height>31</height>
         </rect>
         </rect>
@@ -820,7 +742,7 @@ be useful for preventing those extensions from being used.</string>
       <widget class="QCheckBox" name="enableNeonCheckBox">
       <widget class="QCheckBox" name="enableNeonCheckBox">
        <property name="geometry">
        <property name="geometry">
         <rect>
         <rect>
-         <x>260</x>
+         <x>100</x>
          <y>50</y>
          <y>50</y>
          <width>71</width>
          <width>71</width>
          <height>31</height>
          <height>31</height>
@@ -836,7 +758,7 @@ be useful for preventing those extensions from being used.</string>
       <widget class="QCheckBox" name="enableSSE41CheckBox">
       <widget class="QCheckBox" name="enableSSE41CheckBox">
        <property name="geometry">
        <property name="geometry">
         <rect>
         <rect>
-         <x>260</x>
+         <x>340</x>
          <y>20</y>
          <y>20</y>
          <width>71</width>
          <width>71</width>
          <height>31</height>
          <height>31</height>
@@ -849,6 +771,35 @@ be useful for preventing those extensions from being used.</string>
         <bool>true</bool>
         <bool>true</bool>
        </property>
        </property>
       </widget>
       </widget>
+      <widget class="QCheckBox" name="enableSSE3CheckBox">
+       <property name="geometry">
+        <rect>
+         <x>260</x>
+         <y>20</y>
+         <width>71</width>
+         <height>31</height>
+        </rect>
+       </property>
+       <property name="text">
+        <string>SSE3</string>
+       </property>
+       <property name="checked">
+        <bool>true</bool>
+       </property>
+      </widget>
+      <widget class="QLabel" name="cpuExtDisabledLabel">
+       <property name="geometry">
+        <rect>
+         <x>101</x>
+         <y>80</y>
+         <width>311</width>
+         <height>31</height>
+        </rect>
+       </property>
+       <property name="text">
+        <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;No support enabled for CPU Extensions&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+       </property>
+      </widget>
      </widget>
      </widget>
     </widget>
     </widget>
     <widget class="QWidget" name="tab">
     <widget class="QWidget" name="tab">
@@ -956,87 +907,11 @@ some quality.</string>
        <string>Emulate EAX Reverb:</string>
        <string>Emulate EAX Reverb:</string>
       </property>
       </property>
      </widget>
      </widget>
-     <widget class="QGroupBox" name="groupBox_4">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>100</y>
-        <width>511</width>
-        <height>61</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>Global amplification for reverb output, expressed in decibels.
-+6 will be a scale of (approximately) 2x, +12 will be a scale of
-4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A
-value of 0 means no change.</string>
-      </property>
-      <property name="title">
-       <string>Reverb Boost</string>
-      </property>
-      <widget class="QSlider" name="reverbBoostSlider">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>30</y>
-         <width>391</width>
-         <height>23</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string/>
-       </property>
-       <property name="minimum">
-        <number>-120</number>
-       </property>
-       <property name="maximum">
-        <number>120</number>
-       </property>
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="tickPosition">
-        <enum>QSlider::TicksBelow</enum>
-       </property>
-       <property name="tickInterval">
-        <number>10</number>
-       </property>
-      </widget>
-      <widget class="QLineEdit" name="reverbBoostEdit">
-       <property name="geometry">
-        <rect>
-         <x>410</x>
-         <y>30</y>
-         <width>51</width>
-         <height>22</height>
-        </rect>
-       </property>
-       <property name="alignment">
-        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-       </property>
-       <property name="placeholderText">
-        <string>0.0</string>
-       </property>
-      </widget>
-      <widget class="QLabel" name="label_12">
-       <property name="geometry">
-        <rect>
-         <x>460</x>
-         <y>30</y>
-         <width>31</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>dB</string>
-       </property>
-      </widget>
-     </widget>
      <widget class="QGroupBox" name="groupBox_5">
      <widget class="QGroupBox" name="groupBox_5">
       <property name="geometry">
       <property name="geometry">
        <rect>
        <rect>
         <x>10</x>
         <x>10</x>
-        <y>170</y>
+        <y>100</y>
         <width>511</width>
         <width>511</width>
         <height>191</height>
         <height>191</height>
        </rect>
        </rect>

+ 1 - 93
libs/openal-soft/utils/makehrtf.c

@@ -227,8 +227,7 @@ enum HeadModelT {
 // Desired output format from the command line.
 // Desired output format from the command line.
 enum OutputFormatT {
 enum OutputFormatT {
   OF_NONE  = 0,
   OF_NONE  = 0,
-  OF_MHR      ,   // OpenAL Soft MHR data set file.
-  OF_TABLE        // OpenAL Soft built-in table file (used when compiling).
+  OF_MHR          // OpenAL Soft MHR data set file.
 };
 };
 
 
 // Unsigned integer type.
 // Unsigned integer type.
@@ -2089,84 +2088,6 @@ static int StoreMhr (const HrirDataT * hData, const char * filename) {
   return (1);
   return (1);
 }
 }
 
 
-// Store the OpenAL Soft built-in table.
-static int StoreTable (const HrirDataT * hData, const char * filename) {
-  FILE * fp = NULL;
-  uint step, end, n, j, i;
-  int hpHist, v;
-  char text [128 + 1];
-
-  if ((fp = fopen (filename, "wb")) == NULL) {
-     fprintf (stderr, "Error:  Could not open table file '%s'.\n", filename);
-     return (0);
-  }
-  snprintf (text, 128, "/* Elevation metrics */\n"
-                       "static const ALubyte defaultAzCount[%u] = { ", hData -> mEvCount);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  for (i = 0; i < hData -> mEvCount; i ++) {
-      snprintf (text, 128, "%u, ", hData -> mAzCount [i]);
-      if (! WriteAscii (text, fp, filename))
-         return (0);
-  }
-  snprintf (text, 128, "};\n"
-                       "static const ALushort defaultEvOffset[%u] = { ", hData -> mEvCount);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  for (i = 0; i < hData -> mEvCount; i ++) {
-      snprintf (text, 128, "%u, ", hData -> mEvOffset [i]);
-      if (! WriteAscii (text, fp, filename))
-         return (0);
-  }
-  step = hData -> mIrSize;
-  end = hData -> mIrCount * step;
-  n = hData -> mIrPoints;
-  snprintf (text, 128, "};\n\n"
-                       "/* HRIR Coefficients */\n"
-                       "static const ALshort defaultCoeffs[%u] =\n{\n", hData -> mIrCount * n);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  srand (0x31DF840C);
-  for (j = 0; j < end; j += step) {
-      if (! WriteAscii ("   ", fp, filename))
-         return (0);
-      hpHist = 0;
-      for (i = 0; i < n; i ++) {
-          v = HpTpdfDither (32767.0 * hData -> mHrirs [j + i], & hpHist);
-          snprintf (text, 128, " %+d,", v);
-          if (! WriteAscii (text, fp, filename))
-             return (0);
-      }
-      if (! WriteAscii ("\n", fp, filename))
-         return (0);
-  }
-  snprintf (text, 128, "};\n\n"
-                       "/* HRIR Delays */\n"
-                       "static const ALubyte defaultDelays[%u] =\n{\n"
-                       "   ", hData -> mIrCount);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  for (j = 0; j < hData -> mIrCount; j ++) {
-      v = (int) fmin (round (hData -> mIrRate * hData -> mHrtds [j]), MAX_HRTD);
-      snprintf (text, 128, " %d,", v);
-      if (! WriteAscii (text, fp, filename))
-         return (0);
-  }
-  if (! WriteAscii ("\n};\n\n"
-                    "/* Default HRTF Definition */\n", fp, filename))
-     return (0);
-  snprintf (text, 128, "static const struct Hrtf DefaultHrtf = {\n"
-                       "    %u, %u, %u, defaultAzCount, defaultEvOffset,\n",
-                       hData -> mIrRate, hData -> mIrPoints, hData -> mEvCount);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  if (! WriteAscii ("    defaultCoeffs, defaultDelays, NULL\n"
-                    "};\n", fp, filename))
-     return (0);
-  fclose (fp);
-  return (1);
-}
-
 // Process the data set definition to read and validate the data set metrics.
 // Process the data set definition to read and validate the data set metrics.
 static int ProcessMetrics (TokenReaderT * tr, const uint fftSize, const uint truncSize, HrirDataT * hData) {
 static int ProcessMetrics (TokenReaderT * tr, const uint fftSize, const uint truncSize, HrirDataT * hData) {
   char ident [MAX_IDENT_LEN + 1];
   char ident [MAX_IDENT_LEN + 1];
@@ -2583,11 +2504,6 @@ static int ProcessDefinition (const char * inName, const uint outRate, const uin
       if (! StoreMhr (& hData, expName))
       if (! StoreMhr (& hData, expName))
          return (0);
          return (0);
     break;
     break;
-    case OF_TABLE :
-      fprintf (stderr, "Creating OpenAL Soft table file...\n");
-      if (! StoreTable (& hData, expName))
-         return (0);
-    break;
     default :
     default :
     break;
     break;
   }
   }
@@ -2619,8 +2535,6 @@ int main (const int argc, const char * argv []) {
      fprintf (stdout, "Commands:\n");
      fprintf (stdout, "Commands:\n");
      fprintf (stdout, " -m, --make-mhr  Makes an OpenAL Soft compatible HRTF data set.\n");
      fprintf (stdout, " -m, --make-mhr  Makes an OpenAL Soft compatible HRTF data set.\n");
      fprintf (stdout, "                 Defaults output to: ./oalsoft_hrtf_%%r.mhr\n");
      fprintf (stdout, "                 Defaults output to: ./oalsoft_hrtf_%%r.mhr\n");
-     fprintf (stdout, " -t, --make-tab  Makes the built-in table used when compiling OpenAL Soft.\n");
-     fprintf (stdout, "                 Defaults output to: ./hrtf_tables.inc\n");
      fprintf (stdout, " -h, --help      Displays this help information.\n\n");
      fprintf (stdout, " -h, --help      Displays this help information.\n\n");
      fprintf (stdout, "Options:\n");
      fprintf (stdout, "Options:\n");
      fprintf (stdout, " -r=<rate>       Change the data set sample rate to the specified value and\n");
      fprintf (stdout, " -r=<rate>       Change the data set sample rate to the specified value and\n");
@@ -2647,12 +2561,6 @@ int main (const int argc, const char * argv []) {
      else
      else
         outName = "./oalsoft_hrtf_%r.mhr";
         outName = "./oalsoft_hrtf_%r.mhr";
      outFormat = OF_MHR;
      outFormat = OF_MHR;
-  } else if ((strcmp (argv [1], "--make-tab") == 0) || (strcmp (argv [1], "-t") == 0)) {
-     if (argc > 3)
-        outName = argv [3];
-     else
-        outName = "./hrtf_tables.inc";
-     outFormat = OF_TABLE;
   } else {
   } else {
      fprintf (stderr, "Error:  Invalid command '%s'.\n", argv [1]);
      fprintf (stderr, "Error:  Invalid command '%s'.\n", argv [1]);
      return (-1);
      return (-1);

+ 30 - 0
libs/openal-soft/utils/openal-info.c

@@ -147,6 +147,35 @@ static void printALCInfo(ALCdevice *device)
     }
     }
 }
 }
 
 
+static void printHRTFInfo(ALCdevice *device)
+{
+    LPALCGETSTRINGISOFT alcGetStringiSOFT;
+    ALCint num_hrtfs;
+
+    if(alcIsExtensionPresent(device, "ALC_SOFT_HRTF") == ALC_FALSE)
+    {
+        printf("HRTF extension not available\n");
+        return;
+    }
+
+    alcGetStringiSOFT = alcGetProcAddress(device, "alcGetStringiSOFT");
+
+    alcGetIntegerv(device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtfs);
+    if(!num_hrtfs)
+        printf("No HRTFs found\n");
+    else
+    {
+        ALCint i;
+        printf("Available HRTFs:\n");
+        for(i = 0;i < num_hrtfs;++i)
+        {
+            const ALCchar *name = alcGetStringiSOFT(device, ALC_HRTF_SPECIFIER_SOFT, i);
+            printf("    %s\n", name);
+        }
+    }
+    checkALCErrors(device);
+}
+
 static void printALInfo(void)
 static void printALInfo(void)
 {
 {
     printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
     printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR));
@@ -287,6 +316,7 @@ int main(int argc, char *argv[])
         return 1;
         return 1;
     }
     }
     printALCInfo(device);
     printALCInfo(device);
+    printHRTFInfo(device);
 
 
     context = alcCreateContext(device, NULL);
     context = alcCreateContext(device, NULL);
     if(!context || alcMakeContextCurrent(context) == ALC_FALSE)
     if(!context || alcMakeContextCurrent(context) == ALC_FALSE)

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