Browse Source

Update OpenAL Soft to commit 414b56edec5441211dc924fef365c54267c04f1c

Alex Szpakowski 7 years ago
parent
commit
5be7c968b8
100 changed files with 8202 additions and 12862 deletions
  1. 12 16
      libs/openal-soft/.travis.yml
  2. 378 224
      libs/openal-soft/Alc/ALc.c
  3. 331 279
      libs/openal-soft/Alc/ALu.c
  4. 58 35
      libs/openal-soft/Alc/alconfig.c
  5. 17 0
      libs/openal-soft/Alc/alconfig.h
  6. 9 0
      libs/openal-soft/Alc/alstring.h
  7. 53 35
      libs/openal-soft/Alc/backends/alsa.c
  8. 2 0
      libs/openal-soft/Alc/backends/base.c
  9. 17 4
      libs/openal-soft/Alc/backends/base.h
  10. 66 84
      libs/openal-soft/Alc/backends/coreaudio.c
  11. 72 54
      libs/openal-soft/Alc/backends/dsound.c
  12. 24 57
      libs/openal-soft/Alc/backends/jack.c
  13. 0 5
      libs/openal-soft/Alc/backends/loopback.c
  14. 7 11
      libs/openal-soft/Alc/backends/null.c
  15. 26 87
      libs/openal-soft/Alc/backends/opensl.c
  16. 35 25
      libs/openal-soft/Alc/backends/oss.c
  17. 11 28
      libs/openal-soft/Alc/backends/portaudio.c
  18. 65 71
      libs/openal-soft/Alc/backends/pulseaudio.c
  19. 28 24
      libs/openal-soft/Alc/backends/qsa.c
  20. 287 0
      libs/openal-soft/Alc/backends/sdl2.c
  21. 11 15
      libs/openal-soft/Alc/backends/sndio.c
  22. 7 10
      libs/openal-soft/Alc/backends/solaris.c
  23. 238 254
      libs/openal-soft/Alc/backends/wasapi.c
  24. 17 17
      libs/openal-soft/Alc/backends/wave.c
  25. 39 50
      libs/openal-soft/Alc/backends/winmm.c
  26. 120 140
      libs/openal-soft/Alc/bformatdec.c
  27. 30 14
      libs/openal-soft/Alc/bformatdec.h
  28. 0 5081
      libs/openal-soft/Alc/bsinc.c
  29. 9 1
      libs/openal-soft/Alc/compat.h
  30. 17 16
      libs/openal-soft/Alc/converter.c
  31. 1 1
      libs/openal-soft/Alc/converter.h
  32. 15 0
      libs/openal-soft/Alc/cpu_caps.h
  33. 262 117
      libs/openal-soft/Alc/effects/chorus.c
  34. 29 33
      libs/openal-soft/Alc/effects/compressor.c
  35. 43 62
      libs/openal-soft/Alc/effects/dedicated.c
  36. 64 73
      libs/openal-soft/Alc/effects/distortion.c
  37. 71 81
      libs/openal-soft/Alc/effects/echo.c
  38. 89 114
      libs/openal-soft/Alc/effects/equalizer.c
  39. 0 408
      libs/openal-soft/Alc/effects/flanger.c
  40. 76 83
      libs/openal-soft/Alc/effects/modulator.c
  41. 37 37
      libs/openal-soft/Alc/effects/null.c
  42. 496 0
      libs/openal-soft/Alc/effects/pshifter.c
  43. 297 438
      libs/openal-soft/Alc/effects/reverb.c
  44. 118 0
      libs/openal-soft/Alc/filters/defs.h
  45. 133 0
      libs/openal-soft/Alc/filters/filter.c
  46. 89 79
      libs/openal-soft/Alc/filters/nfc.c
  47. 49 0
      libs/openal-soft/Alc/filters/nfc.h
  48. 37 0
      libs/openal-soft/Alc/fpu_modes.h
  49. 157 69
      libs/openal-soft/Alc/helpers.c
  50. 334 43
      libs/openal-soft/Alc/hrtf.c
  51. 40 3
      libs/openal-soft/Alc/hrtf.h
  52. 79 0
      libs/openal-soft/Alc/inprogext.h
  53. 69 0
      libs/openal-soft/Alc/logging.h
  54. 4 27
      libs/openal-soft/Alc/mastering.c
  55. 57 0
      libs/openal-soft/Alc/mastering.h
  56. 20 30
      libs/openal-soft/Alc/mixer/defs.h
  57. 1 1
      libs/openal-soft/Alc/mixer/hrtf_inc.c
  58. 22 60
      libs/openal-soft/Alc/mixer/mixer_c.c
  59. 16 86
      libs/openal-soft/Alc/mixer/mixer_neon.c
  60. 18 19
      libs/openal-soft/Alc/mixer/mixer_sse.c
  61. 2 2
      libs/openal-soft/Alc/mixer/mixer_sse2.c
  62. 0 0
      libs/openal-soft/Alc/mixer/mixer_sse3.c
  63. 17 28
      libs/openal-soft/Alc/mixer/mixer_sse41.c
  64. 0 154
      libs/openal-soft/Alc/mixer_sse41.c
  65. 262 172
      libs/openal-soft/Alc/mixvoice.c
  66. 0 37
      libs/openal-soft/Alc/nfcfilter.h
  67. 218 203
      libs/openal-soft/Alc/panning.c
  68. 105 0
      libs/openal-soft/Alc/polymorphism.h
  69. 44 66
      libs/openal-soft/Alc/ringbuffer.c
  70. 77 0
      libs/openal-soft/Alc/ringbuffer.h
  71. 17 9
      libs/openal-soft/Alc/uhjfilter.c
  72. 2 1
      libs/openal-soft/Alc/vector.h
  73. 338 250
      libs/openal-soft/CMakeLists.txt
  74. 37 44
      libs/openal-soft/OpenAL32/Include/alAuxEffectSlot.h
  75. 39 52
      libs/openal-soft/OpenAL32/Include/alBuffer.h
  76. 39 39
      libs/openal-soft/OpenAL32/Include/alEffect.h
  77. 8 12
      libs/openal-soft/OpenAL32/Include/alError.h
  78. 30 127
      libs/openal-soft/OpenAL32/Include/alFilter.h
  79. 15 14
      libs/openal-soft/OpenAL32/Include/alListener.h
  80. 234 556
      libs/openal-soft/OpenAL32/Include/alMain.h
  81. 9 17
      libs/openal-soft/OpenAL32/Include/alSource.h
  82. 0 20
      libs/openal-soft/OpenAL32/Include/alThunk.h
  83. 80 72
      libs/openal-soft/OpenAL32/Include/alu.h
  84. 7 1
      libs/openal-soft/OpenAL32/Include/sample_cvt.h
  85. 276 207
      libs/openal-soft/OpenAL32/alAuxEffectSlot.c
  86. 331 433
      libs/openal-soft/OpenAL32/alBuffer.c
  87. 199 111
      libs/openal-soft/OpenAL32/alEffect.c
  88. 43 12
      libs/openal-soft/OpenAL32/alError.c
  89. 2 18
      libs/openal-soft/OpenAL32/alExtension.c
  90. 239 290
      libs/openal-soft/OpenAL32/alFilter.c
  91. 105 113
      libs/openal-soft/OpenAL32/alListener.c
  92. 231 248
      libs/openal-soft/OpenAL32/alSource.c
  93. 208 87
      libs/openal-soft/OpenAL32/alState.c
  94. 0 108
      libs/openal-soft/OpenAL32/alThunk.c
  95. 140 0
      libs/openal-soft/OpenAL32/event.c
  96. 60 788
      libs/openal-soft/OpenAL32/sample_cvt.c
  97. 0 55
      libs/openal-soft/README
  98. 61 0
      libs/openal-soft/README.md
  99. 17 14
      libs/openal-soft/alsoftrc.sample
  100. 1 1
      libs/openal-soft/appveyor.yml

+ 12 - 16
libs/openal-soft/.travis.yml

@@ -9,9 +9,6 @@ matrix:
         - BUILD_ANDROID=true
     - os: osx
 sudo: required
-cache:
-  directories:
-    - $HOME/android-ndk-r14
 install:
   - >
     if [[ "${TRAVIS_OS_NAME}" == "linux" && -z "${BUILD_ANDROID}" ]]; then
@@ -27,18 +24,17 @@ install:
     fi
   - >
     if [[ "${TRAVIS_OS_NAME}" == "linux" && "${BUILD_ANDROID}" == "true" ]]; then
-      if [[ ! -d ~/android-ndk-r14 || -z "$(ls -A ~/android-ndk-r14)" ]]; then
-        curl -o ~/android-ndk.zip https://dl.google.com/android/repository/android-ndk-r14-linux-x86_64.zip
-        unzip -q ~/android-ndk.zip -d ~ \
-          'android-ndk-r14/build/cmake/*' \
-          'android-ndk-r14/platforms/android-9/arch-arm/*' \
-          'android-ndk-r14/source.properties' \
-          'android-ndk-r14/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/*' \
-          'android-ndk-r14/sysroot/*' \
-          'android-ndk-r14/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/*' \
-          'android-ndk-r14/toolchains/llvm/prebuilt/linux-x86_64/*'
-        sed -i -e 's/VERSION 3.6.0/VERSION 3.2/' ~/android-ndk-r14/build/cmake/android.toolchain.cmake
-      fi
+      curl -o ~/android-ndk.zip https://dl.google.com/android/repository/android-ndk-r15-linux-x86_64.zip
+      unzip -q ~/android-ndk.zip -d ~ \
+        'android-ndk-r15/build/cmake/*' \
+        'android-ndk-r15/build/core/toolchains/arm-linux-androideabi-*/*' \
+        'android-ndk-r15/platforms/android-14/arch-arm/*' \
+        'android-ndk-r15/source.properties' \
+        'android-ndk-r15/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/*' \
+        'android-ndk-r15/sources/cxx-stl/gnu-libstdc++/4.9/include/*' \
+        'android-ndk-r15/sysroot/*' \
+        'android-ndk-r15/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/*' \
+        'android-ndk-r15/toolchains/llvm/prebuilt/linux-x86_64/*'
     fi
 script:
   - >
@@ -55,7 +51,7 @@ script:
   - >
     if [[ "${TRAVIS_OS_NAME}" == "linux" && "${BUILD_ANDROID}" == "true" ]]; then
       cmake \
-        -DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r14/build/cmake/android.toolchain.cmake \
+        -DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r15/build/cmake/android.toolchain.cmake \
         -DALSOFT_REQUIRE_OPENSL=ON \
         -DALSOFT_EMBED_HRTF_DATA=YES \
         .

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


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


+ 58 - 35
libs/openal-soft/Alc/alcConfig.c → libs/openal-soft/Alc/alconfig.c

@@ -38,6 +38,7 @@
 #endif
 
 #include "alMain.h"
+#include "alconfig.h"
 #include "compat.h"
 #include "bool.h"
 
@@ -365,9 +366,9 @@ static void LoadConfigFromFile(FILE *f)
 #ifdef _WIN32
 void ReadALConfig(void)
 {
-    WCHAR buffer[PATH_MAX];
+    al_string ppath = AL_STRING_INIT_STATIC();
+    WCHAR buffer[MAX_PATH];
     const WCHAR *str;
-    al_string ppath;
     FILE *f;
 
     if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE)
@@ -386,7 +387,7 @@ void ReadALConfig(void)
         alstr_reset(&filepath);
     }
 
-    ppath = GetProcPath();
+    GetProcBinary(&ppath, NULL);
     if(!alstr_empty(ppath))
     {
         alstr_append_cstr(&ppath, "\\alsoft.ini");
@@ -419,9 +420,9 @@ void ReadALConfig(void)
 #else
 void ReadALConfig(void)
 {
-    char buffer[PATH_MAX];
+    al_string confpaths = AL_STRING_INIT_STATIC();
+    al_string fname = AL_STRING_INIT_STATIC();
     const char *str;
-    al_string ppath;
     FILE *f;
 
     str = "/etc/openal/alsoft.conf";
@@ -436,45 +437,55 @@ void ReadALConfig(void)
 
     if(!(str=getenv("XDG_CONFIG_DIRS")) || str[0] == 0)
         str = "/etc/xdg";
-    strncpy(buffer, str, sizeof(buffer)-1);
-    buffer[sizeof(buffer)-1] = 0;
+    alstr_copy_cstr(&confpaths, str);
     /* Go through the list in reverse, since "the order of base directories
      * denotes their importance; the first directory listed is the most
      * important". Ergo, we need to load the settings from the later dirs
      * first so that the settings in the earlier dirs override them.
      */
-    while(1)
+    while(!alstr_empty(confpaths))
     {
-        char *next = strrchr(buffer, ':');
-        if(next) *(next++) = 0;
-        else next = buffer;
+        char *next = strrchr(alstr_get_cstr(confpaths), ':');
+        if(next)
+        {
+            size_t len = next - alstr_get_cstr(confpaths);
+            alstr_copy_cstr(&fname, next+1);
+            VECTOR_RESIZE(confpaths, len, len+1);
+            VECTOR_ELEM(confpaths, len) = 0;
+        }
+        else
+        {
+            alstr_reset(&fname);
+            fname = confpaths;
+            AL_STRING_INIT(confpaths);
+        }
 
-        if(next[0] != '/')
-            WARN("Ignoring XDG config dir: %s\n", next);
+        if(alstr_empty(fname) || VECTOR_FRONT(fname) != '/')
+            WARN("Ignoring XDG config dir: %s\n", alstr_get_cstr(fname));
         else
         {
-            size_t len = strlen(next);
-            strncpy(next+len, "/alsoft.conf", buffer+sizeof(buffer)-next-len);
-            buffer[sizeof(buffer)-1] = 0;
+            if(VECTOR_BACK(fname) != '/') alstr_append_cstr(&fname, "/alsoft.conf");
+            else alstr_append_cstr(&fname, "alsoft.conf");
 
-            TRACE("Loading config %s...\n", next);
-            f = al_fopen(next, "r");
+            TRACE("Loading config %s...\n", alstr_get_cstr(fname));
+            f = al_fopen(alstr_get_cstr(fname), "r");
             if(f)
             {
                 LoadConfigFromFile(f);
                 fclose(f);
             }
         }
-        if(next == buffer)
-            break;
+        alstr_clear(&fname);
     }
 
     if((str=getenv("HOME")) != NULL && *str)
     {
-        snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str);
+        alstr_copy_cstr(&fname, str);
+        if(VECTOR_BACK(fname) != '/') alstr_append_cstr(&fname, "/.alsoftrc");
+        else alstr_append_cstr(&fname, ".alsoftrc");
 
-        TRACE("Loading config %s...\n", buffer);
-        f = al_fopen(buffer, "r");
+        TRACE("Loading config %s...\n", alstr_get_cstr(fname));
+        f = al_fopen(alstr_get_cstr(fname), "r");
         if(f)
         {
             LoadConfigFromFile(f);
@@ -483,17 +494,25 @@ void ReadALConfig(void)
     }
 
     if((str=getenv("XDG_CONFIG_HOME")) != NULL && str[0] != 0)
-        snprintf(buffer, sizeof(buffer), "%s/%s", str, "alsoft.conf");
+    {
+        alstr_copy_cstr(&fname, str);
+        if(VECTOR_BACK(fname) != '/') alstr_append_cstr(&fname, "/alsoft.conf");
+        else alstr_append_cstr(&fname, "alsoft.conf");
+    }
     else
     {
-        buffer[0] = 0;
+        alstr_clear(&fname);
         if((str=getenv("HOME")) != NULL && str[0] != 0)
-            snprintf(buffer, sizeof(buffer), "%s/.config/%s", str, "alsoft.conf");
+        {
+            alstr_copy_cstr(&fname, str);
+            if(VECTOR_BACK(fname) != '/') alstr_append_cstr(&fname, "/.config/alsoft.conf");
+            else alstr_append_cstr(&fname, ".config/alsoft.conf");
+        }
     }
-    if(buffer[0] != 0)
+    if(!alstr_empty(fname))
     {
-        TRACE("Loading config %s...\n", buffer);
-        f = al_fopen(buffer, "r");
+        TRACE("Loading config %s...\n", alstr_get_cstr(fname));
+        f = al_fopen(alstr_get_cstr(fname), "r");
         if(f)
         {
             LoadConfigFromFile(f);
@@ -501,12 +520,15 @@ void ReadALConfig(void)
         }
     }
 
-    ppath = GetProcPath();
-    if(!alstr_empty(ppath))
+    alstr_clear(&fname);
+    GetProcBinary(&fname, NULL);
+    if(!alstr_empty(fname))
     {
-        alstr_append_cstr(&ppath, "/alsoft.conf");
-        TRACE("Loading config %s...\n", alstr_get_cstr(ppath));
-        f = al_fopen(alstr_get_cstr(ppath), "r");
+        if(VECTOR_BACK(fname) != '/') alstr_append_cstr(&fname, "/alsoft.conf");
+        else alstr_append_cstr(&fname, "alsoft.conf");
+
+        TRACE("Loading config %s...\n", alstr_get_cstr(fname));
+        f = al_fopen(alstr_get_cstr(fname), "r");
         if(f)
         {
             LoadConfigFromFile(f);
@@ -525,7 +547,8 @@ void ReadALConfig(void)
         }
     }
 
-    alstr_reset(&ppath);
+    alstr_reset(&fname);
+    alstr_reset(&confpaths);
 }
 #endif
 

+ 17 - 0
libs/openal-soft/Alc/alconfig.h

@@ -0,0 +1,17 @@
+#ifndef ALCONFIG_H
+#define ALCONFIG_H
+
+void ReadALConfig(void);
+void FreeALConfig(void);
+
+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);
+
+#endif /* ALCONFIG_H */

+ 9 - 0
libs/openal-soft/Alc/alstring.h

@@ -6,6 +6,10 @@
 #include "vector.h"
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef char al_string_char_type;
 TYPEDEF_VECTOR(al_string_char_type, al_string)
 TYPEDEF_VECTOR(al_string, vector_al_string)
@@ -43,7 +47,12 @@ void alstr_append_range(al_string *str, const al_string_char_type *from, const a
 /* Windows-only methods to deal with WideChar strings. */
 void alstr_copy_wcstr(al_string *str, const wchar_t *from);
 void alstr_append_wcstr(al_string *str, const wchar_t *from);
+void alstr_copy_wrange(al_string *str, const wchar_t *from, const wchar_t *to);
 void alstr_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to);
 #endif
 
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
 #endif /* ALSTRING_H */

+ 53 - 35
libs/openal-soft/Alc/backends/alsa.c

@@ -26,6 +26,8 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "alconfig.h"
+#include "ringbuffer.h"
 #include "threads.h"
 #include "compat.h"
 
@@ -436,7 +438,7 @@ typedef struct ALCplaybackAlsa {
     ALvoid *buffer;
     ALsizei size;
 
-    volatile int killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } ALCplaybackAlsa;
 
@@ -444,9 +446,8 @@ static int ALCplaybackAlsa_mixerProc(void *ptr);
 static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr);
 
 static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, Destruct)
+static void ALCplaybackAlsa_Destruct(ALCplaybackAlsa *self);
 static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name);
-static void ALCplaybackAlsa_close(ALCplaybackAlsa *self);
 static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self);
 static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self);
 static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self);
@@ -464,6 +465,19 @@ static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCplaybackAlsa, ALCbackend, self);
+
+    self->pcmHandle = NULL;
+    self->buffer = NULL;
+
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
+}
+
+void ALCplaybackAlsa_Destruct(ALCplaybackAlsa *self)
+{
+    if(self->pcmHandle)
+        snd_pcm_close(self->pcmHandle);
+    self->pcmHandle = NULL;
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
 
@@ -483,14 +497,14 @@ static int ALCplaybackAlsa_mixerProc(void *ptr)
 
     update_size = device->UpdateSize;
     num_updates = device->NumUpdates;
-    while(!self->killNow)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire))
     {
         int state = verify_state(self->pcmHandle);
         if(state < 0)
         {
             ERR("Invalid state detected: %s\n", snd_strerror(state));
             ALCplaybackAlsa_lock(self);
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Bad state: %s", snd_strerror(state));
             ALCplaybackAlsa_unlock(self);
             break;
         }
@@ -573,14 +587,14 @@ static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr)
 
     update_size = device->UpdateSize;
     num_updates = device->NumUpdates;
-    while(!self->killNow)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire))
     {
         int state = verify_state(self->pcmHandle);
         if(state < 0)
         {
             ERR("Invalid state detected: %s\n", snd_strerror(state));
             ALCplaybackAlsa_lock(self);
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Bad state: %s", snd_strerror(state));
             ALCplaybackAlsa_unlock(self);
             break;
         }
@@ -700,11 +714,6 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCplaybackAlsa_close(ALCplaybackAlsa *self)
-{
-    snd_pcm_close(self->pcmHandle);
-}
-
 static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -903,7 +912,7 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self)
         }
         thread_func = ALCplaybackAlsa_mixerProc;
     }
-    self->killNow = 0;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, thread_func, self) != althrd_success)
     {
         ERR("Could not create playback thread\n");
@@ -924,10 +933,8 @@ static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self)
 {
     int res;
 
-    if(self->killNow)
+    if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
-
-    self->killNow = 1;
     althrd_join(self->thread, &res);
 
     al_free(self->buffer);
@@ -971,9 +978,8 @@ typedef struct ALCcaptureAlsa {
 } ALCcaptureAlsa;
 
 static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, Destruct)
+static void ALCcaptureAlsa_Destruct(ALCcaptureAlsa *self);
 static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name);
-static void ALCcaptureAlsa_close(ALCcaptureAlsa *self);
 static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, ALCboolean, reset)
 static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self);
 static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self);
@@ -991,6 +997,25 @@ static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCcaptureAlsa, ALCbackend, self);
+
+    self->pcmHandle = NULL;
+    self->buffer = NULL;
+    self->ring = NULL;
+}
+
+void ALCcaptureAlsa_Destruct(ALCcaptureAlsa *self)
+{
+    if(self->pcmHandle)
+        snd_pcm_close(self->pcmHandle);
+    self->pcmHandle = NULL;
+
+    al_free(self->buffer);
+    self->buffer = NULL;
+
+    ll_ringbuffer_free(self->ring);
+    self->ring = NULL;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
 
@@ -1098,8 +1123,9 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
     if(needring)
     {
         self->ring = ll_ringbuffer_create(
-            device->UpdateSize*device->NumUpdates + 1,
-            FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
+            device->UpdateSize*device->NumUpdates,
+            FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder),
+            false
         );
         if(!self->ring)
         {
@@ -1124,22 +1150,14 @@ error2:
     return ALC_INVALID_VALUE;
 }
 
-static void ALCcaptureAlsa_close(ALCcaptureAlsa *self)
-{
-    snd_pcm_close(self->pcmHandle);
-    ll_ringbuffer_free(self->ring);
-
-    al_free(self->buffer);
-    self->buffer = NULL;
-}
-
 static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self)
 {
     int err = snd_pcm_start(self->pcmHandle);
     if(err < 0)
     {
         ERR("start failed: %s\n", snd_strerror(err));
-        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice, "Capture state failure: %s",
+                            snd_strerror(err));
         return ALC_FALSE;
     }
 
@@ -1190,7 +1208,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff
     }
 
     self->last_avail -= samples;
-    while(device->Connected && samples > 0)
+    while(ATOMIC_LOAD(&device->Connected, almemory_order_acquire) && samples > 0)
     {
         snd_pcm_sframes_t amt = 0;
 
@@ -1233,7 +1251,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff
             if(amt < 0)
             {
                 ERR("restore error: %s\n", snd_strerror(amt));
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Capture recovery failure: %s", snd_strerror(amt));
                 break;
             }
             /* If the amount available is less than what's asked, we lost it
@@ -1258,7 +1276,7 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self)
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     snd_pcm_sframes_t avail = 0;
 
-    if(device->Connected && self->doCapture)
+    if(ATOMIC_LOAD(&device->Connected, almemory_order_acquire) && self->doCapture)
         avail = snd_pcm_avail_update(self->pcmHandle);
     if(avail < 0)
     {
@@ -1274,7 +1292,7 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self)
         if(avail < 0)
         {
             ERR("restore error: %s\n", snd_strerror(avail));
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Capture recovery failure: %s", snd_strerror(avail));
         }
     }
 
@@ -1313,7 +1331,7 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self)
             if(amt < 0)
             {
                 ERR("restore error: %s\n", snd_strerror(amt));
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Capture recovery failure: %s", snd_strerror(amt));
                 break;
             }
             avail = amt;

+ 2 - 0
libs/openal-soft/Alc/backends/base.c

@@ -10,6 +10,8 @@
 
 
 extern inline ALuint64 GetDeviceClockTime(ALCdevice *device);
+extern inline void ALCdevice_Lock(ALCdevice *device);
+extern inline void ALCdevice_Unlock(ALCdevice *device);
 
 /* Base ALCbackend method implementations. */
 void ALCbackend_Construct(ALCbackend *self, ALCdevice *device)

+ 17 - 4
libs/openal-soft/Alc/backends/base.h

@@ -5,6 +5,10 @@
 #include "threads.h"
 
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct ClockLatency {
     ALint64 ClockTime;
     ALint64 Latency;
@@ -43,7 +47,6 @@ struct ALCbackendVtable {
     void (*const Destruct)(ALCbackend*);
 
     ALCenum (*const open)(ALCbackend*, const ALCchar*);
-    void (*const close)(ALCbackend*);
 
     ALCboolean (*const reset)(ALCbackend*);
     ALCboolean (*const start)(ALCbackend*);
@@ -63,7 +66,6 @@ struct ALCbackendVtable {
 #define DEFINE_ALCBACKEND_VTABLE(T)                                           \
 DECLARE_THUNK(T, ALCbackend, void, Destruct)                                  \
 DECLARE_THUNK1(T, ALCbackend, ALCenum, open, const ALCchar*)                  \
-DECLARE_THUNK(T, ALCbackend, void, close)                                     \
 DECLARE_THUNK(T, ALCbackend, ALCboolean, reset)                               \
 DECLARE_THUNK(T, ALCbackend, ALCboolean, start)                               \
 DECLARE_THUNK(T, ALCbackend, void, stop)                                      \
@@ -79,7 +81,6 @@ static const struct ALCbackendVtable T##_ALCbackend_vtable = {                \
     T##_ALCbackend_Destruct,                                                  \
                                                                               \
     T##_ALCbackend_open,                                                      \
-    T##_ALCbackend_close,                                                     \
     T##_ALCbackend_reset,                                                     \
     T##_ALCbackend_start,                                                     \
     T##_ALCbackend_stop,                                                      \
@@ -143,13 +144,25 @@ ALCbackendFactory *ALCjackBackendFactory_getFactory(void);
 ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void);
 ALCbackendFactory *ALCsndioBackendFactory_getFactory(void);
 ALCbackendFactory *ALCqsaBackendFactory_getFactory(void);
-ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void);
+ALCbackendFactory *ALCwasapiBackendFactory_getFactory(void);
 ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void);
 ALCbackendFactory *ALCwinmmBackendFactory_getFactory(void);
 ALCbackendFactory *ALCportBackendFactory_getFactory(void);
 ALCbackendFactory *ALCopenslBackendFactory_getFactory(void);
 ALCbackendFactory *ALCnullBackendFactory_getFactory(void);
 ALCbackendFactory *ALCwaveBackendFactory_getFactory(void);
+ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void);
 ALCbackendFactory *ALCloopbackFactory_getFactory(void);
 
+
+inline void ALCdevice_Lock(ALCdevice *device)
+{ V0(device->Backend,lock)(); }
+
+inline void ALCdevice_Unlock(ALCdevice *device)
+{ V0(device->Backend,unlock)(); }
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
 #endif /* AL_BACKENDS_BASE_H */

+ 66 - 84
libs/openal-soft/Alc/backends/coreaudio.c

@@ -23,10 +23,10 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <alloca.h>
 
 #include "alMain.h"
 #include "alu.h"
+#include "ringbuffer.h"
 
 #include <CoreServices/CoreServices.h>
 #include <unistd.h>
@@ -36,56 +36,9 @@
 #include "backends/base.h"
 
 
-typedef struct {
-    AudioUnit audioUnit;
-
-    ALuint frameSize;
-    ALdouble sampleRateRatio;              // Ratio of hardware sample rate / requested sample rate
-    AudioStreamBasicDescription format;    // This is the OpenAL format as a CoreAudio ASBD
-
-    AudioConverterRef audioConverter;      // Sample rate converter if needed
-    AudioBufferList *bufferList;           // Buffer for data coming from the input device
-    ALCvoid *resampleBuffer;               // Buffer for returned RingBuffer data when resampling
-
-    ll_ringbuffer_t *ring;
-} ca_data;
-
 static const ALCchar ca_device[] = "CoreAudio Default";
 
 
-static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSize)
-{
-    AudioBufferList *list;
-
-    list = calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer));
-    if(list)
-    {
-        list->mNumberBuffers = 1;
-
-        list->mBuffers[0].mNumberChannels = channelCount;
-        list->mBuffers[0].mDataByteSize = byteSize;
-        list->mBuffers[0].mData = malloc(byteSize);
-        if(list->mBuffers[0].mData == NULL)
-        {
-            free(list);
-            list = NULL;
-        }
-    }
-    return list;
-}
-
-static void destroy_buffer_list(AudioBufferList* list)
-{
-    if(list)
-    {
-        UInt32 i;
-        for(i = 0;i < list->mNumberBuffers;i++)
-            free(list->mBuffers[i].mData);
-        free(list);
-    }
-}
-
-
 typedef struct ALCcoreAudioPlayback {
     DERIVE_FROM_TYPE(ALCbackend);
 
@@ -98,7 +51,6 @@ typedef struct ALCcoreAudioPlayback {
 static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice *device);
 static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self);
 static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCchar *name);
-static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback *self);
 static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self);
 static ALCboolean ALCcoreAudioPlayback_start(ALCcoreAudioPlayback *self);
 static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback *self);
@@ -123,6 +75,9 @@ static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice
 
 static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self)
 {
+    AudioUnitUninitialize(self->audioUnit);
+    AudioComponentInstanceDispose(self->audioUnit);
+
     ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
@@ -134,10 +89,10 @@ static OSStatus ALCcoreAudioPlayback_MixerProc(void *inRefCon,
     ALCcoreAudioPlayback *self = inRefCon;
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
 
-    ALCdevice_Lock(device);
+    ALCcoreAudioPlayback_lock(self);
     aluMixData(device, ioData->mBuffers[0].mData,
                ioData->mBuffers[0].mDataByteSize / self->frameSize);
-    ALCdevice_Unlock(device);
+    ALCcoreAudioPlayback_unlock(self);
 
     return noErr;
 }
@@ -189,12 +144,6 @@ static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCch
     return ALC_NO_ERROR;
 }
 
-static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback *self)
-{
-    AudioUnitUninitialize(self->audioUnit);
-    AudioComponentInstanceDispose(self->audioUnit);
-}
-
 static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
@@ -382,7 +331,6 @@ typedef struct ALCcoreAudioCapture {
 static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device);
 static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self);
 static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar *name);
-static void ALCcoreAudioCapture_close(ALCcoreAudioCapture *self);
 static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, ALCboolean, reset)
 static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self);
 static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture *self);
@@ -396,15 +344,59 @@ DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioCapture)
 DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioCapture);
 
 
+static AudioBufferList *allocate_buffer_list(UInt32 channelCount, UInt32 byteSize)
+{
+    AudioBufferList *list;
+
+    list = calloc(1, FAM_SIZE(AudioBufferList, mBuffers, 1) + byteSize);
+    if(list)
+    {
+        list->mNumberBuffers = 1;
+
+        list->mBuffers[0].mNumberChannels = channelCount;
+        list->mBuffers[0].mDataByteSize = byteSize;
+        list->mBuffers[0].mData = &list->mBuffers[1];
+    }
+    return list;
+}
+
+static void destroy_buffer_list(AudioBufferList *list)
+{
+    free(list);
+}
+
+
 static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCcoreAudioCapture, ALCbackend, self);
 
+    self->audioUnit = 0;
+    self->audioConverter = NULL;
+    self->bufferList = NULL;
+    self->resampleBuffer = NULL;
+    self->ring = NULL;
 }
 
 static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self)
 {
+    ll_ringbuffer_free(self->ring);
+    self->ring = NULL;
+
+    free(self->resampleBuffer);
+    self->resampleBuffer = NULL;
+
+    destroy_buffer_list(self->bufferList);
+    self->bufferList = NULL;
+
+    if(self->audioConverter)
+        AudioConverterDispose(self->audioConverter);
+    self->audioConverter = NULL;
+
+    if(self->audioUnit)
+        AudioComponentInstanceDispose(self->audioUnit);
+    self->audioUnit = 0;
+
     ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
@@ -667,8 +659,8 @@ static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar
         goto error;
 
     self->ring = ll_ringbuffer_create(
-        device->UpdateSize*self->sampleRateRatio*device->NumUpdates + 1,
-        self->frameSize
+        (size_t)ceil(device->UpdateSize*self->sampleRateRatio*device->NumUpdates),
+        self->frameSize, false
     );
     if(!self->ring) goto error;
 
@@ -680,30 +672,21 @@ error:
     ll_ringbuffer_free(self->ring);
     self->ring = NULL;
     free(self->resampleBuffer);
+    self->resampleBuffer = NULL;
     destroy_buffer_list(self->bufferList);
+    self->bufferList = NULL;
 
     if(self->audioConverter)
         AudioConverterDispose(self->audioConverter);
+    self->audioConverter = NULL;
     if(self->audioUnit)
         AudioComponentInstanceDispose(self->audioUnit);
+    self->audioUnit = 0;
 
     return ALC_INVALID_VALUE;
 }
 
 
-static void ALCcoreAudioCapture_close(ALCcoreAudioCapture *self)
-{
-    ll_ringbuffer_free(self->ring);
-    self->ring = NULL;
-
-    free(self->resampleBuffer);
-
-    destroy_buffer_list(self->bufferList);
-
-    AudioConverterDispose(self->audioConverter);
-    AudioComponentInstanceDispose(self->audioUnit);
-}
-
 static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self)
 {
     OSStatus err = AudioOutputUnitStart(self->audioUnit);
@@ -724,27 +707,26 @@ static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture *self)
 
 static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALCvoid *buffer, ALCuint samples)
 {
-    AudioBufferList *list;
+    union {
+        ALbyte _[sizeof(AudioBufferList) + sizeof(AudioBuffer)];
+        AudioBufferList list;
+    } audiobuf = { { 0 } };
     UInt32 frameCount;
     OSStatus err;
 
     // If no samples are requested, just return
-    if(samples == 0)
-        return ALC_NO_ERROR;
-
-    // Allocate a temporary AudioBufferList to use as the return resamples data
-    list = alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer));
+    if(samples == 0) return ALC_NO_ERROR;
 
     // Point the resampling buffer to the capture buffer
-    list->mNumberBuffers = 1;
-    list->mBuffers[0].mNumberChannels = self->format.mChannelsPerFrame;
-    list->mBuffers[0].mDataByteSize = samples * self->frameSize;
-    list->mBuffers[0].mData = buffer;
+    audiobuf.list.mNumberBuffers = 1;
+    audiobuf.list.mBuffers[0].mNumberChannels = self->format.mChannelsPerFrame;
+    audiobuf.list.mBuffers[0].mDataByteSize = samples * self->frameSize;
+    audiobuf.list.mBuffers[0].mData = buffer;
 
     // Resample into another AudioBufferList
     frameCount = samples;
     err = AudioConverterFillComplexBuffer(self->audioConverter,
-        ALCcoreAudioCapture_ConvertCallback, self, &frameCount, list, NULL
+        ALCcoreAudioCapture_ConvertCallback, self, &frameCount, &audiobuf.list, NULL
     );
     if(err != noErr)
     {

+ 72 - 54
libs/openal-soft/Alc/backends/dsound.c

@@ -34,6 +34,7 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "ringbuffer.h"
 #include "threads.h"
 #include "compat.h"
 #include "alstring.h"
@@ -184,16 +185,15 @@ typedef struct ALCdsoundPlayback {
     IDirectSoundNotify *Notifies;
     HANDLE             NotifyEvent;
 
-    volatile int killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } ALCdsoundPlayback;
 
 static int ALCdsoundPlayback_mixerProc(void *ptr);
 
 static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, Destruct)
+static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self);
 static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *name);
-static void ALCdsoundPlayback_close(ALCdsoundPlayback *self);
 static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self);
 static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self);
 static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self);
@@ -211,6 +211,35 @@ static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *devi
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCdsoundPlayback, ALCbackend, self);
+
+    self->DS = NULL;
+    self->PrimaryBuffer = NULL;
+    self->Buffer = NULL;
+    self->Notifies = NULL;
+    self->NotifyEvent = NULL;
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
+}
+
+static void ALCdsoundPlayback_Destruct(ALCdsoundPlayback *self)
+{
+    if(self->Notifies)
+        IDirectSoundNotify_Release(self->Notifies);
+    self->Notifies = NULL;
+    if(self->Buffer)
+        IDirectSoundBuffer_Release(self->Buffer);
+    self->Buffer = NULL;
+    if(self->PrimaryBuffer != NULL)
+        IDirectSoundBuffer_Release(self->PrimaryBuffer);
+    self->PrimaryBuffer = NULL;
+
+    if(self->DS)
+        IDirectSound_Release(self->DS);
+    self->DS = NULL;
+    if(self->NotifyEvent)
+        CloseHandle(self->NotifyEvent);
+    self->NotifyEvent = NULL;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
 
@@ -239,7 +268,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
     {
         ERR("Failed to get buffer caps: 0x%lx\n", err);
         ALCdevice_Lock(device);
-        aluHandleDisconnect(device);
+        aluHandleDisconnect(device, "Failure retrieving playback buffer info: 0x%lx", err);
         ALCdevice_Unlock(device);
         return 1;
     }
@@ -248,7 +277,8 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
     FragSize = device->UpdateSize * FrameSize;
 
     IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL);
-    while(!self->killNow)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         // Get current play cursor
         IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &PlayCursor, NULL);
@@ -263,7 +293,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
                 {
                     ERR("Failed to play buffer: 0x%lx\n", err);
                     ALCdevice_Lock(device);
-                    aluHandleDisconnect(device);
+                    aluHandleDisconnect(device, "Failure starting playback: 0x%lx", err);
                     ALCdevice_Unlock(device);
                     return 1;
                 }
@@ -311,7 +341,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
         {
             ERR("Buffer lock error: %#lx\n", err);
             ALCdevice_Lock(device);
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Failed to lock output buffer: 0x%lx", err);
             ALCdevice_Unlock(device);
             return 1;
         }
@@ -386,24 +416,6 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de
     return ALC_NO_ERROR;
 }
 
-static void ALCdsoundPlayback_close(ALCdsoundPlayback *self)
-{
-    if(self->Notifies)
-        IDirectSoundNotify_Release(self->Notifies);
-    self->Notifies = NULL;
-    if(self->Buffer)
-        IDirectSoundBuffer_Release(self->Buffer);
-    self->Buffer = NULL;
-    if(self->PrimaryBuffer != NULL)
-        IDirectSoundBuffer_Release(self->PrimaryBuffer);
-    self->PrimaryBuffer = NULL;
-
-    IDirectSound_Release(self->DS);
-    self->DS = NULL;
-    CloseHandle(self->NotifyEvent);
-    self->NotifyEvent = NULL;
-}
-
 static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -626,7 +638,7 @@ retry_open:
 
 static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self)
 {
-    self->killNow = 0;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, ALCdsoundPlayback_mixerProc, self) != althrd_success)
         return ALC_FALSE;
 
@@ -637,10 +649,8 @@ static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self)
 {
     int res;
 
-    if(self->killNow)
+    if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
-
-    self->killNow = 1;
     althrd_join(self->thread, &res);
 
     IDirectSoundBuffer_Stop(self->Buffer);
@@ -660,9 +670,8 @@ typedef struct ALCdsoundCapture {
 } ALCdsoundCapture;
 
 static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, Destruct)
+static void ALCdsoundCapture_Destruct(ALCdsoundCapture *self);
 static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *name);
-static void ALCdsoundCapture_close(ALCdsoundCapture *self);
 static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALCboolean, reset)
 static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self);
 static void ALCdsoundCapture_stop(ALCdsoundCapture *self);
@@ -679,6 +688,29 @@ static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCdsoundCapture, ALCbackend, self);
+
+    self->DSC = NULL;
+    self->DSCbuffer = NULL;
+    self->Ring = NULL;
+}
+
+static void ALCdsoundCapture_Destruct(ALCdsoundCapture *self)
+{
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = NULL;
+
+    if(self->DSCbuffer != NULL)
+    {
+        IDirectSoundCaptureBuffer_Stop(self->DSCbuffer);
+        IDirectSoundCaptureBuffer_Release(self->DSCbuffer);
+        self->DSCbuffer = NULL;
+    }
+
+    if(self->DSC)
+        IDirectSoundCapture_Release(self->DSC);
+    self->DSC = NULL;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
 
@@ -824,8 +856,8 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
         hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL);
     if(SUCCEEDED(hr))
     {
-         self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1,
-                                           InputType.Format.nBlockAlign);
+         self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates,
+                                           InputType.Format.nBlockAlign, false);
          if(self->Ring == NULL)
              hr = DSERR_OUTOFMEMORY;
     }
@@ -854,22 +886,6 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
     return ALC_NO_ERROR;
 }
 
-static void ALCdsoundCapture_close(ALCdsoundCapture *self)
-{
-    ll_ringbuffer_free(self->Ring);
-    self->Ring = NULL;
-
-    if(self->DSCbuffer != NULL)
-    {
-        IDirectSoundCaptureBuffer_Stop(self->DSCbuffer);
-        IDirectSoundCaptureBuffer_Release(self->DSCbuffer);
-        self->DSCbuffer = NULL;
-    }
-
-    IDirectSoundCapture_Release(self->DSC);
-    self->DSC = NULL;
-}
-
 static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self)
 {
     HRESULT hr;
@@ -878,7 +894,8 @@ static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self)
     if(FAILED(hr))
     {
         ERR("start failed: 0x%08lx\n", hr);
-        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice,
+                            "Failure starting capture: 0x%lx", hr);
         return ALC_FALSE;
     }
 
@@ -893,7 +910,8 @@ static void ALCdsoundCapture_stop(ALCdsoundCapture *self)
     if(FAILED(hr))
     {
         ERR("stop failed: 0x%08lx\n", hr);
-        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice,
+                            "Failure stopping capture: 0x%lx", hr);
     }
 }
 
@@ -912,7 +930,7 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
     DWORD FrameSize;
     HRESULT hr;
 
-    if(!device->Connected)
+    if(!ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
         goto done;
 
     FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
@@ -943,11 +961,11 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
     if(FAILED(hr))
     {
         ERR("update failed: 0x%08lx\n", hr);
-        aluHandleDisconnect(device);
+        aluHandleDisconnect(device, "Failure retrieving capture data: 0x%lx", hr);
     }
 
 done:
-    return ll_ringbuffer_read_space(self->Ring);
+    return (ALCuint)ll_ringbuffer_read_space(self->Ring);
 }
 
 

+ 24 - 57
libs/openal-soft/Alc/backends/jack.c

@@ -26,6 +26,8 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "alconfig.h"
+#include "ringbuffer.h"
 #include "threads.h"
 #include "compat.h"
 
@@ -148,9 +150,9 @@ typedef struct ALCjackPlayback {
     jack_port_t *Port[MAX_OUTPUT_CHANNELS];
 
     ll_ringbuffer_t *Ring;
-    alcnd_t Cond;
+    alsem_t Sem;
 
-    volatile int killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } ALCjackPlayback;
 
@@ -162,7 +164,6 @@ static int ALCjackPlayback_mixerProc(void *arg);
 static void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device);
 static void ALCjackPlayback_Destruct(ALCjackPlayback *self);
 static ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name);
-static void ALCjackPlayback_close(ALCjackPlayback *self);
 static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self);
 static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self);
 static void ALCjackPlayback_stop(ALCjackPlayback *self);
@@ -183,14 +184,14 @@ static void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device)
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCjackPlayback, ALCbackend, self);
 
-    alcnd_init(&self->Cond);
+    alsem_init(&self->Sem, 0);
 
     self->Client = NULL;
     for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
         self->Port[i] = NULL;
     self->Ring = NULL;
 
-    self->killNow = 1;
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
 }
 
 static void ALCjackPlayback_Destruct(ALCjackPlayback *self)
@@ -209,7 +210,7 @@ static void ALCjackPlayback_Destruct(ALCjackPlayback *self)
         self->Client = NULL;
     }
 
-    alcnd_destroy(&self->Cond);
+    alsem_destroy(&self->Sem);
 
     ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
@@ -228,19 +229,19 @@ static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg)
     bufsize = device->UpdateSize;
     if(ConfigValueUInt(alstr_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize))
         bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize);
-    bufsize += device->UpdateSize;
-    device->NumUpdates = bufsize / device->UpdateSize;
+    device->NumUpdates = (bufsize+device->UpdateSize) / device->UpdateSize;
 
     TRACE("%u update size x%u\n", device->UpdateSize, device->NumUpdates);
 
     ll_ringbuffer_free(self->Ring);
     self->Ring = ll_ringbuffer_create(bufsize,
-        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder),
+        true
     );
     if(!self->Ring)
     {
         ERR("Failed to reallocate ringbuffer\n");
-        aluHandleDisconnect(device);
+        aluHandleDisconnect(device, "Failed to reallocate %u-sample buffer", bufsize);
     }
     ALCjackPlayback_unlock(self);
     return 0;
@@ -286,7 +287,7 @@ static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg)
     }
 
     ll_ringbuffer_read_advance(self->Ring, total);
-    alcnd_signal(&self->Cond);
+    alsem_post(&self->Sem);
 
     if(numframes > total)
     {
@@ -311,27 +312,16 @@ static int ALCjackPlayback_mixerProc(void *arg)
     althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
     ALCjackPlayback_lock(self);
-    while(!self->killNow && device->Connected)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         ALuint todo, len1, len2;
 
-        /* NOTE: Unfortunately, there is an unavoidable race condition here.
-         * It's possible for the process() method to run, updating the read
-         * pointer and signaling the condition variable, in between the mixer
-         * loop checking the write size and waiting for the condition variable.
-         * This will cause the mixer loop to wait until the *next* process()
-         * invocation, most likely writing silence for it.
-         *
-         * However, this should only happen if the mixer is running behind
-         * anyway (as ideally we'll be asleep in alcnd_wait by the time the
-         * process() method is invoked), so this behavior is not unwarranted.
-         * It's unfortunate since it'll be wasting time sleeping that could be
-         * used to catch up, but there's no way around it without blocking in
-         * the process() method.
-         */
         if(ll_ringbuffer_write_space(self->Ring) < device->UpdateSize)
         {
-            alcnd_wait(&self->Cond, &STATIC_CAST(ALCbackend,self)->mMutex);
+            ALCjackPlayback_unlock(self);
+            alsem_wait(&self->Sem);
+            ALCjackPlayback_lock(self);
             continue;
         }
 
@@ -386,20 +376,6 @@ static ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCjackPlayback_close(ALCjackPlayback *self)
-{
-    ALuint i;
-
-    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
-    {
-        if(self->Port[i])
-            jack_port_unregister(self->Client, self->Port[i]);
-        self->Port[i] = NULL;
-    }
-    jack_client_close(self->Client);
-    self->Client = NULL;
-}
-
 static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -414,9 +390,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self)
     }
 
     /* Ignore the requested buffer metrics and just keep one JACK-sized buffer
-     * ready for when requested. Note that one period's worth of audio in the
-     * ring buffer will always be left unfilled because one element of the ring
-     * buffer will not be writeable, and we only write in period-sized chunks.
+     * ready for when requested.
      */
     device->Frequency = jack_get_sample_rate(self->Client);
     device->UpdateSize = jack_get_buffer_size(self->Client);
@@ -425,8 +399,7 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self)
     bufsize = device->UpdateSize;
     if(ConfigValueUInt(alstr_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize))
         bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize);
-    bufsize += device->UpdateSize;
-    device->NumUpdates = bufsize / device->UpdateSize;
+    device->NumUpdates = (bufsize+device->UpdateSize) / device->UpdateSize;
 
     /* Force 32-bit float output. */
     device->FmtType = DevFmtFloat;
@@ -461,7 +434,8 @@ static ALCboolean ALCjackPlayback_reset(ALCjackPlayback *self)
 
     ll_ringbuffer_free(self->Ring);
     self->Ring = ll_ringbuffer_create(bufsize,
-        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder),
+        true
     );
     if(!self->Ring)
     {
@@ -504,7 +478,7 @@ static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self)
     }
     jack_free(ports);
 
-    self->killNow = 0;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, ALCjackPlayback_mixerProc, self) != althrd_success)
     {
         jack_deactivate(self->Client);
@@ -518,17 +492,10 @@ static void ALCjackPlayback_stop(ALCjackPlayback *self)
 {
     int res;
 
-    if(self->killNow)
+    if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
 
-    self->killNow = 1;
-    /* Lock the backend to ensure we don't flag the mixer to die and signal the
-     * mixer to wake up in between it checking the flag and going to sleep and
-     * wait for a wakeup (potentially leading to it never waking back up to see
-     * the flag). */
-    ALCjackPlayback_lock(self);
-    ALCjackPlayback_unlock(self);
-    alcnd_signal(&self->Cond);
+    alsem_post(&self->Sem);
     althrd_join(self->thread, &res);
 
     jack_deactivate(self->Client);

+ 0 - 5
libs/openal-soft/Alc/backends/loopback.c

@@ -35,7 +35,6 @@ typedef struct ALCloopback {
 static void ALCloopback_Construct(ALCloopback *self, ALCdevice *device);
 static DECLARE_FORWARD(ALCloopback, ALCbackend, void, Destruct)
 static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name);
-static void ALCloopback_close(ALCloopback *self);
 static ALCboolean ALCloopback_reset(ALCloopback *self);
 static ALCboolean ALCloopback_start(ALCloopback *self);
 static void ALCloopback_stop(ALCloopback *self);
@@ -63,10 +62,6 @@ static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCloopback_close(ALCloopback* UNUSED(self))
-{
-}
-
 static ALCboolean ALCloopback_reset(ALCloopback *self)
 {
     SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice);

+ 7 - 11
libs/openal-soft/Alc/backends/null.c

@@ -36,7 +36,7 @@
 typedef struct ALCnullBackend {
     DERIVE_FROM_TYPE(ALCbackend);
 
-    volatile int killNow;
+    ATOMIC(int) killNow;
     althrd_t thread;
 } ALCnullBackend;
 
@@ -45,7 +45,6 @@ static int ALCnullBackend_mixerProc(void *ptr);
 static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device);
 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, Destruct)
 static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name);
-static void ALCnullBackend_close(ALCnullBackend *self);
 static ALCboolean ALCnullBackend_reset(ALCnullBackend *self);
 static ALCboolean ALCnullBackend_start(ALCnullBackend *self);
 static void ALCnullBackend_stop(ALCnullBackend *self);
@@ -66,6 +65,8 @@ static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCnullBackend, ALCbackend, self);
+
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
 }
 
 
@@ -87,7 +88,8 @@ static int ALCnullBackend_mixerProc(void *ptr)
         ERR("Failed to get starting time\n");
         return 1;
     }
-    while(!self->killNow && device->Connected)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
         {
@@ -135,10 +137,6 @@ static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCnullBackend_close(ALCnullBackend* UNUSED(self))
-{
-}
-
 static ALCboolean ALCnullBackend_reset(ALCnullBackend *self)
 {
     SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice);
@@ -147,7 +145,7 @@ static ALCboolean ALCnullBackend_reset(ALCnullBackend *self)
 
 static ALCboolean ALCnullBackend_start(ALCnullBackend *self)
 {
-    self->killNow = 0;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, ALCnullBackend_mixerProc, self) != althrd_success)
         return ALC_FALSE;
     return ALC_TRUE;
@@ -157,10 +155,8 @@ static void ALCnullBackend_stop(ALCnullBackend *self)
 {
     int res;
 
-    if(self->killNow)
+    if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
-
-    self->killNow = 1;
     althrd_join(self->thread, &res);
 }
 

+ 26 - 87
libs/openal-soft/Alc/backends/opensl.c

@@ -26,8 +26,9 @@
 
 #include "alMain.h"
 #include "alu.h"
-#include "compat.h"
+#include "ringbuffer.h"
 #include "threads.h"
+#include "compat.h"
 
 #include "backends/base.h"
 
@@ -145,7 +146,7 @@ typedef struct ALCopenslPlayback {
     SLObjectItf mBufferQueueObj;
 
     ll_ringbuffer_t *mRing;
-    alcnd_t mCond;
+    alsem_t mSem;
 
     ALsizei mFrameSize;
 
@@ -159,7 +160,6 @@ static int ALCopenslPlayback_mixerProc(void *arg);
 static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *device);
 static void ALCopenslPlayback_Destruct(ALCopenslPlayback *self);
 static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *name);
-static void ALCopenslPlayback_close(ALCopenslPlayback *self);
 static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self);
 static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self);
 static void ALCopenslPlayback_stop(ALCopenslPlayback *self);
@@ -184,7 +184,7 @@ static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *devi
     self->mBufferQueueObj = NULL;
 
     self->mRing = NULL;
-    alcnd_init(&self->mCond);
+    alsem_init(&self->mSem, 0);
 
     self->mFrameSize = 0;
 
@@ -197,19 +197,16 @@ static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self)
         VCALL0(self->mBufferQueueObj,Destroy)();
     self->mBufferQueueObj = NULL;
 
-    if(self->mOutputMix != NULL)
+    if(self->mOutputMix)
         VCALL0(self->mOutputMix,Destroy)();
     self->mOutputMix = NULL;
 
-    if(self->mEngineObj != NULL)
+    if(self->mEngineObj)
         VCALL0(self->mEngineObj,Destroy)();
     self->mEngineObj = NULL;
     self->mEngine = NULL;
 
-    ll_ringbuffer_free(self->mRing);
-    self->mRing = NULL;
-
-    alcnd_destroy(&self->mCond);
+    alsem_destroy(&self->mSem);
 
     ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
@@ -230,7 +227,7 @@ static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq),
      */
     ll_ringbuffer_read_advance(self->mRing, 1);
 
-    alcnd_signal(&self->mCond);
+    alsem_post(&self->mSem);
 }
 
 
@@ -242,7 +239,6 @@ static int ALCopenslPlayback_mixerProc(void *arg)
     ll_ringbuffer_data_t data[2];
     SLPlayItf player;
     SLresult result;
-    size_t padding;
 
     SetRTPriority();
     althrd_setname(althrd_current(), MIXER_THREAD_NAME);
@@ -258,22 +254,18 @@ static int ALCopenslPlayback_mixerProc(void *arg)
     if(SL_RESULT_SUCCESS != result)
     {
         ALCopenslPlayback_lock(self);
-        aluHandleDisconnect(device);
+        aluHandleDisconnect(device, "Failed to get playback buffer: 0x%08x", result);
         ALCopenslPlayback_unlock(self);
         return 1;
     }
 
-    /* NOTE: The ringbuffer will be larger than the desired buffer metrics.
-     * Calculate the amount of extra space so we know how much to keep unused.
-     */
-    padding = ll_ringbuffer_write_space(self->mRing) - device->NumUpdates;
-
     ALCopenslPlayback_lock(self);
-    while(ATOMIC_LOAD_SEQ(&self->mKillNow) == AL_FALSE && device->Connected)
+    while(!ATOMIC_LOAD(&self->mKillNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         size_t todo, len0, len1;
 
-        if(ll_ringbuffer_write_space(self->mRing) <= padding)
+        if(ll_ringbuffer_write_space(self->mRing) == 0)
         {
             SLuint32 state = 0;
 
@@ -286,34 +278,21 @@ static int ALCopenslPlayback_mixerProc(void *arg)
             }
             if(SL_RESULT_SUCCESS != result)
             {
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Failed to start platback: 0x%08x", result);
                 break;
             }
 
-            /* NOTE: Unfortunately, there is an unavoidable race condition
-             * here. It's possible for the process() method to run, updating
-             * the read pointer and signaling the condition variable, in
-             * between checking the write size and waiting for the condition
-             * variable here. This will cause alcnd_wait to wait until the
-             * *next* process() invocation signals the condition variable
-             * again.
-             *
-             * However, this should only happen if the mixer is running behind
-             * anyway (as ideally we'll be asleep in alcnd_wait by the time the
-             * process() method is invoked), so this behavior is not completely
-             * unwarranted. It's unfortunate since it'll be wasting time
-             * sleeping that could be used to catch up, but there's no way
-             * around it without blocking in the process() method.
-             */
-            if(ll_ringbuffer_write_space(self->mRing) <= padding)
+            if(ll_ringbuffer_write_space(self->mRing) == 0)
             {
-                alcnd_wait(&self->mCond, &STATIC_CAST(ALCbackend,self)->mMutex);
+                ALCopenslPlayback_unlock(self);
+                alsem_wait(&self->mSem);
+                ALCopenslPlayback_lock(self);
                 continue;
             }
         }
 
         ll_ringbuffer_get_write_vector(self->mRing, data);
-        todo = data[0].len+data[1].len - padding;
+        todo = data[0].len+data[1].len;
 
         len0 = minu(todo, data[0].len);
         len1 = minu(todo-len0, data[1].len);
@@ -402,20 +381,6 @@ static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *na
     return ALC_NO_ERROR;
 }
 
-static void ALCopenslPlayback_close(ALCopenslPlayback *self)
-{
-    if(self->mBufferQueueObj != NULL)
-        VCALL0(self->mBufferQueueObj,Destroy)();
-    self->mBufferQueueObj = NULL;
-
-    VCALL0(self->mOutputMix,Destroy)();
-    self->mOutputMix = NULL;
-
-    VCALL0(self->mEngineObj,Destroy)();
-    self->mEngineObj = NULL;
-    self->mEngine = NULL;
-}
-
 static ALCboolean ALCopenslPlayback_reset(ALCopenslPlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
@@ -601,12 +566,8 @@ static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self)
     SLresult result;
 
     ll_ringbuffer_free(self->mRing);
-    /* NOTE: Add an extra update since one period's worth of audio in the ring
-     * buffer will always be left unfilled because one element of the ring
-     * buffer will not be writeable, and we only write in period-sized chunks.
-     */
-    self->mRing = ll_ringbuffer_create(device->NumUpdates + 1,
-                                       self->mFrameSize*device->UpdateSize);
+    self->mRing = ll_ringbuffer_create(device->NumUpdates, self->mFrameSize*device->UpdateSize,
+                                       true);
 
     result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
                                                        &bufferQueue);
@@ -640,14 +601,7 @@ static void ALCopenslPlayback_stop(ALCopenslPlayback *self)
     if(ATOMIC_EXCHANGE_SEQ(&self->mKillNow, AL_TRUE))
         return;
 
-    /* Lock the backend to ensure we don't flag the mixer to die and signal the
-     * mixer to wake up in between it checking the flag and going to sleep and
-     * wait for a wakeup (potentially leading to it never waking back up to see
-     * the flag).
-     */
-    ALCopenslPlayback_lock(self);
-    ALCopenslPlayback_unlock(self);
-    alcnd_signal(&self->mCond);
+    alsem_post(&self->mSem);
     althrd_join(self->mThread, &res);
 
     result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
@@ -721,7 +675,6 @@ static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf bq, void *con
 static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device);
 static void ALCopenslCapture_Destruct(ALCopenslCapture *self);
 static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name);
-static void ALCopenslCapture_close(ALCopenslCapture *self);
 static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, ALCboolean, reset)
 static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self);
 static void ALCopenslCapture_stop(ALCopenslCapture *self);
@@ -890,8 +843,8 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name
 
     if(SL_RESULT_SUCCESS == result)
     {
-        self->mRing = ll_ringbuffer_create(device->NumUpdates + 1,
-                                           device->UpdateSize * self->mFrameSize);
+        self->mRing = ll_ringbuffer_create(device->NumUpdates, device->UpdateSize*self->mFrameSize,
+                                           false);
 
         result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
                                                       &bufferQueue);
@@ -940,21 +893,6 @@ static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name
     return ALC_NO_ERROR;
 }
 
-static void ALCopenslCapture_close(ALCopenslCapture *self)
-{
-    ll_ringbuffer_free(self->mRing);
-    self->mRing = NULL;
-
-    if(self->mRecordObj != NULL)
-        VCALL0(self->mRecordObj,Destroy)();
-    self->mRecordObj = NULL;
-
-    if(self->mEngineObj != NULL)
-        VCALL0(self->mEngineObj,Destroy)();
-    self->mEngineObj = NULL;
-    self->mEngine = NULL;
-}
-
 static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self)
 {
     SLRecordItf record;
@@ -972,7 +910,8 @@ static ALCboolean ALCopenslCapture_start(ALCopenslCapture *self)
     if(SL_RESULT_SUCCESS != result)
     {
         ALCopenslCapture_lock(self);
-        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice,
+                            "Failed to start capture: 0x%08x", result);
         ALCopenslCapture_unlock(self);
         return ALC_FALSE;
     }
@@ -1055,7 +994,7 @@ static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid *
     if(SL_RESULT_SUCCESS != result)
     {
         ALCopenslCapture_lock(self);
-        aluHandleDisconnect(device);
+        aluHandleDisconnect(device, "Failed to update capture buffer: 0x%08x", result);
         ALCopenslCapture_unlock(self);
         return ALC_INVALID_DEVICE;
     }

+ 35 - 25
libs/openal-soft/Alc/backends/oss.c

@@ -35,6 +35,8 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "alconfig.h"
+#include "ringbuffer.h"
 #include "threads.h"
 #include "compat.h"
 
@@ -250,9 +252,8 @@ typedef struct ALCplaybackOSS {
 static int ALCplaybackOSS_mixerProc(void *ptr);
 
 static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, Destruct)
+static void ALCplaybackOSS_Destruct(ALCplaybackOSS *self);
 static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name);
-static void ALCplaybackOSS_close(ALCplaybackOSS *self);
 static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self);
 static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self);
 static void ALCplaybackOSS_stop(ALCplaybackOSS *self);
@@ -283,7 +284,8 @@ static int ALCplaybackOSS_mixerProc(void *ptr)
     frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     ALCplaybackOSS_lock(self);
-    while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         FD_ZERO(&wfds);
         FD_SET(self->fd, &wfds);
@@ -298,7 +300,7 @@ static int ALCplaybackOSS_mixerProc(void *ptr)
             if(errno == EINTR)
                 continue;
             ERR("select failed: %s\n", strerror(errno));
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Failed waiting for playback buffer: %s", strerror(errno));
             break;
         }
         else if(sret == 0)
@@ -318,7 +320,8 @@ static int ALCplaybackOSS_mixerProc(void *ptr)
                 if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
                     continue;
                 ERR("write failed: %s\n", strerror(errno));
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Failed writing playback samples: %s",
+                                    strerror(errno));
                 break;
             }
 
@@ -337,9 +340,19 @@ static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device)
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCplaybackOSS, ALCbackend, self);
 
+    self->fd = -1;
     ATOMIC_INIT(&self->killNow, AL_FALSE);
 }
 
+static void ALCplaybackOSS_Destruct(ALCplaybackOSS *self)
+{
+    if(self->fd != -1)
+        close(self->fd);
+    self->fd = -1;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
 static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name)
 {
     struct oss_device *dev = &oss_playback;
@@ -379,12 +392,6 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCplaybackOSS_close(ALCplaybackOSS *self)
-{
-    close(self->fd);
-    self->fd = -1;
-}
-
 static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -517,9 +524,8 @@ typedef struct ALCcaptureOSS {
 static int ALCcaptureOSS_recordProc(void *ptr);
 
 static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device);
-static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, Destruct)
+static void ALCcaptureOSS_Destruct(ALCcaptureOSS *self);
 static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name);
-static void ALCcaptureOSS_close(ALCcaptureOSS *self);
 static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALCboolean, reset)
 static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self);
 static void ALCcaptureOSS_stop(ALCcaptureOSS *self);
@@ -562,7 +568,7 @@ static int ALCcaptureOSS_recordProc(void *ptr)
             if(errno == EINTR)
                 continue;
             ERR("select failed: %s\n", strerror(errno));
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Failed to check capture samples: %s", strerror(errno));
             break;
         }
         else if(sret == 0)
@@ -579,7 +585,7 @@ static int ALCcaptureOSS_recordProc(void *ptr)
             {
                 ERR("read failed: %s\n", strerror(errno));
                 ALCcaptureOSS_lock(self);
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Failed reading capture samples: %s", strerror(errno));
                 ALCcaptureOSS_unlock(self);
                 break;
             }
@@ -596,9 +602,22 @@ static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device)
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCcaptureOSS, ALCbackend, self);
 
+    self->fd = -1;
+    self->ring = NULL;
     ATOMIC_INIT(&self->killNow, AL_FALSE);
 }
 
+static void ALCcaptureOSS_Destruct(ALCcaptureOSS *self)
+{
+    if(self->fd != -1)
+        close(self->fd);
+    self->fd = -1;
+
+    ll_ringbuffer_free(self->ring);
+    self->ring = NULL;
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
 static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -710,7 +729,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
         return ALC_INVALID_VALUE;
     }
 
-    self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, frameSize);
+    self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates, frameSize, false);
     if(!self->ring)
     {
         ERR("Ring buffer create failed\n");
@@ -724,15 +743,6 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCcaptureOSS_close(ALCcaptureOSS *self)
-{
-    close(self->fd);
-    self->fd = -1;
-
-    ll_ringbuffer_free(self->ring);
-    self->ring = NULL;
-}
-
 static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self)
 {
     ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);

+ 11 - 28
libs/openal-soft/Alc/backends/portaudio.c

@@ -26,6 +26,8 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "alconfig.h"
+#include "ringbuffer.h"
 #include "compat.h"
 
 #include "backends/base.h"
@@ -139,7 +141,6 @@ static int ALCportPlayback_WriteCallback(const void *inputBuffer, void *outputBu
 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);
@@ -163,8 +164,9 @@ static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device)
 
 static void ALCportPlayback_Destruct(ALCportPlayback *self)
 {
-    if(self->stream)
-        Pa_CloseStream(self->stream);
+    PaError err = self->stream ? Pa_CloseStream(self->stream) : paNoError;
+    if(err != paNoError)
+        ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
     self->stream = NULL;
 
     ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
@@ -251,14 +253,6 @@ retry_open:
 
 }
 
-static void ALCportPlayback_close(ALCportPlayback *self)
-{
-    PaError err = Pa_CloseStream(self->stream);
-    if(err != paNoError)
-        ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
-    self->stream = NULL;
-}
-
 static ALCboolean ALCportPlayback_reset(ALCportPlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -336,7 +330,6 @@ static int ALCportCapture_ReadCallback(const void *inputBuffer, void *outputBuff
 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);
@@ -356,16 +349,17 @@ static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device)
     SET_VTABLE2(ALCportCapture, ALCbackend, self);
 
     self->stream = NULL;
+    self->ring = NULL;
 }
 
 static void ALCportCapture_Destruct(ALCportCapture *self)
 {
-    if(self->stream)
-        Pa_CloseStream(self->stream);
+    PaError err = self->stream ? Pa_CloseStream(self->stream) : paNoError;
+    if(err != paNoError)
+        ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
     self->stream = NULL;
 
-    if(self->ring)
-        ll_ringbuffer_free(self->ring);
+    ll_ringbuffer_free(self->ring);
     self->ring = NULL;
 
     ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
@@ -401,7 +395,7 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name)
     samples = maxu(samples, 100 * device->Frequency / 1000);
     frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
-    self->ring = ll_ringbuffer_create(samples, frame_size);
+    self->ring = ll_ringbuffer_create(samples, frame_size, false);
     if(self->ring == NULL) return ALC_INVALID_VALUE;
 
     self->params.device = -1;
@@ -450,17 +444,6 @@ static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCportCapture_close(ALCportCapture *self)
-{
-    PaError err = Pa_CloseStream(self->stream);
-    if(err != paNoError)
-        ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
-    self->stream = NULL;
-
-    ll_ringbuffer_free(self->ring);
-    self->ring = NULL;
-}
-
 
 static ALCboolean ALCportCapture_start(ALCportCapture *self)
 {

+ 65 - 71
libs/openal-soft/Alc/backends/pulseaudio.c

@@ -25,6 +25,7 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "alconfig.h"
 #include "threads.h"
 #include "compat.h"
 
@@ -333,18 +334,20 @@ static void wait_for_operation(pa_operation *op, pa_threaded_mainloop *loop)
 static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent)
 {
     const char *name = "OpenAL Soft";
-    char path_name[PATH_MAX];
+    al_string binname = AL_STRING_INIT_STATIC();
     pa_context_state_t state;
     pa_context *context;
     int err;
 
-    if(pa_get_binary_name(path_name, sizeof(path_name)))
-        name = pa_path_get_filename(path_name);
+    GetProcBinary(NULL, &binname);
+    if(!alstr_empty(binname))
+        name = alstr_get_cstr(binname);
 
     context = pa_context_new(pa_threaded_mainloop_get_api(loop), name);
     if(!context)
     {
         ERR("pa_context_new() failed\n");
+        alstr_reset(&binname);
         return NULL;
     }
 
@@ -371,9 +374,10 @@ static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent)
         if(!silent)
             ERR("Context did not connect: %s\n", pa_strerror(err));
         pa_context_unref(context);
-        return NULL;
+        context = NULL;
     }
 
+    alstr_reset(&binname);
     return context;
 }
 
@@ -468,7 +472,7 @@ typedef struct ALCpulsePlayback {
     pa_stream *stream;
     pa_context *context;
 
-    volatile ALboolean killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } ALCpulsePlayback;
 
@@ -491,7 +495,6 @@ static int ALCpulsePlayback_mixerProc(void *ptr);
 static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device);
 static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self);
 static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name);
-static void ALCpulsePlayback_close(ALCpulsePlayback *self);
 static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self);
 static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self);
 static void ALCpulsePlayback_stop(ALCpulsePlayback *self);
@@ -510,11 +513,20 @@ static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCpulsePlayback, ALCbackend, self);
 
+    self->loop = NULL;
     AL_STRING_INIT(self->device_name);
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
 }
 
 static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self)
 {
+    if(self->loop)
+    {
+        pulse_close(self->loop, self->context, self->stream);
+        self->loop = NULL;
+        self->context = NULL;
+        self->stream = NULL;
+    }
     AL_STRING_DEINIT(self->device_name);
     ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
@@ -639,7 +651,7 @@ static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pda
     if(pa_context_get_state(context) == PA_CONTEXT_FAILED)
     {
         ERR("Received context failure!\n");
-        aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice, "Playback state failure");
     }
     pa_threaded_mainloop_signal(self->loop, 0);
 }
@@ -650,7 +662,7 @@ static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata)
     if(pa_stream_get_state(stream) == PA_STREAM_FAILED)
     {
         ERR("Received stream failure!\n");
-        aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice, "Playback stream failure");
     }
     pa_threaded_mainloop_signal(self->loop, 0);
 }
@@ -818,13 +830,17 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
     pa_threaded_mainloop_lock(self->loop);
     frame_size = pa_frame_size(&self->spec);
 
-    while(!self->killNow && device->Connected)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
+        void *buf;
+        int ret;
+
         len = pa_stream_writable_size(self->stream);
         if(len < 0)
         {
             ERR("Failed to get writable size: %ld", (long)len);
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Failed to get writable size: %ld", (long)len);
             break;
         }
 
@@ -850,31 +866,16 @@ static int ALCpulsePlayback_mixerProc(void *ptr)
             pa_threaded_mainloop_wait(self->loop);
             continue;
         }
+
         len -= len%self->attr.minreq;
+        len -= len%frame_size;
 
-        while(len > 0)
-        {
-            size_t newlen = len;
-            int ret;
-            void *buf;
-            pa_free_cb_t free_func = NULL;
+        buf = pa_xmalloc(len);
 
-            if(pa_stream_begin_write(self->stream, &buf, &newlen) < 0)
-            {
-                buf = pa_xmalloc(newlen);
-                free_func = pa_xfree;
-            }
+        aluMixData(device, buf, len/frame_size);
 
-            aluMixData(device, buf, newlen/frame_size);
-
-            ret = pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE);
-            if(ret != PA_OK)
-            {
-                ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
-                break;
-            }
-            len -= newlen;
-        }
+        ret = pa_stream_write(self->stream, buf, len, pa_xfree, 0, PA_SEEK_RELATIVE);
+        if(ret != PA_OK) ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret));
     }
     pa_threaded_mainloop_unlock(self->loop);
 
@@ -952,16 +953,6 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name
     return ALC_NO_ERROR;
 }
 
-static void ALCpulsePlayback_close(ALCpulsePlayback *self)
-{
-    pulse_close(self->loop, self->context, self->stream);
-    self->loop = NULL;
-    self->context = NULL;
-    self->stream = NULL;
-
-    alstr_clear(&self->device_name);
-}
-
 static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
@@ -1138,7 +1129,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self)
 
 static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self)
 {
-    self->killNow = AL_FALSE;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, ALCpulsePlayback_mixerProc, self) != althrd_success)
         return ALC_FALSE;
     return ALC_TRUE;
@@ -1149,10 +1140,9 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self)
     pa_operation *o;
     int res;
 
-    if(!self->stream || self->killNow)
+    if(!self->stream || ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
 
-    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
@@ -1174,13 +1164,16 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self)
 
 static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self)
 {
-    pa_usec_t latency = 0;
     ClockLatency ret;
+    pa_usec_t latency;
     int neg, err;
 
     pa_threaded_mainloop_lock(self->loop);
     ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice);
-    if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0)
+    err = pa_stream_get_latency(self->stream, &latency, &neg);
+    pa_threaded_mainloop_unlock(self->loop);
+
+    if(UNLIKELY(err != 0))
     {
         /* FIXME: if err = -PA_ERR_NODATA, it means we were called too soon
          * after starting the stream and no timing info has been received from
@@ -1191,9 +1184,9 @@ static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self)
         latency = 0;
         neg = 0;
     }
-    if(neg) latency = 0;
-    ret.Latency = minu64(latency, U64(0xffffffffffffffff)/1000) * 1000;
-    pa_threaded_mainloop_unlock(self->loop);
+    else if(UNLIKELY(neg))
+        latency = 0;
+    ret.Latency = (ALint64)minu64(latency, U64(0x7fffffffffffffff)/1000) * 1000;
 
     return ret;
 }
@@ -1245,7 +1238,6 @@ static pa_stream *ALCpulseCapture_connectStream(const char *device_name,
 static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device);
 static void ALCpulseCapture_Destruct(ALCpulseCapture *self);
 static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name);
-static void ALCpulseCapture_close(ALCpulseCapture *self);
 static DECLARE_FORWARD(ALCpulseCapture, ALCbackend, ALCboolean, reset)
 static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self);
 static void ALCpulseCapture_stop(ALCpulseCapture *self);
@@ -1264,11 +1256,19 @@ static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device)
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCpulseCapture, ALCbackend, self);
 
+    self->loop = NULL;
     AL_STRING_INIT(self->device_name);
 }
 
 static void ALCpulseCapture_Destruct(ALCpulseCapture *self)
 {
+    if(self->loop)
+    {
+        pulse_close(self->loop, self->context, self->stream);
+        self->loop = NULL;
+        self->context = NULL;
+        self->stream = NULL;
+    }
     AL_STRING_DEINIT(self->device_name);
     ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
@@ -1380,7 +1380,7 @@ static void ALCpulseCapture_contextStateCallback(pa_context *context, void *pdat
     if(pa_context_get_state(context) == PA_CONTEXT_FAILED)
     {
         ERR("Received context failure!\n");
-        aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice, "Capture state failure");
     }
     pa_threaded_mainloop_signal(self->loop, 0);
 }
@@ -1391,7 +1391,7 @@ static void ALCpulseCapture_streamStateCallback(pa_stream *stream, void *pdata)
     if(pa_stream_get_state(stream) == PA_STREAM_FAILED)
     {
         ERR("Received stream failure!\n");
-        aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice, "Capture stream failure");
     }
     pa_threaded_mainloop_signal(self->loop, 0);
 }
@@ -1615,16 +1615,6 @@ fail:
     return ALC_INVALID_VALUE;
 }
 
-static void ALCpulseCapture_close(ALCpulseCapture *self)
-{
-    pulse_close(self->loop, self->context, self->stream);
-    self->loop = NULL;
-    self->context = NULL;
-    self->stream = NULL;
-
-    alstr_clear(&self->device_name);
-}
-
 static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self)
 {
     pa_operation *o;
@@ -1664,14 +1654,15 @@ static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *bu
             state = pa_stream_get_state(self->stream);
             if(!PA_STREAM_IS_GOOD(state))
             {
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Bad capture state: %u", state);
                 break;
             }
             if(pa_stream_peek(self->stream, &self->cap_store, &self->cap_len) < 0)
             {
                 ERR("pa_stream_peek() failed: %s\n",
                     pa_strerror(pa_context_errno(self->context)));
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Failed retrieving capture samples: %s",
+                                    pa_strerror(pa_context_errno(self->context)));
                 break;
             }
             self->cap_remain = self->cap_len;
@@ -1704,7 +1695,7 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self)
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
     size_t readable = self->cap_remain;
 
-    if(device->Connected)
+    if(ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         ssize_t got;
         pa_threaded_mainloop_lock(self->loop);
@@ -1712,7 +1703,7 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self)
         if(got < 0)
         {
             ERR("pa_stream_readable_size() failed: %s\n", pa_strerror(got));
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Failed getting readable size: %s", pa_strerror(got));
         }
         else if((size_t)got > self->cap_len)
             readable += got - self->cap_len;
@@ -1727,21 +1718,24 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self)
 
 static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self)
 {
-    pa_usec_t latency = 0;
     ClockLatency ret;
+    pa_usec_t latency;
     int neg, err;
 
     pa_threaded_mainloop_lock(self->loop);
     ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice);
-    if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0)
+    err = pa_stream_get_latency(self->stream, &latency, &neg);
+    pa_threaded_mainloop_unlock(self->loop);
+
+    if(UNLIKELY(err != 0))
     {
         ERR("Failed to get stream latency: 0x%x\n", err);
         latency = 0;
         neg = 0;
     }
-    if(neg) latency = 0;
-    ret.Latency = minu64(latency, U64(0xffffffffffffffff)/1000) * 1000;
-    pa_threaded_mainloop_unlock(self->loop);
+    else if(UNLIKELY(neg))
+        latency = 0;
+    ret.Latency = (ALint64)minu64(latency, U64(0x7fffffffffffffff)/1000) * 1000;
 
     return ret;
 }

+ 28 - 24
libs/openal-soft/Alc/backends/qsa.c

@@ -46,7 +46,7 @@ typedef struct {
     ALvoid* buffer;
     ALsizei size;
 
-    volatile int killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } qsa_data;
 
@@ -166,9 +166,8 @@ typedef struct PlaybackWrapper {
 } PlaybackWrapper;
 
 static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device);
-static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct)
+static void PlaybackWrapper_Destruct(PlaybackWrapper *self);
 static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name);
-static void PlaybackWrapper_close(PlaybackWrapper *self);
 static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self);
 static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self);
 static void PlaybackWrapper_stop(PlaybackWrapper *self);
@@ -207,7 +206,7 @@ FORCE_ALIGN static int qsa_proc_playback(void *ptr)
     );
 
     V0(device->Backend,lock)();
-    while(!data->killNow)
+    while(!ATOMIC_LOAD(&data->killNow, almemory_order_acquire))
     {
         FD_ZERO(&wfds);
         FD_SET(data->audio_fd, &wfds);
@@ -221,7 +220,7 @@ FORCE_ALIGN static int qsa_proc_playback(void *ptr)
         if(sret == -1)
         {
             ERR("select error: %s\n", strerror(errno));
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Failed waiting for playback buffer: %s", strerror(errno));
             break;
         }
         if(sret == 0)
@@ -233,7 +232,7 @@ FORCE_ALIGN static int qsa_proc_playback(void *ptr)
         len = data->size;
         write_ptr = data->buffer;
         aluMixData(device, write_ptr, len/frame_size);
-        while(len>0 && !data->killNow)
+        while(len>0 && !ATOMIC_LOAD(&data->killNow, almemory_order_acquire))
         {
             int wrote = snd_pcm_plugin_write(data->pcmHandle, write_ptr, len);
             if(wrote <= 0)
@@ -252,7 +251,7 @@ FORCE_ALIGN static int qsa_proc_playback(void *ptr)
                 {
                     if(snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK) < 0)
                     {
-                        aluHandleDisconnect(device);
+                        aluHandleDisconnect(device, "Playback recovery failed");
                         break;
                     }
                 }
@@ -283,6 +282,7 @@ static ALCenum qsa_open_playback(PlaybackWrapper *self, const ALCchar* deviceNam
     data = (qsa_data*)calloc(1, sizeof(qsa_data));
     if(data == NULL)
         return ALC_OUT_OF_MEMORY;
+    ATOMIC_INIT(&data->killNow, AL_TRUE);
 
     if(!deviceName)
         deviceName = qsaDevice;
@@ -596,7 +596,7 @@ static ALCboolean qsa_start_playback(PlaybackWrapper *self)
 {
     qsa_data *data = self->ExtraData;
 
-    data->killNow = 0;
+    ATOMIC_STORE(&data->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&data->thread, qsa_proc_playback, self) != althrd_success)
         return ALC_FALSE;
 
@@ -608,10 +608,8 @@ static void qsa_stop_playback(PlaybackWrapper *self)
     qsa_data *data = self->ExtraData;
     int res;
 
-    if(data->killNow)
+    if(ATOMIC_EXCHANGE(&data->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
-
-    data->killNow = 1;
     althrd_join(data->thread, &res);
 }
 
@@ -624,14 +622,17 @@ static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device)
     self->ExtraData = NULL;
 }
 
-static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name)
+static void PlaybackWrapper_Destruct(PlaybackWrapper *self)
 {
-    return qsa_open_playback(self, name);
+    if(self->ExtraData)
+        qsa_close_playback(self);
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
-static void PlaybackWrapper_close(PlaybackWrapper *self)
+static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name)
 {
-    qsa_close_playback(self);
+    return qsa_open_playback(self, name);
 }
 
 static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self)
@@ -661,9 +662,8 @@ typedef struct CaptureWrapper {
 } CaptureWrapper;
 
 static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device);
-static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct)
+static void CaptureWrapper_Destruct(CaptureWrapper *self);
 static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name);
-static void CaptureWrapper_close(CaptureWrapper *self);
 static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset)
 static ALCboolean CaptureWrapper_start(CaptureWrapper *self);
 static void CaptureWrapper_stop(CaptureWrapper *self);
@@ -846,7 +846,7 @@ static ALCuint qsa_available_samples(CaptureWrapper *self)
         if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
         {
             ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Failed capture recovery: %s", snd_strerror(rstatus));
             return 0;
         }
 
@@ -889,7 +889,7 @@ static ALCenum qsa_capture_samples(CaptureWrapper *self, ALCvoid *buffer, ALCuin
         switch (selectret)
         {
             case -1:
-                 aluHandleDisconnect(device);
+                 aluHandleDisconnect(device, "Failed to check capture samples");
                  return ALC_INVALID_DEVICE;
             case 0:
                  break;
@@ -920,7 +920,8 @@ static ALCenum qsa_capture_samples(CaptureWrapper *self, ALCvoid *buffer, ALCuin
                 if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
                 {
                     ERR("capture prepare failed: %s\n", snd_strerror(rstatus));
-                    aluHandleDisconnect(device);
+                    aluHandleDisconnect(device, "Failed capture recovery: %s",
+                                        snd_strerror(rstatus));
                     return ALC_INVALID_DEVICE;
                 }
                 snd_pcm_capture_go(data->pcmHandle);
@@ -945,14 +946,17 @@ static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device)
     self->ExtraData = NULL;
 }
 
-static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name)
+static void CaptureWrapper_Destruct(CaptureWrapper *self)
 {
-    return qsa_open_capture(self, name);
+    if(self->ExtraData)
+        qsa_close_capture(self);
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
-static void CaptureWrapper_close(CaptureWrapper *self)
+static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name)
 {
-    qsa_close_capture(self);
+    return qsa_open_capture(self, name);
 }
 
 static ALCboolean CaptureWrapper_start(CaptureWrapper *self)

+ 287 - 0
libs/openal-soft/Alc/backends/sdl2.c

@@ -0,0 +1,287 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 2018 by authors.
+ * This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <SDL2/SDL.h>
+
+#include "alMain.h"
+#include "alu.h"
+#include "threads.h"
+#include "compat.h"
+
+#include "backends/base.h"
+
+
+#ifdef _WIN32
+#define DEVNAME_PREFIX "OpenAL Soft on "
+#else
+#define DEVNAME_PREFIX ""
+#endif
+
+typedef struct ALCsdl2Backend {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    SDL_AudioDeviceID deviceID;
+    ALsizei frameSize;
+
+    ALuint Frequency;
+    enum DevFmtChannels FmtChans;
+    enum DevFmtType     FmtType;
+    ALuint UpdateSize;
+} ALCsdl2Backend;
+
+static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device);
+static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self);
+static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name);
+static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self);
+static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self);
+static void ALCsdl2Backend_stop(ALCsdl2Backend *self);
+static DECLARE_FORWARD2(ALCsdl2Backend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCsdl2Backend, ALCbackend, ClockLatency, getClockLatency)
+static void ALCsdl2Backend_lock(ALCsdl2Backend *self);
+static void ALCsdl2Backend_unlock(ALCsdl2Backend *self);
+DECLARE_DEFAULT_ALLOCATORS(ALCsdl2Backend)
+
+DEFINE_ALCBACKEND_VTABLE(ALCsdl2Backend);
+
+static const ALCchar defaultDeviceName[] = DEVNAME_PREFIX "Default Device";
+
+static void ALCsdl2Backend_Construct(ALCsdl2Backend *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCsdl2Backend, ALCbackend, self);
+
+    self->deviceID = 0;
+    self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+    self->Frequency = device->Frequency;
+    self->FmtChans = device->FmtChans;
+    self->FmtType = device->FmtType;
+    self->UpdateSize = device->UpdateSize;
+}
+
+static void ALCsdl2Backend_Destruct(ALCsdl2Backend *self)
+{
+    if(self->deviceID)
+        SDL_CloseAudioDevice(self->deviceID);
+    self->deviceID = 0;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static void ALCsdl2Backend_audioCallback(void *ptr, Uint8 *stream, int len)
+{
+    ALCsdl2Backend *self = (ALCsdl2Backend*)ptr;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+
+    assert((len % self->frameSize) == 0);
+    aluMixData(device, stream, len / self->frameSize);
+}
+
+static ALCenum ALCsdl2Backend_open(ALCsdl2Backend *self, const ALCchar *name)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    SDL_AudioSpec want, have;
+
+    SDL_zero(want);
+    SDL_zero(have);
+
+    want.freq = device->Frequency;
+    switch(device->FmtType)
+    {
+        case DevFmtUByte: want.format = AUDIO_U8; break;
+        case DevFmtByte: want.format = AUDIO_S8; break;
+        case DevFmtUShort: want.format = AUDIO_U16SYS; break;
+        case DevFmtShort: want.format = AUDIO_S16SYS; break;
+        case DevFmtUInt: /* fall-through */
+        case DevFmtInt: want.format = AUDIO_S32SYS; break;
+        case DevFmtFloat: want.format = AUDIO_F32; break;
+    }
+    want.channels = (device->FmtChans == DevFmtMono) ? 1 : 2;
+    want.samples = device->UpdateSize;
+    want.callback = ALCsdl2Backend_audioCallback;
+    want.userdata = self;
+
+    /* Passing NULL to SDL_OpenAudioDevice opens a default, which isn't
+     * necessarily the first in the list.
+     */
+    if(!name || strcmp(name, defaultDeviceName) == 0)
+        self->deviceID = SDL_OpenAudioDevice(NULL, SDL_FALSE, &want, &have,
+                                             SDL_AUDIO_ALLOW_ANY_CHANGE);
+    else
+    {
+        const size_t prefix_len = strlen(DEVNAME_PREFIX);
+        if(strncmp(name, DEVNAME_PREFIX, prefix_len) == 0)
+            self->deviceID = SDL_OpenAudioDevice(name+prefix_len, SDL_FALSE, &want, &have,
+                                                 SDL_AUDIO_ALLOW_ANY_CHANGE);
+        else
+            self->deviceID = SDL_OpenAudioDevice(name, SDL_FALSE, &want, &have,
+                                                 SDL_AUDIO_ALLOW_ANY_CHANGE);
+    }
+    if(self->deviceID == 0)
+        return ALC_INVALID_VALUE;
+
+    device->Frequency = have.freq;
+    if(have.channels == 1)
+        device->FmtChans = DevFmtMono;
+    else if(have.channels == 2)
+        device->FmtChans = DevFmtStereo;
+    else
+    {
+        ERR("Got unhandled SDL channel count: %d\n", (int)have.channels);
+        return ALC_INVALID_VALUE;
+    }
+    switch(have.format)
+    {
+        case AUDIO_U8:     device->FmtType = DevFmtUByte;  break;
+        case AUDIO_S8:     device->FmtType = DevFmtByte;   break;
+        case AUDIO_U16SYS: device->FmtType = DevFmtUShort; break;
+        case AUDIO_S16SYS: device->FmtType = DevFmtShort;  break;
+        case AUDIO_S32SYS: device->FmtType = DevFmtInt;    break;
+        case AUDIO_F32SYS: device->FmtType = DevFmtFloat;  break;
+        default:
+            ERR("Got unsupported SDL format: 0x%04x\n", have.format);
+            return ALC_INVALID_VALUE;
+    }
+    device->UpdateSize = have.samples;
+    device->NumUpdates = 2; /* SDL always (tries to) use two periods. */
+
+    self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+    self->Frequency = device->Frequency;
+    self->FmtChans = device->FmtChans;
+    self->FmtType = device->FmtType;
+    self->UpdateSize = device->UpdateSize;
+
+    alstr_copy_cstr(&device->DeviceName, name ? name : defaultDeviceName);
+
+    return ALC_NO_ERROR;
+}
+
+static ALCboolean ALCsdl2Backend_reset(ALCsdl2Backend *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    device->Frequency = self->Frequency;
+    device->FmtChans = self->FmtChans;
+    device->FmtType = self->FmtType;
+    device->UpdateSize = self->UpdateSize;
+    device->NumUpdates = 2;
+    SetDefaultWFXChannelOrder(device);
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCsdl2Backend_start(ALCsdl2Backend *self)
+{
+    SDL_PauseAudioDevice(self->deviceID, 0);
+    return ALC_TRUE;
+}
+
+static void ALCsdl2Backend_stop(ALCsdl2Backend *self)
+{
+    SDL_PauseAudioDevice(self->deviceID, 1);
+}
+
+static void ALCsdl2Backend_lock(ALCsdl2Backend *self)
+{
+    SDL_LockAudioDevice(self->deviceID);
+}
+
+static void ALCsdl2Backend_unlock(ALCsdl2Backend *self)
+{
+    SDL_UnlockAudioDevice(self->deviceID);
+}
+
+
+typedef struct ALCsdl2BackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCsdl2BackendFactory;
+#define ALCsdl2BACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCsdl2BackendFactory, ALCbackendFactory) } }
+
+ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void);
+
+static ALCboolean ALCsdl2BackendFactory_init(ALCsdl2BackendFactory *self);
+static void ALCsdl2BackendFactory_deinit(ALCsdl2BackendFactory *self);
+static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory *self, ALCbackend_Type type);
+static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCsdl2BackendFactory_createBackend(ALCsdl2BackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsdl2BackendFactory);
+
+
+ALCbackendFactory *ALCsdl2BackendFactory_getFactory(void)
+{
+    static ALCsdl2BackendFactory factory = ALCsdl2BACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}
+
+
+static ALCboolean ALCsdl2BackendFactory_init(ALCsdl2BackendFactory* UNUSED(self))
+{
+    if(SDL_InitSubSystem(SDL_INIT_AUDIO) == 0)
+        return AL_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCsdl2BackendFactory_deinit(ALCsdl2BackendFactory* UNUSED(self))
+{
+    SDL_QuitSubSystem(SDL_INIT_AUDIO);
+}
+
+static ALCboolean ALCsdl2BackendFactory_querySupport(ALCsdl2BackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCsdl2BackendFactory_probe(ALCsdl2BackendFactory* UNUSED(self), enum DevProbe type)
+{
+    int num_devices, i;
+    al_string name;
+
+    if(type != ALL_DEVICE_PROBE)
+        return;
+
+    AL_STRING_INIT(name);
+    num_devices = SDL_GetNumAudioDevices(SDL_FALSE);
+
+    AppendAllDevicesList(defaultDeviceName);
+    for(i = 0;i < num_devices;++i)
+    {
+        alstr_copy_cstr(&name, DEVNAME_PREFIX);
+        alstr_append_cstr(&name, SDL_GetAudioDeviceName(i, SDL_FALSE));
+        AppendAllDevicesList(alstr_get_cstr(name));
+    }
+    alstr_reset(&name);
+}
+
+static ALCbackend* ALCsdl2BackendFactory_createBackend(ALCsdl2BackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCsdl2Backend *backend;
+        NEW_OBJ(backend, ALCsdl2Backend)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}

+ 11 - 15
libs/openal-soft/Alc/backends/sndio.c

@@ -43,7 +43,7 @@ typedef struct ALCsndioBackend {
     ALvoid *mix_data;
     ALsizei data_size;
 
-    volatile int killNow;
+    ATOMIC(int) killNow;
     althrd_t thread;
 } ALCsndioBackend;
 
@@ -52,7 +52,6 @@ static int ALCsndioBackend_mixerProc(void *ptr);
 static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device);
 static void ALCsndioBackend_Destruct(ALCsndioBackend *self);
 static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name);
-static void ALCsndioBackend_close(ALCsndioBackend *self);
 static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self);
 static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self);
 static void ALCsndioBackend_stop(ALCsndioBackend *self);
@@ -73,6 +72,10 @@ static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCsndioBackend, ALCbackend, self);
+
+    self->sndHandle = NULL;
+    self->mix_data = NULL;
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
 }
 
 static void ALCsndioBackend_Destruct(ALCsndioBackend *self)
@@ -100,7 +103,8 @@ static int ALCsndioBackend_mixerProc(void *ptr)
 
     frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
-    while(!self->killNow && device->Connected)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         ALsizei len = self->data_size;
         ALubyte *WritePtr = self->mix_data;
@@ -108,14 +112,14 @@ static int ALCsndioBackend_mixerProc(void *ptr)
         ALCsndioBackend_lock(self);
         aluMixData(device, WritePtr, len/frameSize);
         ALCsndioBackend_unlock(self);
-        while(len > 0 && !self->killNow)
+        while(len > 0 && !ATOMIC_LOAD(&self->killNow, almemory_order_acquire))
         {
             wrote = sio_write(self->sndHandle, WritePtr, len);
             if(wrote == 0)
             {
                 ERR("sio_write failed\n");
                 ALCdevice_Lock(device);
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Failed to write playback samples");
                 ALCdevice_Unlock(device);
                 break;
             }
@@ -150,12 +154,6 @@ static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCsndioBackend_close(ALCsndioBackend *self)
-{
-    sio_close(self->sndHandle);
-    self->sndHandle = NULL;
-}
-
 static ALCboolean ALCsndioBackend_reset(ALCsndioBackend *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
@@ -257,7 +255,7 @@ static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self)
         return ALC_FALSE;
     }
 
-    self->killNow = 0;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, ALCsndioBackend_mixerProc, self) != althrd_success)
     {
         sio_stop(self->sndHandle);
@@ -271,10 +269,8 @@ static void ALCsndioBackend_stop(ALCsndioBackend *self)
 {
     int res;
 
-    if(self->killNow)
+    if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
-
-    self->killNow = 1;
     althrd_join(self->thread, &res);
 
     if(!sio_stop(self->sndHandle))

+ 7 - 10
libs/openal-soft/Alc/backends/solaris.c

@@ -34,6 +34,7 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "alconfig.h"
 #include "threads.h"
 #include "compat.h"
 
@@ -59,7 +60,6 @@ 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);
@@ -84,6 +84,7 @@ static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *devi
     SET_VTABLE2(ALCsolarisBackend, ALCbackend, self);
 
     self->fd = -1;
+    self->mix_data = NULL;
     ATOMIC_INIT(&self->killNow, AL_FALSE);
 }
 
@@ -119,7 +120,8 @@ static int ALCsolarisBackend_mixerProc(void *ptr)
     frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     ALCsolarisBackend_lock(self);
-    while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         FD_ZERO(&wfds);
         FD_SET(self->fd, &wfds);
@@ -134,7 +136,7 @@ static int ALCsolarisBackend_mixerProc(void *ptr)
             if(errno == EINTR)
                 continue;
             ERR("select failed: %s\n", strerror(errno));
-            aluHandleDisconnect(device);
+            aluHandleDisconnect(device, "Failed to wait for playback buffer: %s", strerror(errno));
             break;
         }
         else if(sret == 0)
@@ -154,7 +156,8 @@ static int ALCsolarisBackend_mixerProc(void *ptr)
                 if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
                     continue;
                 ERR("write failed: %s\n", strerror(errno));
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Failed to write playback samples: %s",
+                                    strerror(errno));
                 break;
             }
 
@@ -190,12 +193,6 @@ static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *na
     return ALC_NO_ERROR;
 }
 
-static void ALCsolarisBackend_close(ALCsolarisBackend *self)
-{
-    close(self->fd);
-    self->fd = -1;
-}
-
 static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;

File diff suppressed because it is too large
+ 238 - 254
libs/openal-soft/Alc/backends/wasapi.c


+ 17 - 17
libs/openal-soft/Alc/backends/wave.c

@@ -27,6 +27,7 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "alconfig.h"
 #include "threads.h"
 #include "compat.h"
 
@@ -76,16 +77,15 @@ typedef struct ALCwaveBackend {
     ALvoid *mBuffer;
     ALuint mSize;
 
-    volatile int killNow;
+    ATOMIC(ALenum) 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 void ALCwaveBackend_Destruct(ALCwaveBackend *self);
 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);
@@ -110,9 +110,17 @@ static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device)
     self->mBuffer = NULL;
     self->mSize = 0;
 
-    self->killNow = 1;
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
 }
 
+static void ALCwaveBackend_Destruct(ALCwaveBackend *self)
+{
+    if(self->mFile)
+        fclose(self->mFile);
+    self->mFile = NULL;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
 
 static int ALCwaveBackend_mixerProc(void *ptr)
 {
@@ -135,7 +143,8 @@ static int ALCwaveBackend_mixerProc(void *ptr)
         ERR("Failed to get starting time\n");
         return 1;
     }
-    while(!self->killNow && device->Connected)
+    while(!ATOMIC_LOAD(&self->killNow, almemory_order_acquire) &&
+          ATOMIC_LOAD(&device->Connected, almemory_order_acquire))
     {
         if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
         {
@@ -196,7 +205,7 @@ static int ALCwaveBackend_mixerProc(void *ptr)
             {
                 ERR("Error writing to file\n");
                 ALCdevice_Lock(device);
-                aluHandleDisconnect(device);
+                aluHandleDisconnect(device, "Failed to write playback samples");
                 ALCdevice_Unlock(device);
                 break;
             }
@@ -233,13 +242,6 @@ static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name)
     return ALC_NO_ERROR;
 }
 
-static void ALCwaveBackend_close(ALCwaveBackend *self)
-{
-    if(self->mFile)
-        fclose(self->mFile);
-    self->mFile = NULL;
-}
-
 static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -354,7 +356,7 @@ static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self)
         return ALC_FALSE;
     }
 
-    self->killNow = 0;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, ALCwaveBackend_mixerProc, self) != althrd_success)
     {
         free(self->mBuffer);
@@ -372,10 +374,8 @@ static void ALCwaveBackend_stop(ALCwaveBackend *self)
     long size;
     int res;
 
-    if(self->killNow)
+    if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
-
-    self->killNow = 1;
     althrd_join(self->thread, &res);
 
     free(self->mBuffer);

+ 39 - 50
libs/openal-soft/Alc/backends/winmm.c

@@ -29,6 +29,7 @@
 
 #include "alMain.h"
 #include "alu.h"
+#include "ringbuffer.h"
 #include "threads.h"
 
 #include "backends/base.h"
@@ -147,7 +148,7 @@ typedef struct ALCwinmmPlayback {
 
     WAVEFORMATEX Format;
 
-    volatile ALboolean killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } ALCwinmmPlayback;
 
@@ -158,7 +159,6 @@ static void CALLBACK ALCwinmmPlayback_waveOutProc(HWAVEOUT device, UINT msg, DWO
 static int ALCwinmmPlayback_mixerProc(void *arg);
 
 static ALCenum ALCwinmmPlayback_open(ALCwinmmPlayback *self, const ALCchar *name);
-static void ALCwinmmPlayback_close(ALCwinmmPlayback *self);
 static ALCboolean ALCwinmmPlayback_reset(ALCwinmmPlayback *self);
 static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self);
 static void ALCwinmmPlayback_stop(ALCwinmmPlayback *self);
@@ -180,7 +180,7 @@ static void ALCwinmmPlayback_Construct(ALCwinmmPlayback *self, ALCdevice *device
     InitRef(&self->WaveBuffersCommitted, 0);
     self->OutHdl = NULL;
 
-    self->killNow = AL_TRUE;
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
 }
 
 static void ALCwinmmPlayback_Destruct(ALCwinmmPlayback *self)
@@ -224,7 +224,7 @@ FORCE_ALIGN static int ALCwinmmPlayback_mixerProc(void *arg)
         if(msg.message != WOM_DONE)
             continue;
 
-        if(self->killNow)
+        if(ATOMIC_LOAD(&self->killNow, almemory_order_acquire))
         {
             if(ReadRef(&self->WaveBuffersCommitted) == 0)
                 break;
@@ -311,9 +311,6 @@ failure:
     return ALC_INVALID_VALUE;
 }
 
-static void ALCwinmmPlayback_close(ALCwinmmPlayback* UNUSED(self))
-{ }
-
 static ALCboolean ALCwinmmPlayback_reset(ALCwinmmPlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
@@ -374,7 +371,7 @@ static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self)
     ALint BufferSize;
     ALuint i;
 
-    self->killNow = AL_FALSE;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, ALCwinmmPlayback_mixerProc, self) != althrd_success)
         return ALC_FALSE;
 
@@ -405,11 +402,8 @@ static void ALCwinmmPlayback_stop(ALCwinmmPlayback *self)
     void *buffer = NULL;
     int i;
 
-    if(self->killNow)
+    if(ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
         return;
-
-    // Set flag to stop processing headers
-    self->killNow = AL_TRUE;
     althrd_join(self->thread, &i);
 
     // Release the wave buffers
@@ -436,7 +430,7 @@ typedef struct ALCwinmmCapture {
 
     WAVEFORMATEX Format;
 
-    volatile ALboolean killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } ALCwinmmCapture;
 
@@ -447,7 +441,6 @@ static void CALLBACK ALCwinmmCapture_waveInProc(HWAVEIN device, UINT msg, DWORD_
 static int ALCwinmmCapture_captureProc(void *arg);
 
 static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name);
-static void ALCwinmmCapture_close(ALCwinmmCapture *self);
 static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, ALCboolean, reset)
 static ALCboolean ALCwinmmCapture_start(ALCwinmmCapture *self);
 static void ALCwinmmCapture_stop(ALCwinmmCapture *self);
@@ -469,11 +462,38 @@ static void ALCwinmmCapture_Construct(ALCwinmmCapture *self, ALCdevice *device)
     InitRef(&self->WaveBuffersCommitted, 0);
     self->InHdl = NULL;
 
-    self->killNow = AL_TRUE;
+    ATOMIC_INIT(&self->killNow, AL_TRUE);
 }
 
 static void ALCwinmmCapture_Destruct(ALCwinmmCapture *self)
 {
+    void *buffer = NULL;
+    int i;
+
+    /* Tell the processing thread to quit and wait for it to do so. */
+    if(!ATOMIC_EXCHANGE(&self->killNow, AL_TRUE, almemory_order_acq_rel))
+    {
+        PostThreadMessage(self->thread, WM_QUIT, 0, 0);
+
+        althrd_join(self->thread, &i);
+
+        /* Make sure capture is stopped and all pending buffers are flushed. */
+        waveInReset(self->InHdl);
+
+        // Release the wave buffers
+        for(i = 0;i < 4;i++)
+        {
+            waveInUnprepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR));
+            if(i == 0) buffer = self->WaveBuffer[i].lpData;
+            self->WaveBuffer[i].lpData = NULL;
+        }
+        free(buffer);
+    }
+
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = NULL;
+
+    // Close the Wave device
     if(self->InHdl)
         waveInClose(self->InHdl);
     self->InHdl = 0;
@@ -512,7 +532,7 @@ static int ALCwinmmCapture_captureProc(void *arg)
             continue;
         /* Don't wait for other buffers to finish before quitting. We're
          * closing so we don't need them. */
-        if(self->killNow)
+        if(ATOMIC_LOAD(&self->killNow, almemory_order_acquire))
             break;
 
         WaveHdr = ((WAVEHDR*)msg.lParam);
@@ -606,7 +626,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name)
     if(CapturedDataSize < (self->Format.nSamplesPerSec / 10))
         CapturedDataSize = self->Format.nSamplesPerSec / 10;
 
-    self->Ring = ll_ringbuffer_create(CapturedDataSize+1, self->Format.nBlockAlign);
+    self->Ring = ll_ringbuffer_create(CapturedDataSize, self->Format.nBlockAlign, false);
     if(!self->Ring) goto failure;
 
     InitRef(&self->WaveBuffersCommitted, 0);
@@ -632,7 +652,7 @@ static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name)
         IncrementRef(&self->WaveBuffersCommitted);
     }
 
-    self->killNow = AL_FALSE;
+    ATOMIC_STORE(&self->killNow, AL_FALSE, almemory_order_release);
     if(althrd_create(&self->thread, ALCwinmmCapture_captureProc, self) != althrd_success)
         goto failure;
 
@@ -657,37 +677,6 @@ failure:
     return ALC_INVALID_VALUE;
 }
 
-static void ALCwinmmCapture_close(ALCwinmmCapture *self)
-{
-    void *buffer = NULL;
-    int i;
-
-    /* Tell the processing thread to quit and wait for it to do so. */
-    self->killNow = AL_TRUE;
-    PostThreadMessage(self->thread, WM_QUIT, 0, 0);
-
-    althrd_join(self->thread, &i);
-
-    /* Make sure capture is stopped and all pending buffers are flushed. */
-    waveInReset(self->InHdl);
-
-    // Release the wave buffers
-    for(i = 0;i < 4;i++)
-    {
-        waveInUnprepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR));
-        if(i == 0) buffer = self->WaveBuffer[i].lpData;
-        self->WaveBuffer[i].lpData = NULL;
-    }
-    free(buffer);
-
-    ll_ringbuffer_free(self->Ring);
-    self->Ring = NULL;
-
-    // Close the Wave device
-    waveInClose(self->InHdl);
-    self->InHdl = NULL;
-}
-
 static ALCboolean ALCwinmmCapture_start(ALCwinmmCapture *self)
 {
     waveInStart(self->InHdl);
@@ -707,7 +696,7 @@ static ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *bu
 
 static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self)
 {
-    return ll_ringbuffer_read_space(self->Ring);
+    return (ALCuint)ll_ringbuffer_read_space(self->Ring);
 }
 
 

+ 120 - 140
libs/openal-soft/Alc/bformatdec.c

@@ -3,7 +3,6 @@
 
 #include "bformatdec.h"
 #include "ambdec.h"
-#include "mixer_defs.h"
 #include "alu.h"
 
 #include "bool.h"
@@ -11,9 +10,9 @@
 #include "almalloc.h"
 
 
-void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult)
+void bandsplit_init(BandSplitter *splitter, ALfloat f0norm)
 {
-    ALfloat w = freq_mult * F_TAU;
+    ALfloat w = f0norm * F_TAU;
     ALfloat cw = cosf(w);
     if(cw > FLT_EPSILON)
         splitter->coeff = (sinf(w) - 1.0f) / cw;
@@ -35,49 +34,47 @@ void bandsplit_clear(BandSplitter *splitter)
 void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
                        const ALfloat *input, ALsizei count)
 {
-    ALfloat coeff, d, x;
-    ALfloat z1, z2;
+    ALfloat lp_coeff, hp_coeff, lp_y, hp_y, d;
+    ALfloat lp_z1, lp_z2, hp_z1;
     ALsizei i;
 
-    coeff = splitter->coeff*0.5f + 0.5f;
-    z1 = splitter->lp_z1;
-    z2 = splitter->lp_z2;
+    hp_coeff = splitter->coeff;
+    lp_coeff = splitter->coeff*0.5f + 0.5f;
+    lp_z1 = splitter->lp_z1;
+    lp_z2 = splitter->lp_z2;
+    hp_z1 = splitter->hp_z1;
     for(i = 0;i < count;i++)
     {
-        x = input[i];
-
-        d = (x - z1) * coeff;
-        x = z1 + d;
-        z1 = x + d;
+        ALfloat in = input[i];
 
-        d = (x - z2) * coeff;
-        x = z2 + d;
-        z2 = x + d;
+        /* Low-pass sample processing. */
+        d = (in - lp_z1) * lp_coeff;
+        lp_y = lp_z1 + d;
+        lp_z1 = lp_y + d;
 
-        lpout[i] = x;
-    }
-    splitter->lp_z1 = z1;
-    splitter->lp_z2 = z2;
+        d = (lp_y - lp_z2) * lp_coeff;
+        lp_y = lp_z2 + d;
+        lp_z2 = lp_y + d;
 
-    coeff = splitter->coeff;
-    z1 = splitter->hp_z1;
-    for(i = 0;i < count;i++)
-    {
-        x = input[i];
+        lpout[i] = lp_y;
 
-        d = x - coeff*z1;
-        x = z1 + coeff*d;
-        z1 = d;
+        /* All-pass sample processing. */
+        d = in - hp_coeff*hp_z1;
+        hp_y = hp_z1 + hp_coeff*d;
+        hp_z1 = d;
 
-        hpout[i] = x - lpout[i];
+        /* High-pass generated from removing low-passed output. */
+        hpout[i] = hp_y - lp_y;
     }
-    splitter->hp_z1 = z1;
+    splitter->lp_z1 = lp_z1;
+    splitter->lp_z2 = lp_z2;
+    splitter->hp_z1 = hp_z1;
 }
 
 
-void splitterap_init(SplitterAllpass *splitter, ALfloat freq_mult)
+void splitterap_init(SplitterAllpass *splitter, ALfloat f0norm)
 {
-    ALfloat w = freq_mult * F_TAU;
+    ALfloat w = f0norm * F_TAU;
     ALfloat cw = cosf(w);
     if(cw > FLT_EPSILON)
         splitter->coeff = (sinf(w) - 1.0f) / cw;
@@ -114,11 +111,14 @@ void splitterap_process(SplitterAllpass *splitter, ALfloat *restrict samples, AL
 }
 
 
-static const ALfloat UnitScale[MAX_AMBI_COEFFS] = {
+/* NOTE: These are scale factors as applied to Ambisonics content. Decoder
+ * coefficients should be divided by these values to get proper N3D scalings.
+ */
+const ALfloat N3D2N3DScale[MAX_AMBI_COEFFS] = {
     1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
     1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
 };
-static const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = {
+const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = {
     1.000000000f, /* ACN  0 (W), sqrt(1) */
     1.732050808f, /* ACN  1 (Y), sqrt(3) */
     1.732050808f, /* ACN  2 (Z), sqrt(3) */
@@ -136,7 +136,7 @@ static const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = {
     2.645751311f, /* ACN 14 (N), sqrt(7) */
     2.645751311f, /* ACN 15 (P), sqrt(7) */
 };
-static const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
+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) */
@@ -156,11 +156,9 @@ static const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = {
 };
 
 
-enum FreqBand {
-    FB_HighFreq,
-    FB_LowFreq,
-    FB_Max
-};
+#define HF_BAND 0
+#define LF_BAND 1
+#define NUM_BANDS 2
 
 /* These points are in AL coordinates! */
 static const ALfloat Ambi3DPoints[8][3] = {
@@ -173,35 +171,28 @@ static const ALfloat Ambi3DPoints[8][3] = {
     { -0.577350269f, -0.577350269f,  0.577350269f },
     {  0.577350269f, -0.577350269f,  0.577350269f },
 };
-static const ALfloat Ambi3DDecoder[8][FB_Max][MAX_AMBI_COEFFS] = {
-    { { 0.25f,  0.1443375672f,  0.1443375672f,  0.1443375672f }, { 0.125f,  0.125f,  0.125f,  0.125f } },
-    { { 0.25f, -0.1443375672f,  0.1443375672f,  0.1443375672f }, { 0.125f, -0.125f,  0.125f,  0.125f } },
-    { { 0.25f,  0.1443375672f,  0.1443375672f, -0.1443375672f }, { 0.125f,  0.125f,  0.125f, -0.125f } },
-    { { 0.25f, -0.1443375672f,  0.1443375672f, -0.1443375672f }, { 0.125f, -0.125f,  0.125f, -0.125f } },
-    { { 0.25f,  0.1443375672f, -0.1443375672f,  0.1443375672f }, { 0.125f,  0.125f, -0.125f,  0.125f } },
-    { { 0.25f, -0.1443375672f, -0.1443375672f,  0.1443375672f }, { 0.125f, -0.125f, -0.125f,  0.125f } },
-    { { 0.25f,  0.1443375672f, -0.1443375672f, -0.1443375672f }, { 0.125f,  0.125f, -0.125f, -0.125f } },
-    { { 0.25f, -0.1443375672f, -0.1443375672f, -0.1443375672f }, { 0.125f, -0.125f, -0.125f, -0.125f } },
+static const ALfloat Ambi3DDecoder[8][MAX_AMBI_COEFFS] = {
+    { 0.125f,  0.125f,  0.125f,  0.125f },
+    { 0.125f, -0.125f,  0.125f,  0.125f },
+    { 0.125f,  0.125f,  0.125f, -0.125f },
+    { 0.125f, -0.125f,  0.125f, -0.125f },
+    { 0.125f,  0.125f, -0.125f,  0.125f },
+    { 0.125f, -0.125f, -0.125f,  0.125f },
+    { 0.125f,  0.125f, -0.125f, -0.125f },
+    { 0.125f, -0.125f, -0.125f, -0.125f },
+};
+static const ALfloat Ambi3DDecoderHFScale[MAX_AMBI_COEFFS] = {
+    2.0f,
+    1.15470054f, 1.15470054f, 1.15470054f
 };
-
-
-static RowMixerFunc MixMatrixRow = MixRow_C;
-
-
-static alonce_flag bformatdec_inited = AL_ONCE_FLAG_INIT;
-
-static void init_bformatdec(void)
-{
-    MixMatrixRow = SelectRowMixer();
-}
 
 
 /* NOTE: BandSplitter filters are unused with single-band decoding */
 typedef struct BFormatDec {
-    ALboolean Enabled[MAX_OUTPUT_CHANNELS];
+    ALuint Enabled; /* Bitfield of enabled channels. */
 
     union {
-        alignas(16) ALfloat Dual[MAX_OUTPUT_CHANNELS][FB_Max][MAX_AMBI_COEFFS];
+        alignas(16) ALfloat Dual[MAX_OUTPUT_CHANNELS][NUM_BANDS][MAX_AMBI_COEFFS];
         alignas(16) ALfloat Single[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
     } Matrix;
 
@@ -216,7 +207,7 @@ typedef struct BFormatDec {
 
     struct {
         BandSplitter XOver;
-        ALfloat Gains[FB_Max];
+        ALfloat Gains[NUM_BANDS];
     } UpSampler[4];
 
     ALsizei NumChannels;
@@ -225,21 +216,20 @@ typedef struct BFormatDec {
 
 BFormatDec *bformatdec_alloc()
 {
-    alcall_once(&bformatdec_inited, init_bformatdec);
     return al_calloc(16, sizeof(BFormatDec));
 }
 
-void bformatdec_free(BFormatDec *dec)
+void bformatdec_free(BFormatDec **dec)
 {
-    if(dec)
+    if(dec && *dec)
     {
-        al_free(dec->Samples);
-        dec->Samples = NULL;
-        dec->SamplesHF = NULL;
-        dec->SamplesLF = NULL;
+        al_free((*dec)->Samples);
+        (*dec)->Samples = NULL;
+        (*dec)->SamplesHF = NULL;
+        (*dec)->SamplesLF = NULL;
 
-        memset(dec, 0, sizeof(*dec));
-        al_free(dec);
+        al_free(*dec);
+        *dec = NULL;
     }
 }
 
@@ -248,7 +238,7 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
     static const ALsizei map2DTo3D[MAX_AMBI2D_COEFFS] = {
         0,  1, 3,  4, 8,  9, 15
     };
-    const ALfloat *coeff_scale = UnitScale;
+    const ALfloat *coeff_scale = N3D2N3DScale;
     bool periphonic;
     ALfloat ratio;
     ALsizei i;
@@ -263,10 +253,9 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
     dec->SamplesHF = dec->Samples;
     dec->SamplesLF = dec->SamplesHF + dec->NumChannels;
 
-    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
-        dec->Enabled[i] = AL_FALSE;
+    dec->Enabled = 0;
     for(i = 0;i < conf->NumSpeakers;i++)
-        dec->Enabled[chanmap[i]] = AL_TRUE;
+        dec->Enabled |= 1 << chanmap[i];
 
     if(conf->CoeffScale == ADS_SN3D)
         coeff_scale = SN3D2N3DScale;
@@ -281,31 +270,31 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
     {
         periphonic = true;
 
-        dec->UpSampler[0].Gains[FB_HighFreq] = (dec->NumChannels > 9) ? W_SCALE3D_THIRD :
-                                               (dec->NumChannels > 4) ? W_SCALE3D_SECOND : 1.0f;
-        dec->UpSampler[0].Gains[FB_LowFreq] = 1.0f;
+        dec->UpSampler[0].Gains[HF_BAND] = (conf->ChanMask > 0x1ff) ? W_SCALE_3H3P :
+                                           (conf->ChanMask > 0xf) ? W_SCALE_2H2P : 1.0f;
+        dec->UpSampler[0].Gains[LF_BAND] = 1.0f;
         for(i = 1;i < 4;i++)
         {
-            dec->UpSampler[i].Gains[FB_HighFreq] = (dec->NumChannels > 9) ? XYZ_SCALE3D_THIRD :
-                                                   (dec->NumChannels > 4) ? XYZ_SCALE3D_SECOND : 1.0f;
-            dec->UpSampler[i].Gains[FB_LowFreq] = 1.0f;
+            dec->UpSampler[i].Gains[HF_BAND] = (conf->ChanMask > 0x1ff) ? XYZ_SCALE_3H3P :
+                                               (conf->ChanMask > 0xf) ? XYZ_SCALE_2H2P : 1.0f;
+            dec->UpSampler[i].Gains[LF_BAND] = 1.0f;
         }
     }
     else
     {
         periphonic = false;
 
-        dec->UpSampler[0].Gains[FB_HighFreq] = (dec->NumChannels > 5) ? W_SCALE2D_THIRD :
-                                               (dec->NumChannels > 3) ? W_SCALE2D_SECOND : 1.0f;
-        dec->UpSampler[0].Gains[FB_LowFreq] = 1.0f;
+        dec->UpSampler[0].Gains[HF_BAND] = (conf->ChanMask > 0x1ff) ? W_SCALE_3H0P :
+                                           (conf->ChanMask > 0xf) ? W_SCALE_2H0P : 1.0f;
+        dec->UpSampler[0].Gains[LF_BAND] = 1.0f;
         for(i = 1;i < 3;i++)
         {
-            dec->UpSampler[i].Gains[FB_HighFreq] = (dec->NumChannels > 5) ? XYZ_SCALE2D_THIRD :
-                                                   (dec->NumChannels > 3) ? XYZ_SCALE2D_SECOND : 1.0f;
-            dec->UpSampler[i].Gains[FB_LowFreq] = 1.0f;
+            dec->UpSampler[i].Gains[HF_BAND] = (conf->ChanMask > 0x1ff) ? XYZ_SCALE_3H0P :
+                                               (conf->ChanMask > 0xf) ? XYZ_SCALE_2H0P : 1.0f;
+            dec->UpSampler[i].Gains[LF_BAND] = 1.0f;
         }
-        dec->UpSampler[3].Gains[FB_HighFreq] = 0.0f;
-        dec->UpSampler[3].Gains[FB_LowFreq] = 0.0f;
+        dec->UpSampler[3].Gains[HF_BAND] = 0.0f;
+        dec->UpSampler[3].Gains[LF_BAND] = 0.0f;
     }
 
     memset(&dec->Matrix, 0, sizeof(dec->Matrix));
@@ -372,8 +361,8 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
                     else if(j == 3) gain = conf->HFOrderGain[2] * ratio;
                     else if(j == 5) gain = conf->HFOrderGain[3] * ratio;
                     if((conf->ChanMask&(1<<l)))
-                        dec->Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] /
-                                                                 coeff_scale[l] * gain;
+                        dec->Matrix.Dual[chan][HF_BAND][j] = conf->HFMatrix[i][k++] /
+                                                             coeff_scale[l] * gain;
                 }
                 for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
                 {
@@ -383,8 +372,8 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
                     else if(j == 3) gain = conf->LFOrderGain[2] / ratio;
                     else if(j == 5) gain = conf->LFOrderGain[3] / ratio;
                     if((conf->ChanMask&(1<<l)))
-                        dec->Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] /
-                                                                coeff_scale[l] * gain;
+                        dec->Matrix.Dual[chan][LF_BAND][j] = conf->LFMatrix[i][k++] /
+                                                             coeff_scale[l] * gain;
                 }
             }
             else
@@ -396,8 +385,8 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
                     else if(j == 4) gain = conf->HFOrderGain[2] * ratio;
                     else if(j == 9) gain = conf->HFOrderGain[3] * ratio;
                     if((conf->ChanMask&(1<<j)))
-                        dec->Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] /
-                                                                 coeff_scale[j] * gain;
+                        dec->Matrix.Dual[chan][HF_BAND][j] = conf->HFMatrix[i][k++] /
+                                                             coeff_scale[j] * gain;
                 }
                 for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
                 {
@@ -406,8 +395,8 @@ void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount
                     else if(j == 4) gain = conf->LFOrderGain[2] / ratio;
                     else if(j == 9) gain = conf->LFOrderGain[3] / ratio;
                     if((conf->ChanMask&(1<<j)))
-                        dec->Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] /
-                                                                coeff_scale[j] * gain;
+                        dec->Matrix.Dual[chan][LF_BAND][j] = conf->LFMatrix[i][k++] /
+                                                             coeff_scale[j] * gain;
                 }
             }
         }
@@ -428,17 +417,15 @@ void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BU
 
         for(chan = 0;chan < OutChannels;chan++)
         {
-            if(!dec->Enabled[chan])
+            if(!(dec->Enabled&(1<<chan)))
                 continue;
 
             memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
-            MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_HighFreq],
-                SAFE_CONST(ALfloatBUFFERSIZE*,dec->SamplesHF), dec->NumChannels, 0,
-                SamplesToDo
+            MixRowSamples(dec->ChannelMix, dec->Matrix.Dual[chan][HF_BAND],
+                dec->SamplesHF, dec->NumChannels, 0, SamplesToDo
             );
-            MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_LowFreq],
-                SAFE_CONST(ALfloatBUFFERSIZE*,dec->SamplesLF), dec->NumChannels, 0,
-                SamplesToDo
+            MixRowSamples(dec->ChannelMix, dec->Matrix.Dual[chan][LF_BAND],
+                dec->SamplesLF, dec->NumChannels, 0, SamplesToDo
             );
 
             for(i = 0;i < SamplesToDo;i++)
@@ -449,12 +436,12 @@ void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BU
     {
         for(chan = 0;chan < OutChannels;chan++)
         {
-            if(!dec->Enabled[chan])
+            if(!(dec->Enabled&(1<<chan)))
                 continue;
 
             memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
-            MixMatrixRow(dec->ChannelMix, dec->Matrix.Single[chan], InSamples,
-                         dec->NumChannels, 0, SamplesToDo);
+            MixRowSamples(dec->ChannelMix, dec->Matrix.Single[chan], InSamples,
+                          dec->NumChannels, 0, SamplesToDo);
 
             for(i = 0;i < SamplesToDo;i++)
                 OutBuffer[chan][i] += dec->ChannelMix[i];
@@ -483,14 +470,13 @@ void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[B
          * bands.
          */
         bandsplit_process(&dec->UpSampler[i].XOver,
-            dec->Samples[FB_HighFreq], dec->Samples[FB_LowFreq],
+            dec->Samples[HF_BAND], dec->Samples[LF_BAND],
             InSamples[i], SamplesToDo
         );
 
         /* Now write each band to the output. */
-        MixMatrixRow(OutBuffer[i], dec->UpSampler[i].Gains,
-            SAFE_CONST(ALfloatBUFFERSIZE*,dec->Samples), FB_Max, 0,
-            SamplesToDo
+        MixRowSamples(OutBuffer[i], dec->UpSampler[i].Gains,
+            dec->Samples, NUM_BANDS, 0, SamplesToDo
         );
     }
 }
@@ -511,28 +497,31 @@ static ALsizei GetACNIndex(const BFChannelConfig *chans, ALsizei numchans, ALsiz
 #define GetChannelForACN(b, a) GetACNIndex((b).Ambi.Map, (b).NumChannels, (a))
 
 typedef struct AmbiUpsampler {
-    alignas(16) ALfloat Samples[FB_Max][BUFFERSIZE];
+    alignas(16) ALfloat Samples[NUM_BANDS][BUFFERSIZE];
 
     BandSplitter XOver[4];
 
-    ALfloat Gains[4][MAX_OUTPUT_CHANNELS][FB_Max];
+    ALfloat Gains[4][MAX_OUTPUT_CHANNELS][NUM_BANDS];
 } AmbiUpsampler;
 
 AmbiUpsampler *ambiup_alloc()
 {
-    alcall_once(&bformatdec_inited, init_bformatdec);
     return al_calloc(16, sizeof(AmbiUpsampler));
 }
 
-void ambiup_free(struct AmbiUpsampler *ambiup)
+void ambiup_free(struct AmbiUpsampler **ambiup)
 {
-    al_free(ambiup);
+    if(ambiup)
+    {
+        al_free(*ambiup);
+        *ambiup = NULL;
+    }
 }
 
-void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device)
+void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device, ALfloat w_scale, ALfloat xyz_scale)
 {
     ALfloat ratio;
-    size_t i;
+    ALsizei i;
 
     ratio = 400.0f / (ALfloat)device->Frequency;
     for(i = 0;i < 4;i++)
@@ -545,11 +534,11 @@ void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device)
         ALsizei j;
         size_t k;
 
-        for(i = 0;i < COUNTOF(Ambi3DPoints);i++)
+        for(k = 0;k < COUNTOF(Ambi3DPoints);k++)
         {
             ALfloat coeffs[MAX_AMBI_COEFFS] = { 0.0f };
-            CalcDirectionCoeffs(Ambi3DPoints[i], 0.0f, coeffs);
-            ComputePanningGains(device->Dry, coeffs, 1.0f, encgains[i]);
+            CalcDirectionCoeffs(Ambi3DPoints[k], 0.0f, coeffs);
+            ComputeDryPanGains(&device->Dry, coeffs, 1.0f, encgains[k]);
         }
 
         /* Combine the matrices that do the in->virt and virt->out conversions
@@ -561,32 +550,24 @@ void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device)
         {
             for(j = 0;j < device->Dry.NumChannels;j++)
             {
-                ALfloat hfgain=0.0f, lfgain=0.0f;
+                ALfloat gain=0.0f;
                 for(k = 0;k < COUNTOF(Ambi3DDecoder);k++)
-                {
-                    hfgain += Ambi3DDecoder[k][FB_HighFreq][i]*encgains[k][j];
-                    lfgain += Ambi3DDecoder[k][FB_LowFreq][i]*encgains[k][j];
-                }
-                ambiup->Gains[i][j][FB_HighFreq] = hfgain;
-                ambiup->Gains[i][j][FB_LowFreq] = lfgain;
+                    gain += Ambi3DDecoder[k][i] * encgains[k][j];
+                ambiup->Gains[i][j][HF_BAND] = gain * Ambi3DDecoderHFScale[i];
+                ambiup->Gains[i][j][LF_BAND] = gain;
             }
         }
     }
     else
     {
-        /* Assumes full 3D/periphonic on the input and output mixes! */
-        ALfloat w_scale = (device->Dry.NumChannels > 9) ? W_SCALE3D_THIRD :
-                          (device->Dry.NumChannels > 4) ? W_SCALE3D_SECOND : 1.0f;
-        ALfloat xyz_scale = (device->Dry.NumChannels > 9) ? XYZ_SCALE3D_THIRD :
-                            (device->Dry.NumChannels > 4) ? XYZ_SCALE3D_SECOND : 1.0f;
         for(i = 0;i < 4;i++)
         {
             ALsizei index = GetChannelForACN(device->Dry, i);
             if(index != INVALID_UPSAMPLE_INDEX)
             {
                 ALfloat scale = device->Dry.Ambi.Map[index].Scale;
-                ambiup->Gains[i][index][FB_HighFreq] = scale * ((i==0) ? w_scale : xyz_scale);
-                ambiup->Gains[i][index][FB_LowFreq] = scale;
+                ambiup->Gains[i][index][HF_BAND] = scale * ((i==0) ? w_scale : xyz_scale);
+                ambiup->Gains[i][index][LF_BAND] = scale;
             }
         }
     }
@@ -599,14 +580,13 @@ void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[
     for(i = 0;i < 4;i++)
     {
         bandsplit_process(&ambiup->XOver[i],
-            ambiup->Samples[FB_HighFreq], ambiup->Samples[FB_LowFreq],
+            ambiup->Samples[HF_BAND], ambiup->Samples[LF_BAND],
             InSamples[i], SamplesToDo
         );
 
         for(j = 0;j < OutChannels;j++)
-            MixMatrixRow(OutBuffer[j], ambiup->Gains[i][j],
-                SAFE_CONST(ALfloatBUFFERSIZE*,ambiup->Samples), FB_Max, 0,
-                SamplesToDo
+            MixRowSamples(OutBuffer[j], ambiup->Gains[i][j],
+                ambiup->Samples, NUM_BANDS, 0, SamplesToDo
             );
     }
 }

+ 30 - 14
libs/openal-soft/Alc/bformatdec.h

@@ -7,18 +7,26 @@
 /* These are the necessary scales for first-order HF responses to play over
  * higher-order 2D (non-periphonic) decoders.
  */
-#define W_SCALE2D_SECOND   1.224744871f /* sqrt(1.5) */
-#define XYZ_SCALE2D_SECOND 1.0f
-#define W_SCALE2D_THIRD   1.414213562f /* sqrt(2) */
-#define XYZ_SCALE2D_THIRD 1.082392196f
+#define W_SCALE_2H0P   1.224744871f /* sqrt(1.5) */
+#define XYZ_SCALE_2H0P 1.0f
+#define W_SCALE_3H0P   1.414213562f /* sqrt(2) */
+#define XYZ_SCALE_3H0P 1.082392196f
 
 /* These are the necessary scales for first-order HF responses to play over
  * higher-order 3D (periphonic) decoders.
  */
-#define W_SCALE3D_SECOND   1.341640787f /* sqrt(1.8) */
-#define XYZ_SCALE3D_SECOND 1.0f
-#define W_SCALE3D_THIRD   1.695486018f
-#define XYZ_SCALE3D_THIRD 1.136697713f
+#define W_SCALE_2H2P   1.341640787f /* sqrt(1.8) */
+#define XYZ_SCALE_2H2P 1.0f
+#define W_SCALE_3H3P   1.695486018f
+#define XYZ_SCALE_3H3P 1.136697713f
+
+
+/* NOTE: These are scale factors as applied to Ambisonics content. Decoder
+ * coefficients should be divided by these values to get proper N3D scalings.
+ */
+const ALfloat N3D2N3DScale[MAX_AMBI_COEFFS];
+const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS];
+const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS];
 
 
 struct AmbDecConf;
@@ -27,7 +35,7 @@ struct AmbiUpsampler;
 
 
 struct BFormatDec *bformatdec_alloc();
-void bformatdec_free(struct BFormatDec *dec);
+void bformatdec_free(struct BFormatDec **dec);
 void bformatdec_reset(struct BFormatDec *dec, const struct AmbDecConf *conf, ALsizei chancount, ALuint srate, const ALsizei chanmap[MAX_OUTPUT_CHANNELS]);
 
 /* Decodes the ambisonic input to the given output channels. */
@@ -38,11 +46,11 @@ void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[B
 
 
 /* Stand-alone first-order upsampler. Kept here because it shares some stuff
- * with bformatdec.
+ * with bformatdec. Assumes a periphonic (4-channel) input mix!
  */
 struct AmbiUpsampler *ambiup_alloc();
-void ambiup_free(struct AmbiUpsampler *ambiup);
-void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device);
+void ambiup_free(struct AmbiUpsampler **ambiup);
+void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device, ALfloat w_scale, ALfloat xyz_scale);
 
 void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
 
@@ -55,7 +63,7 @@ typedef struct BandSplitter {
     ALfloat hp_z1;
 } BandSplitter;
 
-void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult);
+void bandsplit_init(BandSplitter *splitter, ALfloat f0norm);
 void bandsplit_clear(BandSplitter *splitter);
 void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
                        const ALfloat *input, ALsizei count);
@@ -68,8 +76,16 @@ typedef struct SplitterAllpass {
     ALfloat z1;
 } SplitterAllpass;
 
-void splitterap_init(SplitterAllpass *splitter, ALfloat freq_mult);
+void splitterap_init(SplitterAllpass *splitter, ALfloat f0norm);
 void splitterap_clear(SplitterAllpass *splitter);
 void splitterap_process(SplitterAllpass *splitter, ALfloat *restrict samples, ALsizei count);
 
+
+typedef struct FrontStablizer {
+    SplitterAllpass APFilter[MAX_OUTPUT_CHANNELS];
+    BandSplitter LFilter, RFilter;
+    alignas(16) ALfloat LSplit[2][BUFFERSIZE];
+    alignas(16) ALfloat RSplit[2][BUFFERSIZE];
+} FrontStablizer;
+
 #endif /* BFORMATDEC_H */

+ 0 - 5081
libs/openal-soft/Alc/bsinc.c

@@ -1,5081 +0,0 @@
-
-#include "config.h"
-
-#include "AL/al.h"
-#include "align.h"
-
-/* Table of windowed sinc coefficients and deltas.  This 11th order filter
- * has a rejection of -60 dB, yielding a transition width of ~0.302
- * (normalized frequency).  Order increases when downsampling to a limit of
- * one octave, after which the quality of the filter (transition width)
- * suffers to reduce the CPU cost.  The bandlimiting will cut all sound after
- * downsampling by ~2.73 octaves.
- */
-alignas(16) const ALfloat bsincTab[18840] =
-{
-    /* 24, 0 */ +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f, +0.000000000e+00f,
-
-    /* 24, 0 */ +1.501390780e-03f, +3.431804419e-03f, +6.512803185e-03f, +1.091425387e-02f, +1.664594540e-02f, +2.351091132e-02f, +3.109255671e-02f, +3.878419288e-02f, +4.586050701e-02f, +5.158058002e-02f, +5.530384985e-02f, +5.659614054e-02f, +5.530384985e-02f, +5.158058002e-02f, +4.586050701e-02f, +3.878419288e-02f, +3.109255671e-02f, +2.351091132e-02f, +1.664594540e-02f, +1.091425387e-02f, +6.512803185e-03f, +3.431804419e-03f, +1.501390780e-03f, +4.573885647e-04f,
-    /* 24, 1 */ +1.413186400e-03f, +3.279858311e-03f, +6.282638036e-03f, +1.059932179e-02f, +1.625135142e-02f, +2.305547031e-02f, +3.060840342e-02f, +3.831365198e-02f, +4.545054680e-02f, +5.127577001e-02f, +5.513916011e-02f, +5.659104154e-02f, +5.545895049e-02f, +5.187752167e-02f, +4.626513642e-02f, +3.925233583e-02f, +3.157717954e-02f, +2.396921539e-02f, +1.704503934e-02f, +1.123445076e-02f, +6.748179094e-03f, +3.588275667e-03f, +1.593065611e-03f, +5.022154476e-04f,
-    /* 24, 2 */ +1.328380648e-03f, +3.132379333e-03f, +6.057656813e-03f, +1.028967374e-02f, +1.586133102e-02f, +2.260301890e-02f, +3.012488684e-02f, +3.784089895e-02f, +4.503543229e-02f, +5.096323022e-02f, +5.496495842e-02f, +5.657574693e-02f, +5.560438923e-02f, +5.216645963e-02f, +4.666426010e-02f, +3.971789474e-02f, +3.206210284e-02f, +2.443025293e-02f, +1.744855617e-02f, +1.155988996e-02f, +6.988790100e-03f, +3.749328623e-03f, +1.688282347e-03f, +5.494305796e-04f,
-    /* 24, 3 */ +1.246901403e-03f, +2.989308098e-03f, +5.837830254e-03f, +9.985325752e-03f, +1.547595434e-02f, +2.215368059e-02f, +2.964217216e-02f, +3.736611920e-02f, +4.461534144e-02f, +5.064310236e-02f, +5.478132634e-02f, +5.655026396e-02f, +5.574009777e-02f, +5.244726189e-02f, +4.705770477e-02f, +4.018068337e-02f, +3.254715574e-02f, +2.489389144e-02f, +1.785641537e-02f, +1.189054572e-02f, +7.234657995e-03f, +3.915018340e-03f, +1.787112015e-03f, +5.991047395e-04f,
-    /* 24, 4 */ +1.168676301e-03f, +2.850583915e-03f, +5.623126723e-03f, +9.686290690e-03f, +1.509528803e-02f, +2.170757578e-02f, +2.916042250e-02f, +3.688949768e-02f, +4.419045351e-02f, +5.031553118e-02f, +5.458834968e-02f, +5.651460469e-02f, +5.586601230e-02f, +5.271979985e-02f, +4.744529894e-02f, +4.064051541e-02f, +3.303216567e-02f, +2.535999546e-02f, +1.826853297e-02f, +1.222638897e-02f, +7.485801959e-03f, +4.085398290e-03f, +1.889625146e-03f, +6.513091287e-04f,
-    /* 24, 5 */ +1.093632798e-03f, +2.716144855e-03f, +5.413512274e-03f, +9.392578266e-03f, +1.471939531e-02f, +2.126482169e-02f, +2.867979883e-02f, +3.641121873e-02f, +4.376094899e-02f, +4.998066438e-02f, +5.438611851e-02f, +5.646878599e-02f, +5.598207354e-02f, +5.298394839e-02f, +4.782687301e-02f, +4.109720465e-02f, +3.351695842e-02f, +2.582842673e-02f, +1.868482156e-02f, +1.256738733e-02f, +7.742238512e-03f, +4.260520294e-03f, +1.995891717e-03f, +7.061153220e-04f,
-    /* 24, 6 */ +1.021698233e-03f, +2.585927824e-03f, +5.208950715e-03f, +9.104195104e-03f, +1.434833590e-02f, +2.082553239e-02f, +2.820045990e-02f, +3.593146595e-02f, +4.332700946e-02f, +4.963865252e-02f, +5.417472708e-02f, +5.641282954e-02f, +5.608822683e-02f, +5.323958602e-02f, +4.820225940e-02f, +4.155056502e-02f, +3.400135826e-02f, +2.629904416e-02f, +1.910519032e-02f, +1.291350505e-02f, +8.003981455e-03f, +4.440434453e-03f, +2.105981077e-03f, +7.635952183e-04f,
-    /* 24, 7 */ +9.527998831e-04f, +2.459868628e-03f, +5.009403670e-03f, +8.821144768e-03f, +1.398216608e-02f, +2.038981869e-02f, +2.772256216e-02f, +3.545042216e-02f, +4.288881749e-02f, +4.928964888e-02f, +5.395427373e-02f, +5.634676181e-02f, +5.618442211e-02f, +5.348659488e-02f, +4.857129262e-02f, +4.200041076e-02f, +3.448518802e-02f, +2.677170395e-02f, +1.952954505e-02f, +1.326470299e-02f, +8.271041819e-03f, +4.625189083e-03f, +2.219961884e-03f, +8.238209888e-04f,
-    /* 24, 8 */ +8.868650246e-04f, +2.337902042e-03f, +4.814830642e-03f, +8.543427812e-03f, +1.362093865e-02f, +1.995778816e-02f, +2.724625964e-02f, +3.496826923e-02f, +4.244655653e-02f, +4.893380942e-02f, +5.372486088e-02f, +5.627061400e-02f, +5.627061400e-02f, +5.372486088e-02f, +4.893380942e-02f, +4.244655653e-02f, +3.496826923e-02f, +2.724625964e-02f, +1.995778816e-02f, +1.362093865e-02f, +8.543427812e-03f, +4.814830642e-03f, +2.337902042e-03f, +8.868650246e-04f,
-    /* 24, 9 */ +8.238209888e-04f, +2.219961884e-03f, +4.625189083e-03f, +8.271041819e-03f, +1.326470299e-02f, +1.952954505e-02f, +2.677170395e-02f, +3.448518802e-02f, +4.200041076e-02f, +4.857129262e-02f, +5.348659488e-02f, +5.618442211e-02f, +5.634676181e-02f, +5.395427373e-02f, +4.928964888e-02f, +4.288881749e-02f, +3.545042216e-02f, +2.772256216e-02f, +2.038981869e-02f, +1.398216608e-02f, +8.821144768e-03f, +5.009403670e-03f, +2.459868628e-03f, +9.527998831e-04f,
-    /* 24,10 */ +7.635952183e-04f, +2.105981077e-03f, +4.440434453e-03f, +8.003981455e-03f, +1.291350505e-02f, +1.910519032e-02f, +2.629904416e-02f, +3.400135826e-02f, +4.155056502e-02f, +4.820225940e-02f, +5.323958602e-02f, +5.608822683e-02f, +5.641282954e-02f, +5.417472708e-02f, +4.963865252e-02f, +4.332700946e-02f, +3.593146595e-02f, +2.820045990e-02f, +2.082553239e-02f, +1.434833590e-02f, +9.104195104e-03f, +5.208950715e-03f, +2.585927824e-03f, +1.021698233e-03f,
-    /* 24,11 */ +7.061153220e-04f, +1.995891717e-03f, +4.260520294e-03f, +7.742238512e-03f, +1.256738733e-02f, +1.868482156e-02f, +2.582842673e-02f, +3.351695842e-02f, +4.109720465e-02f, +4.782687301e-02f, +5.298394839e-02f, +5.598207354e-02f, +5.646878599e-02f, +5.438611851e-02f, +4.998066438e-02f, +4.376094899e-02f, +3.641121873e-02f, +2.867979883e-02f, +2.126482169e-02f, +1.471939531e-02f, +9.392578266e-03f, +5.413512274e-03f, +2.716144855e-03f, +1.093632798e-03f,
-    /* 24,12 */ +6.513091287e-04f, +1.889625146e-03f, +4.085398290e-03f, +7.485801959e-03f, +1.222638897e-02f, +1.826853297e-02f, +2.535999546e-02f, +3.303216567e-02f, +4.064051541e-02f, +4.744529894e-02f, +5.271979985e-02f, +5.586601230e-02f, +5.651460469e-02f, +5.458834968e-02f, +5.031553118e-02f, +4.419045351e-02f, +3.688949768e-02f, +2.916042250e-02f, +2.170757578e-02f, +1.509528803e-02f, +9.686290690e-03f, +5.623126723e-03f, +2.850583915e-03f, +1.168676301e-03f,
-    /* 24,13 */ +5.991047395e-04f, +1.787112015e-03f, +3.915018340e-03f, +7.234657995e-03f, +1.189054572e-02f, +1.785641537e-02f, +2.489389144e-02f, +3.254715574e-02f, +4.018068337e-02f, +4.705770477e-02f, +5.244726189e-02f, +5.574009777e-02f, +5.655026396e-02f, +5.478132634e-02f, +5.064310236e-02f, +4.461534144e-02f, +3.736611920e-02f, +2.964217216e-02f, +2.215368059e-02f, +1.547595434e-02f, +9.985325752e-03f, +5.837830254e-03f, +2.989308098e-03f, +1.246901403e-03f,
-    /* 24,14 */ +5.494305796e-04f, +1.688282347e-03f, +3.749328623e-03f, +6.988790100e-03f, +1.155988996e-02f, +1.744855617e-02f, +2.443025293e-02f, +3.206210284e-02f, +3.971789474e-02f, +4.666426010e-02f, +5.216645963e-02f, +5.560438923e-02f, +5.657574693e-02f, +5.496495842e-02f, +5.096323022e-02f, +4.503543229e-02f, +3.784089895e-02f, +3.012488684e-02f, +2.260301890e-02f, +1.586133102e-02f, +1.028967374e-02f, +6.057656813e-03f, +3.132379333e-03f, +1.328380648e-03f,
-    /* 24,15 */ +5.022154476e-04f, +1.593065611e-03f, +3.588275667e-03f, +6.748179094e-03f, +1.123445076e-02f, +1.704503934e-02f, +2.396921539e-02f, +3.157717954e-02f, +3.925233583e-02f, +4.626513642e-02f, +5.187752167e-02f, +5.545895049e-02f, +5.659104154e-02f, +5.513916011e-02f, +5.127577001e-02f, +4.545054680e-02f, +3.831365198e-02f, +3.060840342e-02f, +2.305547031e-02f, +1.625135142e-02f, +1.059932179e-02f, +6.282638036e-03f, +3.279858311e-03f, +1.413186400e-03f,
-    /* 24, 0 */ -1.127794091e-03f, -1.412146034e-03f, -3.831821143e-04f, +3.227045776e-03f, +1.066768284e-02f, +2.270769386e-02f, +3.918787347e-02f, +5.876378120e-02f, +7.897914846e-02f, +9.670702233e-02f, +1.088639494e-01f, +1.131922811e-01f, +1.088639494e-01f, +9.670702233e-02f, +7.897914846e-02f, +5.876378120e-02f, +3.918787347e-02f, +2.270769386e-02f, +1.066768284e-02f, +3.227045776e-03f, -3.831821143e-04f, -1.412146034e-03f, -1.127794091e-03f, -4.881068065e-04f,
-    /* 24, 1 */ -1.090580766e-03f, -1.420873386e-03f, -5.091873886e-04f, +2.900756187e-03f, +1.007202248e-02f, +2.181774373e-02f, +3.804709217e-02f, +5.749143322e-02f, +7.775467878e-02f, +9.573284944e-02f, +1.083163184e-01f, +1.131750947e-01f, +1.093805191e-01f, +9.765915788e-02f, +8.019389052e-02f, +6.003885715e-02f, +4.034112484e-02f, +2.361538773e-02f, +1.128161899e-02f, +3.568453927e-03f, -2.470940015e-04f, -1.398398357e-03f, -1.163769773e-03f, -5.264712252e-04f,
-    /* 24, 2 */ -1.052308046e-03f, -1.424863695e-03f, -6.254426725e-04f, +2.589304991e-03f, +9.494532203e-03f, +2.094570441e-02f, +3.691925193e-02f, +5.622252667e-02f, +7.652128881e-02f, +9.473734332e-02f, +1.077380418e-01f, +1.131235487e-01f, +1.098656350e-01f, +9.858856505e-02f, +8.139809812e-02f, +6.131593665e-02f, +4.150635732e-02f, +2.454063933e-02f, +1.191392194e-02f, +3.925253463e-03f, -1.005901154e-04f, -1.379341793e-03f, -1.198322390e-03f, -5.655319713e-04f,
-    /* 24, 3 */ -1.013146991e-03f, -1.424394748e-03f, -7.322803183e-04f, +2.292405169e-03f, +8.935092066e-03f, +2.009172411e-02f, +3.580480556e-02f, +5.495776346e-02f, +7.527978553e-02f, +9.372122042e-02f, +1.071295572e-01f, +1.130376830e-01f, +1.103189277e-01f, +9.949456662e-02f, +8.259096568e-02f, +6.259428489e-02f, +4.268306423e-02f, +2.548324354e-02f, +1.256466766e-02f, +4.297709369e-03f, +5.666214823e-05f, -1.354682733e-03f, -1.231259367e-03f, -6.052075404e-04f,
-    /* 24, 4 */ -9.732614753e-04f, -1.419738627e-03f, -8.300317840e-04f, +2.009763334e-03f, +8.393568260e-03f, +1.925593236e-02f, +3.470418745e-02f, +5.369783330e-02f, +7.403097485e-02f, +9.268520876e-02f, +1.064913245e-01f, +1.129175635e-01f, +1.107400515e-01f, +1.003764999e-01f, +8.377168968e-02f, +6.387315732e-02f, +4.387072153e-02f, +2.644297610e-02f, +1.323391671e-02f, +4.686078310e-03f, +2.249946366e-04f, -1.324122762e-03f, -1.262381011e-03f, -6.454100415e-04f,
-    /* 24, 5 */ -9.328082015e-04f, -1.411161525e-03f, -9.190272443e-04f, +1.741080225e-03f, +7.869813543e-03f, +1.843844016e-02f, +3.361781336e-02f, +5.244341325e-02f, +7.277566076e-02f, +9.163004717e-02f, +1.058238246e-01f, +1.127632829e-01f, +1.111286847e-01f, +1.012337173e-01f, +8.493946948e-02f, +6.515180031e-02f, +4.506878807e-02f, +2.741959349e-02f, +1.392171386e-02f, +5.090608136e-03f, +4.047380047e-04f, -1.287358924e-03f, -1.291480556e-03f, -6.860450823e-04f,
-    /* 24, 6 */ -8.919367204e-04f, -1.398923562e-03f, -9.995952120e-04f, +1.486051192e-03f, +7.363667669e-03f, +1.763934022e-02f, +3.254608027e-02f, +5.119516710e-02f, +7.151464464e-02f, +9.055648452e-02f, +1.051275597e-01f, +1.125749599e-01f, +1.114845301e-01f, +1.020655875e-01f, +8.609350809e-02f, +6.642945179e-02f, +4.627670593e-02f, +2.841283293e-02f, +1.462808772e-02f, +5.511537402e-03f, +5.962212734e-04f, -1.244083985e-03f, -1.318344226e-03f, -7.270116618e-04f,
-    /* 24, 7 */ -8.507894667e-04f, -1.383278624e-03f, -1.072062171e-03f, +1.244366682e-03f, +6.874957829e-03f, +1.685870710e-02f, +3.148936626e-02f, +4.995374490e-02f, +7.024872443e-02f, +8.946527894e-02f, +1.044030520e-01f, +1.123527394e-01f, +1.118073151e-01f, +1.028714955e-01f, +8.723301301e-02f, +6.770534195e-02f, +4.749390083e-02f, +2.942241233e-02f, +1.535305047e-02f, +5.949094883e-03f, +7.997713791e-04f, -1.193986722e-03f, -1.342751302e-03f, -7.682020711e-04f,
-    /* 24, 8 */ -8.095018024e-04f, -1.364474212e-03f, -1.136752219e-03f, +1.015712718e-03f, +6.403499096e-03f, +1.609659749e-02f, +3.044803032e-02f, +4.871978245e-02f, +6.897869391e-02f, +8.835719701e-02f, +1.036508436e-01f, +1.120967923e-01f, +1.120967923e-01f, +1.036508436e-01f, +8.835719701e-02f, +6.897869391e-02f, +4.871978245e-02f, +3.044803032e-02f, +1.609659749e-02f, +6.403499096e-03f, +1.015712718e-03f, -1.136752219e-03f, -1.364474212e-03f, -8.095018024e-04f,
-    /* 24, 9 */ -7.682020711e-04f, -1.342751302e-03f, -1.193986722e-03f, +7.997713791e-04f, +5.949094883e-03f, +1.535305047e-02f, +2.942241233e-02f, +4.749390083e-02f, +6.770534195e-02f, +8.723301301e-02f, +1.028714955e-01f, +1.118073151e-01f, +1.123527394e-01f, +1.044030520e-01f, +8.946527894e-02f, +7.024872443e-02f, +4.995374490e-02f, +3.148936626e-02f, +1.685870710e-02f, +6.874957829e-03f, +1.244366682e-03f, -1.072062171e-03f, -1.383278624e-03f, -8.507894667e-04f,
-    /* 24,10 */ -7.270116618e-04f, -1.318344226e-03f, -1.244083985e-03f, +5.962212734e-04f, +5.511537402e-03f, +1.462808772e-02f, +2.841283293e-02f, +4.627670593e-02f, +6.642945179e-02f, +8.609350809e-02f, +1.020655875e-01f, +1.114845301e-01f, +1.125749599e-01f, +1.051275597e-01f, +9.055648452e-02f, +7.151464464e-02f, +5.119516710e-02f, +3.254608027e-02f, +1.763934022e-02f, +7.363667669e-03f, +1.486051192e-03f, -9.995952120e-04f, -1.398923562e-03f, -8.919367204e-04f,
-    /* 24,11 */ -6.860450823e-04f, -1.291480556e-03f, -1.287358924e-03f, +4.047380047e-04f, +5.090608136e-03f, +1.392171386e-02f, +2.741959349e-02f, +4.506878807e-02f, +6.515180031e-02f, +8.493946948e-02f, +1.012337173e-01f, +1.111286847e-01f, +1.127632829e-01f, +1.058238246e-01f, +9.163004717e-02f, +7.277566076e-02f, +5.244341325e-02f, +3.361781336e-02f, +1.843844016e-02f, +7.869813543e-03f, +1.741080225e-03f, -9.190272443e-04f, -1.411161525e-03f, -9.328082015e-04f,
-    /* 24,12 */ -6.454100415e-04f, -1.262381011e-03f, -1.324122762e-03f, +2.249946366e-04f, +4.686078310e-03f, +1.323391671e-02f, +2.644297610e-02f, +4.387072153e-02f, +6.387315732e-02f, +8.377168968e-02f, +1.003764999e-01f, +1.107400515e-01f, +1.129175635e-01f, +1.064913245e-01f, +9.268520876e-02f, +7.403097485e-02f, +5.369783330e-02f, +3.470418745e-02f, +1.925593236e-02f, +8.393568260e-03f, +2.009763334e-03f, -8.300317840e-04f, -1.419738627e-03f, -9.732614753e-04f,
-    /* 24,13 */ -6.052075404e-04f, -1.231259367e-03f, -1.354682733e-03f, +5.666214823e-05f, +4.297709369e-03f, +1.256466766e-02f, +2.548324354e-02f, +4.268306423e-02f, +6.259428489e-02f, +8.259096568e-02f, +9.949456662e-02f, +1.103189277e-01f, +1.130376830e-01f, +1.071295572e-01f, +9.372122042e-02f, +7.527978553e-02f, +5.495776346e-02f, +3.580480556e-02f, +2.009172411e-02f, +8.935092066e-03f, +2.292405169e-03f, -7.322803183e-04f, -1.424394748e-03f, -1.013146991e-03f,
-    /* 24,14 */ -5.655319713e-04f, -1.198322390e-03f, -1.379341793e-03f, -1.005901154e-04f, +3.925253463e-03f, +1.191392194e-02f, +2.454063933e-02f, +4.150635732e-02f, +6.131593665e-02f, +8.139809812e-02f, +9.858856505e-02f, +1.098656350e-01f, +1.131235487e-01f, +1.077380418e-01f, +9.473734332e-02f, +7.652128881e-02f, +5.622252667e-02f, +3.691925193e-02f, +2.094570441e-02f, +9.494532203e-03f, +2.589304991e-03f, -6.254426725e-04f, -1.424863695e-03f, -1.052308046e-03f,
-    /* 24,15 */ -5.264712252e-04f, -1.163769773e-03f, -1.398398357e-03f, -2.470940015e-04f, +3.568453927e-03f, +1.128161899e-02f, +2.361538773e-02f, +4.034112484e-02f, +6.003885715e-02f, +8.019389052e-02f, +9.765915788e-02f, +1.093805191e-01f, +1.131750947e-01f, +1.083163184e-01f, +9.573284944e-02f, +7.775467878e-02f, +5.749143322e-02f, +3.804709217e-02f, +2.181774373e-02f, +1.007202248e-02f, +2.900756187e-03f, -5.091873886e-04f, -1.420873386e-03f, -1.090580766e-03f,
-    /* 24, 0 */ -6.542299160e-04f, -2.850723396e-03f, -6.490258587e-03f, -9.960104872e-03f, -9.809478345e-03f, -1.578994128e-03f, +1.829834548e-02f, +5.025161588e-02f, +9.015425381e-02f, +1.297327779e-01f, +1.589915292e-01f, +1.697884216e-01f, +1.589915292e-01f, +1.297327779e-01f, +9.015425381e-02f, +5.025161588e-02f, +1.829834548e-02f, -1.578994128e-03f, -9.809478345e-03f, -9.960104872e-03f, -6.490258587e-03f, -2.850723396e-03f, -6.542299160e-04f, +6.349952235e-05f,
-    /* 24, 1 */ -5.715660670e-04f, -2.664319167e-03f, -6.241370053e-03f, -9.805460951e-03f, -1.000906214e-02f, -2.409006146e-03f, +1.668518463e-02f, +4.795494216e-02f, +8.756853655e-02f, +1.274593023e-01f, +1.576392865e-01f, +1.697451719e-01f, +1.602699418e-01f, +1.319653222e-01f, +9.273931864e-02f, +5.258078166e-02f, +1.996024013e-02f, -7.024321916e-04f, -9.578061730e-03f, -1.010098516e-02f, -6.739131402e-03f, -3.043301383e-03f, -7.429059724e-04f, +4.968305000e-05f,
-    /* 24, 2 */ -4.947700224e-04f, -2.484234158e-03f, -5.993080931e-03f, -9.638098137e-03f, -1.017794029e-02f, -3.193110201e-03f, +1.512113085e-02f, +4.569233080e-02f, +8.498458400e-02f, +1.251473534e-01f, +1.562147818e-01f, +1.696154741e-01f, +1.614730379e-01f, +1.341545065e-01f, +9.532128436e-02f, +5.494080034e-02f, +2.167042077e-02f, +2.212715669e-04f, -9.313697641e-03f, -1.022703863e-02f, -6.987342300e-03f, -3.241882098e-03f, -8.377276082e-04f, +3.267464436e-05f,
-    /* 24, 3 */ -4.236872966e-04f, -2.310589033e-03f, -5.745975157e-03f, -9.459041324e-03f, -1.031725016e-02f, -3.931996122e-03f, +1.360648366e-02f, +4.346528177e-02f, +8.240478048e-02f, +1.227994149e-01f, +1.547196623e-01f, +1.693994819e-01f, +1.625994153e-01f, +1.362979353e-01f, +9.789767810e-02f, +5.732996534e-02f, +2.342836441e-02f, +1.192656872e-03f, -9.015286272e-03f, -1.033718507e-02f, -7.234214214e-03f, -3.446268223e-03f, -9.388162067e-04f, +1.226776811e-05f,
-    /* 24, 4 */ -3.581542611e-04f, -2.143480447e-03f, -5.500605429e-03f, -9.269294257e-03f, -1.042813706e-02f, -4.626399385e-03f, +1.214146970e-02f, +4.127522351e-02f, +7.983147433e-02f, +1.204179923e-01f, +1.531556516e-01f, +1.690974512e-01f, +1.636477581e-01f, +1.383932498e-01f, +1.004660042e-01f, +5.974650439e-02f, +2.523347234e-02f, +2.212209196e-03f, -8.681745020e-03f, -1.043032883e-02f, -7.479039479e-03f, -3.656235461e-03f, -1.046280200e-03f, -1.174474466e-05f,
-    /* 24, 5 */ -2.979990698e-04f, -1.982981877e-03f, -5.257493218e-03f, -9.069838305e-03f, -1.051175200e-02f, -5.277098842e-03f, +1.072624378e-02f, +3.912351177e-02f, +7.726697481e-02f, +1.180056089e-01f, +1.515245471e-01f, +1.687097397e-01f, +1.646168392e-01f, +1.404381320e-01f, +1.030237476e-01f, +6.218858132e-02f, +2.708506973e-02f, +3.280357753e-03f, -8.312010872e-03f, -1.050536039e-02f, -7.721080180e-03f, -3.871531888e-03f, -1.160214103e-03f, -3.957001380e-05f,
-    /* 24, 6 */ -2.430425717e-04f, -1.829144469e-03f, -5.017128860e-03f, -8.861631306e-03f, -1.056924947e-02f, -5.884914422e-03f, +9.360889972e-03f, +3.701142868e-02f, +7.471354913e-02f, +1.155648023e-01f, +1.498282170e-01f, +1.682368061e-01f, +1.655055219e-01f, +1.424303080e-01f, +1.055683777e-01f, +6.465429798e-02f, +2.898240538e-02f, +4.397473555e-03f, -7.905042791e-03f, -1.056115807e-02f, -7.959568583e-03f, -4.091877352e-03f, -1.280697546e-03f, -7.141440876e-05f,
-    /* 24, 7 */ -1.930992056e-04f, -1.681997919e-03f, -4.779971710e-03f, -8.645606504e-03f, -1.060178532e-02f, -6.450704795e-03f, +8.045422842e-03f, +3.494018190e-02f, +7.217341954e-02f, +1.130981205e-01f, +1.480685972e-01f, +1.676792097e-01f, +1.663127619e-01f, +1.443675516e-01f, +1.080973515e-01f, +6.714169632e-02f, +3.092465153e-02f, +5.563867546e-03f, -7.459824124e-03f, -1.059658974e-02f, -8.193707637e-03f, -4.316962918e-03f, -1.407794310e-03f, -1.074828157e-04f,
-    /* 24, 8 */ -1.479778772e-04f, -1.541551365e-03f, -4.546450360e-03f, -8.422671559e-03f, -1.061051465e-02f, -6.975365011e-03f, +6.779788805e-03f, +3.291090392e-02f, +6.964876056e-02f, +1.106081178e-01f, +1.462476880e-01f, +1.670376092e-01f, +1.670376092e-01f, +1.462476880e-01f, +1.106081178e-01f, +6.964876056e-02f, +3.291090392e-02f, +6.779788805e-03f, -6.975365011e-03f, -1.061051465e-02f, -8.422671559e-03f, -4.546450360e-03f, -1.541551365e-03f, -1.479778772e-04f,
-    /* 24, 9 */ -1.074828157e-04f, -1.407794310e-03f, -4.316962918e-03f, -8.193707637e-03f, -1.059658974e-02f, -7.459824124e-03f, +5.563867546e-03f, +3.092465153e-02f, +6.714169632e-02f, +1.080973515e-01f, +1.443675516e-01f, +1.663127619e-01f, +1.676792097e-01f, +1.480685972e-01f, +1.130981205e-01f, +7.217341954e-02f, +3.494018190e-02f, +8.045422842e-03f, -6.450704795e-03f, -1.060178532e-02f, -8.645606504e-03f, -4.779971710e-03f, -1.681997919e-03f, -1.930992056e-04f,
-    /* 24,10 */ -7.141440876e-05f, -1.280697546e-03f, -4.091877352e-03f, -7.959568583e-03f, -1.056115807e-02f, -7.905042791e-03f, +4.397473555e-03f, +2.898240538e-02f, +6.465429798e-02f, +1.055683777e-01f, +1.424303080e-01f, +1.655055219e-01f, +1.682368061e-01f, +1.498282170e-01f, +1.155648023e-01f, +7.471354913e-02f, +3.701142868e-02f, +9.360889972e-03f, -5.884914422e-03f, -1.056924947e-02f, -8.861631306e-03f, -5.017128860e-03f, -1.829144469e-03f, -2.430425717e-04f,
-    /* 24,11 */ -3.957001380e-05f, -1.160214103e-03f, -3.871531888e-03f, -7.721080180e-03f, -1.050536039e-02f, -8.312010872e-03f, +3.280357753e-03f, +2.708506973e-02f, +6.218858132e-02f, +1.030237476e-01f, +1.404381320e-01f, +1.646168392e-01f, +1.687097397e-01f, +1.515245471e-01f, +1.180056089e-01f, +7.726697481e-02f, +3.912351177e-02f, +1.072624378e-02f, -5.277098842e-03f, -1.051175200e-02f, -9.069838305e-03f, -5.257493218e-03f, -1.982981877e-03f, -2.979990698e-04f,
-    /* 24,12 */ -1.174474466e-05f, -1.046280200e-03f, -3.656235461e-03f, -7.479039479e-03f, -1.043032883e-02f, -8.681745020e-03f, +2.212209196e-03f, +2.523347234e-02f, +5.974650439e-02f, +1.004660042e-01f, +1.383932498e-01f, +1.636477581e-01f, +1.690974512e-01f, +1.531556516e-01f, +1.204179923e-01f, +7.983147433e-02f, +4.127522351e-02f, +1.214146970e-02f, -4.626399385e-03f, -1.042813706e-02f, -9.269294257e-03f, -5.500605429e-03f, -2.143480447e-03f, -3.581542611e-04f,
-    /* 24,13 */ +1.226776811e-05f, -9.388162067e-04f, -3.446268223e-03f, -7.234214214e-03f, -1.033718507e-02f, -9.015286272e-03f, +1.192656872e-03f, +2.342836441e-02f, +5.732996534e-02f, +9.789767810e-02f, +1.362979353e-01f, +1.625994153e-01f, +1.693994819e-01f, +1.547196623e-01f, +1.227994149e-01f, +8.240478048e-02f, +4.346528177e-02f, +1.360648366e-02f, -3.931996122e-03f, -1.031725016e-02f, -9.459041324e-03f, -5.745975157e-03f, -2.310589033e-03f, -4.236872966e-04f,
-    /* 24,14 */ +3.267464436e-05f, -8.377276082e-04f, -3.241882098e-03f, -6.987342300e-03f, -1.022703863e-02f, -9.313697641e-03f, +2.212715669e-04f, +2.167042077e-02f, +5.494080034e-02f, +9.532128436e-02f, +1.341545065e-01f, +1.614730379e-01f, +1.696154741e-01f, +1.562147818e-01f, +1.251473534e-01f, +8.498458400e-02f, +4.569233080e-02f, +1.512113085e-02f, -3.193110201e-03f, -1.017794029e-02f, -9.638098137e-03f, -5.993080931e-03f, -2.484234158e-03f, -4.947700224e-04f,
-    /* 24,15 */ +4.968305000e-05f, -7.429059724e-04f, -3.043301383e-03f, -6.739131402e-03f, -1.010098516e-02f, -9.578061730e-03f, -7.024321916e-04f, +1.996024013e-02f, +5.258078166e-02f, +9.273931864e-02f, +1.319653222e-01f, +1.602699418e-01f, +1.697451719e-01f, +1.576392865e-01f, +1.274593023e-01f, +8.756853655e-02f, +4.795494216e-02f, +1.668518463e-02f, -2.409006146e-03f, -1.000906214e-02f, -9.805460951e-03f, -6.241370053e-03f, -2.664319167e-03f, -5.715660670e-04f,
-    /* 24, 0 */ +1.619229527e-03f, +2.585184252e-03f, +7.650378125e-04f, -6.171975840e-03f, -1.695416291e-02f, -2.423274385e-02f, -1.612533623e-02f, +1.737483974e-02f, +7.628093610e-02f, +1.465254238e-01f, +2.041060488e-01f, +2.263845622e-01f, +2.041060488e-01f, +1.465254238e-01f, +7.628093610e-02f, +1.737483974e-02f, -1.612533623e-02f, -2.423274385e-02f, -1.695416291e-02f, -6.171975840e-03f, +7.650378125e-04f, +2.585184252e-03f, +1.619229527e-03f, +4.203426526e-04f,
-    /* 24, 1 */ +1.531668339e-03f, +2.575087939e-03f, +1.015030141e-03f, -5.584253498e-03f, -1.627529113e-02f, -2.409742304e-02f, -1.730694612e-02f, +1.446720847e-02f, +7.205349539e-02f, +1.422361210e-01f, +2.013530187e-01f, +2.262942875e-01f, +2.067165090e-01f, +1.507648574e-01f, +8.055624103e-02f, +2.038667606e-02f, -1.484111026e-02f, -2.430745079e-02f, -1.762106127e-02f, -6.776879595e-03f, +4.938567092e-04f, +2.584413048e-03f, +1.706479068e-03f, +4.743886054e-04f,
-    /* 24, 2 */ +1.444251783e-03f, +2.554897668e-03f, +1.244217996e-03f, -5.014646771e-03f, -1.558700841e-02f, -2.390468713e-02f, -1.838770218e-02f, +1.166535016e-02f, +6.787901036e-02f, +1.379034790e-01f, +1.984620386e-01f, +2.260236194e-01f, +2.091800031e-01f, +1.549479100e-01f, +8.487414623e-02f, +2.350091114e-02f, -1.345266938e-02f, -2.431836796e-02f, -1.827334019e-02f, -7.397926552e-03f, +2.011593926e-04f, +2.571998910e-03f, +1.792931314e-03f, +5.318997770e-04f,
-    /* 24, 3 */ +1.357406375e-03f, +2.525382259e-03f, +1.453038602e-03f, -4.463987325e-03f, -1.489178967e-02f, -2.365774922e-02f, -1.936952211e-02f, +8.970595311e-03f, +6.376239146e-02f, +1.335340325e-01f, +1.954379419e-01f, +2.255730254e-01f, +2.114923689e-01f, +1.590681020e-01f, +8.922922426e-02f, +2.671549986e-02f, -1.195858585e-02f, -2.426235104e-02f, -1.890827435e-02f, -8.033973302e-03f, -1.133208208e-04f, +2.547167581e-03f, +1.878071789e-03f, +5.928148062e-04f,
-    /* 24, 4 */ +1.271528621e-03f, +2.487303056e-03f, +1.641978155e-03f, -3.933006021e-03f, -1.419201875e-02f, -2.335982837e-02f, -2.025447087e-02f, +6.384038515e-03f, +5.970836021e-02f, +1.291343068e-01f, +1.922857641e-01f, +2.249432832e-01f, +2.136496877e-01f, +1.631190001e-01f, +9.361589375e-02f, +3.002815853e-02f, -1.035761042e-02f, -2.413629608e-02f, -1.952306378e-02f, -8.683770335e-03f, -4.497860188e-04f, +2.509149105e-03f, +1.961357874e-03f, +6.570484107e-04f,
-    /* 24, 5 */ +1.186984902e-03f, +2.441411339e-03f, +1.811567846e-03f, -3.422334900e-03f, -1.348998519e-02f, -2.301414142e-02f, -2.104475231e-02f, +3.906540614e-03f, +5.572144173e-02f, +1.247108046e-01f, +1.890107314e-01f, +2.241354793e-01f, +2.156482934e-01f, +1.670942309e-01f, +9.802842938e-02f, +3.343636564e-02f, -8.648679404e-03f, -2.393714847e-02f, -2.011483893e-02f, -9.345961431e-03f, -8.083699235e-04f, +2.457181100e-03f, +2.042219659e-03f, +7.244903794e-04f,
-    /* 24, 6 */ +1.104111497e-03f, +2.388445882e-03f, +1.962379900e-03f, -2.932509404e-03f, -1.278788140e-02f, -2.262389503e-02f, -2.174270056e-02f, +1.538731332e-03f, +5.180595798e-02f, +1.202699924e-01f, +1.856182490e-01f, +2.231510062e-01f, +2.174847808e-01f, +1.709874949e-01f, +1.024609723e-01f, +3.693736330e-02f, -6.830921421e-03f, -2.366191192e-02f, -2.068066597e-02f, -1.001908338e-02f, -1.189134206e-03f, +2.390512141e-03f, +2.120060933e-03f, +7.950046334e-04f,
-    /* 24, 7 */ +1.023214729e-03f, +2.329130668e-03f, +2.095023622e-03f, -2.463970822e-03f, -1.208780014e-02f, -2.219227795e-02f, -2.235077131e-02f, -7.189875350e-04f, +4.796602143e-02f, +1.158182872e-01f, +1.821138888e-01f, +2.219915591e-01f, +2.191560137e-01f, +1.747925803e-01f, +1.069075413e-01f, +4.052815924e-02f, -4.903663772e-03f, -2.330765754e-02f, -2.121755248e-02f, -1.070156599e-02f, -1.592064902e-03f, +2.308405249e-03f, +2.194260355e-03f, +8.684283615e-04f,
-    /* 24, 8 */ +9.445712380e-04f, +2.264172764e-03f, +2.210141486e-03f, -2.017068943e-03f, -1.139173248e-02f, -2.172245353e-02f, -2.287153293e-02f, -2.866438416e-03f, +4.420552946e-02f, +1.113620436e-01f, +1.785033768e-01f, +2.206591322e-01f, +2.206591322e-01f, +1.785033768e-01f, +1.113620436e-01f, +4.420552946e-02f, -2.866438416e-03f, -2.287153293e-02f, -2.172245353e-02f, -1.139173248e-02f, -2.017068943e-03f, +2.210141486e-03f, +2.264172764e-03f, +9.445712380e-04f,
-    /* 24, 9 */ +8.684283615e-04f, +2.194260355e-03f, +2.308405249e-03f, -1.592064902e-03f, -1.070156599e-02f, -2.121755248e-02f, -2.330765754e-02f, -4.903663772e-03f, +4.052815924e-02f, +1.069075413e-01f, +1.747925803e-01f, +2.191560137e-01f, +2.219915591e-01f, +1.821138888e-01f, +1.158182872e-01f, +4.796602143e-02f, -7.189875350e-04f, -2.235077131e-02f, -2.219227795e-02f, -1.208780014e-02f, -2.463970822e-03f, +2.095023622e-03f, +2.329130668e-03f, +1.023214729e-03f,
-    /* 24,10 */ +7.950046334e-04f, +2.120060933e-03f, +2.390512141e-03f, -1.189134206e-03f, -1.001908338e-02f, -2.068066597e-02f, -2.366191192e-02f, -6.830921421e-03f, +3.693736330e-02f, +1.024609723e-01f, +1.709874949e-01f, +2.174847808e-01f, +2.231510062e-01f, +1.856182490e-01f, +1.202699924e-01f, +5.180595798e-02f, +1.538731332e-03f, -2.174270056e-02f, -2.262389503e-02f, -1.278788140e-02f, -2.932509404e-03f, +1.962379900e-03f, +2.388445882e-03f, +1.104111497e-03f,
-    /* 24,11 */ +7.244903794e-04f, +2.042219659e-03f, +2.457181100e-03f, -8.083699235e-04f, -9.345961431e-03f, -2.011483893e-02f, -2.393714847e-02f, -8.648679404e-03f, +3.343636564e-02f, +9.802842938e-02f, +1.670942309e-01f, +2.156482934e-01f, +2.241354793e-01f, +1.890107314e-01f, +1.247108046e-01f, +5.572144173e-02f, +3.906540614e-03f, -2.104475231e-02f, -2.301414142e-02f, -1.348998519e-02f, -3.422334900e-03f, +1.811567846e-03f, +2.441411339e-03f, +1.186984902e-03f,
-    /* 24,12 */ +6.570484107e-04f, +1.961357874e-03f, +2.509149105e-03f, -4.497860188e-04f, -8.683770335e-03f, -1.952306378e-02f, -2.413629608e-02f, -1.035761042e-02f, +3.002815853e-02f, +9.361589375e-02f, +1.631190001e-01f, +2.136496877e-01f, +2.249432832e-01f, +1.922857641e-01f, +1.291343068e-01f, +5.970836021e-02f, +6.384038515e-03f, -2.025447087e-02f, -2.335982837e-02f, -1.419201875e-02f, -3.933006021e-03f, +1.641978155e-03f, +2.487303056e-03f, +1.271528621e-03f,
-    /* 24,13 */ +5.928148062e-04f, +1.878071789e-03f, +2.547167581e-03f, -1.133208208e-04f, -8.033973302e-03f, -1.890827435e-02f, -2.426235104e-02f, -1.195858585e-02f, +2.671549986e-02f, +8.922922426e-02f, +1.590681020e-01f, +2.114923689e-01f, +2.255730254e-01f, +1.954379419e-01f, +1.335340325e-01f, +6.376239146e-02f, +8.970595311e-03f, -1.936952211e-02f, -2.365774922e-02f, -1.489178967e-02f, -4.463987325e-03f, +1.453038602e-03f, +2.525382259e-03f, +1.357406375e-03f,
-    /* 24,14 */ +5.318997770e-04f, +1.792931314e-03f, +2.571998910e-03f, +2.011593926e-04f, -7.397926552e-03f, -1.827334019e-02f, -2.431836796e-02f, -1.345266938e-02f, +2.350091114e-02f, +8.487414623e-02f, +1.549479100e-01f, +2.091800031e-01f, +2.260236194e-01f, +1.984620386e-01f, +1.379034790e-01f, +6.787901036e-02f, +1.166535016e-02f, -1.838770218e-02f, -2.390468713e-02f, -1.558700841e-02f, -5.014646771e-03f, +1.244217996e-03f, +2.554897668e-03f, +1.444251783e-03f,
-    /* 24,15 */ +4.743886054e-04f, +1.706479068e-03f, +2.584413048e-03f, +4.938567092e-04f, -6.776879595e-03f, -1.762106127e-02f, -2.430745079e-02f, -1.484111026e-02f, +2.038667606e-02f, +8.055624103e-02f, +1.507648574e-01f, +2.067165090e-01f, +2.262942875e-01f, +2.013530187e-01f, +1.422361210e-01f, +7.205349539e-02f, +1.446720847e-02f, -1.730694612e-02f, -2.409742304e-02f, -1.627529113e-02f, -5.584253498e-03f, +1.015030141e-03f, +2.575087939e-03f, +1.531668339e-03f,
-    /* 24, 0 */ -5.620806651e-04f, +1.786951327e-03f, +6.445247430e-03f, +8.135220753e-03f, -1.055728075e-03f, -2.182587186e-02f, -3.862210468e-02f, -2.392616717e-02f, +4.121375257e-02f, +1.449837419e-01f, +2.427850309e-01f, +2.829807027e-01f, +2.427850309e-01f, +1.449837419e-01f, +4.121375257e-02f, -2.392616717e-02f, -3.862210468e-02f, -2.182587186e-02f, -1.055728075e-03f, +8.135220753e-03f, +6.445247430e-03f, +1.786951327e-03f, -5.620806651e-04f, -5.120724112e-04f,
-    /* 24, 1 */ -6.104492932e-04f, +1.548760636e-03f, +6.159105160e-03f, +8.277197332e-03f, -7.779733613e-05f, -2.039475337e-02f, -3.819819741e-02f, -2.624621678e-02f, +3.569722776e-02f, +1.380982730e-01f, +2.379020609e-01f, +2.828154582e-01f, +2.474326717e-01f, +1.518487179e-01f, +4.689321837e-02f, -2.139810919e-02f, -3.892035913e-02f, -2.324619800e-02f, -2.084809535e-03f, +7.948411519e-03f, +6.721048149e-03f, +2.036121529e-03f, -5.037148469e-04f, -5.469834647e-04f,
-    /* 24, 2 */ -6.493280747e-04f, +1.322056610e-03f, +5.864617557e-03f, +8.376206823e-03f, +8.476165560e-04f, -1.895882060e-02f, -3.765599422e-02f, -2.836041007e-02f, +3.035103267e-02f, +1.312062799e-01f, +2.327950895e-01f, +2.823201223e-01f, +2.518341522e-01f, +1.586790922e-01f, +5.272765217e-02f, -1.866041870e-02f, -3.908572584e-02f, -2.464952038e-02f, -3.163389088e-03f, +7.715013258e-03f, +6.984447000e-03f, +2.295668536e-03f, -4.348733531e-04f, -5.801620624e-04f,
-    /* 24, 3 */ -6.792484933e-04f, +1.107253309e-03f, +5.563710253e-03f, +8.434210700e-03f, +1.719427448e-03f, -1.752380524e-02f, -3.700294628e-02f, -3.027140813e-02f, +2.518195985e-02f, +1.243215533e-01f, +2.274759065e-01f, +2.814958870e-01f, +2.559791715e-01f, +1.654606562e-01f, +5.870851072e-02f, -1.571201688e-02f, -3.911111998e-02f, -2.602940857e-02f, -4.289522020e-03f, +7.433392157e-03f, +7.233326681e-03f, +2.564892035e-03f, -3.551113499e-04f, -6.111213026e-04f,
-    /* 24, 4 */ -7.007615573e-04f, +9.046745282e-04f, +5.258232435e-03f, +8.453253159e-03f, +2.536821717e-03f, -1.609518093e-02f, -3.624657153e-02f, -3.198236083e-02f, +2.019619593e-02f, +1.174576676e-01f, +2.219567270e-01f, +2.803447347e-01f, +2.598579915e-01f, +1.721791413e-01f, +6.482669661e-02f, -1.255238605e-02f, -3.898963496e-02f, -2.737922870e-02f, -5.460966964e-03f, +7.102050305e-03f, +7.465520628e-03f, +2.842992490e-03f, -2.640225027e-04f, -6.393525967e-04f,
-    /* 24, 5 */ -7.144333056e-04f, +7.145569834e-04f, +4.949951622e-03f, +8.435448103e-03f, +3.299249997e-03f, -1.467815287e-02f, -3.539442781e-02f, -3.349688539e-02f, +1.539931407e-02f, +1.106279448e-01f, +2.162501543e-01f, +2.788694321e-01f, +2.634614666e-01f, +1.788202595e-01f, +7.107257652e-02f, -9.181583996e-03f, -3.871457066e-02f, -2.869216031e-02f, -6.675182397e-03f, +6.719638981e-03f, +7.678821339e-03f, +3.129069982e-03f, -1.612438490e-04f, -6.643278432e-04f,
-    /* 24, 6 */ -7.208404573e-04f, +5.370537968e-04f, +4.640549073e-03f, +8.382966356e-03f, +4.006418111e-03f, -1.327764882e-02f, -3.445408633e-02f, -3.481904366e-02f, +1.079626845e-02f, +1.038454185e-01f, +2.103691410e-01f, +2.770735210e-01f, +2.667810728e-01f, +1.853697450e-01f, +7.743600141e-02f, -5.600256400e-03f, -3.827946167e-02f, -2.996121443e-02f, -7.929324241e-03f, +6.284971816e-03f, +7.870989279e-03f, +3.422123547e-03f, -4.646067064e-05f, -6.855018549e-04f,
-    /* 24, 7 */ -7.205662235e-04f, +3.722382714e-04f, +4.331615834e-03f, +8.298023138e-03f, +4.658277300e-03f, -1.189831143e-02f, -3.343310598e-02f, -3.595331849e-02f, +6.391391026e-03f, +9.712280024e-02f, +2.043269499e-01f, +2.749613076e-01f, +2.698089343e-01f, +1.918133956e-01f, +8.390632879e-02f, -1.809647645e-03f, -3.767810524e-02f, -3.117925279e-02f, -9.220244622e-03f, +5.797037759e-03f, +8.039762345e-03f, +3.721051017e-03f, +8.058866307e-05f, -7.023150347e-04f,
-    /* 24, 8 */ -7.141962964e-04f, +2.201079121e-04f, +4.024649403e-03f, +8.182865872e-03f, +5.255013788e-03f, -1.054449181e-02f, -3.233900821e-02f, -3.690458903e-02f, +2.188390323e-03f, +9.047244679e-02f, +1.981371140e-01f, +2.725378483e-01f, +2.725378483e-01f, +1.981371140e-01f, +9.047244679e-02f, +2.188390323e-03f, -3.690458903e-02f, -3.233900821e-02f, -1.054449181e-02f, +5.255013788e-03f, +8.182865872e-03f, +4.024649403e-03f, +2.201079121e-04f, -7.141962964e-04f,
-    /* 24, 9 */ -7.023150347e-04f, +8.058866307e-05f, +3.721051017e-03f, +8.039762345e-03f, +5.797037759e-03f, -9.220244622e-03f, -3.117925279e-02f, -3.767810524e-02f, -1.809647645e-03f, +8.390632879e-02f, +1.918133956e-01f, +2.698089343e-01f, +2.749613076e-01f, +2.043269499e-01f, +9.712280024e-02f, +6.391391026e-03f, -3.595331849e-02f, -3.343310598e-02f, -1.189831143e-02f, +4.658277300e-03f, +8.298023138e-03f, +4.331615834e-03f, +3.722382714e-04f, -7.205662235e-04f,
-    /* 24,10 */ -6.855018549e-04f, -4.646067064e-05f, +3.422123547e-03f, +7.870989279e-03f, +6.284971816e-03f, -7.929324241e-03f, -2.996121443e-02f, -3.827946167e-02f, -5.600256400e-03f, +7.743600141e-02f, +1.853697450e-01f, +2.667810728e-01f, +2.770735210e-01f, +2.103691410e-01f, +1.038454185e-01f, +1.079626845e-02f, -3.481904366e-02f, -3.445408633e-02f, -1.327764882e-02f, +4.006418111e-03f, +8.382966356e-03f, +4.640549073e-03f, +5.370537968e-04f, -7.208404573e-04f,
-    /* 24,11 */ -6.643278432e-04f, -1.612438490e-04f, +3.129069982e-03f, +7.678821339e-03f, +6.719638981e-03f, -6.675182397e-03f, -2.869216031e-02f, -3.871457066e-02f, -9.181583996e-03f, +7.107257652e-02f, +1.788202595e-01f, +2.634614666e-01f, +2.788694321e-01f, +2.162501543e-01f, +1.106279448e-01f, +1.539931407e-02f, -3.349688539e-02f, -3.539442781e-02f, -1.467815287e-02f, +3.299249997e-03f, +8.435448103e-03f, +4.949951622e-03f, +7.145569834e-04f, -7.144333056e-04f,
-    /* 24,12 */ -6.393525967e-04f, -2.640225027e-04f, +2.842992490e-03f, +7.465520628e-03f, +7.102050305e-03f, -5.460966964e-03f, -2.737922870e-02f, -3.898963496e-02f, -1.255238605e-02f, +6.482669661e-02f, +1.721791413e-01f, +2.598579915e-01f, +2.803447347e-01f, +2.219567270e-01f, +1.174576676e-01f, +2.019619593e-02f, -3.198236083e-02f, -3.624657153e-02f, -1.609518093e-02f, +2.536821717e-03f, +8.453253159e-03f, +5.258232435e-03f, +9.046745282e-04f, -7.007615573e-04f,
-    /* 24,13 */ -6.111213026e-04f, -3.551113499e-04f, +2.564892035e-03f, +7.233326681e-03f, +7.433392157e-03f, -4.289522020e-03f, -2.602940857e-02f, -3.911111998e-02f, -1.571201688e-02f, +5.870851072e-02f, +1.654606562e-01f, +2.559791715e-01f, +2.814958870e-01f, +2.274759065e-01f, +1.243215533e-01f, +2.518195985e-02f, -3.027140813e-02f, -3.700294628e-02f, -1.752380524e-02f, +1.719427448e-03f, +8.434210700e-03f, +5.563710253e-03f, +1.107253309e-03f, -6.792484933e-04f,
-    /* 24,14 */ -5.801620624e-04f, -4.348733531e-04f, +2.295668536e-03f, +6.984447000e-03f, +7.715013258e-03f, -3.163389088e-03f, -2.464952038e-02f, -3.908572584e-02f, -1.866041870e-02f, +5.272765217e-02f, +1.586790922e-01f, +2.518341522e-01f, +2.823201223e-01f, +2.327950895e-01f, +1.312062799e-01f, +3.035103267e-02f, -2.836041007e-02f, -3.765599422e-02f, -1.895882060e-02f, +8.476165560e-04f, +8.376206823e-03f, +5.864617557e-03f, +1.322056610e-03f, -6.493280747e-04f,
-    /* 24,15 */ -5.469834647e-04f, -5.037148469e-04f, +2.036121529e-03f, +6.721048149e-03f, +7.948411519e-03f, -2.084809535e-03f, -2.324619800e-02f, -3.892035913e-02f, -2.139810919e-02f, +4.689321837e-02f, +1.518487179e-01f, +2.474326717e-01f, +2.828154582e-01f, +2.379020609e-01f, +1.380982730e-01f, +3.569722776e-02f, -2.624621678e-02f, -3.819819741e-02f, -2.039475337e-02f, -7.779733613e-05f, +8.277197332e-03f, +6.159105160e-03f, +1.548760636e-03f, -6.104492932e-04f,
-    /* 24, 0 */ -1.197013499e-03f, -3.320493122e-03f, -1.144245270e-03f, +8.577337679e-03f, +1.627759141e-02f, +3.152522439e-03f, -3.255249254e-02f, -5.362651723e-02f, -5.304244056e-03f, +1.253006387e-01f, +2.738089134e-01f, +3.395768433e-01f, +2.738089134e-01f, +1.253006387e-01f, -5.304244056e-03f, -5.362651723e-02f, -3.255249254e-02f, +3.152522439e-03f, +1.627759141e-02f, +8.577337679e-03f, -1.144245270e-03f, -3.320493122e-03f, -1.197013499e-03f, +1.261205705e-04f,
-    /* 24, 1 */ -1.060573898e-03f, -3.246029352e-03f, -1.514205592e-03f, +7.849505167e-03f, +1.622707505e-02f, +4.797556391e-03f, -3.017446993e-02f, -5.385088872e-02f, -1.098434059e-02f, +1.155960124e-01f, +2.659858985e-01f, +3.393017042e-01f, +2.812897341e-01f, +1.350895441e-01f, +7.263382766e-04f, -5.311639759e-02f, -3.488122370e-02f, +1.404407443e-03f, +1.624118609e-02f, +9.301572693e-03f, -7.399572733e-04f, -3.377916464e-03f, -1.338504197e-03f, +9.901282259e-05f,
-    /* 24, 2 */ -9.298712414e-04f, -3.156277727e-03f, -1.849729696e-03f, +7.122444811e-03f, +1.609438844e-02f, +6.335978542e-03f, -2.776122262e-02f, -5.380213751e-02f, -1.630850202e-02f, +1.060004951e-01f, +2.578448120e-01f, +3.384771755e-01f, +2.884051592e-01f, +1.449371908e-01f, +7.100538384e-03f, -5.230860749e-02f, -3.714619841e-02f, -4.425295608e-04f, +1.611336946e-02f, +1.001762126e-02f, -3.016869975e-04f, -3.416553196e-03f, -1.484263468e-03f, +6.526428163e-05f,
-    /* 24, 3 */ -8.054954021e-04f, -3.052984548e-03f, -2.150934111e-03f, +6.400291527e-03f, +1.588450664e-02f, +7.764974256e-03f, -2.532636892e-02f, -5.349351937e-02f, -2.127269005e-02f, +9.653812261e-02f, +2.494105998e-01f, +3.371059190e-01f, +2.951330020e-01f, +1.548174220e-01f, +1.381006797e-02f, -5.119199897e-02f, -3.933260713e-02f, -2.383292518e-03f, +1.588995194e-02f, +1.072069264e-02f, +1.699725421e-04f, -3.434676821e-03f, -1.633412152e-03f, +2.453170435e-05f,
-    /* 24, 4 */ -6.879416803e-04f, -2.937877889e-03f, -2.418147761e-03f, +5.686932142e-03f, +1.560259046e-02f, +9.082429619e-03f, -2.288303213e-02f, -5.293884648e-02f, -2.587426360e-02f, +8.723205545e-02f, +2.407089312e-01f, +3.351923590e-01f, +3.014521813e-01f, +1.647035561e-01f, +2.084522321e-02f, -4.975626781e-02f, -4.142535273e-02f, -4.412143180e-03f, +1.556708209e-02f, +1.140581394e-02f, +6.741710759e-04f, -3.430594409e-03f, -1.784975276e-03f, -2.348660763e-05f,
-    /* 24, 5 */ -5.776128643e-04f, -2.812656385e-03f, -2.651898517e-03f, +4.985994150e-03f, +1.525394912e-02f, +1.028691298e-02f, -2.044379769e-02f, -5.215241275e-02f, -3.011195925e-02f, +7.810450253e-02f, +2.317660961e-01f, +3.327426635e-01f, +3.073428069e-01f, +1.745684830e-01f, +2.819489579e-02f, -4.799202051e-02f, -4.340911052e-02f, -6.522599631e-03f, +1.514128438e-02f, +1.206785167e-02f, +1.209792693e-03f, -3.402660968e-03f, -1.937883690e-03f, -7.904503123e-05f,
-    /* 24, 6 */ -4.748218959e-04f, -2.678978820e-03f, -2.852899102e-03f, +4.300836533e-03f, +1.484400357e-02f, +1.137765361e-02f, -1.802067434e-02f, -5.114891871e-02f, -3.398586582e-02f, +6.917664952e-02f, +2.226089010e-01f, +3.297647184e-01f, +3.127862620e-01f, +1.843847637e-01f, +3.584659036e-02f, -4.589083871e-02f, -4.526839113e-02f, -8.707438641e-03f, +1.460949637e-02f, +1.270153536e-02f, +1.775448814e-03f, -3.349294247e-03f, -2.090976552e-03f, -1.423449116e-04f,
-    /* 24, 7 */ -3.797950945e-04f, -2.538454547e-03f, -3.022032460e-03f, +3.634542645e-03f, +1.437825069e-02f, +1.235451773e-02f, -1.562505912e-02f, -4.994339647e-02f, -3.749739364e-02f, +6.046859273e-02f, +2.132645624e-01f, +3.262680950e-01f, +3.177652787e-01f, +1.941247325e-01f, +4.378644843e-02f, -4.344534054e-02f, -4.698760595e-02f, -1.095870195e-02f, +1.396910503e-02f, +1.330148306e-02f, +2.369472628e-03f, -3.268989872e-03f, -2.243004675e-03f, -2.135289700e-04f,
-    /* 24, 8 */ -2.926758839e-04f, -2.392634763e-03f, -3.160336722e-03f, +2.989915102e-03f, +1.386222860e-02f, +1.321798203e-02f, -1.326770657e-02f, -4.855113496e-02f, -4.064923848e-02f, +5.199927852e-02f, +2.037606007e-01f, +3.222640100e-01f, +3.222640100e-01f, +2.037606007e-01f, +5.199927852e-02f, -4.064923848e-02f, -4.855113496e-02f, -1.326770657e-02f, +1.321798203e-02f, +1.386222860e-02f, +2.989915102e-03f, -3.160336722e-03f, -2.392634763e-03f, -2.926758839e-04f,
-    /* 24, 9 */ -2.135289700e-04f, -2.243004675e-03f, -3.268989872e-03f, +2.369472628e-03f, +1.330148306e-02f, +1.396910503e-02f, -1.095870195e-02f, -4.698760595e-02f, -4.344534054e-02f, +4.378644843e-02f, +1.941247325e-01f, +3.177652787e-01f, +3.262680950e-01f, +2.132645624e-01f, +6.046859273e-02f, -3.749739364e-02f, -4.994339647e-02f, -1.562505912e-02f, +1.235451773e-02f, +1.437825069e-02f, +3.634542645e-03f, -3.022032460e-03f, -2.538454547e-03f, -3.797950945e-04f,
-    /* 24,10 */ -1.423449116e-04f, -2.090976552e-03f, -3.349294247e-03f, +1.775448814e-03f, +1.270153536e-02f, +1.460949637e-02f, -8.707438641e-03f, -4.526839113e-02f, -4.589083871e-02f, +3.584659036e-02f, +1.843847637e-01f, +3.127862620e-01f, +3.297647184e-01f, +2.226089010e-01f, +6.917664952e-02f, -3.398586582e-02f, -5.114891871e-02f, -1.802067434e-02f, +1.137765361e-02f, +1.484400357e-02f, +4.300836533e-03f, -2.852899102e-03f, -2.678978820e-03f, -4.748218959e-04f,
-    /* 24,11 */ -7.904503123e-05f, -1.937883690e-03f, -3.402660968e-03f, +1.209792693e-03f, +1.206785167e-02f, +1.514128438e-02f, -6.522599631e-03f, -4.340911052e-02f, -4.799202051e-02f, +2.819489579e-02f, +1.745684830e-01f, +3.073428069e-01f, +3.327426635e-01f, +2.317660961e-01f, +7.810450253e-02f, -3.011195925e-02f, -5.215241275e-02f, -2.044379769e-02f, +1.028691298e-02f, +1.525394912e-02f, +4.985994150e-03f, -2.651898517e-03f, -2.812656385e-03f, -5.776128643e-04f,
-    /* 24,12 */ -2.348660763e-05f, -1.784975276e-03f, -3.430594409e-03f, +6.741710759e-04f, +1.140581394e-02f, +1.556708209e-02f, -4.412143180e-03f, -4.142535273e-02f, -4.975626781e-02f, +2.084522321e-02f, +1.647035561e-01f, +3.014521813e-01f, +3.351923590e-01f, +2.407089312e-01f, +8.723205545e-02f, -2.587426360e-02f, -5.293884648e-02f, -2.288303213e-02f, +9.082429619e-03f, +1.560259046e-02f, +5.686932142e-03f, -2.418147761e-03f, -2.937877889e-03f, -6.879416803e-04f,
-    /* 24,13 */ +2.453170435e-05f, -1.633412152e-03f, -3.434676821e-03f, +1.699725421e-04f, +1.072069264e-02f, +1.588995194e-02f, -2.383292518e-03f, -3.933260713e-02f, -5.119199897e-02f, +1.381006797e-02f, +1.548174220e-01f, +2.951330020e-01f, +3.371059190e-01f, +2.494105998e-01f, +9.653812261e-02f, -2.127269005e-02f, -5.349351937e-02f, -2.532636892e-02f, +7.764974256e-03f, +1.588450664e-02f, +6.400291527e-03f, -2.150934111e-03f, -3.052984548e-03f, -8.054954021e-04f,
-    /* 24,14 */ +6.526428163e-05f, -1.484263468e-03f, -3.416553196e-03f, -3.016869975e-04f, +1.001762126e-02f, +1.611336946e-02f, -4.425295608e-04f, -3.714619841e-02f, -5.230860749e-02f, +7.100538384e-03f, +1.449371908e-01f, +2.884051592e-01f, +3.384771755e-01f, +2.578448120e-01f, +1.060004951e-01f, -1.630850202e-02f, -5.380213751e-02f, -2.776122262e-02f, +6.335978542e-03f, +1.609438844e-02f, +7.122444811e-03f, -1.849729696e-03f, -3.156277727e-03f, -9.298712414e-04f,
-    /* 24,15 */ +9.901282259e-05f, -1.338504197e-03f, -3.377916464e-03f, -7.399572733e-04f, +9.301572693e-03f, +1.624118609e-02f, +1.404407443e-03f, -3.488122370e-02f, -5.311639759e-02f, +7.263382766e-04f, +1.350895441e-01f, +2.812897341e-01f, +3.393017042e-01f, +2.659858985e-01f, +1.155960124e-01f, -1.098434059e-02f, -5.385088872e-02f, -3.017446993e-02f, +4.797556391e-03f, +1.622707505e-02f, +7.849505167e-03f, -1.514205592e-03f, -3.246029352e-03f, -1.060573898e-03f,
-    /* 20, 0 */ -4.161478318e-03f, -1.410215661e-03f, +1.216462436e-02f, +1.839753508e-02f, -1.019572218e-02f, -5.576407638e-02f, -3.857794503e-02f, +9.869941459e-02f, +2.903842315e-01f, +3.819037908e-01f, +2.903842315e-01f, +9.869941459e-02f, -3.857794503e-02f, -5.576407638e-02f, -1.019572218e-02f, +1.839753508e-02f, +1.216462436e-02f, -1.410215661e-03f, -4.161478318e-03f, -1.002136091e-03f,
-    /* 20, 1 */ -4.024812873e-03f, -1.935046598e-03f, +1.120868183e-02f, +1.884704309e-02f, -7.349314558e-03f, -5.377462232e-02f, -4.306909662e-02f, +8.713841011e-02f, +2.797272456e-01f, +3.815142140e-01f, +3.006231905e-01f, +1.105090175e-01f, -3.357053763e-02f, -5.750258783e-02f, -1.313424017e-02f, +1.779561475e-02f, +1.309754391e-02f, -8.338854378e-04f, -4.274968522e-03f, -1.184613130e-03f,
-    /* 20, 2 */ -3.867923854e-03f, -2.407896178e-03f, +1.023778220e-02f, +1.914947854e-02f, -4.608279480e-03f, -5.155911253e-02f, -4.704785126e-02f, +7.585987841e-02f, +2.686929243e-01f, +3.803470604e-01f, +3.104047352e-01f, +1.225315522e-01f, -2.804532708e-02f, -5.896552129e-02f, -1.615031726e-02f, +1.703673197e-02f, +1.399907244e-02f, -2.069933478e-04f, -4.362323551e-03f, -1.376799150e-03f,
-    /* 20, 3 */ -3.693729756e-03f, -2.828715617e-03f, +9.259646102e-03f, +1.931089692e-02f, -1.984565051e-03f, -4.914254142e-02f, -5.052030051e-02f, +6.489576800e-02f, +2.573230589e-01f, +3.784070525e-01f, +3.196909791e-01f, +1.347297046e-01f, -2.200314505e-02f, -6.012863981e-02f, -1.922814732e-02f, +1.611719780e-02f, +1.486058724e-02f, +4.690483654e-04f, -4.420601658e-03f, -1.577606548e-03f,
-    /* 20, 4 */ -3.505092707e-03f, -3.197865053e-03f, +8.281610454e-03f, +1.933799402e-02f, +5.112106557e-04f, -4.654987033e-02f, -5.349467921e-02f, +5.427598051e-02f, +2.456603330e-01f, +3.757020336e-01f, +3.284457292e-01f, +1.470646693e-01f, -1.544725782e-02f, -6.096825350e-02f, -2.235071271e-02f, +1.503425320e-02f, +1.567326271e-02f, +1.192336051e-03f, -4.446907145e-03f, -1.785766437e-03f,
-    /* 20, 5 */ -3.304797071e-03f, -3.516087186e-03f, +7.310594668e-03f, +1.923802927e-02f, +2.869766685e-03f, -4.380589142e-02f, -5.598126618e-02f, +4.402826232e-02f, +2.337481127e-01f, +3.722429273e-01f, +3.366346688e-01f, +1.594963158e-01f, -8.383409345e-03f, -6.146136934e-02f, -2.549983702e-02f, +1.378613431e-02f, +1.642812632e-02f, +1.960461229e-03f, -4.438419451e-03f, -1.999828319e-03f,
-    /* 20, 6 */ -3.095529963e-03f, -3.784479230e-03f, +6.353071566e-03f, +1.901874863e-02f, +5.083157654e-03f, -4.093509653e-02f, -5.799227582e-02f, +3.417810958e-02f, +2.216302330e-01f, +3.680436800e-01f, +3.442255330e-01f, +1.719833640e-01f, -8.198514564e-04f, -6.158584092e-02f, -2.865624686e-02f, +1.237213363e-02f, +1.711611824e-02f, +2.770500592e-03f, -4.392423280e-03f, -2.218161540e-03f,
-    /* 20, 7 */ -2.879863731e-03f, -4.004463491e-03f, +5.415043050e-03f, +1.868830751e-02f, +7.144763866e-03f, -3.796155187e-02f, -5.954174144e-02f, +2.474868675e-02f, +2.093507858e-01f, +3.631211887e-01f, +3.511882735e-01f, +1.844835679e-01f, +7.232639407e-03f, -6.132051750e-02f, -3.179964276e-02f, +1.079265669e-02f, +1.772815465e-02f, +3.619009684e-03f, -4.306339536e-03f, -2.438958613e-03f,
-    /* 20, 8 */ -2.660240473e-03f, -4.177756859e-03f, +4.502020476e-03f, +1.825519424e-02f, +9.049273418e-03f, -3.490877898e-02f, -6.064539119e-02f, +1.576075912e-02f, +1.969539074e-01f, +3.574952133e-01f, +3.574952133e-01f, +1.969539074e-01f, +1.576075912e-02f, -6.064539119e-02f, -3.490877898e-02f, +9.049273418e-03f, +1.825519424e-02f, +4.502020476e-03f, -4.177756859e-03f, -2.660240473e-03f,
-    /* 20, 9 */ -2.438958613e-03f, -4.306339536e-03f, +3.619009684e-03f, +1.772815465e-02f, +1.079265669e-02f, -3.179964276e-02f, -6.132051750e-02f, +7.232639407e-03f, +1.844835679e-01f, +3.511882735e-01f, +3.631211887e-01f, +2.093507858e-01f, +2.474868675e-02f, -5.954174144e-02f, -3.796155187e-02f, +7.144763866e-03f, +1.868830751e-02f, +5.415043050e-03f, -4.004463491e-03f, -2.879863731e-03f,
-    /* 20,10 */ -2.218161540e-03f, -4.392423280e-03f, +2.770500592e-03f, +1.711611824e-02f, +1.237213363e-02f, -2.865624686e-02f, -6.158584092e-02f, -8.198514564e-04f, +1.719833640e-01f, +3.442255330e-01f, +3.680436800e-01f, +2.216302330e-01f, +3.417810958e-02f, -5.799227582e-02f, -4.093509653e-02f, +5.083157654e-03f, +1.901874863e-02f, +6.353071566e-03f, -3.784479230e-03f, -3.095529963e-03f,
-    /* 20,11 */ -1.999828319e-03f, -4.438419451e-03f, +1.960461229e-03f, +1.642812632e-02f, +1.378613431e-02f, -2.549983702e-02f, -6.146136934e-02f, -8.383409345e-03f, +1.594963158e-01f, +3.366346688e-01f, +3.722429273e-01f, +2.337481127e-01f, +4.402826232e-02f, -5.598126618e-02f, -4.380589142e-02f, +2.869766685e-03f, +1.923802927e-02f, +7.310594668e-03f, -3.516087186e-03f, -3.304797071e-03f,
-    /* 20,12 */ -1.785766437e-03f, -4.446907145e-03f, +1.192336051e-03f, +1.567326271e-02f, +1.503425320e-02f, -2.235071271e-02f, -6.096825350e-02f, -1.544725782e-02f, +1.470646693e-01f, +3.284457292e-01f, +3.757020336e-01f, +2.456603330e-01f, +5.427598051e-02f, -5.349467921e-02f, -4.654987033e-02f, +5.112106557e-04f, +1.933799402e-02f, +8.281610454e-03f, -3.197865053e-03f, -3.505092707e-03f,
-    /* 20,13 */ -1.577606548e-03f, -4.420601658e-03f, +4.690483654e-04f, +1.486058724e-02f, +1.611719780e-02f, -1.922814732e-02f, -6.012863981e-02f, -2.200314505e-02f, +1.347297046e-01f, +3.196909791e-01f, +3.784070525e-01f, +2.573230589e-01f, +6.489576800e-02f, -5.052030051e-02f, -4.914254142e-02f, -1.984565051e-03f, +1.931089692e-02f, +9.259646102e-03f, -2.828715617e-03f, -3.693729756e-03f,
-    /* 20,14 */ -1.376799150e-03f, -4.362323551e-03f, -2.069933478e-04f, +1.399907244e-02f, +1.703673197e-02f, -1.615031726e-02f, -5.896552129e-02f, -2.804532708e-02f, +1.225315522e-01f, +3.104047352e-01f, +3.803470604e-01f, +2.686929243e-01f, +7.585987841e-02f, -4.704785126e-02f, -5.155911253e-02f, -4.608279480e-03f, +1.914947854e-02f, +1.023778220e-02f, -2.407896178e-03f, -3.867923854e-03f,
-    /* 20,15 */ -1.184613130e-03f, -4.274968522e-03f, -8.338854378e-04f, +1.309754391e-02f, +1.779561475e-02f, -1.313424017e-02f, -5.750258783e-02f, -3.357053763e-02f, +1.105090175e-01f, +3.006231905e-01f, +3.815142140e-01f, +2.797272456e-01f, +8.713841011e-02f, -4.306909662e-02f, -5.377462232e-02f, -7.349314558e-03f, +1.884704309e-02f, +1.120868183e-02f, -1.935046598e-03f, -4.024812873e-03f,
-    /* 20, 0 */ -1.329352252e-03f, -4.865562069e-03f, +1.662947600e-03f, +1.893743982e-02f, +1.052975469e-02f, -4.314924294e-02f, -6.168215525e-02f, +6.793829558e-02f, +3.007295231e-01f, +4.214013440e-01f, +3.007295231e-01f, +6.793829558e-02f, -6.168215525e-02f, -4.314924294e-02f, +1.052975469e-02f, +1.893743982e-02f, +1.662947600e-03f, -4.865562069e-03f, -1.329352252e-03f, +0.000000000e+00f,
-    /* 20, 1 */ -1.106503038e-03f, -4.784011640e-03f, +7.620481209e-04f, +1.810159639e-02f, +1.258770510e-02f, -3.946126222e-02f, -6.412166469e-02f, +5.516844650e-02f, +2.870012762e-01f, +4.208780002e-01f, +3.139874692e-01f, +8.118253044e-02f, -5.860314053e-02f, -4.671882663e-02f, +8.254179692e-03f, +1.967037055e-02f, +2.622520317e-03f, -4.905078775e-03f, -1.565095816e-03f, +0.000000000e+00f,
-    /* 20, 2 */ -8.979094201e-04f, -4.664743082e-03f, -7.633034189e-05f, +1.717630323e-02f, +1.442449893e-02f, -3.568911340e-02f, -6.594250862e-02f, +4.291292121e-02f, +2.728656387e-01f, +4.193105477e-01f, +3.267137817e-01f, +9.485763802e-02f, -5.486676259e-02f, -5.013477905e-02f, +5.766539049e-03f, +2.028700325e-02f, +3.636071544e-03f, -4.898357639e-03f, -1.812078842e-03f, +3.513221827e-04f,
-    /* 20, 3 */ -7.046452899e-04f, -4.512131585e-03f, -8.491713087e-04f, +1.617498084e-02f, +1.603855621e-02f, -3.186582692e-02f, -6.716828458e-02f, +3.120792005e-02f, +2.583867198e-01f, +4.167067067e-01f, +3.388490774e-01f, +1.089167196e-01f, -5.045835457e-02f, -5.336106841e-02f, +3.074480429e-03f, +2.077415592e-02f, +4.698051453e-03f, -4.841360048e-03f, -2.068349661e-03f, +3.288882594e-04f,
-    /* 20, 4 */ -5.275063595e-04f, -4.330562617e-03f, -1.554266965e-03f, +1.511089362e-02f, +1.743016199e-02f, -2.802305698e-02f, -6.782511100e-02f, +2.008577030e-02f, +2.436294448e-01f, +4.130792899e-01f, +3.503362849e-01f, +1.233097059e-01f, -4.536663323e-02f, -5.636108634e-02f, +1.877878266e-04f, +2.111898038e-02f, +5.802054958e-03f, -4.730268616e-03f, -2.331660076e-03f, +2.941732022e-04f,
-    /* 20, 5 */ -3.670219514e-04f, -4.124385552e-03f, -2.190189120e-03f, +1.399704337e-02f, +1.860136846e-02f, -2.419092016e-02f, -6.794137953e-02f, +9.574818877e-03f, +2.286591711e-01f, +4.084461208e-01f, +3.611209950e-01f, +1.379835966e-01f, -3.958387309e-02f, -5.909788086e-02f, -2.881585959e-03f, +2.130909659e-02f, +6.940829951e-03f, -4.561544087e-03f, -2.599469210e-03f, +2.461206998e-04f,
-    /* 20, 6 */ -2.234691091e-04f, -3.897870552e-03f, -2.756254356e-03f, +1.284607053e-02f, +1.955588746e-02f, -2.039785121e-02f, -6.754749865e-02f, -3.006469464e-04f, +2.135413047e-01f, +4.028299211e-01f, +3.711517965e-01f, +1.528827232e-01f, -3.310606021e-02f, -6.153439984e-02f, -6.119502817e-03f, +2.133272965e-02f, +8.106294302e-03f, -4.331982887e-03f, -2.868951124e-03f, +1.837671888e-04f,
-    /* 20, 7 */ -9.688872179e-05f, -3.655168976e-03f, -3.252484018e-03f, +1.167016373e-02f, +2.029897446e-02f, -1.667047641e-02f, -6.667563061e-02f, -9.520450398e-03f, +1.983409219e-01f, +3.962581664e-01f, +3.803805952e-01f, +1.679490334e-01f, -2.593302438e-02f, -6.363374348e-02f, -9.509639499e-03f, +2.117884859e-02f, +9.289561904e-03f, -4.038774728e-03f, -3.137006363e-03f, +1.062635081e-04f,
-    /* 20, 8 */ +1.289664191e-05f, -3.400277535e-03f, -3.679559671e-03f, +1.048097797e-02f, +2.083730557e-02f, -1.303350512e-02f, -6.535942396e-02f, -1.806854797e-02f, +1.831223958e-01f, +3.887629129e-01f, +3.887629129e-01f, +1.831223958e-01f, -1.806854797e-02f, -6.535942396e-02f, -1.303350512e-02f, +2.083730557e-02f, +1.048097797e-02f, -3.679559671e-03f, -3.400277535e-03f, +1.289664191e-05f,
-    /* 20, 9 */ +1.062635081e-04f, -3.137006363e-03f, -4.038774728e-03f, +9.289561904e-03f, +2.117884859e-02f, -9.509639499e-03f, -6.363374348e-02f, -2.593302438e-02f, +1.679490334e-01f, +3.803805952e-01f, +3.962581664e-01f, +1.983409219e-01f, -9.520450398e-03f, -6.667563061e-02f, -1.667047641e-02f, +2.029897446e-02f, +1.167016373e-02f, -3.252484018e-03f, -3.655168976e-03f, -9.688872179e-05f,
-    /* 20,10 */ +1.837671888e-04f, -2.868951124e-03f, -4.331982887e-03f, +8.106294302e-03f, +2.133272965e-02f, -6.119502817e-03f, -6.153439984e-02f, -3.310606021e-02f, +1.528827232e-01f, +3.711517965e-01f, +4.028299211e-01f, +2.135413047e-01f, -3.006469464e-04f, -6.754749865e-02f, -2.039785121e-02f, +1.955588746e-02f, +1.284607053e-02f, -2.756254356e-03f, -3.897870552e-03f, -2.234691091e-04f,
-    /* 20,11 */ +2.461206998e-04f, -2.599469210e-03f, -4.561544087e-03f, +6.940829951e-03f, +2.130909659e-02f, -2.881585959e-03f, -5.909788086e-02f, -3.958387309e-02f, +1.379835966e-01f, +3.611209950e-01f, +4.084461208e-01f, +2.286591711e-01f, +9.574818877e-03f, -6.794137953e-02f, -2.419092016e-02f, +1.860136846e-02f, +1.399704337e-02f, -2.190189120e-03f, -4.124385552e-03f, -3.670219514e-04f,
-    /* 20,12 */ +2.941732022e-04f, -2.331660076e-03f, -4.730268616e-03f, +5.802054958e-03f, +2.111898038e-02f, +1.877878266e-04f, -5.636108634e-02f, -4.536663323e-02f, +1.233097059e-01f, +3.503362849e-01f, +4.130792899e-01f, +2.436294448e-01f, +2.008577030e-02f, -6.782511100e-02f, -2.802305698e-02f, +1.743016199e-02f, +1.511089362e-02f, -1.554266965e-03f, -4.330562617e-03f, -5.275063595e-04f,
-    /* 20,13 */ +3.288882594e-04f, -2.068349661e-03f, -4.841360048e-03f, +4.698051453e-03f, +2.077415592e-02f, +3.074480429e-03f, -5.336106841e-02f, -5.045835457e-02f, +1.089167196e-01f, +3.388490774e-01f, +4.167067067e-01f, +2.583867198e-01f, +3.120792005e-02f, -6.716828458e-02f, -3.186582692e-02f, +1.603855621e-02f, +1.617498084e-02f, -8.491713087e-04f, -4.512131585e-03f, -7.046452899e-04f,
-    /* 20,14 */ +3.513221827e-04f, -1.812078842e-03f, -4.898357639e-03f, +3.636071544e-03f, +2.028700325e-02f, +5.766539049e-03f, -5.013477905e-02f, -5.486676259e-02f, +9.485763802e-02f, +3.267137817e-01f, +4.193105477e-01f, +2.728656387e-01f, +4.291292121e-02f, -6.594250862e-02f, -3.568911340e-02f, +1.442449893e-02f, +1.717630323e-02f, -7.633034189e-05f, -4.664743082e-03f, -8.979094201e-04f,
-    /* 20,15 */ +0.000000000e+00f, -1.565095816e-03f, -4.905078775e-03f, +2.622520317e-03f, +1.967037055e-02f, +8.254179692e-03f, -4.671882663e-02f, -5.860314053e-02f, +8.118253044e-02f, +3.139874692e-01f, +4.208780002e-01f, +2.870012762e-01f, +5.516844650e-02f, -6.412166469e-02f, -3.946126222e-02f, +1.258770510e-02f, +1.810159639e-02f, +7.620481209e-04f, -4.784011640e-03f, -1.106503038e-03f,
-    /* 20, 0 */ +3.735125865e-04f, -2.550984103e-03f, -4.871486096e-03f, +1.016287769e-02f, +2.252246682e-02f, -2.231523982e-02f, -7.431762424e-02f, +3.414137659e-02f, +3.062278786e-01f, +4.608988972e-01f, +3.062278786e-01f, +3.414137659e-02f, -7.431762424e-02f, -2.231523982e-02f, +2.252246682e-02f, +1.016287769e-02f, -4.871486096e-03f, -2.550984103e-03f, +3.735125865e-04f, +0.000000000e+00f,
-    /* 20, 1 */ +3.929324583e-04f, -2.236335973e-03f, -5.106050653e-03f, +8.748210493e-03f, +2.303691111e-02f, -1.786093260e-02f, -7.411924916e-02f, +2.086992015e-02f, +2.890848421e-01f, +4.602142272e-01f, +3.228796668e-01f, +4.817530421e-02f, -7.382833631e-02f, -2.685541297e-02f, +2.174514756e-02f, +1.158816420e-02f, -4.555417854e-03f, -2.871502680e-03f, +3.387491377e-04f, +0.000000000e+00f,
-    /* 20, 2 */ +0.000000000e+00f, -1.931175707e-03f, -5.263447672e-03f, +7.357928950e-03f, +2.330080531e-02f, -1.352771902e-02f, -7.327813327e-02f, +8.401230311e-03f, +2.715429904e-01f, +4.581642525e-01f, +3.389493512e-01f, +6.292517925e-02f, -7.260941515e-02f, -3.144322519e-02f, +2.069454672e-02f, +1.300917115e-02f, -4.154170312e-03f, -3.193828376e-03f, +2.870815261e-04f, +0.000000000e+00f,
-    /* 20, 3 */ +0.000000000e+00f, -1.638662038e-03f, -5.348575554e-03f, +6.004591146e-03f, +2.332816092e-02f, -9.347674729e-03f, -7.184169597e-02f, -3.230759097e-03f, +2.536956771e-01f, +4.547610488e-01f, +3.543483057e-01f, +7.833843581e-02f, -7.062228683e-02f, -3.603763775e-02f, +1.936240016e-02f, +1.440996064e-02f, -3.664825055e-03f, -3.513472060e-03f, +2.170808154e-04f, +0.000000000e+00f,
-    /* 20, 4 */ +0.000000000e+00f, -1.361489293e-03f, -5.366796329e-03f, +4.699488665e-03f, +2.313444000e-02f, -5.349604768e-03f, -6.985939290e-02f, -1.399855627e-02f, +2.356365195e-01f, +4.500246402e-01f, +3.689907742e-01f, +9.435670405e-02f, -6.783220328e-02f, -4.059502103e-02f, +1.774280068e-02f, +1.577366666e-02f, -3.085314600e-03f, -3.825546457e-03f, +1.274866066e-04f, +0.000000000e+00f,
-    /* 20, 5 */ +0.000000000e+00f, -1.101888322e-03f, -5.323837897e-03f, +3.452605627e-03f, +2.273631696e-02f, -1.558959414e-03f, -6.738225311e-02f, -2.388113922e-02f, +2.174587480e-01f, +4.439828472e-01f, +3.827944964e-01f, +1.109160995e-01f, -6.420865295e-02f, -4.506940842e-02f, +1.583239979e-02f, +1.708262332e-02f, -2.414511840e-03f, -4.124801502e-03f, +1.724424543e-05f, +0.000000000e+00f,
-    /* 20, 6 */ +0.000000000e+00f, -8.616336525e-04f, -5.225698259e-03f, +2.272594520e-03f, +2.215144089e-02f, +2.002216238e-03f, -6.446241843e-02f, -3.286393171e-02f, +1.992545658e-01f, +4.366710759e-01f, +3.956813102e-01f, +1.279475618e-01f, -5.972574809e-02f, -4.941278189e-02f, +1.363059437e-02f, +1.831850983e-02f, -1.652313816e-03f, -4.405667401e-03f, -1.144582079e-04f, +0.000000000e+00f,
-    /* 20, 7 */ +0.000000000e+00f, -6.420563626e-04f, -5.078552799e-03f, +1.166768183e-03f, +2.139820068e-02f, +5.315299677e-03f, -6.115268907e-02f, -4.093872873e-02f, +1.811145256e-01f, +4.281320500e-01f, +4.075777294e-01f, +1.453772407e-01f, -5.436258502e-02f, -5.357538755e-02f, +1.113969540e-02f, +1.946251142e-02f, -7.997184460e-04f, -4.662305323e-03f, -2.681538305e-04f, +0.000000000e+00f,
-    /* 20, 8 */ +0.000000000e+00f, -4.440621234e-04f, -4.888665552e-03f, +1.411071672e-04f, +2.049549532e-02f, +8.365076494e-03f, -5.750607943e-02f, -4.810357305e-02f, +1.631269271e-01f, +4.184154881e-01f, +4.184154881e-01f, +1.631269271e-01f, -4.810357305e-02f, -5.750607943e-02f, +8.365076494e-03f, +2.049549532e-02f, +1.411071672e-04f, -4.888665552e-03f, -4.440621234e-04f, +0.000000000e+00f,
-    /* 20, 9 */ +0.000000000e+00f, -2.681538305e-04f, -4.662305323e-03f, -7.997184460e-04f, +1.946251142e-02f, +1.113969540e-02f, -5.357538755e-02f, -5.436258502e-02f, +1.453772407e-01f, +4.075777294e-01f, +4.281320500e-01f, +1.811145256e-01f, -4.093872873e-02f, -6.115268907e-02f, +5.315299677e-03f, +2.139820068e-02f, +1.166768183e-03f, -5.078552799e-03f, -6.420563626e-04f, +0.000000000e+00f,
-    /* 20,10 */ +0.000000000e+00f, -1.144582079e-04f, -4.405667401e-03f, -1.652313816e-03f, +1.831850983e-02f, +1.363059437e-02f, -4.941278189e-02f, -5.972574809e-02f, +1.279475618e-01f, +3.956813102e-01f, +4.366710759e-01f, +1.992545658e-01f, -3.286393171e-02f, -6.446241843e-02f, +2.002216238e-03f, +2.215144089e-02f, +2.272594520e-03f, -5.225698259e-03f, -8.616336525e-04f, +0.000000000e+00f,
-    /* 20,11 */ +0.000000000e+00f, +1.724424543e-05f, -4.124801502e-03f, -2.414511840e-03f, +1.708262332e-02f, +1.583239979e-02f, -4.506940842e-02f, -6.420865295e-02f, +1.109160995e-01f, +3.827944964e-01f, +4.439828472e-01f, +2.174587480e-01f, -2.388113922e-02f, -6.738225311e-02f, -1.558959414e-03f, +2.273631696e-02f, +3.452605627e-03f, -5.323837897e-03f, -1.101888322e-03f, +0.000000000e+00f,
-    /* 20,12 */ +0.000000000e+00f, +1.274866066e-04f, -3.825546457e-03f, -3.085314600e-03f, +1.577366666e-02f, +1.774280068e-02f, -4.059502103e-02f, -6.783220328e-02f, +9.435670405e-02f, +3.689907742e-01f, +4.500246402e-01f, +2.356365195e-01f, -1.399855627e-02f, -6.985939290e-02f, -5.349604768e-03f, +2.313444000e-02f, +4.699488665e-03f, -5.366796329e-03f, -1.361489293e-03f, +0.000000000e+00f,
-    /* 20,13 */ +0.000000000e+00f, +2.170808154e-04f, -3.513472060e-03f, -3.664825055e-03f, +1.440996064e-02f, +1.936240016e-02f, -3.603763775e-02f, -7.062228683e-02f, +7.833843581e-02f, +3.543483057e-01f, +4.547610488e-01f, +2.536956771e-01f, -3.230759097e-03f, -7.184169597e-02f, -9.347674729e-03f, +2.332816092e-02f, +6.004591146e-03f, -5.348575554e-03f, -1.638662038e-03f, +0.000000000e+00f,
-    /* 20,14 */ +0.000000000e+00f, +2.870815261e-04f, -3.193828376e-03f, -4.154170312e-03f, +1.300917115e-02f, +2.069454672e-02f, -3.144322519e-02f, -7.260941515e-02f, +6.292517925e-02f, +3.389493512e-01f, +4.581642525e-01f, +2.715429904e-01f, +8.401230311e-03f, -7.327813327e-02f, -1.352771902e-02f, +2.330080531e-02f, +7.357928950e-03f, -5.263447672e-03f, -1.931175707e-03f, +0.000000000e+00f,
-    /* 20,15 */ +0.000000000e+00f, +3.387491377e-04f, -2.871502680e-03f, -4.555417854e-03f, +1.158816420e-02f, +2.174514756e-02f, -2.685541297e-02f, -7.382833631e-02f, +4.817530421e-02f, +3.228796668e-01f, +4.602142272e-01f, +2.890848421e-01f, +2.086992015e-02f, -7.411924916e-02f, -1.786093260e-02f, +2.303691111e-02f, +8.748210493e-03f, -5.106050653e-03f, -2.236335973e-03f, +3.929324583e-04f,
-    /* 16, 0 */ -4.898743621e-03f, -8.679086087e-05f, +2.336043359e-02f, +2.135055302e-04f, -7.556698393e-02f, -3.418085064e-04f, +3.068350485e-01f, +5.003964504e-01f, +3.068350485e-01f, -3.418085064e-04f, -7.556698393e-02f, +2.135055302e-04f, +2.336043359e-02f, -8.679086087e-05f, -4.898743621e-03f, +1.466795211e-05f,
-    /* 16, 1 */ -4.577177643e-03f, -1.168030162e-03f, +2.231338881e-02f, +4.259286102e-03f, -7.256190983e-02f, -1.325523148e-02f, +2.859961851e-01f, +4.995203198e-01f, +3.272077887e-01f, +1.366916740e-02f, -7.794631959e-02f, -4.137969722e-03f, +2.421268789e-02f, +1.104119466e-03f, -5.186216174e-03f, -1.424716020e-04f,
-    /* 16, 2 */ -4.229744004e-03f, -2.135347302e-03f, +2.109817837e-02f, +7.975999347e-03f, -6.900371451e-02f, -2.503996167e-02f, +2.648211478e-01f, +4.968980143e-01f, +3.469854770e-01f, +2.873680235e-02f, -7.962890015e-02f, -8.766610174e-03f, +2.484400873e-02f, +2.398541233e-03f, -5.431090074e-03f, -3.278051009e-04f,
-    /* 16, 3 */ -3.864289504e-03f, -2.986316790e-03f, +1.974155805e-02f, +1.134537917e-02f, -6.496587406e-02f, -3.567459207e-02f, +2.434398342e-01f, +4.925477372e-01f, +3.660412816e-01f, +4.481051979e-02f, -8.054606315e-02f, -1.363873477e-02f, +2.522910176e-02f, +3.788344934e-03f, -5.624692566e-03f, -5.415628140e-04f,
-    /* 16, 4 */ -3.488195595e-03f, -3.720237037e-03f, +1.827008292e-02f, +1.435416313e-02f, -6.052200094e-02f, -4.514733704e-02f, +2.219810322e-01f, +4.864996469e-01f, +3.842515379e-01f, +6.183022559e-02f, -8.063225815e-02f, -1.871557408e-02f, +2.534390000e-02f, +5.263393235e-03f, -5.758306879e-03f, -7.834433658e-04f,
-    /* 16, 5 */ -3.108305495e-03f, -4.338012209e-03f, +1.670979794e-02f, +1.699394035e-02f, -5.574514781e-02f, -5.345583367e-02f, +2.005713869e-01f, +4.787955863e-01f, +4.014968013e-01f, +7.972656727e-02f, -7.982580067e-02f, -2.395339311e-02f, +2.516595041e-02f, +6.811528665e-03f, -5.823306183e-03f, -1.052565974e-03f,
-    /* 16, 6 */ -2.730865011e-03f, -4.842020290e-03f, +1.508595356e-02f, +1.926095418e-02f, -5.070714412e-02f, -6.060686010e-02f, +1.793344024e-01f, +4.694887096e-01f, +4.176628724e-01f, +9.842128660e-02f, -7.806961406e-02f, -2.930367505e-02f, +2.467480385e-02f, +8.418588685e-03f, -5.811296621e-03f, -1.347428958e-03f,
-    /* 16, 7 */ -2.361477017e-03f, -5.235970004e-03f, +1.342274837e-02f, +2.115586371e-02f, -4.547797122e-02f, -6.661597542e-02f, +1.583894867e-01f, +4.586430086e-01f, +4.326417845e-01f, +1.178276637e-01f, -7.531195111e-02f, -3.471336612e-02f, +2.385240383e-02f, +1.006844961e-02f, -5.714267850e-03f, -1.665875716e-03f,
-    /* 16, 8 */ -2.005069351e-03f, -5.524749278e-03f, +1.174310057e-02f, +2.268346885e-02f, -4.012518151e-02f, -7.150708699e-02f, +1.378510501e-01f, +4.463327434e-01f, +4.463327434e-01f, +1.378510501e-01f, -7.150708699e-02f, -4.012518151e-02f, +2.268346885e-02f, +1.174310057e-02f, -5.524749278e-03f, -2.005069351e-03f,
-    /* 16, 9 */ -1.665875716e-03f, -5.714267850e-03f, +1.006844961e-02f, +2.385240383e-02f, -3.471336612e-02f, -7.531195111e-02f, +1.178276637e-01f, +4.326417845e-01f, +4.586430086e-01f, +1.583894867e-01f, -6.661597542e-02f, -4.547797122e-02f, +2.115586371e-02f, +1.342274837e-02f, -5.235970004e-03f, -2.361477017e-03f,
-    /* 16,10 */ -1.347428958e-03f, -5.811296621e-03f, +8.418588685e-03f, +2.467480385e-02f, -2.930367505e-02f, -7.806961406e-02f, +9.842128660e-02f, +4.176628724e-01f, +4.694887096e-01f, +1.793344024e-01f, -6.060686010e-02f, -5.070714412e-02f, +1.926095418e-02f, +1.508595356e-02f, -4.842020290e-03f, -2.730865011e-03f,
-    /* 16,11 */ -1.052565974e-03f, -5.823306183e-03f, +6.811528665e-03f, +2.516595041e-02f, -2.395339311e-02f, -7.982580067e-02f, +7.972656727e-02f, +4.014968013e-01f, +4.787955863e-01f, +2.005713869e-01f, -5.345583367e-02f, -5.574514781e-02f, +1.699394035e-02f, +1.670979794e-02f, -4.338012209e-03f, -3.108305495e-03f,
-    /* 16,12 */ -7.834433658e-04f, -5.758306879e-03f, +5.263393235e-03f, +2.534390000e-02f, -1.871557408e-02f, -8.063225815e-02f, +6.183022559e-02f, +3.842515379e-01f, +4.864996469e-01f, +2.219810322e-01f, -4.514733704e-02f, -6.052200094e-02f, +1.435416313e-02f, +1.827008292e-02f, -3.720237037e-03f, -3.488195595e-03f,
-    /* 16,13 */ -5.415628140e-04f, -5.624692566e-03f, +3.788344934e-03f, +2.522910176e-02f, -1.363873477e-02f, -8.054606315e-02f, +4.481051979e-02f, +3.660412816e-01f, +4.925477372e-01f, +2.434398342e-01f, -3.567459207e-02f, -6.496587406e-02f, +1.134537917e-02f, +1.974155805e-02f, -2.986316790e-03f, -3.864289504e-03f,
-    /* 16,14 */ -3.278051009e-04f, -5.431090074e-03f, +2.398541233e-03f, +2.484400873e-02f, -8.766610174e-03f, -7.962890015e-02f, +2.873680235e-02f, +3.469854770e-01f, +4.968980143e-01f, +2.648211478e-01f, -2.503996167e-02f, -6.900371451e-02f, +7.975999347e-03f, +2.109817837e-02f, -2.135347302e-03f, -4.229744004e-03f,
-    /* 16,15 */ -1.424716020e-04f, -5.186216174e-03f, +1.104119466e-03f, +2.421268789e-02f, -4.137969722e-03f, -7.794631959e-02f, +1.366916740e-02f, +3.272077887e-01f, +4.995203198e-01f, +2.859961851e-01f, -1.325523148e-02f, -7.256190983e-02f, +4.259286102e-03f, +2.231338881e-02f, -1.168030162e-03f, -4.577177643e-03f,
-    /* 16, 0 */ -1.854349243e-03f, -5.842655877e-03f, +1.571555836e-02f, +1.847159410e-02f, -6.634453543e-02f, -3.320569278e-02f, +3.025932104e-01f, +5.398940036e-01f, +3.025932104e-01f, -3.320569278e-02f, -6.634453543e-02f, +1.847159410e-02f, +1.571555836e-02f, -5.842655877e-03f, -1.854349243e-03f, +0.000000000e+00f,
-    /* 16, 1 */ -1.480579358e-03f, -6.106700866e-03f, +1.376986381e-02f, +2.107103425e-02f, -6.084498265e-02f, -4.482173865e-02f, +2.778559558e-01f, +5.387937054e-01f, +3.269511876e-01f, -2.013603096e-02f, -7.140657205e-02f, +1.540395578e-02f, +1.762103499e-02f, -5.450677830e-03f, -2.253515747e-03f, +0.000000000e+00f,
-    /* 16, 2 */ -1.136163241e-03f, -6.251562574e-03f, +1.181432209e-02f, +2.320368920e-02f, -5.500558000e-02f, -5.497544958e-02f, +2.529151163e-01f, +5.355017071e-01f, +3.507537104e-01f, -5.635398845e-03f, -7.593183970e-02f, +1.187314151e-02f, +1.945395611e-02f, -4.923375547e-03f, -2.673102395e-03f, +0.000000000e+00f,
-    /* 16, 3 */ -8.240613879e-04f, -6.287094834e-03f, +9.877041313e-03f, +2.487696888e-02f, -4.892141083e-02f, -6.367164518e-02f, +2.279442418e-01f, +5.300446041e-01f, +3.738258052e-01f, +1.025938806e-02f, -7.982055919e-02f, +7.890985370e-03f, +2.118036474e-02f, -4.254967852e-03f, -3.107109230e-03f, +0.000000000e+00f,
-    /* 16, 4 */ -5.462770218e-04f, -6.224002243e-03f, +7.983624178e-03f, +2.610378910e-02f, -4.268405269e-02f, -7.092815895e-02f, +2.031131300e-01f, +5.224664143e-01f, +3.959953988e-01f, +2.749725254e-02f, -8.297353764e-02f, +3.476439880e-03f, +2.276508169e-02f, -3.441527233e-03f, -3.548528769e-03f, +4.634120047e-04f,
-    /* 16, 5 */ -3.039101756e-04f, -6.073592210e-03f, +6.156978545e-03f, +2.690203687e-02f, -3.638073666e-02f, -7.677518685e-02f, +1.785862812e-01f, +5.128281199e-01f, +4.170950072e-01f, +4.601292009e-02f, -8.529332152e-02f, -1.344195268e-03f, +2.417214928e-02f, -2.481210963e-03f, -3.989383394e-03f, +4.400286560e-04f,
-    /* 16, 6 */ -9.722433303e-05f, -5.847536081e-03f, +4.417180930e-03f, +2.729400173e-02f, -3.009359622e-02f, -8.125451993e-02f, +1.545214364e-01f, +5.012070337e-01f, +4.369633957e-01f, +6.572714234e-02f, -8.668537697e-02f, -6.537129252e-03f, +2.536531778e-02f, -1.374474827e-03f, -4.420785166e-03f, +3.921992729e-04f,
-    /* 16, 7 */ +7.427658644e-05f, -5.557642708e-03f, +2.781391675e-03f, +2.730578215e-02f, -2.389901141e-02f, -8.441867356e-02f, +1.310682124e-01f, +4.876959980e-01f, +4.554471907e-01f, +8.654708074e-02f, -8.705928349e-02f, -1.206102709e-02f, +2.630856978e-02f, -1.242645535e-04f, -4.833018707e-03f, +3.169896142e-04f,
-    /* 16, 8 */ +2.117631665e-04f, -5.215647395e-03f, +1.263819875e-03f, +2.696667686e-02f, -1.786705263e-02f, -8.632992647e-02f, +1.083668491e-01f, +4.724024249e-01f, +4.724024249e-01f, +1.083668491e-01f, -8.632992647e-02f, -1.786705263e-02f, +2.696667686e-02f, +1.263819875e-03f, -5.215647395e-03f, +2.117631665e-04f,
-    /* 16, 9 */ +3.169896142e-04f, -4.833018707e-03f, -1.242645535e-04f, +2.630856978e-02f, -1.206102709e-02f, -8.705928349e-02f, +8.654708074e-02f, +4.554471907e-01f, +4.876959980e-01f, +1.310682124e-01f, -8.441867356e-02f, -2.389901141e-02f, +2.730578215e-02f, +2.781391675e-03f, -5.557642708e-03f, +7.427658644e-05f,
-    /* 16,10 */ +3.921992729e-04f, -4.420785166e-03f, -1.374474827e-03f, +2.536531778e-02f, -6.537129252e-03f, -8.668537697e-02f, +6.572714234e-02f, +4.369633957e-01f, +5.012070337e-01f, +1.545214364e-01f, -8.125451993e-02f, -3.009359622e-02f, +2.729400173e-02f, +4.417180930e-03f, -5.847536081e-03f, -9.722433303e-05f,
-    /* 16,11 */ +4.400286560e-04f, -3.989383394e-03f, -2.481210963e-03f, +2.417214928e-02f, -1.344195268e-03f, -8.529332152e-02f, +4.601292009e-02f, +4.170950072e-01f, +5.128281199e-01f, +1.785862812e-01f, -7.677518685e-02f, -3.638073666e-02f, +2.690203687e-02f, +6.156978545e-03f, -6.073592210e-03f, -3.039101756e-04f,
-    /* 16,12 */ +4.634120047e-04f, -3.548528769e-03f, -3.441527233e-03f, +2.276508169e-02f, +3.476439880e-03f, -8.297353764e-02f, +2.749725254e-02f, +3.959953988e-01f, +5.224664143e-01f, +2.031131300e-01f, -7.092815895e-02f, -4.268405269e-02f, +2.610378910e-02f, +7.983624178e-03f, -6.224002243e-03f, -5.462770218e-04f,
-    /* 16,13 */ +0.000000000e+00f, -3.107109230e-03f, -4.254967852e-03f, +2.118036474e-02f, +7.890985370e-03f, -7.982055919e-02f, +1.025938806e-02f, +3.738258052e-01f, +5.300446041e-01f, +2.279442418e-01f, -6.367164518e-02f, -4.892141083e-02f, +2.487696888e-02f, +9.877041313e-03f, -6.287094834e-03f, -8.240613879e-04f,
-    /* 16,14 */ +0.000000000e+00f, -2.673102395e-03f, -4.923375547e-03f, +1.945395611e-02f, +1.187314151e-02f, -7.593183970e-02f, -5.635398845e-03f, +3.507537104e-01f, +5.355017071e-01f, +2.529151163e-01f, -5.497544958e-02f, -5.500558000e-02f, +2.320368920e-02f, +1.181432209e-02f, -6.251562574e-03f, -1.136163241e-03f,
-    /* 16,15 */ +0.000000000e+00f, -2.253515747e-03f, -5.450677830e-03f, +1.762103499e-02f, +1.540395578e-02f, -7.140657205e-02f, -2.013603096e-02f, +3.269511876e-01f, +5.387937054e-01f, +2.778559558e-01f, -4.482173865e-02f, -6.084498265e-02f, +2.107103425e-02f, +1.376986381e-02f, -6.106700866e-03f, -1.480579358e-03f,
-    /* 16, 0 */ +2.517634455e-04f, -5.956310854e-03f, +5.008864062e-03f, +2.864631470e-02f, -4.909056125e-02f, -6.235528720e-02f, +2.936293584e-01f, +5.793915568e-01f, +2.936293584e-01f, -6.235528720e-02f, -4.909056125e-02f, +2.864631470e-02f, +5.008864062e-03f, -5.956310854e-03f, +2.517634455e-04f, +0.000000000e+00f,
-    /* 16, 1 */ +3.647589216e-04f, -5.559366521e-03f, +3.110945653e-03f, +2.922667528e-02f, -4.185408685e-02f, -7.174125192e-02f, +2.648835910e-01f, +5.780318135e-01f, +3.221602930e-01f, -5.117389488e-02f, -5.619351824e-02f, +2.755457966e-02f, +7.032385926e-03f, -6.289189967e-03f, +9.939782505e-05f, +0.000000000e+00f,
-    /* 16, 2 */ +4.414886472e-04f, -5.113535158e-03f, +1.357910925e-03f, +2.932892142e-02f, -3.459618474e-02f, -7.936172697e-02f, +2.361522790e-01f, +5.739652427e-01f, +3.502436629e-01f, -3.818535953e-02f, -6.304412145e-02f, +2.592390265e-02f, +9.158035052e-03f, -6.542440674e-03f, -9.477253367e-05f, +0.000000000e+00f,
-    /* 16, 3 */ +4.855802427e-04f, -4.633347213e-03f, -2.351453324e-04f, +2.899108127e-02f, -2.742112952e-02f, -8.526380919e-02f, +2.076588264e-01f, +5.672296697e-01f, +3.776458156e-01f, -2.339704980e-02f, -6.951800781e-02f, +2.373330296e-02f, +1.135820669e-02f, -6.700410184e-03f, -3.323676319e-04f, +0.000000000e+00f,
-    /* 16, 4 */ +0.000000000e+00f, -4.132457962e-03f, -1.657230762e-03f, +2.825501306e-02f, -2.042447313e-02f, -8.951050933e-02f, +1.796184274e-01f, +5.578876325e-01f, +4.041347532e-01f, -6.836060229e-03f, -7.548664793e-02f, +2.096923455e-02f, +1.360131724e-02f, -6.747680557e-03f, -6.140535745e-04f, +0.000000000e+00f,
-    /* 16, 5 */ +0.000000000e+00f, -3.623457200e-03f, -2.901306411e-03f, +2.716546883e-02f, -1.369230379e-02f, -9.217934767e-02f, +1.522358833e-01f, +5.460256322e-01f, +4.294827240e-01f, +1.145038182e-02f, -8.081883229e-02f, +1.762637069e-02f, +1.585203938e-02f, -6.669417793e-03f, -9.394126333e-04f, +0.000000000e+00f,
-    /* 16, 6 */ +0.000000000e+00f, -3.117716971e-03f, -3.964078879e-03f, +2.576917487e-02f, -7.300675124e-03f, -9.336081470e-02f, +1.257035893e-01f, +5.317530991e-01f, +4.534687988e-01f, +3.139475616e-02f, -8.538226676e-02f, +1.370830904e-02f, +1.807162423e-02f, -6.451740247e-03f, -1.306826648e-03f, +0.000000000e+00f,
-    /* 16, 7 */ +0.000000000e+00f, -2.625277441e-03f, -4.845741482e-03f, +2.411394259e-02f, -1.315205805e-03f, -9.315672206e-02f, +1.001997139e-01f, +5.152010878e-01f, +4.758813956e-01f, +5.290934542e-02f, -8.904525833e-02f, +9.228181275e-03f, +2.021831098e-02f, -6.082100328e-03f, -1.713377737e-03f, +0.000000000e+00f,
-    /* 16, 8 */ +0.000000000e+00f, -2.154770219e-03f, -5.549672684e-03f, +2.224782226e-02f, +4.209152176e-03f, -9.167847004e-02f, +7.588659143e-02f, +4.965207199e-01f, +4.965207199e-01f, +7.588659143e-02f, -9.167847004e-02f, +4.209152176e-03f, +2.224782226e-02f, -5.549672684e-03f, -2.154770219e-03f, +0.000000000e+00f,
-    /* 16, 9 */ +0.000000000e+00f, -1.713377737e-03f, -6.082100328e-03f, +2.021831098e-02f, +9.228181275e-03f, -8.904525833e-02f, +5.290934542e-02f, +4.758813956e-01f, +5.152010878e-01f, +1.001997139e-01f, -9.315672206e-02f, -1.315205805e-03f, +2.411394259e-02f, -4.845741482e-03f, -2.625277441e-03f, +0.000000000e+00f,
-    /* 16,10 */ +0.000000000e+00f, -1.306826648e-03f, -6.451740247e-03f, +1.807162423e-02f, +1.370830904e-02f, -8.538226676e-02f, +3.139475616e-02f, +4.534687988e-01f, +5.317530991e-01f, +1.257035893e-01f, -9.336081470e-02f, -7.300675124e-03f, +2.576917487e-02f, -3.964078879e-03f, -3.117716971e-03f, +0.000000000e+00f,
-    /* 16,11 */ +0.000000000e+00f, -9.394126333e-04f, -6.669417793e-03f, +1.585203938e-02f, +1.762637069e-02f, -8.081883229e-02f, +1.145038182e-02f, +4.294827240e-01f, +5.460256322e-01f, +1.522358833e-01f, -9.217934767e-02f, -1.369230379e-02f, +2.716546883e-02f, -2.901306411e-03f, -3.623457200e-03f, +0.000000000e+00f,
-    /* 16,12 */ +0.000000000e+00f, -6.140535745e-04f, -6.747680557e-03f, +1.360131724e-02f, +2.096923455e-02f, -7.548664793e-02f, -6.836060229e-03f, +4.041347532e-01f, +5.578876325e-01f, +1.796184274e-01f, -8.951050933e-02f, -2.042447313e-02f, +2.825501306e-02f, -1.657230762e-03f, -4.132457962e-03f, +0.000000000e+00f,
-    /* 16,13 */ +0.000000000e+00f, -3.323676319e-04f, -6.700410184e-03f, +1.135820669e-02f, +2.373330296e-02f, -6.951800781e-02f, -2.339704980e-02f, +3.776458156e-01f, +5.672296697e-01f, +2.076588264e-01f, -8.526380919e-02f, -2.742112952e-02f, +2.899108127e-02f, -2.351453324e-04f, -4.633347213e-03f, +4.855802427e-04f,
-    /* 16,14 */ +0.000000000e+00f, -9.477253367e-05f, -6.542440674e-03f, +9.158035052e-03f, +2.592390265e-02f, -6.304412145e-02f, -3.818535953e-02f, +3.502436629e-01f, +5.739652427e-01f, +2.361522790e-01f, -7.936172697e-02f, -3.459618474e-02f, +2.932892142e-02f, +1.357910925e-03f, -5.113535158e-03f, +4.414886472e-04f,
-    /* 16,15 */ +0.000000000e+00f, +9.939782505e-05f, -6.289189967e-03f, +7.032385926e-03f, +2.755457966e-02f, -5.619351824e-02f, -5.117389488e-02f, +3.221602930e-01f, +5.780318135e-01f, +2.648835910e-01f, -7.174125192e-02f, -4.185408685e-02f, +2.922667528e-02f, +3.110945653e-03f, -5.559366521e-03f, +3.647589216e-04f,
-    /* 12, 0 */ -3.638165547e-03f, +2.979985982e-02f, -2.723323293e-02f, -8.605047059e-02f, +2.801520768e-01f, +6.188891100e-01f, +2.801520768e-01f, -8.605047059e-02f, -2.723323293e-02f, +2.979985982e-02f, -3.638165547e-03f, -3.041512814e-03f,
-    /* 12, 1 */ -4.749738186e-03f, +2.841159300e-02f, -1.933319589e-02f, -9.237133076e-02f, +2.473915856e-01f, +6.172320760e-01f, +3.129551421e-01f, -7.764805088e-02f, -3.538029377e-02f, +3.077779188e-02f, -2.305275216e-03f, -3.612081594e-03f,
-    /* 12, 2 */ -5.642312008e-03f, +2.667449885e-02f, -1.178831271e-02f, -9.669686191e-02f, +2.149632830e-01f, +6.122785731e-01f, +3.455026876e-01f, -6.709962705e-02f, -4.365285408e-02f, +3.128617370e-02f, -7.534120996e-04f, -4.192641091e-03f,
-    /* 12, 3 */ -6.322395719e-03f, +2.465107974e-02f, -4.692548813e-03f, -9.913294928e-02f, +1.831448749e-01f, +6.040811565e-01f, +3.774917553e-01f, -5.436442589e-02f, -5.191703591e-02f, +3.126943445e-02f, +1.010002855e-03f, -4.769140004e-03f,
-    /* 12, 4 */ -6.800166749e-03f, +2.240361196e-02f, +1.874795505e-03f, -9.980279721e-02f, +1.521989634e-01f, +5.927266195e-01f, +4.086182709e-01f, -3.942694703e-02f, -6.002791415e-02f, +3.067703358e-02f, +2.972136287e-03f, -5.325763732e-03f,
-    /* 12, 5 */ -7.088917510e-03f, +1.999301835e-02f, +7.849320649e-03f, -9.884443272e-02f, +1.223701278e-01f, +5.783348068e-01f, +4.385808709e-01f, -2.229824534e-02f, -6.783107929e-02f, +2.946485483e-02f, +5.114495497e-03f, -5.845139328e-03f,
-    /* 12, 6 */ -7.204483224e-03f, +1.747784955e-02f, +1.318150805e-02f, -9.640809295e-02f, +9.388232321e-02f, +5.610569814e-01f, +4.670847512e-01f, -3.016864363e-03f, -7.516444191e-02f, +2.759658236e-02f, +7.412783505e-03f, -6.308600966e-03f,
-    /* 12, 7 */ -7.164664930e-03f, +1.491338589e-02f, +1.783645872e-02f, -9.265354184e-02f, +6.693662660e-02f, +5.410737692e-01f, +4.938454794e-01f, +1.835060492e-02f, -8.186025948e-02f, +2.504503167e-02f, +9.836867291e-03f, -6.696514785e-03f,
-    /* 12, 8 */ -6.988660420e-03f, +1.235086875e-02f, +2.179340724e-02f, -8.774736114e-02f, +4.170935934e-02f, +5.185927134e-01f, +5.185927134e-01f, +4.170935934e-02f, -8.774736114e-02f, +2.179340724e-02f, +1.235086875e-02f, -6.988660420e-03f,
-    /* 12, 9 */ -6.696514785e-03f, +9.836867291e-03f, +2.504503167e-02f, -8.186025948e-02f, +1.835060492e-02f, +4.938454794e-01f, +5.410737692e-01f, +6.693662660e-02f, -9.265354184e-02f, +1.783645872e-02f, +1.491338589e-02f, -7.164664930e-03f,
-    /* 12,10 */ -6.308600966e-03f, +7.412783505e-03f, +2.759658236e-02f, -7.516444191e-02f, -3.016864363e-03f, +4.670847512e-01f, +5.610569814e-01f, +9.388232321e-02f, -9.640809295e-02f, +1.318150805e-02f, +1.747784955e-02f, -7.204483224e-03f,
-    /* 12,11 */ -5.845139328e-03f, +5.114495497e-03f, +2.946485483e-02f, -6.783107929e-02f, -2.229824534e-02f, +4.385808709e-01f, +5.783348068e-01f, +1.223701278e-01f, -9.884443272e-02f, +7.849320649e-03f, +1.999301835e-02f, -7.088917510e-03f,
-    /* 12,12 */ -5.325763732e-03f, +2.972136287e-03f, +3.067703358e-02f, -6.002791415e-02f, -3.942694703e-02f, +4.086182709e-01f, +5.927266195e-01f, +1.521989634e-01f, -9.980279721e-02f, +1.874795505e-03f, +2.240361196e-02f, -6.800166749e-03f,
-    /* 12,13 */ -4.769140004e-03f, +1.010002855e-03f, +3.126943445e-02f, -5.191703591e-02f, -5.436442589e-02f, +3.774917553e-01f, +6.040811565e-01f, +1.831448749e-01f, -9.913294928e-02f, -4.692548813e-03f, +2.465107974e-02f, -6.322395719e-03f,
-    /* 12,14 */ -4.192641091e-03f, -7.534120996e-04f, +3.128617370e-02f, -4.365285408e-02f, -6.709962705e-02f, +3.455026876e-01f, +6.122785731e-01f, +2.149632830e-01f, -9.669686191e-02f, -1.178831271e-02f, +2.667449885e-02f, -5.642312008e-03f,
-    /* 12,15 */ -3.612081594e-03f, -2.305275216e-03f, +3.077779188e-02f, -3.538029377e-02f, -7.764805088e-02f, +3.129551421e-01f, +6.172320760e-01f, +2.473915856e-01f, -9.237133076e-02f, -1.933319589e-02f, +2.841159300e-02f, -4.749738186e-03f,
-    /* 12, 0 */ -7.562702671e-03f, +2.362257603e-02f, -4.531854693e-03f, -1.030173373e-01f, +2.624467795e-01f, +6.583866631e-01f, +2.624467795e-01f, -1.030173373e-01f, -4.531854693e-03f, +2.362257603e-02f, -7.562702671e-03f, -3.516889901e-04f,
-    /* 12, 1 */ -7.668183010e-03f, +2.087771707e-02f, +2.839059860e-03f, -1.056218320e-01f, +2.257778124e-01f, +6.563919279e-01f, +2.995227467e-01f, -9.814415944e-02f, -1.254420342e-02f, +2.617709089e-02f, -7.250906804e-03f, -7.142430143e-04f,
-    /* 12, 2 */ -7.590423774e-03f, +1.801705410e-02f, +9.487879886e-03f, -1.061169074e-01f, +1.898705313e-01f, +6.504316937e-01f, +3.366347146e-01f, -9.086648783e-02f, -2.109702270e-02f, +2.846338313e-02f, -6.712315500e-03f, -1.140764971e-03f,
-    /* 12, 3 */ -7.354275530e-03f, +1.511050856e-02f, +1.535418598e-02f, -1.046816488e-01f, +1.550586973e-01f, +6.405775033e-01f, +3.734003416e-01f, -8.107535131e-02f, -3.006937567e-02f, +3.040170317e-02f, -5.929880498e-03f, -1.628307909e-03f,
-    /* 12, 4 */ -6.985575046e-03f, +1.222230420e-02f, +2.039736787e-02f, -1.015111601e-01f, +1.216509697e-01f, +6.269473635e-01f, +4.094311989e-01f, -6.869168809e-02f, -3.932109040e-02f, +3.191206547e-02f, -4.890814148e-03f, -2.171433859e-03f,
-    /* 12, 5 */ -6.510406524e-03f, +9.410098002e-03f, +2.459585213e-02f, -9.681266365e-02f, +8.992722338e-02f, +6.097039216e-01f, +4.443382217e-01f, -5.366903171e-02f, -4.869391429e-02f, +3.291602689e-02f, -3.587389454e-03f, -2.762058981e-03f,
-    /* 12, 6 */ -5.954426605e-03f, +6.724324555e-03f, +2.794602403e-02f, -9.080157573e-02f, +6.013541337e-02f, +5.890519583e-01f, +4.777372670e-01f, -3.599575069e-02f, -5.801308453e-02f, +3.333857894e-02f, -2.017687876e-03f, -3.389362400e-03f,
-    /* 12, 7 */ -5.342264546e-03f, +4.207752570e-03f, +3.046088231e-02f, -8.369763050e-02f, +3.248902822e-02f, +5.652352421e-01f, +5.092546840e-01f, -1.569678608e-02f, -6.708930595e-02f, +3.311011989e-02f, -1.862710466e-04f, -4.039767889e-03f,
-    /* 12, 8 */ -4.697006242e-03f, +1.895247343e-03f, +3.216846911e-02f, -7.572111885e-02f, +7.165160645e-03f, +5.385328020e-01f, +5.385328020e-01f, +7.165160645e-03f, -7.572111885e-02f, +3.216846911e-02f, +1.895247343e-03f, -4.697006242e-03f,
-    /* 12, 9 */ -4.039767889e-03f, -1.862710466e-04f, +3.311011989e-02f, -6.708930595e-02f, -1.569678608e-02f, +5.092546840e-01f, +5.652352421e-01f, +3.248902822e-02f, -8.369763050e-02f, +3.046088231e-02f, +4.207752570e-03f, -5.342264546e-03f,
-    /* 12,10 */ -3.389362400e-03f, -2.017687876e-03f, +3.333857894e-02f, -5.801308453e-02f, -3.599575069e-02f, +4.777372670e-01f, +5.890519583e-01f, +6.013541337e-02f, -9.080157573e-02f, +2.794602403e-02f, +6.724324555e-03f, -5.954426605e-03f,
-    /* 12,11 */ -2.762058981e-03f, -3.587389454e-03f, +3.291602689e-02f, -4.869391429e-02f, -5.366903171e-02f, +4.443382217e-01f, +6.097039216e-01f, +8.992722338e-02f, -9.681266365e-02f, +2.459585213e-02f, +9.410098002e-03f, -6.510406524e-03f,
-    /* 12,12 */ -2.171433859e-03f, -4.890814148e-03f, +3.191206547e-02f, -3.932109040e-02f, -6.869168809e-02f, +4.094311989e-01f, +6.269473635e-01f, +1.216509697e-01f, -1.015111601e-01f, +2.039736787e-02f, +1.222230420e-02f, -6.985575046e-03f,
-    /* 12,13 */ -1.628307909e-03f, -5.929880498e-03f, +3.040170317e-02f, -3.006937567e-02f, -8.107535131e-02f, +3.734003416e-01f, +6.405775033e-01f, +1.550586973e-01f, -1.046816488e-01f, +1.535418598e-02f, +1.511050856e-02f, -7.354275530e-03f,
-    /* 12,14 */ -1.140764971e-03f, -6.712315500e-03f, +2.846338313e-02f, -2.109702270e-02f, -9.086648783e-02f, +3.366347146e-01f, +6.504316937e-01f, +1.898705313e-01f, -1.061169074e-01f, +9.487879886e-03f, +1.801705410e-02f, -7.590423774e-03f,
-    /* 12,15 */ -7.142430143e-04f, -7.250906804e-03f, +2.617709089e-02f, -1.254420342e-02f, -9.814415944e-02f, +2.995227467e-01f, +6.563919279e-01f, +2.257778124e-01f, -1.056218320e-01f, +2.839059860e-03f, +2.087771707e-02f, -7.668183010e-03f,
-    /* 12, 0 */ -7.009786996e-03f, +1.344312953e-02f, +1.557210222e-02f, -1.125190619e-01f, +2.408695221e-01f, +6.978842163e-01f, +2.408695221e-01f, -1.125190619e-01f, +1.557210222e-02f, +1.344312953e-02f, -7.009786996e-03f, +6.003640016e-04f,
-    /* 12, 1 */ -6.398742119e-03f, +1.026913982e-02f, +2.132332546e-02f, -1.110115061e-01f, +2.005160832e-01f, +6.955088069e-01f, +2.821133540e-01f, -1.117099281e-01f, +8.845385329e-03f, +1.669708199e-02f, -7.518519523e-03f, +5.590854556e-04f,
-    /* 12, 2 */ -5.716737920e-03f, +7.240001966e-03f, +2.606967700e-02f, -1.074325911e-01f, +1.614746033e-01f, +6.884146462e-01f, +3.237982615e-01f, -1.083606220e-01f, +1.198165974e-03f, +1.995657080e-02f, -7.892366537e-03f, +4.637249154e-04f,
-    /* 12, 3 */ -4.993154633e-03f, +4.410399512e-03f, +2.980590100e-02f, -1.020439692e-01f, +1.241329667e-01f, +6.766973789e-01f, +3.654537522e-01f, -1.022748781e-01f, -7.287927063e-03f, +2.313861998e-02f, -8.098411048e-03f, +3.063703263e-04f,
-    /* 12, 4 */ -4.254780730e-03f, +1.824453005e-03f, +3.254896791e-02f, -9.511805181e-02f, +8.884019172e-02f, +6.605145641e-01f, +4.065952670e-01f, -9.328874484e-02f, -1.650412301e-02f, +2.615301189e-02f, -8.104377377e-03f, +8.035370630e-05f,
-    /* 12, 5 */ -3.525333045e-03f, -4.843426812e-04f, +3.433584064e-02f, -8.693252112e-02f, +5.590207404e-02f, +6.400829406e-01f, +4.467316931e-01f, -8.127529114e-02f, -2.631456917e-02f, +2.890390773e-02f, -7.879705669e-03f, -2.193022854e-04f,
-    /* 12, 6 */ -2.825116890e-03f, -2.492908449e-03f, +3.522097401e-02f, -7.776502604e-02f, +2.557772128e-02f, +6.156746770e-01f, +4.853731430e-01f, -6.614880956e-02f, -3.655698883e-02f, +3.129176395e-02f, -7.396691856e-03f, -5.954441701e-04f,
-    /* 12, 7 */ -2.170822930e-03f, -4.188126176e-03f, +3.527362061e-02f, -6.788815999e-02f, -1.922977207e-03f, +5.876126808e-01f, +5.220388545e-01f, -4.786841211e-02f, -4.704395826e-02f, +3.321551909e-02f, -6.631665064e-03f, -1.048370326e-03f,
-    /* 12, 8 */ -1.575453811e-03f, -5.566170902e-03f, +3.457501660e-02f, -5.756481055e-02f, -2.644092188e-02f, +5.562650609e-01f, +5.562650609e-01f, -2.644092188e-02f, -5.756481055e-02f, +3.457501660e-02f, -5.566170902e-03f, -1.575453811e-03f,
-    /* 12, 9 */ -1.048370326e-03f, -6.631665064e-03f, +3.321551909e-02f, -4.704395826e-02f, -4.786841211e-02f, +5.220388545e-01f, +5.876126808e-01f, -1.922977207e-03f, -6.788815999e-02f, +3.527362061e-02f, -4.188126176e-03f, -2.170822930e-03f,
-    /* 12,10 */ -5.954441701e-04f, -7.396691856e-03f, +3.129176395e-02f, -3.655698883e-02f, -6.614880956e-02f, +4.853731430e-01f, +6.156746770e-01f, +2.557772128e-02f, -7.776502604e-02f, +3.522097401e-02f, -2.492908449e-03f, -2.825116890e-03f,
-    /* 12,11 */ -2.193022854e-04f, -7.879705669e-03f, +2.890390773e-02f, -2.631456917e-02f, -8.127529114e-02f, +4.467316931e-01f, +6.400829406e-01f, +5.590207404e-02f, -8.693252112e-02f, +3.433584064e-02f, -4.843426812e-04f, -3.525333045e-03f,
-    /* 12,12 */ +8.035370630e-05f, -8.104377377e-03f, +2.615301189e-02f, -1.650412301e-02f, -9.328874484e-02f, +4.065952670e-01f, +6.605145641e-01f, +8.884019172e-02f, -9.511805181e-02f, +3.254896791e-02f, +1.824453005e-03f, -4.254780730e-03f,
-    /* 12,13 */ +3.063703263e-04f, -8.098411048e-03f, +2.313861998e-02f, -7.287927063e-03f, -1.022748781e-01f, +3.654537522e-01f, +6.766973789e-01f, +1.241329667e-01f, -1.020439692e-01f, +2.980590100e-02f, +4.410399512e-03f, -4.993154633e-03f,
-    /* 12,14 */ +4.637249154e-04f, -7.892366537e-03f, +1.995657080e-02f, +1.198165974e-03f, -1.083606220e-01f, +3.237982615e-01f, +6.884146462e-01f, +1.614746033e-01f, -1.074325911e-01f, +2.606967700e-02f, +7.240001966e-03f, -5.716737920e-03f,
-    /* 12,15 */ +5.590854556e-04f, -7.518519523e-03f, +1.669708199e-02f, +8.845385329e-03f, -1.117099281e-01f, +2.821133540e-01f, +6.955088069e-01f, +2.005160832e-01f, -1.110115061e-01f, +2.132332546e-02f, +1.026913982e-02f, -6.398742119e-03f,
-
-    /* 24, 0 */ +1.501390780e-03f, +3.431804419e-03f, +6.512803185e-03f, +1.091425387e-02f, +1.664594540e-02f, +2.351091132e-02f, +3.109255671e-02f, +3.878419288e-02f, +4.586050701e-02f, +5.158058002e-02f, +5.530384985e-02f, +5.659614054e-02f, +5.530384985e-02f, +5.158058002e-02f, +4.586050701e-02f, +3.878419288e-02f, +3.109255671e-02f, +2.351091132e-02f, +1.664594540e-02f, +1.091425387e-02f, +6.512803185e-03f, +3.431804419e-03f, +1.501390780e-03f, +4.573885647e-04f,
-    /* 24, 1 */ +1.413186400e-03f, +3.279858311e-03f, +6.282638036e-03f, +1.059932179e-02f, +1.625135142e-02f, +2.305547031e-02f, +3.060840342e-02f, +3.831365198e-02f, +4.545054680e-02f, +5.127577001e-02f, +5.513916011e-02f, +5.659104154e-02f, +5.545895049e-02f, +5.187752167e-02f, +4.626513642e-02f, +3.925233583e-02f, +3.157717954e-02f, +2.396921539e-02f, +1.704503934e-02f, +1.123445076e-02f, +6.748179094e-03f, +3.588275667e-03f, +1.593065611e-03f, +5.022154476e-04f,
-    /* 24, 2 */ +1.328380648e-03f, +3.132379333e-03f, +6.057656813e-03f, +1.028967374e-02f, +1.586133102e-02f, +2.260301890e-02f, +3.012488684e-02f, +3.784089895e-02f, +4.503543229e-02f, +5.096323022e-02f, +5.496495842e-02f, +5.657574693e-02f, +5.560438923e-02f, +5.216645963e-02f, +4.666426010e-02f, +3.971789474e-02f, +3.206210284e-02f, +2.443025293e-02f, +1.744855617e-02f, +1.155988996e-02f, +6.988790100e-03f, +3.749328623e-03f, +1.688282347e-03f, +5.494305796e-04f,
-    /* 24, 3 */ +1.246901403e-03f, +2.989308098e-03f, +5.837830254e-03f, +9.985325752e-03f, +1.547595434e-02f, +2.215368059e-02f, +2.964217216e-02f, +3.736611920e-02f, +4.461534144e-02f, +5.064310236e-02f, +5.478132634e-02f, +5.655026396e-02f, +5.574009777e-02f, +5.244726189e-02f, +4.705770477e-02f, +4.018068337e-02f, +3.254715574e-02f, +2.489389144e-02f, +1.785641537e-02f, +1.189054572e-02f, +7.234657995e-03f, +3.915018340e-03f, +1.787112015e-03f, +5.991047395e-04f,
-    /* 24, 4 */ +1.168676301e-03f, +2.850583915e-03f, +5.623126723e-03f, +9.686290690e-03f, +1.509528803e-02f, +2.170757578e-02f, +2.916042250e-02f, +3.688949768e-02f, +4.419045351e-02f, +5.031553118e-02f, +5.458834968e-02f, +5.651460469e-02f, +5.586601230e-02f, +5.271979985e-02f, +4.744529894e-02f, +4.064051541e-02f, +3.303216567e-02f, +2.535999546e-02f, +1.826853297e-02f, +1.222638897e-02f, +7.485801959e-03f, +4.085398290e-03f, +1.889625146e-03f, +6.513091287e-04f,
-    /* 24, 5 */ +1.093632798e-03f, +2.716144855e-03f, +5.413512274e-03f, +9.392578266e-03f, +1.471939531e-02f, +2.126482169e-02f, +2.867979883e-02f, +3.641121873e-02f, +4.376094899e-02f, +4.998066438e-02f, +5.438611851e-02f, +5.646878599e-02f, +5.598207354e-02f, +5.298394839e-02f, +4.782687301e-02f, +4.109720465e-02f, +3.351695842e-02f, +2.582842673e-02f, +1.868482156e-02f, +1.256738733e-02f, +7.742238512e-03f, +4.260520294e-03f, +1.995891717e-03f, +7.061153220e-04f,
-    /* 24, 6 */ +1.021698233e-03f, +2.585927824e-03f, +5.208950715e-03f, +9.104195104e-03f, +1.434833590e-02f, +2.082553239e-02f, +2.820045990e-02f, +3.593146595e-02f, +4.332700946e-02f, +4.963865252e-02f, +5.417472708e-02f, +5.641282954e-02f, +5.608822683e-02f, +5.323958602e-02f, +4.820225940e-02f, +4.155056502e-02f, +3.400135826e-02f, +2.629904416e-02f, +1.910519032e-02f, +1.291350505e-02f, +8.003981455e-03f, +4.440434453e-03f, +2.105981077e-03f, +7.635952183e-04f,
-    /* 24, 7 */ +9.527998831e-04f, +2.459868628e-03f, +5.009403670e-03f, +8.821144768e-03f, +1.398216608e-02f, +2.038981869e-02f, +2.772256216e-02f, +3.545042216e-02f, +4.288881749e-02f, +4.928964888e-02f, +5.395427373e-02f, +5.634676181e-02f, +5.618442211e-02f, +5.348659488e-02f, +4.857129262e-02f, +4.200041076e-02f, +3.448518802e-02f, +2.677170395e-02f, +1.952954505e-02f, +1.326470299e-02f, +8.271041819e-03f, +4.625189083e-03f, +2.219961884e-03f, +8.238209888e-04f,
-    /* 24, 8 */ +8.868650246e-04f, +2.337902042e-03f, +4.814830642e-03f, +8.543427812e-03f, +1.362093865e-02f, +1.995778816e-02f, +2.724625964e-02f, +3.496826923e-02f, +4.244655653e-02f, +4.893380942e-02f, +5.372486088e-02f, +5.627061400e-02f, +5.627061400e-02f, +5.372486088e-02f, +4.893380942e-02f, +4.244655653e-02f, +3.496826923e-02f, +2.724625964e-02f, +1.995778816e-02f, +1.362093865e-02f, +8.543427812e-03f, +4.814830642e-03f, +2.337902042e-03f, +8.868650246e-04f,
-    /* 24, 9 */ +8.238209888e-04f, +2.219961884e-03f, +4.625189083e-03f, +8.271041819e-03f, +1.326470299e-02f, +1.952954505e-02f, +2.677170395e-02f, +3.448518802e-02f, +4.200041076e-02f, +4.857129262e-02f, +5.348659488e-02f, +5.618442211e-02f, +5.634676181e-02f, +5.395427373e-02f, +4.928964888e-02f, +4.288881749e-02f, +3.545042216e-02f, +2.772256216e-02f, +2.038981869e-02f, +1.398216608e-02f, +8.821144768e-03f, +5.009403670e-03f, +2.459868628e-03f, +9.527998831e-04f,
-    /* 24,10 */ +7.635952183e-04f, +2.105981077e-03f, +4.440434453e-03f, +8.003981455e-03f, +1.291350505e-02f, +1.910519032e-02f, +2.629904416e-02f, +3.400135826e-02f, +4.155056502e-02f, +4.820225940e-02f, +5.323958602e-02f, +5.608822683e-02f, +5.641282954e-02f, +5.417472708e-02f, +4.963865252e-02f, +4.332700946e-02f, +3.593146595e-02f, +2.820045990e-02f, +2.082553239e-02f, +1.434833590e-02f, +9.104195104e-03f, +5.208950715e-03f, +2.585927824e-03f, +1.021698233e-03f,
-    /* 24,11 */ +7.061153220e-04f, +1.995891717e-03f, +4.260520294e-03f, +7.742238512e-03f, +1.256738733e-02f, +1.868482156e-02f, +2.582842673e-02f, +3.351695842e-02f, +4.109720465e-02f, +4.782687301e-02f, +5.298394839e-02f, +5.598207354e-02f, +5.646878599e-02f, +5.438611851e-02f, +4.998066438e-02f, +4.376094899e-02f, +3.641121873e-02f, +2.867979883e-02f, +2.126482169e-02f, +1.471939531e-02f, +9.392578266e-03f, +5.413512274e-03f, +2.716144855e-03f, +1.093632798e-03f,
-    /* 24,12 */ +6.513091287e-04f, +1.889625146e-03f, +4.085398290e-03f, +7.485801959e-03f, +1.222638897e-02f, +1.826853297e-02f, +2.535999546e-02f, +3.303216567e-02f, +4.064051541e-02f, +4.744529894e-02f, +5.271979985e-02f, +5.586601230e-02f, +5.651460469e-02f, +5.458834968e-02f, +5.031553118e-02f, +4.419045351e-02f, +3.688949768e-02f, +2.916042250e-02f, +2.170757578e-02f, +1.509528803e-02f, +9.686290690e-03f, +5.623126723e-03f, +2.850583915e-03f, +1.168676301e-03f,
-    /* 24,13 */ +5.991047395e-04f, +1.787112015e-03f, +3.915018340e-03f, +7.234657995e-03f, +1.189054572e-02f, +1.785641537e-02f, +2.489389144e-02f, +3.254715574e-02f, +4.018068337e-02f, +4.705770477e-02f, +5.244726189e-02f, +5.574009777e-02f, +5.655026396e-02f, +5.478132634e-02f, +5.064310236e-02f, +4.461534144e-02f, +3.736611920e-02f, +2.964217216e-02f, +2.215368059e-02f, +1.547595434e-02f, +9.985325752e-03f, +5.837830254e-03f, +2.989308098e-03f, +1.246901403e-03f,
-    /* 24,14 */ +5.494305796e-04f, +1.688282347e-03f, +3.749328623e-03f, +6.988790100e-03f, +1.155988996e-02f, +1.744855617e-02f, +2.443025293e-02f, +3.206210284e-02f, +3.971789474e-02f, +4.666426010e-02f, +5.216645963e-02f, +5.560438923e-02f, +5.657574693e-02f, +5.496495842e-02f, +5.096323022e-02f, +4.503543229e-02f, +3.784089895e-02f, +3.012488684e-02f, +2.260301890e-02f, +1.586133102e-02f, +1.028967374e-02f, +6.057656813e-03f, +3.132379333e-03f, +1.328380648e-03f,
-    /* 24,15 */ +5.022154476e-04f, +1.593065611e-03f, +3.588275667e-03f, +6.748179094e-03f, +1.123445076e-02f, +1.704503934e-02f, +2.396921539e-02f, +3.157717954e-02f, +3.925233583e-02f, +4.626513642e-02f, +5.187752167e-02f, +5.545895049e-02f, +5.659104154e-02f, +5.513916011e-02f, +5.127577001e-02f, +4.545054680e-02f, +3.831365198e-02f, +3.060840342e-02f, +2.305547031e-02f, +1.625135142e-02f, +1.059932179e-02f, +6.282638036e-03f, +3.279858311e-03f, +1.413186400e-03f,
-    /* 24, 0 */ -2.629184871e-03f, -4.843950453e-03f, -6.895985300e-03f, -7.687208098e-03f, -5.978262553e-03f, -8.032174656e-04f, +8.095316761e-03f, +1.997958831e-02f, +3.311864145e-02f, +4.512644231e-02f, +5.356009950e-02f, +5.659614054e-02f, +5.356009950e-02f, +4.512644231e-02f, +3.311864145e-02f, +1.997958831e-02f, +8.095316761e-03f, -8.032174656e-04f, -5.978262553e-03f, -7.687208098e-03f, -6.895985300e-03f, -4.843950453e-03f, -2.629184871e-03f, -9.454953712e-04f,
-    /* 24, 1 */ -2.503767166e-03f, -4.700731697e-03f, -6.791825424e-03f, -7.698565601e-03f, -6.179328945e-03f, -1.237726578e-03f, +7.438688744e-03f, +1.917778123e-02f, +3.230413198e-02f, +4.445707943e-02f, +5.317715832e-02f, +5.658405316e-02f, +5.392156860e-02f, +4.578163621e-02f, +3.392875410e-02f, +2.078652132e-02f, +8.763945305e-03f, -3.538276542e-04f, -5.763420347e-03f, -7.665996832e-03f, -6.995273095e-03f, -4.986674025e-03f, -2.756835384e-03f, -1.028686673e-03f,
-    /* 24, 2 */ -2.380688695e-03f, -4.557243028e-03f, -6.683099486e-03f, -7.700368745e-03f, -6.366798820e-03f, -1.657314491e-03f, +6.794365087e-03f, +1.838162773e-02f, +3.148585651e-02f, +4.377411309e-02f, +5.277308334e-02f, +5.654780182e-02f, +5.426124576e-02f, +4.642210542e-02f, +3.473383802e-02f, +2.159804191e-02f, +9.444254477e-03f, +1.103863968e-04f, -5.534634231e-03f, -7.634636496e-03f, -7.089380216e-03f, -5.128670417e-03f, -2.886604737e-03f, -1.114962551e-03f,
-    /* 24, 3 */ -2.260048394e-03f, -4.413702845e-03f, -6.570110572e-03f, -7.692920583e-03f, -6.540862270e-03f, -2.061956485e-03f, +6.162633403e-03f, +1.759164425e-02f, +3.066444409e-02f, +4.307811806e-02f, +5.234823086e-02f, +5.648741902e-02f, +5.457882991e-02f, +4.704730472e-02f, +3.553326091e-02f, +2.241360152e-02f, +1.013590849e-02f, +5.893521078e-04f, -5.291747706e-03f, -7.592836347e-03f, -7.177995846e-03f, -5.269701073e-03f, -3.018371382e-03f, -1.204312280e-03f,
-    /* 24, 4 */ -2.141937776e-03f, -4.270322542e-03f, -6.453158507e-03f, -7.676527355e-03f, -6.701719772e-03f, -2.451643421e-03f, +5.543764951e-03f, +1.680833562e-02f, +2.984052134e-02f, +4.236967758e-02f, +5.190297478e-02f, +5.640295884e-02f, +5.487403917e-02f, +4.765670002e-02f, +3.632639074e-02f, +2.323264190e-02f, +1.083855586e-02f, +1.082980638e-03f, -5.034616251e-03f, -7.540310660e-03f, -7.260807322e-03f, -5.409521052e-03f, -3.152006158e-03f, -1.296719170e-03f,
-    /* 24, 5 */ -2.026441000e-03f, -4.127306381e-03f, -6.332539518e-03f, -7.651498041e-03f, -6.849581767e-03f, -2.826381528e-03f, +4.938014526e-03f, +1.603219452e-02f, +2.901471178e-02f, +4.164938279e-02f, +5.143770614e-02f, +5.629449693e-02f, +5.514661113e-02f, +4.824976895e-02f, +3.711259647e-02f, +2.405459566e-02f, +1.155182965e-02f, +1.591166761e-03f, -4.763107701e-03f, -7.476779193e-03f, -7.337500507e-03f, -5.547879217e-03f, -3.287372274e-03f, -1.392160404e-03f,
-    /* 24, 6 */ -1.913634953e-03f, -3.984851387e-03f, -6.208545927e-03f, -7.618143912e-03f, -6.984668233e-03f, -3.186192169e-03f, +4.345620369e-03f, +1.526370115e-02f, +2.818763519e-02f, +4.091783200e-02f, +5.095283267e-02f, +5.616213037e-02f, +5.539630322e-02f, +4.882600150e-02f, +3.789124869e-02f, +2.487888677e-02f, +1.227534767e-02f, +2.113788767e-03f, -4.477102606e-03f, -7.401967644e-03f, -7.407760182e-03f, -5.684518438e-03f, -3.424325302e-03f, -1.490606880e-03f,
-    /* 24, 7 */ -1.803589350e-03f, -3.843147252e-03f, -6.081465840e-03f, -7.576778087e-03f, -7.107208249e-03f, -3.531111592e-03f, +3.766804102e-03f, +1.450332275e-02f, +2.735990694e-02f, +4.017563005e-02f, +5.044877831e-02f, +5.600597761e-02f, +5.562289296e-02f, +4.938490059e-02f, +3.866172039e-02f, +2.570493119e-02f, +1.300871280e-02f, +2.650708377e-03f, -4.176494585e-03f, -7.315608112e-03f, -7.471270440e-03f, -5.819175805e-03f, -3.562713186e-03f, -1.592023060e-03f,
-    /* 24, 8 */ -1.696366827e-03f, -3.702376254e-03f, -5.951582861e-03f, -7.527715094e-03f, -7.217439556e-03f, -3.861190662e-03f, +3.201770681e-03f, +1.375151322e-02f, +2.653213738e-02f, +3.942338759e-02f, +4.992598268e-02f, +5.582617825e-02f, +5.582617825e-02f, +4.992598268e-02f, +3.942338759e-02f, +2.653213738e-02f, +1.375151322e-02f, +3.201770681e-03f, -3.861190662e-03f, -7.217439556e-03f, -7.527715094e-03f, -5.951582861e-03f, -3.702376254e-03f, -1.696366827e-03f,
-    /* 24, 9 */ -1.592023060e-03f, -3.562713186e-03f, -5.819175805e-03f, -7.471270440e-03f, -7.315608112e-03f, -4.176494585e-03f, +2.650708377e-03f, +1.300871280e-02f, +2.570493119e-02f, +3.866172039e-02f, +4.938490059e-02f, +5.562289296e-02f, +5.600597761e-02f, +5.044877831e-02f, +4.017563005e-02f, +2.735990694e-02f, +1.450332275e-02f, +3.766804102e-03f, -3.531111592e-03f, -7.107208249e-03f, -7.576778087e-03f, -6.081465840e-03f, -3.843147252e-03f, -1.803589350e-03f,
-    /* 24,10 */ -1.490606880e-03f, -3.424325302e-03f, -5.684518438e-03f, -7.407760182e-03f, -7.401967644e-03f, -4.477102606e-03f, +2.113788767e-03f, +1.227534767e-02f, +2.487888677e-02f, +3.789124869e-02f, +4.882600150e-02f, +5.539630322e-02f, +5.616213037e-02f, +5.095283267e-02f, +4.091783200e-02f, +2.818763519e-02f, +1.526370115e-02f, +4.345620369e-03f, -3.186192169e-03f, -6.984668233e-03f, -7.618143912e-03f, -6.208545927e-03f, -3.984851387e-03f, -1.913634953e-03f,
-    /* 24,11 */ -1.392160404e-03f, -3.287372274e-03f, -5.547879217e-03f, -7.337500507e-03f, -7.476779193e-03f, -4.763107701e-03f, +1.591166761e-03f, +1.155182965e-02f, +2.405459566e-02f, +3.711259647e-02f, +4.824976895e-02f, +5.514661113e-02f, +5.629449693e-02f, +5.143770614e-02f, +4.164938279e-02f, +2.901471178e-02f, +1.603219452e-02f, +4.938014526e-03f, -2.826381528e-03f, -6.849581767e-03f, -7.651498041e-03f, -6.332539518e-03f, -4.127306381e-03f, -2.026441000e-03f,
-    /* 24,12 */ -1.296719170e-03f, -3.152006158e-03f, -5.409521052e-03f, -7.260807322e-03f, -7.540310660e-03f, -5.034616251e-03f, +1.082980638e-03f, +1.083855586e-02f, +2.323264190e-02f, +3.632639074e-02f, +4.765670002e-02f, +5.487403917e-02f, +5.640295884e-02f, +5.190297478e-02f, +4.236967758e-02f, +2.984052134e-02f, +1.680833562e-02f, +5.543764951e-03f, -2.451643421e-03f, -6.701719772e-03f, -7.676527355e-03f, -6.453158507e-03f, -4.270322542e-03f, -2.141937776e-03f,
-    /* 24,13 */ -1.204312280e-03f, -3.018371382e-03f, -5.269701073e-03f, -7.177995846e-03f, -7.592836347e-03f, -5.291747706e-03f, +5.893521078e-04f, +1.013590849e-02f, +2.241360152e-02f, +3.553326091e-02f, +4.704730472e-02f, +5.457882991e-02f, +5.648741902e-02f, +5.234823086e-02f, +4.307811806e-02f, +3.066444409e-02f, +1.759164425e-02f, +6.162633403e-03f, -2.061956485e-03f, -6.540862270e-03f, -7.692920583e-03f, -6.570110572e-03f, -4.413702845e-03f, -2.260048394e-03f,
-    /* 24,14 */ -1.114962551e-03f, -2.886604737e-03f, -5.128670417e-03f, -7.089380216e-03f, -7.634636496e-03f, -5.534634231e-03f, +1.103863968e-04f, +9.444254477e-03f, +2.159804191e-02f, +3.473383802e-02f, +4.642210542e-02f, +5.426124576e-02f, +5.654780182e-02f, +5.277308334e-02f, +4.377411309e-02f, +3.148585651e-02f, +1.838162773e-02f, +6.794365087e-03f, -1.657314491e-03f, -6.366798820e-03f, -7.700368745e-03f, -6.683099486e-03f, -4.557243028e-03f, -2.380688695e-03f,
-    /* 24,15 */ -1.028686673e-03f, -2.756835384e-03f, -4.986674025e-03f, -6.995273095e-03f, -7.665996832e-03f, -5.763420347e-03f, -3.538276542e-04f, +8.763945305e-03f, +2.078652132e-02f, +3.392875410e-02f, +4.578163621e-02f, +5.392156860e-02f, +5.658405316e-02f, +5.317715832e-02f, +4.445707943e-02f, +3.230413198e-02f, +1.917778123e-02f, +7.438688744e-03f, -1.237726578e-03f, -6.179328945e-03f, -7.698565601e-03f, -6.791825424e-03f, -4.700731697e-03f, -2.503767166e-03f,
-    /* 24, 0 */ +4.735641749e-04f, -1.438577362e-03f, -6.107076473e-03f, -1.318715065e-02f, -2.047716119e-02f, -2.428668798e-02f, -2.088952800e-02f, -8.512165320e-03f, +1.117510535e-02f, +3.302575560e-02f, +5.012757987e-02f, +5.659614054e-02f, +5.012757987e-02f, +3.302575560e-02f, +1.117510535e-02f, -8.512165320e-03f, -2.088952800e-02f, -2.428668798e-02f, -2.047716119e-02f, -1.318715065e-02f, -6.107076473e-03f, -1.438577362e-03f, +4.735641749e-04f, +5.516063288e-04f,
-    /* 24, 1 */ +5.190146993e-04f, -1.243445781e-03f, -5.732182665e-03f, -1.270621714e-02f, -2.008108462e-02f, -2.422674988e-02f, -2.136190754e-02f, -9.536491055e-03f, +9.813857768e-03f, +3.172645287e-02f, +4.932296812e-02f, +5.657007725e-02f, +5.088942272e-02f, +3.430616434e-02f, +1.254542812e-02f, -7.458075491e-03f, -2.038088472e-02f, -2.431781992e-02f, -2.085968072e-02f, -1.366943909e-02f, -6.492037400e-03f, -1.644903025e-03f, +4.208638005e-04f, +5.761542752e-04f,
-    /* 24, 2 */ +5.575380238e-04f, -1.059370463e-03f, -5.367638258e-03f, -1.222740313e-02f, -1.967247249e-02f, -2.413881461e-02f, -2.179812108e-02f, -1.053019587e-02f, +8.463295193e-03f, +3.041001010e-02f, +4.847674006e-02f, +5.649192540e-02f, +5.160740292e-02f, +3.556594146e-02f, +1.392318625e-02f, -6.375136316e-03f, -1.983593655e-02f, -2.431936776e-02f, -2.122761958e-02f, -1.415229209e-02f, -6.886752185e-03f, -1.862540304e-03f, +3.605947820e-04f, +5.982066157e-04f,
-    /* 24, 3 */ +5.894596941e-04f, -8.861942853e-04f, -5.013694839e-03f, -1.175144649e-02f, -1.925234223e-02f, -2.402372023e-02f, -2.219832191e-02f, -1.149248169e-02f, +7.124994951e-03f, +2.907819451e-02f, +4.759010507e-02f, +5.636179897e-02f, +5.228048761e-02f, +3.680336864e-02f, +1.530671242e-02f, -5.264319552e-03f, -1.925469982e-02f, -2.429058667e-02f, -2.157995394e-02f, -1.463489443e-02f, -7.290876362e-03f, -2.091585491e-03f, +2.924431607e-04f, +6.174753085e-04f,
-    /* 24, 4 */ +6.151072142e-04f, -7.237418200e-04f, -4.670573645e-03f, -1.127905759e-02f, -1.882170532e-02f, -2.388233174e-02f, -2.256271775e-02f, -1.242260980e-02f, +5.800499486e-03f, +2.773278351e-02f, +4.666432713e-02f, +5.617988770e-02f, +5.290770668e-02f, +3.801674993e-02f, +1.669431448e-02f, -4.126652928e-03f, -1.863724919e-02f, -2.423076690e-02f, -2.191566174e-02f, -1.511640714e-02f, -7.704034115e-03f, -2.332112699e-03f, +2.161008111e-04f, +6.336652968e-04f,
-    /* 24, 5 */ +6.348091316e-04f, -5.718203517e-04f, -4.338465973e-03f, -1.081091853e-02f, -1.838156554e-02f, -2.371553901e-02f, -2.289156957e-02f, -1.331990148e-02f, +4.491314051e-03f, +2.637556170e-02f, +4.570072248e-02f, +5.594645674e-02f, +5.348815454e-02f, +3.920441468e-02f, +1.808427811e-02f, -2.963218986e-03f, -1.798371833e-02f, -2.413923574e-02f, -2.223372473e-02f, -1.559596853e-02f, -8.125818185e-03f, -2.584172964e-03f, +1.312664533e-04f, +6.464750685e-04f,
-    /* 24, 6 */ +6.488941487e-04f, -4.302209069e-04f, -4.017533648e-03f, -1.034768250e-02f, -1.793291714e-02f, -2.352425464e-02f, -2.318519030e-02f, -1.418373842e-02f, +3.198904487e-03f, +2.500831779e-02f, +4.470065727e-02f, +5.566184614e-02f, +5.402099181e-02f, +4.036472049e-02f, +1.947486957e-02f, -1.775153809e-03f, -1.729430055e-02f, -2.401535937e-02f, -2.253313051e-02f, -1.607269547e-02f, -8.555789856e-03f, -2.847793367e-03f, +3.764667972e-05f, +6.555972530e-04f,
-    /* 24, 7 */ +6.576902611e-04f, -2.987192943e-04f, -3.707909539e-03f, -9.889973186e-03f, -1.747674315e-02f, -2.330941189e-02f, -2.344394342e-02f, -1.501356300e-02f, +1.924695104e-03f, +2.363284155e-02f, +4.366554511e-02f, +5.532647026e-02f, +5.450544680e-02f, +4.149605616e-02f, +2.086433852e-02f, -5.636456344e-04f, -1.656924930e-02f, -2.385854478e-02f, -2.281287459e-02f, -1.654568462e-02f, -8.993479016e-03f, -3.122976195e-03f, -6.504300803e-05f, +6.607192554e-04f,
-    /* 24, 8 */ +6.615239252e-04f, -1.770771536e-04f, -3.409698141e-03f, -9.438384277e-03f, -1.701401374e-02f, -2.307196251e-02f, -2.366824152e-02f, -1.580887853e-02f, +6.700666468e-04f, +2.225092083e-02f, +4.259684448e-02f, +5.494081698e-02f, +5.494081698e-02f, +4.259684448e-02f, +2.225092083e-02f, +6.700666468e-04f, -1.580887853e-02f, -2.366824152e-02f, -2.307196251e-02f, -1.701401374e-02f, -9.438384277e-03f, -3.409698141e-03f, -1.770771536e-04f, +6.615239252e-04f,
-    /* 24, 9 */ +6.607192554e-04f, -6.504300803e-05f, -3.122976195e-03f, -8.993479016e-03f, -1.654568462e-02f, -2.281287459e-02f, -2.385854478e-02f, -1.656924930e-02f, -5.636456344e-04f, +2.086433852e-02f, +4.149605616e-02f, +5.450544680e-02f, +5.532647026e-02f, +4.366554511e-02f, +2.363284155e-02f, +1.924695104e-03f, -1.501356300e-02f, -2.344394342e-02f, -2.330941189e-02f, -1.747674315e-02f, -9.889973186e-03f, -3.707909539e-03f, -2.987192943e-04f, +6.576902611e-04f,
-    /* 24,10 */ +6.555972530e-04f, +3.764667972e-05f, -2.847793367e-03f, -8.555789856e-03f, -1.607269547e-02f, -2.253313051e-02f, -2.401535937e-02f, -1.729430055e-02f, -1.775153809e-03f, +1.947486957e-02f, +4.036472049e-02f, +5.402099181e-02f, +5.566184614e-02f, +4.470065727e-02f, +2.500831779e-02f, +3.198904487e-03f, -1.418373842e-02f, -2.318519030e-02f, -2.352425464e-02f, -1.793291714e-02f, -1.034768250e-02f, -4.017533648e-03f, -4.302209069e-04f, +6.488941487e-04f,
-    /* 24,11 */ +6.464750685e-04f, +1.312664533e-04f, -2.584172964e-03f, -8.125818185e-03f, -1.559596853e-02f, -2.223372473e-02f, -2.413923574e-02f, -1.798371833e-02f, -2.963218986e-03f, +1.808427811e-02f, +3.920441468e-02f, +5.348815454e-02f, +5.594645674e-02f, +4.570072248e-02f, +2.637556170e-02f, +4.491314051e-03f, -1.331990148e-02f, -2.289156957e-02f, -2.371553901e-02f, -1.838156554e-02f, -1.081091853e-02f, -4.338465973e-03f, -5.718203517e-04f, +6.348091316e-04f,
-    /* 24,12 */ +6.336652968e-04f, +2.161008111e-04f, -2.332112699e-03f, -7.704034115e-03f, -1.511640714e-02f, -2.191566174e-02f, -2.423076690e-02f, -1.863724919e-02f, -4.126652928e-03f, +1.669431448e-02f, +3.801674993e-02f, +5.290770668e-02f, +5.617988770e-02f, +4.666432713e-02f, +2.773278351e-02f, +5.800499486e-03f, -1.242260980e-02f, -2.256271775e-02f, -2.388233174e-02f, -1.882170532e-02f, -1.127905759e-02f, -4.670573645e-03f, -7.237418200e-04f, +6.151072142e-04f,
-    /* 24,13 */ +6.174753085e-04f, +2.924431607e-04f, -2.091585491e-03f, -7.290876362e-03f, -1.463489443e-02f, -2.157995394e-02f, -2.429058667e-02f, -1.925469982e-02f, -5.264319552e-03f, +1.530671242e-02f, +3.680336864e-02f, +5.228048761e-02f, +5.636179897e-02f, +4.759010507e-02f, +2.907819451e-02f, +7.124994951e-03f, -1.149248169e-02f, -2.219832191e-02f, -2.402372023e-02f, -1.925234223e-02f, -1.175144649e-02f, -5.013694839e-03f, -8.861942853e-04f, +5.894596941e-04f,
-    /* 24,14 */ +5.982066157e-04f, +3.605947820e-04f, -1.862540304e-03f, -6.886752185e-03f, -1.415229209e-02f, -2.122761958e-02f, -2.431936776e-02f, -1.983593655e-02f, -6.375136316e-03f, +1.392318625e-02f, +3.556594146e-02f, +5.160740292e-02f, +5.649192540e-02f, +4.847674006e-02f, +3.041001010e-02f, +8.463295193e-03f, -1.053019587e-02f, -2.179812108e-02f, -2.413881461e-02f, -1.967247249e-02f, -1.222740313e-02f, -5.367638258e-03f, -1.059370463e-03f, +5.575380238e-04f,
-    /* 24,15 */ +5.761542752e-04f, +4.208638005e-04f, -1.644903025e-03f, -6.492037400e-03f, -1.366943909e-02f, -2.085968072e-02f, -2.431781992e-02f, -2.038088472e-02f, -7.458075491e-03f, +1.254542812e-02f, +3.430616434e-02f, +5.088942272e-02f, +5.657007725e-02f, +4.932296812e-02f, +3.172645287e-02f, +9.813857768e-03f, -9.536491055e-03f, -2.136190754e-02f, -2.422674988e-02f, -2.008108462e-02f, -1.270621714e-02f, -5.732182665e-03f, -1.243445781e-03f, +5.190146993e-04f,
-    /* 24, 0 */ +2.273459443e-03f, +5.435907648e-03f, +7.255296399e-03f, +3.788129032e-03f, -7.144684562e-03f, -2.265374973e-02f, -3.442368170e-02f, -3.287677614e-02f, -1.387331771e-02f, +1.679264590e-02f, +4.511451955e-02f, +5.659614054e-02f, +4.511451955e-02f, +1.679264590e-02f, -1.387331771e-02f, -3.287677614e-02f, -3.442368170e-02f, -2.265374973e-02f, -7.144684562e-03f, +3.788129032e-03f, +7.255296399e-03f, +5.435907648e-03f, +2.273459443e-03f, +3.568431303e-04f,
-    /* 24, 1 */ +2.103234406e-03f, +5.239407106e-03f, +7.256400195e-03f, +4.221207454e-03f, -6.266228991e-03f, -2.168841690e-02f, -3.399213075e-02f, -3.348773370e-02f, -1.551504116e-02f, +1.477681868e-02f, +4.371373211e-02f, +5.654911556e-02f, +4.644656718e-02f, +1.879953521e-02f, -1.218307761e-02f, -3.219410560e-02f, -3.480135038e-02f, -2.360501860e-02f, -8.042999544e-03f, +3.324105568e-03f, +7.232988111e-03f, +5.627714430e-03f, +2.449385040e-03f, +4.247055554e-04f,
-    /* 24, 2 */ +1.939021806e-03f, +5.039131826e-03f, +7.237298926e-03f, +4.623451366e-03f, -5.409068119e-03f, -2.071157693e-02f, -3.350883303e-02f, -3.402698064e-02f, -1.710557364e-02f, +1.275612557e-02f, +4.224725679e-02f, +5.640814528e-02f, +4.770696520e-02f, +2.079340350e-02f, -1.044713814e-02f, -3.143988919e-02f, -3.512309015e-02f, -2.453963953e-02f, -8.959642554e-03f, +2.829112073e-03f, +7.188501693e-03f, +5.813881008e-03f, +2.630658922e-03f, +4.992251326e-04f,
-    /* 24, 3 */ +1.781093672e-03f, +4.835971292e-03f, +7.199013760e-03f, +4.995053998e-03f, -4.574539506e-03f, -1.972575310e-02f, -3.297600576e-02f, -3.449468646e-02f, -1.864238902e-02f, +1.073461753e-02f, +4.071827965e-02f, +5.617354343e-02f, +4.889295364e-02f, +2.277016679e-02f, -8.668453837e-03f, -3.061446547e-02f, -3.538695026e-02f, -2.545500791e-02f, -9.892988076e-03f, +2.303211764e-03f, +7.120893393e-03f, +5.993435804e-03f, +2.816887995e-03f, +5.805470381e-04f,
-    /* 24, 4 */ +1.629682882e-03f, +4.630783503e-03f, +7.142583584e-03f, +5.336288236e-03f, -3.763881685e-03f, -1.873342898e-02f, -3.239594057e-02f, -3.489118499e-02f, -2.012311412e-02f, +8.716314532e-03f, +3.913011251e-02f, +5.584583195e-02f, +5.000192959e-02f, +2.472575033e-02f, -6.850110412e-03f, -2.971834586e-02f, -3.559108276e-02f, -2.634850527e-02f, -1.084131876e-02f, +1.746558492e-03f, +7.029253460e-03f, +6.165384566e-03f, +3.007638074e-03f, +6.687931554e-04f,
-    /* 24, 5 */ +1.484983972e-03f, +4.424393216e-03f, +7.069061064e-03f, +5.647503405e-03f, -2.978233194e-03f, -1.773704257e-02f, -3.177099609e-02f, -3.521697115e-02f, -2.154553308e-02f, +6.705195776e-03f, +3.748618427e-02f, +5.542573963e-02f, +5.103145416e-02f, +2.665609886e-02f, -4.995318215e-03f, -2.875221569e-02f, -3.573374914e-02f, -2.721750622e-02f, -1.180282806e-02f, +1.159398961e-03f, +6.912710257e-03f, +6.328712988e-03f, +3.202433762e-03f, +7.640603932e-04f,
-    /* 24, 6 */ +1.347154069e-03f, +4.217590351e-03f, +6.979508760e-03f, +5.929121902e-03f, -2.218631929e-03f, -1.673898061e-02f, -3.110359053e-02f, -3.547269735e-02f, -2.290759116e-02f, +4.705190128e-03f, +3.579003198e-02f, +5.491420012e-02f, +5.197925890e-02f, +2.855718684e-02f, -3.107405323e-03f, -2.771693469e-02f, -3.581332680e-02f, -2.805938547e-02f, -1.277562317e-02f, +5.420746921e-04f, +6.770434377e-03f, +6.482389493e-03f, +3.400758480e-03f, +8.664190421e-04f,
-    /* 24, 7 */ +1.216313935e-03f, +4.011128586e-03f, +6.874995333e-03f, +6.181635683e-03f, -1.486014823e-03f, -1.574157316e-02f, -3.039619415e-02f, -3.565916944e-02f, -2.420739811e-02f, +2.720166717e-03f, +3.404529163e-02f, +5.431234943e-02f, +5.284325182e-02f, +3.042502866e-02f, -1.189810237e-03f, -2.661353708e-02f, -3.582831530e-02f, -2.887152508e-02f, -1.375772836e-02f, -1.049762569e-04f, +6.601642735e-03f, +6.625368167e-03f, +3.602054665e-03f, +9.759111772e-04f,
-    /* 24, 8 */ +1.092549115e-03f, +3.805724130e-03f, +6.756591845e-03f, +6.405602617e-03f, -7.812178358e-04f, -1.474708852e-02f, -2.965132174e-02f, -3.577734234e-02f, -2.544323110e-02f, +7.539257812e-04f, +3.225568873e-02f, +5.362152294e-02f, +5.362152294e-02f, +3.225568873e-02f, +7.539257812e-04f, -2.544323110e-02f, -3.577734234e-02f, -2.965132174e-02f, -1.474708852e-02f, -7.812178358e-04f, +6.405602617e-03f, +6.756591845e-03f, +3.805724130e-03f, +1.092549115e-03f,
-    /* 24, 9 */ +9.759111772e-04f, +3.602054665e-03f, +6.625368167e-03f, +6.601642735e-03f, -1.049762569e-04f, -1.375772836e-02f, -2.887152508e-02f, -3.582831530e-02f, -2.661353708e-02f, -1.189810237e-03f, +3.042502866e-02f, +5.284325182e-02f, +5.431234943e-02f, +3.404529163e-02f, +2.720166717e-03f, -2.420739811e-02f, -3.565916944e-02f, -3.039619415e-02f, -1.574157316e-02f, -1.486014823e-03f, +6.181635683e-03f, +6.874995333e-03f, +4.011128586e-03f, +1.216313935e-03f,
-    /* 24,10 */ +8.664190421e-04f, +3.400758480e-03f, +6.482389493e-03f, +6.770434377e-03f, +5.420746921e-04f, -1.277562317e-02f, -2.805938547e-02f, -3.581332680e-02f, -2.771693469e-02f, -3.107405323e-03f, +2.855718684e-02f, +5.197925890e-02f, +5.491420012e-02f, +3.579003198e-02f, +4.705190128e-03f, -2.290759116e-02f, -3.547269735e-02f, -3.110359053e-02f, -1.673898061e-02f, -2.218631929e-03f, +5.929121902e-03f, +6.979508760e-03f, +4.217590351e-03f, +1.347154069e-03f,
-    /* 24,11 */ +7.640603932e-04f, +3.202433762e-03f, +6.328712988e-03f, +6.912710257e-03f, +1.159398961e-03f, -1.180282806e-02f, -2.721750622e-02f, -3.573374914e-02f, -2.875221569e-02f, -4.995318215e-03f, +2.665609886e-02f, +5.103145416e-02f, +5.542573963e-02f, +3.748618427e-02f, +6.705195776e-03f, -2.154553308e-02f, -3.521697115e-02f, -3.177099609e-02f, -1.773704257e-02f, -2.978233194e-03f, +5.647503405e-03f, +7.069061064e-03f, +4.424393216e-03f, +1.484983972e-03f,
-    /* 24,12 */ +6.687931554e-04f, +3.007638074e-03f, +6.165384566e-03f, +7.029253460e-03f, +1.746558492e-03f, -1.084131876e-02f, -2.634850527e-02f, -3.559108276e-02f, -2.971834586e-02f, -6.850110412e-03f, +2.472575033e-02f, +5.000192959e-02f, +5.584583195e-02f, +3.913011251e-02f, +8.716314532e-03f, -2.012311412e-02f, -3.489118499e-02f, -3.239594057e-02f, -1.873342898e-02f, -3.763881685e-03f, +5.336288236e-03f, +7.142583584e-03f, +4.630783503e-03f, +1.629682882e-03f,
-    /* 24,13 */ +5.805470381e-04f, +2.816887995e-03f, +5.993435804e-03f, +7.120893393e-03f, +2.303211764e-03f, -9.892988076e-03f, -2.545500791e-02f, -3.538695026e-02f, -3.061446547e-02f, -8.668453837e-03f, +2.277016679e-02f, +4.889295364e-02f, +5.617354343e-02f, +4.071827965e-02f, +1.073461753e-02f, -1.864238902e-02f, -3.449468646e-02f, -3.297600576e-02f, -1.972575310e-02f, -4.574539506e-03f, +4.995053998e-03f, +7.199013760e-03f, +4.835971292e-03f, +1.781093672e-03f,
-    /* 24,14 */ +4.992251326e-04f, +2.630658922e-03f, +5.813881008e-03f, +7.188501693e-03f, +2.829112073e-03f, -8.959642554e-03f, -2.453963953e-02f, -3.512309015e-02f, -3.143988919e-02f, -1.044713814e-02f, +2.079340350e-02f, +4.770696520e-02f, +5.640814528e-02f, +4.224725679e-02f, +1.275612557e-02f, -1.710557364e-02f, -3.402698064e-02f, -3.350883303e-02f, -2.071157693e-02f, -5.409068119e-03f, +4.623451366e-03f, +7.237298926e-03f, +5.039131826e-03f, +1.939021806e-03f,
-    /* 24,15 */ +4.247055554e-04f, +2.449385040e-03f, +5.627714430e-03f, +7.232988111e-03f, +3.324105568e-03f, -8.042999544e-03f, -2.360501860e-02f, -3.480135038e-02f, -3.219410560e-02f, -1.218307761e-02f, +1.879953521e-02f, +4.644656718e-02f, +5.654911556e-02f, +4.371373211e-02f, +1.477681868e-02f, -1.551504116e-02f, -3.348773370e-02f, -3.399213075e-02f, -2.168841690e-02f, -6.266228991e-03f, +4.221207454e-03f, +7.256400195e-03f, +5.239407106e-03f, +2.103234406e-03f,
-    /* 24, 0 */ -2.181310192e-03f, -7.982329251e-04f, +5.680209618e-03f, +1.430719659e-02f, +1.589843483e-02f, +2.406871994e-03f, -2.249676846e-02f, -4.130100690e-02f, -3.506718353e-02f, -1.541681908e-03f, +3.867898214e-02f, +5.659614054e-02f, +3.867898214e-02f, -1.541681908e-03f, -3.506718353e-02f, -4.130100690e-02f, -2.249676846e-02f, +2.406871994e-03f, +1.589843483e-02f, +1.430719659e-02f, +5.680209618e-03f, -7.982329251e-04f, -2.181310192e-03f, -9.324150638e-04f,
-    /* 24, 1 */ -2.142117633e-03f, -1.026327303e-03f, +5.144075019e-03f, +1.386145083e-02f, +1.619749380e-02f, +3.702669669e-03f, -2.089125129e-02f, -4.071342524e-02f, -3.635626763e-02f, -4.137848013e-03f, +3.654904222e-02f, +5.652117066e-02f, +4.071616274e-02f, +1.083860427e-03f, -3.366302266e-02f, -4.178478525e-02f, -2.407924887e-02f, +1.061252794e-03f, +1.553625174e-02f, +1.472529111e-02f, +6.227191439e-03f, -5.482915187e-04f, -2.210193915e-03f, -1.021372070e-03f,
-    /* 24, 2 */ -2.093579858e-03f, -1.232841058e-03f, +4.620399561e-03f, +1.339085359e-02f, +1.643462496e-02f, +4.945866528e-03f, -1.926829204e-02f, -4.002576024e-02f, -3.752797769e-02f, -6.697199080e-03f, +3.433305089e-02f, +5.629650283e-02f, +4.265414906e-02f, +3.731182183e-03f, -3.214649405e-02f, -4.216132985e-02f, -2.563305646e-02f, -3.311524193e-04f, +1.510995111e-02f, +1.511293981e-02f, +6.783287607e-03f, -2.763303743e-04f, -2.227804667e-03f, -1.112061839e-03f,
-    /* 24, 3 */ -2.036654869e-03f, -1.418128950e-03f, +4.110671651e-03f, +1.289819803e-02f, +1.661121711e-02f, +6.133943976e-03f, -1.763342417e-02f, -3.924200344e-02f, -3.858043162e-02f, -9.212479159e-03f, +3.203796457e-02f, +5.592286159e-02f, +4.448680259e-02f, +6.392554173e-03f, -3.052071354e-02f, -4.242751674e-02f, -2.715253413e-02f, -1.767057534e-03f, +1.461875233e-02f, +1.546736546e-02f, +7.346647501e-03f, +1.772445414e-05f, -2.233183138e-03f, -1.203936109e-03f,
-    /* 24, 4 */ -1.972290178e-03f, -1.582628528e-03f, +3.616254280e-03f, +1.238625918e-02f, +1.672884047e-02f, +7.264647438e-03f, -1.599210066e-02f, -3.836639935e-02f, -3.951216427e-02f, -1.167663915e-02f, +2.967096294e-02f, +5.540145153e-02f, +4.620830373e-02f, +9.060141131e-03f, -2.878919714e-02f, -4.258054458e-02f, -2.863202454e-02f, -3.242932618e-03f, +1.406209682e-02f, +1.578582064e-02f, +7.915306646e-03f, +3.338433846e-04f, -2.225380377e-03f, -1.296401007e-03f,
-    /* 24, 5 */ -1.901418208e-03f, -1.726854356e-03f, +3.138383775e-03f, +1.185778300e-02f, +1.678923519e-02f, +8.335988548e-03f, -1.434967550e-02f, -3.740342600e-02f, -4.032212766e-02f, -1.408285985e-02f, +2.723942290e-02f, +5.473395280e-02f, +4.781317317e-02f, +1.172602857e-02f, -2.695585286e-02f, -4.261794963e-02f, -3.006589126e-02f, -4.755011838e-03f, +1.343965653e-02f, +1.606560041e-02f, +8.487191262e-03f, +6.718888821e-04f, -2.203463508e-03f, -1.388818223e-03f,
-    /* 24, 6 */ -1.824951954e-03f, -1.851392085e-03f, +2.678169173e-03f, +1.131547576e-02f, +1.679429951e-02f, +9.346246206e-03f, -1.271138577e-02f, -3.635777499e-02f, -4.100968953e-02f, -1.642457396e-02f, +2.475089197e-02f, +5.392251484e-02f, +4.929629202e-02f, +1.438225015e-02f, -2.502497093e-02f, -4.253761970e-02f, -3.144854025e-02f, -6.299302508e-03f, +1.275134172e-02f, +1.630405519e-02f, +9.060123484e-03f, +1.031611407e-03f, -2.166521604e-03f, -1.480506488e-03f,
-    /* 24, 7 */ -1.743780953e-03f, -1.956892396e-03f, +2.236592212e-03f, +1.076199396e-02f, +1.674607744e-02f, +1.029396653e-02f, -1.108233467e-02f, -3.523433096e-02f, -4.157463041e-02f, -1.869548696e-02f, +2.221306113e-02f, +5.296974848e-02f, +5.065292065e-02f, +1.702081530e-02f, -2.300121251e-02f, -4.233780689e-02f, -3.277444146e-02f, -7.871595256e-03f, +1.199730786e-02f, +1.649860375e-02f, +9.631827247e-03f, +1.412645767e-03f, -2.113671692e-03f, -1.570743396e-03f,
-    /* 24, 8 */ -1.658767534e-03f, -2.044064852e-03f, +1.814507917e-03f, +1.019993481e-02f, +1.664674627e-02f, +1.117796172e-02f, -9.467475281e-03f, -3.403815061e-02f, -4.201713914e-02f, -2.088959684e-02f, +1.963373727e-02f, +5.187871616e-02f, +5.187871616e-02f, +1.963373727e-02f, -2.088959684e-02f, -4.201713914e-02f, -3.403815061e-02f, -9.467475281e-03f, +1.117796172e-02f, +1.664674627e-02f, +1.019993481e-02f, +1.814507917e-03f, -2.044064852e-03f, -1.658767534e-03f,
-    /* 24, 9 */ -1.570743396e-03f, -2.113671692e-03f, +1.412645767e-03f, +9.631827247e-03f, +1.649860375e-02f, +1.199730786e-02f, -7.871595256e-03f, -3.277444146e-02f, -4.233780689e-02f, -2.300121251e-02f, +1.702081530e-02f, +5.065292065e-02f, +5.296974848e-02f, +2.221306113e-02f, -1.869548696e-02f, -4.157463041e-02f, -3.523433096e-02f, -1.108233467e-02f, +1.029396653e-02f, +1.674607744e-02f, +1.076199396e-02f, +2.236592212e-03f, -1.956892396e-03f, -1.743780953e-03f,
-    /* 24,10 */ -1.480506488e-03f, -2.166521604e-03f, +1.031611407e-03f, +9.060123484e-03f, +1.630405519e-02f, +1.275134172e-02f, -6.299302508e-03f, -3.144854025e-02f, -4.253761970e-02f, -2.502497093e-02f, +1.438225015e-02f, +4.929629202e-02f, +5.392251484e-02f, +2.475089197e-02f, -1.642457396e-02f, -4.100968953e-02f, -3.635777499e-02f, -1.271138577e-02f, +9.346246206e-03f, +1.679429951e-02f, +1.131547576e-02f, +2.678169173e-03f, -1.851392085e-03f, -1.824951954e-03f,
-    /* 24,11 */ -1.388818223e-03f, -2.203463508e-03f, +6.718888821e-04f, +8.487191262e-03f, +1.606560041e-02f, +1.343965653e-02f, -4.755011838e-03f, -3.006589126e-02f, -4.261794963e-02f, -2.695585286e-02f, +1.172602857e-02f, +4.781317317e-02f, +5.473395280e-02f, +2.723942290e-02f, -1.408285985e-02f, -4.032212766e-02f, -3.740342600e-02f, -1.434967550e-02f, +8.335988548e-03f, +1.678923519e-02f, +1.185778300e-02f, +3.138383775e-03f, -1.726854356e-03f, -1.901418208e-03f,
-    /* 24,12 */ -1.296401007e-03f, -2.225380377e-03f, +3.338433846e-04f, +7.915306646e-03f, +1.578582064e-02f, +1.406209682e-02f, -3.242932618e-03f, -2.863202454e-02f, -4.258054458e-02f, -2.878919714e-02f, +9.060141131e-03f, +4.620830373e-02f, +5.540145153e-02f, +2.967096294e-02f, -1.167663915e-02f, -3.951216427e-02f, -3.836639935e-02f, -1.599210066e-02f, +7.264647438e-03f, +1.672884047e-02f, +1.238625918e-02f, +3.616254280e-03f, -1.582628528e-03f, -1.972290178e-03f,
-    /* 24,13 */ -1.203936109e-03f, -2.233183138e-03f, +1.772445414e-05f, +7.346647501e-03f, +1.546736546e-02f, +1.461875233e-02f, -1.767057534e-03f, -2.715253413e-02f, -4.242751674e-02f, -3.052071354e-02f, +6.392554173e-03f, +4.448680259e-02f, +5.592286159e-02f, +3.203796457e-02f, -9.212479159e-03f, -3.858043162e-02f, -3.924200344e-02f, -1.763342417e-02f, +6.133943976e-03f, +1.661121711e-02f, +1.289819803e-02f, +4.110671651e-03f, -1.418128950e-03f, -2.036654869e-03f,
-    /* 24,14 */ -1.112061839e-03f, -2.227804667e-03f, -2.763303743e-04f, +6.783287607e-03f, +1.511293981e-02f, +1.510995111e-02f, -3.311524193e-04f, -2.563305646e-02f, -4.216132985e-02f, -3.214649405e-02f, +3.731182183e-03f, +4.265414906e-02f, +5.629650283e-02f, +3.433305089e-02f, -6.697199080e-03f, -3.752797769e-02f, -4.002576024e-02f, -1.926829204e-02f, +4.945866528e-03f, +1.643462496e-02f, +1.339085359e-02f, +4.620399561e-03f, -1.232841058e-03f, -2.093579858e-03f,
-    /* 24,15 */ -1.021372070e-03f, -2.210193915e-03f, -5.482915187e-04f, +6.227191439e-03f, +1.472529111e-02f, +1.553625174e-02f, +1.061252794e-03f, -2.407924887e-02f, -4.178478525e-02f, -3.366302266e-02f, +1.083860427e-03f, +4.071616274e-02f, +5.652117066e-02f, +3.654904222e-02f, -4.137848013e-03f, -3.635626763e-02f, -4.071342524e-02f, -2.089125129e-02f, +3.702669669e-03f, +1.619749380e-02f, +1.386145083e-02f, +5.144075019e-03f, -1.026327303e-03f, -2.142117633e-03f,
-    /* 24, 0 */ -6.349328336e-04f, -5.107444449e-03f, -7.589492700e-03f, +4.421169254e-04f, +1.733331948e-02f, +2.497839430e-02f, +6.069612140e-03f, -2.970035006e-02f, -4.651799663e-02f, -1.968310326e-02f, +3.102388246e-02f, +5.659614054e-02f, +3.102388246e-02f, -1.968310326e-02f, -4.651799663e-02f, -2.970035006e-02f, +6.069612140e-03f, +2.497839430e-02f, +1.733331948e-02f, +4.421169254e-04f, -7.589492700e-03f, -5.107444449e-03f, -6.349328336e-04f, +6.381929817e-04f,
-    /* 24, 1 */ -4.501246045e-04f, -4.794789988e-03f, -7.673310752e-03f, -4.276921651e-04f, +1.630487239e-02f, +2.519230977e-02f, +8.023727481e-03f, -2.760467194e-02f, -4.668156835e-02f, -2.250226055e-02f, +2.808383767e-02f, +5.648624601e-02f, +3.385706239e-02f, -1.675917373e-02f, -4.616688010e-02f, -3.171828840e-02f, +4.039135426e-03f, +2.465060544e-02f, +1.832599562e-02f, +1.353161175e-03f, -7.461005422e-03f, -5.414037993e-03f, -8.347893499e-04f, +6.459962873e-04f,
-    /* 24, 2 */ -2.805431667e-04f, -4.478334337e-03f, -7.714347254e-03f, -1.253762011e-03f, +1.524677189e-02f, +2.529479915e-02f, +9.894771606e-03f, -2.544172743e-02f, -4.665953469e-02f, -2.520578478e-02f, +2.504972253e-02f, +5.615705320e-02f, +3.657100703e-02f, -1.374190145e-02f, -4.562711379e-02f, -3.364818878e-02f, +1.939527429e-03f, +2.420699082e-02f, +1.927675855e-02f, +2.302607998e-03f, -7.286133997e-03f, -5.712221732e-03f, -1.049390115e-03f, +6.454263440e-04f,
-    /* 24, 3 */ -1.262469087e-04f, -4.160237857e-03f, -7.714644364e-03f, -2.033919173e-03f, +1.416507919e-02f, +2.528877950e-02f, +1.167657735e-02f, -2.322211124e-02f, -4.645464989e-02f, -2.778343069e-02f, +2.193469332e-02f, +5.561003206e-02f, +3.915383052e-02f, -1.064323425e-02f, -4.489844274e-02f, -3.547998209e-02f, -2.214871506e-04f, +2.364611605e-02f, +2.017947396e-02f, +3.287300483e-03f, -7.063354139e-03f, -5.999568857e-03f, -1.278300802e-03f, +6.356530069e-04f,
-    /* 24, 4 */ +1.281987696e-05f, -3.842552418e-03f, -7.676380196e-03f, -2.766321017e-03f, +1.306576874e-02f, +2.517761055e-02f, +1.336353941e-02f, -2.095648565e-02f, -4.607045954e-02f, -3.022561220e-02f, +1.875220414e-02f, +5.484762432e-02f, +4.159418981e-02f, -7.475585158e-03f, -4.398147340e-02f, -3.720388175e-02f, -2.435717775e-03f, +2.296708552e-02f, +2.102804905e-02f, +4.303763633e-03f, -6.791349552e-03f, -6.273586899e-03f, -1.520952773e-03f, +6.158659890e-04f,
-    /* 24, 5 */ +1.368204413e-04f, -3.527213369e-03f, -7.601850138e-03f, -3.449453954e-03f, +1.195469912e-02f, +2.496506585e-02f, +1.495063011e-02f, -1.865552736e-02f, -4.551127331e-02f, -3.252344226e-02f, +1.551594186e-02f, +5.387323140e-02f, +4.388134039e-02f, -4.251776447e-03f, -4.287768073e-02f, -3.881043651e-02f, -4.694539858e-03f, +2.216956067e-02f, +2.181646678e-02f, +5.348212687e-03f, -6.469028645e-03f, -6.531730950e-03f, -1.776639841e-03f, +5.852828120e-04f,
-    /* 24, 6 */ +2.460185614e-04f, -3.216032617e-03f, -7.493448175e-03f, -4.082129823e-03f, +1.083758546e-02f, +2.465530244e-02f, +1.643341199e-02f, -1.632987505e-02f, -4.478213426e-02f, -3.466876896e-02f, +1.223976005e-02f, +5.269119738e-02f, +4.600518917e-02f, -9.849812576e-04f, -4.158941105e-02f, -4.029058231e-02f, -6.988929457e-03f, +2.125377578e-02f, +2.253882061e-02f, +6.416563547e-03f, -6.095540465e-03f, -6.771417794e-03f, -2.044515881e-03f, +5.431569434e-04f,
-    /* 24, 7 */ +3.407711290e-04f, -2.910692818e-03f, -7.353648294e-03f, -4.663480492e-03f, +9.719973395e-03f, +2.425282916e-02f, +1.780804686e-02f, -1.399007798e-02f, -4.388878466e-02f, -3.665420751e-02f, +8.937612534e-03f, +5.130678745e-02f, +4.795634432e-02f, +2.311336934e-03f, -4.011988036e-02f, -4.163569289e-02f, -9.309500719e-03f, +2.022055084e-02f, +2.318934965e-02f, +7.504445299e-03f, -5.670289717e-03f, -6.990040888e-03f, -2.323593338e-03f, +4.887860648e-04f,
-    /* 24, 8 */ +4.215204125e-04f, -2.612742676e-03f, -7.184986124e-03f, -5.192950770e-03f, +8.607214812e-03f, +2.376247385e-02f, +1.907130164e-02f, -1.164654593e-02f, -4.283762880e-02f, -3.847316827e-02f, +5.623486691e-03f, +4.972616165e-02f, +4.972616165e-02f, +5.623486691e-03f, -3.847316827e-02f, -4.283762880e-02f, -1.164654593e-02f, +1.907130164e-02f, +2.376247385e-02f, +8.607214812e-03f, -5.192950770e-03f, -7.184986124e-03f, -2.612742676e-03f, +4.215204125e-04f,
-    /* 24, 9 */ +4.887860648e-04f, -2.323593338e-03f, -6.990040888e-03f, -5.670289717e-03f, +7.504445299e-03f, +2.318934965e-02f, +2.022055084e-02f, -9.309500719e-03f, -4.163569289e-02f, -4.011988036e-02f, +2.311336934e-03f, +4.795634432e-02f, +5.130678745e-02f, +8.937612534e-03f, -3.665420751e-02f, -4.388878466e-02f, -1.399007798e-02f, +1.780804686e-02f, +2.425282916e-02f, +9.719973395e-03f, -4.663480492e-03f, -7.353648294e-03f, -2.910692818e-03f, +3.407711290e-04f,
-    /* 24,10 */ +5.431569434e-04f, -2.044515881e-03f, -6.771417794e-03f, -6.095540465e-03f, +6.416563547e-03f, +2.253882061e-02f, +2.125377578e-02f, -6.988929457e-03f, -4.029058231e-02f, -4.158941105e-02f, -9.849812576e-04f, +4.600518917e-02f, +5.269119738e-02f, +1.223976005e-02f, -3.466876896e-02f, -4.478213426e-02f, -1.632987505e-02f, +1.643341199e-02f, +2.465530244e-02f, +1.083758546e-02f, -4.082129823e-03f, -7.493448175e-03f, -3.216032617e-03f, +2.460185614e-04f,
-    /* 24,11 */ +5.852828120e-04f, -1.776639841e-03f, -6.531730950e-03f, -6.469028645e-03f, +5.348212687e-03f, +2.181646678e-02f, +2.216956067e-02f, -4.694539858e-03f, -3.881043651e-02f, -4.287768073e-02f, -4.251776447e-03f, +4.388134039e-02f, +5.387323140e-02f, +1.551594186e-02f, -3.252344226e-02f, -4.551127331e-02f, -1.865552736e-02f, +1.495063011e-02f, +2.496506585e-02f, +1.195469912e-02f, -3.449453954e-03f, -7.601850138e-03f, -3.527213369e-03f, +1.368204413e-04f,
-    /* 24,12 */ +6.158659890e-04f, -1.520952773e-03f, -6.273586899e-03f, -6.791349552e-03f, +4.303763633e-03f, +2.102804905e-02f, +2.296708552e-02f, -2.435717775e-03f, -3.720388175e-02f, -4.398147340e-02f, -7.475585158e-03f, +4.159418981e-02f, +5.484762432e-02f, +1.875220414e-02f, -3.022561220e-02f, -4.607045954e-02f, -2.095648565e-02f, +1.336353941e-02f, +2.517761055e-02f, +1.306576874e-02f, -2.766321017e-03f, -7.676380196e-03f, -3.842552418e-03f, +1.281987696e-05f,
-    /* 24,13 */ +6.356530069e-04f, -1.278300802e-03f, -5.999568857e-03f, -7.063354139e-03f, +3.287300483e-03f, +2.017947396e-02f, +2.364611605e-02f, -2.214871506e-04f, -3.547998209e-02f, -4.489844274e-02f, -1.064323425e-02f, +3.915383052e-02f, +5.561003206e-02f, +2.193469332e-02f, -2.778343069e-02f, -4.645464989e-02f, -2.322211124e-02f, +1.167657735e-02f, +2.528877950e-02f, +1.416507919e-02f, -2.033919173e-03f, -7.714644364e-03f, -4.160237857e-03f, -1.262469087e-04f,
-    /* 24,14 */ +6.454263440e-04f, -1.049390115e-03f, -5.712221732e-03f, -7.286133997e-03f, +2.302607998e-03f, +1.927675855e-02f, +2.420699082e-02f, +1.939527429e-03f, -3.364818878e-02f, -4.562711379e-02f, -1.374190145e-02f, +3.657100703e-02f, +5.615705320e-02f, +2.504972253e-02f, -2.520578478e-02f, -4.665953469e-02f, -2.544172743e-02f, +9.894771606e-03f, +2.529479915e-02f, +1.524677189e-02f, -1.253762011e-03f, -7.714347254e-03f, -4.478334337e-03f, -2.805431667e-04f,
-    /* 24,15 */ +6.459962873e-04f, -8.347893499e-04f, -5.414037993e-03f, -7.461005422e-03f, +1.353161175e-03f, +1.832599562e-02f, +2.465060544e-02f, +4.039135426e-03f, -3.171828840e-02f, -4.616688010e-02f, -1.675917373e-02f, +3.385706239e-02f, +5.648624601e-02f, +2.808383767e-02f, -2.250226055e-02f, -4.668156835e-02f, -2.760467194e-02f, +8.023727481e-03f, +2.519230977e-02f, +1.630487239e-02f, -4.276921651e-04f, -7.673310752e-03f, -4.794789988e-03f, -4.501246045e-04f,
-    /* 24, 0 */ +1.197013499e-03f, +3.320493122e-03f, -3.017233048e-03f, -9.987553340e-03f, -4.112967049e-03f, +1.524501264e-02f, +2.235677036e-02f, -2.137559158e-03f, -3.327370097e-02f, -2.660122408e-02f, +1.657531807e-02f, +4.232694754e-02f, +1.657531807e-02f, -2.660122408e-02f, -3.327370097e-02f, -2.137559158e-03f, +2.235677036e-02f, +1.524501264e-02f, -4.112967049e-03f, -9.987553340e-03f, -3.017233048e-03f, +2.318357031e-03f, +1.197013499e-03f, -1.261205705e-04f,
-    /* 24, 1 */ +1.060573898e-03f, +3.246029352e-03f, -2.510607281e-03f, -9.784551764e-03f, -5.018393221e-03f, +1.404948670e-02f, +2.282515537e-02f, +7.626640355e-05f, -3.208475603e-02f, -2.845760231e-02f, +1.374134711e-02f, +4.221250979e-02f, +1.933345641e-02f, -2.458052660e-02f, -3.429687591e-02f, -4.386190237e-03f, +2.174698353e-02f, +1.639120730e-02f, -3.143642175e-03f, -1.013545813e-02f, -3.535011248e-03f, +2.193303334e-03f, +1.338504197e-03f, -9.901282259e-05f,
-    /* 24, 2 */ +9.298712414e-04f, +3.156277727e-03f, -2.018194158e-03f, -9.530340989e-03f, -5.856606243e-03f, +1.281349999e-02f, +2.315294314e-02f, +2.243024978e-03f, -3.073934924e-02f, -3.014061672e-02f, +1.084811230e-02f, +4.186988491e-02f, +2.199957595e-02f, -2.240563854e-02f, -3.514586546e-02f, -6.656913804e-03f, +2.099588115e-02f, +1.747926153e-02f, -2.114297018e-03f, -1.022461460e-02f, -4.060636553e-03f, +2.039754046e-03f, +1.484263468e-03f, -6.526428163e-05f,
-    /* 24, 3 */ +8.054954021e-04f, +3.052984548e-03f, -1.542795645e-03f, -9.229007144e-03f, -6.624860539e-03f, +1.154592266e-02f, +2.334180387e-02f, +4.350977952e-03f, -2.924761047e-02f, -3.164235460e-02f, +7.912459038e-03f, +4.130113344e-02f, +2.455797710e-02f, -2.008771737e-02f, -3.581321303e-02f, -8.936640836e-03f, +2.010445982e-02f, +1.850049032e-02f, -1.029364704e-03f, -1.025164428e-02f, -4.590574200e-03f, +1.857070273e-03f, +1.633412152e-03f, -2.453170435e-05f,
-    /* 24, 4 */ +6.879416803e-04f, +2.937877889e-03f, -1.086944946e-03f, -8.884797195e-03f, -7.320980005e-03f, +1.025556440e-02f, +2.339424278e-02f, +6.388976156e-03f, -2.762041561e-02f, -3.295607494e-02f, +4.951401864e-03f, +4.050967459e-02f, +2.699354793e-02f, -1.763888677e-02f, -3.629248103e-02f, -1.121198570e-02f, +1.907464002e-02f, +1.944639638e-02f, +1.061806254e-04f, -1.021347789e-02f, -5.121078221e-03f, +1.644827972e-03f, +1.784975276e-03f, +2.348660763e-05f,
-    /* 24, 5 */ +5.776128643e-04f, +2.812656385e-03f, -6.528985547e-04f, -8.502081335e-03f, -7.943354450e-03f, +8.951116293e-03f, +2.331356438e-02f, +8.346521334e-03f, -2.586930694e-02f, -3.407624020e-02f, +1.982016505e-03f, +3.950026382e-02f, +2.929186185e-02f, -1.507216716e-02f, -3.657830513e-02f, -1.346934883e-02f, +1.790927350e-02f, +2.030873394e-02f, +1.286841938e-03f, -1.010739044e-02f, -5.648212144e-03f, +1.402832649e-03f, +1.937883690e-03f, +7.904503123e-05f,
-    /* 24, 6 */ +4.748218959e-04f, +2.678978820e-03f, -2.426308611e-04f, -8.085315763e-03f, -8.490932000e-03f, +7.641095022e-03f, +2.310383199e-02f, +1.021382218e-02f, -2.400641001e-02f, -3.499853994e-02f, -9.786680537e-04f, +3.827896159e-02f, +3.143927100e-02f, -1.240139974e-02f, -3.666644182e-02f, -1.569500220e-02f, +1.661214427e-02f, +2.107957227e-02f, +2.506621864e-03f, -9.931034771e-03f, -6.167872094e-03f, +1.131132707e-03f, +2.090976552e-03f, +1.423449116e-04f,
-    /* 24, 7 */ +3.797950945e-04f, +2.538454547e-03f, +1.421687298e-04f, -7.639006136e-03f, -8.963207645e-03f, +6.333789781e-03f, +2.276982298e-02f, +1.198184460e-02f, -2.204434780e-02f, -3.571990598e-02f, -3.913776625e-03f, +3.685309369e-02f, +3.342299483e-02f, -9.641164594e-03f, -3.655380902e-02f, -1.787517696e-02f, +1.518796320e-02f, +2.175135864e-02f, +3.759049618e-03f, -9.682473374e-03f, -6.675812165e-03f, +8.300312585e-04f, +2.243004675e-03f, +2.135289700e-04f,
-    /* 24, 8 */ +2.926758839e-04f, +2.392634763e-03f, +5.000962484e-04f, -7.167671961e-03f, -9.360208124e-03f, +5.037212205e-03f, +2.231697999e-02f, +1.364235598e-02f, -1.999615271e-02f, -3.623851940e-02f, -6.806693291e-03f, +3.523120326e-02f, +3.523120326e-02f, -6.806693291e-03f, -3.623851940e-02f, -1.999615271e-02f, +1.364235598e-02f, +2.231697999e-02f, +5.037212205e-03f, -9.360208124e-03f, -7.167671961e-03f, +5.000962484e-04f, +2.392634763e-03f, +2.926758839e-04f,
-    /* 24, 9 */ +2.135289700e-04f, +2.243004675e-03f, +8.300312585e-04f, -6.675812165e-03f, -9.682473374e-03f, +3.759049618e-03f, +2.175135864e-02f, +1.518796320e-02f, -1.787517696e-02f, -3.655380902e-02f, -9.641164594e-03f, +3.342299483e-02f, +3.685309369e-02f, -3.913776625e-03f, -3.571990598e-02f, -2.204434780e-02f, +1.198184460e-02f, +2.276982298e-02f, +6.333789781e-03f, -8.963207645e-03f, -7.639006136e-03f, +1.421687298e-04f, +2.538454547e-03f, +3.797950945e-04f,
-    /* 24,10 */ +1.423449116e-04f, +2.090976552e-03f, +1.131132707e-03f, -6.167872094e-03f, -9.931034771e-03f, +2.506621864e-03f, +2.107957227e-02f, +1.661214427e-02f, -1.569500220e-02f, -3.666644182e-02f, -1.240139974e-02f, +3.143927100e-02f, +3.827896159e-02f, -9.786680537e-04f, -3.499853994e-02f, -2.400641001e-02f, +1.021382218e-02f, +2.310383199e-02f, +7.641095022e-03f, -8.490932000e-03f, -8.085315763e-03f, -2.426308611e-04f, +2.678978820e-03f, +4.748218959e-04f,
-    /* 24,11 */ +7.904503123e-05f, +1.937883690e-03f, +1.402832649e-03f, -5.648212144e-03f, -1.010739044e-02f, +1.286841938e-03f, +2.030873394e-02f, +1.790927350e-02f, -1.346934883e-02f, -3.657830513e-02f, -1.507216716e-02f, +2.929186185e-02f, +3.950026382e-02f, +1.982016505e-03f, -3.407624020e-02f, -2.586930694e-02f, +8.346521334e-03f, +2.331356438e-02f, +8.951116293e-03f, -7.943354450e-03f, -8.502081335e-03f, -6.528985547e-04f, +2.812656385e-03f, +5.776128643e-04f,
-    /* 24,12 */ +2.348660763e-05f, +1.784975276e-03f, +1.644827972e-03f, -5.121078221e-03f, -1.021347789e-02f, +1.061806254e-04f, +1.944639638e-02f, +1.907464002e-02f, -1.121198570e-02f, -3.629248103e-02f, -1.763888677e-02f, +2.699354793e-02f, +4.050967459e-02f, +4.951401864e-03f, -3.295607494e-02f, -2.762041561e-02f, +6.388976156e-03f, +2.339424278e-02f, +1.025556440e-02f, -7.320980005e-03f, -8.884797195e-03f, -1.086944946e-03f, +2.937877889e-03f, +6.879416803e-04f,
-    /* 24,13 */ -2.453170435e-05f, +1.633412152e-03f, +1.857070273e-03f, -4.590574200e-03f, -1.025164428e-02f, -1.029364704e-03f, +1.850049032e-02f, +2.010445982e-02f, -8.936640836e-03f, -3.581321303e-02f, -2.008771737e-02f, +2.455797710e-02f, +4.130113344e-02f, +7.912459038e-03f, -3.164235460e-02f, -2.924761047e-02f, +4.350977952e-03f, +2.334180387e-02f, +1.154592266e-02f, -6.624860539e-03f, -9.229007144e-03f, -1.542795645e-03f, +3.052984548e-03f, +8.054954021e-04f,
-    /* 24,14 */ -6.526428163e-05f, +1.484263468e-03f, +2.039754046e-03f, -4.060636553e-03f, -1.022461460e-02f, -2.114297018e-03f, +1.747926153e-02f, +2.099588115e-02f, -6.656913804e-03f, -3.514586546e-02f, -2.240563854e-02f, +2.199957595e-02f, +4.186988491e-02f, +1.084811230e-02f, -3.014061672e-02f, -3.073934924e-02f, +2.243024978e-03f, +2.315294314e-02f, +1.281349999e-02f, -5.856606243e-03f, -9.530340989e-03f, -2.018194158e-03f, +3.156277727e-03f, +9.298712414e-04f,
-    /* 24,15 */ -9.901282259e-05f, +1.338504197e-03f, +2.193303334e-03f, -3.535011248e-03f, -1.013545813e-02f, -3.143642175e-03f, +1.639120730e-02f, +2.174698353e-02f, -4.386190237e-03f, -3.429687591e-02f, -2.458052660e-02f, +1.933345641e-02f, +4.221250979e-02f, +1.374134711e-02f, -2.845760231e-02f, -3.208475603e-02f, +7.626640355e-05f, +2.282515537e-02f, +1.404948670e-02f, -5.018393221e-03f, -9.784551764e-03f, -2.510607281e-03f, +3.246029352e-03f, +1.060573898e-03f,
-    /* 20, 0 */ +2.832126065e-03f, -3.455346407e-03f, -1.050167676e-02f, +5.399047405e-04f, +2.072547687e-02f, +1.261483344e-02f, -2.310421022e-02f, -3.076111900e-02f, +1.034529168e-02f, +3.949755319e-02f, +1.034529168e-02f, -3.076111900e-02f, -2.310421022e-02f, +1.261483344e-02f, +2.072547687e-02f, +5.399047405e-04f, -1.050167676e-02f, -3.455346407e-03f, +2.832126065e-03f, +1.002136091e-03f,
-    /* 20, 1 */ +2.918309836e-03f, -2.848965042e-03f, -1.044663371e-02f, -7.454467031e-04f, +1.993701966e-02f, +1.431336010e-02f, -2.105256806e-02f, -3.196996361e-02f, +7.274030562e-03f, +3.936378623e-02f, +1.336427867e-02f, -2.932648708e-02f, -2.503260290e-02f, +1.078376120e-02f, +2.138841986e-02f, +1.874755806e-03f, -1.047502359e-02f, -4.071193337e-03f, +2.709872705e-03f, +1.184613130e-03f,
-    /* 20, 2 */ +2.970014434e-03f, -2.256846905e-03f, -1.031411254e-02f, -1.973175306e-03f, +1.903277841e-02f, +1.586999913e-02f, -1.889465735e-02f, -3.294695719e-02f, +4.172714360e-03f, +3.896348732e-02f, +1.630904655e-02f, -2.767391419e-02f, -2.682143551e-02f, +8.830742245e-03f, +2.191685631e-02f, +3.250271284e-03f, -1.036300090e-02f, -4.691364292e-03f, +2.550244709e-03f, +1.728121332e-03f,
-    /* 20, 3 */ +2.989084466e-03f, -1.683415968e-03f, -1.010881741e-02f, -3.135916081e-03f, +1.802312126e-02f, +1.727671449e-02f, -1.664798407e-02f, -3.368784795e-02f, +1.063660935e-03f, +3.829965427e-02f, +1.915809828e-02f, -2.581298498e-02f, -2.845520951e-02f, +6.767571398e-03f, +2.230262774e-02f, +4.656958119e-03f, -1.016253578e-02f, -5.310408414e-03f, +2.352251997e-03f, +1.906494808e-03f,
-    /* 20, 4 */ +2.977586348e-03f, -1.132697564e-03f, -9.835877420e-03f, -4.227100403e-03f, +1.691895133e-02f, +1.852681335e-02f, -1.433043179e-02f, -3.419021020e-02f, -2.030888217e-03f, +3.737725626e-02f, +2.189055571e-02f, -2.375496340e-02f, -2.991937541e-02f, +4.607167163e-03f, +2.253850054e-02f, +6.084727180e-03f, -9.871207756e-03f, -5.922604667e-03f, +2.115247068e-03f, +2.079939639e-03f,
-    /* 20, 5 */ +2.937775120e-03f, -6.082983663e-04f, -9.500783787e-03f, -5.240985904e-03f, +1.573160178e-02f, +1.961497125e-02f, -1.196011335e-02f, -3.445344345e-02f, -5.088941581e-03f, +3.620319350e-02f, +2.448632622e-02f, -2.151271924e-02f, -3.120046374e-02f, +2.363488482e-03f, +2.261825107e-02f, +7.522962281e-03f, -9.487296369e-03f, -6.522005316e-03f, +1.838950241e-03f, +2.245949018e-03f,
-    /* 20, 6 */ +2.872060854e-03f, -1.133913219e-04f, -9.109325922e-03f, -6.172678101e-03f, +1.447272980e-02f, +2.053724533e-02f, -9.555222824e-03f, -3.447875653e-02f, -8.088928223e-03f, +3.478624106e-02f, +2.692626358e-02f, -1.910064083e-02f, -3.228620876e-02f, +5.144107936e-05f, +2.253674404e-02f, +8.960596019e-03f, -9.009823935e-03f, -7.102483479e-03f, +1.523472156e-03f, +2.401928729e-03f,
-    /* 20, 7 */ +2.782975009e-03f, +3.492945151e-04f, -8.667527067e-03f, -7.018143782e-03f, +1.315421060e-02f, +2.129107545e-02f, -7.133889173e-03f, -3.426913715e-02f, -1.100986395e-02f, +3.313697764e-02f, +2.919232167e-02f, -1.653453452e-02f, -3.316566379e-02f, -2.313225982e-03f, +2.229000326e-02f, +1.038619190e-02f, -8.438592747e-03f, -7.657784411e-03f, +1.169333173e-03f, +2.545222121e-03f,
-    /* 20, 8 */ +2.673137115e-03f, +7.774793244e-04f, -8.181580147e-03f, -7.774216267e-03f, +1.178803215e-02f, +2.187527386e-02f, -4.714032773e-03f, -3.382930709e-02f, -1.383151166e-02f, +3.126769968e-02f, +3.126769968e-02f, -1.383151166e-02f, -3.382930709e-02f, -4.714032773e-03f, +2.187527386e-02f, +1.178803215e-02f, -7.774216267e-03f, -8.181580147e-03f, +7.774793244e-04f, +2.673137115e-03f,
-    /* 20, 9 */ +2.545222121e-03f, +1.169333173e-03f, -7.657784411e-03f, -8.438592747e-03f, +1.038619190e-02f, +2.229000326e-02f, -2.313225982e-03f, -3.316566379e-02f, -1.653453452e-02f, +2.919232167e-02f, +3.313697764e-02f, -1.100986395e-02f, -3.426913715e-02f, -7.133889173e-03f, +2.129107545e-02f, +1.315421060e-02f, -7.018143782e-03f, -8.667527067e-03f, +3.492945151e-04f, +2.782975009e-03f,
-    /* 20,10 */ +2.401928729e-03f, +1.523472156e-03f, -7.102483479e-03f, -9.009823935e-03f, +8.960596019e-03f, +2.253674404e-02f, +5.144107936e-05f, -3.228620876e-02f, -1.910064083e-02f, +2.692626358e-02f, +3.478624106e-02f, -8.088928223e-03f, -3.447875653e-02f, -9.555222824e-03f, +2.053724533e-02f, +1.447272980e-02f, -6.172678101e-03f, -9.109325922e-03f, -1.133913219e-04f, +2.872060854e-03f,
-    /* 20,11 */ +2.245949018e-03f, +1.838950241e-03f, -6.522005316e-03f, -9.487296369e-03f, +7.522962281e-03f, +2.261825107e-02f, +2.363488482e-03f, -3.120046374e-02f, -2.151271924e-02f, +2.448632622e-02f, +3.620319350e-02f, -5.088941581e-03f, -3.445344345e-02f, -1.196011335e-02f, +1.961497125e-02f, +1.573160178e-02f, -5.240985904e-03f, -9.500783787e-03f, -6.082983663e-04f, +2.937775120e-03f,
-    /* 20,12 */ +2.079939639e-03f, +2.115247068e-03f, -5.922604667e-03f, -9.871207756e-03f, +6.084727180e-03f, +2.253850054e-02f, +4.607167163e-03f, -2.991937541e-02f, -2.375496340e-02f, +2.189055571e-02f, +3.737725626e-02f, -2.030888217e-03f, -3.419021020e-02f, -1.433043179e-02f, +1.852681335e-02f, +1.691895133e-02f, -4.227100403e-03f, -9.835877420e-03f, -1.132697564e-03f, +2.977586348e-03f,
-    /* 20,13 */ +1.906494808e-03f, +2.352251997e-03f, -5.310408414e-03f, -1.016253578e-02f, +4.656958119e-03f, +2.230262774e-02f, +6.767571398e-03f, -2.845520951e-02f, -2.581298498e-02f, +1.915809828e-02f, +3.829965427e-02f, +1.063660935e-03f, -3.368784795e-02f, -1.664798407e-02f, +1.727671449e-02f, +1.802312126e-02f, -3.135916081e-03f, -1.010881741e-02f, -1.683415968e-03f, +2.989084466e-03f,
-    /* 20,14 */ +1.728121332e-03f, +2.550244709e-03f, -4.691364292e-03f, -1.036300090e-02f, +3.250271284e-03f, +2.191685631e-02f, +8.830742245e-03f, -2.682143551e-02f, -2.767391419e-02f, +1.630904655e-02f, +3.896348732e-02f, +4.172714360e-03f, -3.294695719e-02f, -1.889465735e-02f, +1.586999913e-02f, +1.903277841e-02f, -1.973175306e-03f, -1.031411254e-02f, -2.256846905e-03f, +2.970014434e-03f,
-    /* 20,15 */ +1.184613130e-03f, +2.709872705e-03f, -4.071193337e-03f, -1.047502359e-02f, +1.874755806e-03f, +2.138841986e-02f, +1.078376120e-02f, -2.503260290e-02f, -2.932648708e-02f, +1.336427867e-02f, +3.936378623e-02f, +7.274030562e-03f, -3.196996361e-02f, -2.105256806e-02f, +1.431336010e-02f, +1.993701966e-02f, -7.454467031e-04f, -1.044663371e-02f, -2.848965042e-03f, +2.918309836e-03f,
-    /* 20, 0 */ +1.702864838e-03f, +2.314577966e-03f, -6.534433696e-03f, -8.774562126e-03f, +1.199271213e-02f, +2.083400312e-02f, -1.263546899e-02f, -3.379691899e-02f, +5.498355442e-03f, +3.949755319e-02f, +5.498355442e-03f, -3.379691899e-02f, -1.263546899e-02f, +2.083400312e-02f, +1.199271213e-02f, -8.774562126e-03f, -6.534433696e-03f, +2.314577966e-03f, +1.702864838e-03f, +0.000000000e+00f,
-    /* 20, 1 */ +1.499435496e-03f, +2.547675666e-03f, -5.868098774e-03f, -9.353385898e-03f, +1.044920601e-02f, +2.160032962e-02f, -9.997584470e-03f, -3.429852636e-02f, +2.083565903e-03f, +3.933622696e-02f, +8.892197588e-03f, -3.300722623e-02f, -1.522519578e-02f, +1.986341365e-02f, +1.349096787e-02f, -8.082206357e-03f, -7.177938171e-03f, +2.033576095e-03f, +1.903844954e-03f, +0.000000000e+00f,
-    /* 20, 2 */ +8.979094201e-04f, +2.733567376e-03f, -5.187117330e-03f, -9.818374279e-03f, +8.876306372e-03f, +2.216139438e-02f, -7.335624654e-03f, -3.451169090e-02f, -1.322648265e-03f, +3.885370480e-02f, +1.223556951e-02f, -3.193245877e-02f, -1.774265256e-02f, +1.869155385e-02f, +1.492800767e-02f, -7.277832099e-03f, -7.790241855e-03f, +1.704529263e-03f, +2.099160368e-03f, -3.513221827e-04f,
-    /* 20, 3 */ +7.046452899e-04f, +2.873469547e-03f, -4.499404245e-03f, -1.017038969e-02f, +7.289604703e-03f, +2.251815219e-02f, -4.673411391e-03f, -3.443867914e-02f, -4.691042688e-03f, +3.805434209e-02f, +1.549922824e-02f, -3.057828381e-02f, -2.016393226e-02f, +1.732343066e-02f, +1.628791973e-02f, -6.364195274e-03f, -8.362876507e-03f, +1.327887989e-03f, +2.285430476e-03f, -3.288882594e-04f,
-    /* 20, 4 */ +5.275063595e-04f, +2.969073324e-03f, -3.812529364e-03f, -1.041140495e-02f, +5.704278009e-03f, +2.267345221e-02f, -2.034281900e-03f, -3.408432658e-02f, -7.992925296e-03f, +3.694535030e-02f, +1.865448932e-02f, -2.895300188e-02f, -2.246557005e-02f, +1.576606531e-02f, +1.755501285e-02f, -5.345313722e-03f, -8.887369558e-03f, +9.047221591e-04f, +2.459146683e-03f, -2.941732022e-04f,
-    /* 20, 5 */ +3.670219514e-04f, +3.022497230e-03f, -3.133648777e-03f, -1.054443774e-02f, +4.134948499e-03f, +2.263196075e-02f, +5.591264205e-04f, -3.345595810e-02f, -1.120042307e-02f, +3.553672638e-02f, +2.167350137e-02f, -2.706749712e-02f, -2.462477986e-02f, +1.402847243e-02f, +1.871398575e-02f, -4.226473266e-03f, -9.355341791e-03f, +4.367425848e-04f, +2.616713456e-03f, -2.461206998e-04f,
-    /* 20, 6 */ +2.234691091e-04f, +3.036236900e-03f, -2.469443903e-03f, -1.057347601e-02f, +2.595553432e-03f, +2.240006745e-02f, +3.085080219e-03f, -3.256328476e-02f, -1.428673893e-02f, +3.384115481e-02f, +2.452951370e-02f, -2.493516141e-02f, -2.661968788e-02f, +1.212161795e-02f, +1.975009719e-02f, -3.014219819e-03f, -9.758608118e-03f, -7.368451392e-05f, +2.754492916e-03f, -1.837671888e-04f,
-    /* 20, 7 */ +9.688872179e-05f, +3.013112613e-03f, -1.826068782e-03f, -1.050339555e-02f, +1.099226216e-03f, +2.198577609e-02f, +5.522941542e-03f, -3.141827834e-02f, -1.722639627e-02f, +3.187388359e-02f, +2.719713425e-02f, -2.257179274e-02f, -2.842956063e-02f, +1.005835593e-02f, +2.064933490e-02f, -1.716337171e-03f, -1.008928035e-02f, -6.235305950e-04f, +2.868852533e-03f, -1.062635081e-04f,
-    /* 20, 8 */ -1.289664191e-05f, +2.956215411e-03f, -1.209105881e-03f, -1.033987080e-02f, -3.418102460e-04f, +2.139858161e-02f, +7.853344535e-03f, -3.003502508e-02f, -1.999546871e-02f, +2.965257519e-02f, +2.965257519e-02f, -1.999546871e-02f, -3.003502508e-02f, +7.853344535e-03f, +2.139858161e-02f, -3.418102460e-04f, -1.033987080e-02f, -1.209105881e-03f, +2.956215411e-03f, -1.289664191e-05f,
-    /* 20, 9 */ -1.062635081e-04f, +2.868852533e-03f, -6.235305950e-04f, -1.008928035e-02f, -1.716337171e-03f, +2.064933490e-02f, +1.005835593e-02f, -2.842956063e-02f, -2.257179274e-02f, +2.719713425e-02f, +3.187388359e-02f, -1.722639627e-02f, -3.141827834e-02f, +5.522941542e-03f, +2.198577609e-02f, +1.099226216e-03f, -1.050339555e-02f, -1.826068782e-03f, +3.013112613e-03f, +9.688872179e-05f,
-    /* 20,10 */ -1.837671888e-04f, +2.754492916e-03f, -7.368451392e-05f, -9.758608118e-03f, -3.014219819e-03f, +1.975009719e-02f, +1.212161795e-02f, -2.661968788e-02f, -2.493516141e-02f, +2.452951370e-02f, +3.384115481e-02f, -1.428673893e-02f, -3.256328476e-02f, +3.085080219e-03f, +2.240006745e-02f, +2.595553432e-03f, -1.057347601e-02f, -2.469443903e-03f, +3.036236900e-03f, +2.234691091e-04f,
-    /* 20,11 */ -2.461206998e-04f, +2.616713456e-03f, +4.367425848e-04f, -9.355341791e-03f, -4.226473266e-03f, +1.871398575e-02f, +1.402847243e-02f, -2.462477986e-02f, -2.706749712e-02f, +2.167350137e-02f, +3.553672638e-02f, -1.120042307e-02f, -3.345595810e-02f, +5.591264205e-04f, +2.263196075e-02f, +4.134948499e-03f, -1.054443774e-02f, -3.133648777e-03f, +3.022497230e-03f, +3.670219514e-04f,
-    /* 20,12 */ -2.941732022e-04f, +2.459146683e-03f, +9.047221591e-04f, -8.887369558e-03f, -5.345313722e-03f, +1.755501285e-02f, +1.576606531e-02f, -2.246557005e-02f, -2.895300188e-02f, +1.865448932e-02f, +3.694535030e-02f, -7.992925296e-03f, -3.408432658e-02f, -2.034281900e-03f, +2.267345221e-02f, +5.704278009e-03f, -1.041140495e-02f, -3.812529364e-03f, +2.969073324e-03f, +5.275063595e-04f,
-    /* 20,13 */ -3.288882594e-04f, +2.285430476e-03f, +1.327887989e-03f, -8.362876507e-03f, -6.364195274e-03f, +1.628791973e-02f, +1.732343066e-02f, -2.016393226e-02f, -3.057828381e-02f, +1.549922824e-02f, +3.805434209e-02f, -4.691042688e-03f, -3.443867914e-02f, -4.673411391e-03f, +2.251815219e-02f, +7.289604703e-03f, -1.017038969e-02f, -4.499404245e-03f, +2.873469547e-03f, +7.046452899e-04f,
-    /* 20,14 */ -3.513221827e-04f, +2.099160368e-03f, +1.704529263e-03f, -7.790241855e-03f, -7.277832099e-03f, +1.492800767e-02f, +1.869155385e-02f, -1.774265256e-02f, -3.193245877e-02f, +1.223556951e-02f, +3.885370480e-02f, -1.322648265e-03f, -3.451169090e-02f, -7.335624654e-03f, +2.216139438e-02f, +8.876306372e-03f, -9.818374279e-03f, -5.187117330e-03f, +2.733567376e-03f, +8.979094201e-04f,
-    /* 20,15 */ +0.000000000e+00f, +1.903844954e-03f, +2.033576095e-03f, -7.177938171e-03f, -8.082206357e-03f, +1.349096787e-02f, +1.986341365e-02f, -1.522519578e-02f, -3.300722623e-02f, +8.892197588e-03f, +3.933622696e-02f, +2.083565903e-03f, -3.429852636e-02f, -9.997584470e-03f, +2.160032962e-02f, +1.044920601e-02f, -9.353385898e-03f, -5.868098774e-03f, +2.547675666e-03f, +1.499435496e-03f,
-    /* 20, 0 */ -3.735125865e-04f, +2.550984103e-03f, -2.725752467e-05f, -1.024966855e-02f, +8.379667777e-04f, +2.252874535e-02f, -1.249359695e-03f, -3.448318510e-02f, +6.071698875e-04f, +3.949755319e-02f, +6.071698875e-04f, -3.448318510e-02f, -1.249359695e-03f, +2.252874535e-02f, +8.379667777e-04f, -1.024966855e-02f, -2.725752467e-05f, +2.565652055e-03f, -3.735125865e-04f, +0.000000000e+00f,
-    /* 20, 1 */ -3.929324583e-04f, +2.236335973e-03f, +5.288730096e-04f, -9.916240655e-03f, -7.235223044e-04f, +2.212021870e-02f, +1.557339330e-03f, -3.412515163e-02f, -3.088657053e-03f, +3.930609269e-02f, +4.328121901e-03f, -3.450613681e-02f, -4.117983282e-03f, +2.271744325e-02f, +2.467540325e-03f, -1.048404473e-02f, -6.307983207e-04f, +2.729031078e-03f, -3.387491377e-04f, +0.000000000e+00f,
-    /* 20, 2 */ +0.000000000e+00f, +1.931175707e-03f, +1.033703668e-03f, -9.493276252e-03f, -2.202626937e-03f, +2.150371837e-02f, +4.274418757e-03f, -3.344119198e-02f, -6.721842627e-03f, +3.873376177e-02f, +8.036125742e-03f, -3.418837690e-02f, -7.019484999e-03f, +2.267661502e-02f, +4.149462009e-03f, -1.061062992e-02f, -1.276919763e-03f, +2.866023275e-03f, -2.870815261e-04f, +0.000000000e+00f,
-    /* 20, 3 */ +0.000000000e+00f, +1.638662038e-03f, +1.484286050e-03f, -8.990907936e-03f, -3.586602863e-03f, +2.069305390e-02f, +6.875821908e-03f, -3.244383298e-02f, -1.025584288e-02f, +3.778668841e-02f, +1.169297592e-02f, -3.352791602e-02f, -9.923776326e-03f, +2.239890298e-02f, +5.866701604e-03f, -1.062161571e-02f, -1.959867511e-03f, +2.971909246e-03f, -2.170808154e-04f, +0.000000000e+00f,
-    /* 20, 4 */ +0.000000000e+00f, +1.361489293e-03f, +1.878600735e-03f, -8.419725702e-03f, -4.864357078e-03f, +1.970376789e-02f, +9.337391966e-03f, -3.114878076e-02f, -1.365548733e-02f, +3.647500669e-02f, +1.526076366e-02f, -3.252647846e-02f, -1.280005487e-02f, +2.187944695e-02f, +7.601099328e-03f, -1.051027343e-02f, -2.672992279e-03f, +3.042103091e-03f, -1.274866066e-04f, +0.000000000e+00f,
-    /* 20, 5 */ +0.000000000e+00f, +1.101888322e-03f, +2.215532402e-03f, -7.790617836e-03f, -6.026519023e-03f, +1.855289977e-02f, +1.163710530e-02f, -2.957469445e-02f, -1.688736106e-02f, +3.481273909e-02f, +1.870230489e-02f, -3.118953221e-02f, -1.561714772e-02f, +2.111601531e-02f, +9.333550613e-03f, -1.027109466e-02f, -3.408794343e-03f, +3.072235528e-03f, -1.724424543e-05f, +0.000000000e+00f,
-    /* 20, 6 */ +0.000000000e+00f, +8.616336525e-04f, +2.494833248e-03f, -7.114614810e-03f, -7.065487327e-03f, +1.725873795e-02f, +1.375527431e-02f, -2.774292839e-02f, -1.992016339e-02f, +3.281763375e-02f, +2.198156213e-02f, -2.952627516e-02f, -1.834386597e-02f, +2.010910684e-02f, +1.104420948e-02f, -9.899921148e-03f, -4.158982805e-03f, +3.058238443e-03f, +1.144582079e-04f, +0.000000000e+00f,
-    /* 20, 7 */ +0.000000000e+00f, +6.420563626e-04f, +2.717075783e-03f, -6.402738187e-03f, -7.975452307e-03f, +1.584056403e-02f, +1.567471786e-02f, -2.567724669e-02f, -2.272503888e-02f, +3.051095862e-02f, +2.506405514e-02f, -2.754957697e-02f, -2.094936609e-02f, +1.886202143e-02f, +1.271270843e-02f, -9.394061811e-03f, -4.914549404e-03f, +2.996429606e-03f, +2.681538305e-04f, +0.000000000e+00f,
-    /* 20, 8 */ +0.000000000e+00f, +4.440621234e-04f, +2.883596201e-03f, -5.665856445e-03f, -8.752394750e-03f, +1.431839236e-02f, +1.738089791e-02f, -2.340351394e-02f, -2.527587699e-02f, +2.791725525e-02f, +2.791725525e-02f, -2.527587699e-02f, -2.340351394e-02f, +1.738089791e-02f, +1.431839236e-02f, -8.752394750e-03f, -5.665856445e-03f, +2.883596201e-03f, +4.440621234e-04f, +0.000000000e+00f,
-    /* 20, 9 */ +0.000000000e+00f, +2.681538305e-04f, +2.996429606e-03f, -4.914549404e-03f, -9.394061811e-03f, +1.271270843e-02f, +1.886202143e-02f, -2.094936609e-02f, -2.754957697e-02f, +2.506405514e-02f, +3.051095862e-02f, -2.272503888e-02f, -2.567724669e-02f, +1.567471786e-02f, +1.584056403e-02f, -7.975452307e-03f, -6.402738187e-03f, +2.717075783e-03f, +6.420563626e-04f, +0.000000000e+00f,
-    /* 20,10 */ +0.000000000e+00f, +1.144582079e-04f, +3.058238443e-03f, -4.158982805e-03f, -9.899921148e-03f, +1.104420948e-02f, +2.010910684e-02f, -1.834386597e-02f, -2.952627516e-02f, +2.198156213e-02f, +3.281763375e-02f, -1.992016339e-02f, -2.774292839e-02f, +1.375527431e-02f, +1.725873795e-02f, -7.065487327e-03f, -7.114614810e-03f, +2.494833248e-03f, +8.616336525e-04f, +0.000000000e+00f,
-    /* 20,11 */ +0.000000000e+00f, -1.724424543e-05f, +3.072235528e-03f, -3.408794343e-03f, -1.027109466e-02f, +9.333550613e-03f, +2.111601531e-02f, -1.561714772e-02f, -3.118953221e-02f, +1.870230489e-02f, +3.481273909e-02f, -1.688736106e-02f, -2.957469445e-02f, +1.163710530e-02f, +1.855289977e-02f, -6.026519023e-03f, -7.790617836e-03f, +2.215532402e-03f, +1.101888322e-03f, +0.000000000e+00f,
-    /* 20,12 */ +0.000000000e+00f, -1.274866066e-04f, +3.042103091e-03f, -2.672992279e-03f, -1.051027343e-02f, +7.601099328e-03f, +2.187944695e-02f, -1.280005487e-02f, -3.252647846e-02f, +1.526076366e-02f, +3.647500669e-02f, -1.365548733e-02f, -3.114878076e-02f, +9.337391966e-03f, +1.970376789e-02f, -4.864357078e-03f, -8.419725702e-03f, +1.878600735e-03f, +1.361489293e-03f, +0.000000000e+00f,
-    /* 20,13 */ +0.000000000e+00f, -2.170808154e-04f, +2.971909246e-03f, -1.959867511e-03f, -1.062161571e-02f, +5.866701604e-03f, +2.239890298e-02f, -9.923776326e-03f, -3.352791602e-02f, +1.169297592e-02f, +3.778668841e-02f, -1.025584288e-02f, -3.244383298e-02f, +6.875821908e-03f, +2.069305390e-02f, -3.586602863e-03f, -8.990907936e-03f, +1.484286050e-03f, +1.638662038e-03f, +0.000000000e+00f,
-    /* 20,14 */ +0.000000000e+00f, -2.870815261e-04f, +2.866023275e-03f, -1.276919763e-03f, -1.061062992e-02f, +4.149462009e-03f, +2.267661502e-02f, -7.019484999e-03f, -3.418837690e-02f, +8.036125742e-03f, +3.873376177e-02f, -6.721842627e-03f, -3.344119198e-02f, +4.274418757e-03f, +2.150371837e-02f, -2.202626937e-03f, -9.493276252e-03f, +1.033703668e-03f, +1.931175707e-03f, +0.000000000e+00f,
-    /* 20,15 */ +0.000000000e+00f, -3.387491377e-04f, +2.729031078e-03f, -6.307983207e-04f, -1.048404473e-02f, +2.467540325e-03f, +2.271744325e-02f, -4.117983282e-03f, -3.450613681e-02f, +4.328121901e-03f, +3.930609269e-02f, -3.088657053e-03f, -3.412515163e-02f, +1.557339330e-03f, +2.212021870e-02f, -7.235223044e-04f, -9.916240655e-03f, +5.288730096e-04f, +2.236335973e-03f, -3.929324583e-04f,
-    /* 16, 0 */ +3.044394378e-03f, -5.755865016e-03f, -7.644875237e-03f, +1.825808857e-02f, +9.222448502e-03f, -3.286388427e-02f, -4.241838036e-03f, +3.949755319e-02f, -4.241838036e-03f, -3.286388427e-02f, +9.222448502e-03f, +1.825808857e-02f, -7.644875237e-03f, -5.755865016e-03f, +3.044394378e-03f, -1.466795211e-05f,
-    /* 16, 1 */ +3.096598285e-03f, -4.938670705e-03f, -8.543525001e-03f, +1.681174815e-02f, +1.171692718e-02f, -3.156650717e-02f, -8.140229219e-03f, +3.927338559e-02f, -2.566011090e-04f, -3.380519836e-02f, +6.539747546e-03f, +1.954192550e-02f, -6.591652894e-03f, -6.554797296e-03f, +2.932700428e-03f, +1.424716020e-04f,
-    /* 16, 2 */ +3.093580763e-03f, -4.116215273e-03f, -9.283856280e-03f, +1.522768985e-02f, +1.399813452e-02f, -2.993548791e-02f, -1.190603152e-02f, +3.860369285e-02f, +3.768233493e-03f, -3.437220120e-02f, +3.697060454e-03f, +2.063975168e-02f, -5.390052618e-03f, -7.321916780e-03f, +2.757987679e-03f, +3.278051009e-04f,
-    /* 16, 3 */ +3.040228116e-03f, -3.300778044e-03f, -9.864516741e-03f, +1.353158972e-02f, +1.604446323e-02f, -2.799705310e-02f, -1.549559239e-02f, +3.749686691e-02f, +7.784523662e-03f, -3.455113173e-02f, +7.255039591e-04f, +2.152972014e-02f, -4.048737024e-03f, -8.043312786e-03f, +2.517583336e-03f, +5.415628140e-04f,
-    /* 16, 4 */ +2.941918573e-03f, -2.503765206e-03f, -1.028645874e-02f, +1.174962597e-02f, +1.783794825e-02f, -2.578082191e-02f, -1.886790220e-02f, +3.596676747e-02f, +1.174386090e-02f, -3.433297304e-02f, -2.341279491e-03f, +2.219201396e-02f, -2.578818314e-03f, -8.704920467e-03f, +2.209778110e-03f, +1.246855370e-03f,
-    /* 16, 5 */ +2.804395319e-03f, -1.735580001e-03f, -1.055281940e-02f, +9.908096520e-03f, +1.936441115e-02f, -2.331935318e-02f, -2.198510572e-02f, +3.403253365e-02f, +1.559820593e-02f, -3.371364718e-02f, -5.467520855e-03f, +2.260919785e-02f, -9.938011251e-04f, -9.292739628e-03f, +1.833922789e-03f, +1.492594630e-03f,
-    /* 16, 6 */ +2.633640678e-03f, -1.005515791e-03f, -1.066877263e-02f, +8.033047542e-03f, +2.061354789e-02f, -2.064765983e-02f, -2.481296600e-02f, +3.171832409e-02f, +1.930052332e-02f, -3.269414425e-02f, -8.615762914e-03f, +2.276654580e-02f, +6.905139302e-04f, -9.793063512e-03f, +1.390511455e-03f, +1.739628231e-03f,
-    /* 16, 7 */ +2.435753603e-03f, -3.216727033e-04f, -1.064135670e-02f, +6.149918447e-03f, +2.157895980e-02f, -1.780269814e-02f, -2.732127429e-02f, +2.905298940e-02f, +2.280540611e-02f, -3.128058296e-02f, -1.174733238e-02f, +2.265233903e-02f, +2.456165958e-03f, -1.019271416e-02f, +8.812491435e-04f, +1.982865330e-03f,
-    /* 16, 8 */ +2.216832517e-03f, +3.091018830e-04f, -1.047928070e-02f, +4.283208005e-03f, +2.225812888e-02f, -1.482283947e-02f, -2.948420097e-02f, +2.606968157e-02f, +2.606968157e-02f, -2.948420097e-02f, -1.482283947e-02f, +2.225812888e-02f, +4.283208005e-03f, -1.047928070e-02f, +3.091018830e-04f, +2.216832517e-03f,
-    /* 16, 9 */ +1.982865330e-03f, +8.812491435e-04f, -1.019271416e-02f, +2.456165958e-03f, +2.265233903e-02f, -1.174733238e-02f, -3.128058296e-02f, +2.280540611e-02f, +2.905298940e-02f, -2.732127429e-02f, -1.780269814e-02f, +2.157895980e-02f, +6.149918447e-03f, -1.064135670e-02f, -3.216727033e-04f, +2.435753603e-03f,
-    /* 16,10 */ +1.739628231e-03f, +1.390511455e-03f, -9.793063512e-03f, +6.905139302e-04f, +2.276654580e-02f, -8.615762914e-03f, -3.269414425e-02f, +1.930052332e-02f, +3.171832409e-02f, -2.481296600e-02f, -2.064765983e-02f, +2.061354789e-02f, +8.033047542e-03f, -1.066877263e-02f, -1.005515791e-03f, +2.633640678e-03f,
-    /* 16,11 */ +1.492594630e-03f, +1.833922789e-03f, -9.292739628e-03f, -9.938011251e-04f, +2.260919785e-02f, -5.467520855e-03f, -3.371364718e-02f, +1.559820593e-02f, +3.403253365e-02f, -2.198510572e-02f, -2.331935318e-02f, +1.936441115e-02f, +9.908096520e-03f, -1.055281940e-02f, -1.735580001e-03f, +2.804395319e-03f,
-    /* 16,12 */ +1.246855370e-03f, +2.209778110e-03f, -8.704920467e-03f, -2.578818314e-03f, +2.219201396e-02f, -2.341279491e-03f, -3.433297304e-02f, +1.174386090e-02f, +3.596676747e-02f, -1.886790220e-02f, -2.578082191e-02f, +1.783794825e-02f, +1.174962597e-02f, -1.028645874e-02f, -2.503765206e-03f, +2.941918573e-03f,
-    /* 16,13 */ +5.415628140e-04f, +2.517583336e-03f, -8.043312786e-03f, -4.048737024e-03f, +2.152972014e-02f, +7.255039591e-04f, -3.455113173e-02f, +7.784523662e-03f, +3.749686691e-02f, -1.549559239e-02f, -2.799705310e-02f, +1.604446323e-02f, +1.353158972e-02f, -9.864516741e-03f, -3.300778044e-03f, +3.040228116e-03f,
-    /* 16,14 */ +3.278051009e-04f, +2.757987679e-03f, -7.321916780e-03f, -5.390052618e-03f, +2.063975168e-02f, +3.697060454e-03f, -3.437220120e-02f, +3.768233493e-03f, +3.860369285e-02f, -1.190603152e-02f, -2.993548791e-02f, +1.399813452e-02f, +1.522768985e-02f, -9.283856280e-03f, -4.116215273e-03f, +3.093580763e-03f,
-    /* 16,15 */ +1.424716020e-04f, +2.932700428e-03f, -6.554797296e-03f, -6.591652894e-03f, +1.954192550e-02f, +6.539747546e-03f, -3.380519836e-02f, -2.566011090e-04f, +3.927338559e-02f, -8.140229219e-03f, -3.156650717e-02f, +1.171692718e-02f, +1.681174815e-02f, -8.543525001e-03f, -4.938670705e-03f, +3.096598285e-03f,
-    /* 16, 0 */ +2.106112688e-03f, -1.136549770e-04f, -1.070669430e-02f, +1.017472059e-02f, +1.725397418e-02f, -2.914959442e-02f, -8.963852042e-03f, +3.949755319e-02f, -8.963852042e-03f, -2.914959442e-02f, +1.725397418e-02f, +1.017472059e-02f, -1.070669430e-02f, -1.136549770e-04f, +2.106112688e-03f, +0.000000000e+00f,
-    /* 16, 1 */ +1.845338280e-03f, +5.473343456e-04f, -1.065891816e-02f, +8.155641030e-03f, +1.899089579e-02f, -2.691951328e-02f, -1.297236480e-02f, +3.923810803e-02f, -4.790894575e-03f, -3.103786392e-02f, +1.521305380e-02f, +1.215062389e-02f, -1.058864907e-02f, -8.385121370e-04f, +2.352913572e-03f, +0.000000000e+00f,
-    /* 16, 2 */ +1.577651889e-03f, +1.138027416e-03f, -1.045641117e-02f, +6.125232216e-03f, +2.040939526e-02f, -2.438627738e-02f, -1.676283724e-02f, +3.846353557e-02f, -5.100475811e-04f, -3.254996068e-02f, +1.288771825e-02f, +1.405076114e-02f, -1.029592106e-02f, -1.619065127e-03f, +2.578329862e-03f, +0.000000000e+00f,
-    /* 16, 3 */ +1.309641631e-03f, +1.653747621e-03f, -1.011218665e-02f, +4.114112388e-03f, +2.150028131e-02f, -2.159216402e-02f, -2.028541539e-02f, +3.718506562e-02f, +3.820010384e-03f, -3.365643786e-02f, +1.030255138e-02f, +1.584231759e-02f, -9.822158049e-03f, -2.445442331e-03f, +2.774741598e-03f, +0.000000000e+00f,
-    /* 16, 4 */ +5.462770218e-04f, +2.091544281e-03f, -9.640854940e-03f, +2.151223968e-03f, +2.225957955e-02f, -1.858235038e-02f, -2.349470263e-02f, +3.542121816e-02f, +8.139354376e-03f, -3.433331277e-02f, +7.486889709e-03f, +1.749279467e-02f, -9.163764446e-03f, -3.306153325e-03f, +2.934475195e-03f, -4.634120047e-04f,
-    /* 16, 5 */ +3.039101756e-04f, +2.450135010e-03f, -9.058284956e-03f, +2.634319572e-04f, +2.268843286e-02f, -1.540416082e-02f, -2.635039795e-02f, +3.319751225e-02f, +1.238771678e-02f, -3.456253827e-02f, +4.474489227e-03f, +1.897056596e-02f, -8.320109905e-03f, -4.188206830e-03f, +3.049970761e-03f, -4.400286560e-04f,
-    /* 16, 6 */ +9.722433303e-05f, +2.729819110e-03f, -8.381259809e-03f, -1.524826854e-03f, +2.279292110e-02f, -1.210629477e-02f, -2.881784707e-02f, +3.054606534e-02f, +1.650540309e-02f, -3.433238619e-02f, +1.303110212e-03f, +2.024543829e-02f, -7.293693549e-03f, -5.077265419e-03f, +3.113958519e-03f, -3.921992729e-04f,
-    /* 16, 7 */ -7.427658644e-05f, +2.932365266e-03f, -7.627133157e-03f, -3.191839567e-03f, +2.258380561e-02f, -8.738048497e-03f, -3.086849848e-02f, +2.750508980e-02f, +2.043420490e-02f, -3.363773532e-02f, -1.985974837e-03f, +2.128920837e-02f, -6.090258802e-03f, -5.957835775e-03f, +3.119640969e-03f, -3.169896142e-04f,
-    /* 16, 8 */ -2.117631665e-04f, +3.060877176e-03f, -6.813492559e-03f, -4.718854594e-03f, +2.207620481e-02f, -5.348543574e-03f, -3.248025769e-02f, +2.411829496e-02f, +2.411829496e-02f, -3.248025769e-02f, -5.348543574e-03f, +2.207620481e-02f, -4.718854594e-03f, -6.813492559e-03f, +3.060877176e-03f, -2.117631665e-04f,
-    /* 16, 9 */ -3.169896142e-04f, +3.119640969e-03f, -5.957835775e-03f, -6.090258802e-03f, +2.128920837e-02f, -1.985974837e-03f, -3.363773532e-02f, +2.043420490e-02f, +2.750508980e-02f, -3.086849848e-02f, -8.738048497e-03f, +2.258380561e-02f, -3.191839567e-03f, -7.627133157e-03f, +2.932365266e-03f, -7.427658644e-05f,
-    /* 16,10 */ -3.921992729e-04f, +3.113958519e-03f, -5.077265419e-03f, -7.293693549e-03f, +2.024543829e-02f, +1.303110212e-03f, -3.433238619e-02f, +1.650540309e-02f, +3.054606534e-02f, -2.881784707e-02f, -1.210629477e-02f, +2.279292110e-02f, -1.524826854e-03f, -8.381259809e-03f, +2.729819110e-03f, +9.722433303e-05f,
-    /* 16,11 */ -4.400286560e-04f, +3.049970761e-03f, -4.188206830e-03f, -8.320109905e-03f, +1.897056596e-02f, +4.474489227e-03f, -3.456253827e-02f, +1.238771678e-02f, +3.319751225e-02f, -2.635039795e-02f, -1.540416082e-02f, +2.268843286e-02f, +2.634319572e-04f, -9.058284956e-03f, +2.450135010e-03f, +3.039101756e-04f,
-    /* 16,12 */ -4.634120047e-04f, +2.934475195e-03f, -3.306153325e-03f, -9.163764446e-03f, +1.749279467e-02f, +7.486889709e-03f, -3.433331277e-02f, +8.139354376e-03f, +3.542121816e-02f, -2.349470263e-02f, -1.858235038e-02f, +2.225957955e-02f, +2.151223968e-03f, -9.640854940e-03f, +2.091544281e-03f, +5.462770218e-04f,
-    /* 16,13 */ +0.000000000e+00f, +2.774741598e-03f, -2.445442331e-03f, -9.822158049e-03f, +1.584231759e-02f, +1.030255138e-02f, -3.365643786e-02f, +3.820010384e-03f, +3.718506562e-02f, -2.028541539e-02f, -2.159216402e-02f, +2.150028131e-02f, +4.114112388e-03f, -1.011218665e-02f, +1.653747621e-03f, +1.309641631e-03f,
-    /* 16,14 */ +0.000000000e+00f, +2.578329862e-03f, -1.619065127e-03f, -1.029592106e-02f, +1.405076114e-02f, +1.288771825e-02f, -3.254996068e-02f, -5.100475811e-04f, +3.846353557e-02f, -1.676283724e-02f, -2.438627738e-02f, +2.040939526e-02f, +6.125232216e-03f, -1.045641117e-02f, +1.138027416e-03f, +1.577651889e-03f,
-    /* 16,15 */ +0.000000000e+00f, +2.352913572e-03f, -8.385121370e-04f, -1.058864907e-02f, +1.215062389e-02f, +1.521305380e-02f, -3.103786392e-02f, -4.790894575e-03f, +3.923810803e-02f, -1.297236480e-02f, -2.691951328e-02f, +1.899089579e-02f, +8.155641030e-03f, -1.065891816e-02f, +5.473343456e-04f, +1.845338280e-03f,
-    /* 16, 0 */ -2.517634455e-04f, +5.956310854e-03f, -8.647029609e-03f, +1.153545125e-03f, +2.185732832e-02f, -2.369518339e-02f, -1.347728153e-02f, +3.949755319e-02f, -1.347728153e-02f, -2.369518339e-02f, +2.185732832e-02f, +1.153545125e-03f, -8.647029609e-03f, +2.914798040e-03f, -2.517634455e-04f, +0.000000000e+00f,
-    /* 16, 1 */ -3.647589216e-04f, +5.559366521e-03f, -7.860683839e-03f, -8.150822761e-04f, +2.252089097e-02f, -2.063007883e-02f, -1.749200540e-02f, +3.920026256e-02f, -9.205150933e-03f, -2.647415600e-02f, +2.081322447e-02f, +3.223212212e-03f, -9.337661142e-03f, +2.677108373e-03f, -9.939782505e-05f, +0.000000000e+00f,
-    /* 16, 2 */ -4.414886472e-04f, +5.113535158e-03f, -7.000222932e-03f, -2.654422569e-03f, +2.280787202e-02f, -1.733513495e-02f, -2.118899605e-02f, +3.831333038e-02f, -4.740975303e-03f, -2.891426752e-02f, +1.939126736e-02f, +5.362271050e-03f, -9.911447152e-03f, +2.349799583e-03f, +9.477253367e-05f, +0.000000000e+00f,
-    /* 16, 3 */ -4.855802427e-04f, +4.633347213e-03f, -6.087250386e-03f, -4.340001532e-03f, +2.272858071e-02f, -1.386914009e-02f, -2.451395150e-02f, +3.685148678e-02f, -1.540603716e-04f, -3.096737610e-02f, +1.760097190e-02f, +7.536131493e-03f, -1.034820384e-02f, +1.931270179e-03f, +3.323676319e-04f, +0.000000000e+00f,
-    /* 16, 4 */ +0.000000000e+00f, +4.132457962e-03f, -5.142935987e-03f, -5.851401101e-03f, +2.229926864e-02f, -1.029228788e-02f, -2.741946400e-02f, +3.483898696e-02f, +4.483517704e-03f, -3.259088680e-02f, +1.545873378e-02f, +9.707799030e-03f, -1.062918096e-02f, +1.421916825e-03f, +6.140535745e-04f, +0.000000000e+00f,
-    /* 16, 5 */ +0.000000000e+00f, +3.623457200e-03f, -4.187611099e-03f, -7.172450485e-03f, +2.154162444e-02f, -6.665085054e-03f, -2.986575546e-02f, +3.230917458e-02f, +9.098146940e-03f, -3.374862716e-02f, +1.298775300e-02f, +1.183848413e-02f, -1.073754388e-02f, +8.242784646e-04f, +9.394126333e-04f, +0.000000000e+00f,
-    /* 16, 6 */ +0.000000000e+00f, +3.117716971e-03f, -3.240404345e-03f, -8.291325326e-03f, +2.048218318e-02f, -3.047278250e-03f, -3.182126614e-02f, +2.930388237e-02f, +1.361595241e-02f, -3.441162052e-02f, +1.021782484e-02f, +1.388827332e-02f, -1.065884073e-02f, +1.431392807e-04f, +1.306826648e-03f, +0.000000000e+00f,
-    /* 16, 7 */ +0.000000000e+00f, +2.625277441e-03f, -2.318923448e-03f, -9.200556695e-03f, +1.915166452e-02f, +5.031802154e-04f, -3.326308735e-02f, +2.587268140e-02f, +1.796408380e-02f, -3.455874049e-02f, +7.184998851e-03f, +1.581685040e-02f, -1.038144369e-02f, -6.144144569e-04f, +1.713377737e-03f, +0.000000000e+00f,
-    /* 16, 8 */ +0.000000000e+00f, +2.154770219e-03f, -1.438987736e-03f, -9.896953513e-03f, +1.758425506e-02f, +3.931108902e-03f, -3.417723209e-02f, +2.207199352e-02f, +2.207199352e-02f, -3.417723209e-02f, +3.931108902e-03f, +1.758425506e-02f, -9.896953513e-03f, -1.438987736e-03f, +2.154770219e-03f, +0.000000000e+00f,
-    /* 16, 9 */ +0.000000000e+00f, +1.713377737e-03f, -6.144144569e-04f, -1.038144369e-02f, +1.581685040e-02f, +7.184998851e-03f, -3.455874049e-02f, +1.796408380e-02f, +2.587268140e-02f, -3.326308735e-02f, +5.031802154e-04f, +1.915166452e-02f, -9.200556695e-03f, -2.318923448e-03f, +2.625277441e-03f, +0.000000000e+00f,
-    /* 16,10 */ +0.000000000e+00f, +1.306826648e-03f, +1.431392807e-04f, -1.065884073e-02f, +1.388827332e-02f, +1.021782484e-02f, -3.441162052e-02f, +1.361595241e-02f, +2.930388237e-02f, -3.182126614e-02f, -3.047278250e-03f, +2.048218318e-02f, -8.291325326e-03f, -3.240404345e-03f, +3.117716971e-03f, +0.000000000e+00f,
-    /* 16,11 */ +0.000000000e+00f, +9.394126333e-04f, +8.242784646e-04f, -1.073754388e-02f, +1.183848413e-02f, +1.298775300e-02f, -3.374862716e-02f, +9.098146940e-03f, +3.230917458e-02f, -2.986575546e-02f, -6.665085054e-03f, +2.154162444e-02f, -7.172450485e-03f, -4.187611099e-03f, +3.623457200e-03f, +0.000000000e+00f,
-    /* 16,12 */ +0.000000000e+00f, +6.140535745e-04f, +1.421916825e-03f, -1.062918096e-02f, +9.707799030e-03f, +1.545873378e-02f, -3.259088680e-02f, +4.483517704e-03f, +3.483898696e-02f, -2.741946400e-02f, -1.029228788e-02f, +2.229926864e-02f, -5.851401101e-03f, -5.142935987e-03f, +4.132457962e-03f, +0.000000000e+00f,
-    /* 16,13 */ +0.000000000e+00f, +3.323676319e-04f, +1.931270179e-03f, -1.034820384e-02f, +7.536131493e-03f, +1.760097190e-02f, -3.096737610e-02f, -1.540603716e-04f, +3.685148678e-02f, -2.451395150e-02f, -1.386914009e-02f, +2.272858071e-02f, -4.340001532e-03f, -6.087250386e-03f, +4.633347213e-03f, -4.855802427e-04f,
-    /* 16,14 */ +0.000000000e+00f, +9.477253367e-05f, +2.349799583e-03f, -9.911447152e-03f, +5.362271050e-03f, +1.939126736e-02f, -2.891426752e-02f, -4.740975303e-03f, +3.831333038e-02f, -2.118899605e-02f, -1.733513495e-02f, +2.280787202e-02f, -2.654422569e-03f, -7.000222932e-03f, +5.113535158e-03f, -4.414886472e-04f,
-    /* 16,15 */ +0.000000000e+00f, -9.939782505e-05f, +2.677108373e-03f, -9.337661142e-03f, +3.223212212e-03f, +2.081322447e-02f, -2.647415600e-02f, -9.205150933e-03f, +3.920026256e-02f, -1.749200540e-02f, -2.063007883e-02f, +2.252089097e-02f, -8.150822761e-04f, -7.860683839e-03f, +5.559366521e-03f, -3.647589216e-04f,
-    /* 12, 0 */ -3.924537125e-03f, -6.177283790e-03f, +2.270137823e-02f, -1.696686670e-02f, -1.770529738e-02f, +3.949755319e-02f, -1.770529738e-02f, -1.696686670e-02f, +2.270137823e-02f, -6.177283790e-03f, -3.924537125e-03f, +2.689823824e-03f,
-    /* 12, 1 */ -2.918444824e-03f, -7.533875928e-03f, +2.217225575e-02f, -1.325050127e-02f, -2.161377319e-02f, +3.915985190e-02f, -1.343239533e-02f, -2.049610855e-02f, +2.283609035e-02f, -4.600700986e-03f, -4.945631587e-03f, +2.897838580e-03f,
-    /* 12, 2 */ -1.948111766e-03f, -8.657444743e-03f, +2.127619260e-02f, -9.420045488e-03f, -2.509275167e-02f, +3.815312062e-02f, -8.867972963e-03f, -2.376686078e-02f, +2.255583139e-02f, -2.822790564e-03f, -5.958903400e-03f, +3.051876120e-03f,
-    /* 12, 3 */ -1.031879811e-03f, -9.540571177e-03f, +2.004673480e-02f, -5.548699503e-03f, -2.808617760e-02f, +3.649634673e-02f, -4.091413649e-03f, -2.671092541e-02f, +2.184766025e-02f, -8.677312765e-04f, -6.939883353e-03f, +3.140832095e-03f,
-    /* 12, 4 */ -1.854082964e-04f, -1.018130776e-02f, +1.852257236e-02f, -1.708362919e-03f, -3.054799363e-02f, +3.422074403e-02f, +8.129280323e-04f, -2.926474106e-02f, +2.070682375e-02f, +1.235031889e-03f, -7.862950435e-03f, +3.154329873e-03f,
-    /* 12, 5 */ +5.785109863e-04f, -1.058292035e-02f, +1.674653148e-02f, +2.031769072e-03f, -3.244290444e-02f, +3.136911490e-02f, +5.757350815e-03f, -3.137078637e-02f, +1.913716500e-02f, +3.451172065e-03f, -8.701884951e-03f, +3.083080347e-03f,
-    /* 12, 6 */ +1.250056620e-03f, -1.075352499e-02f, +1.476451598e-02f, +5.606517218e-03f, -3.374690984e-02f, +2.799497691e-02f, +1.065251585e-02f, -3.297888633e-02f, +1.715135739e-02f, +5.741996578e-03f, -9.430471381e-03f, +2.919238566e-03f,
-    /* 12, 7 */ +1.822400383e-03f, -1.070563332e-02f, +1.262442359e-02f, +8.955911342e-03f, -3.444759838e-02f, +2.416147295e-02f, +1.540920462e-02f, -3.404739100e-02f, +1.477095353e-02f, +8.065088216e-03f, -1.002313834e-02f, +2.656746896e-03f,
-    /* 12, 8 */ +2.291654178e-03f, -1.045562141e-02f, +1.037506188e-02f, +1.202624229e-02f, -3.454419870e-02f, +1.994008861e-02f, +1.994008861e-02f, -3.454419870e-02f, +1.202624229e-02f, +1.037506188e-02f, -1.045562141e-02f, +2.291654178e-03f,
-    /* 12, 9 */ +2.656746896e-03f, -1.002313834e-02f, +8.065088216e-03f, +1.477095353e-02f, -3.404739100e-02f, +1.540920462e-02f, +2.416147295e-02f, -3.444759838e-02f, +8.955911342e-03f, +1.262442359e-02f, -1.070563332e-02f, +1.822400383e-03f,
-    /* 12,10 */ +2.919238566e-03f, -9.430471381e-03f, +5.741996578e-03f, +1.715135739e-02f, -3.297888633e-02f, +1.065251585e-02f, +2.799497691e-02f, -3.374690984e-02f, +5.606517218e-03f, +1.476451598e-02f, -1.075352499e-02f, +1.250056620e-03f,
-    /* 12,11 */ +3.083080347e-03f, -8.701884951e-03f, +3.451172065e-03f, +1.913716500e-02f, -3.137078637e-02f, +5.757350815e-03f, +3.136911490e-02f, -3.244290444e-02f, +2.031769072e-03f, +1.674653148e-02f, -1.058292035e-02f, +5.785109863e-04f,
-    /* 12,12 */ +3.154329873e-03f, -7.862950435e-03f, +1.235031889e-03f, +2.070682375e-02f, -2.926474106e-02f, +8.129280323e-04f, +3.422074403e-02f, -3.054799363e-02f, -1.708362919e-03f, +1.852257236e-02f, -1.018130776e-02f, -1.854082964e-04f,
-    /* 12,13 */ +3.140832095e-03f, -6.939883353e-03f, -8.677312765e-04f, +2.184766025e-02f, -2.671092541e-02f, -4.091413649e-03f, +3.649634673e-02f, -2.808617760e-02f, -5.548699503e-03f, +2.004673480e-02f, -9.540571177e-03f, -1.031879811e-03f,
-    /* 12,14 */ +3.051876120e-03f, -5.958903400e-03f, -2.822790564e-03f, +2.255583139e-02f, -2.376686078e-02f, -8.867972963e-03f, +3.815312062e-02f, -2.509275167e-02f, -9.420045488e-03f, +2.127619260e-02f, -8.657444743e-03f, -1.948111766e-03f,
-    /* 12,15 */ +2.897838580e-03f, -4.945631587e-03f, -4.600700986e-03f, +2.283609035e-02f, -2.049610855e-02f, -1.343239533e-02f, +3.915985190e-02f, -2.161377319e-02f, -1.325050127e-02f, +2.217225575e-02f, -7.533875928e-03f, -2.918444824e-03f,
-    /* 12, 0 */ +5.529156756e-04f, -1.017944650e-02f, +2.010395691e-02f, -9.501724583e-03f, -2.157725737e-02f, +3.949755319e-02f, -2.157725737e-02f, -9.501724583e-03f, +2.010395691e-02f, -1.017944650e-02f, +5.529156756e-04f, +9.520529918e-04f,
-    /* 12, 1 */ +1.269440891e-03f, -1.060857725e-02f, +1.848426560e-02f, -5.389674050e-03f, -2.526172923e-02f, +3.911687897e-02f, -1.740939271e-02f, -1.356576871e-02f, +2.138958875e-02f, -9.480008902e-03f, -2.676127190e-04f, +1.273328470e-03f,
-    /* 12, 2 */ +1.873685854e-03f, -1.077705214e-02f, +1.658179711e-02f, -1.315683663e-03f, -2.839592801e-02f, +3.798295250e-02f, -1.283645305e-02f, -1.749413418e-02f, +2.229518867e-02f, -8.506812328e-03f, -1.180051037e-03f, +1.604489886e-03f,
-    /* 12, 3 */ +2.361120897e-03f, -1.070010905e-02f, +1.445171501e-02f, +2.637679549e-03f, -3.092573063e-02f, +3.611987567e-02f, -7.946589383e-03f, -2.119952675e-02f, +2.278144860e-02f, -7.263083188e-03f, -2.168530550e-03f, +1.934678236e-03f,
-    /* 12, 4 */ +2.730794315e-03f, -1.039785120e-02f, +1.215160004e-02f, +6.393108320e-03f, -3.281077803e-02f, +3.356720057e-02f, -2.835931904e-03f, -2.459705675e-02f, +2.281696739e-02f, -5.759053577e-03f, -3.213563229e-03f, +2.251787566e-03f,
-    /* 12, 5 */ +2.985073479e-03f, -9.894440683e-03f, +9.739988515e-03f, +9.880142532e-03f, -3.402514934e-02f, +3.037901891e-02f, +2.393471366e-03f, -2.760625942e-02f, +2.237934513e-02f, -4.012119167e-03f, -4.292316215e-03f, +2.542756696e-03f,
-    /* 12, 6 */ +3.129309714e-03f, -9.217233004e-03f, +7.274949975e-03f, +1.303654969e-02f, -3.455769209e-02f, +2.662271867e-02f, +7.635875993e-03f, -3.015305887e-02f, +2.145609570e-02f, -2.046814992e-03f, -5.379003980e-03f, +2.793918230e-03f,
-    /* 12, 7 */ +3.171441616e-03f, -8.395878746e-03f, +4.812738303e-03f, +1.580947051e-02f, -3.441200543e-02f, +2.237743869e-02f, +1.278417054e-02f, -3.217162603e-02f, +2.004534769e-02f, +1.053992035e-04f, -6.445394017e-03f, +2.991397563e-03f,
-    /* 12, 8 */ +3.121552430e-03f, -7.461418245e-03f, +2.406547485e-03f, +1.815630830e-02f, -3.360608252e-02f, +1.773225889e-02f, +1.773225889e-02f, -3.360608252e-02f, +1.815630830e-02f, +2.406547485e-03f, -7.461418245e-03f, +3.121552430e-03f,
-    /* 12, 9 */ +2.991397563e-03f, -6.445394017e-03f, +1.053992035e-04f, +2.004534769e-02f, -3.217162603e-02f, +1.278417054e-02f, +2.237743869e-02f, -3.441200543e-02f, +1.580947051e-02f, +4.812738303e-03f, -8.395878746e-03f, +3.171441616e-03f,
-    /* 12,10 */ +2.793918230e-03f, -5.379003980e-03f, -2.046814992e-03f, +2.145609570e-02f, -3.015305887e-02f, +7.635875993e-03f, +2.662271867e-02f, -3.455769209e-02f, +1.303654969e-02f, +7.274949975e-03f, -9.217233004e-03f, +3.129309714e-03f,
-    /* 12,11 */ +2.542756696e-03f, -4.292316215e-03f, -4.012119167e-03f, +2.237934513e-02f, -2.760625942e-02f, +2.393471366e-03f, +3.037901891e-02f, -3.402514934e-02f, +9.880142532e-03f, +9.739988515e-03f, -9.894440683e-03f, +2.985073479e-03f,
-    /* 12,12 */ +2.251787566e-03f, -3.213563229e-03f, -5.759053577e-03f, +2.281696739e-02f, -2.459705675e-02f, -2.835931904e-03f, +3.356720057e-02f, -3.281077803e-02f, +6.393108320e-03f, +1.215160004e-02f, -1.039785120e-02f, +2.730794315e-03f,
-    /* 12,13 */ +1.934678236e-03f, -2.168530550e-03f, -7.263083188e-03f, +2.278144860e-02f, -2.119952675e-02f, -7.946589383e-03f, +3.611987567e-02f, -3.092573063e-02f, +2.637679549e-03f, +1.445171501e-02f, -1.070010905e-02f, +2.361120897e-03f,
-    /* 12,14 */ +1.604489886e-03f, -1.180051037e-03f, -8.506812328e-03f, +2.229518867e-02f, -1.749413418e-02f, -1.283645305e-02f, +3.798295250e-02f, -2.839592801e-02f, -1.315683663e-03f, +1.658179711e-02f, -1.077705214e-02f, +1.873685854e-03f,
-    /* 12,15 */ +1.273328470e-03f, -2.676127190e-04f, -9.480008902e-03f, +2.138958875e-02f, -1.356576871e-02f, -1.740939271e-02f, +3.911687897e-02f, -2.526172923e-02f, -5.389674050e-03f, +1.848426560e-02f, -1.060857725e-02f, +1.269440891e-03f,
-
-    /* 24, 0 */ -8.820438069e-05f, -1.519461079e-04f, -2.301651496e-04f, -3.149320871e-04f, -3.945939739e-04f, -4.554410135e-04f, -4.841532882e-04f, -4.705408991e-04f, -4.099602091e-04f, -3.048100066e-04f, -1.646897470e-04f, -5.099007530e-06f, +1.551006323e-04f, +2.969416536e-04f, +4.046294158e-04f, +4.681429482e-04f, +4.846228261e-04f, +4.583040637e-04f, +3.990939388e-04f, +3.201968846e-04f, +2.353759082e-04f, +1.564712483e-04f, +9.167483068e-05f, +4.482688286e-05f,
-    /* 24, 1 */ -8.480575132e-05f, -1.474789784e-04f, -2.249812225e-04f, -3.096480504e-04f, -3.900204007e-04f, -4.524514078e-04f, -4.835165803e-04f, -4.727530367e-04f, -4.151145025e-04f, -3.125397891e-04f, -1.742016828e-04f, -1.529460870e-05f, +1.454387449e-04f, +2.889379628e-04f, +3.991236794e-04f, +4.655589110e-04f, +4.849233000e-04f, +4.610375470e-04f, +4.035168325e-04f, +3.254391996e-04f, +2.406110065e-04f, +1.610529558e-04f, +9.521673594e-05f, +4.721513201e-05f,
-    /* 24, 2 */ -8.147924507e-05f, -1.430712350e-04f, -2.198265592e-04f, -3.043479843e-04f, -3.853766873e-04f, -4.493383067e-04f, -4.827146831e-04f, -4.747797448e-04f, -4.200908527e-04f, -3.201278616e-04f, -1.836320864e-04f, -2.548296987e-05f, +1.357085413e-04f, +2.808022583e-04f, +3.934446700e-04f, +4.627886263e-04f, +4.850529052e-04f, +4.636385032e-04f, +4.078592000e-04f, +3.306557574e-04f, +2.458678944e-04f, +1.656897170e-04f, +9.882966748e-05f, +4.967415993e-05f,
-    /* 24, 3 */ -7.822510242e-05f, -1.387241832e-04f, -2.147035314e-04f, -2.990350629e-04f, -3.806663042e-04f, -4.461048161e-04f, -4.817496625e-04f, -4.766215175e-04f, -4.248879309e-04f, -3.275711800e-04f, -1.929766610e-04f, -3.565926997e-05f, +1.259145254e-04f, +2.725379532e-04f, +3.875941701e-04f, +4.598320457e-04f, +4.850099279e-04f, +4.661040260e-04f, +4.121175966e-04f, +3.358432542e-04f, +2.511439643e-04f, +1.703799499e-04f, +1.025131319e-04f, +5.220438912e-05f,
-    /* 24, 4 */ -7.504350274e-05f, -1.344390595e-04f, -2.096144489e-04f, -2.937124231e-04f, -3.758927218e-04f, -4.427540852e-04f, -4.806236671e-04f, -4.782789577e-04f, -4.295045226e-04f, -3.348667971e-04f, -2.022311686e-04f, -4.581869630e-05f, +1.160612449e-04f, +2.641485480e-04f, +3.815740737e-04f, +4.566892339e-04f, +4.847927474e-04f, +4.684312656e-04f, +4.162885910e-04f, +3.409983591e-04f, +2.564365532e-04f, +1.751220037e-04f, +1.062665706e-04f, +5.480619333e-05f,
-    /* 24, 5 */ -7.193456522e-05f, -1.302170312e-04f, -2.045615590e-04f, -2.883831622e-04f, -3.710594077e-04f, -4.392893036e-04f, -4.793389263e-04f, -4.797527765e-04f, -4.339395286e-04f, -3.420118645e-04f, -2.113914331e-04f, -5.595644787e-05f, +1.061532886e-04f, +2.556376279e-04f, +3.753863858e-04f, +4.533603695e-04f, +4.843998374e-04f, +4.706174312e-04f, +4.203687678e-04f, +3.461177167e-04f, +2.617429433e-04f, +1.799141593e-04f, +1.100893595e-04f, +5.747989630e-05f,
-    /* 24, 6 */ -6.889834987e-05f, -1.260591965e-04f, -1.995470454e-04f, -2.830503358e-04f, -3.661698243e-04f, -4.357136989e-04f, -4.778977479e-04f, -4.810437916e-04f, -4.381919648e-04f, -3.490036345e-04f, -2.204533432e-04f, -6.606773875e-05f, +9.619528314e-05f, +2.470088608e-04f, +3.690332209e-04f, +4.498457452e-04f, +4.838297683e-04f, +4.726597937e-04f, +4.243547301e-04f, +3.511979487e-04f, +2.670603639e-04f, +1.847546294e-04f, +1.139808078e-04f, +6.022577049e-05f,
-    /* 24, 7 */ -6.593485851e-05f, -1.219665852e-04f, -1.945730275e-04f, -2.777169567e-04f, -3.612274261e-04f, -4.320305335e-04f, -4.763025159e-04f, -4.821529264e-04f, -4.422609626e-04f, -3.558394612e-04f, -2.294128549e-04f, -7.614780136e-05f, +8.619188981e-05f, +2.382659945e-04f, +3.625168024e-04f, +4.461457687e-04f, +4.830812085e-04f, +4.745556880e-04f, +4.282431024e-04f, +3.562356572e-04f, +2.723859925e-04f, +1.896415594e-04f, +1.179401580e-04f, +6.304403582e-05f,
-    /* 24, 8 */ -6.304403582e-05f, -1.179401580e-04f, -1.896415594e-04f, -2.723859925e-04f, -3.562356572e-04f, -4.282431024e-04f, -4.745556880e-04f, -4.830812085e-04f, -4.461457687e-04f, -3.625168024e-04f, -2.382659945e-04f, -8.619188981e-05f, +7.614780136e-05f, +2.294128549e-04f, +3.558394612e-04f, +4.422609626e-04f, +4.821529264e-04f, +4.763025159e-04f, +4.320305335e-04f, +3.612274261e-04f, +2.777169567e-04f, +1.945730275e-04f, +1.219665852e-04f, +6.593485851e-05f,
-    /* 24, 9 */ -6.022577049e-05f, -1.139808078e-04f, -1.847546294e-04f, -2.670603639e-04f, -3.511979487e-04f, -4.243547301e-04f, -4.726597937e-04f, -4.838297683e-04f, -4.498457452e-04f, -3.690332209e-04f, -2.470088608e-04f, -9.619528314e-05f, +6.606773875e-05f, +2.204533432e-04f, +3.490036345e-04f, +4.381919648e-04f, +4.810437916e-04f, +4.778977479e-04f, +4.357136989e-04f, +3.661698243e-04f, +2.830503358e-04f, +1.995470454e-04f, +1.260591965e-04f, +6.889834987e-05f,
-    /* 24,10 */ -5.747989630e-05f, -1.100893595e-04f, -1.799141593e-04f, -2.617429433e-04f, -3.461177167e-04f, -4.203687678e-04f, -4.706174312e-04f, -4.843998374e-04f, -4.533603695e-04f, -3.753863858e-04f, -2.556376279e-04f, -1.061532886e-04f, +5.595644787e-05f, +2.113914331e-04f, +3.420118645e-04f, +4.339395286e-04f, +4.797527765e-04f, +4.793389263e-04f, +4.392893036e-04f, +3.710594077e-04f, +2.883831622e-04f, +2.045615590e-04f, +1.302170312e-04f, +7.193456522e-05f,
-    /* 24,11 */ -5.480619333e-05f, -1.062665706e-04f, -1.751220037e-04f, -2.564365532e-04f, -3.409983591e-04f, -4.162885910e-04f, -4.684312656e-04f, -4.847927474e-04f, -4.566892339e-04f, -3.815740737e-04f, -2.641485480e-04f, -1.160612449e-04f, +4.581869630e-05f, +2.022311686e-04f, +3.348667971e-04f, +4.295045226e-04f, +4.782789577e-04f, +4.806236671e-04f, +4.427540852e-04f, +3.758927218e-04f, +2.937124231e-04f, +2.096144489e-04f, +1.344390595e-04f, +7.504350274e-05f,
-    /* 24,12 */ -5.220438912e-05f, -1.025131319e-04f, -1.703799499e-04f, -2.511439643e-04f, -3.358432542e-04f, -4.121175966e-04f, -4.661040260e-04f, -4.850099279e-04f, -4.598320457e-04f, -3.875941701e-04f, -2.725379532e-04f, -1.259145254e-04f, +3.565926997e-05f, +1.929766610e-04f, +3.275711800e-04f, +4.248879309e-04f, +4.766215175e-04f, +4.817496625e-04f, +4.461048161e-04f, +3.806663042e-04f, +2.990350629e-04f, +2.147035314e-04f, +1.387241832e-04f, +7.822510242e-05f,
-    /* 24,13 */ -4.967415993e-05f, -9.882966748e-05f, -1.656897170e-04f, -2.458678944e-04f, -3.306557574e-04f, -4.078592000e-04f, -4.636385032e-04f, -4.850529052e-04f, -4.627886263e-04f, -3.934446700e-04f, -2.808022583e-04f, -1.357085413e-04f, +2.548296987e-05f, +1.836320864e-04f, +3.201278616e-04f, +4.200908527e-04f, +4.747797448e-04f, +4.827146831e-04f, +4.493383067e-04f, +3.853766873e-04f, +3.043479843e-04f, +2.198265592e-04f, +1.430712350e-04f, +8.147924507e-05f,
-    /* 24,14 */ -4.721513201e-05f, -9.521673594e-05f, -1.610529558e-04f, -2.406110065e-04f, -3.254391996e-04f, -4.035168325e-04f, -4.610375470e-04f, -4.849233000e-04f, -4.655589110e-04f, -3.991236794e-04f, -2.889379628e-04f, -1.454387449e-04f, +1.529460870e-05f, +1.742016828e-04f, +3.125397891e-04f, +4.151145025e-04f, +4.727530367e-04f, +4.835165803e-04f, +4.524514078e-04f, +3.900204007e-04f, +3.096480504e-04f, +2.249812225e-04f, +1.474789784e-04f, +8.480575132e-05f,
-    /* 24,15 */ -4.482688286e-05f, -9.167483068e-05f, -1.564712483e-04f, -2.353759082e-04f, -3.201968846e-04f, -3.990939388e-04f, -4.583040637e-04f, -4.846228261e-04f, -4.681429482e-04f, -4.046294158e-04f, -2.969416536e-04f, -1.551006323e-04f, +5.099007530e-06f, +1.646897470e-04f, +3.048100066e-04f, +4.099602091e-04f, +4.705408991e-04f, +4.841532882e-04f, +4.554410135e-04f, +3.945939739e-04f, +3.149320871e-04f, +2.301651496e-04f, +1.519461079e-04f, +8.820438069e-05f,
-    /* 24, 0 */ +3.721332452e-05f, -8.727351622e-06f, -1.260052743e-04f, -3.262895896e-04f, -5.956603662e-04f, -8.899501259e-04f, -1.140781305e-03f, -1.272347980e-03f, -1.224469676e-03f, -9.741728935e-04f, -5.476309302e-04f, -1.718639697e-05f, +5.165697336e-04f, +9.521355524e-04f, +1.214742061e-03f, +1.275075958e-03f, +1.153251370e-03f, +9.076938752e-04f, +6.139361451e-04f, +3.414081512e-04f, +1.360881127e-04f, +1.374767685e-05f, -3.597568203e-05f, -3.836441874e-05f,
-    /* 24, 1 */ +3.827272022e-05f, -3.990309212e-06f, -1.162552839e-04f, -3.114511951e-04f, -5.774902753e-04f, -8.720393210e-04f, -1.127840237e-03f, -1.268906542e-03f, -1.233389975e-03f, -9.955061195e-04f, -5.782766642e-04f, -5.154594549e-05f, +4.851159022e-04f, +9.294071718e-04f, +1.204207601e-03f, +1.277079499e-03f, +1.165232472e-03f, +9.252515980e-04f, +6.323029482e-04f, +3.567995352e-04f, +1.465038861e-04f, +1.905656402e-05f, -3.455261727e-05f, -3.906074609e-05f,
-    /* 24, 2 */ +3.916105537e-05f, +4.689475139e-07f, -1.068376458e-04f, -2.968998221e-04f, -5.594401371e-04f, -8.539803004e-04f, -1.114446367e-03f, -1.264763218e-03f, -1.241503276e-03f, -1.016122900e-03f, -6.084845647e-04f, -8.586577249e-05f, +4.532926958e-04f, +9.060015608e-04f, +1.192867560e-03f, +1.278348235e-03f, +1.176706916e-03f, +9.426042142e-04f, +6.507457252e-04f, +3.724559064e-04f, +1.572522637e-04f, +2.465906089e-05f, -3.293697730e-05f, -3.967556907e-05f,
-    /* 24, 3 */ +3.988551544e-05f, +4.656120273e-06f, -9.775146571e-05f, -2.826418349e-04f, -5.415238064e-04f, -8.357917522e-04f, -1.100618114e-03f, -1.259930153e-03f, -1.248810685e-03f, -1.036011659e-03f, -6.382327409e-04f, -1.201194461e-04f, +4.211237814e-04f, +8.819332498e-04f, +1.180724004e-03f, +1.278872430e-03f, +1.187657300e-03f, +9.597325558e-04f, +6.692490513e-04f, +3.883689407e-04f, +1.683324883e-04f, +3.055997058e-05f, -3.112164378e-05f, -4.020250110e-05f,
-    /* 24, 4 */ +4.045327387e-05f, +8.577101915e-06f, -8.899546026e-05f, -2.686831091e-04f, -5.237547173e-04f, -8.174921923e-04f, -1.086374092e-03f, -1.254420050e-03f, -1.255314082e-03f, -1.055161588e-03f, -6.674998060e-04f, -1.542806079e-04f, +3.886332072e-04f, +8.572174771e-04f, +1.167779798e-03f, +1.278642989e-03f, +1.198066533e-03f, +9.766173891e-04f, +6.877971412e-04f, +4.045298263e-04f, +1.797433681e-04f, +3.676383839e-05f, -2.909954521e-05f, -4.063504078e-05f,
-    /* 24, 5 */ +4.087148106e-05f, +1.223796294e-05f, -8.056796775e-05f, -2.550290329e-04f, -5.061458738e-04f, -7.990999447e-04f, -1.071733083e-03f, -1.248246148e-03f, -1.261016119e-03f, -1.073562648e-03f, -6.962648992e-04f, -1.883230024e-04f, +3.558453770e-04f, +8.318701747e-04f, +1.154038613e-03f, +1.277651484e-03f, +1.207917863e-03f, +9.932394374e-04f, +7.063738625e-04f, +4.209292660e-04f, +1.914832687e-04f, +4.327493877e-05f, -2.686366939e-05f, -4.096657950e-05f,
-    /* 24, 6 */ +4.114725367e-05f, +1.564493806e-05f, -7.246695886e-05f, -2.416845105e-04f, -4.887098400e-04f, -7.806331214e-04f, -1.056714015e-03f, -1.241422199e-03f, -1.265920211e-03f, -1.091205584e-03f, -7.245077077e-04f, -2.222205061e-04f, +3.227850234e-04f, +8.059079530e-04f, +1.139504920e-03f, +1.275890161e-03f, +1.217194897e-03f, +1.009579403e-03f, +7.249627509e-04f, +4.375574807e-04f, +2.035501057e-04f, +5.009726244e-05f, -2.440707607e-05f, -4.119040933e-05f,
-    /* 24, 7 */ +4.128766430e-05f, +1.880441272e-05f, -6.469004778e-05f, -2.286539641e-04f, -4.714587328e-04f, -7.621096041e-04f, -1.041335936e-03f, -1.233962452e-03f, -1.270030522e-03f, -1.108081926e-03f, -7.522084876e-04f, -2.559471563e-04f, +2.894771803e-04f, +7.793480846e-04f, +1.124183998e-03f, +1.273351959e-03f, +1.225881627e-03f, +1.025617992e-03f, +7.435470253e-04f, +4.544042133e-04f, +2.159413387e-04f, +5.723450367e-05f, -2.172290976e-05f, -4.129973134e-05f,
-    /* 24, 8 */ +4.129973134e-05f, +2.172290976e-05f, -5.723450367e-05f, -2.159413387e-04f, -4.544042133e-04f, -7.435470253e-04f, -1.025617992e-03f, -1.225881627e-03f, -1.273351959e-03f, -1.124183998e-03f, -7.793480846e-04f, -2.894771803e-04f, +2.559471563e-04f, +7.522084876e-04f, +1.108081926e-03f, +1.270030522e-03f, +1.233962452e-03f, +1.041335936e-03f, +7.621096041e-04f, +4.714587328e-04f, +2.286539641e-04f, +6.469004778e-05f, -1.880441272e-05f, -4.128766430e-05f,
-    /* 24, 9 */ +4.119040933e-05f, +2.440707607e-05f, -5.009726244e-05f, -2.035501057e-04f, -4.375574807e-04f, -7.249627509e-04f, -1.009579403e-03f, -1.217194897e-03f, -1.275890161e-03f, -1.139504920e-03f, -8.059079530e-04f, -3.227850234e-04f, +2.222205061e-04f, +7.245077077e-04f, +1.091205584e-03f, +1.265920211e-03f, +1.241422199e-03f, +1.056714015e-03f, +7.806331214e-04f, +4.887098400e-04f, +2.416845105e-04f, +7.246695886e-05f, -1.564493806e-05f, -4.114725367e-05f,
-    /* 24,10 */ +4.096657950e-05f, +2.686366939e-05f, -4.327493877e-05f, -1.914832687e-04f, -4.209292660e-04f, -7.063738625e-04f, -9.932394374e-04f, -1.207917863e-03f, -1.277651484e-03f, -1.154038613e-03f, -8.318701747e-04f, -3.558453770e-04f, +1.883230024e-04f, +6.962648992e-04f, +1.073562648e-03f, +1.261016119e-03f, +1.248246148e-03f, +1.071733083e-03f, +7.990999447e-04f, +5.061458738e-04f, +2.550290329e-04f, +8.056796775e-05f, -1.223796294e-05f, -4.087148106e-05f,
-    /* 24,11 */ +4.063504078e-05f, +2.909954521e-05f, -3.676383839e-05f, -1.797433681e-04f, -4.045298263e-04f, -6.877971412e-04f, -9.766173891e-04f, -1.198066533e-03f, -1.278642989e-03f, -1.167779798e-03f, -8.572174771e-04f, -3.886332072e-04f, +1.542806079e-04f, +6.674998060e-04f, +1.055161588e-03f, +1.255314082e-03f, +1.254420050e-03f, +1.086374092e-03f, +8.174921923e-04f, +5.237547173e-04f, +2.686831091e-04f, +8.899546026e-05f, -8.577101915e-06f, -4.045327387e-05f,
-    /* 24,12 */ +4.020250110e-05f, +3.112164378e-05f, -3.055997058e-05f, -1.683324883e-04f, -3.883689407e-04f, -6.692490513e-04f, -9.597325558e-04f, -1.187657300e-03f, -1.278872430e-03f, -1.180724004e-03f, -8.819332498e-04f, -4.211237814e-04f, +1.201194461e-04f, +6.382327409e-04f, +1.036011659e-03f, +1.248810685e-03f, +1.259930153e-03f, +1.100618114e-03f, +8.357917522e-04f, +5.415238064e-04f, +2.826418349e-04f, +9.775146571e-05f, -4.656120273e-06f, -3.988551544e-05f,
-    /* 24,13 */ +3.967556907e-05f, +3.293697730e-05f, -2.465906089e-05f, -1.572522637e-04f, -3.724559064e-04f, -6.507457252e-04f, -9.426042142e-04f, -1.176706916e-03f, -1.278348235e-03f, -1.192867560e-03f, -9.060015608e-04f, -4.532926958e-04f, +8.586577249e-05f, +6.084845647e-04f, +1.016122900e-03f, +1.241503276e-03f, +1.264763218e-03f, +1.114446367e-03f, +8.539803004e-04f, +5.594401371e-04f, +2.968998221e-04f, +1.068376458e-04f, -4.689475139e-07f, -3.916105537e-05f,
-    /* 24,14 */ +3.906074609e-05f, +3.455261727e-05f, -1.905656402e-05f, -1.465038861e-04f, -3.567995352e-04f, -6.323029482e-04f, -9.252515980e-04f, -1.165232472e-03f, -1.277079499e-03f, -1.204207601e-03f, -9.294071718e-04f, -4.851159022e-04f, +5.154594549e-05f, +5.782766642e-04f, +9.955061195e-04f, +1.233389975e-03f, +1.268906542e-03f, +1.127840237e-03f, +8.720393210e-04f, +5.774902753e-04f, +3.114511951e-04f, +1.162552839e-04f, +3.990309212e-06f, -3.827272022e-05f,
-    /* 24,15 */ +3.836441874e-05f, +3.597568203e-05f, -1.374767685e-05f, -1.360881127e-04f, -3.414081512e-04f, -6.139361451e-04f, -9.076938752e-04f, -1.153251370e-03f, -1.275075958e-03f, -1.214742061e-03f, -9.521355524e-04f, -5.165697336e-04f, +1.718639697e-05f, +5.476309302e-04f, +9.741728935e-04f, +1.224469676e-03f, +1.272347980e-03f, +1.140781305e-03f, +8.899501259e-04f, +5.956603662e-04f, +3.262895896e-04f, +1.260052743e-04f, +8.727351622e-06f, -3.721332452e-05f,
-    /* 24, 0 */ +8.266384897e-05f, +1.864042294e-04f, +2.488885336e-04f, +1.546439211e-04f, -1.995837972e-04f, -8.300120177e-04f, -1.613160849e-03f, -2.296673715e-03f, -2.585717258e-03f, -2.273475621e-03f, -1.352242686e-03f, -4.324968723e-05f, +1.278412578e-03f, +2.232544293e-03f, +2.585064833e-03f, +2.329165788e-03f, +1.661894649e-03f, +8.765619362e-04f, +2.314166150e-04f, -1.408802900e-04f, -2.488728147e-04f, -1.925779863e-04f, -8.867605644e-05f, -1.381647235e-05f,
-    /* 24, 1 */ +7.679604466e-05f, +1.800850086e-04f, +2.482891228e-04f, +1.673628145e-04f, -1.688781476e-04f, -7.841040553e-04f, -1.564053778e-03f, -2.262611362e-03f, -2.583952550e-03f, -2.311948888e-03f, -1.424504725e-03f, -1.296977982e-04f, +1.203096102e-03f, +2.189184288e-03f, +2.581965725e-03f, +2.360018674e-03f, +1.710180642e-03f, +9.237037585e-04f, +2.643640884e-04f, -1.260534627e-04f, -2.482108983e-04f, -1.985807152e-04f, -9.482163577e-05f, -1.700840565e-05f,
-    /* 24, 2 */ +7.108272573e-05f, +1.736451253e-04f, +2.471057735e-04f, +1.790568131e-04f, -1.393098721e-04f, -7.388859215e-04f, -1.514647192e-03f, -2.227049028e-03f, -2.579803518e-03f, -2.347938498e-03f, -1.495119547e-03f, -2.159922036e-04f, +1.126377386e-03f, +2.143428746e-03f, +2.576393731e-03f, +2.389164999e-03f, +1.757943642e-03f, +9.713853048e-04f, +2.984113695e-04f, -1.101464409e-04f, -2.468719141e-04f, -2.043861254e-04f, -1.010885985e-04f, -2.040687624e-05f,
-    /* 24, 3 */ +6.553303557e-05f, +1.671085856e-04f, +2.453697283e-04f, +1.897470664e-04f, -1.108869031e-04f, -6.944032625e-04f, -1.465013955e-03f, -2.190058265e-03f, -2.573306150e-03f, -2.381422658e-03f, -1.564010684e-03f, -3.020307159e-04f, +1.048342851e-03f, +2.095314540e-03f, +2.568326065e-03f, +2.416539054e-03f, +1.805107932e-03f, +1.019552324e-03f, +3.335412514e-04f, -9.314376077e-05f, -2.448252646e-04f, -2.099672379e-04f, -1.074639934e-04f, -2.401251277e-05f,
-    /* 24, 4 */ +6.015519126e-05f, +1.604985702e-04f, +2.431122111e-04f, +1.994559526e-04f, -8.361493575e-05f, -6.506994570e-04f, -1.415225919e-03f, -2.151711738e-03f, -2.564499518e-03f, -2.412383397e-03f, -1.631104459e-03f, -3.877115714e-04f, +9.690810727e-04f, +2.044882222e-03f, +2.557743429e-03f, +2.442076932e-03f, +1.851597394e-03f, +1.068148557e-03f, +3.697341485e-04f, -7.503156587e-05f, -2.420407013e-04f, -2.152964269e-04f, -1.139339030e-04f, -2.782526914e-05f,
-    /* 24, 5 */ +5.495649810e-05f, +1.538374078e-04f, +2.403643576e-04f, +2.082069988e-04f, -5.749746926e-05f, -6.078155802e-04f, -1.365353811e-03f, -2.112083086e-03f, -2.553425683e-03f, -2.440806561e-03f, -1.696330106e-03f, -4.729335981e-04f, +8.886826408e-04f, +1.992175989e-03f, +2.544630075e-03f, +2.465716661e-03f, +1.897335642e-03f, +1.117115802e-03f, +4.069680813e-04f, -5.579767803e-05f, -2.384884029e-04f, -2.203454641e-04f, -1.204834430e-04f, -3.184439496e-05f,
-    /* 24, 6 */ +4.994336610e-05f, +1.471465506e-04f, +2.371571498e-04f, +2.160248014e-04f, -3.253585139e-05f, -5.657903730e-04f, -1.315467130e-03f, -2.071246779e-03f, -2.540129593e-03f, -2.466681818e-03f, -1.759619871e-03f, -5.575963834e-04f, +8.072400133e-04f, +1.937243618e-03f, +2.528973864e-03f, +2.487398336e-03f, +1.942246152e-03f, +1.166393990e-03f, +4.452186667e-04f, -3.543166589e-05f, -2.341390536e-04f, -2.250855657e-04f, -1.270967638e-04f, -3.606840695e-05f,
-    /* 24, 7 */ +4.512132841e-05f, +1.404465535e-04f, +2.335213506e-04f, +2.229349451e-04f, -8.729326764e-06f, -5.246602166e-04f, -1.265634037e-03f, -2.029277978e-03f, -2.524658979e-03f, -2.490002646e-03f, -1.820909115e-03f, -6.416004392e-04f, +7.248473657e-04f, +1.880136408e-03f, +2.510766314e-03f, +2.507064240e-03f, +1.986252395e-03f, +1.215921259e-03f, +4.844591124e-04f, -1.392491133e-05f, -2.289639228e-04f, -2.294874421e-04f, -1.337570553e-04f, -4.049506149e-05f,
-    /* 24, 8 */ +4.049506149e-05f, +1.337570553e-04f, +2.294874421e-04f, +2.289639228e-04f, +1.392491133e-05f, -4.844591124e-04f, -1.215921259e-03f, -1.986252395e-03f, -2.507064240e-03f, -2.510766314e-03f, -1.880136408e-03f, -7.248473657e-04f, +6.416004392e-04f, +1.820909115e-03f, +2.490002646e-03f, +2.524658979e-03f, +2.029277978e-03f, +1.265634037e-03f, +5.246602166e-04f, +8.729326764e-06f, -2.229349451e-04f, -2.335213506e-04f, -1.404465535e-04f, -4.512132841e-05f,
-    /* 24, 9 */ +3.606840695e-05f, +1.270967638e-04f, +2.250855657e-04f, +2.341390536e-04f, +3.543166589e-05f, -4.452186667e-04f, -1.166393990e-03f, -1.942246152e-03f, -2.487398336e-03f, -2.528973864e-03f, -1.937243618e-03f, -8.072400133e-04f, +5.575963834e-04f, +1.759619871e-03f, +2.466681818e-03f, +2.540129593e-03f, +2.071246779e-03f, +1.315467130e-03f, +5.657903730e-04f, +3.253585139e-05f, -2.160248014e-04f, -2.371571498e-04f, -1.471465506e-04f, -4.994336610e-05f,
-    /* 24,10 */ +3.184439496e-05f, +1.204834430e-04f, +2.203454641e-04f, +2.384884029e-04f, +5.579767803e-05f, -4.069680813e-04f, -1.117115802e-03f, -1.897335642e-03f, -2.465716661e-03f, -2.544630075e-03f, -1.992175989e-03f, -8.886826408e-04f, +4.729335981e-04f, +1.696330106e-03f, +2.440806561e-03f, +2.553425683e-03f, +2.112083086e-03f, +1.365353811e-03f, +6.078155802e-04f, +5.749746926e-05f, -2.082069988e-04f, -2.403643576e-04f, -1.538374078e-04f, -5.495649810e-05f,
-    /* 24,11 */ +2.782526914e-05f, +1.139339030e-04f, +2.152964269e-04f, +2.420407013e-04f, +7.503156587e-05f, -3.697341485e-04f, -1.068148557e-03f, -1.851597394e-03f, -2.442076932e-03f, -2.557743429e-03f, -2.044882222e-03f, -9.690810727e-04f, +3.877115714e-04f, +1.631104459e-03f, +2.412383397e-03f, +2.564499518e-03f, +2.151711738e-03f, +1.415225919e-03f, +6.506994570e-04f, +8.361493575e-05f, -1.994559526e-04f, -2.431122111e-04f, -1.604985702e-04f, -6.015519126e-05f,
-    /* 24,12 */ +2.401251277e-05f, +1.074639934e-04f, +2.099672379e-04f, +2.448252646e-04f, +9.314376077e-05f, -3.335412514e-04f, -1.019552324e-03f, -1.805107932e-03f, -2.416539054e-03f, -2.568326065e-03f, -2.095314540e-03f, -1.048342851e-03f, +3.020307159e-04f, +1.564010684e-03f, +2.381422658e-03f, +2.573306150e-03f, +2.190058265e-03f, +1.465013955e-03f, +6.944032625e-04f, +1.108869031e-04f, -1.897470664e-04f, -2.453697283e-04f, -1.671085856e-04f, -6.553303557e-05f,
-    /* 24,13 */ +2.040687624e-05f, +1.010885985e-04f, +2.043861254e-04f, +2.468719141e-04f, +1.101464409e-04f, -2.984113695e-04f, -9.713853048e-04f, -1.757943642e-03f, -2.389164999e-03f, -2.576393731e-03f, -2.143428746e-03f, -1.126377386e-03f, +2.159922036e-04f, +1.495119547e-03f, +2.347938498e-03f, +2.579803518e-03f, +2.227049028e-03f, +1.514647192e-03f, +7.388859215e-04f, +1.393098721e-04f, -1.790568131e-04f, -2.471057735e-04f, -1.736451253e-04f, -7.108272573e-05f,
-    /* 24,14 */ +1.700840565e-05f, +9.482163577e-05f, +1.985807152e-04f, +2.482108983e-04f, +1.260534627e-04f, -2.643640884e-04f, -9.237037585e-04f, -1.710180642e-03f, -2.360018674e-03f, -2.581965725e-03f, -2.189184288e-03f, -1.203096102e-03f, +1.296977982e-04f, +1.424504725e-03f, +2.311948888e-03f, +2.583952550e-03f, +2.262611362e-03f, +1.564053778e-03f, +7.841040553e-04f, +1.688781476e-04f, -1.673628145e-04f, -2.482891228e-04f, -1.800850086e-04f, -7.679604466e-05f,
-    /* 24,15 */ +1.381647235e-05f, +8.867605644e-05f, +1.925779863e-04f, +2.488728147e-04f, +1.408802900e-04f, -2.314166150e-04f, -8.765619362e-04f, -1.661894649e-03f, -2.329165788e-03f, -2.585064833e-03f, -2.232544293e-03f, -1.278412578e-03f, +4.324968723e-05f, +1.352242686e-03f, +2.273475621e-03f, +2.585717258e-03f, +2.296673715e-03f, +1.613160849e-03f, +8.300120177e-04f, +1.995837972e-04f, -1.546439211e-04f, -2.488885336e-04f, -1.864042294e-04f, -8.266384897e-05f,
-    /* 24, 0 */ -8.756118778e-05f, -1.009631262e-05f, +2.499923290e-04f, +5.877223422e-04f, +6.788717735e-04f, +1.353208099e-04f, -1.181609893e-03f, -2.907631270e-03f, -4.227440709e-03f, -4.289302846e-03f, -2.753030129e-03f, -9.027467135e-05f, +2.610460208e-03f, +4.239433597e-03f, +4.275304929e-03f, +3.011836329e-03f, +1.284225967e-03f, -7.470693818e-05f, -6.668983668e-04f, -6.049037547e-04f, -2.711811033e-04f, -7.712041122e-07f, +8.724954076e-05f, +5.404595280e-05f,
-    /* 24, 1 */ -8.741655630e-05f, -2.019027119e-05f, +2.291878545e-04f, +5.696067266e-04f, +6.882827247e-04f, +1.927359117e-04f, -1.080756061e-03f, -2.801858302e-03f, -4.174485032e-03f, -4.332641998e-03f, -2.890980043e-03f, -2.706680808e-04f, +2.463494124e-03f, +4.183052585e-03f, +4.317905196e-03f, +3.114235078e-03f, +1.388440877e-03f, -1.091717027e-05f, -6.522789212e-04f, -6.210469572e-04f, -2.926973166e-04f, -1.241413728e-05f, +8.645224618e-05f, +5.751117153e-05f,
-    /* 24, 2 */ -8.684540791e-05f, -2.951540942e-05f, +2.088206066e-04f, +5.506594457e-04f, +6.952187414e-04f, +2.469379129e-04f, -9.818199274e-04f, -2.694754852e-03f, -4.116618896e-03f, -4.369446535e-03f, -3.024096686e-03f, -4.505940556e-04f, +2.312365817e-03f, +4.120192033e-03f, +4.355078033e-03f, +3.214588722e-03f, +1.494083528e-03f, +5.601692583e-05f, -6.349341530e-04f, -6.360467505e-04f, -3.144802134e-04f, -2.483132916e-05f, +8.514047439e-05f, +6.091502927e-05f,
-    /* 24, 3 */ -8.587775422e-05f, -3.807920270e-05f, +1.889395528e-04f, +5.309813040e-04f, +6.997709178e-04f, +2.979208532e-04f, -8.849487633e-04f, -2.586556795e-03f, -4.054031257e-03f, -4.399725659e-03f, -3.152177828e-03f, -6.297421881e-04f, +2.157318805e-03f, +4.050898074e-03f, +4.386669491e-03f, +3.312658663e-03f, +1.600975431e-03f, +1.260549593e-04f, -6.147894349e-04f, -6.497970322e-04f, -3.364651980e-04f, -3.801847602e-05f, +8.328608571e-05f, +6.423360450e-05f,
-    /* 24, 4 */ -8.454371894e-05f, -4.589171696e-05f, +1.695896910e-04f, +5.106711213e-04f, +7.020335552e-04f, +3.456869501e-04f, -7.902814402e-04f, -2.477497901e-03f, -3.986918477e-03f, -4.423502152e-03f, -3.275032702e-03f, -8.078038906e-04f, +1.998605647e-03f, +3.975230752e-03f, +4.412535626e-03f, +3.408207107e-03f, +1.708931018e-03f, +1.991476106e-04f, -5.917751493e-04f, -6.621910968e-04f, -3.585839047e-04f, -5.196800512e-05f, +8.086178430e-05f, +6.744196867e-05f,
-    /* 24, 5 */ -8.287340509e-05f, -5.296545744e-05f, +1.508120534e-04f, +4.898254962e-04f, +7.021037953e-04f, +3.902463858e-04f, -6.979482496e-04f, -2.367809282e-03f, -3.915483754e-03f, -4.440812209e-03f, -3.392482395e-03f, -9.844731162e-04f, +1.836487379e-03f, +3.893263974e-03f, +4.432542967e-03f, +3.500997660e-03f, +1.817757983e-03f, +2.752365501e-04f, -5.658270331e-04f, -6.731219472e-04f, -3.807642824e-04f, -6.666895953e-05f, +7.784127492e-05f, +7.051425394e-05f,
-    /* 24, 6 */ -8.089676755e-05f, -5.931521393e-05f, +1.326437227e-04f, +4.685385820e-04f, +7.000812546e-04f, +4.316170765e-04f, -6.080707472e-04f, -2.257718867e-03f, -3.839936544e-03f, -4.451705229e-03f, -3.504360214e-03f, -1.159447072e-03f, +1.671232927e-03f, +3.805085432e-03f, +4.446568950e-03f, +3.590795947e-03f, +1.927257648e-03f, +3.542543807e-04f, -5.368865161e-04f, -6.824826149e-04f, -4.029306956e-04f, -8.210689127e-05f, +7.419942176e-05f, +7.342372810e-05f,
-    /* 24, 7 */ -7.864349144e-05f, -6.495790319e-05f, +1.151178633e-04f, +4.469018792e-04f, +6.960676605e-04f, +4.698244236e-04f, -5.207616239e-04f, -2.147450881e-03f, -3.760491970e-03f, -4.456243581e-03f, -3.610512013e-03f, -1.332426925e-03f, +1.503118492e-03f, +3.710796487e-03f, +4.454502333e-03f, +3.677370219e-03f, +2.037225356e-03f, +4.361246060e-04f, -5.049010493e-04f, -6.901664903e-04f, -4.250040411e-04f, -9.826376366e-05f, +6.991240915e-05f, +7.614287656e-05f,
-    /* 24, 8 */ -7.614287656e-05f, -6.991240915e-05f, +9.826376366e-05f, +4.250040411e-04f, +6.901664903e-04f, +5.049010493e-04f, -4.361246060e-04f, -2.037225356e-03f, -3.677370219e-03f, -4.454502333e-03f, -3.710796487e-03f, -1.503118492e-03f, +1.332426925e-03f, +3.610512013e-03f, +4.456243581e-03f, +3.760491970e-03f, +2.147450881e-03f, +5.207616239e-04f, -4.698244236e-04f, -6.960676605e-04f, -4.469018792e-04f, -1.151178633e-04f, +6.495790319e-05f, +7.864349144e-05f,
-    /* 24, 9 */ -7.342372810e-05f, -7.419942176e-05f, +8.210689127e-05f, +4.029306956e-04f, +6.824826149e-04f, +5.368865161e-04f, -3.542543807e-04f, -1.927257648e-03f, -3.590795947e-03f, -4.446568950e-03f, -3.805085432e-03f, -1.671232927e-03f, +1.159447072e-03f, +3.504360214e-03f, +4.451705229e-03f, +3.839936544e-03f, +2.257718867e-03f, +6.080707472e-04f, -4.316170765e-04f, -7.000812546e-04f, -4.685385820e-04f, -1.326437227e-04f, +5.931521393e-05f, +8.089676755e-05f,
-    /* 24,10 */ -7.051425394e-05f, -7.784127492e-05f, +6.666895953e-05f, +3.807642824e-04f, +6.731219472e-04f, +5.658270331e-04f, -2.752365501e-04f, -1.817757983e-03f, -3.500997660e-03f, -4.432542967e-03f, -3.893263974e-03f, -1.836487379e-03f, +9.844731162e-04f, +3.392482395e-03f, +4.440812209e-03f, +3.915483754e-03f, +2.367809282e-03f, +6.979482496e-04f, -3.902463858e-04f, -7.021037953e-04f, -4.898254962e-04f, -1.508120534e-04f, +5.296545744e-05f, +8.287340509e-05f,
-    /* 24,11 */ -6.744196867e-05f, -8.086178430e-05f, +5.196800512e-05f, +3.585839047e-04f, +6.621910968e-04f, +5.917751493e-04f, -1.991476106e-04f, -1.708931018e-03f, -3.408207107e-03f, -4.412535626e-03f, -3.975230752e-03f, -1.998605647e-03f, +8.078038906e-04f, +3.275032702e-03f, +4.423502152e-03f, +3.986918477e-03f, +2.477497901e-03f, +7.902814402e-04f, -3.456869501e-04f, -7.020335552e-04f, -5.106711213e-04f, -1.695896910e-04f, +4.589171696e-05f, +8.454371894e-05f,
-    /* 24,12 */ -6.423360450e-05f, -8.328608571e-05f, +3.801847602e-05f, +3.364651980e-04f, +6.497970322e-04f, +6.147894349e-04f, -1.260549593e-04f, -1.600975431e-03f, -3.312658663e-03f, -4.386669491e-03f, -4.050898074e-03f, -2.157318805e-03f, +6.297421881e-04f, +3.152177828e-03f, +4.399725659e-03f, +4.054031257e-03f, +2.586556795e-03f, +8.849487633e-04f, -2.979208532e-04f, -6.997709178e-04f, -5.309813040e-04f, -1.889395528e-04f, +3.807920270e-05f, +8.587775422e-05f,
-    /* 24,13 */ -6.091502927e-05f, -8.514047439e-05f, +2.483132916e-05f, +3.144802134e-04f, +6.360467505e-04f, +6.349341530e-04f, -5.601692583e-05f, -1.494083528e-03f, -3.214588722e-03f, -4.355078033e-03f, -4.120192033e-03f, -2.312365817e-03f, +4.505940556e-04f, +3.024096686e-03f, +4.369446535e-03f, +4.116618896e-03f, +2.694754852e-03f, +9.818199274e-04f, -2.469379129e-04f, -6.952187414e-04f, -5.506594457e-04f, -2.088206066e-04f, +2.951540942e-05f, +8.684540791e-05f,
-    /* 24,14 */ -5.751117153e-05f, -8.645224618e-05f, +1.241413728e-05f, +2.926973166e-04f, +6.210469572e-04f, +6.522789212e-04f, +1.091717027e-05f, -1.388440877e-03f, -3.114235078e-03f, -4.317905196e-03f, -4.183052585e-03f, -2.463494124e-03f, +2.706680808e-04f, +2.890980043e-03f, +4.332641998e-03f, +4.174485032e-03f, +2.801858302e-03f, +1.080756061e-03f, -1.927359117e-04f, -6.882827247e-04f, -5.696067266e-04f, -2.291878545e-04f, +2.019027119e-05f, +8.741655630e-05f,
-    /* 24,15 */ -5.404595280e-05f, -8.724954076e-05f, +7.712041122e-07f, +2.711811033e-04f, +6.049037547e-04f, +6.668983668e-04f, +7.470693818e-05f, -1.284225967e-03f, -3.011836329e-03f, -4.275304929e-03f, -4.239433597e-03f, -2.610460208e-03f, +9.027467135e-05f, +2.753030129e-03f, +4.289302846e-03f, +4.227440709e-03f, +2.907631270e-03f, +1.181609893e-03f, -1.353208099e-04f, -6.788717735e-04f, -5.877223422e-04f, -2.499923290e-04f, +1.009631262e-05f, +8.756118778e-05f,
-    /* 24, 0 */ -4.836862817e-05f, -2.381906908e-04f, -2.861422699e-04f, +1.419765781e-04f, +9.779307384e-04f, +1.431118485e-03f, +4.239072727e-04f, -2.320049614e-03f, -5.516524807e-03f, -6.885468951e-03f, -4.882970050e-03f, -1.652445539e-04f, +4.647640808e-03f, +6.864975932e-03f, +5.679465803e-03f, +2.528057977e-03f, -2.982544427e-04f, -1.420326139e-03f, -1.029081461e-03f, -1.868092348e-04f, +2.758007186e-04f, +2.491702023e-04f, +5.836581816e-05f, -3.491105347e-05f,
-    /* 24, 1 */ -3.887878147e-05f, -2.267040256e-04f, -2.944876029e-04f, +9.900949096e-05f, +9.254138922e-04f, +1.435932770e-03f, +5.422031866e-04f, -2.114193296e-03f, -5.346195092e-03f, -6.891993065e-03f, -5.106971374e-03f, -4.953359135e-04f, +4.401480442e-03f, +6.830374341e-03f, +5.834433801e-03f, +2.737690485e-03f, -1.653667139e-04f, -1.403322383e-03f, -1.078579553e-03f, -2.333982604e-04f, +2.633988510e-04f, +2.595470071e-04f, +6.884149383e-05f, -3.317859772e-05f,
-    /* 24, 2 */ -2.992041863e-05f, -2.148033017e-04f, -3.009073041e-04f, +5.800387728e-05f, +8.718108917e-04f, +1.435015360e-03f, +6.530479478e-04f, -1.910998057e-03f, -5.169072824e-03f, -6.884726614e-03f, -5.319183002e-03f, -8.242352929e-04f, +4.145019341e-03f, +6.781564023e-03f, +5.980858542e-03f, +2.948401826e-03f, -2.539414214e-05f, -1.379888189e-03f, -1.126132932e-03f, -2.816211011e-04f, +2.488796810e-04f, +2.692234993e-04f, +7.976200316e-05f, -3.095924021e-05f,
-    /* 24, 3 */ -2.151306397e-05f, -2.025787804e-04f, -3.054778181e-04f, +1.904245883e-05f, +8.173942695e-04f, +1.428624316e-03f, +7.563747429e-04f, -1.710952703e-03f, -4.985763915e-03f, -6.863885651e-03f, -5.519179462e-03f, -1.151152247e-03f, +3.878819947e-03f, +6.718485032e-03f, +6.118185890e-03f, +3.159630822e-03f, +1.214850236e-04f, -1.349820125e-03f, -1.171444944e-03f, -3.313418525e-04f, +2.321939470e-04f, +2.781004545e-04f, +9.108884721e-05f, -2.823129406e-05f,
-    /* 24, 4 */ -1.367174826e-05f, -1.901175448e-04f, -3.082808136e-04f, -1.780505549e-05f, +7.624282793e-04f, +1.417028061e-03f, +8.521437270e-04f, -1.514524553e-03f, -4.796881865e-03f, -6.829722854e-03f, -5.706572744e-03f, -1.475302628e-03f, +3.603475092e-03f, +6.641118197e-03f, +6.245879909e-03f, +3.370802059e-03f, +2.750642929e-04f, -1.312931609e-03f, -1.214215433e-03f, -3.824113238e-04f, +2.133007109e-04f, +2.860774924e-04f, +1.027786538e-04f, -2.497524656e-05f,
-    /* 24, 5 */ -6.407151783e-06f, -1.775031866e-04f, -3.094025487e-04f, -5.248174754e-05f, +7.071681142e-04f, +1.400504044e-03f, +9.403414758e-04f, -1.322158275e-03f, -4.603045619e-03f, -6.782526316e-03f, -5.881013326e-03f, -1.795911068e-03f, +3.319606230e-03f, +6.549485546e-03f, +6.363424898e-03f, +3.581327596e-03f, +4.351089927e-04f, -1.269054120e-03f, -1.254141844e-03f, -4.346671648e-04f, +1.921679399e-04f, +2.930535649e-04f, +1.147831783e-04f, -2.117401174e-05f,
-    /* 24, 6 */ +2.742338831e-07f, -1.648155254e-04f, -3.089332390e-04f, -8.494321776e-05f, +6.518591895e-04f, +1.379337399e-03f, +1.020980349e-03f, -1.134274832e-03f, -4.404877423e-03f, -6.722618231e-03f, -6.042191052e-03f, -2.112213435e-03f, +3.027861551e-03f, +6.443650588e-03f, +6.470327373e-03f, +3.790608755e-03f, +6.013564365e-04f, -1.218038367e-03f, -1.290920380e-03f, -4.879340571e-04f, +1.687730668e-04f, +2.989274696e-04f, +1.270493337e-04f, -1.681317980e-05f,
-    /* 24, 7 */ +6.369927035e-06f, -1.521303593e-04f, -3.069664313e-04f, -1.151572658e-04f, +5.967364879e-04f, +1.353819611e-03f, +1.094097769e-03f, -9.512705360e-04f, -4.203000702e-03f, -6.650353458e-03f, -6.189835876e-03f, -2.423459243e-03f, +2.728914008e-03f, +6.323718452e-03f, +6.566118000e-03f, +3.998037969e-03f, +7.735162047e-04f, -1.159755419e-03f, -1.324247193e-03f, -5.420239710e-04f, +1.431035268e-04f, +3.035983857e-04f, +1.395192491e-04f, -1.188126168e-05f,
-    /* 24, 8 */ +1.188126168e-05f, -1.395192491e-04f, -3.035983857e-04f, -1.431035268e-04f, +5.420239710e-04f, +1.324247193e-03f, +1.159755419e-03f, -7.735162047e-04f, -3.998037969e-03f, -6.566118000e-03f, -6.323718452e-03f, -2.728914008e-03f, +2.423459243e-03f, +6.189835876e-03f, +6.650353458e-03f, +4.203000702e-03f, +9.512705360e-04f, -1.094097769e-03f, -1.353819611e-03f, -5.967364879e-04f, +1.151572658e-04f, +3.069664313e-04f, +1.521303593e-04f, -6.369927035e-06f,
-    /* 24, 9 */ +1.681317980e-05f, -1.270493337e-04f, -2.989274696e-04f, -1.687730668e-04f, +4.879340571e-04f, +1.290920380e-03f, +1.218038367e-03f, -6.013564365e-04f, -3.790608755e-03f, -6.470327373e-03f, -6.443650588e-03f, -3.027861551e-03f, +2.112213435e-03f, +6.042191052e-03f, +6.722618231e-03f, +4.404877423e-03f, +1.134274832e-03f, -1.020980349e-03f, -1.379337399e-03f, -6.518591895e-04f, +8.494321776e-05f, +3.089332390e-04f, +1.648155254e-04f, -2.742338831e-07f,
-    /* 24,10 */ +2.117401174e-05f, -1.147831783e-04f, -2.930535649e-04f, -1.921679399e-04f, +4.346671648e-04f, +1.254141844e-03f, +1.269054120e-03f, -4.351089927e-04f, -3.581327596e-03f, -6.363424898e-03f, -6.549485546e-03f, -3.319606230e-03f, +1.795911068e-03f, +5.881013326e-03f, +6.782526316e-03f, +4.603045619e-03f, +1.322158275e-03f, -9.403414758e-04f, -1.400504044e-03f, -7.071681142e-04f, +5.248174754e-05f, +3.094025487e-04f, +1.775031866e-04f, +6.407151783e-06f,
-    /* 24,11 */ +2.497524656e-05f, -1.027786538e-04f, -2.860774924e-04f, -2.133007109e-04f, +3.824113238e-04f, +1.214215433e-03f, +1.312931609e-03f, -2.750642929e-04f, -3.370802059e-03f, -6.245879909e-03f, -6.641118197e-03f, -3.603475092e-03f, +1.475302628e-03f, +5.706572744e-03f, +6.829722854e-03f, +4.796881865e-03f, +1.514524553e-03f, -8.521437270e-04f, -1.417028061e-03f, -7.624282793e-04f, +1.780505549e-05f, +3.082808136e-04f, +1.901175448e-04f, +1.367174826e-05f,
-    /* 24,12 */ +2.823129406e-05f, -9.108884721e-05f, -2.781004545e-04f, -2.321939470e-04f, +3.313418525e-04f, +1.171444944e-03f, +1.349820125e-03f, -1.214850236e-04f, -3.159630822e-03f, -6.118185890e-03f, -6.718485032e-03f, -3.878819947e-03f, +1.151152247e-03f, +5.519179462e-03f, +6.863885651e-03f, +4.985763915e-03f, +1.710952703e-03f, -7.563747429e-04f, -1.428624316e-03f, -8.173942695e-04f, -1.904245883e-05f, +3.054778181e-04f, +2.025787804e-04f, +2.151306397e-05f,
-    /* 24,13 */ +3.095924021e-05f, -7.976200316e-05f, -2.692234993e-04f, -2.488796810e-04f, +2.816211011e-04f, +1.126132932e-03f, +1.379888189e-03f, +2.539414214e-05f, -2.948401826e-03f, -5.980858542e-03f, -6.781564023e-03f, -4.145019341e-03f, +8.242352929e-04f, +5.319183002e-03f, +6.884726614e-03f, +5.169072824e-03f, +1.910998057e-03f, -6.530479478e-04f, -1.435015360e-03f, -8.718108917e-04f, -5.800387728e-05f, +3.009073041e-04f, +2.148033017e-04f, +2.992041863e-05f,
-    /* 24,14 */ +3.317859772e-05f, -6.884149383e-05f, -2.595470071e-04f, -2.633988510e-04f, +2.333982604e-04f, +1.078579553e-03f, +1.403322383e-03f, +1.653667139e-04f, -2.737690485e-03f, -5.834433801e-03f, -6.830374341e-03f, -4.401480442e-03f, +4.953359135e-04f, +5.106971374e-03f, +6.891993065e-03f, +5.346195092e-03f, +2.114193296e-03f, -5.422031866e-04f, -1.435932770e-03f, -9.254138922e-04f, -9.900949096e-05f, +2.944876029e-04f, +2.267040256e-04f, +3.887878147e-05f,
-    /* 24,15 */ +3.491105347e-05f, -5.836581816e-05f, -2.491702023e-04f, -2.758007186e-04f, +1.868092348e-04f, +1.029081461e-03f, +1.420326139e-03f, +2.982544427e-04f, -2.528057977e-03f, -5.679465803e-03f, -6.864975932e-03f, -4.647640808e-03f, +1.652445539e-04f, +4.882970050e-03f, +6.885468951e-03f, +5.516524807e-03f, +2.320049614e-03f, -4.239072727e-04f, -1.431118485e-03f, -9.779307384e-04f, -1.419765781e-04f, +2.861422699e-04f, +2.381906908e-04f, +4.836862817e-05f,
-    /* 24, 0 */ +1.364396009e-04f, +7.446376994e-05f, -3.699603221e-04f, -7.278325124e-04f, -5.051635567e-05f, +1.645033952e-03f, +2.378022613e-03f, -2.243714932e-04f, -5.680096534e-03f, -9.704626250e-03f, -7.823014841e-03f, -2.751390883e-04f, +7.480820734e-03f, +9.788905453e-03f, +6.030582333e-03f, +5.101196376e-04f, -2.328731157e-03f, -1.748114996e-03f, -3.640531891e-05f, +7.242350145e-04f, +4.042879967e-04f, -5.742334247e-05f, -1.414906982e-04f, -2.710774794e-05f,
-    /* 24, 1 */ +1.307026563e-04f, +8.975162518e-05f, -3.355241044e-04f, -7.270603554e-04f, -1.326866063e-04f, +1.538422151e-03f, +2.413247311e-03f, +4.875121157e-05f, -5.324161431e-03f, -9.595517291e-03f, -8.141086512e-03f, -8.245287223e-04f, +7.115425083e-03f, +9.847646625e-03f, +6.374200107e-03f, +8.077901021e-04f, -2.264974711e-03f, -1.846937004e-03f, -1.278166248e-04f, +7.160485626e-04f, +4.382702758e-04f, -3.863673145e-05f, -1.457592711e-04f, -3.374854096e-05f,
-    /* 24, 2 */ +1.243758393e-04f, +1.032931784e-04f, -3.012044148e-04f, -7.221532843e-04f, -2.098818030e-04f, +1.428995714e-03f, +2.434853697e-03f, +3.086181402e-04f, -4.964188024e-03f, -9.462372525e-03f, -8.434212217e-03f, -1.371256439e-03f, +6.727842835e-03f, +9.880231223e-03f, +6.709529590e-03f, +1.116608515e-03f, -2.186408722e-03f, -1.940762958e-03f, -2.234175210e-04f, +7.030713845e-04f, +4.716595396e-04f, -1.812362539e-05f, -1.491486840e-04f, -4.073257728e-05f,
-    /* 24, 3 */ +1.175537217e-04f, +1.151066589e-04f, -2.672136493e-04f, -7.133593846e-04f, -2.819161814e-04f, +1.317455363e-03f, +2.443336794e-03f, +5.546728855e-04f, -4.601573558e-03f, -9.306067159e-03f, -8.701668636e-03f, -1.913559980e-03f, +6.319179241e-03f, +9.886134123e-03f, +7.035155238e-03f, +1.435731166e-03f, -2.092745601e-03f, -2.028850662e-03f, -3.228698520e-04f, +6.851212972e-04f, +5.041985339e-04f, +4.082412249e-06f, -1.515631236e-04f, -4.801831197e-05f,
-    /* 24, 4 */ +1.103288160e-04f, +1.252215041e-04f, -2.337507561e-04f, -7.009379926e-04f, -3.486413414e-04f, +1.204483360e-03f, +2.439234434e-03f, +7.864337317e-04f, -4.237695644e-03f, -9.127552920e-03f, -8.942835031e-03f, -2.449695551e-03f, +5.890625670e-03f, +9.864926907e-03f, +7.349672574e-03f, +1.764247300e-03f, -1.983757790e-03f, -2.110456450e-03f, -4.257977068e-04f, +6.620377298e-04f, +5.356216172e-04f, +2.793344097e-05f, -1.529084143e-04f, -5.555842361e-05f,
-    /* 24, 5 */ +1.027909684e-04f, +1.336775649e-04f, -2.010005851e-04f, -6.851576168e-04f, -4.099455518e-04f, +1.090740633e-03f, +2.423123355e-03f, +1.003494037e-03f, -3.873906570e-03f, -8.927853008e-03f, -9.157195135e-03f, -2.977945083e-03f, +5.443455012e-03f, +9.816280735e-03f, +7.651694576e-03f, +2.101181791e-03f, -1.859280606e-03f, -2.184839011e-03f, -5.317880090e-04f, +6.336836952e-04f, +5.656561208e-04f, +5.336672075e-05f, -1.530928622e-04f, -6.329988035e-05f,
-    /* 24, 6 */ +9.502680145e-05f, +1.405242734e-04f, -1.691333585e-04f, -6.662938873e-04f, -4.657528710e-04f, +9.768641187e-04f, +2.395615219e-03f, +1.205522243e-03f, -3.511527821e-03f, -8.708056786e-03f, -9.344338564e-03f, -3.496623369e-03f, +4.979016698e-03f, +9.739968779e-03f, +7.939858067e-03f, +2.445498177e-03f, -1.719214825e-03f, -2.251263312e-03f, -6.403913399e-04f, +5.999476948e-04f, +5.940238143e-04f, +8.030437567e-05f, -1.520281231e-04f, -7.118405837e-05f,
-    /* 24, 7 */ +8.711921055e-05f, +1.458197836e-04f, -1.383042613e-04f, -6.446275435e-04f, -5.160220948e-04f, +8.634643034e-04f, +2.357352548e-03f, +1.392261511e-03f, -3.151844842e-03f, -8.469314215e-03f, -9.503961719e-03f, -4.004085039e-03f, +4.498731341e-03f, +9.635868210e-03f, +8.212830089e-03f, +2.796102059e-03f, -1.563529005e-03f, -2.309004616e-03f, -7.511229995e-04f, +5.607455425e-04f, +6.204424737e-04f, +1.086531499e-04f, -1.496300883e-04f, -7.914691395e-05f,
-    /* 24, 8 */ +7.914691395e-05f, +1.496300883e-04f, -1.086531499e-04f, -6.204424737e-04f, -5.607455425e-04f, +7.511229995e-04f, +2.309004616e-03f, +1.563529005e-03f, -2.796102059e-03f, -8.212830089e-03f, -9.635868210e-03f, -4.498731341e-03f, +4.004085039e-03f, +9.503961719e-03f, +8.469314215e-03f, +3.151844842e-03f, -1.392261511e-03f, -2.357352548e-03f, -8.634643034e-04f, +5.160220948e-04f, +6.446275435e-04f, +1.383042613e-04f, -1.458197836e-04f, -8.711921055e-05f,
-    /* 24, 9 */ +7.118405837e-05f, +1.520281231e-04f, -8.030437567e-05f, -5.940238143e-04f, -5.999476948e-04f, +6.403913399e-04f, +2.251263312e-03f, +1.719214825e-03f, -2.445498177e-03f, -7.939858067e-03f, -9.739968779e-03f, -4.979016698e-03f, +3.496623369e-03f, +9.344338564e-03f, +8.708056786e-03f, +3.511527821e-03f, -1.205522243e-03f, -2.395615219e-03f, -9.768641187e-04f, +4.657528710e-04f, +6.662938873e-04f, +1.691333585e-04f, -1.405242734e-04f, -9.502680145e-05f,
-    /* 24,10 */ +6.329988035e-05f, +1.530928622e-04f, -5.336672075e-05f, -5.656561208e-04f, -6.336836952e-04f, +5.317880090e-04f, +2.184839011e-03f, +1.859280606e-03f, -2.101181791e-03f, -7.651694576e-03f, -9.816280735e-03f, -5.443455012e-03f, +2.977945083e-03f, +9.157195135e-03f, +8.927853008e-03f, +3.873906570e-03f, -1.003494037e-03f, -2.423123355e-03f, -1.090740633e-03f, +4.099455518e-04f, +6.851576168e-04f, +2.010005851e-04f, -1.336775649e-04f, -1.027909684e-04f,
-    /* 24,11 */ +5.555842361e-05f, +1.529084143e-04f, -2.793344097e-05f, -5.356216172e-04f, -6.620377298e-04f, +4.257977068e-04f, +2.110456450e-03f, +1.983757790e-03f, -1.764247300e-03f, -7.349672574e-03f, -9.864926907e-03f, -5.890625670e-03f, +2.449695551e-03f, +8.942835031e-03f, +9.127552920e-03f, +4.237695644e-03f, -7.864337317e-04f, -2.439234434e-03f, -1.204483360e-03f, +3.486413414e-04f, +7.009379926e-04f, +2.337507561e-04f, -1.252215041e-04f, -1.103288160e-04f,
-    /* 24,12 */ +4.801831197e-05f, +1.515631236e-04f, -4.082412249e-06f, -5.041985339e-04f, -6.851212972e-04f, +3.228698520e-04f, +2.028850662e-03f, +2.092745601e-03f, -1.435731166e-03f, -7.035155238e-03f, -9.886134123e-03f, -6.319179241e-03f, +1.913559980e-03f, +8.701668636e-03f, +9.306067159e-03f, +4.601573558e-03f, -5.546728855e-04f, -2.443336794e-03f, -1.317455363e-03f, +2.819161814e-04f, +7.133593846e-04f, +2.672136493e-04f, -1.151066589e-04f, -1.175537217e-04f,
-    /* 24,13 */ +4.073257728e-05f, +1.491486840e-04f, +1.812362539e-05f, -4.716595396e-04f, -7.030713845e-04f, +2.234175210e-04f, +1.940762958e-03f, +2.186408722e-03f, -1.116608515e-03f, -6.709529590e-03f, -9.880231223e-03f, -6.727842835e-03f, +1.371256439e-03f, +8.434212217e-03f, +9.462372525e-03f, +4.964188024e-03f, -3.086181402e-04f, -2.434853697e-03f, -1.428995714e-03f, +2.098818030e-04f, +7.221532843e-04f, +3.012044148e-04f, -1.032931784e-04f, -1.243758393e-04f,
-    /* 24,14 */ +3.374854096e-05f, +1.457592711e-04f, +3.863673145e-05f, -4.382702758e-04f, -7.160485626e-04f, +1.278166248e-04f, +1.846937004e-03f, +2.264974711e-03f, -8.077901021e-04f, -6.374200107e-03f, -9.847646625e-03f, -7.115425083e-03f, +8.245287223e-04f, +8.141086512e-03f, +9.595517291e-03f, +5.324161431e-03f, -4.875121157e-05f, -2.413247311e-03f, -1.538422151e-03f, +1.326866063e-04f, +7.270603554e-04f, +3.355241044e-04f, -8.975162518e-05f, -1.307026563e-04f,
-    /* 24,15 */ +2.710774794e-05f, +1.414906982e-04f, +5.742334247e-05f, -4.042879967e-04f, -7.242350145e-04f, +3.640531891e-05f, +1.748114996e-03f, +2.328731157e-03f, -5.101196376e-04f, -6.030582333e-03f, -9.788905453e-03f, -7.480820734e-03f, +2.751390883e-04f, +7.823014841e-03f, +9.704626250e-03f, +5.680096534e-03f, +2.243714932e-04f, -2.378022613e-03f, -1.645033952e-03f, +5.051635567e-05f, +7.278325124e-04f, +3.699603221e-04f, -7.446376994e-05f, -1.364396009e-04f,
-    /* 20, 0 */ +1.366654441e-04f, -5.248309364e-04f, -9.559425272e-04f, +4.495080153e-04f, +2.846407623e-03f, +1.989454068e-03f, -4.491151594e-03f, -1.156100448e-02f, -1.065698581e-02f, -3.895768346e-04f, +1.023895907e-02f, +1.180960294e-02f, +5.007407400e-03f, -1.738511442e-03f, -2.938517986e-03f, -6.019203323e-04f, +9.329195550e-04f, +5.763302237e-04f, -1.134902041e-04f, -1.824770389e-04f,
-    /* 20, 1 */ +1.568890194e-04f, -4.728495798e-04f, -9.708996289e-04f, +3.024354413e-04f, +2.741035078e-03f, +2.215509786e-03f, -3.978754642e-03f, -1.127853170e-02f, -1.103432131e-02f, -1.167153605e-03f, +9.781544627e-03f, +1.202253469e-02f, +5.525210549e-03f, -1.462933465e-03f, -3.016077094e-03f, -7.588827792e-04f, +9.015285321e-04f, +6.268920900e-04f, -8.735502929e-05f, -1.921860197e-04f,
-    /* 20, 2 */ +1.741940978e-04f, -4.208194393e-04f, -9.781360984e-04f, +1.614183836e-04f, +2.623714429e-03f, +2.416571115e-03f, -3.472449249e-03f, -1.096411041e-02f, -1.136986548e-02f, -1.940007910e-03f, +9.286243980e-03f, +1.219815240e-02f, +6.042182027e-03f, -1.163118517e-03f, -3.077830056e-03f, -9.195341683e-04f, +8.615147935e-04f, +6.760417132e-04f, -5.827810709e-05f, -2.008073985e-04f,
-    /* 20, 3 */ +1.886370492e-04f, -3.691494362e-04f, -9.780356474e-04f, +2.709710175e-05f, +2.495775707e-03f, +2.592671089e-03f, -2.974378699e-03f, -1.061978749e-02f, -1.166272581e-02f, -2.705018824e-03f, +8.754750074e-03f, +1.233496472e-02f, +6.555887236e-03f, -8.396136973e-04f, -3.122565398e-03f, -1.082944596e-03f, +8.126754773e-04f, +7.232876858e-04f, -2.630548656e-05f, -2.081598890e-04f,
-    /* 20, 4 */ +2.002956356e-04f, -3.182221327e-04f, -9.710157868e-04f, -9.996474913e-05f, +2.358556029e-03f, +2.743978910e-03f, -2.486586970e-03f, -1.024771819e-02f, -1.191222039e-02f, -3.459106327e-03f, +8.188939591e-03f, +1.243164652e-02f, +7.063848473e-03f, -4.931158341e-04f, -3.149124311e-03f, -1.248118895e-03f, +7.548636055e-04f, +7.681251779e-04f, +8.487693398e-06f, -2.140618814e-04f,
-    /* 20, 5 */ +2.092671085e-04f, -2.683920446e-04f, -9.575231021e-04f, -2.192806382e-04f, +2.213390969e-03f, +2.870794883e-03f, -2.011009640e-03f, -9.850152742e-03f, -1.211787969e-02f, -4.199247312e-03f, +7.590864160e-03f, +1.248704815e-02f, +7.563557889e-03f, -1.244715801e-04f, -3.156409832e-03f, -1.414000676e-03f, +6.879919170e-04f, +8.100393630e-04f, +4.599617124e-05f, -2.183332212e-04f,
-    /* 20, 6 */ +2.156662323e-04f, -2.199842607e-04f, -9.380285157e-04f, -3.304411223e-04f, +2.061606212e-03f, +2.973544666e-03f, -1.549465619e-03f, -9.429422833e-03f, -1.227944713e-02f, -4.922491262e-03f, +6.962740532e-03f, +1.250020393e-02f, +8.052490864e-03f, +2.653234199e-04f, -3.143395899e-03f, -1.579476941e-03f, +6.120364145e-04f, +8.485090918e-04f, +8.608374363e-05f, -2.207970734e-04f,
-    /* 20, 7 */ +2.196232573e-04f, -1.732933680e-04f, -9.130225739e-04f, -4.331132727e-04f, +1.904509553e-03f, +3.052772891e-03f, -1.103649750e-03f, -8.987927630e-03f, -1.239687839e-02f, -5.625975475e-03f, +6.306939763e-03f, +1.247033951e-02f, +8.528119711e-03f, +6.751263085e-04f, -3.109136222e-03f, -1.743383273e-03f, +5.270395872e-04f, +8.830107920e-04f, +1.285826773e-04f, -2.212818602e-04f,
-    /* 20, 8 */ +2.212818602e-04f, -1.285826773e-04f, -8.830107920e-04f, -5.270395872e-04f, +1.743383273e-03f, +3.109136222e-03f, -6.751263085e-04f, -8.528119711e-03f, -1.247033951e-02f, -6.306939763e-03f, +5.625975475e-03f, +1.239687839e-02f, +8.987927630e-03f, +1.103649750e-03f, -3.052772891e-03f, -1.904509553e-03f, +4.331132727e-04f, +9.130225739e-04f, +1.732933680e-04f, -2.196232573e-04f,
-    /* 20, 9 */ +2.207970734e-04f, -8.608374363e-05f, -8.485090918e-04f, -6.120364145e-04f, +1.579476941e-03f, +3.143395899e-03f, -2.653234199e-04f, -8.052490864e-03f, -1.250020393e-02f, -6.962740532e-03f, +4.922491262e-03f, +1.227944713e-02f, +9.429422833e-03f, +1.549465619e-03f, -2.973544666e-03f, -2.061606212e-03f, +3.304411223e-04f, +9.380285157e-04f, +2.199842607e-04f, -2.156662323e-04f,
-    /* 20,10 */ +2.183332212e-04f, -4.599617124e-05f, -8.100393630e-04f, -6.879919170e-04f, +1.414000676e-03f, +3.156409832e-03f, +1.244715801e-04f, -7.563557889e-03f, -1.248704815e-02f, -7.590864160e-03f, +4.199247312e-03f, +1.211787969e-02f, +9.850152742e-03f, +2.011009640e-03f, -2.870794883e-03f, -2.213390969e-03f, +2.192806382e-04f, +9.575231021e-04f, +2.683920446e-04f, -2.092671085e-04f,
-    /* 20,11 */ +2.140618814e-04f, -8.487693398e-06f, -7.681251779e-04f, -7.548636055e-04f, +1.248118895e-03f, +3.149124311e-03f, +4.931158341e-04f, -7.063848473e-03f, -1.243164652e-02f, -8.188939591e-03f, +3.459106327e-03f, +1.191222039e-02f, +1.024771819e-02f, +2.486586970e-03f, -2.743978910e-03f, -2.358556029e-03f, +9.996474913e-05f, +9.710157868e-04f, +3.182221327e-04f, -2.002956356e-04f,
-    /* 20,12 */ +2.081598890e-04f, +2.630548656e-05f, -7.232876858e-04f, -8.126754773e-04f, +1.082944596e-03f, +3.122565398e-03f, +8.396136973e-04f, -6.555887236e-03f, -1.233496472e-02f, -8.754750074e-03f, +2.705018824e-03f, +1.166272581e-02f, +1.061978749e-02f, +2.974378699e-03f, -2.592671089e-03f, -2.495775707e-03f, -2.709710175e-05f, +9.780356474e-04f, +3.691494362e-04f, -1.886370492e-04f,
-    /* 20,13 */ +2.008073985e-04f, +5.827810709e-05f, -6.760417132e-04f, -8.615147935e-04f, +9.195341683e-04f, +3.077830056e-03f, +1.163118517e-03f, -6.042182027e-03f, -1.219815240e-02f, -9.286243980e-03f, +1.940007910e-03f, +1.136986548e-02f, +1.096411041e-02f, +3.472449249e-03f, -2.416571115e-03f, -2.623714429e-03f, -1.614183836e-04f, +9.781360984e-04f, +4.208194393e-04f, -1.741940978e-04f,
-    /* 20,14 */ +1.921860197e-04f, +8.735502929e-05f, -6.268920900e-04f, -9.015285321e-04f, +7.588827792e-04f, +3.016077094e-03f, +1.462933465e-03f, -5.525210549e-03f, -1.202253469e-02f, -9.781544627e-03f, +1.167153605e-03f, +1.103432131e-02f, +1.127853170e-02f, +3.978754642e-03f, -2.215509786e-03f, -2.741035078e-03f, -3.024354413e-04f, +9.708996289e-04f, +4.728495798e-04f, -1.568890194e-04f,
-    /* 20,15 */ +1.824770389e-04f, +1.134902041e-04f, -5.763302237e-04f, -9.329195550e-04f, +6.019203323e-04f, +2.938517986e-03f, +1.738511442e-03f, -5.007407400e-03f, -1.180960294e-02f, -1.023895907e-02f, +3.895768346e-04f, +1.065698581e-02f, +1.156100448e-02f, +4.491151594e-03f, -1.989454068e-03f, -2.846407623e-03f, -4.495080153e-04f, +9.559425272e-04f, +5.248309364e-04f, -1.366654441e-04f,
-    /* 20, 0 */ +2.228492143e-04f, +8.155042897e-05f, -9.008994790e-04f, -8.358434283e-04f, +2.057950411e-03f, +3.687980724e-03f, -2.439509438e-03f, -1.276984908e-02f, -1.372824692e-02f, -5.233437973e-04f, +1.325794606e-02f, +1.324423486e-02f, +3.079014715e-03f, -3.569583683e-03f, -2.275574997e-03f, +7.329307333e-04f, +9.595727172e-04f, -3.951670647e-05f, -2.357435643e-04f, +0.000000000e+00f,
-    /* 20, 1 */ +2.085936177e-04f, +1.192685572e-04f, -8.383784628e-04f, -9.252931617e-04f, +1.836793834e-03f, +3.772148819e-03f, -1.820843931e-03f, -1.225552529e-02f, -1.413563751e-02f, -1.567452511e-03f, +1.272631251e-02f, +1.367510758e-02f, +3.736377939e-03f, -3.415952420e-03f, -2.487640644e-03f, +6.166326985e-04f, +1.013551226e-03f, +6.721135679e-06f, -2.469830254e-04f, +3.513221827e-04f,
-    /* 20, 2 */ +1.932641301e-04f, +1.526114972e-04f, -7.728409668e-04f, -1.001322392e-03f, +1.614057279e-03f, +3.823286477e-03f, -1.225775962e-03f, -1.170500117e-02f, -1.447891891e-02f, -2.603840968e-03f, +1.213529571e-02f, +1.405908160e-02f, +4.408408028e-03f, -3.226289363e-03f, -2.692058620e-03f, +4.871526668e-04f, +1.061979909e-03f, +5.699759108e-05f, -2.562708188e-04f, -2.243392330e-05f,
-    /* 20, 3 */ +1.771389305e-04f, +1.815689683e-04f, -7.050956564e-04f, -1.064087220e-03f, +1.391605775e-03f, +3.842769943e-03f, -6.568264230e-04f, -1.112214974e-02f, -1.475727496e-02f, -3.627416831e-03f, +1.148720750e-02f, +1.439298630e-02f, +5.091721334e-03f, -3.000017933e-03f, -2.886692602e-03f, +3.448244648e-04f, +1.104003505e-03f, +1.110914327e-04f, -2.633104157e-04f, -3.471505729e-05f,
-    /* 20, 4 */ +1.604844080e-04f, +2.061770649e-04f, -6.359221544e-04f, -1.113850250e-03f, +1.171206475e-03f, +3.832136817e-03f, -1.162685315e-04f, -1.051095143e-02f, -1.497027375e-02f, -4.633169088e-03f, +1.078471010e-02f, +1.467389068e-02f, +5.782760145e-03f, -2.736794515e-03f, -3.069373786e-03f, +1.901162062e-04f, +1.138774993e-03f, +1.687245284e-04f, -2.678091338e-04f, -4.805250238e-05f,
-    /* 20, 5 */ +1.435528424e-04f, +2.265149998e-04f, -5.660652366e-04f, -1.150972836e-03f, +9.545189950e-04f, +3.793068954e-03f, +3.938808876e-04f, -9.875465824e-03f, -1.511786634e-02f, -5.616199746e-03f, +1.003080152e-02f, +1.489912656e-02f, +6.477812874e-03f, -2.436518983e-03f, -3.237916857e-03f, +2.363306300e-05f, +1.165464351e-03f, +2.295611999e-04f, -2.694819135e-04f, -6.235351094e-05f,
-    /* 20, 6 */ +1.265803873e-04f, +2.427015763e-04f, -4.962296614e-04f, -1.175906803e-03f, +7.430870045e-04f, +3.727374795e-03f, +8.718680321e-04f, -9.219803451e-03f, -1.520038286e-02f, -6.571754682e-03f, +9.228798617e-03f, +1.506631023e-02f, +7.173035830e-03f, -2.099343642e-03f, -3.390136682e-03f, -1.538810619e-04f, +1.183267602e-03f, +2.932081598e-04f, -2.680552395e-04f, -7.750368078e-05f,
-    /* 20, 7 */ +1.097853637e-04f, +2.548914413e-04f, -4.270756535e-04f, -1.189185758e-03f, +5.383311068e-04f, +3.636971298e-03f, +1.316206650e-03f, -8.548097577e-03f, -1.521852609e-02f, -7.495253444e-03f, +8.382317770e-03f, +1.517336238e-02f, +7.864476409e-03f, -1.725680482e-03f, -3.523865616e-03f, -3.415430197e-04f, +1.191416067e-03f, +3.592150564e-04f, -2.632711715e-04f, -9.336686615e-05f,
-    /* 20, 8 */ +9.336686615e-05f, +2.632711715e-04f, -3.592150564e-04f, -1.191416067e-03f, +3.415430197e-04f, +3.523865616e-03f, +1.725680482e-03f, -7.864476409e-03f, -1.517336238e-02f, -8.382317770e-03f, +7.495253444e-03f, +1.521852609e-02f, +8.548097577e-03f, -1.316206650e-03f, -3.636971298e-03f, -5.383311068e-04f, +1.189185758e-03f, +4.270756535e-04f, -2.548914413e-04f, -1.097853637e-04f,
-    /* 20, 9 */ +7.750368078e-05f, +2.680552395e-04f, -2.932081598e-04f, -1.183267602e-03f, +1.538810619e-04f, +3.390136682e-03f, +2.099343642e-03f, -7.173035830e-03f, -1.506631023e-02f, -9.228798617e-03f, +6.571754682e-03f, +1.520038286e-02f, +9.219803451e-03f, -8.718680321e-04f, -3.727374795e-03f, -7.430870045e-04f, +1.175906803e-03f, +4.962296614e-04f, -2.427015763e-04f, -1.265803873e-04f,
-    /* 20,10 */ +6.235351094e-05f, +2.694819135e-04f, -2.295611999e-04f, -1.165464351e-03f, -2.363306300e-05f, +3.237916857e-03f, +2.436518983e-03f, -6.477812874e-03f, -1.489912656e-02f, -1.003080152e-02f, +5.616199746e-03f, +1.511786634e-02f, +9.875465824e-03f, -3.938808876e-04f, -3.793068954e-03f, -9.545189950e-04f, +1.150972836e-03f, +5.660652366e-04f, -2.265149998e-04f, -1.435528424e-04f,
-    /* 20,11 */ +4.805250238e-05f, +2.678091338e-04f, -1.687245284e-04f, -1.138774993e-03f, -1.901162062e-04f, +3.069373786e-03f, +2.736794515e-03f, -5.782760145e-03f, -1.467389068e-02f, -1.078471010e-02f, +4.633169088e-03f, +1.497027375e-02f, +1.051095143e-02f, +1.162685315e-04f, -3.832136817e-03f, -1.171206475e-03f, +1.113850250e-03f, +6.359221544e-04f, -2.061770649e-04f, -1.604844080e-04f,
-    /* 20,12 */ +3.471505729e-05f, +2.633104157e-04f, -1.110914327e-04f, -1.104003505e-03f, -3.448244648e-04f, +2.886692602e-03f, +3.000017933e-03f, -5.091721334e-03f, -1.439298630e-02f, -1.148720750e-02f, +3.627416831e-03f, +1.475727496e-02f, +1.112214974e-02f, +6.568264230e-04f, -3.842769943e-03f, -1.391605775e-03f, +1.064087220e-03f, +7.050956564e-04f, -1.815689683e-04f, -1.771389305e-04f,
-    /* 20,13 */ +2.243392330e-05f, +2.562708188e-04f, -5.699759108e-05f, -1.061979909e-03f, -4.871526668e-04f, +2.692058620e-03f, +3.226289363e-03f, -4.408408028e-03f, -1.405908160e-02f, -1.213529571e-02f, +2.603840968e-03f, +1.447891891e-02f, +1.170500117e-02f, +1.225775962e-03f, -3.823286477e-03f, -1.614057279e-03f, +1.001322392e-03f, +7.728409668e-04f, -1.526114972e-04f, -1.932641301e-04f,
-    /* 20,14 */ -3.513221827e-04f, +2.469830254e-04f, -6.721135679e-06f, -1.013551226e-03f, -6.166326985e-04f, +2.487640644e-03f, +3.415952420e-03f, -3.736377939e-03f, -1.367510758e-02f, -1.272631251e-02f, +1.567452511e-03f, +1.413563751e-02f, +1.225552529e-02f, +1.820843931e-03f, -3.772148819e-03f, -1.836793834e-03f, +9.252931617e-04f, +8.383784628e-04f, -1.192685572e-04f, -2.085936177e-04f,
-    /* 20,15 */ +0.000000000e+00f, +2.357435643e-04f, +3.951670647e-05f, -9.595727172e-04f, -7.329307333e-04f, +2.275574997e-03f, +3.569583683e-03f, -3.079014715e-03f, -1.324423486e-02f, -1.325794606e-02f, +5.233437973e-04f, +1.372824692e-02f, +1.276984908e-02f, +2.439509438e-03f, -3.687980724e-03f, -2.057950411e-03f, +8.358434283e-04f, +9.008994790e-04f, -8.155042897e-05f, -2.228492143e-04f,
-    /* 20, 0 */ +1.941987182e-05f, +3.146481294e-04f, -2.345645569e-04f, -1.414667200e-03f, +5.144442975e-04f, +4.454307224e-03f, +1.983750799e-04f, -1.327145644e-02f, -1.714303646e-02f, -6.846700315e-04f, +1.665178821e-02f, +1.403392762e-02f, +4.892879248e-04f, -4.540173148e-03f, -7.773192529e-04f, +1.425286503e-03f, +3.160682424e-04f, -3.205185770e-04f, -3.476344875e-05f, +0.000000000e+00f,
-    /* 20, 1 */ -3.929324583e-04f, +3.051602666e-04f, -1.573970191e-04f, -1.390281543e-03f, +2.638941923e-04f, +4.333213577e-03f, +8.411158857e-04f, -1.246868983e-02f, -1.754185168e-02f, -2.049974665e-03f, +1.606968443e-02f, +1.474987505e-02f, +1.218921159e-03f, -4.587812221e-03f, -1.050600845e-03f, +1.421006956e-03f, +4.012475422e-04f, -3.223256966e-04f, -5.166761157e-05f, +0.000000000e+00f,
-    /* 20, 2 */ +0.000000000e+00f, +2.925136688e-04f, -8.512788201e-05f, -1.353337804e-03f, +2.735561011e-05f, +4.180044295e-03f, +1.436437300e-03f, -1.163198941e-02f, -1.784731333e-02f, -3.403203680e-03f, +1.539895444e-02f, +1.541325656e-02f, +1.987128326e-03f, -4.594412557e-03f, -1.332146559e-03f, +1.400789491e-03f, +4.893452569e-04f, -3.196436833e-04f, -7.000071077e-05f, +0.000000000e+00f,
-    /* 20, 3 */ +0.000000000e+00f, +2.771727451e-04f, -1.822077520e-05f, -1.305102482e-03f, -1.937209193e-04f, +3.998069961e-03f, +1.982303068e-03f, -1.076779718e-02f, -1.805915757e-02f, -4.736408619e-03f, +1.464246859e-02f, +1.601826823e-02f, +2.790083541e-03f, -4.557383277e-03f, -1.619599483e-03f, +1.363706016e-03f, +5.795104543e-04f, -3.120743969e-04f, -8.959420873e-05f, +0.000000000e+00f,
-    /* 20, 4 */ +0.000000000e+00f, +2.596009711e-04f, +4.295843246e-05f, -1.246883037e-03f, -3.981230344e-04f, +3.790645354e-03f, +2.477139789e-03f, -9.882582946e-03f, -1.817777152e-02f, -6.041793017e-03f, +1.380372215e-02f, +1.655939544e-02f, +3.623550339e-03f, -4.474387395e-03f, -1.910400883e-03f, +1.308956662e-03f, +6.708027600e-04f, -2.992550459e-04f, -1.102423612e-04f, +0.000000000e+00f,
-    /* 20, 5 */ +0.000000000e+00f, +2.402546692e-04f, +9.813963752e-05f, -1.180011107e-03f, -5.848760724e-04f, +3.561175652e-03f, +2.919834686e-03f, -8.982792490e-03f, -1.820418220e-02f, -7.311771311e-03f, +1.288681385e-02f, +1.703146227e-02f, +4.482904855e-03f, -4.343373467e-03f, -2.201805423e-03f, +1.235886510e-03f, +7.621980241e-04f, -2.808658988e-04f, -1.317024534e-04f, +0.000000000e+00f,
-    /* 20, 6 */ +0.000000000e+00f, +2.195772899e-04f, +1.471454599e-04f, -1.105826337e-03f, -7.532402115e-04f, +3.313083439e-03f, +3.309729355e-03f, -8.074797022e-03f, -1.814004021e-02f, -8.539025902e-03f, +1.189641917e-02f, +1.742967891e-02f, +5.363163073e-03f, -4.162605659e-03f, -2.490898970e-03f, +1.144001586e-03f, +8.525953702e-04f, -2.566379213e-04f, -1.536956226e-04f, +0.000000000e+00f,
-    /* 20, 7 */ +0.000000000e+00f, +1.979942392e-04f, +1.898872476e-04f, -1.025661016e-03f, -9.027053553e-04f, +3.049776817e-03f, +3.646609643e-03f, -7.164844319e-03f, -1.798759853e-02f, -9.716561844e-03f, +1.083775871e-02f, +1.774968640e-02f, +6.259011965e-03f, -3.930691879e-03f, -2.774618906e-03f, +1.032983905e-03f, +9.408256132e-04f, -2.263602294e-04f, -1.759082929e-04f, +0.000000000e+00f,
-    /* 20, 8 */ +0.000000000e+00f, +1.759082929e-04f, +2.263602294e-04f, -9.408256132e-04f, -1.032983905e-03f, +2.774618906e-03f, +3.930691879e-03f, -6.259011965e-03f, -1.774968640e-02f, -1.083775871e-02f, +9.716561844e-03f, +1.798759853e-02f, +7.164844319e-03f, -3.646609643e-03f, -3.049776817e-03f, +9.027053553e-04f, +1.025661016e-03f, -1.898872476e-04f, -1.979942392e-04f, +0.000000000e+00f,
-    /* 20, 9 */ +0.000000000e+00f, +1.536956226e-04f, +2.566379213e-04f, -8.525953702e-04f, -1.144001586e-03f, +2.490898970e-03f, +4.162605659e-03f, -5.363163073e-03f, -1.742967891e-02f, -1.189641917e-02f, +8.539025902e-03f, +1.814004021e-02f, +8.074797022e-03f, -3.309729355e-03f, -3.313083439e-03f, +7.532402115e-04f, +1.105826337e-03f, -1.471454599e-04f, -2.195772899e-04f, +0.000000000e+00f,
-    /* 20,10 */ +0.000000000e+00f, +1.317024534e-04f, +2.808658988e-04f, -7.621980241e-04f, -1.235886510e-03f, +2.201805423e-03f, +4.343373467e-03f, -4.482904855e-03f, -1.703146227e-02f, -1.288681385e-02f, +7.311771311e-03f, +1.820418220e-02f, +8.982792490e-03f, -2.919834686e-03f, -3.561175652e-03f, +5.848760724e-04f, +1.180011107e-03f, -9.813963752e-05f, -2.402546692e-04f, +0.000000000e+00f,
-    /* 20,11 */ +0.000000000e+00f, +1.102423612e-04f, +2.992550459e-04f, -6.708027600e-04f, -1.308956662e-03f, +1.910400883e-03f, +4.474387395e-03f, -3.623550339e-03f, -1.655939544e-02f, -1.380372215e-02f, +6.041793017e-03f, +1.817777152e-02f, +9.882582946e-03f, -2.477139789e-03f, -3.790645354e-03f, +3.981230344e-04f, +1.246883037e-03f, -4.295843246e-05f, -2.596009711e-04f, +0.000000000e+00f,
-    /* 20,12 */ +0.000000000e+00f, +8.959420873e-05f, +3.120743969e-04f, -5.795104543e-04f, -1.363706016e-03f, +1.619599483e-03f, +4.557383277e-03f, -2.790083541e-03f, -1.601826823e-02f, -1.464246859e-02f, +4.736408619e-03f, +1.805915757e-02f, +1.076779718e-02f, -1.982303068e-03f, -3.998069961e-03f, +1.937209193e-04f, +1.305102482e-03f, +1.822077520e-05f, -2.771727451e-04f, +0.000000000e+00f,
-    /* 20,13 */ +0.000000000e+00f, +7.000071077e-05f, +3.196436833e-04f, -4.893452569e-04f, -1.400789491e-03f, +1.332146559e-03f, +4.594412557e-03f, -1.987128326e-03f, -1.541325656e-02f, -1.539895444e-02f, +3.403203680e-03f, +1.784731333e-02f, +1.163198941e-02f, -1.436437300e-03f, -4.180044295e-03f, -2.735561011e-05f, +1.353337804e-03f, +8.512788201e-05f, -2.925136688e-04f, +0.000000000e+00f,
-    /* 20,14 */ +0.000000000e+00f, +5.166761157e-05f, +3.223256966e-04f, -4.012475422e-04f, -1.421006956e-03f, +1.050600845e-03f, +4.587812221e-03f, -1.218921159e-03f, -1.474987505e-02f, -1.606968443e-02f, +2.049974665e-03f, +1.754185168e-02f, +1.246868983e-02f, -8.411158857e-04f, -4.333213577e-03f, -2.638941923e-04f, +1.390281543e-03f, +1.573970191e-04f, -3.051602666e-04f, +3.929324583e-04f,
-    /* 20,15 */ +0.000000000e+00f, +3.476344875e-05f, +3.205185770e-04f, -3.160682424e-04f, -1.425286503e-03f, +7.773192529e-04f, +4.540173148e-03f, -4.892879248e-04f, -1.403392762e-02f, -1.665178821e-02f, +6.846700315e-04f, +1.714303646e-02f, +1.327145644e-02f, -1.983750799e-04f, -4.454307224e-03f, -5.144442975e-04f, +1.414667200e-03f, +2.345645569e-04f, -3.146481294e-04f, -1.941987182e-05f,
-    /* 16, 0 */ +3.215659774e-04f, -1.081239301e-03f, -1.047044785e-03f, +4.045780572e-03f, +3.005074105e-03f, -1.291342297e-02f, -2.083886340e-02f, -8.761305366e-04f, +2.037274022e-02f, +1.401097590e-02f, -2.379335663e-03f, -4.351475252e-03f, +8.522542940e-04f, +1.190910327e-03f, -2.874725537e-04f, -1.571395541e-04f,
-    /* 16, 1 */ +3.474336395e-04f, -9.673171402e-04f, -1.215210440e-03f, +3.716713245e-03f, +3.558195313e-03f, -1.178473019e-02f, -2.117503726e-02f, -2.622305580e-03f, +1.977768827e-02f, +1.506763496e-02f, -1.682580557e-03f, -4.628640452e-03f, +6.313208395e-04f, +1.294421768e-03f, -2.448738999e-04f, -1.853334990e-04f,
-    /* 16, 2 */ +3.654544998e-04f, -8.509694882e-04f, -1.356620316e-03f, +3.369379821e-03f, +4.037840451e-03f, -1.063463040e-02f, -2.138131359e-02f, -4.350277043e-03f, +1.905580462e-02f, +1.607371744e-02f, -9.171630004e-04f, -4.872124601e-03f, +3.850930357e-04f, +1.389803701e-03f, -1.936024914e-04f, -2.137577131e-04f,
-    /* 16, 3 */ +3.760939096e-04f, -7.339202470e-04f, -1.471475134e-03f, +3.008783957e-03f, +4.443873126e-03f, -9.472744965e-03f, -2.145880202e-02f, -6.048090342e-03f, +1.821025632e-02f, +1.701970579e-02f, -8.619500088e-05f, -5.076839304e-03f, +1.147982409e-04f, +1.475048300e-03f, -1.336143134e-04f, -2.418805517e-04f,
-    /* 16, 4 */ +3.798900997e-04f, -6.177751723e-04f, -1.560284979e-03f, +2.639777229e-03f, +4.776853126e-03f, -8.308496634e-03f, -2.140964525e-02f, -7.704060609e-03f, +1.724526338e-02f, +1.789634168e-02f, +8.064574864e-04f, -5.237819035e-03f, -1.779495980e-04f, +1.548135431e-03f, -6.499930382e-05f, -2.691226085e-04f,
-    /* 16, 5 */ +3.774404835e-04f, -5.040080805e-04f, -1.623844377e-03f, +2.267013831e-03f, +5.038003695e-03f, -7.151026424e-03f, -2.123698452e-02f, -9.306876654e-03f, +1.616607109e-02f, +1.869471933e-02f, +1.756186609e-03f, -5.350281937e-03f, -4.911465534e-04f, +1.607060019e-03f, +1.200956190e-05f, -2.948629835e-04f,
-    /* 16, 6 */ +3.693879948e-04f, -3.939497146e-04f, -1.663205192e-03f, +1.894909522e-03f, +5.229172900e-03f, -6.009115326e-03f, -2.094491570e-02f, -1.084570103e-02f, +1.497891218e-02f, +1.940637710e-02f, +2.757662946e-03f, -5.409691072e-03f, -8.224000281e-04f, +1.649860923e-03f, +9.702877105e-05f, -3.184467584e-04f,
-    /* 16, 7 */ +3.564076658e-04f, -2.887792732e-04f, -1.679647798e-03f, +1.527605146e-03f, +5.352789702e-03f, -4.891111570e-03f, -2.053843663e-02f, -1.231026521e-02f, +1.369095882e-02f, +2.002338639e-02f, +3.804864118e-03f, -5.411815390e-03f, -1.168934972e-03f, +1.674650966e-03f, +1.895185724e-04f, -3.391936346e-04f,
-    /* 16, 8 */ +3.391936346e-04f, -1.895185724e-04f, -1.674650966e-03f, +1.168934972e-03f, +5.411815390e-03f, -3.804864118e-03f, -2.002338639e-02f, -1.369095882e-02f, +1.231026521e-02f, +2.053843663e-02f, +4.891111570e-03f, -5.352789702e-03f, -1.527605146e-03f, +1.679647798e-03f, +2.887792732e-04f, -3.564076658e-04f,
-    /* 16, 9 */ +3.184467584e-04f, -9.702877105e-05f, -1.649860923e-03f, +8.224000281e-04f, +5.409691072e-03f, -2.757662946e-03f, -1.940637710e-02f, -1.497891218e-02f, +1.084570103e-02f, +2.094491570e-02f, +6.009115326e-03f, -5.229172900e-03f, -1.894909522e-03f, +1.663205192e-03f, +3.939497146e-04f, -3.693879948e-04f,
-    /* 16,10 */ +2.948629835e-04f, -1.200956190e-05f, -1.607060019e-03f, +4.911465534e-04f, +5.350281937e-03f, -1.756186609e-03f, -1.869471933e-02f, -1.616607109e-02f, +9.306876654e-03f, +2.123698452e-02f, +7.151026424e-03f, -5.038003695e-03f, -2.267013831e-03f, +1.623844377e-03f, +5.040080805e-04f, -3.774404835e-04f,
-    /* 16,11 */ +2.691226085e-04f, +6.499930382e-05f, -1.548135431e-03f, +1.779495980e-04f, +5.237819035e-03f, -8.064574864e-04f, -1.789634168e-02f, -1.724526338e-02f, +7.704060609e-03f, +2.140964525e-02f, +8.308496634e-03f, -4.776853126e-03f, -2.639777229e-03f, +1.560284979e-03f, +6.177751723e-04f, -3.798900997e-04f,
-    /* 16,12 */ +2.418805517e-04f, +1.336143134e-04f, -1.475048300e-03f, -1.147982409e-04f, +5.076839304e-03f, +8.619500088e-05f, -1.701970579e-02f, -1.821025632e-02f, +6.048090342e-03f, +2.145880202e-02f, +9.472744965e-03f, -4.443873126e-03f, -3.008783957e-03f, +1.471475134e-03f, +7.339202470e-04f, -3.760939096e-04f,
-    /* 16,13 */ +2.137577131e-04f, +1.936024914e-04f, -1.389803701e-03f, -3.850930357e-04f, +4.872124601e-03f, +9.171630004e-04f, -1.607371744e-02f, -1.905580462e-02f, +4.350277043e-03f, +2.138131359e-02f, +1.063463040e-02f, -4.037840451e-03f, -3.369379821e-03f, +1.356620316e-03f, +8.509694882e-04f, -3.654544998e-04f,
-    /* 16,14 */ +1.853334990e-04f, +2.448738999e-04f, -1.294421768e-03f, -6.313208395e-04f, +4.628640452e-03f, +1.682580557e-03f, -1.506763496e-02f, -1.977768827e-02f, +2.622305580e-03f, +2.117503726e-02f, +1.178473019e-02f, -3.558195313e-03f, -3.716713245e-03f, +1.215210440e-03f, +9.673171402e-04f, -3.474336395e-04f,
-    /* 16,15 */ +1.571395541e-04f, +2.874725537e-04f, -1.190910327e-03f, -8.522542940e-04f, +4.351475252e-03f, +2.379335663e-03f, -1.401097590e-02f, -2.037274022e-02f, +8.761305366e-04f, +2.083886340e-02f, +1.291342297e-02f, -3.005074105e-03f, -4.045780572e-03f, +1.047044785e-03f, +1.081239301e-03f, -3.215659774e-04f,
-    /* 16, 0 */ +3.737698842e-04f, -2.640449894e-04f, -1.945694549e-03f, +2.599440145e-03f, +5.499552783e-03f, -1.161604587e-02f, -2.473725459e-02f, -1.100298137e-03f, +2.435797715e-02f, +1.306966182e-02f, -5.062036618e-03f, -3.067638325e-03f, +1.905476637e-03f, +3.919780470e-04f, -3.991665042e-04f, +0.000000000e+00f,
-    /* 16, 1 */ +3.444161169e-04f, -1.448617079e-04f, -1.955541719e-03f, +2.132654952e-03f, +5.839402648e-03f, -1.015371093e-02f, -2.494083956e-02f, -3.291998323e-03f, +2.380252288e-02f, +1.450063212e-02f, -4.525267650e-03f, -3.530814272e-03f, +1.832921116e-03f, +5.273022833e-04f, -4.195866486e-04f, +0.000000000e+00f,
-    /* 16, 2 */ +3.121018536e-04f, -3.553225965e-05f, -1.937280777e-03f, +1.673279684e-03f, +6.084169165e-03f, -8.696195593e-03f, -2.497087446e-02f, -5.457102987e-03f, +2.307209479e-02f, +1.589478690e-02f, -3.888719495e-03f, -3.982156136e-03f, +1.726408630e-03f, +6.684076945e-04f, -4.340068349e-04f, +0.000000000e+00f,
-    /* 16, 3 */ +2.777843660e-04f, +6.309259068e-05f, -1.893417136e-03f, +1.226820211e-03f, +6.237358144e-03f, -7.256513778e-03f, -2.483111182e-02f, -7.578189778e-03f, +2.216959356e-02f, +1.723786448e-02f, -3.152978451e-03f, -4.414545490e-03f, +1.584716951e-03f, +8.134406195e-04f, -4.414195390e-04f, +4.634120047e-04f,
-    /* 16, 4 */ +2.423668462e-04f, +1.504100330e-04f, -1.826645633e-03f, +7.982477790e-04f, +6.303316031e-03f, -5.847027899e-03f, -2.452684878e-02f, -9.638294429e-03f, +2.109960841e-02f, +1.851566754e-02f, -2.319783877e-03f, -4.820635148e-03f, +1.407067591e-03f, +9.603162700e-04f, -4.408546251e-04f, -2.338334874e-05f,
-    /* 16, 5 */ +2.066858426e-04f, +2.260561294e-04f, -1.739797615e-03f, +3.919648528e-04f, +6.287140435e-03f, -4.479333074e-03f, -2.406484480e-02f, -1.162108621e-02f, +1.986838848e-02f, +1.971422226e-02f, -1.392055451e-03f, -5.192933984e-03f, +1.193168502e-03f, +1.106736135e-03f, -4.314017719e-04f, -4.782938304e-05f,
-    /* 16, 6 */ +1.715009195e-04f, +2.898933732e-04f, -1.635789255e-03f, +1.178042715e-05f, +6.194584811e-03f, -3.164153635e-03f, -2.345322399e-02f, -1.351103572e-02f, +1.848379497e-02f, +2.081993840e-02f, -3.739065234e-04f, -5.523897843e-03f, +9.432519997e-04f, +1.250210274e-03f, -4.122335402e-04f, -7.520965874e-05f,
-    /* 16, 7 */ +1.374865801e-04f, +3.419953130e-04f, -1.517571800e-03f, -3.391052954e-04f, +6.031958779e-03f, -1.911252903e-03f, -2.270136331e-02f, -1.529357304e-02f, +1.695523429e-02f, +2.181976838e-02f, +7.293570292e-04f, -5.806025538e-03f, +6.581070752e-04f, +1.388084428e-03f, -3.826286881e-04f, -1.052264476e-04f,
-    /* 16, 8 */ +1.052264476e-04f, +3.826286881e-04f, -1.388084428e-03f, -6.581070752e-04f, +5.806025538e-03f, -7.293570292e-04f, -2.181976838e-02f, -1.695523429e-02f, +1.529357304e-02f, +2.270136331e-02f, +1.911252903e-03f, -6.031958779e-03f, +3.391052954e-04f, +1.517571800e-03f, -3.419953130e-04f, -1.374865801e-04f,
-    /* 16, 9 */ +7.520965874e-05f, +4.122335402e-04f, -1.250210274e-03f, -9.432519997e-04f, +5.523897843e-03f, +3.739065234e-04f, -2.081993840e-02f, -1.848379497e-02f, +1.351103572e-02f, +2.345322399e-02f, +3.164153635e-03f, -6.194584811e-03f, -1.178042715e-05f, +1.635789255e-03f, -2.898933732e-04f, -1.715009195e-04f,
-    /* 16,10 */ +4.782938304e-05f, +4.314017719e-04f, -1.106736135e-03f, -1.193168502e-03f, +5.192933984e-03f, +1.392055451e-03f, -1.971422226e-02f, -1.986838848e-02f, +1.162108621e-02f, +2.406484480e-02f, +4.479333074e-03f, -6.287140435e-03f, -3.919648528e-04f, +1.739797615e-03f, -2.260561294e-04f, -2.066858426e-04f,
-    /* 16,11 */ +2.338334874e-05f, +4.408546251e-04f, -9.603162700e-04f, -1.407067591e-03f, +4.820635148e-03f, +2.319783877e-03f, -1.851566754e-02f, -2.109960841e-02f, +9.638294429e-03f, +2.452684878e-02f, +5.847027899e-03f, -6.303316031e-03f, -7.982477790e-04f, +1.826645633e-03f, -1.504100330e-04f, -2.423668462e-04f,
-    /* 16,12 */ -4.634120047e-04f, +4.414195390e-04f, -8.134406195e-04f, -1.584716951e-03f, +4.414545490e-03f, +3.152978451e-03f, -1.723786448e-02f, -2.216959356e-02f, +7.578189778e-03f, +2.483111182e-02f, +7.256513778e-03f, -6.237358144e-03f, -1.226820211e-03f, +1.893417136e-03f, -6.309259068e-05f, -2.777843660e-04f,
-    /* 16,13 */ +0.000000000e+00f, +4.340068349e-04f, -6.684076945e-04f, -1.726408630e-03f, +3.982156136e-03f, +3.888719495e-03f, -1.589478690e-02f, -2.307209479e-02f, +5.457102987e-03f, +2.497087446e-02f, +8.696195593e-03f, -6.084169165e-03f, -1.673279684e-03f, +1.937280777e-03f, +3.553225965e-05f, -3.121018536e-04f,
-    /* 16,14 */ +0.000000000e+00f, +4.195866486e-04f, -5.273022833e-04f, -1.832921116e-03f, +3.530814272e-03f, +4.525267650e-03f, -1.450063212e-02f, -2.380252288e-02f, +3.291998323e-03f, +2.494083956e-02f, +1.015371093e-02f, -5.839402648e-03f, -2.132654952e-03f, +1.955541719e-03f, +1.448617079e-04f, -3.444161169e-04f,
-    /* 16,15 */ +0.000000000e+00f, +3.991665042e-04f, -3.919780470e-04f, -1.905476637e-03f, +3.067638325e-03f, +5.062036618e-03f, -1.306966182e-02f, -2.435797715e-02f, +1.100298137e-03f, +2.473725459e-02f, +1.161604587e-02f, -5.499552783e-03f, -2.599440145e-03f, +1.945694549e-03f, +2.640449894e-04f, -3.737698842e-04f,
-    /* 16, 0 */ +1.129954761e-04f, +3.969443331e-04f, -1.897918409e-03f, +5.803605804e-04f, +7.236474393e-03f, -9.385964725e-03f, -2.874576735e-02f, -1.359743295e-03f, +2.853093461e-02f, +1.118139232e-02f, -7.102956997e-03f, -1.091735034e-03f, +2.023521864e-03f, -3.328791130e-04f, -1.523656204e-04f, +0.000000000e+00f,
-    /* 16, 1 */ +7.672972562e-05f, +4.458313625e-04f, -1.753034729e-03f, +1.022461377e-04f, +7.257902118e-03f, -7.620475041e-03f, -2.873131200e-02f, -4.066570788e-03f, +2.808336987e-02f, +1.298853535e-02f, -6.850603202e-03f, -1.630677017e-03f, +2.125649126e-03f, -2.532507071e-04f, -1.941703587e-04f, +0.000000000e+00f,
-    /* 16, 2 */ +4.409159553e-05f, +4.801879450e-04f, -1.593056257e-03f, -3.378401438e-04f, +7.175055211e-03f, -5.902082228e-03f, -2.849345261e-02f, -6.735572940e-03f, +2.740215275e-02f, +1.478830973e-02f, -6.473886365e-03f, -2.190599691e-03f, +2.200171639e-03f, -1.579695096e-04f, -2.375950982e-04f, +0.000000000e+00f,
-    /* 16, 3 */ -4.855802427e-04f, +5.008892512e-04f, -1.422085430e-03f, -7.360682089e-04f, +6.996656391e-03f, -4.246700138e-03f, -2.804039906e-02f, -9.342037235e-03f, +2.648893755e-02f, +1.656098957e-02f, -5.968640123e-03f, -2.764068406e-03f, +2.243110553e-03f, -4.727037370e-05f, -2.816859426e-04f, +0.000000000e+00f,
-    /* 16, 4 */ +0.000000000e+00f, +5.090007623e-04f, -1.244075649e-03f, -1.089544232e-03f, +6.732169339e-03f, -2.668838337e-03f, -2.738254409e-02f, -1.186200034e-02f, +2.534797081e-02f, +1.828644204e-02f, -5.332184360e-03f, -3.342863857e-03f, +2.250722132e-03f, +7.826276448e-05f, -3.253590588e-04f, +0.000000000e+00f,
-    /* 16, 5 */ +0.000000000e+00f, +5.057402285e-04f, -1.062772468e-03f, -1.396293958e-03f, +6.391628670e-03f, -1.181467029e-03f, -2.653229393e-02f, -1.427253312e-02f, +2.398607480e-02f, +1.994437434e-02f, -4.563434465e-03f, -3.918061651e-03f, +2.219584858e-03f, +2.176775461e-04f, -3.674140144e-04f, +0.000000000e+00f,
-    /* 16, 6 */ +0.000000000e+00f, +4.924395299e-04f, -8.816626027e-04f, -1.655232286e-03f, +5.985469320e-03f, +2.040926394e-04f, -2.550387540e-02f, -1.655201127e-02f, +2.241259678e-02f, +2.151458926e-02f, -3.662991573e-03f, -4.480127768e-03f, +2.146686747e-03f, +3.696399185e-04f, -4.065510896e-04f, +0.000000000e+00f,
-    /* 16, 7 */ +0.000000000e+00f, +4.705072223e-04f, -7.039312026e-04f, -1.866120323e-03f, +5.524357980e-03f, +1.478252020e-03f, -2.431312252e-02f, -1.868036788e-02f, +2.063932435e-02f, +2.297724601e-02f, -2.633211707e-03f, -5.019029099e-03f, +2.029511283e-03f, +5.324276437e-04f, -4.413924818e-04f, +0.000000000e+00f,
-    /* 16, 8 */ +0.000000000e+00f, +4.413924818e-04f, -5.324276437e-04f, -2.029511283e-03f, +5.019029099e-03f, +2.633211707e-03f, -2.297724601e-02f, -2.063932435e-02f, +1.868036788e-02f, +2.431312252e-02f, -1.478252020e-03f, -5.524357980e-03f, +1.866120323e-03f, +7.039312026e-04f, -4.705072223e-04f, +0.000000000e+00f,
-    /* 16, 9 */ +0.000000000e+00f, +4.065510896e-04f, -3.696399185e-04f, -2.146686747e-03f, +4.480127768e-03f, +3.662991573e-03f, -2.151458926e-02f, -2.241259678e-02f, +1.655201127e-02f, +2.550387540e-02f, -2.040926394e-04f, -5.985469320e-03f, +1.655232286e-03f, +8.816626027e-04f, -4.924395299e-04f, +0.000000000e+00f,
-    /* 16,10 */ +0.000000000e+00f, +3.674140144e-04f, -2.176775461e-04f, -2.219584858e-03f, +3.918061651e-03f, +4.563434465e-03f, -1.994437434e-02f, -2.398607480e-02f, +1.427253312e-02f, +2.653229393e-02f, +1.181467029e-03f, -6.391628670e-03f, +1.396293958e-03f, +1.062772468e-03f, -5.057402285e-04f, +0.000000000e+00f,
-    /* 16,11 */ +0.000000000e+00f, +3.253590588e-04f, -7.826276448e-05f, -2.250722132e-03f, +3.342863857e-03f, +5.332184360e-03f, -1.828644204e-02f, -2.534797081e-02f, +1.186200034e-02f, +2.738254409e-02f, +2.668838337e-03f, -6.732169339e-03f, +1.089544232e-03f, +1.244075649e-03f, -5.090007623e-04f, +0.000000000e+00f,
-    /* 16,12 */ +0.000000000e+00f, +2.816859426e-04f, +4.727037370e-05f, -2.243110553e-03f, +2.764068406e-03f, +5.968640123e-03f, -1.656098957e-02f, -2.648893755e-02f, +9.342037235e-03f, +2.804039906e-02f, +4.246700138e-03f, -6.996656391e-03f, +7.360682089e-04f, +1.422085430e-03f, -5.008892512e-04f, +4.855802427e-04f,
-    /* 16,13 */ +0.000000000e+00f, +2.375950982e-04f, +1.579695096e-04f, -2.200171639e-03f, +2.190599691e-03f, +6.473886365e-03f, -1.478830973e-02f, -2.740215275e-02f, +6.735572940e-03f, +2.849345261e-02f, +5.902082228e-03f, -7.175055211e-03f, +3.378401438e-04f, +1.593056257e-03f, -4.801879450e-04f, -4.409159553e-05f,
-    /* 16,14 */ +0.000000000e+00f, +1.941703587e-04f, +2.532507071e-04f, -2.125649126e-03f, +1.630677017e-03f, +6.850603202e-03f, -1.298853535e-02f, -2.808336987e-02f, +4.066570788e-03f, +2.873131200e-02f, +7.620475041e-03f, -7.257902118e-03f, -1.022461377e-04f, +1.753034729e-03f, -4.458313625e-04f, -7.672972562e-05f,
-    /* 16,15 */ +0.000000000e+00f, +1.523656204e-04f, +3.328791130e-04f, -2.023521864e-03f, +1.091735034e-03f, +7.102956997e-03f, -1.118139232e-02f, -2.853093461e-02f, +1.359743295e-03f, +2.874576735e-02f, +9.385964725e-03f, -7.236474393e-03f, -5.803605804e-04f, +1.897918409e-03f, -3.969443331e-04f, -1.129954761e-04f,
-    /* 12, 0 */ -1.111572639e-03f, -1.388266820e-03f, +7.900037037e-03f, -6.320860170e-03f, -3.276049121e-02f, -1.657033928e-03f, +3.280306521e-02f, +8.402419704e-03f, -8.147060845e-03f, +9.779320530e-04f, +1.332890330e-03f, -5.705687800e-04f,
-    /* 12, 1 */ -8.925738220e-04f, -1.737094155e-03f, +7.544883174e-03f, -4.325531156e-03f, -3.242830266e-02f, -4.953502968e-03f, +3.254754550e-02f, +1.054842384e-02f, -8.272560314e-03f, +5.083818205e-04f, +1.551863117e-03f, -5.805594968e-04f,
-    /* 12, 2 */ -6.800837112e-04f, -2.023419107e-03f, +7.095763901e-03f, -2.436087367e-03f, -3.181840805e-02f, -8.197416535e-03f, +3.198906769e-02f, +1.273520115e-02f, -8.264181830e-03f, -1.673924732e-05f, +1.763414955e-03f, -5.764989135e-04f,
-    /* 12, 3 */ -4.777710304e-04f, -2.247467778e-03f, +6.567344318e-03f, -6.698479312e-04f, -3.094591156e-02f, -1.135453705e-02f, +3.112651563e-02f, +1.493747887e-02f, -8.110878239e-03f, -5.924008684e-04f, +1.962133432e-03f, -5.566237283e-04f,
-    /* 12, 4 */ -2.887507612e-04f, -2.410593616e-03f, +5.974525144e-03f, +9.583644900e-04f, -2.982883555e-02f, -1.439181272e-02f, +2.996260004e-02f, +1.712870168e-02f, -7.803165138e-03f, -1.212178752e-03f, +2.142359210e-03f, -5.193755958e-04f,
-    /* 12, 5 */ -1.155657138e-04f, -2.515168800e-03f, +5.332187403e-03f, +2.436339775e-03f, -2.848780461e-02f, -1.727782533e-02f, +2.850388027e-02f, +1.928138098e-02f, -7.333362623e-03f, -1.868272468e-03f, +2.298288008e-03f, -4.634616378e-04f,
-    /* 12, 6 */ +3.981829456e-05f, -2.564463655e-03f, +4.654950666e-03f, +3.754551105e-03f, -2.694569661e-02f, -1.998321224e-02f, +2.676072816e-02f, +2.136746929e-02f, -6.695817566e-03f, -2.551550686e-03f, +2.424083786e-03f, -3.879138191e-04f,
-    /* 12, 7 */ +1.760045094e-04f, -2.562517141e-03f, +3.956948521e-03f, +4.906180706e-03f, -2.522726725e-02f, -2.248105576e-02f, +2.474723407e-02f, +2.335875442e-02f, -5.887101657e-03f, -3.251624436e-03f, +2.514001460e-03f, -2.921456350e-04f,
-    /* 12, 8 */ +2.921456350e-04f, -2.514001460e-03f, +3.251624436e-03f, +5.887101657e-03f, -2.335875442e-02f, -2.474723407e-02f, +2.248105576e-02f, +2.522726725e-02f, -4.906180706e-03f, -3.956948521e-03f, +2.562517141e-03f, -1.760045094e-04f,
-    /* 12, 9 */ +3.879138191e-04f, -2.424083786e-03f, +2.551550686e-03f, +6.695817566e-03f, -2.136746929e-02f, -2.676072816e-02f, +1.998321224e-02f, +2.694569661e-02f, -3.754551105e-03f, -4.654950666e-03f, +2.564463655e-03f, -3.981829456e-05f,
-    /* 12,10 */ +4.634616378e-04f, -2.298288008e-03f, +1.868272468e-03f, +7.333362623e-03f, -1.928138098e-02f, -2.850388027e-02f, +1.727782533e-02f, +2.848780461e-02f, -2.436339775e-03f, -5.332187403e-03f, +2.515168800e-03f, +1.155657138e-04f,
-    /* 12,11 */ +5.193755958e-04f, -2.142359210e-03f, +1.212178752e-03f, +7.803165138e-03f, -1.712870168e-02f, -2.996260004e-02f, +1.439181272e-02f, +2.982883555e-02f, -9.583644900e-04f, -5.974525144e-03f, +2.410593616e-03f, +2.887507612e-04f,
-    /* 12,12 */ +5.566237283e-04f, -1.962133432e-03f, +5.924008684e-04f, +8.110878239e-03f, -1.493747887e-02f, -3.112651563e-02f, +1.135453705e-02f, +3.094591156e-02f, +6.698479312e-04f, -6.567344318e-03f, +2.247467778e-03f, +4.777710304e-04f,
-    /* 12,13 */ +5.764989135e-04f, -1.763414955e-03f, +1.673924732e-05f, +8.264181830e-03f, -1.273520115e-02f, -3.198906769e-02f, +8.197416535e-03f, +3.181840805e-02f, +2.436087367e-03f, -7.095763901e-03f, +2.023419107e-03f, +6.800837112e-04f,
-    /* 12,14 */ +5.805594968e-04f, -1.551863117e-03f, -5.083818205e-04f, +8.272560314e-03f, -1.054842384e-02f, -3.254754550e-02f, +4.953502968e-03f, +3.242830266e-02f, +4.325531156e-03f, -7.544883174e-03f, +1.737094155e-03f, +8.925738220e-04f,
-    /* 12,15 */ +5.705687800e-04f, -1.332890330e-03f, -9.779320530e-04f, +8.147060845e-03f, -8.402419704e-03f, -3.280306521e-02f, +1.657033928e-03f, +3.276049121e-02f, +6.320860170e-03f, -7.900037037e-03f, +1.388266820e-03f, +1.111572639e-03f,
-    /* 12, 0 */ -1.054803383e-04f, -2.744858958e-03f, +7.370914553e-03f, -2.604494739e-03f, -3.666896703e-02f, -1.994735221e-03f, +3.707596726e-02f, +4.873177855e-03f, -8.012348726e-03f, +2.554514858e-03f, +3.117958677e-04f, -3.625540242e-04f,
-    /* 12, 1 */ +7.775923585e-05f, -2.860662969e-03f, +6.648820026e-03f, -4.950753709e-04f, -3.590728113e-02f, -5.960234251e-03f, +3.711196787e-02f, +7.277671607e-03f, -8.552819277e-03f, +2.286292242e-03f, +5.385913036e-04f, -4.265219564e-04f,
-    /* 12, 2 */ +2.361482435e-04f, -2.906545541e-03f, +5.866306097e-03f, +1.435258618e-03f, -3.481183398e-02f, -9.854190425e-03f, +3.676562700e-02f, +9.791136525e-03f, -8.972352970e-03f, +1.938320040e-03f, +7.824350015e-04f, -4.875429386e-04f,
-    /* 12, 3 */ +3.687004846e-04f, -2.888204359e-03f, +5.043181884e-03f, +3.170488652e-03f, -3.340772759e-02f, -1.363013975e-02f, +3.603085731e-02f, +1.238366322e-02f, -9.251714734e-03f, +1.510362297e-03f, +1.039066351e-03f, -5.431259501e-04f,
-    /* 12, 4 */ +4.751685216e-04f, -2.812206203e-03f, +4.198484259e-03f, +4.698496481e-03f, -3.172374637e-02f, -1.724344185e-02f, +3.490702283e-02f, +1.502265637e-02f, -9.372823891e-03f, +1.003961424e-03f, +1.303424694e-03f, -5.906251216e-04f,
-    /* 12, 5 */ +5.559799195e-04f, -2.685773447e-03f, +3.350171906e-03f, +6.011087921e-03f, -2.979181001e-02f, -2.065196332e-02f, +3.339904530e-02f, +1.767328103e-02f, -9.319170237e-03f, +4.225520445e-04f, +1.569701578e-03f, -6.273034189e-04f,
-    /* 12, 6 */ +6.121620582e-04f, -2.516571985e-03f, +2.514858275e-03f, +7.103945228e-03f, -2.764638515e-02f, -2.381671619e-02f, +3.151741694e-02f, +2.029896461e-02f, -9.076221424e-03f, -2.284590483e-04f, +1.831416829e-03f, -6.504054889e-04f,
-    /* 12, 7 */ +6.452583046e-04f, -2.312505227e-03f, +1.707586806e-03f, +7.976511649e-03f, -2.532386758e-02f, -2.670244010e-02f, +2.927811806e-02f, +2.286194672e-02f, -8.631812899e-03f, -9.416507761e-04f, +2.081518390e-03f, -6.572383529e-04f,
-    /* 12, 8 */ +6.572383529e-04f, -2.081518390e-03f, +9.416507761e-04f, +8.631812899e-03f, -2.286194672e-02f, -2.927811806e-02f, +2.670244010e-02f, +2.532386758e-02f, -7.976511649e-03f, -1.707586806e-03f, +2.312505227e-03f, -6.452583046e-04f,
-    /* 12, 9 */ +6.504054889e-04f, -1.831416829e-03f, +2.284590483e-04f, +9.076221424e-03f, -2.029896461e-02f, -3.151741694e-02f, +2.381671619e-02f, +2.764638515e-02f, -7.103945228e-03f, -2.514858275e-03f, +2.516571985e-03f, -6.121620582e-04f,
-    /* 12,10 */ +6.273034189e-04f, -1.569701578e-03f, -4.225520445e-04f, +9.319170237e-03f, -1.767328103e-02f, -3.339904530e-02f, +2.065196332e-02f, +2.979181001e-02f, -6.011087921e-03f, -3.350171906e-03f, +2.685773447e-03f, -5.559799195e-04f,
-    /* 12,11 */ +5.906251216e-04f, -1.303424694e-03f, -1.003961424e-03f, +9.372823891e-03f, -1.502265637e-02f, -3.490702283e-02f, +1.724344185e-02f, +3.172374637e-02f, -4.698496481e-03f, -4.198484259e-03f, +2.812206203e-03f, -4.751685216e-04f,
-    /* 12,12 */ +5.431259501e-04f, -1.039066351e-03f, -1.510362297e-03f, +9.251714734e-03f, -1.238366322e-02f, -3.603085731e-02f, +1.363013975e-02f, +3.340772759e-02f, -3.170488652e-03f, -5.043181884e-03f, +2.888204359e-03f, -3.687004846e-04f,
-    /* 12,13 */ +4.875429386e-04f, -7.824350015e-04f, -1.938320040e-03f, +8.972352970e-03f, -9.791136525e-03f, -3.676562700e-02f, +9.854190425e-03f, +3.481183398e-02f, -1.435258618e-03f, -5.866306097e-03f, +2.906545541e-03f, -2.361482435e-04f,
-    /* 12,14 */ +4.265219564e-04f, -5.385913036e-04f, -2.286292242e-03f, +8.552819277e-03f, -7.277671607e-03f, -3.711196787e-02f, +5.960234251e-03f, +3.590728113e-02f, +4.950753709e-04f, -6.648820026e-03f, +2.860662969e-03f, -7.775923585e-05f,
-    /* 12,15 */ +3.625540242e-04f, -3.117958677e-04f, -2.554514858e-03f, +8.012348726e-03f, -4.873177855e-03f, -3.707596726e-02f, +1.994735221e-03f, +3.666896703e-02f, +2.604494739e-03f, -7.370914553e-03f, +2.744858958e-03f, +1.054803383e-04f,
-    /* 12, 0 */ +6.110448771e-04f, -3.173989705e-03f, +5.751223243e-03f, +1.507555794e-03f, -4.035343888e-02f, -2.375409442e-03f, +4.124383193e-02f, +8.091337269e-04f, -6.726716888e-03f, +3.253952459e-03f, -5.087325269e-04f, -4.127854608e-05f,
-    /* 12, 1 */ +6.820041984e-04f, -3.029137857e-03f, +4.746351538e-03f, +3.578915017e-03f, -3.904147991e-02f, -7.094160720e-03f, +4.168490752e-02f, +3.349306133e-03f, -7.647219355e-03f, +3.259488816e-03f, -3.738470149e-04f, -9.536054020e-05f,
-    /* 12, 2 */ +7.235832870e-04f, -2.829602454e-03f, +3.736224000e-03f, +5.388621830e-03f, -3.734163661e-02f, -1.171726725e-02f, +4.165549067e-02f, +6.085743956e-03f, -8.486093037e-03f, +3.182049180e-03f, -2.060445111e-04f, -1.573545891e-04f,
-    /* 12, 3 */ +7.383739029e-04f, -2.585946508e-03f, +2.743066911e-03f, +6.925917423e-03f, -3.529277498e-02f, -1.618281485e-02f, +4.114151479e-02f, +8.986133221e-03f, -9.216195947e-03f, +3.014391908e-03f, -5.966328360e-06f, -2.260166200e-04f,
-    /* 12, 4 */ +7.294476853e-04f, -2.308795686e-03f, +1.786872733e-03f, +8.185530694e-03f, -3.293811768e-02f, -2.043162352e-02f, +4.013642610e-02f, +1.201345370e-02f, -9.810446156e-03f, +2.750895834e-03f, +2.246717082e-04f, -2.996559917e-04f,
-    /* 12, 5 */ +7.002161546e-04f, -2.008565767e-03f, +8.851333656e-04f, +9.167495079e-03f, -3.032435275e-02f, -2.440826356e-02f, +3.864144993e-02f, +1.512648157e-02f, -1.024241966e-02f, +2.387856219e-03f, +4.830138128e-04f, -3.761418846e-04f,
-    /* 12, 6 */ +6.542939604e-04f, -1.695217727e-03f, +5.264660367e-05f, +9.876866054e-03f, -2.750069849e-02f, -2.806199617e-02f, +3.666571148e-02f, +1.828039745e-02f, -1.048696943e-02f, +1.923755148e-03f, +7.650267923e-04f, -4.529261561e-04f,
-    /* 12, 7 */ +5.953691186e-04f, -1.378044726e-03f, -6.986040124e-04f, +1.032334944e-02f, -2.451794467e-02f, -3.134761990e-02f, +3.422620641e-02f, +2.142749023e-02f, -1.052085229e-02f, +1.359497506e-03f, +1.065494162e-03f, -5.270834853e-04f,
-    /* 12, 8 */ +5.270834853e-04f, -1.065494162e-03f, -1.359497506e-03f, +1.052085229e-02f, -2.142749023e-02f, -3.422620641e-02f, +3.134761990e-02f, +2.451794467e-02f, -1.032334944e-02f, +6.986040124e-04f, +1.378044726e-03f, -5.953691186e-04f,
-    /* 12, 9 */ +4.529261561e-04f, -7.650267923e-04f, -1.923755148e-03f, +1.048696943e-02f, -1.828039745e-02f, -3.666571148e-02f, +2.806199617e-02f, +2.750069849e-02f, -9.876866054e-03f, -5.264660367e-05f, +1.695217727e-03f, -6.542939604e-04f,
-    /* 12,10 */ +3.761418846e-04f, -4.830138128e-04f, -2.387856219e-03f, +1.024241966e-02f, -1.512648157e-02f, -3.864144993e-02f, +2.440826356e-02f, +3.032435275e-02f, -9.167495079e-03f, -8.851333656e-04f, +2.008565767e-03f, -7.002161546e-04f,
-    /* 12,11 */ +2.996559917e-04f, -2.246717082e-04f, -2.750895834e-03f, +9.810446156e-03f, -1.201345370e-02f, -4.013642610e-02f, +2.043162352e-02f, +3.293811768e-02f, -8.185530694e-03f, -1.786872733e-03f, +2.308795686e-03f, -7.294476853e-04f,
-    /* 12,12 */ +2.260166200e-04f, +5.966328360e-06f, -3.014391908e-03f, +9.216195947e-03f, -8.986133221e-03f, -4.114151479e-02f, +1.618281485e-02f, +3.529277498e-02f, -6.925917423e-03f, -2.743066911e-03f, +2.585946508e-03f, -7.383739029e-04f,
-    /* 12,13 */ +1.573545891e-04f, +2.060445111e-04f, -3.182049180e-03f, +8.486093037e-03f, -6.085743956e-03f, -4.165549067e-02f, +1.171726725e-02f, +3.734163661e-02f, -5.388621830e-03f, -3.736224000e-03f, +2.829602454e-03f, -7.235832870e-04f,
-    /* 12,14 */ +9.536054020e-05f, +3.738470149e-04f, -3.259488816e-03f, +7.647219355e-03f, -3.349306133e-03f, -4.168490752e-02f, +7.094160720e-03f, +3.904147991e-02f, -3.578915017e-03f, -4.746351538e-03f, +3.029137857e-03f, -6.820041984e-04f,
-    /* 12,15 */ +4.127854608e-05f, +5.087325269e-04f, -3.253952459e-03f, +6.726716888e-03f, -8.091337269e-04f, -4.124383193e-02f, +2.375409442e-03f, +4.035343888e-02f, -1.507555794e-03f, -5.751223243e-03f, +3.173989705e-03f, -6.110448771e-04f,
-
-    /* 24, 0 */ -8.820438069e-05f, -1.519461079e-04f, -2.301651496e-04f, -3.149320871e-04f, -3.945939739e-04f, -4.554410135e-04f, -4.841532882e-04f, -4.705408991e-04f, -4.099602091e-04f, -3.048100066e-04f, -1.646897470e-04f, -5.099007530e-06f, +1.551006323e-04f, +2.969416536e-04f, +4.046294158e-04f, +4.681429482e-04f, +4.846228261e-04f, +4.583040637e-04f, +3.990939388e-04f, +3.201968846e-04f, +2.353759082e-04f, +1.564712483e-04f, +9.167483068e-05f, +4.482688286e-05f,
-    /* 24, 1 */ -8.480575132e-05f, -1.474789784e-04f, -2.249812225e-04f, -3.096480504e-04f, -3.900204007e-04f, -4.524514078e-04f, -4.835165803e-04f, -4.727530367e-04f, -4.151145025e-04f, -3.125397891e-04f, -1.742016828e-04f, -1.529460870e-05f, +1.454387449e-04f, +2.889379628e-04f, +3.991236794e-04f, +4.655589110e-04f, +4.849233000e-04f, +4.610375470e-04f, +4.035168325e-04f, +3.254391996e-04f, +2.406110065e-04f, +1.610529558e-04f, +9.521673594e-05f, +4.721513201e-05f,
-    /* 24, 2 */ -8.147924507e-05f, -1.430712350e-04f, -2.198265592e-04f, -3.043479843e-04f, -3.853766873e-04f, -4.493383067e-04f, -4.827146831e-04f, -4.747797448e-04f, -4.200908527e-04f, -3.201278616e-04f, -1.836320864e-04f, -2.548296987e-05f, +1.357085413e-04f, +2.808022583e-04f, +3.934446700e-04f, +4.627886263e-04f, +4.850529052e-04f, +4.636385032e-04f, +4.078592000e-04f, +3.306557574e-04f, +2.458678944e-04f, +1.656897170e-04f, +9.882966748e-05f, +4.967415993e-05f,
-    /* 24, 3 */ -7.822510242e-05f, -1.387241832e-04f, -2.147035314e-04f, -2.990350629e-04f, -3.806663042e-04f, -4.461048161e-04f, -4.817496625e-04f, -4.766215175e-04f, -4.248879309e-04f, -3.275711800e-04f, -1.929766610e-04f, -3.565926997e-05f, +1.259145254e-04f, +2.725379532e-04f, +3.875941701e-04f, +4.598320457e-04f, +4.850099279e-04f, +4.661040260e-04f, +4.121175966e-04f, +3.358432542e-04f, +2.511439643e-04f, +1.703799499e-04f, +1.025131319e-04f, +5.220438912e-05f,
-    /* 24, 4 */ -7.504350274e-05f, -1.344390595e-04f, -2.096144489e-04f, -2.937124231e-04f, -3.758927218e-04f, -4.427540852e-04f, -4.806236671e-04f, -4.782789577e-04f, -4.295045226e-04f, -3.348667971e-04f, -2.022311686e-04f, -4.581869630e-05f, +1.160612449e-04f, +2.641485480e-04f, +3.815740737e-04f, +4.566892339e-04f, +4.847927474e-04f, +4.684312656e-04f, +4.162885910e-04f, +3.409983591e-04f, +2.564365532e-04f, +1.751220037e-04f, +1.062665706e-04f, +5.480619333e-05f,
-    /* 24, 5 */ -7.193456522e-05f, -1.302170312e-04f, -2.045615590e-04f, -2.883831622e-04f, -3.710594077e-04f, -4.392893036e-04f, -4.793389263e-04f, -4.797527765e-04f, -4.339395286e-04f, -3.420118645e-04f, -2.113914331e-04f, -5.595644787e-05f, +1.061532886e-04f, +2.556376279e-04f, +3.753863858e-04f, +4.533603695e-04f, +4.843998374e-04f, +4.706174312e-04f, +4.203687678e-04f, +3.461177167e-04f, +2.617429433e-04f, +1.799141593e-04f, +1.100893595e-04f, +5.747989630e-05f,
-    /* 24, 6 */ -6.889834987e-05f, -1.260591965e-04f, -1.995470454e-04f, -2.830503358e-04f, -3.661698243e-04f, -4.357136989e-04f, -4.778977479e-04f, -4.810437916e-04f, -4.381919648e-04f, -3.490036345e-04f, -2.204533432e-04f, -6.606773875e-05f, +9.619528314e-05f, +2.470088608e-04f, +3.690332209e-04f, +4.498457452e-04f, +4.838297683e-04f, +4.726597937e-04f, +4.243547301e-04f, +3.511979487e-04f, +2.670603639e-04f, +1.847546294e-04f, +1.139808078e-04f, +6.022577049e-05f,
-    /* 24, 7 */ -6.593485851e-05f, -1.219665852e-04f, -1.945730275e-04f, -2.777169567e-04f, -3.612274261e-04f, -4.320305335e-04f, -4.763025159e-04f, -4.821529264e-04f, -4.422609626e-04f, -3.558394612e-04f, -2.294128549e-04f, -7.614780136e-05f, +8.619188981e-05f, +2.382659945e-04f, +3.625168024e-04f, +4.461457687e-04f, +4.830812085e-04f, +4.745556880e-04f, +4.282431024e-04f, +3.562356572e-04f, +2.723859925e-04f, +1.896415594e-04f, +1.179401580e-04f, +6.304403582e-05f,
-    /* 24, 8 */ -6.304403582e-05f, -1.179401580e-04f, -1.896415594e-04f, -2.723859925e-04f, -3.562356572e-04f, -4.282431024e-04f, -4.745556880e-04f, -4.830812085e-04f, -4.461457687e-04f, -3.625168024e-04f, -2.382659945e-04f, -8.619188981e-05f, +7.614780136e-05f, +2.294128549e-04f, +3.558394612e-04f, +4.422609626e-04f, +4.821529264e-04f, +4.763025159e-04f, +4.320305335e-04f, +3.612274261e-04f, +2.777169567e-04f, +1.945730275e-04f, +1.219665852e-04f, +6.593485851e-05f,
-    /* 24, 9 */ -6.022577049e-05f, -1.139808078e-04f, -1.847546294e-04f, -2.670603639e-04f, -3.511979487e-04f, -4.243547301e-04f, -4.726597937e-04f, -4.838297683e-04f, -4.498457452e-04f, -3.690332209e-04f, -2.470088608e-04f, -9.619528314e-05f, +6.606773875e-05f, +2.204533432e-04f, +3.490036345e-04f, +4.381919648e-04f, +4.810437916e-04f, +4.778977479e-04f, +4.357136989e-04f, +3.661698243e-04f, +2.830503358e-04f, +1.995470454e-04f, +1.260591965e-04f, +6.889834987e-05f,
-    /* 24,10 */ -5.747989630e-05f, -1.100893595e-04f, -1.799141593e-04f, -2.617429433e-04f, -3.461177167e-04f, -4.203687678e-04f, -4.706174312e-04f, -4.843998374e-04f, -4.533603695e-04f, -3.753863858e-04f, -2.556376279e-04f, -1.061532886e-04f, +5.595644787e-05f, +2.113914331e-04f, +3.420118645e-04f, +4.339395286e-04f, +4.797527765e-04f, +4.793389263e-04f, +4.392893036e-04f, +3.710594077e-04f, +2.883831622e-04f, +2.045615590e-04f, +1.302170312e-04f, +7.193456522e-05f,
-    /* 24,11 */ -5.480619333e-05f, -1.062665706e-04f, -1.751220037e-04f, -2.564365532e-04f, -3.409983591e-04f, -4.162885910e-04f, -4.684312656e-04f, -4.847927474e-04f, -4.566892339e-04f, -3.815740737e-04f, -2.641485480e-04f, -1.160612449e-04f, +4.581869630e-05f, +2.022311686e-04f, +3.348667971e-04f, +4.295045226e-04f, +4.782789577e-04f, +4.806236671e-04f, +4.427540852e-04f, +3.758927218e-04f, +2.937124231e-04f, +2.096144489e-04f, +1.344390595e-04f, +7.504350274e-05f,
-    /* 24,12 */ -5.220438912e-05f, -1.025131319e-04f, -1.703799499e-04f, -2.511439643e-04f, -3.358432542e-04f, -4.121175966e-04f, -4.661040260e-04f, -4.850099279e-04f, -4.598320457e-04f, -3.875941701e-04f, -2.725379532e-04f, -1.259145254e-04f, +3.565926997e-05f, +1.929766610e-04f, +3.275711800e-04f, +4.248879309e-04f, +4.766215175e-04f, +4.817496625e-04f, +4.461048161e-04f, +3.806663042e-04f, +2.990350629e-04f, +2.147035314e-04f, +1.387241832e-04f, +7.822510242e-05f,
-    /* 24,13 */ -4.967415993e-05f, -9.882966748e-05f, -1.656897170e-04f, -2.458678944e-04f, -3.306557574e-04f, -4.078592000e-04f, -4.636385032e-04f, -4.850529052e-04f, -4.627886263e-04f, -3.934446700e-04f, -2.808022583e-04f, -1.357085413e-04f, +2.548296987e-05f, +1.836320864e-04f, +3.201278616e-04f, +4.200908527e-04f, +4.747797448e-04f, +4.827146831e-04f, +4.493383067e-04f, +3.853766873e-04f, +3.043479843e-04f, +2.198265592e-04f, +1.430712350e-04f, +8.147924507e-05f,
-    /* 24,14 */ -4.721513201e-05f, -9.521673594e-05f, -1.610529558e-04f, -2.406110065e-04f, -3.254391996e-04f, -4.035168325e-04f, -4.610375470e-04f, -4.849233000e-04f, -4.655589110e-04f, -3.991236794e-04f, -2.889379628e-04f, -1.454387449e-04f, +1.529460870e-05f, +1.742016828e-04f, +3.125397891e-04f, +4.151145025e-04f, +4.727530367e-04f, +4.835165803e-04f, +4.524514078e-04f, +3.900204007e-04f, +3.096480504e-04f, +2.249812225e-04f, +1.474789784e-04f, +8.480575132e-05f,
-    /* 24,15 */ -4.482688286e-05f, -9.167483068e-05f, -1.564712483e-04f, -2.353759082e-04f, -3.201968846e-04f, -3.990939388e-04f, -4.583040637e-04f, -4.846228261e-04f, -4.681429482e-04f, -4.046294158e-04f, -2.969416536e-04f, -1.551006323e-04f, +5.099007530e-06f, +1.646897470e-04f, +3.048100066e-04f, +4.099602091e-04f, +4.705408991e-04f, +4.841532882e-04f, +4.554410135e-04f, +3.945939739e-04f, +3.149320871e-04f, +2.301651496e-04f, +1.519461079e-04f, +8.820438069e-05f,
-    /* 24, 0 */ +1.254177052e-04f, +1.432187562e-04f, +1.041598752e-04f, -1.135750248e-05f, -2.010663923e-04f, -4.345091125e-04f, -6.566280172e-04f, -8.018070806e-04f, -8.145094672e-04f, -6.693628869e-04f, -3.829411831e-04f, -1.208738944e-05f, +3.614691013e-04f, +6.551938988e-04f, +8.101126455e-04f, +8.069330100e-04f, +6.686285441e-04f, +4.493898115e-04f, +2.148422063e-04f, +2.121126661e-05f, -9.928779545e-05f, -1.427235715e-04f, -1.276505127e-04f, -8.319130160e-05f,
-    /* 24, 1 */ +1.230784715e-04f, +1.434886692e-04f, +1.087259386e-04f, -1.803144714e-06f, -1.874698746e-04f, -4.195879132e-04f, -6.443236569e-04f, -7.961535056e-04f, -8.182754723e-04f, -6.829663304e-04f, -4.040749814e-04f, -3.625133679e-05f, +3.396771574e-04f, +6.404692089e-04f, +8.050839212e-04f, +8.115205881e-04f, +6.803091718e-04f, +4.642140510e-04f, +2.287861157e-04f, +3.136033560e-05f, -9.410712043e-05f, -1.419963918e-04f, -1.297693532e-04f, -8.627587811e-05f,
-    /* 24, 2 */ +1.206403004e-04f, +1.435401825e-04f, +1.129889134e-04f, +7.448162127e-06f, -1.740634498e-04f, -4.046419937e-04f, -6.317316839e-04f, -7.899834729e-04f, -8.214124236e-04f, -6.959950382e-04f, -4.248524782e-04f, -6.038280262e-05f, +3.175841545e-04f, +6.251993025e-04f, +7.994228899e-04f, +8.155596091e-04f, +6.916540113e-04f, +4.789657110e-04f, +2.428865252e-04f, +4.180014906e-05f, -8.861563067e-05f, -1.410306561e-04f, -1.317666448e-04f, -8.934972901e-05f,
-    /* 24, 3 */ +1.181106179e-04f, +1.433803035e-04f, +1.169520657e-04f, +1.639322797e-05f, -1.608575022e-04f, -3.896869361e-04f, -6.188684520e-04f, -7.833086355e-04f, -8.239227539e-04f, -7.084404793e-04f, -4.452560799e-04f, -8.446017611e-05f, +2.952092559e-04f, +6.093952965e-04f, +7.931298338e-04f, +8.190403838e-04f, +7.026473724e-04f, +4.936285297e-04f, +2.571314547e-04f, +5.252568657e-05f, -8.281147599e-05f, -1.398199793e-04f, -1.336347757e-04f, -9.240689021e-05f,
-    /* 24, 4 */ +1.154967766e-04f, +1.430161614e-04f, +1.206189886e-04f, +2.502931407e-05f, -1.478619956e-04f, -3.747381071e-04f, -6.057504254e-04f, -7.761410928e-04f, -8.258095592e-04f, -7.202947906e-04f, -4.652686374e-04f, -1.084619116e-04f, +2.725719623e-04f, +5.930689291e-04f, +7.862057246e-04f, +8.219537553e-04f, +7.132737861e-04f, +5.081861235e-04f, +2.715085502e-04f, +6.353146713e-05f, -7.669318508e-05f, -1.383581653e-04f, -1.353661159e-04f, -9.544123411e-05f,
-    /* 24, 5 */ +1.128060463e-04f, +1.424549941e-04f, +1.239935912e-04f, +3.335412922e-05f, -1.350864661e-04f, -3.598106411e-04f, -5.923941571e-04f, -7.684933716e-04f, -8.270765907e-04f, -7.315507834e-04f, -4.848734661e-04f, -1.323665545e-04f, +2.496920884e-04f, +5.762325468e-04f, +7.786522269e-04f, +8.242911148e-04f, +7.235180256e-04f, +5.226220062e-04f, +2.860050947e-04f, +7.481154929e-05f, -7.025967465e-05f, -1.366392205e-04f, -1.369530289e-04f, -9.844647580e-05f,
-    /* 24, 6 */ +1.100456035e-04f, +1.417041346e-04f, +1.270800866e-04f, +4.136582536e-05f, -1.225400157e-04f, -3.449194225e-04f, -5.788162671e-04f, -7.603784078e-04f, -8.277282458e-04f, -7.422019493e-04f, -5.040543645e-04f, -1.561527673e-04f, +2.265897402e-04f, +5.588990922e-04f, +7.704716994e-04f, +8.260444163e-04f, +7.333651287e-04f, +5.369196097e-04f, +3.006080208e-04f, +8.635953200e-05f, -6.351025813e-05f, -1.346573670e-04f, -1.383878839e-04f, -1.014161798e-04f,
-    /* 24, 7 */ +1.072225228e-04f, +1.407709979e-04f, +1.298829797e-04f, +4.906299265e-05f, -1.102313067e-04f, -3.300790706e-04f, -5.650334202e-04f, -7.518095256e-04f, -8.277695590e-04f, -7.522424649e-04f, -5.227956327e-04f, -1.797993550e-04f, +2.032852905e-04f, +5.410820901e-04f, +7.616671958e-04f, +8.272061905e-04f, +7.428004186e-04f, +5.510623045e-04f, +3.153039229e-04f, +9.816855611e-05f, -5.644465382e-05f, -1.324070557e-04f, -1.396630677e-04f, -1.043437672e-04f,
-    /* 24, 8 */ +1.043437672e-04f, +1.396630677e-04f, +1.324070557e-04f, +5.644465382e-05f, -9.816855611e-05f, -3.153039229e-04f, -5.510623045e-04f, -7.428004186e-04f, -8.272061905e-04f, -7.616671958e-04f, -5.410820901e-04f, -2.032852905e-04f, +1.797993550e-04f, +5.227956327e-04f, +7.522424649e-04f, +8.277695590e-04f, +7.518095256e-04f, +5.650334202e-04f, +3.300790706e-04f, +1.102313067e-04f, -4.906299265e-05f, -1.298829797e-04f, -1.407709979e-04f, -1.072225228e-04f,
-    /* 24, 9 */ +1.014161798e-04f, +1.383878839e-04f, +1.346573670e-04f, +6.351025813e-05f, -8.635953200e-05f, -3.006080208e-04f, -5.369196097e-04f, -7.333651287e-04f, -8.260444163e-04f, -7.704716994e-04f, -5.588990922e-04f, -2.265897402e-04f, +1.561527673e-04f, +5.040543645e-04f, +7.422019493e-04f, +8.277282458e-04f, +7.603784078e-04f, +5.788162671e-04f, +3.449194225e-04f, +1.225400157e-04f, -4.136582536e-05f, -1.270800866e-04f, -1.417041346e-04f, -1.100456035e-04f,
-    /* 24,10 */ +9.844647580e-05f, +1.369530289e-04f, +1.366392205e-04f, +7.025967465e-05f, -7.481154929e-05f, -2.860050947e-04f, -5.226220062e-04f, -7.235180256e-04f, -8.242911148e-04f, -7.786522269e-04f, -5.762325468e-04f, -2.496920884e-04f, +1.323665545e-04f, +4.848734661e-04f, +7.315507834e-04f, +8.270765907e-04f, +7.684933716e-04f, +5.923941571e-04f, +3.598106411e-04f, +1.350864661e-04f, -3.335412922e-05f, -1.239935912e-04f, -1.424549941e-04f, -1.128060463e-04f,
-    /* 24,11 */ +9.544123411e-05f, +1.353661159e-04f, +1.383581653e-04f, +7.669318508e-05f, -6.353146713e-05f, -2.715085502e-04f, -5.081861235e-04f, -7.132737861e-04f, -8.219537553e-04f, -7.862057246e-04f, -5.930689291e-04f, -2.725719623e-04f, +1.084619116e-04f, +4.652686374e-04f, +7.202947906e-04f, +8.258095592e-04f, +7.761410928e-04f, +6.057504254e-04f, +3.747381071e-04f, +1.478619956e-04f, -2.502931407e-05f, -1.206189886e-04f, -1.430161614e-04f, -1.154967766e-04f,
-    /* 24,12 */ +9.240689021e-05f, +1.336347757e-04f, +1.398199793e-04f, +8.281147599e-05f, -5.252568657e-05f, -2.571314547e-04f, -4.936285297e-04f, -7.026473724e-04f, -8.190403838e-04f, -7.931298338e-04f, -6.093952965e-04f, -2.952092559e-04f, +8.446017611e-05f, +4.452560799e-04f, +7.084404793e-04f, +8.239227539e-04f, +7.833086355e-04f, +6.188684520e-04f, +3.896869361e-04f, +1.608575022e-04f, -1.639322797e-05f, -1.169520657e-04f, -1.433803035e-04f, -1.181106179e-04f,
-    /* 24,13 */ +8.934972901e-05f, +1.317666448e-04f, +1.410306561e-04f, +8.861563067e-05f, -4.180014906e-05f, -2.428865252e-04f, -4.789657110e-04f, -6.916540113e-04f, -8.155596091e-04f, -7.994228899e-04f, -6.251993025e-04f, -3.175841545e-04f, +6.038280262e-05f, +4.248524782e-04f, +6.959950382e-04f, +8.214124236e-04f, +7.899834729e-04f, +6.317316839e-04f, +4.046419937e-04f, +1.740634498e-04f, -7.448162127e-06f, -1.129889134e-04f, -1.435401825e-04f, -1.206403004e-04f,
-    /* 24,14 */ +8.627587811e-05f, +1.297693532e-04f, +1.419963918e-04f, +9.410712043e-05f, -3.136033560e-05f, -2.287861157e-04f, -4.642140510e-04f, -6.803091718e-04f, -8.115205881e-04f, -8.050839212e-04f, -6.404692089e-04f, -3.396771574e-04f, +3.625133679e-05f, +4.040749814e-04f, +6.829663304e-04f, +8.182754723e-04f, +7.961535056e-04f, +6.443236569e-04f, +4.195879132e-04f, +1.874698746e-04f, +1.803144714e-06f, -1.087259386e-04f, -1.434886692e-04f, -1.230784715e-04f,
-    /* 24,15 */ +8.319130160e-05f, +1.276505127e-04f, +1.427235715e-04f, +9.928779545e-05f, -2.121126661e-05f, -2.148422063e-04f, -4.493898115e-04f, -6.686285441e-04f, -8.069330100e-04f, -8.101126455e-04f, -6.551938988e-04f, -3.614691013e-04f, +1.208738944e-05f, +3.829411831e-04f, +6.693628869e-04f, +8.145094672e-04f, +8.018070806e-04f, +6.566280172e-04f, +4.345091125e-04f, +2.010663923e-04f, +1.135750248e-05f, -1.041598752e-04f, -1.432187562e-04f, -1.254177052e-04f,
-    /* 24, 0 */ +4.545052445e-05f, +1.951315810e-04f, +3.748938080e-04f, +4.809335107e-04f, +3.960765690e-04f, +5.993810822e-05f, -4.723795438e-04f, -1.024325735e-03f, -1.361247582e-03f, -1.299302728e-03f, -8.046117557e-04f, -2.606329026e-05f, +7.618428442e-04f, +1.280408741e-03f, +1.370322771e-03f, +1.054089829e-03f, +5.086432784e-04f, -3.113193898e-05f, -3.825195300e-04f, -4.822884412e-04f, -3.849609275e-04f, -2.063256631e-04f, -5.270037440e-05f, +2.454794639e-05f,
-    /* 24, 1 */ +3.852332445e-05f, +1.840753178e-04f, +3.645444067e-04f, +4.788140096e-04f, +4.086121277e-04f, +8.793526572e-05f, -4.362135407e-04f, -9.937048198e-04f, -1.350562575e-03f, -1.316442769e-03f, -8.462280606e-04f, -7.815185270e-05f, +7.179801999e-04f, +1.259777116e-03f, +1.377758125e-03f, +1.082939175e-03f, +5.449481703e-04f, -1.547839432e-06f, -3.679388598e-04f, -4.828529979e-04f, -3.947147844e-04f, -2.176372792e-04f, -6.026901850e-05f, +2.205234045e-05f,
-    /* 24, 2 */ +3.192167036e-05f, +1.731761778e-04f, +3.539434193e-04f, +4.759566352e-04f, +4.201302650e-04f, +1.150943789e-04f, -4.002008253e-04f, -9.622858103e-04f, -1.338300241e-03f, -1.331815598e-03f, -8.866349827e-04f, -1.301264311e-04f, +6.730846905e-04f, +1.237427186e-03f, +1.383526171e-03f, +1.110816763e-03f, +5.812367254e-04f, +2.878109064e-05f, -3.523343557e-04f, -4.826023474e-04f, -4.041241778e-04f, -2.290451863e-04f, -6.815162122e-05f, +1.926869283e-05f,
-    /* 24, 3 */ +2.564752013e-05f, +1.624524653e-04f, +3.431211940e-04f, +4.723889014e-04f, +4.306369033e-04f, +1.413884897e-04f, -3.643958409e-04f, -9.301281119e-04f, -1.324495465e-03f, -1.345410999e-03f, -9.257779427e-04f, -1.819112698e-04f, +6.272190697e-04f, +1.213381290e-03f, +1.387602061e-03f, +1.137666624e-03f, +6.174506312e-04f, +5.981976836e-05f, -3.357077999e-04f, -4.815127015e-04f, -4.131577529e-04f, -2.405272085e-04f, -7.634234963e-05f, +1.618998833e-05f,
-    /* 24, 4 */ +1.970191739e-05f, +1.519214683e-04f, +3.321076713e-04f, +4.681390617e-04f, +4.401397816e-04f, +1.667927354e-04f, -3.288518263e-04f, -8.972916878e-04f, -1.309185436e-03f, -1.357221809e-03f, -9.636046528e-04f, -2.334309635e-04f, +5.804478655e-04f, +1.187664745e-03f, +1.389963631e-03f, +1.163433942e-03f, +6.535308606e-04f, +9.153116784e-05f, -3.180629927e-04f, -4.795613921e-04f, -4.217840695e-04f, -2.520602653e-04f, -8.483435780e-05f, +1.280977164e-05f,
-    /* 24, 5 */ +1.408501704e-05f, +1.415994448e-04f, +3.209323254e-04f, +4.632360317e-04f, +4.486484045e-04f, +1.912843645e-04f, -2.936207276e-04f, -8.638369381e-04f, -1.292409564e-03f, -1.367243913e-03f, -1.000065207e-03f, -2.846105957e-04f, +5.328372638e-04f, +1.160305814e-03f, +1.390591463e-03f, +1.188065177e-03f, +6.894177793e-04f, +1.238763650e-04f, -2.994057812e-04f, -4.767269440e-04f, -4.299716716e-04f, -2.636204028e-04f, -9.361977359e-05f, +9.122184539e-06f,
-    /* 24, 6 */ +8.796112429e-06f, +1.315016126e-04f, +3.096241086e-04f, +4.577093118e-04f, +4.561739887e-04f, +2.148427485e-04f, -2.587531149e-04f, -8.298245798e-04f, -1.274209383e-03f, -1.375476234e-03f, -1.035112163e-03f, -3.353758773e-04f, +4.844549899e-04f, +1.131335665e-03f, +1.389468944e-03f, +1.211508174e-03f, +7.250512548e-04f, +1.568145870e-04f, -2.797440842e-04f, -4.729891466e-04f, -4.376891593e-04f, -2.751828281e-04f, -1.026896878e-04f, +5.122002376e-06f,
-    /* 24, 7 */ +3.833664119e-06f, +1.216421408e-04f, +2.982113984e-04f, +4.515889092e-04f, +4.627294060e-04f, +2.374493875e-04f, -2.242981012e-04f, -7.953155261e-04f, -1.254628457e-03f, -1.381920720e-03f, -1.068700627e-03f, -3.856532828e-04f, +4.353701854e-04f, +1.100788324e-03f, +1.386582316e-03f, +1.233712281e-03f, +7.603707678e-04f, +1.903032668e-04f, -2.590879129e-04f, -4.683291247e-04f, -4.449052614e-04f, -2.867219458e-04f, -1.120341455e-04f, +8.046698450e-07f,
-    /* 24, 8 */ -8.046698450e-07f, +1.120341455e-04f, +2.867219458e-04f, +4.449052614e-04f, +4.683291247e-04f, +2.590879129e-04f, -1.903032668e-04f, -7.603707678e-04f, -1.233712281e-03f, -1.386582316e-03f, -1.100788324e-03f, -4.353701854e-04f, +3.856532828e-04f, +1.068700627e-03f, +1.381920720e-03f, +1.254628457e-03f, +7.953155261e-04f, +2.242981012e-04f, -2.374493875e-04f, -4.627294060e-04f, -4.515889092e-04f, -2.982113984e-04f, -1.216421408e-04f, -3.833664119e-06f,
-    /* 24, 9 */ -5.122002376e-06f, +1.026896878e-04f, +2.751828281e-04f, +4.376891593e-04f, +4.729891466e-04f, +2.797440842e-04f, -1.568145870e-04f, -7.250512548e-04f, -1.211508174e-03f, -1.389468944e-03f, -1.131335665e-03f, -4.844549899e-04f, +3.353758773e-04f, +1.035112163e-03f, +1.375476234e-03f, +1.274209383e-03f, +8.298245798e-04f, +2.587531149e-04f, -2.148427485e-04f, -4.561739887e-04f, -4.577093118e-04f, -3.096241086e-04f, -1.315016126e-04f, -8.796112429e-06f,
-    /* 24,10 */ -9.122184539e-06f, +9.361977359e-05f, +2.636204028e-04f, +4.299716716e-04f, +4.767269440e-04f, +2.994057812e-04f, -1.238763650e-04f, -6.894177793e-04f, -1.188065177e-03f, -1.390591463e-03f, -1.160305814e-03f, -5.328372638e-04f, +2.846105957e-04f, +1.000065207e-03f, +1.367243913e-03f, +1.292409564e-03f, +8.638369381e-04f, +2.936207276e-04f, -1.912843645e-04f, -4.486484045e-04f, -4.632360317e-04f, -3.209323254e-04f, -1.415994448e-04f, -1.408501704e-05f,
-    /* 24,11 */ -1.280977164e-05f, +8.483435780e-05f, +2.520602653e-04f, +4.217840695e-04f, +4.795613921e-04f, +3.180629927e-04f, -9.153116784e-05f, -6.535308606e-04f, -1.163433942e-03f, -1.389963631e-03f, -1.187664745e-03f, -5.804478655e-04f, +2.334309635e-04f, +9.636046528e-04f, +1.357221809e-03f, +1.309185436e-03f, +8.972916878e-04f, +3.288518263e-04f, -1.667927354e-04f, -4.401397816e-04f, -4.681390617e-04f, -3.321076713e-04f, -1.519214683e-04f, -1.970191739e-05f,
-    /* 24,12 */ -1.618998833e-05f, +7.634234963e-05f, +2.405272085e-04f, +4.131577529e-04f, +4.815127015e-04f, +3.357077999e-04f, -5.981976836e-05f, -6.174506312e-04f, -1.137666624e-03f, -1.387602061e-03f, -1.213381290e-03f, -6.272190697e-04f, +1.819112698e-04f, +9.257779427e-04f, +1.345410999e-03f, +1.324495465e-03f, +9.301281119e-04f, +3.643958409e-04f, -1.413884897e-04f, -4.306369033e-04f, -4.723889014e-04f, -3.431211940e-04f, -1.624524653e-04f, -2.564752013e-05f,
-    /* 24,13 */ -1.926869283e-05f, +6.815162122e-05f, +2.290451863e-04f, +4.041241778e-04f, +4.826023474e-04f, +3.523343557e-04f, -2.878109064e-05f, -5.812367254e-04f, -1.110816763e-03f, -1.383526171e-03f, -1.237427186e-03f, -6.730846905e-04f, +1.301264311e-04f, +8.866349827e-04f, +1.331815598e-03f, +1.338300241e-03f, +9.622858103e-04f, +4.002008253e-04f, -1.150943789e-04f, -4.201302650e-04f, -4.759566352e-04f, -3.539434193e-04f, -1.731761778e-04f, -3.192167036e-05f,
-    /* 24,14 */ -2.205234045e-05f, +6.026901850e-05f, +2.176372792e-04f, +3.947147844e-04f, +4.828529979e-04f, +3.679388598e-04f, +1.547839432e-06f, -5.449481703e-04f, -1.082939175e-03f, -1.377758125e-03f, -1.259777116e-03f, -7.179801999e-04f, +7.815185270e-05f, +8.462280606e-04f, +1.316442769e-03f, +1.350562575e-03f, +9.937048198e-04f, +4.362135407e-04f, -8.793526572e-05f, -4.086121277e-04f, -4.788140096e-04f, -3.645444067e-04f, -1.840753178e-04f, -3.852332445e-05f,
-    /* 24,15 */ -2.454794639e-05f, +5.270037440e-05f, +2.063256631e-04f, +3.849609275e-04f, +4.822884412e-04f, +3.825195300e-04f, +3.113193898e-05f, -5.086432784e-04f, -1.054089829e-03f, -1.370322771e-03f, -1.280408741e-03f, -7.618428442e-04f, +2.606329026e-05f, +8.046117557e-04f, +1.299302728e-03f, +1.361247582e-03f, +1.024325735e-03f, +4.723795438e-04f, -5.993810822e-05f, -3.960765690e-04f, -4.809335107e-04f, -3.748938080e-04f, -1.951315810e-04f, -4.545052445e-05f,
-    /* 24, 0 */ -1.702250368e-04f, -1.965005420e-04f, +1.103795304e-06f, +4.330784212e-04f, +8.784555707e-04f, +9.653328276e-04f, +4.315509563e-04f, -6.109575553e-04f, -1.641723450e-03f, -2.015827225e-03f, -1.400787443e-03f, -4.702498413e-05f, +1.332047630e-03f, +2.006889303e-03f, +1.690240096e-03f, +6.826705419e-04f, -3.776686811e-04f, -9.512688743e-04f, -8.983149818e-04f, -4.640234647e-04f, -2.230828855e-05f, +1.918067822e-04f, +1.759255972e-04f, +6.786242515e-05f,
-    /* 24, 1 */ -1.642126010e-04f, -2.002752798e-04f, -1.910126829e-05f, +4.022439121e-04f, +8.571608722e-04f, +9.768399670e-04f, +4.832977173e-04f, -5.392469404e-04f, -1.590532482e-03f, -2.020693110e-03f, -1.466475318e-03f, -1.409702826e-04f, +1.260398022e-03f, +1.993868298e-03f, +1.735939471e-03f, +7.542164043e-04f, -3.217397652e-04f, -9.346209288e-04f, -9.166430096e-04f, -4.949934945e-04f, -4.448641826e-05f, +1.861665779e-04f, +1.812738819e-04f, +7.451957718e-05f,
-    /* 24, 2 */ -1.579281336e-04f, -2.031605347e-04f, -3.828516688e-05f, +3.716026326e-04f, +8.345286135e-04f, +9.858238344e-04f, +5.328272649e-04f, -4.677058239e-04f, -1.536815378e-03f, -2.021508037e-03f, -1.528977139e-03f, -2.346018520e-04f, +1.185988431e-03f, +1.976763286e-03f, +1.778684302e-03f, +8.254237228e-04f, -2.638601140e-04f, -9.153683790e-04f, -9.333455225e-04f, -5.259003096e-04f, -6.760829922e-05f, +1.795547962e-04f, +1.862290729e-04f, +8.132190552e-05f,
-    /* 24, 3 */ -1.514107898e-04f, -2.051877883e-04f, -5.643017558e-05f, +3.412342375e-04f, +8.106578209e-04f, +9.923241157e-04f, +5.800651921e-04f, -3.964985305e-04f, -1.480725107e-03f, -2.018303000e-03f, -1.588167145e-03f, -3.277114722e-04f, +1.108975953e-03f, +1.955583535e-03f, +1.818343426e-03f, +8.961196099e-04f, -2.041325004e-04f, -8.934973649e-04f, -9.483306864e-04f, -5.566532714e-04f, -9.163993343e-05f, +1.719487619e-04f, +1.907500791e-04f, +8.824611727e-05f,
-    /* 24, 4 */ -1.446989102e-04f, -2.063902871e-04f, -7.352252002e-05f, +3.112151687e-04f, +7.856484910e-04f, +9.963864071e-04f, +6.249444785e-04f, -3.257861630e-04f, -1.422418959e-03f, -2.011118755e-03f, -1.643928243e-03f, -4.200923193e-04f, +1.029524574e-03f, +1.930348530e-03f, +1.854792197e-03f, +9.661301752e-04f, -1.426663759e-04f, -8.690009463e-04f, -9.615092978e-04f, -5.871595310e-04f, -1.165432034e-04f, +1.633284218e-04f, +1.947956873e-04f, +9.526723781e-05f,
-    /* 24, 5 */ -1.378299032e-04f, -2.068028652e-04f, -8.955230425e-05f, +2.816184974e-04f, +7.596012646e-04f, +9.980619660e-04f, +6.674055614e-04f, -2.557261963e-04f, -1.362058071e-03f, -2.000005648e-03f, -1.696152289e-03f, -5.115395181e-04f, +9.478047386e-04f, +1.901087985e-03f, +1.887912892e-03f, +1.035280999e-03f, -7.957765930e-05f, -8.418792522e-04f, -9.727951144e-04f, -6.173242692e-04f, -1.422758795e-04f, +1.536765045e-04f, +1.983247179e-04f, +1.023586489e-04f,
-    /* 24, 6 */ -1.308401336e-04f, -2.064617646e-04f, -1.045134271e-04f, +2.525137807e-04f, +7.326171060e-04f, +9.974074494e-04f, +7.073963828e-04f, -1.864720875e-04f, -1.299806951e-03f, -1.985023411e-03f, -1.744740344e-03f, -6.018506887e-04f, +8.639929140e-04f, +1.867841815e-03f, +1.917595086e-03f, +1.103397612e-03f, -1.498850339e-05f, -8.121396097e-04f, -9.821051828e-04f, -6.470509490e-04f, -1.687916421e-04f, +1.429786744e-04f, +2.012961856e-04f, +1.094921351e-04f,
-    /* 24, 7 */ -1.237648199e-04f, -2.054044567e-04f, -1.184034872e-04f, +2.239669341e-04f, +7.047969872e-04f, +9.944846402e-04f, +7.448724134e-04f, -1.181729029e-04f, -1.235832990e-03f, -1.966240936e-03f, -1.789602898e-03f, -6.908264855e-04f, +7.782711267e-04f, +1.830660078e-03f, +1.943736019e-03f, +1.170305979e-03f, +5.097296116e-05f, -7.797966533e-04f, -9.893601617e-04f, -6.762415789e-04f, -1.960401183e-04f, +1.312236785e-04f, +2.036694644e-04f, +1.166379381e-04f,
-    /* 24, 8 */ -1.166379381e-04f, -2.036694644e-04f, -1.312236785e-04f, +1.960401183e-04f, +6.762415789e-04f, +9.893601617e-04f, +7.797966533e-04f, -5.097296116e-05f, -1.170305979e-03f, -1.943736019e-03f, -1.830660078e-03f, -7.782711267e-04f, +6.908264855e-04f, +1.789602898e-03f, +1.966240936e-03f, +1.235832990e-03f, +1.181729029e-04f, -7.448724134e-04f, -9.944846402e-04f, -7.047969872e-04f, -2.239669341e-04f, +1.184034872e-04f, +2.054044567e-04f, +1.237648199e-04f,
-    /* 24, 9 */ -1.094921351e-04f, -2.012961856e-04f, -1.429786744e-04f, +1.687916421e-04f, +6.470509490e-04f, +9.821051828e-04f, +8.121396097e-04f, +1.498850339e-05f, -1.103397612e-03f, -1.917595086e-03f, -1.867841815e-03f, -8.639929140e-04f, +6.018506887e-04f, +1.744740344e-03f, +1.985023411e-03f, +1.299806951e-03f, +1.864720875e-04f, -7.073963828e-04f, -9.974074494e-04f, -7.326171060e-04f, -2.525137807e-04f, +1.045134271e-04f, +2.064617646e-04f, +1.308401336e-04f,
-    /* 24,10 */ -1.023586489e-04f, -1.983247179e-04f, -1.536765045e-04f, +1.422758795e-04f, +6.173242692e-04f, +9.727951144e-04f, +8.418792522e-04f, +7.957765930e-05f, -1.035280999e-03f, -1.887912892e-03f, -1.901087985e-03f, -9.478047386e-04f, +5.115395181e-04f, +1.696152289e-03f, +2.000005648e-03f, +1.362058071e-03f, +2.557261963e-04f, -6.674055614e-04f, -9.980619660e-04f, -7.596012646e-04f, -2.816184974e-04f, +8.955230425e-05f, +2.068028652e-04f, +1.378299032e-04f,
-    /* 24,11 */ -9.526723781e-05f, -1.947956873e-04f, -1.633284218e-04f, +1.165432034e-04f, +5.871595310e-04f, +9.615092978e-04f, +8.690009463e-04f, +1.426663759e-04f, -9.661301752e-04f, -1.854792197e-03f, -1.930348530e-03f, -1.029524574e-03f, +4.200923193e-04f, +1.643928243e-03f, +2.011118755e-03f, +1.422418959e-03f, +3.257861630e-04f, -6.249444785e-04f, -9.963864071e-04f, -7.856484910e-04f, -3.112151687e-04f, +7.352252002e-05f, +2.063902871e-04f, +1.446989102e-04f,
-    /* 24,12 */ -8.824611727e-05f, -1.907500791e-04f, -1.719487619e-04f, +9.163993343e-05f, +5.566532714e-04f, +9.483306864e-04f, +8.934973649e-04f, +2.041325004e-04f, -8.961196099e-04f, -1.818343426e-03f, -1.955583535e-03f, -1.108975953e-03f, +3.277114722e-04f, +1.588167145e-03f, +2.018303000e-03f, +1.480725107e-03f, +3.964985305e-04f, -5.800651921e-04f, -9.923241157e-04f, -8.106578209e-04f, -3.412342375e-04f, +5.643017558e-05f, +2.051877883e-04f, +1.514107898e-04f,
-    /* 24,13 */ -8.132190552e-05f, -1.862290729e-04f, -1.795547962e-04f, +6.760829922e-05f, +5.259003096e-04f, +9.333455225e-04f, +9.153683790e-04f, +2.638601140e-04f, -8.254237228e-04f, -1.778684302e-03f, -1.976763286e-03f, -1.185988431e-03f, +2.346018520e-04f, +1.528977139e-03f, +2.021508037e-03f, +1.536815378e-03f, +4.677058239e-04f, -5.328272649e-04f, -9.858238344e-04f, -8.345286135e-04f, -3.716026326e-04f, +3.828516688e-05f, +2.031605347e-04f, +1.579281336e-04f,
-    /* 24,14 */ -7.451957718e-05f, -1.812738819e-04f, -1.861665779e-04f, +4.448641826e-05f, +4.949934945e-04f, +9.166430096e-04f, +9.346209288e-04f, +3.217397652e-04f, -7.542164043e-04f, -1.735939471e-03f, -1.993868298e-03f, -1.260398022e-03f, +1.409702826e-04f, +1.466475318e-03f, +2.020693110e-03f, +1.590532482e-03f, +5.392469404e-04f, -4.832977173e-04f, -9.768399670e-04f, -8.571608722e-04f, -4.022439121e-04f, +1.910126829e-05f, +2.002752798e-04f, +1.642126010e-04f,
-    /* 24,15 */ -6.786242515e-05f, -1.759255972e-04f, -1.918067822e-04f, +2.230828855e-05f, +4.640234647e-04f, +8.983149818e-04f, +9.512688743e-04f, +3.776686811e-04f, -6.826705419e-04f, -1.690240096e-03f, -2.006889303e-03f, -1.332047630e-03f, +4.702498413e-05f, +1.400787443e-03f, +2.015827225e-03f, +1.641723450e-03f, +6.109575553e-04f, -4.315509563e-04f, -9.653328276e-04f, -8.784555707e-04f, -4.330784212e-04f, -1.103795304e-06f, +1.965005420e-04f, +1.702250368e-04f,
-    /* 24, 0 */ +3.919255962e-05f, -2.280943782e-04f, -5.361345988e-04f, -4.457457641e-04f, +2.990589649e-04f, +1.295797675e-03f, +1.605517166e-03f, +5.875816565e-04f, -1.289084098e-03f, -2.596166105e-03f, -2.129939921e-03f, -7.496988250e-05f, +2.037180601e-03f, +2.625542335e-03f, +1.404160874e-03f, -4.837783526e-04f, -1.582480410e-03f, -1.345619201e-03f, -3.621830939e-04f, +4.180945199e-04f, +5.469818219e-04f, +2.499414065e-04f, -2.888372260e-05f, -8.895700627e-05f,
-    /* 24, 1 */ +4.853777483e-05f, -2.065137544e-04f, -5.236754574e-04f, -4.705972357e-04f, +2.371311675e-04f, +1.243196859e-03f, +1.622959247e-03f, +6.876650067e-04f, -1.171710060e-03f, -2.559351067e-03f, -2.215991331e-03f, -2.246678327e-04f, +1.937986318e-03f, +2.647321756e-03f, +1.516528605e-03f, -3.765445934e-04f, -1.553807591e-03f, -1.392405213e-03f, -4.263006320e-04f, +3.876486968e-04f, +5.560961676e-04f, +2.719611444e-04f, -1.761075235e-05f, -9.068976925e-05f,
-    /* 24, 2 */ +5.692498928e-05f, -1.852878923e-04f, -5.097279107e-04f, -4.926555685e-04f, +1.765921503e-04f, +1.188077447e-03f, +1.634867875e-03f, +7.837567953e-04f, -1.052453928e-03f, -2.515280079e-03f, -2.295086316e-03f, -3.736412373e-04f, +1.832653524e-03f, +2.661371990e-03f, +1.625780509e-03f, -2.661868955e-04f, -1.519477670e-03f, -1.435905115e-03f, -4.911987788e-04f, +3.544256494e-04f, +5.633598944e-04f, +2.940548284e-04f, -5.378471232e-06f, -9.187426948e-05f,
-    /* 24, 3 */ +6.436469025e-05f, -1.644995777e-04f, -4.944173708e-04f, -5.119388451e-04f, +1.176233517e-04f, +1.130703462e-03f, +1.641323506e-03f, +8.756040923e-04f, -9.317326579e-04f, -2.464159993e-03f, -2.367001633e-03f, -5.214100591e-04f, +1.721501142e-03f, +2.667586958e-03f, +1.731516399e-03f, -1.530278412e-04f, -1.479490407e-03f, -1.475875084e-03f, -5.566555092e-04f, +3.184551797e-04f, +5.686591450e-04f, +3.161189305e-04f, +7.802761507e-06f, -9.246489856e-05f,
-    /* 24, 4 */ +7.087197068e-05f, -1.442258278e-04f, -4.778705046e-04f, -5.284761768e-04f, +6.039472401e-05f, +1.071341110e-03f, +1.642425167e-03f, +9.629733481e-04f, -8.099633882e-04f, -2.406220702e-03f, -2.431540042e-03f, -6.674987371e-04f, +1.604869446e-03f, +2.665887444e-03f, +1.833344283e-03f, -3.740504807e-05f, -1.433866725e-03f, -1.512079220e-03f, -6.224402836e-04f, +2.797797731e-04f, +5.718846156e-04f, +3.380454975e-04f, +2.191686946e-05f, -9.241721523e-05f,
-    /* 24, 5 */ +7.646625331e-05f, -1.245377292e-04f, -4.602146020e-04f, -5.423072437e-04f, +5.064318866e-06f, +1.010257658e-03f, +1.638289725e-03f, +1.045651008e-03f, -6.875618648e-04f, -2.341714107e-03f, -2.488530931e-03f, -8.114379517e-04f, +1.483118851e-03f, +2.656221571e-03f, +1.930881931e-03f, +8.032993590e-05f, -1.382648990e-03f, -1.544290670e-03f, -6.883148110e-04f, +2.384547825e-04f, +5.729322223e-04f, +3.597225244e-04f, +3.694190340e-05f, -9.168826568e-05f,
-    /* 24, 6 */ +8.117100143e-05f, -1.055003114e-04f, -4.415769617e-04f, -5.534817998e-04f, -4.822206513e-05f, +9.477203224e-04f, +1.629051096e-03f, +1.123444034e-03f, -5.649408783e-04f, -2.270913001e-03f, -2.537830838e-03f, -9.527663633e-04f, +1.356628624e-03f, +2.638565156e-03f, +2.023758423e-03f, +1.998128074e-04f, -1.325901212e-03f, -1.572292748e-03f, -7.540338642e-04f, +1.945485578e-04f, +5.717037624e-04f, +3.810343609e-04f, +5.284991195e-05f, -9.023690790e-05f,
-    /* 24, 7 */ +8.501341847e-05f, -8.717245610e-05f, -4.220842946e-04f, -5.620591450e-04f, -9.933117260e-05f, +8.839951872e-04f, +1.614859393e-03f, +1.196180345e-03f, -4.425087329e-04f, -2.194109877e-03f, -2.579323863e-03f, -1.091032318e-03f, +1.225795515e-03f, +2.612921966e-03f, +2.111615667e-03f, +3.206677492e-04f, -1.263709151e-03f, -1.595880025e-03f, -8.193461436e-04f, +1.481425192e-04f, +5.681075679e-04f, +4.018621494e-04f, +6.960683992e-05f, -8.802413824e-05f,
-    /* 24, 8 */ +8.802413824e-05f, -6.960683992e-05f, -4.018621494e-04f, -5.681075679e-04f, -1.481425192e-04f, +8.193461436e-04f, +1.595880025e-03f, +1.263709151e-03f, -3.206677492e-04f, -2.111615667e-03f, -2.612921966e-03f, -1.225795515e-03f, +1.091032318e-03f, +2.579323863e-03f, +2.194109877e-03f, +4.425087329e-04f, -1.196180345e-03f, -1.614859393e-03f, -8.839951872e-04f, +9.933117260e-05f, +5.620591450e-04f, +4.220842946e-04f, +8.717245610e-05f, -8.501341847e-05f,
-    /* 24, 9 */ +9.023690790e-05f, -5.284991195e-05f, -3.810343609e-04f, -5.717037624e-04f, -1.945485578e-04f, +7.540338642e-04f, +1.572292748e-03f, +1.325901212e-03f, -1.998128074e-04f, -2.023758423e-03f, -2.638565156e-03f, -1.356628624e-03f, +9.527663633e-04f, +2.537830838e-03f, +2.270913001e-03f, +5.649408783e-04f, -1.123444034e-03f, -1.629051096e-03f, -9.477203224e-04f, +4.822206513e-05f, +5.534817998e-04f, +4.415769617e-04f, +1.055003114e-04f, -8.117100143e-05f,
-    /* 24,10 */ +9.168826568e-05f, -3.694190340e-05f, -3.597225244e-04f, -5.729322223e-04f, -2.384547825e-04f, +6.883148110e-04f, +1.544290670e-03f, +1.382648990e-03f, -8.032993590e-05f, -1.930881931e-03f, -2.656221571e-03f, -1.483118851e-03f, +8.114379517e-04f, +2.488530931e-03f, +2.341714107e-03f, +6.875618648e-04f, -1.045651008e-03f, -1.638289725e-03f, -1.010257658e-03f, -5.064318866e-06f, +5.423072437e-04f, +4.602146020e-04f, +1.245377292e-04f, -7.646625331e-05f,
-    /* 24,11 */ +9.241721523e-05f, -2.191686946e-05f, -3.380454975e-04f, -5.718846156e-04f, -2.797797731e-04f, +6.224402836e-04f, +1.512079220e-03f, +1.433866725e-03f, +3.740504807e-05f, -1.833344283e-03f, -2.665887444e-03f, -1.604869446e-03f, +6.674987371e-04f, +2.431540042e-03f, +2.406220702e-03f, +8.099633882e-04f, -9.629733481e-04f, -1.642425167e-03f, -1.071341110e-03f, -6.039472401e-05f, +5.284761768e-04f, +4.778705046e-04f, +1.442258278e-04f, -7.087197068e-05f,
-    /* 24,12 */ +9.246489856e-05f, -7.802761507e-06f, -3.161189305e-04f, -5.686591450e-04f, -3.184551797e-04f, +5.566555092e-04f, +1.475875084e-03f, +1.479490407e-03f, +1.530278412e-04f, -1.731516399e-03f, -2.667586958e-03f, -1.721501142e-03f, +5.214100591e-04f, +2.367001633e-03f, +2.464159993e-03f, +9.317326579e-04f, -8.756040923e-04f, -1.641323506e-03f, -1.130703462e-03f, -1.176233517e-04f, +5.119388451e-04f, +4.944173708e-04f, +1.644995777e-04f, -6.436469025e-05f,
-    /* 24,13 */ +9.187426948e-05f, +5.378471232e-06f, -2.940548284e-04f, -5.633598944e-04f, -3.544256494e-04f, +4.911987788e-04f, +1.435905115e-03f, +1.519477670e-03f, +2.661868955e-04f, -1.625780509e-03f, -2.661371990e-03f, -1.832653524e-03f, +3.736412373e-04f, +2.295086316e-03f, +2.515280079e-03f, +1.052453928e-03f, -7.837567953e-04f, -1.634867875e-03f, -1.188077447e-03f, -1.765921503e-04f, +4.926555685e-04f, +5.097279107e-04f, +1.852878923e-04f, -5.692498928e-05f,
-    /* 24,14 */ +9.068976925e-05f, +1.761075235e-05f, -2.719611444e-04f, -5.560961676e-04f, -3.876486968e-04f, +4.263006320e-04f, +1.392405213e-03f, +1.553807591e-03f, +3.765445934e-04f, -1.516528605e-03f, -2.647321756e-03f, -1.937986318e-03f, +2.246678327e-04f, +2.215991331e-03f, +2.559351067e-03f, +1.171710060e-03f, -6.876650067e-04f, -1.622959247e-03f, -1.243196859e-03f, -2.371311675e-04f, +4.705972357e-04f, +5.236754574e-04f, +2.065137544e-04f, -4.853777483e-05f,
-    /* 24,15 */ +8.895700627e-05f, +2.888372260e-05f, -2.499414065e-04f, -5.469818219e-04f, -4.180945199e-04f, +3.621830939e-04f, +1.345619201e-03f, +1.582480410e-03f, +4.837783526e-04f, -1.404160874e-03f, -2.625542335e-03f, -2.037180601e-03f, +7.496988250e-05f, +2.129939921e-03f, +2.596166105e-03f, +1.289084098e-03f, -5.875816565e-04f, -1.605517166e-03f, -1.295797675e-03f, -2.990589649e-04f, +4.457457641e-04f, +5.361345988e-04f, +2.280943782e-04f, -3.919255962e-05f,
-    /* 24, 0 */ +1.848082291e-04f, +3.126544607e-04f, -8.381805218e-05f, -8.698090905e-04f, -1.028447094e-03f, +2.139154673e-04f, +1.954115341e-03f, +2.095678120e-03f, -1.635717275e-04f, -2.819157299e-03f, -2.940044791e-03f, -1.098945345e-04f, +2.833179926e-03f, +2.923929522e-03f, +3.511165299e-04f, -2.017938339e-03f, -2.030476715e-03f, -3.277888569e-04f, +9.926761418e-04f, +9.110442493e-04f, +1.284872781e-04f, -3.065935448e-04f, -1.998565163e-04f, +7.803305534e-06f,
-    /* 24, 1 */ +1.695814378e-04f, +3.164556508e-04f, -4.103650150e-05f, -8.260698464e-04f, -1.058100498e-03f, +1.024893805e-04f, +1.871044125e-03f, +2.162944507e-03f, +2.203366063e-05f, -2.703524226e-03f, -3.034115138e-03f, -3.291928088e-04f, +2.713944640e-03f, +3.017272284e-03f, +5.397663057e-04f, -1.929900383e-03f, -2.099607997e-03f, -4.436146208e-04f, +9.507629285e-04f, +9.494468230e-04f, +1.748714247e-04f, -2.981837386e-04f, -2.146007649e-04f, -5.699432396e-07f,
-    /* 24, 2 */ +1.542962580e-04f, +3.180964801e-04f, -2.971107404e-07f, -7.801571616e-04f, -1.081692695e-03f, -6.019646704e-06f, +1.781805749e-03f, +2.219616197e-03f, +2.048848004e-04f, -2.577645910e-03f, -3.115029215e-03f, -5.470211463e-04f, +2.582823494e-03f, +3.098667200e-03f, +7.286710477e-04f, -1.831793311e-03f, -2.161014579e-03f, -5.608747689e-04f, +9.027154107e-04f, +9.846924856e-04f, +2.227798586e-04f, -2.873471247e-04f, -2.289106872e-04f, -9.773337074e-06f,
-    /* 24, 3 */ +1.390667857e-04f, +3.176854393e-04f, +3.826416878e-05f, -7.324018434e-04f, -1.099310451e-03f, -1.111689527e-04f, +1.686962051e-03f, +2.265625589e-03f, +3.841903571e-04f, -2.442181508e-03f, -3.182489175e-03f, -7.624077328e-04f, +2.440359294e-03f, +3.167649091e-03f, +9.169693475e-04f, -1.723899657e-03f, -2.214230624e-03f, -6.790305367e-04f, +8.485750922e-04f, +1.016463150e-03f, +2.720045869e-04f, -2.740180422e-04f, -2.426519708e-04f, -1.978701792e-05f,
-    /* 24, 4 */ +1.240005643e-04f, +3.153390489e-04f, +7.453005747e-05f, -6.831329371e-04f, -1.111069621e-03f, -2.125447010e-04f, +1.587090707e-03f, +2.300958285e-03f, +5.591862212e-04f, -2.297830066e-03f, -3.236262287e-03f, -9.743929228e-04f, +2.287150577e-03f, +3.223808711e-03f, +1.103792665e-03f, -1.606554759e-03f, -2.258822083e-03f, -7.975248409e-04f, +7.884177261e-04f, +1.044449054e-03f, +3.223209063e-04f, -2.581440514e-04f, -2.556870681e-04f, -3.058317705e-05f,
-    /* 24, 5 */ +1.091981202e-04f, +3.111807515e-04f, +1.084019636e-04f, -6.326758693e-04f, -1.117113666e-03f, -3.097634105e-04f, +1.482781879e-03f, +2.325652312e-03f, +7.291390495e-04f, -2.145326692e-03f, -3.276181809e-03f, -1.182034015e-03f, +2.123848782e-03f, +3.266795190e-03f, +1.288269679e-03f, -1.480145805e-03f, -2.294389599e-03f, -9.157848908e-04f, +7.223538352e-04f, +1.068350860e-03f, +3.734881809e-04f, -2.396868442e-04f, -2.678760406e-04f, -4.212586861e-05f,
-    /* 24, 6 */ +9.475256757e-05f, +3.053397988e-04f, +1.397998805e-04f, -5.813506695e-04f, -1.117612060e-03f, -4.024732802e-04f, +1.374634870e-03f, +2.339797075e-03f, +8.933496022e-04f, -1.985438555e-03f, -3.302147511e-03f, -1.384409934e-03f, +1.951155148e-03f, +3.296318191e-03f, +1.469530695e-03f, -1.345110577e-03f, -2.320571262e-03f, -1.033224945e-03f, +6.505290403e-04f, +1.087881752e-03f, +4.252507475e-04f, -2.186230940e-04f, -2.790774568e-04f, -5.437087857e-05f,
-    /* 24, 7 */ +8.074928352e-05f, +2.979501429e-04f, +1.686621699e-04f, -5.294702777e-04f, -1.112758583e-03f, -4.903553074e-04f, +1.263254779e-03f, +2.343532047e-03f, +1.051155860e-03f, -1.818960757e-03f, -3.314125843e-03f, -1.580625796e-03f, +1.769817333e-03f, +3.312149758e-03f, +1.646712089e-03f, -1.201935910e-03f, -2.337045209e-03f, -1.149249197e-03f, +5.731241934e-04f, +1.102769514e-03f, +4.773389469e-04f, -1.949452358e-04f, -2.891493374e-04f, -6.726565227e-05f,
-    /* 24, 8 */ +6.726565227e-05f, +2.891493374e-04f, +1.949452358e-04f, -4.773389469e-04f, -1.102769514e-03f, -5.731241934e-04f, +1.149249197e-03f, +2.337045209e-03f, +1.201935910e-03f, -1.646712089e-03f, -3.312149758e-03f, -1.769817333e-03f, +1.580625796e-03f, +3.314125843e-03f, +1.818960757e-03f, -1.051155860e-03f, -2.343532047e-03f, -1.263254779e-03f, +4.903553074e-04f, +1.112758583e-03f, +5.294702777e-04f, -1.686621699e-04f, -2.979501429e-04f, -8.074928352e-05f,
-    /* 24, 9 */ +5.437087857e-05f, +2.790774568e-04f, +2.186230940e-04f, -4.252507475e-04f, -1.087881752e-03f, -6.505290403e-04f, +1.033224945e-03f, +2.320571262e-03f, +1.345110577e-03f, -1.469530695e-03f, -3.296318191e-03f, -1.951155148e-03f, +1.384409934e-03f, +3.302147511e-03f, +1.985438555e-03f, -8.933496022e-04f, -2.339797075e-03f, -1.374634870e-03f, +4.024732802e-04f, +1.117612060e-03f, +5.813506695e-04f, -1.397998805e-04f, -3.053397988e-04f, -9.475256757e-05f,
-    /* 24,10 */ +4.212586861e-05f, +2.678760406e-04f, +2.396868442e-04f, -3.734881809e-04f, -1.068350860e-03f, -7.223538352e-04f, +9.157848908e-04f, +2.294389599e-03f, +1.480145805e-03f, -1.288269679e-03f, -3.266795190e-03f, -2.123848782e-03f, +1.182034015e-03f, +3.276181809e-03f, +2.145326692e-03f, -7.291390495e-04f, -2.325652312e-03f, -1.482781879e-03f, +3.097634105e-04f, +1.117113666e-03f, +6.326758693e-04f, -1.084019636e-04f, -3.111807515e-04f, -1.091981202e-04f,
-    /* 24,11 */ +3.058317705e-05f, +2.556870681e-04f, +2.581440514e-04f, -3.223209063e-04f, -1.044449054e-03f, -7.884177261e-04f, +7.975248409e-04f, +2.258822083e-03f, +1.606554759e-03f, -1.103792665e-03f, -3.223808711e-03f, -2.287150577e-03f, +9.743929228e-04f, +3.236262287e-03f, +2.297830066e-03f, -5.591862212e-04f, -2.300958285e-03f, -1.587090707e-03f, +2.125447010e-04f, +1.111069621e-03f, +6.831329371e-04f, -7.453005747e-05f, -3.153390489e-04f, -1.240005643e-04f,
-    /* 24,12 */ +1.978701792e-05f, +2.426519708e-04f, +2.740180422e-04f, -2.720045869e-04f, -1.016463150e-03f, -8.485750922e-04f, +6.790305367e-04f, +2.214230624e-03f, +1.723899657e-03f, -9.169693475e-04f, -3.167649091e-03f, -2.440359294e-03f, +7.624077328e-04f, +3.182489175e-03f, +2.442181508e-03f, -3.841903571e-04f, -2.265625589e-03f, -1.686962051e-03f, +1.111689527e-04f, +1.099310451e-03f, +7.324018434e-04f, -3.826416878e-05f, -3.176854393e-04f, -1.390667857e-04f,
-    /* 24,13 */ +9.773337074e-06f, +2.289106872e-04f, +2.873471247e-04f, -2.227798586e-04f, -9.846924856e-04f, -9.027154107e-04f, +5.608747689e-04f, +2.161014579e-03f, +1.831793311e-03f, -7.286710477e-04f, -3.098667200e-03f, -2.582823494e-03f, +5.470211463e-04f, +3.115029215e-03f, +2.577645910e-03f, -2.048848004e-04f, -2.219616197e-03f, -1.781805749e-03f, +6.019646704e-06f, +1.081692695e-03f, +7.801571616e-04f, +2.971107404e-07f, -3.180964801e-04f, -1.542962580e-04f,
-    /* 24,14 */ +5.699432396e-07f, +2.146007649e-04f, +2.981837386e-04f, -1.748714247e-04f, -9.494468230e-04f, -9.507629285e-04f, +4.436146208e-04f, +2.099607997e-03f, +1.929900383e-03f, -5.397663057e-04f, -3.017272284e-03f, -2.713944640e-03f, +3.291928088e-04f, +3.034115138e-03f, +2.703524226e-03f, -2.203366063e-05f, -2.162944507e-03f, -1.871044125e-03f, -1.024893805e-04f, +1.058100498e-03f, +8.260698464e-04f, +4.103650150e-05f, -3.164556508e-04f, -1.695814378e-04f,
-    /* 24,15 */ -7.803305534e-06f, +1.998565163e-04f, +3.065935448e-04f, -1.284872781e-04f, -9.110442493e-04f, -9.926761418e-04f, +3.277888569e-04f, +2.030476715e-03f, +2.017938339e-03f, -3.511165299e-04f, -2.923929522e-03f, -2.833179926e-03f, +1.098945345e-04f, +2.940044791e-03f, +2.819157299e-03f, +1.635717275e-04f, -2.095678120e-03f, -1.954115341e-03f, -2.139154673e-04f, +1.028447094e-03f, +8.698090905e-04f, +8.381805218e-05f, -3.126544607e-04f, -1.848082291e-04f,
-    /* 24, 0 */ -1.364396009e-04f, -7.446376994e-05f, +5.066257662e-04f, +2.030015760e-04f, -9.054261715e-04f, -1.195525937e-03f, +4.683850093e-04f, +2.213825561e-03f, +1.188944940e-03f, -1.856378227e-03f, -2.833970964e-03f, -1.144377463e-04f, +2.758138339e-03f, +2.020697482e-03f, -1.023174933e-03f, -2.248631080e-03f, -6.097868283e-04f, +1.146194663e-03f, +9.693248739e-04f, -1.479047908e-04f, -5.177782008e-04f, -1.250536964e-04f, +1.414906982e-04f, +2.710774794e-05f,
-    /* 24, 1 */ -1.307026563e-04f, -8.975162518e-05f, +4.924131238e-04f, +2.542107757e-04f, -8.382130226e-04f, -1.235986710e-03f, +3.277877666e-04f, +2.166758574e-03f, +1.345406789e-03f, -1.683014413e-03f, -2.893234801e-03f, -3.426248829e-04f, +2.666119545e-03f, +2.174888063e-03f, -8.489895579e-04f, -2.270723567e-03f, -7.511023835e-04f, +1.088054225e-03f, +1.029345157e-03f, -8.915647260e-05f, -5.256253050e-04f, -1.535492882e-04f, +1.457592711e-04f, +3.374854096e-05f,
-    /* 24, 2 */ -1.243758393e-04f, -1.032931784e-04f, +4.753985127e-04f, +3.013338450e-04f, -7.682542954e-04f, -1.267577330e-03f, +1.888607322e-04f, +2.107952975e-03f, +1.491738775e-03f, -1.501737881e-03f, -2.935653267e-03f, -5.687514710e-04f, +2.558401145e-03f, +2.317921172e-03f, -6.673475630e-04f, -2.279727032e-03f, -8.914213340e-04f, +1.021228789e-03f, +1.084932315e-03f, -2.702967135e-05f, -5.299376467e-04f, -1.826837732e-04f, +1.491486840e-04f, +4.073257728e-05f,
-    /* 24, 3 */ -1.175537217e-04f, -1.151066589e-04f, +4.558506985e-04f, +3.442099484e-04f, -6.961194660e-04f, -1.290358261e-03f, +5.243891240e-05f, +2.037998203e-03f, +1.627194859e-03f, -1.313720334e-03f, -2.961057174e-03f, -7.914588446e-04f, +2.435570833e-03f, +2.448830599e-03f, -4.792680017e-04f, -2.275344863e-03f, -1.029819797e-03f, +9.459060659e-04f, +1.135545329e-03f, +3.816638860e-05f, -5.305040204e-04f, -2.122423012e-04f, +1.515631236e-04f, +4.801831197e-05f,
-    /* 24, 4 */ -1.103288160e-04f, -1.252215041e-04f, +4.340463917e-04f, +3.827158599e-04f, -6.223744454e-04f, -1.304448109e-03f, -8.067840470e-05f, +1.957545178e-03f, +1.751108674e-03f, -1.120165265e-03f, -2.969385358e-03f, -1.009410776e-03f, +2.298313921e-03f, +2.566719612e-03f, -2.858241016e-04f, -2.257363134e-03f, -1.165366520e-03f, +8.623375551e-04f, +1.180661312e-03f, +1.060874480e-04f, -5.271339238e-04f, -2.419953224e-04f, +1.529084143e-04f, +5.555842361e-05f,
-    /* 24, 5 */ -1.027909684e-04f, -1.336775649e-04f, +4.102676936e-04f, +4.167655723e-04f, -5.475775503e-04f, -1.310021272e-03f, -2.097323863e-04f, +1.867300846e-03f, +1.862896930e-03f, -9.222997333e-04f, -2.960684559e-03f, -1.221302229e-03f, +2.147409148e-03f, +2.670767418e-03f, -8.813668768e-05f, -2.225653372e-03f, -1.297129225e-03f, +7.708383352e-04f, +1.219779926e-03f, +1.763556677e-04f, -5.196599496e-04f, -2.716999419e-04f, +1.530928622e-04f, +6.329988035e-05f,
-    /* 24, 6 */ -9.502680145e-05f, -1.405242734e-04f, +3.847995909e-04f, +4.463096266e-04f, -4.722756447e-04f, -1.307305241e-03f, -3.340090076e-04f, +1.768022423e-03f, +1.962062202e-03f, -7.213660470e-04f, -2.935108571e-03f, -1.425867893e-03f, +1.983723834e-03f, +2.760235146e-03f, +1.126327965e-04f, -2.180174758e-03f, -1.424181074e-03f, +6.717863708e-04f, +1.252427754e-03f, +2.485613970e-04f, -5.079400707e-04f, -3.011014490e-04f, +1.520281231e-04f, +7.118405837e-05f,
-    /* 24, 7 */ -8.711921055e-05f, -1.458197836e-04f, +3.579275186e-04f, +4.713341756e-04f, -3.970004792e-04f, -1.296577576e-03f, -4.528429958e-04f, +1.660511380e-03f, +2.048195092e-03f, -5.186134147e-04f, -2.892916666e-03f, -1.621890436e-03f, +1.808208423e-03f, +2.834471303e-03f, +3.152896222e-04f, -2.120975750e-03f, -1.545607217e-03f, +5.656213428e-04f, +1.278162587e-03f, +3.222652495e-04f, -4.918597964e-04f, -3.299350101e-04f, +1.496300883e-04f, +7.914691395e-05f,
-    /* 24, 8 */ -7.914691395e-05f, -1.496300883e-04f, +3.299350101e-04f, +4.918597964e-04f, -3.222652495e-04f, -1.278162587e-03f, -5.656213428e-04f, +1.545607217e-03f, +2.120975750e-03f, -3.152896222e-04f, -2.834471303e-03f, -1.808208423e-03f, +1.621890436e-03f, +2.892916666e-03f, +5.186134147e-04f, -2.048195092e-03f, -1.660511380e-03f, +4.528429958e-04f, +1.296577576e-03f, +3.970004792e-04f, -4.713341756e-04f, -3.579275186e-04f, +1.458197836e-04f, +8.711921055e-05f,
-    /* 24, 9 */ -7.118405837e-05f, -1.520281231e-04f, +3.011014490e-04f, +5.079400707e-04f, -2.485613970e-04f, -1.252427754e-03f, -6.717863708e-04f, +1.424181074e-03f, +2.180174758e-03f, -1.126327965e-04f, -2.760235146e-03f, -1.983723834e-03f, +1.425867893e-03f, +2.935108571e-03f, +7.213660470e-04f, -1.962062202e-03f, -1.768022423e-03f, +3.340090076e-04f, +1.307305241e-03f, +4.722756447e-04f, -4.463096266e-04f, -3.847995909e-04f, +1.405242734e-04f, +9.502680145e-05f,
-    /* 24,10 */ -6.329988035e-05f, -1.530928622e-04f, +2.716999419e-04f, +5.196599496e-04f, -1.763556677e-04f, -1.219779926e-03f, -7.708383352e-04f, +1.297129225e-03f, +2.225653372e-03f, +8.813668768e-05f, -2.670767418e-03f, -2.147409148e-03f, +1.221302229e-03f, +2.960684559e-03f, +9.222997333e-04f, -1.862896930e-03f, -1.867300846e-03f, +2.097323863e-04f, +1.310021272e-03f, +5.475775503e-04f, -4.167655723e-04f, -4.102676936e-04f, +1.336775649e-04f, +1.027909684e-04f,
-    /* 24,11 */ -5.555842361e-05f, -1.529084143e-04f, +2.419953224e-04f, +5.271339238e-04f, -1.060874480e-04f, -1.180661312e-03f, -8.623375551e-04f, +1.165366520e-03f, +2.257363134e-03f, +2.858241016e-04f, -2.566719612e-03f, -2.298313921e-03f, +1.009410776e-03f, +2.969385358e-03f, +1.120165265e-03f, -1.751108674e-03f, -1.957545178e-03f, +8.067840470e-05f, +1.304448109e-03f, +6.223744454e-04f, -3.827158599e-04f, -4.340463917e-04f, +1.252215041e-04f, +1.103288160e-04f,
-    /* 24,12 */ -4.801831197e-05f, -1.515631236e-04f, +2.122423012e-04f, +5.305040204e-04f, -3.816638860e-05f, -1.135545329e-03f, -9.459060659e-04f, +1.029819797e-03f, +2.275344863e-03f, +4.792680017e-04f, -2.448830599e-03f, -2.435570833e-03f, +7.914588446e-04f, +2.961057174e-03f, +1.313720334e-03f, -1.627194859e-03f, -2.037998203e-03f, -5.243891240e-05f, +1.290358261e-03f, +6.961194660e-04f, -3.442099484e-04f, -4.558506985e-04f, +1.151066589e-04f, +1.175537217e-04f,
-    /* 24,13 */ -4.073257728e-05f, -1.491486840e-04f, +1.826837732e-04f, +5.299376467e-04f, +2.702967135e-05f, -1.084932315e-03f, -1.021228789e-03f, +8.914213340e-04f, +2.279727032e-03f, +6.673475630e-04f, -2.317921172e-03f, -2.558401145e-03f, +5.687514710e-04f, +2.935653267e-03f, +1.501737881e-03f, -1.491738775e-03f, -2.107952975e-03f, -1.888607322e-04f, +1.267577330e-03f, +7.682542954e-04f, -3.013338450e-04f, -4.753985127e-04f, +1.032931784e-04f, +1.243758393e-04f,
-    /* 24,14 */ -3.374854096e-05f, -1.457592711e-04f, +1.535492882e-04f, +5.256253050e-04f, +8.915647260e-05f, -1.029345157e-03f, -1.088054225e-03f, +7.511023835e-04f, +2.270723567e-03f, +8.489895579e-04f, -2.174888063e-03f, -2.666119545e-03f, +3.426248829e-04f, +2.893234801e-03f, +1.683014413e-03f, -1.345406789e-03f, -2.166758574e-03f, -3.277877666e-04f, +1.235986710e-03f, +8.382130226e-04f, -2.542107757e-04f, -4.924131238e-04f, +8.975162518e-05f, +1.307026563e-04f,
-    /* 24,15 */ -2.710774794e-05f, -1.414906982e-04f, +1.250536964e-04f, +5.177782008e-04f, +1.479047908e-04f, -9.693248739e-04f, -1.146194663e-03f, +6.097868283e-04f, +2.248631080e-03f, +1.023174933e-03f, -2.020697482e-03f, -2.758138339e-03f, +1.144377463e-04f, +2.833970964e-03f, +1.856378227e-03f, -1.188944940e-03f, -2.213825561e-03f, -4.683850093e-04f, +1.195525937e-03f, +9.054261715e-04f, -2.030015760e-04f, -5.066257662e-04f, +7.446376994e-05f, +1.364396009e-04f,
-    /* 20, 0 */ +8.618377023e-05f, +6.063813654e-04f, +5.504304823e-05f, -1.285351444e-03f, -7.884572117e-04f, +1.698526656e-03f, +2.051642156e-03f, -1.208844608e-03f, -3.071261118e-03f, -1.337669627e-04f, +3.018986987e-03f, +1.434631920e-03f, -1.928392685e-03f, -1.831072241e-03f, +6.629429882e-04f, +1.334851066e-03f, +2.665316224e-05f, -6.158469302e-04f, -1.222533602e-04f, +1.824770389e-04f,
-    /* 20, 1 */ +5.170459821e-05f, +5.921181369e-04f, +1.325211661e-04f, -1.227728603e-03f, -9.042412445e-04f, +1.556639033e-03f, +2.157910711e-03f, -9.769935819e-04f, -3.101316201e-03f, -4.002989059e-04f, +2.944767882e-03f, +1.652572896e-03f, -1.788832610e-03f, -1.953018956e-03f, +5.284364506e-04f, +1.375515478e-03f, +1.120226944e-04f, -6.201709543e-04f, -1.596279961e-04f, +5.435082024e-04f,
-    /* 20, 2 */ +1.907003227e-05f, +5.734309365e-04f, +2.052951315e-04f, -1.162740775e-03f, -1.009657150e-03f, +1.406715362e-03f, +2.246673287e-03f, -7.408907618e-04f, -3.109053425e-03f, -6.638330580e-04f, +2.849051730e-03f, +1.860929207e-03f, -1.633773999e-03f, -2.063170847e-03f, +3.857714352e-04f, +1.406686835e-03f, +2.004651158e-04f, -6.190441221e-04f, -1.979927117e-04f, +1.783734753e-04f,
-    /* 20, 3 */ -1.149811868e-05f, +5.507184044e-04f, +2.729399910e-04f, -1.091184321e-03f, -1.104169932e-03f, +1.250098855e-03f, +2.317552276e-03f, -5.023622502e-04f, -3.094549152e-03f, -9.223980063e-04f, +2.732457430e-03f, +2.058021578e-03f, -1.464165902e-03f, -2.160404235e-03f, +2.358727957e-04f, +1.427769061e-03f, +2.913280278e-04f, -6.121962531e-04f, -2.370049292e-04f, +1.734448317e-04f,
-    /* 20, 4 */ -3.981122763e-05f, +5.243991976e-04f, +3.350936324e-04f, -1.013885501e-03f, -1.187349554e-03f, +1.088157908e-03f, +2.370318438e-03f, -2.632332411e-04f, -3.058053364e-03f, -1.174062761e-03f, +2.595770512e-03f, +2.242244162e-03f, -1.281088328e-03f, -2.243678681e-03f, +7.975052491e-05f, +1.438235101e-03f, +3.839113875e-04f, -5.994006494e-04f, -2.762968272e-04f, +1.660093790e-04f,
-    /* 20, 5 */ -6.571426612e-05f, +4.949070444e-04f, +3.914578654e-04f, -9.316921975e-04f, -1.258871974e-03f, +9.222740706e-04f, +2.404890527e-03f, -2.531308203e-05f, -2.999986642e-03f, -1.416952434e-03f, +2.439937364e-03f, +2.412078410e-03f, -1.085745014e-03f, -2.312047403e-03f, -8.150702581e-05f, +1.437633739e-03f, +4.774724341e-04f, -5.804781630e-04f, -3.154780847e-04f, +1.559797103e-04f,
-    /* 20, 6 */ -8.908584503e-05f, +4.626858369e-04f, +4.417988543e-04f, -8.454656803e-04f, -1.318519207e-03f, +7.538301290e-04f, +2.421333651e-03f, +2.096193816e-04f, -2.920935727e-03f, -1.649263420e-03f, +2.266058084e-03f, +2.566106310e-03f, -8.794550343e-04f, -2.364667062e-03f, -2.467407834e-04f, +1.425595879e-03f, +5.712311871e-04f, -5.553009320e-04f, -3.541389831e-04f, +1.432933926e-04f,
-    /* 20, 7 */ -1.098378936e-04f, +4.281848093e-04f, +4.859469205e-04f, -7.560724855e-04f, -1.366178446e-03f, +5.841984075e-04f, +2.419856400e-03f, +4.398300532e-04f, -2.821647705e-03f, -1.869277969e-03f, +2.075378006e-03f, +2.703022864e-03f, -6.636433018e-04f, -2.400806791e-03f, -4.147293943e-04f, +1.401840253e-03f, +6.643764801e-04f, -5.237957356e-04f, -3.918538488e-04f, +1.279149940e-04f,
-    /* 20, 8 */ -1.279149940e-04f, +3.918538488e-04f, +5.237957356e-04f, -6.643764801e-04f, -1.401840253e-03f, +4.147293943e-04f, +2.400806791e-03f, +6.636433018e-04f, -2.703022864e-03f, -2.075378006e-03f, +1.869277969e-03f, +2.821647705e-03f, -4.398300532e-04f, -2.419856400e-03f, -5.841984075e-04f, +1.366178446e-03f, +7.560724855e-04f, -4.859469205e-04f, -4.281848093e-04f, +1.098378936e-04f,
-    /* 20, 9 */ -1.432933926e-04f, +3.541389831e-04f, +5.553009320e-04f, -5.712311871e-04f, -1.425595879e-03f, +2.467407834e-04f, +2.364667062e-03f, +8.794550343e-04f, -2.566106310e-03f, -2.266058084e-03f, +1.649263420e-03f, +2.920935727e-03f, -2.096193816e-04f, -2.421333651e-03f, -7.538301290e-04f, +1.318519207e-03f, +8.454656803e-04f, -4.417988543e-04f, -4.626858369e-04f, +8.908584503e-05f,
-    /* 20,10 */ -1.559797103e-04f, +3.154780847e-04f, +5.804781630e-04f, -4.774724341e-04f, -1.437633739e-03f, +8.150702581e-05f, +2.312047403e-03f, +1.085745014e-03f, -2.412078410e-03f, -2.439937364e-03f, +1.416952434e-03f, +2.999986642e-03f, +2.531308203e-05f, -2.404890527e-03f, -9.222740706e-04f, +1.258871974e-03f, +9.316921975e-04f, -3.914578654e-04f, -4.949070444e-04f, +6.571426612e-05f,
-    /* 20,11 */ -1.660093790e-04f, +2.762968272e-04f, +5.994006494e-04f, -3.839113875e-04f, -1.438235101e-03f, -7.975052491e-05f, +2.243678681e-03f, +1.281088328e-03f, -2.242244162e-03f, -2.595770512e-03f, +1.174062761e-03f, +3.058053364e-03f, +2.632332411e-04f, -2.370318438e-03f, -1.088157908e-03f, +1.187349554e-03f, +1.013885501e-03f, -3.350936324e-04f, -5.243991976e-04f, +3.981122763e-05f,
-    /* 20,12 */ -1.734448317e-04f, +2.370049292e-04f, +6.121962531e-04f, -2.913280278e-04f, -1.427769061e-03f, -2.358727957e-04f, +2.160404235e-03f, +1.464165902e-03f, -2.058021578e-03f, -2.732457430e-03f, +9.223980063e-04f, +3.094549152e-03f, +5.023622502e-04f, -2.317552276e-03f, -1.250098855e-03f, +1.104169932e-03f, +1.091184321e-03f, -2.729399910e-04f, -5.507184044e-04f, +1.149811868e-05f,
-    /* 20,13 */ -1.783734753e-04f, +1.979927117e-04f, +6.190441221e-04f, -2.004651158e-04f, -1.406686835e-03f, -3.857714352e-04f, +2.063170847e-03f, +1.633773999e-03f, -1.860929207e-03f, -2.849051730e-03f, +6.638330580e-04f, +3.109053425e-03f, +7.408907618e-04f, -2.246673287e-03f, -1.406715362e-03f, +1.009657150e-03f, +1.162740775e-03f, -2.052951315e-04f, -5.734309365e-04f, -1.907003227e-05f,
-    /* 20,14 */ -5.435082024e-04f, +1.596279961e-04f, +6.201709543e-04f, -1.120226944e-04f, -1.375515478e-03f, -5.284364506e-04f, +1.953018956e-03f, +1.788832610e-03f, -1.652572896e-03f, -2.944767882e-03f, +4.002989059e-04f, +3.101316201e-03f, +9.769935819e-04f, -2.157910711e-03f, -1.556639033e-03f, +9.042412445e-04f, +1.227728603e-03f, -1.325211661e-04f, -5.921181369e-04f, -5.170459821e-05f,
-    /* 20,15 */ -1.824770389e-04f, +1.222533602e-04f, +6.158469302e-04f, -2.665316224e-05f, -1.334851066e-03f, -6.629429882e-04f, +1.831072241e-03f, +1.928392685e-03f, -1.434631920e-03f, -3.018986987e-03f, +1.337669627e-04f, +3.071261118e-03f, +1.208844608e-03f, -2.051642156e-03f, -1.698526656e-03f, +7.884572117e-04f, +1.285351444e-03f, -5.504304823e-05f, -6.063813654e-04f, -8.618377023e-05f,
-    /* 20, 0 */ -2.034293425e-04f, +2.330977005e-04f, +6.663349221e-04f, -5.788237715e-04f, -1.543506114e-03f, +7.663264997e-04f, +2.637884518e-03f, -5.016073607e-04f, -3.414789539e-03f, -1.613262342e-04f, +3.393842146e-03f, +7.896927597e-04f, -2.589726790e-03f, -9.705894653e-04f, +1.498255744e-03f, +6.923557695e-04f, -6.435044748e-04f, -2.810018705e-04f, +2.009801156e-04f, +0.000000000e+00f,
-    /* 20, 1 */ -6.015260759e-04f, +1.858917095e-04f, +6.809814437e-04f, -4.649883812e-04f, -1.572899641e-03f, +5.610647582e-04f, +2.661959816e-03f, -2.131645492e-04f, -3.406214168e-03f, -4.825221542e-04f, +3.343371924e-03f, +1.074767465e-03f, -2.517456780e-03f, -1.171859801e-03f, +1.437039798e-03f, +8.043742580e-04f, -6.123036842e-04f, -3.290468323e-04f, +1.953154138e-04f, -3.513221827e-04f,
-    /* 20, 2 */ -1.932641301e-04f, +1.399021716e-04f, +6.877130848e-04f, -3.520154127e-04f, -1.586701669e-03f, +3.567578182e-04f, +2.662213263e-03f, +7.301175991e-05f, -3.368394423e-03f, -7.993627115e-04f, +3.263658730e-03f, +1.354174959e-03f, -2.421279702e-03f, -1.368123194e-03f, +1.359912061e-03f, +9.136368247e-04f, -5.726346524e-04f, -3.766412744e-04f, +1.862701081e-04f, +2.243392330e-05f,
-    /* 20, 3 */ -1.771389305e-04f, +9.560377684e-05f, +6.868748812e-04f, -2.410152618e-04f, -1.585326694e-03f, +1.553000173e-04f, +2.639129491e-03f, +3.543525656e-04f, -3.301882608e-03f, -1.108991788e-03f, +3.155261081e-03f, +1.625281932e-03f, -2.301637793e-03f, -1.557365345e-03f, +1.267093119e-03f, +1.018881552e-03f, -5.244930508e-04f, -4.231658296e-04f, +1.737162070e-04f, +3.471505729e-05f,
-    /* 20, 4 */ -1.604844080e-04f, +5.342390613e-05f, +6.788805869e-04f, -1.330327870e-04f, -1.569329509e-03f, -4.149146373e-05f, +2.593408320e-03f, +6.283684809e-04f, -3.207497769e-03f, -1.408623929e-03f, +3.019012048e-03f, +1.885504757e-03f, -2.159209806e-03f, -1.737592880e-03f, +1.158972903e-03f, +1.118840456e-03f, -4.679722330e-04f, -4.679795743e-04f, +1.575667726e-04f, +4.805250238e-05f,
-    /* 20, 5 */ -1.435528424e-04f, +1.373966937e-05f, +6.642048742e-04f, -2.903827106e-05f, -1.539395067e-03f, -2.318933016e-04f, +2.525953799e-03f, +8.926733333e-04f, -3.086315860e-03f, -1.695571566e-03f, +2.856012327e-03f, +2.132335710e-03f, -1.994908019e-03f, -1.906854484e-03f, +1.036111434e-03f, +1.212253447e-03f, -4.032663270e-04f, -5.104270987e-04f, +1.377794601e-04f, +6.235351094e-05f,
-    /* 20, 6 */ -1.265803873e-04f, -2.312428639e-05f, +6.433751213e-04f, +7.008046528e-05f, -1.496327216e-03f, -4.142913555e-04f, +2.437861323e-03f, +1.145006429e-03f, -2.939657349e-03f, -1.967271220e-03f, +2.667620552e-03f, +2.363368676e-03f, -1.809872756e-03f, -2.063262017e-03f, +8.992377119e-04f, +1.297882648e-03f, -3.306722314e-04f, -5.498460811e-04f, +1.143596169e-04f, +7.750368078e-05f,
-    /* 20, 7 */ -1.097853637e-04f, -5.689720211e-05f, +6.169629011e-04f, +1.635247423e-04f, -1.441036462e-03f, -5.871944806e-04f, +2.330402993e-03f, +1.383253258e-03f, -2.769072436e-03f, -2.221308400e-03f, +2.455440941e-03f, +2.576324026e-03f, -1.605464444e-03f, -2.205011397e-03f, +7.492467105e-04f, +1.374526925e-03f, -2.505904541e-04f, -5.855752858e-04f, +8.736287854e-05f, +9.336686615e-05f,
-    /* 20, 8 */ -9.336686615e-05f, -8.736287854e-05f, +5.855752858e-04f, +2.505904541e-04f, -1.374526925e-03f, -7.492467105e-04f, +2.205011397e-03f, +1.605464444e-03f, -2.576324026e-03f, -2.455440941e-03f, +2.221308400e-03f, +2.769072436e-03f, -1.383253258e-03f, -2.330402993e-03f, +5.871944806e-04f, +1.441036462e-03f, -1.635247423e-04f, -6.169629011e-04f, +5.689720211e-05f, +1.097853637e-04f,
-    /* 20, 9 */ -7.750368078e-05f, -1.143596169e-04f, +5.498460811e-04f, +3.306722314e-04f, -1.297882648e-03f, -8.992377119e-04f, +2.063262017e-03f, +1.809872756e-03f, -2.363368676e-03f, -2.667620552e-03f, +1.967271220e-03f, +2.939657349e-03f, -1.145006429e-03f, -2.437861323e-03f, +4.142913555e-04f, +1.496327216e-03f, -7.008046528e-05f, -6.433751213e-04f, +2.312428639e-05f, +1.265803873e-04f,
-    /* 20,10 */ -6.235351094e-05f, -1.377794601e-04f, +5.104270987e-04f, +4.032663270e-04f, -1.212253447e-03f, -1.036111434e-03f, +1.906854484e-03f, +1.994908019e-03f, -2.132335710e-03f, -2.856012327e-03f, +1.695571566e-03f, +3.086315860e-03f, -8.926733333e-04f, -2.525953799e-03f, +2.318933016e-04f, +1.539395067e-03f, +2.903827106e-05f, -6.642048742e-04f, -1.373966937e-05f, +1.435528424e-04f,
-    /* 20,11 */ -4.805250238e-05f, -1.575667726e-04f, +4.679795743e-04f, +4.679722330e-04f, -1.118840456e-03f, -1.158972903e-03f, +1.737592880e-03f, +2.159209806e-03f, -1.885504757e-03f, -3.019012048e-03f, +1.408623929e-03f, +3.207497769e-03f, -6.283684809e-04f, -2.593408320e-03f, +4.149146373e-05f, +1.569329509e-03f, +1.330327870e-04f, -6.788805869e-04f, -5.342390613e-05f, +1.604844080e-04f,
-    /* 20,12 */ -3.471505729e-05f, -1.737162070e-04f, +4.231658296e-04f, +5.244930508e-04f, -1.018881552e-03f, -1.267093119e-03f, +1.557365345e-03f, +2.301637793e-03f, -1.625281932e-03f, -3.155261081e-03f, +1.108991788e-03f, +3.301882608e-03f, -3.543525656e-04f, -2.639129491e-03f, -1.553000173e-04f, +1.585326694e-03f, +2.410152618e-04f, -6.868748812e-04f, -9.560377684e-05f, +1.771389305e-04f,
-    /* 20,13 */ -2.243392330e-05f, -1.862701081e-04f, +3.766412744e-04f, +5.726346524e-04f, -9.136368247e-04f, -1.359912061e-03f, +1.368123194e-03f, +2.421279702e-03f, -1.354174959e-03f, -3.263658730e-03f, +7.993627115e-04f, +3.368394423e-03f, -7.301175991e-05f, -2.662213263e-03f, -3.567578182e-04f, +1.586701669e-03f, +3.520154127e-04f, -6.877130848e-04f, -1.399021716e-04f, +1.932641301e-04f,
-    /* 20,14 */ +3.513221827e-04f, -1.953154138e-04f, +3.290468323e-04f, +6.123036842e-04f, -8.043742580e-04f, -1.437039798e-03f, +1.171859801e-03f, +2.517456780e-03f, -1.074767465e-03f, -3.343371924e-03f, +4.825221542e-04f, +3.406214168e-03f, +2.131645492e-04f, -2.661959816e-03f, -5.610647582e-04f, +1.572899641e-03f, +4.649883812e-04f, -6.809814437e-04f, -1.858917095e-04f, +6.015260759e-04f,
-    /* 20,15 */ +0.000000000e+00f, -2.009801156e-04f, +2.810018705e-04f, +6.435044748e-04f, -6.923557695e-04f, -1.498255744e-03f, +9.705894653e-04f, +2.589726790e-03f, -7.896927597e-04f, -3.393842146e-03f, +1.613262342e-04f, +3.414789539e-03f, +5.016073607e-04f, -2.637884518e-03f, -7.663264997e-04f, +1.543506114e-03f, +5.788237715e-04f, -6.663349221e-04f, -2.330977005e-04f, +2.034293425e-04f,
-    /* 20, 0 */ -1.941987182e-05f, -3.146481294e-04f, +5.561305343e-04f, +3.334278991e-04f, -1.561489082e-03f, -4.085266513e-04f, +2.806699025e-03f, +3.580334706e-04f, -3.695826941e-03f, -1.914605051e-04f, +3.720952014e-03f, -2.295171057e-05f, -2.868623587e-03f, +1.886978960e-04f, +1.629573547e-03f, -2.343761763e-04f, -6.035407960e-04f, +1.633790229e-04f, +3.476344875e-05f, +0.000000000e+00f,
-    /* 20, 1 */ +3.929324583e-04f, -3.051602666e-04f, +5.048306585e-04f, +4.229644027e-04f, -1.479104632e-03f, -6.165003319e-04f, +2.717079427e-03f, +6.839596419e-04f, -3.633185574e-03f, -5.723309145e-04f, +3.708003841e-03f, +3.177599071e-04f, -2.901501717e-03f, -4.082823094e-05f, +1.681921685e-03f, -1.265851889e-04f, -6.461214422e-04f, +1.369921977e-04f, +5.166761157e-05f, +0.000000000e+00f,
-    /* 20, 2 */ +0.000000000e+00f, -2.925136688e-04f, +4.505823818e-04f, +5.023683161e-04f, -1.383975926e-03f, -8.106644739e-04f, +2.601403151e-03f, +9.973590062e-04f, -3.534000256e-03f, -9.470733637e-04f, +3.656850180e-03f, +6.604608766e-04f, -2.904291326e-03f, -2.777120434e-04f, +1.717239595e-03f, -1.098579054e-05f, -6.829477483e-04f, +1.058859702e-04f, +7.000071077e-05f, +0.000000000e+00f,
-    /* 20, 3 */ +0.000000000e+00f, -2.771727451e-04f, +3.943146848e-04f, +5.711822345e-04f, -1.277754215e-03f, -9.892860040e-04f, +2.461570058e-03f, +1.295052213e-03f, -3.399644449e-03f, -1.311681723e-03f, +3.567787737e-03f, +1.001437562e-03f, -2.876278542e-03f, -5.194560271e-04f, +1.734397724e-03f, +1.113422841e-04f, -7.131247677e-04f, +7.019384523e-05f, +8.959420873e-05f, +0.000000000e+00f,
-    /* 20, 4 */ +0.000000000e+00f, -2.596009711e-04f, +3.369316672e-04f, +6.291078651e-04f, -1.162161945e-03f, -1.150868125e-03f, +2.299713337e-03f, +1.574086312e-03f, -3.231873732e-03f, -1.662267592e-03f, +3.441541225e-03f, +1.336946247e-03f, -2.817092852e-03f, -7.634316403e-04f, +1.732451285e-03f, +2.391787684e-04f, -7.358020638e-04f, +3.013243736e-05f, +1.102423612e-04f, +0.000000000e+00f,
-    /* 20, 5 */ +0.000000000e+00f, -2.402546692e-04f, +2.793008459e-04f, +6.760030262e-04f, -1.038968304e-03f, -1.294161821e-03f, +2.118169008e-03f, +1.831766066e-03f, -3.032802328e-03f, -1.995105343e-03f, +3.279257242e-03f, +1.663257052e-03f, -2.726718246e-03f, -1.006908470e-03f, +1.710658870e-03f, +3.711735089e-04f, -7.501884622e-04f, -1.399708473e-05f, +1.317024534e-04f, +0.000000000e+00f,
-    /* 20, 6 */ +0.000000000e+00f, -2.195772899e-04f, +2.222425350e-04f, +7.118766228e-04f, -9.099649801e-04f, -1.418173917e-03f, +1.919443545e-03f, +2.065681697e-03f, -2.804875489e-03f, -2.306675131e-03f, +3.082493013e-03f, +1.976698190e-03f, -2.605500127e-03f, -1.247085413e-03f, +1.668498942e-03f, +5.058593370e-04f, -7.555665992e-04f, -6.180883712e-05f, +1.536956226e-04f, +0.000000000e+00f,
-    /* 20, 7 */ +0.000000000e+00f, -1.979942392e-04f, +1.665204182e-04f, +7.368817426e-04f, -7.769424426e-04f, -1.522171671e-03f, +1.706180058e-03f, +2.273732749e-03f, -2.550838108e-03f, -2.593703365e-03f, +2.853200114e-03f, +2.273699984e-03f, -2.454147846e-03f, -1.481123511e-03f, +1.605683934e-03f, +6.416670612e-04f, -7.513070408e-04f, -1.128334053e-04f, +1.759082929e-04f, +0.000000000e+00f,
-    /* 20, 8 */ +0.000000000e+00f, -1.759082929e-04f, +1.128334053e-04f, +7.513070408e-04f, -6.416670612e-04f, -1.605683934e-03f, +1.481123511e-03f, +2.454147846e-03f, -2.273699984e-03f, -2.853200114e-03f, +2.593703365e-03f, +2.550838108e-03f, -2.273732749e-03f, -1.706180058e-03f, +1.522171671e-03f, +7.769424426e-04f, -7.368817426e-04f, -1.665204182e-04f, +1.979942392e-04f, +0.000000000e+00f,
-    /* 20, 9 */ +0.000000000e+00f, -1.536956226e-04f, +6.180883712e-05f, +7.555665992e-04f, -5.058593370e-04f, -1.668498942e-03f, +1.247085413e-03f, +2.605500127e-03f, -1.976698190e-03f, -3.082493013e-03f, +2.306675131e-03f, +2.804875489e-03f, -2.065681697e-03f, -1.919443545e-03f, +1.418173917e-03f, +9.099649801e-04f, -7.118766228e-04f, -2.222425350e-04f, +2.195772899e-04f, +0.000000000e+00f,
-    /* 20,10 */ +0.000000000e+00f, -1.317024534e-04f, +1.399708473e-05f, +7.501884622e-04f, -3.711735089e-04f, -1.710658870e-03f, +1.006908470e-03f, +2.726718246e-03f, -1.663257052e-03f, -3.279257242e-03f, +1.995105343e-03f, +3.032802328e-03f, -1.831766066e-03f, -2.118169008e-03f, +1.294161821e-03f, +1.038968304e-03f, -6.760030262e-04f, -2.793008459e-04f, +2.402546692e-04f, +0.000000000e+00f,
-    /* 20,11 */ +0.000000000e+00f, -1.102423612e-04f, -3.013243736e-05f, +7.358020638e-04f, -2.391787684e-04f, -1.732451285e-03f, +7.634316403e-04f, +2.817092852e-03f, -1.336946247e-03f, -3.441541225e-03f, +1.662267592e-03f, +3.231873732e-03f, -1.574086312e-03f, -2.299713337e-03f, +1.150868125e-03f, +1.162161945e-03f, -6.291078651e-04f, -3.369316672e-04f, +2.596009711e-04f, +0.000000000e+00f,
-    /* 20,12 */ +0.000000000e+00f, -8.959420873e-05f, -7.019384523e-05f, +7.131247677e-04f, -1.113422841e-04f, -1.734397724e-03f, +5.194560271e-04f, +2.876278542e-03f, -1.001437562e-03f, -3.567787737e-03f, +1.311681723e-03f, +3.399644449e-03f, -1.295052213e-03f, -2.461570058e-03f, +9.892860040e-04f, +1.277754215e-03f, -5.711822345e-04f, -3.943146848e-04f, +2.771727451e-04f, +0.000000000e+00f,
-    /* 20,13 */ +0.000000000e+00f, -7.000071077e-05f, -1.058859702e-04f, +6.829477483e-04f, +1.098579054e-05f, -1.717239595e-03f, +2.777120434e-04f, +2.904291326e-03f, -6.604608766e-04f, -3.656850180e-03f, +9.470733637e-04f, +3.534000256e-03f, -9.973590062e-04f, -2.601403151e-03f, +8.106644739e-04f, +1.383975926e-03f, -5.023683161e-04f, -4.505823818e-04f, +2.925136688e-04f, +0.000000000e+00f,
-    /* 20,14 */ +0.000000000e+00f, -5.166761157e-05f, -1.369921977e-04f, +6.461214422e-04f, +1.265851889e-04f, -1.681921685e-03f, +4.082823094e-05f, +2.901501717e-03f, -3.177599071e-04f, -3.708003841e-03f, +5.723309145e-04f, +3.633185574e-03f, -6.839596419e-04f, -2.717079427e-03f, +6.165003319e-04f, +1.479104632e-03f, -4.229644027e-04f, -5.048306585e-04f, +3.051602666e-04f, -3.929324583e-04f,
-    /* 20,15 */ +0.000000000e+00f, -3.476344875e-05f, -1.633790229e-04f, +6.035407960e-04f, +2.343761763e-04f, -1.629573547e-03f, -1.886978960e-04f, +2.868623587e-03f, +2.295171057e-05f, -3.720952014e-03f, +1.914605051e-04f, +3.695826941e-03f, -3.580334706e-04f, -2.806699025e-03f, +4.085266513e-04f, +1.561489082e-03f, -3.334278991e-04f, -5.561305343e-04f, +3.146481294e-04f, +1.941987182e-05f,
-    /* 16, 0 */ +5.220390682e-05f, +8.171943113e-04f, -8.986497643e-04f, -1.446340428e-03f, +2.494478678e-03f, +1.297377101e-03f, -3.898391184e-03f, -2.241676001e-04f, +3.985236927e-03f, -9.413140896e-04f, -2.682700956e-03f, +1.283836927e-03f, +1.053222343e-03f, -7.989322796e-04f, -1.116939505e-04f, +1.571395541e-04f,
-    /* 16, 1 */ -3.017522584e-06f, +8.224554322e-04f, -7.403312787e-04f, -1.584058293e-03f, +2.281207335e-03f, +1.631019258e-03f, -3.765802305e-03f, -6.696927435e-04f, +4.024834602e-03f, -5.670028406e-04f, -2.842687093e-03f, +1.097826180e-03f, +1.201600277e-03f, -7.671194843e-04f, -1.747127487e-04f, +1.853334990e-04f,
-    /* 16, 2 */ -5.335264618e-05f, +8.154372286e-04f, -5.806604605e-04f, -1.696100138e-03f, +2.046328714e-03f, +1.938434809e-03f, -3.589560871e-03f, -1.106825943e-03f, +4.016290169e-03f, -1.789305351e-04f, -2.971556495e-03f, +8.899684644e-04f, +1.341315594e-03f, -7.213960065e-04f, -2.404043435e-04f, +2.137577131e-04f,
-    /* 16, 3 */ -9.830954357e-05f, +7.970128377e-04f, -4.219420013e-04f, -1.781963746e-03f, +1.793485018e-03f, +2.216231187e-03f, -3.372309802e-03f, -1.530099436e-03f, +3.959337237e-03f, +2.181586899e-04f, -3.066783450e-03f, +6.622938144e-04f, +1.469918710e-03f, -6.616076810e-04f, -3.078052257e-04f, +7.052925564e-04f,
-    /* 16, 4 */ -1.375232535e-04f, +7.681852053e-04f, -2.663606532e-04f, -1.841529450e-03f, +1.526462906e-03f, +2.461468734e-03f, -3.117203525e-03f, -1.934233820e-03f, +3.854345030e-03f, +6.193258599e-04f, -3.126241364e-03f, +4.171838871e-04f, +1.585017189e-03f, -5.878191605e-04f, -3.758553213e-04f, +2.457392598e-04f,
-    /* 16, 5 */ -1.707546409e-04f, +7.300642099e-04f, -1.159532388e-04f, -1.875048978e-03f, +1.249136740e-03f, +2.671693350e-03f, -2.827860277e-03f, -2.314209556e-03f, +3.702317390e-03f, +1.019502933e-03f, -3.148242059e-03f, +1.573479538e-04f, +1.684315055e-03f, -5.003238841e-04f, -4.434113338e-04f, +2.470336005e-04f,
-    /* 16, 6 */ -1.978870754e-04f, +6.838430878e-04f, +2.741593655e-05f, -1.883129095e-03f, +9.654119112e-04f, +2.844961691e-03f, -2.508308289e-03f, -2.665334690e-03f, +3.504882792e-03f, +1.413561295e-03f, -3.131569469e-03f, -1.142067707e-04f, +1.765652028e-03f, -3.996506493e-04f, -5.092623113e-04f, +2.432370997e-04f,
-    /* 16, 7 */ -2.189210857e-04f, +6.307745862e-04f, +1.620759979e-04f, -1.866710442e-03f, +6.791690772e-04f, +2.979858667e-03f, -2.162926680e-03f, -2.983307830e-03f, +3.264275462e-03f, +1.796381989e-03f, -3.075507089e-03f, -3.942101476e-04f, +1.827042047e-03f, -2.865665382e-04f, -5.721472605e-04f, +2.339671870e-04f,
-    /* 16, 8 */ -2.339671870e-04f, +5.721472605e-04f, +2.865665382e-04f, -1.827042047e-03f, +3.942101476e-04f, +3.075507089e-03f, -1.796381989e-03f, -3.264275462e-03f, +2.983307830e-03f, +2.162926680e-03f, -2.979858667e-03f, -6.791690772e-04f, +1.866710442e-03f, -1.620759979e-04f, -6.307745862e-04f, +2.189210857e-04f,
-    /* 16, 9 */ -2.432370997e-04f, +5.092623113e-04f, +3.996506493e-04f, -1.765652028e-03f, +1.142067707e-04f, +3.131569469e-03f, -1.413561295e-03f, -3.504882792e-03f, +2.665334690e-03f, +2.508308289e-03f, -2.844961691e-03f, -9.654119112e-04f, +1.883129095e-03f, -2.741593655e-05f, -6.838430878e-04f, +1.978870754e-04f,
-    /* 16,10 */ -2.470336005e-04f, +4.434113338e-04f, +5.003238841e-04f, -1.684315055e-03f, -1.573479538e-04f, +3.148242059e-03f, -1.019502933e-03f, -3.702317390e-03f, +2.314209556e-03f, +2.827860277e-03f, -2.671693350e-03f, -1.249136740e-03f, +1.875048978e-03f, +1.159532388e-04f, -7.300642099e-04f, +1.707546409e-04f,
-    /* 16,11 */ -2.457392598e-04f, +3.758553213e-04f, +5.878191605e-04f, -1.585017189e-03f, -4.171838871e-04f, +3.126241364e-03f, -6.193258599e-04f, -3.854345030e-03f, +1.934233820e-03f, +3.117203525e-03f, -2.461468734e-03f, -1.526462906e-03f, +1.841529450e-03f, +2.663606532e-04f, -7.681852053e-04f, +1.375232535e-04f,
-    /* 16,12 */ -7.052925564e-04f, +3.078052257e-04f, +6.616076810e-04f, -1.469918710e-03f, -6.622938144e-04f, +3.066783450e-03f, -2.181586899e-04f, -3.959337237e-03f, +1.530099436e-03f, +3.372309802e-03f, -2.216231187e-03f, -1.793485018e-03f, +1.781963746e-03f, +4.219420013e-04f, -7.970128377e-04f, +9.830954357e-05f,
-    /* 16,13 */ -2.137577131e-04f, +2.404043435e-04f, +7.213960065e-04f, -1.341315594e-03f, -8.899684644e-04f, +2.971556495e-03f, +1.789305351e-04f, -4.016290169e-03f, +1.106825943e-03f, +3.589560871e-03f, -1.938434809e-03f, -2.046328714e-03f, +1.696100138e-03f, +5.806604605e-04f, -8.154372286e-04f, +5.335264618e-05f,
-    /* 16,14 */ -1.853334990e-04f, +1.747127487e-04f, +7.671194843e-04f, -1.201600277e-03f, -1.097826180e-03f, +2.842687093e-03f, +5.670028406e-04f, -4.024834602e-03f, +6.696927435e-04f, +3.765802305e-03f, -1.631019258e-03f, -2.281207335e-03f, +1.584058293e-03f, +7.403312787e-04f, -8.224554322e-04f, +3.017522584e-06f,
-    /* 16,15 */ -1.571395541e-04f, +1.116939505e-04f, +7.989322796e-04f, -1.053222343e-03f, -1.283836927e-03f, +2.682700956e-03f, +9.413140896e-04f, -3.985236927e-03f, +2.241676001e-04f, +3.898391184e-03f, -1.297377101e-03f, -2.494478678e-03f, +1.446340428e-03f, +8.986497643e-04f, -8.171943113e-04f, -5.220390682e-05f,
-    /* 16, 0 */ -2.607744081e-04f, +6.609893225e-04f, +4.777614003e-05f, -2.019079564e-03f, +1.736921610e-03f, +2.230081148e-03f, -4.008512761e-03f, -2.594451583e-04f, +4.172957467e-03f, -1.888269495e-03f, -2.040920379e-03f, +1.975903291e-03f, +1.180452271e-04f, -7.248571600e-04f, +2.468008838e-04f, +0.000000000e+00f,
-    /* 16, 1 */ -2.676863913e-04f, +5.906930705e-04f, +2.025069901e-04f, -2.030408814e-03f, +1.418499470e-03f, +2.533235894e-03f, -3.790472440e-03f, -7.745724648e-04f, +4.280846994e-03f, -1.512096765e-03f, -2.325335551e-03f, +1.900137256e-03f, +2.927280105e-04f, -7.805529904e-04f, +2.254162899e-04f, +0.000000000e+00f,
-    /* 16, 2 */ -2.680102581e-04f, +5.157202047e-04f, +3.442245196e-04f, -2.011119828e-03f, +1.090886046e-03f, +2.794113365e-03f, -3.522578151e-03f, -1.278469954e-03f, +4.330057965e-03f, -1.106477171e-03f, -2.585166870e-03f, +1.791556445e-03f, +4.737630093e-04f, -8.263772041e-04f, +1.964117366e-04f, +0.000000000e+00f,
-    /* 16, 3 */ -7.633646088e-04f, +4.377966605e-04f, +4.713317060e-04f, -1.962888420e-03f, +7.592982470e-04f, +3.009813640e-03f, -3.209287239e-03f, -1.763847458e-03f, +4.319343992e-03f, -6.768749158e-04f, -2.815661672e-03f, +1.650477084e-03f, +6.583936022e-04f, -8.607109932e-04f, +1.597335965e-04f, -4.634120047e-04f,
-    /* 16, 4 */ -2.423668462e-04f, +3.585907293e-04f, +5.825699836e-04f, -1.887792011e-03f, +4.288533077e-04f, +3.178189562e-03f, -2.855695312e-03f, -2.223705909e-03f, +4.248362401e-03f, -2.292254995e-04f, -3.012400483e-03f, +1.477771292e-03f, +8.436545409e-04f, -8.820535056e-04f, +1.154955663e-04f, +2.338334874e-05f,
-    /* 16, 5 */ -2.066858426e-04f, +2.796840991e-04f, +6.770251471e-04f, -1.788258811e-03f, +1.044882353e-04f, +3.297866045e-03f, -2.467449129e-03f, -2.651446905e-03f, +4.117686315e-03f, +2.301520823e-04f, -3.171379014e-03f, +1.274872332e-03f, +1.026416356e-03f, -8.890585891e-04f, +6.398775754e-05f, +4.782938304e-05f,
-    /* 16, 6 */ -1.715009195e-04f, +2.025461567e-04f, +7.541266524e-04f, -1.667012713e-03f, -2.091154912e-04f, +3.368246274e-03f, -2.050651409e-03f, -3.040975547e-03f, +3.928801804e-03f, +6.946508648e-04f, -3.289085050e-03f, +1.043770075e-03f, +1.203434747e-03f, -8.805703554e-04f, +5.682450650e-06f, +7.520965874e-05f,
-    /* 16, 7 */ -1.374865801e-04f, +1.285119093e-04f, +8.136405975e-04f, -1.527015027e-03f, -5.076007987e-04f, +3.389504923e-03f, -1.611759203e-03f, -3.386794836e-03f, +3.684090065e-03f, +1.157477637e-03f, -3.362568736e-03f, +7.869964389e-04f, +1.371404208e-03f, -8.556567843e-04f, -5.876379361e-05f, +1.052264476e-04f,
-    /* 16, 8 */ -1.052264476e-04f, +5.876379361e-05f, +8.556567843e-04f, -1.371404208e-03f, -7.869964389e-04f, +3.362568736e-03f, -1.157477637e-03f, -3.684090065e-03f, +3.386794836e-03f, +1.611759203e-03f, -3.389504923e-03f, +5.076007987e-04f, +1.527015027e-03f, -8.136405975e-04f, -1.285119093e-04f, +1.374865801e-04f,
-    /* 16, 9 */ -7.520965874e-05f, -5.682450650e-06f, +8.805703554e-04f, -1.203434747e-03f, -1.043770075e-03f, +3.289085050e-03f, -6.946508648e-04f, -3.928801804e-03f, +3.040975547e-03f, +2.050651409e-03f, -3.368246274e-03f, +2.091154912e-04f, +1.667012713e-03f, -7.541266524e-04f, -2.025461567e-04f, +1.715009195e-04f,
-    /* 16,10 */ -4.782938304e-05f, -6.398775754e-05f, +8.890585891e-04f, -1.026416356e-03f, -1.274872332e-03f, +3.171379014e-03f, -2.301520823e-04f, -4.117686315e-03f, +2.651446905e-03f, +2.467449129e-03f, -3.297866045e-03f, -1.044882353e-04f, +1.788258811e-03f, -6.770251471e-04f, -2.796840991e-04f, +2.066858426e-04f,
-    /* 16,11 */ -2.338334874e-05f, -1.154955663e-04f, +8.820535056e-04f, -8.436545409e-04f, -1.477771292e-03f, +3.012400483e-03f, +2.292254995e-04f, -4.248362401e-03f, +2.223705909e-03f, +2.855695312e-03f, -3.178189562e-03f, -4.288533077e-04f, +1.887792011e-03f, -5.825699836e-04f, -3.585907293e-04f, +2.423668462e-04f,
-    /* 16,12 */ +4.634120047e-04f, -1.597335965e-04f, +8.607109932e-04f, -6.583936022e-04f, -1.650477084e-03f, +2.815661672e-03f, +6.768749158e-04f, -4.319343992e-03f, +1.763847458e-03f, +3.209287239e-03f, -3.009813640e-03f, -7.592982470e-04f, +1.962888420e-03f, -4.713317060e-04f, -4.377966605e-04f, +7.633646088e-04f,
-    /* 16,13 */ +0.000000000e+00f, -1.964117366e-04f, +8.263772041e-04f, -4.737630093e-04f, -1.791556445e-03f, +2.585166870e-03f, +1.106477171e-03f, -4.330057965e-03f, +1.278469954e-03f, +3.522578151e-03f, -2.794113365e-03f, -1.090886046e-03f, +2.011119828e-03f, -3.442245196e-04f, -5.157202047e-04f, +2.680102581e-04f,
-    /* 16,14 */ +0.000000000e+00f, -2.254162899e-04f, +7.805529904e-04f, -2.927280105e-04f, -1.900137256e-03f, +2.325335551e-03f, +1.512096765e-03f, -4.280846994e-03f, +7.745724648e-04f, +3.790472440e-03f, -2.533235894e-03f, -1.418499470e-03f, +2.030408814e-03f, -2.025069901e-04f, -5.906930705e-04f, +2.676863913e-04f,
-    /* 16,15 */ +0.000000000e+00f, -2.468008838e-04f, +7.248571600e-04f, -1.180452271e-04f, -1.975903291e-03f, +2.040920379e-03f, +1.888269495e-03f, -4.172957467e-03f, +2.594451583e-04f, +4.008512761e-03f, -2.230081148e-03f, -1.736921610e-03f, +2.019079564e-03f, -4.777614003e-05f, -6.609893225e-04f, +2.607744081e-04f,
-    /* 16, 0 */ -1.129954761e-04f, -3.969443331e-04f, +7.863457700e-04f, -1.968627401e-03f, +6.635626436e-04f, +3.065104554e-03f, -4.014723865e-03f, -2.972906332e-04f, +4.272130602e-03f, -2.778972616e-03f, -1.044103847e-03f, +2.069667087e-03f, -6.906315332e-04f, -2.376896670e-04f, +1.523656204e-04f, +0.000000000e+00f,
-    /* 16, 1 */ -7.672972562e-05f, -4.458313625e-04f, +8.604609066e-04f, -1.839340292e-03f, +2.869810557e-04f, +3.294943885e-03f, -3.696990655e-03f, -8.869321804e-04f, +4.464175630e-03f, -2.440111513e-03f, -1.421957113e-03f, +2.139058837e-03f, -5.737860098e-04f, -3.273087897e-04f, +1.941703587e-04f, +0.000000000e+00f,
-    /* 16, 2 */ -4.409159553e-05f, -4.801879450e-04f, +9.129725459e-04f, -1.685578963e-03f, -7.929130936e-05f, +3.465994861e-03f, -3.324955442e-03f, -1.461843594e-03f, +4.586914931e-03f, -2.053108579e-03f, -1.790295465e-03f, +2.173860444e-03f, -4.367566844e-04f, -4.185294039e-04f, +2.375950982e-04f, +0.000000000e+00f,
-    /* 16, 3 */ +4.855802427e-04f, -5.008892512e-04f, +9.443143993e-04f, -1.511399569e-03f, -4.293120730e-04f, +3.576852207e-03f, -2.905512498e-03f, -2.012499819e-03f, +4.637578076e-03f, -1.623510702e-03f, -2.142238116e-03f, +2.171667537e-03f, -2.809771210e-04f, -5.093533546e-04f, +2.816859426e-04f, +0.000000000e+00f,
-    /* 16, 4 */ +0.000000000e+00f, -5.090007623e-04f, +9.553248878e-04f, -1.321049384e-03f, -7.576441950e-04f, +3.627202827e-03f, -2.446291464e-03f, -2.529812382e-03f, +4.614629236e-03f, -1.157740361e-03f, -2.470980778e-03f, +2.130685105e-03f, -1.083629217e-04f, -5.976383603e-04f, +3.253590588e-04f, +0.000000000e+00f,
-    /* 16, 5 */ +0.000000000e+00f, -5.057402285e-04f, +9.472067544e-04f, -1.118874842e-03f, -1.059441268e-03f, +3.617806804e-03f, -1.955510679e-03f, -3.005292216e-03f, +4.517805471e-03f, -6.629933593e-04f, -2.769928158e-03f, +2.049789183e-03f, +7.870314989e-05f, -6.811391839e-04f, +3.674140144e-04f, +0.000000000e+00f,
-    /* 16, 6 */ +0.000000000e+00f, -4.924395299e-04f, +9.214808972e-04f, -9.092313688e-04f, -1.330518654e-03f, +3.550458465e-03f, -1.441821213e-03f, -3.431200966e-03f, +4.348131386e-03f, -1.471199733e-04f, -3.032825993e-03f, +1.928577081e-03f, +2.773970394e-04f, -7.575537377e-04f, +4.065510896e-04f, +0.000000000e+00f,
-    /* 16, 7 */ +0.000000000e+00f, -4.705072223e-04f, +8.799357120e-04f, -6.963968181e-04f, -1.567409460e-03f, +3.427928686e-03f, -9.141447359e-04f, -3.800687882e-03f, +4.107909720e-03f, +3.815084058e-04f, -3.253889950e-03f, +1.767404663e-03f, +4.844901765e-04f, -8.245732787e-04f, +4.413924818e-04f, +0.000000000e+00f,
-    /* 16, 8 */ +0.000000000e+00f, -4.413924818e-04f, +8.245732787e-04f, -4.844901765e-04f, -1.767404663e-03f, +3.253889950e-03f, -3.815084058e-04f, -4.107909720e-03f, +3.800687882e-03f, +9.141447359e-04f, -3.427928686e-03f, +1.567409460e-03f, +6.963968181e-04f, -8.799357120e-04f, +4.705072223e-04f, +0.000000000e+00f,
-    /* 16, 9 */ +0.000000000e+00f, -4.065510896e-04f, +7.575537377e-04f, -2.773970394e-04f, -1.928577081e-03f, +3.032825993e-03f, +1.471199733e-04f, -4.348131386e-03f, +3.431200966e-03f, +1.441821213e-03f, -3.550458465e-03f, +1.330518654e-03f, +9.092313688e-04f, -9.214808972e-04f, +4.924395299e-04f, +0.000000000e+00f,
-    /* 16,10 */ +0.000000000e+00f, -3.674140144e-04f, +6.811391839e-04f, -7.870314989e-05f, -2.049789183e-03f, +2.769928158e-03f, +6.629933593e-04f, -4.517805471e-03f, +3.005292216e-03f, +1.955510679e-03f, -3.617806804e-03f, +1.059441268e-03f, +1.118874842e-03f, -9.472067544e-04f, +5.057402285e-04f, +0.000000000e+00f,
-    /* 16,11 */ +0.000000000e+00f, -3.253590588e-04f, +5.976383603e-04f, +1.083629217e-04f, -2.130685105e-03f, +2.470980778e-03f, +1.157740361e-03f, -4.614629236e-03f, +2.529812382e-03f, +2.446291464e-03f, -3.627202827e-03f, +7.576441950e-04f, +1.321049384e-03f, -9.553248878e-04f, +5.090007623e-04f, +0.000000000e+00f,
-    /* 16,12 */ +0.000000000e+00f, -2.816859426e-04f, +5.093533546e-04f, +2.809771210e-04f, -2.171667537e-03f, +2.142238116e-03f, +1.623510702e-03f, -4.637578076e-03f, +2.012499819e-03f, +2.905512498e-03f, -3.576852207e-03f, +4.293120730e-04f, +1.511399569e-03f, -9.443143993e-04f, +5.008892512e-04f, -4.855802427e-04f,
-    /* 16,13 */ +0.000000000e+00f, -2.375950982e-04f, +4.185294039e-04f, +4.367566844e-04f, -2.173860444e-03f, +1.790295465e-03f, +2.053108579e-03f, -4.586914931e-03f, +1.461843594e-03f, +3.324955442e-03f, -3.465994861e-03f, +7.929130936e-05f, +1.685578963e-03f, -9.129725459e-04f, +4.801879450e-04f, +4.409159553e-05f,
-    /* 16,14 */ +0.000000000e+00f, -1.941703587e-04f, +3.273087897e-04f, +5.737860098e-04f, -2.139058837e-03f, +1.421957113e-03f, +2.440111513e-03f, -4.464175630e-03f, +8.869321804e-04f, +3.696990655e-03f, -3.294943885e-03f, -2.869810557e-04f, +1.839340292e-03f, -8.604609066e-04f, +4.458313625e-04f, +7.672972562e-05f,
-    /* 16,15 */ +0.000000000e+00f, -1.523656204e-04f, +2.376896670e-04f, +6.906315332e-04f, -2.069667087e-03f, +1.044103847e-03f, +2.778972616e-03f, -4.272130602e-03f, +2.972906332e-04f, +4.014723865e-03f, -3.065104554e-03f, -6.635626436e-04f, +1.968627401e-03f, -7.863457700e-04f, +3.969443331e-04f, +1.129954761e-04f,
-    /* 12, 0 */ +1.006092301e-03f, -1.356592138e-03f, -5.291224839e-04f, +3.716365432e-03f, -3.908475818e-03f, -3.377012930e-04f, +4.272902045e-03f, -3.529241849e-03f, +1.347121185e-04f, +1.576582805e-03f, -1.021094463e-03f, +2.080147558e-04f,
-    /* 12, 1 */ +9.703330579e-04f, -1.123568815e-03f, -8.960631472e-04f, +3.830455785e-03f, -3.478978472e-03f, -1.006731283e-03f, +4.564422369e-03f, -3.270752231e-03f, -2.802589631e-04f, +1.777910422e-03f, -1.013271813e-03f, +1.540375404e-04f,
-    /* 12, 2 */ +9.162319547e-04f, -8.831264337e-04f, -1.229457804e-03f, +3.871345986e-03f, -2.993425932e-03f, -1.656773890e-03f, +4.776559314e-03f, -2.944064628e-03f, -7.081711396e-04f, +1.955059288e-03f, -9.809799530e-04f, +8.895597490e-05f,
-    /* 12, 3 */ +8.464715149e-04f, -6.407365814e-04f, -1.524162434e-03f, +3.840336583e-03f, -2.461816027e-03f, -2.275602698e-03f, +4.904341682e-03f, -2.553815646e-03f, -1.140836495e-03f, +2.102763165e-03f, -9.230670815e-04f, +1.349777819e-05f,
-    /* 12, 4 */ +7.639192828e-04f, -4.016125871e-04f, -1.776040886e-03f, +3.740131991e-03f, -1.894910812e-03f, -2.851629129e-03f, +4.944422783e-03f, -2.106045312e-03f, -1.569658753e-03f, +2.216140176e-03f, -8.389345160e-04f, -7.124952580e-05f,
-    /* 12, 5 */ +6.715456333e-04f, -1.706046467e-04f, -1.982015497e-03f, +3.574748146e-03f, -1.304005398e-03f, -3.374137989e-03f, +4.895165032e-03f, -1.608099956e-03f, -1.985807614e-03f, +2.290824513e-03f, -7.285864297e-04f, -1.638417811e-04f,
-    /* 12, 6 */ +5.723437636e-04f, +4.789167018e-05f, -2.140092391e-03f, +3.349394124e-03f, -7.006885404e-04f, -3.833503957e-03f, +4.756688774e-03f, -1.068504673e-03f, -2.380403858e-03f, +2.323091638e-03f, -5.926669574e-04f, -2.624916697e-04f,
-    /* 12, 7 */ +4.692537952e-04f, +2.500119139e-04f, -2.249361715e-03f, +3.070330944e-03f, -9.660032268e-05f, -4.221384345e-03f, +4.530883988e-03f, -4.968076992e-04f, -2.744711242e-03f, +2.309973659e-03f, -4.324830696e-04f, -3.650927179e-04f,
-    /* 12, 8 */ +3.650927179e-04f, +4.324830696e-04f, -2.309973659e-03f, +2.744711242e-03f, +4.968076992e-04f, -4.530883988e-03f, +4.221384345e-03f, +9.660032268e-05f, -3.070330944e-03f, +2.249361715e-03f, -2.500119139e-04f, -4.692537952e-04f,
-    /* 12, 9 */ +2.624916697e-04f, +5.926669574e-04f, -2.323091638e-03f, +2.380403858e-03f, +1.068504673e-03f, -4.756688774e-03f, +3.833503957e-03f, +7.006885404e-04f, -3.349394124e-03f, +2.140092391e-03f, -4.789167018e-05f, -5.723437636e-04f,
-    /* 12,10 */ +1.638417811e-04f, +7.285864297e-04f, -2.290824513e-03f, +1.985807614e-03f, +1.608099956e-03f, -4.895165032e-03f, +3.374137989e-03f, +1.304005398e-03f, -3.574748146e-03f, +1.982015497e-03f, +1.706046467e-04f, -6.715456333e-04f,
-    /* 12,11 */ +7.124952580e-05f, +8.389345160e-04f, -2.216140176e-03f, +1.569658753e-03f, +2.106045312e-03f, -4.944422783e-03f, +2.851629129e-03f, +1.894910812e-03f, -3.740131991e-03f, +1.776040886e-03f, +4.016125871e-04f, -7.639192828e-04f,
-    /* 12,12 */ -1.349777819e-05f, +9.230670815e-04f, -2.102763165e-03f, +1.140836495e-03f, +2.553815646e-03f, -4.904341682e-03f, +2.275602698e-03f, +2.461816027e-03f, -3.840336583e-03f, +1.524162434e-03f, +6.407365814e-04f, -8.464715149e-04f,
-    /* 12,13 */ -8.895597490e-05f, +9.809799530e-04f, -1.955059288e-03f, +7.081711396e-04f, +2.944064628e-03f, -4.776559314e-03f, +1.656773890e-03f, +2.993425932e-03f, -3.871345986e-03f, +1.229457804e-03f, +8.831264337e-04f, -9.162319547e-04f,
-    /* 12,14 */ -1.540375404e-04f, +1.013271813e-03f, -1.777910422e-03f, +2.802589631e-04f, +3.270752231e-03f, -4.564422369e-03f, +1.006731283e-03f, +3.478978472e-03f, -3.830455785e-03f, +8.960631472e-04f, +1.123568815e-03f, -9.703330579e-04f,
-    /* 12,15 */ -2.080147558e-04f, +1.021094463e-03f, -1.576582805e-03f, -1.347121185e-04f, +3.529241849e-03f, -4.272902045e-03f, +3.377012930e-04f, +3.908475818e-03f, -3.716365432e-03f, +5.291224839e-04f, +1.356592138e-03f, -1.006092301e-03f,
-    /* 12, 0 */ +7.165252154e-04f, -4.291307465e-04f, -1.619691310e-03f, +4.112050532e-03f, -3.684471854e-03f, -3.806742210e-04f, +4.167864669e-03f, -4.064044128e-03f, +1.285631838e-03f, +6.994376016e-04f, -8.205283947e-04f, +3.212754781e-04f,
-    /* 12, 1 */ +6.042449626e-04f, -1.684748882e-04f, -1.902468489e-03f, +4.073990388e-03f, -3.134198780e-03f, -1.133926469e-03f, +4.572939653e-03f, -3.928365474e-03f, +9.055999228e-04f, +9.731965741e-04f, -9.124383184e-04f, +3.311614162e-04f,
-    /* 12, 2 */ +4.874350434e-04f, +7.694308689e-05f, -2.130082097e-03f, +3.953363211e-03f, -2.529802622e-03f, -1.863076830e-03f, +4.889863669e-03f, -3.705392569e-03f, +4.862599326e-04f, +1.243729140e-03f, -9.884795125e-04f, +3.301883495e-04f,
-    /* 12, 3 */ +3.696734183e-04f, +3.022578517e-04f, -2.300114973e-03f, +3.755428771e-03f, -1.885047396e-03f, -2.552675098e-03f, +5.110657479e-03f, -3.397530000e-03f, +3.551878686e-05f, +1.504029611e-03f, -1.045032679e-03f, +3.171093301e-04f,
-    /* 12, 4 */ +2.542791637e-04f, +5.034105172e-04f, -2.411611526e-03f, +3.487034212e-03f, -1.214371318e-03f, -3.188181667e-03f, +5.229403271e-03f, -3.009202669e-03f, -4.376222644e-04f, +1.746934410e-03f, -1.078752986e-03f, +2.909691299e-04f,
-    /* 12, 5 */ +1.442362351e-04f, +6.772076791e-04f, -2.465038541e-03f, +3.156407157e-03f, -5.325427440e-04f, -3.756300237e-03f, +5.242404627e-03f, -2.546799451e-03f, -9.232494237e-04f, +1.965304174e-03f, -1.086687765e-03f, +2.511615343e-04f,
-    /* 12, 6 */ +4.213190220e-05f, +8.213542577e-04f, -2.462211671e-03f, +2.772920825e-03f, +1.456866600e-04f, -4.245279979e-03f, +5.148294544e-03f, -2.018567160e-03f, -1.410748009e-03f, +2.152214196e-03f, -1.066390037e-03f, +1.974793328e-04f,
-    /* 12, 7 */ -4.988918599e-05f, +9.344605010e-04f, -2.406190818e-03f, +2.346837790e-03f, +8.059229054e-04f, -4.645179801e-03f, +4.948088353e-03f, -1.434456490e-03f, -1.889039390e-03f, +2.301148282e-03f, -1.016024228e-03f, +1.301548676e-04f,
-    /* 12, 8 */ -1.301548676e-04f, +1.016024228e-03f, -2.301148282e-03f, +1.889039390e-03f, +1.434456490e-03f, -4.948088353e-03f, +4.645179801e-03f, -8.059229054e-04f, -2.346837790e-03f, +2.406190818e-03f, -9.344605010e-04f, +4.988918599e-05f,
-    /* 12, 9 */ -1.974793328e-04f, +1.066390037e-03f, -2.152214196e-03f, +1.410748009e-03f, +2.018567160e-03f, -5.148294544e-03f, +4.245279979e-03f, -1.456866600e-04f, -2.772920825e-03f, +2.462211671e-03f, -8.213542577e-04f, -4.213190220e-05f,
-    /* 12,10 */ -2.511615343e-04f, +1.086687765e-03f, -1.965304174e-03f, +9.232494237e-04f, +2.546799451e-03f, -5.242404627e-03f, +3.756300237e-03f, +5.325427440e-04f, -3.156407157e-03f, +2.465038541e-03f, -6.772076791e-04f, -1.442362351e-04f,
-    /* 12,11 */ -2.909691299e-04f, +1.078752986e-03f, -1.746934410e-03f, +4.376222644e-04f, +3.009202669e-03f, -5.229403271e-03f, +3.188181667e-03f, +1.214371318e-03f, -3.487034212e-03f, +2.411611526e-03f, -5.034105172e-04f, -2.542791637e-04f,
-    /* 12,12 */ -3.171093301e-04f, +1.045032679e-03f, -1.504029611e-03f, -3.551878686e-05f, +3.397530000e-03f, -5.110657479e-03f, +2.552675098e-03f, +1.885047396e-03f, -3.755428771e-03f, +2.300114973e-03f, -3.022578517e-04f, -3.696734183e-04f,
-    /* 12,13 */ -3.301883495e-04f, +9.884795125e-04f, -1.243729140e-03f, -4.862599326e-04f, +3.705392569e-03f, -4.889863669e-03f, +1.863076830e-03f, +2.529802622e-03f, -3.953363211e-03f, +2.130082097e-03f, -7.694308689e-05f, -4.874350434e-04f,
-    /* 12,14 */ -3.311614162e-04f, +9.124383184e-04f, -9.731965741e-04f, -9.055999228e-04f, +3.928365474e-03f, -4.572939653e-03f, +1.133926469e-03f, +3.134198780e-03f, -4.073990388e-03f, +1.902468489e-03f, +1.684748882e-04f, -6.042449626e-04f,
-    /* 12,15 */ -3.212754781e-04f, +8.205283947e-04f, -6.994376016e-04f, -1.285631838e-03f, +4.064044128e-03f, -4.167864669e-03f, +3.806742210e-04f, +3.684471854e-03f, -4.112050532e-03f, +1.619691310e-03f, +4.291307465e-04f, -7.165252154e-04f
-};
-
-alignas(16) const ALfloat sinc4Tab[4096][4] =
-{
-    { +1.972846707e-17f, +1.000000000e+00f, +1.972846707e-17f, -7.947592825e-19f },
-    { -1.234844220e-04f, +9.999998638e-01f, +1.236324705e-04f, -2.493930525e-06f },
-    { -2.468208365e-04f, +9.999994551e-01f, +2.474130305e-04f, -4.998192808e-06f },
-    { -3.700092848e-04f, +9.999987739e-01f, +3.713417210e-04f, -7.512801591e-06f },
-    { -4.930498082e-04f, +9.999978203e-01f, +4.954185828e-04f, -1.003777162e-05f },
-    { -6.159424479e-04f, +9.999965942e-01f, +6.196436566e-04f, -1.257311763e-05f },
-    { -7.386872455e-04f, +9.999950956e-01f, +7.440169831e-04f, -1.511885438e-05f },
-    { -8.612842424e-04f, +9.999933246e-01f, +8.685386028e-04f, -1.767499661e-05f },
-    { -9.837334803e-04f, +9.999912812e-01f, +9.932085563e-04f, -2.024155907e-05f },
-    { -1.106035001e-03f, +9.999889652e-01f, +1.118026884e-03f, -2.281855651e-05f },
-    { -1.228188846e-03f, +9.999863768e-01f, +1.242993626e-03f, -2.540600368e-05f },
-    { -1.350195058e-03f, +9.999835160e-01f, +1.368108822e-03f, -2.800391533e-05f },
-    { -1.472053677e-03f, +9.999803827e-01f, +1.493372514e-03f, -3.061230620e-05f },
-    { -1.593764748e-03f, +9.999769770e-01f, +1.618784740e-03f, -3.323119106e-05f },
-    { -1.715328311e-03f, +9.999732988e-01f, +1.744345541e-03f, -3.586058466e-05f },
-    { -1.836744408e-03f, +9.999693481e-01f, +1.870054956e-03f, -3.850050175e-05f },
-    { -1.958013083e-03f, +9.999651250e-01f, +1.995913026e-03f, -4.115095708e-05f },
-    { -2.079134377e-03f, +9.999606295e-01f, +2.121919790e-03f, -4.381196542e-05f },
-    { -2.200108333e-03f, +9.999558615e-01f, +2.248075287e-03f, -4.648354151e-05f },
-    { -2.320934994e-03f, +9.999508211e-01f, +2.374379558e-03f, -4.916570012e-05f },
-    { -2.441614402e-03f, +9.999455083e-01f, +2.500832641e-03f, -5.185845600e-05f },
-    { -2.562146601e-03f, +9.999399230e-01f, +2.627434576e-03f, -5.456182391e-05f },
-    { -2.682531632e-03f, +9.999340653e-01f, +2.754185402e-03f, -5.727581862e-05f },
-    { -2.802769538e-03f, +9.999279352e-01f, +2.881085158e-03f, -6.000045487e-05f },
-    { -2.922860364e-03f, +9.999215326e-01f, +3.008133883e-03f, -6.273574744e-05f },
-    { -3.042804151e-03f, +9.999148577e-01f, +3.135331617e-03f, -6.548171107e-05f },
-    { -3.162600944e-03f, +9.999079103e-01f, +3.262678397e-03f, -6.823836055e-05f },
-    { -3.282250785e-03f, +9.999006906e-01f, +3.390174264e-03f, -7.100571061e-05f },
-    { -3.401753717e-03f, +9.998931984e-01f, +3.517819255e-03f, -7.378377604e-05f },
-    { -3.521109785e-03f, +9.998854338e-01f, +3.645613409e-03f, -7.657257158e-05f },
-    { -3.640319031e-03f, +9.998773969e-01f, +3.773556765e-03f, -7.937211202e-05f },
-    { -3.759381500e-03f, +9.998690875e-01f, +3.901649361e-03f, -8.218241209e-05f },
-    { -3.878297235e-03f, +9.998605058e-01f, +4.029891236e-03f, -8.500348659e-05f },
-    { -3.997066279e-03f, +9.998516517e-01f, +4.158282427e-03f, -8.783535025e-05f },
-    { -4.115688677e-03f, +9.998425252e-01f, +4.286822973e-03f, -9.067801786e-05f },
-    { -4.234164473e-03f, +9.998331264e-01f, +4.415512912e-03f, -9.353150418e-05f },
-    { -4.352493710e-03f, +9.998234552e-01f, +4.544352281e-03f, -9.639582397e-05f },
-    { -4.470676433e-03f, +9.998135116e-01f, +4.673341119e-03f, -9.927099199e-05f },
-    { -4.588712686e-03f, +9.998032957e-01f, +4.802479464e-03f, -1.021570230e-04f },
-    { -4.706602513e-03f, +9.997928075e-01f, +4.931767353e-03f, -1.050539318e-04f },
-    { -4.824345959e-03f, +9.997820469e-01f, +5.061204824e-03f, -1.079617332e-04f },
-    { -4.941943068e-03f, +9.997710141e-01f, +5.190791913e-03f, -1.108804418e-04f },
-    { -5.059393885e-03f, +9.997597089e-01f, +5.320528660e-03f, -1.138100725e-04f },
-    { -5.176698454e-03f, +9.997481313e-01f, +5.450415101e-03f, -1.167506400e-04f },
-    { -5.293856820e-03f, +9.997362815e-01f, +5.580451273e-03f, -1.197021592e-04f },
-    { -5.410869028e-03f, +9.997241594e-01f, +5.710637213e-03f, -1.226646447e-04f },
-    { -5.527735122e-03f, +9.997117650e-01f, +5.840972959e-03f, -1.256381113e-04f },
-    { -5.644455148e-03f, +9.996990983e-01f, +5.971458547e-03f, -1.286225739e-04f },
-    { -5.761029151e-03f, +9.996861593e-01f, +6.102094014e-03f, -1.316180471e-04f },
-    { -5.877457176e-03f, +9.996729481e-01f, +6.232879398e-03f, -1.346245458e-04f },
-    { -5.993739268e-03f, +9.996594646e-01f, +6.363814734e-03f, -1.376420846e-04f },
-    { -6.109875472e-03f, +9.996457089e-01f, +6.494900059e-03f, -1.406706784e-04f },
-    { -6.225865834e-03f, +9.996316809e-01f, +6.626135411e-03f, -1.437103420e-04f },
-    { -6.341710400e-03f, +9.996173807e-01f, +6.757520824e-03f, -1.467610900e-04f },
-    { -6.457409214e-03f, +9.996028083e-01f, +6.889056337e-03f, -1.498229373e-04f },
-    { -6.572962323e-03f, +9.995879637e-01f, +7.020741983e-03f, -1.528958987e-04f },
-    { -6.688369772e-03f, +9.995728468e-01f, +7.152577801e-03f, -1.559799888e-04f },
-    { -6.803631606e-03f, +9.995574578e-01f, +7.284563826e-03f, -1.590752225e-04f },
-    { -6.918747873e-03f, +9.995417966e-01f, +7.416700094e-03f, -1.621816145e-04f },
-    { -7.033718618e-03f, +9.995258632e-01f, +7.548986640e-03f, -1.652991797e-04f },
-    { -7.148543887e-03f, +9.995096577e-01f, +7.681423501e-03f, -1.684279326e-04f },
-    { -7.263223725e-03f, +9.994931800e-01f, +7.814010713e-03f, -1.715678882e-04f },
-    { -7.377758181e-03f, +9.994764302e-01f, +7.946748310e-03f, -1.747190612e-04f },
-    { -7.492147298e-03f, +9.994594082e-01f, +8.079636328e-03f, -1.778814663e-04f },
-    { -7.606391125e-03f, +9.994421141e-01f, +8.212674803e-03f, -1.810551183e-04f },
-    { -7.720489707e-03f, +9.994245479e-01f, +8.345863769e-03f, -1.842400320e-04f },
-    { -7.834443092e-03f, +9.994067096e-01f, +8.479203263e-03f, -1.874362221e-04f },
-    { -7.948251325e-03f, +9.993885992e-01f, +8.612693320e-03f, -1.906437034e-04f },
-    { -8.061914453e-03f, +9.993702168e-01f, +8.746333973e-03f, -1.938624906e-04f },
-    { -8.175432524e-03f, +9.993515622e-01f, +8.880125258e-03f, -1.970925985e-04f },
-    { -8.288805583e-03f, +9.993326357e-01f, +9.014067211e-03f, -2.003340419e-04f },
-    { -8.402033679e-03f, +9.993134371e-01f, +9.148159865e-03f, -2.035868356e-04f },
-    { -8.515116858e-03f, +9.992939664e-01f, +9.282403256e-03f, -2.068509942e-04f },
-    { -8.628055168e-03f, +9.992742238e-01f, +9.416797418e-03f, -2.101265325e-04f },
-    { -8.740848654e-03f, +9.992542091e-01f, +9.551342385e-03f, -2.134134654e-04f },
-    { -8.853497366e-03f, +9.992339225e-01f, +9.686038192e-03f, -2.167118075e-04f },
-    { -8.966001349e-03f, +9.992133639e-01f, +9.820884872e-03f, -2.200215735e-04f },
-    { -9.078360653e-03f, +9.991925333e-01f, +9.955882461e-03f, -2.233427784e-04f },
-    { -9.190575323e-03f, +9.991714307e-01f, +1.009103099e-02f, -2.266754367e-04f },
-    { -9.302645409e-03f, +9.991500563e-01f, +1.022633050e-02f, -2.300195634e-04f },
-    { -9.414570956e-03f, +9.991284099e-01f, +1.036178102e-02f, -2.333751730e-04f },
-    { -9.526352014e-03f, +9.991064916e-01f, +1.049738258e-02f, -2.367422804e-04f },
-    { -9.637988631e-03f, +9.990843014e-01f, +1.063313522e-02f, -2.401209002e-04f },
-    { -9.749480853e-03f, +9.990618393e-01f, +1.076903897e-02f, -2.435110474e-04f },
-    { -9.860828729e-03f, +9.990391053e-01f, +1.090509386e-02f, -2.469127365e-04f },
-    { -9.972032308e-03f, +9.990160995e-01f, +1.104129994e-02f, -2.503259824e-04f },
-    { -1.008309164e-02f, +9.989928219e-01f, +1.117765722e-02f, -2.537507998e-04f },
-    { -1.019400677e-02f, +9.989692724e-01f, +1.131416575e-02f, -2.571872034e-04f },
-    { -1.030477774e-02f, +9.989454512e-01f, +1.145082556e-02f, -2.606352080e-04f },
-    { -1.041540461e-02f, +9.989213581e-01f, +1.158763668e-02f, -2.640948284e-04f },
-    { -1.052588743e-02f, +9.988969933e-01f, +1.172459914e-02f, -2.675660791e-04f },
-    { -1.063622623e-02f, +9.988723567e-01f, +1.186171298e-02f, -2.710489751e-04f },
-    { -1.074642108e-02f, +9.988474483e-01f, +1.199897823e-02f, -2.745435310e-04f },
-    { -1.085647202e-02f, +9.988222682e-01f, +1.213639492e-02f, -2.780497616e-04f },
-    { -1.096637910e-02f, +9.987968164e-01f, +1.227396308e-02f, -2.815676816e-04f },
-    { -1.107614236e-02f, +9.987710929e-01f, +1.241168275e-02f, -2.850973058e-04f },
-    { -1.118576186e-02f, +9.987450978e-01f, +1.254955397e-02f, -2.886386488e-04f },
-    { -1.129523765e-02f, +9.987188309e-01f, +1.268757675e-02f, -2.921917254e-04f },
-    { -1.140456977e-02f, +9.986922924e-01f, +1.282575114e-02f, -2.957565503e-04f },
-    { -1.151375828e-02f, +9.986654823e-01f, +1.296407716e-02f, -2.993331383e-04f },
-    { -1.162280322e-02f, +9.986384006e-01f, +1.310255485e-02f, -3.029215041e-04f },
-    { -1.173170465e-02f, +9.986110473e-01f, +1.324118424e-02f, -3.065216624e-04f },
-    { -1.184046260e-02f, +9.985834223e-01f, +1.337996537e-02f, -3.101336280e-04f },
-    { -1.194907714e-02f, +9.985555259e-01f, +1.351889825e-02f, -3.137574155e-04f },
-    { -1.205754831e-02f, +9.985273578e-01f, +1.365798293e-02f, -3.173930397e-04f },
-    { -1.216587616e-02f, +9.984989183e-01f, +1.379721944e-02f, -3.210405152e-04f },
-    { -1.227406075e-02f, +9.984702072e-01f, +1.393660781e-02f, -3.246998569e-04f },
-    { -1.238210211e-02f, +9.984412247e-01f, +1.407614806e-02f, -3.283710794e-04f },
-    { -1.249000030e-02f, +9.984119707e-01f, +1.421584024e-02f, -3.320541975e-04f },
-    { -1.259775538e-02f, +9.983824452e-01f, +1.435568436e-02f, -3.357492258e-04f },
-    { -1.270536739e-02f, +9.983526483e-01f, +1.449568047e-02f, -3.394561791e-04f },
-    { -1.281283638e-02f, +9.983225800e-01f, +1.463582860e-02f, -3.431750720e-04f },
-    { -1.292016240e-02f, +9.982922403e-01f, +1.477612876e-02f, -3.469059193e-04f },
-    { -1.302734550e-02f, +9.982616292e-01f, +1.491658101e-02f, -3.506487357e-04f },
-    { -1.313438573e-02f, +9.982307467e-01f, +1.505718535e-02f, -3.544035359e-04f },
-    { -1.324128315e-02f, +9.981995929e-01f, +1.519794184e-02f, -3.581703346e-04f },
-    { -1.334803780e-02f, +9.981681678e-01f, +1.533885049e-02f, -3.619491465e-04f },
-    { -1.345464973e-02f, +9.981364714e-01f, +1.547991134e-02f, -3.657399862e-04f },
-    { -1.356111900e-02f, +9.981045038e-01f, +1.562112441e-02f, -3.695428686e-04f },
-    { -1.366744566e-02f, +9.980722648e-01f, +1.576248975e-02f, -3.733578082e-04f },
-    { -1.377362975e-02f, +9.980397546e-01f, +1.590400737e-02f, -3.771848197e-04f },
-    { -1.387967133e-02f, +9.980069732e-01f, +1.604567730e-02f, -3.810239179e-04f },
-    { -1.398557045e-02f, +9.979739207e-01f, +1.618749959e-02f, -3.848751175e-04f },
-    { -1.409132716e-02f, +9.979405969e-01f, +1.632947425e-02f, -3.887384331e-04f },
-    { -1.419694151e-02f, +9.979070020e-01f, +1.647160132e-02f, -3.926138794e-04f },
-    { -1.430241355e-02f, +9.978731359e-01f, +1.661388082e-02f, -3.965014710e-04f },
-    { -1.440774333e-02f, +9.978389988e-01f, +1.675631280e-02f, -4.004012227e-04f },
-    { -1.451293091e-02f, +9.978045905e-01f, +1.689889726e-02f, -4.043131492e-04f },
-    { -1.461797634e-02f, +9.977699112e-01f, +1.704163425e-02f, -4.082372651e-04f },
-    { -1.472287966e-02f, +9.977349608e-01f, +1.718452380e-02f, -4.121735850e-04f },
-    { -1.482764093e-02f, +9.976997395e-01f, +1.732756592e-02f, -4.161221238e-04f },
-    { -1.493226021e-02f, +9.976642471e-01f, +1.747076066e-02f, -4.200828959e-04f },
-    { -1.503673754e-02f, +9.976284837e-01f, +1.761410804e-02f, -4.240559161e-04f },
-    { -1.514107297e-02f, +9.975924494e-01f, +1.775760809e-02f, -4.280411991e-04f },
-    { -1.524526657e-02f, +9.975561442e-01f, +1.790126083e-02f, -4.320387594e-04f },
-    { -1.534931837e-02f, +9.975195680e-01f, +1.804506631e-02f, -4.360486119e-04f },
-    { -1.545322843e-02f, +9.974827210e-01f, +1.818902453e-02f, -4.400707710e-04f },
-    { -1.555699680e-02f, +9.974456031e-01f, +1.833313554e-02f, -4.441052515e-04f },
-    { -1.566062355e-02f, +9.974082143e-01f, +1.847739937e-02f, -4.481520680e-04f },
-    { -1.576410871e-02f, +9.973705548e-01f, +1.862181603e-02f, -4.522112352e-04f },
-    { -1.586745234e-02f, +9.973326244e-01f, +1.876638556e-02f, -4.562827677e-04f },
-    { -1.597065449e-02f, +9.972944233e-01f, +1.891110799e-02f, -4.603666801e-04f },
-    { -1.607371522e-02f, +9.972559515e-01f, +1.905598334e-02f, -4.644629872e-04f },
-    { -1.617663458e-02f, +9.972172089e-01f, +1.920101164e-02f, -4.685717034e-04f },
-    { -1.627941262e-02f, +9.971781956e-01f, +1.934619292e-02f, -4.726928435e-04f },
-    { -1.638204939e-02f, +9.971389117e-01f, +1.949152721e-02f, -4.768264221e-04f },
-    { -1.648454495e-02f, +9.970993571e-01f, +1.963701453e-02f, -4.809724538e-04f },
-    { -1.658689935e-02f, +9.970595319e-01f, +1.978265492e-02f, -4.851309533e-04f },
-    { -1.668911265e-02f, +9.970194362e-01f, +1.992844839e-02f, -4.893019351e-04f },
-    { -1.679118489e-02f, +9.969790698e-01f, +2.007439498e-02f, -4.934854139e-04f },
-    { -1.689311613e-02f, +9.969384329e-01f, +2.022049471e-02f, -4.976814042e-04f },
-    { -1.699490642e-02f, +9.968975255e-01f, +2.036674762e-02f, -5.018899208e-04f },
-    { -1.709655581e-02f, +9.968563476e-01f, +2.051315372e-02f, -5.061109782e-04f },
-    { -1.719806437e-02f, +9.968148993e-01f, +2.065971304e-02f, -5.103445911e-04f },
-    { -1.729943214e-02f, +9.967731805e-01f, +2.080642562e-02f, -5.145907739e-04f },
-    { -1.740065918e-02f, +9.967311913e-01f, +2.095329147e-02f, -5.188495414e-04f },
-    { -1.750174553e-02f, +9.966889317e-01f, +2.110031063e-02f, -5.231209082e-04f },
-    { -1.760269126e-02f, +9.966464017e-01f, +2.124748312e-02f, -5.274048887e-04f },
-    { -1.770349642e-02f, +9.966036014e-01f, +2.139480896e-02f, -5.317014977e-04f },
-    { -1.780416106e-02f, +9.965605309e-01f, +2.154228819e-02f, -5.360107497e-04f },
-    { -1.790468523e-02f, +9.965171900e-01f, +2.168992083e-02f, -5.403326592e-04f },
-    { -1.800506899e-02f, +9.964735789e-01f, +2.183770690e-02f, -5.446672410e-04f },
-    { -1.810531240e-02f, +9.964296976e-01f, +2.198564643e-02f, -5.490145094e-04f },
-    { -1.820541550e-02f, +9.963855461e-01f, +2.213373945e-02f, -5.533744792e-04f },
-    { -1.830537836e-02f, +9.963411244e-01f, +2.228198598e-02f, -5.577471650e-04f },
-    { -1.840520102e-02f, +9.962964326e-01f, +2.243038605e-02f, -5.621325811e-04f },
-    { -1.850488354e-02f, +9.962514707e-01f, +2.257893968e-02f, -5.665307423e-04f },
-    { -1.860442598e-02f, +9.962062387e-01f, +2.272764690e-02f, -5.709416631e-04f },
-    { -1.870382839e-02f, +9.961607366e-01f, +2.287650774e-02f, -5.753653581e-04f },
-    { -1.880309082e-02f, +9.961149645e-01f, +2.302552221e-02f, -5.798018418e-04f },
-    { -1.890221333e-02f, +9.960689225e-01f, +2.317469035e-02f, -5.842511287e-04f },
-    { -1.900119597e-02f, +9.960226105e-01f, +2.332401218e-02f, -5.887132334e-04f },
-    { -1.910003880e-02f, +9.959760285e-01f, +2.347348772e-02f, -5.931881705e-04f },
-    { -1.919874188e-02f, +9.959291766e-01f, +2.362311700e-02f, -5.976759545e-04f },
-    { -1.929730525e-02f, +9.958820549e-01f, +2.377290004e-02f, -6.021765999e-04f },
-    { -1.939572898e-02f, +9.958346633e-01f, +2.392283688e-02f, -6.066901213e-04f },
-    { -1.949401312e-02f, +9.957870019e-01f, +2.407292752e-02f, -6.112165332e-04f },
-    { -1.959215772e-02f, +9.957390708e-01f, +2.422317200e-02f, -6.157558500e-04f },
-    { -1.969016283e-02f, +9.956908698e-01f, +2.437357035e-02f, -6.203080865e-04f },
-    { -1.978802853e-02f, +9.956423992e-01f, +2.452412258e-02f, -6.248732570e-04f },
-    { -1.988575485e-02f, +9.955936589e-01f, +2.467482872e-02f, -6.294513760e-04f },
-    { -1.998334185e-02f, +9.955446489e-01f, +2.482568879e-02f, -6.340424582e-04f },
-    { -2.008078960e-02f, +9.954953692e-01f, +2.497670282e-02f, -6.386465180e-04f },
-    { -2.017809815e-02f, +9.954458200e-01f, +2.512787083e-02f, -6.432635698e-04f },
-    { -2.027526754e-02f, +9.953960012e-01f, +2.527919285e-02f, -6.478936283e-04f },
-    { -2.037229785e-02f, +9.953459129e-01f, +2.543066889e-02f, -6.525367078e-04f },
-    { -2.046918912e-02f, +9.952955551e-01f, +2.558229899e-02f, -6.571928229e-04f },
-    { -2.056594140e-02f, +9.952449278e-01f, +2.573408316e-02f, -6.618619881e-04f },
-    { -2.066255477e-02f, +9.951940310e-01f, +2.588602143e-02f, -6.665442179e-04f },
-    { -2.075902926e-02f, +9.951428649e-01f, +2.603811383e-02f, -6.712395266e-04f },
-    { -2.085536494e-02f, +9.950914294e-01f, +2.619036036e-02f, -6.759479289e-04f },
-    { -2.095156187e-02f, +9.950397245e-01f, +2.634276107e-02f, -6.806694392e-04f },
-    { -2.104762010e-02f, +9.949877504e-01f, +2.649531596e-02f, -6.854040719e-04f },
-    { -2.114353968e-02f, +9.949355069e-01f, +2.664802507e-02f, -6.901518415e-04f },
-    { -2.123932068e-02f, +9.948829943e-01f, +2.680088842e-02f, -6.949127625e-04f },
-    { -2.133496314e-02f, +9.948302124e-01f, +2.695390602e-02f, -6.996868493e-04f },
-    { -2.143046713e-02f, +9.947771613e-01f, +2.710707790e-02f, -7.044741164e-04f },
-    { -2.152583271e-02f, +9.947238411e-01f, +2.726040409e-02f, -7.092745782e-04f },
-    { -2.162105992e-02f, +9.946702518e-01f, +2.741388460e-02f, -7.140882492e-04f },
-    { -2.171614883e-02f, +9.946163934e-01f, +2.756751946e-02f, -7.189151437e-04f },
-    { -2.181109950e-02f, +9.945622660e-01f, +2.772130869e-02f, -7.237552763e-04f },
-    { -2.190591197e-02f, +9.945078696e-01f, +2.787525232e-02f, -7.286086614e-04f },
-    { -2.200058631e-02f, +9.944532042e-01f, +2.802935035e-02f, -7.334753133e-04f },
-    { -2.209512257e-02f, +9.943982699e-01f, +2.818360282e-02f, -7.383552465e-04f },
-    { -2.218952082e-02f, +9.943430666e-01f, +2.833800975e-02f, -7.432484754e-04f },
-    { -2.228378110e-02f, +9.942875945e-01f, +2.849257115e-02f, -7.481550144e-04f },
-    { -2.237790348e-02f, +9.942318536e-01f, +2.864728706e-02f, -7.530748780e-04f },
-    { -2.247188802e-02f, +9.941758439e-01f, +2.880215748e-02f, -7.580080805e-04f },
-    { -2.256573476e-02f, +9.941195654e-01f, +2.895718245e-02f, -7.629546363e-04f },
-    { -2.265944377e-02f, +9.940630182e-01f, +2.911236198e-02f, -7.679145598e-04f },
-    { -2.275301511e-02f, +9.940062023e-01f, +2.926769610e-02f, -7.728878654e-04f },
-    { -2.284644883e-02f, +9.939491178e-01f, +2.942318481e-02f, -7.778745675e-04f },
-    { -2.293974499e-02f, +9.938917647e-01f, +2.957882816e-02f, -7.828746805e-04f },
-    { -2.303290364e-02f, +9.938341429e-01f, +2.973462615e-02f, -7.878882187e-04f },
-    { -2.312592486e-02f, +9.937762527e-01f, +2.989057881e-02f, -7.929151965e-04f },
-    { -2.321880869e-02f, +9.937180939e-01f, +3.004668616e-02f, -7.979556282e-04f },
-    { -2.331155519e-02f, +9.936596666e-01f, +3.020294821e-02f, -8.030095283e-04f },
-    { -2.340416442e-02f, +9.936009710e-01f, +3.035936500e-02f, -8.080769110e-04f },
-    { -2.349663644e-02f, +9.935420069e-01f, +3.051593653e-02f, -8.131577908e-04f },
-    { -2.358897131e-02f, +9.934827745e-01f, +3.067266283e-02f, -8.182521819e-04f },
-    { -2.368116908e-02f, +9.934232738e-01f, +3.082954391e-02f, -8.233600987e-04f },
-    { -2.377322981e-02f, +9.933635047e-01f, +3.098657981e-02f, -8.284815556e-04f },
-    { -2.386515357e-02f, +9.933034675e-01f, +3.114377053e-02f, -8.336165668e-04f },
-    { -2.395694040e-02f, +9.932431620e-01f, +3.130111610e-02f, -8.387651466e-04f },
-    { -2.404859038e-02f, +9.931825884e-01f, +3.145861654e-02f, -8.439273095e-04f },
-    { -2.414010355e-02f, +9.931217466e-01f, +3.161627187e-02f, -8.491030697e-04f },
-    { -2.423147998e-02f, +9.930606368e-01f, +3.177408210e-02f, -8.542924415e-04f },
-    { -2.432271972e-02f, +9.929992589e-01f, +3.193204725e-02f, -8.594954392e-04f },
-    { -2.441382283e-02f, +9.929376130e-01f, +3.209016735e-02f, -8.647120771e-04f },
-    { -2.450478938e-02f, +9.928756991e-01f, +3.224844242e-02f, -8.699423695e-04f },
-    { -2.459561942e-02f, +9.928135173e-01f, +3.240687246e-02f, -8.751863308e-04f },
-    { -2.468631300e-02f, +9.927510676e-01f, +3.256545750e-02f, -8.804439750e-04f },
-    { -2.477687020e-02f, +9.926883501e-01f, +3.272419757e-02f, -8.857153167e-04f },
-    { -2.486729107e-02f, +9.926253647e-01f, +3.288309267e-02f, -8.910003699e-04f },
-    { -2.495757566e-02f, +9.925621116e-01f, +3.304214283e-02f, -8.962991490e-04f },
-    { -2.504772404e-02f, +9.924985907e-01f, +3.320134807e-02f, -9.016116683e-04f },
-    { -2.513773626e-02f, +9.924348021e-01f, +3.336070839e-02f, -9.069379419e-04f },
-    { -2.522761239e-02f, +9.923707459e-01f, +3.352022383e-02f, -9.122779842e-04f },
-    { -2.531735249e-02f, +9.923064221e-01f, +3.367989440e-02f, -9.176318093e-04f },
-    { -2.540695661e-02f, +9.922418307e-01f, +3.383972011e-02f, -9.229994316e-04f },
-    { -2.549642481e-02f, +9.921769718e-01f, +3.399970099e-02f, -9.283808652e-04f },
-    { -2.558575716e-02f, +9.921118453e-01f, +3.415983706e-02f, -9.337761243e-04f },
-    { -2.567495371e-02f, +9.920464515e-01f, +3.432012832e-02f, -9.391852233e-04f },
-    { -2.576401452e-02f, +9.919807902e-01f, +3.448057480e-02f, -9.446081762e-04f },
-    { -2.585293966e-02f, +9.919148616e-01f, +3.464117652e-02f, -9.500449974e-04f },
-    { -2.594172918e-02f, +9.918486656e-01f, +3.480193349e-02f, -9.554957009e-04f },
-    { -2.603038315e-02f, +9.917822024e-01f, +3.496284573e-02f, -9.609603011e-04f },
-    { -2.611890161e-02f, +9.917154719e-01f, +3.512391325e-02f, -9.664388120e-04f },
-    { -2.620728464e-02f, +9.916484743e-01f, +3.528513608e-02f, -9.719312480e-04f },
-    { -2.629553230e-02f, +9.915812094e-01f, +3.544651423e-02f, -9.774376231e-04f },
-    { -2.638364463e-02f, +9.915136775e-01f, +3.560804772e-02f, -9.829579515e-04f },
-    { -2.647162171e-02f, +9.914458785e-01f, +3.576973656e-02f, -9.884922474e-04f },
-    { -2.655946360e-02f, +9.913778125e-01f, +3.593158078e-02f, -9.940405249e-04f },
-    { -2.664717035e-02f, +9.913094795e-01f, +3.609358038e-02f, -9.996027983e-04f },
-    { -2.673474203e-02f, +9.912408796e-01f, +3.625573538e-02f, -1.005179082e-03f },
-    { -2.682217869e-02f, +9.911720128e-01f, +3.641804581e-02f, -1.010769389e-03f },
-    { -2.690948040e-02f, +9.911028791e-01f, +3.658051167e-02f, -1.016373735e-03f },
-    { -2.699664722e-02f, +9.910334786e-01f, +3.674313298e-02f, -1.021992133e-03f },
-    { -2.708367921e-02f, +9.909638114e-01f, +3.690590976e-02f, -1.027624597e-03f },
-    { -2.717057642e-02f, +9.908938774e-01f, +3.706884203e-02f, -1.033271142e-03f },
-    { -2.725733893e-02f, +9.908236768e-01f, +3.723192979e-02f, -1.038931782e-03f },
-    { -2.734396678e-02f, +9.907532095e-01f, +3.739517307e-02f, -1.044606531e-03f },
-    { -2.743046005e-02f, +9.906824756e-01f, +3.755857188e-02f, -1.050295402e-03f },
-    { -2.751681879e-02f, +9.906114753e-01f, +3.772212623e-02f, -1.055998411e-03f },
-    { -2.760304307e-02f, +9.905402084e-01f, +3.788583615e-02f, -1.061715570e-03f },
-    { -2.768913294e-02f, +9.904686751e-01f, +3.804970164e-02f, -1.067446895e-03f },
-    { -2.777508847e-02f, +9.903968753e-01f, +3.821372273e-02f, -1.073192399e-03f },
-    { -2.786090972e-02f, +9.903248092e-01f, +3.837789942e-02f, -1.078952096e-03f },
-    { -2.794659675e-02f, +9.902524768e-01f, +3.854223173e-02f, -1.084726001e-03f },
-    { -2.803214962e-02f, +9.901798782e-01f, +3.870671968e-02f, -1.090514127e-03f },
-    { -2.811756839e-02f, +9.901070133e-01f, +3.887136328e-02f, -1.096316489e-03f },
-    { -2.820285313e-02f, +9.900338822e-01f, +3.903616254e-02f, -1.102133100e-03f },
-    { -2.828800389e-02f, +9.899604850e-01f, +3.920111748e-02f, -1.107963974e-03f },
-    { -2.837302075e-02f, +9.898868218e-01f, +3.936622812e-02f, -1.113809126e-03f },
-    { -2.845790375e-02f, +9.898128925e-01f, +3.953149447e-02f, -1.119668570e-03f },
-    { -2.854265296e-02f, +9.897386972e-01f, +3.969691653e-02f, -1.125542319e-03f },
-    { -2.862726845e-02f, +9.896642360e-01f, +3.986249434e-02f, -1.131430388e-03f },
-    { -2.871175028e-02f, +9.895895088e-01f, +4.002822789e-02f, -1.137332791e-03f },
-    { -2.879609850e-02f, +9.895145159e-01f, +4.019411721e-02f, -1.143249541e-03f },
-    { -2.888031318e-02f, +9.894392571e-01f, +4.036016230e-02f, -1.149180652e-03f },
-    { -2.896439439e-02f, +9.893637326e-01f, +4.052636319e-02f, -1.155126140e-03f },
-    { -2.904834218e-02f, +9.892879424e-01f, +4.069271988e-02f, -1.161086016e-03f },
-    { -2.913215661e-02f, +9.892118865e-01f, +4.085923238e-02f, -1.167060297e-03f },
-    { -2.921583776e-02f, +9.891355651e-01f, +4.102590072e-02f, -1.173048994e-03f },
-    { -2.929938568e-02f, +9.890589780e-01f, +4.119272490e-02f, -1.179052123e-03f },
-    { -2.938280043e-02f, +9.889821255e-01f, +4.135970494e-02f, -1.185069698e-03f },
-    { -2.946608208e-02f, +9.889050075e-01f, +4.152684085e-02f, -1.191101731e-03f },
-    { -2.954923069e-02f, +9.888276241e-01f, +4.169413264e-02f, -1.197148238e-03f },
-    { -2.963224632e-02f, +9.887499753e-01f, +4.186158033e-02f, -1.203209232e-03f },
-    { -2.971512904e-02f, +9.886720613e-01f, +4.202918393e-02f, -1.209284727e-03f },
-    { -2.979787891e-02f, +9.885938819e-01f, +4.219694344e-02f, -1.215374737e-03f },
-    { -2.988049599e-02f, +9.885154374e-01f, +4.236485889e-02f, -1.221479275e-03f },
-    { -2.996298034e-02f, +9.884367276e-01f, +4.253293028e-02f, -1.227598357e-03f },
-    { -3.004533202e-02f, +9.883577528e-01f, +4.270115763e-02f, -1.233731995e-03f },
-    { -3.012755111e-02f, +9.882785129e-01f, +4.286954095e-02f, -1.239880203e-03f },
-    { -3.020963766e-02f, +9.881990080e-01f, +4.303808025e-02f, -1.246042996e-03f },
-    { -3.029159174e-02f, +9.881192381e-01f, +4.320677555e-02f, -1.252220388e-03f },
-    { -3.037341341e-02f, +9.880392034e-01f, +4.337562684e-02f, -1.258412391e-03f },
-    { -3.045510273e-02f, +9.879589037e-01f, +4.354463416e-02f, -1.264619020e-03f },
-    { -3.053665977e-02f, +9.878783393e-01f, +4.371379750e-02f, -1.270840289e-03f },
-    { -3.061808459e-02f, +9.877975101e-01f, +4.388311688e-02f, -1.277076211e-03f },
-    { -3.069937725e-02f, +9.877164161e-01f, +4.405259231e-02f, -1.283326801e-03f },
-    { -3.078053782e-02f, +9.876350576e-01f, +4.422222380e-02f, -1.289592072e-03f },
-    { -3.086156636e-02f, +9.875534344e-01f, +4.439201136e-02f, -1.295872038e-03f },
-    { -3.094246293e-02f, +9.874715467e-01f, +4.456195501e-02f, -1.302166714e-03f },
-    { -3.102322761e-02f, +9.873893944e-01f, +4.473205475e-02f, -1.308476111e-03f },
-    { -3.110386044e-02f, +9.873069778e-01f, +4.490231060e-02f, -1.314800245e-03f },
-    { -3.118436150e-02f, +9.872242967e-01f, +4.507272256e-02f, -1.321139130e-03f },
-    { -3.126473085e-02f, +9.871413513e-01f, +4.524329065e-02f, -1.327492778e-03f },
-    { -3.134496856e-02f, +9.870581415e-01f, +4.541401487e-02f, -1.333861204e-03f },
-    { -3.142507468e-02f, +9.869746676e-01f, +4.558489524e-02f, -1.340244422e-03f },
-    { -3.150504929e-02f, +9.868909295e-01f, +4.575593177e-02f, -1.346642444e-03f },
-    { -3.158489244e-02f, +9.868069272e-01f, +4.592712446e-02f, -1.353055286e-03f },
-    { -3.166460421e-02f, +9.867226608e-01f, +4.609847333e-02f, -1.359482960e-03f },
-    { -3.174418465e-02f, +9.866381305e-01f, +4.626997838e-02f, -1.365925481e-03f },
-    { -3.182363382e-02f, +9.865533361e-01f, +4.644163964e-02f, -1.372382862e-03f },
-    { -3.190295181e-02f, +9.864682779e-01f, +4.661345709e-02f, -1.378855117e-03f },
-    { -3.198213866e-02f, +9.863829557e-01f, +4.678543077e-02f, -1.385342260e-03f },
-    { -3.206119444e-02f, +9.862973698e-01f, +4.695756066e-02f, -1.391844303e-03f },
-    { -3.214011922e-02f, +9.862115201e-01f, +4.712984679e-02f, -1.398361262e-03f },
-    { -3.221891307e-02f, +9.861254067e-01f, +4.730228917e-02f, -1.404893149e-03f },
-    { -3.229757604e-02f, +9.860390297e-01f, +4.747488779e-02f, -1.411439979e-03f },
-    { -3.237610820e-02f, +9.859523890e-01f, +4.764764268e-02f, -1.418001764e-03f },
-    { -3.245450962e-02f, +9.858654848e-01f, +4.782055384e-02f, -1.424578519e-03f },
-    { -3.253278036e-02f, +9.857783172e-01f, +4.799362127e-02f, -1.431170257e-03f },
-    { -3.261092049e-02f, +9.856908861e-01f, +4.816684499e-02f, -1.437776992e-03f },
-    { -3.268893007e-02f, +9.856031917e-01f, +4.834022501e-02f, -1.444398738e-03f },
-    { -3.276680917e-02f, +9.855152339e-01f, +4.851376133e-02f, -1.451035507e-03f },
-    { -3.284455785e-02f, +9.854270129e-01f, +4.868745396e-02f, -1.457687314e-03f },
-    { -3.292217617e-02f, +9.853385286e-01f, +4.886130292e-02f, -1.464354173e-03f },
-    { -3.299966421e-02f, +9.852497812e-01f, +4.903530820e-02f, -1.471036096e-03f },
-    { -3.307702203e-02f, +9.851607708e-01f, +4.920946982e-02f, -1.477733098e-03f },
-    { -3.315424969e-02f, +9.850714973e-01f, +4.938378778e-02f, -1.484445192e-03f },
-    { -3.323134726e-02f, +9.849819608e-01f, +4.955826209e-02f, -1.491172391e-03f },
-    { -3.330831480e-02f, +9.848921614e-01f, +4.973289276e-02f, -1.497914710e-03f },
-    { -3.338515239e-02f, +9.848020991e-01f, +4.990767980e-02f, -1.504672161e-03f },
-    { -3.346186007e-02f, +9.847117740e-01f, +5.008262322e-02f, -1.511444759e-03f },
-    { -3.353843793e-02f, +9.846211862e-01f, +5.025772301e-02f, -1.518232516e-03f },
-    { -3.361488603e-02f, +9.845303356e-01f, +5.043297919e-02f, -1.525035446e-03f },
-    { -3.369120443e-02f, +9.844392225e-01f, +5.060839177e-02f, -1.531853564e-03f },
-    { -3.376739320e-02f, +9.843478467e-01f, +5.078396076e-02f, -1.538686881e-03f },
-    { -3.384345240e-02f, +9.842562085e-01f, +5.095968615e-02f, -1.545535412e-03f },
-    { -3.391938210e-02f, +9.841643077e-01f, +5.113556795e-02f, -1.552399171e-03f },
-    { -3.399518237e-02f, +9.840721446e-01f, +5.131160618e-02f, -1.559278170e-03f },
-    { -3.407085327e-02f, +9.839797191e-01f, +5.148780084e-02f, -1.566172424e-03f },
-    { -3.414639488e-02f, +9.838870314e-01f, +5.166415193e-02f, -1.573081945e-03f },
-    { -3.422180724e-02f, +9.837940814e-01f, +5.184065947e-02f, -1.580006747e-03f },
-    { -3.429709044e-02f, +9.837008692e-01f, +5.201732345e-02f, -1.586946844e-03f },
-    { -3.437224453e-02f, +9.836073950e-01f, +5.219414389e-02f, -1.593902249e-03f },
-    { -3.444726959e-02f, +9.835136587e-01f, +5.237112079e-02f, -1.600872975e-03f },
-    { -3.452216568e-02f, +9.834196603e-01f, +5.254825415e-02f, -1.607859036e-03f },
-    { -3.459693287e-02f, +9.833254001e-01f, +5.272554398e-02f, -1.614860445e-03f },
-    { -3.467157122e-02f, +9.832308780e-01f, +5.290299029e-02f, -1.621877216e-03f },
-    { -3.474608080e-02f, +9.831360941e-01f, +5.308059308e-02f, -1.628909362e-03f },
-    { -3.482046167e-02f, +9.830410484e-01f, +5.325835236e-02f, -1.635956896e-03f },
-    { -3.489471391e-02f, +9.829457410e-01f, +5.343626813e-02f, -1.643019832e-03f },
-    { -3.496883758e-02f, +9.828501720e-01f, +5.361434040e-02f, -1.650098183e-03f },
-    { -3.504283275e-02f, +9.827543414e-01f, +5.379256918e-02f, -1.657191962e-03f },
-    { -3.511669948e-02f, +9.826582494e-01f, +5.397095446e-02f, -1.664301183e-03f },
-    { -3.519043784e-02f, +9.825618958e-01f, +5.414949625e-02f, -1.671425859e-03f },
-    { -3.526404790e-02f, +9.824652809e-01f, +5.432819456e-02f, -1.678566004e-03f },
-    { -3.533752973e-02f, +9.823684047e-01f, +5.450704939e-02f, -1.685721630e-03f },
-    { -3.541088338e-02f, +9.822712671e-01f, +5.468606075e-02f, -1.692892751e-03f },
-    { -3.548410894e-02f, +9.821738684e-01f, +5.486522863e-02f, -1.700079381e-03f },
-    { -3.555720646e-02f, +9.820762086e-01f, +5.504455306e-02f, -1.707281532e-03f },
-    { -3.563017602e-02f, +9.819782876e-01f, +5.522403402e-02f, -1.714499218e-03f },
-    { -3.570301768e-02f, +9.818801056e-01f, +5.540367152e-02f, -1.721732452e-03f },
-    { -3.577573150e-02f, +9.817816627e-01f, +5.558346557e-02f, -1.728981247e-03f },
-    { -3.584831757e-02f, +9.816829589e-01f, +5.576341617e-02f, -1.736245617e-03f },
-    { -3.592077593e-02f, +9.815839943e-01f, +5.594352333e-02f, -1.743525575e-03f },
-    { -3.599310667e-02f, +9.814847688e-01f, +5.612378704e-02f, -1.750821133e-03f },
-    { -3.606530984e-02f, +9.813852827e-01f, +5.630420731e-02f, -1.758132306e-03f },
-    { -3.613738552e-02f, +9.812855360e-01f, +5.648478415e-02f, -1.765459107e-03f },
-    { -3.620933378e-02f, +9.811855286e-01f, +5.666551755e-02f, -1.772801548e-03f },
-    { -3.628115468e-02f, +9.810852607e-01f, +5.684640752e-02f, -1.780159642e-03f },
-    { -3.635284829e-02f, +9.809847324e-01f, +5.702745407e-02f, -1.787533404e-03f },
-    { -3.642441467e-02f, +9.808839437e-01f, +5.720865720e-02f, -1.794922846e-03f },
-    { -3.649585390e-02f, +9.807828947e-01f, +5.739001690e-02f, -1.802327981e-03f },
-    { -3.656716604e-02f, +9.806815854e-01f, +5.757153318e-02f, -1.809748823e-03f },
-    { -3.663835117e-02f, +9.805800159e-01f, +5.775320605e-02f, -1.817185384e-03f },
-    { -3.670940934e-02f, +9.804781863e-01f, +5.793503550e-02f, -1.824637677e-03f },
-    { -3.678034064e-02f, +9.803760966e-01f, +5.811702155e-02f, -1.832105717e-03f },
-    { -3.685114512e-02f, +9.802737469e-01f, +5.829916418e-02f, -1.839589515e-03f },
-    { -3.692182285e-02f, +9.801711372e-01f, +5.848146341e-02f, -1.847089085e-03f },
-    { -3.699237391e-02f, +9.800682677e-01f, +5.866391923e-02f, -1.854604440e-03f },
-    { -3.706279835e-02f, +9.799651384e-01f, +5.884653165e-02f, -1.862135594e-03f },
-    { -3.713309626e-02f, +9.798617493e-01f, +5.902930066e-02f, -1.869682558e-03f },
-    { -3.720326769e-02f, +9.797581006e-01f, +5.921222628e-02f, -1.877245347e-03f },
-    { -3.727331272e-02f, +9.796541922e-01f, +5.939530849e-02f, -1.884823973e-03f },
-    { -3.734323142e-02f, +9.795500243e-01f, +5.957854731e-02f, -1.892418449e-03f },
-    { -3.741302385e-02f, +9.794455969e-01f, +5.976194274e-02f, -1.900028788e-03f },
-    { -3.748269008e-02f, +9.793409101e-01f, +5.994549476e-02f, -1.907655004e-03f },
-    { -3.755223018e-02f, +9.792359640e-01f, +6.012920340e-02f, -1.915297108e-03f },
-    { -3.762164423e-02f, +9.791307585e-01f, +6.031306864e-02f, -1.922955116e-03f },
-    { -3.769093228e-02f, +9.790252939e-01f, +6.049709048e-02f, -1.930629038e-03f },
-    { -3.776009441e-02f, +9.789195701e-01f, +6.068126894e-02f, -1.938318888e-03f },
-    { -3.782913069e-02f, +9.788135872e-01f, +6.086560401e-02f, -1.946024680e-03f },
-    { -3.789804118e-02f, +9.787073453e-01f, +6.105009568e-02f, -1.953746425e-03f },
-    { -3.796682595e-02f, +9.786008444e-01f, +6.123474396e-02f, -1.961484138e-03f },
-    { -3.803548508e-02f, +9.784940847e-01f, +6.141954886e-02f, -1.969237830e-03f },
-    { -3.810401864e-02f, +9.783870661e-01f, +6.160451036e-02f, -1.977007515e-03f },
-    { -3.817242668e-02f, +9.782797888e-01f, +6.178962847e-02f, -1.984793206e-03f },
-    { -3.824070929e-02f, +9.781722528e-01f, +6.197490319e-02f, -1.992594915e-03f },
-    { -3.830886653e-02f, +9.780644583e-01f, +6.216033452e-02f, -2.000412656e-03f },
-    { -3.837689847e-02f, +9.779564051e-01f, +6.234592246e-02f, -2.008246441e-03f },
-    { -3.844480518e-02f, +9.778480935e-01f, +6.253166701e-02f, -2.016096283e-03f },
-    { -3.851258673e-02f, +9.777395235e-01f, +6.271756817e-02f, -2.023962196e-03f },
-    { -3.858024318e-02f, +9.776306952e-01f, +6.290362593e-02f, -2.031844191e-03f },
-    { -3.864777462e-02f, +9.775216086e-01f, +6.308984030e-02f, -2.039742281e-03f },
-    { -3.871518110e-02f, +9.774122638e-01f, +6.327621127e-02f, -2.047656480e-03f },
-    { -3.878246270e-02f, +9.773026608e-01f, +6.346273885e-02f, -2.055586801e-03f },
-    { -3.884961949e-02f, +9.771927998e-01f, +6.364942303e-02f, -2.063533255e-03f },
-    { -3.891665153e-02f, +9.770826809e-01f, +6.383626381e-02f, -2.071495856e-03f },
-    { -3.898355890e-02f, +9.769723040e-01f, +6.402326120e-02f, -2.079474617e-03f },
-    { -3.905034167e-02f, +9.768616692e-01f, +6.421041518e-02f, -2.087469549e-03f },
-    { -3.911699991e-02f, +9.767507766e-01f, +6.439772576e-02f, -2.095480667e-03f },
-    { -3.918353368e-02f, +9.766396264e-01f, +6.458519293e-02f, -2.103507983e-03f },
-    { -3.924994306e-02f, +9.765282185e-01f, +6.477281670e-02f, -2.111551509e-03f },
-    { -3.931622812e-02f, +9.764165530e-01f, +6.496059705e-02f, -2.119611258e-03f },
-    { -3.938238892e-02f, +9.763046301e-01f, +6.514853400e-02f, -2.127687243e-03f },
-    { -3.944842554e-02f, +9.761924497e-01f, +6.533662753e-02f, -2.135779477e-03f },
-    { -3.951433805e-02f, +9.760800119e-01f, +6.552487765e-02f, -2.143887971e-03f },
-    { -3.958012651e-02f, +9.759673169e-01f, +6.571328435e-02f, -2.152012740e-03f },
-    { -3.964579101e-02f, +9.758543646e-01f, +6.590184763e-02f, -2.160153795e-03f },
-    { -3.971133160e-02f, +9.757411552e-01f, +6.609056749e-02f, -2.168311149e-03f },
-    { -3.977674836e-02f, +9.756276888e-01f, +6.627944392e-02f, -2.176484815e-03f },
-    { -3.984204137e-02f, +9.755139653e-01f, +6.646847692e-02f, -2.184674805e-03f },
-    { -3.990721068e-02f, +9.753999849e-01f, +6.665766648e-02f, -2.192881133e-03f },
-    { -3.997225637e-02f, +9.752857476e-01f, +6.684701262e-02f, -2.201103809e-03f },
-    { -4.003717851e-02f, +9.751712536e-01f, +6.703651531e-02f, -2.209342848e-03f },
-    { -4.010197718e-02f, +9.750565028e-01f, +6.722617456e-02f, -2.217598262e-03f },
-    { -4.016665244e-02f, +9.749414954e-01f, +6.741599037e-02f, -2.225870062e-03f },
-    { -4.023120436e-02f, +9.748262314e-01f, +6.760596272e-02f, -2.234158263e-03f },
-    { -4.029563302e-02f, +9.747107110e-01f, +6.779609163e-02f, -2.242462875e-03f },
-    { -4.035993848e-02f, +9.745949341e-01f, +6.798637707e-02f, -2.250783913e-03f },
-    { -4.042412082e-02f, +9.744789009e-01f, +6.817681906e-02f, -2.259121387e-03f },
-    { -4.048818011e-02f, +9.743626113e-01f, +6.836741758e-02f, -2.267475312e-03f },
-    { -4.055211641e-02f, +9.742460656e-01f, +6.855817263e-02f, -2.275845698e-03f },
-    { -4.061592981e-02f, +9.741292638e-01f, +6.874908421e-02f, -2.284232560e-03f },
-    { -4.067962036e-02f, +9.740122059e-01f, +6.894015231e-02f, -2.292635908e-03f },
-    { -4.074318815e-02f, +9.738948920e-01f, +6.913137692e-02f, -2.301055756e-03f },
-    { -4.080663324e-02f, +9.737773222e-01f, +6.932275805e-02f, -2.309492116e-03f },
-    { -4.086995570e-02f, +9.736594966e-01f, +6.951429569e-02f, -2.317945001e-03f },
-    { -4.093315561e-02f, +9.735414153e-01f, +6.970598983e-02f, -2.326414422e-03f },
-    { -4.099623304e-02f, +9.734230782e-01f, +6.989784046e-02f, -2.334900392e-03f },
-    { -4.105918805e-02f, +9.733044855e-01f, +7.008984759e-02f, -2.343402924e-03f },
-    { -4.112202073e-02f, +9.731856373e-01f, +7.028201121e-02f, -2.351922030e-03f },
-    { -4.118473113e-02f, +9.730665337e-01f, +7.047433131e-02f, -2.360457723e-03f },
-    { -4.124731934e-02f, +9.729471746e-01f, +7.066680788e-02f, -2.369010014e-03f },
-    { -4.130978543e-02f, +9.728275603e-01f, +7.085944093e-02f, -2.377578915e-03f },
-    { -4.137212946e-02f, +9.727076907e-01f, +7.105223044e-02f, -2.386164441e-03f },
-    { -4.143435151e-02f, +9.725875660e-01f, +7.124517640e-02f, -2.394766601e-03f },
-    { -4.149645164e-02f, +9.724671862e-01f, +7.143827882e-02f, -2.403385410e-03f },
-    { -4.155842994e-02f, +9.723465513e-01f, +7.163153769e-02f, -2.412020878e-03f },
-    { -4.162028648e-02f, +9.722256616e-01f, +7.182495300e-02f, -2.420673020e-03f },
-    { -4.168202131e-02f, +9.721045170e-01f, +7.201852474e-02f, -2.429341845e-03f },
-    { -4.174363453e-02f, +9.719831176e-01f, +7.221225291e-02f, -2.438027368e-03f },
-    { -4.180512620e-02f, +9.718614635e-01f, +7.240613750e-02f, -2.446729599e-03f },
-    { -4.186649638e-02f, +9.717395548e-01f, +7.260017851e-02f, -2.455448552e-03f },
-    { -4.192774516e-02f, +9.716173916e-01f, +7.279437592e-02f, -2.464184239e-03f },
-    { -4.198887261e-02f, +9.714949738e-01f, +7.298872973e-02f, -2.472936671e-03f },
-    { -4.204987879e-02f, +9.713723017e-01f, +7.318323994e-02f, -2.481705861e-03f },
-    { -4.211076378e-02f, +9.712493753e-01f, +7.337790653e-02f, -2.490491821e-03f },
-    { -4.217152766e-02f, +9.711261947e-01f, +7.357272950e-02f, -2.499294563e-03f },
-    { -4.223217049e-02f, +9.710027598e-01f, +7.376770885e-02f, -2.508114099e-03f },
-    { -4.229269235e-02f, +9.708790709e-01f, +7.396284455e-02f, -2.516950442e-03f },
-    { -4.235309331e-02f, +9.707551280e-01f, +7.415813662e-02f, -2.525803603e-03f },
-    { -4.241337343e-02f, +9.706309312e-01f, +7.435358503e-02f, -2.534673595e-03f },
-    { -4.247353281e-02f, +9.705064805e-01f, +7.454918978e-02f, -2.543560430e-03f },
-    { -4.253357150e-02f, +9.703817761e-01f, +7.474495086e-02f, -2.552464119e-03f },
-    { -4.259348958e-02f, +9.702568180e-01f, +7.494086827e-02f, -2.561384675e-03f },
-    { -4.265328712e-02f, +9.701316062e-01f, +7.513694200e-02f, -2.570322110e-03f },
-    { -4.271296420e-02f, +9.700061410e-01f, +7.533317203e-02f, -2.579276435e-03f },
-    { -4.277252088e-02f, +9.698804222e-01f, +7.552955836e-02f, -2.588247664e-03f },
-    { -4.283195724e-02f, +9.697544501e-01f, +7.572610098e-02f, -2.597235807e-03f },
-    { -4.289127336e-02f, +9.696282248e-01f, +7.592279989e-02f, -2.606240877e-03f },
-    { -4.295046931e-02f, +9.695017462e-01f, +7.611965506e-02f, -2.615262886e-03f },
-    { -4.300954515e-02f, +9.693750144e-01f, +7.631666650e-02f, -2.624301846e-03f },
-    { -4.306850096e-02f, +9.692480296e-01f, +7.651383420e-02f, -2.633357769e-03f },
-    { -4.312733682e-02f, +9.691207919e-01f, +7.671115814e-02f, -2.642430666e-03f },
-    { -4.318605280e-02f, +9.689933012e-01f, +7.690863832e-02f, -2.651520549e-03f },
-    { -4.324464897e-02f, +9.688655578e-01f, +7.710627472e-02f, -2.660627431e-03f },
-    { -4.330312541e-02f, +9.687375615e-01f, +7.730406734e-02f, -2.669751324e-03f },
-    { -4.336148218e-02f, +9.686093127e-01f, +7.750201617e-02f, -2.678892238e-03f },
-    { -4.341971936e-02f, +9.684808113e-01f, +7.770012120e-02f, -2.688050187e-03f },
-    { -4.347783703e-02f, +9.683520574e-01f, +7.789838241e-02f, -2.697225181e-03f },
-    { -4.353583525e-02f, +9.682230510e-01f, +7.809679980e-02f, -2.706417234e-03f },
-    { -4.359371410e-02f, +9.680937924e-01f, +7.829537336e-02f, -2.715626355e-03f },
-    { -4.365147366e-02f, +9.679642815e-01f, +7.849410308e-02f, -2.724852558e-03f },
-    { -4.370911400e-02f, +9.678345184e-01f, +7.869298894e-02f, -2.734095855e-03f },
-    { -4.376663518e-02f, +9.677045033e-01f, +7.889203094e-02f, -2.743356256e-03f },
-    { -4.382403729e-02f, +9.675742361e-01f, +7.909122907e-02f, -2.752633774e-03f },
-    { -4.388132040e-02f, +9.674437171e-01f, +7.929058330e-02f, -2.761928420e-03f },
-    { -4.393848458e-02f, +9.673129462e-01f, +7.949009365e-02f, -2.771240206e-03f },
-    { -4.399552991e-02f, +9.671819235e-01f, +7.968976008e-02f, -2.780569145e-03f },
-    { -4.405245646e-02f, +9.670506492e-01f, +7.988958260e-02f, -2.789915247e-03f },
-    { -4.410926430e-02f, +9.669191233e-01f, +8.008956119e-02f, -2.799278524e-03f },
-    { -4.416595350e-02f, +9.667873459e-01f, +8.028969584e-02f, -2.808658988e-03f },
-    { -4.422252415e-02f, +9.666553170e-01f, +8.048998653e-02f, -2.818056650e-03f },
-    { -4.427897631e-02f, +9.665230369e-01f, +8.069043326e-02f, -2.827471523e-03f },
-    { -4.433531006e-02f, +9.663905054e-01f, +8.089103602e-02f, -2.836903618e-03f },
-    { -4.439152547e-02f, +9.662577228e-01f, +8.109179479e-02f, -2.846352946e-03f },
-    { -4.444762262e-02f, +9.661246891e-01f, +8.129270955e-02f, -2.855819519e-03f },
-    { -4.450360157e-02f, +9.659914044e-01f, +8.149378031e-02f, -2.865303349e-03f },
-    { -4.455946242e-02f, +9.658578688e-01f, +8.169500704e-02f, -2.874804447e-03f },
-    { -4.461520522e-02f, +9.657240824e-01f, +8.189638974e-02f, -2.884322825e-03f },
-    { -4.467083005e-02f, +9.655900451e-01f, +8.209792838e-02f, -2.893858495e-03f },
-    { -4.472633699e-02f, +9.654557573e-01f, +8.229962297e-02f, -2.903411467e-03f },
-    { -4.478172612e-02f, +9.653212188e-01f, +8.250147348e-02f, -2.912981754e-03f },
-    { -4.483699749e-02f, +9.651864298e-01f, +8.270347990e-02f, -2.922569366e-03f },
-    { -4.489215120e-02f, +9.650513905e-01f, +8.290564223e-02f, -2.932174316e-03f },
-    { -4.494718732e-02f, +9.649161008e-01f, +8.310796044e-02f, -2.941796615e-03f },
-    { -4.500210591e-02f, +9.647805608e-01f, +8.331043452e-02f, -2.951436274e-03f },
-    { -4.505690705e-02f, +9.646447707e-01f, +8.351306447e-02f, -2.961093304e-03f },
-    { -4.511159083e-02f, +9.645087305e-01f, +8.371585026e-02f, -2.970767718e-03f },
-    { -4.516615730e-02f, +9.643724404e-01f, +8.391879188e-02f, -2.980459527e-03f },
-    { -4.522060655e-02f, +9.642359003e-01f, +8.412188933e-02f, -2.990168741e-03f },
-    { -4.527493866e-02f, +9.640991104e-01f, +8.432514258e-02f, -2.999895373e-03f },
-    { -4.532915369e-02f, +9.639620708e-01f, +8.452855162e-02f, -3.009639433e-03f },
-    { -4.538325172e-02f, +9.638247816e-01f, +8.473211644e-02f, -3.019400934e-03f },
-    { -4.543723283e-02f, +9.636872427e-01f, +8.493583703e-02f, -3.029179886e-03f },
-    { -4.549109708e-02f, +9.635494545e-01f, +8.513971336e-02f, -3.038976300e-03f },
-    { -4.554484457e-02f, +9.634114168e-01f, +8.534374543e-02f, -3.048790189e-03f },
-    { -4.559847535e-02f, +9.632731298e-01f, +8.554793322e-02f, -3.058621563e-03f },
-    { -4.565198951e-02f, +9.631345937e-01f, +8.575227672e-02f, -3.068470433e-03f },
-    { -4.570538712e-02f, +9.629958084e-01f, +8.595677591e-02f, -3.078336812e-03f },
-    { -4.575866826e-02f, +9.628567741e-01f, +8.616143077e-02f, -3.088220709e-03f },
-    { -4.581183299e-02f, +9.627174908e-01f, +8.636624129e-02f, -3.098122137e-03f },
-    { -4.586488140e-02f, +9.625779587e-01f, +8.657120747e-02f, -3.108041106e-03f },
-    { -4.591781356e-02f, +9.624381778e-01f, +8.677632927e-02f, -3.117977628e-03f },
-    { -4.597062955e-02f, +9.622981482e-01f, +8.698160668e-02f, -3.127931713e-03f },
-    { -4.602332944e-02f, +9.621578700e-01f, +8.718703970e-02f, -3.137903374e-03f },
-    { -4.607591330e-02f, +9.620173433e-01f, +8.739262830e-02f, -3.147892621e-03f },
-    { -4.612838122e-02f, +9.618765682e-01f, +8.759837247e-02f, -3.157899465e-03f },
-    { -4.618073326e-02f, +9.617355447e-01f, +8.780427220e-02f, -3.167923918e-03f },
-    { -4.623296951e-02f, +9.615942731e-01f, +8.801032746e-02f, -3.177965990e-03f },
-    { -4.628509003e-02f, +9.614527532e-01f, +8.821653824e-02f, -3.188025693e-03f },
-    { -4.633709491e-02f, +9.613109853e-01f, +8.842290452e-02f, -3.198103037e-03f },
-    { -4.638898421e-02f, +9.611689695e-01f, +8.862942629e-02f, -3.208198035e-03f },
-    { -4.644075802e-02f, +9.610267057e-01f, +8.883610354e-02f, -3.218310696e-03f },
-    { -4.649241641e-02f, +9.608841941e-01f, +8.904293624e-02f, -3.228441031e-03f },
-    { -4.654395945e-02f, +9.607414349e-01f, +8.924992437e-02f, -3.238589053e-03f },
-    { -4.659538723e-02f, +9.605984280e-01f, +8.945706793e-02f, -3.248754771e-03f },
-    { -4.664669981e-02f, +9.604551736e-01f, +8.966436689e-02f, -3.258938197e-03f },
-    { -4.669789727e-02f, +9.603116718e-01f, +8.987182124e-02f, -3.269139342e-03f },
-    { -4.674897969e-02f, +9.601679226e-01f, +9.007943096e-02f, -3.279358217e-03f },
-    { -4.679994715e-02f, +9.600239261e-01f, +9.028719604e-02f, -3.289594832e-03f },
-    { -4.685079971e-02f, +9.598796825e-01f, +9.049511645e-02f, -3.299849199e-03f },
-    { -4.690153746e-02f, +9.597351919e-01f, +9.070319217e-02f, -3.310121328e-03f },
-    { -4.695216048e-02f, +9.595904542e-01f, +9.091142320e-02f, -3.320411230e-03f },
-    { -4.700266883e-02f, +9.594454696e-01f, +9.111980950e-02f, -3.330718916e-03f },
-    { -4.705306259e-02f, +9.593002383e-01f, +9.132835108e-02f, -3.341044398e-03f },
-    { -4.710334184e-02f, +9.591547602e-01f, +9.153704790e-02f, -3.351387685e-03f },
-    { -4.715350666e-02f, +9.590090355e-01f, +9.174589994e-02f, -3.361748789e-03f },
-    { -4.720355712e-02f, +9.588630643e-01f, +9.195490720e-02f, -3.372127720e-03f },
-    { -4.725349330e-02f, +9.587168467e-01f, +9.216406964e-02f, -3.382524489e-03f },
-    { -4.730331527e-02f, +9.585703827e-01f, +9.237338726e-02f, -3.392939107e-03f },
-    { -4.735302311e-02f, +9.584236724e-01f, +9.258286004e-02f, -3.403371585e-03f },
-    { -4.740261690e-02f, +9.582767160e-01f, +9.279248795e-02f, -3.413821934e-03f },
-    { -4.745209672e-02f, +9.581295136e-01f, +9.300227097e-02f, -3.424290163e-03f },
-    { -4.750146263e-02f, +9.579820651e-01f, +9.321220909e-02f, -3.434776284e-03f },
-    { -4.755071471e-02f, +9.578343708e-01f, +9.342230229e-02f, -3.445280308e-03f },
-    { -4.759985305e-02f, +9.576864307e-01f, +9.363255055e-02f, -3.455802245e-03f },
-    { -4.764887772e-02f, +9.575382449e-01f, +9.384295385e-02f, -3.466342106e-03f },
-    { -4.769778879e-02f, +9.573898135e-01f, +9.405351217e-02f, -3.476899901e-03f },
-    { -4.774658634e-02f, +9.572411365e-01f, +9.426422548e-02f, -3.487475641e-03f },
-    { -4.779527045e-02f, +9.570922142e-01f, +9.447509378e-02f, -3.498069337e-03f },
-    { -4.784384120e-02f, +9.569430465e-01f, +9.468611704e-02f, -3.508680999e-03f },
-    { -4.789229866e-02f, +9.567936336e-01f, +9.489729524e-02f, -3.519310638e-03f },
-    { -4.794064290e-02f, +9.566439756e-01f, +9.510862835e-02f, -3.529958264e-03f },
-    { -4.798887401e-02f, +9.564940726e-01f, +9.532011637e-02f, -3.540623888e-03f },
-    { -4.803699206e-02f, +9.563439245e-01f, +9.553175927e-02f, -3.551307520e-03f },
-    { -4.808499713e-02f, +9.561935317e-01f, +9.574355703e-02f, -3.562009171e-03f },
-    { -4.813288929e-02f, +9.560428941e-01f, +9.595550962e-02f, -3.572728851e-03f },
-    { -4.818066862e-02f, +9.558920118e-01f, +9.616761703e-02f, -3.583466571e-03f },
-    { -4.822833521e-02f, +9.557408849e-01f, +9.637987924e-02f, -3.594222342e-03f },
-    { -4.827588911e-02f, +9.555895136e-01f, +9.659229622e-02f, -3.604996173e-03f },
-    { -4.832333042e-02f, +9.554378979e-01f, +9.680486796e-02f, -3.615788075e-03f },
-    { -4.837065921e-02f, +9.552860379e-01f, +9.701759443e-02f, -3.626598058e-03f },
-    { -4.841787556e-02f, +9.551339337e-01f, +9.723047561e-02f, -3.637426133e-03f },
-    { -4.846497954e-02f, +9.549815854e-01f, +9.744351149e-02f, -3.648272311e-03f },
-    { -4.851197123e-02f, +9.548289931e-01f, +9.765670203e-02f, -3.659136601e-03f },
-    { -4.855885071e-02f, +9.546761570e-01f, +9.787004721e-02f, -3.670019013e-03f },
-    { -4.860561805e-02f, +9.545230770e-01f, +9.808354703e-02f, -3.680919559e-03f },
-    { -4.865227334e-02f, +9.543697533e-01f, +9.829720144e-02f, -3.691838248e-03f },
-    { -4.869881664e-02f, +9.542161860e-01f, +9.851101044e-02f, -3.702775091e-03f },
-    { -4.874524804e-02f, +9.540623752e-01f, +9.872497399e-02f, -3.713730097e-03f },
-    { -4.879156762e-02f, +9.539083209e-01f, +9.893909208e-02f, -3.724703278e-03f },
-    { -4.883777544e-02f, +9.537540234e-01f, +9.915336469e-02f, -3.735694643e-03f },
-    { -4.888387160e-02f, +9.535994826e-01f, +9.936779178e-02f, -3.746704203e-03f },
-    { -4.892985616e-02f, +9.534446987e-01f, +9.958237334e-02f, -3.757731967e-03f },
-    { -4.897572920e-02f, +9.532896717e-01f, +9.979710935e-02f, -3.768777946e-03f },
-    { -4.902149080e-02f, +9.531344018e-01f, +1.000119998e-01f, -3.779842151e-03f },
-    { -4.906714105e-02f, +9.529788891e-01f, +1.002270446e-01f, -3.790924590e-03f },
-    { -4.911268001e-02f, +9.528231336e-01f, +1.004422438e-01f, -3.802025274e-03f },
-    { -4.915810776e-02f, +9.526671355e-01f, +1.006575974e-01f, -3.813144214e-03f },
-    { -4.920342438e-02f, +9.525108949e-01f, +1.008731053e-01f, -3.824281419e-03f },
-    { -4.924862995e-02f, +9.523544118e-01f, +1.010887674e-01f, -3.835436900e-03f },
-    { -4.929372455e-02f, +9.521976863e-01f, +1.013045839e-01f, -3.846610666e-03f },
-    { -4.933870825e-02f, +9.520407186e-01f, +1.015205546e-01f, -3.857802728e-03f },
-    { -4.938358114e-02f, +9.518835087e-01f, +1.017366796e-01f, -3.869013095e-03f },
-    { -4.942834328e-02f, +9.517260568e-01f, +1.019529588e-01f, -3.880241778e-03f },
-    { -4.947299476e-02f, +9.515683630e-01f, +1.021693921e-01f, -3.891488786e-03f },
-    { -4.951753566e-02f, +9.514104273e-01f, +1.023859797e-01f, -3.902754129e-03f },
-    { -4.956196605e-02f, +9.512522498e-01f, +1.026027213e-01f, -3.914037818e-03f },
-    { -4.960628601e-02f, +9.510938306e-01f, +1.028196171e-01f, -3.925339862e-03f },
-    { -4.965049562e-02f, +9.509351700e-01f, +1.030366669e-01f, -3.936660271e-03f },
-    { -4.969459496e-02f, +9.507762678e-01f, +1.032538708e-01f, -3.947999054e-03f },
-    { -4.973858410e-02f, +9.506171243e-01f, +1.034712288e-01f, -3.959356223e-03f },
-    { -4.978246313e-02f, +9.504577395e-01f, +1.036887408e-01f, -3.970731786e-03f },
-    { -4.982623211e-02f, +9.502981136e-01f, +1.039064067e-01f, -3.982125754e-03f },
-    { -4.986989114e-02f, +9.501382466e-01f, +1.041242266e-01f, -3.993538136e-03f },
-    { -4.991344028e-02f, +9.499781386e-01f, +1.043422005e-01f, -4.004968942e-03f },
-    { -4.995687962e-02f, +9.498177898e-01f, +1.045603282e-01f, -4.016418182e-03f },
-    { -5.000020923e-02f, +9.496572003e-01f, +1.047786099e-01f, -4.027885865e-03f },
-    { -5.004342920e-02f, +9.494963700e-01f, +1.049970454e-01f, -4.039372002e-03f },
-    { -5.008653959e-02f, +9.493352993e-01f, +1.052156347e-01f, -4.050876601e-03f },
-    { -5.012954049e-02f, +9.491739880e-01f, +1.054343779e-01f, -4.062399673e-03f },
-    { -5.017243198e-02f, +9.490124364e-01f, +1.056532748e-01f, -4.073941228e-03f },
-    { -5.021521414e-02f, +9.488506446e-01f, +1.058723254e-01f, -4.085501274e-03f },
-    { -5.025788704e-02f, +9.486886126e-01f, +1.060915299e-01f, -4.097079822e-03f },
-    { -5.030045076e-02f, +9.485263405e-01f, +1.063108880e-01f, -4.108676881e-03f },
-    { -5.034290538e-02f, +9.483638285e-01f, +1.065303997e-01f, -4.120292461e-03f },
-    { -5.038525098e-02f, +9.482010767e-01f, +1.067500652e-01f, -4.131926571e-03f },
-    { -5.042748764e-02f, +9.480380851e-01f, +1.069698842e-01f, -4.143579220e-03f },
-    { -5.046961543e-02f, +9.478748538e-01f, +1.071898568e-01f, -4.155250420e-03f },
-    { -5.051163444e-02f, +9.477113830e-01f, +1.074099830e-01f, -4.166940178e-03f },
-    { -5.055354474e-02f, +9.475476728e-01f, +1.076302628e-01f, -4.178648505e-03f },
-    { -5.059534642e-02f, +9.473837233e-01f, +1.078506960e-01f, -4.190375409e-03f },
-    { -5.063703954e-02f, +9.472195345e-01f, +1.080712828e-01f, -4.202120901e-03f },
-    { -5.067862420e-02f, +9.470551065e-01f, +1.082920229e-01f, -4.213884989e-03f },
-    { -5.072010046e-02f, +9.468904396e-01f, +1.085129166e-01f, -4.225667684e-03f },
-    { -5.076146841e-02f, +9.467255337e-01f, +1.087339636e-01f, -4.237468994e-03f },
-    { -5.080272812e-02f, +9.465603890e-01f, +1.089551640e-01f, -4.249288929e-03f },
-    { -5.084387968e-02f, +9.463950056e-01f, +1.091765177e-01f, -4.261127499e-03f },
-    { -5.088492316e-02f, +9.462293836e-01f, +1.093980247e-01f, -4.272984712e-03f },
-    { -5.092585865e-02f, +9.460635230e-01f, +1.096196851e-01f, -4.284860578e-03f },
-    { -5.096668621e-02f, +9.458974241e-01f, +1.098414987e-01f, -4.296755107e-03f },
-    { -5.100740594e-02f, +9.457310868e-01f, +1.100634655e-01f, -4.308668306e-03f },
-    { -5.104801790e-02f, +9.455645113e-01f, +1.102855855e-01f, -4.320600187e-03f },
-    { -5.108852219e-02f, +9.453976978e-01f, +1.105078587e-01f, -4.332550758e-03f },
-    { -5.112891887e-02f, +9.452306462e-01f, +1.107302850e-01f, -4.344520028e-03f },
-    { -5.116920802e-02f, +9.450633568e-01f, +1.109528645e-01f, -4.356508006e-03f },
-    { -5.120938973e-02f, +9.448958296e-01f, +1.111755970e-01f, -4.368514702e-03f },
-    { -5.124946408e-02f, +9.447280647e-01f, +1.113984826e-01f, -4.380540125e-03f },
-    { -5.128943114e-02f, +9.445600623e-01f, +1.116215212e-01f, -4.392584284e-03f },
-    { -5.132929099e-02f, +9.443918223e-01f, +1.118447128e-01f, -4.404647188e-03f },
-    { -5.136904371e-02f, +9.442233450e-01f, +1.120680573e-01f, -4.416728846e-03f },
-    { -5.140868939e-02f, +9.440546305e-01f, +1.122915548e-01f, -4.428829267e-03f },
-    { -5.144822810e-02f, +9.438856788e-01f, +1.125152052e-01f, -4.440948461e-03f },
-    { -5.148765991e-02f, +9.437164901e-01f, +1.127390085e-01f, -4.453086436e-03f },
-    { -5.152698491e-02f, +9.435470644e-01f, +1.129629646e-01f, -4.465243201e-03f },
-    { -5.156620319e-02f, +9.433774019e-01f, +1.131870735e-01f, -4.477418765e-03f },
-    { -5.160531481e-02f, +9.432075026e-01f, +1.134113352e-01f, -4.489613138e-03f },
-    { -5.164431986e-02f, +9.430373667e-01f, +1.136357497e-01f, -4.501826329e-03f },
-    { -5.168321841e-02f, +9.428669944e-01f, +1.138603169e-01f, -4.514058345e-03f },
-    { -5.172201055e-02f, +9.426963856e-01f, +1.140850368e-01f, -4.526309197e-03f },
-    { -5.176069636e-02f, +9.425255405e-01f, +1.143099093e-01f, -4.538578892e-03f },
-    { -5.179927591e-02f, +9.423544592e-01f, +1.145349345e-01f, -4.550867441e-03f },
-    { -5.183774929e-02f, +9.421831418e-01f, +1.147601122e-01f, -4.563174852e-03f },
-    { -5.187611657e-02f, +9.420115885e-01f, +1.149854425e-01f, -4.575501133e-03f },
-    { -5.191437783e-02f, +9.418397993e-01f, +1.152109254e-01f, -4.587846293e-03f },
-    { -5.195253316e-02f, +9.416677743e-01f, +1.154365607e-01f, -4.600210342e-03f },
-    { -5.199058263e-02f, +9.414955136e-01f, +1.156623486e-01f, -4.612593288e-03f },
-    { -5.202852632e-02f, +9.413230174e-01f, +1.158882888e-01f, -4.624995140e-03f },
-    { -5.206636432e-02f, +9.411502858e-01f, +1.161143815e-01f, -4.637415906e-03f },
-    { -5.210409670e-02f, +9.409773188e-01f, +1.163406265e-01f, -4.649855595e-03f },
-    { -5.214172354e-02f, +9.408041166e-01f, +1.165670239e-01f, -4.662314217e-03f },
-    { -5.217924493e-02f, +9.406306792e-01f, +1.167935736e-01f, -4.674791779e-03f },
-    { -5.221666093e-02f, +9.404570069e-01f, +1.170202755e-01f, -4.687288290e-03f },
-    { -5.225397164e-02f, +9.402830997e-01f, +1.172471298e-01f, -4.699803759e-03f },
-    { -5.229117713e-02f, +9.401089576e-01f, +1.174741362e-01f, -4.712338195e-03f },
-    { -5.232827748e-02f, +9.399345809e-01f, +1.177012947e-01f, -4.724891606e-03f },
-    { -5.236527277e-02f, +9.397599696e-01f, +1.179286055e-01f, -4.737464000e-03f },
-    { -5.240216308e-02f, +9.395851238e-01f, +1.181560683e-01f, -4.750055387e-03f },
-    { -5.243894849e-02f, +9.394100437e-01f, +1.183836832e-01f, -4.762665774e-03f },
-    { -5.247562909e-02f, +9.392347294e-01f, +1.186114502e-01f, -4.775295171e-03f },
-    { -5.251220495e-02f, +9.390591808e-01f, +1.188393692e-01f, -4.787943585e-03f },
-    { -5.254867615e-02f, +9.388833983e-01f, +1.190674401e-01f, -4.800611026e-03f },
-    { -5.258504277e-02f, +9.387073818e-01f, +1.192956630e-01f, -4.813297501e-03f },
-    { -5.262130489e-02f, +9.385311316e-01f, +1.195240378e-01f, -4.826003020e-03f },
-    { -5.265746259e-02f, +9.383546476e-01f, +1.197525644e-01f, -4.838727590e-03f },
-    { -5.269351596e-02f, +9.381779301e-01f, +1.199812429e-01f, -4.851471219e-03f },
-    { -5.272946506e-02f, +9.380009790e-01f, +1.202100732e-01f, -4.864233917e-03f },
-    { -5.276531000e-02f, +9.378237946e-01f, +1.204390553e-01f, -4.877015692e-03f },
-    { -5.280105083e-02f, +9.376463769e-01f, +1.206681891e-01f, -4.889816551e-03f },
-    { -5.283668764e-02f, +9.374687261e-01f, +1.208974746e-01f, -4.902636504e-03f },
-    { -5.287222052e-02f, +9.372908423e-01f, +1.211269118e-01f, -4.915475558e-03f },
-    { -5.290764955e-02f, +9.371127255e-01f, +1.213565006e-01f, -4.928333721e-03f },
-    { -5.294297479e-02f, +9.369343759e-01f, +1.215862410e-01f, -4.941211003e-03f },
-    { -5.297819635e-02f, +9.367557936e-01f, +1.218161330e-01f, -4.954107411e-03f },
-    { -5.301331428e-02f, +9.365769788e-01f, +1.220461765e-01f, -4.967022953e-03f },
-    { -5.304832868e-02f, +9.363979314e-01f, +1.222763714e-01f, -4.979957637e-03f },
-    { -5.308323963e-02f, +9.362186517e-01f, +1.225067179e-01f, -4.992911472e-03f },
-    { -5.311804720e-02f, +9.360391397e-01f, +1.227372157e-01f, -5.005884466e-03f },
-    { -5.315275148e-02f, +9.358593955e-01f, +1.229678649e-01f, -5.018876627e-03f },
-    { -5.318735255e-02f, +9.356794194e-01f, +1.231986655e-01f, -5.031887963e-03f },
-    { -5.322185049e-02f, +9.354992113e-01f, +1.234296174e-01f, -5.044918481e-03f },
-    { -5.325624537e-02f, +9.353187714e-01f, +1.236607205e-01f, -5.057968191e-03f },
-    { -5.329053728e-02f, +9.351380998e-01f, +1.238919749e-01f, -5.071037100e-03f },
-    { -5.332472630e-02f, +9.349571966e-01f, +1.241233805e-01f, -5.084125216e-03f },
-    { -5.335881251e-02f, +9.347760620e-01f, +1.243549372e-01f, -5.097232546e-03f },
-    { -5.339279600e-02f, +9.345946960e-01f, +1.245866451e-01f, -5.110359100e-03f },
-    { -5.342667683e-02f, +9.344130987e-01f, +1.248185041e-01f, -5.123504885e-03f },
-    { -5.346045510e-02f, +9.342312704e-01f, +1.250505141e-01f, -5.136669908e-03f },
-    { -5.349413088e-02f, +9.340492110e-01f, +1.252826751e-01f, -5.149854178e-03f },
-    { -5.352770425e-02f, +9.338669207e-01f, +1.255149871e-01f, -5.163057703e-03f },
-    { -5.356117530e-02f, +9.336843996e-01f, +1.257474501e-01f, -5.176280490e-03f },
-    { -5.359454410e-02f, +9.335016478e-01f, +1.259800639e-01f, -5.189522547e-03f },
-    { -5.362781074e-02f, +9.333186655e-01f, +1.262128286e-01f, -5.202783882e-03f },
-    { -5.366097530e-02f, +9.331354527e-01f, +1.264457441e-01f, -5.216064503e-03f },
-    { -5.369403785e-02f, +9.329520096e-01f, +1.266788105e-01f, -5.229364417e-03f },
-    { -5.372699848e-02f, +9.327683363e-01f, +1.269120275e-01f, -5.242683633e-03f },
-    { -5.375985728e-02f, +9.325844328e-01f, +1.271453953e-01f, -5.256022157e-03f },
-    { -5.379261431e-02f, +9.324002994e-01f, +1.273789138e-01f, -5.269379998e-03f },
-    { -5.382526966e-02f, +9.322159361e-01f, +1.276125829e-01f, -5.282757164e-03f },
-    { -5.385782342e-02f, +9.320313430e-01f, +1.278464026e-01f, -5.296153661e-03f },
-    { -5.389027566e-02f, +9.318465203e-01f, +1.280803728e-01f, -5.309569498e-03f },
-    { -5.392262647e-02f, +9.316614680e-01f, +1.283144936e-01f, -5.323004682e-03f },
-    { -5.395487592e-02f, +9.314761864e-01f, +1.285487648e-01f, -5.336459220e-03f },
-    { -5.398702410e-02f, +9.312906754e-01f, +1.287831865e-01f, -5.349933121e-03f },
-    { -5.401907109e-02f, +9.311049353e-01f, +1.290177586e-01f, -5.363426391e-03f },
-    { -5.405101697e-02f, +9.309189660e-01f, +1.292524811e-01f, -5.376939039e-03f },
-    { -5.408286181e-02f, +9.307327679e-01f, +1.294873538e-01f, -5.390471071e-03f },
-    { -5.411460571e-02f, +9.305463408e-01f, +1.297223769e-01f, -5.404022496e-03f },
-    { -5.414624875e-02f, +9.303596851e-01f, +1.299575502e-01f, -5.417593320e-03f },
-    { -5.417779099e-02f, +9.301728008e-01f, +1.301928737e-01f, -5.431183551e-03f },
-    { -5.420923253e-02f, +9.299856879e-01f, +1.304283474e-01f, -5.444793197e-03f },
-    { -5.424057345e-02f, +9.297983467e-01f, +1.306639711e-01f, -5.458422264e-03f },
-    { -5.427181382e-02f, +9.296107773e-01f, +1.308997450e-01f, -5.472070761e-03f },
-    { -5.430295374e-02f, +9.294229797e-01f, +1.311356689e-01f, -5.485738694e-03f },
-    { -5.433399327e-02f, +9.292349540e-01f, +1.313717428e-01f, -5.499426070e-03f },
-    { -5.436493251e-02f, +9.290467005e-01f, +1.316079667e-01f, -5.513132898e-03f },
-    { -5.439577153e-02f, +9.288582192e-01f, +1.318443405e-01f, -5.526859184e-03f },
-    { -5.442651041e-02f, +9.286695102e-01f, +1.320808642e-01f, -5.540604935e-03f },
-    { -5.445714924e-02f, +9.284805736e-01f, +1.323175377e-01f, -5.554370159e-03f },
-    { -5.448768810e-02f, +9.282914097e-01f, +1.325543610e-01f, -5.568154863e-03f },
-    { -5.451812706e-02f, +9.281020184e-01f, +1.327913341e-01f, -5.581959054e-03f },
-    { -5.454846622e-02f, +9.279123998e-01f, +1.330284568e-01f, -5.595782739e-03f },
-    { -5.457870565e-02f, +9.277225543e-01f, +1.332657293e-01f, -5.609625925e-03f },
-    { -5.460884543e-02f, +9.275324817e-01f, +1.335031514e-01f, -5.623488619e-03f },
-    { -5.463888565e-02f, +9.273421823e-01f, +1.337407230e-01f, -5.637370829e-03f },
-    { -5.466882638e-02f, +9.271516562e-01f, +1.339784442e-01f, -5.651272561e-03f },
-    { -5.469866771e-02f, +9.269609034e-01f, +1.342163150e-01f, -5.665193823e-03f },
-    { -5.472840972e-02f, +9.267699242e-01f, +1.344543351e-01f, -5.679134621e-03f },
-    { -5.475805249e-02f, +9.265787186e-01f, +1.346925048e-01f, -5.693094963e-03f },
-    { -5.478759611e-02f, +9.263872867e-01f, +1.349308237e-01f, -5.707074854e-03f },
-    { -5.481704064e-02f, +9.261956287e-01f, +1.351692920e-01f, -5.721074303e-03f },
-    { -5.484638619e-02f, +9.260037447e-01f, +1.354079097e-01f, -5.735093317e-03f },
-    { -5.487563282e-02f, +9.258116348e-01f, +1.356466765e-01f, -5.749131901e-03f },
-    { -5.490478063e-02f, +9.256192991e-01f, +1.358855926e-01f, -5.763190063e-03f },
-    { -5.493382968e-02f, +9.254267378e-01f, +1.361246578e-01f, -5.777267810e-03f },
-    { -5.496278007e-02f, +9.252339509e-01f, +1.363638722e-01f, -5.791365148e-03f },
-    { -5.499163187e-02f, +9.250409386e-01f, +1.366032356e-01f, -5.805482085e-03f },
-    { -5.502038517e-02f, +9.248477010e-01f, +1.368427480e-01f, -5.819618626e-03f },
-    { -5.504904005e-02f, +9.246542383e-01f, +1.370824095e-01f, -5.833774780e-03f },
-    { -5.507759658e-02f, +9.244605504e-01f, +1.373222199e-01f, -5.847950552e-03f },
-    { -5.510605486e-02f, +9.242666377e-01f, +1.375621792e-01f, -5.862145949e-03f },
-    { -5.513441497e-02f, +9.240725001e-01f, +1.378022873e-01f, -5.876360977e-03f },
-    { -5.516267698e-02f, +9.238781378e-01f, +1.380425443e-01f, -5.890595645e-03f },
-    { -5.519084097e-02f, +9.236835509e-01f, +1.382829500e-01f, -5.904849957e-03f },
-    { -5.521890704e-02f, +9.234887396e-01f, +1.385235045e-01f, -5.919123921e-03f },
-    { -5.524687526e-02f, +9.232937039e-01f, +1.387642076e-01f, -5.933417543e-03f },
-    { -5.527474572e-02f, +9.230984441e-01f, +1.390050594e-01f, -5.947730830e-03f },
-    { -5.530251848e-02f, +9.229029601e-01f, +1.392460598e-01f, -5.962063788e-03f },
-    { -5.533019365e-02f, +9.227072522e-01f, +1.394872087e-01f, -5.976416423e-03f },
-    { -5.535777130e-02f, +9.225113204e-01f, +1.397285061e-01f, -5.990788743e-03f },
-    { -5.538525151e-02f, +9.223151649e-01f, +1.399699520e-01f, -6.005180754e-03f },
-    { -5.541263436e-02f, +9.221187858e-01f, +1.402115463e-01f, -6.019592461e-03f },
-    { -5.543991994e-02f, +9.219221832e-01f, +1.404532889e-01f, -6.034023872e-03f },
-    { -5.546710832e-02f, +9.217253573e-01f, +1.406951799e-01f, -6.048474993e-03f },
-    { -5.549419960e-02f, +9.215283081e-01f, +1.409372192e-01f, -6.062945830e-03f },
-    { -5.552119385e-02f, +9.213310358e-01f, +1.411794066e-01f, -6.077436389e-03f },
-    { -5.554809115e-02f, +9.211335405e-01f, +1.414217423e-01f, -6.091946678e-03f },
-    { -5.557489159e-02f, +9.209358223e-01f, +1.416642261e-01f, -6.106476701e-03f },
-    { -5.560159525e-02f, +9.207378813e-01f, +1.419068580e-01f, -6.121026465e-03f },
-    { -5.562820221e-02f, +9.205397178e-01f, +1.421496379e-01f, -6.135595977e-03f },
-    { -5.565471255e-02f, +9.203413317e-01f, +1.423925658e-01f, -6.150185242e-03f },
-    { -5.568112636e-02f, +9.201427233e-01f, +1.426356417e-01f, -6.164794268e-03f },
-    { -5.570744371e-02f, +9.199438926e-01f, +1.428788655e-01f, -6.179423059e-03f },
-    { -5.573366470e-02f, +9.197448398e-01f, +1.431222371e-01f, -6.194071622e-03f },
-    { -5.575978940e-02f, +9.195455649e-01f, +1.433657566e-01f, -6.208739964e-03f },
-    { -5.578581789e-02f, +9.193460682e-01f, +1.436094238e-01f, -6.223428090e-03f },
-    { -5.581175026e-02f, +9.191463497e-01f, +1.438532387e-01f, -6.238136006e-03f },
-    { -5.583758659e-02f, +9.189464096e-01f, +1.440972013e-01f, -6.252863718e-03f },
-    { -5.586332696e-02f, +9.187462479e-01f, +1.443413115e-01f, -6.267611233e-03f },
-    { -5.588897145e-02f, +9.185458649e-01f, +1.445855693e-01f, -6.282378556e-03f },
-    { -5.591452015e-02f, +9.183452606e-01f, +1.448299746e-01f, -6.297165693e-03f },
-    { -5.593997314e-02f, +9.181444351e-01f, +1.450745274e-01f, -6.311972650e-03f },
-    { -5.596533050e-02f, +9.179433886e-01f, +1.453192276e-01f, -6.326799433e-03f },
-    { -5.599059231e-02f, +9.177421213e-01f, +1.455640752e-01f, -6.341646048e-03f },
-    { -5.601575866e-02f, +9.175406331e-01f, +1.458090702e-01f, -6.356512501e-03f },
-    { -5.604082963e-02f, +9.173389243e-01f, +1.460542124e-01f, -6.371398797e-03f },
-    { -5.606580530e-02f, +9.171369950e-01f, +1.462995018e-01f, -6.386304943e-03f },
-    { -5.609068575e-02f, +9.169348454e-01f, +1.465449385e-01f, -6.401230944e-03f },
-    { -5.611547107e-02f, +9.167324754e-01f, +1.467905223e-01f, -6.416176806e-03f },
-    { -5.614016133e-02f, +9.165298853e-01f, +1.470362531e-01f, -6.431142534e-03f },
-    { -5.616475663e-02f, +9.163270752e-01f, +1.472821311e-01f, -6.446128134e-03f },
-    { -5.618925704e-02f, +9.161240451e-01f, +1.475281560e-01f, -6.461133612e-03f },
-    { -5.621366265e-02f, +9.159207954e-01f, +1.477743278e-01f, -6.476158974e-03f },
-    { -5.623797353e-02f, +9.157173259e-01f, +1.480206466e-01f, -6.491204225e-03f },
-    { -5.626218978e-02f, +9.155136370e-01f, +1.482671122e-01f, -6.506269371e-03f },
-    { -5.628631147e-02f, +9.153097287e-01f, +1.485137245e-01f, -6.521354417e-03f },
-    { -5.631033869e-02f, +9.151056011e-01f, +1.487604837e-01f, -6.536459369e-03f },
-    { -5.633427152e-02f, +9.149012543e-01f, +1.490073895e-01f, -6.551584232e-03f },
-    { -5.635811004e-02f, +9.146966886e-01f, +1.492544420e-01f, -6.566729012e-03f },
-    { -5.638185433e-02f, +9.144919040e-01f, +1.495016410e-01f, -6.581893714e-03f },
-    { -5.640550448e-02f, +9.142869006e-01f, +1.497489866e-01f, -6.597078344e-03f },
-    { -5.642906057e-02f, +9.140816786e-01f, +1.499964787e-01f, -6.612282907e-03f },
-    { -5.645252268e-02f, +9.138762381e-01f, +1.502441173e-01f, -6.627507408e-03f },
-    { -5.647589090e-02f, +9.136705792e-01f, +1.504919022e-01f, -6.642751853e-03f },
-    { -5.649916531e-02f, +9.134647021e-01f, +1.507398335e-01f, -6.658016248e-03f },
-    { -5.652234599e-02f, +9.132586068e-01f, +1.509879110e-01f, -6.673300597e-03f },
-    { -5.654543302e-02f, +9.130522936e-01f, +1.512361348e-01f, -6.688604905e-03f },
-    { -5.656842649e-02f, +9.128457625e-01f, +1.514845048e-01f, -6.703929179e-03f },
-    { -5.659132648e-02f, +9.126390136e-01f, +1.517330210e-01f, -6.719273423e-03f },
-    { -5.661413307e-02f, +9.124320471e-01f, +1.519816832e-01f, -6.734637642e-03f },
-    { -5.663684634e-02f, +9.122248632e-01f, +1.522304914e-01f, -6.750021842e-03f },
-    { -5.665946638e-02f, +9.120174619e-01f, +1.524794457e-01f, -6.765426027e-03f },
-    { -5.668199328e-02f, +9.118098434e-01f, +1.527285458e-01f, -6.780850204e-03f },
-    { -5.670442710e-02f, +9.116020078e-01f, +1.529777918e-01f, -6.796294376e-03f },
-    { -5.672676795e-02f, +9.113939552e-01f, +1.532271837e-01f, -6.811758549e-03f },
-    { -5.674901589e-02f, +9.111856858e-01f, +1.534767213e-01f, -6.827242728e-03f },
-    { -5.677117101e-02f, +9.109771996e-01f, +1.537264047e-01f, -6.842746919e-03f },
-    { -5.679323340e-02f, +9.107684969e-01f, +1.539762337e-01f, -6.858271125e-03f },
-    { -5.681520314e-02f, +9.105595777e-01f, +1.542262084e-01f, -6.873815352e-03f },
-    { -5.683708031e-02f, +9.103504422e-01f, +1.544763286e-01f, -6.889379605e-03f },
-    { -5.685886499e-02f, +9.101410905e-01f, +1.547265943e-01f, -6.904963889e-03f },
-    { -5.688055727e-02f, +9.099315228e-01f, +1.549770055e-01f, -6.920568209e-03f },
-    { -5.690215723e-02f, +9.097217391e-01f, +1.552275620e-01f, -6.936192569e-03f },
-    { -5.692366496e-02f, +9.095117396e-01f, +1.554782640e-01f, -6.951836974e-03f },
-    { -5.694508053e-02f, +9.093015244e-01f, +1.557291112e-01f, -6.967501430e-03f },
-    { -5.696640402e-02f, +9.090910937e-01f, +1.559801037e-01f, -6.983185940e-03f },
-    { -5.698763554e-02f, +9.088804476e-01f, +1.562312413e-01f, -6.998890510e-03f },
-    { -5.700877514e-02f, +9.086695861e-01f, +1.564825241e-01f, -7.014615145e-03f },
-    { -5.702982292e-02f, +9.084585096e-01f, +1.567339520e-01f, -7.030359849e-03f },
-    { -5.705077897e-02f, +9.082472180e-01f, +1.569855249e-01f, -7.046124626e-03f },
-    { -5.707164336e-02f, +9.080357115e-01f, +1.572372428e-01f, -7.061909482e-03f },
-    { -5.709241618e-02f, +9.078239902e-01f, +1.574891056e-01f, -7.077714420e-03f },
-    { -5.711309750e-02f, +9.076120543e-01f, +1.577411133e-01f, -7.093539446e-03f },
-    { -5.713368743e-02f, +9.073999039e-01f, +1.579932657e-01f, -7.109384565e-03f },
-    { -5.715418602e-02f, +9.071875391e-01f, +1.582455630e-01f, -7.125249780e-03f },
-    { -5.717459338e-02f, +9.069749601e-01f, +1.584980049e-01f, -7.141135096e-03f },
-    { -5.719490958e-02f, +9.067621670e-01f, +1.587505915e-01f, -7.157040517e-03f },
-    { -5.721513471e-02f, +9.065491599e-01f, +1.590033227e-01f, -7.172966049e-03f },
-    { -5.723526885e-02f, +9.063359389e-01f, +1.592561984e-01f, -7.188911695e-03f },
-    { -5.725531208e-02f, +9.061225043e-01f, +1.595092186e-01f, -7.204877460e-03f },
-    { -5.727526448e-02f, +9.059088560e-01f, +1.597623832e-01f, -7.220863348e-03f },
-    { -5.729512615e-02f, +9.056949943e-01f, +1.600156922e-01f, -7.236869364e-03f },
-    { -5.731489716e-02f, +9.054809193e-01f, +1.602691455e-01f, -7.252895512e-03f },
-    { -5.733457759e-02f, +9.052666311e-01f, +1.605227430e-01f, -7.268941796e-03f },
-    { -5.735416753e-02f, +9.050521298e-01f, +1.607764848e-01f, -7.285008220e-03f },
-    { -5.737366706e-02f, +9.048374156e-01f, +1.610303707e-01f, -7.301094788e-03f },
-    { -5.739307627e-02f, +9.046224887e-01f, +1.612844007e-01f, -7.317201506e-03f },
-    { -5.741239524e-02f, +9.044073490e-01f, +1.615385747e-01f, -7.333328376e-03f },
-    { -5.743162405e-02f, +9.041919969e-01f, +1.617928927e-01f, -7.349475404e-03f },
-    { -5.745076279e-02f, +9.039764323e-01f, +1.620473546e-01f, -7.365642593e-03f },
-    { -5.746981153e-02f, +9.037606555e-01f, +1.623019604e-01f, -7.381829947e-03f },
-    { -5.748877036e-02f, +9.035446666e-01f, +1.625567100e-01f, -7.398037471e-03f },
-    { -5.750763937e-02f, +9.033284656e-01f, +1.628116034e-01f, -7.414265167e-03f },
-    { -5.752641864e-02f, +9.031120528e-01f, +1.630666404e-01f, -7.430513042e-03f },
-    { -5.754510825e-02f, +9.028954283e-01f, +1.633218211e-01f, -7.446781098e-03f },
-    { -5.756370829e-02f, +9.026785922e-01f, +1.635771453e-01f, -7.463069339e-03f },
-    { -5.758221883e-02f, +9.024615447e-01f, +1.638326131e-01f, -7.479377769e-03f },
-    { -5.760063997e-02f, +9.022442858e-01f, +1.640882243e-01f, -7.495706392e-03f },
-    { -5.761897178e-02f, +9.020268157e-01f, +1.643439789e-01f, -7.512055213e-03f },
-    { -5.763721435e-02f, +9.018091345e-01f, +1.645998769e-01f, -7.528424234e-03f },
-    { -5.765536777e-02f, +9.015912425e-01f, +1.648559182e-01f, -7.544813460e-03f },
-    { -5.767343210e-02f, +9.013731396e-01f, +1.651121027e-01f, -7.561222894e-03f },
-    { -5.769140745e-02f, +9.011548261e-01f, +1.653684303e-01f, -7.577652540e-03f },
-    { -5.770929389e-02f, +9.009363021e-01f, +1.656249011e-01f, -7.594102403e-03f },
-    { -5.772709151e-02f, +9.007175676e-01f, +1.658815150e-01f, -7.610572484e-03f },
-    { -5.774480038e-02f, +9.004986230e-01f, +1.661382718e-01f, -7.627062789e-03f },
-    { -5.776242060e-02f, +9.002794682e-01f, +1.663951716e-01f, -7.643573321e-03f },
-    { -5.777995224e-02f, +9.000601034e-01f, +1.666522142e-01f, -7.660104084e-03f },
-    { -5.779739540e-02f, +8.998405288e-01f, +1.669093997e-01f, -7.676655080e-03f },
-    { -5.781475014e-02f, +8.996207445e-01f, +1.671667279e-01f, -7.693226314e-03f },
-    { -5.783201657e-02f, +8.994007506e-01f, +1.674241988e-01f, -7.709817790e-03f },
-    { -5.784919475e-02f, +8.991805472e-01f, +1.676818124e-01f, -7.726429509e-03f },
-    { -5.786628478e-02f, +8.989601346e-01f, +1.679395686e-01f, -7.743061477e-03f },
-    { -5.788328673e-02f, +8.987395128e-01f, +1.681974672e-01f, -7.759713697e-03f },
-    { -5.790020070e-02f, +8.985186819e-01f, +1.684555084e-01f, -7.776386171e-03f },
-    { -5.791702676e-02f, +8.982976422e-01f, +1.687136919e-01f, -7.793078904e-03f },
-    { -5.793376500e-02f, +8.980763937e-01f, +1.689720178e-01f, -7.809791898e-03f },
-    { -5.795041550e-02f, +8.978549365e-01f, +1.692304860e-01f, -7.826525157e-03f },
-    { -5.796697834e-02f, +8.976332709e-01f, +1.694890963e-01f, -7.843278685e-03f },
-    { -5.798345361e-02f, +8.974113969e-01f, +1.697478489e-01f, -7.860052484e-03f },
-    { -5.799984140e-02f, +8.971893148e-01f, +1.700067435e-01f, -7.876846558e-03f },
-    { -5.801614178e-02f, +8.969670245e-01f, +1.702657802e-01f, -7.893660909e-03f },
-    { -5.803235484e-02f, +8.967445263e-01f, +1.705249588e-01f, -7.910495542e-03f },
-    { -5.804848066e-02f, +8.965218203e-01f, +1.707842794e-01f, -7.927350459e-03f },
-    { -5.806451933e-02f, +8.962989066e-01f, +1.710437419e-01f, -7.944225664e-03f },
-    { -5.808047093e-02f, +8.960757854e-01f, +1.713033461e-01f, -7.961121159e-03f },
-    { -5.809633554e-02f, +8.958524568e-01f, +1.715630920e-01f, -7.978036948e-03f },
-    { -5.811211325e-02f, +8.956289209e-01f, +1.718229797e-01f, -7.994973033e-03f },
-    { -5.812780414e-02f, +8.954051779e-01f, +1.720830089e-01f, -8.011929418e-03f },
-    { -5.814340830e-02f, +8.951812279e-01f, +1.723431797e-01f, -8.028906105e-03f },
-    { -5.815892580e-02f, +8.949570711e-01f, +1.726034920e-01f, -8.045903098e-03f },
-    { -5.817435673e-02f, +8.947327076e-01f, +1.728639457e-01f, -8.062920399e-03f },
-    { -5.818970119e-02f, +8.945081375e-01f, +1.731245407e-01f, -8.079958012e-03f },
-    { -5.820495924e-02f, +8.942833610e-01f, +1.733852771e-01f, -8.097015938e-03f },
-    { -5.822013097e-02f, +8.940583782e-01f, +1.736461547e-01f, -8.114094182e-03f },
-    { -5.823521647e-02f, +8.938331892e-01f, +1.739071734e-01f, -8.131192745e-03f },
-    { -5.825021582e-02f, +8.936077942e-01f, +1.741683333e-01f, -8.148311631e-03f },
-    { -5.826512910e-02f, +8.933821934e-01f, +1.744296343e-01f, -8.165450843e-03f },
-    { -5.827995640e-02f, +8.931563868e-01f, +1.746910762e-01f, -8.182610382e-03f },
-    { -5.829469780e-02f, +8.929303746e-01f, +1.749526590e-01f, -8.199790252e-03f },
-    { -5.830935339e-02f, +8.927041569e-01f, +1.752143827e-01f, -8.216990455e-03f },
-    { -5.832392325e-02f, +8.924777339e-01f, +1.754762472e-01f, -8.234210994e-03f },
-    { -5.833840746e-02f, +8.922511057e-01f, +1.757382524e-01f, -8.251451871e-03f },
-    { -5.835280610e-02f, +8.920242725e-01f, +1.760003983e-01f, -8.268713090e-03f },
-    { -5.836711927e-02f, +8.917972344e-01f, +1.762626848e-01f, -8.285994652e-03f },
-    { -5.838134704e-02f, +8.915699915e-01f, +1.765251119e-01f, -8.303296561e-03f },
-    { -5.839548949e-02f, +8.913425440e-01f, +1.767876794e-01f, -8.320618817e-03f },
-    { -5.840954672e-02f, +8.911148920e-01f, +1.770503873e-01f, -8.337961425e-03f },
-    { -5.842351880e-02f, +8.908870357e-01f, +1.773132356e-01f, -8.355324387e-03f },
-    { -5.843740582e-02f, +8.906589751e-01f, +1.775762242e-01f, -8.372707704e-03f },
-    { -5.845120786e-02f, +8.904307105e-01f, +1.778393529e-01f, -8.390111379e-03f },
-    { -5.846492501e-02f, +8.902022419e-01f, +1.781026219e-01f, -8.407535414e-03f },
-    { -5.847855735e-02f, +8.899735696e-01f, +1.783660309e-01f, -8.424979813e-03f },
-    { -5.849210496e-02f, +8.897446936e-01f, +1.786295800e-01f, -8.442444576e-03f },
-    { -5.850556793e-02f, +8.895156142e-01f, +1.788932690e-01f, -8.459929707e-03f },
-    { -5.851894634e-02f, +8.892863313e-01f, +1.791570979e-01f, -8.477435207e-03f },
-    { -5.853224028e-02f, +8.890568452e-01f, +1.794210666e-01f, -8.494961078e-03f },
-    { -5.854544983e-02f, +8.888271561e-01f, +1.796851751e-01f, -8.512507324e-03f },
-    { -5.855857506e-02f, +8.885972640e-01f, +1.799494234e-01f, -8.530073945e-03f },
-    { -5.857161608e-02f, +8.883671691e-01f, +1.802138112e-01f, -8.547660944e-03f },
-    { -5.858457295e-02f, +8.881368715e-01f, +1.804783386e-01f, -8.565268323e-03f },
-    { -5.859744577e-02f, +8.879063714e-01f, +1.807430055e-01f, -8.582896084e-03f },
-    { -5.861023462e-02f, +8.876756689e-01f, +1.810078118e-01f, -8.600544229e-03f },
-    { -5.862293958e-02f, +8.874447642e-01f, +1.812727576e-01f, -8.618212759e-03f },
-    { -5.863556073e-02f, +8.872136574e-01f, +1.815378426e-01f, -8.635901678e-03f },
-    { -5.864809816e-02f, +8.869823487e-01f, +1.818030668e-01f, -8.653610986e-03f },
-    { -5.866055196e-02f, +8.867508381e-01f, +1.820684302e-01f, -8.671340686e-03f },
-    { -5.867292220e-02f, +8.865191259e-01f, +1.823339328e-01f, -8.689090780e-03f },
-    { -5.868520898e-02f, +8.862872121e-01f, +1.825995743e-01f, -8.706861268e-03f },
-    { -5.869741236e-02f, +8.860550970e-01f, +1.828653548e-01f, -8.724652154e-03f },
-    { -5.870953245e-02f, +8.858227806e-01f, +1.831312743e-01f, -8.742463438e-03f },
-    { -5.872156932e-02f, +8.855902631e-01f, +1.833973325e-01f, -8.760295123e-03f },
-    { -5.873352306e-02f, +8.853575446e-01f, +1.836635296e-01f, -8.778147210e-03f },
-    { -5.874539374e-02f, +8.851246253e-01f, +1.839298653e-01f, -8.796019700e-03f },
-    { -5.875718146e-02f, +8.848915054e-01f, +1.841963397e-01f, -8.813912596e-03f },
-    { -5.876888630e-02f, +8.846581849e-01f, +1.844629526e-01f, -8.831825899e-03f },
-    { -5.878050834e-02f, +8.844246640e-01f, +1.847297040e-01f, -8.849759611e-03f },
-    { -5.879204767e-02f, +8.841909429e-01f, +1.849965939e-01f, -8.867713732e-03f },
-    { -5.880350436e-02f, +8.839570217e-01f, +1.852636221e-01f, -8.885688265e-03f },
-    { -5.881487851e-02f, +8.837229005e-01f, +1.855307886e-01f, -8.903683211e-03f },
-    { -5.882617019e-02f, +8.834885795e-01f, +1.857980933e-01f, -8.921698572e-03f },
-    { -5.883737950e-02f, +8.832540589e-01f, +1.860655362e-01f, -8.939734348e-03f },
-    { -5.884850651e-02f, +8.830193387e-01f, +1.863331172e-01f, -8.957790542e-03f },
-    { -5.885955131e-02f, +8.827844191e-01f, +1.866008361e-01f, -8.975867154e-03f },
-    { -5.887051398e-02f, +8.825493003e-01f, +1.868686931e-01f, -8.993964185e-03f },
-    { -5.888139461e-02f, +8.823139824e-01f, +1.871366879e-01f, -9.012081638e-03f },
-    { -5.889219328e-02f, +8.820784655e-01f, +1.874048205e-01f, -9.030219514e-03f },
-    { -5.890291007e-02f, +8.818427498e-01f, +1.876730909e-01f, -9.048377812e-03f },
-    { -5.891354507e-02f, +8.816068354e-01f, +1.879414989e-01f, -9.066556536e-03f },
-    { -5.892409837e-02f, +8.813707226e-01f, +1.882100446e-01f, -9.084755685e-03f },
-    { -5.893457003e-02f, +8.811344113e-01f, +1.884787277e-01f, -9.102975262e-03f },
-    { -5.894496016e-02f, +8.808979018e-01f, +1.887475484e-01f, -9.121215266e-03f },
-    { -5.895526884e-02f, +8.806611943e-01f, +1.890165064e-01f, -9.139475700e-03f },
-    { -5.896549614e-02f, +8.804242888e-01f, +1.892856017e-01f, -9.157756564e-03f },
-    { -5.897564215e-02f, +8.801871854e-01f, +1.895548343e-01f, -9.176057859e-03f },
-    { -5.898570696e-02f, +8.799498845e-01f, +1.898242041e-01f, -9.194379586e-03f },
-    { -5.899569065e-02f, +8.797123860e-01f, +1.900937110e-01f, -9.212721746e-03f },
-    { -5.900559330e-02f, +8.794746902e-01f, +1.903633550e-01f, -9.231084340e-03f },
-    { -5.901541499e-02f, +8.792367971e-01f, +1.906331359e-01f, -9.249467369e-03f },
-    { -5.902515582e-02f, +8.789987070e-01f, +1.909030537e-01f, -9.267870833e-03f },
-    { -5.903481587e-02f, +8.787604199e-01f, +1.911731083e-01f, -9.286294734e-03f },
-    { -5.904439521e-02f, +8.785219361e-01f, +1.914432997e-01f, -9.304739072e-03f },
-    { -5.905389393e-02f, +8.782832556e-01f, +1.917136278e-01f, -9.323203848e-03f },
-    { -5.906331213e-02f, +8.780443786e-01f, +1.919840925e-01f, -9.341689062e-03f },
-    { -5.907264987e-02f, +8.778053053e-01f, +1.922546937e-01f, -9.360194716e-03f },
-    { -5.908190725e-02f, +8.775660358e-01f, +1.925254314e-01f, -9.378720810e-03f },
-    { -5.909108434e-02f, +8.773265703e-01f, +1.927963055e-01f, -9.397267344e-03f },
-    { -5.910018124e-02f, +8.770869088e-01f, +1.930673159e-01f, -9.415834320e-03f },
-    { -5.910919802e-02f, +8.768470516e-01f, +1.933384626e-01f, -9.434421737e-03f },
-    { -5.911813478e-02f, +8.766069987e-01f, +1.936097455e-01f, -9.453029596e-03f },
-    { -5.912699159e-02f, +8.763667504e-01f, +1.938811645e-01f, -9.471657898e-03f },
-    { -5.913576853e-02f, +8.761263068e-01f, +1.941527195e-01f, -9.490306643e-03f },
-    { -5.914446570e-02f, +8.758856680e-01f, +1.944244105e-01f, -9.508975831e-03f },
-    { -5.915308317e-02f, +8.756448342e-01f, +1.946962373e-01f, -9.527665464e-03f },
-    { -5.916162104e-02f, +8.754038055e-01f, +1.949682000e-01f, -9.546375540e-03f },
-    { -5.917007938e-02f, +8.751625821e-01f, +1.952402985e-01f, -9.565106062e-03f },
-    { -5.917845827e-02f, +8.749211640e-01f, +1.955125326e-01f, -9.583857028e-03f },
-    { -5.918675781e-02f, +8.746795516e-01f, +1.957849023e-01f, -9.602628439e-03f },
-    { -5.919497807e-02f, +8.744377448e-01f, +1.960574076e-01f, -9.621420295e-03f },
-    { -5.920311914e-02f, +8.741957439e-01f, +1.963300483e-01f, -9.640232597e-03f },
-    { -5.921118110e-02f, +8.739535491e-01f, +1.966028244e-01f, -9.659065344e-03f },
-    { -5.921916404e-02f, +8.737111603e-01f, +1.968757357e-01f, -9.677918538e-03f },
-    { -5.922706804e-02f, +8.734685779e-01f, +1.971487824e-01f, -9.696792177e-03f },
-    { -5.923489319e-02f, +8.732258019e-01f, +1.974219642e-01f, -9.715686262e-03f },
-    { -5.924263957e-02f, +8.729828325e-01f, +1.976952810e-01f, -9.734600793e-03f },
-    { -5.925030726e-02f, +8.727396699e-01f, +1.979687329e-01f, -9.753535770e-03f },
-    { -5.925789634e-02f, +8.724963141e-01f, +1.982423197e-01f, -9.772491192e-03f },
-    { -5.926540690e-02f, +8.722527654e-01f, +1.985160414e-01f, -9.791467061e-03f },
-    { -5.927283903e-02f, +8.720090239e-01f, +1.987898979e-01f, -9.810463375e-03f },
-    { -5.928019281e-02f, +8.717650897e-01f, +1.990638891e-01f, -9.829480135e-03f },
-    { -5.928746832e-02f, +8.715209630e-01f, +1.993380149e-01f, -9.848517340e-03f },
-    { -5.929466565e-02f, +8.712766439e-01f, +1.996122753e-01f, -9.867574990e-03f },
-    { -5.930178487e-02f, +8.710321326e-01f, +1.998866701e-01f, -9.886653086e-03f },
-    { -5.930882608e-02f, +8.707874293e-01f, +2.001611994e-01f, -9.905751626e-03f },
-    { -5.931578936e-02f, +8.705425340e-01f, +2.004358631e-01f, -9.924870610e-03f },
-    { -5.932267479e-02f, +8.702974470e-01f, +2.007106609e-01f, -9.944010038e-03f },
-    { -5.932948245e-02f, +8.700521683e-01f, +2.009855930e-01f, -9.963169910e-03f },
-    { -5.933621243e-02f, +8.698066982e-01f, +2.012606592e-01f, -9.982350225e-03f },
-    { -5.934286482e-02f, +8.695610368e-01f, +2.015358594e-01f, -1.000155098e-02f },
-    { -5.934943969e-02f, +8.693151841e-01f, +2.018111936e-01f, -1.002077218e-02f },
-    { -5.935593714e-02f, +8.690691405e-01f, +2.020866616e-01f, -1.004001383e-02f },
-    { -5.936235724e-02f, +8.688229060e-01f, +2.023622635e-01f, -1.005927591e-02f },
-    { -5.936870008e-02f, +8.685764808e-01f, +2.026379991e-01f, -1.007855843e-02f },
-    { -5.937496574e-02f, +8.683298650e-01f, +2.029138683e-01f, -1.009786140e-02f },
-    { -5.938115430e-02f, +8.680830587e-01f, +2.031898712e-01f, -1.011718480e-02f },
-    { -5.938726586e-02f, +8.678360622e-01f, +2.034660075e-01f, -1.013652864e-02f },
-    { -5.939330049e-02f, +8.675888756e-01f, +2.037422772e-01f, -1.015589292e-02f },
-    { -5.939925828e-02f, +8.673414990e-01f, +2.040186803e-01f, -1.017527764e-02f },
-    { -5.940513931e-02f, +8.670939326e-01f, +2.042952167e-01f, -1.019468279e-02f },
-    { -5.941094367e-02f, +8.668461765e-01f, +2.045718862e-01f, -1.021410838e-02f },
-    { -5.941667144e-02f, +8.665982309e-01f, +2.048486889e-01f, -1.023355441e-02f },
-    { -5.942232269e-02f, +8.663500959e-01f, +2.051256246e-01f, -1.025302087e-02f },
-    { -5.942789753e-02f, +8.661017718e-01f, +2.054026933e-01f, -1.027250776e-02f },
-    { -5.943339603e-02f, +8.658532585e-01f, +2.056798948e-01f, -1.029201508e-02f },
-    { -5.943881827e-02f, +8.656045563e-01f, +2.059572292e-01f, -1.031154284e-02f },
-    { -5.944416434e-02f, +8.653556654e-01f, +2.062346962e-01f, -1.033109103e-02f },
-    { -5.944943433e-02f, +8.651065858e-01f, +2.065122959e-01f, -1.035065964e-02f },
-    { -5.945462831e-02f, +8.648573178e-01f, +2.067900282e-01f, -1.037024868e-02f },
-    { -5.945974637e-02f, +8.646078615e-01f, +2.070678930e-01f, -1.038985815e-02f },
-    { -5.946478859e-02f, +8.643582170e-01f, +2.073458902e-01f, -1.040948805e-02f },
-    { -5.946975506e-02f, +8.641083845e-01f, +2.076240197e-01f, -1.042913837e-02f },
-    { -5.947464586e-02f, +8.638583642e-01f, +2.079022815e-01f, -1.044880911e-02f },
-    { -5.947946108e-02f, +8.636081562e-01f, +2.081806754e-01f, -1.046850028e-02f },
-    { -5.948420080e-02f, +8.633577606e-01f, +2.084592015e-01f, -1.048821187e-02f },
-    { -5.948886510e-02f, +8.631071776e-01f, +2.087378595e-01f, -1.050794387e-02f },
-    { -5.949345407e-02f, +8.628564073e-01f, +2.090166495e-01f, -1.052769630e-02f },
-    { -5.949796779e-02f, +8.626054500e-01f, +2.092955714e-01f, -1.054746914e-02f },
-    { -5.950240634e-02f, +8.623543057e-01f, +2.095746250e-01f, -1.056726239e-02f },
-    { -5.950676981e-02f, +8.621029746e-01f, +2.098538103e-01f, -1.058707606e-02f },
-    { -5.951105828e-02f, +8.618514569e-01f, +2.101331273e-01f, -1.060691015e-02f },
-    { -5.951527184e-02f, +8.615997527e-01f, +2.104125758e-01f, -1.062676464e-02f },
-    { -5.951941056e-02f, +8.613478622e-01f, +2.106921557e-01f, -1.064663954e-02f },
-    { -5.952347454e-02f, +8.610957855e-01f, +2.109718671e-01f, -1.066653486e-02f },
-    { -5.952746386e-02f, +8.608435227e-01f, +2.112517097e-01f, -1.068645057e-02f },
-    { -5.953137860e-02f, +8.605910741e-01f, +2.115316835e-01f, -1.070638669e-02f },
-    { -5.953521884e-02f, +8.603384398e-01f, +2.118117885e-01f, -1.072634322e-02f },
-    { -5.953898467e-02f, +8.600856199e-01f, +2.120920245e-01f, -1.074632015e-02f },
-    { -5.954267617e-02f, +8.598326146e-01f, +2.123723915e-01f, -1.076631747e-02f },
-    { -5.954629343e-02f, +8.595794240e-01f, +2.126528894e-01f, -1.078633519e-02f },
-    { -5.954983652e-02f, +8.593260484e-01f, +2.129335181e-01f, -1.080637331e-02f },
-    { -5.955330554e-02f, +8.590724878e-01f, +2.132142776e-01f, -1.082643182e-02f },
-    { -5.955670057e-02f, +8.588187423e-01f, +2.134951677e-01f, -1.084651073e-02f },
-    { -5.956002168e-02f, +8.585648123e-01f, +2.137761883e-01f, -1.086661002e-02f },
-    { -5.956326897e-02f, +8.583106977e-01f, +2.140573395e-01f, -1.088672970e-02f },
-    { -5.956644252e-02f, +8.580563988e-01f, +2.143386210e-01f, -1.090686977e-02f },
-    { -5.956954241e-02f, +8.578019157e-01f, +2.146200329e-01f, -1.092703022e-02f },
-    { -5.957256872e-02f, +8.575472486e-01f, +2.149015750e-01f, -1.094721106e-02f },
-    { -5.957552154e-02f, +8.572923976e-01f, +2.151832473e-01f, -1.096741227e-02f },
-    { -5.957840096e-02f, +8.570373629e-01f, +2.154650497e-01f, -1.098763386e-02f },
-    { -5.958120705e-02f, +8.567821446e-01f, +2.157469820e-01f, -1.100787583e-02f },
-    { -5.958393990e-02f, +8.565267430e-01f, +2.160290443e-01f, -1.102813817e-02f },
-    { -5.958659959e-02f, +8.562711580e-01f, +2.163112364e-01f, -1.104842088e-02f },
-    { -5.958918621e-02f, +8.560153900e-01f, +2.165935582e-01f, -1.106872396e-02f },
-    { -5.959169984e-02f, +8.557594390e-01f, +2.168760097e-01f, -1.108904740e-02f },
-    { -5.959414057e-02f, +8.555033052e-01f, +2.171585908e-01f, -1.110939121e-02f },
-    { -5.959650847e-02f, +8.552469888e-01f, +2.174413013e-01f, -1.112975538e-02f },
-    { -5.959880364e-02f, +8.549904899e-01f, +2.177241413e-01f, -1.115013991e-02f },
-    { -5.960102614e-02f, +8.547338087e-01f, +2.180071107e-01f, -1.117054480e-02f },
-    { -5.960317608e-02f, +8.544769453e-01f, +2.182902092e-01f, -1.119097004e-02f },
-    { -5.960525353e-02f, +8.542198999e-01f, +2.185734369e-01f, -1.121141563e-02f },
-    { -5.960725858e-02f, +8.539626726e-01f, +2.188567938e-01f, -1.123188157e-02f },
-    { -5.960919130e-02f, +8.537052637e-01f, +2.191402796e-01f, -1.125236786e-02f },
-    { -5.961105179e-02f, +8.534476731e-01f, +2.194238943e-01f, -1.127287449e-02f },
-    { -5.961284013e-02f, +8.531899012e-01f, +2.197076378e-01f, -1.129340147e-02f },
-    { -5.961455639e-02f, +8.529319481e-01f, +2.199915101e-01f, -1.131394878e-02f },
-    { -5.961620067e-02f, +8.526738139e-01f, +2.202755110e-01f, -1.133451643e-02f },
-    { -5.961777305e-02f, +8.524154987e-01f, +2.205596406e-01f, -1.135510441e-02f },
-    { -5.961927360e-02f, +8.521570028e-01f, +2.208438986e-01f, -1.137571272e-02f },
-    { -5.962070242e-02f, +8.518983262e-01f, +2.211282850e-01f, -1.139634135e-02f },
-    { -5.962205959e-02f, +8.516394693e-01f, +2.214127997e-01f, -1.141699032e-02f },
-    { -5.962334519e-02f, +8.513804320e-01f, +2.216974426e-01f, -1.143765960e-02f },
-    { -5.962455930e-02f, +8.511212145e-01f, +2.219822138e-01f, -1.145834920e-02f },
-    { -5.962570201e-02f, +8.508618171e-01f, +2.222671129e-01f, -1.147905912e-02f },
-    { -5.962677341e-02f, +8.506022399e-01f, +2.225521401e-01f, -1.149978935e-02f },
-    { -5.962777357e-02f, +8.503424830e-01f, +2.228372951e-01f, -1.152053989e-02f },
-    { -5.962870257e-02f, +8.500825465e-01f, +2.231225780e-01f, -1.154131073e-02f },
-    { -5.962956051e-02f, +8.498224307e-01f, +2.234079885e-01f, -1.156210188e-02f },
-    { -5.963034747e-02f, +8.495621358e-01f, +2.236935267e-01f, -1.158291333e-02f },
-    { -5.963106352e-02f, +8.493016617e-01f, +2.239791925e-01f, -1.160374507e-02f },
-    { -5.963170876e-02f, +8.490410088e-01f, +2.242649857e-01f, -1.162459711e-02f },
-    { -5.963228326e-02f, +8.487801771e-01f, +2.245509063e-01f, -1.164546944e-02f },
-    { -5.963278711e-02f, +8.485191669e-01f, +2.248369542e-01f, -1.166636205e-02f },
-    { -5.963322039e-02f, +8.482579783e-01f, +2.251231293e-01f, -1.168727495e-02f },
-    { -5.963358319e-02f, +8.479966114e-01f, +2.254094315e-01f, -1.170820813e-02f },
-    { -5.963387559e-02f, +8.477350664e-01f, +2.256958607e-01f, -1.172916159e-02f },
-    { -5.963409767e-02f, +8.474733435e-01f, +2.259824169e-01f, -1.175013531e-02f },
-    { -5.963424952e-02f, +8.472114428e-01f, +2.262690999e-01f, -1.177112931e-02f },
-    { -5.963433122e-02f, +8.469493644e-01f, +2.265559097e-01f, -1.179214358e-02f },
-    { -5.963434285e-02f, +8.466871086e-01f, +2.268428462e-01f, -1.181317810e-02f },
-    { -5.963428449e-02f, +8.464246755e-01f, +2.271299092e-01f, -1.183423289e-02f },
-    { -5.963415624e-02f, +8.461620653e-01f, +2.274170988e-01f, -1.185530793e-02f },
-    { -5.963395817e-02f, +8.458992780e-01f, +2.277044148e-01f, -1.187640322e-02f },
-    { -5.963369036e-02f, +8.456363139e-01f, +2.279918571e-01f, -1.189751876e-02f },
-    { -5.963335291e-02f, +8.453731732e-01f, +2.282794257e-01f, -1.191865455e-02f },
-    { -5.963294588e-02f, +8.451098559e-01f, +2.285671204e-01f, -1.193981057e-02f },
-    { -5.963246938e-02f, +8.448463623e-01f, +2.288549412e-01f, -1.196098683e-02f },
-    { -5.963192347e-02f, +8.445826924e-01f, +2.291428879e-01f, -1.198218333e-02f },
-    { -5.963130824e-02f, +8.443188466e-01f, +2.294309606e-01f, -1.200340005e-02f },
-    { -5.963062378e-02f, +8.440548248e-01f, +2.297191590e-01f, -1.202463700e-02f },
-    { -5.962987017e-02f, +8.437906274e-01f, +2.300074831e-01f, -1.204589416e-02f },
-    { -5.962904749e-02f, +8.435262543e-01f, +2.302959329e-01f, -1.206717155e-02f },
-    { -5.962815583e-02f, +8.432617059e-01f, +2.305845082e-01f, -1.208846914e-02f },
-    { -5.962719526e-02f, +8.429969822e-01f, +2.308732090e-01f, -1.210978695e-02f },
-    { -5.962616588e-02f, +8.427320835e-01f, +2.311620351e-01f, -1.213112496e-02f },
-    { -5.962506776e-02f, +8.424670098e-01f, +2.314509865e-01f, -1.215248317e-02f },
-    { -5.962390099e-02f, +8.422017613e-01f, +2.317400630e-01f, -1.217386158e-02f },
-    { -5.962266566e-02f, +8.419363383e-01f, +2.320292646e-01f, -1.219526018e-02f },
-    { -5.962136183e-02f, +8.416707408e-01f, +2.323185913e-01f, -1.221667896e-02f },
-    { -5.961998961e-02f, +8.414049690e-01f, +2.326080428e-01f, -1.223811793e-02f },
-    { -5.961854906e-02f, +8.411390231e-01f, +2.328976192e-01f, -1.225957708e-02f },
-    { -5.961704028e-02f, +8.408729033e-01f, +2.331873202e-01f, -1.228105640e-02f },
-    { -5.961546335e-02f, +8.406066096e-01f, +2.334771460e-01f, -1.230255589e-02f },
-    { -5.961381834e-02f, +8.403401423e-01f, +2.337670962e-01f, -1.232407555e-02f },
-    { -5.961210535e-02f, +8.400735015e-01f, +2.340571709e-01f, -1.234561537e-02f },
-    { -5.961032446e-02f, +8.398066874e-01f, +2.343473700e-01f, -1.236717535e-02f },
-    { -5.960847575e-02f, +8.395397001e-01f, +2.346376934e-01f, -1.238875548e-02f },
-    { -5.960655929e-02f, +8.392725398e-01f, +2.349281409e-01f, -1.241035575e-02f },
-    { -5.960457519e-02f, +8.390052067e-01f, +2.352187125e-01f, -1.243197617e-02f },
-    { -5.960252351e-02f, +8.387377009e-01f, +2.355094081e-01f, -1.245361672e-02f },
-    { -5.960040434e-02f, +8.384700225e-01f, +2.358002277e-01f, -1.247527741e-02f },
-    { -5.959821777e-02f, +8.382021718e-01f, +2.360911710e-01f, -1.249695823e-02f },
-    { -5.959596388e-02f, +8.379341490e-01f, +2.363822381e-01f, -1.251865917e-02f },
-    { -5.959364274e-02f, +8.376659540e-01f, +2.366734288e-01f, -1.254038023e-02f },
-    { -5.959125445e-02f, +8.373975872e-01f, +2.369647431e-01f, -1.256212141e-02f },
-    { -5.958879909e-02f, +8.371290487e-01f, +2.372561808e-01f, -1.258388269e-02f },
-    { -5.958627674e-02f, +8.368603387e-01f, +2.375477418e-01f, -1.260566408e-02f },
-    { -5.958368747e-02f, +8.365914572e-01f, +2.378394262e-01f, -1.262746557e-02f },
-    { -5.958103139e-02f, +8.363224045e-01f, +2.381312337e-01f, -1.264928715e-02f },
-    { -5.957830856e-02f, +8.360531808e-01f, +2.384231642e-01f, -1.267112882e-02f },
-    { -5.957551907e-02f, +8.357837861e-01f, +2.387152178e-01f, -1.269299057e-02f },
-    { -5.957266301e-02f, +8.355142207e-01f, +2.390073943e-01f, -1.271487241e-02f },
-    { -5.956974045e-02f, +8.352444848e-01f, +2.392996936e-01f, -1.273677432e-02f },
-    { -5.956675149e-02f, +8.349745784e-01f, +2.395921155e-01f, -1.275869629e-02f },
-    { -5.956369619e-02f, +8.347045017e-01f, +2.398846601e-01f, -1.278063833e-02f },
-    { -5.956057466e-02f, +8.344342550e-01f, +2.401773273e-01f, -1.280260043e-02f },
-    { -5.955738696e-02f, +8.341638383e-01f, +2.404701168e-01f, -1.282458258e-02f },
-    { -5.955413318e-02f, +8.338932518e-01f, +2.407630287e-01f, -1.284658477e-02f },
-    { -5.955081340e-02f, +8.336224957e-01f, +2.410560629e-01f, -1.286860701e-02f },
-    { -5.954742771e-02f, +8.333515702e-01f, +2.413492191e-01f, -1.289064929e-02f },
-    { -5.954397620e-02f, +8.330804754e-01f, +2.416424975e-01f, -1.291271159e-02f },
-    { -5.954045893e-02f, +8.328092115e-01f, +2.419358978e-01f, -1.293479392e-02f },
-    { -5.953687600e-02f, +8.325377786e-01f, +2.422294200e-01f, -1.295689627e-02f },
-    { -5.953322748e-02f, +8.322661770e-01f, +2.425230639e-01f, -1.297901864e-02f },
-    { -5.952951347e-02f, +8.319944067e-01f, +2.428168296e-01f, -1.300116101e-02f },
-    { -5.952573404e-02f, +8.317224679e-01f, +2.431107168e-01f, -1.302332339e-02f },
-    { -5.952188928e-02f, +8.314503608e-01f, +2.434047255e-01f, -1.304550576e-02f },
-    { -5.951797926e-02f, +8.311780856e-01f, +2.436988556e-01f, -1.306770813e-02f },
-    { -5.951400408e-02f, +8.309056424e-01f, +2.439931070e-01f, -1.308993048e-02f },
-    { -5.950996381e-02f, +8.306330313e-01f, +2.442874796e-01f, -1.311217281e-02f },
-    { -5.950585853e-02f, +8.303602527e-01f, +2.445819733e-01f, -1.313443511e-02f },
-    { -5.950168834e-02f, +8.300873065e-01f, +2.448765881e-01f, -1.315671739e-02f },
-    { -5.949745330e-02f, +8.298141930e-01f, +2.451713237e-01f, -1.317901962e-02f },
-    { -5.949315351e-02f, +8.295409124e-01f, +2.454661802e-01f, -1.320134181e-02f },
-    { -5.948878905e-02f, +8.292674647e-01f, +2.457611574e-01f, -1.322368395e-02f },
-    { -5.948436000e-02f, +8.289938502e-01f, +2.460562553e-01f, -1.324604604e-02f },
-    { -5.947986644e-02f, +8.287200691e-01f, +2.463514737e-01f, -1.326842806e-02f },
-    { -5.947530845e-02f, +8.284461214e-01f, +2.466468125e-01f, -1.329083001e-02f },
-    { -5.947068612e-02f, +8.281720074e-01f, +2.469422717e-01f, -1.331325190e-02f },
-    { -5.946599953e-02f, +8.278977272e-01f, +2.472378511e-01f, -1.333569370e-02f },
-    { -5.946124877e-02f, +8.276232810e-01f, +2.475335507e-01f, -1.335815541e-02f },
-    { -5.945643390e-02f, +8.273486689e-01f, +2.478293703e-01f, -1.338063703e-02f },
-    { -5.945155503e-02f, +8.270738912e-01f, +2.481253099e-01f, -1.340313855e-02f },
-    { -5.944661222e-02f, +8.267989479e-01f, +2.484213694e-01f, -1.342565996e-02f },
-    { -5.944160557e-02f, +8.265238393e-01f, +2.487175486e-01f, -1.344820127e-02f },
-    { -5.943653515e-02f, +8.262485655e-01f, +2.490138475e-01f, -1.347076245e-02f },
-    { -5.943140104e-02f, +8.259731267e-01f, +2.493102660e-01f, -1.349334351e-02f },
-    { -5.942620334e-02f, +8.256975230e-01f, +2.496068040e-01f, -1.351594444e-02f },
-    { -5.942094212e-02f, +8.254217546e-01f, +2.499034613e-01f, -1.353856523e-02f },
-    { -5.941561746e-02f, +8.251458217e-01f, +2.502002379e-01f, -1.356120587e-02f },
-    { -5.941022944e-02f, +8.248697244e-01f, +2.504971337e-01f, -1.358386636e-02f },
-    { -5.940477816e-02f, +8.245934629e-01f, +2.507941486e-01f, -1.360654670e-02f },
-    { -5.939926369e-02f, +8.243170373e-01f, +2.510912825e-01f, -1.362924687e-02f },
-    { -5.939368611e-02f, +8.240404479e-01f, +2.513885353e-01f, -1.365196686e-02f },
-    { -5.938804550e-02f, +8.237636948e-01f, +2.516859068e-01f, -1.367470668e-02f },
-    { -5.938234196e-02f, +8.234867781e-01f, +2.519833971e-01f, -1.369746632e-02f },
-    { -5.937657555e-02f, +8.232096981e-01f, +2.522810059e-01f, -1.372024576e-02f },
-    { -5.937074636e-02f, +8.229324548e-01f, +2.525787333e-01f, -1.374304500e-02f },
-    { -5.936485448e-02f, +8.226550485e-01f, +2.528765790e-01f, -1.376586404e-02f },
-    { -5.935889999e-02f, +8.223774794e-01f, +2.531745431e-01f, -1.378870286e-02f },
-    { -5.935288297e-02f, +8.220997475e-01f, +2.534726253e-01f, -1.381156147e-02f },
-    { -5.934680349e-02f, +8.218218531e-01f, +2.537708257e-01f, -1.383443984e-02f },
-    { -5.934066165e-02f, +8.215437962e-01f, +2.540691440e-01f, -1.385733799e-02f },
-    { -5.933445753e-02f, +8.212655772e-01f, +2.543675803e-01f, -1.388025589e-02f },
-    { -5.932819120e-02f, +8.209871961e-01f, +2.546661344e-01f, -1.390319354e-02f },
-    { -5.932186275e-02f, +8.207086532e-01f, +2.549648062e-01f, -1.392615094e-02f },
-    { -5.931547226e-02f, +8.204299485e-01f, +2.552635955e-01f, -1.394912807e-02f },
-    { -5.930901982e-02f, +8.201510823e-01f, +2.555625024e-01f, -1.397212493e-02f },
-    { -5.930250550e-02f, +8.198720547e-01f, +2.558615267e-01f, -1.399514152e-02f },
-    { -5.929592939e-02f, +8.195928658e-01f, +2.561606683e-01f, -1.401817782e-02f },
-    { -5.928929157e-02f, +8.193135159e-01f, +2.564599271e-01f, -1.404123383e-02f },
-    { -5.928259213e-02f, +8.190340052e-01f, +2.567593031e-01f, -1.406430953e-02f },
-    { -5.927583113e-02f, +8.187543337e-01f, +2.570587960e-01f, -1.408740493e-02f },
-    { -5.926900867e-02f, +8.184745017e-01f, +2.573584058e-01f, -1.411052002e-02f },
-    { -5.926212483e-02f, +8.181945092e-01f, +2.576581325e-01f, -1.413365478e-02f },
-    { -5.925517969e-02f, +8.179143566e-01f, +2.579579758e-01f, -1.415680921e-02f },
-    { -5.924817333e-02f, +8.176340439e-01f, +2.582579358e-01f, -1.417998331e-02f },
-    { -5.924110584e-02f, +8.173535714e-01f, +2.585580122e-01f, -1.420317705e-02f },
-    { -5.923397729e-02f, +8.170729391e-01f, +2.588582051e-01f, -1.422639045e-02f },
-    { -5.922678777e-02f, +8.167921473e-01f, +2.591585142e-01f, -1.424962348e-02f },
-    { -5.921953735e-02f, +8.165111960e-01f, +2.594589396e-01f, -1.427287614e-02f },
-    { -5.921222613e-02f, +8.162300856e-01f, +2.597594810e-01f, -1.429614843e-02f },
-    { -5.920485418e-02f, +8.159488162e-01f, +2.600601385e-01f, -1.431944033e-02f },
-    { -5.919742158e-02f, +8.156673878e-01f, +2.603609118e-01f, -1.434275184e-02f },
-    { -5.918992842e-02f, +8.153858007e-01f, +2.606618010e-01f, -1.436608295e-02f },
-    { -5.918237478e-02f, +8.151040551e-01f, +2.609628058e-01f, -1.438943365e-02f },
-    { -5.917476074e-02f, +8.148221512e-01f, +2.612639263e-01f, -1.441280393e-02f },
-    { -5.916708638e-02f, +8.145400890e-01f, +2.615651622e-01f, -1.443619379e-02f },
-    { -5.915935179e-02f, +8.142578688e-01f, +2.618665135e-01f, -1.445960321e-02f },
-    { -5.915155704e-02f, +8.139754907e-01f, +2.621679801e-01f, -1.448303220e-02f },
-    { -5.914370221e-02f, +8.136929549e-01f, +2.624695618e-01f, -1.450648073e-02f },
-    { -5.913578740e-02f, +8.134102615e-01f, +2.627712587e-01f, -1.452994881e-02f },
-    { -5.912781267e-02f, +8.131274108e-01f, +2.630730705e-01f, -1.455343641e-02f },
-    { -5.911977812e-02f, +8.128444029e-01f, +2.633749972e-01f, -1.457694355e-02f },
-    { -5.911168382e-02f, +8.125612380e-01f, +2.636770386e-01f, -1.460047020e-02f },
-    { -5.910352985e-02f, +8.122779162e-01f, +2.639791948e-01f, -1.462401636e-02f },
-    { -5.909531630e-02f, +8.119944377e-01f, +2.642814655e-01f, -1.464758202e-02f },
-    { -5.908704325e-02f, +8.117108027e-01f, +2.645838506e-01f, -1.467116717e-02f },
-    { -5.907871078e-02f, +8.114270114e-01f, +2.648863501e-01f, -1.469477181e-02f },
-    { -5.907031897e-02f, +8.111430638e-01f, +2.651889639e-01f, -1.471839591e-02f },
-    { -5.906186790e-02f, +8.108589603e-01f, +2.654916918e-01f, -1.474203949e-02f },
-    { -5.905335765e-02f, +8.105747008e-01f, +2.657945338e-01f, -1.476570252e-02f },
-    { -5.904478831e-02f, +8.102902857e-01f, +2.660974897e-01f, -1.478938500e-02f },
-    { -5.903615996e-02f, +8.100057151e-01f, +2.664005594e-01f, -1.481308692e-02f },
-    { -5.902747268e-02f, +8.097209892e-01f, +2.667037429e-01f, -1.483680827e-02f },
-    { -5.901872654e-02f, +8.094361081e-01f, +2.670070400e-01f, -1.486054904e-02f },
-    { -5.900992164e-02f, +8.091510719e-01f, +2.673104506e-01f, -1.488430923e-02f },
-    { -5.900105805e-02f, +8.088658810e-01f, +2.676139746e-01f, -1.490808882e-02f },
-    { -5.899213585e-02f, +8.085805354e-01f, +2.679176120e-01f, -1.493188780e-02f },
-    { -5.898315513e-02f, +8.082950352e-01f, +2.682213626e-01f, -1.495570618e-02f },
-    { -5.897411596e-02f, +8.080093808e-01f, +2.685252263e-01f, -1.497954392e-02f },
-    { -5.896501843e-02f, +8.077235722e-01f, +2.688292029e-01f, -1.500340104e-02f },
-    { -5.895586262e-02f, +8.074376096e-01f, +2.691332925e-01f, -1.502727751e-02f },
-    { -5.894664861e-02f, +8.071514932e-01f, +2.694374949e-01f, -1.505117334e-02f },
-    { -5.893737648e-02f, +8.068652231e-01f, +2.697418099e-01f, -1.507508850e-02f },
-    { -5.892804632e-02f, +8.065787996e-01f, +2.700462376e-01f, -1.509902300e-02f },
-    { -5.891865819e-02f, +8.062922227e-01f, +2.703507777e-01f, -1.512297682e-02f },
-    { -5.890921220e-02f, +8.060054928e-01f, +2.706554301e-01f, -1.514694995e-02f },
-    { -5.889970841e-02f, +8.057186098e-01f, +2.709601949e-01f, -1.517094238e-02f },
-    { -5.889014690e-02f, +8.054315741e-01f, +2.712650718e-01f, -1.519495411e-02f },
-    { -5.888052777e-02f, +8.051443857e-01f, +2.715700607e-01f, -1.521898512e-02f },
-    { -5.887085108e-02f, +8.048570449e-01f, +2.718751616e-01f, -1.524303541e-02f },
-    { -5.886111692e-02f, +8.045695518e-01f, +2.721803743e-01f, -1.526710496e-02f },
-    { -5.885132538e-02f, +8.042819066e-01f, +2.724856987e-01f, -1.529119377e-02f },
-    { -5.884147653e-02f, +8.039941094e-01f, +2.727911348e-01f, -1.531530183e-02f },
-    { -5.883157045e-02f, +8.037061604e-01f, +2.730966824e-01f, -1.533942912e-02f },
-    { -5.882160722e-02f, +8.034180599e-01f, +2.734023414e-01f, -1.536357563e-02f },
-    { -5.881158693e-02f, +8.031298079e-01f, +2.737081117e-01f, -1.538774137e-02f },
-    { -5.880150966e-02f, +8.028414047e-01f, +2.740139932e-01f, -1.541192631e-02f },
-    { -5.879137549e-02f, +8.025528503e-01f, +2.743199858e-01f, -1.543613045e-02f },
-    { -5.878118449e-02f, +8.022641451e-01f, +2.746260894e-01f, -1.546035377e-02f },
-    { -5.877093675e-02f, +8.019752891e-01f, +2.749323038e-01f, -1.548459628e-02f },
-    { -5.876063235e-02f, +8.016862825e-01f, +2.752386291e-01f, -1.550885795e-02f },
-    { -5.875027137e-02f, +8.013971255e-01f, +2.755450649e-01f, -1.553313878e-02f },
-    { -5.873985390e-02f, +8.011078183e-01f, +2.758516114e-01f, -1.555743875e-02f },
-    { -5.872938000e-02f, +8.008183610e-01f, +2.761582682e-01f, -1.558175787e-02f },
-    { -5.871884977e-02f, +8.005287538e-01f, +2.764650354e-01f, -1.560609611e-02f },
-    { -5.870826329e-02f, +8.002389969e-01f, +2.767719129e-01f, -1.563045347e-02f },
-    { -5.869762062e-02f, +7.999490904e-01f, +2.770789004e-01f, -1.565482993e-02f },
-    { -5.868692187e-02f, +7.996590346e-01f, +2.773859980e-01f, -1.567922549e-02f },
-    { -5.867616710e-02f, +7.993688295e-01f, +2.776932054e-01f, -1.570364014e-02f },
-    { -5.866535639e-02f, +7.990784754e-01f, +2.780005227e-01f, -1.572807386e-02f },
-    { -5.865448983e-02f, +7.987879725e-01f, +2.783079496e-01f, -1.575252665e-02f },
-    { -5.864356750e-02f, +7.984973209e-01f, +2.786154861e-01f, -1.577699850e-02f },
-    { -5.863258948e-02f, +7.982065207e-01f, +2.789231321e-01f, -1.580148939e-02f },
-    { -5.862155585e-02f, +7.979155722e-01f, +2.792308874e-01f, -1.582599931e-02f },
-    { -5.861046669e-02f, +7.976244755e-01f, +2.795387520e-01f, -1.585052826e-02f },
-    { -5.859932207e-02f, +7.973332308e-01f, +2.798467258e-01f, -1.587507622e-02f },
-    { -5.858812209e-02f, +7.970418383e-01f, +2.801548085e-01f, -1.589964318e-02f },
-    { -5.857686682e-02f, +7.967502981e-01f, +2.804630002e-01f, -1.592422914e-02f },
-    { -5.856555634e-02f, +7.964586105e-01f, +2.807713007e-01f, -1.594883407e-02f },
-    { -5.855419074e-02f, +7.961667755e-01f, +2.810797098e-01f, -1.597345798e-02f },
-    { -5.854277008e-02f, +7.958747933e-01f, +2.813882276e-01f, -1.599810084e-02f },
-    { -5.853129446e-02f, +7.955826642e-01f, +2.816968539e-01f, -1.602276266e-02f },
-    { -5.851976395e-02f, +7.952903884e-01f, +2.820055885e-01f, -1.604744341e-02f },
-    { -5.850817864e-02f, +7.949979658e-01f, +2.823144314e-01f, -1.607214309e-02f },
-    { -5.849653859e-02f, +7.947053969e-01f, +2.826233824e-01f, -1.609686168e-02f },
-    { -5.848484391e-02f, +7.944126816e-01f, +2.829324415e-01f, -1.612159918e-02f },
-    { -5.847309465e-02f, +7.941198202e-01f, +2.832416085e-01f, -1.614635558e-02f },
-    { -5.846129092e-02f, +7.938268129e-01f, +2.835508833e-01f, -1.617113085e-02f },
-    { -5.844943277e-02f, +7.935336599e-01f, +2.838602658e-01f, -1.619592500e-02f },
-    { -5.843752031e-02f, +7.932403612e-01f, +2.841697559e-01f, -1.622073801e-02f },
-    { -5.842555359e-02f, +7.929469172e-01f, +2.844793535e-01f, -1.624556986e-02f },
-    { -5.841353272e-02f, +7.926533279e-01f, +2.847890584e-01f, -1.627042056e-02f },
-    { -5.840145776e-02f, +7.923595935e-01f, +2.850988707e-01f, -1.629529008e-02f },
-    { -5.838932879e-02f, +7.920657142e-01f, +2.854087900e-01f, -1.632017842e-02f },
-    { -5.837714590e-02f, +7.917716902e-01f, +2.857188164e-01f, -1.634508556e-02f },
-    { -5.836490917e-02f, +7.914775217e-01f, +2.860289498e-01f, -1.637001149e-02f },
-    { -5.835261867e-02f, +7.911832088e-01f, +2.863391899e-01f, -1.639495620e-02f },
-    { -5.834027449e-02f, +7.908887516e-01f, +2.866495368e-01f, -1.641991969e-02f },
-    { -5.832787671e-02f, +7.905941505e-01f, +2.869599902e-01f, -1.644490193e-02f },
-    { -5.831542540e-02f, +7.902994055e-01f, +2.872705501e-01f, -1.646990291e-02f },
-    { -5.830292065e-02f, +7.900045168e-01f, +2.875812164e-01f, -1.649492264e-02f },
-    { -5.829036253e-02f, +7.897094846e-01f, +2.878919890e-01f, -1.651996108e-02f },
-    { -5.827775113e-02f, +7.894143091e-01f, +2.882028676e-01f, -1.654501824e-02f },
-    { -5.826508653e-02f, +7.891189904e-01f, +2.885138523e-01f, -1.657009409e-02f },
-    { -5.825236880e-02f, +7.888235287e-01f, +2.888249429e-01f, -1.659518863e-02f },
-    { -5.823959802e-02f, +7.885279242e-01f, +2.891361394e-01f, -1.662030185e-02f },
-    { -5.822677428e-02f, +7.882321771e-01f, +2.894474415e-01f, -1.664543373e-02f },
-    { -5.821389766e-02f, +7.879362875e-01f, +2.897588491e-01f, -1.667058426e-02f },
-    { -5.820096823e-02f, +7.876402556e-01f, +2.900703623e-01f, -1.669575344e-02f },
-    { -5.818798608e-02f, +7.873440816e-01f, +2.903819808e-01f, -1.672094124e-02f },
-    { -5.817495128e-02f, +7.870477656e-01f, +2.906937045e-01f, -1.674614765e-02f },
-    { -5.816186392e-02f, +7.867513079e-01f, +2.910055333e-01f, -1.677137267e-02f },
-    { -5.814872407e-02f, +7.864547086e-01f, +2.913174672e-01f, -1.679661628e-02f },
-    { -5.813553181e-02f, +7.861579679e-01f, +2.916295059e-01f, -1.682187847e-02f },
-    { -5.812228722e-02f, +7.858610859e-01f, +2.919416495e-01f, -1.684715923e-02f },
-    { -5.810899039e-02f, +7.855640629e-01f, +2.922538976e-01f, -1.687245854e-02f },
-    { -5.809564139e-02f, +7.852668990e-01f, +2.925662504e-01f, -1.689777639e-02f },
-    { -5.808224030e-02f, +7.849695943e-01f, +2.928787076e-01f, -1.692311278e-02f },
-    { -5.806878721e-02f, +7.846721491e-01f, +2.931912691e-01f, -1.694846768e-02f },
-    { -5.805528218e-02f, +7.843745636e-01f, +2.935039348e-01f, -1.697384108e-02f },
-    { -5.804172530e-02f, +7.840768378e-01f, +2.938167045e-01f, -1.699923298e-02f },
-    { -5.802811666e-02f, +7.837789720e-01f, +2.941295783e-01f, -1.702464336e-02f },
-    { -5.801445632e-02f, +7.834809664e-01f, +2.944425560e-01f, -1.705007220e-02f },
-    { -5.800074437e-02f, +7.831828211e-01f, +2.947556373e-01f, -1.707551950e-02f },
-    { -5.798698089e-02f, +7.828845363e-01f, +2.950688223e-01f, -1.710098524e-02f },
-    { -5.797316596e-02f, +7.825861121e-01f, +2.953821109e-01f, -1.712646941e-02f },
-    { -5.795929965e-02f, +7.822875489e-01f, +2.956955028e-01f, -1.715197200e-02f },
-    { -5.794538205e-02f, +7.819888466e-01f, +2.960089980e-01f, -1.717749299e-02f },
-    { -5.793141324e-02f, +7.816900056e-01f, +2.963225964e-01f, -1.720303237e-02f },
-    { -5.791739329e-02f, +7.813910260e-01f, +2.966362979e-01f, -1.722859012e-02f },
-    { -5.790332228e-02f, +7.810919079e-01f, +2.969501022e-01f, -1.725416625e-02f },
-    { -5.788920029e-02f, +7.807926515e-01f, +2.972640094e-01f, -1.727976072e-02f },
-    { -5.787502741e-02f, +7.804932570e-01f, +2.975780194e-01f, -1.730537353e-02f },
-    { -5.786080371e-02f, +7.801937247e-01f, +2.978921319e-01f, -1.733100467e-02f },
-    { -5.784652927e-02f, +7.798940546e-01f, +2.982063468e-01f, -1.735665412e-02f },
-    { -5.783220417e-02f, +7.795942469e-01f, +2.985206642e-01f, -1.738232187e-02f },
-    { -5.781782849e-02f, +7.792943018e-01f, +2.988350837e-01f, -1.740800791e-02f },
-    { -5.780340230e-02f, +7.789942195e-01f, +2.991496054e-01f, -1.743371222e-02f },
-    { -5.778892569e-02f, +7.786940002e-01f, +2.994642291e-01f, -1.745943479e-02f },
-    { -5.777439874e-02f, +7.783936440e-01f, +2.997789547e-01f, -1.748517560e-02f },
-    { -5.775982152e-02f, +7.780931511e-01f, +3.000937821e-01f, -1.751093465e-02f },
-    { -5.774519411e-02f, +7.777925218e-01f, +3.004087111e-01f, -1.753671192e-02f },
-    { -5.773051660e-02f, +7.774917560e-01f, +3.007237417e-01f, -1.756250739e-02f },
-    { -5.771578906e-02f, +7.771908542e-01f, +3.010388736e-01f, -1.758832105e-02f },
-    { -5.770101157e-02f, +7.768898163e-01f, +3.013541069e-01f, -1.761415290e-02f },
-    { -5.768618420e-02f, +7.765886426e-01f, +3.016694414e-01f, -1.764000291e-02f },
-    { -5.767130705e-02f, +7.762873333e-01f, +3.019848769e-01f, -1.766587107e-02f },
-    { -5.765638018e-02f, +7.759858886e-01f, +3.023004134e-01f, -1.769175736e-02f },
-    { -5.764140368e-02f, +7.756843086e-01f, +3.026160507e-01f, -1.771766179e-02f },
-    { -5.762637762e-02f, +7.753825935e-01f, +3.029317887e-01f, -1.774358432e-02f },
-    { -5.761130208e-02f, +7.750807434e-01f, +3.032476274e-01f, -1.776952495e-02f },
-    { -5.759617715e-02f, +7.747787586e-01f, +3.035635665e-01f, -1.779548366e-02f },
-    { -5.758100289e-02f, +7.744766393e-01f, +3.038796059e-01f, -1.782146044e-02f },
-    { -5.756577939e-02f, +7.741743855e-01f, +3.041957456e-01f, -1.784745527e-02f },
-    { -5.755050673e-02f, +7.738719975e-01f, +3.045119855e-01f, -1.787346814e-02f },
-    { -5.753518499e-02f, +7.735694755e-01f, +3.048283253e-01f, -1.789949905e-02f },
-    { -5.751981424e-02f, +7.732668197e-01f, +3.051447650e-01f, -1.792554796e-02f },
-    { -5.750439457e-02f, +7.729640301e-01f, +3.054613045e-01f, -1.795161487e-02f },
-    { -5.748892604e-02f, +7.726611070e-01f, +3.057779436e-01f, -1.797769977e-02f },
-    { -5.747340875e-02f, +7.723580506e-01f, +3.060946822e-01f, -1.800380263e-02f },
-    { -5.745784276e-02f, +7.720548611e-01f, +3.064115203e-01f, -1.802992345e-02f },
-    { -5.744222816e-02f, +7.717515386e-01f, +3.067284576e-01f, -1.805606221e-02f },
-    { -5.742656503e-02f, +7.714480832e-01f, +3.070454941e-01f, -1.808221890e-02f },
-    { -5.741085343e-02f, +7.711444953e-01f, +3.073626297e-01f, -1.810839350e-02f },
-    { -5.739509346e-02f, +7.708407749e-01f, +3.076798642e-01f, -1.813458600e-02f },
-    { -5.737928519e-02f, +7.705369222e-01f, +3.079971975e-01f, -1.816079639e-02f },
-    { -5.736342870e-02f, +7.702329374e-01f, +3.083146294e-01f, -1.818702464e-02f },
-    { -5.734752407e-02f, +7.699288208e-01f, +3.086321600e-01f, -1.821327074e-02f },
-    { -5.733157137e-02f, +7.696245724e-01f, +3.089497890e-01f, -1.823953469e-02f },
-    { -5.731557068e-02f, +7.693201924e-01f, +3.092675163e-01f, -1.826581646e-02f },
-    { -5.729952209e-02f, +7.690156811e-01f, +3.095853418e-01f, -1.829211604e-02f },
-    { -5.728342566e-02f, +7.687110385e-01f, +3.099032654e-01f, -1.831843341e-02f },
-    { -5.726728148e-02f, +7.684062649e-01f, +3.102212870e-01f, -1.834476857e-02f },
-    { -5.725108962e-02f, +7.681013605e-01f, +3.105394064e-01f, -1.837112149e-02f },
-    { -5.723485017e-02f, +7.677963254e-01f, +3.108576236e-01f, -1.839749217e-02f },
-    { -5.721856321e-02f, +7.674911598e-01f, +3.111759383e-01f, -1.842388058e-02f },
-    { -5.720222880e-02f, +7.671858639e-01f, +3.114943506e-01f, -1.845028671e-02f },
-    { -5.718584702e-02f, +7.668804379e-01f, +3.118128601e-01f, -1.847671054e-02f },
-    { -5.716941797e-02f, +7.665748819e-01f, +3.121314670e-01f, -1.850315207e-02f },
-    { -5.715294170e-02f, +7.662691962e-01f, +3.124501709e-01f, -1.852961127e-02f },
-    { -5.713641831e-02f, +7.659633808e-01f, +3.127689718e-01f, -1.855608813e-02f },
-    { -5.711984787e-02f, +7.656574360e-01f, +3.130878696e-01f, -1.858258264e-02f },
-    { -5.710323045e-02f, +7.653513620e-01f, +3.134068642e-01f, -1.860909478e-02f },
-    { -5.708656614e-02f, +7.650451589e-01f, +3.137259554e-01f, -1.863562453e-02f },
-    { -5.706985501e-02f, +7.647388269e-01f, +3.140451431e-01f, -1.866217188e-02f },
-    { -5.705309714e-02f, +7.644323662e-01f, +3.143644272e-01f, -1.868873682e-02f },
-    { -5.703629260e-02f, +7.641257769e-01f, +3.146838075e-01f, -1.871531932e-02f },
-    { -5.701944149e-02f, +7.638190593e-01f, +3.150032840e-01f, -1.874191938e-02f },
-    { -5.700254386e-02f, +7.635122136e-01f, +3.153228565e-01f, -1.876853697e-02f },
-    { -5.698559981e-02f, +7.632052398e-01f, +3.156425249e-01f, -1.879517209e-02f },
-    { -5.696860941e-02f, +7.628981382e-01f, +3.159622890e-01f, -1.882182471e-02f },
-    { -5.695157273e-02f, +7.625909090e-01f, +3.162821488e-01f, -1.884849482e-02f },
-    { -5.693448985e-02f, +7.622835524e-01f, +3.166021042e-01f, -1.887518241e-02f },
-    { -5.691736086e-02f, +7.619760684e-01f, +3.169221549e-01f, -1.890188745e-02f },
-    { -5.690018582e-02f, +7.616684574e-01f, +3.172423009e-01f, -1.892860994e-02f },
-    { -5.688296482e-02f, +7.613607194e-01f, +3.175625421e-01f, -1.895534986e-02f },
-    { -5.686569793e-02f, +7.610528546e-01f, +3.178828783e-01f, -1.898210719e-02f },
-    { -5.684838523e-02f, +7.607448634e-01f, +3.182033094e-01f, -1.900888191e-02f },
-    { -5.683102681e-02f, +7.604367457e-01f, +3.185238353e-01f, -1.903567401e-02f },
-    { -5.681362272e-02f, +7.601285018e-01f, +3.188444558e-01f, -1.906248348e-02f },
-    { -5.679617306e-02f, +7.598201319e-01f, +3.191651709e-01f, -1.908931029e-02f },
-    { -5.677867790e-02f, +7.595116361e-01f, +3.194859804e-01f, -1.911615443e-02f },
-    { -5.676113731e-02f, +7.592030147e-01f, +3.198068842e-01f, -1.914301589e-02f },
-    { -5.674355138e-02f, +7.588942678e-01f, +3.201278822e-01f, -1.916989465e-02f },
-    { -5.672592019e-02f, +7.585853955e-01f, +3.204489742e-01f, -1.919679069e-02f },
-    { -5.670824380e-02f, +7.582763982e-01f, +3.207701601e-01f, -1.922370400e-02f },
-    { -5.669052229e-02f, +7.579672759e-01f, +3.210914398e-01f, -1.925063455e-02f },
-    { -5.667275575e-02f, +7.576580288e-01f, +3.214128132e-01f, -1.927758234e-02f },
-    { -5.665494425e-02f, +7.573486571e-01f, +3.217342801e-01f, -1.930454735e-02f },
-    { -5.663708786e-02f, +7.570391610e-01f, +3.220558404e-01f, -1.933152956e-02f },
-    { -5.661918667e-02f, +7.567295407e-01f, +3.223774940e-01f, -1.935852895e-02f },
-    { -5.660124075e-02f, +7.564197963e-01f, +3.226992408e-01f, -1.938554550e-02f },
-    { -5.658325018e-02f, +7.561099280e-01f, +3.230210806e-01f, -1.941257921e-02f },
-    { -5.656521503e-02f, +7.557999361e-01f, +3.233430133e-01f, -1.943963005e-02f },
-    { -5.654713538e-02f, +7.554898206e-01f, +3.236650389e-01f, -1.946669801e-02f },
-    { -5.652901131e-02f, +7.551795818e-01f, +3.239871571e-01f, -1.949378307e-02f },
-    { -5.651084290e-02f, +7.548692198e-01f, +3.243093678e-01f, -1.952088522e-02f },
-    { -5.649263022e-02f, +7.545587349e-01f, +3.246316709e-01f, -1.954800443e-02f },
-    { -5.647437335e-02f, +7.542481271e-01f, +3.249540663e-01f, -1.957514069e-02f },
-    { -5.645607236e-02f, +7.539373968e-01f, +3.252765539e-01f, -1.960229398e-02f },
-    { -5.643772734e-02f, +7.536265440e-01f, +3.255991335e-01f, -1.962946429e-02f },
-    { -5.641933835e-02f, +7.533155690e-01f, +3.259218051e-01f, -1.965665160e-02f },
-    { -5.640090548e-02f, +7.530044718e-01f, +3.262445684e-01f, -1.968385589e-02f },
-    { -5.638242880e-02f, +7.526932528e-01f, +3.265674233e-01f, -1.971107714e-02f },
-    { -5.636390839e-02f, +7.523819121e-01f, +3.268903698e-01f, -1.973831534e-02f },
-    { -5.634534432e-02f, +7.520704498e-01f, +3.272134077e-01f, -1.976557047e-02f },
-    { -5.632673668e-02f, +7.517588662e-01f, +3.275365369e-01f, -1.979284251e-02f },
-    { -5.630808553e-02f, +7.514471614e-01f, +3.278597572e-01f, -1.982013145e-02f },
-    { -5.628939096e-02f, +7.511353356e-01f, +3.281830685e-01f, -1.984743727e-02f },
-    { -5.627065304e-02f, +7.508233890e-01f, +3.285064707e-01f, -1.987475995e-02f },
-    { -5.625187185e-02f, +7.505113218e-01f, +3.288299637e-01f, -1.990209947e-02f },
-    { -5.623304746e-02f, +7.501991341e-01f, +3.291535473e-01f, -1.992945582e-02f },
-    { -5.621417995e-02f, +7.498868261e-01f, +3.294772215e-01f, -1.995682897e-02f },
-    { -5.619526939e-02f, +7.495743981e-01f, +3.298009860e-01f, -1.998421892e-02f },
-    { -5.617631587e-02f, +7.492618501e-01f, +3.301248407e-01f, -2.001162564e-02f },
-    { -5.615731946e-02f, +7.489491824e-01f, +3.304487856e-01f, -2.003904911e-02f },
-    { -5.613828023e-02f, +7.486363951e-01f, +3.307728205e-01f, -2.006648932e-02f },
-    { -5.611919827e-02f, +7.483234885e-01f, +3.310969453e-01f, -2.009394625e-02f },
-    { -5.610007364e-02f, +7.480104627e-01f, +3.314211598e-01f, -2.012141988e-02f },
-    { -5.608090642e-02f, +7.476973179e-01f, +3.317454639e-01f, -2.014891020e-02f },
-    { -5.606169669e-02f, +7.473840543e-01f, +3.320698576e-01f, -2.017641718e-02f },
-    { -5.604244453e-02f, +7.470706720e-01f, +3.323943405e-01f, -2.020394081e-02f },
-    { -5.602315001e-02f, +7.467571712e-01f, +3.327189127e-01f, -2.023148107e-02f },
-    { -5.600381321e-02f, +7.464435522e-01f, +3.330435740e-01f, -2.025903794e-02f },
-    { -5.598443420e-02f, +7.461298151e-01f, +3.333683243e-01f, -2.028661141e-02f },
-    { -5.596501306e-02f, +7.458159600e-01f, +3.336931634e-01f, -2.031420145e-02f },
-    { -5.594554986e-02f, +7.455019872e-01f, +3.340180912e-01f, -2.034180804e-02f },
-    { -5.592604469e-02f, +7.451878969e-01f, +3.343431076e-01f, -2.036943118e-02f },
-    { -5.590649761e-02f, +7.448736891e-01f, +3.346682125e-01f, -2.039707084e-02f },
-    { -5.588690871e-02f, +7.445593642e-01f, +3.349934057e-01f, -2.042472700e-02f },
-    { -5.586727805e-02f, +7.442449222e-01f, +3.353186871e-01f, -2.045239964e-02f },
-    { -5.584760571e-02f, +7.439303635e-01f, +3.356440565e-01f, -2.048008875e-02f },
-    { -5.582789178e-02f, +7.436156880e-01f, +3.359695139e-01f, -2.050779431e-02f },
-    { -5.580813632e-02f, +7.433008961e-01f, +3.362950591e-01f, -2.053551629e-02f },
-    { -5.578833941e-02f, +7.429859879e-01f, +3.366206920e-01f, -2.056325469e-02f },
-    { -5.576850113e-02f, +7.426709636e-01f, +3.369464124e-01f, -2.059100947e-02f },
-    { -5.574862155e-02f, +7.423558234e-01f, +3.372722202e-01f, -2.061878063e-02f },
-    { -5.572870075e-02f, +7.420405674e-01f, +3.375981153e-01f, -2.064656814e-02f },
-    { -5.570873880e-02f, +7.417251959e-01f, +3.379240976e-01f, -2.067437199e-02f },
-    { -5.568873578e-02f, +7.414097090e-01f, +3.382501669e-01f, -2.070219216e-02f },
-    { -5.566869176e-02f, +7.410941069e-01f, +3.385763231e-01f, -2.073002862e-02f },
-    { -5.564860682e-02f, +7.407783897e-01f, +3.389025660e-01f, -2.075788136e-02f },
-    { -5.562848104e-02f, +7.404625577e-01f, +3.392288956e-01f, -2.078575035e-02f },
-    { -5.560831448e-02f, +7.401466111e-01f, +3.395553117e-01f, -2.081363559e-02f },
-    { -5.558810723e-02f, +7.398305500e-01f, +3.398818142e-01f, -2.084153705e-02f },
-    { -5.556785936e-02f, +7.395143746e-01f, +3.402084029e-01f, -2.086945472e-02f },
-    { -5.554757095e-02f, +7.391980851e-01f, +3.405350777e-01f, -2.089738856e-02f },
-    { -5.552724207e-02f, +7.388816817e-01f, +3.408618385e-01f, -2.092533857e-02f },
-    { -5.550687279e-02f, +7.385651645e-01f, +3.411886851e-01f, -2.095330472e-02f },
-    { -5.548646320e-02f, +7.382485338e-01f, +3.415156174e-01f, -2.098128700e-02f },
-    { -5.546601336e-02f, +7.379317896e-01f, +3.418426354e-01f, -2.100928539e-02f },
-    { -5.544552335e-02f, +7.376149323e-01f, +3.421697387e-01f, -2.103729986e-02f },
-    { -5.542499324e-02f, +7.372979620e-01f, +3.424969274e-01f, -2.106533040e-02f },
-    { -5.540442312e-02f, +7.369808788e-01f, +3.428242013e-01f, -2.109337699e-02f },
-    { -5.538381306e-02f, +7.366636830e-01f, +3.431515602e-01f, -2.112143960e-02f },
-    { -5.536316312e-02f, +7.363463747e-01f, +3.434790041e-01f, -2.114951822e-02f },
-    { -5.534247339e-02f, +7.360289541e-01f, +3.438065327e-01f, -2.117761283e-02f },
-    { -5.532174395e-02f, +7.357114214e-01f, +3.441341461e-01f, -2.120572342e-02f },
-    { -5.530097485e-02f, +7.353937768e-01f, +3.444618439e-01f, -2.123384995e-02f },
-    { -5.528016619e-02f, +7.350760204e-01f, +3.447896261e-01f, -2.126199241e-02f },
-    { -5.525931803e-02f, +7.347581525e-01f, +3.451174926e-01f, -2.129015078e-02f },
-    { -5.523843046e-02f, +7.344401732e-01f, +3.454454432e-01f, -2.131832504e-02f },
-    { -5.521750353e-02f, +7.341220827e-01f, +3.457734778e-01f, -2.134651517e-02f },
-    { -5.519653734e-02f, +7.338038812e-01f, +3.461015962e-01f, -2.137472115e-02f },
-    { -5.517553195e-02f, +7.334855689e-01f, +3.464297984e-01f, -2.140294296e-02f },
-    { -5.515448744e-02f, +7.331671459e-01f, +3.467580842e-01f, -2.143118058e-02f },
-    { -5.513340388e-02f, +7.328486125e-01f, +3.470864534e-01f, -2.145943399e-02f },
-    { -5.511228134e-02f, +7.325299688e-01f, +3.474149060e-01f, -2.148770317e-02f },
-    { -5.509111991e-02f, +7.322112150e-01f, +3.477434418e-01f, -2.151598810e-02f },
-    { -5.506991966e-02f, +7.318923513e-01f, +3.480720606e-01f, -2.154428875e-02f },
-    { -5.504868065e-02f, +7.315733778e-01f, +3.484007623e-01f, -2.157260512e-02f },
-    { -5.502740298e-02f, +7.312542948e-01f, +3.487295469e-01f, -2.160093718e-02f },
-    { -5.500608670e-02f, +7.309351024e-01f, +3.490584141e-01f, -2.162928490e-02f },
-    { -5.498473189e-02f, +7.306158008e-01f, +3.493873638e-01f, -2.165764827e-02f },
-    { -5.496333863e-02f, +7.302963903e-01f, +3.497163959e-01f, -2.168602727e-02f },
-    { -5.494190699e-02f, +7.299768709e-01f, +3.500455102e-01f, -2.171442188e-02f },
-    { -5.492043705e-02f, +7.296572429e-01f, +3.503747067e-01f, -2.174283207e-02f },
-    { -5.489892888e-02f, +7.293375064e-01f, +3.507039852e-01f, -2.177125783e-02f },
-    { -5.487738256e-02f, +7.290176616e-01f, +3.510333455e-01f, -2.179969913e-02f },
-    { -5.485579815e-02f, +7.286977088e-01f, +3.513627875e-01f, -2.182815596e-02f },
-    { -5.483417574e-02f, +7.283776481e-01f, +3.516923111e-01f, -2.185662829e-02f },
-    { -5.481251539e-02f, +7.280574796e-01f, +3.520219162e-01f, -2.188511610e-02f },
-    { -5.479081718e-02f, +7.277372036e-01f, +3.523516026e-01f, -2.191361938e-02f },
-    { -5.476908119e-02f, +7.274168203e-01f, +3.526813701e-01f, -2.194213809e-02f },
-    { -5.474730748e-02f, +7.270963298e-01f, +3.530112187e-01f, -2.197067223e-02f },
-    { -5.472549614e-02f, +7.267757323e-01f, +3.533411482e-01f, -2.199922176e-02f },
-    { -5.470364724e-02f, +7.264550280e-01f, +3.536711584e-01f, -2.202778667e-02f },
-    { -5.468176084e-02f, +7.261342170e-01f, +3.540012493e-01f, -2.205636694e-02f },
-    { -5.465983703e-02f, +7.258132997e-01f, +3.543314207e-01f, -2.208496254e-02f },
-    { -5.463787587e-02f, +7.254922761e-01f, +3.546616725e-01f, -2.211357346e-02f },
-    { -5.461587745e-02f, +7.251711464e-01f, +3.549920045e-01f, -2.214219967e-02f },
-    { -5.459384183e-02f, +7.248499108e-01f, +3.553224165e-01f, -2.217084115e-02f },
-    { -5.457176909e-02f, +7.245285695e-01f, +3.556529085e-01f, -2.219949788e-02f },
-    { -5.454965931e-02f, +7.242071227e-01f, +3.559834804e-01f, -2.222816984e-02f },
-    { -5.452751254e-02f, +7.238855706e-01f, +3.563141319e-01f, -2.225685701e-02f },
-    { -5.450532888e-02f, +7.235639133e-01f, +3.566448630e-01f, -2.228555936e-02f },
-    { -5.448310839e-02f, +7.232421510e-01f, +3.569756734e-01f, -2.231427688e-02f },
-    { -5.446085115e-02f, +7.229202840e-01f, +3.573065632e-01f, -2.234300954e-02f },
-    { -5.443855722e-02f, +7.225983123e-01f, +3.576375321e-01f, -2.237175733e-02f },
-    { -5.441622669e-02f, +7.222762363e-01f, +3.579685799e-01f, -2.240052021e-02f },
-    { -5.439385962e-02f, +7.219540560e-01f, +3.582997067e-01f, -2.242929816e-02f },
-    { -5.437145610e-02f, +7.216317716e-01f, +3.586309121e-01f, -2.245809118e-02f },
-    { -5.434901618e-02f, +7.213093834e-01f, +3.589621962e-01f, -2.248689923e-02f },
-    { -5.432653996e-02f, +7.209868915e-01f, +3.592935587e-01f, -2.251572229e-02f },
-    { -5.430402749e-02f, +7.206642961e-01f, +3.596249995e-01f, -2.254456034e-02f },
-    { -5.428147885e-02f, +7.203415974e-01f, +3.599565185e-01f, -2.257341336e-02f },
-    { -5.425889412e-02f, +7.200187955e-01f, +3.602881155e-01f, -2.260228132e-02f },
-    { -5.423627337e-02f, +7.196958907e-01f, +3.606197904e-01f, -2.263116421e-02f },
-    { -5.421361667e-02f, +7.193728831e-01f, +3.609515431e-01f, -2.266006200e-02f },
-    { -5.419092410e-02f, +7.190497730e-01f, +3.612833734e-01f, -2.268897467e-02f },
-    { -5.416819572e-02f, +7.187265605e-01f, +3.616152812e-01f, -2.271790220e-02f },
-    { -5.414543161e-02f, +7.184032457e-01f, +3.619472663e-01f, -2.274684456e-02f },
-    { -5.412263185e-02f, +7.180798289e-01f, +3.622793287e-01f, -2.277580174e-02f },
-    { -5.409979650e-02f, +7.177563103e-01f, +3.626114681e-01f, -2.280477371e-02f },
-    { -5.407692564e-02f, +7.174326900e-01f, +3.629436844e-01f, -2.283376044e-02f },
-    { -5.405401935e-02f, +7.171089682e-01f, +3.632759775e-01f, -2.286276192e-02f },
-    { -5.403107768e-02f, +7.167851452e-01f, +3.636083473e-01f, -2.289177812e-02f },
-    { -5.400810073e-02f, +7.164612210e-01f, +3.639407936e-01f, -2.292080903e-02f },
-    { -5.398508856e-02f, +7.161371959e-01f, +3.642733163e-01f, -2.294985461e-02f },
-    { -5.396204124e-02f, +7.158130701e-01f, +3.646059152e-01f, -2.297891485e-02f },
-    { -5.393895884e-02f, +7.154888437e-01f, +3.649385903e-01f, -2.300798972e-02f },
-    { -5.391584144e-02f, +7.151645170e-01f, +3.652713412e-01f, -2.303707919e-02f },
-    { -5.389268911e-02f, +7.148400900e-01f, +3.656041680e-01f, -2.306618326e-02f },
-    { -5.386950193e-02f, +7.145155631e-01f, +3.659370705e-01f, -2.309530189e-02f },
-    { -5.384627996e-02f, +7.141909364e-01f, +3.662700485e-01f, -2.312443506e-02f },
-    { -5.382302328e-02f, +7.138662100e-01f, +3.666031020e-01f, -2.315358275e-02f },
-    { -5.379973196e-02f, +7.135413841e-01f, +3.669362306e-01f, -2.318274493e-02f },
-    { -5.377640607e-02f, +7.132164590e-01f, +3.672694344e-01f, -2.321192159e-02f },
-    { -5.375304569e-02f, +7.128914348e-01f, +3.676027132e-01f, -2.324111270e-02f },
-    { -5.372965088e-02f, +7.125663118e-01f, +3.679360669e-01f, -2.327031823e-02f },
-    { -5.370622173e-02f, +7.122410900e-01f, +3.682694952e-01f, -2.329953816e-02f },
-    { -5.368275829e-02f, +7.119157697e-01f, +3.686029981e-01f, -2.332877247e-02f },
-    { -5.365926065e-02f, +7.115903510e-01f, +3.689365754e-01f, -2.335802114e-02f },
-    { -5.363572888e-02f, +7.112648342e-01f, +3.692702270e-01f, -2.338728414e-02f },
-    { -5.361216304e-02f, +7.109392194e-01f, +3.696039527e-01f, -2.341656145e-02f },
-    { -5.358856321e-02f, +7.106135068e-01f, +3.699377525e-01f, -2.344585305e-02f },
-    { -5.356492947e-02f, +7.102876966e-01f, +3.702716261e-01f, -2.347515891e-02f },
-    { -5.354126188e-02f, +7.099617891e-01f, +3.706055734e-01f, -2.350447901e-02f },
-    { -5.351756051e-02f, +7.096357842e-01f, +3.709395943e-01f, -2.353381332e-02f },
-    { -5.349382545e-02f, +7.093096823e-01f, +3.712736886e-01f, -2.356316182e-02f },
-    { -5.347005675e-02f, +7.089834836e-01f, +3.716078562e-01f, -2.359252450e-02f },
-    { -5.344625449e-02f, +7.086571882e-01f, +3.719420970e-01f, -2.362190131e-02f },
-    { -5.342241875e-02f, +7.083307963e-01f, +3.722764108e-01f, -2.365129225e-02f },
-    { -5.339854959e-02f, +7.080043080e-01f, +3.726107975e-01f, -2.368069728e-02f },
-    { -5.337464709e-02f, +7.076777237e-01f, +3.729452569e-01f, -2.371011639e-02f },
-    { -5.335071132e-02f, +7.073510434e-01f, +3.732797888e-01f, -2.373954954e-02f },
-    { -5.332674235e-02f, +7.070242673e-01f, +3.736143933e-01f, -2.376899672e-02f },
-    { -5.330274025e-02f, +7.066973957e-01f, +3.739490700e-01f, -2.379845790e-02f },
-    { -5.327870509e-02f, +7.063704287e-01f, +3.742838189e-01f, -2.382793305e-02f },
-    { -5.325463695e-02f, +7.060433665e-01f, +3.746186398e-01f, -2.385742216e-02f },
-    { -5.323053590e-02f, +7.057162093e-01f, +3.749535326e-01f, -2.388692520e-02f },
-    { -5.320640200e-02f, +7.053889572e-01f, +3.752884971e-01f, -2.391644214e-02f },
-    { -5.318223533e-02f, +7.050616105e-01f, +3.756235333e-01f, -2.394597296e-02f },
-    { -5.315803596e-02f, +7.047341694e-01f, +3.759586408e-01f, -2.397551763e-02f },
-    { -5.313380397e-02f, +7.044066339e-01f, +3.762938197e-01f, -2.400507614e-02f },
-    { -5.310953941e-02f, +7.040790044e-01f, +3.766290698e-01f, -2.403464845e-02f },
-    { -5.308524237e-02f, +7.037512810e-01f, +3.769643909e-01f, -2.406423454e-02f },
-    { -5.306091292e-02f, +7.034234638e-01f, +3.772997828e-01f, -2.409383439e-02f },
-    { -5.303655112e-02f, +7.030955531e-01f, +3.776352455e-01f, -2.412344797e-02f },
-    { -5.301215705e-02f, +7.027675491e-01f, +3.779707788e-01f, -2.415307527e-02f },
-    { -5.298773078e-02f, +7.024394519e-01f, +3.783063825e-01f, -2.418271624e-02f },
-    { -5.296327238e-02f, +7.021112617e-01f, +3.786420566e-01f, -2.421237087e-02f },
-    { -5.293878193e-02f, +7.017829788e-01f, +3.789778008e-01f, -2.424203914e-02f },
-    { -5.291425948e-02f, +7.014546032e-01f, +3.793136151e-01f, -2.427172102e-02f },
-    { -5.288970511e-02f, +7.011261352e-01f, +3.796494992e-01f, -2.430141648e-02f },
-    { -5.286511890e-02f, +7.007975749e-01f, +3.799854530e-01f, -2.433112550e-02f },
-    { -5.284050092e-02f, +7.004689226e-01f, +3.803214765e-01f, -2.436084805e-02f },
-    { -5.281585123e-02f, +7.001401785e-01f, +3.806575694e-01f, -2.439058412e-02f },
-    { -5.279116991e-02f, +6.998113426e-01f, +3.809937316e-01f, -2.442033366e-02f },
-    { -5.276645702e-02f, +6.994824153e-01f, +3.813299629e-01f, -2.445009667e-02f },
-    { -5.274171264e-02f, +6.991533966e-01f, +3.816662633e-01f, -2.447987311e-02f },
-    { -5.271693684e-02f, +6.988242869e-01f, +3.820026325e-01f, -2.450966296e-02f },
-    { -5.269212969e-02f, +6.984950861e-01f, +3.823390705e-01f, -2.453946619e-02f },
-    { -5.266729126e-02f, +6.981657947e-01f, +3.826755771e-01f, -2.456928278e-02f },
-    { -5.264242161e-02f, +6.978364126e-01f, +3.830121520e-01f, -2.459911271e-02f },
-    { -5.261752083e-02f, +6.975069402e-01f, +3.833487953e-01f, -2.462895594e-02f },
-    { -5.259258898e-02f, +6.971773775e-01f, +3.836855068e-01f, -2.465881245e-02f },
-    { -5.256762613e-02f, +6.968477249e-01f, +3.840222862e-01f, -2.468868221e-02f },
-    { -5.254263236e-02f, +6.965179824e-01f, +3.843591335e-01f, -2.471856521e-02f },
-    { -5.251760772e-02f, +6.961881503e-01f, +3.846960485e-01f, -2.474846141e-02f },
-    { -5.249255230e-02f, +6.958582288e-01f, +3.850330311e-01f, -2.477837080e-02f },
-    { -5.246746616e-02f, +6.955282179e-01f, +3.853700811e-01f, -2.480829333e-02f },
-    { -5.244234938e-02f, +6.951981180e-01f, +3.857071983e-01f, -2.483822900e-02f },
-    { -5.241720201e-02f, +6.948679292e-01f, +3.860443828e-01f, -2.486817776e-02f },
-    { -5.239202415e-02f, +6.945376516e-01f, +3.863816342e-01f, -2.489813960e-02f },
-    { -5.236681584e-02f, +6.942072855e-01f, +3.867189524e-01f, -2.492811449e-02f },
-    { -5.234157717e-02f, +6.938768311e-01f, +3.870563373e-01f, -2.495810241e-02f },
-    { -5.231630820e-02f, +6.935462886e-01f, +3.873937888e-01f, -2.498810332e-02f },
-    { -5.229100900e-02f, +6.932156580e-01f, +3.877313067e-01f, -2.501811720e-02f },
-    { -5.226567965e-02f, +6.928849397e-01f, +3.880688909e-01f, -2.504814403e-02f },
-    { -5.224032022e-02f, +6.925541338e-01f, +3.884065411e-01f, -2.507818379e-02f },
-    { -5.221493076e-02f, +6.922232404e-01f, +3.887442574e-01f, -2.510823643e-02f },
-    { -5.218951136e-02f, +6.918922599e-01f, +3.890820394e-01f, -2.513830194e-02f },
-    { -5.216406208e-02f, +6.915611922e-01f, +3.894198871e-01f, -2.516838029e-02f },
-    { -5.213858300e-02f, +6.912300378e-01f, +3.897578004e-01f, -2.519847146e-02f },
-    { -5.211307417e-02f, +6.908987966e-01f, +3.900957790e-01f, -2.522857541e-02f },
-    { -5.208753568e-02f, +6.905674690e-01f, +3.904338229e-01f, -2.525869212e-02f },
-    { -5.206196759e-02f, +6.902360551e-01f, +3.907719318e-01f, -2.528882157e-02f },
-    { -5.203636997e-02f, +6.899045550e-01f, +3.911101057e-01f, -2.531896373e-02f },
-    { -5.201074290e-02f, +6.895729691e-01f, +3.914483444e-01f, -2.534911857e-02f },
-    { -5.198508643e-02f, +6.892412974e-01f, +3.917866477e-01f, -2.537928607e-02f },
-    { -5.195940064e-02f, +6.889095401e-01f, +3.921250156e-01f, -2.540946619e-02f },
-    { -5.193368560e-02f, +6.885776975e-01f, +3.924634478e-01f, -2.543965891e-02f },
-    { -5.190794138e-02f, +6.882457697e-01f, +3.928019442e-01f, -2.546986421e-02f },
-    { -5.188216805e-02f, +6.879137568e-01f, +3.931405046e-01f, -2.550008206e-02f },
-    { -5.185636568e-02f, +6.875816592e-01f, +3.934791290e-01f, -2.553031243e-02f },
-    { -5.183053433e-02f, +6.872494769e-01f, +3.938178171e-01f, -2.556055529e-02f },
-    { -5.180467408e-02f, +6.869172102e-01f, +3.941565688e-01f, -2.559081062e-02f },
-    { -5.177878499e-02f, +6.865848593e-01f, +3.944953840e-01f, -2.562107838e-02f },
-    { -5.175286714e-02f, +6.862524243e-01f, +3.948342626e-01f, -2.565135856e-02f },
-    { -5.172692059e-02f, +6.859199054e-01f, +3.951732042e-01f, -2.568165113e-02f },
-    { -5.170094541e-02f, +6.855873028e-01f, +3.955122090e-01f, -2.571195605e-02f },
-    { -5.167494167e-02f, +6.852546167e-01f, +3.958512766e-01f, -2.574227331e-02f },
-    { -5.164890945e-02f, +6.849218472e-01f, +3.961904069e-01f, -2.577260287e-02f },
-    { -5.162284880e-02f, +6.845889947e-01f, +3.965295998e-01f, -2.580294470e-02f },
-    { -5.159675980e-02f, +6.842560591e-01f, +3.968688551e-01f, -2.583329878e-02f },
-    { -5.157064252e-02f, +6.839230409e-01f, +3.972081727e-01f, -2.586366508e-02f },
-    { -5.154449702e-02f, +6.835899400e-01f, +3.975475525e-01f, -2.589404358e-02f },
-    { -5.151832338e-02f, +6.832567567e-01f, +3.978869942e-01f, -2.592443425e-02f },
-    { -5.149212166e-02f, +6.829234913e-01f, +3.982264977e-01f, -2.595483705e-02f },
-    { -5.146589193e-02f, +6.825901438e-01f, +3.985660630e-01f, -2.598525196e-02f },
-    { -5.143963427e-02f, +6.822567144e-01f, +3.989056898e-01f, -2.601567895e-02f },
-    { -5.141334873e-02f, +6.819232035e-01f, +3.992453779e-01f, -2.604611800e-02f },
-    { -5.138703539e-02f, +6.815896110e-01f, +3.995851274e-01f, -2.607656908e-02f },
-    { -5.136069431e-02f, +6.812559373e-01f, +3.999249379e-01f, -2.610703216e-02f },
-    { -5.133432558e-02f, +6.809221825e-01f, +4.002648093e-01f, -2.613750720e-02f },
-    { -5.130792924e-02f, +6.805883468e-01f, +4.006047415e-01f, -2.616799420e-02f },
-    { -5.128150537e-02f, +6.802544304e-01f, +4.009447344e-01f, -2.619849310e-02f },
-    { -5.125505405e-02f, +6.799204334e-01f, +4.012847878e-01f, -2.622900390e-02f },
-    { -5.122857533e-02f, +6.795863561e-01f, +4.016249015e-01f, -2.625952655e-02f },
-    { -5.120206929e-02f, +6.792521986e-01f, +4.019650754e-01f, -2.629006103e-02f },
-    { -5.117553600e-02f, +6.789179612e-01f, +4.023053093e-01f, -2.632060732e-02f },
-    { -5.114897551e-02f, +6.785836440e-01f, +4.026456031e-01f, -2.635116538e-02f },
-    { -5.112238791e-02f, +6.782492471e-01f, +4.029859567e-01f, -2.638173519e-02f },
-    { -5.109577326e-02f, +6.779147709e-01f, +4.033263699e-01f, -2.641231671e-02f },
-    { -5.106913162e-02f, +6.775802154e-01f, +4.036668425e-01f, -2.644290992e-02f },
-    { -5.104246307e-02f, +6.772455809e-01f, +4.040073744e-01f, -2.647351480e-02f },
-    { -5.101576767e-02f, +6.769108675e-01f, +4.043479654e-01f, -2.650413130e-02f },
-    { -5.098904550e-02f, +6.765760755e-01f, +4.046886155e-01f, -2.653475941e-02f },
-    { -5.096229661e-02f, +6.762412050e-01f, +4.050293243e-01f, -2.656539910e-02f },
-    { -5.093552108e-02f, +6.759062562e-01f, +4.053700919e-01f, -2.659605033e-02f },
-    { -5.090871897e-02f, +6.755712292e-01f, +4.057109180e-01f, -2.662671308e-02f },
-    { -5.088189036e-02f, +6.752361244e-01f, +4.060518025e-01f, -2.665738731e-02f },
-    { -5.085503531e-02f, +6.749009418e-01f, +4.063927452e-01f, -2.668807301e-02f },
-    { -5.082815388e-02f, +6.745656817e-01f, +4.067337460e-01f, -2.671877013e-02f },
-    { -5.080124615e-02f, +6.742303442e-01f, +4.070748047e-01f, -2.674947866e-02f },
-    { -5.077431218e-02f, +6.738949295e-01f, +4.074159212e-01f, -2.678019856e-02f },
-    { -5.074735205e-02f, +6.735594378e-01f, +4.077570954e-01f, -2.681092981e-02f },
-    { -5.072036581e-02f, +6.732238693e-01f, +4.080983270e-01f, -2.684167237e-02f },
-    { -5.069335353e-02f, +6.728882242e-01f, +4.084396159e-01f, -2.687242621e-02f },
-    { -5.066631529e-02f, +6.725525027e-01f, +4.087809621e-01f, -2.690319131e-02f },
-    { -5.063925115e-02f, +6.722167049e-01f, +4.091223652e-01f, -2.693396764e-02f },
-    { -5.061216118e-02f, +6.718808311e-01f, +4.094638252e-01f, -2.696475516e-02f },
-    { -5.058504544e-02f, +6.715448814e-01f, +4.098053420e-01f, -2.699555385e-02f },
-    { -5.055790401e-02f, +6.712088560e-01f, +4.101469153e-01f, -2.702636369e-02f },
-    { -5.053073694e-02f, +6.708727551e-01f, +4.104885450e-01f, -2.705718463e-02f },
-    { -5.050354431e-02f, +6.705365788e-01f, +4.108302310e-01f, -2.708801665e-02f },
-    { -5.047632619e-02f, +6.702003275e-01f, +4.111719731e-01f, -2.711885972e-02f },
-    { -5.044908263e-02f, +6.698640012e-01f, +4.115137711e-01f, -2.714971381e-02f },
-    { -5.042181372e-02f, +6.695276002e-01f, +4.118556250e-01f, -2.718057889e-02f },
-    { -5.039451951e-02f, +6.691911246e-01f, +4.121975345e-01f, -2.721145493e-02f },
-    { -5.036720007e-02f, +6.688545746e-01f, +4.125394995e-01f, -2.724234191e-02f },
-    { -5.033985546e-02f, +6.685179504e-01f, +4.128815199e-01f, -2.727323979e-02f },
-    { -5.031248577e-02f, +6.681812522e-01f, +4.132235955e-01f, -2.730414853e-02f },
-    { -5.028509105e-02f, +6.678444802e-01f, +4.135657261e-01f, -2.733506812e-02f },
-    { -5.025767136e-02f, +6.675076346e-01f, +4.139079116e-01f, -2.736599852e-02f },
-    { -5.023022678e-02f, +6.671707155e-01f, +4.142501518e-01f, -2.739693971e-02f },
-    { -5.020275738e-02f, +6.668337231e-01f, +4.145924466e-01f, -2.742789164e-02f },
-    { -5.017526321e-02f, +6.664966577e-01f, +4.149347959e-01f, -2.745885430e-02f },
-    { -5.014774435e-02f, +6.661595193e-01f, +4.152771994e-01f, -2.748982764e-02f },
-    { -5.012020087e-02f, +6.658223083e-01f, +4.156196570e-01f, -2.752081165e-02f },
-    { -5.009263282e-02f, +6.654850247e-01f, +4.159621686e-01f, -2.755180629e-02f },
-    { -5.006504027e-02f, +6.651476689e-01f, +4.163047340e-01f, -2.758281153e-02f },
-    { -5.003742330e-02f, +6.648102408e-01f, +4.166473531e-01f, -2.761382734e-02f },
-    { -5.000978197e-02f, +6.644727409e-01f, +4.169900257e-01f, -2.764485368e-02f },
-    { -4.998211634e-02f, +6.641351691e-01f, +4.173327517e-01f, -2.767589054e-02f },
-    { -4.995442649e-02f, +6.637975258e-01f, +4.176755308e-01f, -2.770693788e-02f },
-    { -4.992671247e-02f, +6.634598110e-01f, +4.180183630e-01f, -2.773799566e-02f },
-    { -4.989897435e-02f, +6.631220251e-01f, +4.183612481e-01f, -2.776906386e-02f },
-    { -4.987121220e-02f, +6.627841681e-01f, +4.187041859e-01f, -2.780014245e-02f },
-    { -4.984342609e-02f, +6.624462403e-01f, +4.190471763e-01f, -2.783123139e-02f },
-    { -4.981561608e-02f, +6.621082419e-01f, +4.193902192e-01f, -2.786233066e-02f },
-    { -4.978778224e-02f, +6.617701729e-01f, +4.197333143e-01f, -2.789344022e-02f },
-    { -4.975992463e-02f, +6.614320337e-01f, +4.200764615e-01f, -2.792456005e-02f },
-    { -4.973204333e-02f, +6.610938245e-01f, +4.204196607e-01f, -2.795569010e-02f },
-    { -4.970413838e-02f, +6.607555453e-01f, +4.207629117e-01f, -2.798683036e-02f },
-    { -4.967620987e-02f, +6.604171963e-01f, +4.211062143e-01f, -2.801798079e-02f },
-    { -4.964825786e-02f, +6.600787779e-01f, +4.214495685e-01f, -2.804914136e-02f },
-    { -4.962028241e-02f, +6.597402901e-01f, +4.217929740e-01f, -2.808031203e-02f },
-    { -4.959228359e-02f, +6.594017331e-01f, +4.221364307e-01f, -2.811149279e-02f },
-    { -4.956426147e-02f, +6.590631072e-01f, +4.224799384e-01f, -2.814268358e-02f },
-    { -4.953621610e-02f, +6.587244125e-01f, +4.228234970e-01f, -2.817388439e-02f },
-    { -4.950814756e-02f, +6.583856492e-01f, +4.231671063e-01f, -2.820509519e-02f },
-    { -4.948005591e-02f, +6.580468175e-01f, +4.235107662e-01f, -2.823631593e-02f },
-    { -4.945194122e-02f, +6.577079175e-01f, +4.238544765e-01f, -2.826754660e-02f },
-    { -4.942380356e-02f, +6.573689495e-01f, +4.241982371e-01f, -2.829878715e-02f },
-    { -4.939564297e-02f, +6.570299137e-01f, +4.245420477e-01f, -2.833003756e-02f },
-    { -4.936745955e-02f, +6.566908102e-01f, +4.248859083e-01f, -2.836129779e-02f },
-    { -4.933925334e-02f, +6.563516392e-01f, +4.252298187e-01f, -2.839256782e-02f },
-    { -4.931102441e-02f, +6.560124009e-01f, +4.255737788e-01f, -2.842384761e-02f },
-    { -4.928277284e-02f, +6.556730955e-01f, +4.259177883e-01f, -2.845513713e-02f },
-    { -4.925449868e-02f, +6.553337232e-01f, +4.262618471e-01f, -2.848643635e-02f },
-    { -4.922620200e-02f, +6.549942842e-01f, +4.266059551e-01f, -2.851774523e-02f },
-    { -4.919788286e-02f, +6.546547786e-01f, +4.269501121e-01f, -2.854906375e-02f },
-    { -4.916954133e-02f, +6.543152066e-01f, +4.272943179e-01f, -2.858039187e-02f },
-    { -4.914117748e-02f, +6.539755685e-01f, +4.276385725e-01f, -2.861172956e-02f },
-    { -4.911279137e-02f, +6.536358644e-01f, +4.279828756e-01f, -2.864307678e-02f },
-    { -4.908438306e-02f, +6.532960945e-01f, +4.283272270e-01f, -2.867443352e-02f },
-    { -4.905595262e-02f, +6.529562589e-01f, +4.286716267e-01f, -2.870579972e-02f },
-    { -4.902750012e-02f, +6.526163580e-01f, +4.290160745e-01f, -2.873717537e-02f },
-    { -4.899902562e-02f, +6.522763918e-01f, +4.293605701e-01f, -2.876856043e-02f },
-    { -4.897052918e-02f, +6.519363605e-01f, +4.297051136e-01f, -2.879995486e-02f },
-    { -4.894201087e-02f, +6.515962644e-01f, +4.300497046e-01f, -2.883135864e-02f },
-    { -4.891347075e-02f, +6.512561036e-01f, +4.303943430e-01f, -2.886277173e-02f },
-    { -4.888490889e-02f, +6.509158783e-01f, +4.307390288e-01f, -2.889419410e-02f },
-    { -4.885632535e-02f, +6.505755887e-01f, +4.310837617e-01f, -2.892562571e-02f },
-    { -4.882772020e-02f, +6.502352350e-01f, +4.314285415e-01f, -2.895706654e-02f },
-    { -4.879909350e-02f, +6.498948173e-01f, +4.317733681e-01f, -2.898851656e-02f },
-    { -4.877044532e-02f, +6.495543359e-01f, +4.321182414e-01f, -2.901997572e-02f },
-    { -4.874177572e-02f, +6.492137910e-01f, +4.324631612e-01f, -2.905144399e-02f },
-    { -4.871308476e-02f, +6.488731826e-01f, +4.328081273e-01f, -2.908292135e-02f },
-    { -4.868437251e-02f, +6.485325111e-01f, +4.331531396e-01f, -2.911440776e-02f },
-    { -4.865563904e-02f, +6.481917765e-01f, +4.334981980e-01f, -2.914590319e-02f },
-    { -4.862688440e-02f, +6.478509792e-01f, +4.338433021e-01f, -2.917740760e-02f },
-    { -4.859810867e-02f, +6.475101192e-01f, +4.341884520e-01f, -2.920892096e-02f },
-    { -4.856931190e-02f, +6.471691968e-01f, +4.345336475e-01f, -2.924044325e-02f },
-    { -4.854049416e-02f, +6.468282121e-01f, +4.348788883e-01f, -2.927197441e-02f },
-    { -4.851165552e-02f, +6.464871653e-01f, +4.352241743e-01f, -2.930351443e-02f },
-    { -4.848279603e-02f, +6.461460567e-01f, +4.355695055e-01f, -2.933506327e-02f },
-    { -4.845391577e-02f, +6.458048863e-01f, +4.359148815e-01f, -2.936662089e-02f },
-    { -4.842501479e-02f, +6.454636545e-01f, +4.362603023e-01f, -2.939818727e-02f },
-    { -4.839609316e-02f, +6.451223613e-01f, +4.366057677e-01f, -2.942976236e-02f },
-    { -4.836715094e-02f, +6.447810070e-01f, +4.369512775e-01f, -2.946134614e-02f },
-    { -4.833818821e-02f, +6.444395917e-01f, +4.372968316e-01f, -2.949293857e-02f },
-    { -4.830920501e-02f, +6.440981157e-01f, +4.376424298e-01f, -2.952453962e-02f },
-    { -4.828020142e-02f, +6.437565791e-01f, +4.379880720e-01f, -2.955614925e-02f },
-    { -4.825117750e-02f, +6.434149821e-01f, +4.383337580e-01f, -2.958776743e-02f },
-    { -4.822213331e-02f, +6.430733249e-01f, +4.386794876e-01f, -2.961939414e-02f },
-    { -4.819306891e-02f, +6.427316077e-01f, +4.390252607e-01f, -2.965102932e-02f },
-    { -4.816398438e-02f, +6.423898306e-01f, +4.393710771e-01f, -2.968267296e-02f },
-    { -4.813487976e-02f, +6.420479939e-01f, +4.397169367e-01f, -2.971432501e-02f },
-    { -4.810575513e-02f, +6.417060978e-01f, +4.400628392e-01f, -2.974598544e-02f },
-    { -4.807661056e-02f, +6.413641423e-01f, +4.404087847e-01f, -2.977765422e-02f },
-    { -4.804744609e-02f, +6.410221278e-01f, +4.407547728e-01f, -2.980933131e-02f },
-    { -4.801826180e-02f, +6.406800544e-01f, +4.411008034e-01f, -2.984101669e-02f },
-    { -4.798905775e-02f, +6.403379223e-01f, +4.414468764e-01f, -2.987271031e-02f },
-    { -4.795983400e-02f, +6.399957316e-01f, +4.417929916e-01f, -2.990441214e-02f },
-    { -4.793059062e-02f, +6.396534826e-01f, +4.421391489e-01f, -2.993612215e-02f },
-    { -4.790132766e-02f, +6.393111754e-01f, +4.424853480e-01f, -2.996784030e-02f },
-    { -4.787204520e-02f, +6.389688103e-01f, +4.428315888e-01f, -2.999956656e-02f },
-    { -4.784274329e-02f, +6.386263874e-01f, +4.431778713e-01f, -3.003130090e-02f },
-    { -4.781342200e-02f, +6.382839069e-01f, +4.435241951e-01f, -3.006304328e-02f },
-    { -4.778408139e-02f, +6.379413690e-01f, +4.438705601e-01f, -3.009479366e-02f },
-    { -4.775472152e-02f, +6.375987738e-01f, +4.442169663e-01f, -3.012655201e-02f },
-    { -4.772534246e-02f, +6.372561217e-01f, +4.445634133e-01f, -3.015831830e-02f },
-    { -4.769594427e-02f, +6.369134126e-01f, +4.449099012e-01f, -3.019009249e-02f },
-    { -4.766652701e-02f, +6.365706469e-01f, +4.452564296e-01f, -3.022187454e-02f },
-    { -4.763709074e-02f, +6.362278248e-01f, +4.456029984e-01f, -3.025366443e-02f },
-    { -4.760763553e-02f, +6.358849463e-01f, +4.459496076e-01f, -3.028546212e-02f },
-    { -4.757816144e-02f, +6.355420117e-01f, +4.462962568e-01f, -3.031726757e-02f },
-    { -4.754866853e-02f, +6.351990212e-01f, +4.466429460e-01f, -3.034908075e-02f },
-    { -4.751915687e-02f, +6.348559750e-01f, +4.469896750e-01f, -3.038090162e-02f },
-    { -4.748962651e-02f, +6.345128733e-01f, +4.473364437e-01f, -3.041273015e-02f },
-    { -4.746007752e-02f, +6.341697161e-01f, +4.476832518e-01f, -3.044456630e-02f },
-    { -4.743050997e-02f, +6.338265038e-01f, +4.480300992e-01f, -3.047641003e-02f },
-    { -4.740092391e-02f, +6.334832365e-01f, +4.483769858e-01f, -3.050826133e-02f },
-    { -4.737131940e-02f, +6.331399144e-01f, +4.487239113e-01f, -3.054012013e-02f },
-    { -4.734169651e-02f, +6.327965377e-01f, +4.490708757e-01f, -3.057198642e-02f },
-    { -4.731205530e-02f, +6.324531066e-01f, +4.494178788e-01f, -3.060386016e-02f },
-    { -4.728239584e-02f, +6.321096212e-01f, +4.497649203e-01f, -3.063574131e-02f },
-    { -4.725271818e-02f, +6.317660818e-01f, +4.501120002e-01f, -3.066762983e-02f },
-    { -4.722302238e-02f, +6.314224885e-01f, +4.504591183e-01f, -3.069952570e-02f },
-    { -4.719330852e-02f, +6.310788415e-01f, +4.508062744e-01f, -3.073142887e-02f },
-    { -4.716357665e-02f, +6.307351410e-01f, +4.511534683e-01f, -3.076333930e-02f },
-    { -4.713382682e-02f, +6.303913872e-01f, +4.515006999e-01f, -3.079525698e-02f },
-    { -4.710405912e-02f, +6.300475802e-01f, +4.518479691e-01f, -3.082718185e-02f },
-    { -4.707427359e-02f, +6.297037204e-01f, +4.521952756e-01f, -3.085911388e-02f },
-    { -4.704447029e-02f, +6.293598077e-01f, +4.525426193e-01f, -3.089105304e-02f },
-    { -4.701464930e-02f, +6.290158425e-01f, +4.528900001e-01f, -3.092299929e-02f },
-    { -4.698481067e-02f, +6.286718249e-01f, +4.532374178e-01f, -3.095495259e-02f },
-    { -4.695495446e-02f, +6.283277552e-01f, +4.535848721e-01f, -3.098691291e-02f },
-    { -4.692508073e-02f, +6.279836334e-01f, +4.539323631e-01f, -3.101888022e-02f },
-    { -4.689518955e-02f, +6.276394598e-01f, +4.542798904e-01f, -3.105085447e-02f },
-    { -4.686528098e-02f, +6.272952345e-01f, +4.546274539e-01f, -3.108283564e-02f },
-    { -4.683535507e-02f, +6.269509578e-01f, +4.549750535e-01f, -3.111482367e-02f },
-    { -4.680541190e-02f, +6.266066299e-01f, +4.553226890e-01f, -3.114681855e-02f },
-    { -4.677545152e-02f, +6.262622508e-01f, +4.556703603e-01f, -3.117882023e-02f },
-    { -4.674547399e-02f, +6.259178209e-01f, +4.560180671e-01f, -3.121082867e-02f },
-    { -4.671547937e-02f, +6.255733402e-01f, +4.563658094e-01f, -3.124284384e-02f },
-    { -4.668546773e-02f, +6.252288091e-01f, +4.567135869e-01f, -3.127486571e-02f },
-    { -4.665543913e-02f, +6.248842275e-01f, +4.570613994e-01f, -3.130689423e-02f },
-    { -4.662539362e-02f, +6.245395959e-01f, +4.574092469e-01f, -3.133892937e-02f },
-    { -4.659533127e-02f, +6.241949143e-01f, +4.577571292e-01f, -3.137097110e-02f },
-    { -4.656525215e-02f, +6.238501829e-01f, +4.581050460e-01f, -3.140301937e-02f },
-    { -4.653515630e-02f, +6.235054019e-01f, +4.584529973e-01f, -3.143507415e-02f },
-    { -4.650504379e-02f, +6.231605715e-01f, +4.588009829e-01f, -3.146713541e-02f },
-    { -4.647491468e-02f, +6.228156918e-01f, +4.591490025e-01f, -3.149920310e-02f },
-    { -4.644476904e-02f, +6.224707632e-01f, +4.594970561e-01f, -3.153127720e-02f },
-    { -4.641460692e-02f, +6.221257857e-01f, +4.598451435e-01f, -3.156335765e-02f },
-    { -4.638442839e-02f, +6.217807595e-01f, +4.601932645e-01f, -3.159544443e-02f },
-    { -4.635423350e-02f, +6.214356849e-01f, +4.605414189e-01f, -3.162753750e-02f },
-    { -4.632402231e-02f, +6.210905619e-01f, +4.608896066e-01f, -3.165963682e-02f },
-    { -4.629379489e-02f, +6.207453909e-01f, +4.612378274e-01f, -3.169174236e-02f },
-    { -4.626355130e-02f, +6.204001719e-01f, +4.615860812e-01f, -3.172385407e-02f },
-    { -4.623329159e-02f, +6.200549052e-01f, +4.619343678e-01f, -3.175597193e-02f },
-    { -4.620301584e-02f, +6.197095909e-01f, +4.622826870e-01f, -3.178809589e-02f },
-    { -4.617272409e-02f, +6.193642293e-01f, +4.626310387e-01f, -3.182022591e-02f },
-    { -4.614241641e-02f, +6.190188205e-01f, +4.629794226e-01f, -3.185236196e-02f },
-    { -4.611209285e-02f, +6.186733647e-01f, +4.633278387e-01f, -3.188450401e-02f },
-    { -4.608175349e-02f, +6.183278621e-01f, +4.636762867e-01f, -3.191665200e-02f },
-    { -4.605139837e-02f, +6.179823129e-01f, +4.640247666e-01f, -3.194880592e-02f },
-    { -4.602102757e-02f, +6.176367173e-01f, +4.643732781e-01f, -3.198096571e-02f },
-    { -4.599064113e-02f, +6.172910754e-01f, +4.647218210e-01f, -3.201313134e-02f },
-    { -4.596023912e-02f, +6.169453874e-01f, +4.650703953e-01f, -3.204530278e-02f },
-    { -4.592982160e-02f, +6.165996536e-01f, +4.654190007e-01f, -3.207747998e-02f },
-    { -4.589938863e-02f, +6.162538740e-01f, +4.657676371e-01f, -3.210966291e-02f },
-    { -4.586894027e-02f, +6.159080490e-01f, +4.661163043e-01f, -3.214185153e-02f },
-    { -4.583847658e-02f, +6.155621786e-01f, +4.664650021e-01f, -3.217404580e-02f },
-    { -4.580799762e-02f, +6.152162631e-01f, +4.668137304e-01f, -3.220624568e-02f },
-    { -4.577750344e-02f, +6.148703026e-01f, +4.671624891e-01f, -3.223845114e-02f },
-    { -4.574699411e-02f, +6.145242974e-01f, +4.675112778e-01f, -3.227066214e-02f },
-    { -4.571646969e-02f, +6.141782476e-01f, +4.678600966e-01f, -3.230287864e-02f },
-    { -4.568593024e-02f, +6.138321534e-01f, +4.682089452e-01f, -3.233510060e-02f },
-    { -4.565537582e-02f, +6.134860150e-01f, +4.685578234e-01f, -3.236732799e-02f },
-    { -4.562480648e-02f, +6.131398326e-01f, +4.689067311e-01f, -3.239956076e-02f },
-    { -4.559422228e-02f, +6.127936063e-01f, +4.692556681e-01f, -3.243179888e-02f },
-    { -4.556362330e-02f, +6.124473364e-01f, +4.696046343e-01f, -3.246404230e-02f },
-    { -4.553300957e-02f, +6.121010230e-01f, +4.699536294e-01f, -3.249629100e-02f },
-    { -4.550238117e-02f, +6.117546663e-01f, +4.703026534e-01f, -3.252854493e-02f },
-    { -4.547173816e-02f, +6.114082665e-01f, +4.706517061e-01f, -3.256080405e-02f },
-    { -4.544108058e-02f, +6.110618238e-01f, +4.710007872e-01f, -3.259306833e-02f },
-    { -4.541040851e-02f, +6.107153384e-01f, +4.713498966e-01f, -3.262533772e-02f },
-    { -4.537972200e-02f, +6.103688104e-01f, +4.716990342e-01f, -3.265761219e-02f },
-    { -4.534902111e-02f, +6.100222401e-01f, +4.720481998e-01f, -3.268989170e-02f },
-    { -4.531830590e-02f, +6.096756276e-01f, +4.723973932e-01f, -3.272217621e-02f },
-    { -4.528757642e-02f, +6.093289732e-01f, +4.727466142e-01f, -3.275446568e-02f },
-    { -4.525683274e-02f, +6.089822769e-01f, +4.730958628e-01f, -3.278676008e-02f },
-    { -4.522607492e-02f, +6.086355390e-01f, +4.734451386e-01f, -3.281905935e-02f },
-    { -4.519530301e-02f, +6.082887597e-01f, +4.737944416e-01f, -3.285136347e-02f },
-    { -4.516451708e-02f, +6.079419391e-01f, +4.741437716e-01f, -3.288367240e-02f },
-    { -4.513371718e-02f, +6.075950775e-01f, +4.744931285e-01f, -3.291598609e-02f },
-    { -4.510290336e-02f, +6.072481750e-01f, +4.748425119e-01f, -3.294830451e-02f },
-    { -4.507207570e-02f, +6.069012318e-01f, +4.751919219e-01f, -3.298062762e-02f },
-    { -4.504123425e-02f, +6.065542481e-01f, +4.755413581e-01f, -3.301295538e-02f },
-    { -4.501037906e-02f, +6.062072240e-01f, +4.758908206e-01f, -3.304528775e-02f },
-    { -4.497951020e-02f, +6.058601599e-01f, +4.762403090e-01f, -3.307762468e-02f },
-    { -4.494862772e-02f, +6.055130558e-01f, +4.765898232e-01f, -3.310996615e-02f },
-    { -4.491773168e-02f, +6.051659119e-01f, +4.769393630e-01f, -3.314231211e-02f },
-    { -4.488682214e-02f, +6.048187284e-01f, +4.772889284e-01f, -3.317466252e-02f },
-    { -4.485589916e-02f, +6.044715056e-01f, +4.776385190e-01f, -3.320701734e-02f },
-    { -4.482496280e-02f, +6.041242435e-01f, +4.779881348e-01f, -3.323937653e-02f },
-    { -4.479401311e-02f, +6.037769424e-01f, +4.783377756e-01f, -3.327174006e-02f },
-    { -4.476305016e-02f, +6.034296025e-01f, +4.786874411e-01f, -3.330410788e-02f },
-    { -4.473207400e-02f, +6.030822239e-01f, +4.790371313e-01f, -3.333647996e-02f },
-    { -4.470108468e-02f, +6.027348068e-01f, +4.793868460e-01f, -3.336885624e-02f },
-    { -4.467008228e-02f, +6.023873514e-01f, +4.797365850e-01f, -3.340123671e-02f },
-    { -4.463906683e-02f, +6.020398580e-01f, +4.800863481e-01f, -3.343362130e-02f },
-    { -4.460803842e-02f, +6.016923266e-01f, +4.804361352e-01f, -3.346600999e-02f },
-    { -4.457699708e-02f, +6.013447575e-01f, +4.807859461e-01f, -3.349840273e-02f },
-    { -4.454594288e-02f, +6.009971508e-01f, +4.811357806e-01f, -3.353079949e-02f },
-    { -4.451487588e-02f, +6.006495068e-01f, +4.814856386e-01f, -3.356320022e-02f },
-    { -4.448379613e-02f, +6.003018256e-01f, +4.818355198e-01f, -3.359560488e-02f },
-    { -4.445270370e-02f, +5.999541074e-01f, +4.821854242e-01f, -3.362801344e-02f },
-    { -4.442159863e-02f, +5.996063524e-01f, +4.825353516e-01f, -3.366042585e-02f },
-    { -4.439048099e-02f, +5.992585607e-01f, +4.828853017e-01f, -3.369284207e-02f },
-    { -4.435935084e-02f, +5.989107327e-01f, +4.832352745e-01f, -3.372526206e-02f },
-    { -4.432820823e-02f, +5.985628683e-01f, +4.835852697e-01f, -3.375768579e-02f },
-    { -4.429705321e-02f, +5.982149679e-01f, +4.839352871e-01f, -3.379011321e-02f },
-    { -4.426588586e-02f, +5.978670316e-01f, +4.842853267e-01f, -3.382254427e-02f },
-    { -4.423470622e-02f, +5.975190596e-01f, +4.846353882e-01f, -3.385497895e-02f },
-    { -4.420351435e-02f, +5.971710521e-01f, +4.849854715e-01f, -3.388741720e-02f },
-    { -4.417231031e-02f, +5.968230092e-01f, +4.853355764e-01f, -3.391985897e-02f },
-    { -4.414109415e-02f, +5.964749312e-01f, +4.856857028e-01f, -3.395230423e-02f },
-    { -4.410986594e-02f, +5.961268182e-01f, +4.860358504e-01f, -3.398475294e-02f },
-    { -4.407862573e-02f, +5.957786704e-01f, +4.863860191e-01f, -3.401720506e-02f },
-    { -4.404737358e-02f, +5.954304881e-01f, +4.867362087e-01f, -3.404966054e-02f },
-    { -4.401610954e-02f, +5.950822713e-01f, +4.870864191e-01f, -3.408211934e-02f },
-    { -4.398483367e-02f, +5.947340203e-01f, +4.874366500e-01f, -3.411458143e-02f },
-    { -4.395354603e-02f, +5.943857352e-01f, +4.877869014e-01f, -3.414704676e-02f },
-    { -4.392224667e-02f, +5.940374163e-01f, +4.881371730e-01f, -3.417951529e-02f },
-    { -4.389093566e-02f, +5.936890637e-01f, +4.884874647e-01f, -3.421198698e-02f },
-    { -4.385961304e-02f, +5.933406776e-01f, +4.888377763e-01f, -3.424446179e-02f },
-    { -4.382827888e-02f, +5.929922582e-01f, +4.891881076e-01f, -3.427693968e-02f },
-    { -4.379693323e-02f, +5.926438057e-01f, +4.895384585e-01f, -3.430942060e-02f },
-    { -4.376557615e-02f, +5.922953202e-01f, +4.898888288e-01f, -3.434190452e-02f },
-    { -4.373420769e-02f, +5.919468020e-01f, +4.902392184e-01f, -3.437439139e-02f },
-    { -4.370282792e-02f, +5.915982512e-01f, +4.905896269e-01f, -3.440688117e-02f },
-    { -4.367143688e-02f, +5.912496680e-01f, +4.909400544e-01f, -3.443937382e-02f },
-    { -4.364003464e-02f, +5.909010526e-01f, +4.912905006e-01f, -3.447186930e-02f },
-    { -4.360862124e-02f, +5.905524052e-01f, +4.916409653e-01f, -3.450436756e-02f },
-    { -4.357719676e-02f, +5.902037260e-01f, +4.919914484e-01f, -3.453686857e-02f },
-    { -4.354576123e-02f, +5.898550151e-01f, +4.923419497e-01f, -3.456937229e-02f },
-    { -4.351431473e-02f, +5.895062727e-01f, +4.926924690e-01f, -3.460187866e-02f },
-    { -4.348285730e-02f, +5.891574990e-01f, +4.930430062e-01f, -3.463438766e-02f },
-    { -4.345138900e-02f, +5.888086942e-01f, +4.933935611e-01f, -3.466689923e-02f },
-    { -4.341990989e-02f, +5.884598586e-01f, +4.937441335e-01f, -3.469941334e-02f },
-    { -4.338842003e-02f, +5.881109921e-01f, +4.940947233e-01f, -3.473192994e-02f },
-    { -4.335691946e-02f, +5.877620952e-01f, +4.944453302e-01f, -3.476444900e-02f },
-    { -4.332540825e-02f, +5.874131678e-01f, +4.947959542e-01f, -3.479697046e-02f },
-    { -4.329388645e-02f, +5.870642103e-01f, +4.951465949e-01f, -3.482949429e-02f },
-    { -4.326235411e-02f, +5.867152227e-01f, +4.954972524e-01f, -3.486202044e-02f },
-    { -4.323081130e-02f, +5.863662054e-01f, +4.958479263e-01f, -3.489454888e-02f },
-    { -4.319925807e-02f, +5.860171584e-01f, +4.961986166e-01f, -3.492707956e-02f },
-    { -4.316769447e-02f, +5.856680820e-01f, +4.965493230e-01f, -3.495961243e-02f },
-    { -4.313612056e-02f, +5.853189763e-01f, +4.969000454e-01f, -3.499214746e-02f },
-    { -4.310453640e-02f, +5.849698415e-01f, +4.972507836e-01f, -3.502468461e-02f },
-    { -4.307294203e-02f, +5.846206778e-01f, +4.976015374e-01f, -3.505722382e-02f },
-    { -4.304133752e-02f, +5.842714854e-01f, +4.979523067e-01f, -3.508976506e-02f },
-    { -4.300972293e-02f, +5.839222644e-01f, +4.983030913e-01f, -3.512230829e-02f },
-    { -4.297809830e-02f, +5.835730151e-01f, +4.986538910e-01f, -3.515485346e-02f },
-    { -4.294646369e-02f, +5.832237377e-01f, +4.990047056e-01f, -3.518740053e-02f },
-    { -4.291481916e-02f, +5.828744322e-01f, +4.993555351e-01f, -3.521994946e-02f },
-    { -4.288316476e-02f, +5.825250990e-01f, +4.997063791e-01f, -3.525250020e-02f },
-    { -4.285150055e-02f, +5.821757381e-01f, +5.000572376e-01f, -3.528505271e-02f },
-    { -4.281982659e-02f, +5.818263498e-01f, +5.004081103e-01f, -3.531760695e-02f },
-    { -4.278814292e-02f, +5.814769342e-01f, +5.007589972e-01f, -3.535016287e-02f },
-    { -4.275644960e-02f, +5.811274916e-01f, +5.011098979e-01f, -3.538272044e-02f },
-    { -4.272474669e-02f, +5.807780221e-01f, +5.014608124e-01f, -3.541527960e-02f },
-    { -4.269303424e-02f, +5.804285259e-01f, +5.018117405e-01f, -3.544784032e-02f },
-    { -4.266131231e-02f, +5.800790031e-01f, +5.021626819e-01f, -3.548040255e-02f },
-    { -4.262958096e-02f, +5.797294541e-01f, +5.025136366e-01f, -3.551296626e-02f },
-    { -4.259784023e-02f, +5.793798788e-01f, +5.028646044e-01f, -3.554553138e-02f },
-    { -4.256609018e-02f, +5.790302776e-01f, +5.032155850e-01f, -3.557809789e-02f },
-    { -4.253433087e-02f, +5.786806507e-01f, +5.035665783e-01f, -3.561066574e-02f },
-    { -4.250256235e-02f, +5.783309981e-01f, +5.039175842e-01f, -3.564323489e-02f },
-    { -4.247078467e-02f, +5.779813201e-01f, +5.042686025e-01f, -3.567580528e-02f },
-    { -4.243899790e-02f, +5.776316168e-01f, +5.046196329e-01f, -3.570837689e-02f },
-    { -4.240720208e-02f, +5.772818885e-01f, +5.049706753e-01f, -3.574094966e-02f },
-    { -4.237539726e-02f, +5.769321353e-01f, +5.053217296e-01f, -3.577352355e-02f },
-    { -4.234358351e-02f, +5.765823574e-01f, +5.056727956e-01f, -3.580609851e-02f },
-    { -4.231176088e-02f, +5.762325550e-01f, +5.060238731e-01f, -3.583867451e-02f },
-    { -4.227992942e-02f, +5.758827283e-01f, +5.063749619e-01f, -3.587125150e-02f },
-    { -4.224808919e-02f, +5.755328774e-01f, +5.067260619e-01f, -3.590382944e-02f },
-    { -4.221624023e-02f, +5.751830026e-01f, +5.070771728e-01f, -3.593640828e-02f },
-    { -4.218438261e-02f, +5.748331040e-01f, +5.074282945e-01f, -3.596898797e-02f },
-    { -4.215251638e-02f, +5.744831818e-01f, +5.077794269e-01f, -3.600156848e-02f },
-    { -4.212064159e-02f, +5.741332362e-01f, +5.081305697e-01f, -3.603414976e-02f },
-    { -4.208875830e-02f, +5.737832673e-01f, +5.084817229e-01f, -3.606673176e-02f },
-    { -4.205686655e-02f, +5.734332754e-01f, +5.088328861e-01f, -3.609931444e-02f },
-    { -4.202496641e-02f, +5.730832607e-01f, +5.091840593e-01f, -3.613189776e-02f },
-    { -4.199305793e-02f, +5.727332232e-01f, +5.095352422e-01f, -3.616448168e-02f },
-    { -4.196114116e-02f, +5.723831633e-01f, +5.098864348e-01f, -3.619706614e-02f },
-    { -4.192921615e-02f, +5.720330810e-01f, +5.102376367e-01f, -3.622965110e-02f },
-    { -4.189728297e-02f, +5.716829766e-01f, +5.105888479e-01f, -3.626223652e-02f },
-    { -4.186534165e-02f, +5.713328502e-01f, +5.109400682e-01f, -3.629482236e-02f },
-    { -4.183339226e-02f, +5.709827020e-01f, +5.112912974e-01f, -3.632740857e-02f },
-    { -4.180143485e-02f, +5.706325323e-01f, +5.116425353e-01f, -3.635999510e-02f },
-    { -4.176946947e-02f, +5.702823411e-01f, +5.119937817e-01f, -3.639258191e-02f },
-    { -4.173749618e-02f, +5.699321287e-01f, +5.123450366e-01f, -3.642516896e-02f },
-    { -4.170551503e-02f, +5.695818953e-01f, +5.126962996e-01f, -3.645775620e-02f },
-    { -4.167352607e-02f, +5.692316410e-01f, +5.130475706e-01f, -3.649034358e-02f },
-    { -4.164152936e-02f, +5.688813660e-01f, +5.133988495e-01f, -3.652293107e-02f },
-    { -4.160952494e-02f, +5.685310706e-01f, +5.137501361e-01f, -3.655551861e-02f },
-    { -4.157751288e-02f, +5.681807548e-01f, +5.141014302e-01f, -3.658810617e-02f },
-    { -4.154549322e-02f, +5.678304188e-01f, +5.144527316e-01f, -3.662069369e-02f },
-    { -4.151346602e-02f, +5.674800629e-01f, +5.148040402e-01f, -3.665328113e-02f },
-    { -4.148143133e-02f, +5.671296873e-01f, +5.151553558e-01f, -3.668586844e-02f },
-    { -4.144938921e-02f, +5.667792920e-01f, +5.155066781e-01f, -3.671845559e-02f },
-    { -4.141733970e-02f, +5.664288773e-01f, +5.158580071e-01f, -3.675104252e-02f },
-    { -4.138528287e-02f, +5.660784434e-01f, +5.162093426e-01f, -3.678362919e-02f },
-    { -4.135321875e-02f, +5.657279905e-01f, +5.165606843e-01f, -3.681621556e-02f },
-    { -4.132114741e-02f, +5.653775186e-01f, +5.169120321e-01f, -3.684880158e-02f },
-    { -4.128906890e-02f, +5.650270281e-01f, +5.172633859e-01f, -3.688138720e-02f },
-    { -4.125698327e-02f, +5.646765191e-01f, +5.176147454e-01f, -3.691397237e-02f },
-    { -4.122489058e-02f, +5.643259918e-01f, +5.179661105e-01f, -3.694655706e-02f },
-    { -4.119279087e-02f, +5.639754463e-01f, +5.183174810e-01f, -3.697914122e-02f },
-    { -4.116068419e-02f, +5.636248829e-01f, +5.186688568e-01f, -3.701172480e-02f },
-    { -4.112857061e-02f, +5.632743017e-01f, +5.190202376e-01f, -3.704430775e-02f },
-    { -4.109645017e-02f, +5.629237029e-01f, +5.193716233e-01f, -3.707689003e-02f },
-    { -4.106432293e-02f, +5.625730867e-01f, +5.197230137e-01f, -3.710947160e-02f },
-    { -4.103218893e-02f, +5.622224532e-01f, +5.200744086e-01f, -3.714205241e-02f },
-    { -4.100004824e-02f, +5.618718027e-01f, +5.204258079e-01f, -3.717463240e-02f },
-    { -4.096790089e-02f, +5.615211353e-01f, +5.207772113e-01f, -3.720721154e-02f },
-    { -4.093574695e-02f, +5.611704512e-01f, +5.211286188e-01f, -3.723978979e-02f },
-    { -4.090358647e-02f, +5.608197506e-01f, +5.214800301e-01f, -3.727236708e-02f },
-    { -4.087141949e-02f, +5.604690337e-01f, +5.218314450e-01f, -3.730494338e-02f },
-    { -4.083924608e-02f, +5.601183006e-01f, +5.221828634e-01f, -3.733751865e-02f },
-    { -4.080706628e-02f, +5.597675516e-01f, +5.225342852e-01f, -3.737009283e-02f },
-    { -4.077488014e-02f, +5.594167868e-01f, +5.228857100e-01f, -3.740266587e-02f },
-    { -4.074268771e-02f, +5.590660064e-01f, +5.232371378e-01f, -3.743523774e-02f },
-    { -4.071048906e-02f, +5.587152105e-01f, +5.235885684e-01f, -3.746780839e-02f },
-    { -4.067828422e-02f, +5.583643994e-01f, +5.239400015e-01f, -3.750037777e-02f },
-    { -4.064607325e-02f, +5.580135732e-01f, +5.242914371e-01f, -3.753294582e-02f },
-    { -4.061385621e-02f, +5.576627322e-01f, +5.246428750e-01f, -3.756551252e-02f },
-    { -4.058163314e-02f, +5.573118764e-01f, +5.249943149e-01f, -3.759807780e-02f },
-    { -4.054940409e-02f, +5.569610062e-01f, +5.253457567e-01f, -3.763064163e-02f },
-    { -4.051716913e-02f, +5.566101215e-01f, +5.256972002e-01f, -3.766320395e-02f },
-    { -4.048492829e-02f, +5.562592228e-01f, +5.260486453e-01f, -3.769576473e-02f },
-    { -4.045268163e-02f, +5.559083100e-01f, +5.264000917e-01f, -3.772832390e-02f },
-    { -4.042042920e-02f, +5.555573834e-01f, +5.267515394e-01f, -3.776088143e-02f },
-    { -4.038817105e-02f, +5.552064433e-01f, +5.271029880e-01f, -3.779343727e-02f },
-    { -4.035590724e-02f, +5.548554896e-01f, +5.274544375e-01f, -3.782599137e-02f },
-    { -4.032363781e-02f, +5.545045228e-01f, +5.278058876e-01f, -3.785854369e-02f },
-    { -4.029136282e-02f, +5.541535428e-01f, +5.281573382e-01f, -3.789109417e-02f },
-    { -4.025908231e-02f, +5.538025499e-01f, +5.285087891e-01f, -3.792364277e-02f },
-    { -4.022679634e-02f, +5.534515443e-01f, +5.288602402e-01f, -3.795618945e-02f },
-    { -4.019450496e-02f, +5.531005262e-01f, +5.292116912e-01f, -3.798873415e-02f },
-    { -4.016220822e-02f, +5.527494957e-01f, +5.295631419e-01f, -3.802127683e-02f },
-    { -4.012990617e-02f, +5.523984531e-01f, +5.299145923e-01f, -3.805381745e-02f },
-    { -4.009759887e-02f, +5.520473984e-01f, +5.302660421e-01f, -3.808635594e-02f },
-    { -4.006528635e-02f, +5.516963319e-01f, +5.306174912e-01f, -3.811889228e-02f },
-    { -4.003296867e-02f, +5.513452538e-01f, +5.309689393e-01f, -3.815142640e-02f },
-    { -4.000064589e-02f, +5.509941643e-01f, +5.313203863e-01f, -3.818395826e-02f },
-    { -3.996831805e-02f, +5.506430634e-01f, +5.316718320e-01f, -3.821648782e-02f },
-    { -3.993598521e-02f, +5.502919514e-01f, +5.320232763e-01f, -3.824901502e-02f },
-    { -3.990364741e-02f, +5.499408286e-01f, +5.323747189e-01f, -3.828153982e-02f },
-    { -3.987130471e-02f, +5.495896949e-01f, +5.327261597e-01f, -3.831406217e-02f },
-    { -3.983895715e-02f, +5.492385508e-01f, +5.330775985e-01f, -3.834658202e-02f },
-    { -3.980660479e-02f, +5.488873962e-01f, +5.334290351e-01f, -3.837909933e-02f },
-    { -3.977424767e-02f, +5.485362314e-01f, +5.337804694e-01f, -3.841161404e-02f },
-    { -3.974188585e-02f, +5.481850566e-01f, +5.341319012e-01f, -3.844412612e-02f },
-    { -3.970951938e-02f, +5.478338720e-01f, +5.344833302e-01f, -3.847663550e-02f },
-    { -3.967714830e-02f, +5.474826777e-01f, +5.348347564e-01f, -3.850914215e-02f },
-    { -3.964477267e-02f, +5.471314739e-01f, +5.351861795e-01f, -3.854164601e-02f },
-    { -3.961239253e-02f, +5.467802608e-01f, +5.355375994e-01f, -3.857414703e-02f },
-    { -3.958000795e-02f, +5.464290386e-01f, +5.358890159e-01f, -3.860664518e-02f },
-    { -3.954761896e-02f, +5.460778075e-01f, +5.362404287e-01f, -3.863914039e-02f },
-    { -3.951522561e-02f, +5.457265676e-01f, +5.365918378e-01f, -3.867163263e-02f },
-    { -3.948282796e-02f, +5.453753190e-01f, +5.369432430e-01f, -3.870412184e-02f },
-    { -3.945042606e-02f, +5.450240621e-01f, +5.372946440e-01f, -3.873660797e-02f },
-    { -3.941801995e-02f, +5.446727970e-01f, +5.376460407e-01f, -3.876909098e-02f },
-    { -3.938560969e-02f, +5.443215238e-01f, +5.379974330e-01f, -3.880157082e-02f },
-    { -3.935319533e-02f, +5.439702427e-01f, +5.383488206e-01f, -3.883404743e-02f },
-    { -3.932077690e-02f, +5.436189539e-01f, +5.387002033e-01f, -3.886652078e-02f },
-    { -3.928835448e-02f, +5.432676576e-01f, +5.390515810e-01f, -3.889899081e-02f },
-    { -3.925592809e-02f, +5.429163540e-01f, +5.394029536e-01f, -3.893145747e-02f },
-    { -3.922349780e-02f, +5.425650432e-01f, +5.397543207e-01f, -3.896392071e-02f },
-    { -3.919106365e-02f, +5.422137254e-01f, +5.401056823e-01f, -3.899638049e-02f },
-    { -3.915862569e-02f, +5.418624009e-01f, +5.404570382e-01f, -3.902883675e-02f },
-    { -3.912618397e-02f, +5.415110697e-01f, +5.408083882e-01f, -3.906128945e-02f },
-    { -3.909373854e-02f, +5.411597321e-01f, +5.411597321e-01f, -3.909373854e-02f },
-    { -3.906128945e-02f, +5.408083882e-01f, +5.415110697e-01f, -3.912618397e-02f },
-    { -3.902883675e-02f, +5.404570382e-01f, +5.418624009e-01f, -3.915862569e-02f },
-    { -3.899638049e-02f, +5.401056823e-01f, +5.422137254e-01f, -3.919106365e-02f },
-    { -3.896392071e-02f, +5.397543207e-01f, +5.425650432e-01f, -3.922349780e-02f },
-    { -3.893145747e-02f, +5.394029536e-01f, +5.429163540e-01f, -3.925592809e-02f },
-    { -3.889899081e-02f, +5.390515810e-01f, +5.432676576e-01f, -3.928835448e-02f },
-    { -3.886652078e-02f, +5.387002033e-01f, +5.436189539e-01f, -3.932077690e-02f },
-    { -3.883404743e-02f, +5.383488206e-01f, +5.439702427e-01f, -3.935319533e-02f },
-    { -3.880157082e-02f, +5.379974330e-01f, +5.443215238e-01f, -3.938560969e-02f },
-    { -3.876909098e-02f, +5.376460407e-01f, +5.446727970e-01f, -3.941801995e-02f },
-    { -3.873660797e-02f, +5.372946440e-01f, +5.450240621e-01f, -3.945042606e-02f },
-    { -3.870412184e-02f, +5.369432430e-01f, +5.453753190e-01f, -3.948282796e-02f },
-    { -3.867163263e-02f, +5.365918378e-01f, +5.457265676e-01f, -3.951522561e-02f },
-    { -3.863914039e-02f, +5.362404287e-01f, +5.460778075e-01f, -3.954761896e-02f },
-    { -3.860664518e-02f, +5.358890159e-01f, +5.464290386e-01f, -3.958000795e-02f },
-    { -3.857414703e-02f, +5.355375994e-01f, +5.467802608e-01f, -3.961239253e-02f },
-    { -3.854164601e-02f, +5.351861795e-01f, +5.471314739e-01f, -3.964477267e-02f },
-    { -3.850914215e-02f, +5.348347564e-01f, +5.474826777e-01f, -3.967714830e-02f },
-    { -3.847663550e-02f, +5.344833302e-01f, +5.478338720e-01f, -3.970951938e-02f },
-    { -3.844412612e-02f, +5.341319012e-01f, +5.481850566e-01f, -3.974188585e-02f },
-    { -3.841161404e-02f, +5.337804694e-01f, +5.485362314e-01f, -3.977424767e-02f },
-    { -3.837909933e-02f, +5.334290351e-01f, +5.488873962e-01f, -3.980660479e-02f },
-    { -3.834658202e-02f, +5.330775985e-01f, +5.492385508e-01f, -3.983895715e-02f },
-    { -3.831406217e-02f, +5.327261597e-01f, +5.495896949e-01f, -3.987130471e-02f },
-    { -3.828153982e-02f, +5.323747189e-01f, +5.499408286e-01f, -3.990364741e-02f },
-    { -3.824901502e-02f, +5.320232763e-01f, +5.502919514e-01f, -3.993598521e-02f },
-    { -3.821648782e-02f, +5.316718320e-01f, +5.506430634e-01f, -3.996831805e-02f },
-    { -3.818395826e-02f, +5.313203863e-01f, +5.509941643e-01f, -4.000064589e-02f },
-    { -3.815142640e-02f, +5.309689393e-01f, +5.513452538e-01f, -4.003296867e-02f },
-    { -3.811889228e-02f, +5.306174912e-01f, +5.516963319e-01f, -4.006528635e-02f },
-    { -3.808635594e-02f, +5.302660421e-01f, +5.520473984e-01f, -4.009759887e-02f },
-    { -3.805381745e-02f, +5.299145923e-01f, +5.523984531e-01f, -4.012990617e-02f },
-    { -3.802127683e-02f, +5.295631419e-01f, +5.527494957e-01f, -4.016220822e-02f },
-    { -3.798873415e-02f, +5.292116912e-01f, +5.531005262e-01f, -4.019450496e-02f },
-    { -3.795618945e-02f, +5.288602402e-01f, +5.534515443e-01f, -4.022679634e-02f },
-    { -3.792364277e-02f, +5.285087891e-01f, +5.538025499e-01f, -4.025908231e-02f },
-    { -3.789109417e-02f, +5.281573382e-01f, +5.541535428e-01f, -4.029136282e-02f },
-    { -3.785854369e-02f, +5.278058876e-01f, +5.545045228e-01f, -4.032363781e-02f },
-    { -3.782599137e-02f, +5.274544375e-01f, +5.548554896e-01f, -4.035590724e-02f },
-    { -3.779343727e-02f, +5.271029880e-01f, +5.552064433e-01f, -4.038817105e-02f },
-    { -3.776088143e-02f, +5.267515394e-01f, +5.555573834e-01f, -4.042042920e-02f },
-    { -3.772832390e-02f, +5.264000917e-01f, +5.559083100e-01f, -4.045268163e-02f },
-    { -3.769576473e-02f, +5.260486453e-01f, +5.562592228e-01f, -4.048492829e-02f },
-    { -3.766320395e-02f, +5.256972002e-01f, +5.566101215e-01f, -4.051716913e-02f },
-    { -3.763064163e-02f, +5.253457567e-01f, +5.569610062e-01f, -4.054940409e-02f },
-    { -3.759807780e-02f, +5.249943149e-01f, +5.573118764e-01f, -4.058163314e-02f },
-    { -3.756551252e-02f, +5.246428750e-01f, +5.576627322e-01f, -4.061385621e-02f },
-    { -3.753294582e-02f, +5.242914371e-01f, +5.580135732e-01f, -4.064607325e-02f },
-    { -3.750037777e-02f, +5.239400015e-01f, +5.583643994e-01f, -4.067828422e-02f },
-    { -3.746780839e-02f, +5.235885684e-01f, +5.587152105e-01f, -4.071048906e-02f },
-    { -3.743523774e-02f, +5.232371378e-01f, +5.590660064e-01f, -4.074268771e-02f },
-    { -3.740266587e-02f, +5.228857100e-01f, +5.594167868e-01f, -4.077488014e-02f },
-    { -3.737009283e-02f, +5.225342852e-01f, +5.597675516e-01f, -4.080706628e-02f },
-    { -3.733751865e-02f, +5.221828634e-01f, +5.601183006e-01f, -4.083924608e-02f },
-    { -3.730494338e-02f, +5.218314450e-01f, +5.604690337e-01f, -4.087141949e-02f },
-    { -3.727236708e-02f, +5.214800301e-01f, +5.608197506e-01f, -4.090358647e-02f },
-    { -3.723978979e-02f, +5.211286188e-01f, +5.611704512e-01f, -4.093574695e-02f },
-    { -3.720721154e-02f, +5.207772113e-01f, +5.615211353e-01f, -4.096790089e-02f },
-    { -3.717463240e-02f, +5.204258079e-01f, +5.618718027e-01f, -4.100004824e-02f },
-    { -3.714205241e-02f, +5.200744086e-01f, +5.622224532e-01f, -4.103218893e-02f },
-    { -3.710947160e-02f, +5.197230137e-01f, +5.625730867e-01f, -4.106432293e-02f },
-    { -3.707689003e-02f, +5.193716233e-01f, +5.629237029e-01f, -4.109645017e-02f },
-    { -3.704430775e-02f, +5.190202376e-01f, +5.632743017e-01f, -4.112857061e-02f },
-    { -3.701172480e-02f, +5.186688568e-01f, +5.636248829e-01f, -4.116068419e-02f },
-    { -3.697914122e-02f, +5.183174810e-01f, +5.639754463e-01f, -4.119279087e-02f },
-    { -3.694655706e-02f, +5.179661105e-01f, +5.643259918e-01f, -4.122489058e-02f },
-    { -3.691397237e-02f, +5.176147454e-01f, +5.646765191e-01f, -4.125698327e-02f },
-    { -3.688138720e-02f, +5.172633859e-01f, +5.650270281e-01f, -4.128906890e-02f },
-    { -3.684880158e-02f, +5.169120321e-01f, +5.653775186e-01f, -4.132114741e-02f },
-    { -3.681621556e-02f, +5.165606843e-01f, +5.657279905e-01f, -4.135321875e-02f },
-    { -3.678362919e-02f, +5.162093426e-01f, +5.660784434e-01f, -4.138528287e-02f },
-    { -3.675104252e-02f, +5.158580071e-01f, +5.664288773e-01f, -4.141733970e-02f },
-    { -3.671845559e-02f, +5.155066781e-01f, +5.667792920e-01f, -4.144938921e-02f },
-    { -3.668586844e-02f, +5.151553558e-01f, +5.671296873e-01f, -4.148143133e-02f },
-    { -3.665328113e-02f, +5.148040402e-01f, +5.674800629e-01f, -4.151346602e-02f },
-    { -3.662069369e-02f, +5.144527316e-01f, +5.678304188e-01f, -4.154549322e-02f },
-    { -3.658810617e-02f, +5.141014302e-01f, +5.681807548e-01f, -4.157751288e-02f },
-    { -3.655551861e-02f, +5.137501361e-01f, +5.685310706e-01f, -4.160952494e-02f },
-    { -3.652293107e-02f, +5.133988495e-01f, +5.688813660e-01f, -4.164152936e-02f },
-    { -3.649034358e-02f, +5.130475706e-01f, +5.692316410e-01f, -4.167352607e-02f },
-    { -3.645775620e-02f, +5.126962996e-01f, +5.695818953e-01f, -4.170551503e-02f },
-    { -3.642516896e-02f, +5.123450366e-01f, +5.699321287e-01f, -4.173749618e-02f },
-    { -3.639258191e-02f, +5.119937817e-01f, +5.702823411e-01f, -4.176946947e-02f },
-    { -3.635999510e-02f, +5.116425353e-01f, +5.706325323e-01f, -4.180143485e-02f },
-    { -3.632740857e-02f, +5.112912974e-01f, +5.709827020e-01f, -4.183339226e-02f },
-    { -3.629482236e-02f, +5.109400682e-01f, +5.713328502e-01f, -4.186534165e-02f },
-    { -3.626223652e-02f, +5.105888479e-01f, +5.716829766e-01f, -4.189728297e-02f },
-    { -3.622965110e-02f, +5.102376367e-01f, +5.720330810e-01f, -4.192921615e-02f },
-    { -3.619706614e-02f, +5.098864348e-01f, +5.723831633e-01f, -4.196114116e-02f },
-    { -3.616448168e-02f, +5.095352422e-01f, +5.727332232e-01f, -4.199305793e-02f },
-    { -3.613189776e-02f, +5.091840593e-01f, +5.730832607e-01f, -4.202496641e-02f },
-    { -3.609931444e-02f, +5.088328861e-01f, +5.734332754e-01f, -4.205686655e-02f },
-    { -3.606673176e-02f, +5.084817229e-01f, +5.737832673e-01f, -4.208875830e-02f },
-    { -3.603414976e-02f, +5.081305697e-01f, +5.741332362e-01f, -4.212064159e-02f },
-    { -3.600156848e-02f, +5.077794269e-01f, +5.744831818e-01f, -4.215251638e-02f },
-    { -3.596898797e-02f, +5.074282945e-01f, +5.748331040e-01f, -4.218438261e-02f },
-    { -3.593640828e-02f, +5.070771728e-01f, +5.751830026e-01f, -4.221624023e-02f },
-    { -3.590382944e-02f, +5.067260619e-01f, +5.755328774e-01f, -4.224808919e-02f },
-    { -3.587125150e-02f, +5.063749619e-01f, +5.758827283e-01f, -4.227992942e-02f },
-    { -3.583867451e-02f, +5.060238731e-01f, +5.762325550e-01f, -4.231176088e-02f },
-    { -3.580609851e-02f, +5.056727956e-01f, +5.765823574e-01f, -4.234358351e-02f },
-    { -3.577352355e-02f, +5.053217296e-01f, +5.769321353e-01f, -4.237539726e-02f },
-    { -3.574094966e-02f, +5.049706753e-01f, +5.772818885e-01f, -4.240720208e-02f },
-    { -3.570837689e-02f, +5.046196329e-01f, +5.776316168e-01f, -4.243899790e-02f },
-    { -3.567580528e-02f, +5.042686025e-01f, +5.779813201e-01f, -4.247078467e-02f },
-    { -3.564323489e-02f, +5.039175842e-01f, +5.783309981e-01f, -4.250256235e-02f },
-    { -3.561066574e-02f, +5.035665783e-01f, +5.786806507e-01f, -4.253433087e-02f },
-    { -3.557809789e-02f, +5.032155850e-01f, +5.790302776e-01f, -4.256609018e-02f },
-    { -3.554553138e-02f, +5.028646044e-01f, +5.793798788e-01f, -4.259784023e-02f },
-    { -3.551296626e-02f, +5.025136366e-01f, +5.797294541e-01f, -4.262958096e-02f },
-    { -3.548040255e-02f, +5.021626819e-01f, +5.800790031e-01f, -4.266131231e-02f },
-    { -3.544784032e-02f, +5.018117405e-01f, +5.804285259e-01f, -4.269303424e-02f },
-    { -3.541527960e-02f, +5.014608124e-01f, +5.807780221e-01f, -4.272474669e-02f },
-    { -3.538272044e-02f, +5.011098979e-01f, +5.811274916e-01f, -4.275644960e-02f },
-    { -3.535016287e-02f, +5.007589972e-01f, +5.814769342e-01f, -4.278814292e-02f },
-    { -3.531760695e-02f, +5.004081103e-01f, +5.818263498e-01f, -4.281982659e-02f },
-    { -3.528505271e-02f, +5.000572376e-01f, +5.821757381e-01f, -4.285150055e-02f },
-    { -3.525250020e-02f, +4.997063791e-01f, +5.825250990e-01f, -4.288316476e-02f },
-    { -3.521994946e-02f, +4.993555351e-01f, +5.828744322e-01f, -4.291481916e-02f },
-    { -3.518740053e-02f, +4.990047056e-01f, +5.832237377e-01f, -4.294646369e-02f },
-    { -3.515485346e-02f, +4.986538910e-01f, +5.835730151e-01f, -4.297809830e-02f },
-    { -3.512230829e-02f, +4.983030913e-01f, +5.839222644e-01f, -4.300972293e-02f },
-    { -3.508976506e-02f, +4.979523067e-01f, +5.842714854e-01f, -4.304133752e-02f },
-    { -3.505722382e-02f, +4.976015374e-01f, +5.846206778e-01f, -4.307294203e-02f },
-    { -3.502468461e-02f, +4.972507836e-01f, +5.849698415e-01f, -4.310453640e-02f },
-    { -3.499214746e-02f, +4.969000454e-01f, +5.853189763e-01f, -4.313612056e-02f },
-    { -3.495961243e-02f, +4.965493230e-01f, +5.856680820e-01f, -4.316769447e-02f },
-    { -3.492707956e-02f, +4.961986166e-01f, +5.860171584e-01f, -4.319925807e-02f },
-    { -3.489454888e-02f, +4.958479263e-01f, +5.863662054e-01f, -4.323081130e-02f },
-    { -3.486202044e-02f, +4.954972524e-01f, +5.867152227e-01f, -4.326235411e-02f },
-    { -3.482949429e-02f, +4.951465949e-01f, +5.870642103e-01f, -4.329388645e-02f },
-    { -3.479697046e-02f, +4.947959542e-01f, +5.874131678e-01f, -4.332540825e-02f },
-    { -3.476444900e-02f, +4.944453302e-01f, +5.877620952e-01f, -4.335691946e-02f },
-    { -3.473192994e-02f, +4.940947233e-01f, +5.881109921e-01f, -4.338842003e-02f },
-    { -3.469941334e-02f, +4.937441335e-01f, +5.884598586e-01f, -4.341990989e-02f },
-    { -3.466689923e-02f, +4.933935611e-01f, +5.888086942e-01f, -4.345138900e-02f },
-    { -3.463438766e-02f, +4.930430062e-01f, +5.891574990e-01f, -4.348285730e-02f },
-    { -3.460187866e-02f, +4.926924690e-01f, +5.895062727e-01f, -4.351431473e-02f },
-    { -3.456937229e-02f, +4.923419497e-01f, +5.898550151e-01f, -4.354576123e-02f },
-    { -3.453686857e-02f, +4.919914484e-01f, +5.902037260e-01f, -4.357719676e-02f },
-    { -3.450436756e-02f, +4.916409653e-01f, +5.905524052e-01f, -4.360862124e-02f },
-    { -3.447186930e-02f, +4.912905006e-01f, +5.909010526e-01f, -4.364003464e-02f },
-    { -3.443937382e-02f, +4.909400544e-01f, +5.912496680e-01f, -4.367143688e-02f },
-    { -3.440688117e-02f, +4.905896269e-01f, +5.915982512e-01f, -4.370282792e-02f },
-    { -3.437439139e-02f, +4.902392184e-01f, +5.919468020e-01f, -4.373420769e-02f },
-    { -3.434190452e-02f, +4.898888288e-01f, +5.922953202e-01f, -4.376557615e-02f },
-    { -3.430942060e-02f, +4.895384585e-01f, +5.926438057e-01f, -4.379693323e-02f },
-    { -3.427693968e-02f, +4.891881076e-01f, +5.929922582e-01f, -4.382827888e-02f },
-    { -3.424446179e-02f, +4.888377763e-01f, +5.933406776e-01f, -4.385961304e-02f },
-    { -3.421198698e-02f, +4.884874647e-01f, +5.936890637e-01f, -4.389093566e-02f },
-    { -3.417951529e-02f, +4.881371730e-01f, +5.940374163e-01f, -4.392224667e-02f },
-    { -3.414704676e-02f, +4.877869014e-01f, +5.943857352e-01f, -4.395354603e-02f },
-    { -3.411458143e-02f, +4.874366500e-01f, +5.947340203e-01f, -4.398483367e-02f },
-    { -3.408211934e-02f, +4.870864191e-01f, +5.950822713e-01f, -4.401610954e-02f },
-    { -3.404966054e-02f, +4.867362087e-01f, +5.954304881e-01f, -4.404737358e-02f },
-    { -3.401720506e-02f, +4.863860191e-01f, +5.957786704e-01f, -4.407862573e-02f },
-    { -3.398475294e-02f, +4.860358504e-01f, +5.961268182e-01f, -4.410986594e-02f },
-    { -3.395230423e-02f, +4.856857028e-01f, +5.964749312e-01f, -4.414109415e-02f },
-    { -3.391985897e-02f, +4.853355764e-01f, +5.968230092e-01f, -4.417231031e-02f },
-    { -3.388741720e-02f, +4.849854715e-01f, +5.971710521e-01f, -4.420351435e-02f },
-    { -3.385497895e-02f, +4.846353882e-01f, +5.975190596e-01f, -4.423470622e-02f },
-    { -3.382254427e-02f, +4.842853267e-01f, +5.978670316e-01f, -4.426588586e-02f },
-    { -3.379011321e-02f, +4.839352871e-01f, +5.982149679e-01f, -4.429705321e-02f },
-    { -3.375768579e-02f, +4.835852697e-01f, +5.985628683e-01f, -4.432820823e-02f },
-    { -3.372526206e-02f, +4.832352745e-01f, +5.989107327e-01f, -4.435935084e-02f },
-    { -3.369284207e-02f, +4.828853017e-01f, +5.992585607e-01f, -4.439048099e-02f },
-    { -3.366042585e-02f, +4.825353516e-01f, +5.996063524e-01f, -4.442159863e-02f },
-    { -3.362801344e-02f, +4.821854242e-01f, +5.999541074e-01f, -4.445270370e-02f },
-    { -3.359560488e-02f, +4.818355198e-01f, +6.003018256e-01f, -4.448379613e-02f },
-    { -3.356320022e-02f, +4.814856386e-01f, +6.006495068e-01f, -4.451487588e-02f },
-    { -3.353079949e-02f, +4.811357806e-01f, +6.009971508e-01f, -4.454594288e-02f },
-    { -3.349840273e-02f, +4.807859461e-01f, +6.013447575e-01f, -4.457699708e-02f },
-    { -3.346600999e-02f, +4.804361352e-01f, +6.016923266e-01f, -4.460803842e-02f },
-    { -3.343362130e-02f, +4.800863481e-01f, +6.020398580e-01f, -4.463906683e-02f },
-    { -3.340123671e-02f, +4.797365850e-01f, +6.023873514e-01f, -4.467008228e-02f },
-    { -3.336885624e-02f, +4.793868460e-01f, +6.027348068e-01f, -4.470108468e-02f },
-    { -3.333647996e-02f, +4.790371313e-01f, +6.030822239e-01f, -4.473207400e-02f },
-    { -3.330410788e-02f, +4.786874411e-01f, +6.034296025e-01f, -4.476305016e-02f },
-    { -3.327174006e-02f, +4.783377756e-01f, +6.037769424e-01f, -4.479401311e-02f },
-    { -3.323937653e-02f, +4.779881348e-01f, +6.041242435e-01f, -4.482496280e-02f },
-    { -3.320701734e-02f, +4.776385190e-01f, +6.044715056e-01f, -4.485589916e-02f },
-    { -3.317466252e-02f, +4.772889284e-01f, +6.048187284e-01f, -4.488682214e-02f },
-    { -3.314231211e-02f, +4.769393630e-01f, +6.051659119e-01f, -4.491773168e-02f },
-    { -3.310996615e-02f, +4.765898232e-01f, +6.055130558e-01f, -4.494862772e-02f },
-    { -3.307762468e-02f, +4.762403090e-01f, +6.058601599e-01f, -4.497951020e-02f },
-    { -3.304528775e-02f, +4.758908206e-01f, +6.062072240e-01f, -4.501037906e-02f },
-    { -3.301295538e-02f, +4.755413581e-01f, +6.065542481e-01f, -4.504123425e-02f },
-    { -3.298062762e-02f, +4.751919219e-01f, +6.069012318e-01f, -4.507207570e-02f },
-    { -3.294830451e-02f, +4.748425119e-01f, +6.072481750e-01f, -4.510290336e-02f },
-    { -3.291598609e-02f, +4.744931285e-01f, +6.075950775e-01f, -4.513371718e-02f },
-    { -3.288367240e-02f, +4.741437716e-01f, +6.079419391e-01f, -4.516451708e-02f },
-    { -3.285136347e-02f, +4.737944416e-01f, +6.082887597e-01f, -4.519530301e-02f },
-    { -3.281905935e-02f, +4.734451386e-01f, +6.086355390e-01f, -4.522607492e-02f },
-    { -3.278676008e-02f, +4.730958628e-01f, +6.089822769e-01f, -4.525683274e-02f },
-    { -3.275446568e-02f, +4.727466142e-01f, +6.093289732e-01f, -4.528757642e-02f },
-    { -3.272217621e-02f, +4.723973932e-01f, +6.096756276e-01f, -4.531830590e-02f },
-    { -3.268989170e-02f, +4.720481998e-01f, +6.100222401e-01f, -4.534902111e-02f },
-    { -3.265761219e-02f, +4.716990342e-01f, +6.103688104e-01f, -4.537972200e-02f },
-    { -3.262533772e-02f, +4.713498966e-01f, +6.107153384e-01f, -4.541040851e-02f },
-    { -3.259306833e-02f, +4.710007872e-01f, +6.110618238e-01f, -4.544108058e-02f },
-    { -3.256080405e-02f, +4.706517061e-01f, +6.114082665e-01f, -4.547173816e-02f },
-    { -3.252854493e-02f, +4.703026534e-01f, +6.117546663e-01f, -4.550238117e-02f },
-    { -3.249629100e-02f, +4.699536294e-01f, +6.121010230e-01f, -4.553300957e-02f },
-    { -3.246404230e-02f, +4.696046343e-01f, +6.124473364e-01f, -4.556362330e-02f },
-    { -3.243179888e-02f, +4.692556681e-01f, +6.127936063e-01f, -4.559422228e-02f },
-    { -3.239956076e-02f, +4.689067311e-01f, +6.131398326e-01f, -4.562480648e-02f },
-    { -3.236732799e-02f, +4.685578234e-01f, +6.134860150e-01f, -4.565537582e-02f },
-    { -3.233510060e-02f, +4.682089452e-01f, +6.138321534e-01f, -4.568593024e-02f },
-    { -3.230287864e-02f, +4.678600966e-01f, +6.141782476e-01f, -4.571646969e-02f },
-    { -3.227066214e-02f, +4.675112778e-01f, +6.145242974e-01f, -4.574699411e-02f },
-    { -3.223845114e-02f, +4.671624891e-01f, +6.148703026e-01f, -4.577750344e-02f },
-    { -3.220624568e-02f, +4.668137304e-01f, +6.152162631e-01f, -4.580799762e-02f },
-    { -3.217404580e-02f, +4.664650021e-01f, +6.155621786e-01f, -4.583847658e-02f },
-    { -3.214185153e-02f, +4.661163043e-01f, +6.159080490e-01f, -4.586894027e-02f },
-    { -3.210966291e-02f, +4.657676371e-01f, +6.162538740e-01f, -4.589938863e-02f },
-    { -3.207747998e-02f, +4.654190007e-01f, +6.165996536e-01f, -4.592982160e-02f },
-    { -3.204530278e-02f, +4.650703953e-01f, +6.169453874e-01f, -4.596023912e-02f },
-    { -3.201313134e-02f, +4.647218210e-01f, +6.172910754e-01f, -4.599064113e-02f },
-    { -3.198096571e-02f, +4.643732781e-01f, +6.176367173e-01f, -4.602102757e-02f },
-    { -3.194880592e-02f, +4.640247666e-01f, +6.179823129e-01f, -4.605139837e-02f },
-    { -3.191665200e-02f, +4.636762867e-01f, +6.183278621e-01f, -4.608175349e-02f },
-    { -3.188450401e-02f, +4.633278387e-01f, +6.186733647e-01f, -4.611209285e-02f },
-    { -3.185236196e-02f, +4.629794226e-01f, +6.190188205e-01f, -4.614241641e-02f },
-    { -3.182022591e-02f, +4.626310387e-01f, +6.193642293e-01f, -4.617272409e-02f },
-    { -3.178809589e-02f, +4.622826870e-01f, +6.197095909e-01f, -4.620301584e-02f },
-    { -3.175597193e-02f, +4.619343678e-01f, +6.200549052e-01f, -4.623329159e-02f },
-    { -3.172385407e-02f, +4.615860812e-01f, +6.204001719e-01f, -4.626355130e-02f },
-    { -3.169174236e-02f, +4.612378274e-01f, +6.207453909e-01f, -4.629379489e-02f },
-    { -3.165963682e-02f, +4.608896066e-01f, +6.210905619e-01f, -4.632402231e-02f },
-    { -3.162753750e-02f, +4.605414189e-01f, +6.214356849e-01f, -4.635423350e-02f },
-    { -3.159544443e-02f, +4.601932645e-01f, +6.217807595e-01f, -4.638442839e-02f },
-    { -3.156335765e-02f, +4.598451435e-01f, +6.221257857e-01f, -4.641460692e-02f },
-    { -3.153127720e-02f, +4.594970561e-01f, +6.224707632e-01f, -4.644476904e-02f },
-    { -3.149920310e-02f, +4.591490025e-01f, +6.228156918e-01f, -4.647491468e-02f },
-    { -3.146713541e-02f, +4.588009829e-01f, +6.231605715e-01f, -4.650504379e-02f },
-    { -3.143507415e-02f, +4.584529973e-01f, +6.235054019e-01f, -4.653515630e-02f },
-    { -3.140301937e-02f, +4.581050460e-01f, +6.238501829e-01f, -4.656525215e-02f },
-    { -3.137097110e-02f, +4.577571292e-01f, +6.241949143e-01f, -4.659533127e-02f },
-    { -3.133892937e-02f, +4.574092469e-01f, +6.245395959e-01f, -4.662539362e-02f },
-    { -3.130689423e-02f, +4.570613994e-01f, +6.248842275e-01f, -4.665543913e-02f },
-    { -3.127486571e-02f, +4.567135869e-01f, +6.252288091e-01f, -4.668546773e-02f },
-    { -3.124284384e-02f, +4.563658094e-01f, +6.255733402e-01f, -4.671547937e-02f },
-    { -3.121082867e-02f, +4.560180671e-01f, +6.259178209e-01f, -4.674547399e-02f },
-    { -3.117882023e-02f, +4.556703603e-01f, +6.262622508e-01f, -4.677545152e-02f },
-    { -3.114681855e-02f, +4.553226890e-01f, +6.266066299e-01f, -4.680541190e-02f },
-    { -3.111482367e-02f, +4.549750535e-01f, +6.269509578e-01f, -4.683535507e-02f },
-    { -3.108283564e-02f, +4.546274539e-01f, +6.272952345e-01f, -4.686528098e-02f },
-    { -3.105085447e-02f, +4.542798904e-01f, +6.276394598e-01f, -4.689518955e-02f },
-    { -3.101888022e-02f, +4.539323631e-01f, +6.279836334e-01f, -4.692508073e-02f },
-    { -3.098691291e-02f, +4.535848721e-01f, +6.283277552e-01f, -4.695495446e-02f },
-    { -3.095495259e-02f, +4.532374178e-01f, +6.286718249e-01f, -4.698481067e-02f },
-    { -3.092299929e-02f, +4.528900001e-01f, +6.290158425e-01f, -4.701464930e-02f },
-    { -3.089105304e-02f, +4.525426193e-01f, +6.293598077e-01f, -4.704447029e-02f },
-    { -3.085911388e-02f, +4.521952756e-01f, +6.297037204e-01f, -4.707427359e-02f },
-    { -3.082718185e-02f, +4.518479691e-01f, +6.300475802e-01f, -4.710405912e-02f },
-    { -3.079525698e-02f, +4.515006999e-01f, +6.303913872e-01f, -4.713382682e-02f },
-    { -3.076333930e-02f, +4.511534683e-01f, +6.307351410e-01f, -4.716357665e-02f },
-    { -3.073142887e-02f, +4.508062744e-01f, +6.310788415e-01f, -4.719330852e-02f },
-    { -3.069952570e-02f, +4.504591183e-01f, +6.314224885e-01f, -4.722302238e-02f },
-    { -3.066762983e-02f, +4.501120002e-01f, +6.317660818e-01f, -4.725271818e-02f },
-    { -3.063574131e-02f, +4.497649203e-01f, +6.321096212e-01f, -4.728239584e-02f },
-    { -3.060386016e-02f, +4.494178788e-01f, +6.324531066e-01f, -4.731205530e-02f },
-    { -3.057198642e-02f, +4.490708757e-01f, +6.327965377e-01f, -4.734169651e-02f },
-    { -3.054012013e-02f, +4.487239113e-01f, +6.331399144e-01f, -4.737131940e-02f },
-    { -3.050826133e-02f, +4.483769858e-01f, +6.334832365e-01f, -4.740092391e-02f },
-    { -3.047641003e-02f, +4.480300992e-01f, +6.338265038e-01f, -4.743050997e-02f },
-    { -3.044456630e-02f, +4.476832518e-01f, +6.341697161e-01f, -4.746007752e-02f },
-    { -3.041273015e-02f, +4.473364437e-01f, +6.345128733e-01f, -4.748962651e-02f },
-    { -3.038090162e-02f, +4.469896750e-01f, +6.348559750e-01f, -4.751915687e-02f },
-    { -3.034908075e-02f, +4.466429460e-01f, +6.351990212e-01f, -4.754866853e-02f },
-    { -3.031726757e-02f, +4.462962568e-01f, +6.355420117e-01f, -4.757816144e-02f },
-    { -3.028546212e-02f, +4.459496076e-01f, +6.358849463e-01f, -4.760763553e-02f },
-    { -3.025366443e-02f, +4.456029984e-01f, +6.362278248e-01f, -4.763709074e-02f },
-    { -3.022187454e-02f, +4.452564296e-01f, +6.365706469e-01f, -4.766652701e-02f },
-    { -3.019009249e-02f, +4.449099012e-01f, +6.369134126e-01f, -4.769594427e-02f },
-    { -3.015831830e-02f, +4.445634133e-01f, +6.372561217e-01f, -4.772534246e-02f },
-    { -3.012655201e-02f, +4.442169663e-01f, +6.375987738e-01f, -4.775472152e-02f },
-    { -3.009479366e-02f, +4.438705601e-01f, +6.379413690e-01f, -4.778408139e-02f },
-    { -3.006304328e-02f, +4.435241951e-01f, +6.382839069e-01f, -4.781342200e-02f },
-    { -3.003130090e-02f, +4.431778713e-01f, +6.386263874e-01f, -4.784274329e-02f },
-    { -2.999956656e-02f, +4.428315888e-01f, +6.389688103e-01f, -4.787204520e-02f },
-    { -2.996784030e-02f, +4.424853480e-01f, +6.393111754e-01f, -4.790132766e-02f },
-    { -2.993612215e-02f, +4.421391489e-01f, +6.396534826e-01f, -4.793059062e-02f },
-    { -2.990441214e-02f, +4.417929916e-01f, +6.399957316e-01f, -4.795983400e-02f },
-    { -2.987271031e-02f, +4.414468764e-01f, +6.403379223e-01f, -4.798905775e-02f },
-    { -2.984101669e-02f, +4.411008034e-01f, +6.406800544e-01f, -4.801826180e-02f },
-    { -2.980933131e-02f, +4.407547728e-01f, +6.410221278e-01f, -4.804744609e-02f },
-    { -2.977765422e-02f, +4.404087847e-01f, +6.413641423e-01f, -4.807661056e-02f },
-    { -2.974598544e-02f, +4.400628392e-01f, +6.417060978e-01f, -4.810575513e-02f },
-    { -2.971432501e-02f, +4.397169367e-01f, +6.420479939e-01f, -4.813487976e-02f },
-    { -2.968267296e-02f, +4.393710771e-01f, +6.423898306e-01f, -4.816398438e-02f },
-    { -2.965102932e-02f, +4.390252607e-01f, +6.427316077e-01f, -4.819306891e-02f },
-    { -2.961939414e-02f, +4.386794876e-01f, +6.430733249e-01f, -4.822213331e-02f },
-    { -2.958776743e-02f, +4.383337580e-01f, +6.434149821e-01f, -4.825117750e-02f },
-    { -2.955614925e-02f, +4.379880720e-01f, +6.437565791e-01f, -4.828020142e-02f },
-    { -2.952453962e-02f, +4.376424298e-01f, +6.440981157e-01f, -4.830920501e-02f },
-    { -2.949293857e-02f, +4.372968316e-01f, +6.444395917e-01f, -4.833818821e-02f },
-    { -2.946134614e-02f, +4.369512775e-01f, +6.447810070e-01f, -4.836715094e-02f },
-    { -2.942976236e-02f, +4.366057677e-01f, +6.451223613e-01f, -4.839609316e-02f },
-    { -2.939818727e-02f, +4.362603023e-01f, +6.454636545e-01f, -4.842501479e-02f },
-    { -2.936662089e-02f, +4.359148815e-01f, +6.458048863e-01f, -4.845391577e-02f },
-    { -2.933506327e-02f, +4.355695055e-01f, +6.461460567e-01f, -4.848279603e-02f },
-    { -2.930351443e-02f, +4.352241743e-01f, +6.464871653e-01f, -4.851165552e-02f },
-    { -2.927197441e-02f, +4.348788883e-01f, +6.468282121e-01f, -4.854049416e-02f },
-    { -2.924044325e-02f, +4.345336475e-01f, +6.471691968e-01f, -4.856931190e-02f },
-    { -2.920892096e-02f, +4.341884520e-01f, +6.475101192e-01f, -4.859810867e-02f },
-    { -2.917740760e-02f, +4.338433021e-01f, +6.478509792e-01f, -4.862688440e-02f },
-    { -2.914590319e-02f, +4.334981980e-01f, +6.481917765e-01f, -4.865563904e-02f },
-    { -2.911440776e-02f, +4.331531396e-01f, +6.485325111e-01f, -4.868437251e-02f },
-    { -2.908292135e-02f, +4.328081273e-01f, +6.488731826e-01f, -4.871308476e-02f },
-    { -2.905144399e-02f, +4.324631612e-01f, +6.492137910e-01f, -4.874177572e-02f },
-    { -2.901997572e-02f, +4.321182414e-01f, +6.495543359e-01f, -4.877044532e-02f },
-    { -2.898851656e-02f, +4.317733681e-01f, +6.498948173e-01f, -4.879909350e-02f },
-    { -2.895706654e-02f, +4.314285415e-01f, +6.502352350e-01f, -4.882772020e-02f },
-    { -2.892562571e-02f, +4.310837617e-01f, +6.505755887e-01f, -4.885632535e-02f },
-    { -2.889419410e-02f, +4.307390288e-01f, +6.509158783e-01f, -4.888490889e-02f },
-    { -2.886277173e-02f, +4.303943430e-01f, +6.512561036e-01f, -4.891347075e-02f },
-    { -2.883135864e-02f, +4.300497046e-01f, +6.515962644e-01f, -4.894201087e-02f },
-    { -2.879995486e-02f, +4.297051136e-01f, +6.519363605e-01f, -4.897052918e-02f },
-    { -2.876856043e-02f, +4.293605701e-01f, +6.522763918e-01f, -4.899902562e-02f },
-    { -2.873717537e-02f, +4.290160745e-01f, +6.526163580e-01f, -4.902750012e-02f },
-    { -2.870579972e-02f, +4.286716267e-01f, +6.529562589e-01f, -4.905595262e-02f },
-    { -2.867443352e-02f, +4.283272270e-01f, +6.532960945e-01f, -4.908438306e-02f },
-    { -2.864307678e-02f, +4.279828756e-01f, +6.536358644e-01f, -4.911279137e-02f },
-    { -2.861172956e-02f, +4.276385725e-01f, +6.539755685e-01f, -4.914117748e-02f },
-    { -2.858039187e-02f, +4.272943179e-01f, +6.543152066e-01f, -4.916954133e-02f },
-    { -2.854906375e-02f, +4.269501121e-01f, +6.546547786e-01f, -4.919788286e-02f },
-    { -2.851774523e-02f, +4.266059551e-01f, +6.549942842e-01f, -4.922620200e-02f },
-    { -2.848643635e-02f, +4.262618471e-01f, +6.553337232e-01f, -4.925449868e-02f },
-    { -2.845513713e-02f, +4.259177883e-01f, +6.556730955e-01f, -4.928277284e-02f },
-    { -2.842384761e-02f, +4.255737788e-01f, +6.560124009e-01f, -4.931102441e-02f },
-    { -2.839256782e-02f, +4.252298187e-01f, +6.563516392e-01f, -4.933925334e-02f },
-    { -2.836129779e-02f, +4.248859083e-01f, +6.566908102e-01f, -4.936745955e-02f },
-    { -2.833003756e-02f, +4.245420477e-01f, +6.570299137e-01f, -4.939564297e-02f },
-    { -2.829878715e-02f, +4.241982371e-01f, +6.573689495e-01f, -4.942380356e-02f },
-    { -2.826754660e-02f, +4.238544765e-01f, +6.577079175e-01f, -4.945194122e-02f },
-    { -2.823631593e-02f, +4.235107662e-01f, +6.580468175e-01f, -4.948005591e-02f },
-    { -2.820509519e-02f, +4.231671063e-01f, +6.583856492e-01f, -4.950814756e-02f },
-    { -2.817388439e-02f, +4.228234970e-01f, +6.587244125e-01f, -4.953621610e-02f },
-    { -2.814268358e-02f, +4.224799384e-01f, +6.590631072e-01f, -4.956426147e-02f },
-    { -2.811149279e-02f, +4.221364307e-01f, +6.594017331e-01f, -4.959228359e-02f },
-    { -2.808031203e-02f, +4.217929740e-01f, +6.597402901e-01f, -4.962028241e-02f },
-    { -2.804914136e-02f, +4.214495685e-01f, +6.600787779e-01f, -4.964825786e-02f },
-    { -2.801798079e-02f, +4.211062143e-01f, +6.604171963e-01f, -4.967620987e-02f },
-    { -2.798683036e-02f, +4.207629117e-01f, +6.607555453e-01f, -4.970413838e-02f },
-    { -2.795569010e-02f, +4.204196607e-01f, +6.610938245e-01f, -4.973204333e-02f },
-    { -2.792456005e-02f, +4.200764615e-01f, +6.614320337e-01f, -4.975992463e-02f },
-    { -2.789344022e-02f, +4.197333143e-01f, +6.617701729e-01f, -4.978778224e-02f },
-    { -2.786233066e-02f, +4.193902192e-01f, +6.621082419e-01f, -4.981561608e-02f },
-    { -2.783123139e-02f, +4.190471763e-01f, +6.624462403e-01f, -4.984342609e-02f },
-    { -2.780014245e-02f, +4.187041859e-01f, +6.627841681e-01f, -4.987121220e-02f },
-    { -2.776906386e-02f, +4.183612481e-01f, +6.631220251e-01f, -4.989897435e-02f },
-    { -2.773799566e-02f, +4.180183630e-01f, +6.634598110e-01f, -4.992671247e-02f },
-    { -2.770693788e-02f, +4.176755308e-01f, +6.637975258e-01f, -4.995442649e-02f },
-    { -2.767589054e-02f, +4.173327517e-01f, +6.641351691e-01f, -4.998211634e-02f },
-    { -2.764485368e-02f, +4.169900257e-01f, +6.644727409e-01f, -5.000978197e-02f },
-    { -2.761382734e-02f, +4.166473531e-01f, +6.648102408e-01f, -5.003742330e-02f },
-    { -2.758281153e-02f, +4.163047340e-01f, +6.651476689e-01f, -5.006504027e-02f },
-    { -2.755180629e-02f, +4.159621686e-01f, +6.654850247e-01f, -5.009263282e-02f },
-    { -2.752081165e-02f, +4.156196570e-01f, +6.658223083e-01f, -5.012020087e-02f },
-    { -2.748982764e-02f, +4.152771994e-01f, +6.661595193e-01f, -5.014774435e-02f },
-    { -2.745885430e-02f, +4.149347959e-01f, +6.664966577e-01f, -5.017526321e-02f },
-    { -2.742789164e-02f, +4.145924466e-01f, +6.668337231e-01f, -5.020275738e-02f },
-    { -2.739693971e-02f, +4.142501518e-01f, +6.671707155e-01f, -5.023022678e-02f },
-    { -2.736599852e-02f, +4.139079116e-01f, +6.675076346e-01f, -5.025767136e-02f },
-    { -2.733506812e-02f, +4.135657261e-01f, +6.678444802e-01f, -5.028509105e-02f },
-    { -2.730414853e-02f, +4.132235955e-01f, +6.681812522e-01f, -5.031248577e-02f },
-    { -2.727323979e-02f, +4.128815199e-01f, +6.685179504e-01f, -5.033985546e-02f },
-    { -2.724234191e-02f, +4.125394995e-01f, +6.688545746e-01f, -5.036720007e-02f },
-    { -2.721145493e-02f, +4.121975345e-01f, +6.691911246e-01f, -5.039451951e-02f },
-    { -2.718057889e-02f, +4.118556250e-01f, +6.695276002e-01f, -5.042181372e-02f },
-    { -2.714971381e-02f, +4.115137711e-01f, +6.698640012e-01f, -5.044908263e-02f },
-    { -2.711885972e-02f, +4.111719731e-01f, +6.702003275e-01f, -5.047632619e-02f },
-    { -2.708801665e-02f, +4.108302310e-01f, +6.705365788e-01f, -5.050354431e-02f },
-    { -2.705718463e-02f, +4.104885450e-01f, +6.708727551e-01f, -5.053073694e-02f },
-    { -2.702636369e-02f, +4.101469153e-01f, +6.712088560e-01f, -5.055790401e-02f },
-    { -2.699555385e-02f, +4.098053420e-01f, +6.715448814e-01f, -5.058504544e-02f },
-    { -2.696475516e-02f, +4.094638252e-01f, +6.718808311e-01f, -5.061216118e-02f },
-    { -2.693396764e-02f, +4.091223652e-01f, +6.722167049e-01f, -5.063925115e-02f },
-    { -2.690319131e-02f, +4.087809621e-01f, +6.725525027e-01f, -5.066631529e-02f },
-    { -2.687242621e-02f, +4.084396159e-01f, +6.728882242e-01f, -5.069335353e-02f },
-    { -2.684167237e-02f, +4.080983270e-01f, +6.732238693e-01f, -5.072036581e-02f },
-    { -2.681092981e-02f, +4.077570954e-01f, +6.735594378e-01f, -5.074735205e-02f },
-    { -2.678019856e-02f, +4.074159212e-01f, +6.738949295e-01f, -5.077431218e-02f },
-    { -2.674947866e-02f, +4.070748047e-01f, +6.742303442e-01f, -5.080124615e-02f },
-    { -2.671877013e-02f, +4.067337460e-01f, +6.745656817e-01f, -5.082815388e-02f },
-    { -2.668807301e-02f, +4.063927452e-01f, +6.749009418e-01f, -5.085503531e-02f },
-    { -2.665738731e-02f, +4.060518025e-01f, +6.752361244e-01f, -5.088189036e-02f },
-    { -2.662671308e-02f, +4.057109180e-01f, +6.755712292e-01f, -5.090871897e-02f },
-    { -2.659605033e-02f, +4.053700919e-01f, +6.759062562e-01f, -5.093552108e-02f },
-    { -2.656539910e-02f, +4.050293243e-01f, +6.762412050e-01f, -5.096229661e-02f },
-    { -2.653475941e-02f, +4.046886155e-01f, +6.765760755e-01f, -5.098904550e-02f },
-    { -2.650413130e-02f, +4.043479654e-01f, +6.769108675e-01f, -5.101576767e-02f },
-    { -2.647351480e-02f, +4.040073744e-01f, +6.772455809e-01f, -5.104246307e-02f },
-    { -2.644290992e-02f, +4.036668425e-01f, +6.775802154e-01f, -5.106913162e-02f },
-    { -2.641231671e-02f, +4.033263699e-01f, +6.779147709e-01f, -5.109577326e-02f },
-    { -2.638173519e-02f, +4.029859567e-01f, +6.782492471e-01f, -5.112238791e-02f },
-    { -2.635116538e-02f, +4.026456031e-01f, +6.785836440e-01f, -5.114897551e-02f },
-    { -2.632060732e-02f, +4.023053093e-01f, +6.789179612e-01f, -5.117553600e-02f },
-    { -2.629006103e-02f, +4.019650754e-01f, +6.792521986e-01f, -5.120206929e-02f },
-    { -2.625952655e-02f, +4.016249015e-01f, +6.795863561e-01f, -5.122857533e-02f },
-    { -2.622900390e-02f, +4.012847878e-01f, +6.799204334e-01f, -5.125505405e-02f },
-    { -2.619849310e-02f, +4.009447344e-01f, +6.802544304e-01f, -5.128150537e-02f },
-    { -2.616799420e-02f, +4.006047415e-01f, +6.805883468e-01f, -5.130792924e-02f },
-    { -2.613750720e-02f, +4.002648093e-01f, +6.809221825e-01f, -5.133432558e-02f },
-    { -2.610703216e-02f, +3.999249379e-01f, +6.812559373e-01f, -5.136069431e-02f },
-    { -2.607656908e-02f, +3.995851274e-01f, +6.815896110e-01f, -5.138703539e-02f },
-    { -2.604611800e-02f, +3.992453779e-01f, +6.819232035e-01f, -5.141334873e-02f },
-    { -2.601567895e-02f, +3.989056898e-01f, +6.822567144e-01f, -5.143963427e-02f },
-    { -2.598525196e-02f, +3.985660630e-01f, +6.825901438e-01f, -5.146589193e-02f },
-    { -2.595483705e-02f, +3.982264977e-01f, +6.829234913e-01f, -5.149212166e-02f },
-    { -2.592443425e-02f, +3.978869942e-01f, +6.832567567e-01f, -5.151832338e-02f },
-    { -2.589404358e-02f, +3.975475525e-01f, +6.835899400e-01f, -5.154449702e-02f },
-    { -2.586366508e-02f, +3.972081727e-01f, +6.839230409e-01f, -5.157064252e-02f },
-    { -2.583329878e-02f, +3.968688551e-01f, +6.842560591e-01f, -5.159675980e-02f },
-    { -2.580294470e-02f, +3.965295998e-01f, +6.845889947e-01f, -5.162284880e-02f },
-    { -2.577260287e-02f, +3.961904069e-01f, +6.849218472e-01f, -5.164890945e-02f },
-    { -2.574227331e-02f, +3.958512766e-01f, +6.852546167e-01f, -5.167494167e-02f },
-    { -2.571195605e-02f, +3.955122090e-01f, +6.855873028e-01f, -5.170094541e-02f },
-    { -2.568165113e-02f, +3.951732042e-01f, +6.859199054e-01f, -5.172692059e-02f },
-    { -2.565135856e-02f, +3.948342626e-01f, +6.862524243e-01f, -5.175286714e-02f },
-    { -2.562107838e-02f, +3.944953840e-01f, +6.865848593e-01f, -5.177878499e-02f },
-    { -2.559081062e-02f, +3.941565688e-01f, +6.869172102e-01f, -5.180467408e-02f },
-    { -2.556055529e-02f, +3.938178171e-01f, +6.872494769e-01f, -5.183053433e-02f },
-    { -2.553031243e-02f, +3.934791290e-01f, +6.875816592e-01f, -5.185636568e-02f },
-    { -2.550008206e-02f, +3.931405046e-01f, +6.879137568e-01f, -5.188216805e-02f },
-    { -2.546986421e-02f, +3.928019442e-01f, +6.882457697e-01f, -5.190794138e-02f },
-    { -2.543965891e-02f, +3.924634478e-01f, +6.885776975e-01f, -5.193368560e-02f },
-    { -2.540946619e-02f, +3.921250156e-01f, +6.889095401e-01f, -5.195940064e-02f },
-    { -2.537928607e-02f, +3.917866477e-01f, +6.892412974e-01f, -5.198508643e-02f },
-    { -2.534911857e-02f, +3.914483444e-01f, +6.895729691e-01f, -5.201074290e-02f },
-    { -2.531896373e-02f, +3.911101057e-01f, +6.899045550e-01f, -5.203636997e-02f },
-    { -2.528882157e-02f, +3.907719318e-01f, +6.902360551e-01f, -5.206196759e-02f },
-    { -2.525869212e-02f, +3.904338229e-01f, +6.905674690e-01f, -5.208753568e-02f },
-    { -2.522857541e-02f, +3.900957790e-01f, +6.908987966e-01f, -5.211307417e-02f },
-    { -2.519847146e-02f, +3.897578004e-01f, +6.912300378e-01f, -5.213858300e-02f },
-    { -2.516838029e-02f, +3.894198871e-01f, +6.915611922e-01f, -5.216406208e-02f },
-    { -2.513830194e-02f, +3.890820394e-01f, +6.918922599e-01f, -5.218951136e-02f },
-    { -2.510823643e-02f, +3.887442574e-01f, +6.922232404e-01f, -5.221493076e-02f },
-    { -2.507818379e-02f, +3.884065411e-01f, +6.925541338e-01f, -5.224032022e-02f },
-    { -2.504814403e-02f, +3.880688909e-01f, +6.928849397e-01f, -5.226567965e-02f },
-    { -2.501811720e-02f, +3.877313067e-01f, +6.932156580e-01f, -5.229100900e-02f },
-    { -2.498810332e-02f, +3.873937888e-01f, +6.935462886e-01f, -5.231630820e-02f },
-    { -2.495810241e-02f, +3.870563373e-01f, +6.938768311e-01f, -5.234157717e-02f },
-    { -2.492811449e-02f, +3.867189524e-01f, +6.942072855e-01f, -5.236681584e-02f },
-    { -2.489813960e-02f, +3.863816342e-01f, +6.945376516e-01f, -5.239202415e-02f },
-    { -2.486817776e-02f, +3.860443828e-01f, +6.948679292e-01f, -5.241720201e-02f },
-    { -2.483822900e-02f, +3.857071983e-01f, +6.951981180e-01f, -5.244234938e-02f },
-    { -2.480829333e-02f, +3.853700811e-01f, +6.955282179e-01f, -5.246746616e-02f },
-    { -2.477837080e-02f, +3.850330311e-01f, +6.958582288e-01f, -5.249255230e-02f },
-    { -2.474846141e-02f, +3.846960485e-01f, +6.961881503e-01f, -5.251760772e-02f },
-    { -2.471856521e-02f, +3.843591335e-01f, +6.965179824e-01f, -5.254263236e-02f },
-    { -2.468868221e-02f, +3.840222862e-01f, +6.968477249e-01f, -5.256762613e-02f },
-    { -2.465881245e-02f, +3.836855068e-01f, +6.971773775e-01f, -5.259258898e-02f },
-    { -2.462895594e-02f, +3.833487953e-01f, +6.975069402e-01f, -5.261752083e-02f },
-    { -2.459911271e-02f, +3.830121520e-01f, +6.978364126e-01f, -5.264242161e-02f },
-    { -2.456928278e-02f, +3.826755771e-01f, +6.981657947e-01f, -5.266729126e-02f },
-    { -2.453946619e-02f, +3.823390705e-01f, +6.984950861e-01f, -5.269212969e-02f },
-    { -2.450966296e-02f, +3.820026325e-01f, +6.988242869e-01f, -5.271693684e-02f },
-    { -2.447987311e-02f, +3.816662633e-01f, +6.991533966e-01f, -5.274171264e-02f },
-    { -2.445009667e-02f, +3.813299629e-01f, +6.994824153e-01f, -5.276645702e-02f },
-    { -2.442033366e-02f, +3.809937316e-01f, +6.998113426e-01f, -5.279116991e-02f },
-    { -2.439058412e-02f, +3.806575694e-01f, +7.001401785e-01f, -5.281585123e-02f },
-    { -2.436084805e-02f, +3.803214765e-01f, +7.004689226e-01f, -5.284050092e-02f },
-    { -2.433112550e-02f, +3.799854530e-01f, +7.007975749e-01f, -5.286511890e-02f },
-    { -2.430141648e-02f, +3.796494992e-01f, +7.011261352e-01f, -5.288970511e-02f },
-    { -2.427172102e-02f, +3.793136151e-01f, +7.014546032e-01f, -5.291425948e-02f },
-    { -2.424203914e-02f, +3.789778008e-01f, +7.017829788e-01f, -5.293878193e-02f },
-    { -2.421237087e-02f, +3.786420566e-01f, +7.021112617e-01f, -5.296327238e-02f },
-    { -2.418271624e-02f, +3.783063825e-01f, +7.024394519e-01f, -5.298773078e-02f },
-    { -2.415307527e-02f, +3.779707788e-01f, +7.027675491e-01f, -5.301215705e-02f },
-    { -2.412344797e-02f, +3.776352455e-01f, +7.030955531e-01f, -5.303655112e-02f },
-    { -2.409383439e-02f, +3.772997828e-01f, +7.034234638e-01f, -5.306091292e-02f },
-    { -2.406423454e-02f, +3.769643909e-01f, +7.037512810e-01f, -5.308524237e-02f },
-    { -2.403464845e-02f, +3.766290698e-01f, +7.040790044e-01f, -5.310953941e-02f },
-    { -2.400507614e-02f, +3.762938197e-01f, +7.044066339e-01f, -5.313380397e-02f },
-    { -2.397551763e-02f, +3.759586408e-01f, +7.047341694e-01f, -5.315803596e-02f },
-    { -2.394597296e-02f, +3.756235333e-01f, +7.050616105e-01f, -5.318223533e-02f },
-    { -2.391644214e-02f, +3.752884971e-01f, +7.053889572e-01f, -5.320640200e-02f },
-    { -2.388692520e-02f, +3.749535326e-01f, +7.057162093e-01f, -5.323053590e-02f },
-    { -2.385742216e-02f, +3.746186398e-01f, +7.060433665e-01f, -5.325463695e-02f },
-    { -2.382793305e-02f, +3.742838189e-01f, +7.063704287e-01f, -5.327870509e-02f },
-    { -2.379845790e-02f, +3.739490700e-01f, +7.066973957e-01f, -5.330274025e-02f },
-    { -2.376899672e-02f, +3.736143933e-01f, +7.070242673e-01f, -5.332674235e-02f },
-    { -2.373954954e-02f, +3.732797888e-01f, +7.073510434e-01f, -5.335071132e-02f },
-    { -2.371011639e-02f, +3.729452569e-01f, +7.076777237e-01f, -5.337464709e-02f },
-    { -2.368069728e-02f, +3.726107975e-01f, +7.080043080e-01f, -5.339854959e-02f },
-    { -2.365129225e-02f, +3.722764108e-01f, +7.083307963e-01f, -5.342241875e-02f },
-    { -2.362190131e-02f, +3.719420970e-01f, +7.086571882e-01f, -5.344625449e-02f },
-    { -2.359252450e-02f, +3.716078562e-01f, +7.089834836e-01f, -5.347005675e-02f },
-    { -2.356316182e-02f, +3.712736886e-01f, +7.093096823e-01f, -5.349382545e-02f },
-    { -2.353381332e-02f, +3.709395943e-01f, +7.096357842e-01f, -5.351756051e-02f },
-    { -2.350447901e-02f, +3.706055734e-01f, +7.099617891e-01f, -5.354126188e-02f },
-    { -2.347515891e-02f, +3.702716261e-01f, +7.102876966e-01f, -5.356492947e-02f },
-    { -2.344585305e-02f, +3.699377525e-01f, +7.106135068e-01f, -5.358856321e-02f },
-    { -2.341656145e-02f, +3.696039527e-01f, +7.109392194e-01f, -5.361216304e-02f },
-    { -2.338728414e-02f, +3.692702270e-01f, +7.112648342e-01f, -5.363572888e-02f },
-    { -2.335802114e-02f, +3.689365754e-01f, +7.115903510e-01f, -5.365926065e-02f },
-    { -2.332877247e-02f, +3.686029981e-01f, +7.119157697e-01f, -5.368275829e-02f },
-    { -2.329953816e-02f, +3.682694952e-01f, +7.122410900e-01f, -5.370622173e-02f },
-    { -2.327031823e-02f, +3.679360669e-01f, +7.125663118e-01f, -5.372965088e-02f },
-    { -2.324111270e-02f, +3.676027132e-01f, +7.128914348e-01f, -5.375304569e-02f },
-    { -2.321192159e-02f, +3.672694344e-01f, +7.132164590e-01f, -5.377640607e-02f },
-    { -2.318274493e-02f, +3.669362306e-01f, +7.135413841e-01f, -5.379973196e-02f },
-    { -2.315358275e-02f, +3.666031020e-01f, +7.138662100e-01f, -5.382302328e-02f },
-    { -2.312443506e-02f, +3.662700485e-01f, +7.141909364e-01f, -5.384627996e-02f },
-    { -2.309530189e-02f, +3.659370705e-01f, +7.145155631e-01f, -5.386950193e-02f },
-    { -2.306618326e-02f, +3.656041680e-01f, +7.148400900e-01f, -5.389268911e-02f },
-    { -2.303707919e-02f, +3.652713412e-01f, +7.151645170e-01f, -5.391584144e-02f },
-    { -2.300798972e-02f, +3.649385903e-01f, +7.154888437e-01f, -5.393895884e-02f },
-    { -2.297891485e-02f, +3.646059152e-01f, +7.158130701e-01f, -5.396204124e-02f },
-    { -2.294985461e-02f, +3.642733163e-01f, +7.161371959e-01f, -5.398508856e-02f },
-    { -2.292080903e-02f, +3.639407936e-01f, +7.164612210e-01f, -5.400810073e-02f },
-    { -2.289177812e-02f, +3.636083473e-01f, +7.167851452e-01f, -5.403107768e-02f },
-    { -2.286276192e-02f, +3.632759775e-01f, +7.171089682e-01f, -5.405401935e-02f },
-    { -2.283376044e-02f, +3.629436844e-01f, +7.174326900e-01f, -5.407692564e-02f },
-    { -2.280477371e-02f, +3.626114681e-01f, +7.177563103e-01f, -5.409979650e-02f },
-    { -2.277580174e-02f, +3.622793287e-01f, +7.180798289e-01f, -5.412263185e-02f },
-    { -2.274684456e-02f, +3.619472663e-01f, +7.184032457e-01f, -5.414543161e-02f },
-    { -2.271790220e-02f, +3.616152812e-01f, +7.187265605e-01f, -5.416819572e-02f },
-    { -2.268897467e-02f, +3.612833734e-01f, +7.190497730e-01f, -5.419092410e-02f },
-    { -2.266006200e-02f, +3.609515431e-01f, +7.193728831e-01f, -5.421361667e-02f },
-    { -2.263116421e-02f, +3.606197904e-01f, +7.196958907e-01f, -5.423627337e-02f },
-    { -2.260228132e-02f, +3.602881155e-01f, +7.200187955e-01f, -5.425889412e-02f },
-    { -2.257341336e-02f, +3.599565185e-01f, +7.203415974e-01f, -5.428147885e-02f },
-    { -2.254456034e-02f, +3.596249995e-01f, +7.206642961e-01f, -5.430402749e-02f },
-    { -2.251572229e-02f, +3.592935587e-01f, +7.209868915e-01f, -5.432653996e-02f },
-    { -2.248689923e-02f, +3.589621962e-01f, +7.213093834e-01f, -5.434901618e-02f },
-    { -2.245809118e-02f, +3.586309121e-01f, +7.216317716e-01f, -5.437145610e-02f },
-    { -2.242929816e-02f, +3.582997067e-01f, +7.219540560e-01f, -5.439385962e-02f },
-    { -2.240052021e-02f, +3.579685799e-01f, +7.222762363e-01f, -5.441622669e-02f },
-    { -2.237175733e-02f, +3.576375321e-01f, +7.225983123e-01f, -5.443855722e-02f },
-    { -2.234300954e-02f, +3.573065632e-01f, +7.229202840e-01f, -5.446085115e-02f },
-    { -2.231427688e-02f, +3.569756734e-01f, +7.232421510e-01f, -5.448310839e-02f },
-    { -2.228555936e-02f, +3.566448630e-01f, +7.235639133e-01f, -5.450532888e-02f },
-    { -2.225685701e-02f, +3.563141319e-01f, +7.238855706e-01f, -5.452751254e-02f },
-    { -2.222816984e-02f, +3.559834804e-01f, +7.242071227e-01f, -5.454965931e-02f },
-    { -2.219949788e-02f, +3.556529085e-01f, +7.245285695e-01f, -5.457176909e-02f },
-    { -2.217084115e-02f, +3.553224165e-01f, +7.248499108e-01f, -5.459384183e-02f },
-    { -2.214219967e-02f, +3.549920045e-01f, +7.251711464e-01f, -5.461587745e-02f },
-    { -2.211357346e-02f, +3.546616725e-01f, +7.254922761e-01f, -5.463787587e-02f },
-    { -2.208496254e-02f, +3.543314207e-01f, +7.258132997e-01f, -5.465983703e-02f },
-    { -2.205636694e-02f, +3.540012493e-01f, +7.261342170e-01f, -5.468176084e-02f },
-    { -2.202778667e-02f, +3.536711584e-01f, +7.264550280e-01f, -5.470364724e-02f },
-    { -2.199922176e-02f, +3.533411482e-01f, +7.267757323e-01f, -5.472549614e-02f },
-    { -2.197067223e-02f, +3.530112187e-01f, +7.270963298e-01f, -5.474730748e-02f },
-    { -2.194213809e-02f, +3.526813701e-01f, +7.274168203e-01f, -5.476908119e-02f },
-    { -2.191361938e-02f, +3.523516026e-01f, +7.277372036e-01f, -5.479081718e-02f },
-    { -2.188511610e-02f, +3.520219162e-01f, +7.280574796e-01f, -5.481251539e-02f },
-    { -2.185662829e-02f, +3.516923111e-01f, +7.283776481e-01f, -5.483417574e-02f },
-    { -2.182815596e-02f, +3.513627875e-01f, +7.286977088e-01f, -5.485579815e-02f },
-    { -2.179969913e-02f, +3.510333455e-01f, +7.290176616e-01f, -5.487738256e-02f },
-    { -2.177125783e-02f, +3.507039852e-01f, +7.293375064e-01f, -5.489892888e-02f },
-    { -2.174283207e-02f, +3.503747067e-01f, +7.296572429e-01f, -5.492043705e-02f },
-    { -2.171442188e-02f, +3.500455102e-01f, +7.299768709e-01f, -5.494190699e-02f },
-    { -2.168602727e-02f, +3.497163959e-01f, +7.302963903e-01f, -5.496333863e-02f },
-    { -2.165764827e-02f, +3.493873638e-01f, +7.306158008e-01f, -5.498473189e-02f },
-    { -2.162928490e-02f, +3.490584141e-01f, +7.309351024e-01f, -5.500608670e-02f },
-    { -2.160093718e-02f, +3.487295469e-01f, +7.312542948e-01f, -5.502740298e-02f },
-    { -2.157260512e-02f, +3.484007623e-01f, +7.315733778e-01f, -5.504868065e-02f },
-    { -2.154428875e-02f, +3.480720606e-01f, +7.318923513e-01f, -5.506991966e-02f },
-    { -2.151598810e-02f, +3.477434418e-01f, +7.322112150e-01f, -5.509111991e-02f },
-    { -2.148770317e-02f, +3.474149060e-01f, +7.325299688e-01f, -5.511228134e-02f },
-    { -2.145943399e-02f, +3.470864534e-01f, +7.328486125e-01f, -5.513340388e-02f },
-    { -2.143118058e-02f, +3.467580842e-01f, +7.331671459e-01f, -5.515448744e-02f },
-    { -2.140294296e-02f, +3.464297984e-01f, +7.334855689e-01f, -5.517553195e-02f },
-    { -2.137472115e-02f, +3.461015962e-01f, +7.338038812e-01f, -5.519653734e-02f },
-    { -2.134651517e-02f, +3.457734778e-01f, +7.341220827e-01f, -5.521750353e-02f },
-    { -2.131832504e-02f, +3.454454432e-01f, +7.344401732e-01f, -5.523843046e-02f },
-    { -2.129015078e-02f, +3.451174926e-01f, +7.347581525e-01f, -5.525931803e-02f },
-    { -2.126199241e-02f, +3.447896261e-01f, +7.350760204e-01f, -5.528016619e-02f },
-    { -2.123384995e-02f, +3.444618439e-01f, +7.353937768e-01f, -5.530097485e-02f },
-    { -2.120572342e-02f, +3.441341461e-01f, +7.357114214e-01f, -5.532174395e-02f },
-    { -2.117761283e-02f, +3.438065327e-01f, +7.360289541e-01f, -5.534247339e-02f },
-    { -2.114951822e-02f, +3.434790041e-01f, +7.363463747e-01f, -5.536316312e-02f },
-    { -2.112143960e-02f, +3.431515602e-01f, +7.366636830e-01f, -5.538381306e-02f },
-    { -2.109337699e-02f, +3.428242013e-01f, +7.369808788e-01f, -5.540442312e-02f },
-    { -2.106533040e-02f, +3.424969274e-01f, +7.372979620e-01f, -5.542499324e-02f },
-    { -2.103729986e-02f, +3.421697387e-01f, +7.376149323e-01f, -5.544552335e-02f },
-    { -2.100928539e-02f, +3.418426354e-01f, +7.379317896e-01f, -5.546601336e-02f },
-    { -2.098128700e-02f, +3.415156174e-01f, +7.382485338e-01f, -5.548646320e-02f },
-    { -2.095330472e-02f, +3.411886851e-01f, +7.385651645e-01f, -5.550687279e-02f },
-    { -2.092533857e-02f, +3.408618385e-01f, +7.388816817e-01f, -5.552724207e-02f },
-    { -2.089738856e-02f, +3.405350777e-01f, +7.391980851e-01f, -5.554757095e-02f },
-    { -2.086945472e-02f, +3.402084029e-01f, +7.395143746e-01f, -5.556785936e-02f },
-    { -2.084153705e-02f, +3.398818142e-01f, +7.398305500e-01f, -5.558810723e-02f },
-    { -2.081363559e-02f, +3.395553117e-01f, +7.401466111e-01f, -5.560831448e-02f },
-    { -2.078575035e-02f, +3.392288956e-01f, +7.404625577e-01f, -5.562848104e-02f },
-    { -2.075788136e-02f, +3.389025660e-01f, +7.407783897e-01f, -5.564860682e-02f },
-    { -2.073002862e-02f, +3.385763231e-01f, +7.410941069e-01f, -5.566869176e-02f },
-    { -2.070219216e-02f, +3.382501669e-01f, +7.414097090e-01f, -5.568873578e-02f },
-    { -2.067437199e-02f, +3.379240976e-01f, +7.417251959e-01f, -5.570873880e-02f },
-    { -2.064656814e-02f, +3.375981153e-01f, +7.420405674e-01f, -5.572870075e-02f },
-    { -2.061878063e-02f, +3.372722202e-01f, +7.423558234e-01f, -5.574862155e-02f },
-    { -2.059100947e-02f, +3.369464124e-01f, +7.426709636e-01f, -5.576850113e-02f },
-    { -2.056325469e-02f, +3.366206920e-01f, +7.429859879e-01f, -5.578833941e-02f },
-    { -2.053551629e-02f, +3.362950591e-01f, +7.433008961e-01f, -5.580813632e-02f },
-    { -2.050779431e-02f, +3.359695139e-01f, +7.436156880e-01f, -5.582789178e-02f },
-    { -2.048008875e-02f, +3.356440565e-01f, +7.439303635e-01f, -5.584760571e-02f },
-    { -2.045239964e-02f, +3.353186871e-01f, +7.442449222e-01f, -5.586727805e-02f },
-    { -2.042472700e-02f, +3.349934057e-01f, +7.445593642e-01f, -5.588690871e-02f },
-    { -2.039707084e-02f, +3.346682125e-01f, +7.448736891e-01f, -5.590649761e-02f },
-    { -2.036943118e-02f, +3.343431076e-01f, +7.451878969e-01f, -5.592604469e-02f },
-    { -2.034180804e-02f, +3.340180912e-01f, +7.455019872e-01f, -5.594554986e-02f },
-    { -2.031420145e-02f, +3.336931634e-01f, +7.458159600e-01f, -5.596501306e-02f },
-    { -2.028661141e-02f, +3.333683243e-01f, +7.461298151e-01f, -5.598443420e-02f },
-    { -2.025903794e-02f, +3.330435740e-01f, +7.464435522e-01f, -5.600381321e-02f },
-    { -2.023148107e-02f, +3.327189127e-01f, +7.467571712e-01f, -5.602315001e-02f },
-    { -2.020394081e-02f, +3.323943405e-01f, +7.470706720e-01f, -5.604244453e-02f },
-    { -2.017641718e-02f, +3.320698576e-01f, +7.473840543e-01f, -5.606169669e-02f },
-    { -2.014891020e-02f, +3.317454639e-01f, +7.476973179e-01f, -5.608090642e-02f },
-    { -2.012141988e-02f, +3.314211598e-01f, +7.480104627e-01f, -5.610007364e-02f },
-    { -2.009394625e-02f, +3.310969453e-01f, +7.483234885e-01f, -5.611919827e-02f },
-    { -2.006648932e-02f, +3.307728205e-01f, +7.486363951e-01f, -5.613828023e-02f },
-    { -2.003904911e-02f, +3.304487856e-01f, +7.489491824e-01f, -5.615731946e-02f },
-    { -2.001162564e-02f, +3.301248407e-01f, +7.492618501e-01f, -5.617631587e-02f },
-    { -1.998421892e-02f, +3.298009860e-01f, +7.495743981e-01f, -5.619526939e-02f },
-    { -1.995682897e-02f, +3.294772215e-01f, +7.498868261e-01f, -5.621417995e-02f },
-    { -1.992945582e-02f, +3.291535473e-01f, +7.501991341e-01f, -5.623304746e-02f },
-    { -1.990209947e-02f, +3.288299637e-01f, +7.505113218e-01f, -5.625187185e-02f },
-    { -1.987475995e-02f, +3.285064707e-01f, +7.508233890e-01f, -5.627065304e-02f },
-    { -1.984743727e-02f, +3.281830685e-01f, +7.511353356e-01f, -5.628939096e-02f },
-    { -1.982013145e-02f, +3.278597572e-01f, +7.514471614e-01f, -5.630808553e-02f },
-    { -1.979284251e-02f, +3.275365369e-01f, +7.517588662e-01f, -5.632673668e-02f },
-    { -1.976557047e-02f, +3.272134077e-01f, +7.520704498e-01f, -5.634534432e-02f },
-    { -1.973831534e-02f, +3.268903698e-01f, +7.523819121e-01f, -5.636390839e-02f },
-    { -1.971107714e-02f, +3.265674233e-01f, +7.526932528e-01f, -5.638242880e-02f },
-    { -1.968385589e-02f, +3.262445684e-01f, +7.530044718e-01f, -5.640090548e-02f },
-    { -1.965665160e-02f, +3.259218051e-01f, +7.533155690e-01f, -5.641933835e-02f },
-    { -1.962946429e-02f, +3.255991335e-01f, +7.536265440e-01f, -5.643772734e-02f },
-    { -1.960229398e-02f, +3.252765539e-01f, +7.539373968e-01f, -5.645607236e-02f },
-    { -1.957514069e-02f, +3.249540663e-01f, +7.542481271e-01f, -5.647437335e-02f },
-    { -1.954800443e-02f, +3.246316709e-01f, +7.545587349e-01f, -5.649263022e-02f },
-    { -1.952088522e-02f, +3.243093678e-01f, +7.548692198e-01f, -5.651084290e-02f },
-    { -1.949378307e-02f, +3.239871571e-01f, +7.551795818e-01f, -5.652901131e-02f },
-    { -1.946669801e-02f, +3.236650389e-01f, +7.554898206e-01f, -5.654713538e-02f },
-    { -1.943963005e-02f, +3.233430133e-01f, +7.557999361e-01f, -5.656521503e-02f },
-    { -1.941257921e-02f, +3.230210806e-01f, +7.561099280e-01f, -5.658325018e-02f },
-    { -1.938554550e-02f, +3.226992408e-01f, +7.564197963e-01f, -5.660124075e-02f },
-    { -1.935852895e-02f, +3.223774940e-01f, +7.567295407e-01f, -5.661918667e-02f },
-    { -1.933152956e-02f, +3.220558404e-01f, +7.570391610e-01f, -5.663708786e-02f },
-    { -1.930454735e-02f, +3.217342801e-01f, +7.573486571e-01f, -5.665494425e-02f },
-    { -1.927758234e-02f, +3.214128132e-01f, +7.576580288e-01f, -5.667275575e-02f },
-    { -1.925063455e-02f, +3.210914398e-01f, +7.579672759e-01f, -5.669052229e-02f },
-    { -1.922370400e-02f, +3.207701601e-01f, +7.582763982e-01f, -5.670824380e-02f },
-    { -1.919679069e-02f, +3.204489742e-01f, +7.585853955e-01f, -5.672592019e-02f },
-    { -1.916989465e-02f, +3.201278822e-01f, +7.588942678e-01f, -5.674355138e-02f },
-    { -1.914301589e-02f, +3.198068842e-01f, +7.592030147e-01f, -5.676113731e-02f },
-    { -1.911615443e-02f, +3.194859804e-01f, +7.595116361e-01f, -5.677867790e-02f },
-    { -1.908931029e-02f, +3.191651709e-01f, +7.598201319e-01f, -5.679617306e-02f },
-    { -1.906248348e-02f, +3.188444558e-01f, +7.601285018e-01f, -5.681362272e-02f },
-    { -1.903567401e-02f, +3.185238353e-01f, +7.604367457e-01f, -5.683102681e-02f },
-    { -1.900888191e-02f, +3.182033094e-01f, +7.607448634e-01f, -5.684838523e-02f },
-    { -1.898210719e-02f, +3.178828783e-01f, +7.610528546e-01f, -5.686569793e-02f },
-    { -1.895534986e-02f, +3.175625421e-01f, +7.613607194e-01f, -5.688296482e-02f },
-    { -1.892860994e-02f, +3.172423009e-01f, +7.616684574e-01f, -5.690018582e-02f },
-    { -1.890188745e-02f, +3.169221549e-01f, +7.619760684e-01f, -5.691736086e-02f },
-    { -1.887518241e-02f, +3.166021042e-01f, +7.622835524e-01f, -5.693448985e-02f },
-    { -1.884849482e-02f, +3.162821488e-01f, +7.625909090e-01f, -5.695157273e-02f },
-    { -1.882182471e-02f, +3.159622890e-01f, +7.628981382e-01f, -5.696860941e-02f },
-    { -1.879517209e-02f, +3.156425249e-01f, +7.632052398e-01f, -5.698559981e-02f },
-    { -1.876853697e-02f, +3.153228565e-01f, +7.635122136e-01f, -5.700254386e-02f },
-    { -1.874191938e-02f, +3.150032840e-01f, +7.638190593e-01f, -5.701944149e-02f },
-    { -1.871531932e-02f, +3.146838075e-01f, +7.641257769e-01f, -5.703629260e-02f },
-    { -1.868873682e-02f, +3.143644272e-01f, +7.644323662e-01f, -5.705309714e-02f },
-    { -1.866217188e-02f, +3.140451431e-01f, +7.647388269e-01f, -5.706985501e-02f },
-    { -1.863562453e-02f, +3.137259554e-01f, +7.650451589e-01f, -5.708656614e-02f },
-    { -1.860909478e-02f, +3.134068642e-01f, +7.653513620e-01f, -5.710323045e-02f },
-    { -1.858258264e-02f, +3.130878696e-01f, +7.656574360e-01f, -5.711984787e-02f },
-    { -1.855608813e-02f, +3.127689718e-01f, +7.659633808e-01f, -5.713641831e-02f },
-    { -1.852961127e-02f, +3.124501709e-01f, +7.662691962e-01f, -5.715294170e-02f },
-    { -1.850315207e-02f, +3.121314670e-01f, +7.665748819e-01f, -5.716941797e-02f },
-    { -1.847671054e-02f, +3.118128601e-01f, +7.668804379e-01f, -5.718584702e-02f },
-    { -1.845028671e-02f, +3.114943506e-01f, +7.671858639e-01f, -5.720222880e-02f },
-    { -1.842388058e-02f, +3.111759383e-01f, +7.674911598e-01f, -5.721856321e-02f },
-    { -1.839749217e-02f, +3.108576236e-01f, +7.677963254e-01f, -5.723485017e-02f },
-    { -1.837112149e-02f, +3.105394064e-01f, +7.681013605e-01f, -5.725108962e-02f },
-    { -1.834476857e-02f, +3.102212870e-01f, +7.684062649e-01f, -5.726728148e-02f },
-    { -1.831843341e-02f, +3.099032654e-01f, +7.687110385e-01f, -5.728342566e-02f },
-    { -1.829211604e-02f, +3.095853418e-01f, +7.690156811e-01f, -5.729952209e-02f },
-    { -1.826581646e-02f, +3.092675163e-01f, +7.693201924e-01f, -5.731557068e-02f },
-    { -1.823953469e-02f, +3.089497890e-01f, +7.696245724e-01f, -5.733157137e-02f },
-    { -1.821327074e-02f, +3.086321600e-01f, +7.699288208e-01f, -5.734752407e-02f },
-    { -1.818702464e-02f, +3.083146294e-01f, +7.702329374e-01f, -5.736342870e-02f },
-    { -1.816079639e-02f, +3.079971975e-01f, +7.705369222e-01f, -5.737928519e-02f },
-    { -1.813458600e-02f, +3.076798642e-01f, +7.708407749e-01f, -5.739509346e-02f },
-    { -1.810839350e-02f, +3.073626297e-01f, +7.711444953e-01f, -5.741085343e-02f },
-    { -1.808221890e-02f, +3.070454941e-01f, +7.714480832e-01f, -5.742656503e-02f },
-    { -1.805606221e-02f, +3.067284576e-01f, +7.717515386e-01f, -5.744222816e-02f },
-    { -1.802992345e-02f, +3.064115203e-01f, +7.720548611e-01f, -5.745784276e-02f },
-    { -1.800380263e-02f, +3.060946822e-01f, +7.723580506e-01f, -5.747340875e-02f },
-    { -1.797769977e-02f, +3.057779436e-01f, +7.726611070e-01f, -5.748892604e-02f },
-    { -1.795161487e-02f, +3.054613045e-01f, +7.729640301e-01f, -5.750439457e-02f },
-    { -1.792554796e-02f, +3.051447650e-01f, +7.732668197e-01f, -5.751981424e-02f },
-    { -1.789949905e-02f, +3.048283253e-01f, +7.735694755e-01f, -5.753518499e-02f },
-    { -1.787346814e-02f, +3.045119855e-01f, +7.738719975e-01f, -5.755050673e-02f },
-    { -1.784745527e-02f, +3.041957456e-01f, +7.741743855e-01f, -5.756577939e-02f },
-    { -1.782146044e-02f, +3.038796059e-01f, +7.744766393e-01f, -5.758100289e-02f },
-    { -1.779548366e-02f, +3.035635665e-01f, +7.747787586e-01f, -5.759617715e-02f },
-    { -1.776952495e-02f, +3.032476274e-01f, +7.750807434e-01f, -5.761130208e-02f },
-    { -1.774358432e-02f, +3.029317887e-01f, +7.753825935e-01f, -5.762637762e-02f },
-    { -1.771766179e-02f, +3.026160507e-01f, +7.756843086e-01f, -5.764140368e-02f },
-    { -1.769175736e-02f, +3.023004134e-01f, +7.759858886e-01f, -5.765638018e-02f },
-    { -1.766587107e-02f, +3.019848769e-01f, +7.762873333e-01f, -5.767130705e-02f },
-    { -1.764000291e-02f, +3.016694414e-01f, +7.765886426e-01f, -5.768618420e-02f },
-    { -1.761415290e-02f, +3.013541069e-01f, +7.768898163e-01f, -5.770101157e-02f },
-    { -1.758832105e-02f, +3.010388736e-01f, +7.771908542e-01f, -5.771578906e-02f },
-    { -1.756250739e-02f, +3.007237417e-01f, +7.774917560e-01f, -5.773051660e-02f },
-    { -1.753671192e-02f, +3.004087111e-01f, +7.777925218e-01f, -5.774519411e-02f },
-    { -1.751093465e-02f, +3.000937821e-01f, +7.780931511e-01f, -5.775982152e-02f },
-    { -1.748517560e-02f, +2.997789547e-01f, +7.783936440e-01f, -5.777439874e-02f },
-    { -1.745943479e-02f, +2.994642291e-01f, +7.786940002e-01f, -5.778892569e-02f },
-    { -1.743371222e-02f, +2.991496054e-01f, +7.789942195e-01f, -5.780340230e-02f },
-    { -1.740800791e-02f, +2.988350837e-01f, +7.792943018e-01f, -5.781782849e-02f },
-    { -1.738232187e-02f, +2.985206642e-01f, +7.795942469e-01f, -5.783220417e-02f },
-    { -1.735665412e-02f, +2.982063468e-01f, +7.798940546e-01f, -5.784652927e-02f },
-    { -1.733100467e-02f, +2.978921319e-01f, +7.801937247e-01f, -5.786080371e-02f },
-    { -1.730537353e-02f, +2.975780194e-01f, +7.804932570e-01f, -5.787502741e-02f },
-    { -1.727976072e-02f, +2.972640094e-01f, +7.807926515e-01f, -5.788920029e-02f },
-    { -1.725416625e-02f, +2.969501022e-01f, +7.810919079e-01f, -5.790332228e-02f },
-    { -1.722859012e-02f, +2.966362979e-01f, +7.813910260e-01f, -5.791739329e-02f },
-    { -1.720303237e-02f, +2.963225964e-01f, +7.816900056e-01f, -5.793141324e-02f },
-    { -1.717749299e-02f, +2.960089980e-01f, +7.819888466e-01f, -5.794538205e-02f },
-    { -1.715197200e-02f, +2.956955028e-01f, +7.822875489e-01f, -5.795929965e-02f },
-    { -1.712646941e-02f, +2.953821109e-01f, +7.825861121e-01f, -5.797316596e-02f },
-    { -1.710098524e-02f, +2.950688223e-01f, +7.828845363e-01f, -5.798698089e-02f },
-    { -1.707551950e-02f, +2.947556373e-01f, +7.831828211e-01f, -5.800074437e-02f },
-    { -1.705007220e-02f, +2.944425560e-01f, +7.834809664e-01f, -5.801445632e-02f },
-    { -1.702464336e-02f, +2.941295783e-01f, +7.837789720e-01f, -5.802811666e-02f },
-    { -1.699923298e-02f, +2.938167045e-01f, +7.840768378e-01f, -5.804172530e-02f },
-    { -1.697384108e-02f, +2.935039348e-01f, +7.843745636e-01f, -5.805528218e-02f },
-    { -1.694846768e-02f, +2.931912691e-01f, +7.846721491e-01f, -5.806878721e-02f },
-    { -1.692311278e-02f, +2.928787076e-01f, +7.849695943e-01f, -5.808224030e-02f },
-    { -1.689777639e-02f, +2.925662504e-01f, +7.852668990e-01f, -5.809564139e-02f },
-    { -1.687245854e-02f, +2.922538976e-01f, +7.855640629e-01f, -5.810899039e-02f },
-    { -1.684715923e-02f, +2.919416495e-01f, +7.858610859e-01f, -5.812228722e-02f },
-    { -1.682187847e-02f, +2.916295059e-01f, +7.861579679e-01f, -5.813553181e-02f },
-    { -1.679661628e-02f, +2.913174672e-01f, +7.864547086e-01f, -5.814872407e-02f },
-    { -1.677137267e-02f, +2.910055333e-01f, +7.867513079e-01f, -5.816186392e-02f },
-    { -1.674614765e-02f, +2.906937045e-01f, +7.870477656e-01f, -5.817495128e-02f },
-    { -1.672094124e-02f, +2.903819808e-01f, +7.873440816e-01f, -5.818798608e-02f },
-    { -1.669575344e-02f, +2.900703623e-01f, +7.876402556e-01f, -5.820096823e-02f },
-    { -1.667058426e-02f, +2.897588491e-01f, +7.879362875e-01f, -5.821389766e-02f },
-    { -1.664543373e-02f, +2.894474415e-01f, +7.882321771e-01f, -5.822677428e-02f },
-    { -1.662030185e-02f, +2.891361394e-01f, +7.885279242e-01f, -5.823959802e-02f },
-    { -1.659518863e-02f, +2.888249429e-01f, +7.888235287e-01f, -5.825236880e-02f },
-    { -1.657009409e-02f, +2.885138523e-01f, +7.891189904e-01f, -5.826508653e-02f },
-    { -1.654501824e-02f, +2.882028676e-01f, +7.894143091e-01f, -5.827775113e-02f },
-    { -1.651996108e-02f, +2.878919890e-01f, +7.897094846e-01f, -5.829036253e-02f },
-    { -1.649492264e-02f, +2.875812164e-01f, +7.900045168e-01f, -5.830292065e-02f },
-    { -1.646990291e-02f, +2.872705501e-01f, +7.902994055e-01f, -5.831542540e-02f },
-    { -1.644490193e-02f, +2.869599902e-01f, +7.905941505e-01f, -5.832787671e-02f },
-    { -1.641991969e-02f, +2.866495368e-01f, +7.908887516e-01f, -5.834027449e-02f },
-    { -1.639495620e-02f, +2.863391899e-01f, +7.911832088e-01f, -5.835261867e-02f },
-    { -1.637001149e-02f, +2.860289498e-01f, +7.914775217e-01f, -5.836490917e-02f },
-    { -1.634508556e-02f, +2.857188164e-01f, +7.917716902e-01f, -5.837714590e-02f },
-    { -1.632017842e-02f, +2.854087900e-01f, +7.920657142e-01f, -5.838932879e-02f },
-    { -1.629529008e-02f, +2.850988707e-01f, +7.923595935e-01f, -5.840145776e-02f },
-    { -1.627042056e-02f, +2.847890584e-01f, +7.926533279e-01f, -5.841353272e-02f },
-    { -1.624556986e-02f, +2.844793535e-01f, +7.929469172e-01f, -5.842555359e-02f },
-    { -1.622073801e-02f, +2.841697559e-01f, +7.932403612e-01f, -5.843752031e-02f },
-    { -1.619592500e-02f, +2.838602658e-01f, +7.935336599e-01f, -5.844943277e-02f },
-    { -1.617113085e-02f, +2.835508833e-01f, +7.938268129e-01f, -5.846129092e-02f },
-    { -1.614635558e-02f, +2.832416085e-01f, +7.941198202e-01f, -5.847309465e-02f },
-    { -1.612159918e-02f, +2.829324415e-01f, +7.944126816e-01f, -5.848484391e-02f },
-    { -1.609686168e-02f, +2.826233824e-01f, +7.947053969e-01f, -5.849653859e-02f },
-    { -1.607214309e-02f, +2.823144314e-01f, +7.949979658e-01f, -5.850817864e-02f },
-    { -1.604744341e-02f, +2.820055885e-01f, +7.952903884e-01f, -5.851976395e-02f },
-    { -1.602276266e-02f, +2.816968539e-01f, +7.955826642e-01f, -5.853129446e-02f },
-    { -1.599810084e-02f, +2.813882276e-01f, +7.958747933e-01f, -5.854277008e-02f },
-    { -1.597345798e-02f, +2.810797098e-01f, +7.961667755e-01f, -5.855419074e-02f },
-    { -1.594883407e-02f, +2.807713007e-01f, +7.964586105e-01f, -5.856555634e-02f },
-    { -1.592422914e-02f, +2.804630002e-01f, +7.967502981e-01f, -5.857686682e-02f },
-    { -1.589964318e-02f, +2.801548085e-01f, +7.970418383e-01f, -5.858812209e-02f },
-    { -1.587507622e-02f, +2.798467258e-01f, +7.973332308e-01f, -5.859932207e-02f },
-    { -1.585052826e-02f, +2.795387520e-01f, +7.976244755e-01f, -5.861046669e-02f },
-    { -1.582599931e-02f, +2.792308874e-01f, +7.979155722e-01f, -5.862155585e-02f },
-    { -1.580148939e-02f, +2.789231321e-01f, +7.982065207e-01f, -5.863258948e-02f },
-    { -1.577699850e-02f, +2.786154861e-01f, +7.984973209e-01f, -5.864356750e-02f },
-    { -1.575252665e-02f, +2.783079496e-01f, +7.987879725e-01f, -5.865448983e-02f },
-    { -1.572807386e-02f, +2.780005227e-01f, +7.990784754e-01f, -5.866535639e-02f },
-    { -1.570364014e-02f, +2.776932054e-01f, +7.993688295e-01f, -5.867616710e-02f },
-    { -1.567922549e-02f, +2.773859980e-01f, +7.996590346e-01f, -5.868692187e-02f },
-    { -1.565482993e-02f, +2.770789004e-01f, +7.999490904e-01f, -5.869762062e-02f },
-    { -1.563045347e-02f, +2.767719129e-01f, +8.002389969e-01f, -5.870826329e-02f },
-    { -1.560609611e-02f, +2.764650354e-01f, +8.005287538e-01f, -5.871884977e-02f },
-    { -1.558175787e-02f, +2.761582682e-01f, +8.008183610e-01f, -5.872938000e-02f },
-    { -1.555743875e-02f, +2.758516114e-01f, +8.011078183e-01f, -5.873985390e-02f },
-    { -1.553313878e-02f, +2.755450649e-01f, +8.013971255e-01f, -5.875027137e-02f },
-    { -1.550885795e-02f, +2.752386291e-01f, +8.016862825e-01f, -5.876063235e-02f },
-    { -1.548459628e-02f, +2.749323038e-01f, +8.019752891e-01f, -5.877093675e-02f },
-    { -1.546035377e-02f, +2.746260894e-01f, +8.022641451e-01f, -5.878118449e-02f },
-    { -1.543613045e-02f, +2.743199858e-01f, +8.025528503e-01f, -5.879137549e-02f },
-    { -1.541192631e-02f, +2.740139932e-01f, +8.028414047e-01f, -5.880150966e-02f },
-    { -1.538774137e-02f, +2.737081117e-01f, +8.031298079e-01f, -5.881158693e-02f },
-    { -1.536357563e-02f, +2.734023414e-01f, +8.034180599e-01f, -5.882160722e-02f },
-    { -1.533942912e-02f, +2.730966824e-01f, +8.037061604e-01f, -5.883157045e-02f },
-    { -1.531530183e-02f, +2.727911348e-01f, +8.039941094e-01f, -5.884147653e-02f },
-    { -1.529119377e-02f, +2.724856987e-01f, +8.042819066e-01f, -5.885132538e-02f },
-    { -1.526710496e-02f, +2.721803743e-01f, +8.045695518e-01f, -5.886111692e-02f },
-    { -1.524303541e-02f, +2.718751616e-01f, +8.048570449e-01f, -5.887085108e-02f },
-    { -1.521898512e-02f, +2.715700607e-01f, +8.051443857e-01f, -5.888052777e-02f },
-    { -1.519495411e-02f, +2.712650718e-01f, +8.054315741e-01f, -5.889014690e-02f },
-    { -1.517094238e-02f, +2.709601949e-01f, +8.057186098e-01f, -5.889970841e-02f },
-    { -1.514694995e-02f, +2.706554301e-01f, +8.060054928e-01f, -5.890921220e-02f },
-    { -1.512297682e-02f, +2.703507777e-01f, +8.062922227e-01f, -5.891865819e-02f },
-    { -1.509902300e-02f, +2.700462376e-01f, +8.065787996e-01f, -5.892804632e-02f },
-    { -1.507508850e-02f, +2.697418099e-01f, +8.068652231e-01f, -5.893737648e-02f },
-    { -1.505117334e-02f, +2.694374949e-01f, +8.071514932e-01f, -5.894664861e-02f },
-    { -1.502727751e-02f, +2.691332925e-01f, +8.074376096e-01f, -5.895586262e-02f },
-    { -1.500340104e-02f, +2.688292029e-01f, +8.077235722e-01f, -5.896501843e-02f },
-    { -1.497954392e-02f, +2.685252263e-01f, +8.080093808e-01f, -5.897411596e-02f },
-    { -1.495570618e-02f, +2.682213626e-01f, +8.082950352e-01f, -5.898315513e-02f },
-    { -1.493188780e-02f, +2.679176120e-01f, +8.085805354e-01f, -5.899213585e-02f },
-    { -1.490808882e-02f, +2.676139746e-01f, +8.088658810e-01f, -5.900105805e-02f },
-    { -1.488430923e-02f, +2.673104506e-01f, +8.091510719e-01f, -5.900992164e-02f },
-    { -1.486054904e-02f, +2.670070400e-01f, +8.094361081e-01f, -5.901872654e-02f },
-    { -1.483680827e-02f, +2.667037429e-01f, +8.097209892e-01f, -5.902747268e-02f },
-    { -1.481308692e-02f, +2.664005594e-01f, +8.100057151e-01f, -5.903615996e-02f },
-    { -1.478938500e-02f, +2.660974897e-01f, +8.102902857e-01f, -5.904478831e-02f },
-    { -1.476570252e-02f, +2.657945338e-01f, +8.105747008e-01f, -5.905335765e-02f },
-    { -1.474203949e-02f, +2.654916918e-01f, +8.108589603e-01f, -5.906186790e-02f },
-    { -1.471839591e-02f, +2.651889639e-01f, +8.111430638e-01f, -5.907031897e-02f },
-    { -1.469477181e-02f, +2.648863501e-01f, +8.114270114e-01f, -5.907871078e-02f },
-    { -1.467116717e-02f, +2.645838506e-01f, +8.117108027e-01f, -5.908704325e-02f },
-    { -1.464758202e-02f, +2.642814655e-01f, +8.119944377e-01f, -5.909531630e-02f },
-    { -1.462401636e-02f, +2.639791948e-01f, +8.122779162e-01f, -5.910352985e-02f },
-    { -1.460047020e-02f, +2.636770386e-01f, +8.125612380e-01f, -5.911168382e-02f },
-    { -1.457694355e-02f, +2.633749972e-01f, +8.128444029e-01f, -5.911977812e-02f },
-    { -1.455343641e-02f, +2.630730705e-01f, +8.131274108e-01f, -5.912781267e-02f },
-    { -1.452994881e-02f, +2.627712587e-01f, +8.134102615e-01f, -5.913578740e-02f },
-    { -1.450648073e-02f, +2.624695618e-01f, +8.136929549e-01f, -5.914370221e-02f },
-    { -1.448303220e-02f, +2.621679801e-01f, +8.139754907e-01f, -5.915155704e-02f },
-    { -1.445960321e-02f, +2.618665135e-01f, +8.142578688e-01f, -5.915935179e-02f },
-    { -1.443619379e-02f, +2.615651622e-01f, +8.145400890e-01f, -5.916708638e-02f },
-    { -1.441280393e-02f, +2.612639263e-01f, +8.148221512e-01f, -5.917476074e-02f },
-    { -1.438943365e-02f, +2.609628058e-01f, +8.151040551e-01f, -5.918237478e-02f },
-    { -1.436608295e-02f, +2.606618010e-01f, +8.153858007e-01f, -5.918992842e-02f },
-    { -1.434275184e-02f, +2.603609118e-01f, +8.156673878e-01f, -5.919742158e-02f },
-    { -1.431944033e-02f, +2.600601385e-01f, +8.159488162e-01f, -5.920485418e-02f },
-    { -1.429614843e-02f, +2.597594810e-01f, +8.162300856e-01f, -5.921222613e-02f },
-    { -1.427287614e-02f, +2.594589396e-01f, +8.165111960e-01f, -5.921953735e-02f },
-    { -1.424962348e-02f, +2.591585142e-01f, +8.167921473e-01f, -5.922678777e-02f },
-    { -1.422639045e-02f, +2.588582051e-01f, +8.170729391e-01f, -5.923397729e-02f },
-    { -1.420317705e-02f, +2.585580122e-01f, +8.173535714e-01f, -5.924110584e-02f },
-    { -1.417998331e-02f, +2.582579358e-01f, +8.176340439e-01f, -5.924817333e-02f },
-    { -1.415680921e-02f, +2.579579758e-01f, +8.179143566e-01f, -5.925517969e-02f },
-    { -1.413365478e-02f, +2.576581325e-01f, +8.181945092e-01f, -5.926212483e-02f },
-    { -1.411052002e-02f, +2.573584058e-01f, +8.184745017e-01f, -5.926900867e-02f },
-    { -1.408740493e-02f, +2.570587960e-01f, +8.187543337e-01f, -5.927583113e-02f },
-    { -1.406430953e-02f, +2.567593031e-01f, +8.190340052e-01f, -5.928259213e-02f },
-    { -1.404123383e-02f, +2.564599271e-01f, +8.193135159e-01f, -5.928929157e-02f },
-    { -1.401817782e-02f, +2.561606683e-01f, +8.195928658e-01f, -5.929592939e-02f },
-    { -1.399514152e-02f, +2.558615267e-01f, +8.198720547e-01f, -5.930250550e-02f },
-    { -1.397212493e-02f, +2.555625024e-01f, +8.201510823e-01f, -5.930901982e-02f },
-    { -1.394912807e-02f, +2.552635955e-01f, +8.204299485e-01f, -5.931547226e-02f },
-    { -1.392615094e-02f, +2.549648062e-01f, +8.207086532e-01f, -5.932186275e-02f },
-    { -1.390319354e-02f, +2.546661344e-01f, +8.209871961e-01f, -5.932819120e-02f },
-    { -1.388025589e-02f, +2.543675803e-01f, +8.212655772e-01f, -5.933445753e-02f },
-    { -1.385733799e-02f, +2.540691440e-01f, +8.215437962e-01f, -5.934066165e-02f },
-    { -1.383443984e-02f, +2.537708257e-01f, +8.218218531e-01f, -5.934680349e-02f },
-    { -1.381156147e-02f, +2.534726253e-01f, +8.220997475e-01f, -5.935288297e-02f },
-    { -1.378870286e-02f, +2.531745431e-01f, +8.223774794e-01f, -5.935889999e-02f },
-    { -1.376586404e-02f, +2.528765790e-01f, +8.226550485e-01f, -5.936485448e-02f },
-    { -1.374304500e-02f, +2.525787333e-01f, +8.229324548e-01f, -5.937074636e-02f },
-    { -1.372024576e-02f, +2.522810059e-01f, +8.232096981e-01f, -5.937657555e-02f },
-    { -1.369746632e-02f, +2.519833971e-01f, +8.234867781e-01f, -5.938234196e-02f },
-    { -1.367470668e-02f, +2.516859068e-01f, +8.237636948e-01f, -5.938804550e-02f },
-    { -1.365196686e-02f, +2.513885353e-01f, +8.240404479e-01f, -5.939368611e-02f },
-    { -1.362924687e-02f, +2.510912825e-01f, +8.243170373e-01f, -5.939926369e-02f },
-    { -1.360654670e-02f, +2.507941486e-01f, +8.245934629e-01f, -5.940477816e-02f },
-    { -1.358386636e-02f, +2.504971337e-01f, +8.248697244e-01f, -5.941022944e-02f },
-    { -1.356120587e-02f, +2.502002379e-01f, +8.251458217e-01f, -5.941561746e-02f },
-    { -1.353856523e-02f, +2.499034613e-01f, +8.254217546e-01f, -5.942094212e-02f },
-    { -1.351594444e-02f, +2.496068040e-01f, +8.256975230e-01f, -5.942620334e-02f },
-    { -1.349334351e-02f, +2.493102660e-01f, +8.259731267e-01f, -5.943140104e-02f },
-    { -1.347076245e-02f, +2.490138475e-01f, +8.262485655e-01f, -5.943653515e-02f },
-    { -1.344820127e-02f, +2.487175486e-01f, +8.265238393e-01f, -5.944160557e-02f },
-    { -1.342565996e-02f, +2.484213694e-01f, +8.267989479e-01f, -5.944661222e-02f },
-    { -1.340313855e-02f, +2.481253099e-01f, +8.270738912e-01f, -5.945155503e-02f },
-    { -1.338063703e-02f, +2.478293703e-01f, +8.273486689e-01f, -5.945643390e-02f },
-    { -1.335815541e-02f, +2.475335507e-01f, +8.276232810e-01f, -5.946124877e-02f },
-    { -1.333569370e-02f, +2.472378511e-01f, +8.278977272e-01f, -5.946599953e-02f },
-    { -1.331325190e-02f, +2.469422717e-01f, +8.281720074e-01f, -5.947068612e-02f },
-    { -1.329083001e-02f, +2.466468125e-01f, +8.284461214e-01f, -5.947530845e-02f },
-    { -1.326842806e-02f, +2.463514737e-01f, +8.287200691e-01f, -5.947986644e-02f },
-    { -1.324604604e-02f, +2.460562553e-01f, +8.289938502e-01f, -5.948436000e-02f },
-    { -1.322368395e-02f, +2.457611574e-01f, +8.292674647e-01f, -5.948878905e-02f },
-    { -1.320134181e-02f, +2.454661802e-01f, +8.295409124e-01f, -5.949315351e-02f },
-    { -1.317901962e-02f, +2.451713237e-01f, +8.298141930e-01f, -5.949745330e-02f },
-    { -1.315671739e-02f, +2.448765881e-01f, +8.300873065e-01f, -5.950168834e-02f },
-    { -1.313443511e-02f, +2.445819733e-01f, +8.303602527e-01f, -5.950585853e-02f },
-    { -1.311217281e-02f, +2.442874796e-01f, +8.306330313e-01f, -5.950996381e-02f },
-    { -1.308993048e-02f, +2.439931070e-01f, +8.309056424e-01f, -5.951400408e-02f },
-    { -1.306770813e-02f, +2.436988556e-01f, +8.311780856e-01f, -5.951797926e-02f },
-    { -1.304550576e-02f, +2.434047255e-01f, +8.314503608e-01f, -5.952188928e-02f },
-    { -1.302332339e-02f, +2.431107168e-01f, +8.317224679e-01f, -5.952573404e-02f },
-    { -1.300116101e-02f, +2.428168296e-01f, +8.319944067e-01f, -5.952951347e-02f },
-    { -1.297901864e-02f, +2.425230639e-01f, +8.322661770e-01f, -5.953322748e-02f },
-    { -1.295689627e-02f, +2.422294200e-01f, +8.325377786e-01f, -5.953687600e-02f },
-    { -1.293479392e-02f, +2.419358978e-01f, +8.328092115e-01f, -5.954045893e-02f },
-    { -1.291271159e-02f, +2.416424975e-01f, +8.330804754e-01f, -5.954397620e-02f },
-    { -1.289064929e-02f, +2.413492191e-01f, +8.333515702e-01f, -5.954742771e-02f },
-    { -1.286860701e-02f, +2.410560629e-01f, +8.336224957e-01f, -5.955081340e-02f },
-    { -1.284658477e-02f, +2.407630287e-01f, +8.338932518e-01f, -5.955413318e-02f },
-    { -1.282458258e-02f, +2.404701168e-01f, +8.341638383e-01f, -5.955738696e-02f },
-    { -1.280260043e-02f, +2.401773273e-01f, +8.344342550e-01f, -5.956057466e-02f },
-    { -1.278063833e-02f, +2.398846601e-01f, +8.347045017e-01f, -5.956369619e-02f },
-    { -1.275869629e-02f, +2.395921155e-01f, +8.349745784e-01f, -5.956675149e-02f },
-    { -1.273677432e-02f, +2.392996936e-01f, +8.352444848e-01f, -5.956974045e-02f },
-    { -1.271487241e-02f, +2.390073943e-01f, +8.355142207e-01f, -5.957266301e-02f },
-    { -1.269299057e-02f, +2.387152178e-01f, +8.357837861e-01f, -5.957551907e-02f },
-    { -1.267112882e-02f, +2.384231642e-01f, +8.360531808e-01f, -5.957830856e-02f },
-    { -1.264928715e-02f, +2.381312337e-01f, +8.363224045e-01f, -5.958103139e-02f },
-    { -1.262746557e-02f, +2.378394262e-01f, +8.365914572e-01f, -5.958368747e-02f },
-    { -1.260566408e-02f, +2.375477418e-01f, +8.368603387e-01f, -5.958627674e-02f },
-    { -1.258388269e-02f, +2.372561808e-01f, +8.371290487e-01f, -5.958879909e-02f },
-    { -1.256212141e-02f, +2.369647431e-01f, +8.373975872e-01f, -5.959125445e-02f },
-    { -1.254038023e-02f, +2.366734288e-01f, +8.376659540e-01f, -5.959364274e-02f },
-    { -1.251865917e-02f, +2.363822381e-01f, +8.379341490e-01f, -5.959596388e-02f },
-    { -1.249695823e-02f, +2.360911710e-01f, +8.382021718e-01f, -5.959821777e-02f },
-    { -1.247527741e-02f, +2.358002277e-01f, +8.384700225e-01f, -5.960040434e-02f },
-    { -1.245361672e-02f, +2.355094081e-01f, +8.387377009e-01f, -5.960252351e-02f },
-    { -1.243197617e-02f, +2.352187125e-01f, +8.390052067e-01f, -5.960457519e-02f },
-    { -1.241035575e-02f, +2.349281409e-01f, +8.392725398e-01f, -5.960655929e-02f },
-    { -1.238875548e-02f, +2.346376934e-01f, +8.395397001e-01f, -5.960847575e-02f },
-    { -1.236717535e-02f, +2.343473700e-01f, +8.398066874e-01f, -5.961032446e-02f },
-    { -1.234561537e-02f, +2.340571709e-01f, +8.400735015e-01f, -5.961210535e-02f },
-    { -1.232407555e-02f, +2.337670962e-01f, +8.403401423e-01f, -5.961381834e-02f },
-    { -1.230255589e-02f, +2.334771460e-01f, +8.406066096e-01f, -5.961546335e-02f },
-    { -1.228105640e-02f, +2.331873202e-01f, +8.408729033e-01f, -5.961704028e-02f },
-    { -1.225957708e-02f, +2.328976192e-01f, +8.411390231e-01f, -5.961854906e-02f },
-    { -1.223811793e-02f, +2.326080428e-01f, +8.414049690e-01f, -5.961998961e-02f },
-    { -1.221667896e-02f, +2.323185913e-01f, +8.416707408e-01f, -5.962136183e-02f },
-    { -1.219526018e-02f, +2.320292646e-01f, +8.419363383e-01f, -5.962266566e-02f },
-    { -1.217386158e-02f, +2.317400630e-01f, +8.422017613e-01f, -5.962390099e-02f },
-    { -1.215248317e-02f, +2.314509865e-01f, +8.424670098e-01f, -5.962506776e-02f },
-    { -1.213112496e-02f, +2.311620351e-01f, +8.427320835e-01f, -5.962616588e-02f },
-    { -1.210978695e-02f, +2.308732090e-01f, +8.429969822e-01f, -5.962719526e-02f },
-    { -1.208846914e-02f, +2.305845082e-01f, +8.432617059e-01f, -5.962815583e-02f },
-    { -1.206717155e-02f, +2.302959329e-01f, +8.435262543e-01f, -5.962904749e-02f },
-    { -1.204589416e-02f, +2.300074831e-01f, +8.437906274e-01f, -5.962987017e-02f },
-    { -1.202463700e-02f, +2.297191590e-01f, +8.440548248e-01f, -5.963062378e-02f },
-    { -1.200340005e-02f, +2.294309606e-01f, +8.443188466e-01f, -5.963130824e-02f },
-    { -1.198218333e-02f, +2.291428879e-01f, +8.445826924e-01f, -5.963192347e-02f },
-    { -1.196098683e-02f, +2.288549412e-01f, +8.448463623e-01f, -5.963246938e-02f },
-    { -1.193981057e-02f, +2.285671204e-01f, +8.451098559e-01f, -5.963294588e-02f },
-    { -1.191865455e-02f, +2.282794257e-01f, +8.453731732e-01f, -5.963335291e-02f },
-    { -1.189751876e-02f, +2.279918571e-01f, +8.456363139e-01f, -5.963369036e-02f },
-    { -1.187640322e-02f, +2.277044148e-01f, +8.458992780e-01f, -5.963395817e-02f },
-    { -1.185530793e-02f, +2.274170988e-01f, +8.461620653e-01f, -5.963415624e-02f },
-    { -1.183423289e-02f, +2.271299092e-01f, +8.464246755e-01f, -5.963428449e-02f },
-    { -1.181317810e-02f, +2.268428462e-01f, +8.466871086e-01f, -5.963434285e-02f },
-    { -1.179214358e-02f, +2.265559097e-01f, +8.469493644e-01f, -5.963433122e-02f },
-    { -1.177112931e-02f, +2.262690999e-01f, +8.472114428e-01f, -5.963424952e-02f },
-    { -1.175013531e-02f, +2.259824169e-01f, +8.474733435e-01f, -5.963409767e-02f },
-    { -1.172916159e-02f, +2.256958607e-01f, +8.477350664e-01f, -5.963387559e-02f },
-    { -1.170820813e-02f, +2.254094315e-01f, +8.479966114e-01f, -5.963358319e-02f },
-    { -1.168727495e-02f, +2.251231293e-01f, +8.482579783e-01f, -5.963322039e-02f },
-    { -1.166636205e-02f, +2.248369542e-01f, +8.485191669e-01f, -5.963278711e-02f },
-    { -1.164546944e-02f, +2.245509063e-01f, +8.487801771e-01f, -5.963228326e-02f },
-    { -1.162459711e-02f, +2.242649857e-01f, +8.490410088e-01f, -5.963170876e-02f },
-    { -1.160374507e-02f, +2.239791925e-01f, +8.493016617e-01f, -5.963106352e-02f },
-    { -1.158291333e-02f, +2.236935267e-01f, +8.495621358e-01f, -5.963034747e-02f },
-    { -1.156210188e-02f, +2.234079885e-01f, +8.498224307e-01f, -5.962956051e-02f },
-    { -1.154131073e-02f, +2.231225780e-01f, +8.500825465e-01f, -5.962870257e-02f },
-    { -1.152053989e-02f, +2.228372951e-01f, +8.503424830e-01f, -5.962777357e-02f },
-    { -1.149978935e-02f, +2.225521401e-01f, +8.506022399e-01f, -5.962677341e-02f },
-    { -1.147905912e-02f, +2.222671129e-01f, +8.508618171e-01f, -5.962570201e-02f },
-    { -1.145834920e-02f, +2.219822138e-01f, +8.511212145e-01f, -5.962455930e-02f },
-    { -1.143765960e-02f, +2.216974426e-01f, +8.513804320e-01f, -5.962334519e-02f },
-    { -1.141699032e-02f, +2.214127997e-01f, +8.516394693e-01f, -5.962205959e-02f },
-    { -1.139634135e-02f, +2.211282850e-01f, +8.518983262e-01f, -5.962070242e-02f },
-    { -1.137571272e-02f, +2.208438986e-01f, +8.521570028e-01f, -5.961927360e-02f },
-    { -1.135510441e-02f, +2.205596406e-01f, +8.524154987e-01f, -5.961777305e-02f },
-    { -1.133451643e-02f, +2.202755110e-01f, +8.526738139e-01f, -5.961620067e-02f },
-    { -1.131394878e-02f, +2.199915101e-01f, +8.529319481e-01f, -5.961455639e-02f },
-    { -1.129340147e-02f, +2.197076378e-01f, +8.531899012e-01f, -5.961284013e-02f },
-    { -1.127287449e-02f, +2.194238943e-01f, +8.534476731e-01f, -5.961105179e-02f },
-    { -1.125236786e-02f, +2.191402796e-01f, +8.537052637e-01f, -5.960919130e-02f },
-    { -1.123188157e-02f, +2.188567938e-01f, +8.539626726e-01f, -5.960725858e-02f },
-    { -1.121141563e-02f, +2.185734369e-01f, +8.542198999e-01f, -5.960525353e-02f },
-    { -1.119097004e-02f, +2.182902092e-01f, +8.544769453e-01f, -5.960317608e-02f },
-    { -1.117054480e-02f, +2.180071107e-01f, +8.547338087e-01f, -5.960102614e-02f },
-    { -1.115013991e-02f, +2.177241413e-01f, +8.549904899e-01f, -5.959880364e-02f },
-    { -1.112975538e-02f, +2.174413013e-01f, +8.552469888e-01f, -5.959650847e-02f },
-    { -1.110939121e-02f, +2.171585908e-01f, +8.555033052e-01f, -5.959414057e-02f },
-    { -1.108904740e-02f, +2.168760097e-01f, +8.557594390e-01f, -5.959169984e-02f },
-    { -1.106872396e-02f, +2.165935582e-01f, +8.560153900e-01f, -5.958918621e-02f },
-    { -1.104842088e-02f, +2.163112364e-01f, +8.562711580e-01f, -5.958659959e-02f },
-    { -1.102813817e-02f, +2.160290443e-01f, +8.565267430e-01f, -5.958393990e-02f },
-    { -1.100787583e-02f, +2.157469820e-01f, +8.567821446e-01f, -5.958120705e-02f },
-    { -1.098763386e-02f, +2.154650497e-01f, +8.570373629e-01f, -5.957840096e-02f },
-    { -1.096741227e-02f, +2.151832473e-01f, +8.572923976e-01f, -5.957552154e-02f },
-    { -1.094721106e-02f, +2.149015750e-01f, +8.575472486e-01f, -5.957256872e-02f },
-    { -1.092703022e-02f, +2.146200329e-01f, +8.578019157e-01f, -5.956954241e-02f },
-    { -1.090686977e-02f, +2.143386210e-01f, +8.580563988e-01f, -5.956644252e-02f },
-    { -1.088672970e-02f, +2.140573395e-01f, +8.583106977e-01f, -5.956326897e-02f },
-    { -1.086661002e-02f, +2.137761883e-01f, +8.585648123e-01f, -5.956002168e-02f },
-    { -1.084651073e-02f, +2.134951677e-01f, +8.588187423e-01f, -5.955670057e-02f },
-    { -1.082643182e-02f, +2.132142776e-01f, +8.590724878e-01f, -5.955330554e-02f },
-    { -1.080637331e-02f, +2.129335181e-01f, +8.593260484e-01f, -5.954983652e-02f },
-    { -1.078633519e-02f, +2.126528894e-01f, +8.595794240e-01f, -5.954629343e-02f },
-    { -1.076631747e-02f, +2.123723915e-01f, +8.598326146e-01f, -5.954267617e-02f },
-    { -1.074632015e-02f, +2.120920245e-01f, +8.600856199e-01f, -5.953898467e-02f },
-    { -1.072634322e-02f, +2.118117885e-01f, +8.603384398e-01f, -5.953521884e-02f },
-    { -1.070638669e-02f, +2.115316835e-01f, +8.605910741e-01f, -5.953137860e-02f },
-    { -1.068645057e-02f, +2.112517097e-01f, +8.608435227e-01f, -5.952746386e-02f },
-    { -1.066653486e-02f, +2.109718671e-01f, +8.610957855e-01f, -5.952347454e-02f },
-    { -1.064663954e-02f, +2.106921557e-01f, +8.613478622e-01f, -5.951941056e-02f },
-    { -1.062676464e-02f, +2.104125758e-01f, +8.615997527e-01f, -5.951527184e-02f },
-    { -1.060691015e-02f, +2.101331273e-01f, +8.618514569e-01f, -5.951105828e-02f },
-    { -1.058707606e-02f, +2.098538103e-01f, +8.621029746e-01f, -5.950676981e-02f },
-    { -1.056726239e-02f, +2.095746250e-01f, +8.623543057e-01f, -5.950240634e-02f },
-    { -1.054746914e-02f, +2.092955714e-01f, +8.626054500e-01f, -5.949796779e-02f },
-    { -1.052769630e-02f, +2.090166495e-01f, +8.628564073e-01f, -5.949345407e-02f },
-    { -1.050794387e-02f, +2.087378595e-01f, +8.631071776e-01f, -5.948886510e-02f },
-    { -1.048821187e-02f, +2.084592015e-01f, +8.633577606e-01f, -5.948420080e-02f },
-    { -1.046850028e-02f, +2.081806754e-01f, +8.636081562e-01f, -5.947946108e-02f },
-    { -1.044880911e-02f, +2.079022815e-01f, +8.638583642e-01f, -5.947464586e-02f },
-    { -1.042913837e-02f, +2.076240197e-01f, +8.641083845e-01f, -5.946975506e-02f },
-    { -1.040948805e-02f, +2.073458902e-01f, +8.643582170e-01f, -5.946478859e-02f },
-    { -1.038985815e-02f, +2.070678930e-01f, +8.646078615e-01f, -5.945974637e-02f },
-    { -1.037024868e-02f, +2.067900282e-01f, +8.648573178e-01f, -5.945462831e-02f },
-    { -1.035065964e-02f, +2.065122959e-01f, +8.651065858e-01f, -5.944943433e-02f },
-    { -1.033109103e-02f, +2.062346962e-01f, +8.653556654e-01f, -5.944416434e-02f },
-    { -1.031154284e-02f, +2.059572292e-01f, +8.656045563e-01f, -5.943881827e-02f },
-    { -1.029201508e-02f, +2.056798948e-01f, +8.658532585e-01f, -5.943339603e-02f },
-    { -1.027250776e-02f, +2.054026933e-01f, +8.661017718e-01f, -5.942789753e-02f },
-    { -1.025302087e-02f, +2.051256246e-01f, +8.663500959e-01f, -5.942232269e-02f },
-    { -1.023355441e-02f, +2.048486889e-01f, +8.665982309e-01f, -5.941667144e-02f },
-    { -1.021410838e-02f, +2.045718862e-01f, +8.668461765e-01f, -5.941094367e-02f },
-    { -1.019468279e-02f, +2.042952167e-01f, +8.670939326e-01f, -5.940513931e-02f },
-    { -1.017527764e-02f, +2.040186803e-01f, +8.673414990e-01f, -5.939925828e-02f },
-    { -1.015589292e-02f, +2.037422772e-01f, +8.675888756e-01f, -5.939330049e-02f },
-    { -1.013652864e-02f, +2.034660075e-01f, +8.678360622e-01f, -5.938726586e-02f },
-    { -1.011718480e-02f, +2.031898712e-01f, +8.680830587e-01f, -5.938115430e-02f },
-    { -1.009786140e-02f, +2.029138683e-01f, +8.683298650e-01f, -5.937496574e-02f },
-    { -1.007855843e-02f, +2.026379991e-01f, +8.685764808e-01f, -5.936870008e-02f },
-    { -1.005927591e-02f, +2.023622635e-01f, +8.688229060e-01f, -5.936235724e-02f },
-    { -1.004001383e-02f, +2.020866616e-01f, +8.690691405e-01f, -5.935593714e-02f },
-    { -1.002077218e-02f, +2.018111936e-01f, +8.693151841e-01f, -5.934943969e-02f },
-    { -1.000155098e-02f, +2.015358594e-01f, +8.695610368e-01f, -5.934286482e-02f },
-    { -9.982350225e-03f, +2.012606592e-01f, +8.698066982e-01f, -5.933621243e-02f },
-    { -9.963169910e-03f, +2.009855930e-01f, +8.700521683e-01f, -5.932948245e-02f },
-    { -9.944010038e-03f, +2.007106609e-01f, +8.702974470e-01f, -5.932267479e-02f },
-    { -9.924870610e-03f, +2.004358631e-01f, +8.705425340e-01f, -5.931578936e-02f },
-    { -9.905751626e-03f, +2.001611994e-01f, +8.707874293e-01f, -5.930882608e-02f },
-    { -9.886653086e-03f, +1.998866701e-01f, +8.710321326e-01f, -5.930178487e-02f },
-    { -9.867574990e-03f, +1.996122753e-01f, +8.712766439e-01f, -5.929466565e-02f },
-    { -9.848517340e-03f, +1.993380149e-01f, +8.715209630e-01f, -5.928746832e-02f },
-    { -9.829480135e-03f, +1.990638891e-01f, +8.717650897e-01f, -5.928019281e-02f },
-    { -9.810463375e-03f, +1.987898979e-01f, +8.720090239e-01f, -5.927283903e-02f },
-    { -9.791467061e-03f, +1.985160414e-01f, +8.722527654e-01f, -5.926540690e-02f },
-    { -9.772491192e-03f, +1.982423197e-01f, +8.724963141e-01f, -5.925789634e-02f },
-    { -9.753535770e-03f, +1.979687329e-01f, +8.727396699e-01f, -5.925030726e-02f },
-    { -9.734600793e-03f, +1.976952810e-01f, +8.729828325e-01f, -5.924263957e-02f },
-    { -9.715686262e-03f, +1.974219642e-01f, +8.732258019e-01f, -5.923489319e-02f },
-    { -9.696792177e-03f, +1.971487824e-01f, +8.734685779e-01f, -5.922706804e-02f },
-    { -9.677918538e-03f, +1.968757357e-01f, +8.737111603e-01f, -5.921916404e-02f },
-    { -9.659065344e-03f, +1.966028244e-01f, +8.739535491e-01f, -5.921118110e-02f },
-    { -9.640232597e-03f, +1.963300483e-01f, +8.741957439e-01f, -5.920311914e-02f },
-    { -9.621420295e-03f, +1.960574076e-01f, +8.744377448e-01f, -5.919497807e-02f },
-    { -9.602628439e-03f, +1.957849023e-01f, +8.746795516e-01f, -5.918675781e-02f },
-    { -9.583857028e-03f, +1.955125326e-01f, +8.749211640e-01f, -5.917845827e-02f },
-    { -9.565106062e-03f, +1.952402985e-01f, +8.751625821e-01f, -5.917007938e-02f },
-    { -9.546375540e-03f, +1.949682000e-01f, +8.754038055e-01f, -5.916162104e-02f },
-    { -9.527665464e-03f, +1.946962373e-01f, +8.756448342e-01f, -5.915308317e-02f },
-    { -9.508975831e-03f, +1.944244105e-01f, +8.758856680e-01f, -5.914446570e-02f },
-    { -9.490306643e-03f, +1.941527195e-01f, +8.761263068e-01f, -5.913576853e-02f },
-    { -9.471657898e-03f, +1.938811645e-01f, +8.763667504e-01f, -5.912699159e-02f },
-    { -9.453029596e-03f, +1.936097455e-01f, +8.766069987e-01f, -5.911813478e-02f },
-    { -9.434421737e-03f, +1.933384626e-01f, +8.768470516e-01f, -5.910919802e-02f },
-    { -9.415834320e-03f, +1.930673159e-01f, +8.770869088e-01f, -5.910018124e-02f },
-    { -9.397267344e-03f, +1.927963055e-01f, +8.773265703e-01f, -5.909108434e-02f },
-    { -9.378720810e-03f, +1.925254314e-01f, +8.775660358e-01f, -5.908190725e-02f },
-    { -9.360194716e-03f, +1.922546937e-01f, +8.778053053e-01f, -5.907264987e-02f },
-    { -9.341689062e-03f, +1.919840925e-01f, +8.780443786e-01f, -5.906331213e-02f },
-    { -9.323203848e-03f, +1.917136278e-01f, +8.782832556e-01f, -5.905389393e-02f },
-    { -9.304739072e-03f, +1.914432997e-01f, +8.785219361e-01f, -5.904439521e-02f },
-    { -9.286294734e-03f, +1.911731083e-01f, +8.787604199e-01f, -5.903481587e-02f },
-    { -9.267870833e-03f, +1.909030537e-01f, +8.789987070e-01f, -5.902515582e-02f },
-    { -9.249467369e-03f, +1.906331359e-01f, +8.792367971e-01f, -5.901541499e-02f },
-    { -9.231084340e-03f, +1.903633550e-01f, +8.794746902e-01f, -5.900559330e-02f },
-    { -9.212721746e-03f, +1.900937110e-01f, +8.797123860e-01f, -5.899569065e-02f },
-    { -9.194379586e-03f, +1.898242041e-01f, +8.799498845e-01f, -5.898570696e-02f },
-    { -9.176057859e-03f, +1.895548343e-01f, +8.801871854e-01f, -5.897564215e-02f },
-    { -9.157756564e-03f, +1.892856017e-01f, +8.804242888e-01f, -5.896549614e-02f },
-    { -9.139475700e-03f, +1.890165064e-01f, +8.806611943e-01f, -5.895526884e-02f },
-    { -9.121215266e-03f, +1.887475484e-01f, +8.808979018e-01f, -5.894496016e-02f },
-    { -9.102975262e-03f, +1.884787277e-01f, +8.811344113e-01f, -5.893457003e-02f },
-    { -9.084755685e-03f, +1.882100446e-01f, +8.813707226e-01f, -5.892409837e-02f },
-    { -9.066556536e-03f, +1.879414989e-01f, +8.816068354e-01f, -5.891354507e-02f },
-    { -9.048377812e-03f, +1.876730909e-01f, +8.818427498e-01f, -5.890291007e-02f },
-    { -9.030219514e-03f, +1.874048205e-01f, +8.820784655e-01f, -5.889219328e-02f },
-    { -9.012081638e-03f, +1.871366879e-01f, +8.823139824e-01f, -5.888139461e-02f },
-    { -8.993964185e-03f, +1.868686931e-01f, +8.825493003e-01f, -5.887051398e-02f },
-    { -8.975867154e-03f, +1.866008361e-01f, +8.827844191e-01f, -5.885955131e-02f },
-    { -8.957790542e-03f, +1.863331172e-01f, +8.830193387e-01f, -5.884850651e-02f },
-    { -8.939734348e-03f, +1.860655362e-01f, +8.832540589e-01f, -5.883737950e-02f },
-    { -8.921698572e-03f, +1.857980933e-01f, +8.834885795e-01f, -5.882617019e-02f },
-    { -8.903683211e-03f, +1.855307886e-01f, +8.837229005e-01f, -5.881487851e-02f },
-    { -8.885688265e-03f, +1.852636221e-01f, +8.839570217e-01f, -5.880350436e-02f },
-    { -8.867713732e-03f, +1.849965939e-01f, +8.841909429e-01f, -5.879204767e-02f },
-    { -8.849759611e-03f, +1.847297040e-01f, +8.844246640e-01f, -5.878050834e-02f },
-    { -8.831825899e-03f, +1.844629526e-01f, +8.846581849e-01f, -5.876888630e-02f },
-    { -8.813912596e-03f, +1.841963397e-01f, +8.848915054e-01f, -5.875718146e-02f },
-    { -8.796019700e-03f, +1.839298653e-01f, +8.851246253e-01f, -5.874539374e-02f },
-    { -8.778147210e-03f, +1.836635296e-01f, +8.853575446e-01f, -5.873352306e-02f },
-    { -8.760295123e-03f, +1.833973325e-01f, +8.855902631e-01f, -5.872156932e-02f },
-    { -8.742463438e-03f, +1.831312743e-01f, +8.858227806e-01f, -5.870953245e-02f },
-    { -8.724652154e-03f, +1.828653548e-01f, +8.860550970e-01f, -5.869741236e-02f },
-    { -8.706861268e-03f, +1.825995743e-01f, +8.862872121e-01f, -5.868520898e-02f },
-    { -8.689090780e-03f, +1.823339328e-01f, +8.865191259e-01f, -5.867292220e-02f },
-    { -8.671340686e-03f, +1.820684302e-01f, +8.867508381e-01f, -5.866055196e-02f },
-    { -8.653610986e-03f, +1.818030668e-01f, +8.869823487e-01f, -5.864809816e-02f },
-    { -8.635901678e-03f, +1.815378426e-01f, +8.872136574e-01f, -5.863556073e-02f },
-    { -8.618212759e-03f, +1.812727576e-01f, +8.874447642e-01f, -5.862293958e-02f },
-    { -8.600544229e-03f, +1.810078118e-01f, +8.876756689e-01f, -5.861023462e-02f },
-    { -8.582896084e-03f, +1.807430055e-01f, +8.879063714e-01f, -5.859744577e-02f },
-    { -8.565268323e-03f, +1.804783386e-01f, +8.881368715e-01f, -5.858457295e-02f },
-    { -8.547660944e-03f, +1.802138112e-01f, +8.883671691e-01f, -5.857161608e-02f },
-    { -8.530073945e-03f, +1.799494234e-01f, +8.885972640e-01f, -5.855857506e-02f },
-    { -8.512507324e-03f, +1.796851751e-01f, +8.888271561e-01f, -5.854544983e-02f },
-    { -8.494961078e-03f, +1.794210666e-01f, +8.890568452e-01f, -5.853224028e-02f },
-    { -8.477435207e-03f, +1.791570979e-01f, +8.892863313e-01f, -5.851894634e-02f },
-    { -8.459929707e-03f, +1.788932690e-01f, +8.895156142e-01f, -5.850556793e-02f },
-    { -8.442444576e-03f, +1.786295800e-01f, +8.897446936e-01f, -5.849210496e-02f },
-    { -8.424979813e-03f, +1.783660309e-01f, +8.899735696e-01f, -5.847855735e-02f },
-    { -8.407535414e-03f, +1.781026219e-01f, +8.902022419e-01f, -5.846492501e-02f },
-    { -8.390111379e-03f, +1.778393529e-01f, +8.904307105e-01f, -5.845120786e-02f },
-    { -8.372707704e-03f, +1.775762242e-01f, +8.906589751e-01f, -5.843740582e-02f },
-    { -8.355324387e-03f, +1.773132356e-01f, +8.908870357e-01f, -5.842351880e-02f },
-    { -8.337961425e-03f, +1.770503873e-01f, +8.911148920e-01f, -5.840954672e-02f },
-    { -8.320618817e-03f, +1.767876794e-01f, +8.913425440e-01f, -5.839548949e-02f },
-    { -8.303296561e-03f, +1.765251119e-01f, +8.915699915e-01f, -5.838134704e-02f },
-    { -8.285994652e-03f, +1.762626848e-01f, +8.917972344e-01f, -5.836711927e-02f },
-    { -8.268713090e-03f, +1.760003983e-01f, +8.920242725e-01f, -5.835280610e-02f },
-    { -8.251451871e-03f, +1.757382524e-01f, +8.922511057e-01f, -5.833840746e-02f },
-    { -8.234210994e-03f, +1.754762472e-01f, +8.924777339e-01f, -5.832392325e-02f },
-    { -8.216990455e-03f, +1.752143827e-01f, +8.927041569e-01f, -5.830935339e-02f },
-    { -8.199790252e-03f, +1.749526590e-01f, +8.929303746e-01f, -5.829469780e-02f },
-    { -8.182610382e-03f, +1.746910762e-01f, +8.931563868e-01f, -5.827995640e-02f },
-    { -8.165450843e-03f, +1.744296343e-01f, +8.933821934e-01f, -5.826512910e-02f },
-    { -8.148311631e-03f, +1.741683333e-01f, +8.936077942e-01f, -5.825021582e-02f },
-    { -8.131192745e-03f, +1.739071734e-01f, +8.938331892e-01f, -5.823521647e-02f },
-    { -8.114094182e-03f, +1.736461547e-01f, +8.940583782e-01f, -5.822013097e-02f },
-    { -8.097015938e-03f, +1.733852771e-01f, +8.942833610e-01f, -5.820495924e-02f },
-    { -8.079958012e-03f, +1.731245407e-01f, +8.945081375e-01f, -5.818970119e-02f },
-    { -8.062920399e-03f, +1.728639457e-01f, +8.947327076e-01f, -5.817435673e-02f },
-    { -8.045903098e-03f, +1.726034920e-01f, +8.949570711e-01f, -5.815892580e-02f },
-    { -8.028906105e-03f, +1.723431797e-01f, +8.951812279e-01f, -5.814340830e-02f },
-    { -8.011929418e-03f, +1.720830089e-01f, +8.954051779e-01f, -5.812780414e-02f },
-    { -7.994973033e-03f, +1.718229797e-01f, +8.956289209e-01f, -5.811211325e-02f },
-    { -7.978036948e-03f, +1.715630920e-01f, +8.958524568e-01f, -5.809633554e-02f },
-    { -7.961121159e-03f, +1.713033461e-01f, +8.960757854e-01f, -5.808047093e-02f },
-    { -7.944225664e-03f, +1.710437419e-01f, +8.962989066e-01f, -5.806451933e-02f },
-    { -7.927350459e-03f, +1.707842794e-01f, +8.965218203e-01f, -5.804848066e-02f },
-    { -7.910495542e-03f, +1.705249588e-01f, +8.967445263e-01f, -5.803235484e-02f },
-    { -7.893660909e-03f, +1.702657802e-01f, +8.969670245e-01f, -5.801614178e-02f },
-    { -7.876846558e-03f, +1.700067435e-01f, +8.971893148e-01f, -5.799984140e-02f },
-    { -7.860052484e-03f, +1.697478489e-01f, +8.974113969e-01f, -5.798345361e-02f },
-    { -7.843278685e-03f, +1.694890963e-01f, +8.976332709e-01f, -5.796697834e-02f },
-    { -7.826525157e-03f, +1.692304860e-01f, +8.978549365e-01f, -5.795041550e-02f },
-    { -7.809791898e-03f, +1.689720178e-01f, +8.980763937e-01f, -5.793376500e-02f },
-    { -7.793078904e-03f, +1.687136919e-01f, +8.982976422e-01f, -5.791702676e-02f },
-    { -7.776386171e-03f, +1.684555084e-01f, +8.985186819e-01f, -5.790020070e-02f },
-    { -7.759713697e-03f, +1.681974672e-01f, +8.987395128e-01f, -5.788328673e-02f },
-    { -7.743061477e-03f, +1.679395686e-01f, +8.989601346e-01f, -5.786628478e-02f },
-    { -7.726429509e-03f, +1.676818124e-01f, +8.991805472e-01f, -5.784919475e-02f },
-    { -7.709817790e-03f, +1.674241988e-01f, +8.994007506e-01f, -5.783201657e-02f },
-    { -7.693226314e-03f, +1.671667279e-01f, +8.996207445e-01f, -5.781475014e-02f },
-    { -7.676655080e-03f, +1.669093997e-01f, +8.998405288e-01f, -5.779739540e-02f },
-    { -7.660104084e-03f, +1.666522142e-01f, +9.000601034e-01f, -5.777995224e-02f },
-    { -7.643573321e-03f, +1.663951716e-01f, +9.002794682e-01f, -5.776242060e-02f },
-    { -7.627062789e-03f, +1.661382718e-01f, +9.004986230e-01f, -5.774480038e-02f },
-    { -7.610572484e-03f, +1.658815150e-01f, +9.007175676e-01f, -5.772709151e-02f },
-    { -7.594102403e-03f, +1.656249011e-01f, +9.009363021e-01f, -5.770929389e-02f },
-    { -7.577652540e-03f, +1.653684303e-01f, +9.011548261e-01f, -5.769140745e-02f },
-    { -7.561222894e-03f, +1.651121027e-01f, +9.013731396e-01f, -5.767343210e-02f },
-    { -7.544813460e-03f, +1.648559182e-01f, +9.015912425e-01f, -5.765536777e-02f },
-    { -7.528424234e-03f, +1.645998769e-01f, +9.018091345e-01f, -5.763721435e-02f },
-    { -7.512055213e-03f, +1.643439789e-01f, +9.020268157e-01f, -5.761897178e-02f },
-    { -7.495706392e-03f, +1.640882243e-01f, +9.022442858e-01f, -5.760063997e-02f },
-    { -7.479377769e-03f, +1.638326131e-01f, +9.024615447e-01f, -5.758221883e-02f },
-    { -7.463069339e-03f, +1.635771453e-01f, +9.026785922e-01f, -5.756370829e-02f },
-    { -7.446781098e-03f, +1.633218211e-01f, +9.028954283e-01f, -5.754510825e-02f },
-    { -7.430513042e-03f, +1.630666404e-01f, +9.031120528e-01f, -5.752641864e-02f },
-    { -7.414265167e-03f, +1.628116034e-01f, +9.033284656e-01f, -5.750763937e-02f },
-    { -7.398037471e-03f, +1.625567100e-01f, +9.035446666e-01f, -5.748877036e-02f },
-    { -7.381829947e-03f, +1.623019604e-01f, +9.037606555e-01f, -5.746981153e-02f },
-    { -7.365642593e-03f, +1.620473546e-01f, +9.039764323e-01f, -5.745076279e-02f },
-    { -7.349475404e-03f, +1.617928927e-01f, +9.041919969e-01f, -5.743162405e-02f },
-    { -7.333328376e-03f, +1.615385747e-01f, +9.044073490e-01f, -5.741239524e-02f },
-    { -7.317201506e-03f, +1.612844007e-01f, +9.046224887e-01f, -5.739307627e-02f },
-    { -7.301094788e-03f, +1.610303707e-01f, +9.048374156e-01f, -5.737366706e-02f },
-    { -7.285008220e-03f, +1.607764848e-01f, +9.050521298e-01f, -5.735416753e-02f },
-    { -7.268941796e-03f, +1.605227430e-01f, +9.052666311e-01f, -5.733457759e-02f },
-    { -7.252895512e-03f, +1.602691455e-01f, +9.054809193e-01f, -5.731489716e-02f },
-    { -7.236869364e-03f, +1.600156922e-01f, +9.056949943e-01f, -5.729512615e-02f },
-    { -7.220863348e-03f, +1.597623832e-01f, +9.059088560e-01f, -5.727526448e-02f },
-    { -7.204877460e-03f, +1.595092186e-01f, +9.061225043e-01f, -5.725531208e-02f },
-    { -7.188911695e-03f, +1.592561984e-01f, +9.063359389e-01f, -5.723526885e-02f },
-    { -7.172966049e-03f, +1.590033227e-01f, +9.065491599e-01f, -5.721513471e-02f },
-    { -7.157040517e-03f, +1.587505915e-01f, +9.067621670e-01f, -5.719490958e-02f },
-    { -7.141135096e-03f, +1.584980049e-01f, +9.069749601e-01f, -5.717459338e-02f },
-    { -7.125249780e-03f, +1.582455630e-01f, +9.071875391e-01f, -5.715418602e-02f },
-    { -7.109384565e-03f, +1.579932657e-01f, +9.073999039e-01f, -5.713368743e-02f },
-    { -7.093539446e-03f, +1.577411133e-01f, +9.076120543e-01f, -5.711309750e-02f },
-    { -7.077714420e-03f, +1.574891056e-01f, +9.078239902e-01f, -5.709241618e-02f },
-    { -7.061909482e-03f, +1.572372428e-01f, +9.080357115e-01f, -5.707164336e-02f },
-    { -7.046124626e-03f, +1.569855249e-01f, +9.082472180e-01f, -5.705077897e-02f },
-    { -7.030359849e-03f, +1.567339520e-01f, +9.084585096e-01f, -5.702982292e-02f },
-    { -7.014615145e-03f, +1.564825241e-01f, +9.086695861e-01f, -5.700877514e-02f },
-    { -6.998890510e-03f, +1.562312413e-01f, +9.088804476e-01f, -5.698763554e-02f },
-    { -6.983185940e-03f, +1.559801037e-01f, +9.090910937e-01f, -5.696640402e-02f },
-    { -6.967501430e-03f, +1.557291112e-01f, +9.093015244e-01f, -5.694508053e-02f },
-    { -6.951836974e-03f, +1.554782640e-01f, +9.095117396e-01f, -5.692366496e-02f },
-    { -6.936192569e-03f, +1.552275620e-01f, +9.097217391e-01f, -5.690215723e-02f },
-    { -6.920568209e-03f, +1.549770055e-01f, +9.099315228e-01f, -5.688055727e-02f },
-    { -6.904963889e-03f, +1.547265943e-01f, +9.101410905e-01f, -5.685886499e-02f },
-    { -6.889379605e-03f, +1.544763286e-01f, +9.103504422e-01f, -5.683708031e-02f },
-    { -6.873815352e-03f, +1.542262084e-01f, +9.105595777e-01f, -5.681520314e-02f },
-    { -6.858271125e-03f, +1.539762337e-01f, +9.107684969e-01f, -5.679323340e-02f },
-    { -6.842746919e-03f, +1.537264047e-01f, +9.109771996e-01f, -5.677117101e-02f },
-    { -6.827242728e-03f, +1.534767213e-01f, +9.111856858e-01f, -5.674901589e-02f },
-    { -6.811758549e-03f, +1.532271837e-01f, +9.113939552e-01f, -5.672676795e-02f },
-    { -6.796294376e-03f, +1.529777918e-01f, +9.116020078e-01f, -5.670442710e-02f },
-    { -6.780850204e-03f, +1.527285458e-01f, +9.118098434e-01f, -5.668199328e-02f },
-    { -6.765426027e-03f, +1.524794457e-01f, +9.120174619e-01f, -5.665946638e-02f },
-    { -6.750021842e-03f, +1.522304914e-01f, +9.122248632e-01f, -5.663684634e-02f },
-    { -6.734637642e-03f, +1.519816832e-01f, +9.124320471e-01f, -5.661413307e-02f },
-    { -6.719273423e-03f, +1.517330210e-01f, +9.126390136e-01f, -5.659132648e-02f },
-    { -6.703929179e-03f, +1.514845048e-01f, +9.128457625e-01f, -5.656842649e-02f },
-    { -6.688604905e-03f, +1.512361348e-01f, +9.130522936e-01f, -5.654543302e-02f },
-    { -6.673300597e-03f, +1.509879110e-01f, +9.132586068e-01f, -5.652234599e-02f },
-    { -6.658016248e-03f, +1.507398335e-01f, +9.134647021e-01f, -5.649916531e-02f },
-    { -6.642751853e-03f, +1.504919022e-01f, +9.136705792e-01f, -5.647589090e-02f },
-    { -6.627507408e-03f, +1.502441173e-01f, +9.138762381e-01f, -5.645252268e-02f },
-    { -6.612282907e-03f, +1.499964787e-01f, +9.140816786e-01f, -5.642906057e-02f },
-    { -6.597078344e-03f, +1.497489866e-01f, +9.142869006e-01f, -5.640550448e-02f },
-    { -6.581893714e-03f, +1.495016410e-01f, +9.144919040e-01f, -5.638185433e-02f },
-    { -6.566729012e-03f, +1.492544420e-01f, +9.146966886e-01f, -5.635811004e-02f },
-    { -6.551584232e-03f, +1.490073895e-01f, +9.149012543e-01f, -5.633427152e-02f },
-    { -6.536459369e-03f, +1.487604837e-01f, +9.151056011e-01f, -5.631033869e-02f },
-    { -6.521354417e-03f, +1.485137245e-01f, +9.153097287e-01f, -5.628631147e-02f },
-    { -6.506269371e-03f, +1.482671122e-01f, +9.155136370e-01f, -5.626218978e-02f },
-    { -6.491204225e-03f, +1.480206466e-01f, +9.157173259e-01f, -5.623797353e-02f },
-    { -6.476158974e-03f, +1.477743278e-01f, +9.159207954e-01f, -5.621366265e-02f },
-    { -6.461133612e-03f, +1.475281560e-01f, +9.161240451e-01f, -5.618925704e-02f },
-    { -6.446128134e-03f, +1.472821311e-01f, +9.163270752e-01f, -5.616475663e-02f },
-    { -6.431142534e-03f, +1.470362531e-01f, +9.165298853e-01f, -5.614016133e-02f },
-    { -6.416176806e-03f, +1.467905223e-01f, +9.167324754e-01f, -5.611547107e-02f },
-    { -6.401230944e-03f, +1.465449385e-01f, +9.169348454e-01f, -5.609068575e-02f },
-    { -6.386304943e-03f, +1.462995018e-01f, +9.171369950e-01f, -5.606580530e-02f },
-    { -6.371398797e-03f, +1.460542124e-01f, +9.173389243e-01f, -5.604082963e-02f },
-    { -6.356512501e-03f, +1.458090702e-01f, +9.175406331e-01f, -5.601575866e-02f },
-    { -6.341646048e-03f, +1.455640752e-01f, +9.177421213e-01f, -5.599059231e-02f },
-    { -6.326799433e-03f, +1.453192276e-01f, +9.179433886e-01f, -5.596533050e-02f },
-    { -6.311972650e-03f, +1.450745274e-01f, +9.181444351e-01f, -5.593997314e-02f },
-    { -6.297165693e-03f, +1.448299746e-01f, +9.183452606e-01f, -5.591452015e-02f },
-    { -6.282378556e-03f, +1.445855693e-01f, +9.185458649e-01f, -5.588897145e-02f },
-    { -6.267611233e-03f, +1.443413115e-01f, +9.187462479e-01f, -5.586332696e-02f },
-    { -6.252863718e-03f, +1.440972013e-01f, +9.189464096e-01f, -5.583758659e-02f },
-    { -6.238136006e-03f, +1.438532387e-01f, +9.191463497e-01f, -5.581175026e-02f },
-    { -6.223428090e-03f, +1.436094238e-01f, +9.193460682e-01f, -5.578581789e-02f },
-    { -6.208739964e-03f, +1.433657566e-01f, +9.195455649e-01f, -5.575978940e-02f },
-    { -6.194071622e-03f, +1.431222371e-01f, +9.197448398e-01f, -5.573366470e-02f },
-    { -6.179423059e-03f, +1.428788655e-01f, +9.199438926e-01f, -5.570744371e-02f },
-    { -6.164794268e-03f, +1.426356417e-01f, +9.201427233e-01f, -5.568112636e-02f },
-    { -6.150185242e-03f, +1.423925658e-01f, +9.203413317e-01f, -5.565471255e-02f },
-    { -6.135595977e-03f, +1.421496379e-01f, +9.205397178e-01f, -5.562820221e-02f },
-    { -6.121026465e-03f, +1.419068580e-01f, +9.207378813e-01f, -5.560159525e-02f },
-    { -6.106476701e-03f, +1.416642261e-01f, +9.209358223e-01f, -5.557489159e-02f },
-    { -6.091946678e-03f, +1.414217423e-01f, +9.211335405e-01f, -5.554809115e-02f },
-    { -6.077436389e-03f, +1.411794066e-01f, +9.213310358e-01f, -5.552119385e-02f },
-    { -6.062945830e-03f, +1.409372192e-01f, +9.215283081e-01f, -5.549419960e-02f },
-    { -6.048474993e-03f, +1.406951799e-01f, +9.217253573e-01f, -5.546710832e-02f },
-    { -6.034023872e-03f, +1.404532889e-01f, +9.219221832e-01f, -5.543991994e-02f },
-    { -6.019592461e-03f, +1.402115463e-01f, +9.221187858e-01f, -5.541263436e-02f },
-    { -6.005180754e-03f, +1.399699520e-01f, +9.223151649e-01f, -5.538525151e-02f },
-    { -5.990788743e-03f, +1.397285061e-01f, +9.225113204e-01f, -5.535777130e-02f },
-    { -5.976416423e-03f, +1.394872087e-01f, +9.227072522e-01f, -5.533019365e-02f },
-    { -5.962063788e-03f, +1.392460598e-01f, +9.229029601e-01f, -5.530251848e-02f },
-    { -5.947730830e-03f, +1.390050594e-01f, +9.230984441e-01f, -5.527474572e-02f },
-    { -5.933417543e-03f, +1.387642076e-01f, +9.232937039e-01f, -5.524687526e-02f },
-    { -5.919123921e-03f, +1.385235045e-01f, +9.234887396e-01f, -5.521890704e-02f },
-    { -5.904849957e-03f, +1.382829500e-01f, +9.236835509e-01f, -5.519084097e-02f },
-    { -5.890595645e-03f, +1.380425443e-01f, +9.238781378e-01f, -5.516267698e-02f },
-    { -5.876360977e-03f, +1.378022873e-01f, +9.240725001e-01f, -5.513441497e-02f },
-    { -5.862145949e-03f, +1.375621792e-01f, +9.242666377e-01f, -5.510605486e-02f },
-    { -5.847950552e-03f, +1.373222199e-01f, +9.244605504e-01f, -5.507759658e-02f },
-    { -5.833774780e-03f, +1.370824095e-01f, +9.246542383e-01f, -5.504904005e-02f },
-    { -5.819618626e-03f, +1.368427480e-01f, +9.248477010e-01f, -5.502038517e-02f },
-    { -5.805482085e-03f, +1.366032356e-01f, +9.250409386e-01f, -5.499163187e-02f },
-    { -5.791365148e-03f, +1.363638722e-01f, +9.252339509e-01f, -5.496278007e-02f },
-    { -5.777267810e-03f, +1.361246578e-01f, +9.254267378e-01f, -5.493382968e-02f },
-    { -5.763190063e-03f, +1.358855926e-01f, +9.256192991e-01f, -5.490478063e-02f },
-    { -5.749131901e-03f, +1.356466765e-01f, +9.258116348e-01f, -5.487563282e-02f },
-    { -5.735093317e-03f, +1.354079097e-01f, +9.260037447e-01f, -5.484638619e-02f },
-    { -5.721074303e-03f, +1.351692920e-01f, +9.261956287e-01f, -5.481704064e-02f },
-    { -5.707074854e-03f, +1.349308237e-01f, +9.263872867e-01f, -5.478759611e-02f },
-    { -5.693094963e-03f, +1.346925048e-01f, +9.265787186e-01f, -5.475805249e-02f },
-    { -5.679134621e-03f, +1.344543351e-01f, +9.267699242e-01f, -5.472840972e-02f },
-    { -5.665193823e-03f, +1.342163150e-01f, +9.269609034e-01f, -5.469866771e-02f },
-    { -5.651272561e-03f, +1.339784442e-01f, +9.271516562e-01f, -5.466882638e-02f },
-    { -5.637370829e-03f, +1.337407230e-01f, +9.273421823e-01f, -5.463888565e-02f },
-    { -5.623488619e-03f, +1.335031514e-01f, +9.275324817e-01f, -5.460884543e-02f },
-    { -5.609625925e-03f, +1.332657293e-01f, +9.277225543e-01f, -5.457870565e-02f },
-    { -5.595782739e-03f, +1.330284568e-01f, +9.279123998e-01f, -5.454846622e-02f },
-    { -5.581959054e-03f, +1.327913341e-01f, +9.281020184e-01f, -5.451812706e-02f },
-    { -5.568154863e-03f, +1.325543610e-01f, +9.282914097e-01f, -5.448768810e-02f },
-    { -5.554370159e-03f, +1.323175377e-01f, +9.284805736e-01f, -5.445714924e-02f },
-    { -5.540604935e-03f, +1.320808642e-01f, +9.286695102e-01f, -5.442651041e-02f },
-    { -5.526859184e-03f, +1.318443405e-01f, +9.288582192e-01f, -5.439577153e-02f },
-    { -5.513132898e-03f, +1.316079667e-01f, +9.290467005e-01f, -5.436493251e-02f },
-    { -5.499426070e-03f, +1.313717428e-01f, +9.292349540e-01f, -5.433399327e-02f },
-    { -5.485738694e-03f, +1.311356689e-01f, +9.294229797e-01f, -5.430295374e-02f },
-    { -5.472070761e-03f, +1.308997450e-01f, +9.296107773e-01f, -5.427181382e-02f },
-    { -5.458422264e-03f, +1.306639711e-01f, +9.297983467e-01f, -5.424057345e-02f },
-    { -5.444793197e-03f, +1.304283474e-01f, +9.299856879e-01f, -5.420923253e-02f },
-    { -5.431183551e-03f, +1.301928737e-01f, +9.301728008e-01f, -5.417779099e-02f },
-    { -5.417593320e-03f, +1.299575502e-01f, +9.303596851e-01f, -5.414624875e-02f },
-    { -5.404022496e-03f, +1.297223769e-01f, +9.305463408e-01f, -5.411460571e-02f },
-    { -5.390471071e-03f, +1.294873538e-01f, +9.307327679e-01f, -5.408286181e-02f },
-    { -5.376939039e-03f, +1.292524811e-01f, +9.309189660e-01f, -5.405101697e-02f },
-    { -5.363426391e-03f, +1.290177586e-01f, +9.311049353e-01f, -5.401907109e-02f },
-    { -5.349933121e-03f, +1.287831865e-01f, +9.312906754e-01f, -5.398702410e-02f },
-    { -5.336459220e-03f, +1.285487648e-01f, +9.314761864e-01f, -5.395487592e-02f },
-    { -5.323004682e-03f, +1.283144936e-01f, +9.316614680e-01f, -5.392262647e-02f },
-    { -5.309569498e-03f, +1.280803728e-01f, +9.318465203e-01f, -5.389027566e-02f },
-    { -5.296153661e-03f, +1.278464026e-01f, +9.320313430e-01f, -5.385782342e-02f },
-    { -5.282757164e-03f, +1.276125829e-01f, +9.322159361e-01f, -5.382526966e-02f },
-    { -5.269379998e-03f, +1.273789138e-01f, +9.324002994e-01f, -5.379261431e-02f },
-    { -5.256022157e-03f, +1.271453953e-01f, +9.325844328e-01f, -5.375985728e-02f },
-    { -5.242683633e-03f, +1.269120275e-01f, +9.327683363e-01f, -5.372699848e-02f },
-    { -5.229364417e-03f, +1.266788105e-01f, +9.329520096e-01f, -5.369403785e-02f },
-    { -5.216064503e-03f, +1.264457441e-01f, +9.331354527e-01f, -5.366097530e-02f },
-    { -5.202783882e-03f, +1.262128286e-01f, +9.333186655e-01f, -5.362781074e-02f },
-    { -5.189522547e-03f, +1.259800639e-01f, +9.335016478e-01f, -5.359454410e-02f },
-    { -5.176280490e-03f, +1.257474501e-01f, +9.336843996e-01f, -5.356117530e-02f },
-    { -5.163057703e-03f, +1.255149871e-01f, +9.338669207e-01f, -5.352770425e-02f },
-    { -5.149854178e-03f, +1.252826751e-01f, +9.340492110e-01f, -5.349413088e-02f },
-    { -5.136669908e-03f, +1.250505141e-01f, +9.342312704e-01f, -5.346045510e-02f },
-    { -5.123504885e-03f, +1.248185041e-01f, +9.344130987e-01f, -5.342667683e-02f },
-    { -5.110359100e-03f, +1.245866451e-01f, +9.345946960e-01f, -5.339279600e-02f },
-    { -5.097232546e-03f, +1.243549372e-01f, +9.347760620e-01f, -5.335881251e-02f },
-    { -5.084125216e-03f, +1.241233805e-01f, +9.349571966e-01f, -5.332472630e-02f },
-    { -5.071037100e-03f, +1.238919749e-01f, +9.351380998e-01f, -5.329053728e-02f },
-    { -5.057968191e-03f, +1.236607205e-01f, +9.353187714e-01f, -5.325624537e-02f },
-    { -5.044918481e-03f, +1.234296174e-01f, +9.354992113e-01f, -5.322185049e-02f },
-    { -5.031887963e-03f, +1.231986655e-01f, +9.356794194e-01f, -5.318735255e-02f },
-    { -5.018876627e-03f, +1.229678649e-01f, +9.358593955e-01f, -5.315275148e-02f },
-    { -5.005884466e-03f, +1.227372157e-01f, +9.360391397e-01f, -5.311804720e-02f },
-    { -4.992911472e-03f, +1.225067179e-01f, +9.362186517e-01f, -5.308323963e-02f },
-    { -4.979957637e-03f, +1.222763714e-01f, +9.363979314e-01f, -5.304832868e-02f },
-    { -4.967022953e-03f, +1.220461765e-01f, +9.365769788e-01f, -5.301331428e-02f },
-    { -4.954107411e-03f, +1.218161330e-01f, +9.367557936e-01f, -5.297819635e-02f },
-    { -4.941211003e-03f, +1.215862410e-01f, +9.369343759e-01f, -5.294297479e-02f },
-    { -4.928333721e-03f, +1.213565006e-01f, +9.371127255e-01f, -5.290764955e-02f },
-    { -4.915475558e-03f, +1.211269118e-01f, +9.372908423e-01f, -5.287222052e-02f },
-    { -4.902636504e-03f, +1.208974746e-01f, +9.374687261e-01f, -5.283668764e-02f },
-    { -4.889816551e-03f, +1.206681891e-01f, +9.376463769e-01f, -5.280105083e-02f },
-    { -4.877015692e-03f, +1.204390553e-01f, +9.378237946e-01f, -5.276531000e-02f },
-    { -4.864233917e-03f, +1.202100732e-01f, +9.380009790e-01f, -5.272946506e-02f },
-    { -4.851471219e-03f, +1.199812429e-01f, +9.381779301e-01f, -5.269351596e-02f },
-    { -4.838727590e-03f, +1.197525644e-01f, +9.383546476e-01f, -5.265746259e-02f },
-    { -4.826003020e-03f, +1.195240378e-01f, +9.385311316e-01f, -5.262130489e-02f },
-    { -4.813297501e-03f, +1.192956630e-01f, +9.387073818e-01f, -5.258504277e-02f },
-    { -4.800611026e-03f, +1.190674401e-01f, +9.388833983e-01f, -5.254867615e-02f },
-    { -4.787943585e-03f, +1.188393692e-01f, +9.390591808e-01f, -5.251220495e-02f },
-    { -4.775295171e-03f, +1.186114502e-01f, +9.392347294e-01f, -5.247562909e-02f },
-    { -4.762665774e-03f, +1.183836832e-01f, +9.394100437e-01f, -5.243894849e-02f },
-    { -4.750055387e-03f, +1.181560683e-01f, +9.395851238e-01f, -5.240216308e-02f },
-    { -4.737464000e-03f, +1.179286055e-01f, +9.397599696e-01f, -5.236527277e-02f },
-    { -4.724891606e-03f, +1.177012947e-01f, +9.399345809e-01f, -5.232827748e-02f },
-    { -4.712338195e-03f, +1.174741362e-01f, +9.401089576e-01f, -5.229117713e-02f },
-    { -4.699803759e-03f, +1.172471298e-01f, +9.402830997e-01f, -5.225397164e-02f },
-    { -4.687288290e-03f, +1.170202755e-01f, +9.404570069e-01f, -5.221666093e-02f },
-    { -4.674791779e-03f, +1.167935736e-01f, +9.406306792e-01f, -5.217924493e-02f },
-    { -4.662314217e-03f, +1.165670239e-01f, +9.408041166e-01f, -5.214172354e-02f },
-    { -4.649855595e-03f, +1.163406265e-01f, +9.409773188e-01f, -5.210409670e-02f },
-    { -4.637415906e-03f, +1.161143815e-01f, +9.411502858e-01f, -5.206636432e-02f },
-    { -4.624995140e-03f, +1.158882888e-01f, +9.413230174e-01f, -5.202852632e-02f },
-    { -4.612593288e-03f, +1.156623486e-01f, +9.414955136e-01f, -5.199058263e-02f },
-    { -4.600210342e-03f, +1.154365607e-01f, +9.416677743e-01f, -5.195253316e-02f },
-    { -4.587846293e-03f, +1.152109254e-01f, +9.418397993e-01f, -5.191437783e-02f },
-    { -4.575501133e-03f, +1.149854425e-01f, +9.420115885e-01f, -5.187611657e-02f },
-    { -4.563174852e-03f, +1.147601122e-01f, +9.421831418e-01f, -5.183774929e-02f },
-    { -4.550867441e-03f, +1.145349345e-01f, +9.423544592e-01f, -5.179927591e-02f },
-    { -4.538578892e-03f, +1.143099093e-01f, +9.425255405e-01f, -5.176069636e-02f },
-    { -4.526309197e-03f, +1.140850368e-01f, +9.426963856e-01f, -5.172201055e-02f },
-    { -4.514058345e-03f, +1.138603169e-01f, +9.428669944e-01f, -5.168321841e-02f },
-    { -4.501826329e-03f, +1.136357497e-01f, +9.430373667e-01f, -5.164431986e-02f },
-    { -4.489613138e-03f, +1.134113352e-01f, +9.432075026e-01f, -5.160531481e-02f },
-    { -4.477418765e-03f, +1.131870735e-01f, +9.433774019e-01f, -5.156620319e-02f },
-    { -4.465243201e-03f, +1.129629646e-01f, +9.435470644e-01f, -5.152698491e-02f },
-    { -4.453086436e-03f, +1.127390085e-01f, +9.437164901e-01f, -5.148765991e-02f },
-    { -4.440948461e-03f, +1.125152052e-01f, +9.438856788e-01f, -5.144822810e-02f },
-    { -4.428829267e-03f, +1.122915548e-01f, +9.440546305e-01f, -5.140868939e-02f },
-    { -4.416728846e-03f, +1.120680573e-01f, +9.442233450e-01f, -5.136904371e-02f },
-    { -4.404647188e-03f, +1.118447128e-01f, +9.443918223e-01f, -5.132929099e-02f },
-    { -4.392584284e-03f, +1.116215212e-01f, +9.445600623e-01f, -5.128943114e-02f },
-    { -4.380540125e-03f, +1.113984826e-01f, +9.447280647e-01f, -5.124946408e-02f },
-    { -4.368514702e-03f, +1.111755970e-01f, +9.448958296e-01f, -5.120938973e-02f },
-    { -4.356508006e-03f, +1.109528645e-01f, +9.450633568e-01f, -5.116920802e-02f },
-    { -4.344520028e-03f, +1.107302850e-01f, +9.452306462e-01f, -5.112891887e-02f },
-    { -4.332550758e-03f, +1.105078587e-01f, +9.453976978e-01f, -5.108852219e-02f },
-    { -4.320600187e-03f, +1.102855855e-01f, +9.455645113e-01f, -5.104801790e-02f },
-    { -4.308668306e-03f, +1.100634655e-01f, +9.457310868e-01f, -5.100740594e-02f },
-    { -4.296755107e-03f, +1.098414987e-01f, +9.458974241e-01f, -5.096668621e-02f },
-    { -4.284860578e-03f, +1.096196851e-01f, +9.460635230e-01f, -5.092585865e-02f },
-    { -4.272984712e-03f, +1.093980247e-01f, +9.462293836e-01f, -5.088492316e-02f },
-    { -4.261127499e-03f, +1.091765177e-01f, +9.463950056e-01f, -5.084387968e-02f },
-    { -4.249288929e-03f, +1.089551640e-01f, +9.465603890e-01f, -5.080272812e-02f },
-    { -4.237468994e-03f, +1.087339636e-01f, +9.467255337e-01f, -5.076146841e-02f },
-    { -4.225667684e-03f, +1.085129166e-01f, +9.468904396e-01f, -5.072010046e-02f },
-    { -4.213884989e-03f, +1.082920229e-01f, +9.470551065e-01f, -5.067862420e-02f },
-    { -4.202120901e-03f, +1.080712828e-01f, +9.472195345e-01f, -5.063703954e-02f },
-    { -4.190375409e-03f, +1.078506960e-01f, +9.473837233e-01f, -5.059534642e-02f },
-    { -4.178648505e-03f, +1.076302628e-01f, +9.475476728e-01f, -5.055354474e-02f },
-    { -4.166940178e-03f, +1.074099830e-01f, +9.477113830e-01f, -5.051163444e-02f },
-    { -4.155250420e-03f, +1.071898568e-01f, +9.478748538e-01f, -5.046961543e-02f },
-    { -4.143579220e-03f, +1.069698842e-01f, +9.480380851e-01f, -5.042748764e-02f },
-    { -4.131926571e-03f, +1.067500652e-01f, +9.482010767e-01f, -5.038525098e-02f },
-    { -4.120292461e-03f, +1.065303997e-01f, +9.483638285e-01f, -5.034290538e-02f },
-    { -4.108676881e-03f, +1.063108880e-01f, +9.485263405e-01f, -5.030045076e-02f },
-    { -4.097079822e-03f, +1.060915299e-01f, +9.486886126e-01f, -5.025788704e-02f },
-    { -4.085501274e-03f, +1.058723254e-01f, +9.488506446e-01f, -5.021521414e-02f },
-    { -4.073941228e-03f, +1.056532748e-01f, +9.490124364e-01f, -5.017243198e-02f },
-    { -4.062399673e-03f, +1.054343779e-01f, +9.491739880e-01f, -5.012954049e-02f },
-    { -4.050876601e-03f, +1.052156347e-01f, +9.493352993e-01f, -5.008653959e-02f },
-    { -4.039372002e-03f, +1.049970454e-01f, +9.494963700e-01f, -5.004342920e-02f },
-    { -4.027885865e-03f, +1.047786099e-01f, +9.496572003e-01f, -5.000020923e-02f },
-    { -4.016418182e-03f, +1.045603282e-01f, +9.498177898e-01f, -4.995687962e-02f },
-    { -4.004968942e-03f, +1.043422005e-01f, +9.499781386e-01f, -4.991344028e-02f },
-    { -3.993538136e-03f, +1.041242266e-01f, +9.501382466e-01f, -4.986989114e-02f },
-    { -3.982125754e-03f, +1.039064067e-01f, +9.502981136e-01f, -4.982623211e-02f },
-    { -3.970731786e-03f, +1.036887408e-01f, +9.504577395e-01f, -4.978246313e-02f },
-    { -3.959356223e-03f, +1.034712288e-01f, +9.506171243e-01f, -4.973858410e-02f },
-    { -3.947999054e-03f, +1.032538708e-01f, +9.507762678e-01f, -4.969459496e-02f },
-    { -3.936660271e-03f, +1.030366669e-01f, +9.509351700e-01f, -4.965049562e-02f },
-    { -3.925339862e-03f, +1.028196171e-01f, +9.510938306e-01f, -4.960628601e-02f },
-    { -3.914037818e-03f, +1.026027213e-01f, +9.512522498e-01f, -4.956196605e-02f },
-    { -3.902754129e-03f, +1.023859797e-01f, +9.514104273e-01f, -4.951753566e-02f },
-    { -3.891488786e-03f, +1.021693921e-01f, +9.515683630e-01f, -4.947299476e-02f },
-    { -3.880241778e-03f, +1.019529588e-01f, +9.517260568e-01f, -4.942834328e-02f },
-    { -3.869013095e-03f, +1.017366796e-01f, +9.518835087e-01f, -4.938358114e-02f },
-    { -3.857802728e-03f, +1.015205546e-01f, +9.520407186e-01f, -4.933870825e-02f },
-    { -3.846610666e-03f, +1.013045839e-01f, +9.521976863e-01f, -4.929372455e-02f },
-    { -3.835436900e-03f, +1.010887674e-01f, +9.523544118e-01f, -4.924862995e-02f },
-    { -3.824281419e-03f, +1.008731053e-01f, +9.525108949e-01f, -4.920342438e-02f },
-    { -3.813144214e-03f, +1.006575974e-01f, +9.526671355e-01f, -4.915810776e-02f },
-    { -3.802025274e-03f, +1.004422438e-01f, +9.528231336e-01f, -4.911268001e-02f },
-    { -3.790924590e-03f, +1.002270446e-01f, +9.529788891e-01f, -4.906714105e-02f },
-    { -3.779842151e-03f, +1.000119998e-01f, +9.531344018e-01f, -4.902149080e-02f },
-    { -3.768777946e-03f, +9.979710935e-02f, +9.532896717e-01f, -4.897572920e-02f },
-    { -3.757731967e-03f, +9.958237334e-02f, +9.534446987e-01f, -4.892985616e-02f },
-    { -3.746704203e-03f, +9.936779178e-02f, +9.535994826e-01f, -4.888387160e-02f },
-    { -3.735694643e-03f, +9.915336469e-02f, +9.537540234e-01f, -4.883777544e-02f },
-    { -3.724703278e-03f, +9.893909208e-02f, +9.539083209e-01f, -4.879156762e-02f },
-    { -3.713730097e-03f, +9.872497399e-02f, +9.540623752e-01f, -4.874524804e-02f },
-    { -3.702775091e-03f, +9.851101044e-02f, +9.542161860e-01f, -4.869881664e-02f },
-    { -3.691838248e-03f, +9.829720144e-02f, +9.543697533e-01f, -4.865227334e-02f },
-    { -3.680919559e-03f, +9.808354703e-02f, +9.545230770e-01f, -4.860561805e-02f },
-    { -3.670019013e-03f, +9.787004721e-02f, +9.546761570e-01f, -4.855885071e-02f },
-    { -3.659136601e-03f, +9.765670203e-02f, +9.548289931e-01f, -4.851197123e-02f },
-    { -3.648272311e-03f, +9.744351149e-02f, +9.549815854e-01f, -4.846497954e-02f },
-    { -3.637426133e-03f, +9.723047561e-02f, +9.551339337e-01f, -4.841787556e-02f },
-    { -3.626598058e-03f, +9.701759443e-02f, +9.552860379e-01f, -4.837065921e-02f },
-    { -3.615788075e-03f, +9.680486796e-02f, +9.554378979e-01f, -4.832333042e-02f },
-    { -3.604996173e-03f, +9.659229622e-02f, +9.555895136e-01f, -4.827588911e-02f },
-    { -3.594222342e-03f, +9.637987924e-02f, +9.557408849e-01f, -4.822833521e-02f },
-    { -3.583466571e-03f, +9.616761703e-02f, +9.558920118e-01f, -4.818066862e-02f },
-    { -3.572728851e-03f, +9.595550962e-02f, +9.560428941e-01f, -4.813288929e-02f },
-    { -3.562009171e-03f, +9.574355703e-02f, +9.561935317e-01f, -4.808499713e-02f },
-    { -3.551307520e-03f, +9.553175927e-02f, +9.563439245e-01f, -4.803699206e-02f },
-    { -3.540623888e-03f, +9.532011637e-02f, +9.564940726e-01f, -4.798887401e-02f },
-    { -3.529958264e-03f, +9.510862835e-02f, +9.566439756e-01f, -4.794064290e-02f },
-    { -3.519310638e-03f, +9.489729524e-02f, +9.567936336e-01f, -4.789229866e-02f },
-    { -3.508680999e-03f, +9.468611704e-02f, +9.569430465e-01f, -4.784384120e-02f },
-    { -3.498069337e-03f, +9.447509378e-02f, +9.570922142e-01f, -4.779527045e-02f },
-    { -3.487475641e-03f, +9.426422548e-02f, +9.572411365e-01f, -4.774658634e-02f },
-    { -3.476899901e-03f, +9.405351217e-02f, +9.573898135e-01f, -4.769778879e-02f },
-    { -3.466342106e-03f, +9.384295385e-02f, +9.575382449e-01f, -4.764887772e-02f },
-    { -3.455802245e-03f, +9.363255055e-02f, +9.576864307e-01f, -4.759985305e-02f },
-    { -3.445280308e-03f, +9.342230229e-02f, +9.578343708e-01f, -4.755071471e-02f },
-    { -3.434776284e-03f, +9.321220909e-02f, +9.579820651e-01f, -4.750146263e-02f },
-    { -3.424290163e-03f, +9.300227097e-02f, +9.581295136e-01f, -4.745209672e-02f },
-    { -3.413821934e-03f, +9.279248795e-02f, +9.582767160e-01f, -4.740261690e-02f },
-    { -3.403371585e-03f, +9.258286004e-02f, +9.584236724e-01f, -4.735302311e-02f },
-    { -3.392939107e-03f, +9.237338726e-02f, +9.585703827e-01f, -4.730331527e-02f },
-    { -3.382524489e-03f, +9.216406964e-02f, +9.587168467e-01f, -4.725349330e-02f },
-    { -3.372127720e-03f, +9.195490720e-02f, +9.588630643e-01f, -4.720355712e-02f },
-    { -3.361748789e-03f, +9.174589994e-02f, +9.590090355e-01f, -4.715350666e-02f },
-    { -3.351387685e-03f, +9.153704790e-02f, +9.591547602e-01f, -4.710334184e-02f },
-    { -3.341044398e-03f, +9.132835108e-02f, +9.593002383e-01f, -4.705306259e-02f },
-    { -3.330718916e-03f, +9.111980950e-02f, +9.594454696e-01f, -4.700266883e-02f },
-    { -3.320411230e-03f, +9.091142320e-02f, +9.595904542e-01f, -4.695216048e-02f },
-    { -3.310121328e-03f, +9.070319217e-02f, +9.597351919e-01f, -4.690153746e-02f },
-    { -3.299849199e-03f, +9.049511645e-02f, +9.598796825e-01f, -4.685079971e-02f },
-    { -3.289594832e-03f, +9.028719604e-02f, +9.600239261e-01f, -4.679994715e-02f },
-    { -3.279358217e-03f, +9.007943096e-02f, +9.601679226e-01f, -4.674897969e-02f },
-    { -3.269139342e-03f, +8.987182124e-02f, +9.603116718e-01f, -4.669789727e-02f },
-    { -3.258938197e-03f, +8.966436689e-02f, +9.604551736e-01f, -4.664669981e-02f },
-    { -3.248754771e-03f, +8.945706793e-02f, +9.605984280e-01f, -4.659538723e-02f },
-    { -3.238589053e-03f, +8.924992437e-02f, +9.607414349e-01f, -4.654395945e-02f },
-    { -3.228441031e-03f, +8.904293624e-02f, +9.608841941e-01f, -4.649241641e-02f },
-    { -3.218310696e-03f, +8.883610354e-02f, +9.610267057e-01f, -4.644075802e-02f },
-    { -3.208198035e-03f, +8.862942629e-02f, +9.611689695e-01f, -4.638898421e-02f },
-    { -3.198103037e-03f, +8.842290452e-02f, +9.613109853e-01f, -4.633709491e-02f },
-    { -3.188025693e-03f, +8.821653824e-02f, +9.614527532e-01f, -4.628509003e-02f },
-    { -3.177965990e-03f, +8.801032746e-02f, +9.615942731e-01f, -4.623296951e-02f },
-    { -3.167923918e-03f, +8.780427220e-02f, +9.617355447e-01f, -4.618073326e-02f },
-    { -3.157899465e-03f, +8.759837247e-02f, +9.618765682e-01f, -4.612838122e-02f },
-    { -3.147892621e-03f, +8.739262830e-02f, +9.620173433e-01f, -4.607591330e-02f },
-    { -3.137903374e-03f, +8.718703970e-02f, +9.621578700e-01f, -4.602332944e-02f },
-    { -3.127931713e-03f, +8.698160668e-02f, +9.622981482e-01f, -4.597062955e-02f },
-    { -3.117977628e-03f, +8.677632927e-02f, +9.624381778e-01f, -4.591781356e-02f },
-    { -3.108041106e-03f, +8.657120747e-02f, +9.625779587e-01f, -4.586488140e-02f },
-    { -3.098122137e-03f, +8.636624129e-02f, +9.627174908e-01f, -4.581183299e-02f },
-    { -3.088220709e-03f, +8.616143077e-02f, +9.628567741e-01f, -4.575866826e-02f },
-    { -3.078336812e-03f, +8.595677591e-02f, +9.629958084e-01f, -4.570538712e-02f },
-    { -3.068470433e-03f, +8.575227672e-02f, +9.631345937e-01f, -4.565198951e-02f },
-    { -3.058621563e-03f, +8.554793322e-02f, +9.632731298e-01f, -4.559847535e-02f },
-    { -3.048790189e-03f, +8.534374543e-02f, +9.634114168e-01f, -4.554484457e-02f },
-    { -3.038976300e-03f, +8.513971336e-02f, +9.635494545e-01f, -4.549109708e-02f },
-    { -3.029179886e-03f, +8.493583703e-02f, +9.636872427e-01f, -4.543723283e-02f },
-    { -3.019400934e-03f, +8.473211644e-02f, +9.638247816e-01f, -4.538325172e-02f },
-    { -3.009639433e-03f, +8.452855162e-02f, +9.639620708e-01f, -4.532915369e-02f },
-    { -2.999895373e-03f, +8.432514258e-02f, +9.640991104e-01f, -4.527493866e-02f },
-    { -2.990168741e-03f, +8.412188933e-02f, +9.642359003e-01f, -4.522060655e-02f },
-    { -2.980459527e-03f, +8.391879188e-02f, +9.643724404e-01f, -4.516615730e-02f },
-    { -2.970767718e-03f, +8.371585026e-02f, +9.645087305e-01f, -4.511159083e-02f },
-    { -2.961093304e-03f, +8.351306447e-02f, +9.646447707e-01f, -4.505690705e-02f },
-    { -2.951436274e-03f, +8.331043452e-02f, +9.647805608e-01f, -4.500210591e-02f },
-    { -2.941796615e-03f, +8.310796044e-02f, +9.649161008e-01f, -4.494718732e-02f },
-    { -2.932174316e-03f, +8.290564223e-02f, +9.650513905e-01f, -4.489215120e-02f },
-    { -2.922569366e-03f, +8.270347990e-02f, +9.651864298e-01f, -4.483699749e-02f },
-    { -2.912981754e-03f, +8.250147348e-02f, +9.653212188e-01f, -4.478172612e-02f },
-    { -2.903411467e-03f, +8.229962297e-02f, +9.654557573e-01f, -4.472633699e-02f },
-    { -2.893858495e-03f, +8.209792838e-02f, +9.655900451e-01f, -4.467083005e-02f },
-    { -2.884322825e-03f, +8.189638974e-02f, +9.657240824e-01f, -4.461520522e-02f },
-    { -2.874804447e-03f, +8.169500704e-02f, +9.658578688e-01f, -4.455946242e-02f },
-    { -2.865303349e-03f, +8.149378031e-02f, +9.659914044e-01f, -4.450360157e-02f },
-    { -2.855819519e-03f, +8.129270955e-02f, +9.661246891e-01f, -4.444762262e-02f },
-    { -2.846352946e-03f, +8.109179479e-02f, +9.662577228e-01f, -4.439152547e-02f },
-    { -2.836903618e-03f, +8.089103602e-02f, +9.663905054e-01f, -4.433531006e-02f },
-    { -2.827471523e-03f, +8.069043326e-02f, +9.665230369e-01f, -4.427897631e-02f },
-    { -2.818056650e-03f, +8.048998653e-02f, +9.666553170e-01f, -4.422252415e-02f },
-    { -2.808658988e-03f, +8.028969584e-02f, +9.667873459e-01f, -4.416595350e-02f },
-    { -2.799278524e-03f, +8.008956119e-02f, +9.669191233e-01f, -4.410926430e-02f },
-    { -2.789915247e-03f, +7.988958260e-02f, +9.670506492e-01f, -4.405245646e-02f },
-    { -2.780569145e-03f, +7.968976008e-02f, +9.671819235e-01f, -4.399552991e-02f },
-    { -2.771240206e-03f, +7.949009365e-02f, +9.673129462e-01f, -4.393848458e-02f },
-    { -2.761928420e-03f, +7.929058330e-02f, +9.674437171e-01f, -4.388132040e-02f },
-    { -2.752633774e-03f, +7.909122907e-02f, +9.675742361e-01f, -4.382403729e-02f },
-    { -2.743356256e-03f, +7.889203094e-02f, +9.677045033e-01f, -4.376663518e-02f },
-    { -2.734095855e-03f, +7.869298894e-02f, +9.678345184e-01f, -4.370911400e-02f },
-    { -2.724852558e-03f, +7.849410308e-02f, +9.679642815e-01f, -4.365147366e-02f },
-    { -2.715626355e-03f, +7.829537336e-02f, +9.680937924e-01f, -4.359371410e-02f },
-    { -2.706417234e-03f, +7.809679980e-02f, +9.682230510e-01f, -4.353583525e-02f },
-    { -2.697225181e-03f, +7.789838241e-02f, +9.683520574e-01f, -4.347783703e-02f },
-    { -2.688050187e-03f, +7.770012120e-02f, +9.684808113e-01f, -4.341971936e-02f },
-    { -2.678892238e-03f, +7.750201617e-02f, +9.686093127e-01f, -4.336148218e-02f },
-    { -2.669751324e-03f, +7.730406734e-02f, +9.687375615e-01f, -4.330312541e-02f },
-    { -2.660627431e-03f, +7.710627472e-02f, +9.688655578e-01f, -4.324464897e-02f },
-    { -2.651520549e-03f, +7.690863832e-02f, +9.689933012e-01f, -4.318605280e-02f },
-    { -2.642430666e-03f, +7.671115814e-02f, +9.691207919e-01f, -4.312733682e-02f },
-    { -2.633357769e-03f, +7.651383420e-02f, +9.692480296e-01f, -4.306850096e-02f },
-    { -2.624301846e-03f, +7.631666650e-02f, +9.693750144e-01f, -4.300954515e-02f },
-    { -2.615262886e-03f, +7.611965506e-02f, +9.695017462e-01f, -4.295046931e-02f },
-    { -2.606240877e-03f, +7.592279989e-02f, +9.696282248e-01f, -4.289127336e-02f },
-    { -2.597235807e-03f, +7.572610098e-02f, +9.697544501e-01f, -4.283195724e-02f },
-    { -2.588247664e-03f, +7.552955836e-02f, +9.698804222e-01f, -4.277252088e-02f },
-    { -2.579276435e-03f, +7.533317203e-02f, +9.700061410e-01f, -4.271296420e-02f },
-    { -2.570322110e-03f, +7.513694200e-02f, +9.701316062e-01f, -4.265328712e-02f },
-    { -2.561384675e-03f, +7.494086827e-02f, +9.702568180e-01f, -4.259348958e-02f },
-    { -2.552464119e-03f, +7.474495086e-02f, +9.703817761e-01f, -4.253357150e-02f },
-    { -2.543560430e-03f, +7.454918978e-02f, +9.705064805e-01f, -4.247353281e-02f },
-    { -2.534673595e-03f, +7.435358503e-02f, +9.706309312e-01f, -4.241337343e-02f },
-    { -2.525803603e-03f, +7.415813662e-02f, +9.707551280e-01f, -4.235309331e-02f },
-    { -2.516950442e-03f, +7.396284455e-02f, +9.708790709e-01f, -4.229269235e-02f },
-    { -2.508114099e-03f, +7.376770885e-02f, +9.710027598e-01f, -4.223217049e-02f },
-    { -2.499294563e-03f, +7.357272950e-02f, +9.711261947e-01f, -4.217152766e-02f },
-    { -2.490491821e-03f, +7.337790653e-02f, +9.712493753e-01f, -4.211076378e-02f },
-    { -2.481705861e-03f, +7.318323994e-02f, +9.713723017e-01f, -4.204987879e-02f },
-    { -2.472936671e-03f, +7.298872973e-02f, +9.714949738e-01f, -4.198887261e-02f },
-    { -2.464184239e-03f, +7.279437592e-02f, +9.716173916e-01f, -4.192774516e-02f },
-    { -2.455448552e-03f, +7.260017851e-02f, +9.717395548e-01f, -4.186649638e-02f },
-    { -2.446729599e-03f, +7.240613750e-02f, +9.718614635e-01f, -4.180512620e-02f },
-    { -2.438027368e-03f, +7.221225291e-02f, +9.719831176e-01f, -4.174363453e-02f },
-    { -2.429341845e-03f, +7.201852474e-02f, +9.721045170e-01f, -4.168202131e-02f },
-    { -2.420673020e-03f, +7.182495300e-02f, +9.722256616e-01f, -4.162028648e-02f },
-    { -2.412020878e-03f, +7.163153769e-02f, +9.723465513e-01f, -4.155842994e-02f },
-    { -2.403385410e-03f, +7.143827882e-02f, +9.724671862e-01f, -4.149645164e-02f },
-    { -2.394766601e-03f, +7.124517640e-02f, +9.725875660e-01f, -4.143435151e-02f },
-    { -2.386164441e-03f, +7.105223044e-02f, +9.727076907e-01f, -4.137212946e-02f },
-    { -2.377578915e-03f, +7.085944093e-02f, +9.728275603e-01f, -4.130978543e-02f },
-    { -2.369010014e-03f, +7.066680788e-02f, +9.729471746e-01f, -4.124731934e-02f },
-    { -2.360457723e-03f, +7.047433131e-02f, +9.730665337e-01f, -4.118473113e-02f },
-    { -2.351922030e-03f, +7.028201121e-02f, +9.731856373e-01f, -4.112202073e-02f },
-    { -2.343402924e-03f, +7.008984759e-02f, +9.733044855e-01f, -4.105918805e-02f },
-    { -2.334900392e-03f, +6.989784046e-02f, +9.734230782e-01f, -4.099623304e-02f },
-    { -2.326414422e-03f, +6.970598983e-02f, +9.735414153e-01f, -4.093315561e-02f },
-    { -2.317945001e-03f, +6.951429569e-02f, +9.736594966e-01f, -4.086995570e-02f },
-    { -2.309492116e-03f, +6.932275805e-02f, +9.737773222e-01f, -4.080663324e-02f },
-    { -2.301055756e-03f, +6.913137692e-02f, +9.738948920e-01f, -4.074318815e-02f },
-    { -2.292635908e-03f, +6.894015231e-02f, +9.740122059e-01f, -4.067962036e-02f },
-    { -2.284232560e-03f, +6.874908421e-02f, +9.741292638e-01f, -4.061592981e-02f },
-    { -2.275845698e-03f, +6.855817263e-02f, +9.742460656e-01f, -4.055211641e-02f },
-    { -2.267475312e-03f, +6.836741758e-02f, +9.743626113e-01f, -4.048818011e-02f },
-    { -2.259121387e-03f, +6.817681906e-02f, +9.744789009e-01f, -4.042412082e-02f },
-    { -2.250783913e-03f, +6.798637707e-02f, +9.745949341e-01f, -4.035993848e-02f },
-    { -2.242462875e-03f, +6.779609163e-02f, +9.747107110e-01f, -4.029563302e-02f },
-    { -2.234158263e-03f, +6.760596272e-02f, +9.748262314e-01f, -4.023120436e-02f },
-    { -2.225870062e-03f, +6.741599037e-02f, +9.749414954e-01f, -4.016665244e-02f },
-    { -2.217598262e-03f, +6.722617456e-02f, +9.750565028e-01f, -4.010197718e-02f },
-    { -2.209342848e-03f, +6.703651531e-02f, +9.751712536e-01f, -4.003717851e-02f },
-    { -2.201103809e-03f, +6.684701262e-02f, +9.752857476e-01f, -3.997225637e-02f },
-    { -2.192881133e-03f, +6.665766648e-02f, +9.753999849e-01f, -3.990721068e-02f },
-    { -2.184674805e-03f, +6.646847692e-02f, +9.755139653e-01f, -3.984204137e-02f },
-    { -2.176484815e-03f, +6.627944392e-02f, +9.756276888e-01f, -3.977674836e-02f },
-    { -2.168311149e-03f, +6.609056749e-02f, +9.757411552e-01f, -3.971133160e-02f },
-    { -2.160153795e-03f, +6.590184763e-02f, +9.758543646e-01f, -3.964579101e-02f },
-    { -2.152012740e-03f, +6.571328435e-02f, +9.759673169e-01f, -3.958012651e-02f },
-    { -2.143887971e-03f, +6.552487765e-02f, +9.760800119e-01f, -3.951433805e-02f },
-    { -2.135779477e-03f, +6.533662753e-02f, +9.761924497e-01f, -3.944842554e-02f },
-    { -2.127687243e-03f, +6.514853400e-02f, +9.763046301e-01f, -3.938238892e-02f },
-    { -2.119611258e-03f, +6.496059705e-02f, +9.764165530e-01f, -3.931622812e-02f },
-    { -2.111551509e-03f, +6.477281670e-02f, +9.765282185e-01f, -3.924994306e-02f },
-    { -2.103507983e-03f, +6.458519293e-02f, +9.766396264e-01f, -3.918353368e-02f },
-    { -2.095480667e-03f, +6.439772576e-02f, +9.767507766e-01f, -3.911699991e-02f },
-    { -2.087469549e-03f, +6.421041518e-02f, +9.768616692e-01f, -3.905034167e-02f },
-    { -2.079474617e-03f, +6.402326120e-02f, +9.769723040e-01f, -3.898355890e-02f },
-    { -2.071495856e-03f, +6.383626381e-02f, +9.770826809e-01f, -3.891665153e-02f },
-    { -2.063533255e-03f, +6.364942303e-02f, +9.771927998e-01f, -3.884961949e-02f },
-    { -2.055586801e-03f, +6.346273885e-02f, +9.773026608e-01f, -3.878246270e-02f },
-    { -2.047656480e-03f, +6.327621127e-02f, +9.774122638e-01f, -3.871518110e-02f },
-    { -2.039742281e-03f, +6.308984030e-02f, +9.775216086e-01f, -3.864777462e-02f },
-    { -2.031844191e-03f, +6.290362593e-02f, +9.776306952e-01f, -3.858024318e-02f },
-    { -2.023962196e-03f, +6.271756817e-02f, +9.777395235e-01f, -3.851258673e-02f },
-    { -2.016096283e-03f, +6.253166701e-02f, +9.778480935e-01f, -3.844480518e-02f },
-    { -2.008246441e-03f, +6.234592246e-02f, +9.779564051e-01f, -3.837689847e-02f },
-    { -2.000412656e-03f, +6.216033452e-02f, +9.780644583e-01f, -3.830886653e-02f },
-    { -1.992594915e-03f, +6.197490319e-02f, +9.781722528e-01f, -3.824070929e-02f },
-    { -1.984793206e-03f, +6.178962847e-02f, +9.782797888e-01f, -3.817242668e-02f },
-    { -1.977007515e-03f, +6.160451036e-02f, +9.783870661e-01f, -3.810401864e-02f },
-    { -1.969237830e-03f, +6.141954886e-02f, +9.784940847e-01f, -3.803548508e-02f },
-    { -1.961484138e-03f, +6.123474396e-02f, +9.786008444e-01f, -3.796682595e-02f },
-    { -1.953746425e-03f, +6.105009568e-02f, +9.787073453e-01f, -3.789804118e-02f },
-    { -1.946024680e-03f, +6.086560401e-02f, +9.788135872e-01f, -3.782913069e-02f },
-    { -1.938318888e-03f, +6.068126894e-02f, +9.789195701e-01f, -3.776009441e-02f },
-    { -1.930629038e-03f, +6.049709048e-02f, +9.790252939e-01f, -3.769093228e-02f },
-    { -1.922955116e-03f, +6.031306864e-02f, +9.791307585e-01f, -3.762164423e-02f },
-    { -1.915297108e-03f, +6.012920340e-02f, +9.792359640e-01f, -3.755223018e-02f },
-    { -1.907655004e-03f, +5.994549476e-02f, +9.793409101e-01f, -3.748269008e-02f },
-    { -1.900028788e-03f, +5.976194274e-02f, +9.794455969e-01f, -3.741302385e-02f },
-    { -1.892418449e-03f, +5.957854731e-02f, +9.795500243e-01f, -3.734323142e-02f },
-    { -1.884823973e-03f, +5.939530849e-02f, +9.796541922e-01f, -3.727331272e-02f },
-    { -1.877245347e-03f, +5.921222628e-02f, +9.797581006e-01f, -3.720326769e-02f },
-    { -1.869682558e-03f, +5.902930066e-02f, +9.798617493e-01f, -3.713309626e-02f },
-    { -1.862135594e-03f, +5.884653165e-02f, +9.799651384e-01f, -3.706279835e-02f },
-    { -1.854604440e-03f, +5.866391923e-02f, +9.800682677e-01f, -3.699237391e-02f },
-    { -1.847089085e-03f, +5.848146341e-02f, +9.801711372e-01f, -3.692182285e-02f },
-    { -1.839589515e-03f, +5.829916418e-02f, +9.802737469e-01f, -3.685114512e-02f },
-    { -1.832105717e-03f, +5.811702155e-02f, +9.803760966e-01f, -3.678034064e-02f },
-    { -1.824637677e-03f, +5.793503550e-02f, +9.804781863e-01f, -3.670940934e-02f },
-    { -1.817185384e-03f, +5.775320605e-02f, +9.805800159e-01f, -3.663835117e-02f },
-    { -1.809748823e-03f, +5.757153318e-02f, +9.806815854e-01f, -3.656716604e-02f },
-    { -1.802327981e-03f, +5.739001690e-02f, +9.807828947e-01f, -3.649585390e-02f },
-    { -1.794922846e-03f, +5.720865720e-02f, +9.808839437e-01f, -3.642441467e-02f },
-    { -1.787533404e-03f, +5.702745407e-02f, +9.809847324e-01f, -3.635284829e-02f },
-    { -1.780159642e-03f, +5.684640752e-02f, +9.810852607e-01f, -3.628115468e-02f },
-    { -1.772801548e-03f, +5.666551755e-02f, +9.811855286e-01f, -3.620933378e-02f },
-    { -1.765459107e-03f, +5.648478415e-02f, +9.812855360e-01f, -3.613738552e-02f },
-    { -1.758132306e-03f, +5.630420731e-02f, +9.813852827e-01f, -3.606530984e-02f },
-    { -1.750821133e-03f, +5.612378704e-02f, +9.814847688e-01f, -3.599310667e-02f },
-    { -1.743525575e-03f, +5.594352333e-02f, +9.815839943e-01f, -3.592077593e-02f },
-    { -1.736245617e-03f, +5.576341617e-02f, +9.816829589e-01f, -3.584831757e-02f },
-    { -1.728981247e-03f, +5.558346557e-02f, +9.817816627e-01f, -3.577573150e-02f },
-    { -1.721732452e-03f, +5.540367152e-02f, +9.818801056e-01f, -3.570301768e-02f },
-    { -1.714499218e-03f, +5.522403402e-02f, +9.819782876e-01f, -3.563017602e-02f },
-    { -1.707281532e-03f, +5.504455306e-02f, +9.820762086e-01f, -3.555720646e-02f },
-    { -1.700079381e-03f, +5.486522863e-02f, +9.821738684e-01f, -3.548410894e-02f },
-    { -1.692892751e-03f, +5.468606075e-02f, +9.822712671e-01f, -3.541088338e-02f },
-    { -1.685721630e-03f, +5.450704939e-02f, +9.823684047e-01f, -3.533752973e-02f },
-    { -1.678566004e-03f, +5.432819456e-02f, +9.824652809e-01f, -3.526404790e-02f },
-    { -1.671425859e-03f, +5.414949625e-02f, +9.825618958e-01f, -3.519043784e-02f },
-    { -1.664301183e-03f, +5.397095446e-02f, +9.826582494e-01f, -3.511669948e-02f },
-    { -1.657191962e-03f, +5.379256918e-02f, +9.827543414e-01f, -3.504283275e-02f },
-    { -1.650098183e-03f, +5.361434040e-02f, +9.828501720e-01f, -3.496883758e-02f },
-    { -1.643019832e-03f, +5.343626813e-02f, +9.829457410e-01f, -3.489471391e-02f },
-    { -1.635956896e-03f, +5.325835236e-02f, +9.830410484e-01f, -3.482046167e-02f },
-    { -1.628909362e-03f, +5.308059308e-02f, +9.831360941e-01f, -3.474608080e-02f },
-    { -1.621877216e-03f, +5.290299029e-02f, +9.832308780e-01f, -3.467157122e-02f },
-    { -1.614860445e-03f, +5.272554398e-02f, +9.833254001e-01f, -3.459693287e-02f },
-    { -1.607859036e-03f, +5.254825415e-02f, +9.834196603e-01f, -3.452216568e-02f },
-    { -1.600872975e-03f, +5.237112079e-02f, +9.835136587e-01f, -3.444726959e-02f },
-    { -1.593902249e-03f, +5.219414389e-02f, +9.836073950e-01f, -3.437224453e-02f },
-    { -1.586946844e-03f, +5.201732345e-02f, +9.837008692e-01f, -3.429709044e-02f },
-    { -1.580006747e-03f, +5.184065947e-02f, +9.837940814e-01f, -3.422180724e-02f },
-    { -1.573081945e-03f, +5.166415193e-02f, +9.838870314e-01f, -3.414639488e-02f },
-    { -1.566172424e-03f, +5.148780084e-02f, +9.839797191e-01f, -3.407085327e-02f },
-    { -1.559278170e-03f, +5.131160618e-02f, +9.840721446e-01f, -3.399518237e-02f },
-    { -1.552399171e-03f, +5.113556795e-02f, +9.841643077e-01f, -3.391938210e-02f },
-    { -1.545535412e-03f, +5.095968615e-02f, +9.842562085e-01f, -3.384345240e-02f },
-    { -1.538686881e-03f, +5.078396076e-02f, +9.843478467e-01f, -3.376739320e-02f },
-    { -1.531853564e-03f, +5.060839177e-02f, +9.844392225e-01f, -3.369120443e-02f },
-    { -1.525035446e-03f, +5.043297919e-02f, +9.845303356e-01f, -3.361488603e-02f },
-    { -1.518232516e-03f, +5.025772301e-02f, +9.846211862e-01f, -3.353843793e-02f },
-    { -1.511444759e-03f, +5.008262322e-02f, +9.847117740e-01f, -3.346186007e-02f },
-    { -1.504672161e-03f, +4.990767980e-02f, +9.848020991e-01f, -3.338515239e-02f },
-    { -1.497914710e-03f, +4.973289276e-02f, +9.848921614e-01f, -3.330831480e-02f },
-    { -1.491172391e-03f, +4.955826209e-02f, +9.849819608e-01f, -3.323134726e-02f },
-    { -1.484445192e-03f, +4.938378778e-02f, +9.850714973e-01f, -3.315424969e-02f },
-    { -1.477733098e-03f, +4.920946982e-02f, +9.851607708e-01f, -3.307702203e-02f },
-    { -1.471036096e-03f, +4.903530820e-02f, +9.852497812e-01f, -3.299966421e-02f },
-    { -1.464354173e-03f, +4.886130292e-02f, +9.853385286e-01f, -3.292217617e-02f },
-    { -1.457687314e-03f, +4.868745396e-02f, +9.854270129e-01f, -3.284455785e-02f },
-    { -1.451035507e-03f, +4.851376133e-02f, +9.855152339e-01f, -3.276680917e-02f },
-    { -1.444398738e-03f, +4.834022501e-02f, +9.856031917e-01f, -3.268893007e-02f },
-    { -1.437776992e-03f, +4.816684499e-02f, +9.856908861e-01f, -3.261092049e-02f },
-    { -1.431170257e-03f, +4.799362127e-02f, +9.857783172e-01f, -3.253278036e-02f },
-    { -1.424578519e-03f, +4.782055384e-02f, +9.858654848e-01f, -3.245450962e-02f },
-    { -1.418001764e-03f, +4.764764268e-02f, +9.859523890e-01f, -3.237610820e-02f },
-    { -1.411439979e-03f, +4.747488779e-02f, +9.860390297e-01f, -3.229757604e-02f },
-    { -1.404893149e-03f, +4.730228917e-02f, +9.861254067e-01f, -3.221891307e-02f },
-    { -1.398361262e-03f, +4.712984679e-02f, +9.862115201e-01f, -3.214011922e-02f },
-    { -1.391844303e-03f, +4.695756066e-02f, +9.862973698e-01f, -3.206119444e-02f },
-    { -1.385342260e-03f, +4.678543077e-02f, +9.863829557e-01f, -3.198213866e-02f },
-    { -1.378855117e-03f, +4.661345709e-02f, +9.864682779e-01f, -3.190295181e-02f },
-    { -1.372382862e-03f, +4.644163964e-02f, +9.865533361e-01f, -3.182363382e-02f },
-    { -1.365925481e-03f, +4.626997838e-02f, +9.866381305e-01f, -3.174418465e-02f },
-    { -1.359482960e-03f, +4.609847333e-02f, +9.867226608e-01f, -3.166460421e-02f },
-    { -1.353055286e-03f, +4.592712446e-02f, +9.868069272e-01f, -3.158489244e-02f },
-    { -1.346642444e-03f, +4.575593177e-02f, +9.868909295e-01f, -3.150504929e-02f },
-    { -1.340244422e-03f, +4.558489524e-02f, +9.869746676e-01f, -3.142507468e-02f },
-    { -1.333861204e-03f, +4.541401487e-02f, +9.870581415e-01f, -3.134496856e-02f },
-    { -1.327492778e-03f, +4.524329065e-02f, +9.871413513e-01f, -3.126473085e-02f },
-    { -1.321139130e-03f, +4.507272256e-02f, +9.872242967e-01f, -3.118436150e-02f },
-    { -1.314800245e-03f, +4.490231060e-02f, +9.873069778e-01f, -3.110386044e-02f },
-    { -1.308476111e-03f, +4.473205475e-02f, +9.873893944e-01f, -3.102322761e-02f },
-    { -1.302166714e-03f, +4.456195501e-02f, +9.874715467e-01f, -3.094246293e-02f },
-    { -1.295872038e-03f, +4.439201136e-02f, +9.875534344e-01f, -3.086156636e-02f },
-    { -1.289592072e-03f, +4.422222380e-02f, +9.876350576e-01f, -3.078053782e-02f },
-    { -1.283326801e-03f, +4.405259231e-02f, +9.877164161e-01f, -3.069937725e-02f },
-    { -1.277076211e-03f, +4.388311688e-02f, +9.877975101e-01f, -3.061808459e-02f },
-    { -1.270840289e-03f, +4.371379750e-02f, +9.878783393e-01f, -3.053665977e-02f },
-    { -1.264619020e-03f, +4.354463416e-02f, +9.879589037e-01f, -3.045510273e-02f },
-    { -1.258412391e-03f, +4.337562684e-02f, +9.880392034e-01f, -3.037341341e-02f },
-    { -1.252220388e-03f, +4.320677555e-02f, +9.881192381e-01f, -3.029159174e-02f },
-    { -1.246042996e-03f, +4.303808025e-02f, +9.881990080e-01f, -3.020963766e-02f },
-    { -1.239880203e-03f, +4.286954095e-02f, +9.882785129e-01f, -3.012755111e-02f },
-    { -1.233731995e-03f, +4.270115763e-02f, +9.883577528e-01f, -3.004533202e-02f },
-    { -1.227598357e-03f, +4.253293028e-02f, +9.884367276e-01f, -2.996298034e-02f },
-    { -1.221479275e-03f, +4.236485889e-02f, +9.885154374e-01f, -2.988049599e-02f },
-    { -1.215374737e-03f, +4.219694344e-02f, +9.885938819e-01f, -2.979787891e-02f },
-    { -1.209284727e-03f, +4.202918393e-02f, +9.886720613e-01f, -2.971512904e-02f },
-    { -1.203209232e-03f, +4.186158033e-02f, +9.887499753e-01f, -2.963224632e-02f },
-    { -1.197148238e-03f, +4.169413264e-02f, +9.888276241e-01f, -2.954923069e-02f },
-    { -1.191101731e-03f, +4.152684085e-02f, +9.889050075e-01f, -2.946608208e-02f },
-    { -1.185069698e-03f, +4.135970494e-02f, +9.889821255e-01f, -2.938280043e-02f },
-    { -1.179052123e-03f, +4.119272490e-02f, +9.890589780e-01f, -2.929938568e-02f },
-    { -1.173048994e-03f, +4.102590072e-02f, +9.891355651e-01f, -2.921583776e-02f },
-    { -1.167060297e-03f, +4.085923238e-02f, +9.892118865e-01f, -2.913215661e-02f },
-    { -1.161086016e-03f, +4.069271988e-02f, +9.892879424e-01f, -2.904834218e-02f },
-    { -1.155126140e-03f, +4.052636319e-02f, +9.893637326e-01f, -2.896439439e-02f },
-    { -1.149180652e-03f, +4.036016230e-02f, +9.894392571e-01f, -2.888031318e-02f },
-    { -1.143249541e-03f, +4.019411721e-02f, +9.895145159e-01f, -2.879609850e-02f },
-    { -1.137332791e-03f, +4.002822789e-02f, +9.895895088e-01f, -2.871175028e-02f },
-    { -1.131430388e-03f, +3.986249434e-02f, +9.896642360e-01f, -2.862726845e-02f },
-    { -1.125542319e-03f, +3.969691653e-02f, +9.897386972e-01f, -2.854265296e-02f },
-    { -1.119668570e-03f, +3.953149447e-02f, +9.898128925e-01f, -2.845790375e-02f },
-    { -1.113809126e-03f, +3.936622812e-02f, +9.898868218e-01f, -2.837302075e-02f },
-    { -1.107963974e-03f, +3.920111748e-02f, +9.899604850e-01f, -2.828800389e-02f },
-    { -1.102133100e-03f, +3.903616254e-02f, +9.900338822e-01f, -2.820285313e-02f },
-    { -1.096316489e-03f, +3.887136328e-02f, +9.901070133e-01f, -2.811756839e-02f },
-    { -1.090514127e-03f, +3.870671968e-02f, +9.901798782e-01f, -2.803214962e-02f },
-    { -1.084726001e-03f, +3.854223173e-02f, +9.902524768e-01f, -2.794659675e-02f },
-    { -1.078952096e-03f, +3.837789942e-02f, +9.903248092e-01f, -2.786090972e-02f },
-    { -1.073192399e-03f, +3.821372273e-02f, +9.903968753e-01f, -2.777508847e-02f },
-    { -1.067446895e-03f, +3.804970164e-02f, +9.904686751e-01f, -2.768913294e-02f },
-    { -1.061715570e-03f, +3.788583615e-02f, +9.905402084e-01f, -2.760304307e-02f },
-    { -1.055998411e-03f, +3.772212623e-02f, +9.906114753e-01f, -2.751681879e-02f },
-    { -1.050295402e-03f, +3.755857188e-02f, +9.906824756e-01f, -2.743046005e-02f },
-    { -1.044606531e-03f, +3.739517307e-02f, +9.907532095e-01f, -2.734396678e-02f },
-    { -1.038931782e-03f, +3.723192979e-02f, +9.908236768e-01f, -2.725733893e-02f },
-    { -1.033271142e-03f, +3.706884203e-02f, +9.908938774e-01f, -2.717057642e-02f },
-    { -1.027624597e-03f, +3.690590976e-02f, +9.909638114e-01f, -2.708367921e-02f },
-    { -1.021992133e-03f, +3.674313298e-02f, +9.910334786e-01f, -2.699664722e-02f },
-    { -1.016373735e-03f, +3.658051167e-02f, +9.911028791e-01f, -2.690948040e-02f },
-    { -1.010769389e-03f, +3.641804581e-02f, +9.911720128e-01f, -2.682217869e-02f },
-    { -1.005179082e-03f, +3.625573538e-02f, +9.912408796e-01f, -2.673474203e-02f },
-    { -9.996027983e-04f, +3.609358038e-02f, +9.913094795e-01f, -2.664717035e-02f },
-    { -9.940405249e-04f, +3.593158078e-02f, +9.913778125e-01f, -2.655946360e-02f },
-    { -9.884922474e-04f, +3.576973656e-02f, +9.914458785e-01f, -2.647162171e-02f },
-    { -9.829579515e-04f, +3.560804772e-02f, +9.915136775e-01f, -2.638364463e-02f },
-    { -9.774376231e-04f, +3.544651423e-02f, +9.915812094e-01f, -2.629553230e-02f },
-    { -9.719312480e-04f, +3.528513608e-02f, +9.916484743e-01f, -2.620728464e-02f },
-    { -9.664388120e-04f, +3.512391325e-02f, +9.917154719e-01f, -2.611890161e-02f },
-    { -9.609603011e-04f, +3.496284573e-02f, +9.917822024e-01f, -2.603038315e-02f },
-    { -9.554957009e-04f, +3.480193349e-02f, +9.918486656e-01f, -2.594172918e-02f },
-    { -9.500449974e-04f, +3.464117652e-02f, +9.919148616e-01f, -2.585293966e-02f },
-    { -9.446081762e-04f, +3.448057480e-02f, +9.919807902e-01f, -2.576401452e-02f },
-    { -9.391852233e-04f, +3.432012832e-02f, +9.920464515e-01f, -2.567495371e-02f },
-    { -9.337761243e-04f, +3.415983706e-02f, +9.921118453e-01f, -2.558575716e-02f },
-    { -9.283808652e-04f, +3.399970099e-02f, +9.921769718e-01f, -2.549642481e-02f },
-    { -9.229994316e-04f, +3.383972011e-02f, +9.922418307e-01f, -2.540695661e-02f },
-    { -9.176318093e-04f, +3.367989440e-02f, +9.923064221e-01f, -2.531735249e-02f },
-    { -9.122779842e-04f, +3.352022383e-02f, +9.923707459e-01f, -2.522761239e-02f },
-    { -9.069379419e-04f, +3.336070839e-02f, +9.924348021e-01f, -2.513773626e-02f },
-    { -9.016116683e-04f, +3.320134807e-02f, +9.924985907e-01f, -2.504772404e-02f },
-    { -8.962991490e-04f, +3.304214283e-02f, +9.925621116e-01f, -2.495757566e-02f },
-    { -8.910003699e-04f, +3.288309267e-02f, +9.926253647e-01f, -2.486729107e-02f },
-    { -8.857153167e-04f, +3.272419757e-02f, +9.926883501e-01f, -2.477687020e-02f },
-    { -8.804439750e-04f, +3.256545750e-02f, +9.927510676e-01f, -2.468631300e-02f },
-    { -8.751863308e-04f, +3.240687246e-02f, +9.928135173e-01f, -2.459561942e-02f },
-    { -8.699423695e-04f, +3.224844242e-02f, +9.928756991e-01f, -2.450478938e-02f },
-    { -8.647120771e-04f, +3.209016735e-02f, +9.929376130e-01f, -2.441382283e-02f },
-    { -8.594954392e-04f, +3.193204725e-02f, +9.929992589e-01f, -2.432271972e-02f },
-    { -8.542924415e-04f, +3.177408210e-02f, +9.930606368e-01f, -2.423147998e-02f },
-    { -8.491030697e-04f, +3.161627187e-02f, +9.931217466e-01f, -2.414010355e-02f },
-    { -8.439273095e-04f, +3.145861654e-02f, +9.931825884e-01f, -2.404859038e-02f },
-    { -8.387651466e-04f, +3.130111610e-02f, +9.932431620e-01f, -2.395694040e-02f },
-    { -8.336165668e-04f, +3.114377053e-02f, +9.933034675e-01f, -2.386515357e-02f },
-    { -8.284815556e-04f, +3.098657981e-02f, +9.933635047e-01f, -2.377322981e-02f },
-    { -8.233600987e-04f, +3.082954391e-02f, +9.934232738e-01f, -2.368116908e-02f },
-    { -8.182521819e-04f, +3.067266283e-02f, +9.934827745e-01f, -2.358897131e-02f },
-    { -8.131577908e-04f, +3.051593653e-02f, +9.935420069e-01f, -2.349663644e-02f },
-    { -8.080769110e-04f, +3.035936500e-02f, +9.936009710e-01f, -2.340416442e-02f },
-    { -8.030095283e-04f, +3.020294821e-02f, +9.936596666e-01f, -2.331155519e-02f },
-    { -7.979556282e-04f, +3.004668616e-02f, +9.937180939e-01f, -2.321880869e-02f },
-    { -7.929151965e-04f, +2.989057881e-02f, +9.937762527e-01f, -2.312592486e-02f },
-    { -7.878882187e-04f, +2.973462615e-02f, +9.938341429e-01f, -2.303290364e-02f },
-    { -7.828746805e-04f, +2.957882816e-02f, +9.938917647e-01f, -2.293974499e-02f },
-    { -7.778745675e-04f, +2.942318481e-02f, +9.939491178e-01f, -2.284644883e-02f },
-    { -7.728878654e-04f, +2.926769610e-02f, +9.940062023e-01f, -2.275301511e-02f },
-    { -7.679145598e-04f, +2.911236198e-02f, +9.940630182e-01f, -2.265944377e-02f },
-    { -7.629546363e-04f, +2.895718245e-02f, +9.941195654e-01f, -2.256573476e-02f },
-    { -7.580080805e-04f, +2.880215748e-02f, +9.941758439e-01f, -2.247188802e-02f },
-    { -7.530748780e-04f, +2.864728706e-02f, +9.942318536e-01f, -2.237790348e-02f },
-    { -7.481550144e-04f, +2.849257115e-02f, +9.942875945e-01f, -2.228378110e-02f },
-    { -7.432484754e-04f, +2.833800975e-02f, +9.943430666e-01f, -2.218952082e-02f },
-    { -7.383552465e-04f, +2.818360282e-02f, +9.943982699e-01f, -2.209512257e-02f },
-    { -7.334753133e-04f, +2.802935035e-02f, +9.944532042e-01f, -2.200058631e-02f },
-    { -7.286086614e-04f, +2.787525232e-02f, +9.945078696e-01f, -2.190591197e-02f },
-    { -7.237552763e-04f, +2.772130869e-02f, +9.945622660e-01f, -2.181109950e-02f },
-    { -7.189151437e-04f, +2.756751946e-02f, +9.946163934e-01f, -2.171614883e-02f },
-    { -7.140882492e-04f, +2.741388460e-02f, +9.946702518e-01f, -2.162105992e-02f },
-    { -7.092745782e-04f, +2.726040409e-02f, +9.947238411e-01f, -2.152583271e-02f },
-    { -7.044741164e-04f, +2.710707790e-02f, +9.947771613e-01f, -2.143046713e-02f },
-    { -6.996868493e-04f, +2.695390602e-02f, +9.948302124e-01f, -2.133496314e-02f },
-    { -6.949127625e-04f, +2.680088842e-02f, +9.948829943e-01f, -2.123932068e-02f },
-    { -6.901518415e-04f, +2.664802507e-02f, +9.949355069e-01f, -2.114353968e-02f },
-    { -6.854040719e-04f, +2.649531596e-02f, +9.949877504e-01f, -2.104762010e-02f },
-    { -6.806694392e-04f, +2.634276107e-02f, +9.950397245e-01f, -2.095156187e-02f },
-    { -6.759479289e-04f, +2.619036036e-02f, +9.950914294e-01f, -2.085536494e-02f },
-    { -6.712395266e-04f, +2.603811383e-02f, +9.951428649e-01f, -2.075902926e-02f },
-    { -6.665442179e-04f, +2.588602143e-02f, +9.951940310e-01f, -2.066255477e-02f },
-    { -6.618619881e-04f, +2.573408316e-02f, +9.952449278e-01f, -2.056594140e-02f },
-    { -6.571928229e-04f, +2.558229899e-02f, +9.952955551e-01f, -2.046918912e-02f },
-    { -6.525367078e-04f, +2.543066889e-02f, +9.953459129e-01f, -2.037229785e-02f },
-    { -6.478936283e-04f, +2.527919285e-02f, +9.953960012e-01f, -2.027526754e-02f },
-    { -6.432635698e-04f, +2.512787083e-02f, +9.954458200e-01f, -2.017809815e-02f },
-    { -6.386465180e-04f, +2.497670282e-02f, +9.954953692e-01f, -2.008078960e-02f },
-    { -6.340424582e-04f, +2.482568879e-02f, +9.955446489e-01f, -1.998334185e-02f },
-    { -6.294513760e-04f, +2.467482872e-02f, +9.955936589e-01f, -1.988575485e-02f },
-    { -6.248732570e-04f, +2.452412258e-02f, +9.956423992e-01f, -1.978802853e-02f },
-    { -6.203080865e-04f, +2.437357035e-02f, +9.956908698e-01f, -1.969016283e-02f },
-    { -6.157558500e-04f, +2.422317200e-02f, +9.957390708e-01f, -1.959215772e-02f },
-    { -6.112165332e-04f, +2.407292752e-02f, +9.957870019e-01f, -1.949401312e-02f },
-    { -6.066901213e-04f, +2.392283688e-02f, +9.958346633e-01f, -1.939572898e-02f },
-    { -6.021765999e-04f, +2.377290004e-02f, +9.958820549e-01f, -1.929730525e-02f },
-    { -5.976759545e-04f, +2.362311700e-02f, +9.959291766e-01f, -1.919874188e-02f },
-    { -5.931881705e-04f, +2.347348772e-02f, +9.959760285e-01f, -1.910003880e-02f },
-    { -5.887132334e-04f, +2.332401218e-02f, +9.960226105e-01f, -1.900119597e-02f },
-    { -5.842511287e-04f, +2.317469035e-02f, +9.960689225e-01f, -1.890221333e-02f },
-    { -5.798018418e-04f, +2.302552221e-02f, +9.961149645e-01f, -1.880309082e-02f },
-    { -5.753653581e-04f, +2.287650774e-02f, +9.961607366e-01f, -1.870382839e-02f },
-    { -5.709416631e-04f, +2.272764690e-02f, +9.962062387e-01f, -1.860442598e-02f },
-    { -5.665307423e-04f, +2.257893968e-02f, +9.962514707e-01f, -1.850488354e-02f },
-    { -5.621325811e-04f, +2.243038605e-02f, +9.962964326e-01f, -1.840520102e-02f },
-    { -5.577471650e-04f, +2.228198598e-02f, +9.963411244e-01f, -1.830537836e-02f },
-    { -5.533744792e-04f, +2.213373945e-02f, +9.963855461e-01f, -1.820541550e-02f },
-    { -5.490145094e-04f, +2.198564643e-02f, +9.964296976e-01f, -1.810531240e-02f },
-    { -5.446672410e-04f, +2.183770690e-02f, +9.964735789e-01f, -1.800506899e-02f },
-    { -5.403326592e-04f, +2.168992083e-02f, +9.965171900e-01f, -1.790468523e-02f },
-    { -5.360107497e-04f, +2.154228819e-02f, +9.965605309e-01f, -1.780416106e-02f },
-    { -5.317014977e-04f, +2.139480896e-02f, +9.966036014e-01f, -1.770349642e-02f },
-    { -5.274048887e-04f, +2.124748312e-02f, +9.966464017e-01f, -1.760269126e-02f },
-    { -5.231209082e-04f, +2.110031063e-02f, +9.966889317e-01f, -1.750174553e-02f },
-    { -5.188495414e-04f, +2.095329147e-02f, +9.967311913e-01f, -1.740065918e-02f },
-    { -5.145907739e-04f, +2.080642562e-02f, +9.967731805e-01f, -1.729943214e-02f },
-    { -5.103445911e-04f, +2.065971304e-02f, +9.968148993e-01f, -1.719806437e-02f },
-    { -5.061109782e-04f, +2.051315372e-02f, +9.968563476e-01f, -1.709655581e-02f },
-    { -5.018899208e-04f, +2.036674762e-02f, +9.968975255e-01f, -1.699490642e-02f },
-    { -4.976814042e-04f, +2.022049471e-02f, +9.969384329e-01f, -1.689311613e-02f },
-    { -4.934854139e-04f, +2.007439498e-02f, +9.969790698e-01f, -1.679118489e-02f },
-    { -4.893019351e-04f, +1.992844839e-02f, +9.970194362e-01f, -1.668911265e-02f },
-    { -4.851309533e-04f, +1.978265492e-02f, +9.970595319e-01f, -1.658689935e-02f },
-    { -4.809724538e-04f, +1.963701453e-02f, +9.970993571e-01f, -1.648454495e-02f },
-    { -4.768264221e-04f, +1.949152721e-02f, +9.971389117e-01f, -1.638204939e-02f },
-    { -4.726928435e-04f, +1.934619292e-02f, +9.971781956e-01f, -1.627941262e-02f },
-    { -4.685717034e-04f, +1.920101164e-02f, +9.972172089e-01f, -1.617663458e-02f },
-    { -4.644629872e-04f, +1.905598334e-02f, +9.972559515e-01f, -1.607371522e-02f },
-    { -4.603666801e-04f, +1.891110799e-02f, +9.972944233e-01f, -1.597065449e-02f },
-    { -4.562827677e-04f, +1.876638556e-02f, +9.973326244e-01f, -1.586745234e-02f },
-    { -4.522112352e-04f, +1.862181603e-02f, +9.973705548e-01f, -1.576410871e-02f },
-    { -4.481520680e-04f, +1.847739937e-02f, +9.974082143e-01f, -1.566062355e-02f },
-    { -4.441052515e-04f, +1.833313554e-02f, +9.974456031e-01f, -1.555699680e-02f },
-    { -4.400707710e-04f, +1.818902453e-02f, +9.974827210e-01f, -1.545322843e-02f },
-    { -4.360486119e-04f, +1.804506631e-02f, +9.975195680e-01f, -1.534931837e-02f },
-    { -4.320387594e-04f, +1.790126083e-02f, +9.975561442e-01f, -1.524526657e-02f },
-    { -4.280411991e-04f, +1.775760809e-02f, +9.975924494e-01f, -1.514107297e-02f },
-    { -4.240559161e-04f, +1.761410804e-02f, +9.976284837e-01f, -1.503673754e-02f },
-    { -4.200828959e-04f, +1.747076066e-02f, +9.976642471e-01f, -1.493226021e-02f },
-    { -4.161221238e-04f, +1.732756592e-02f, +9.976997395e-01f, -1.482764093e-02f },
-    { -4.121735850e-04f, +1.718452380e-02f, +9.977349608e-01f, -1.472287966e-02f },
-    { -4.082372651e-04f, +1.704163425e-02f, +9.977699112e-01f, -1.461797634e-02f },
-    { -4.043131492e-04f, +1.689889726e-02f, +9.978045905e-01f, -1.451293091e-02f },
-    { -4.004012227e-04f, +1.675631280e-02f, +9.978389988e-01f, -1.440774333e-02f },
-    { -3.965014710e-04f, +1.661388082e-02f, +9.978731359e-01f, -1.430241355e-02f },
-    { -3.926138794e-04f, +1.647160132e-02f, +9.979070020e-01f, -1.419694151e-02f },
-    { -3.887384331e-04f, +1.632947425e-02f, +9.979405969e-01f, -1.409132716e-02f },
-    { -3.848751175e-04f, +1.618749959e-02f, +9.979739207e-01f, -1.398557045e-02f },
-    { -3.810239179e-04f, +1.604567730e-02f, +9.980069732e-01f, -1.387967133e-02f },
-    { -3.771848197e-04f, +1.590400737e-02f, +9.980397546e-01f, -1.377362975e-02f },
-    { -3.733578082e-04f, +1.576248975e-02f, +9.980722648e-01f, -1.366744566e-02f },
-    { -3.695428686e-04f, +1.562112441e-02f, +9.981045038e-01f, -1.356111900e-02f },
-    { -3.657399862e-04f, +1.547991134e-02f, +9.981364714e-01f, -1.345464973e-02f },
-    { -3.619491465e-04f, +1.533885049e-02f, +9.981681678e-01f, -1.334803780e-02f },
-    { -3.581703346e-04f, +1.519794184e-02f, +9.981995929e-01f, -1.324128315e-02f },
-    { -3.544035359e-04f, +1.505718535e-02f, +9.982307467e-01f, -1.313438573e-02f },
-    { -3.506487357e-04f, +1.491658101e-02f, +9.982616292e-01f, -1.302734550e-02f },
-    { -3.469059193e-04f, +1.477612876e-02f, +9.982922403e-01f, -1.292016240e-02f },
-    { -3.431750720e-04f, +1.463582860e-02f, +9.983225800e-01f, -1.281283638e-02f },
-    { -3.394561791e-04f, +1.449568047e-02f, +9.983526483e-01f, -1.270536739e-02f },
-    { -3.357492258e-04f, +1.435568436e-02f, +9.983824452e-01f, -1.259775538e-02f },
-    { -3.320541975e-04f, +1.421584024e-02f, +9.984119707e-01f, -1.249000030e-02f },
-    { -3.283710794e-04f, +1.407614806e-02f, +9.984412247e-01f, -1.238210211e-02f },
-    { -3.246998569e-04f, +1.393660781e-02f, +9.984702072e-01f, -1.227406075e-02f },
-    { -3.210405152e-04f, +1.379721944e-02f, +9.984989183e-01f, -1.216587616e-02f },
-    { -3.173930397e-04f, +1.365798293e-02f, +9.985273578e-01f, -1.205754831e-02f },
-    { -3.137574155e-04f, +1.351889825e-02f, +9.985555259e-01f, -1.194907714e-02f },
-    { -3.101336280e-04f, +1.337996537e-02f, +9.985834223e-01f, -1.184046260e-02f },
-    { -3.065216624e-04f, +1.324118424e-02f, +9.986110473e-01f, -1.173170465e-02f },
-    { -3.029215041e-04f, +1.310255485e-02f, +9.986384006e-01f, -1.162280322e-02f },
-    { -2.993331383e-04f, +1.296407716e-02f, +9.986654823e-01f, -1.151375828e-02f },
-    { -2.957565503e-04f, +1.282575114e-02f, +9.986922924e-01f, -1.140456977e-02f },
-    { -2.921917254e-04f, +1.268757675e-02f, +9.987188309e-01f, -1.129523765e-02f },
-    { -2.886386488e-04f, +1.254955397e-02f, +9.987450978e-01f, -1.118576186e-02f },
-    { -2.850973058e-04f, +1.241168275e-02f, +9.987710929e-01f, -1.107614236e-02f },
-    { -2.815676816e-04f, +1.227396308e-02f, +9.987968164e-01f, -1.096637910e-02f },
-    { -2.780497616e-04f, +1.213639492e-02f, +9.988222682e-01f, -1.085647202e-02f },
-    { -2.745435310e-04f, +1.199897823e-02f, +9.988474483e-01f, -1.074642108e-02f },
-    { -2.710489751e-04f, +1.186171298e-02f, +9.988723567e-01f, -1.063622623e-02f },
-    { -2.675660791e-04f, +1.172459914e-02f, +9.988969933e-01f, -1.052588743e-02f },
-    { -2.640948284e-04f, +1.158763668e-02f, +9.989213581e-01f, -1.041540461e-02f },
-    { -2.606352080e-04f, +1.145082556e-02f, +9.989454512e-01f, -1.030477774e-02f },
-    { -2.571872034e-04f, +1.131416575e-02f, +9.989692724e-01f, -1.019400677e-02f },
-    { -2.537507998e-04f, +1.117765722e-02f, +9.989928219e-01f, -1.008309164e-02f },
-    { -2.503259824e-04f, +1.104129994e-02f, +9.990160995e-01f, -9.972032308e-03f },
-    { -2.469127365e-04f, +1.090509386e-02f, +9.990391053e-01f, -9.860828729e-03f },
-    { -2.435110474e-04f, +1.076903897e-02f, +9.990618393e-01f, -9.749480853e-03f },
-    { -2.401209002e-04f, +1.063313522e-02f, +9.990843014e-01f, -9.637988631e-03f },
-    { -2.367422804e-04f, +1.049738258e-02f, +9.991064916e-01f, -9.526352014e-03f },
-    { -2.333751730e-04f, +1.036178102e-02f, +9.991284099e-01f, -9.414570956e-03f },
-    { -2.300195634e-04f, +1.022633050e-02f, +9.991500563e-01f, -9.302645409e-03f },
-    { -2.266754367e-04f, +1.009103099e-02f, +9.991714307e-01f, -9.190575323e-03f },
-    { -2.233427784e-04f, +9.955882461e-03f, +9.991925333e-01f, -9.078360653e-03f },
-    { -2.200215735e-04f, +9.820884872e-03f, +9.992133639e-01f, -8.966001349e-03f },
-    { -2.167118075e-04f, +9.686038192e-03f, +9.992339225e-01f, -8.853497366e-03f },
-    { -2.134134654e-04f, +9.551342385e-03f, +9.992542091e-01f, -8.740848654e-03f },
-    { -2.101265325e-04f, +9.416797418e-03f, +9.992742238e-01f, -8.628055168e-03f },
-    { -2.068509942e-04f, +9.282403256e-03f, +9.992939664e-01f, -8.515116858e-03f },
-    { -2.035868356e-04f, +9.148159865e-03f, +9.993134371e-01f, -8.402033679e-03f },
-    { -2.003340419e-04f, +9.014067211e-03f, +9.993326357e-01f, -8.288805583e-03f },
-    { -1.970925985e-04f, +8.880125258e-03f, +9.993515622e-01f, -8.175432524e-03f },
-    { -1.938624906e-04f, +8.746333973e-03f, +9.993702168e-01f, -8.061914453e-03f },
-    { -1.906437034e-04f, +8.612693320e-03f, +9.993885992e-01f, -7.948251325e-03f },
-    { -1.874362221e-04f, +8.479203263e-03f, +9.994067096e-01f, -7.834443092e-03f },
-    { -1.842400320e-04f, +8.345863769e-03f, +9.994245479e-01f, -7.720489707e-03f },
-    { -1.810551183e-04f, +8.212674803e-03f, +9.994421141e-01f, -7.606391125e-03f },
-    { -1.778814663e-04f, +8.079636328e-03f, +9.994594082e-01f, -7.492147298e-03f },
-    { -1.747190612e-04f, +7.946748310e-03f, +9.994764302e-01f, -7.377758181e-03f },
-    { -1.715678882e-04f, +7.814010713e-03f, +9.994931800e-01f, -7.263223725e-03f },
-    { -1.684279326e-04f, +7.681423501e-03f, +9.995096577e-01f, -7.148543887e-03f },
-    { -1.652991797e-04f, +7.548986640e-03f, +9.995258632e-01f, -7.033718618e-03f },
-    { -1.621816145e-04f, +7.416700094e-03f, +9.995417966e-01f, -6.918747873e-03f },
-    { -1.590752225e-04f, +7.284563826e-03f, +9.995574578e-01f, -6.803631606e-03f },
-    { -1.559799888e-04f, +7.152577801e-03f, +9.995728468e-01f, -6.688369772e-03f },
-    { -1.528958987e-04f, +7.020741983e-03f, +9.995879637e-01f, -6.572962323e-03f },
-    { -1.498229373e-04f, +6.889056337e-03f, +9.996028083e-01f, -6.457409214e-03f },
-    { -1.467610900e-04f, +6.757520824e-03f, +9.996173807e-01f, -6.341710400e-03f },
-    { -1.437103420e-04f, +6.626135411e-03f, +9.996316809e-01f, -6.225865834e-03f },
-    { -1.406706784e-04f, +6.494900059e-03f, +9.996457089e-01f, -6.109875472e-03f },
-    { -1.376420846e-04f, +6.363814734e-03f, +9.996594646e-01f, -5.993739268e-03f },
-    { -1.346245458e-04f, +6.232879398e-03f, +9.996729481e-01f, -5.877457176e-03f },
-    { -1.316180471e-04f, +6.102094014e-03f, +9.996861593e-01f, -5.761029151e-03f },
-    { -1.286225739e-04f, +5.971458547e-03f, +9.996990983e-01f, -5.644455148e-03f },
-    { -1.256381113e-04f, +5.840972959e-03f, +9.997117650e-01f, -5.527735122e-03f },
-    { -1.226646447e-04f, +5.710637213e-03f, +9.997241594e-01f, -5.410869028e-03f },
-    { -1.197021592e-04f, +5.580451273e-03f, +9.997362815e-01f, -5.293856820e-03f },
-    { -1.167506400e-04f, +5.450415101e-03f, +9.997481313e-01f, -5.176698454e-03f },
-    { -1.138100725e-04f, +5.320528660e-03f, +9.997597089e-01f, -5.059393885e-03f },
-    { -1.108804418e-04f, +5.190791913e-03f, +9.997710141e-01f, -4.941943068e-03f },
-    { -1.079617332e-04f, +5.061204824e-03f, +9.997820469e-01f, -4.824345959e-03f },
-    { -1.050539318e-04f, +4.931767353e-03f, +9.997928075e-01f, -4.706602513e-03f },
-    { -1.021570230e-04f, +4.802479464e-03f, +9.998032957e-01f, -4.588712686e-03f },
-    { -9.927099199e-05f, +4.673341119e-03f, +9.998135116e-01f, -4.470676433e-03f },
-    { -9.639582397e-05f, +4.544352281e-03f, +9.998234552e-01f, -4.352493710e-03f },
-    { -9.353150418e-05f, +4.415512912e-03f, +9.998331264e-01f, -4.234164473e-03f },
-    { -9.067801786e-05f, +4.286822973e-03f, +9.998425252e-01f, -4.115688677e-03f },
-    { -8.783535025e-05f, +4.158282427e-03f, +9.998516517e-01f, -3.997066279e-03f },
-    { -8.500348659e-05f, +4.029891236e-03f, +9.998605058e-01f, -3.878297235e-03f },
-    { -8.218241209e-05f, +3.901649361e-03f, +9.998690875e-01f, -3.759381500e-03f },
-    { -7.937211202e-05f, +3.773556765e-03f, +9.998773969e-01f, -3.640319031e-03f },
-    { -7.657257158e-05f, +3.645613409e-03f, +9.998854338e-01f, -3.521109785e-03f },
-    { -7.378377604e-05f, +3.517819255e-03f, +9.998931984e-01f, -3.401753717e-03f },
-    { -7.100571061e-05f, +3.390174264e-03f, +9.999006906e-01f, -3.282250785e-03f },
-    { -6.823836055e-05f, +3.262678397e-03f, +9.999079103e-01f, -3.162600944e-03f },
-    { -6.548171107e-05f, +3.135331617e-03f, +9.999148577e-01f, -3.042804151e-03f },
-    { -6.273574744e-05f, +3.008133883e-03f, +9.999215326e-01f, -2.922860364e-03f },
-    { -6.000045487e-05f, +2.881085158e-03f, +9.999279352e-01f, -2.802769538e-03f },
-    { -5.727581862e-05f, +2.754185402e-03f, +9.999340653e-01f, -2.682531632e-03f },
-    { -5.456182391e-05f, +2.627434576e-03f, +9.999399230e-01f, -2.562146601e-03f },
-    { -5.185845600e-05f, +2.500832641e-03f, +9.999455083e-01f, -2.441614402e-03f },
-    { -4.916570012e-05f, +2.374379558e-03f, +9.999508211e-01f, -2.320934994e-03f },
-    { -4.648354151e-05f, +2.248075287e-03f, +9.999558615e-01f, -2.200108333e-03f },
-    { -4.381196542e-05f, +2.121919790e-03f, +9.999606295e-01f, -2.079134377e-03f },
-    { -4.115095708e-05f, +1.995913026e-03f, +9.999651250e-01f, -1.958013083e-03f },
-    { -3.850050175e-05f, +1.870054956e-03f, +9.999693481e-01f, -1.836744408e-03f },
-    { -3.586058466e-05f, +1.744345541e-03f, +9.999732988e-01f, -1.715328311e-03f },
-    { -3.323119106e-05f, +1.618784740e-03f, +9.999769770e-01f, -1.593764748e-03f },
-    { -3.061230620e-05f, +1.493372514e-03f, +9.999803827e-01f, -1.472053677e-03f },
-    { -2.800391533e-05f, +1.368108822e-03f, +9.999835160e-01f, -1.350195058e-03f },
-    { -2.540600368e-05f, +1.242993626e-03f, +9.999863768e-01f, -1.228188846e-03f },
-    { -2.281855651e-05f, +1.118026884e-03f, +9.999889652e-01f, -1.106035001e-03f },
-    { -2.024155907e-05f, +9.932085563e-04f, +9.999912812e-01f, -9.837334803e-04f },
-    { -1.767499661e-05f, +8.685386028e-04f, +9.999933246e-01f, -8.612842424e-04f },
-    { -1.511885438e-05f, +7.440169831e-04f, +9.999950956e-01f, -7.386872455e-04f },
-    { -1.257311763e-05f, +6.196436566e-04f, +9.999965942e-01f, -6.159424479e-04f },
-    { -1.003777162e-05f, +4.954185828e-04f, +9.999978203e-01f, -4.930498082e-04f },
-    { -7.512801591e-06f, +3.713417210e-04f, +9.999987739e-01f, -3.700092848e-04f },
-    { -4.998192808e-06f, +2.474130305e-04f, +9.999994551e-01f, -2.468208365e-04f },
-    { -2.493930525e-06f, +1.236324705e-04f, +9.999998638e-01f, -1.234844220e-04f },
-};

+ 9 - 1
libs/openal-soft/Alc/compat.h

@@ -3,6 +3,10 @@
 
 #include "alstring.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #ifdef _WIN32
 
 #define WIN32_LEAN_AND_MEAN
@@ -38,7 +42,7 @@ struct FileMapping {
 struct FileMapping MapFileToMem(const char *fname);
 void UnmapFileMem(const struct FileMapping *mapping);
 
-al_string GetProcPath(void);
+void GetProcBinary(al_string *path, al_string *fname);
 
 #ifdef HAVE_DYNLOAD
 void *LoadLib(const char *name);
@@ -54,4 +58,8 @@ void *GetSymbol(void *handle, const char *name);
 void *Android_GetJNIEnv(void);
 #endif
 
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
 #endif /* AL_COMPAT_H */

+ 17 - 16
libs/openal-soft/Alc/converter.c

@@ -3,7 +3,8 @@
 
 #include "converter.h"
 
-#include "mixer_defs.h"
+#include "fpu_modes.h"
+#include "mixer/defs.h"
 
 
 SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType dstType, ALsizei numchans, ALsizei srcRate, ALsizei dstRate)
@@ -26,15 +27,15 @@ SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType
 
     /* Have to set the mixer FPU mode since that's what the resampler code expects. */
     START_MIXER_MODE();
-    step = fastf2i(minf((ALdouble)srcRate / dstRate, MAX_PITCH)*FRACTIONONE + 0.5f);
+    step = fastf2i((ALfloat)mind((ALdouble)srcRate / dstRate, MAX_PITCH)*FRACTIONONE + 0.5f);
     converter->mIncrement = maxi(step, 1);
     if(converter->mIncrement == FRACTIONONE)
-        converter->mResample = Resample_copy32_C;
+        converter->mResample = Resample_copy_C;
     else
     {
         /* TODO: Allow other resamplers. */
-        BsincPrepare(converter->mIncrement, &converter->mState.bsinc);
-        converter->mResample = SelectResampler(BSincResampler);
+        BsincPrepare(converter->mIncrement, &converter->mState.bsinc, &bsinc12);
+        converter->mResample = SelectResampler(BSinc12Resampler);
     }
     END_MIXER_MODE();
 
@@ -205,8 +206,8 @@ ALsizei SampleConverterAvailableOut(SampleConverter *converter, ALsizei srcframe
         return 0;
     }
 
-    if(prepcount < MAX_POST_SAMPLES+MAX_PRE_SAMPLES &&
-       MAX_POST_SAMPLES+MAX_PRE_SAMPLES-prepcount >= srcframes)
+    if(prepcount < MAX_RESAMPLE_PADDING*2 &&
+       MAX_RESAMPLE_PADDING*2 - prepcount >= srcframes)
     {
         /* Not enough input samples to generate an output sample. */
         return 0;
@@ -214,7 +215,7 @@ ALsizei SampleConverterAvailableOut(SampleConverter *converter, ALsizei srcframe
 
     DataSize64  = prepcount;
     DataSize64 += srcframes;
-    DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
+    DataSize64 -= MAX_RESAMPLE_PADDING*2;
     DataSize64 <<= FRACTIONBITS;
     DataSize64 -= DataPosFrac;
 
@@ -256,10 +257,10 @@ ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALs
             converter->mSrcPrepCount = 0;
             continue;
         }
-        toread = mini(*srcframes, BUFFERSIZE-(MAX_POST_SAMPLES+MAX_PRE_SAMPLES));
+        toread = mini(*srcframes, BUFFERSIZE - MAX_RESAMPLE_PADDING*2);
 
-        if(prepcount < MAX_POST_SAMPLES+MAX_PRE_SAMPLES &&
-           MAX_POST_SAMPLES+MAX_PRE_SAMPLES-prepcount >= toread)
+        if(prepcount < MAX_RESAMPLE_PADDING*2 &&
+           MAX_RESAMPLE_PADDING*2 - prepcount >= toread)
         {
             /* Not enough input samples to generate an output sample. Store
              * what we're given for later.
@@ -277,7 +278,7 @@ ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALs
 
         DataSize64  = prepcount;
         DataSize64 += toread;
-        DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
+        DataSize64 -= MAX_RESAMPLE_PADDING*2;
         DataSize64 <<= FRACTIONBITS;
         DataSize64 -= DataPosFrac;
 
@@ -310,7 +311,7 @@ ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALs
                        sizeof(converter->Chan[chan].mPrevSamples));
             else
             {
-                size_t len = mini(MAX_PRE_SAMPLES+MAX_POST_SAMPLES, prepcount+toread-SrcDataEnd);
+                size_t len = mini(MAX_RESAMPLE_PADDING*2, prepcount+toread-SrcDataEnd);
                 memcpy(converter->Chan[chan].mPrevSamples, &SrcData[SrcDataEnd],
                        len*sizeof(ALfloat));
                 memset(converter->Chan[chan].mPrevSamples+len, 0,
@@ -319,7 +320,7 @@ ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALs
 
             /* Now resample, and store the result in the output buffer. */
             ResampledData = converter->mResample(&converter->mState,
-                SrcData+MAX_PRE_SAMPLES, DataPosFrac, increment,
+                SrcData+MAX_RESAMPLE_PADDING, DataPosFrac, increment,
                 DstData, DstSize
             );
 
@@ -331,8 +332,8 @@ ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALs
          * fractional offset.
          */
         DataPosFrac += increment*DstSize;
-        converter->mSrcPrepCount = mini(MAX_PRE_SAMPLES+MAX_POST_SAMPLES,
-                                        prepcount+toread-(DataPosFrac>>FRACTIONBITS));
+        converter->mSrcPrepCount = mini(prepcount + toread - (DataPosFrac>>FRACTIONBITS),
+                                        MAX_RESAMPLE_PADDING*2);
         converter->mFracOffset = DataPosFrac & FRACTIONMASK;
 
         /* Update the src and dst pointers in case there's still more to do. */

+ 1 - 1
libs/openal-soft/Alc/converter.h

@@ -26,7 +26,7 @@ typedef struct SampleConverter {
     alignas(16) ALfloat mDstSamples[BUFFERSIZE];
 
     struct {
-        alignas(16) ALfloat mPrevSamples[MAX_PRE_SAMPLES+MAX_POST_SAMPLES];
+        alignas(16) ALfloat mPrevSamples[MAX_RESAMPLE_PADDING*2];
     } Chan[];
 } SampleConverter;
 

+ 15 - 0
libs/openal-soft/Alc/cpu_caps.h

@@ -0,0 +1,15 @@
+#ifndef CPU_CAPS_H
+#define CPU_CAPS_H
+
+extern int CPUCapFlags;
+enum {
+    CPU_CAP_SSE    = 1<<0,
+    CPU_CAP_SSE2   = 1<<1,
+    CPU_CAP_SSE3   = 1<<2,
+    CPU_CAP_SSE4_1 = 1<<3,
+    CPU_CAP_NEON   = 1<<4,
+};
+
+void FillCPUCaps(int capfilter);
+
+#endif /* CPU_CAPS_H */

+ 262 - 117
libs/openal-soft/Alc/effects/chorus.c

@@ -24,32 +24,40 @@
 #include <stdlib.h>
 
 #include "alMain.h"
-#include "alFilter.h"
 #include "alAuxEffectSlot.h"
 #include "alError.h"
 #include "alu.h"
+#include "filters/defs.h"
 
 
-enum ChorusWaveForm {
-    CWF_Triangle = AL_CHORUS_WAVEFORM_TRIANGLE,
-    CWF_Sinusoid = AL_CHORUS_WAVEFORM_SINUSOID
+static_assert(AL_CHORUS_WAVEFORM_SINUSOID == AL_FLANGER_WAVEFORM_SINUSOID, "Chorus/Flanger waveform value mismatch");
+static_assert(AL_CHORUS_WAVEFORM_TRIANGLE == AL_FLANGER_WAVEFORM_TRIANGLE, "Chorus/Flanger waveform value mismatch");
+
+enum WaveForm {
+    WF_Sinusoid,
+    WF_Triangle
 };
 
 typedef struct ALchorusState {
     DERIVE_FROM_TYPE(ALeffectState);
 
-    ALfloat *SampleBuffer[2];
+    ALfloat *SampleBuffer;
     ALsizei BufferLength;
     ALsizei offset;
+
+    ALsizei lfo_offset;
     ALsizei lfo_range;
     ALfloat lfo_scale;
     ALint lfo_disp;
 
     /* Gains for left and right sides */
-    ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
+    struct {
+        ALfloat Current[MAX_OUTPUT_CHANNELS];
+        ALfloat Target[MAX_OUTPUT_CHANNELS];
+    } Gains[2];
 
     /* effect parameters */
-    enum ChorusWaveForm waveform;
+    enum WaveForm waveform;
     ALint delay;
     ALfloat depth;
     ALfloat feedback;
@@ -57,7 +65,7 @@ typedef struct ALchorusState {
 
 static ALvoid ALchorusState_Destruct(ALchorusState *state);
 static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Device);
-static ALvoid ALchorusState_update(ALchorusState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props);
+static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Context, const ALeffectslot *Slot, const ALeffectProps *props);
 static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
 DECLARE_DEFAULT_ALLOCATORS(ALchorusState)
 
@@ -70,54 +78,51 @@ static void ALchorusState_Construct(ALchorusState *state)
     SET_VTABLE2(ALchorusState, ALeffectState, state);
 
     state->BufferLength = 0;
-    state->SampleBuffer[0] = NULL;
-    state->SampleBuffer[1] = NULL;
+    state->SampleBuffer = NULL;
     state->offset = 0;
+    state->lfo_offset = 0;
     state->lfo_range = 1;
-    state->waveform = CWF_Triangle;
+    state->waveform = WF_Triangle;
 }
 
 static ALvoid ALchorusState_Destruct(ALchorusState *state)
 {
-    al_free(state->SampleBuffer[0]);
-    state->SampleBuffer[0] = NULL;
-    state->SampleBuffer[1] = NULL;
+    al_free(state->SampleBuffer);
+    state->SampleBuffer = NULL;
 
     ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
 static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Device)
 {
+    const ALfloat max_delay = maxf(AL_CHORUS_MAX_DELAY, AL_FLANGER_MAX_DELAY);
     ALsizei maxlen;
-    ALsizei it;
 
-    maxlen = fastf2i(AL_CHORUS_MAX_DELAY * 2.0f * Device->Frequency) + 1;
-    maxlen = NextPowerOf2(maxlen);
+    maxlen = NextPowerOf2(fastf2i(max_delay*2.0f*Device->Frequency) + 1);
+    if(maxlen <= 0) return AL_FALSE;
 
     if(maxlen != state->BufferLength)
     {
-        void *temp = al_calloc(16, maxlen * sizeof(ALfloat) * 2);
+        void *temp = al_calloc(16, maxlen * sizeof(ALfloat));
         if(!temp) return AL_FALSE;
 
-        al_free(state->SampleBuffer[0]);
-        state->SampleBuffer[0] = temp;
-        state->SampleBuffer[1] = state->SampleBuffer[0] + maxlen;
+        al_free(state->SampleBuffer);
+        state->SampleBuffer = temp;
 
         state->BufferLength = maxlen;
     }
 
-    for(it = 0;it < state->BufferLength;it++)
-    {
-        state->SampleBuffer[0][it] = 0.0f;
-        state->SampleBuffer[1][it] = 0.0f;
-    }
+    memset(state->SampleBuffer, 0, state->BufferLength*sizeof(ALfloat));
+    memset(state->Gains, 0, sizeof(state->Gains));
 
     return AL_TRUE;
 }
 
-static ALvoid ALchorusState_update(ALchorusState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props)
+static ALvoid ALchorusState_update(ALchorusState *state, const ALCcontext *Context, const ALeffectslot *Slot, const ALeffectProps *props)
 {
-    ALfloat frequency = (ALfloat)Device->Frequency;
+    const ALsizei mindelay = MAX_RESAMPLE_PADDING << FRACTIONBITS;
+    const ALCdevice *device = Context->Device;
+    ALfloat frequency = (ALfloat)device->Frequency;
     ALfloat coeffs[MAX_AMBI_COEFFS];
     ALfloat rate;
     ALint phase;
@@ -125,50 +130,61 @@ static ALvoid ALchorusState_update(ALchorusState *state, const ALCdevice *Device
     switch(props->Chorus.Waveform)
     {
         case AL_CHORUS_WAVEFORM_TRIANGLE:
-            state->waveform = CWF_Triangle;
+            state->waveform = WF_Triangle;
             break;
         case AL_CHORUS_WAVEFORM_SINUSOID:
-            state->waveform = CWF_Sinusoid;
+            state->waveform = WF_Sinusoid;
             break;
     }
+
+    /* The LFO depth is scaled to be relative to the sample delay. Clamp the
+     * delay and depth to allow enough padding for resampling.
+     */
+    state->delay = maxi(fastf2i(props->Chorus.Delay*frequency*FRACTIONONE + 0.5f),
+                        mindelay);
+    state->depth = minf(props->Chorus.Depth * state->delay,
+                        (ALfloat)(state->delay - mindelay));
+
     state->feedback = props->Chorus.Feedback;
-    state->delay = fastf2i(props->Chorus.Delay * frequency);
-    /* The LFO depth is scaled to be relative to the sample delay. */
-    state->depth = props->Chorus.Depth * state->delay;
 
     /* Gains for left and right sides */
     CalcAngleCoeffs(-F_PI_2, 0.0f, 0.0f, coeffs);
-    ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[0]);
+    ComputeDryPanGains(&device->Dry, coeffs, Slot->Params.Gain, state->Gains[0].Target);
     CalcAngleCoeffs( F_PI_2, 0.0f, 0.0f, coeffs);
-    ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[1]);
+    ComputeDryPanGains(&device->Dry, coeffs, Slot->Params.Gain, state->Gains[1].Target);
 
     phase = props->Chorus.Phase;
     rate = props->Chorus.Rate;
     if(!(rate > 0.0f))
     {
-        state->lfo_scale = 0.0f;
+        state->lfo_offset = 0;
         state->lfo_range = 1;
+        state->lfo_scale = 0.0f;
         state->lfo_disp = 0;
     }
     else
     {
-        /* Calculate LFO coefficient */
-        state->lfo_range = fastf2i(frequency/rate + 0.5f);
+        /* Calculate LFO coefficient (number of samples per cycle). Limit the
+         * max range to avoid overflow when calculating the displacement.
+         */
+        ALsizei lfo_range = mini(fastf2i(frequency/rate + 0.5f), INT_MAX/360 - 180);
+
+        state->lfo_offset = fastf2i((ALfloat)state->lfo_offset/state->lfo_range*
+                                    lfo_range + 0.5f) % lfo_range;
+        state->lfo_range = lfo_range;
         switch(state->waveform)
         {
-            case CWF_Triangle:
+            case WF_Triangle:
                 state->lfo_scale = 4.0f / state->lfo_range;
                 break;
-            case CWF_Sinusoid:
+            case WF_Sinusoid:
                 state->lfo_scale = F_TAU / state->lfo_range;
                 break;
         }
 
         /* Calculate lfo phase displacement */
-        if(phase >= 0)
-            state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f));
-        else
-            state->lfo_disp = fastf2i(state->lfo_range * ((360+phase)/360.0f));
+        if(phase < 0) phase = 360 + phase;
+        state->lfo_disp = (state->lfo_range*phase + 180) / 360;
     }
 }
 
@@ -199,67 +215,68 @@ static void GetSinusoidDelays(ALint *restrict delays, ALsizei offset, const ALsi
 
 static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
-    ALfloat *restrict leftbuf = state->SampleBuffer[0];
-    ALfloat *restrict rightbuf = state->SampleBuffer[1];
     const ALsizei bufmask = state->BufferLength-1;
     const ALfloat feedback = state->feedback;
+    const ALsizei avgdelay = (state->delay + (FRACTIONONE>>1)) >> FRACTIONBITS;
+    ALfloat *restrict delaybuf = state->SampleBuffer;
     ALsizei offset = state->offset;
     ALsizei i, c;
     ALsizei base;
 
     for(base = 0;base < SamplesToDo;)
     {
-        const ALsizei todo = mini(128, SamplesToDo-base);
-        ALfloat temps[128][2];
-        ALint moddelays[2][128];
+        const ALsizei todo = mini(256, SamplesToDo-base);
+        ALint moddelays[2][256];
+        alignas(16) ALfloat temps[2][256];
 
-        switch(state->waveform)
+        if(state->waveform == WF_Sinusoid)
         {
-            case CWF_Triangle:
-                GetTriangleDelays(moddelays[0], offset%state->lfo_range, state->lfo_range,
-                                  state->lfo_scale, state->depth, state->delay, todo);
-                GetTriangleDelays(moddelays[1], (offset+state->lfo_disp)%state->lfo_range,
-                                  state->lfo_range, state->lfo_scale, state->depth, state->delay,
-                                  todo);
-                break;
-            case CWF_Sinusoid:
-                GetSinusoidDelays(moddelays[0], offset%state->lfo_range, state->lfo_range,
-                                  state->lfo_scale, state->depth, state->delay, todo);
-                GetSinusoidDelays(moddelays[1], (offset+state->lfo_disp)%state->lfo_range,
-                                  state->lfo_range, state->lfo_scale, state->depth, state->delay,
-                                  todo);
-                break;
+            GetSinusoidDelays(moddelays[0], state->lfo_offset, state->lfo_range, state->lfo_scale,
+                              state->depth, state->delay, todo);
+            GetSinusoidDelays(moddelays[1], (state->lfo_offset+state->lfo_disp)%state->lfo_range,
+                              state->lfo_range, state->lfo_scale, state->depth, state->delay,
+                              todo);
         }
+        else /*if(state->waveform == WF_Triangle)*/
+        {
+            GetTriangleDelays(moddelays[0], state->lfo_offset, state->lfo_range, state->lfo_scale,
+                              state->depth, state->delay, todo);
+            GetTriangleDelays(moddelays[1], (state->lfo_offset+state->lfo_disp)%state->lfo_range,
+                              state->lfo_range, state->lfo_scale, state->depth, state->delay,
+                              todo);
+        }
+        state->lfo_offset = (state->lfo_offset+todo) % state->lfo_range;
 
         for(i = 0;i < todo;i++)
         {
-            leftbuf[offset&bufmask] = SamplesIn[0][base+i];
-            temps[i][0] = leftbuf[(offset-moddelays[0][i])&bufmask] * feedback;
-            leftbuf[offset&bufmask] += temps[i][0];
-
-            rightbuf[offset&bufmask] = SamplesIn[0][base+i];
-            temps[i][1] = rightbuf[(offset-moddelays[1][i])&bufmask] * feedback;
-            rightbuf[offset&bufmask] += temps[i][1];
-
+            ALint delay;
+            ALfloat mu;
+
+            // Feed the buffer's input first (necessary for delays < 1).
+            delaybuf[offset&bufmask] = SamplesIn[0][base+i];
+
+            // Tap for the left output.
+            delay = offset - (moddelays[0][i]>>FRACTIONBITS);
+            mu = (moddelays[0][i]&FRACTIONMASK) * (1.0f/FRACTIONONE);
+            temps[0][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay  ) & bufmask],
+                                delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask],
+                                mu);
+
+            // Tap for the right output.
+            delay = offset - (moddelays[1][i]>>FRACTIONBITS);
+            mu = (moddelays[1][i]&FRACTIONMASK) * (1.0f/FRACTIONONE);
+            temps[1][i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay  ) & bufmask],
+                                delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask],
+                                mu);
+
+            // Accumulate feedback from the average delay of the taps.
+            delaybuf[offset&bufmask] += delaybuf[(offset-avgdelay) & bufmask] * feedback;
             offset++;
         }
 
-        for(c = 0;c < NumChannels;c++)
-        {
-            ALfloat gain = state->Gain[0][c];
-            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
-            {
-                for(i = 0;i < todo;i++)
-                    SamplesOut[c][i+base] += temps[i][0] * gain;
-            }
-
-            gain = state->Gain[1][c];
-            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
-            {
-                for(i = 0;i < todo;i++)
-                    SamplesOut[c][i+base] += temps[i][1] * gain;
-            }
-        }
+        for(c = 0;c < 2;c++)
+            MixSamples(temps[c], NumChannels, SamplesOut, state->Gains[c].Current,
+                       state->Gains[c].Target, SamplesToDo-base, base, todo);
 
         base += todo;
     }
@@ -268,11 +285,11 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, c
 }
 
 
-typedef struct ALchorusStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALchorusStateFactory;
+typedef struct ChorusStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} ChorusStateFactory;
 
-static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(factory))
+static ALeffectState *ChorusStateFactory_create(ChorusStateFactory *UNUSED(factory))
 {
     ALchorusState *state;
 
@@ -282,14 +299,14 @@ static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(f
     return STATIC_CAST(ALeffectState, state);
 }
 
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALchorusStateFactory);
+DEFINE_EFFECTSTATEFACTORY_VTABLE(ChorusStateFactory);
 
 
-ALeffectStateFactory *ALchorusStateFactory_getFactory(void)
+EffectStateFactory *ChorusStateFactory_getFactory(void)
 {
-    static ALchorusStateFactory ChorusFactory = { { GET_VTABLE2(ALchorusStateFactory, ALeffectStateFactory) } };
+    static ChorusStateFactory ChorusFactory = { { GET_VTABLE2(ChorusStateFactory, EffectStateFactory) } };
 
-    return STATIC_CAST(ALeffectStateFactory, &ChorusFactory);
+    return STATIC_CAST(EffectStateFactory, &ChorusFactory);
 }
 
 
@@ -300,24 +317,22 @@ void ALchorus_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALi
     {
         case AL_CHORUS_WAVEFORM:
             if(!(val >= AL_CHORUS_MIN_WAVEFORM && val <= AL_CHORUS_MAX_WAVEFORM))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid chorus waveform");
             props->Chorus.Waveform = val;
             break;
 
         case AL_CHORUS_PHASE:
             if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus phase out of range");
             props->Chorus.Phase = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param);
     }
 }
 void ALchorus_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALchorus_setParami(effect, context, param, vals[0]);
-}
+{ ALchorus_setParami(effect, context, param, vals[0]); }
 void ALchorus_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
 {
     ALeffectProps *props = &effect->Props;
@@ -325,36 +340,34 @@ void ALchorus_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALf
     {
         case AL_CHORUS_RATE:
             if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus rate out of range");
             props->Chorus.Rate = val;
             break;
 
         case AL_CHORUS_DEPTH:
             if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus depth out of range");
             props->Chorus.Depth = val;
             break;
 
         case AL_CHORUS_FEEDBACK:
             if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus feedback out of range");
             props->Chorus.Feedback = val;
             break;
 
         case AL_CHORUS_DELAY:
             if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Chorus delay out of range");
             props->Chorus.Delay = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param);
     }
 }
 void ALchorus_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALchorus_setParamf(effect, context, param, vals[0]);
-}
+{ ALchorus_setParamf(effect, context, param, vals[0]); }
 
 void ALchorus_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
 {
@@ -370,13 +383,11 @@ void ALchorus_getParami(const ALeffect *effect, ALCcontext *context, ALenum para
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param);
     }
 }
 void ALchorus_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALchorus_getParami(effect, context, param, vals);
-}
+{ ALchorus_getParami(effect, context, param, vals); }
 void ALchorus_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
 {
     const ALeffectProps *props = &effect->Props;
@@ -399,12 +410,146 @@ void ALchorus_getParamf(const ALeffect *effect, ALCcontext *context, ALenum para
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param);
     }
 }
 void ALchorus_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
+{ ALchorus_getParamf(effect, context, param, vals); }
+
+DEFINE_ALEFFECT_VTABLE(ALchorus);
+
+
+/* Flanger is basically a chorus with a really short delay. They can both use
+ * the same processing functions, so piggyback flanger on the chorus functions.
+ */
+typedef struct FlangerStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} FlangerStateFactory;
+
+ALeffectState *FlangerStateFactory_create(FlangerStateFactory *UNUSED(factory))
+{
+    ALchorusState *state;
+
+    NEW_OBJ0(state, ALchorusState)();
+    if(!state) return NULL;
+
+    return STATIC_CAST(ALeffectState, state);
+}
+
+DEFINE_EFFECTSTATEFACTORY_VTABLE(FlangerStateFactory);
+
+EffectStateFactory *FlangerStateFactory_getFactory(void)
 {
-    ALchorus_getParamf(effect, context, param, vals);
+    static FlangerStateFactory FlangerFactory = { { GET_VTABLE2(FlangerStateFactory, EffectStateFactory) } };
+
+    return STATIC_CAST(EffectStateFactory, &FlangerFactory);
 }
 
-DEFINE_ALEFFECT_VTABLE(ALchorus);
+
+void ALflanger_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
+{
+    ALeffectProps *props = &effect->Props;
+    switch(param)
+    {
+        case AL_FLANGER_WAVEFORM:
+            if(!(val >= AL_FLANGER_MIN_WAVEFORM && val <= AL_FLANGER_MAX_WAVEFORM))
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid flanger waveform");
+            props->Chorus.Waveform = val;
+            break;
+
+        case AL_FLANGER_PHASE:
+            if(!(val >= AL_FLANGER_MIN_PHASE && val <= AL_FLANGER_MAX_PHASE))
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger phase out of range");
+            props->Chorus.Phase = val;
+            break;
+
+        default:
+            alSetError(context, AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param);
+    }
+}
+void ALflanger_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
+{ ALflanger_setParami(effect, context, param, vals[0]); }
+void ALflanger_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
+{
+    ALeffectProps *props = &effect->Props;
+    switch(param)
+    {
+        case AL_FLANGER_RATE:
+            if(!(val >= AL_FLANGER_MIN_RATE && val <= AL_FLANGER_MAX_RATE))
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger rate out of range");
+            props->Chorus.Rate = val;
+            break;
+
+        case AL_FLANGER_DEPTH:
+            if(!(val >= AL_FLANGER_MIN_DEPTH && val <= AL_FLANGER_MAX_DEPTH))
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger depth out of range");
+            props->Chorus.Depth = val;
+            break;
+
+        case AL_FLANGER_FEEDBACK:
+            if(!(val >= AL_FLANGER_MIN_FEEDBACK && val <= AL_FLANGER_MAX_FEEDBACK))
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger feedback out of range");
+            props->Chorus.Feedback = val;
+            break;
+
+        case AL_FLANGER_DELAY:
+            if(!(val >= AL_FLANGER_MIN_DELAY && val <= AL_FLANGER_MAX_DELAY))
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Flanger delay out of range");
+            props->Chorus.Delay = val;
+            break;
+
+        default:
+            alSetError(context, AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param);
+    }
+}
+void ALflanger_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
+{ ALflanger_setParamf(effect, context, param, vals[0]); }
+
+void ALflanger_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
+{
+    const ALeffectProps *props = &effect->Props;
+    switch(param)
+    {
+        case AL_FLANGER_WAVEFORM:
+            *val = props->Chorus.Waveform;
+            break;
+
+        case AL_FLANGER_PHASE:
+            *val = props->Chorus.Phase;
+            break;
+
+        default:
+            alSetError(context, AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param);
+    }
+}
+void ALflanger_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
+{ ALflanger_getParami(effect, context, param, vals); }
+void ALflanger_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
+{
+    const ALeffectProps *props = &effect->Props;
+    switch(param)
+    {
+        case AL_FLANGER_RATE:
+            *val = props->Chorus.Rate;
+            break;
+
+        case AL_FLANGER_DEPTH:
+            *val = props->Chorus.Depth;
+            break;
+
+        case AL_FLANGER_FEEDBACK:
+            *val = props->Chorus.Feedback;
+            break;
+
+        case AL_FLANGER_DELAY:
+            *val = props->Chorus.Delay;
+            break;
+
+        default:
+            alSetError(context, AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param);
+    }
+}
+void ALflanger_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
+{ ALflanger_getParamf(effect, context, param, vals); }
+
+DEFINE_ALEFFECT_VTABLE(ALflanger);

+ 29 - 33
libs/openal-soft/Alc/effects/compressor.c

@@ -42,7 +42,7 @@ typedef struct ALcompressorState {
 
 static ALvoid ALcompressorState_Destruct(ALcompressorState *state);
 static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdevice *device);
-static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props);
+static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
 static ALvoid ALcompressorState_process(ALcompressorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
 DECLARE_DEFAULT_ALLOCATORS(ALcompressorState)
 
@@ -76,8 +76,9 @@ static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdev
     return AL_TRUE;
 }
 
-static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props)
+static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
 {
+    const ALCdevice *device = context->Device;
     ALuint i;
 
     state->Enabled = props->Compressor.OnOff;
@@ -85,7 +86,7 @@ static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice
     STATIC_CAST(ALeffectState,state)->OutBuffer = device->FOAOut.Buffer;
     STATIC_CAST(ALeffectState,state)->OutChannels = device->FOAOut.NumChannels;
     for(i = 0;i < 4;i++)
-        ComputeFirstOrderGains(device->FOAOut, IdentityMatrixf.m[i],
+        ComputeFirstOrderGains(&device->FOAOut, IdentityMatrixf.m[i],
                                slot->Params.Gain, state->Gain[i]);
 }
 
@@ -178,11 +179,11 @@ static ALvoid ALcompressorState_process(ALcompressorState *state, ALsizei Sample
 }
 
 
-typedef struct ALcompressorStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALcompressorStateFactory;
+typedef struct CompressorStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} CompressorStateFactory;
 
-static ALeffectState *ALcompressorStateFactory_create(ALcompressorStateFactory *UNUSED(factory))
+static ALeffectState *CompressorStateFactory_create(CompressorStateFactory *UNUSED(factory))
 {
     ALcompressorState *state;
 
@@ -192,13 +193,13 @@ static ALeffectState *ALcompressorStateFactory_create(ALcompressorStateFactory *
     return STATIC_CAST(ALeffectState, state);
 }
 
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALcompressorStateFactory);
+DEFINE_EFFECTSTATEFACTORY_VTABLE(CompressorStateFactory);
 
-ALeffectStateFactory *ALcompressorStateFactory_getFactory(void)
+EffectStateFactory *CompressorStateFactory_getFactory(void)
 {
-    static ALcompressorStateFactory CompressorFactory = { { GET_VTABLE2(ALcompressorStateFactory, ALeffectStateFactory) } };
+    static CompressorStateFactory CompressorFactory = { { GET_VTABLE2(CompressorStateFactory, EffectStateFactory) } };
 
-    return STATIC_CAST(ALeffectStateFactory, &CompressorFactory);
+    return STATIC_CAST(EffectStateFactory, &CompressorFactory);
 }
 
 
@@ -209,24 +210,21 @@ void ALcompressor_setParami(ALeffect *effect, ALCcontext *context, ALenum param,
     {
         case AL_COMPRESSOR_ONOFF:
             if(!(val >= AL_COMPRESSOR_MIN_ONOFF && val <= AL_COMPRESSOR_MAX_ONOFF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Compressor state out of range");
             props->Compressor.OnOff = val;
             break;
 
-    default:
-        SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+        default:
+            alSetError(context, AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
+                       param);
     }
 }
 void ALcompressor_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALcompressor_setParami(effect, context, param, vals[0]);
-}
-void ALcompressor_setParamf(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALfloat UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALcompressor_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALcompressor_setParamf(effect, context, param, vals[0]);
-}
+{ ALcompressor_setParami(effect, context, param, vals[0]); }
+void ALcompressor_setParamf(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param); }
+void ALcompressor_setParamfv(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, const ALfloat *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x", param); }
 
 void ALcompressor_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
 { 
@@ -236,19 +234,17 @@ void ALcompressor_getParami(const ALeffect *effect, ALCcontext *context, ALenum
         case AL_COMPRESSOR_ONOFF:
             *val = props->Compressor.OnOff;
             break;
+
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x",
+                       param);
     }
 }
 void ALcompressor_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALcompressor_getParami(effect, context, param, vals);
-}
-void ALcompressor_getParamf(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALcompressor_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALcompressor_getParamf(effect, context, param, vals);
-}
+{ ALcompressor_getParami(effect, context, param, vals); }
+void ALcompressor_getParamf(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param); }
+void ALcompressor_getParamfv(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x", param); }
 
 DEFINE_ALEFFECT_VTABLE(ALcompressor);

+ 43 - 62
libs/openal-soft/Alc/effects/dedicated.c

@@ -23,21 +23,22 @@
 #include <stdlib.h>
 
 #include "alMain.h"
-#include "alFilter.h"
 #include "alAuxEffectSlot.h"
 #include "alError.h"
 #include "alu.h"
+#include "filters/defs.h"
 
 
 typedef struct ALdedicatedState {
     DERIVE_FROM_TYPE(ALeffectState);
 
-    ALfloat gains[MAX_OUTPUT_CHANNELS];
+    ALfloat CurrentGains[MAX_OUTPUT_CHANNELS];
+    ALfloat TargetGains[MAX_OUTPUT_CHANNELS];
 } ALdedicatedState;
 
 static ALvoid ALdedicatedState_Destruct(ALdedicatedState *state);
 static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *state, ALCdevice *device);
-static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCdevice *device, const ALeffectslot *Slot, const ALeffectProps *props);
+static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
 static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
 DECLARE_DEFAULT_ALLOCATORS(ALdedicatedState)
 
@@ -46,13 +47,8 @@ DEFINE_ALEFFECTSTATE_VTABLE(ALdedicatedState);
 
 static void ALdedicatedState_Construct(ALdedicatedState *state)
 {
-    ALsizei s;
-
     ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
     SET_VTABLE2(ALdedicatedState, ALeffectState, state);
-
-    for(s = 0;s < MAX_OUTPUT_CHANNELS;s++)
-        state->gains[s] = 0.0f;
 }
 
 static ALvoid ALdedicatedState_Destruct(ALdedicatedState *state)
@@ -60,40 +56,44 @@ static ALvoid ALdedicatedState_Destruct(ALdedicatedState *state)
     ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
-static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *UNUSED(state), ALCdevice *UNUSED(device))
+static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *state, ALCdevice *UNUSED(device))
 {
+    ALsizei i;
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+        state->CurrentGains[i] = 0.0f;
     return AL_TRUE;
 }
 
-static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCdevice *device, const ALeffectslot *Slot, const ALeffectProps *props)
+static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
 {
+    const ALCdevice *device = context->Device;
     ALfloat Gain;
-    ALuint i;
+    ALsizei i;
 
     for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
-        state->gains[i] = 0.0f;
+        state->TargetGains[i] = 0.0f;
 
-    Gain = Slot->Params.Gain * props->Dedicated.Gain;
-    if(Slot->Params.EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
+    Gain = slot->Params.Gain * props->Dedicated.Gain;
+    if(slot->Params.EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
     {
         int idx;
-        if((idx=GetChannelIdxByName(device->RealOut, LFE)) != -1)
+        if((idx=GetChannelIdxByName(&device->RealOut, LFE)) != -1)
         {
             STATIC_CAST(ALeffectState,state)->OutBuffer = device->RealOut.Buffer;
             STATIC_CAST(ALeffectState,state)->OutChannels = device->RealOut.NumChannels;
-            state->gains[idx] = Gain;
+            state->TargetGains[idx] = Gain;
         }
     }
-    else if(Slot->Params.EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
+    else if(slot->Params.EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
     {
         int idx;
         /* Dialog goes to the front-center speaker if it exists, otherwise it
          * plays from the front-center location. */
-        if((idx=GetChannelIdxByName(device->RealOut, FrontCenter)) != -1)
+        if((idx=GetChannelIdxByName(&device->RealOut, FrontCenter)) != -1)
         {
             STATIC_CAST(ALeffectState,state)->OutBuffer = device->RealOut.Buffer;
             STATIC_CAST(ALeffectState,state)->OutChannels = device->RealOut.NumChannels;
-            state->gains[idx] = Gain;
+            state->TargetGains[idx] = Gain;
         }
         else
         {
@@ -102,34 +102,23 @@ static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCdevice *
 
             STATIC_CAST(ALeffectState,state)->OutBuffer = device->Dry.Buffer;
             STATIC_CAST(ALeffectState,state)->OutChannels = device->Dry.NumChannels;
-            ComputePanningGains(device->Dry, coeffs, Gain, state->gains);
+            ComputeDryPanGains(&device->Dry, coeffs, Gain, state->TargetGains);
         }
     }
 }
 
 static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
-    ALsizei i, c;
-
-    SamplesIn = ASSUME_ALIGNED(SamplesIn, 16);
-    SamplesOut = ASSUME_ALIGNED(SamplesOut, 16);
-    for(c = 0;c < NumChannels;c++)
-    {
-        const ALfloat gain = state->gains[c];
-        if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
-            continue;
-
-        for(i = 0;i < SamplesToDo;i++)
-            SamplesOut[c][i] += SamplesIn[0][i] * gain;
-    }
+    MixSamples(SamplesIn[0], NumChannels, SamplesOut, state->CurrentGains,
+               state->TargetGains, SamplesToDo, 0, SamplesToDo);
 }
 
 
-typedef struct ALdedicatedStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALdedicatedStateFactory;
+typedef struct DedicatedStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} DedicatedStateFactory;
 
-ALeffectState *ALdedicatedStateFactory_create(ALdedicatedStateFactory *UNUSED(factory))
+ALeffectState *DedicatedStateFactory_create(DedicatedStateFactory *UNUSED(factory))
 {
     ALdedicatedState *state;
 
@@ -139,23 +128,21 @@ ALeffectState *ALdedicatedStateFactory_create(ALdedicatedStateFactory *UNUSED(fa
     return STATIC_CAST(ALeffectState, state);
 }
 
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALdedicatedStateFactory);
+DEFINE_EFFECTSTATEFACTORY_VTABLE(DedicatedStateFactory);
 
 
-ALeffectStateFactory *ALdedicatedStateFactory_getFactory(void)
+EffectStateFactory *DedicatedStateFactory_getFactory(void)
 {
-    static ALdedicatedStateFactory DedicatedFactory = { { GET_VTABLE2(ALdedicatedStateFactory, ALeffectStateFactory) } };
+    static DedicatedStateFactory DedicatedFactory = { { GET_VTABLE2(DedicatedStateFactory, EffectStateFactory) } };
 
-    return STATIC_CAST(ALeffectStateFactory, &DedicatedFactory);
+    return STATIC_CAST(EffectStateFactory, &DedicatedFactory);
 }
 
 
-void ALdedicated_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALdedicated_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALdedicated_setParami(effect, context, param, vals[0]);
-}
+void ALdedicated_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param); }
+void ALdedicated_setParamiv(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x", param); }
 void ALdedicated_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
 {
     ALeffectProps *props = &effect->Props;
@@ -163,25 +150,21 @@ void ALdedicated_setParamf(ALeffect *effect, ALCcontext *context, ALenum param,
     {
         case AL_DEDICATED_GAIN:
             if(!(val >= 0.0f && isfinite(val)))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Dedicated gain out of range");
             props->Dedicated.Gain = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid dedicated float property 0x%04x", param);
     }
 }
 void ALdedicated_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALdedicated_setParamf(effect, context, param, vals[0]);
-}
+{ ALdedicated_setParamf(effect, context, param, vals[0]); }
 
-void ALdedicated_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALdedicated_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALdedicated_getParami(effect, context, param, vals);
-}
+void ALdedicated_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param); }
+void ALdedicated_getParamiv(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x", param); }
 void ALdedicated_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
 {
     const ALeffectProps *props = &effect->Props;
@@ -192,12 +175,10 @@ void ALdedicated_getParamf(const ALeffect *effect, ALCcontext *context, ALenum p
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid dedicated float property 0x%04x", param);
     }
 }
 void ALdedicated_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALdedicated_getParamf(effect, context, param, vals);
-}
+{ ALdedicated_getParamf(effect, context, param, vals); }
 
 DEFINE_ALEFFECT_VTABLE(ALdedicated);

+ 64 - 73
libs/openal-soft/Alc/effects/distortion.c

@@ -24,10 +24,10 @@
 #include <stdlib.h>
 
 #include "alMain.h"
-#include "alFilter.h"
 #include "alAuxEffectSlot.h"
 #include "alError.h"
 #include "alu.h"
+#include "filters/defs.h"
 
 
 typedef struct ALdistortionState {
@@ -37,15 +37,17 @@ typedef struct ALdistortionState {
     ALfloat Gain[MAX_OUTPUT_CHANNELS];
 
     /* Effect parameters */
-    ALfilterState lowpass;
-    ALfilterState bandpass;
+    BiquadState lowpass;
+    BiquadState bandpass;
     ALfloat attenuation;
     ALfloat edge_coeff;
+
+    ALfloat Buffer[2][BUFFERSIZE];
 } ALdistortionState;
 
 static ALvoid ALdistortionState_Destruct(ALdistortionState *state);
 static ALboolean ALdistortionState_deviceUpdate(ALdistortionState *state, ALCdevice *device);
-static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props);
+static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
 static ALvoid ALdistortionState_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
 DECLARE_DEFAULT_ALLOCATORS(ALdistortionState)
 
@@ -57,8 +59,8 @@ static void ALdistortionState_Construct(ALdistortionState *state)
     ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
     SET_VTABLE2(ALdistortionState, ALeffectState, state);
 
-    ALfilterState_clear(&state->lowpass);
-    ALfilterState_clear(&state->bandpass);
+    BiquadState_clear(&state->lowpass);
+    BiquadState_clear(&state->bandpass);
 }
 
 static ALvoid ALdistortionState_Destruct(ALdistortionState *state)
@@ -71,16 +73,15 @@ static ALboolean ALdistortionState_deviceUpdate(ALdistortionState *UNUSED(state)
     return AL_TRUE;
 }
 
-static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props)
+static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
 {
-    ALfloat frequency = (ALfloat)Device->Frequency;
+    const ALCdevice *device = context->Device;
+    ALfloat frequency = (ALfloat)device->Frequency;
+    ALfloat coeffs[MAX_AMBI_COEFFS];
     ALfloat bandwidth;
     ALfloat cutoff;
     ALfloat edge;
 
-    /* Store distorted signal attenuation settings. */
-    state->attenuation = props->Distortion.Gain;
-
     /* Store waveshaper edge settings. */
     edge = sinf(props->Distortion.Edge * (F_PI_2));
     edge = minf(edge, 0.99f);
@@ -92,98 +93,94 @@ static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCdevice
     /* Multiply sampling frequency by the amount of oversampling done during
      * processing.
      */
-    ALfilterState_setParams(&state->lowpass, ALfilterType_LowPass, 1.0f,
+    BiquadState_setParams(&state->lowpass, BiquadType_LowPass, 1.0f,
         cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
     );
 
     cutoff = props->Distortion.EQCenter;
     /* Convert bandwidth in Hz to octaves. */
     bandwidth = props->Distortion.EQBandwidth / (cutoff * 0.67f);
-    ALfilterState_setParams(&state->bandpass, ALfilterType_BandPass, 1.0f,
+    BiquadState_setParams(&state->bandpass, BiquadType_BandPass, 1.0f,
         cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
     );
 
-    ComputeAmbientGains(Device->Dry, Slot->Params.Gain, state->Gain);
+    CalcAngleCoeffs(0.0f, 0.0f, 0.0f, coeffs);
+    ComputeDryPanGains(&device->Dry, coeffs, slot->Params.Gain * props->Distortion.Gain,
+                       state->Gain);
 }
 
 static ALvoid ALdistortionState_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
+    ALfloat (*restrict buffer)[BUFFERSIZE] = state->Buffer;
     const ALfloat fc = state->edge_coeff;
-    ALsizei it, kt;
     ALsizei base;
+    ALsizei i, k;
 
     for(base = 0;base < SamplesToDo;)
     {
-        float buffer[2][64 * 4];
-        ALsizei td = mini(64, SamplesToDo-base);
-
         /* Perform 4x oversampling to avoid aliasing. Oversampling greatly
          * improves distortion quality and allows to implement lowpass and
          * bandpass filters using high frequencies, at which classic IIR
          * filters became unstable.
          */
+        ALsizei todo = mini(BUFFERSIZE, (SamplesToDo-base) * 4);
 
-        /* Fill oversample buffer using zero stuffing. */
-        for(it = 0;it < td;it++)
-        {
-            /* Multiply the sample by the amount of oversampling to maintain
-             * the signal's power.
-             */
-            buffer[0][it*4 + 0] = SamplesIn[0][it+base] * 4.0f;
-            buffer[0][it*4 + 1] = 0.0f;
-            buffer[0][it*4 + 2] = 0.0f;
-            buffer[0][it*4 + 3] = 0.0f;
-        }
+        /* Fill oversample buffer using zero stuffing. Multiply the sample by
+         * the amount of oversampling to maintain the signal's power.
+         */
+        for(i = 0;i < todo;i++)
+            buffer[0][i] = !(i&3) ? SamplesIn[0][(i>>2)+base] * 4.0f : 0.0f;
 
         /* First step, do lowpass filtering of original signal. Additionally
          * perform buffer interpolation and lowpass cutoff for oversampling
          * (which is fortunately first step of distortion). So combine three
          * operations into the one.
          */
-        ALfilterState_process(&state->lowpass, buffer[1], buffer[0], td*4);
+        BiquadState_process(&state->lowpass, buffer[1], buffer[0], todo);
 
         /* Second step, do distortion using waveshaper function to emulate
          * signal processing during tube overdriving. Three steps of
          * waveshaping are intended to modify waveform without boost/clipping/
          * attenuation process.
          */
-        for(it = 0;it < td*4;it++)
+        for(i = 0;i < todo;i++)
         {
-            ALfloat smp = buffer[1][it];
+            ALfloat smp = buffer[1][i];
 
             smp = (1.0f + fc) * smp/(1.0f + fc*fabsf(smp));
             smp = (1.0f + fc) * smp/(1.0f + fc*fabsf(smp)) * -1.0f;
             smp = (1.0f + fc) * smp/(1.0f + fc*fabsf(smp));
 
-            buffer[0][it] = smp;
+            buffer[0][i] = smp;
         }
 
         /* Third step, do bandpass filtering of distorted signal. */
-        ALfilterState_process(&state->bandpass, buffer[1], buffer[0], td*4);
+        BiquadState_process(&state->bandpass, buffer[1], buffer[0], todo);
 
-        for(kt = 0;kt < NumChannels;kt++)
+        todo >>= 2;
+        for(k = 0;k < NumChannels;k++)
         {
             /* Fourth step, final, do attenuation and perform decimation,
-             * store only one sample out of 4.
+             * storing only one sample out of four.
              */
-            ALfloat gain = state->Gain[kt] * state->attenuation;
+            ALfloat gain = state->Gain[k];
             if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
                 continue;
 
-            for(it = 0;it < td;it++)
-                SamplesOut[kt][base+it] += gain * buffer[1][it*4];
+            for(i = 0;i < todo;i++)
+                SamplesOut[k][base+i] += gain * buffer[1][i*4];
         }
 
-        base += td;
+        base += todo;
     }
 }
 
 
-typedef struct ALdistortionStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALdistortionStateFactory;
+typedef struct DistortionStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} DistortionStateFactory;
 
-static ALeffectState *ALdistortionStateFactory_create(ALdistortionStateFactory *UNUSED(factory))
+static ALeffectState *DistortionStateFactory_create(DistortionStateFactory *UNUSED(factory))
 {
     ALdistortionState *state;
 
@@ -193,23 +190,21 @@ static ALeffectState *ALdistortionStateFactory_create(ALdistortionStateFactory *
     return STATIC_CAST(ALeffectState, state);
 }
 
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALdistortionStateFactory);
+DEFINE_EFFECTSTATEFACTORY_VTABLE(DistortionStateFactory);
 
 
-ALeffectStateFactory *ALdistortionStateFactory_getFactory(void)
+EffectStateFactory *DistortionStateFactory_getFactory(void)
 {
-    static ALdistortionStateFactory DistortionFactory = { { GET_VTABLE2(ALdistortionStateFactory, ALeffectStateFactory) } };
+    static DistortionStateFactory DistortionFactory = { { GET_VTABLE2(DistortionStateFactory, EffectStateFactory) } };
 
-    return STATIC_CAST(ALeffectStateFactory, &DistortionFactory);
+    return STATIC_CAST(EffectStateFactory, &DistortionFactory);
 }
 
 
-void ALdistortion_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALdistortion_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALdistortion_setParami(effect, context, param, vals[0]);
-}
+void ALdistortion_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param); }
+void ALdistortion_setParamiv(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x", param); }
 void ALdistortion_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
 {
     ALeffectProps *props = &effect->Props;
@@ -217,49 +212,46 @@ void ALdistortion_setParamf(ALeffect *effect, ALCcontext *context, ALenum param,
     {
         case AL_DISTORTION_EDGE:
             if(!(val >= AL_DISTORTION_MIN_EDGE && val <= AL_DISTORTION_MAX_EDGE))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Distortion edge out of range");
             props->Distortion.Edge = val;
             break;
 
         case AL_DISTORTION_GAIN:
             if(!(val >= AL_DISTORTION_MIN_GAIN && val <= AL_DISTORTION_MAX_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Distortion gain out of range");
             props->Distortion.Gain = val;
             break;
 
         case AL_DISTORTION_LOWPASS_CUTOFF:
             if(!(val >= AL_DISTORTION_MIN_LOWPASS_CUTOFF && val <= AL_DISTORTION_MAX_LOWPASS_CUTOFF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Distortion low-pass cutoff out of range");
             props->Distortion.LowpassCutoff = val;
             break;
 
         case AL_DISTORTION_EQCENTER:
             if(!(val >= AL_DISTORTION_MIN_EQCENTER && val <= AL_DISTORTION_MAX_EQCENTER))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Distortion EQ center out of range");
             props->Distortion.EQCenter = val;
             break;
 
         case AL_DISTORTION_EQBANDWIDTH:
             if(!(val >= AL_DISTORTION_MIN_EQBANDWIDTH && val <= AL_DISTORTION_MAX_EQBANDWIDTH))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Distortion EQ bandwidth out of range");
             props->Distortion.EQBandwidth = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid distortion float property 0x%04x",
+                       param);
     }
 }
 void ALdistortion_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALdistortion_setParamf(effect, context, param, vals[0]);
-}
+{ ALdistortion_setParamf(effect, context, param, vals[0]); }
 
-void ALdistortion_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALdistortion_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALdistortion_getParami(effect, context, param, vals);
-}
+void ALdistortion_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param); }
+void ALdistortion_getParamiv(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x", param); }
 void ALdistortion_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
 {
     const ALeffectProps *props = &effect->Props;
@@ -286,12 +278,11 @@ void ALdistortion_getParamf(const ALeffect *effect, ALCcontext *context, ALenum
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid distortion float property 0x%04x",
+                       param);
     }
 }
 void ALdistortion_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALdistortion_getParamf(effect, context, param, vals);
-}
+{ ALdistortion_getParamf(effect, context, param, vals); }
 
 DEFINE_ALEFFECT_VTABLE(ALdistortion);

+ 71 - 81
libs/openal-soft/Alc/effects/echo.c

@@ -28,6 +28,7 @@
 #include "alAuxEffectSlot.h"
 #include "alError.h"
 #include "alu.h"
+#include "filters/defs.h"
 
 
 typedef struct ALechoState {
@@ -42,17 +43,21 @@ typedef struct ALechoState {
         ALsizei delay;
     } Tap[2];
     ALsizei Offset;
+
     /* The panning gains for the two taps */
-    ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
+    struct {
+        ALfloat Current[MAX_OUTPUT_CHANNELS];
+        ALfloat Target[MAX_OUTPUT_CHANNELS];
+    } Gains[2];
 
     ALfloat FeedGain;
 
-    ALfilterState Filter;
+    BiquadState Filter;
 } ALechoState;
 
 static ALvoid ALechoState_Destruct(ALechoState *state);
 static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device);
-static ALvoid ALechoState_update(ALechoState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props);
+static ALvoid ALechoState_update(ALechoState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
 static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
 DECLARE_DEFAULT_ALLOCATORS(ALechoState)
 
@@ -71,7 +76,7 @@ static void ALechoState_Construct(ALechoState *state)
     state->Tap[1].delay = 0;
     state->Offset = 0;
 
-    ALfilterState_clear(&state->Filter);
+    BiquadState_clear(&state->Filter);
 }
 
 static ALvoid ALechoState_Destruct(ALechoState *state)
@@ -83,13 +88,14 @@ static ALvoid ALechoState_Destruct(ALechoState *state)
 
 static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device)
 {
-    ALsizei maxlen, i;
+    ALsizei maxlen;
 
     // Use the next power of 2 for the buffer length, so the tap offsets can be
     // wrapped using a mask instead of a modulo
-    maxlen  = fastf2i(AL_ECHO_MAX_DELAY * Device->Frequency) + 1;
-    maxlen += fastf2i(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1;
-    maxlen  = NextPowerOf2(maxlen);
+    maxlen = fastf2i(AL_ECHO_MAX_DELAY*Device->Frequency + 0.5f) +
+             fastf2i(AL_ECHO_MAX_LRDELAY*Device->Frequency + 0.5f);
+    maxlen = NextPowerOf2(maxlen);
+    if(maxlen <= 0) return AL_FALSE;
 
     if(maxlen != state->BufferLength)
     {
@@ -100,20 +106,22 @@ static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device)
         state->SampleBuffer = temp;
         state->BufferLength = maxlen;
     }
-    for(i = 0;i < state->BufferLength;i++)
-        state->SampleBuffer[i] = 0.0f;
+
+    memset(state->SampleBuffer, 0, state->BufferLength*sizeof(ALfloat));
+    memset(state->Gains, 0, sizeof(state->Gains));
 
     return AL_TRUE;
 }
 
-static ALvoid ALechoState_update(ALechoState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props)
+static ALvoid ALechoState_update(ALechoState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
 {
-    ALuint frequency = Device->Frequency;
+    const ALCdevice *device = context->Device;
+    ALuint frequency = device->Frequency;
     ALfloat coeffs[MAX_AMBI_COEFFS];
-    ALfloat gain, lrpan, spread;
+    ALfloat gainhf, lrpan, spread;
 
-    state->Tap[0].delay = fastf2i(props->Echo.Delay * frequency) + 1;
-    state->Tap[1].delay = fastf2i(props->Echo.LRDelay * frequency);
+    state->Tap[0].delay = maxi(fastf2i(props->Echo.Delay*frequency + 0.5f), 1);
+    state->Tap[1].delay = fastf2i(props->Echo.LRDelay*frequency + 0.5f);
     state->Tap[1].delay += state->Tap[0].delay;
 
     spread = props->Echo.Spread;
@@ -126,20 +134,18 @@ static ALvoid ALechoState_update(ALechoState *state, const ALCdevice *Device, co
 
     state->FeedGain = props->Echo.Feedback;
 
-    gain = maxf(1.0f - props->Echo.Damping, 0.0625f); /* Limit -24dB */
-    ALfilterState_setParams(&state->Filter, ALfilterType_HighShelf,
-                            gain, LOWPASSFREQREF/frequency,
-                            calc_rcpQ_from_slope(gain, 1.0f));
-
-    gain = Slot->Params.Gain;
+    gainhf = maxf(1.0f - props->Echo.Damping, 0.0625f); /* Limit -24dB */
+    BiquadState_setParams(&state->Filter, BiquadType_HighShelf,
+                          gainhf, LOWPASSFREQREF/frequency,
+                          calc_rcpQ_from_slope(gainhf, 1.0f));
 
     /* First tap panning */
     CalcAngleCoeffs(-F_PI_2*lrpan, 0.0f, spread, coeffs);
-    ComputePanningGains(Device->Dry, coeffs, gain, state->Gain[0]);
+    ComputeDryPanGains(&device->Dry, coeffs, slot->Params.Gain, state->Gains[0].Target);
 
     /* Second tap panning */
     CalcAngleCoeffs( F_PI_2*lrpan, 0.0f, spread, coeffs);
-    ComputePanningGains(Device->Dry, coeffs, gain, state->Gain[1]);
+    ComputeDryPanGains(&device->Dry, coeffs, slot->Params.Gain, state->Gains[1].Target);
 }
 
 static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
@@ -147,10 +153,11 @@ static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const
     const ALsizei mask = state->BufferLength-1;
     const ALsizei tap1 = state->Tap[0].delay;
     const ALsizei tap2 = state->Tap[1].delay;
+    ALfloat *restrict delaybuf = state->SampleBuffer;
     ALsizei offset = state->Offset;
     ALfloat x[2], y[2], in, out;
-    ALsizei base, k;
-    ALsizei i;
+    ALsizei base;
+    ALsizei c, i;
 
     x[0] = state->Filter.x[0];
     x[1] = state->Filter.x[1];
@@ -158,45 +165,36 @@ static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const
     y[1] = state->Filter.y[1];
     for(base = 0;base < SamplesToDo;)
     {
-        ALfloat temps[128][2];
+        alignas(16) ALfloat temps[2][128];
         ALsizei td = mini(128, SamplesToDo-base);
 
         for(i = 0;i < td;i++)
         {
+            /* Feed the delay buffer's input first. */
+            delaybuf[offset&mask] = SamplesIn[0][i+base];
+
             /* First tap */
-            temps[i][0] = state->SampleBuffer[(offset-tap1) & mask];
+            temps[0][i] = delaybuf[(offset-tap1) & mask];
             /* Second tap */
-            temps[i][1] = state->SampleBuffer[(offset-tap2) & mask];
+            temps[1][i] = delaybuf[(offset-tap2) & mask];
 
-            // Apply damping and feedback gain to the second tap, and mix in the
-            // new sample
-            in = temps[i][1] + SamplesIn[0][i+base];
+            /* Apply damping to the second tap, then add it to the buffer with
+             * feedback attenuation.
+             */
+            in = temps[1][i];
             out = in*state->Filter.b0 +
                   x[0]*state->Filter.b1 + x[1]*state->Filter.b2 -
                   y[0]*state->Filter.a1 - y[1]*state->Filter.a2;
             x[1] = x[0]; x[0] = in;
             y[1] = y[0]; y[0] = out;
 
-            state->SampleBuffer[offset&mask] = out * state->FeedGain;
+            delaybuf[offset&mask] += out * state->FeedGain;
             offset++;
         }
 
-        for(k = 0;k < NumChannels;k++)
-        {
-            ALfloat gain = state->Gain[0][k];
-            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
-            {
-                for(i = 0;i < td;i++)
-                    SamplesOut[k][i+base] += temps[i][0] * gain;
-            }
-
-            gain = state->Gain[1][k];
-            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
-            {
-                for(i = 0;i < td;i++)
-                    SamplesOut[k][i+base] += temps[i][1] * gain;
-            }
-        }
+        for(c = 0;c < 2;c++)
+            MixSamples(temps[c], NumChannels, SamplesOut, state->Gains[c].Current,
+                       state->Gains[c].Target, SamplesToDo-base, base, td);
 
         base += td;
     }
@@ -209,11 +207,11 @@ static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const
 }
 
 
-typedef struct ALechoStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALechoStateFactory;
+typedef struct EchoStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} EchoStateFactory;
 
-ALeffectState *ALechoStateFactory_create(ALechoStateFactory *UNUSED(factory))
+ALeffectState *EchoStateFactory_create(EchoStateFactory *UNUSED(factory))
 {
     ALechoState *state;
 
@@ -223,22 +221,20 @@ ALeffectState *ALechoStateFactory_create(ALechoStateFactory *UNUSED(factory))
     return STATIC_CAST(ALeffectState, state);
 }
 
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALechoStateFactory);
+DEFINE_EFFECTSTATEFACTORY_VTABLE(EchoStateFactory);
 
-ALeffectStateFactory *ALechoStateFactory_getFactory(void)
+EffectStateFactory *EchoStateFactory_getFactory(void)
 {
-    static ALechoStateFactory EchoFactory = { { GET_VTABLE2(ALechoStateFactory, ALeffectStateFactory) } };
+    static EchoStateFactory EchoFactory = { { GET_VTABLE2(EchoStateFactory, EffectStateFactory) } };
 
-    return STATIC_CAST(ALeffectStateFactory, &EchoFactory);
+    return STATIC_CAST(EffectStateFactory, &EchoFactory);
 }
 
 
-void ALecho_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALecho_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALecho_setParami(effect, context, param, vals[0]);
-}
+void ALecho_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param); }
+void ALecho_setParamiv(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param); }
 void ALecho_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
 {
     ALeffectProps *props = &effect->Props;
@@ -246,49 +242,45 @@ void ALecho_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALflo
     {
         case AL_ECHO_DELAY:
             if(!(val >= AL_ECHO_MIN_DELAY && val <= AL_ECHO_MAX_DELAY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Echo delay out of range");
             props->Echo.Delay = val;
             break;
 
         case AL_ECHO_LRDELAY:
             if(!(val >= AL_ECHO_MIN_LRDELAY && val <= AL_ECHO_MAX_LRDELAY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Echo LR delay out of range");
             props->Echo.LRDelay = val;
             break;
 
         case AL_ECHO_DAMPING:
             if(!(val >= AL_ECHO_MIN_DAMPING && val <= AL_ECHO_MAX_DAMPING))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Echo damping out of range");
             props->Echo.Damping = val;
             break;
 
         case AL_ECHO_FEEDBACK:
             if(!(val >= AL_ECHO_MIN_FEEDBACK && val <= AL_ECHO_MAX_FEEDBACK))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Echo feedback out of range");
             props->Echo.Feedback = val;
             break;
 
         case AL_ECHO_SPREAD:
             if(!(val >= AL_ECHO_MIN_SPREAD && val <= AL_ECHO_MAX_SPREAD))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Echo spread out of range");
             props->Echo.Spread = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid echo float property 0x%04x", param);
     }
 }
 void ALecho_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALecho_setParamf(effect, context, param, vals[0]);
-}
+{ ALecho_setParamf(effect, context, param, vals[0]); }
 
-void ALecho_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALecho_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALecho_getParami(effect, context, param, vals);
-}
+void ALecho_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param); }
+void ALecho_getParamiv(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param); }
 void ALecho_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
 {
     const ALeffectProps *props = &effect->Props;
@@ -315,12 +307,10 @@ void ALecho_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param,
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid echo float property 0x%04x", param);
     }
 }
 void ALecho_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALecho_getParamf(effect, context, param, vals);
-}
+{ ALecho_getParamf(effect, context, param, vals); }
 
 DEFINE_ALEFFECT_VTABLE(ALecho);

+ 89 - 114
libs/openal-soft/Alc/effects/equalizer.c

@@ -24,10 +24,10 @@
 #include <stdlib.h>
 
 #include "alMain.h"
-#include "alFilter.h"
 #include "alAuxEffectSlot.h"
 #include "alError.h"
 #include "alu.h"
+#include "filters/defs.h"
 
 
 /*  The document  "Effects Extension Guide.pdf"  says that low and high  *
@@ -72,24 +72,24 @@
  * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt                   */
 
 
-/* The maximum number of sample frames per update. */
-#define MAX_UPDATE_SAMPLES 256
-
 typedef struct ALequalizerState {
     DERIVE_FROM_TYPE(ALeffectState);
 
-    /* Effect gains for each channel */
-    ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS];
+    struct {
+        /* Effect gains for each channel */
+        ALfloat CurrentGains[MAX_OUTPUT_CHANNELS];
+        ALfloat TargetGains[MAX_OUTPUT_CHANNELS];
 
-    /* Effect parameters */
-    ALfilterState filter[4][MAX_EFFECT_CHANNELS];
+        /* Effect parameters */
+        BiquadState filter[4];
+    } Chans[MAX_EFFECT_CHANNELS];
 
-    ALfloat SampleBuffer[4][MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES];
+    ALfloat SampleBuffer[MAX_EFFECT_CHANNELS][BUFFERSIZE];
 } ALequalizerState;
 
 static ALvoid ALequalizerState_Destruct(ALequalizerState *state);
 static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *state, ALCdevice *device);
-static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props);
+static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
 static ALvoid ALequalizerState_process(ALequalizerState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
 DECLARE_DEFAULT_ALLOCATORS(ALequalizerState)
 
@@ -98,18 +98,8 @@ DEFINE_ALEFFECTSTATE_VTABLE(ALequalizerState);
 
 static void ALequalizerState_Construct(ALequalizerState *state)
 {
-    int it, ft;
-
     ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
     SET_VTABLE2(ALequalizerState, ALeffectState, state);
-
-    /* Initialize sample history only on filter creation to avoid */
-    /* sound clicks if filter settings were changed in runtime.   */
-    for(it = 0; it < 4; it++)
-    {
-        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
-            ALfilterState_clear(&state->filter[it][ft]);
-    }
 }
 
 static ALvoid ALequalizerState_Destruct(ALequalizerState *state)
@@ -117,107 +107,100 @@ static ALvoid ALequalizerState_Destruct(ALequalizerState *state)
     ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
-static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *UNUSED(state), ALCdevice *UNUSED(device))
+static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *state, ALCdevice *UNUSED(device))
 {
+    ALsizei i, j;
+
+    for(i = 0; i < MAX_EFFECT_CHANNELS;i++)
+    {
+        for(j = 0;j < 4;j++)
+            BiquadState_clear(&state->Chans[i].filter[j]);
+        for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
+            state->Chans[i].CurrentGains[j] = 0.0f;
+    }
     return AL_TRUE;
 }
 
-static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props)
+static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
 {
+    const ALCdevice *device = context->Device;
     ALfloat frequency = (ALfloat)device->Frequency;
-    ALfloat gain, freq_mult;
+    ALfloat gain, f0norm;
     ALuint i;
 
     STATIC_CAST(ALeffectState,state)->OutBuffer = device->FOAOut.Buffer;
     STATIC_CAST(ALeffectState,state)->OutChannels = device->FOAOut.NumChannels;
     for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
-        ComputeFirstOrderGains(device->FOAOut, IdentityMatrixf.m[i],
-                               slot->Params.Gain, state->Gain[i]);
+        ComputeFirstOrderGains(&device->FOAOut, IdentityMatrixf.m[i],
+                               slot->Params.Gain, state->Chans[i].TargetGains);
 
     /* 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 = maxf(sqrtf(props->Equalizer.LowGain), 0.0625f); /* Limit -24dB */
-    freq_mult = props->Equalizer.LowCutoff/frequency;
-    ALfilterState_setParams(&state->filter[0][0], ALfilterType_LowShelf,
-        gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
+    f0norm = props->Equalizer.LowCutoff/frequency;
+    BiquadState_setParams(&state->Chans[0].filter[0], BiquadType_LowShelf,
+        gain, f0norm, calc_rcpQ_from_slope(gain, 0.75f)
     );
-    /* Copy the filter coefficients for the other input channels. */
-    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
-        ALfilterState_copyParams(&state->filter[0][i], &state->filter[0][0]);
 
     gain = maxf(props->Equalizer.Mid1Gain, 0.0625f);
-    freq_mult = props->Equalizer.Mid1Center/frequency;
-    ALfilterState_setParams(&state->filter[1][0], ALfilterType_Peaking,
-        gain, freq_mult, calc_rcpQ_from_bandwidth(
-            freq_mult, props->Equalizer.Mid1Width
+    f0norm = props->Equalizer.Mid1Center/frequency;
+    BiquadState_setParams(&state->Chans[0].filter[1], BiquadType_Peaking,
+        gain, f0norm, calc_rcpQ_from_bandwidth(
+            f0norm, props->Equalizer.Mid1Width
         )
     );
-    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
-        ALfilterState_copyParams(&state->filter[1][i], &state->filter[1][0]);
 
     gain = maxf(props->Equalizer.Mid2Gain, 0.0625f);
-    freq_mult = props->Equalizer.Mid2Center/frequency;
-    ALfilterState_setParams(&state->filter[2][0], ALfilterType_Peaking,
-        gain, freq_mult, calc_rcpQ_from_bandwidth(
-            freq_mult, props->Equalizer.Mid2Width
+    f0norm = props->Equalizer.Mid2Center/frequency;
+    BiquadState_setParams(&state->Chans[0].filter[2], BiquadType_Peaking,
+        gain, f0norm, calc_rcpQ_from_bandwidth(
+            f0norm, props->Equalizer.Mid2Width
         )
     );
-    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
-        ALfilterState_copyParams(&state->filter[2][i], &state->filter[2][0]);
 
     gain = maxf(sqrtf(props->Equalizer.HighGain), 0.0625f);
-    freq_mult = props->Equalizer.HighCutoff/frequency;
-    ALfilterState_setParams(&state->filter[3][0], ALfilterType_HighShelf,
-        gain, freq_mult, calc_rcpQ_from_slope(gain, 0.75f)
+    f0norm = props->Equalizer.HighCutoff/frequency;
+    BiquadState_setParams(&state->Chans[0].filter[3], BiquadType_HighShelf,
+        gain, f0norm, calc_rcpQ_from_slope(gain, 0.75f)
     );
+
+    /* Copy the filter coefficients for the other input channels. */
     for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
-        ALfilterState_copyParams(&state->filter[3][i], &state->filter[3][0]);
+    {
+        BiquadState_copyParams(&state->Chans[i].filter[0], &state->Chans[0].filter[0]);
+        BiquadState_copyParams(&state->Chans[i].filter[1], &state->Chans[0].filter[1]);
+        BiquadState_copyParams(&state->Chans[i].filter[2], &state->Chans[0].filter[2]);
+        BiquadState_copyParams(&state->Chans[i].filter[3], &state->Chans[0].filter[3]);
+    }
 }
 
 static ALvoid ALequalizerState_process(ALequalizerState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
-    ALfloat (*Samples)[MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES] = state->SampleBuffer;
-    ALsizei it, kt, ft;
-    ALsizei base;
+    ALfloat (*restrict temps)[BUFFERSIZE] = state->SampleBuffer;
+    ALsizei c;
 
-    for(base = 0;base < SamplesToDo;)
+    for(c = 0;c < MAX_EFFECT_CHANNELS;c++)
     {
-        ALsizei td = mini(MAX_UPDATE_SAMPLES, SamplesToDo-base);
-
-        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
-            ALfilterState_process(&state->filter[0][ft], Samples[0][ft], &SamplesIn[ft][base], td);
-        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
-            ALfilterState_process(&state->filter[1][ft], Samples[1][ft], Samples[0][ft], td);
-        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
-            ALfilterState_process(&state->filter[2][ft], Samples[2][ft], Samples[1][ft], td);
-        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
-            ALfilterState_process(&state->filter[3][ft], Samples[3][ft], Samples[2][ft], td);
-
-        for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++)
-        {
-            for(kt = 0;kt < NumChannels;kt++)
-            {
-                ALfloat gain = state->Gain[ft][kt];
-                if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
-                    continue;
-
-                for(it = 0;it < td;it++)
-                    SamplesOut[kt][base+it] += gain * Samples[3][ft][it];
-            }
-        }
-
-        base += td;
+        BiquadState_process(&state->Chans[c].filter[0], temps[0], SamplesIn[c], SamplesToDo);
+        BiquadState_process(&state->Chans[c].filter[1], temps[1], temps[0], SamplesToDo);
+        BiquadState_process(&state->Chans[c].filter[2], temps[2], temps[1], SamplesToDo);
+        BiquadState_process(&state->Chans[c].filter[3], temps[3], temps[2], SamplesToDo);
+
+        MixSamples(temps[3], NumChannels, SamplesOut,
+            state->Chans[c].CurrentGains, state->Chans[c].TargetGains,
+            SamplesToDo, 0, SamplesToDo
+        );
     }
 }
 
 
-typedef struct ALequalizerStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALequalizerStateFactory;
+typedef struct EqualizerStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} EqualizerStateFactory;
 
-ALeffectState *ALequalizerStateFactory_create(ALequalizerStateFactory *UNUSED(factory))
+ALeffectState *EqualizerStateFactory_create(EqualizerStateFactory *UNUSED(factory))
 {
     ALequalizerState *state;
 
@@ -227,22 +210,20 @@ ALeffectState *ALequalizerStateFactory_create(ALequalizerStateFactory *UNUSED(fa
     return STATIC_CAST(ALeffectState, state);
 }
 
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALequalizerStateFactory);
+DEFINE_EFFECTSTATEFACTORY_VTABLE(EqualizerStateFactory);
 
-ALeffectStateFactory *ALequalizerStateFactory_getFactory(void)
+EffectStateFactory *EqualizerStateFactory_getFactory(void)
 {
-    static ALequalizerStateFactory EqualizerFactory = { { GET_VTABLE2(ALequalizerStateFactory, ALeffectStateFactory) } };
+    static EqualizerStateFactory EqualizerFactory = { { GET_VTABLE2(EqualizerStateFactory, EffectStateFactory) } };
 
-    return STATIC_CAST(ALeffectStateFactory, &EqualizerFactory);
+    return STATIC_CAST(EffectStateFactory, &EqualizerFactory);
 }
 
 
-void ALequalizer_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALequalizer_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALequalizer_setParami(effect, context, param, vals[0]);
-}
+void ALequalizer_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param); }
+void ALequalizer_setParamiv(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x", param); }
 void ALequalizer_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
 {
     ALeffectProps *props = &effect->Props;
@@ -250,79 +231,75 @@ void ALequalizer_setParamf(ALeffect *effect, ALCcontext *context, ALenum param,
     {
         case AL_EQUALIZER_LOW_GAIN:
             if(!(val >= AL_EQUALIZER_MIN_LOW_GAIN && val <= AL_EQUALIZER_MAX_LOW_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer low-band gain out of range");
             props->Equalizer.LowGain = val;
             break;
 
         case AL_EQUALIZER_LOW_CUTOFF:
             if(!(val >= AL_EQUALIZER_MIN_LOW_CUTOFF && val <= AL_EQUALIZER_MAX_LOW_CUTOFF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer low-band cutoff out of range");
             props->Equalizer.LowCutoff = val;
             break;
 
         case AL_EQUALIZER_MID1_GAIN:
             if(!(val >= AL_EQUALIZER_MIN_MID1_GAIN && val <= AL_EQUALIZER_MAX_MID1_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer mid1-band gain out of range");
             props->Equalizer.Mid1Gain = val;
             break;
 
         case AL_EQUALIZER_MID1_CENTER:
             if(!(val >= AL_EQUALIZER_MIN_MID1_CENTER && val <= AL_EQUALIZER_MAX_MID1_CENTER))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer mid1-band center out of range");
             props->Equalizer.Mid1Center = val;
             break;
 
         case AL_EQUALIZER_MID1_WIDTH:
             if(!(val >= AL_EQUALIZER_MIN_MID1_WIDTH && val <= AL_EQUALIZER_MAX_MID1_WIDTH))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer mid1-band width out of range");
             props->Equalizer.Mid1Width = val;
             break;
 
         case AL_EQUALIZER_MID2_GAIN:
             if(!(val >= AL_EQUALIZER_MIN_MID2_GAIN && val <= AL_EQUALIZER_MAX_MID2_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer mid2-band gain out of range");
             props->Equalizer.Mid2Gain = val;
             break;
 
         case AL_EQUALIZER_MID2_CENTER:
             if(!(val >= AL_EQUALIZER_MIN_MID2_CENTER && val <= AL_EQUALIZER_MAX_MID2_CENTER))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer mid2-band center out of range");
             props->Equalizer.Mid2Center = val;
             break;
 
         case AL_EQUALIZER_MID2_WIDTH:
             if(!(val >= AL_EQUALIZER_MIN_MID2_WIDTH && val <= AL_EQUALIZER_MAX_MID2_WIDTH))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer mid2-band width out of range");
             props->Equalizer.Mid2Width = val;
             break;
 
         case AL_EQUALIZER_HIGH_GAIN:
             if(!(val >= AL_EQUALIZER_MIN_HIGH_GAIN && val <= AL_EQUALIZER_MAX_HIGH_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer high-band gain out of range");
             props->Equalizer.HighGain = val;
             break;
 
         case AL_EQUALIZER_HIGH_CUTOFF:
             if(!(val >= AL_EQUALIZER_MIN_HIGH_CUTOFF && val <= AL_EQUALIZER_MAX_HIGH_CUTOFF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Equalizer high-band cutoff out of range");
             props->Equalizer.HighCutoff = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param);
     }
 }
 void ALequalizer_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALequalizer_setParamf(effect, context, param, vals[0]);
-}
+{ ALequalizer_setParamf(effect, context, param, vals[0]); }
 
-void ALequalizer_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALequalizer_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALequalizer_getParami(effect, context, param, vals);
-}
+void ALequalizer_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param); }
+void ALequalizer_getParamiv(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x", param); }
 void ALequalizer_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
 {
     const ALeffectProps *props = &effect->Props;
@@ -369,12 +346,10 @@ void ALequalizer_getParamf(const ALeffect *effect, ALCcontext *context, ALenum p
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param);
     }
 }
 void ALequalizer_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALequalizer_getParamf(effect, context, param, vals);
-}
+{ ALequalizer_getParamf(effect, context, param, vals); }
 
 DEFINE_ALEFFECT_VTABLE(ALequalizer);

+ 0 - 408
libs/openal-soft/Alc/effects/flanger.c

@@ -1,408 +0,0 @@
-/**
- * OpenAL cross platform audio library
- * Copyright (C) 2013 by Mike Gorchak
- * This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <math.h>
-#include <stdlib.h>
-
-#include "alMain.h"
-#include "alFilter.h"
-#include "alAuxEffectSlot.h"
-#include "alError.h"
-#include "alu.h"
-
-
-enum FlangerWaveForm {
-    FWF_Triangle = AL_FLANGER_WAVEFORM_TRIANGLE,
-    FWF_Sinusoid = AL_FLANGER_WAVEFORM_SINUSOID
-};
-
-typedef struct ALflangerState {
-    DERIVE_FROM_TYPE(ALeffectState);
-
-    ALfloat *SampleBuffer[2];
-    ALsizei BufferLength;
-    ALsizei offset;
-    ALsizei lfo_range;
-    ALfloat lfo_scale;
-    ALint lfo_disp;
-
-    /* Gains for left and right sides */
-    ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
-
-    /* effect parameters */
-    enum FlangerWaveForm waveform;
-    ALint delay;
-    ALfloat depth;
-    ALfloat feedback;
-} ALflangerState;
-
-static ALvoid ALflangerState_Destruct(ALflangerState *state);
-static ALboolean ALflangerState_deviceUpdate(ALflangerState *state, ALCdevice *Device);
-static ALvoid ALflangerState_update(ALflangerState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props);
-static ALvoid ALflangerState_process(ALflangerState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
-DECLARE_DEFAULT_ALLOCATORS(ALflangerState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALflangerState);
-
-
-static void ALflangerState_Construct(ALflangerState *state)
-{
-    ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
-    SET_VTABLE2(ALflangerState, ALeffectState, state);
-
-    state->BufferLength = 0;
-    state->SampleBuffer[0] = NULL;
-    state->SampleBuffer[1] = NULL;
-    state->offset = 0;
-    state->lfo_range = 1;
-    state->waveform = FWF_Triangle;
-}
-
-static ALvoid ALflangerState_Destruct(ALflangerState *state)
-{
-    al_free(state->SampleBuffer[0]);
-    state->SampleBuffer[0] = NULL;
-    state->SampleBuffer[1] = NULL;
-
-    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
-}
-
-static ALboolean ALflangerState_deviceUpdate(ALflangerState *state, ALCdevice *Device)
-{
-    ALsizei maxlen;
-    ALsizei it;
-
-    maxlen = fastf2i(AL_FLANGER_MAX_DELAY * 2.0f * Device->Frequency) + 1;
-    maxlen = NextPowerOf2(maxlen);
-
-    if(maxlen != state->BufferLength)
-    {
-        void *temp = al_calloc(16, maxlen * sizeof(ALfloat) * 2);
-        if(!temp) return AL_FALSE;
-
-        al_free(state->SampleBuffer[0]);
-        state->SampleBuffer[0] = temp;
-        state->SampleBuffer[1] = state->SampleBuffer[0] + maxlen;
-
-        state->BufferLength = maxlen;
-    }
-
-    for(it = 0;it < state->BufferLength;it++)
-    {
-        state->SampleBuffer[0][it] = 0.0f;
-        state->SampleBuffer[1][it] = 0.0f;
-    }
-
-    return AL_TRUE;
-}
-
-static ALvoid ALflangerState_update(ALflangerState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props)
-{
-    ALfloat frequency = (ALfloat)Device->Frequency;
-    ALfloat coeffs[MAX_AMBI_COEFFS];
-    ALfloat rate;
-    ALint phase;
-
-    switch(props->Flanger.Waveform)
-    {
-        case AL_FLANGER_WAVEFORM_TRIANGLE:
-            state->waveform = FWF_Triangle;
-            break;
-        case AL_FLANGER_WAVEFORM_SINUSOID:
-            state->waveform = FWF_Sinusoid;
-            break;
-    }
-    state->feedback = props->Flanger.Feedback;
-    state->delay = fastf2i(props->Flanger.Delay * frequency);
-    /* The LFO depth is scaled to be relative to the sample delay. */
-    state->depth = props->Flanger.Depth * state->delay;
-
-    /* Gains for left and right sides */
-    CalcAngleCoeffs(-F_PI_2, 0.0f, 0.0f, coeffs);
-    ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[0]);
-    CalcAngleCoeffs( F_PI_2, 0.0f, 0.0f, coeffs);
-    ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[1]);
-
-    phase = props->Flanger.Phase;
-    rate = props->Flanger.Rate;
-    if(!(rate > 0.0f))
-    {
-        state->lfo_scale = 0.0f;
-        state->lfo_range = 1;
-        state->lfo_disp = 0;
-    }
-    else
-    {
-        /* Calculate LFO coefficient */
-        state->lfo_range = fastf2i(frequency/rate + 0.5f);
-        switch(state->waveform)
-        {
-            case FWF_Triangle:
-                state->lfo_scale = 4.0f / state->lfo_range;
-                break;
-            case FWF_Sinusoid:
-                state->lfo_scale = F_TAU / state->lfo_range;
-                break;
-        }
-
-        /* Calculate lfo phase displacement */
-        if(phase >= 0)
-            state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f));
-        else
-            state->lfo_disp = fastf2i(state->lfo_range * ((360+phase)/360.0f));
-    }
-}
-
-static void GetTriangleDelays(ALint *restrict delays, ALsizei offset, const ALsizei lfo_range,
-                              const ALfloat lfo_scale, const ALfloat depth, const ALsizei delay,
-                              const ALsizei todo)
-{
-    ALsizei i;
-    for(i = 0;i < todo;i++)
-    {
-        delays[i] = fastf2i((1.0f - fabsf(2.0f - lfo_scale*offset)) * depth) + delay;
-        offset = (offset+1)%lfo_range;
-    }
-}
-
-static void GetSinusoidDelays(ALint *restrict delays, ALsizei offset, const ALsizei lfo_range,
-                              const ALfloat lfo_scale, const ALfloat depth, const ALsizei delay,
-                              const ALsizei todo)
-{
-    ALsizei i;
-    for(i = 0;i < todo;i++)
-    {
-        delays[i] = fastf2i(sinf(lfo_scale*offset) * depth) + delay;
-        offset = (offset+1)%lfo_range;
-    }
-}
-
-static ALvoid ALflangerState_process(ALflangerState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
-{
-    ALfloat *restrict leftbuf = state->SampleBuffer[0];
-    ALfloat *restrict rightbuf = state->SampleBuffer[1];
-    const ALsizei bufmask = state->BufferLength-1;
-    const ALfloat feedback = state->feedback;
-    ALsizei offset = state->offset;
-    ALsizei i, c;
-    ALsizei base;
-
-    for(base = 0;base < SamplesToDo;)
-    {
-        const ALsizei todo = mini(128, SamplesToDo-base);
-        ALfloat temps[128][2];
-        ALint moddelays[2][128];
-
-        switch(state->waveform)
-        {
-            case FWF_Triangle:
-                GetTriangleDelays(moddelays[0], offset%state->lfo_range, state->lfo_range,
-                                  state->lfo_scale, state->depth, state->delay, todo);
-                GetTriangleDelays(moddelays[1], (offset+state->lfo_disp)%state->lfo_range,
-                                  state->lfo_range, state->lfo_scale, state->depth, state->delay,
-                                  todo);
-                break;
-            case FWF_Sinusoid:
-                GetSinusoidDelays(moddelays[0], offset%state->lfo_range, state->lfo_range,
-                                  state->lfo_scale, state->depth, state->delay, todo);
-                GetSinusoidDelays(moddelays[1], (offset+state->lfo_disp)%state->lfo_range,
-                                  state->lfo_range, state->lfo_scale, state->depth, state->delay,
-                                  todo);
-                break;
-        }
-
-        for(i = 0;i < todo;i++)
-        {
-            leftbuf[offset&bufmask] = SamplesIn[0][base+i];
-            temps[i][0] = leftbuf[(offset-moddelays[0][i])&bufmask] * feedback;
-            leftbuf[offset&bufmask] += temps[i][0];
-
-            rightbuf[offset&bufmask] = SamplesIn[0][base+i];
-            temps[i][1] = rightbuf[(offset-moddelays[1][i])&bufmask] * feedback;
-            rightbuf[offset&bufmask] += temps[i][1];
-
-            offset++;
-        }
-
-        for(c = 0;c < NumChannels;c++)
-        {
-            ALfloat gain = state->Gain[0][c];
-            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
-            {
-                for(i = 0;i < todo;i++)
-                    SamplesOut[c][i+base] += temps[i][0] * gain;
-            }
-
-            gain = state->Gain[1][c];
-            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
-            {
-                for(i = 0;i < todo;i++)
-                    SamplesOut[c][i+base] += temps[i][1] * gain;
-            }
-        }
-
-        base += todo;
-    }
-
-    state->offset = offset;
-}
-
-
-typedef struct ALflangerStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALflangerStateFactory;
-
-ALeffectState *ALflangerStateFactory_create(ALflangerStateFactory *UNUSED(factory))
-{
-    ALflangerState *state;
-
-    NEW_OBJ0(state, ALflangerState)();
-    if(!state) return NULL;
-
-    return STATIC_CAST(ALeffectState, state);
-}
-
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALflangerStateFactory);
-
-ALeffectStateFactory *ALflangerStateFactory_getFactory(void)
-{
-    static ALflangerStateFactory FlangerFactory = { { GET_VTABLE2(ALflangerStateFactory, ALeffectStateFactory) } };
-
-    return STATIC_CAST(ALeffectStateFactory, &FlangerFactory);
-}
-
-
-void ALflanger_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
-{
-    ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_FLANGER_WAVEFORM:
-            if(!(val >= AL_FLANGER_MIN_WAVEFORM && val <= AL_FLANGER_MAX_WAVEFORM))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Flanger.Waveform = val;
-            break;
-
-        case AL_FLANGER_PHASE:
-            if(!(val >= AL_FLANGER_MIN_PHASE && val <= AL_FLANGER_MAX_PHASE))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Flanger.Phase = val;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALflanger_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALflanger_setParami(effect, context, param, vals[0]);
-}
-void ALflanger_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
-{
-    ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_FLANGER_RATE:
-            if(!(val >= AL_FLANGER_MIN_RATE && val <= AL_FLANGER_MAX_RATE))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Flanger.Rate = val;
-            break;
-
-        case AL_FLANGER_DEPTH:
-            if(!(val >= AL_FLANGER_MIN_DEPTH && val <= AL_FLANGER_MAX_DEPTH))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Flanger.Depth = val;
-            break;
-
-        case AL_FLANGER_FEEDBACK:
-            if(!(val >= AL_FLANGER_MIN_FEEDBACK && val <= AL_FLANGER_MAX_FEEDBACK))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Flanger.Feedback = val;
-            break;
-
-        case AL_FLANGER_DELAY:
-            if(!(val >= AL_FLANGER_MIN_DELAY && val <= AL_FLANGER_MAX_DELAY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Flanger.Delay = val;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALflanger_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALflanger_setParamf(effect, context, param, vals[0]);
-}
-
-void ALflanger_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
-{
-    const ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_FLANGER_WAVEFORM:
-            *val = props->Flanger.Waveform;
-            break;
-
-        case AL_FLANGER_PHASE:
-            *val = props->Flanger.Phase;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALflanger_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALflanger_getParami(effect, context, param, vals);
-}
-void ALflanger_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
-{
-    const ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_FLANGER_RATE:
-            *val = props->Flanger.Rate;
-            break;
-
-        case AL_FLANGER_DEPTH:
-            *val = props->Flanger.Depth;
-            break;
-
-        case AL_FLANGER_FEEDBACK:
-            *val = props->Flanger.Feedback;
-            break;
-
-        case AL_FLANGER_DELAY:
-            *val = props->Flanger.Delay;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALflanger_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALflanger_getParamf(effect, context, param, vals);
-}
-
-DEFINE_ALEFFECT_VTABLE(ALflanger);

+ 76 - 83
libs/openal-soft/Alc/effects/modulator.c

@@ -24,28 +24,35 @@
 #include <stdlib.h>
 
 #include "alMain.h"
-#include "alFilter.h"
 #include "alAuxEffectSlot.h"
 #include "alError.h"
 #include "alu.h"
+#include "filters/defs.h"
 
 
+#define MAX_UPDATE_SAMPLES 128
+
 typedef struct ALmodulatorState {
     DERIVE_FROM_TYPE(ALeffectState);
 
-    void (*Process)(ALfloat*, const ALfloat*, ALsizei, const ALsizei, ALsizei);
+    void (*GetSamples)(ALfloat*, ALsizei, const ALsizei, ALsizei);
 
     ALsizei index;
     ALsizei step;
 
-    ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS];
+    alignas(16) ALfloat ModSamples[MAX_UPDATE_SAMPLES];
+
+    struct {
+        BiquadState Filter;
 
-    ALfilterState Filter[MAX_EFFECT_CHANNELS];
+        ALfloat CurrentGains[MAX_OUTPUT_CHANNELS];
+        ALfloat TargetGains[MAX_OUTPUT_CHANNELS];
+    } Chans[MAX_EFFECT_CHANNELS];
 } ALmodulatorState;
 
 static ALvoid ALmodulatorState_Destruct(ALmodulatorState *state);
 static ALboolean ALmodulatorState_deviceUpdate(ALmodulatorState *state, ALCdevice *device);
-static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props);
+static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
 static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
 DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState)
 
@@ -72,15 +79,15 @@ static inline ALfloat Square(ALsizei index)
 }
 
 #define DECL_TEMPLATE(func)                                                   \
-static void Modulate##func(ALfloat *restrict dst, const ALfloat *restrict src,\
-                           ALsizei index, const ALsizei step, ALsizei todo)   \
+static void Modulate##func(ALfloat *restrict dst, ALsizei index,              \
+                           const ALsizei step, ALsizei todo)                  \
 {                                                                             \
     ALsizei i;                                                                \
     for(i = 0;i < todo;i++)                                                   \
     {                                                                         \
         index += step;                                                        \
         index &= WAVEFORM_FRACMASK;                                           \
-        dst[i] = src[i] * func(index);                                        \
+        dst[i] = func(index);                                                 \
     }                                                                         \
 }
 
@@ -93,16 +100,11 @@ DECL_TEMPLATE(Square)
 
 static void ALmodulatorState_Construct(ALmodulatorState *state)
 {
-    ALuint i;
-
     ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
     SET_VTABLE2(ALmodulatorState, ALeffectState, state);
 
     state->index = 0;
     state->step = 1;
-
-    for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
-        ALfilterState_clear(&state->Filter[i]);
 }
 
 static ALvoid ALmodulatorState_Destruct(ALmodulatorState *state)
@@ -110,91 +112,90 @@ static ALvoid ALmodulatorState_Destruct(ALmodulatorState *state)
     ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
-static ALboolean ALmodulatorState_deviceUpdate(ALmodulatorState *UNUSED(state), ALCdevice *UNUSED(device))
+static ALboolean ALmodulatorState_deviceUpdate(ALmodulatorState *state, ALCdevice *UNUSED(device))
 {
+    ALsizei i, j;
+    for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
+    {
+        BiquadState_clear(&state->Chans[i].Filter);
+        for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
+            state->Chans[i].CurrentGains[j] = 0.0f;
+    }
     return AL_TRUE;
 }
 
-static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props)
+static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
 {
+    const ALCdevice *device = context->Device;
     ALfloat cw, a;
     ALsizei i;
 
     if(props->Modulator.Waveform == AL_RING_MODULATOR_SINUSOID)
-        state->Process = ModulateSin;
+        state->GetSamples = ModulateSin;
     else if(props->Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH)
-        state->Process = ModulateSaw;
+        state->GetSamples = ModulateSaw;
     else /*if(Slot->Params.EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)*/
-        state->Process = ModulateSquare;
+        state->GetSamples = ModulateSquare;
 
     state->step = fastf2i(props->Modulator.Frequency*WAVEFORM_FRACONE /
-                          Device->Frequency);
-    if(state->step == 0) state->step = 1;
+                          device->Frequency);
+    state->step = clampi(state->step, 1, WAVEFORM_FRACONE-1);
 
     /* Custom filter coeffs, which match the old version instead of a low-shelf. */
-    cw = cosf(F_TAU * props->Modulator.HighPassCutoff / Device->Frequency);
+    cw = cosf(F_TAU * props->Modulator.HighPassCutoff / device->Frequency);
     a = (2.0f-cw) - sqrtf(powf(2.0f-cw, 2.0f) - 1.0f);
 
-    for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
-    {
-        state->Filter[i].b0 = a;
-        state->Filter[i].b1 = -a;
-        state->Filter[i].b2 = 0.0f;
-        state->Filter[i].a1 = -a;
-        state->Filter[i].a2 = 0.0f;
-    }
+    state->Chans[0].Filter.b0 = a;
+    state->Chans[0].Filter.b1 = -a;
+    state->Chans[0].Filter.b2 = 0.0f;
+    state->Chans[0].Filter.a1 = -a;
+    state->Chans[0].Filter.a2 = 0.0f;
+    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
+        BiquadState_copyParams(&state->Chans[i].Filter, &state->Chans[0].Filter);
 
-    STATIC_CAST(ALeffectState,state)->OutBuffer = Device->FOAOut.Buffer;
-    STATIC_CAST(ALeffectState,state)->OutChannels = Device->FOAOut.NumChannels;
+    STATIC_CAST(ALeffectState,state)->OutBuffer = device->FOAOut.Buffer;
+    STATIC_CAST(ALeffectState,state)->OutChannels = device->FOAOut.NumChannels;
     for(i = 0;i < MAX_EFFECT_CHANNELS;i++)
-        ComputeFirstOrderGains(Device->FOAOut, IdentityMatrixf.m[i],
-                               Slot->Params.Gain, state->Gain[i]);
+        ComputeFirstOrderGains(&device->FOAOut, IdentityMatrixf.m[i],
+                               slot->Params.Gain, state->Chans[i].TargetGains);
 }
 
 static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
+    ALfloat *restrict modsamples = ASSUME_ALIGNED(state->ModSamples, 16);
     const ALsizei step = state->step;
-    ALsizei index = state->index;
     ALsizei base;
 
     for(base = 0;base < SamplesToDo;)
     {
-        ALfloat temps[2][128];
-        ALsizei td = mini(128, SamplesToDo-base);
-        ALsizei i, j, k;
+        alignas(16) ALfloat temps[2][MAX_UPDATE_SAMPLES];
+        ALsizei td = mini(MAX_UPDATE_SAMPLES, SamplesToDo-base);
+        ALsizei c, i;
 
-        for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
-        {
-            ALfilterState_process(&state->Filter[j], temps[0], &SamplesIn[j][base], td);
-            state->Process(temps[1], temps[0], index, step, td);
-
-            for(k = 0;k < NumChannels;k++)
-            {
-                ALfloat gain = state->Gain[j][k];
-                if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
-                    continue;
-
-                for(i = 0;i < td;i++)
-                    SamplesOut[k][base+i] += gain * temps[1][i];
-            }
-        }
+        state->GetSamples(modsamples, state->index, step, td);
+        state->index += (step*td) & WAVEFORM_FRACMASK;
+        state->index &= WAVEFORM_FRACMASK;
 
-        for(i = 0;i < td;i++)
+        for(c = 0;c < MAX_EFFECT_CHANNELS;c++)
         {
-            index += step;
-            index &= WAVEFORM_FRACMASK;
+            BiquadState_process(&state->Chans[c].Filter, temps[0], &SamplesIn[c][base], td);
+            for(i = 0;i < td;i++)
+                temps[1][i] = temps[0][i] * modsamples[i];
+
+            MixSamples(temps[1], NumChannels, SamplesOut, state->Chans[c].CurrentGains,
+                       state->Chans[c].TargetGains, SamplesToDo-base, base, td);
         }
+
         base += td;
     }
-    state->index = index;
 }
 
 
-typedef struct ALmodulatorStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALmodulatorStateFactory;
+typedef struct ModulatorStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} ModulatorStateFactory;
 
-static ALeffectState *ALmodulatorStateFactory_create(ALmodulatorStateFactory *UNUSED(factory))
+static ALeffectState *ModulatorStateFactory_create(ModulatorStateFactory *UNUSED(factory))
 {
     ALmodulatorState *state;
 
@@ -204,13 +205,13 @@ static ALeffectState *ALmodulatorStateFactory_create(ALmodulatorStateFactory *UN
     return STATIC_CAST(ALeffectState, state);
 }
 
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALmodulatorStateFactory);
+DEFINE_EFFECTSTATEFACTORY_VTABLE(ModulatorStateFactory);
 
-ALeffectStateFactory *ALmodulatorStateFactory_getFactory(void)
+EffectStateFactory *ModulatorStateFactory_getFactory(void)
 {
-    static ALmodulatorStateFactory ModulatorFactory = { { GET_VTABLE2(ALmodulatorStateFactory, ALeffectStateFactory) } };
+    static ModulatorStateFactory ModulatorFactory = { { GET_VTABLE2(ModulatorStateFactory, EffectStateFactory) } };
 
-    return STATIC_CAST(ALeffectStateFactory, &ModulatorFactory);
+    return STATIC_CAST(EffectStateFactory, &ModulatorFactory);
 }
 
 
@@ -221,24 +222,22 @@ void ALmodulator_setParamf(ALeffect *effect, ALCcontext *context, ALenum param,
     {
         case AL_RING_MODULATOR_FREQUENCY:
             if(!(val >= AL_RING_MODULATOR_MIN_FREQUENCY && val <= AL_RING_MODULATOR_MAX_FREQUENCY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Modulator frequency out of range");
             props->Modulator.Frequency = val;
             break;
 
         case AL_RING_MODULATOR_HIGHPASS_CUTOFF:
             if(!(val >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && val <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Modulator high-pass cutoff out of range");
             props->Modulator.HighPassCutoff = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid modulator float property 0x%04x", param);
     }
 }
 void ALmodulator_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALmodulator_setParamf(effect, context, param, vals[0]);
-}
+{ ALmodulator_setParamf(effect, context, param, vals[0]); }
 void ALmodulator_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
 {
     ALeffectProps *props = &effect->Props;
@@ -251,18 +250,16 @@ void ALmodulator_setParami(ALeffect *effect, ALCcontext *context, ALenum param,
 
         case AL_RING_MODULATOR_WAVEFORM:
             if(!(val >= AL_RING_MODULATOR_MIN_WAVEFORM && val <= AL_RING_MODULATOR_MAX_WAVEFORM))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Invalid modulator waveform");
             props->Modulator.Waveform = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid modulator integer property 0x%04x", param);
     }
 }
 void ALmodulator_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALmodulator_setParami(effect, context, param, vals[0]);
-}
+{ ALmodulator_setParami(effect, context, param, vals[0]); }
 
 void ALmodulator_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
 {
@@ -280,13 +277,11 @@ void ALmodulator_getParami(const ALeffect *effect, ALCcontext *context, ALenum p
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid modulator integer property 0x%04x", param);
     }
 }
 void ALmodulator_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALmodulator_getParami(effect, context, param, vals);
-}
+{ ALmodulator_getParami(effect, context, param, vals); }
 void ALmodulator_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
 {
     const ALeffectProps *props = &effect->Props;
@@ -300,12 +295,10 @@ void ALmodulator_getParamf(const ALeffect *effect, ALCcontext *context, ALenum p
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid modulator float property 0x%04x", param);
     }
 }
 void ALmodulator_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALmodulator_getParamf(effect, context, param, vals);
-}
+{ ALmodulator_getParamf(effect, context, param, vals); }
 
 DEFINE_ALEFFECT_VTABLE(ALmodulator);

+ 37 - 37
libs/openal-soft/Alc/effects/null.c

@@ -16,8 +16,8 @@ typedef struct ALnullState {
 /* Forward-declare "virtual" functions to define the vtable with. */
 static ALvoid ALnullState_Destruct(ALnullState *state);
 static ALboolean ALnullState_deviceUpdate(ALnullState *state, ALCdevice *device);
-static ALvoid ALnullState_update(ALnullState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props);
-static ALvoid ALnullState_process(ALnullState *state, ALsizei samplesToDo, const ALfloatBUFFERSIZE*restrict samplesIn, ALfloatBUFFERSIZE*restrict samplesOut, ALsizei NumChannels);
+static ALvoid ALnullState_update(ALnullState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
+static ALvoid ALnullState_process(ALnullState *state, ALsizei samplesToDo, const ALfloat (*restrict samplesIn)[BUFFERSIZE], ALfloat (*restrict samplesOut)[BUFFERSIZE], ALsizei mumChannels);
 static void *ALnullState_New(size_t size);
 static void ALnullState_Delete(void *ptr);
 
@@ -56,7 +56,7 @@ static ALboolean ALnullState_deviceUpdate(ALnullState* UNUSED(state), ALCdevice*
 /* This updates the effect state. This is called any time the effect is
  * (re)loaded into a slot.
  */
-static ALvoid ALnullState_update(ALnullState* UNUSED(state), const ALCdevice* UNUSED(device), const ALeffectslot* UNUSED(slot), const ALeffectProps* UNUSED(props))
+static ALvoid ALnullState_update(ALnullState* UNUSED(state), const ALCcontext* UNUSED(context), const ALeffectslot* UNUSED(slot), const ALeffectProps* UNUSED(props))
 {
 }
 
@@ -64,7 +64,7 @@ static ALvoid ALnullState_update(ALnullState* UNUSED(state), const ALCdevice* UN
  * input to the output buffer. The result should be added to the output buffer,
  * not replace it.
  */
-static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALsizei UNUSED(samplesToDo), const ALfloatBUFFERSIZE*restrict UNUSED(samplesIn), ALfloatBUFFERSIZE*restrict UNUSED(samplesOut), ALsizei UNUSED(NumChannels))
+static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALsizei UNUSED(samplesToDo), const ALfloatBUFFERSIZE*restrict UNUSED(samplesIn), ALfloatBUFFERSIZE*restrict UNUSED(samplesOut), ALsizei UNUSED(numChannels))
 {
 }
 
@@ -85,12 +85,12 @@ static void ALnullState_Delete(void *ptr)
 }
 
 
-typedef struct ALnullStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALnullStateFactory;
+typedef struct NullStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} NullStateFactory;
 
 /* Creates ALeffectState objects of the appropriate type. */
-ALeffectState *ALnullStateFactory_create(ALnullStateFactory *UNUSED(factory))
+ALeffectState *NullStateFactory_create(NullStateFactory *UNUSED(factory))
 {
     ALnullState *state;
 
@@ -100,79 +100,79 @@ ALeffectState *ALnullStateFactory_create(ALnullStateFactory *UNUSED(factory))
     return STATIC_CAST(ALeffectState, state);
 }
 
-/* Define the ALeffectStateFactory vtable for this type. */
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALnullStateFactory);
+/* Define the EffectStateFactory vtable for this type. */
+DEFINE_EFFECTSTATEFACTORY_VTABLE(NullStateFactory);
 
-ALeffectStateFactory *ALnullStateFactory_getFactory(void)
+EffectStateFactory *NullStateFactory_getFactory(void)
 {
-    static ALnullStateFactory NullFactory = { { GET_VTABLE2(ALnullStateFactory, ALeffectStateFactory) } };
-    return STATIC_CAST(ALeffectStateFactory, &NullFactory);
+    static NullStateFactory NullFactory = { { GET_VTABLE2(NullStateFactory, EffectStateFactory) } };
+    return STATIC_CAST(EffectStateFactory, &NullFactory);
 }
 
 
-void ALnull_setParami(ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALint UNUSED(val))
+void ALnull_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint UNUSED(val))
 {
     switch(param)
     {
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    default:
+        alSetError(context, AL_INVALID_ENUM, "Invalid null effect integer property 0x%04x", param);
     }
 }
-void ALnull_setParamiv(ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, const ALint* UNUSED(vals))
+void ALnull_setParamiv(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, const ALint* UNUSED(vals))
 {
     switch(param)
     {
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    default:
+        alSetError(context, AL_INVALID_ENUM, "Invalid null effect integer-vector property 0x%04x", param);
     }
 }
-void ALnull_setParamf(ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALfloat UNUSED(val))
+void ALnull_setParamf(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat UNUSED(val))
 {
     switch(param)
     {
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    default:
+        alSetError(context, AL_INVALID_ENUM, "Invalid null effect float property 0x%04x", param);
     }
 }
-void ALnull_setParamfv(ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, const ALfloat* UNUSED(vals))
+void ALnull_setParamfv(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, const ALfloat* UNUSED(vals))
 {
     switch(param)
     {
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    default:
+        alSetError(context, AL_INVALID_ENUM, "Invalid null effect float-vector property 0x%04x", param);
     }
 }
 
-void ALnull_getParami(const ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALint* UNUSED(val))
+void ALnull_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint* UNUSED(val))
 {
     switch(param)
     {
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    default:
+        alSetError(context, AL_INVALID_ENUM, "Invalid null effect integer property 0x%04x", param);
     }
 }
-void ALnull_getParamiv(const ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALint* UNUSED(vals))
+void ALnull_getParamiv(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALint* UNUSED(vals))
 {
     switch(param)
     {
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    default:
+        alSetError(context, AL_INVALID_ENUM, "Invalid null effect integer-vector property 0x%04x", param);
     }
 }
-void ALnull_getParamf(const ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALfloat* UNUSED(val))
+void ALnull_getParamf(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat* UNUSED(val))
 {
     switch(param)
     {
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    default:
+        alSetError(context, AL_INVALID_ENUM, "Invalid null effect float property 0x%04x", param);
     }
 }
-void ALnull_getParamfv(const ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALfloat* UNUSED(vals))
+void ALnull_getParamfv(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat* UNUSED(vals))
 {
     switch(param)
     {
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+    default:
+        alSetError(context, AL_INVALID_ENUM, "Invalid null effect float-vector property 0x%04x", param);
     }
 }
 

+ 496 - 0
libs/openal-soft/Alc/effects/pshifter.c

@@ -0,0 +1,496 @@
+/**
+ * OpenAL cross platform audio library
+ * Copyright (C) 2018 by Raul Herraiz.
+ * This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Library General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ *  License along with this library; if not, write to the
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ * Or go to http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <stdlib.h>
+
+#include "alMain.h"
+#include "alAuxEffectSlot.h"
+#include "alError.h"
+#include "alu.h"
+#include "filters/defs.h"
+
+
+#define STFT_SIZE      1024
+#define STFT_HALF_SIZE (STFT_SIZE>>1)
+#define OVERSAMP       (1<<2)
+
+#define STFT_STEP    (STFT_SIZE / OVERSAMP)
+#define FIFO_LATENCY (STFT_STEP * (OVERSAMP-1))
+
+typedef struct ALcomplex {
+    ALfloat Real;
+    ALfloat Imag;
+} ALcomplex;
+
+typedef struct ALphasor {
+    ALfloat Amplitude;
+    ALfloat Phase;
+} ALphasor;
+
+typedef struct ALFrequencyDomain {
+    ALfloat Amplitude;
+    ALfloat Frequency;
+} ALfrequencyDomain;
+
+typedef struct ALpshifterState {
+    DERIVE_FROM_TYPE(ALeffectState);
+
+    /* Effect parameters */
+    ALsizei count;
+    ALfloat PitchShift;
+    ALfloat FreqPerBin;
+
+    /*Effects buffers*/
+    ALfloat InFIFO[STFT_SIZE];
+    ALfloat OutFIFO[STFT_STEP];
+    ALfloat LastPhase[STFT_HALF_SIZE+1];
+    ALfloat SumPhase[STFT_HALF_SIZE+1];
+    ALfloat OutputAccum[STFT_SIZE];
+
+    ALcomplex FFTbuffer[STFT_SIZE];
+
+    ALfrequencyDomain Analysis_buffer[STFT_HALF_SIZE+1];
+    ALfrequencyDomain Syntesis_buffer[STFT_HALF_SIZE+1];
+
+    alignas(16) ALfloat BufferOut[BUFFERSIZE];
+
+    /* Effect gains for each output channel */
+    ALfloat CurrentGains[MAX_OUTPUT_CHANNELS];
+    ALfloat TargetGains[MAX_OUTPUT_CHANNELS];
+} ALpshifterState;
+
+static ALvoid ALpshifterState_Destruct(ALpshifterState *state);
+static ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device);
+static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props);
+static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+DECLARE_DEFAULT_ALLOCATORS(ALpshifterState)
+
+DEFINE_ALEFFECTSTATE_VTABLE(ALpshifterState);
+
+
+/* Define a Hann window, used to filter the STFT input and output. */
+alignas(16) static ALfloat HannWindow[STFT_SIZE];
+
+static void InitHannWindow(void)
+{
+    ALsizei i;
+
+    /* Create lookup table of the Hann window for the desired size, i.e. STFT_SIZE */
+    for(i = 0;i < STFT_SIZE>>1;i++)
+    {
+        ALdouble val = sin(M_PI * (ALdouble)i / (ALdouble)(STFT_SIZE-1));
+        HannWindow[i] = HannWindow[STFT_SIZE-(i+1)] = (ALfloat)(val * val);
+    }
+}
+static alonce_flag HannInitOnce = AL_ONCE_FLAG_INIT;
+
+
+/* Converts ALcomplex to ALphasor */
+static inline ALphasor rect2polar(ALcomplex number)
+{
+    ALphasor polar;
+
+    polar.Amplitude = sqrtf(number.Real*number.Real + number.Imag*number.Imag);
+    polar.Phase     = atan2f(number.Imag , number.Real);
+
+    return polar;
+}
+
+/* Converts ALphasor to ALcomplex */
+static inline ALcomplex polar2rect(ALphasor  number)
+{
+    ALcomplex cartesian;
+
+    cartesian.Real = number.Amplitude * cosf(number.Phase);
+    cartesian.Imag = number.Amplitude * sinf(number.Phase);
+
+    return cartesian;
+}
+
+/* Addition of two complex numbers (ALcomplex format) */
+static inline ALcomplex complex_add(ALcomplex a, ALcomplex b)
+{
+    ALcomplex result;
+
+    result.Real = a.Real + b.Real;
+    result.Imag = a.Imag + b.Imag;
+
+    return result;
+}
+
+/* Subtraction of two complex numbers (ALcomplex format) */
+static inline ALcomplex complex_sub(ALcomplex a, ALcomplex b)
+{
+    ALcomplex result;
+
+    result.Real = a.Real - b.Real;
+    result.Imag = a.Imag - b.Imag;
+
+    return result;
+}
+
+/* Multiplication of two complex numbers (ALcomplex format) */
+static inline ALcomplex complex_mult(ALcomplex a, ALcomplex b)
+{
+    ALcomplex result;
+
+    result.Real = a.Real*b.Real - a.Imag*b.Imag;
+    result.Imag = a.Imag*b.Real + a.Real*b.Imag;
+
+    return result;
+}
+
+/* Iterative implementation of 2-radix FFT (In-place algorithm). Sign = -1 is
+ * FFT and 1 is iFFT (inverse). Fills FFTBuffer[0...FFTSize-1] with the
+ * Discrete Fourier Transform (DFT) of the time domain data stored in
+ * FFTBuffer[0...FFTSize-1]. FFTBuffer is an array of complex numbers
+ * (ALcomplex), FFTSize MUST BE power of two.
+ */
+static inline ALvoid FFT(ALcomplex *FFTBuffer, ALsizei FFTSize, ALfloat Sign)
+{
+    ALsizei i, j, k, mask, step, step2;
+    ALcomplex temp, u, w;
+    ALfloat arg;
+
+    /* Bit-reversal permutation applied to a sequence of FFTSize items */
+    for(i = 1;i < FFTSize-1;i++)
+    {
+        for(mask = 0x1, j = 0;mask < FFTSize;mask <<= 1)
+        {
+            if((i&mask) != 0)
+                j++;
+            j <<= 1;
+        }
+        j >>= 1;
+
+        if(i < j)
+        {
+            temp         = FFTBuffer[i];
+            FFTBuffer[i] = FFTBuffer[j];
+            FFTBuffer[j] = temp;
+        }
+    }
+
+    /* Iterative form of Danielson–Lanczos lemma */
+    for(i = 1, step = 2;i < FFTSize;i<<=1, step<<=1)
+    {
+        step2 = step >> 1;
+        arg   = F_PI / step2;
+
+        w.Real = cosf(arg);
+        w.Imag = sinf(arg) * Sign;
+
+        u.Real = 1.0f;
+        u.Imag = 0.0f;
+
+        for(j = 0;j < step2;j++)
+        {
+            for(k = j;k < FFTSize;k+=step)
+            {
+                temp               = complex_mult(FFTBuffer[k+step2], u);
+                FFTBuffer[k+step2] = complex_sub(FFTBuffer[k], temp);
+                FFTBuffer[k]       = complex_add(FFTBuffer[k], temp);
+            }
+
+            u = complex_mult(u, w);
+        }
+    }
+}
+
+
+static void ALpshifterState_Construct(ALpshifterState *state)
+{
+    ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
+    SET_VTABLE2(ALpshifterState, ALeffectState, state);
+
+    alcall_once(&HannInitOnce, InitHannWindow);
+}
+
+static ALvoid ALpshifterState_Destruct(ALpshifterState *state)
+{
+    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
+}
+
+static ALboolean ALpshifterState_deviceUpdate(ALpshifterState *state, ALCdevice *device)
+{
+    /* (Re-)initializing parameters and clear the buffers. */
+    state->count      = FIFO_LATENCY;
+    state->PitchShift = 1.0f;
+    state->FreqPerBin = device->Frequency / (ALfloat)STFT_SIZE;
+
+    memset(state->InFIFO,          0, sizeof(state->InFIFO));
+    memset(state->OutFIFO,         0, sizeof(state->OutFIFO));
+    memset(state->FFTbuffer,       0, sizeof(state->FFTbuffer));
+    memset(state->LastPhase,       0, sizeof(state->LastPhase));
+    memset(state->SumPhase,        0, sizeof(state->SumPhase));
+    memset(state->OutputAccum,     0, sizeof(state->OutputAccum));
+    memset(state->Analysis_buffer, 0, sizeof(state->Analysis_buffer));
+    memset(state->Syntesis_buffer, 0, sizeof(state->Syntesis_buffer));
+
+    memset(state->CurrentGains, 0, sizeof(state->CurrentGains));
+    memset(state->TargetGains,  0, sizeof(state->TargetGains));
+
+    return AL_TRUE;
+}
+
+static ALvoid ALpshifterState_update(ALpshifterState *state, const ALCcontext *context, const ALeffectslot *slot, const ALeffectProps *props)
+{
+    const ALCdevice *device = context->Device;
+    ALfloat coeffs[MAX_AMBI_COEFFS];
+
+    state->PitchShift = powf(2.0f,
+        (ALfloat)(props->Pshifter.CoarseTune*100 + props->Pshifter.FineTune) / 1200.0f
+    );
+
+    CalcAngleCoeffs(0.0f, 0.0f, 0.0f, coeffs);
+    ComputeDryPanGains(&device->Dry, coeffs, slot->Params.Gain, state->TargetGains);
+}
+
+static ALvoid ALpshifterState_process(ALpshifterState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
+{
+    /* Pitch shifter engine based on the work of Stephan Bernsee.
+     * http://blogs.zynaptiq.com/bernsee/pitch-shifting-using-the-ft/
+     */
+
+    static const ALfloat expected = F_TAU / (ALfloat)OVERSAMP;
+    const ALfloat freq_per_bin = state->FreqPerBin;
+    ALfloat *restrict bufferOut = state->BufferOut;
+    ALsizei count = state->count;
+    ALsizei i, j, k;
+
+    for(i = 0;i < SamplesToDo;)
+    {
+        do {
+            /* Fill FIFO buffer with samples data */
+            state->InFIFO[count] = SamplesIn[0][i];
+            bufferOut[i] = state->OutFIFO[count - FIFO_LATENCY];
+
+            count++;
+        } while(++i < SamplesToDo && count < STFT_SIZE);
+
+        /* Check whether FIFO buffer is filled */
+        if(count < STFT_SIZE) break;
+        count = FIFO_LATENCY;
+
+        /* Real signal windowing and store in FFTbuffer */
+        for(k = 0;k < STFT_SIZE;k++)
+        {
+            state->FFTbuffer[k].Real = state->InFIFO[k] * HannWindow[k];
+            state->FFTbuffer[k].Imag = 0.0f;
+        }
+
+        /* ANALYSIS */
+        /* Apply FFT to FFTbuffer data */
+        FFT(state->FFTbuffer, STFT_SIZE, -1.0f);
+
+        /* Analyze the obtained data. Since the real FFT is symmetric, only
+         * STFT_HALF_SIZE+1 samples are needed.
+         */
+        for(k = 0;k < STFT_HALF_SIZE+1;k++)
+        {
+            ALphasor component;
+            ALfloat tmp;
+            ALint qpd;
+
+            /* Compute amplitude and phase */
+            component = rect2polar(state->FFTbuffer[k]);
+
+            /* Compute phase difference and subtract expected phase difference */
+            tmp = (component.Phase - state->LastPhase[k]) - (ALfloat)k*expected;
+
+            /* Map delta phase into +/- Pi interval */
+            qpd = fastf2i(tmp / F_PI);
+            tmp -= F_PI * (ALfloat)(qpd + (qpd%2));
+
+            /* Get deviation from bin frequency from the +/- Pi interval */
+            tmp /= expected;
+
+            /* Compute the k-th partials' true frequency, twice the amplitude
+             * for maintain the gain (because half of bins are used) and store
+             * amplitude and true frequency in analysis buffer.
+             */
+            state->Analysis_buffer[k].Amplitude = 2.0f * component.Amplitude;
+            state->Analysis_buffer[k].Frequency = ((ALfloat)k + tmp) * freq_per_bin;
+
+            /* Store actual phase[k] for the calculations in the next frame*/
+            state->LastPhase[k] = component.Phase;
+        }
+
+        /* PROCESSING */
+        /* pitch shifting */
+        for(k = 0;k < STFT_HALF_SIZE+1;k++)
+        {
+            state->Syntesis_buffer[k].Amplitude = 0.0f;
+            state->Syntesis_buffer[k].Frequency = 0.0f;
+        }
+
+        for(k = 0;k < STFT_HALF_SIZE+1;k++)
+        {
+            j = fastf2i((ALfloat)k * state->PitchShift);
+            if(j >= STFT_HALF_SIZE+1) break;
+
+            state->Syntesis_buffer[j].Amplitude += state->Analysis_buffer[k].Amplitude;
+            state->Syntesis_buffer[j].Frequency  = state->Analysis_buffer[k].Frequency *
+                                                   state->PitchShift;
+        }
+
+        /* SYNTHESIS */
+        /* Synthesis the processing data */
+        for(k = 0;k < STFT_HALF_SIZE+1;k++)
+        {
+            ALphasor component;
+            ALfloat tmp;
+
+            /* Compute bin deviation from scaled freq */
+            tmp = state->Syntesis_buffer[k].Frequency/freq_per_bin - (ALfloat)k;
+
+            /* Calculate actual delta phase and accumulate it to get bin phase */
+            state->SumPhase[k] += ((ALfloat)k + tmp) * expected;
+
+            component.Amplitude = state->Syntesis_buffer[k].Amplitude;
+            component.Phase     = state->SumPhase[k];
+
+            /* Compute phasor component to cartesian complex number and storage it into FFTbuffer*/
+            state->FFTbuffer[k] = polar2rect(component);
+        }
+        /* zero negative frequencies for recontruct a real signal */
+        for(k = STFT_HALF_SIZE+1;k < STFT_SIZE;k++)
+        {
+            state->FFTbuffer[k].Real = 0.0f;
+            state->FFTbuffer[k].Imag = 0.0f;
+        }
+
+        /* Apply iFFT to buffer data */
+        FFT(state->FFTbuffer, STFT_SIZE, 1.0f);
+
+        /* Windowing and add to output */
+        for(k = 0;k < STFT_SIZE;k++)
+            state->OutputAccum[k] += HannWindow[k] * state->FFTbuffer[k].Real /
+                                     (0.5f * STFT_HALF_SIZE * OVERSAMP);
+
+        /* Shift accumulator, input & output FIFO */
+        for(k = 0;k < STFT_STEP;k++) state->OutFIFO[k] = state->OutputAccum[k];
+        for(j = 0;k < STFT_SIZE;k++,j++) state->OutputAccum[j] = state->OutputAccum[k];
+        for(;j < STFT_SIZE;j++) state->OutputAccum[j] = 0.0f;
+        for(k = 0;k < FIFO_LATENCY;k++)
+            state->InFIFO[k] = state->InFIFO[k+STFT_STEP];
+    }
+    state->count = count;
+
+    /* Now, mix the processed sound data to the output. */
+    MixSamples(bufferOut, NumChannels, SamplesOut, state->CurrentGains, state->TargetGains,
+               maxi(SamplesToDo, 512), 0, SamplesToDo);
+}
+
+typedef struct PshifterStateFactory {
+    DERIVE_FROM_TYPE(EffectStateFactory);
+} PshifterStateFactory;
+
+static ALeffectState *PshifterStateFactory_create(PshifterStateFactory *UNUSED(factory))
+{
+    ALpshifterState *state;
+
+    NEW_OBJ0(state, ALpshifterState)();
+    if(!state) return NULL;
+
+    return STATIC_CAST(ALeffectState, state);
+}
+
+DEFINE_EFFECTSTATEFACTORY_VTABLE(PshifterStateFactory);
+
+EffectStateFactory *PshifterStateFactory_getFactory(void)
+{
+    static PshifterStateFactory PshifterFactory = { { GET_VTABLE2(PshifterStateFactory, EffectStateFactory) } };
+
+    return STATIC_CAST(EffectStateFactory, &PshifterFactory);
+}
+
+
+void ALpshifter_setParamf(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat UNUSED(val))
+{
+    alSetError( context, AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param );
+}
+
+void ALpshifter_setParamfv(ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, const ALfloat *UNUSED(vals))
+{
+    alSetError( context, AL_INVALID_ENUM, "Invalid pitch shifter float-vector property 0x%04x", param );
+}
+
+void ALpshifter_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
+{
+    ALeffectProps *props = &effect->Props;
+    switch(param)
+    {
+        case AL_PITCH_SHIFTER_COARSE_TUNE:
+            if(!(val >= AL_PITCH_SHIFTER_MIN_COARSE_TUNE && val <= AL_PITCH_SHIFTER_MAX_COARSE_TUNE))
+                SETERR_RETURN(context, AL_INVALID_VALUE,,"Pitch shifter coarse tune out of range");
+            props->Pshifter.CoarseTune = val;
+            break;
+
+        case AL_PITCH_SHIFTER_FINE_TUNE:
+            if(!(val >= AL_PITCH_SHIFTER_MIN_FINE_TUNE && val <= AL_PITCH_SHIFTER_MAX_FINE_TUNE))
+                SETERR_RETURN(context, AL_INVALID_VALUE,,"Pitch shifter fine tune out of range");
+            props->Pshifter.FineTune = val;
+            break;
+
+        default:
+            alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x", param);
+    }
+}
+void ALpshifter_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
+{
+    ALpshifter_setParami(effect, context, param, vals[0]);
+}
+
+void ALpshifter_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
+{
+    const ALeffectProps *props = &effect->Props;
+    switch(param)
+    {
+        case AL_PITCH_SHIFTER_COARSE_TUNE:
+            *val = (ALint)props->Pshifter.CoarseTune;
+            break;
+        case AL_PITCH_SHIFTER_FINE_TUNE:
+            *val = (ALint)props->Pshifter.FineTune;
+            break;
+
+        default:
+            alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x", param);
+    }
+}
+void ALpshifter_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
+{
+    ALpshifter_getParami(effect, context, param, vals);
+}
+
+void ALpshifter_getParamf(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat *UNUSED(val))
+{
+    alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param);
+}
+
+void ALpshifter_getParamfv(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum param, ALfloat *UNUSED(vals))
+{
+    alSetError(context, AL_INVALID_ENUM, "Invalid pitch shifter float vector-property 0x%04x", param);
+}
+
+DEFINE_ALEFFECT_VTABLE(ALpshifter);

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


+ 118 - 0
libs/openal-soft/Alc/filters/defs.h

@@ -0,0 +1,118 @@
+#ifndef ALC_FILTER_H
+#define ALC_FILTER_H
+
+#include "AL/al.h"
+#include "math_defs.h"
+
+/* 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 BiquadType {
+    /** EFX-style low-pass filter, specifying a gain and reference frequency. */
+    BiquadType_HighShelf,
+    /** EFX-style high-pass filter, specifying a gain and reference frequency. */
+    BiquadType_LowShelf,
+    /** Peaking filter, specifying a gain and reference frequency. */
+    BiquadType_Peaking,
+
+    /** Low-pass cut-off filter, specifying a cut-off frequency. */
+    BiquadType_LowPass,
+    /** High-pass cut-off filter, specifying a cut-off frequency. */
+    BiquadType_HighPass,
+    /** Band-pass filter, specifying a center frequency. */
+    BiquadType_BandPass,
+} BiquadType;
+
+typedef struct BiquadState {
+    ALfloat x[2]; /* History of two last input samples  */
+    ALfloat y[2]; /* History of two last output samples */
+    ALfloat b0, b1, b2; /* Transfer function coefficients "b" */
+    ALfloat a1, a2; /* Transfer function coefficients "a" (a0 is pre-applied) */
+} BiquadState;
+/* Currently only a C-based filter process method is implemented. */
+#define BiquadState_process BiquadState_processC
+
+/**
+ * Calculates the rcpQ (i.e. 1/Q) coefficient for shelving filters, using the
+ * reference gain and shelf slope parameter.
+ * \param gain 0 < gain
+ * \param slope 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 normalized
+ * reference frequency and bandwidth.
+ * \param f0norm 0 < f0norm < 0.5.
+ * \param bandwidth 0 < bandwidth
+ */
+inline ALfloat calc_rcpQ_from_bandwidth(ALfloat f0norm, ALfloat bandwidth)
+{
+    ALfloat w0 = F_TAU * f0norm;
+    return 2.0f*sinhf(logf(2.0f)/2.0f*bandwidth*w0/sinf(w0));
+}
+
+inline void BiquadState_clear(BiquadState *filter)
+{
+    filter->x[0] = 0.0f;
+    filter->x[1] = 0.0f;
+    filter->y[0] = 0.0f;
+    filter->y[1] = 0.0f;
+}
+
+/**
+ * Sets up the filter state for the specified filter type and its parameters.
+ *
+ * \param filter The filter object to prepare.
+ * \param type The type of filter for the object to apply.
+ * \param gain The gain for the reference frequency response. Only used by the
+ *             Shelf and Peaking filter types.
+ * \param f0norm The normalized reference frequency (ref_freq / sample_rate).
+ *               This is the center point for the Shelf, Peaking, and BandPass
+ *               filter types, or the cutoff frequency for the LowPass and
+ *               HighPass filter types.
+ * \param rcpQ The reciprocal of the Q coefficient for the filter's transition
+ *             band. Can be generated from calc_rcpQ_from_slope or
+ *             calc_rcpQ_from_bandwidth depending on the available data.
+ */
+void BiquadState_setParams(BiquadState *filter, BiquadType type, ALfloat gain, ALfloat f0norm, ALfloat rcpQ);
+
+inline void BiquadState_copyParams(BiquadState *restrict dst, const BiquadState *restrict src)
+{
+    dst->b0 = src->b0;
+    dst->b1 = src->b1;
+    dst->b2 = src->b2;
+    dst->a1 = src->a1;
+    dst->a2 = src->a2;
+}
+
+void BiquadState_processC(BiquadState *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALsizei numsamples);
+
+inline void BiquadState_processPassthru(BiquadState *filter, const ALfloat *restrict src, ALsizei 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];
+    }
+}
+
+#endif /* ALC_FILTER_H */

+ 133 - 0
libs/openal-soft/Alc/filters/filter.c

@@ -0,0 +1,133 @@
+
+#include "config.h"
+
+#include "AL/alc.h"
+#include "AL/al.h"
+
+#include "alMain.h"
+#include "defs.h"
+
+extern inline void BiquadState_clear(BiquadState *filter);
+extern inline void BiquadState_copyParams(BiquadState *restrict dst, const BiquadState *restrict src);
+extern inline void BiquadState_processPassthru(BiquadState *filter, const ALfloat *restrict src, ALsizei numsamples);
+extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope);
+extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat f0norm, ALfloat bandwidth);
+
+
+void BiquadState_setParams(BiquadState *filter, BiquadType type, ALfloat gain, ALfloat f0norm, ALfloat rcpQ)
+{
+    ALfloat alpha, sqrtgain_alpha_2;
+    ALfloat w0, sin_w0, cos_w0;
+    ALfloat a[3] = { 1.0f, 0.0f, 0.0f };
+    ALfloat b[3] = { 1.0f, 0.0f, 0.0f };
+
+    // Limit gain to -100dB
+    assert(gain > 0.00001f);
+
+    w0 = F_TAU * f0norm;
+    sin_w0 = sinf(w0);
+    cos_w0 = cosf(w0);
+    alpha = sin_w0/2.0f * rcpQ;
+
+    /* Calculate filter coefficients depending on filter type */
+    switch(type)
+    {
+        case BiquadType_HighShelf:
+            sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
+            b[0] =       gain*((gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
+            b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cos_w0                   );
+            b[2] =       gain*((gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
+            a[0] =             (gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2;
+            a[1] =  2.0f*     ((gain-1.0f) - (gain+1.0f)*cos_w0                   );
+            a[2] =             (gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
+            break;
+        case BiquadType_LowShelf:
+            sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
+            b[0] =       gain*((gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
+            b[1] =  2.0f*gain*((gain-1.0f) - (gain+1.0f)*cos_w0                   );
+            b[2] =       gain*((gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
+            a[0] =             (gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2;
+            a[1] = -2.0f*     ((gain-1.0f) + (gain+1.0f)*cos_w0                   );
+            a[2] =             (gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
+            break;
+        case BiquadType_Peaking:
+            gain = sqrtf(gain);
+            b[0] =  1.0f + alpha * gain;
+            b[1] = -2.0f * cos_w0;
+            b[2] =  1.0f - alpha * gain;
+            a[0] =  1.0f + alpha / gain;
+            a[1] = -2.0f * cos_w0;
+            a[2] =  1.0f - alpha / gain;
+            break;
+
+        case BiquadType_LowPass:
+            b[0] = (1.0f - cos_w0) / 2.0f;
+            b[1] =  1.0f - cos_w0;
+            b[2] = (1.0f - cos_w0) / 2.0f;
+            a[0] =  1.0f + alpha;
+            a[1] = -2.0f * cos_w0;
+            a[2] =  1.0f - alpha;
+            break;
+        case BiquadType_HighPass:
+            b[0] =  (1.0f + cos_w0) / 2.0f;
+            b[1] = -(1.0f + cos_w0);
+            b[2] =  (1.0f + cos_w0) / 2.0f;
+            a[0] =   1.0f + alpha;
+            a[1] =  -2.0f * cos_w0;
+            a[2] =   1.0f - alpha;
+            break;
+        case BiquadType_BandPass:
+            b[0] =  alpha;
+            b[1] =  0;
+            b[2] = -alpha;
+            a[0] =  1.0f + alpha;
+            a[1] = -2.0f * cos_w0;
+            a[2] =  1.0f - alpha;
+            break;
+    }
+
+    filter->a1 = a[1] / a[0];
+    filter->a2 = a[2] / a[0];
+    filter->b0 = b[0] / a[0];
+    filter->b1 = b[1] / a[0];
+    filter->b2 = b[2] / a[0];
+}
+
+
+void BiquadState_processC(BiquadState *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALsizei numsamples)
+{
+    ALsizei i;
+    if(LIKELY(numsamples > 1))
+    {
+        ALfloat x0 = filter->x[0];
+        ALfloat x1 = filter->x[1];
+        ALfloat y0 = filter->y[0];
+        ALfloat y1 = filter->y[1];
+
+        for(i = 0;i < numsamples;i++)
+        {
+            dst[i] = filter->b0* src[i] +
+                     filter->b1*x0 + filter->b2*x1 -
+                     filter->a1*y0 - filter->a2*y1;
+            y1 = y0; y0 = dst[i];
+            x1 = x0; x0 = src[i];
+        }
+
+        filter->x[0] = x0;
+        filter->x[1] = x1;
+        filter->y[0] = y0;
+        filter->y[1] = y1;
+    }
+    else if(numsamples == 1)
+    {
+        dst[0] = filter->b0 * src[0] +
+                 filter->b1 * filter->x[0] +
+                 filter->b2 * filter->x[1] -
+                 filter->a1 * filter->y[0] -
+                 filter->a2 * filter->y[1];
+        filter->x[1] = filter->x[0];
+        filter->x[0] = src[0];
+        filter->y[1] = filter->y[0];
+        filter->y[0] = dst[0];
+    }
+}

+ 89 - 79
libs/openal-soft/Alc/nfcfilter.c → libs/openal-soft/Alc/filters/nfc.c

@@ -1,9 +1,9 @@
 
 #include "config.h"
 
-#include "nfcfilter.h"
+#include "nfc.h"
 
-#include "alu.h"
+#include <string.h>
 
 
 /* Near-field control filters are the basis for handling the near-field effect.
@@ -52,13 +52,11 @@ static const float B[4][3] = {
   /*{ 4.2076f, 11.4877f, 5.7924f, 9.1401f }*/
 };
 
-void NfcFilterCreate1(NfcFilter *nfc, const float w0, const float w1)
+static void NfcFilterCreate1(struct NfcFilter1 *nfc, const float w0, const float w1)
 {
     float b_00, g_0;
     float r;
 
-    memset(nfc, 0, sizeof(*nfc));
-
     nfc->g = 1.0f;
     nfc->coeffs[0] = 1.0f;
 
@@ -80,7 +78,7 @@ void NfcFilterCreate1(NfcFilter *nfc, const float w0, const float w1)
     nfc->coeffs[1+1] = (2.0f * b_00) / g_0;
 }
 
-void NfcFilterAdjust1(NfcFilter *nfc, const float w0)
+static void NfcFilterAdjust1(struct NfcFilter1 *nfc, const float w0)
 {
     float b_00, g_0;
     float r;
@@ -93,36 +91,12 @@ void NfcFilterAdjust1(NfcFilter *nfc, const float w0)
     nfc->coeffs[1] = (2.0f * b_00) / g_0;
 }
 
-void NfcFilterUpdate1(NfcFilter *nfc, ALfloat *restrict dst, const float *restrict src, const int count)
-{
-    const float b0 = nfc->coeffs[0];
-    const float a0 = nfc->coeffs[1];
-    const float a1 = nfc->coeffs[2];
-    float z1 = nfc->history[0];
-    int i;
 
-    for(i = 0;i < count;i++)
-    {
-        float out = src[i] * b0;
-        float y;
-
-        y = out - (a1*z1);
-        out = y + (a0*z1);
-        z1 += y;
-
-        dst[i] = out;
-    }
-    nfc->history[0] = z1;
-}
-
-
-void NfcFilterCreate2(NfcFilter *nfc, const float w0, const float w1)
+static void NfcFilterCreate2(struct NfcFilter2 *nfc, const float w0, const float w1)
 {
     float b_10, b_11, g_1;
     float r;
 
-    memset(nfc, 0, sizeof(*nfc));
-
     nfc->g = 1.0f;
     nfc->coeffs[0] = 1.0f;
 
@@ -148,7 +122,7 @@ void NfcFilterCreate2(NfcFilter *nfc, const float w0, const float w1)
     nfc->coeffs[2+2] = (4.0f * b_11) / g_1;
 }
 
-void NfcFilterAdjust2(NfcFilter *nfc, const float w0)
+static void NfcFilterAdjust2(struct NfcFilter2 *nfc, const float w0)
 {
     float b_10, b_11, g_1;
     float r;
@@ -163,42 +137,13 @@ void NfcFilterAdjust2(NfcFilter *nfc, const float w0)
     nfc->coeffs[2] = (4.0f * b_11) / g_1;
 }
 
-void NfcFilterUpdate2(NfcFilter *nfc, ALfloat *restrict dst, const float *restrict src, const int count)
-{
-    const float b0 = nfc->coeffs[0];
-    const float a00 = nfc->coeffs[1];
-    const float a01 = nfc->coeffs[2];
-    const float a10 = nfc->coeffs[3];
-    const float a11 = nfc->coeffs[4];
-    float z1 = nfc->history[0];
-    float z2 = nfc->history[1];
-    int i;
-
-    for(i = 0;i < count;i++)
-    {
-        float out = src[i] * b0;
-        float y;
-
-        y = out - (a10*z1) - (a11*z2);
-        out = y + (a00*z1) + (a01*z2);
-        z2 += z1;
-        z1 += y;
-
-        dst[i] = out;
-    }
-    nfc->history[0] = z1;
-    nfc->history[1] = z2;
-}
 
-
-void NfcFilterCreate3(NfcFilter *nfc, const float w0, const float w1)
+static void NfcFilterCreate3(struct NfcFilter3 *nfc, const float w0, const float w1)
 {
     float b_10, b_11, g_1;
     float b_00, g_0;
     float r;
 
-    memset(nfc, 0, sizeof(*nfc));
-
     nfc->g = 1.0f;
     nfc->coeffs[0] = 1.0f;
 
@@ -237,7 +182,7 @@ void NfcFilterCreate3(NfcFilter *nfc, const float w0, const float w1)
     nfc->coeffs[3+2+1] = (2.0f * b_00) / g_0;
 }
 
-void NfcFilterAdjust3(NfcFilter *nfc, const float w0)
+static void NfcFilterAdjust3(struct NfcFilter3 *nfc, const float w0)
 {
     float b_10, b_11, g_1;
     float b_00, g_0;
@@ -259,18 +204,84 @@ void NfcFilterAdjust3(NfcFilter *nfc, const float w0)
     nfc->coeffs[2+1] = (2.0f * b_00) / g_0;
 }
 
-void NfcFilterUpdate3(NfcFilter *nfc, ALfloat *restrict dst, const float *restrict src, const int count)
+
+void NfcFilterCreate(NfcFilter *nfc, const float w0, const float w1)
+{
+    memset(nfc, 0, sizeof(*nfc));
+    NfcFilterCreate1(&nfc->first, w0, w1);
+    NfcFilterCreate2(&nfc->second, w0, w1);
+    NfcFilterCreate3(&nfc->third, w0, w1);
+}
+
+void NfcFilterAdjust(NfcFilter *nfc, const float w0)
 {
-    const float b0 = nfc->coeffs[0];
-    const float a00 = nfc->coeffs[1];
-    const float a01 = nfc->coeffs[2];
-    const float a02 = nfc->coeffs[3];
-    const float a10 = nfc->coeffs[4];
-    const float a11 = nfc->coeffs[5];
-    const float a12 = nfc->coeffs[6];
-    float z1 = nfc->history[0];
-    float z2 = nfc->history[1];
-    float z3 = nfc->history[2];
+    NfcFilterAdjust1(&nfc->first, w0);
+    NfcFilterAdjust2(&nfc->second, w0);
+    NfcFilterAdjust3(&nfc->third, w0);
+}
+
+
+void NfcFilterProcess1(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count)
+{
+    const float b0 = nfc->first.coeffs[0];
+    const float a0 = nfc->first.coeffs[1];
+    const float a1 = nfc->first.coeffs[2];
+    float z1 = nfc->first.history[0];
+    int i;
+
+    for(i = 0;i < count;i++)
+    {
+        float out = src[i] * b0;
+        float y;
+
+        y = out - (a1*z1);
+        out = y + (a0*z1);
+        z1 += y;
+
+        dst[i] = out;
+    }
+    nfc->first.history[0] = z1;
+}
+
+void NfcFilterProcess2(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count)
+{
+    const float b0 = nfc->second.coeffs[0];
+    const float a00 = nfc->second.coeffs[1];
+    const float a01 = nfc->second.coeffs[2];
+    const float a10 = nfc->second.coeffs[3];
+    const float a11 = nfc->second.coeffs[4];
+    float z1 = nfc->second.history[0];
+    float z2 = nfc->second.history[1];
+    int i;
+
+    for(i = 0;i < count;i++)
+    {
+        float out = src[i] * b0;
+        float y;
+
+        y = out - (a10*z1) - (a11*z2);
+        out = y + (a00*z1) + (a01*z2);
+        z2 += z1;
+        z1 += y;
+
+        dst[i] = out;
+    }
+    nfc->second.history[0] = z1;
+    nfc->second.history[1] = z2;
+}
+
+void NfcFilterProcess3(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count)
+{
+    const float b0 = nfc->third.coeffs[0];
+    const float a00 = nfc->third.coeffs[1];
+    const float a01 = nfc->third.coeffs[2];
+    const float a02 = nfc->third.coeffs[3];
+    const float a10 = nfc->third.coeffs[4];
+    const float a11 = nfc->third.coeffs[5];
+    const float a12 = nfc->third.coeffs[6];
+    float z1 = nfc->third.history[0];
+    float z2 = nfc->third.history[1];
+    float z3 = nfc->third.history[2];
     int i;
 
     for(i = 0;i < count;i++)
@@ -289,12 +300,11 @@ void NfcFilterUpdate3(NfcFilter *nfc, ALfloat *restrict dst, const float *restri
 
         dst[i] = out;
     }
-    nfc->history[0] = z1;
-    nfc->history[1] = z2;
-    nfc->history[2] = z3;
+    nfc->third.history[0] = z1;
+    nfc->third.history[1] = z2;
+    nfc->third.history[2] = z3;
 }
 
-
 #if 0 /* Original methods the above are derived from. */
 static void NfcFilterCreate(NfcFilter *nfc, const ALsizei order, const float src_dist, const float ctl_dist, const float rate)
 {
@@ -391,7 +401,7 @@ static void NfcFilterAdjust(NfcFilter *nfc, const float distance)
     }
 }
 
-static float NfcFilterUpdate(const float in, NfcFilter *nfc)
+static float NfcFilterProcess(const float in, NfcFilter *nfc)
 {
     int i;
     float out = in * nfc->coeffs[0];

+ 49 - 0
libs/openal-soft/Alc/filters/nfc.h

@@ -0,0 +1,49 @@
+#ifndef FILTER_NFC_H
+#define FILTER_NFC_H
+
+struct NfcFilter1 {
+    float g;
+    float coeffs[1*2 + 1];
+    float history[1];
+};
+struct NfcFilter2 {
+    float g;
+    float coeffs[2*2 + 1];
+    float history[2];
+};
+struct NfcFilter3 {
+    float g;
+    float coeffs[3*2 + 1];
+    float history[3];
+};
+
+typedef struct NfcFilter {
+    struct NfcFilter1 first;
+    struct NfcFilter2 second;
+    struct NfcFilter3 third;
+} NfcFilter;
+
+
+/* NOTE:
+ * w0 = speed_of_sound / (source_distance * sample_rate);
+ * w1 = speed_of_sound / (control_distance * sample_rate);
+ *
+ * Generally speaking, the control distance should be approximately the average
+ * speaker distance, or based on the reference delay if outputing NFC-HOA. It
+ * must not be negative, 0, or infinite. The source distance should not be too
+ * small relative to the control distance.
+ */
+
+void NfcFilterCreate(NfcFilter *nfc, const float w0, const float w1);
+void NfcFilterAdjust(NfcFilter *nfc, const float w0);
+
+/* Near-field control filter for first-order ambisonic channels (1-3). */
+void NfcFilterProcess1(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
+
+/* Near-field control filter for second-order ambisonic channels (4-8). */
+void NfcFilterProcess2(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
+
+/* Near-field control filter for third-order ambisonic channels (9-15). */
+void NfcFilterProcess3(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
+
+#endif /* FILTER_NFC_H */

+ 37 - 0
libs/openal-soft/Alc/fpu_modes.h

@@ -0,0 +1,37 @@
+#ifndef FPU_MODES_H
+#define FPU_MODES_H
+
+#ifdef HAVE_FENV_H
+#include <fenv.h>
+#endif
+
+
+typedef struct FPUCtl {
+#ifdef HAVE_FENV_H
+    fenv_t flt_env;
+#ifdef _WIN32
+    int round_mode;
+#endif
+#else
+    int state;
+#endif
+#ifdef HAVE_SSE
+    int sse_state;
+#endif
+} FPUCtl;
+void SetMixerFPUMode(FPUCtl *ctl);
+void RestoreFPUMode(const FPUCtl *ctl);
+
+#ifdef __GNUC__
+/* Use an alternate macro set with GCC to avoid accidental continue or break
+ * statements within the mixer mode.
+ */
+#define START_MIXER_MODE() __extension__({ FPUCtl _oldMode; SetMixerFPUMode(&_oldMode)
+#define END_MIXER_MODE() RestoreFPUMode(&_oldMode); })
+#else
+#define START_MIXER_MODE() do { FPUCtl _oldMode; SetMixerFPUMode(&_oldMode)
+#define END_MIXER_MODE() RestoreFPUMode(&_oldMode); } while(0)
+#endif
+#define LEAVE_MIXER_MODE() RestoreFPUMode(&_oldMode)
+
+#endif /* FPU_MODES_H */

+ 157 - 69
libs/openal-soft/Alc/helpers.c

@@ -39,6 +39,9 @@
 #ifdef HAVE_DIRENT_H
 #include <dirent.h>
 #endif
+#ifdef HAVE_PROC_PIDPATH
+#include <libproc.h>
+#endif
 
 #ifdef __FreeBSD__
 #include <sys/types.h>
@@ -66,7 +69,7 @@ DEFINE_GUID(IID_IAudioClient,         0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc
 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_WASAPI
 #include <wtypes.h>
 #include <devpropdef.h>
 #include <propkeydef.h>
@@ -108,6 +111,8 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x
 
 #include "alMain.h"
 #include "alu.h"
+#include "cpu_caps.h"
+#include "fpu_modes.h"
 #include "atomic.h"
 #include "uintmap.h"
 #include "vector.h"
@@ -118,18 +123,24 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x
 
 extern inline ALuint NextPowerOf2(ALuint value);
 extern inline size_t RoundUp(size_t value, size_t r);
-extern inline ALuint64 ScaleRound(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale);
-extern inline ALuint64 ScaleFloor(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale);
-extern inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale);
 extern inline ALint fastf2i(ALfloat f);
+#ifndef __GNUC__
+#if defined(HAVE_BITSCANFORWARD64_INTRINSIC)
+extern inline int msvc64_ctz64(ALuint64 v);
+#elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
+extern inline int msvc_ctz64(ALuint64 v);
+#else
+extern inline int fallback_popcnt64(ALuint64 v);
+extern inline int fallback_ctz64(ALuint64 value);
+#endif
+#endif
 
 
-ALuint CPUCapFlags = 0;
-
+int CPUCapFlags = 0;
 
-void FillCPUCaps(ALuint capfilter)
+void FillCPUCaps(int capfilter)
 {
-    ALuint caps = 0;
+    int caps = 0;
 
 /* FIXME: We really should get this for all available CPUs in case different
  * CPUs have different caps (is that possible on one machine?). */
@@ -295,7 +306,7 @@ void FillCPUCaps(ALuint capfilter)
 void SetMixerFPUMode(FPUCtl *ctl)
 {
 #ifdef HAVE_FENV_H
-    fegetenv(STATIC_CAST(fenv_t, ctl));
+    fegetenv(&ctl->flt_env);
 #ifdef _WIN32
     /* HACK: A nasty bug in MinGW-W64 causes fegetenv and fesetenv to not save
      * and restore the FPU rounding mode, so we have to do it manually. Don't
@@ -348,7 +359,7 @@ void SetMixerFPUMode(FPUCtl *ctl)
 void RestoreFPUMode(const FPUCtl *ctl)
 {
 #ifdef HAVE_FENV_H
-    fesetenv(STATIC_CAST(fenv_t, ctl));
+    fesetenv(&ctl->flt_env);
 #ifdef _WIN32
     fesetround(ctl->round_mode);
 #endif
@@ -392,9 +403,8 @@ static WCHAR *strrchrW(WCHAR *str, WCHAR ch)
     return ret;
 }
 
-al_string GetProcPath(void)
+void GetProcBinary(al_string *path, al_string *fname)
 {
-    al_string ret = AL_STRING_INIT_STATIC();
     WCHAR *pathname, *sep;
     DWORD pathlen;
     DWORD len;
@@ -411,23 +421,34 @@ al_string GetProcPath(void)
     {
         free(pathname);
         ERR("Failed to get process name: error %lu\n", GetLastError());
-        return ret;
+        return;
     }
 
     pathname[len] = 0;
-    if((sep = strrchrW(pathname, '\\')))
+    if((sep=strrchrW(pathname, '\\')) != NULL)
     {
-        WCHAR *sep2 = strrchrW(pathname, '/');
-        if(sep2) *sep2 = 0;
-        else *sep = 0;
+        WCHAR *sep2 = strrchrW(sep+1, '/');
+        if(sep2) sep = sep2;
+    }
+    else
+        sep = strrchrW(pathname, '/');
+
+    if(sep)
+    {
+        if(path) alstr_copy_wrange(path, pathname, sep);
+        if(fname) alstr_copy_wcstr(fname, sep+1);
+    }
+    else
+    {
+        if(path) alstr_clear(path);
+        if(fname) alstr_copy_wcstr(fname, pathname);
     }
-    else if((sep = strrchrW(pathname, '/')))
-        *sep = 0;
-    alstr_copy_wcstr(&ret, pathname);
     free(pathname);
 
-    TRACE("Got: %s\n", alstr_get_cstr(ret));
-    return ret;
+    if(path && fname)
+        TRACE("Got: %s, %s\n", alstr_get_cstr(*path), alstr_get_cstr(*fname));
+    else if(path) TRACE("Got path: %s\n", alstr_get_cstr(*path));
+    else if(fname) TRACE("Got filename: %s\n", alstr_get_cstr(*fname));
 }
 
 
@@ -634,7 +655,7 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir)
         /* Search the local and global data dirs. */
         for(i = 0;i < COUNTOF(ids);i++)
         {
-            WCHAR buffer[PATH_MAX];
+            WCHAR buffer[MAX_PATH];
             if(SHGetSpecialFolderPathW(NULL, buffer, ids[i], FALSE) != FALSE)
             {
                 alstr_copy_wcstr(&path, buffer);
@@ -721,64 +742,103 @@ void UnmapFileMem(const struct FileMapping *mapping)
 
 #else
 
-al_string GetProcPath(void)
+void GetProcBinary(al_string *path, al_string *fname)
 {
-    al_string ret = AL_STRING_INIT_STATIC();
-    char *pathname, *sep;
+    char *pathname = NULL;
     size_t pathlen;
 
 #ifdef __FreeBSD__
-    int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
-    mib[3] = getpid();
-    if (sysctl(mib, 4, NULL, &pathlen, NULL, 0) == -1) {
-        WARN("Failed to sysctl kern.proc.pathname.%d: %s\n", mib[3], strerror(errno));
-        return ret;
+    int mib[4] = { CTL_KERN, KERN_PROC_ARGS, getpid() };
+    if(sysctl(mib, 3, NULL, &pathlen, NULL, 0) == -1)
+        WARN("Failed to sysctl kern.procargs.%d: %s\n", mib[2], strerror(errno));
+    else
+    {
+        pathname = malloc(pathlen + 1);
+        sysctl(mib, 3, (void*)pathname, &pathlen, NULL, 0);
+        pathname[pathlen] = 0;
     }
+#endif
+#ifdef HAVE_PROC_PIDPATH
+    if(!pathname)
+    {
+        const pid_t pid = getpid();
+        char procpath[PROC_PIDPATHINFO_MAXSIZE];
+        int ret;
 
-    pathname = malloc(pathlen + 1);
-    sysctl(mib, 4, (void*)pathname, &pathlen, NULL, 0);
-    pathname[pathlen] = 0;
-#else
-    const char *fname;
-    ssize_t len;
+        ret = proc_pidpath(pid, procpath, sizeof(procpath));
+        if(ret < 1)
+        {
+            WARN("proc_pidpath(%d, ...) failed: %s\n", pid, strerror(errno));
+            free(pathname);
+            pathname = NULL;
+        }
+        else
+        {
+            pathlen = strlen(procpath);
+            pathname = strdup(procpath);
+        }
+    }
+#endif
+    if(!pathname)
+    {
+        const char *selfname;
+        ssize_t len;
 
-    pathlen = 256;
-    pathname = malloc(pathlen);
+        pathlen = 256;
+        pathname = malloc(pathlen);
 
-    fname = "/proc/self/exe";
-    len = readlink(fname, pathname, pathlen);
-    if(len == -1 && errno == ENOENT)
-    {
-        fname = "/proc/self/file";
-        len = readlink(fname, pathname, pathlen);
+        selfname = "/proc/self/exe";
+        len = readlink(selfname, pathname, pathlen);
+        if(len == -1 && errno == ENOENT)
+        {
+            selfname = "/proc/self/file";
+            len = readlink(selfname, pathname, pathlen);
+        }
+        if(len == -1 && errno == ENOENT)
+        {
+            selfname = "/proc/curproc/exe";
+            len = readlink(selfname, pathname, pathlen);
+        }
+        if(len == -1 && errno == ENOENT)
+        {
+            selfname = "/proc/curproc/file";
+            len = readlink(selfname, pathname, pathlen);
+        }
+
+        while(len > 0 && (size_t)len == pathlen)
+        {
+            free(pathname);
+            pathlen <<= 1;
+            pathname = malloc(pathlen);
+            len = readlink(selfname, pathname, pathlen);
+        }
+        if(len <= 0)
+        {
+            free(pathname);
+            WARN("Failed to readlink %s: %s\n", selfname, strerror(errno));
+            return;
+        }
+
+        pathname[len] = 0;
     }
 
-    while(len > 0 && (size_t)len == pathlen)
+    char *sep = strrchr(pathname, '/');
+    if(sep)
     {
-        free(pathname);
-        pathlen <<= 1;
-        pathname = malloc(pathlen);
-        len = readlink(fname, pathname, pathlen);
+        if(path) alstr_copy_range(path, pathname, sep);
+        if(fname) alstr_copy_cstr(fname, sep+1);
     }
-    if(len <= 0)
+    else
     {
-        free(pathname);
-        WARN("Failed to readlink %s: %s\n", fname, strerror(errno));
-        return ret;
+        if(path) alstr_clear(path);
+        if(fname) alstr_copy_cstr(fname, pathname);
     }
-
-    pathname[len] = 0;
-#endif
-
-    sep = strrchr(pathname, '/');
-    if(sep)
-        alstr_copy_range(&ret, pathname, sep);
-    else
-        alstr_copy_cstr(&ret, pathname);
     free(pathname);
 
-    TRACE("Got: %s\n", alstr_get_cstr(ret));
-    return ret;
+    if(path && fname)
+        TRACE("Got: %s, %s\n", alstr_get_cstr(*path), alstr_get_cstr(*fname));
+    else if(path) TRACE("Got path: %s\n", alstr_get_cstr(*path));
+    else if(fname) TRACE("Got filename: %s\n", alstr_get_cstr(*fname));
 }
 
 
@@ -881,15 +941,32 @@ vector_al_string SearchDataFiles(const char *ext, const char *subdir)
     {
         al_string path = AL_STRING_INIT_STATIC();
         const char *str, *next;
-        char cwdbuf[PATH_MAX];
 
         /* Search the app-local directory. */
         if((str=getenv("ALSOFT_LOCAL_PATH")) && *str != '\0')
             DirectorySearch(str, ext, &results);
-        else if(getcwd(cwdbuf, sizeof(cwdbuf)))
-            DirectorySearch(cwdbuf, ext, &results);
         else
-            DirectorySearch(".", ext, &results);
+        {
+            size_t cwdlen = 256;
+            char *cwdbuf = malloc(cwdlen);
+            while(!getcwd(cwdbuf, cwdlen))
+            {
+                free(cwdbuf);
+                cwdbuf = NULL;
+                if(errno != ERANGE)
+                    break;
+                cwdlen <<= 1;
+                cwdbuf = malloc(cwdlen);
+            }
+            if(!cwdbuf)
+                DirectorySearch(".", ext, &results);
+            else
+            {
+                DirectorySearch(cwdbuf, ext, &results);
+                free(cwdbuf);
+                cwdbuf = NULL;
+            }
+        }
 
         // Search local data dir
         if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0')
@@ -1151,6 +1228,17 @@ void alstr_append_wcstr(al_string *str, const wchar_t *from)
     }
 }
 
+void alstr_copy_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)
+    {
+        VECTOR_RESIZE(*str, len, len+1);
+        WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), &VECTOR_FRONT(*str), len+1, NULL, NULL);
+        VECTOR_ELEM(*str, len) = 0;
+    }
+}
+
 void alstr_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to)
 {
     int len;

+ 334 - 43
libs/openal-soft/Alc/hrtf.c

@@ -30,6 +30,7 @@
 #include "alu.h"
 #include "bformatdec.h"
 #include "hrtf.h"
+#include "alconfig.h"
 
 #include "compat.h"
 #include "almalloc.h"
@@ -40,12 +41,20 @@
 #define MAX_IR_SIZE                  (512)
 #define MOD_IR_SIZE                  (8)
 
+#define MIN_FD_COUNT                 (1)
+#define MAX_FD_COUNT                 (16)
+
+#define MIN_FD_DISTANCE              (50)
+#define MAX_FD_DISTANCE              (2500)
+
 #define MIN_EV_COUNT                 (5)
 #define MAX_EV_COUNT                 (128)
 
 #define MIN_AZ_COUNT                 (1)
 #define MAX_AZ_COUNT                 (128)
 
+#define MAX_HRIR_DELAY               (HRTF_HISTORY_LENGTH-1)
+
 struct HrtfEntry {
     struct HrtfEntry *next;
     struct Hrtf *handle;
@@ -54,6 +63,7 @@ struct HrtfEntry {
 
 static const ALchar magicMarker00[8] = "MinPHR00";
 static const ALchar magicMarker01[8] = "MinPHR01";
+static const ALchar magicMarker02[8] = "MinPHR02";
 
 /* First value for pass-through coefficients (remaining are 0), used for omni-
  * directional sounds. */
@@ -94,7 +104,8 @@ static ALsizei CalcAzIndex(ALsizei azcount, ALfloat az, ALfloat *mu)
 /* Calculates static HRIR coefficients and delays for the given polar elevation
  * and azimuth in radians. The coefficients are normalized.
  */
-void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat (*coeffs)[2], ALsizei *delays)
+void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread,
+                   ALfloat (*restrict coeffs)[2], ALsizei *delays)
 {
     ALsizei evidx, azidx, idx[4];
     ALsizei evoffset;
@@ -162,6 +173,7 @@ void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth,
     idx[2] *= Hrtf->irSize;
     idx[3] *= Hrtf->irSize;
 
+    coeffs = ASSUME_ALIGNED(coeffs, 16);
     /* Calculate the blended HRIR coefficients. */
     coeffs[0][0] = PassthruCoeff * (1.0f-dirfact);
     coeffs[0][1] = PassthruCoeff * (1.0f-dirfact);
@@ -172,16 +184,17 @@ void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth,
     }
     for(c = 0;c < 4;c++)
     {
+        const ALfloat (*restrict srccoeffs)[2] = ASSUME_ALIGNED(Hrtf->coeffs+idx[c], 16);
         for(i = 0;i < Hrtf->irSize;i++)
         {
-            coeffs[i][0] += Hrtf->coeffs[idx[c]+i][0] * blend[c];
-            coeffs[i][1] += Hrtf->coeffs[idx[c]+i][1] * blend[c];
+            coeffs[i][0] += srccoeffs[i][0] * blend[c];
+            coeffs[i][1] += srccoeffs[i][1] * blend[c];
         }
     }
 }
 
 
-ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const ALfloat (*restrict AmbiPoints)[2], const ALfloat (*restrict AmbiMatrix)[2][MAX_AMBI_COEFFS], ALsizei AmbiCount)
+void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const struct AngularPoint *AmbiPoints, const ALfloat (*restrict AmbiMatrix)[MAX_AMBI_COEFFS], ALsizei AmbiCount, const ALfloat *restrict AmbiOrderHFGain)
 {
 /* Set this to 2 for dual-band HRTF processing. May require a higher quality
  * band-splitter, or better calculation of the new IR length to deal with the
@@ -191,6 +204,7 @@ ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsize
     BandSplitter splitter;
     ALsizei idx[HRTF_AMBI_MAX_CHANNELS];
     ALsizei min_delay = HRTF_HISTORY_LENGTH;
+    ALsizei max_delay = 0;
     ALfloat temps[3][HRIR_LENGTH];
     ALsizei max_length = 0;
     ALsizei i, c, b;
@@ -202,21 +216,19 @@ ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsize
         ALuint azcount;
 
         /* Calculate elevation index. */
-        evidx = (ALsizei)floorf((F_PI_2 + AmbiPoints[c][0]) *
+        evidx = (ALsizei)floorf((F_PI_2 + AmbiPoints[c].Elev) *
                                 (Hrtf->evCount-1)/F_PI + 0.5f);
-        evidx = mini(evidx, Hrtf->evCount-1);
+        evidx = clampi(evidx, 0, Hrtf->evCount-1);
 
         azcount = Hrtf->azCount[evidx];
         evoffset = Hrtf->evOffset[evidx];
 
         /* Calculate azimuth index for this elevation. */
-        azidx = (ALsizei)floorf((F_TAU+AmbiPoints[c][1]) *
+        azidx = (ALsizei)floorf((F_TAU+AmbiPoints[c].Azim) *
                                 azcount/F_TAU + 0.5f) % azcount;
 
         /* Calculate indices for left and right channels. */
         idx[c] = evoffset + azidx;
-
-        min_delay = mini(min_delay, mini(Hrtf->delays[idx[c]][0], Hrtf->delays[idx[c]][1]));
     }
 
     memset(temps, 0, sizeof(temps));
@@ -224,8 +236,12 @@ ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsize
     for(c = 0;c < AmbiCount;c++)
     {
         const ALfloat (*fir)[2] = &Hrtf->coeffs[idx[c] * Hrtf->irSize];
-        ALsizei ldelay = Hrtf->delays[idx[c]][0] - min_delay;
-        ALsizei rdelay = Hrtf->delays[idx[c]][1] - min_delay;
+        const ALsizei res_delay = mini(Hrtf->delays[idx[c]][0], Hrtf->delays[idx[c]][1]);
+        ALsizei ldelay = Hrtf->delays[idx[c]][0] - res_delay;
+        ALsizei rdelay = Hrtf->delays[idx[c]][1] - res_delay;
+
+        min_delay = mini(min_delay, res_delay);
+        max_delay = maxi(max_delay, res_delay);
 
         max_length = maxi(max_length,
             mini(maxi(ldelay, rdelay) + Hrtf->irSize, HRIR_LENGTH)
@@ -235,12 +251,13 @@ ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsize
         {
             for(i = 0;i < NumChannels;++i)
             {
+                ALfloat hfgain = AmbiOrderHFGain[(ALsizei)floor(sqrt(i))];
                 ALsizei lidx = ldelay, ridx = rdelay;
                 ALsizei j = 0;
                 while(lidx < HRIR_LENGTH && ridx < HRIR_LENGTH && j < Hrtf->irSize)
                 {
-                    state->Chan[i].Coeffs[lidx++][0] += fir[j][0] * AmbiMatrix[c][0][i];
-                    state->Chan[i].Coeffs[ridx++][1] += fir[j][1] * AmbiMatrix[c][0][i];
+                    state->Chan[i].Coeffs[lidx++][0] += fir[j][0] * AmbiMatrix[c][i] * hfgain;
+                    state->Chan[i].Coeffs[ridx++][1] += fir[j][1] * AmbiMatrix[c][i] * hfgain;
                     j++;
                 }
             }
@@ -256,12 +273,15 @@ ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsize
             /* Apply left ear response with delay. */
             for(i = 0;i < NumChannels;++i)
             {
+                ALfloat hfgain = AmbiOrderHFGain[(ALsizei)floor(sqrt(i))];
                 for(b = 0;b < NUM_BANDS;b++)
                 {
                     ALsizei lidx = ldelay;
                     ALsizei j = 0;
                     while(lidx < HRIR_LENGTH)
-                        state->Chan[i].Coeffs[lidx++][0] += temps[b][j++] * AmbiMatrix[c][b][i];
+                        state->Chan[i].Coeffs[lidx++][0] += temps[b][j++] * AmbiMatrix[c][i] *
+                                                            hfgain;
+                    hfgain = 1.0f;
                 }
             }
 
@@ -274,29 +294,34 @@ ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsize
             /* Apply right ear response with delay. */
             for(i = 0;i < NumChannels;++i)
             {
+                ALfloat hfgain = AmbiOrderHFGain[(ALsizei)floor(sqrt(i))];
                 for(b = 0;b < NUM_BANDS;b++)
                 {
                     ALsizei ridx = rdelay;
                     ALsizei j = 0;
                     while(ridx < HRIR_LENGTH)
-                        state->Chan[i].Coeffs[ridx++][1] += temps[b][j++] * AmbiMatrix[c][b][i];
+                        state->Chan[i].Coeffs[ridx++][1] += temps[b][j++] * AmbiMatrix[c][i] *
+                                                            hfgain;
+                    hfgain = 1.0f;
                 }
             }
         }
     }
     /* Round up to the next IR size multiple. */
-    max_length = RoundUp(max_length, MOD_IR_SIZE);
+    max_length += MOD_IR_SIZE-1;
+    max_length -= max_length%MOD_IR_SIZE;
 
-    TRACE("Skipped min delay: %d, new combined length: %d\n", min_delay, max_length);
-    return max_length;
+    TRACE("Skipped delay min: %d, max: %d, new FIR length: %d\n", min_delay, max_delay,
+          max_length);
+    state->IrSize = max_length;
 #undef NUM_BANDS
 }
 
 
-static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount, ALsizei irCount,
-                                    const ALubyte *azCount, const ALushort *evOffset,
-                                    const ALfloat (*coeffs)[2], const ALubyte (*delays)[2],
-                                    const char *filename)
+static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize,
+  ALfloat distance, ALsizei evCount, ALsizei irCount, const ALubyte *azCount,
+  const ALushort *evOffset, const ALfloat (*coeffs)[2], const ALubyte (*delays)[2],
+  const char *filename)
 {
     struct Hrtf *Hrtf;
     size_t total;
@@ -325,23 +350,26 @@ static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount
         InitRef(&Hrtf->ref, 0);
         Hrtf->sampleRate = rate;
         Hrtf->irSize = irSize;
+        Hrtf->distance = distance;
         Hrtf->evCount = evCount;
 
         /* Set up pointers to storage following the main HRTF struct. */
-        _azCount = (ALubyte*)(base + offset); Hrtf->azCount = _azCount;
+        _azCount = (ALubyte*)(base + offset);
         offset += sizeof(_azCount[0])*evCount;
 
         offset = RoundUp(offset, sizeof(ALushort)); /* Align for ushort fields */
-        _evOffset = (ALushort*)(base + offset); Hrtf->evOffset = _evOffset;
+        _evOffset = (ALushort*)(base + offset);
         offset += sizeof(_evOffset[0])*evCount;
 
         offset = RoundUp(offset, 16); /* Align for coefficients using SIMD */
-        _coeffs = (ALfloat(*)[2])(base + offset); Hrtf->coeffs = _coeffs;
+        _coeffs = (ALfloat(*)[2])(base + offset);
         offset += sizeof(_coeffs[0])*irSize*irCount;
 
-        _delays = (ALubyte(*)[2])(base + offset); Hrtf->delays = _delays;
+        _delays = (ALubyte(*)[2])(base + offset);
         offset += sizeof(_delays[0])*irCount;
 
+        assert(offset == total);
+
         /* Copy input data to storage. */
         for(i = 0;i < evCount;i++) _azCount[i] = azCount[i];
         for(i = 0;i < evCount;i++) _evOffset[i] = evOffset[i];
@@ -356,7 +384,11 @@ static struct Hrtf *CreateHrtfStore(ALuint rate, ALsizei irSize, ALsizei evCount
             _delays[i][1] = delays[i][1];
         }
 
-        assert(offset == total);
+        /* Finally, assign the storage pointers. */
+        Hrtf->azCount = _azCount;
+        Hrtf->evOffset = _evOffset;
+        Hrtf->coeffs = _coeffs;
+        Hrtf->delays = _delays;
     }
 
     return Hrtf;
@@ -383,9 +415,16 @@ static ALushort GetLE_ALushort(const ALubyte **data, size_t *len)
     return ret;
 }
 
-static ALint GetLE_ALuint(const ALubyte **data, size_t *len)
+static ALint GetLE_ALint24(const ALubyte **data, size_t *len)
+{
+    ALint ret = (*data)[0] | ((*data)[1]<<8) | ((*data)[2]<<16);
+    *data += 3; *len -= 3;
+    return (ret^0x800000) - 0x800000;
+}
+
+static ALuint GetLE_ALuint(const ALubyte **data, size_t *len)
 {
-    ALint ret = (*data)[0] | ((*data)[1]<<8) | ((*data)[2]<<16) | ((*data)[3]<<24);
+    ALuint ret = (*data)[0] | ((*data)[1]<<8) | ((*data)[2]<<16) | ((*data)[3]<<24);
     *data += 4; *len -= 4;
     return ret;
 }
@@ -399,7 +438,6 @@ static const ALubyte *Get_ALubytePtr(const ALubyte **data, size_t *len, size_t s
 
 static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const char *filename)
 {
-    const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
     struct Hrtf *Hrtf = NULL;
     ALboolean failed = AL_FALSE;
     ALuint rate = 0;
@@ -525,9 +563,9 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const char *
         for(i = 0;i < irCount;i++)
         {
             delays[i][0] = GetLE_ALubyte(&data, &datalen);
-            if(delays[i][0] > maxDelay)
+            if(delays[i][0] > MAX_HRIR_DELAY)
             {
-                ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i][0], maxDelay);
+                ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i][0], MAX_HRIR_DELAY);
                 failed = AL_TRUE;
             }
         }
@@ -552,7 +590,7 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const char *
             }
         }
 
-        Hrtf = CreateHrtfStore(rate, irSize, evCount, irCount, azCount,
+        Hrtf = CreateHrtfStore(rate, irSize, 0.0f, evCount, irCount, azCount,
                                evOffset, coeffs, delays, filename);
     }
 
@@ -565,7 +603,6 @@ static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const char *
 
 static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const char *filename)
 {
-    const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
     struct Hrtf *Hrtf = NULL;
     ALboolean failed = AL_FALSE;
     ALuint rate = 0;
@@ -674,9 +711,9 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const char *
         for(i = 0;i < irCount;i++)
         {
             delays[i][0] = GetLE_ALubyte(&data, &datalen);
-            if(delays[i][0] > maxDelay)
+            if(delays[i][0] > MAX_HRIR_DELAY)
             {
-                ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i][0], maxDelay);
+                ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i][0], MAX_HRIR_DELAY);
                 failed = AL_TRUE;
             }
         }
@@ -701,7 +738,7 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const char *
             }
         }
 
-        Hrtf = CreateHrtfStore(rate, irSize, evCount, irCount, azCount,
+        Hrtf = CreateHrtfStore(rate, irSize, 0.0f, evCount, irCount, azCount,
                                evOffset, coeffs, delays, filename);
     }
 
@@ -711,6 +748,253 @@ static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const char *
     return Hrtf;
 }
 
+#define SAMPLETYPE_S16 0
+#define SAMPLETYPE_S24 1
+
+#define CHANTYPE_LEFTONLY  0
+#define CHANTYPE_LEFTRIGHT 1
+
+static struct Hrtf *LoadHrtf02(const ALubyte *data, size_t datalen, const char *filename)
+{
+    struct Hrtf *Hrtf = NULL;
+    ALboolean failed = AL_FALSE;
+    ALuint rate = 0;
+    ALubyte sampleType;
+    ALubyte channelType;
+    ALushort irCount = 0;
+    ALushort irSize = 0;
+    ALubyte fdCount = 0;
+    ALushort distance = 0;
+    ALubyte evCount = 0;
+    const ALubyte *azCount = NULL;
+    ALushort *evOffset = NULL;
+    ALfloat (*coeffs)[2] = NULL;
+    ALubyte (*delays)[2] = NULL;
+    ALsizei i, j;
+
+    if(datalen < 8)
+    {
+        ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", filename, 8, datalen);
+        return NULL;
+    }
+
+    rate = GetLE_ALuint(&data, &datalen);
+    sampleType = GetLE_ALubyte(&data, &datalen);
+    channelType = GetLE_ALubyte(&data, &datalen);
+
+    irSize = GetLE_ALubyte(&data, &datalen);
+
+    fdCount = GetLE_ALubyte(&data, &datalen);
+
+    if(sampleType > SAMPLETYPE_S24)
+    {
+        ERR("Unsupported sample type: %d\n", sampleType);
+        failed = AL_TRUE;
+    }
+    if(channelType > CHANTYPE_LEFTRIGHT)
+    {
+        ERR("Unsupported channel type: %d\n", channelType);
+        failed = AL_TRUE;
+    }
+
+    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",
+            irSize, MIN_IR_SIZE, MAX_IR_SIZE, MOD_IR_SIZE);
+        failed = AL_TRUE;
+    }
+    if(fdCount != 1)
+    {
+        ERR("Multiple field-depths not supported: fdCount=%d (%d to %d)\n",
+            evCount, MIN_FD_COUNT, MAX_FD_COUNT);
+        failed = AL_TRUE;
+    }
+    if(failed)
+        return NULL;
+
+    for(i = 0;i < fdCount;i++)
+    {
+        if(datalen < 3)
+        {
+            ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", filename, 3, datalen);
+            return NULL;
+        }
+
+        distance = GetLE_ALushort(&data, &datalen);
+        if(distance < MIN_FD_DISTANCE || distance > MAX_FD_DISTANCE)
+        {
+            ERR("Unsupported field distance: distance=%d (%dmm to %dmm)\n",
+                distance, MIN_FD_DISTANCE, MAX_FD_DISTANCE);
+            failed = AL_TRUE;
+        }
+
+        evCount = GetLE_ALubyte(&data, &datalen);
+        if(evCount < MIN_EV_COUNT || evCount > MAX_EV_COUNT)
+        {
+            ERR("Unsupported elevation count: evCount=%d (%d to %d)\n",
+                evCount, MIN_EV_COUNT, MAX_EV_COUNT);
+            failed = AL_TRUE;
+        }
+        if(failed)
+            return NULL;
+
+        if(datalen < evCount)
+        {
+            ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", filename, evCount, datalen);
+            return NULL;
+        }
+
+        azCount = Get_ALubytePtr(&data, &datalen, evCount);
+        for(j = 0;j < evCount;j++)
+        {
+            if(azCount[j] < MIN_AZ_COUNT || azCount[j] > MAX_AZ_COUNT)
+            {
+                ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
+                    j, azCount[j], MIN_AZ_COUNT, MAX_AZ_COUNT);
+                failed = AL_TRUE;
+            }
+        }
+    }
+    if(failed)
+        return NULL;
+
+    evOffset = malloc(sizeof(evOffset[0])*evCount);
+    if(azCount == NULL || evOffset == NULL)
+    {
+        ERR("Out of memory.\n");
+        failed = AL_TRUE;
+    }
+
+    if(!failed)
+    {
+        evOffset[0] = 0;
+        irCount = azCount[0];
+        for(i = 1;i < evCount;i++)
+        {
+            evOffset[i] = evOffset[i-1] + azCount[i-1];
+            irCount += azCount[i];
+        }
+
+        coeffs = malloc(sizeof(coeffs[0])*irSize*irCount);
+        delays = malloc(sizeof(delays[0])*irCount);
+        if(coeffs == NULL || delays == NULL)
+        {
+            ERR("Out of memory.\n");
+            failed = AL_TRUE;
+        }
+    }
+
+    if(!failed)
+    {
+        size_t reqsize = 2*irSize*irCount + irCount;
+        if(datalen < reqsize)
+        {
+            ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n",
+                filename, reqsize, datalen);
+            failed = AL_TRUE;
+        }
+    }
+
+    if(!failed)
+    {
+        if(channelType == CHANTYPE_LEFTONLY)
+        {
+            if(sampleType == SAMPLETYPE_S16)
+                for(i = 0;i < irCount;i++)
+                {
+                    for(j = 0;j < irSize;j++)
+                        coeffs[i*irSize + j][0] = GetLE_ALshort(&data, &datalen) / 32768.0f;
+                }
+            else if(sampleType == SAMPLETYPE_S24)
+                for(i = 0;i < irCount;i++)
+                {
+                    for(j = 0;j < irSize;j++)
+                        coeffs[i*irSize + j][0] = GetLE_ALint24(&data, &datalen) / 8388608.0f;
+                }
+
+            for(i = 0;i < irCount;i++)
+            {
+                delays[i][0] = GetLE_ALubyte(&data, &datalen);
+                if(delays[i][0] > MAX_HRIR_DELAY)
+                {
+                    ERR("Invalid delays[%d][0]: %d (%d)\n", i, delays[i][0], MAX_HRIR_DELAY);
+                    failed = AL_TRUE;
+                }
+            }
+        }
+        else if(channelType == CHANTYPE_LEFTRIGHT)
+        {
+            if(sampleType == SAMPLETYPE_S16)
+                for(i = 0;i < irCount;i++)
+                {
+                    for(j = 0;j < irSize;j++)
+                    {
+                        coeffs[i*irSize + j][0] = GetLE_ALshort(&data, &datalen) / 32768.0f;
+                        coeffs[i*irSize + j][1] = GetLE_ALshort(&data, &datalen) / 32768.0f;
+                    }
+                }
+            else if(sampleType == SAMPLETYPE_S24)
+                for(i = 0;i < irCount;i++)
+                {
+                    for(j = 0;j < irSize;j++)
+                    {
+                        coeffs[i*irSize + j][0] = GetLE_ALint24(&data, &datalen) / 8388608.0f;
+                        coeffs[i*irSize + j][1] = GetLE_ALint24(&data, &datalen) / 8388608.0f;
+                    }
+                }
+
+            for(i = 0;i < irCount;i++)
+            {
+                delays[i][0] = GetLE_ALubyte(&data, &datalen);
+                if(delays[i][0] > MAX_HRIR_DELAY)
+                {
+                    ERR("Invalid delays[%d][0]: %d (%d)\n", i, delays[i][0], MAX_HRIR_DELAY);
+                    failed = AL_TRUE;
+                }
+                delays[i][1] = GetLE_ALubyte(&data, &datalen);
+                if(delays[i][1] > MAX_HRIR_DELAY)
+                {
+                    ERR("Invalid delays[%d][1]: %d (%d)\n", i, delays[i][1], MAX_HRIR_DELAY);
+                    failed = AL_TRUE;
+                }
+            }
+        }
+    }
+
+    if(!failed)
+    {
+        if(channelType == CHANTYPE_LEFTONLY)
+        {
+            /* Mirror the left ear responses to the right ear. */
+            for(i = 0;i < evCount;i++)
+            {
+                ALushort evoffset = evOffset[i];
+                ALubyte azcount = azCount[i];
+                for(j = 0;j < azcount;j++)
+                {
+                    ALsizei lidx = evoffset + j;
+                    ALsizei ridx = evoffset + ((azcount-j) % azcount);
+                    ALsizei k;
+
+                    for(k = 0;k < irSize;k++)
+                        coeffs[ridx*irSize + k][1] = coeffs[lidx*irSize + k][0];
+                    delays[ridx][1] = delays[lidx][0];
+                }
+            }
+        }
+
+        Hrtf = CreateHrtfStore(rate, irSize,
+            (ALfloat)distance / 1000.0f, evCount, irCount, azCount, evOffset,
+            coeffs, delays, filename
+        );
+    }
+
+    free(evOffset);
+    free(coeffs);
+    free(delays);
+    return Hrtf;
+}
+
 
 static void AddFileEntry(vector_EnumeratedHrtf *list, const_al_string filename)
 {
@@ -792,7 +1076,7 @@ static void AddFileEntry(vector_EnumeratedHrtf *list, const_al_string filename)
 /* Unfortunate that we have to duplicate AddFileEntry to take a memory buffer
  * for input instead of opening the given filename.
  */
-static void AddBuiltInEntry(vector_EnumeratedHrtf *list, const_al_string filename, size_t residx)
+static void AddBuiltInEntry(vector_EnumeratedHrtf *list, const_al_string filename, ALuint residx)
 {
     EnumeratedHrtf entry = { AL_STRING_INIT_STATIC(), NULL };
     struct HrtfEntry *loaded_entry;
@@ -832,7 +1116,7 @@ static void AddBuiltInEntry(vector_EnumeratedHrtf *list, const_al_string filenam
         );
         loaded_entry->next = LoadedHrtfs;
         loaded_entry->handle = hrtf;
-        snprintf(loaded_entry->filename, namelen,  "!"SZFMT"_%s",
+        snprintf(loaded_entry->filename, namelen,  "!%u_%s",
                  residx, alstr_get_cstr(filename));
         LoadedHrtfs = loaded_entry;
     }
@@ -1020,7 +1304,7 @@ struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
     struct FileMapping fmap;
     const ALubyte *rdata;
     const char *name;
-    size_t residx;
+    ALuint residx;
     size_t rsize;
     char ch;
 
@@ -1036,7 +1320,7 @@ struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
 
     fmap.ptr = NULL;
     fmap.len = 0;
-    if(sscanf(entry->filename, "!"SZFMT"%c", &residx, &ch) == 2 && ch == '_')
+    if(sscanf(entry->filename, "!%u%c", &residx, &ch) == 2 && ch == '_')
     {
         name = strchr(entry->filename, ch)+1;
 
@@ -1044,7 +1328,7 @@ struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
         rdata = GetResource(residx, &rsize);
         if(rdata == NULL || rsize == 0)
         {
-            ERR("Could not get resource "SZFMT", %s\n", residx, name);
+            ERR("Could not get resource %u, %s\n", residx, name);
             goto done;
         }
     }
@@ -1064,8 +1348,15 @@ struct Hrtf *GetLoadedHrtf(struct HrtfEntry *entry)
         rsize = fmap.len;
     }
 
-    if(rsize < sizeof(magicMarker01))
+    if(rsize < sizeof(magicMarker02))
         ERR("%s data is too short ("SZFMT" bytes)\n", name, rsize);
+    else if(memcmp(rdata, magicMarker02, sizeof(magicMarker02)) == 0)
+    {
+        TRACE("Detected data set format v2\n");
+        hrtf = LoadHrtf02(rdata+sizeof(magicMarker02),
+            rsize-sizeof(magicMarker02), name
+        );
+    }
     else if(memcmp(rdata, magicMarker01, sizeof(magicMarker01)) == 0)
     {
         TRACE("Detected data set format v1\n");

+ 40 - 3
libs/openal-soft/Alc/hrtf.h

@@ -12,7 +12,16 @@
 /* The maximum number of virtual speakers used to generate HRTF coefficients
  * for decoding B-Format.
  */
-#define HRTF_AMBI_MAX_CHANNELS 16
+#define HRTF_AMBI_MAX_CHANNELS 18
+
+
+#define HRTF_HISTORY_BITS   (6)
+#define HRTF_HISTORY_LENGTH (1<<HRTF_HISTORY_BITS)
+#define HRTF_HISTORY_MASK   (HRTF_HISTORY_LENGTH-1)
+
+#define HRIR_BITS        (7)
+#define HRIR_LENGTH      (1<<HRIR_BITS)
+#define HRIR_MASK        (HRIR_LENGTH-1)
 
 
 struct HrtfEntry;
@@ -22,6 +31,8 @@ struct Hrtf {
 
     ALuint sampleRate;
     ALsizei irSize;
+
+    ALfloat distance;
     ALubyte evCount;
 
     const ALubyte *azCount;
@@ -31,6 +42,33 @@ struct Hrtf {
 };
 
 
+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];
+    ALsizei Delay[2];
+    ALfloat Gain;
+} HrtfParams;
+
+typedef struct DirectHrtfState {
+    /* HRTF filter state for dry buffer content */
+    ALsizei Offset;
+    ALsizei IrSize;
+    struct {
+        alignas(16) ALfloat Values[HRIR_LENGTH][2];
+        alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
+    } Chan[];
+} DirectHrtfState;
+
+struct AngularPoint {
+    ALfloat Elev;
+    ALfloat Azim;
+};
+
+
 void FreeHrtfs(void);
 
 vector_EnumeratedHrtf EnumerateHrtf(const_al_string devname);
@@ -45,8 +83,7 @@ void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth,
  * Produces HRTF filter coefficients for decoding B-Format, given a set of
  * virtual speaker positions and HF/LF matrices for decoding to them. The
  * returned coefficients are ordered and scaled according to the matrices.
- * Returns the maximum impulse-response length of the generated coefficients.
  */
-ALsizei BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const ALfloat (*restrict AmbiPoints)[2], const ALfloat (*restrict AmbiMatrix)[2][MAX_AMBI_COEFFS], ALsizei AmbiCount);
+void BuildBFormatHrtf(const struct Hrtf *Hrtf, DirectHrtfState *state, ALsizei NumChannels, const struct AngularPoint *AmbiPoints, const ALfloat (*restrict AmbiMatrix)[MAX_AMBI_COEFFS], ALsizei AmbiCount, const ALfloat *restrict AmbiOrderHFGain);
 
 #endif /* ALC_HRTF_H */

+ 79 - 0
libs/openal-soft/Alc/inprogext.h

@@ -0,0 +1,79 @@
+#ifndef INPROGEXT_H
+#define INPROGEXT_H
+
+#include "AL/al.h"
+#include "AL/alc.h"
+#include "AL/alext.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef ALC_SOFT_loopback2
+#define ALC_SOFT_loopback2 1
+#define ALC_AMBISONIC_LAYOUT_SOFT                0xfff0
+#define ALC_AMBISONIC_SCALING_SOFT               0xfff1
+#define ALC_AMBISONIC_ORDER_SOFT                 0xfff2
+#define ALC_MAX_AMBISONIC_ORDER_SOFT             0xfff3
+
+#define ALC_BFORMAT3D_SOFT                       0x1508
+
+/* Ambisonic layouts */
+#define ALC_ACN_SOFT                             0xfff4
+#define ALC_FUMA_SOFT                            0xfff5
+
+/* Ambisonic scalings (normalization) */
+/*#define ALC_FUMA_SOFT*/
+#define ALC_SN3D_SOFT                            0xfff6
+#define ALC_N3D_SOFT                             0xfff7
+#endif
+
+#ifndef AL_SOFT_map_buffer
+#define AL_SOFT_map_buffer 1
+typedef unsigned int ALbitfieldSOFT;
+#define AL_MAP_READ_BIT_SOFT                     0x00000001
+#define AL_MAP_WRITE_BIT_SOFT                    0x00000002
+#define AL_MAP_PERSISTENT_BIT_SOFT               0x00000004
+#define AL_PRESERVE_DATA_BIT_SOFT                0x00000008
+typedef void (AL_APIENTRY*LPALBUFFERSTORAGESOFT)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags);
+typedef void* (AL_APIENTRY*LPALMAPBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access);
+typedef void (AL_APIENTRY*LPALUNMAPBUFFERSOFT)(ALuint buffer);
+typedef void (AL_APIENTRY*LPALFLUSHMAPPEDBUFFERSOFT)(ALuint buffer, ALsizei offset, ALsizei length);
+#ifdef AL_ALEXT_PROTOTYPES
+AL_API void AL_APIENTRY alBufferStorageSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags);
+AL_API void* AL_APIENTRY alMapBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access);
+AL_API void AL_APIENTRY alUnmapBufferSOFT(ALuint buffer);
+AL_API void AL_APIENTRY alFlushMappedBufferSOFT(ALuint buffer, ALsizei offset, ALsizei length);
+#endif
+#endif
+
+#ifndef AL_SOFT_events
+#define AL_SOFT_events 1
+#define AL_EVENT_CALLBACK_FUNCTION_SOFT          0x1220
+#define AL_EVENT_CALLBACK_USER_PARAM_SOFT        0x1221
+#define AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT      0x1222
+#define AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT  0x1223
+#define AL_EVENT_TYPE_ERROR_SOFT                 0x1224
+#define AL_EVENT_TYPE_PERFORMANCE_SOFT           0x1225
+#define AL_EVENT_TYPE_DEPRECATED_SOFT            0x1226
+#define AL_EVENT_TYPE_DISCONNECTED_SOFT          0x1227
+typedef void (AL_APIENTRY*ALEVENTPROCSOFT)(ALenum eventType, ALuint object, ALuint param,
+                                           ALsizei length, const ALchar *message,
+                                           void *userParam);
+typedef void (AL_APIENTRY*LPALEVENTCONTROLSOFT)(ALsizei count, const ALenum *types, ALboolean enable);
+typedef void (AL_APIENTRY*LPALEVENTCALLBACKSOFT)(ALEVENTPROCSOFT callback, void *userParam);
+typedef void* (AL_APIENTRY*LPALGETPOINTERSOFT)(ALenum pname);
+typedef void (AL_APIENTRY*LPALGETPOINTERVSOFT)(ALenum pname, void **values);
+#ifdef AL_ALEXT_PROTOTYPES
+AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable);
+AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam);
+AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname);
+AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values);
+#endif
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* INPROGEXT_H */

+ 69 - 0
libs/openal-soft/Alc/logging.h

@@ -0,0 +1,69 @@
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#include <stdio.h>
+
+
+#ifdef __GNUC__
+#define DECL_FORMAT(x, y, z) __attribute__((format(x, (y), (z))))
+#else
+#define DECL_FORMAT(x, y, z)
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern FILE *LogFile;
+
+#if defined(__GNUC__) && !defined(_WIN32)
+#define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: "MSG, T, __FUNCTION__ , ## __VA_ARGS__)
+#else
+void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4);
+#define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__)
+#endif
+
+#ifdef __ANDROID__
+#include <android/log.h>
+#define LOG_ANDROID(T, MSG, ...) __android_log_print(T, "openal", "AL lib: %s: "MSG, __FUNCTION__ , ## __VA_ARGS__)
+#else
+#define LOG_ANDROID(T, MSG, ...) ((void)0)
+#endif
+
+enum LogLevel {
+    NoLog,
+    LogError,
+    LogWarning,
+    LogTrace,
+    LogRef
+};
+extern enum LogLevel LogLevel;
+
+#define TRACEREF(...) do {                                                    \
+    if(LogLevel >= LogRef)                                                    \
+        AL_PRINT("(--)", __VA_ARGS__);                                        \
+} while(0)
+
+#define TRACE(...) do {                                                       \
+    if(LogLevel >= LogTrace)                                                  \
+        AL_PRINT("(II)", __VA_ARGS__);                                        \
+    LOG_ANDROID(ANDROID_LOG_DEBUG, __VA_ARGS__);                              \
+} while(0)
+
+#define WARN(...) do {                                                        \
+    if(LogLevel >= LogWarning)                                                \
+        AL_PRINT("(WW)", __VA_ARGS__);                                        \
+    LOG_ANDROID(ANDROID_LOG_WARN, __VA_ARGS__);                               \
+} while(0)
+
+#define ERR(...) do {                                                         \
+    if(LogLevel >= LogError)                                                  \
+        AL_PRINT("(EE)", __VA_ARGS__);                                        \
+    LOG_ANDROID(ANDROID_LOG_ERROR, __VA_ARGS__);                              \
+} while(0)
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LOGGING_H */

+ 4 - 27
libs/openal-soft/Alc/mastering.c

@@ -2,37 +2,19 @@
 
 #include <math.h>
 
+#include "mastering.h"
 #include "alu.h"
 #include "almalloc.h"
 
+
+extern inline ALuint GetCompressorSampleRate(const Compressor *Comp);
+
 #define RMS_WINDOW_SIZE (1<<7)
 #define RMS_WINDOW_MASK (RMS_WINDOW_SIZE-1)
 #define RMS_VALUE_MAX  (1<<24)
 
-#define LOOKAHEAD_SIZE (1<<13)
-#define LOOKAHEAD_MASK (LOOKAHEAD_SIZE-1)
-
 static_assert(RMS_VALUE_MAX < (UINT_MAX / RMS_WINDOW_SIZE), "RMS_VALUE_MAX is too big");
 
-typedef struct Compressor {
-    ALfloat PreGain;
-    ALfloat PostGain;
-    ALboolean SummedLink;
-    ALfloat AttackMin;
-    ALfloat AttackMax;
-    ALfloat ReleaseMin;
-    ALfloat ReleaseMax;
-    ALfloat Ratio;
-    ALfloat Threshold;
-    ALfloat Knee;
-    ALuint SampleRate;
-
-    ALuint RmsSum;
-    ALuint *RmsWindow;
-    ALsizei RmsIndex;
-    ALfloat Envelope[BUFFERSIZE];
-    ALfloat EnvLast;
-} Compressor;
 
 /* Multichannel compression is linked via one of two modes:
  *
@@ -209,11 +191,6 @@ Compressor *CompressorInit(const ALfloat PreGainDb, const ALfloat PostGainDb,
     return Comp;
 }
 
-ALuint GetCompressorSampleRate(const Compressor *Comp)
-{
-    return Comp->SampleRate;
-}
-
 void ApplyCompression(Compressor *Comp, const ALsizei NumChans, const ALsizei SamplesToDo,
                       ALfloat (*restrict OutBuffer)[BUFFERSIZE])
 {

+ 57 - 0
libs/openal-soft/Alc/mastering.h

@@ -0,0 +1,57 @@
+#ifndef MASTERING_H
+#define MASTERING_H
+
+#include "AL/al.h"
+
+/* For BUFFERSIZE. */
+#include "alMain.h"
+
+typedef struct Compressor {
+    ALfloat PreGain;
+    ALfloat PostGain;
+    ALboolean SummedLink;
+    ALfloat AttackMin;
+    ALfloat AttackMax;
+    ALfloat ReleaseMin;
+    ALfloat ReleaseMax;
+    ALfloat Ratio;
+    ALfloat Threshold;
+    ALfloat Knee;
+    ALuint SampleRate;
+
+    ALuint RmsSum;
+    ALuint *RmsWindow;
+    ALsizei RmsIndex;
+    ALfloat Envelope[BUFFERSIZE];
+    ALfloat EnvLast;
+} Compressor;
+
+/* The compressor requires the following information for proper
+ * initialization:
+ *
+ *   PreGainDb      - Gain applied before detection (in dB).
+ *   PostGainDb     - Gain applied after compression (in dB).
+ *   SummedLink     - Whether to use summed (true) or maxed (false) linking.
+ *   RmsSensing     - Whether to use RMS (true) or Peak (false) sensing.
+ *   AttackTimeMin  - Minimum attack time (in seconds).
+ *   AttackTimeMax  - Maximum attack time.  Automates when min != max.
+ *   ReleaseTimeMin - Minimum release time (in seconds).
+ *   ReleaseTimeMax - Maximum release time.  Automates when min != max.
+ *   Ratio          - Compression ratio (x:1).  Set to 0 for true limiter.
+ *   ThresholdDb    - Triggering threshold (in dB).
+ *   KneeDb         - Knee width (below threshold; in dB).
+ *   SampleRate     - Sample rate to process.
+ */
+Compressor *CompressorInit(const ALfloat PreGainDb, const ALfloat PostGainDb,
+    const ALboolean SummedLink, const ALboolean RmsSensing, const ALfloat AttackTimeMin,
+    const ALfloat AttackTimeMax, const ALfloat ReleaseTimeMin, const ALfloat ReleaseTimeMax,
+    const ALfloat Ratio, const ALfloat ThresholdDb, const ALfloat KneeDb,
+    const ALuint SampleRate);
+
+void ApplyCompression(struct Compressor *Comp, const ALsizei NumChans, const ALsizei SamplesToDo,
+                      ALfloat (*restrict OutBuffer)[BUFFERSIZE]);
+
+inline ALuint GetCompressorSampleRate(const Compressor *Comp)
+{ return Comp->SampleRate; }
+
+#endif /* MASTERING_H */

+ 20 - 30
libs/openal-soft/Alc/mixer_defs.h → libs/openal-soft/Alc/mixer/defs.h

@@ -12,11 +12,11 @@ struct MixHrtfParams;
 struct HrtfState;
 
 /* C resamplers */
-const ALfloat *Resample_copy32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
-const ALfloat *Resample_point32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
-const ALfloat *Resample_lerp32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
-const ALfloat *Resample_fir4_32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
-const ALfloat *Resample_bsinc32_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
+const ALfloat *Resample_copy_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
+const ALfloat *Resample_point_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
+const ALfloat *Resample_lerp_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
+const ALfloat *Resample_cubic_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
+const ALfloat *Resample_bsinc_C(const InterpState *state, const ALfloat *restrict src, ALsizei frac, ALint increment, ALfloat *restrict dst, ALsizei dstlen);
 
 
 /* C mixers */
@@ -76,23 +76,16 @@ inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *restr
     }
 }
 
-const ALfloat *Resample_lerp32_SSE2(const InterpState *state, const ALfloat *restrict src,
-                                    ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                    ALsizei numsamples);
-const ALfloat *Resample_lerp32_SSE41(const InterpState *state, const ALfloat *restrict src,
-                                     ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                     ALsizei numsamples);
+const ALfloat *Resample_lerp_SSE2(const InterpState *state, const ALfloat *restrict src,
+                                  ALsizei frac, ALint increment, ALfloat *restrict dst,
+                                  ALsizei numsamples);
+const ALfloat *Resample_lerp_SSE41(const InterpState *state, const ALfloat *restrict src,
+                                   ALsizei frac, ALint increment, ALfloat *restrict dst,
+                                   ALsizei numsamples);
 
-const ALfloat *Resample_fir4_32_SSE3(const InterpState *state, const ALfloat *restrict src,
-                                     ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                     ALsizei numsamples);
-const ALfloat *Resample_fir4_32_SSE41(const InterpState *state, const ALfloat *restrict src,
-                                      ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                      ALsizei numsamples);
-
-const ALfloat *Resample_bsinc32_SSE(const InterpState *state, const ALfloat *restrict src,
-                                    ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                    ALsizei dstlen);
+const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *restrict src,
+                                  ALsizei frac, ALint increment, ALfloat *restrict dst,
+                                  ALsizei dstlen);
 
 /* Neon mixers */
 void MixHrtf_Neon(ALfloat *restrict LeftOut, ALfloat *restrict RightOut,
@@ -116,14 +109,11 @@ void MixRow_Neon(ALfloat *OutBuffer, const ALfloat *Gains,
                  ALsizei InPos, ALsizei BufferSize);
 
 /* Neon resamplers */
-const ALfloat *Resample_lerp32_Neon(const InterpState *state, const ALfloat *restrict src,
-                                    ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                    ALsizei numsamples);
-const ALfloat *Resample_fir4_32_Neon(const InterpState *state, const ALfloat *restrict src,
-                                     ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                     ALsizei numsamples);
-const ALfloat *Resample_bsinc32_Neon(const InterpState *state, const ALfloat *restrict src,
-                                     ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                     ALsizei dstlen);
+const ALfloat *Resample_lerp_Neon(const InterpState *state, const ALfloat *restrict src,
+                                  ALsizei frac, ALint increment, ALfloat *restrict dst,
+                                  ALsizei numsamples);
+const ALfloat *Resample_bsinc_Neon(const InterpState *state, const ALfloat *restrict src,
+                                   ALsizei frac, ALint increment, ALfloat *restrict dst,
+                                   ALsizei dstlen);
 
 #endif /* MIXER_DEFS_H */

+ 1 - 1
libs/openal-soft/Alc/mixer_inc.c → libs/openal-soft/Alc/mixer/hrtf_inc.c

@@ -4,9 +4,9 @@
 #include "alSource.h"
 
 #include "hrtf.h"
-#include "mixer_defs.h"
 #include "align.h"
 #include "alu.h"
+#include "defs.h"
 
 
 static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],

+ 22 - 60
libs/openal-soft/Alc/mixer_c.c → libs/openal-soft/Alc/mixer/mixer_c.c

@@ -6,17 +6,17 @@
 #include "alu.h"
 #include "alSource.h"
 #include "alAuxEffectSlot.h"
+#include "defs.h"
 
 
-static inline ALfloat point32(const ALfloat *restrict vals, ALsizei UNUSED(frac))
+static inline ALfloat do_point(const ALfloat *restrict vals, ALsizei UNUSED(frac))
 { return vals[0]; }
-static inline ALfloat lerp32(const ALfloat *restrict vals, ALsizei frac)
+static inline ALfloat do_lerp(const ALfloat *restrict vals, ALsizei frac)
 { return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); }
-static inline ALfloat fir4_32(const ALfloat *restrict vals, ALsizei frac)
-{ return resample_fir4(vals[-1], vals[0], vals[1], vals[2], frac); }
+static inline ALfloat do_cubic(const ALfloat *restrict vals, ALsizei frac)
+{ return cubic(vals[0], vals[1], vals[2], vals[3], frac * (1.0f/FRACTIONONE)); }
 
-
-const ALfloat *Resample_copy32_C(const InterpState* UNUSED(state),
+const ALfloat *Resample_copy_C(const InterpState* UNUSED(state),
   const ALfloat *restrict src, ALsizei UNUSED(frac), ALint UNUSED(increment),
   ALfloat *restrict dst, ALsizei numsamples)
 {
@@ -29,12 +29,14 @@ const ALfloat *Resample_copy32_C(const InterpState* UNUSED(state),
     return dst;
 }
 
-#define DECL_TEMPLATE(Sampler)                                                \
-const ALfloat *Resample_##Sampler##_C(const InterpState* UNUSED(state),       \
+#define DECL_TEMPLATE(Tag, Sampler, O)                                        \
+const ALfloat *Resample_##Tag##_C(const InterpState* UNUSED(state),           \
   const ALfloat *restrict src, ALsizei frac, ALint increment,                 \
   ALfloat *restrict dst, ALsizei numsamples)                                  \
 {                                                                             \
     ALsizei i;                                                                \
+                                                                              \
+    src -= O;                                                                 \
     for(i = 0;i < numsamples;i++)                                             \
     {                                                                         \
         dst[i] = Sampler(src, frac);                                          \
@@ -46,17 +48,18 @@ const ALfloat *Resample_##Sampler##_C(const InterpState* UNUSED(state),       \
     return dst;                                                               \
 }
 
-DECL_TEMPLATE(point32)
-DECL_TEMPLATE(lerp32)
-DECL_TEMPLATE(fir4_32)
+DECL_TEMPLATE(point, do_point, 0)
+DECL_TEMPLATE(lerp, do_lerp, 0)
+DECL_TEMPLATE(cubic, do_cubic, 1)
 
 #undef DECL_TEMPLATE
 
-const ALfloat *Resample_bsinc32_C(const InterpState *state, const ALfloat *restrict src,
-                                  ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                  ALsizei dstlen)
+const ALfloat *Resample_bsinc_C(const InterpState *state, const ALfloat *restrict src,
+                                ALsizei frac, ALint increment, ALfloat *restrict dst,
+                                ALsizei dstlen)
 {
     const ALfloat *fil, *scd, *phd, *spd;
+    const ALfloat *const filter = state->bsinc.filter;
     const ALfloat sf = state->bsinc.sf;
     const ALsizei m = state->bsinc.m;
     ALsizei j_f, pi, i;
@@ -71,10 +74,10 @@ const ALfloat *Resample_bsinc32_C(const InterpState *state, const ALfloat *restr
         pf = (frac & ((1<<FRAC_PHASE_BITDIFF)-1)) * (1.0f/(1<<FRAC_PHASE_BITDIFF));
 #undef FRAC_PHASE_BITDIFF
 
-        fil = ASSUME_ALIGNED(state->bsinc.coeffs[pi].filter, 16);
-        scd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].scDelta, 16);
-        phd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].phDelta, 16);
-        spd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].spDelta, 16);
+        fil = ASSUME_ALIGNED(filter + m*pi*4, 16);
+        scd = ASSUME_ALIGNED(fil + m, 16);
+        phd = ASSUME_ALIGNED(scd + m, 16);
+        spd = ASSUME_ALIGNED(phd + m, 16);
 
         // Apply the scale and phase interpolated filter.
         r = 0.0f;
@@ -90,47 +93,6 @@ const ALfloat *Resample_bsinc32_C(const InterpState *state, const ALfloat *restr
 }
 
 
-void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALsizei numsamples)
-{
-    ALsizei i;
-    if(numsamples > 1)
-    {
-        dst[0] = filter->b0 * src[0] +
-                 filter->b1 * filter->x[0] +
-                 filter->b2 * filter->x[1] -
-                 filter->a1 * filter->y[0] -
-                 filter->a2 * filter->y[1];
-        dst[1] = filter->b0 * src[1] +
-                 filter->b1 * src[0] +
-                 filter->b2 * filter->x[0] -
-                 filter->a1 * dst[0] -
-                 filter->a2 * filter->y[0];
-        for(i = 2;i < numsamples;i++)
-            dst[i] = filter->b0 * src[i] +
-                     filter->b1 * src[i-1] +
-                     filter->b2 * src[i-2] -
-                     filter->a1 * dst[i-1] -
-                     filter->a2 * dst[i-2];
-        filter->x[0] = src[i-1];
-        filter->x[1] = src[i-2];
-        filter->y[0] = dst[i-1];
-        filter->y[1] = dst[i-2];
-    }
-    else if(numsamples == 1)
-    {
-        dst[0] = filter->b0 * src[0] +
-                 filter->b1 * filter->x[0] +
-                 filter->b2 * filter->x[1] -
-                 filter->a1 * filter->y[0] -
-                 filter->a2 * filter->y[1];
-        filter->x[1] = filter->x[0];
-        filter->x[0] = src[0];
-        filter->y[1] = filter->y[0];
-        filter->y[0] = dst[0];
-    }
-}
-
-
 static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
                                const ALsizei IrSize,
                                const ALfloat (*restrict Coeffs)[2],
@@ -148,7 +110,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
 #define MixHrtf MixHrtf_C
 #define MixHrtfBlend MixHrtfBlend_C
 #define MixDirectHrtf MixDirectHrtf_C
-#include "mixer_inc.c"
+#include "hrtf_inc.c"
 #undef MixHrtf
 
 

+ 16 - 86
libs/openal-soft/Alc/mixer_neon.c → libs/openal-soft/Alc/mixer/mixer_neon.c

@@ -7,10 +7,10 @@
 #include "alMain.h"
 #include "alu.h"
 #include "hrtf.h"
-#include "mixer_defs.h"
+#include "defs.h"
 
 
-const ALfloat *Resample_lerp32_Neon(const InterpState* UNUSED(state),
+const ALfloat *Resample_lerp_Neon(const InterpState* UNUSED(state),
   const ALfloat *restrict src, ALsizei frac, ALint increment,
   ALfloat *restrict dst, ALsizei numsamples)
 {
@@ -66,84 +66,15 @@ const ALfloat *Resample_lerp32_Neon(const InterpState* UNUSED(state),
     return dst;
 }
 
-const ALfloat *Resample_fir4_32_Neon(const InterpState* UNUSED(state),
-  const ALfloat *restrict src, ALsizei frac, ALint increment,
-  ALfloat *restrict dst, ALsizei numsamples)
-{
-    const int32x4_t increment4 = vdupq_n_s32(increment*4);
-    const int32x4_t fracMask4 = vdupq_n_s32(FRACTIONMASK);
-    alignas(16) ALint pos_[4];
-    alignas(16) ALsizei frac_[4];
-    int32x4_t pos4;
-    int32x4_t frac4;
-    ALsizei i;
-
-    InitiatePositionArrays(frac, increment, frac_, pos_, 4);
-
-    frac4 = vld1q_s32(frac_);
-    pos4 = vld1q_s32(pos_);
-
-    --src;
-    for(i = 0;numsamples-i > 3;i += 4)
-    {
-        const float32x4_t val0 = vld1q_f32(&src[pos_[0]]);
-        const float32x4_t val1 = vld1q_f32(&src[pos_[1]]);
-        const float32x4_t val2 = vld1q_f32(&src[pos_[2]]);
-        const float32x4_t val3 = vld1q_f32(&src[pos_[3]]);
-        float32x4_t k0 = vld1q_f32(sinc4Tab[frac_[0]]);
-        float32x4_t k1 = vld1q_f32(sinc4Tab[frac_[1]]);
-        float32x4_t k2 = vld1q_f32(sinc4Tab[frac_[2]]);
-        float32x4_t k3 = vld1q_f32(sinc4Tab[frac_[3]]);
-        float32x4_t out;
-
-        k0 = vmulq_f32(k0, val0);
-        k1 = vmulq_f32(k1, val1);
-        k2 = vmulq_f32(k2, val2);
-        k3 = vmulq_f32(k3, val3);
-        k0 = vcombine_f32(vpadd_f32(vget_low_f32(k0), vget_high_f32(k0)),
-                          vpadd_f32(vget_low_f32(k1), vget_high_f32(k1)));
-        k2 = vcombine_f32(vpadd_f32(vget_low_f32(k2), vget_high_f32(k2)),
-                          vpadd_f32(vget_low_f32(k3), vget_high_f32(k3)));
-        out = vcombine_f32(vpadd_f32(vget_low_f32(k0), vget_high_f32(k0)),
-                           vpadd_f32(vget_low_f32(k2), vget_high_f32(k2)));
-
-        vst1q_f32(&dst[i], out);
-
-        frac4 = vaddq_s32(frac4, increment4);
-        pos4 = vaddq_s32(pos4, vshrq_n_s32(frac4, FRACTIONBITS));
-        frac4 = vandq_s32(frac4, fracMask4);
-
-        vst1q_s32(pos_, pos4);
-        vst1q_s32(frac_, frac4);
-    }
-
-    if(i < numsamples)
-    {
-        /* NOTE: These four elements represent the position *after* the last
-         * four samples, so the lowest element is the next position to
-         * resample.
-         */
-        ALint pos = pos_[0];
-        frac = frac_[0];
-        do {
-            dst[i] = resample_fir4(src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
-
-            frac += increment;
-            pos  += frac>>FRACTIONBITS;
-            frac &= FRACTIONMASK;
-        } while(++i < numsamples);
-    }
-    return dst;
-}
-
-const ALfloat *Resample_bsinc32_Neon(const InterpState *state,
+const ALfloat *Resample_bsinc_Neon(const InterpState *state,
   const ALfloat *restrict src, ALsizei frac, ALint increment,
   ALfloat *restrict dst, ALsizei dstlen)
 {
+    const ALfloat *const filter = state->bsinc.filter;
     const float32x4_t sf4 = vdupq_n_f32(state->bsinc.sf);
     const ALsizei m = state->bsinc.m;
-    const ALfloat *fil, *scd, *phd, *spd;
-    ALsizei pi, i, j;
+    const float32x4_t *fil, *scd, *phd, *spd;
+    ALsizei pi, i, j, offset;
     float32x4_t r4;
     ALfloat pf;
 
@@ -156,23 +87,22 @@ const ALfloat *Resample_bsinc32_Neon(const InterpState *state,
         pf = (frac & ((1<<FRAC_PHASE_BITDIFF)-1)) * (1.0f/(1<<FRAC_PHASE_BITDIFF));
 #undef FRAC_PHASE_BITDIFF
 
-        fil = ASSUME_ALIGNED(state->bsinc.coeffs[pi].filter, 16);
-        scd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].scDelta, 16);
-        phd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].phDelta, 16);
-        spd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].spDelta, 16);
+        offset = m*pi*4;
+        fil = ASSUME_ALIGNED(filter + offset, 16); offset += m;
+        scd = ASSUME_ALIGNED(filter + offset, 16); offset += m;
+        phd = ASSUME_ALIGNED(filter + offset, 16); offset += m;
+        spd = ASSUME_ALIGNED(filter + offset, 16);
 
         // Apply the scale and phase interpolated filter.
         r4 = vdupq_n_f32(0.0f);
         {
             const float32x4_t pf4 = vdupq_n_f32(pf);
-            for(j = 0;j < m;j+=4)
+            for(j = 0;j < m;j+=4,fil++,scd++,phd++,spd++)
             {
                 /* f = ((fil + sf*scd) + pf*(phd + sf*spd)) */
-                const float32x4_t f4 = vmlaq_f32(vmlaq_f32(vld1q_f32(&fil[j]),
-                                                           sf4, vld1q_f32(&scd[j])),
-                    pf4, vmlaq_f32(vld1q_f32(&phd[j]),
-                        sf4, vld1q_f32(&spd[j])
-                    )
+                const float32x4_t f4 = vmlaq_f32(
+                    vmlaq_f32(*fil, sf4, *scd),
+                    pf4, vmlaq_f32(*phd, sf4, *spd)
                 );
                 /* r += f*src */
                 r4 = vmlaq_f32(r4, f4, vld1q_f32(&src[j]));
@@ -223,7 +153,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
 #define MixHrtf MixHrtf_Neon
 #define MixHrtfBlend MixHrtfBlend_Neon
 #define MixDirectHrtf MixDirectHrtf_Neon
-#include "mixer_inc.c"
+#include "hrtf_inc.c"
 #undef MixHrtf
 
 

+ 18 - 19
libs/openal-soft/Alc/mixer_sse.c → libs/openal-soft/Alc/mixer/mixer_sse.c

@@ -9,17 +9,18 @@
 
 #include "alSource.h"
 #include "alAuxEffectSlot.h"
-#include "mixer_defs.h"
+#include "defs.h"
 
 
-const ALfloat *Resample_bsinc32_SSE(const InterpState *state, const ALfloat *restrict src,
-                                    ALsizei frac, ALint increment, ALfloat *restrict dst,
-                                    ALsizei dstlen)
+const ALfloat *Resample_bsinc_SSE(const InterpState *state, const ALfloat *restrict src,
+                                  ALsizei frac, ALint increment, ALfloat *restrict dst,
+                                  ALsizei dstlen)
 {
+    const ALfloat *const filter = state->bsinc.filter;
     const __m128 sf4 = _mm_set1_ps(state->bsinc.sf);
     const ALsizei m = state->bsinc.m;
-    const ALfloat *fil, *scd, *phd, *spd;
-    ALsizei pi, i, j;
+    const __m128 *fil, *scd, *phd, *spd;
+    ALsizei pi, i, j, offset;
     ALfloat pf;
     __m128 r4;
 
@@ -32,30 +33,28 @@ const ALfloat *Resample_bsinc32_SSE(const InterpState *state, const ALfloat *res
         pf = (frac & ((1<<FRAC_PHASE_BITDIFF)-1)) * (1.0f/(1<<FRAC_PHASE_BITDIFF));
 #undef FRAC_PHASE_BITDIFF
 
-        fil = ASSUME_ALIGNED(state->bsinc.coeffs[pi].filter, 16);
-        scd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].scDelta, 16);
-        phd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].phDelta, 16);
-        spd = ASSUME_ALIGNED(state->bsinc.coeffs[pi].spDelta, 16);
+        offset = m*pi*4;
+        fil = (const __m128*)ASSUME_ALIGNED(filter + offset, 16); offset += m;
+        scd = (const __m128*)ASSUME_ALIGNED(filter + offset, 16); offset += m;
+        phd = (const __m128*)ASSUME_ALIGNED(filter + offset, 16); offset += m;
+        spd = (const __m128*)ASSUME_ALIGNED(filter + offset, 16);
 
         // Apply the scale and phase interpolated filter.
         r4 = _mm_setzero_ps();
         {
             const __m128 pf4 = _mm_set1_ps(pf);
-#define LD4(x) _mm_load_ps(x)
-#define ULD4(x) _mm_loadu_ps(x)
 #define MLA4(x, y, z) _mm_add_ps(x, _mm_mul_ps(y, z))
-            for(j = 0;j < m;j+=4)
+            for(j = 0;j < m;j+=4,fil++,scd++,phd++,spd++)
             {
                 /* f = ((fil + sf*scd) + pf*(phd + sf*spd)) */
-                const __m128 f4 = MLA4(MLA4(LD4(&fil[j]), sf4, LD4(&scd[j])),
-                    pf4, MLA4(LD4(&phd[j]), sf4, LD4(&spd[j]))
+                const __m128 f4 = MLA4(
+                    MLA4(*fil, sf4, *scd),
+                    pf4, MLA4(*phd, sf4, *spd)
                 );
                 /* r += f*src */
-                r4 = MLA4(r4, f4, ULD4(&src[j]));
+                r4 = MLA4(r4, f4, _mm_loadu_ps(&src[j]));
             }
 #undef MLA4
-#undef ULD4
-#undef LD4
         }
         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));
@@ -126,7 +125,7 @@ static inline void ApplyCoeffs(ALsizei Offset, ALfloat (*restrict Values)[2],
 #define MixHrtf MixHrtf_SSE
 #define MixHrtfBlend MixHrtfBlend_SSE
 #define MixDirectHrtf MixDirectHrtf_SSE
-#include "mixer_inc.c"
+#include "hrtf_inc.c"
 #undef MixHrtf
 
 

+ 2 - 2
libs/openal-soft/Alc/mixer_sse2.c → libs/openal-soft/Alc/mixer/mixer_sse2.c

@@ -24,10 +24,10 @@
 #include <emmintrin.h>
 
 #include "alu.h"
-#include "mixer_defs.h"
+#include "defs.h"
 
 
-const ALfloat *Resample_lerp32_SSE2(const InterpState* UNUSED(state),
+const ALfloat *Resample_lerp_SSE2(const InterpState* UNUSED(state),
   const ALfloat *restrict src, ALsizei frac, ALint increment,
   ALfloat *restrict dst, ALsizei numsamples)
 {

+ 0 - 0
libs/openal-soft/Alc/mixer/mixer_sse3.c


+ 17 - 28
libs/openal-soft/Alc/mixer_sse3.c → libs/openal-soft/Alc/mixer/mixer_sse41.c

@@ -1,9 +1,6 @@
 /**
- * OpenAL cross platform audio library, SSE3 mixer functions
- *
+ * OpenAL cross platform audio library
  * Copyright (C) 2014 by Timothy Arceri <[email protected]>.
- * Copyright (C) 2015 by Chris Robinson <[email protected]>.
- *
  * This library is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Library General Public
  *  License as published by the Free Software Foundation; either
@@ -25,17 +22,18 @@
 
 #include <xmmintrin.h>
 #include <emmintrin.h>
-#include <pmmintrin.h>
+#include <smmintrin.h>
 
 #include "alu.h"
-#include "mixer_defs.h"
+#include "defs.h"
 
 
-const ALfloat *Resample_fir4_32_SSE3(const InterpState* UNUSED(state),
+const ALfloat *Resample_lerp_SSE41(const InterpState* UNUSED(state),
   const ALfloat *restrict src, ALsizei frac, ALint increment,
   ALfloat *restrict dst, ALsizei numsamples)
 {
     const __m128i increment4 = _mm_set1_epi32(increment*4);
+    const __m128 fracOne4 = _mm_set1_ps(1.0f/FRACTIONONE);
     const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK);
     union { alignas(16) ALint i[4]; float f[4]; } pos_;
     union { alignas(16) ALsizei i[4]; float f[4]; } frac_;
@@ -48,26 +46,15 @@ const ALfloat *Resample_fir4_32_SSE3(const InterpState* UNUSED(state),
     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(sinc4Tab[frac_.i[0]]);
-        __m128 k1 = _mm_load_ps(sinc4Tab[frac_.i[1]]);
-        __m128 k2 = _mm_load_ps(sinc4Tab[frac_.i[2]]);
-        __m128 k3 = _mm_load_ps(sinc4Tab[frac_.i[3]]);
-        __m128 out;
+        const __m128 val1 = _mm_setr_ps(src[pos_.i[0]], src[pos_.i[1]], src[pos_.i[2]], src[pos_.i[3]]);
+        const __m128 val2 = _mm_setr_ps(src[pos_.i[0]+1], src[pos_.i[1]+1], src[pos_.i[2]+1], src[pos_.i[3]+1]);
 
-        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);
+        /* val1 + (val2-val1)*mu */
+        const __m128 r0 = _mm_sub_ps(val2, val1);
+        const __m128 mu = _mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4);
+        const __m128 out = _mm_add_ps(val1, _mm_mul_ps(mu, r0));
 
         _mm_store_ps(&dst[i], out);
 
@@ -75,19 +62,21 @@ const ALfloat *Resample_fir4_32_SSE3(const InterpState* UNUSED(state),
         pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS));
         frac4 = _mm_and_si128(frac4, fracMask4);
 
-        _mm_store_ps(pos_.f, _mm_castsi128_ps(pos4));
-        _mm_store_ps(frac_.f, _mm_castsi128_ps(frac4));
+        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);
     }
 
     /* 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];
-    frac = frac_.i[0];
+    frac = _mm_cvtsi128_si32(frac4);
 
     for(;i < numsamples;i++)
     {
-        dst[i] = resample_fir4(src[pos], src[pos+1], src[pos+2], src[pos+3], frac);
+        dst[i] = lerp(src[pos], src[pos+1], frac * (1.0f/FRACTIONONE));
 
         frac += increment;
         pos  += frac>>FRACTIONBITS;

+ 0 - 154
libs/openal-soft/Alc/mixer_sse41.c

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

+ 262 - 172
libs/openal-soft/Alc/mixer.c → libs/openal-soft/Alc/mixvoice.c

@@ -33,9 +33,13 @@
 #include "alBuffer.h"
 #include "alListener.h"
 #include "alAuxEffectSlot.h"
+#include "sample_cvt.h"
 #include "alu.h"
+#include "alconfig.h"
+#include "ringbuffer.h"
 
-#include "mixer_defs.h"
+#include "cpu_caps.h"
+#include "mixer/defs.h"
 
 
 static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
@@ -44,18 +48,18 @@ static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
 extern inline void InitiatePositionArrays(ALsizei frac, ALint increment, ALsizei *restrict frac_arr, ALint *restrict pos_arr, ALsizei size);
 
 
-/* BSinc requires up to 11 extra samples before the current position, and 12 after. */
-static_assert(MAX_PRE_SAMPLES >= 11, "MAX_PRE_SAMPLES must be at least 11!");
-static_assert(MAX_POST_SAMPLES >= 12, "MAX_POST_SAMPLES must be at least 12!");
+/* BSinc24 requires up to 23 extra samples before the current position, and 24 after. */
+static_assert(MAX_RESAMPLE_PADDING >= 24, "MAX_RESAMPLE_PADDING must be at least 24!");
 
 
 enum Resampler ResamplerDefault = LinearResampler;
 
-static MixerFunc MixSamples = Mix_C;
+MixerFunc MixSamples = Mix_C;
+RowMixerFunc MixRowSamples = MixRow_C;
 static HrtfMixerFunc MixHrtfSamples = MixHrtf_C;
-HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_C;
+static HrtfMixerBlendFunc MixHrtfBlendSamples = MixHrtfBlend_C;
 
-MixerFunc SelectMixer(void)
+static MixerFunc SelectMixer(void)
 {
 #ifdef HAVE_NEON
     if((CPUCapFlags&CPU_CAP_NEON))
@@ -68,7 +72,7 @@ MixerFunc SelectMixer(void)
     return Mix_C;
 }
 
-RowMixerFunc SelectRowMixer(void)
+static RowMixerFunc SelectRowMixer(void)
 {
 #ifdef HAVE_NEON
     if((CPUCapFlags&CPU_CAP_NEON))
@@ -112,48 +116,37 @@ ResamplerFunc SelectResampler(enum Resampler resampler)
     switch(resampler)
     {
         case PointResampler:
-            return Resample_point32_C;
+            return Resample_point_C;
         case LinearResampler:
 #ifdef HAVE_NEON
             if((CPUCapFlags&CPU_CAP_NEON))
-                return Resample_lerp32_Neon;
+                return Resample_lerp_Neon;
 #endif
 #ifdef HAVE_SSE4_1
             if((CPUCapFlags&CPU_CAP_SSE4_1))
-                return Resample_lerp32_SSE41;
+                return Resample_lerp_SSE41;
 #endif
 #ifdef HAVE_SSE2
             if((CPUCapFlags&CPU_CAP_SSE2))
-                return Resample_lerp32_SSE2;
+                return Resample_lerp_SSE2;
 #endif
-            return Resample_lerp32_C;
+            return Resample_lerp_C;
         case FIR4Resampler:
+            return Resample_cubic_C;
+        case BSinc12Resampler:
+        case BSinc24Resampler:
 #ifdef HAVE_NEON
             if((CPUCapFlags&CPU_CAP_NEON))
-                return Resample_fir4_32_Neon;
-#endif
-#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 BSincResampler:
-#ifdef HAVE_NEON
-            if((CPUCapFlags&CPU_CAP_NEON))
-                return Resample_bsinc32_Neon;
+                return Resample_bsinc_Neon;
 #endif
 #ifdef HAVE_SSE
             if((CPUCapFlags&CPU_CAP_SSE))
-                return Resample_bsinc32_SSE;
+                return Resample_bsinc_SSE;
 #endif
-            return Resample_bsinc32_C;
+            return Resample_bsinc_C;
     }
 
-    return Resample_point32_C;
+    return Resample_point_C;
 }
 
 
@@ -167,13 +160,20 @@ void aluInitMixer(void)
             ResamplerDefault = PointResampler;
         else if(strcasecmp(str, "linear") == 0)
             ResamplerDefault = LinearResampler;
-        else if(strcasecmp(str, "sinc4") == 0)
+        else if(strcasecmp(str, "cubic") == 0)
             ResamplerDefault = FIR4Resampler;
+        else if(strcasecmp(str, "bsinc12") == 0)
+            ResamplerDefault = BSinc12Resampler;
+        else if(strcasecmp(str, "bsinc24") == 0)
+            ResamplerDefault = BSinc24Resampler;
         else if(strcasecmp(str, "bsinc") == 0)
-            ResamplerDefault = BSincResampler;
-        else if(strcasecmp(str, "cubic") == 0 || strcasecmp(str, "sinc8") == 0)
         {
-            WARN("Resampler option \"%s\" is deprecated, using sinc4\n", str);
+            WARN("Resampler option \"%s\" is deprecated, using bsinc12\n", str);
+            ResamplerDefault = BSinc12Resampler;
+        }
+        else if(strcasecmp(str, "sinc4") == 0 || strcasecmp(str, "sinc8") == 0)
+        {
+            WARN("Resampler option \"%s\" is deprecated, using cubic\n", str);
             ResamplerDefault = FIR4Resampler;
         }
         else
@@ -190,11 +190,26 @@ void aluInitMixer(void)
     MixHrtfBlendSamples = SelectHrtfBlendMixer();
     MixHrtfSamples = SelectHrtfMixer();
     MixSamples = SelectMixer();
+    MixRowSamples = SelectRowMixer();
 }
 
 
-static inline ALfloat Sample_ALbyte(ALbyte val)
-{ return val * (1.0f/128.0f); }
+static void SendAsyncEvent(ALCcontext *context, ALuint enumtype, ALenum type,
+                           ALuint objid, ALuint param, const char *msg)
+{
+    AsyncEvent evt;
+    evt.EnumType = enumtype;
+    evt.Type = type;
+    evt.ObjectId = objid;
+    evt.Param = param;
+    strcpy(evt.Message, msg);
+    if(ll_ringbuffer_write(context->AsyncEvents, (const char*)&evt, 1) == 1)
+        alsem_post(&context->EventSem);
+}
+
+
+static inline ALfloat Sample_ALubyte(ALubyte val)
+{ return (val-128) * (1.0f/128.0f); }
 
 static inline ALfloat Sample_ALshort(ALshort val)
 { return val * (1.0f/32768.0f); }
@@ -202,45 +217,53 @@ static inline ALfloat Sample_ALshort(ALshort val)
 static inline ALfloat Sample_ALfloat(ALfloat val)
 { return val; }
 
+static inline ALfloat Sample_ALdouble(ALdouble val)
+{ return (ALfloat)val; }
+
+typedef ALubyte ALmulaw;
+static inline ALfloat Sample_ALmulaw(ALmulaw val)
+{ return muLawDecompressionTable[val] * (1.0f/32768.0f); }
+
+typedef ALubyte ALalaw;
+static inline ALfloat Sample_ALalaw(ALalaw val)
+{ return aLawDecompressionTable[val] * (1.0f/32768.0f); }
+
 #define DECL_TEMPLATE(T)                                                      \
-static inline void Load_##T(ALfloat *dst, const T *src, ALint srcstep, ALsizei samples)\
+static inline void Load_##T(ALfloat *restrict dst, const T *restrict src,     \
+                            ALint srcstep, ALsizei samples)                   \
 {                                                                             \
     ALsizei i;                                                                \
     for(i = 0;i < samples;i++)                                                \
-        dst[i] = Sample_##T(src[i*srcstep]);                                  \
+        dst[i] += Sample_##T(src[i*srcstep]);                                 \
 }
 
-DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
 DECL_TEMPLATE(ALshort)
 DECL_TEMPLATE(ALfloat)
+DECL_TEMPLATE(ALdouble)
+DECL_TEMPLATE(ALmulaw)
+DECL_TEMPLATE(ALalaw)
 
 #undef DECL_TEMPLATE
 
-static void LoadSamples(ALfloat *dst, const ALvoid *src, ALint srcstep, enum FmtType srctype, ALsizei samples)
+static void LoadSamples(ALfloat *restrict dst, const ALvoid *restrict src, ALint srcstep,
+                        enum FmtType srctype, ALsizei samples)
 {
+#define HANDLE_FMT(ET, ST) case ET: Load_##ST(dst, src, srcstep, samples); break
     switch(srctype)
     {
-        case FmtByte:
-            Load_ALbyte(dst, src, srcstep, samples);
-            break;
-        case FmtShort:
-            Load_ALshort(dst, src, srcstep, samples);
-            break;
-        case FmtFloat:
-            Load_ALfloat(dst, src, srcstep, samples);
-            break;
+        HANDLE_FMT(FmtUByte, ALubyte);
+        HANDLE_FMT(FmtShort, ALshort);
+        HANDLE_FMT(FmtFloat, ALfloat);
+        HANDLE_FMT(FmtDouble, ALdouble);
+        HANDLE_FMT(FmtMulaw, ALmulaw);
+        HANDLE_FMT(FmtAlaw, ALalaw);
     }
-}
-
-static inline void SilenceSamples(ALfloat *dst, ALsizei samples)
-{
-    ALsizei i;
-    for(i = 0;i < samples;i++)
-        dst[i] = 0.0f;
+#undef HANDLE_FMT
 }
 
 
-static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter,
+static const ALfloat *DoFilters(BiquadState *lpfilter, BiquadState *hpfilter,
                                 ALfloat *restrict dst, const ALfloat *restrict src,
                                 ALsizei numsamples, enum ActiveFilters type)
 {
@@ -248,17 +271,17 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
     switch(type)
     {
         case AF_None:
-            ALfilterState_processPassthru(lpfilter, src, numsamples);
-            ALfilterState_processPassthru(hpfilter, src, numsamples);
+            BiquadState_processPassthru(lpfilter, src, numsamples);
+            BiquadState_processPassthru(hpfilter, src, numsamples);
             break;
 
         case AF_LowPass:
-            ALfilterState_process(lpfilter, dst, src, numsamples);
-            ALfilterState_processPassthru(hpfilter, dst, numsamples);
+            BiquadState_process(lpfilter, dst, src, numsamples);
+            BiquadState_processPassthru(hpfilter, dst, numsamples);
             return dst;
         case AF_HighPass:
-            ALfilterState_processPassthru(lpfilter, src, numsamples);
-            ALfilterState_process(hpfilter, dst, src, numsamples);
+            BiquadState_processPassthru(lpfilter, src, numsamples);
+            BiquadState_process(hpfilter, dst, src, numsamples);
             return dst;
 
         case AF_BandPass:
@@ -267,8 +290,8 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
                 ALfloat temp[256];
                 ALsizei todo = mini(256, numsamples-i);
 
-                ALfilterState_process(lpfilter, temp, src+i, todo);
-                ALfilterState_process(hpfilter, dst+i, temp, todo);
+                BiquadState_process(lpfilter, temp, src+i, todo);
+                BiquadState_process(hpfilter, dst+i, temp, todo);
                 i += todo;
             }
             return dst;
@@ -277,11 +300,19 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
 }
 
 
-ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo)
+/* This function uses these device temp buffers. */
+#define SOURCE_DATA_BUF 0
+#define RESAMPLED_BUF 1
+#define FILTERED_BUF 2
+#define NFC_DATA_BUF 3
+ALboolean MixSource(ALvoice *voice, ALuint SourceID, ALCcontext *Context, ALsizei SamplesToDo)
 {
+    ALCdevice *Device = Context->Device;
     ALbufferlistitem *BufferListItem;
     ALbufferlistitem *BufferLoopItem;
     ALsizei NumChannels, SampleSize;
+    ALbitfieldSOFT enabledevt;
+    ALsizei buffers_done = 0;
     ResamplerFunc Resample;
     ALsizei DataPosInt;
     ALsizei DataPosFrac;
@@ -292,11 +323,13 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
     ALsizei IrSize;
     bool isplaying;
     bool firstpass;
+    bool isstatic;
     ALsizei chan;
     ALsizei send;
 
     /* Get source info */
     isplaying      = true; /* Will only be called while playing. */
+    isstatic       = !!(voice->Flags&VOICE_IS_STATIC);
     DataPosInt     = ATOMIC_LOAD(&voice->position, almemory_order_acquire);
     DataPosFrac    = ATOMIC_LOAD(&voice->position_fraction, almemory_order_relaxed);
     BufferListItem = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
@@ -308,7 +341,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
     IrSize = (Device->HrtfHandle ? Device->HrtfHandle->irSize : 0);
 
     Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
-                Resample_copy32_C : voice->Resampler);
+                Resample_copy_C : voice->Resampler);
 
     Counter = (voice->Flags&VOICE_IS_FADING) ? SamplesToDo : 0;
     firstpass = true;
@@ -322,81 +355,126 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
         DataSize64 *= increment;
         DataSize64 += DataPosFrac+FRACTIONMASK;
         DataSize64 >>= FRACTIONBITS;
-        DataSize64 += MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
-
+        DataSize64 += MAX_RESAMPLE_PADDING*2;
         SrcBufferSize = (ALsizei)mini64(DataSize64, BUFFERSIZE);
 
         /* Figure out how many samples we can actually mix from this. */
         DataSize64  = SrcBufferSize;
-        DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
+        DataSize64 -= MAX_RESAMPLE_PADDING*2;
         DataSize64 <<= FRACTIONBITS;
         DataSize64 -= DataPosFrac;
-
-        DstBufferSize = (ALsizei)((DataSize64+(increment-1)) / increment);
-        DstBufferSize = mini(DstBufferSize, (SamplesToDo-OutPos));
+        DstBufferSize = (ALsizei)mini64((DataSize64+(increment-1)) / increment,
+                                        SamplesToDo - OutPos);
 
         /* Some mixers like having a multiple of 4, so try to give that unless
          * this is the last update. */
-        if(OutPos+DstBufferSize < SamplesToDo)
+        if(DstBufferSize < SamplesToDo-OutPos)
             DstBufferSize &= ~3;
 
+        /* It's impossible to have a buffer list item with no entries. */
+        assert(BufferListItem->num_buffers > 0);
+
         for(chan = 0;chan < NumChannels;chan++)
         {
             const ALfloat *ResampledData;
-            ALfloat *SrcData = Device->SourceData;
-            ALsizei SrcDataSize;
+            ALfloat *SrcData = Device->TempBuffer[SOURCE_DATA_BUF];
+            ALsizei FilledAmt;
 
-            /* Load the previous samples into the source data first. */
-            memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat));
-            SrcDataSize = MAX_PRE_SAMPLES;
+            /* Load the previous samples into the source data first, and clear the rest. */
+            memcpy(SrcData, voice->PrevSamples[chan], MAX_RESAMPLE_PADDING*sizeof(ALfloat));
+            memset(SrcData+MAX_RESAMPLE_PADDING, 0, (BUFFERSIZE-MAX_RESAMPLE_PADDING)*
+                                                    sizeof(ALfloat));
+            FilledAmt = MAX_RESAMPLE_PADDING;
 
-            if(Source->SourceType == AL_STATIC)
+            if(isstatic)
             {
-                const ALbuffer *ALBuffer = BufferListItem->buffer;
-                const ALubyte *Data = ALBuffer->data;
-                ALsizei DataSize;
-
-                /* Offset buffer data to current channel */
-                Data += chan*SampleSize;
+                /* TODO: For static sources, loop points are taken from the
+                 * first buffer (should be adjusted by any buffer offset, to
+                 * possibly be added later).
+                 */
+                const ALbuffer *Buffer0 = BufferListItem->buffers[0];
+                const ALsizei LoopStart = Buffer0->LoopStart;
+                const ALsizei LoopEnd   = Buffer0->LoopEnd;
+                const ALsizei LoopSize  = LoopEnd - LoopStart;
 
                 /* If current pos is beyond the loop range, do not loop */
-                if(!BufferLoopItem || DataPosInt >= ALBuffer->LoopEnd)
+                if(!BufferLoopItem || DataPosInt >= LoopEnd)
                 {
+                    ALsizei SizeToDo = SrcBufferSize - FilledAmt;
+                    ALsizei CompLen = 0;
+                    ALsizei i;
+
                     BufferLoopItem = NULL;
 
-                    /* Load what's left to play from the source buffer, and
-                     * clear the rest of the temp buffer */
-                    DataSize = minu(SrcBufferSize - SrcDataSize,
-                                    ALBuffer->SampleLen - DataPosInt);
+                    for(i = 0;i < BufferListItem->num_buffers;i++)
+                    {
+                        const ALbuffer *buffer = BufferListItem->buffers[i];
+                        const ALubyte *Data = buffer->data;
+                        ALsizei DataSize;
+
+                        if(DataPosInt >= buffer->SampleLen)
+                            continue;
 
-                    LoadSamples(&SrcData[SrcDataSize], &Data[DataPosInt * NumChannels*SampleSize],
-                                NumChannels, ALBuffer->FmtType, DataSize);
-                    SrcDataSize += DataSize;
+                        /* Load what's left to play from the buffer */
+                        DataSize = mini(SizeToDo, buffer->SampleLen - DataPosInt);
+                        CompLen = maxi(CompLen, DataSize);
 
-                    SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
-                    SrcDataSize += SrcBufferSize - SrcDataSize;
+                        LoadSamples(&SrcData[FilledAmt],
+                            &Data[(DataPosInt*NumChannels + chan)*SampleSize],
+                            NumChannels, buffer->FmtType, DataSize
+                        );
+                    }
+                    FilledAmt += CompLen;
                 }
                 else
                 {
-                    ALsizei LoopStart = ALBuffer->LoopStart;
-                    ALsizei LoopEnd   = ALBuffer->LoopEnd;
+                    ALsizei SizeToDo = mini(SrcBufferSize - FilledAmt, LoopEnd - DataPosInt);
+                    ALsizei CompLen = 0;
+                    ALsizei i;
+
+                    for(i = 0;i < BufferListItem->num_buffers;i++)
+                    {
+                        const ALbuffer *buffer = BufferListItem->buffers[i];
+                        const ALubyte *Data = buffer->data;
+                        ALsizei DataSize;
+
+                        if(DataPosInt >= buffer->SampleLen)
+                            continue;
 
-                    /* Load what's left of this loop iteration, then load
-                     * repeats of the loop section */
-                    DataSize = minu(SrcBufferSize - SrcDataSize, LoopEnd - DataPosInt);
+                        /* Load what's left of this loop iteration */
+                        DataSize = mini(SizeToDo, buffer->SampleLen - DataPosInt);
+                        CompLen = maxi(CompLen, DataSize);
 
-                    LoadSamples(&SrcData[SrcDataSize], &Data[DataPosInt * NumChannels*SampleSize],
-                                NumChannels, ALBuffer->FmtType, DataSize);
-                    SrcDataSize += DataSize;
+                        LoadSamples(&SrcData[FilledAmt],
+                            &Data[(DataPosInt*NumChannels + chan)*SampleSize],
+                            NumChannels, buffer->FmtType, DataSize
+                        );
+                    }
+                    FilledAmt += CompLen;
 
-                    DataSize = LoopEnd-LoopStart;
-                    while(SrcBufferSize > SrcDataSize)
+                    while(SrcBufferSize > FilledAmt)
                     {
-                        DataSize = mini(SrcBufferSize - SrcDataSize, DataSize);
+                        const ALsizei SizeToDo = mini(SrcBufferSize - FilledAmt, LoopSize);
+
+                        CompLen = 0;
+                        for(i = 0;i < BufferListItem->num_buffers;i++)
+                        {
+                            const ALbuffer *buffer = BufferListItem->buffers[i];
+                            const ALubyte *Data = buffer->data;
+                            ALsizei DataSize;
+
+                            if(LoopStart >= buffer->SampleLen)
+                                continue;
 
-                        LoadSamples(&SrcData[SrcDataSize], &Data[LoopStart * NumChannels*SampleSize],
-                                    NumChannels, ALBuffer->FmtType, DataSize);
-                        SrcDataSize += DataSize;
+                            DataSize = mini(SizeToDo, buffer->SampleLen - LoopStart);
+                            CompLen = maxi(CompLen, DataSize);
+
+                            LoadSamples(&SrcData[FilledAmt],
+                                &Data[(LoopStart*NumChannels + chan)*SampleSize],
+                                NumChannels, buffer->FmtType, DataSize
+                            );
+                        }
+                        FilledAmt += CompLen;
                     }
                 }
             }
@@ -406,36 +484,37 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
                 ALbufferlistitem *tmpiter = BufferListItem;
                 ALsizei pos = DataPosInt;
 
-                while(tmpiter && SrcBufferSize > SrcDataSize)
+                while(tmpiter && SrcBufferSize > FilledAmt)
                 {
-                    const ALbuffer *ALBuffer;
-                    if((ALBuffer=tmpiter->buffer) != NULL)
+                    ALsizei SizeToDo = SrcBufferSize - FilledAmt;
+                    ALsizei i;
+
+                    for(i = 0;i < tmpiter->num_buffers;i++)
                     {
-                        const ALubyte *Data = ALBuffer->data;
-                        ALsizei DataSize = ALBuffer->SampleLen;
+                        const ALbuffer *ALBuffer = tmpiter->buffers[i];
+                        ALsizei DataSize = ALBuffer ? ALBuffer->SampleLen : 0;
 
-                        /* Skip the data already played */
-                        if(DataSize <= pos)
-                            pos -= DataSize;
-                        else
+                        if(DataSize > pos)
                         {
+                            const ALubyte *Data = ALBuffer->data;
                             Data += (pos*NumChannels + chan)*SampleSize;
-                            DataSize -= pos;
-                            pos -= pos;
 
-                            DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-                            LoadSamples(&SrcData[SrcDataSize], Data, NumChannels,
+                            DataSize = minu(SizeToDo, DataSize - pos);
+                            LoadSamples(&SrcData[FilledAmt], Data, NumChannels,
                                         ALBuffer->FmtType, DataSize);
-                            SrcDataSize += DataSize;
                         }
                     }
-                    tmpiter = ATOMIC_LOAD(&tmpiter->next, almemory_order_acquire);
-                    if(!tmpiter && BufferLoopItem)
-                        tmpiter = BufferLoopItem;
-                    else if(!tmpiter)
+                    if(pos > tmpiter->max_samples)
+                        pos -= tmpiter->max_samples;
+                    else
+                    {
+                        FilledAmt += tmpiter->max_samples - pos;
+                        pos = 0;
+                    }
+                    if(SrcBufferSize > FilledAmt)
                     {
-                        SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
-                        SrcDataSize += SrcBufferSize - SrcDataSize;
+                        tmpiter = ATOMIC_LOAD(&tmpiter->next, almemory_order_acquire);
+                        if(!tmpiter) tmpiter = BufferLoopItem;
                     }
                 }
             }
@@ -443,20 +522,20 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
             /* Store the last source samples used for next time. */
             memcpy(voice->PrevSamples[chan],
                 &SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
-                MAX_PRE_SAMPLES*sizeof(ALfloat)
+                MAX_RESAMPLE_PADDING*sizeof(ALfloat)
             );
 
             /* Now resample, then filter and mix to the appropriate outputs. */
             ResampledData = Resample(&voice->ResampleState,
-                &SrcData[MAX_PRE_SAMPLES], DataPosFrac, increment,
-                Device->ResampledData, DstBufferSize
+                &SrcData[MAX_RESAMPLE_PADDING], DataPosFrac, increment,
+                Device->TempBuffer[RESAMPLED_BUF], DstBufferSize
             );
             {
                 DirectParams *parms = &voice->Direct.Params[chan];
                 const ALfloat *samples;
 
                 samples = DoFilters(
-                    &parms->LowPass, &parms->HighPass, Device->FilteredData,
+                    &parms->LowPass, &parms->HighPass, Device->TempBuffer[FILTERED_BUF],
                     ResampledData, DstBufferSize, voice->Direct.FilterType
                 );
                 if(!(voice->Flags&VOICE_HAS_HRTF))
@@ -471,7 +550,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
                         );
                     else
                     {
-                        ALfloat *nfcsamples = Device->NFCtrlData;
+                        ALfloat *nfcsamples = Device->TempBuffer[NFC_DATA_BUF];
                         ALsizei chanoffset = 0;
 
                         MixSamples(samples,
@@ -483,8 +562,8 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
 #define APPLY_NFC_MIX(order)                                                  \
     if(voice->Direct.ChannelsPerOrder[order] > 0)                             \
     {                                                                         \
-        NfcFilterUpdate##order(&parms->NFCtrlFilter[order-1], nfcsamples,     \
-                               samples, DstBufferSize);                       \
+        NfcFilterProcess##order(&parms->NFCtrlFilter, nfcsamples, samples,    \
+                               DstBufferSize);                                \
         MixSamples(nfcsamples, voice->Direct.ChannelsPerOrder[order],         \
             voice->Direct.Buffer+chanoffset, parms->Gains.Current+chanoffset, \
             parms->Gains.Target+chanoffset, Counter, OutPos, DstBufferSize    \
@@ -503,8 +582,8 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
                     ALsizei fademix = 0;
                     int lidx, ridx;
 
-                    lidx = GetChannelIdxByName(Device->RealOut, FrontLeft);
-                    ridx = GetChannelIdxByName(Device->RealOut, FrontRight);
+                    lidx = GetChannelIdxByName(&Device->RealOut, FrontLeft);
+                    ridx = GetChannelIdxByName(&Device->RealOut, FrontRight);
                     assert(lidx != -1 && ridx != -1);
 
                     if(!Counter)
@@ -536,7 +615,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
                          */
                         gain = lerp(parms->Hrtf.Old.Gain, parms->Hrtf.Target.Gain,
                                     minf(1.0f, (ALfloat)fademix/Counter));
-                        hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Target.Coeffs);
+                        hrtfparams.Coeffs = parms->Hrtf.Target.Coeffs;
                         hrtfparams.Delay[0] = parms->Hrtf.Target.Delay[0];
                         hrtfparams.Delay[1] = parms->Hrtf.Target.Delay[1];
                         hrtfparams.Gain = 0.0f;
@@ -565,7 +644,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
                             gain = lerp(parms->Hrtf.Old.Gain, gain,
                                         (ALfloat)todo/(Counter-fademix));
 
-                        hrtfparams.Coeffs = SAFE_CONST(ALfloat2*,parms->Hrtf.Target.Coeffs);
+                        hrtfparams.Coeffs = parms->Hrtf.Target.Coeffs;
                         hrtfparams.Delay[0] = parms->Hrtf.Target.Delay[0];
                         hrtfparams.Delay[1] = parms->Hrtf.Target.Delay[1];
                         hrtfparams.Gain = parms->Hrtf.Old.Gain;
@@ -595,7 +674,7 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
                     continue;
 
                 samples = DoFilters(
-                    &parms->LowPass, &parms->HighPass, Device->FilteredData,
+                    &parms->LowPass, &parms->HighPass, Device->TempBuffer[FILTERED_BUF],
                     ResampledData, DstBufferSize, voice->Send[send].FilterType
                 );
 
@@ -617,47 +696,50 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
         Counter = maxi(DstBufferSize, Counter) - DstBufferSize;
         firstpass = false;
 
-        /* Handle looping sources */
-        while(1)
+        if(isstatic)
         {
-            const ALbuffer *ALBuffer;
-            ALsizei DataSize = 0;
-            ALsizei LoopStart = 0;
-            ALsizei LoopEnd = 0;
-
-            if((ALBuffer=BufferListItem->buffer) != NULL)
+            if(BufferLoopItem)
             {
-                DataSize = ALBuffer->SampleLen;
-                LoopStart = ALBuffer->LoopStart;
-                LoopEnd = ALBuffer->LoopEnd;
-                if(LoopEnd > DataPosInt)
-                    break;
-            }
-
-            if(BufferLoopItem && Source->SourceType == AL_STATIC)
-            {
-                assert(LoopEnd > LoopStart);
-                DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
-                break;
+                /* Handle looping static source */
+                const ALbuffer *Buffer = BufferListItem->buffers[0];
+                ALsizei LoopStart = Buffer->LoopStart;
+                ALsizei LoopEnd = Buffer->LoopEnd;
+                if(DataPosInt >= LoopEnd)
+                {
+                    assert(LoopEnd > LoopStart);
+                    DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
+                }
             }
-
-            if(DataSize > DataPosInt)
-                break;
-
-            BufferListItem = ATOMIC_LOAD(&BufferListItem->next, almemory_order_acquire);
-            if(!BufferListItem)
+            else
             {
-                BufferListItem = BufferLoopItem;
-                if(!BufferListItem)
+                /* Handle non-looping static source */
+                if(DataPosInt >= BufferListItem->max_samples)
                 {
                     isplaying = false;
+                    BufferListItem = NULL;
                     DataPosInt = 0;
                     DataPosFrac = 0;
                     break;
                 }
             }
+        }
+        else while(1)
+        {
+            /* Handle streaming source */
+            if(BufferListItem->max_samples > DataPosInt)
+                break;
+
+            buffers_done += BufferListItem->num_buffers;
+            BufferListItem = ATOMIC_LOAD(&BufferListItem->next, almemory_order_acquire);
+            if(!BufferListItem && !(BufferListItem=BufferLoopItem))
+            {
+                isplaying = false;
+                DataPosInt = 0;
+                DataPosFrac = 0;
+                break;
+            }
 
-            DataPosInt -= DataSize;
+            DataPosInt -= BufferListItem->max_samples;
         }
     } while(isplaying && OutPos < SamplesToDo);
 
@@ -667,5 +749,13 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
     ATOMIC_STORE(&voice->position,          DataPosInt, almemory_order_relaxed);
     ATOMIC_STORE(&voice->position_fraction, DataPosFrac, almemory_order_relaxed);
     ATOMIC_STORE(&voice->current_buffer,    BufferListItem, almemory_order_release);
+
+    /* Send any events now, after the position/buffer info was updated. */
+    enabledevt = ATOMIC_LOAD(&Context->EnabledEvts, almemory_order_acquire);
+    if(buffers_done > 0 && (enabledevt&EventType_BufferCompleted))
+        SendAsyncEvent(Context, EventType_BufferCompleted,
+            AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT, SourceID, buffers_done, "Buffer completed"
+        );
+
     return isplaying;
 }

+ 0 - 37
libs/openal-soft/Alc/nfcfilter.h

@@ -1,37 +0,0 @@
-#ifndef NFCFILTER_H
-#define NFCFILTER_H
-
-#include "alMain.h"
-
-typedef struct NfcFilter {
-    float g;
-    float coeffs[MAX_AMBI_ORDER*2 + 1];
-    float history[MAX_AMBI_ORDER];
-} NfcFilter;
-
-/* NOTE:
- * w0 = speed_of_sound / (source_distance * sample_rate);
- * w1 = speed_of_sound / (control_distance * sample_rate);
- *
- * Generally speaking, the control distance should be approximately the average
- * speaker distance, or based on the reference delay if outputing NFC-HOA. It
- * must not be negative, 0, or infinite. The source distance should not be too
- * small relative to the control distance.
- */
-
-/* Near-field control filter for first-order ambisonic channels (1-3). */
-void NfcFilterCreate1(NfcFilter *nfc, const float w0, const float w1);
-void NfcFilterAdjust1(NfcFilter *nfc, const float w0);
-void NfcFilterUpdate1(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
-
-/* Near-field control filter for second-order ambisonic channels (4-8). */
-void NfcFilterCreate2(NfcFilter *nfc, const float w0, const float w1);
-void NfcFilterAdjust2(NfcFilter *nfc, const float w0);
-void NfcFilterUpdate2(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
-
-/* Near-field control filter for third-order ambisonic channels (9-15). */
-void NfcFilterCreate3(NfcFilter *nfc, const float w0, const float w1);
-void NfcFilterAdjust3(NfcFilter *nfc, const float w0);
-void NfcFilterUpdate3(NfcFilter *nfc, float *restrict dst, const float *restrict src, const int count);
-
-#endif /* NFCFILTER_H */

+ 218 - 203
libs/openal-soft/Alc/panning.c

@@ -29,6 +29,7 @@
 #include "alMain.h"
 #include "alAuxEffectSlot.h"
 #include "alu.h"
+#include "alconfig.h"
 #include "bool.h"
 #include "ambdec.h"
 #include "bformatdec.h"
@@ -37,6 +38,8 @@
 
 
 extern inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
+extern inline void ComputeDryPanGains(const DryMixParams *dry, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+extern inline void ComputeFirstOrderGains(const BFMixParams *foa, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
 
 
 static const ALsizei FuMa2ACN[MAX_AMBI_COEFFS] = {
@@ -62,50 +65,6 @@ static const ALsizei ACN2ACN[MAX_AMBI_COEFFS] = {
     8,  9, 10, 11, 12, 13, 14, 15
 };
 
-/* NOTE: These are scale factors as applied to Ambisonics content. Decoder
- * coefficients should be divided by these values to get proper N3D scalings.
- */
-static const ALfloat UnitScale[MAX_AMBI_COEFFS] = {
-    1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
-    1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f
-};
-static const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = {
-    1.000000000f, /* ACN  0 (W), sqrt(1) */
-    1.732050808f, /* ACN  1 (Y), sqrt(3) */
-    1.732050808f, /* ACN  2 (Z), sqrt(3) */
-    1.732050808f, /* ACN  3 (X), sqrt(3) */
-    2.236067978f, /* ACN  4 (V), sqrt(5) */
-    2.236067978f, /* ACN  5 (T), sqrt(5) */
-    2.236067978f, /* ACN  6 (R), sqrt(5) */
-    2.236067978f, /* ACN  7 (S), sqrt(5) */
-    2.236067978f, /* ACN  8 (U), sqrt(5) */
-    2.645751311f, /* ACN  9 (Q), sqrt(7) */
-    2.645751311f, /* ACN 10 (O), sqrt(7) */
-    2.645751311f, /* ACN 11 (M), sqrt(7) */
-    2.645751311f, /* ACN 12 (K), sqrt(7) */
-    2.645751311f, /* ACN 13 (L), sqrt(7) */
-    2.645751311f, /* ACN 14 (N), sqrt(7) */
-    2.645751311f, /* ACN 15 (P), sqrt(7) */
-};
-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 CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS])
 {
@@ -202,31 +161,6 @@ void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread,
 }
 
 
-void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
-{
-    ALsizei i;
-
-    for(i = 0;i < numchans;i++)
-        gains[i] = chancoeffs[i][0] * 1.414213562f * ingain;
-    for(;i < MAX_OUTPUT_CHANNELS;i++)
-        gains[i] = 0.0f;
-}
-
-void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
-{
-    ALfloat gain = 0.0f;
-    ALsizei i;
-
-    for(i = 0;i < numchans;i++)
-    {
-        if(chanmap[i].Index == 0)
-            gain += chanmap[i].Scale;
-    }
-    gains[0] = gain * 1.414213562f * ingain;
-    for(i = 1;i < MAX_OUTPUT_CHANNELS;i++)
-        gains[i] = 0.0f;
-}
-
 void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
 {
     ALsizei i, j;
@@ -329,34 +263,28 @@ typedef struct ChannelMap {
     ChannelConfig Config;
 } ChannelMap;
 
-static void SetChannelMap(const enum Channel *devchans, ChannelConfig *ambicoeffs,
-                          const ChannelMap *chanmap, size_t count, ALsizei *outcount)
+static void SetChannelMap(const enum Channel devchans[MAX_OUTPUT_CHANNELS],
+                          ChannelConfig *ambicoeffs, const ChannelMap *chanmap,
+                          ALsizei count, ALsizei *outcount)
 {
-    size_t j, k;
-    ALsizei i;
+    ALsizei maxchans = 0;
+    ALsizei i, j;
 
-    for(i = 0;i < MAX_OUTPUT_CHANNELS && devchans[i] != InvalidChannel;i++)
+    for(i = 0;i < count;i++)
     {
-        if(devchans[i] == LFE)
+        ALint idx = GetChannelIndex(devchans, chanmap[i].ChanName);
+        if(idx < 0)
         {
-            for(j = 0;j < MAX_AMBI_COEFFS;j++)
-                ambicoeffs[i][j] = 0.0f;
+            ERR("Failed to find %s channel in device\n",
+                GetLabelFromChannel(chanmap[i].ChanName));
             continue;
         }
 
-        for(j = 0;j < count;j++)
-        {
-            if(devchans[i] != chanmap[j].ChanName)
-                continue;
-
-            for(k = 0;k < MAX_AMBI_COEFFS;++k)
-                ambicoeffs[i][k] = chanmap[j].Config[k];
-            break;
-        }
-        if(j == count)
-            ERR("Failed to match %s channel (%u) in channel map\n", GetLabelFromChannel(devchans[i]), i);
+        maxchans = maxi(maxchans, idx+1);
+        for(j = 0;j < MAX_AMBI_COEFFS;j++)
+            ambicoeffs[idx][j] = chanmap[i].Config[j];
     }
-    *outcount = i;
+    *outcount = mini(maxchans, MAX_OUTPUT_CHANNELS);
 }
 
 static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei speakermap[MAX_OUTPUT_CHANNELS])
@@ -365,7 +293,8 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei sp
 
     for(i = 0;i < conf->NumSpeakers;i++)
     {
-        int c = -1;
+        enum Channel ch;
+        int chidx = -1;
 
         /* NOTE: AmbDec does not define any standard speaker names, however
          * for this to work we have to by able to find the output channel
@@ -388,62 +317,63 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei sp
          * and vice-versa.
          */
         if(alstr_cmp_cstr(conf->Speakers[i].Name, "LF") == 0)
-            c = GetChannelIdxByName(device->RealOut, FrontLeft);
+            ch = FrontLeft;
         else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RF") == 0)
-            c = GetChannelIdxByName(device->RealOut, FrontRight);
+            ch = FrontRight;
         else if(alstr_cmp_cstr(conf->Speakers[i].Name, "CE") == 0)
-            c = GetChannelIdxByName(device->RealOut, FrontCenter);
+            ch = FrontCenter;
         else if(alstr_cmp_cstr(conf->Speakers[i].Name, "LS") == 0)
         {
             if(device->FmtChans == DevFmtX51Rear)
-                c = GetChannelIdxByName(device->RealOut, BackLeft);
+                ch = BackLeft;
             else
-                c = GetChannelIdxByName(device->RealOut, SideLeft);
+                ch = SideLeft;
         }
         else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RS") == 0)
         {
             if(device->FmtChans == DevFmtX51Rear)
-                c = GetChannelIdxByName(device->RealOut, BackRight);
+                ch = BackRight;
             else
-                c = GetChannelIdxByName(device->RealOut, SideRight);
+                ch = SideRight;
         }
         else if(alstr_cmp_cstr(conf->Speakers[i].Name, "LB") == 0)
         {
             if(device->FmtChans == DevFmtX51)
-                c = GetChannelIdxByName(device->RealOut, SideLeft);
+                ch = SideLeft;
             else
-                c = GetChannelIdxByName(device->RealOut, BackLeft);
+                ch = BackLeft;
         }
         else if(alstr_cmp_cstr(conf->Speakers[i].Name, "RB") == 0)
         {
             if(device->FmtChans == DevFmtX51)
-                c = GetChannelIdxByName(device->RealOut, SideRight);
+                ch = SideRight;
             else
-                c = GetChannelIdxByName(device->RealOut, BackRight);
+                ch = BackRight;
         }
         else if(alstr_cmp_cstr(conf->Speakers[i].Name, "CB") == 0)
-            c = GetChannelIdxByName(device->RealOut, BackCenter);
+            ch = BackCenter;
         else
         {
             const char *name = alstr_get_cstr(conf->Speakers[i].Name);
             unsigned int n;
-            char ch;
+            char c;
 
-            if(sscanf(name, "AUX%u%c", &n, &ch) == 1 && n < 16)
-                c = GetChannelIdxByName(device->RealOut, Aux0+n);
+            if(sscanf(name, "AUX%u%c", &n, &c) == 1 && n < 16)
+                ch = Aux0+n;
             else
             {
                 ERR("AmbDec speaker label \"%s\" not recognized\n", name);
                 return false;
             }
         }
-        if(c == -1)
+        chidx = GetChannelIdxByName(&device->RealOut, ch);
+        if(chidx == -1)
         {
             ERR("Failed to lookup AmbDec speaker label %s\n",
                 alstr_get_cstr(conf->Speakers[i].Name));
             return false;
         }
-        speakermap[i] = c;
+        speakermap[i] = chidx;
     }
 
     return true;
@@ -453,31 +383,28 @@ static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALsizei sp
 static const ChannelMap MonoCfg[1] = {
     { FrontCenter, { 1.0f } },
 }, StereoCfg[2] = {
-    { FrontLeft,   { 5.00000000e-1f,  2.88675135e-1f, 0.0f,  1.19573156e-1f } },
-    { FrontRight,  { 5.00000000e-1f, -2.88675135e-1f, 0.0f,  1.19573156e-1f } },
+    { FrontLeft,   { 5.00000000e-1f,  2.88675135e-1f, 0.0f,  5.77350269e-2f } },
+    { FrontRight,  { 5.00000000e-1f, -2.88675135e-1f, 0.0f,  5.77350269e-2f } },
 }, QuadCfg[4] = {
     { BackLeft,    { 3.53553391e-1f,  2.04124145e-1f, 0.0f, -2.04124145e-1f } },
     { FrontLeft,   { 3.53553391e-1f,  2.04124145e-1f, 0.0f,  2.04124145e-1f } },
     { FrontRight,  { 3.53553391e-1f, -2.04124145e-1f, 0.0f,  2.04124145e-1f } },
     { BackRight,   { 3.53553391e-1f, -2.04124145e-1f, 0.0f, -2.04124145e-1f } },
-}, X51SideCfg[5] = {
-    { SideLeft,    { 3.33001372e-1f,  1.89085671e-1f, 0.0f, -2.00041334e-1f, -2.12309737e-2f, 0.0f, 0.0f, 0.0f, -1.14573483e-2f } },
-    { FrontLeft,   { 1.47751298e-1f,  1.28994110e-1f, 0.0f,  1.15190495e-1f,  7.44949143e-2f, 0.0f, 0.0f, 0.0f, -6.47739980e-3f } },
-    { FrontCenter, { 7.73595729e-2f,  0.00000000e+0f, 0.0f,  9.71390298e-2f,  0.00000000e+0f, 0.0f, 0.0f, 0.0f,  5.18625335e-2f } },
-    { FrontRight,  { 1.47751298e-1f, -1.28994110e-1f, 0.0f,  1.15190495e-1f, -7.44949143e-2f, 0.0f, 0.0f, 0.0f, -6.47739980e-3f } },
-    { SideRight,   { 3.33001372e-1f, -1.89085671e-1f, 0.0f, -2.00041334e-1f,  2.12309737e-2f, 0.0f, 0.0f, 0.0f, -1.14573483e-2f } },
-}, X51RearCfg[5] = {
-    { BackLeft,    { 3.33001372e-1f,  1.89085671e-1f, 0.0f, -2.00041334e-1f, -2.12309737e-2f, 0.0f, 0.0f, 0.0f, -1.14573483e-2f } },
-    { FrontLeft,   { 1.47751298e-1f,  1.28994110e-1f, 0.0f,  1.15190495e-1f,  7.44949143e-2f, 0.0f, 0.0f, 0.0f, -6.47739980e-3f } },
-    { FrontCenter, { 7.73595729e-2f,  0.00000000e+0f, 0.0f,  9.71390298e-2f,  0.00000000e+0f, 0.0f, 0.0f, 0.0f,  5.18625335e-2f } },
-    { FrontRight,  { 1.47751298e-1f, -1.28994110e-1f, 0.0f,  1.15190495e-1f, -7.44949143e-2f, 0.0f, 0.0f, 0.0f, -6.47739980e-3f } },
-    { BackRight,   { 3.33001372e-1f, -1.89085671e-1f, 0.0f, -2.00041334e-1f,  2.12309737e-2f, 0.0f, 0.0f, 0.0f, -1.14573483e-2f } },
+}, X51SideCfg[4] = {
+    { SideLeft,    { 3.33000782e-1f,  1.89084803e-1f, 0.0f, -2.00042375e-1f, -2.12307769e-2f, 0.0f, 0.0f, 0.0f, -1.14579885e-2f } },
+    { FrontLeft,   { 1.88542860e-1f,  1.27709292e-1f, 0.0f,  1.66295695e-1f,  7.30571517e-2f, 0.0f, 0.0f, 0.0f,  2.10901184e-2f } },
+    { FrontRight,  { 1.88542860e-1f, -1.27709292e-1f, 0.0f,  1.66295695e-1f, -7.30571517e-2f, 0.0f, 0.0f, 0.0f,  2.10901184e-2f } },
+    { SideRight,   { 3.33000782e-1f, -1.89084803e-1f, 0.0f, -2.00042375e-1f,  2.12307769e-2f, 0.0f, 0.0f, 0.0f, -1.14579885e-2f } },
+}, X51RearCfg[4] = {
+    { BackLeft,    { 3.33000782e-1f,  1.89084803e-1f, 0.0f, -2.00042375e-1f, -2.12307769e-2f, 0.0f, 0.0f, 0.0f, -1.14579885e-2f } },
+    { FrontLeft,   { 1.88542860e-1f,  1.27709292e-1f, 0.0f,  1.66295695e-1f,  7.30571517e-2f, 0.0f, 0.0f, 0.0f,  2.10901184e-2f } },
+    { FrontRight,  { 1.88542860e-1f, -1.27709292e-1f, 0.0f,  1.66295695e-1f, -7.30571517e-2f, 0.0f, 0.0f, 0.0f,  2.10901184e-2f } },
+    { BackRight,   { 3.33000782e-1f, -1.89084803e-1f, 0.0f, -2.00042375e-1f,  2.12307769e-2f, 0.0f, 0.0f, 0.0f, -1.14579885e-2f } },
 }, X61Cfg[6] = {
-    { SideLeft,    { 2.04462744e-1f,  2.17178497e-1f, 0.0f, -4.39990188e-2f, -2.60787329e-2f, 0.0f, 0.0f, 0.0f, -6.87238843e-2f } },
-    { FrontLeft,   { 1.18130342e-1f,  9.34633906e-2f, 0.0f,  1.08553749e-1f,  6.80658795e-2f, 0.0f, 0.0f, 0.0f,  1.08999485e-2f } },
-    { FrontCenter, { 7.73595729e-2f,  0.00000000e+0f, 0.0f,  9.71390298e-2f,  0.00000000e+0f, 0.0f, 0.0f, 0.0f,  5.18625335e-2f } },
-    { FrontRight,  { 1.18130342e-1f, -9.34633906e-2f, 0.0f,  1.08553749e-1f, -6.80658795e-2f, 0.0f, 0.0f, 0.0f,  1.08999485e-2f } },
-    { SideRight,   { 2.04462744e-1f, -2.17178497e-1f, 0.0f, -4.39990188e-2f,  2.60787329e-2f, 0.0f, 0.0f, 0.0f, -6.87238843e-2f } },
+    { SideLeft,    { 2.04460341e-1f,  2.17177926e-1f, 0.0f, -4.39996780e-2f, -2.60790269e-2f, 0.0f, 0.0f, 0.0f, -6.87239792e-2f } },
+    { FrontLeft,   { 1.58923161e-1f,  9.21772680e-2f, 0.0f,  1.59658796e-1f,  6.66278083e-2f, 0.0f, 0.0f, 0.0f,  3.84686854e-2f } },
+    { FrontRight,  { 1.58923161e-1f, -9.21772680e-2f, 0.0f,  1.59658796e-1f, -6.66278083e-2f, 0.0f, 0.0f, 0.0f,  3.84686854e-2f } },
+    { SideRight,   { 2.04460341e-1f, -2.17177926e-1f, 0.0f, -4.39996780e-2f,  2.60790269e-2f, 0.0f, 0.0f, 0.0f, -6.87239792e-2f } },
     { BackCenter,  { 2.50001688e-1f,  0.00000000e+0f, 0.0f, -2.50000094e-1f,  0.00000000e+0f, 0.0f, 0.0f, 0.0f,  6.05133395e-2f } },
 }, X71Cfg[6] = {
     { BackLeft,    { 2.04124145e-1f,  1.08880247e-1f, 0.0f, -1.88586120e-1f, -1.29099444e-1f, 0.0f, 0.0f, 0.0f,  7.45355993e-2f,  3.73460789e-2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,  0.00000000e+0f } },
@@ -495,11 +422,10 @@ static void InitNearFieldCtrl(ALCdevice *device, ALfloat ctrl_dist, ALsizei orde
 
     if(GetConfigValueBool(devname, "decoder", "nfc", 1) && ctrl_dist > 0.0f)
     {
-        /* NFC is only used when AvgSpeakerDist is greater than 0, and
-         * METERS_PER_UNIT is also greater than 0. In addition, NFC can only be
-         * used when rendering to an ambisonic buffer.
+        /* NFC is only used when AvgSpeakerDist is greater than 0, and can only
+         * be used when rendering to an ambisonic buffer.
          */
-        device->AvgSpeakerDist = ctrl_dist;
+        device->AvgSpeakerDist = minf(ctrl_dist, 10.0f);
 
         device->Dry.NumChannelsPerOrder[0] = 1;
         if(periphonic)
@@ -517,7 +443,7 @@ static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const AL
 {
     const char *devname = alstr_get_cstr(device->DeviceName);
     ALfloat maxdist = 0.0f;
-    ALsizei total = 0;
+    size_t total = 0;
     ALsizei i;
 
     for(i = 0;i < conf->NumSpeakers;i++)
@@ -631,7 +557,7 @@ static void InitPanning(ALCdevice *device)
         const ALsizei *acnmap = (device->AmbiLayout == AmbiLayout_FuMa) ? FuMa2ACN : ACN2ACN;
         const ALfloat *n3dscale = (device->AmbiScale == AmbiNorm_FuMa) ? FuMa2N3DScale :
                                   (device->AmbiScale == AmbiNorm_SN3D) ? SN3D2N3DScale :
-                                  /*(device->AmbiScale == AmbiNorm_N3D) ?*/ UnitScale;
+                                  /*(device->AmbiScale == AmbiNorm_N3D) ?*/ N3D2N3DScale;
         ALfloat nfc_delay = 0.0f;
 
         count = (device->AmbiOrder == 3) ? 16 :
@@ -654,6 +580,8 @@ static void InitPanning(ALCdevice *device)
         }
         else
         {
+            ALfloat w_scale=1.0f, xyz_scale=1.0f;
+
             /* FOA output is always ACN+N3D for higher-order ambisonic output.
              * The upsampler expects this and will convert it for output.
              */
@@ -666,7 +594,17 @@ static void InitPanning(ALCdevice *device)
             device->FOAOut.CoeffCount = 0;
             device->FOAOut.NumChannels = 4;
 
-            ambiup_reset(device->AmbiUp, device);
+            if(device->AmbiOrder >= 3)
+            {
+                w_scale = W_SCALE_3H3P;
+                xyz_scale = XYZ_SCALE_3H3P;
+            }
+            else
+            {
+                w_scale = W_SCALE_2H2P;
+                xyz_scale = XYZ_SCALE_2H2P;
+            }
+            ambiup_reset(device->AmbiUp, device, w_scale, xyz_scale);
         }
 
         if(ConfigValueFloat(devname, "decoder", "nfc-ref-delay", &nfc_delay) && nfc_delay > 0.0f)
@@ -684,10 +622,10 @@ static void InitPanning(ALCdevice *device)
                       chanmap, count, &device->Dry.NumChannels);
         device->Dry.CoeffCount = coeffcount;
 
-        w_scale = (device->Dry.CoeffCount > 9) ? W_SCALE2D_THIRD :
-                  (device->Dry.CoeffCount > 4) ? W_SCALE2D_SECOND : 1.0f;
-        xyz_scale = (device->Dry.CoeffCount > 9) ? XYZ_SCALE2D_THIRD :
-                    (device->Dry.CoeffCount > 4) ? XYZ_SCALE2D_SECOND : 1.0f;
+        w_scale = (device->Dry.CoeffCount > 9) ? W_SCALE_3H0P :
+                  (device->Dry.CoeffCount > 4) ? W_SCALE_2H0P : 1.0f;
+        xyz_scale = (device->Dry.CoeffCount > 9) ? XYZ_SCALE_3H0P :
+                    (device->Dry.CoeffCount > 4) ? XYZ_SCALE_2H0P : 1.0f;
 
         memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi));
         for(i = 0;i < device->Dry.NumChannels;i++)
@@ -705,7 +643,7 @@ static void InitPanning(ALCdevice *device)
 static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
 {
     ChannelMap chanmap[MAX_OUTPUT_CHANNELS];
-    const ALfloat *coeff_scale = UnitScale;
+    const ALfloat *coeff_scale = N3D2N3DScale;
     ALfloat w_scale = 1.0f;
     ALfloat xyz_scale = 1.0f;
     ALsizei i, j;
@@ -718,26 +656,26 @@ static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const A
     {
         if(conf->ChanMask > 0x1ff)
         {
-            w_scale = W_SCALE3D_THIRD;
-            xyz_scale = XYZ_SCALE3D_THIRD;
+            w_scale = W_SCALE_3H3P;
+            xyz_scale = XYZ_SCALE_3H3P;
         }
         else if(conf->ChanMask > 0xf)
         {
-            w_scale = W_SCALE3D_SECOND;
-            xyz_scale = XYZ_SCALE3D_SECOND;
+            w_scale = W_SCALE_2H2P;
+            xyz_scale = XYZ_SCALE_2H2P;
         }
     }
     else
     {
         if(conf->ChanMask > 0x1ff)
         {
-            w_scale = W_SCALE2D_THIRD;
-            xyz_scale = XYZ_SCALE2D_THIRD;
+            w_scale = W_SCALE_3H0P;
+            xyz_scale = XYZ_SCALE_3H0P;
         }
         else if(conf->ChanMask > 0xf)
         {
-            w_scale = W_SCALE2D_SECOND;
-            xyz_scale = XYZ_SCALE2D_SECOND;
+            w_scale = W_SCALE_2H0P;
+            xyz_scale = XYZ_SCALE_2H0P;
         }
     }
 
@@ -874,66 +812,93 @@ static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsiz
 static void InitHrtfPanning(ALCdevice *device)
 {
     /* NOTE: azimuth goes clockwise. */
-    static const ALfloat AmbiPoints[][2] = {
+    static const struct AngularPoint AmbiPoints[] = {
         { DEG2RAD( 90.0f), DEG2RAD(   0.0f) },
-        { DEG2RAD( 35.0f), DEG2RAD( -45.0f) },
         { DEG2RAD( 35.0f), DEG2RAD(  45.0f) },
         { DEG2RAD( 35.0f), DEG2RAD( 135.0f) },
         { DEG2RAD( 35.0f), DEG2RAD(-135.0f) },
+        { DEG2RAD( 35.0f), DEG2RAD( -45.0f) },
         { DEG2RAD(  0.0f), DEG2RAD(   0.0f) },
+        { DEG2RAD(  0.0f), DEG2RAD(  45.0f) },
         { DEG2RAD(  0.0f), DEG2RAD(  90.0f) },
+        { DEG2RAD(  0.0f), DEG2RAD( 135.0f) },
         { DEG2RAD(  0.0f), DEG2RAD( 180.0f) },
+        { DEG2RAD(  0.0f), DEG2RAD(-135.0f) },
         { DEG2RAD(  0.0f), DEG2RAD( -90.0f) },
-        { DEG2RAD(-35.0f), DEG2RAD( -45.0f) },
+        { DEG2RAD(  0.0f), DEG2RAD( -45.0f) },
         { DEG2RAD(-35.0f), DEG2RAD(  45.0f) },
         { DEG2RAD(-35.0f), DEG2RAD( 135.0f) },
         { DEG2RAD(-35.0f), DEG2RAD(-135.0f) },
+        { DEG2RAD(-35.0f), DEG2RAD( -45.0f) },
         { DEG2RAD(-90.0f), DEG2RAD(   0.0f) },
     };
-    static const ALfloat AmbiMatrixFOA[][2][MAX_AMBI_COEFFS] = {
-        { { 1.88982237e-001f,  0.00000000e+000f,  1.90399923e-001f,  0.00000000e+000f }, { 7.14285714e-002f,  0.00000000e+000f,  1.24646009e-001f,  0.00000000e+000f } },
-        { { 1.88982237e-001f,  1.09057783e-001f,  1.09208910e-001f,  1.09057783e-001f }, { 7.14285714e-002f,  7.13950780e-002f,  7.14940135e-002f,  7.13950780e-002f } },
-        { { 1.88982237e-001f, -1.09057783e-001f,  1.09208910e-001f,  1.09057783e-001f }, { 7.14285714e-002f, -7.13950780e-002f,  7.14940135e-002f,  7.13950780e-002f } },
-        { { 1.88982237e-001f, -1.09057783e-001f,  1.09208910e-001f, -1.09057783e-001f }, { 7.14285714e-002f, -7.13950780e-002f,  7.14940135e-002f, -7.13950780e-002f } },
-        { { 1.88982237e-001f,  1.09057783e-001f,  1.09208910e-001f, -1.09057783e-001f }, { 7.14285714e-002f,  7.13950780e-002f,  7.14940135e-002f, -7.13950780e-002f } },
-        { { 1.88982237e-001f,  0.00000000e+000f,  0.00000000e+000f,  1.88281281e-001f }, { 7.14285714e-002f,  0.00000000e+000f,  0.00000000e+000f,  1.23259031e-001f } },
-        { { 1.88982237e-001f, -1.88281281e-001f,  0.00000000e+000f,  0.00000000e+000f }, { 7.14285714e-002f, -1.23259031e-001f,  0.00000000e+000f,  0.00000000e+000f } },
-        { { 1.88982237e-001f,  0.00000000e+000f,  0.00000000e+000f, -1.88281281e-001f }, { 7.14285714e-002f,  0.00000000e+000f,  0.00000000e+000f, -1.23259031e-001f } },
-        { { 1.88982237e-001f,  1.88281281e-001f,  0.00000000e+000f,  0.00000000e+000f }, { 7.14285714e-002f,  1.23259031e-001f,  0.00000000e+000f,  0.00000000e+000f } },
-        { { 1.88982237e-001f,  1.09057783e-001f, -1.09208910e-001f,  1.09057783e-001f }, { 7.14285714e-002f,  7.13950780e-002f, -7.14940135e-002f,  7.13950780e-002f } },
-        { { 1.88982237e-001f, -1.09057783e-001f, -1.09208910e-001f,  1.09057783e-001f }, { 7.14285714e-002f, -7.13950780e-002f, -7.14940135e-002f,  7.13950780e-002f } },
-        { { 1.88982237e-001f, -1.09057783e-001f, -1.09208910e-001f, -1.09057783e-001f }, { 7.14285714e-002f, -7.13950780e-002f, -7.14940135e-002f, -7.13950780e-002f } },
-        { { 1.88982237e-001f,  1.09057783e-001f, -1.09208910e-001f, -1.09057783e-001f }, { 7.14285714e-002f,  7.13950780e-002f, -7.14940135e-002f, -7.13950780e-002f } },
-        { { 1.88982237e-001f,  0.00000000e+000f, -1.90399923e-001f,  0.00000000e+000f }, { 7.14285714e-002f,  0.00000000e+000f, -1.24646009e-001f,  0.00000000e+000f } }
-    }, AmbiMatrixHOA[][2][MAX_AMBI_COEFFS] = {
-        { { 1.43315266e-001f,  0.00000000e+000f,  1.90399923e-001f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f,  1.18020996e-001f,  0.00000000e+000f,  0.00000000e+000f }, { 7.26741039e-002f,  0.00000000e+000f,  1.24646009e-001f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f,  1.49618920e-001f,  0.00000000e+000f,  0.00000000e+000f } },
-        { { 1.40852210e-001f,  1.09057783e-001f,  1.09208910e-001f,  1.09057783e-001f,  7.58818830e-002f,  7.66295578e-002f, -3.28314629e-004f,  7.66295578e-002f,  0.00000000e+000f }, { 7.14251066e-002f,  7.13950780e-002f,  7.14940135e-002f,  7.13950780e-002f,  9.61978444e-002f,  9.71456952e-002f, -4.16214759e-004f,  9.71456952e-002f,  0.00000000e+000f } },
-        { { 1.40852210e-001f, -1.09057783e-001f,  1.09208910e-001f,  1.09057783e-001f, -7.58818830e-002f, -7.66295578e-002f, -3.28314629e-004f,  7.66295578e-002f,  0.00000000e+000f }, { 7.14251066e-002f, -7.13950780e-002f,  7.14940135e-002f,  7.13950780e-002f, -9.61978444e-002f, -9.71456952e-002f, -4.16214759e-004f,  9.71456952e-002f,  0.00000000e+000f } },
-        { { 1.40852210e-001f, -1.09057783e-001f,  1.09208910e-001f, -1.09057783e-001f,  7.58818830e-002f, -7.66295578e-002f, -3.28314629e-004f, -7.66295578e-002f,  0.00000000e+000f }, { 7.14251066e-002f, -7.13950780e-002f,  7.14940135e-002f, -7.13950780e-002f,  9.61978444e-002f, -9.71456952e-002f, -4.16214759e-004f, -9.71456952e-002f,  0.00000000e+000f } },
-        { { 1.40852210e-001f,  1.09057783e-001f,  1.09208910e-001f, -1.09057783e-001f, -7.58818830e-002f,  7.66295578e-002f, -3.28314629e-004f, -7.66295578e-002f,  0.00000000e+000f }, { 7.14251066e-002f,  7.13950780e-002f,  7.14940135e-002f, -7.13950780e-002f, -9.61978444e-002f,  9.71456952e-002f, -4.16214759e-004f, -9.71456952e-002f,  0.00000000e+000f } },
-        { { 1.39644596e-001f,  0.00000000e+000f,  0.00000000e+000f,  1.88281281e-001f,  0.00000000e+000f,  0.00000000e+000f, -5.83538687e-002f,  0.00000000e+000f,  1.01835015e-001f }, { 7.08127349e-002f,  0.00000000e+000f,  0.00000000e+000f,  1.23259031e-001f,  0.00000000e+000f,  0.00000000e+000f, -7.39770307e-002f,  0.00000000e+000f,  1.29099445e-001f } },
-        { { 1.39644596e-001f, -1.88281281e-001f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f, -5.83538687e-002f,  0.00000000e+000f, -1.01835015e-001f }, { 7.08127349e-002f, -1.23259031e-001f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f, -7.39770307e-002f,  0.00000000e+000f, -1.29099445e-001f } },
-        { { 1.39644596e-001f,  0.00000000e+000f,  0.00000000e+000f, -1.88281281e-001f,  0.00000000e+000f,  0.00000000e+000f, -5.83538687e-002f,  0.00000000e+000f,  1.01835015e-001f }, { 7.08127349e-002f,  0.00000000e+000f,  0.00000000e+000f, -1.23259031e-001f,  0.00000000e+000f,  0.00000000e+000f, -7.39770307e-002f,  0.00000000e+000f,  1.29099445e-001f } },
-        { { 1.39644596e-001f,  1.88281281e-001f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f, -5.83538687e-002f,  0.00000000e+000f, -1.01835015e-001f }, { 7.08127349e-002f,  1.23259031e-001f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f, -7.39770307e-002f,  0.00000000e+000f, -1.29099445e-001f } },
-        { { 1.40852210e-001f,  1.09057783e-001f, -1.09208910e-001f,  1.09057783e-001f,  7.58818830e-002f, -7.66295578e-002f, -3.28314629e-004f, -7.66295578e-002f,  0.00000000e+000f }, { 7.14251066e-002f,  7.13950780e-002f, -7.14940135e-002f,  7.13950780e-002f,  9.61978444e-002f, -9.71456952e-002f, -4.16214759e-004f, -9.71456952e-002f,  0.00000000e+000f } },
-        { { 1.40852210e-001f, -1.09057783e-001f, -1.09208910e-001f,  1.09057783e-001f, -7.58818830e-002f,  7.66295578e-002f, -3.28314629e-004f, -7.66295578e-002f,  0.00000000e+000f }, { 7.14251066e-002f, -7.13950780e-002f, -7.14940135e-002f,  7.13950780e-002f, -9.61978444e-002f,  9.71456952e-002f, -4.16214759e-004f, -9.71456952e-002f,  0.00000000e+000f } },
-        { { 1.40852210e-001f, -1.09057783e-001f, -1.09208910e-001f, -1.09057783e-001f,  7.58818830e-002f,  7.66295578e-002f, -3.28314629e-004f,  7.66295578e-002f,  0.00000000e+000f }, { 7.14251066e-002f, -7.13950780e-002f, -7.14940135e-002f, -7.13950780e-002f,  9.61978444e-002f,  9.71456952e-002f, -4.16214759e-004f,  9.71456952e-002f,  0.00000000e+000f } },
-        { { 1.40852210e-001f,  1.09057783e-001f, -1.09208910e-001f, -1.09057783e-001f, -7.58818830e-002f, -7.66295578e-002f, -3.28314629e-004f,  7.66295578e-002f,  0.00000000e+000f }, { 7.14251066e-002f,  7.13950780e-002f, -7.14940135e-002f, -7.13950780e-002f, -9.61978444e-002f, -9.71456952e-002f, -4.16214759e-004f,  9.71456952e-002f,  0.00000000e+000f } },
-        { { 1.43315266e-001f,  0.00000000e+000f, -1.90399923e-001f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f,  1.18020996e-001f,  0.00000000e+000f,  0.00000000e+000f }, { 7.26741039e-002f,  0.00000000e+000f, -1.24646009e-001f,  0.00000000e+000f,  0.00000000e+000f,  0.00000000e+000f,  1.49618920e-001f,  0.00000000e+000f,  0.00000000e+000f } },
+    static const ALfloat AmbiMatrixFOA[][MAX_AMBI_COEFFS] = {
+        { 5.55555556e-02f,  0.00000000e+00f,  1.23717915e-01f,  0.00000000e+00f },
+        { 5.55555556e-02f, -5.00000000e-02f,  7.14285715e-02f,  5.00000000e-02f },
+        { 5.55555556e-02f, -5.00000000e-02f,  7.14285715e-02f, -5.00000000e-02f },
+        { 5.55555556e-02f,  5.00000000e-02f,  7.14285715e-02f, -5.00000000e-02f },
+        { 5.55555556e-02f,  5.00000000e-02f,  7.14285715e-02f,  5.00000000e-02f },
+        { 5.55555556e-02f,  0.00000000e+00f,  0.00000000e+00f,  8.66025404e-02f },
+        { 5.55555556e-02f, -6.12372435e-02f,  0.00000000e+00f,  6.12372435e-02f },
+        { 5.55555556e-02f, -8.66025404e-02f,  0.00000000e+00f,  0.00000000e+00f },
+        { 5.55555556e-02f, -6.12372435e-02f,  0.00000000e+00f, -6.12372435e-02f },
+        { 5.55555556e-02f,  0.00000000e+00f,  0.00000000e+00f, -8.66025404e-02f },
+        { 5.55555556e-02f,  6.12372435e-02f,  0.00000000e+00f, -6.12372435e-02f },
+        { 5.55555556e-02f,  8.66025404e-02f,  0.00000000e+00f,  0.00000000e+00f },
+        { 5.55555556e-02f,  6.12372435e-02f,  0.00000000e+00f,  6.12372435e-02f },
+        { 5.55555556e-02f, -5.00000000e-02f, -7.14285715e-02f,  5.00000000e-02f },
+        { 5.55555556e-02f, -5.00000000e-02f, -7.14285715e-02f, -5.00000000e-02f },
+        { 5.55555556e-02f,  5.00000000e-02f, -7.14285715e-02f, -5.00000000e-02f },
+        { 5.55555556e-02f,  5.00000000e-02f, -7.14285715e-02f,  5.00000000e-02f },
+        { 5.55555556e-02f,  0.00000000e+00f, -1.23717915e-01f,  0.00000000e+00f },
+    }, AmbiMatrixHOA[][MAX_AMBI_COEFFS] = {
+        { 5.55555556e-02f,  0.00000000e+00f,  1.23717915e-01f,  0.00000000e+00f,  0.00000000e+00f,  0.00000000e+00f },
+        { 5.55555556e-02f, -5.00000000e-02f,  7.14285715e-02f,  5.00000000e-02f, -4.55645099e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f, -5.00000000e-02f,  7.14285715e-02f, -5.00000000e-02f,  4.55645099e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f,  5.00000000e-02f,  7.14285715e-02f, -5.00000000e-02f, -4.55645099e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f,  5.00000000e-02f,  7.14285715e-02f,  5.00000000e-02f,  4.55645099e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f,  0.00000000e+00f,  0.00000000e+00f,  8.66025404e-02f,  0.00000000e+00f,  1.29099445e-01f },
+        { 5.55555556e-02f, -6.12372435e-02f,  0.00000000e+00f,  6.12372435e-02f, -6.83467648e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f, -8.66025404e-02f,  0.00000000e+00f,  0.00000000e+00f,  0.00000000e+00f, -1.29099445e-01f },
+        { 5.55555556e-02f, -6.12372435e-02f,  0.00000000e+00f, -6.12372435e-02f,  6.83467648e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f,  0.00000000e+00f,  0.00000000e+00f, -8.66025404e-02f,  0.00000000e+00f,  1.29099445e-01f },
+        { 5.55555556e-02f,  6.12372435e-02f,  0.00000000e+00f, -6.12372435e-02f, -6.83467648e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f,  8.66025404e-02f,  0.00000000e+00f,  0.00000000e+00f,  0.00000000e+00f, -1.29099445e-01f },
+        { 5.55555556e-02f,  6.12372435e-02f,  0.00000000e+00f,  6.12372435e-02f,  6.83467648e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f, -5.00000000e-02f, -7.14285715e-02f,  5.00000000e-02f, -4.55645099e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f, -5.00000000e-02f, -7.14285715e-02f, -5.00000000e-02f,  4.55645099e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f,  5.00000000e-02f, -7.14285715e-02f, -5.00000000e-02f, -4.55645099e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f,  5.00000000e-02f, -7.14285715e-02f,  5.00000000e-02f,  4.55645099e-02f,  0.00000000e+00f },
+        { 5.55555556e-02f,  0.00000000e+00f, -1.23717915e-01f,  0.00000000e+00f,  0.00000000e+00f,  0.00000000e+00f },
+    };
+    static const ALfloat AmbiOrderHFGainFOA[MAX_AMBI_ORDER+1] = {
+        1.00000000e+00f, 5.77350269e-01f
+    }, AmbiOrderHFGainHOA[MAX_AMBI_ORDER+1] = {
+        9.80580676e-01f, 7.59554525e-01f, 3.92232270e-01f
     };
-    const ALfloat (*AmbiMatrix)[2][MAX_AMBI_COEFFS] = device->AmbiUp ? AmbiMatrixHOA :
-                                                                       AmbiMatrixFOA;
-    ALsizei count = device->AmbiUp ? 9 : 4;
+    static const ALsizei IndexMap[6] = { 0, 1, 2, 3, 4, 8 };
+    const ALfloat (*restrict AmbiMatrix)[MAX_AMBI_COEFFS] = AmbiMatrixFOA;
+    const ALfloat *restrict AmbiOrderHFGain = AmbiOrderHFGainFOA;
+    ALsizei count = 4;
     ALsizei i;
 
+    static_assert(COUNTOF(AmbiPoints) == COUNTOF(AmbiMatrixFOA), "FOA Ambisonic HRTF mismatch");
+    static_assert(COUNTOF(AmbiPoints) == COUNTOF(AmbiMatrixHOA), "HOA Ambisonic HRTF mismatch");
     static_assert(COUNTOF(AmbiPoints) <= HRTF_AMBI_MAX_CHANNELS, "HRTF_AMBI_MAX_CHANNELS is too small");
 
+    if(device->AmbiUp)
+    {
+        AmbiMatrix = AmbiMatrixHOA;
+        AmbiOrderHFGain = AmbiOrderHFGainHOA;
+        count = COUNTOF(IndexMap);
+    }
+
     device->Hrtf = al_calloc(16, FAM_SIZE(DirectHrtfState, Chan, count));
 
     for(i = 0;i < count;i++)
     {
         device->Dry.Ambi.Map[i].Scale = 1.0f;
-        device->Dry.Ambi.Map[i].Index = i;
+        device->Dry.Ambi.Map[i].Index = IndexMap[i];
     }
     device->Dry.CoeffCount = 0;
     device->Dry.NumChannels = count;
@@ -949,7 +914,8 @@ static void InitHrtfPanning(ALCdevice *device)
         device->FOAOut.CoeffCount = 0;
         device->FOAOut.NumChannels = 4;
 
-        ambiup_reset(device->AmbiUp, device);
+        ambiup_reset(device->AmbiUp, device, AmbiOrderHFGainFOA[0] / AmbiOrderHFGain[0],
+                     AmbiOrderHFGainFOA[1] / AmbiOrderHFGain[1]);
     }
     else
     {
@@ -960,10 +926,27 @@ static void InitHrtfPanning(ALCdevice *device)
 
     device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
 
-    device->Hrtf->IrSize = BuildBFormatHrtf(device->HrtfHandle,
-        device->Hrtf, device->Dry.NumChannels,
-        AmbiPoints, AmbiMatrix, COUNTOF(AmbiPoints)
+    BuildBFormatHrtf(device->HrtfHandle,
+        device->Hrtf, device->Dry.NumChannels, AmbiPoints, AmbiMatrix, COUNTOF(AmbiPoints),
+        AmbiOrderHFGain
     );
+
+    if(GetConfigValueBool(alstr_get_cstr(device->DeviceName), "decoder", "nfc", 1) &&
+       device->HrtfHandle->distance > 0.0f)
+    {
+        /* NFC is only used when AvgSpeakerDist is greater than 0, and can only
+         * be used when rendering to an ambisonic buffer.
+         */
+        device->AvgSpeakerDist = minf(device->HrtfHandle->distance, 10.0f);
+
+        i = 0;
+        device->Dry.NumChannelsPerOrder[i++] = 1;
+        device->Dry.NumChannelsPerOrder[i++] = 3;
+        if(device->AmbiUp)
+            device->Dry.NumChannelsPerOrder[i++] = 2;
+        while(i < MAX_AMBI_ORDER+1)
+            device->Dry.NumChannelsPerOrder[i++] = 0;
+    }
 }
 
 static void InitUhjPanning(ALCdevice *device)
@@ -1016,6 +999,9 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
         device->ChannelDelay[i].Length = 0;
     }
 
+    al_free(device->Stablizer);
+    device->Stablizer = NULL;
+
     if(device->FmtChans != DevFmtStereo)
     {
         ALsizei speakermap[MAX_OUTPUT_CHANNELS];
@@ -1066,25 +1052,20 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
 
         if(pconf && GetConfigValueBool(devname, "decoder", "hq-mode", 0))
         {
-            ambiup_free(device->AmbiUp);
-            device->AmbiUp = NULL;
+            ambiup_free(&device->AmbiUp);
             if(!device->AmbiDecoder)
                 device->AmbiDecoder = bformatdec_alloc();
         }
         else
         {
-            bformatdec_free(device->AmbiDecoder);
-            device->AmbiDecoder = NULL;
-            if(device->FmtChans == DevFmtAmbi3D && device->AmbiOrder > 1)
+            bformatdec_free(&device->AmbiDecoder);
+            if(device->FmtChans != DevFmtAmbi3D || device->AmbiOrder < 2)
+                ambiup_free(&device->AmbiUp);
+            else
             {
                 if(!device->AmbiUp)
                     device->AmbiUp = ambiup_alloc();
             }
-            else
-            {
-                ambiup_free(device->AmbiUp);
-                device->AmbiUp = NULL;
-            }
         }
 
         if(!pconf)
@@ -1094,12 +1075,48 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
         else
             InitCustomPanning(device, pconf, speakermap);
 
+        /* Enable the stablizer only for formats that have front-left, front-
+         * right, and front-center outputs.
+         */
+        switch(device->FmtChans)
+        {
+        case DevFmtX51:
+        case DevFmtX51Rear:
+        case DevFmtX61:
+        case DevFmtX71:
+            if(GetConfigValueBool(devname, NULL, "front-stablizer", 0))
+            {
+                /* Initialize band-splitting filters for the front-left and
+                 * front-right channels, with a crossover at 5khz (could be
+                 * higher).
+                 */
+                ALfloat scale = (ALfloat)(5000.0 / device->Frequency);
+                FrontStablizer *stablizer = al_calloc(16, sizeof(*stablizer));
+
+                bandsplit_init(&stablizer->LFilter, scale);
+                stablizer->RFilter = stablizer->LFilter;
+
+                /* Initialize all-pass filters for all other channels. */
+                splitterap_init(&stablizer->APFilter[0], scale);
+                for(i = 1;i < (size_t)device->RealOut.NumChannels;i++)
+                    stablizer->APFilter[i] = stablizer->APFilter[0];
+
+                device->Stablizer = stablizer;
+            }
+            break;
+        case DevFmtMono:
+        case DevFmtStereo:
+        case DevFmtQuad:
+        case DevFmtAmbi3D:
+            break;
+        }
+        TRACE("Front stablizer %s\n", device->Stablizer ? "enabled" : "disabled");
+
         ambdec_deinit(&conf);
         return;
     }
 
-    bformatdec_free(device->AmbiDecoder);
-    device->AmbiDecoder = NULL;
+    bformatdec_free(&device->AmbiDecoder);
 
     headphones = device->IsHeadphones;
     if(device->Type != Loopback)
@@ -1191,8 +1208,7 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
             /* Don't bother with HOA when using full HRTF rendering. Nothing
              * needs it, and it eases the CPU/memory load.
              */
-            ambiup_free(device->AmbiUp);
-            device->AmbiUp = NULL;
+            ambiup_free(&device->AmbiUp);
         }
         else
         {
@@ -1217,8 +1233,7 @@ no_hrtf:
 
     device->Render_Mode = StereoPair;
 
-    ambiup_free(device->AmbiUp);
-    device->AmbiUp = NULL;
+    ambiup_free(&device->AmbiUp);
 
     bs2blevel = ((headphones && hrtf_appreq != Hrtf_Disable) ||
                  (hrtf_appreq == Hrtf_Enable)) ? 5 : 0;

+ 105 - 0
libs/openal-soft/Alc/polymorphism.h

@@ -0,0 +1,105 @@
+#ifndef POLYMORPHISM_H
+#define POLYMORPHISM_H
+
+/* Macros to declare inheriting types, and to (down-)cast and up-cast. */
+#define DERIVE_FROM_TYPE(t)          t t##_parent
+#define STATIC_CAST(to, obj)         (&(obj)->to##_parent)
+#ifdef __GNUC__
+#define STATIC_UPCAST(to, from, obj) __extension__({                          \
+    static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))),       \
+                  "Invalid upcast object from type");                         \
+    (to*)((char*)(obj) - offsetof(to, from##_parent));                        \
+})
+#else
+#define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent)))
+#endif
+
+/* Defines method forwards, which call the given parent's (T2's) implementation. */
+#define DECLARE_FORWARD(T1, T2, rettype, func)                                \
+rettype T1##_##func(T1 *obj)                                                  \
+{ return T2##_##func(STATIC_CAST(T2, obj)); }
+
+#define DECLARE_FORWARD1(T1, T2, rettype, func, argtype1)                     \
+rettype T1##_##func(T1 *obj, argtype1 a)                                      \
+{ return T2##_##func(STATIC_CAST(T2, obj), a); }
+
+#define DECLARE_FORWARD2(T1, T2, rettype, func, argtype1, argtype2)           \
+rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b)                          \
+{ return T2##_##func(STATIC_CAST(T2, obj), a, b); }
+
+#define DECLARE_FORWARD3(T1, T2, rettype, func, argtype1, argtype2, argtype3) \
+rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b, argtype3 c)              \
+{ return T2##_##func(STATIC_CAST(T2, obj), a, b, c); }
+
+/* Defines method thunks, functions that call to the child's method. */
+#define DECLARE_THUNK(T1, T2, rettype, func)                                  \
+static rettype T1##_##T2##_##func(T2 *obj)                                    \
+{ return T1##_##func(STATIC_UPCAST(T1, T2, obj)); }
+
+#define DECLARE_THUNK1(T1, T2, rettype, func, argtype1)                       \
+static rettype T1##_##T2##_##func(T2 *obj, argtype1 a)                        \
+{ return T1##_##func(STATIC_UPCAST(T1, T2, obj), a); }
+
+#define DECLARE_THUNK2(T1, T2, rettype, func, argtype1, argtype2)             \
+static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b)            \
+{ return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b); }
+
+#define DECLARE_THUNK3(T1, T2, rettype, func, argtype1, argtype2, argtype3)   \
+static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \
+{ return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); }
+
+#define DECLARE_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); }
+
+/* Defines the default functions used to (de)allocate a polymorphic object. */
+#define DECLARE_DEFAULT_ALLOCATORS(T)                                         \
+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 virtual method calls. */
+#define EXTRACT_VCALL_ARGS(...)  __VA_ARGS__))
+
+/* Call a "virtual" method on an object, with arguments. */
+#define V(obj, func)  ((obj)->vtbl->func((obj), EXTRACT_VCALL_ARGS
+/* Call a "virtual" method on an object, with no arguments. */
+#define V0(obj, func) ((obj)->vtbl->func((obj) EXTRACT_VCALL_ARGS
+
+
+/* Helper to extract an argument list for NEW_OBJ calls. */
+#define EXTRACT_NEW_ARGS(...)  __VA_ARGS__);                                  \
+    }                                                                         \
+} while(0)
+
+/* Allocate and construct an object, with arguments. */
+#define NEW_OBJ(_res, T) do {                                                 \
+    _res = T##_New(sizeof(T));                                                \
+    if(_res)                                                                  \
+    {                                                                         \
+        memset(_res, 0, sizeof(T));                                           \
+        T##_Construct(_res, EXTRACT_NEW_ARGS
+/* Allocate and construct an object, with no arguments. */
+#define NEW_OBJ0(_res, T) do {                                                \
+    _res = T##_New(sizeof(T));                                                \
+    if(_res)                                                                  \
+    {                                                                         \
+        memset(_res, 0, sizeof(T));                                           \
+        T##_Construct(_res EXTRACT_NEW_ARGS
+
+/* Destructs and deallocate an object. */
+#define DELETE_OBJ(obj) do {                                                  \
+    if((obj) != NULL)                                                         \
+    {                                                                         \
+        V0((obj),Destruct)();                                                 \
+        V0((obj),Delete)();                                                   \
+    }                                                                         \
+} while(0)
+
+
+/* Helper to get a type's vtable thunk for a child type. */
+#define GET_VTABLE2(T1, T2) (&(T1##_##T2##_vtable))
+/* Helper to set an object's vtable thunk for a child type. Used when constructing an object. */
+#define SET_VTABLE2(T1, T2, obj) (STATIC_CAST(T2, obj)->vtbl = GET_VTABLE2(T1, T2))
+
+#endif /* POLYMORPHISM_H */

+ 44 - 66
libs/openal-soft/Alc/alcRing.c → libs/openal-soft/Alc/ringbuffer.c

@@ -22,8 +22,11 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <limits.h>
 
-#include "alMain.h"
+#include "ringbuffer.h"
+#include "align.h"
+#include "atomic.h"
 #include "threads.h"
 #include "almalloc.h"
 #include "compat.h"
@@ -39,85 +42,70 @@ struct ll_ringbuffer {
     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 *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes)
 {
     ll_ringbuffer_t *rb;
-    ALuint power_of_two;
+    size_t power_of_two = 0;
 
-    power_of_two = NextPowerOf2(sz);
-    if(power_of_two < sz)
-        return NULL;
+    if(sz > 0)
+    {
+        power_of_two = sz;
+        power_of_two |= power_of_two>>1;
+        power_of_two |= power_of_two>>2;
+        power_of_two |= power_of_two>>4;
+        power_of_two |= power_of_two>>8;
+        power_of_two |= power_of_two>>16;
+#if SIZE_MAX > UINT_MAX
+        power_of_two |= power_of_two>>32;
+#endif
+    }
+    power_of_two++;
+    if(power_of_two < sz) return NULL;
 
     rb = al_malloc(16, sizeof(*rb) + power_of_two*elem_sz);
     if(!rb) return NULL;
 
     ATOMIC_INIT(&rb->write_ptr, 0);
     ATOMIC_INIT(&rb->read_ptr, 0);
-    rb->size = power_of_two;
-    rb->size_mask = rb->size - 1;
+    rb->size = limit_writes ? sz : power_of_two;
+    rb->size_mask = power_of_two - 1;
     rb->elem_size = elem_sz;
-    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->mlocked && mlock(rb, sizeof(*rb) + rb->size*rb->elem_size))
-        return -1;
-#endif /* USE_MLOCK */
-    rb->mlocked = 1;
-    return 0;
+    al_free(rb);
 }
 
-/* Reset the read and write pointers to zero. This is not thread safe. */
 void ll_ringbuffer_reset(ll_ringbuffer_t *rb)
 {
     ATOMIC_STORE(&rb->write_ptr, 0, almemory_order_release);
     ATOMIC_STORE(&rb->read_ptr, 0, almemory_order_release);
-    memset(rb->buf, 0, rb->size*rb->elem_size);
+    memset(rb->buf, 0, (rb->size_mask+1)*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 = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire);
     size_t r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire);
     return (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 = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire);
     size_t r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire);
-    return (r-w-1) & rb->size_mask;
+    w = (r-w-1) & rb->size_mask;
+    return (w > rb->size) ? rb->size : w;
 }
 
-/* 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 read_ptr;
@@ -133,9 +121,9 @@ size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt)
     read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask;
 
     cnt2 = read_ptr + to_read;
-    if(cnt2 > rb->size)
+    if(cnt2 > rb->size_mask+1)
     {
-        n1 = rb->size - read_ptr;
+        n1 = rb->size_mask+1 - read_ptr;
         n2 = cnt2 & rb->size_mask;
     }
     else
@@ -156,9 +144,6 @@ size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt)
     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;
@@ -174,9 +159,9 @@ size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt)
     read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask;
 
     cnt2 = read_ptr + to_read;
-    if(cnt2 > rb->size)
+    if(cnt2 > rb->size_mask+1)
     {
-        n1 = rb->size - read_ptr;
+        n1 = rb->size_mask+1 - read_ptr;
         n2 = cnt2 & rb->size_mask;
     }
     else
@@ -195,8 +180,6 @@ size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt)
     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 write_ptr;
@@ -212,9 +195,9 @@ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt)
     write_ptr = ATOMIC_LOAD(&rb->write_ptr, almemory_order_relaxed) & rb->size_mask;
 
     cnt2 = write_ptr + to_write;
-    if(cnt2 > rb->size)
+    if(cnt2 > rb->size_mask+1)
     {
-        n1 = rb->size - write_ptr;
+        n1 = rb->size_mask+1 - write_ptr;
         n2 = cnt2 & rb->size_mask;
     }
     else
@@ -235,22 +218,19 @@ size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt)
     return to_write;
 }
 
-/* Advance the read pointer `cnt' places. */
+
 void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt)
 {
     ATOMIC_ADD(&rb->read_ptr, cnt, almemory_order_acq_rel);
 }
 
-/* Advance the write pointer `cnt' places. */
 void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt)
 {
     ATOMIC_ADD(&rb->write_ptr, cnt, almemory_order_acq_rel);
 }
 
-/* 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)
+
+void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t vec[2])
 {
     size_t free_cnt;
     size_t cnt2;
@@ -263,12 +243,12 @@ void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data
     free_cnt = (w-r) & rb->size_mask;
 
     cnt2 = r + free_cnt;
-    if(cnt2 > rb->size)
+    if(cnt2 > rb->size_mask+1)
     {
         /* 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[0].len = rb->size_mask+1 - r;
         vec[1].buf = (char*)rb->buf;
         vec[1].len = cnt2 & rb->size_mask;
     }
@@ -282,10 +262,7 @@ void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data
     }
 }
 
-/* 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)
+void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t vec[2])
 {
     size_t free_cnt;
     size_t cnt2;
@@ -296,14 +273,15 @@ void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_dat
     w &= rb->size_mask;
     r &= rb->size_mask;
     free_cnt = (r-w-1) & rb->size_mask;
+    if(free_cnt > rb->size) free_cnt = rb->size;
 
     cnt2 = w + free_cnt;
-    if(cnt2 > rb->size)
+    if(cnt2 > rb->size_mask+1)
     {
         /* 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[0].len = rb->size_mask+1 - w;
         vec[1].buf = (char*)rb->buf;
         vec[1].len = cnt2 & rb->size_mask;
     }

+ 77 - 0
libs/openal-soft/Alc/ringbuffer.h

@@ -0,0 +1,77 @@
+#ifndef RINGBUFFER_H
+#define RINGBUFFER_H
+
+#include <stddef.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct ll_ringbuffer ll_ringbuffer_t;
+typedef struct ll_ringbuffer_data {
+    char *buf;
+    size_t len;
+} ll_ringbuffer_data_t;
+
+
+/**
+ * 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 (even if it is
+ * already a power of two, to ensure the requested amount can be written).
+ */
+ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz, int limit_writes);
+/** Free all data associated with the ringbuffer `rb'. */
+void ll_ringbuffer_free(ll_ringbuffer_t *rb);
+/** Reset the read and write pointers to zero. This is not thread safe. */
+void ll_ringbuffer_reset(ll_ringbuffer_t *rb);
+
+/**
+ * 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[2]);
+/**
+ * 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[2]);
+
+/**
+ * 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);
+/**
+ * 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);
+/**
+ * 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);
+/** Advance the read pointer `cnt' places. */
+void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt);
+
+/**
+ * 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);
+/**
+ * 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);
+/** Advance the write pointer `cnt' places. */
+void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* RINGBUFFER_H */

+ 17 - 9
libs/openal-soft/Alc/uhjfilter.c

@@ -20,16 +20,24 @@ static void allpass_process(AllPassState *state, ALfloat *restrict dst, const AL
 {
     ALsizei i;
 
-    if(todo > 1)
+    if(LIKELY(todo > 1))
     {
-        dst[0] = aa*(src[0] + state->y[1]) - state->x[1];
-        dst[1] = aa*(src[1] + state->y[0]) - state->x[0];
-        for(i = 2;i < todo;i++)
-            dst[i] = aa*(src[i] + dst[i-2]) - src[i-2];
-        state->x[1] = src[i-2];
-        state->x[0] = src[i-1];
-        state->y[1] = dst[i-2];
-        state->y[0] = dst[i-1];
+        ALfloat x0 = state->x[0];
+        ALfloat x1 = state->x[1];
+        ALfloat y0 = state->y[0];
+        ALfloat y1 = state->y[1];
+
+        for(i = 0;i < todo;i++)
+        {
+            dst[i] = aa*(src[i] + y1) - x1;
+            y1 = y0; y0 = dst[i];
+            x1 = x0; x0 = src[i];
+        }
+
+        state->x[0] = x0;
+        state->x[1] = x1;
+        state->y[0] = y0;
+        state->y[1] = y1;
     }
     else if(todo == 1)
     {

+ 2 - 1
libs/openal-soft/Alc/vector.h

@@ -37,7 +37,8 @@ typedef const _##N* const_##N;
                                                                               \
     if(((_x) ? (_x)->Capacity : 0) < _cap)                                    \
     {                                                                         \
-        ptrdiff_t data_offset = (char*)((_x)->Data) - (char*)(_x);            \
+        ptrdiff_t data_offset = (_x) ? (char*)((_x)->Data) - (char*)(_x) :    \
+                                sizeof(*(_x));                                \
         size_t old_size = ((_x) ? (_x)->Size : 0);                            \
         void *temp;                                                           \
                                                                               \

File diff suppressed because it is too large
+ 338 - 250
libs/openal-soft/CMakeLists.txt


+ 37 - 44
libs/openal-soft/OpenAL32/Include/alAuxEffectSlot.h

@@ -29,16 +29,21 @@ struct ALeffectStateVtable {
     void (*const Destruct)(ALeffectState *state);
 
     ALboolean (*const deviceUpdate)(ALeffectState *state, ALCdevice *device);
-    void (*const update)(ALeffectState *state, const ALCdevice *device, const struct ALeffectslot *slot, const union ALeffectProps *props);
+    void (*const update)(ALeffectState *state, const ALCcontext *context, const struct ALeffectslot *slot, const union ALeffectProps *props);
     void (*const process)(ALeffectState *state, ALsizei samplesToDo, const ALfloat (*restrict samplesIn)[BUFFERSIZE], ALfloat (*restrict samplesOut)[BUFFERSIZE], ALsizei numChannels);
 
     void (*const Delete)(void *ptr);
 };
 
+/* Small hack to use a pointer-to-array types as a normal argument type.
+ * Shouldn't be used directly.
+ */
+typedef ALfloat ALfloatBUFFERSIZE[BUFFERSIZE];
+
 #define DEFINE_ALEFFECTSTATE_VTABLE(T)                                        \
 DECLARE_THUNK(T, ALeffectState, void, Destruct)                               \
 DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*)         \
-DECLARE_THUNK3(T, ALeffectState, void, update, const ALCdevice*, const ALeffectslot*, const ALeffectProps*) \
+DECLARE_THUNK3(T, ALeffectState, void, update, const ALCcontext*, const ALeffectslot*, const ALeffectProps*) \
 DECLARE_THUNK4(T, ALeffectState, void, process, ALsizei, const ALfloatBUFFERSIZE*restrict, ALfloatBUFFERSIZE*restrict, ALsizei) \
 static void T##_ALeffectState_Delete(void *ptr)                               \
 { return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); }  \
@@ -54,21 +59,22 @@ static const struct ALeffectStateVtable T##_ALeffectState_vtable = {          \
 }
 
 
-struct ALeffectStateFactoryVtable;
+struct EffectStateFactoryVtable;
 
-typedef struct ALeffectStateFactory {
-    const struct ALeffectStateFactoryVtable *vtbl;
-} ALeffectStateFactory;
+typedef struct EffectStateFactory {
+    const struct EffectStateFactoryVtable *vtab;
+} EffectStateFactory;
 
-struct ALeffectStateFactoryVtable {
-    ALeffectState *(*const create)(ALeffectStateFactory *factory);
+struct EffectStateFactoryVtable {
+    ALeffectState *(*const create)(EffectStateFactory *factory);
 };
+#define EffectStateFactory_create(x) ((x)->vtab->create((x)))
 
-#define DEFINE_ALEFFECTSTATEFACTORY_VTABLE(T)                                 \
-DECLARE_THUNK(T, ALeffectStateFactory, ALeffectState*, create)                \
+#define DEFINE_EFFECTSTATEFACTORY_VTABLE(T)                                   \
+DECLARE_THUNK(T, EffectStateFactory, ALeffectState*, create)                  \
                                                                               \
-static const struct ALeffectStateFactoryVtable T##_ALeffectStateFactory_vtable = { \
-    T##_ALeffectStateFactory_create,                                          \
+static const struct EffectStateFactoryVtable T##_EffectStateFactory_vtable = { \
+    T##_EffectStateFactory_create,                                            \
 }
 
 
@@ -110,17 +116,18 @@ typedef struct ALeffectslot {
     RefCount ref;
 
     ATOMIC(struct ALeffectslotProps*) Update;
-    ATOMIC(struct ALeffectslotProps*) FreeList;
 
     struct {
         ALfloat   Gain;
         ALboolean AuxSendAuto;
 
         ALenum EffectType;
+        ALeffectProps EffectProps;
         ALeffectState *EffectState;
 
         ALfloat RoomRolloff; /* Added to the source's room rolloff, not multiplied. */
         ALfloat DecayTime;
+        ALfloat DecayLFRatio;
         ALfloat DecayHFRatio;
         ALboolean DecayHFLimit;
         ALfloat AirAbsorptionGainHF;
@@ -133,9 +140,9 @@ typedef struct ALeffectslot {
     BFChannelConfig ChanMap[MAX_EFFECT_CHANNELS];
     /* Wet buffer configuration is ACN channel order with N3D scaling:
      * * Channel 0 is the unattenuated mono signal.
-     * * Channel 1 is OpenAL -X
-     * * Channel 2 is OpenAL Y
-     * * Channel 3 is OpenAL -Z
+     * * Channel 1 is OpenAL -X * sqrt(3)
+     * * Channel 2 is OpenAL Y * sqrt(3)
+     * * Channel 3 is OpenAL -Z * sqrt(3)
      * Consequently, effects that only want to work with mono input can use
      * channel 0 by itself. Effects that want multichannel can process the
      * ambisonics signal and make a B-Format pan (ComputeFirstOrderGains) for
@@ -144,44 +151,30 @@ typedef struct ALeffectslot {
     alignas(16) ALfloat WetBuffer[MAX_EFFECT_CHANNELS][BUFFERSIZE];
 } ALeffectslot;
 
-inline void LockEffectSlotsRead(ALCcontext *context)
-{ LockUIntMapRead(&context->EffectSlotMap); }
-inline void UnlockEffectSlotsRead(ALCcontext *context)
-{ UnlockUIntMapRead(&context->EffectSlotMap); }
-inline void LockEffectSlotsWrite(ALCcontext *context)
-{ LockUIntMapWrite(&context->EffectSlotMap); }
-inline void UnlockEffectSlotsWrite(ALCcontext *context)
-{ UnlockUIntMapWrite(&context->EffectSlotMap); }
-
-inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)
-{ return (struct ALeffectslot*)LookupUIntMapKeyNoLock(&context->EffectSlotMap, id); }
-inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id)
-{ return (struct ALeffectslot*)RemoveUIntMapKeyNoLock(&context->EffectSlotMap, id); }
-
 ALenum InitEffectSlot(ALeffectslot *slot);
 void DeinitEffectSlot(ALeffectslot *slot);
-void UpdateEffectSlotProps(ALeffectslot *slot);
+void UpdateEffectSlotProps(ALeffectslot *slot, ALCcontext *context);
 void UpdateAllEffectSlotProps(ALCcontext *context);
 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context);
 
 
-ALeffectStateFactory *ALnullStateFactory_getFactory(void);
-ALeffectStateFactory *ALreverbStateFactory_getFactory(void);
-ALeffectStateFactory *ALchorusStateFactory_getFactory(void);
-ALeffectStateFactory *ALcompressorStateFactory_getFactory(void);
-ALeffectStateFactory *ALdistortionStateFactory_getFactory(void);
-ALeffectStateFactory *ALechoStateFactory_getFactory(void);
-ALeffectStateFactory *ALequalizerStateFactory_getFactory(void);
-ALeffectStateFactory *ALflangerStateFactory_getFactory(void);
-ALeffectStateFactory *ALmodulatorStateFactory_getFactory(void);
+EffectStateFactory *NullStateFactory_getFactory(void);
+EffectStateFactory *ReverbStateFactory_getFactory(void);
+EffectStateFactory *ChorusStateFactory_getFactory(void);
+EffectStateFactory *CompressorStateFactory_getFactory(void);
+EffectStateFactory *DistortionStateFactory_getFactory(void);
+EffectStateFactory *EchoStateFactory_getFactory(void);
+EffectStateFactory *EqualizerStateFactory_getFactory(void);
+EffectStateFactory *FlangerStateFactory_getFactory(void);
+EffectStateFactory *ModulatorStateFactory_getFactory(void);
+EffectStateFactory *PshifterStateFactory_getFactory(void);
 
-ALeffectStateFactory *ALdedicatedStateFactory_getFactory(void);
+EffectStateFactory *DedicatedStateFactory_getFactory(void);
 
 
-ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect);
+ALenum InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect);
 
-void InitEffectFactoryMap(void);
-void DeinitEffectFactoryMap(void);
+void ALeffectState_DecRef(ALeffectState *state);
 
 #ifdef __cplusplus
 }

+ 39 - 52
libs/openal-soft/OpenAL32/Include/alBuffer.h

@@ -1,7 +1,13 @@
 #ifndef _AL_BUFFER_H_
 #define _AL_BUFFER_H_
 
-#include "alMain.h"
+#include "AL/alc.h"
+#include "AL/al.h"
+#include "AL/alext.h"
+
+#include "inprogext.h"
+#include "atomic.h"
+#include "rwlock.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -9,29 +15,25 @@ extern "C" {
 
 /* User formats */
 enum UserFmtType {
-    UserFmtByte   = AL_BYTE_SOFT,
-    UserFmtUByte  = AL_UNSIGNED_BYTE_SOFT,
-    UserFmtShort  = AL_SHORT_SOFT,
-    UserFmtUShort = AL_UNSIGNED_SHORT_SOFT,
-    UserFmtInt    = AL_INT_SOFT,
-    UserFmtUInt   = AL_UNSIGNED_INT_SOFT,
-    UserFmtFloat  = AL_FLOAT_SOFT,
-    UserFmtDouble = AL_DOUBLE_SOFT,
-    UserFmtMulaw  = AL_MULAW_SOFT,
-    UserFmtAlaw   = 0x10000000,
+    UserFmtUByte,
+    UserFmtShort,
+    UserFmtFloat,
+    UserFmtDouble,
+    UserFmtMulaw,
+    UserFmtAlaw,
     UserFmtIMA4,
     UserFmtMSADPCM,
 };
 enum UserFmtChannels {
-    UserFmtMono      = AL_MONO_SOFT,
-    UserFmtStereo    = AL_STEREO_SOFT,
-    UserFmtRear      = AL_REAR_SOFT,
-    UserFmtQuad      = AL_QUAD_SOFT,
-    UserFmtX51       = AL_5POINT1_SOFT, /* (WFX order) */
-    UserFmtX61       = AL_6POINT1_SOFT, /* (WFX order) */
-    UserFmtX71       = AL_7POINT1_SOFT, /* (WFX order) */
-    UserFmtBFormat2D = AL_BFORMAT2D_SOFT, /* WXY */
-    UserFmtBFormat3D = AL_BFORMAT3D_SOFT, /* WXYZ */
+    UserFmtMono,
+    UserFmtStereo,
+    UserFmtRear,
+    UserFmtQuad,
+    UserFmtX51, /* (WFX order) */
+    UserFmtX61, /* (WFX order) */
+    UserFmtX71, /* (WFX order) */
+    UserFmtBFormat2D, /* WXY */
+    UserFmtBFormat3D, /* WXYZ */
 };
 
 ALsizei BytesFromUserFmt(enum UserFmtType type);
@@ -44,9 +46,12 @@ inline ALsizei FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType
 
 /* Storable formats */
 enum FmtType {
-    FmtByte  = UserFmtByte,
-    FmtShort = UserFmtShort,
-    FmtFloat = UserFmtFloat,
+    FmtUByte  = UserFmtUByte,
+    FmtShort  = UserFmtShort,
+    FmtFloat  = UserFmtFloat,
+    FmtDouble = UserFmtDouble,
+    FmtMulaw  = UserFmtMulaw,
+    FmtAlaw   = UserFmtAlaw,
 };
 enum FmtChannels {
     FmtMono   = UserFmtMono,
@@ -72,18 +77,17 @@ inline ALsizei FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type)
 typedef struct ALbuffer {
     ALvoid  *data;
 
-    ALsizei  Frequency;
-    ALenum   Format;
-    ALsizei  SampleLen;
+    ALsizei Frequency;
+    ALbitfieldSOFT Access;
+    ALsizei SampleLen;
 
     enum FmtChannels FmtChannels;
     enum FmtType     FmtType;
-    ALuint BytesAlloc;
+    ALsizei BytesAlloc;
 
-    enum UserFmtChannels OriginalChannels;
-    enum UserFmtType     OriginalType;
-    ALsizei              OriginalSize;
-    ALsizei              OriginalAlign;
+    enum UserFmtType OriginalType;
+    ALsizei OriginalSize;
+    ALsizei OriginalAlign;
 
     ALsizei LoopStart;
     ALsizei LoopEnd;
@@ -91,34 +95,17 @@ typedef struct ALbuffer {
     ATOMIC(ALsizei) UnpackAlign;
     ATOMIC(ALsizei) PackAlign;
 
+    ALbitfieldSOFT MappedAccess;
+    ALsizei MappedOffset;
+    ALsizei MappedSize;
+
     /* Number of times buffer was attached to a source (deletion can only occur when 0) */
     RefCount ref;
 
-    RWLock lock;
-
     /* Self ID */
     ALuint id;
 } ALbuffer;
 
-ALbuffer *NewBuffer(ALCcontext *context);
-void DeleteBuffer(ALCdevice *device, ALbuffer *buffer);
-
-ALenum LoadData(ALbuffer *buffer, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc);
-
-inline void LockBuffersRead(ALCdevice *device)
-{ LockUIntMapRead(&device->BufferMap); }
-inline void UnlockBuffersRead(ALCdevice *device)
-{ UnlockUIntMapRead(&device->BufferMap); }
-inline void LockBuffersWrite(ALCdevice *device)
-{ LockUIntMapWrite(&device->BufferMap); }
-inline void UnlockBuffersWrite(ALCdevice *device)
-{ UnlockUIntMapWrite(&device->BufferMap); }
-
-inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id)
-{ return (struct ALbuffer*)LookupUIntMapKeyNoLock(&device->BufferMap, id); }
-inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id)
-{ return (struct ALbuffer*)RemoveUIntMapKeyNoLock(&device->BufferMap, id); }
-
 ALvoid ReleaseALBuffers(ALCdevice *device);
 
 #ifdef __cplusplus

+ 39 - 39
libs/openal-soft/OpenAL32/Include/alEffect.h

@@ -10,23 +10,32 @@ extern "C" {
 struct ALeffect;
 
 enum {
-    AL__EAXREVERB = 0,
-    AL__REVERB,
-    AL__CHORUS,
-    AL__COMPRESSOR,
-    AL__DISTORTION,
-    AL__ECHO,
-    AL__EQUALIZER,
-    AL__FLANGER,
-    AL__MODULATOR,
-    AL__DEDICATED,
+    EAXREVERB_EFFECT = 0,
+    REVERB_EFFECT,
+    CHORUS_EFFECT,
+    COMPRESSOR_EFFECT,
+    DISTORTION_EFFECT,
+    ECHO_EFFECT,
+    EQUALIZER_EFFECT,
+    FLANGER_EFFECT,
+    MODULATOR_EFFECT,
+    PSHIFTER_EFFECT,
+    DEDICATED_EFFECT,
 
     MAX_EFFECTS
 };
 extern ALboolean DisabledEffects[MAX_EFFECTS];
 
 extern ALfloat ReverbBoost;
-extern ALboolean EmulateEAXReverb;
+
+struct EffectList {
+    const char name[16];
+    int type;
+    ALenum val;
+};
+#define EFFECTLIST_SIZE 12
+extern const struct EffectList EffectList[EFFECTLIST_SIZE];
+
 
 struct ALeffectVtable {
     void (*const setParami)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALint val);
@@ -58,6 +67,7 @@ extern const struct ALeffectVtable ALequalizer_vtable;
 extern const struct ALeffectVtable ALflanger_vtable;
 extern const struct ALeffectVtable ALmodulator_vtable;
 extern const struct ALeffectVtable ALnull_vtable;
+extern const struct ALeffectVtable ALpshifter_vtable;
 extern const struct ALeffectVtable ALdedicated_vtable;
 
 
@@ -98,7 +108,7 @@ typedef union ALeffectProps {
         ALfloat Depth;
         ALfloat Feedback;
         ALfloat Delay;
-    } Chorus;
+    } Chorus; /* Also Flanger */
 
     struct {
         ALboolean OnOff;
@@ -135,21 +145,17 @@ typedef union ALeffectProps {
         ALfloat HighGain;
     } Equalizer;
 
-    struct {
-        ALint Waveform;
-        ALint Phase;
-        ALfloat Rate;
-        ALfloat Depth;
-        ALfloat Feedback;
-        ALfloat Delay;
-    } Flanger;
-
     struct {
         ALfloat Frequency;
         ALfloat HighPassCutoff;
         ALint Waveform;
     } Modulator;
 
+    struct {
+        ALint CoarseTune;
+        ALint FineTune;
+    } Pshifter;
+
     struct {
         ALfloat Gain;
     } Dedicated;
@@ -161,33 +167,27 @@ typedef struct ALeffect {
 
     ALeffectProps Props;
 
-    const struct ALeffectVtable *vtbl;
+    const struct ALeffectVtable *vtab;
 
     /* Self ID */
     ALuint id;
 } ALeffect;
-
-inline void LockEffectsRead(ALCdevice *device)
-{ LockUIntMapRead(&device->EffectMap); }
-inline void UnlockEffectsRead(ALCdevice *device)
-{ UnlockUIntMapRead(&device->EffectMap); }
-inline void LockEffectsWrite(ALCdevice *device)
-{ LockUIntMapWrite(&device->EffectMap); }
-inline void UnlockEffectsWrite(ALCdevice *device)
-{ UnlockUIntMapWrite(&device->EffectMap); }
-
-inline struct ALeffect *LookupEffect(ALCdevice *device, ALuint id)
-{ return (struct ALeffect*)LookupUIntMapKeyNoLock(&device->EffectMap, id); }
-inline struct ALeffect *RemoveEffect(ALCdevice *device, ALuint id)
-{ return (struct ALeffect*)RemoveUIntMapKeyNoLock(&device->EffectMap, id); }
+#define ALeffect_setParami(o, c, p, v)   ((o)->vtab->setParami(o, c, p, v))
+#define ALeffect_setParamf(o, c, p, v)   ((o)->vtab->setParamf(o, c, p, v))
+#define ALeffect_setParamiv(o, c, p, v)  ((o)->vtab->setParamiv(o, c, p, v))
+#define ALeffect_setParamfv(o, c, p, v)  ((o)->vtab->setParamfv(o, c, p, v))
+#define ALeffect_getParami(o, c, p, v)   ((o)->vtab->getParami(o, c, p, v))
+#define ALeffect_getParamf(o, c, p, v)   ((o)->vtab->getParamf(o, c, p, v))
+#define ALeffect_getParamiv(o, c, p, v)  ((o)->vtab->getParamiv(o, c, p, v))
+#define ALeffect_getParamfv(o, c, p, v)  ((o)->vtab->getParamfv(o, c, p, v))
 
 inline ALboolean IsReverbEffect(ALenum type)
 { return type == AL_EFFECT_REVERB || type == AL_EFFECT_EAXREVERB; }
 
-ALenum InitEffect(ALeffect *effect);
-ALvoid ReleaseALEffects(ALCdevice *device);
+void InitEffect(ALeffect *effect);
+void ReleaseALEffects(ALCdevice *device);
 
-ALvoid LoadReverbPreset(const char *name, ALeffect *effect);
+void LoadReverbPreset(const char *name, ALeffect *effect);
 
 #ifdef __cplusplus
 }

+ 8 - 12
libs/openal-soft/OpenAL32/Include/alError.h

@@ -2,6 +2,7 @@
 #define _AL_ERROR_H_
 
 #include "alMain.h"
+#include "logging.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -9,21 +10,16 @@ extern "C" {
 
 extern ALboolean TrapALError;
 
-ALvoid alSetError(ALCcontext *Context, ALenum errorCode);
+void alSetError(ALCcontext *context, ALenum errorCode, const char *msg, ...) DECL_FORMAT(printf, 3, 4);
 
-#define SET_ERROR_AND_RETURN(ctx, err) do {                                    \
-    alSetError((ctx), (err));                                                  \
-    return;                                                                    \
-} while(0)
-
-#define SET_ERROR_AND_RETURN_VALUE(ctx, err, val) do {                         \
-    alSetError((ctx), (err));                                                  \
-    return (val);                                                              \
+#define SETERR_GOTO(ctx, err, lbl, ...) do {                                   \
+    alSetError((ctx), (err), __VA_ARGS__);                                     \
+    goto lbl;                                                                  \
 } while(0)
 
-#define SET_ERROR_AND_GOTO(ctx, err, lbl) do {                                 \
-    alSetError((ctx), (err));                                                  \
-    goto lbl;                                                                  \
+#define SETERR_RETURN(ctx, err, retval, ...) do {                              \
+    alSetError((ctx), (err), __VA_ARGS__);                                     \
+    return retval;                                                             \
 } while(0)
 
 #ifdef __cplusplus

+ 30 - 127
libs/openal-soft/OpenAL32/Include/alFilter.h

@@ -1,9 +1,8 @@
 #ifndef _AL_FILTER_H_
 #define _AL_FILTER_H_
 
-#include "alMain.h"
-
-#include "math_defs.h"
+#include "AL/alc.h"
+#include "AL/al.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -13,100 +12,28 @@ extern "C" {
 #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
- */
-/* 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 {
-    /** EFX-style low-pass filter, specifying a gain and reference frequency. */
-    ALfilterType_HighShelf,
-    /** EFX-style high-pass filter, specifying a gain and reference frequency. */
-    ALfilterType_LowShelf,
-    /** Peaking filter, specifying a gain and reference frequency. */
-    ALfilterType_Peaking,
-
-    /** Low-pass cut-off filter, specifying a cut-off frequency. */
-    ALfilterType_LowPass,
-    /** High-pass cut-off filter, specifying a cut-off frequency. */
-    ALfilterType_HighPass,
-    /** Band-pass filter, specifying a center frequency. */
-    ALfilterType_BandPass,
-} ALfilterType;
-
-typedef struct ALfilterState {
-    ALfloat x[2]; /* History of two last input samples  */
-    ALfloat y[2]; /* History of two last output samples */
-    ALfloat b0, b1, b2; /* Transfer function coefficients "b" */
-    ALfloat a1, a2; /* Transfer function coefficients "a" (a0 is pre-applied) */
-} ALfilterState;
-/* Currently only a C-based filter process method is implemented. */
-#define ALfilterState_process ALfilterState_processC
-
-/* 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));
-}
-
-inline void ALfilterState_clear(ALfilterState *filter)
-{
-    filter->x[0] = 0.0f;
-    filter->x[1] = 0.0f;
-    filter->y[0] = 0.0f;
-    filter->y[1] = 0.0f;
-}
-
-void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat rcpQ);
+struct ALfilter;
 
-inline void ALfilterState_copyParams(ALfilterState *restrict dst, const ALfilterState *restrict src)
-{
-    dst->b0 = src->b0;
-    dst->b1 = src->b1;
-    dst->b2 = src->b2;
-    dst->a1 = src->a1;
-    dst->a2 = src->a2;
-}
+typedef struct ALfilterVtable {
+    void (*const setParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint val);
+    void (*const setParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals);
+    void (*const setParamf)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val);
+    void (*const setParamfv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals);
 
-void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALsizei numsamples);
+    void (*const getParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint *val);
+    void (*const getParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals);
+    void (*const getParamf)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val);
+    void (*const getParamfv)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals);
+} ALfilterVtable;
 
-inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *restrict src, ALsizei 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];
-    }
+#define DEFINE_ALFILTER_VTABLE(T)           \
+const struct ALfilterVtable T##_vtable = {  \
+    T##_setParami, T##_setParamiv,          \
+    T##_setParamf, T##_setParamfv,          \
+    T##_getParami, T##_getParamiv,          \
+    T##_getParamf, T##_getParamfv,          \
 }
 
-
 typedef struct ALfilter {
     // Filter type (AL_FILTER_NULL, ...)
     ALenum type;
@@ -117,45 +44,21 @@ typedef struct ALfilter {
     ALfloat GainLF;
     ALfloat LFReference;
 
-    void (*SetParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint val);
-    void (*SetParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals);
-    void (*SetParamf)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val);
-    void (*SetParamfv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals);
-
-    void (*GetParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint *val);
-    void (*GetParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint *vals);
-    void (*GetParamf)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val);
-    void (*GetParamfv)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals);
+    const struct ALfilterVtable *vtab;
 
     /* Self ID */
     ALuint id;
 } ALfilter;
-
-#define ALfilter_SetParami(x, c, p, v)  ((x)->SetParami((x),(c),(p),(v)))
-#define ALfilter_SetParamiv(x, c, p, v) ((x)->SetParamiv((x),(c),(p),(v)))
-#define ALfilter_SetParamf(x, c, p, v)  ((x)->SetParamf((x),(c),(p),(v)))
-#define ALfilter_SetParamfv(x, c, p, v) ((x)->SetParamfv((x),(c),(p),(v)))
-
-#define ALfilter_GetParami(x, c, p, v)  ((x)->GetParami((x),(c),(p),(v)))
-#define ALfilter_GetParamiv(x, c, p, v) ((x)->GetParamiv((x),(c),(p),(v)))
-#define ALfilter_GetParamf(x, c, p, v)  ((x)->GetParamf((x),(c),(p),(v)))
-#define ALfilter_GetParamfv(x, c, p, v) ((x)->GetParamfv((x),(c),(p),(v)))
-
-inline void LockFiltersRead(ALCdevice *device)
-{ LockUIntMapRead(&device->FilterMap); }
-inline void UnlockFiltersRead(ALCdevice *device)
-{ UnlockUIntMapRead(&device->FilterMap); }
-inline void LockFiltersWrite(ALCdevice *device)
-{ LockUIntMapWrite(&device->FilterMap); }
-inline void UnlockFiltersWrite(ALCdevice *device)
-{ UnlockUIntMapWrite(&device->FilterMap); }
-
-inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id)
-{ return (struct ALfilter*)LookupUIntMapKeyNoLock(&device->FilterMap, id); }
-inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id)
-{ return (struct ALfilter*)RemoveUIntMapKeyNoLock(&device->FilterMap, id); }
-
-ALvoid ReleaseALFilters(ALCdevice *device);
+#define ALfilter_setParami(o, c, p, v)   ((o)->vtab->setParami(o, c, p, v))
+#define ALfilter_setParamf(o, c, p, v)   ((o)->vtab->setParamf(o, c, p, v))
+#define ALfilter_setParamiv(o, c, p, v)  ((o)->vtab->setParamiv(o, c, p, v))
+#define ALfilter_setParamfv(o, c, p, v)  ((o)->vtab->setParamfv(o, c, p, v))
+#define ALfilter_getParami(o, c, p, v)   ((o)->vtab->getParami(o, c, p, v))
+#define ALfilter_getParamf(o, c, p, v)   ((o)->vtab->getParamf(o, c, p, v))
+#define ALfilter_getParamiv(o, c, p, v)  ((o)->vtab->getParamiv(o, c, p, v))
+#define ALfilter_getParamfv(o, c, p, v)  ((o)->vtab->getParamfv(o, c, p, v))
+
+void ReleaseALFilters(ALCdevice *device);
 
 #ifdef __cplusplus
 }

+ 15 - 14
libs/openal-soft/OpenAL32/Include/alListener.h

@@ -8,19 +8,23 @@
 extern "C" {
 #endif
 
+struct ALcontextProps {
+    ALfloat DopplerFactor;
+    ALfloat DopplerVelocity;
+    ALfloat SpeedOfSound;
+    ALboolean SourceDistanceModel;
+    enum DistanceModel DistanceModel;
+    ALfloat MetersPerUnit;
+
+    ATOMIC(struct ALcontextProps*) next;
+};
+
 struct ALlistenerProps {
     ALfloat Position[3];
     ALfloat Velocity[3];
     ALfloat Forward[3];
     ALfloat Up[3];
     ALfloat Gain;
-    ALfloat MetersPerUnit;
-
-    ALfloat DopplerFactor;
-    ALfloat DopplerVelocity;
-    ALfloat SpeedOfSound;
-    ALboolean SourceDistanceModel;
-    enum DistanceModel DistanceModel;
 
     ATOMIC(struct ALlistenerProps*) next;
 };
@@ -31,17 +35,13 @@ typedef struct ALlistener {
     ALfloat Forward[3];
     ALfloat Up[3];
     ALfloat Gain;
-    ALfloat MetersPerUnit;
+
+    ATOMIC_FLAG PropsClean;
 
     /* Pointer to the most recent property values that are awaiting an update.
      */
     ATOMIC(struct ALlistenerProps*) Update;
 
-    /* A linked list of unused property containers, free to use for future
-     * updates.
-     */
-    ATOMIC(struct ALlistenerProps*) FreeList;
-
     struct {
         aluMatrixf Matrix;
         aluVector  Velocity;
@@ -50,7 +50,8 @@ typedef struct ALlistener {
         ALfloat MetersPerUnit;
 
         ALfloat DopplerFactor;
-        ALfloat SpeedOfSound;
+        ALfloat SpeedOfSound; /* in units per sec! */
+        ALfloat ReverbSpeedOfSound; /* in meters per sec! */
 
         ALboolean SourceDistanceModel;
         enum DistanceModel DistanceModel;

+ 234 - 556
libs/openal-soft/OpenAL32/Include/alMain.h

@@ -12,133 +12,25 @@
 #ifdef HAVE_STRINGS_H
 #include <strings.h>
 #endif
-
-#ifdef HAVE_FENV_H
-#include <fenv.h>
+#ifdef HAVE_INTRIN_H
+#include <intrin.h>
 #endif
 
 #include "AL/al.h"
 #include "AL/alc.h"
 #include "AL/alext.h"
 
+#include "inprogext.h"
+#include "logging.h"
+#include "polymorphism.h"
 #include "static_assert.h"
 #include "align.h"
 #include "atomic.h"
-#include "uintmap.h"
 #include "vector.h"
 #include "alstring.h"
 #include "almalloc.h"
 #include "threads.h"
 
-#ifndef ALC_SOFT_loopback2
-#define ALC_SOFT_loopback2 1
-#define ALC_AMBISONIC_LAYOUT_SOFT                0x1997
-#define ALC_AMBISONIC_SCALING_SOFT               0x1998
-#define ALC_AMBISONIC_ORDER_SOFT                 0x1999
-
-#define ALC_BFORMAT3D_SOFT                       0x1508
-
-/* Ambisonic layouts */
-#define ALC_ACN_SOFT                             0x1600
-#define ALC_FUMA_SOFT                            0x1601
-
-/* Ambisonic scalings (normalization) */
-/*#define ALC_FUMA_SOFT*/
-#define ALC_SN3D_SOFT                            0x1602
-#define ALC_N3D_SOFT                             0x1603
-
-typedef ALCboolean (ALC_APIENTRY*LPALCISAMBISONICFORMATSUPPORTEDSOFT)(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order);
-#ifdef AL_ALEXT_PROTOTYPES
-ALC_API ALCboolean ALC_APIENTRY alcIsAmbisonicFormatSupportedSOFT(ALCdevice *device, ALCenum layout, ALCenum scaling, ALsizei order);
-#endif
-#endif
-
-#ifndef ALC_SOFT_device_clock
-#define ALC_SOFT_device_clock 1
-typedef int64_t ALCint64SOFT;
-typedef uint64_t ALCuint64SOFT;
-#define ALC_DEVICE_CLOCK_SOFT                    0x1600
-#define ALC_DEVICE_LATENCY_SOFT                  0x1601
-#define ALC_DEVICE_CLOCK_LATENCY_SOFT            0x1602
-typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
-#ifdef AL_ALEXT_PROTOTYPES
-ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
-#endif
-#endif
-
-#ifndef AL_SOFT_buffer_samples2
-#define AL_SOFT_buffer_samples2 1
-/* Channel configurations */
-#define AL_MONO_SOFT                             0x1500
-#define AL_STEREO_SOFT                           0x1501
-#define AL_REAR_SOFT                             0x1502
-#define AL_QUAD_SOFT                             0x1503
-#define AL_5POINT1_SOFT                          0x1504
-#define AL_6POINT1_SOFT                          0x1505
-#define AL_7POINT1_SOFT                          0x1506
-#define AL_BFORMAT2D_SOFT                        0x1507
-#define AL_BFORMAT3D_SOFT                        0x1508
-
-/* Sample types */
-#define AL_BYTE_SOFT                             0x1400
-#define AL_UNSIGNED_BYTE_SOFT                    0x1401
-#define AL_SHORT_SOFT                            0x1402
-#define AL_UNSIGNED_SHORT_SOFT                   0x1403
-#define AL_INT_SOFT                              0x1404
-#define AL_UNSIGNED_INT_SOFT                     0x1405
-#define AL_FLOAT_SOFT                            0x1406
-#define AL_DOUBLE_SOFT                           0x1407
-#define AL_BYTE3_SOFT                            0x1408
-#define AL_UNSIGNED_BYTE3_SOFT                   0x1409
-#define AL_MULAW_SOFT                            0x140A
-
-/* Storage formats */
-#define AL_MONO8_SOFT                            0x1100
-#define AL_MONO16_SOFT                           0x1101
-#define AL_MONO32F_SOFT                          0x10010
-#define AL_STEREO8_SOFT                          0x1102
-#define AL_STEREO16_SOFT                         0x1103
-#define AL_STEREO32F_SOFT                        0x10011
-#define AL_QUAD8_SOFT                            0x1204
-#define AL_QUAD16_SOFT                           0x1205
-#define AL_QUAD32F_SOFT                          0x1206
-#define AL_REAR8_SOFT                            0x1207
-#define AL_REAR16_SOFT                           0x1208
-#define AL_REAR32F_SOFT                          0x1209
-#define AL_5POINT1_8_SOFT                        0x120A
-#define AL_5POINT1_16_SOFT                       0x120B
-#define AL_5POINT1_32F_SOFT                      0x120C
-#define AL_6POINT1_8_SOFT                        0x120D
-#define AL_6POINT1_16_SOFT                       0x120E
-#define AL_6POINT1_32F_SOFT                      0x120F
-#define AL_7POINT1_8_SOFT                        0x1210
-#define AL_7POINT1_16_SOFT                       0x1211
-#define AL_7POINT1_32F_SOFT                      0x1212
-#define AL_BFORMAT2D_8_SOFT                      0x20021
-#define AL_BFORMAT2D_16_SOFT                     0x20022
-#define AL_BFORMAT2D_32F_SOFT                    0x20023
-#define AL_BFORMAT3D_8_SOFT                      0x20031
-#define AL_BFORMAT3D_16_SOFT                     0x20032
-#define AL_BFORMAT3D_32F_SOFT                    0x20033
-
-/* Buffer attributes */
-#define AL_INTERNAL_FORMAT_SOFT                  0x2008
-#define AL_BYTE_LENGTH_SOFT                      0x2009
-#define AL_SAMPLE_LENGTH_SOFT                    0x200A
-#define AL_SEC_LENGTH_SOFT                       0x200B
-
-#if 0
-typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*);
-typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*);
-typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum);
-#ifdef AL_ALEXT_PROTOTYPES
-AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data);
-AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data);
-AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);
-#endif
-#endif
-#endif
-
 
 #if defined(_WIN64)
 #define SZFMT "%I64u"
@@ -150,72 +42,11 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format);
 
 
 #ifdef __GNUC__
-/* Because of a long-standing deficiency in C, you're not allowed to implicitly
- * cast a pointer-to-type-array to a pointer-to-const-type-array. For example,
- *
- * int (*ptr)[10];
- * const int (*cptr)[10] = ptr;
- *
- * is not allowed and most compilers will generate noisy warnings about
- * incompatible types, even though it just makes the array elements const.
- * Clang will allow it if you make the array type a typedef, like this:
- *
- * typedef int int10[10];
- * int10 *ptr;
- * const int10 *cptr = ptr;
- *
- * however GCC does not and still issues the incompatible type warning. The
- * "proper" way to fix it is to add an explicit cast for the constified type,
- * but that removes the vast majority of otherwise useful type-checking you'd
- * get, and runs the risk of improper casts if types are later changed. Leaving
- * it non-const can also be an issue if you use it as a function parameter, and
- * happen to have a const type as input (and also reduce the capabilities of
- * the compiler to better optimize the function).
- *
- * So to work around the problem, we use a macro. The macro first assigns the
- * incoming variable to the specified non-const type to ensure it's the correct
- * type, then casts the variable as the desired constified type. Very ugly, but
- * I'd rather not have hundreds of lines of warnings because I want to tell the
- * compiler that some array(s) can't be changed by the code, or have lots of
- * error-prone casts.
- */
-#define SAFE_CONST(T, var) __extension__({                                    \
-    T _tmp = (var);                                                           \
-    (const T)_tmp;                                                            \
-})
-#else
-/* Non-GNU-compatible compilers have to use a straight cast with no extra
- * checks, due to the lack of multi-statement expressions.
- */
-#define SAFE_CONST(T, var) ((const T)(var))
-#endif
-
-
-#ifdef __GNUC__
-/* This helps cast away the const-ness of a pointer without accidentally
- * changing the pointer type. This is necessary due to Clang's inability to use
- * atomic_load on a const _Atomic variable.
- */
-#define CONST_CAST(T, V) __extension__({                                      \
-    const T _tmp = (V);                                                       \
-    (T)_tmp;                                                                  \
-})
+#define LIKELY(x) __builtin_expect(!!(x), !0)
+#define UNLIKELY(x) __builtin_expect(!!(x), 0)
 #else
-#define CONST_CAST(T, V) ((T)(V))
-#endif
-
-
-typedef ALint64SOFT ALint64;
-typedef ALuint64SOFT ALuint64;
-
-#ifndef U64
-#if defined(_MSC_VER)
-#define U64(x) ((ALuint64)(x##ui64))
-#elif SIZEOF_LONG == 8
-#define U64(x) ((ALuint64)(x##ul))
-#elif SIZEOF_LONG_LONG == 8
-#define U64(x) ((ALuint64)(x##ull))
-#endif
+#define LIKELY(x) (!!(x))
+#define UNLIKELY(x) (!!(x))
 #endif
 
 #ifndef UINT64_MAX
@@ -234,153 +65,113 @@ typedef ALuint64SOFT ALuint64;
 #endif
 #endif
 
-#ifdef __GNUC__
-#define DECL_FORMAT(x, y, z) __attribute__((format(x, (y), (z))))
-#else
-#define DECL_FORMAT(x, y, z)
-#endif
-
 /* Calculates the size of a struct with N elements of a flexible array member.
  * GCC and Clang allow offsetof(Type, fam[N]) for this, but MSVC seems to have
  * trouble, so a bit more verbose workaround is needed.
  */
 #define FAM_SIZE(T, M, N)  (offsetof(T, M) + sizeof(((T*)NULL)->M[0])*(N))
 
-#if defined(__GNUC__) && defined(__i386__)
-/* force_align_arg_pointer is required for proper function arguments aligning
- * when SSE code is used. Some systems (Windows, QNX) do not guarantee our
- * thread functions will be properly aligned on the stack, even though GCC may
- * generate code with the assumption that it is. */
-#define FORCE_ALIGN __attribute__((force_align_arg_pointer))
-#else
-#define FORCE_ALIGN
-#endif
 
-#ifdef HAVE_C99_VLA
-#define DECL_VLA(T, _name, _size)  T _name[(_size)]
-#else
-#define DECL_VLA(T, _name, _size)  T *_name = alloca((_size) * sizeof(T))
+#ifdef __cplusplus
+extern "C" {
 #endif
 
-#ifndef PATH_MAX
-#ifdef MAX_PATH
-#define PATH_MAX MAX_PATH
-#else
-#define PATH_MAX 4096
+typedef ALint64SOFT ALint64;
+typedef ALuint64SOFT ALuint64;
+
+#ifndef U64
+#if defined(_MSC_VER)
+#define U64(x) ((ALuint64)(x##ui64))
+#elif SIZEOF_LONG == 8
+#define U64(x) ((ALuint64)(x##ul))
+#elif SIZEOF_LONG_LONG == 8
+#define U64(x) ((ALuint64)(x##ull))
 #endif
 #endif
 
-
-static const union {
-    ALuint u;
-    ALubyte b[sizeof(ALuint)];
-} EndianTest = { 1 };
-#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
-
-#define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
-
-
-#define DERIVE_FROM_TYPE(t)          t t##_parent
-#define STATIC_CAST(to, obj)         (&(obj)->to##_parent)
+/* Define a CTZ64 macro (count trailing zeros, for 64-bit integers). The result
+ * is *UNDEFINED* if the value is 0.
+ */
 #ifdef __GNUC__
-#define STATIC_UPCAST(to, from, obj) __extension__({                          \
-    static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))),       \
-                  "Invalid upcast object from type");                         \
-    (to*)((char*)(obj) - offsetof(to, from##_parent));                        \
-})
+
+#if SIZEOF_LONG == 8
+#define CTZ64(x) __builtin_ctzl(x)
 #else
-#define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent)))
+#define CTZ64(x) __builtin_ctzll(x)
 #endif
 
-#define DECLARE_FORWARD(T1, T2, rettype, func)                                \
-rettype T1##_##func(T1 *obj)                                                  \
-{ return T2##_##func(STATIC_CAST(T2, obj)); }
-
-#define DECLARE_FORWARD1(T1, T2, rettype, func, argtype1)                     \
-rettype T1##_##func(T1 *obj, argtype1 a)                                      \
-{ return T2##_##func(STATIC_CAST(T2, obj), a); }
+#elif defined(HAVE_BITSCANFORWARD64_INTRINSIC)
 
-#define DECLARE_FORWARD2(T1, T2, rettype, func, argtype1, argtype2)           \
-rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b)                          \
-{ return T2##_##func(STATIC_CAST(T2, obj), a, b); }
-
-#define DECLARE_FORWARD3(T1, T2, rettype, func, argtype1, argtype2, argtype3) \
-rettype T1##_##func(T1 *obj, argtype1 a, argtype2 b, argtype3 c)              \
-{ return T2##_##func(STATIC_CAST(T2, obj), a, b, c); }
-
-
-#define GET_VTABLE1(T1)     (&(T1##_vtable))
-#define GET_VTABLE2(T1, T2) (&(T1##_##T2##_vtable))
-
-#define SET_VTABLE1(T1, obj)     ((obj)->vtbl = GET_VTABLE1(T1))
-#define SET_VTABLE2(T1, T2, obj) (STATIC_CAST(T2, obj)->vtbl = GET_VTABLE2(T1, T2))
-
-#define DECLARE_THUNK(T1, T2, rettype, func)                                  \
-static rettype T1##_##T2##_##func(T2 *obj)                                    \
-{ return T1##_##func(STATIC_UPCAST(T1, T2, obj)); }
-
-#define DECLARE_THUNK1(T1, T2, rettype, func, argtype1)                       \
-static rettype T1##_##T2##_##func(T2 *obj, argtype1 a)                        \
-{ return T1##_##func(STATIC_UPCAST(T1, T2, obj), a); }
-
-#define DECLARE_THUNK2(T1, T2, rettype, func, argtype1, argtype2)             \
-static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b)            \
-{ return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b); }
-
-#define DECLARE_THUNK3(T1, T2, rettype, func, argtype1, argtype2, argtype3)   \
-static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \
-{ return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); }
-
-#define DECLARE_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)                                         \
-static void* T##_New(size_t size) { return al_malloc(16, size); }             \
-static void T##_Delete(void *ptr) { al_free(ptr); }
+inline int msvc64_ctz64(ALuint64 v)
+{
+    unsigned long idx = 64;
+    _BitScanForward64(&idx, v);
+    return (int)idx;
+}
+#define CTZ64(x) msvc64_ctz64(x)
 
-/* Helper to extract an argument list for VCALL. Not used directly. */
-#define EXTRACT_VCALL_ARGS(...)  __VA_ARGS__))
+#elif defined(HAVE_BITSCANFORWARD_INTRINSIC)
 
-/* Call a "virtual" method on an object, with arguments. */
-#define V(obj, func)  ((obj)->vtbl->func((obj), EXTRACT_VCALL_ARGS
-/* Call a "virtual" method on an object, with no arguments. */
-#define V0(obj, func) ((obj)->vtbl->func((obj) EXTRACT_VCALL_ARGS
+inline int msvc_ctz64(ALuint64 v)
+{
+    unsigned long idx = 64;
+    if(!_BitScanForward(&idx, v&0xffffffff))
+    {
+        if(_BitScanForward(&idx, v>>32))
+            idx += 32;
+    }
+    return (int)idx;
+}
+#define CTZ64(x) msvc_ctz64(x)
 
-#define DELETE_OBJ(obj) do {                                                  \
-    if((obj) != NULL)                                                         \
-    {                                                                         \
-        V0((obj),Destruct)();                                                 \
-        V0((obj),Delete)();                                                   \
-    }                                                                         \
-} while(0)
+#else
 
+/* There be black magics here. The popcnt64 method is derived from
+ * https://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel
+ * while the ctz-utilizing-popcnt algorithm is shown here
+ * http://www.hackersdelight.org/hdcodetxt/ntz.c.txt
+ * as the ntz2 variant. These likely aren't the most efficient methods, but
+ * they're good enough if the GCC or MSVC intrinsics aren't available.
+ */
+inline int fallback_popcnt64(ALuint64 v)
+{
+    v = v - ((v >> 1) & U64(0x5555555555555555));
+    v = (v & U64(0x3333333333333333)) + ((v >> 2) & U64(0x3333333333333333));
+    v = (v + (v >> 4)) & U64(0x0f0f0f0f0f0f0f0f);
+    return (int)((v * U64(0x0101010101010101)) >> 56);
+}
 
-#define EXTRACT_NEW_ARGS(...)  __VA_ARGS__);                                  \
-    }                                                                         \
-} while(0)
+inline int fallback_ctz64(ALuint64 value)
+{
+    return fallback_popcnt64(~value & (value - 1));
+}
+#define CTZ64(x) fallback_ctz64(x)
+#endif
 
-#define NEW_OBJ(_res, T) do {                                                 \
-    _res = T##_New(sizeof(T));                                                \
-    if(_res)                                                                  \
-    {                                                                         \
-        memset(_res, 0, sizeof(T));                                           \
-        T##_Construct(_res, EXTRACT_NEW_ARGS
-#define NEW_OBJ0(_res, T) do {                                                \
-    _res = T##_New(sizeof(T));                                                \
-    if(_res)                                                                  \
-    {                                                                         \
-        memset(_res, 0, sizeof(T));                                           \
-        T##_Construct(_res EXTRACT_NEW_ARGS
+static const union {
+    ALuint u;
+    ALubyte b[sizeof(ALuint)];
+} EndianTest = { 1 };
+#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1)
 
+#define COUNTOF(x) (sizeof(x) / sizeof(0[x]))
 
-#ifdef __cplusplus
-extern "C" {
-#endif
 
+struct ll_ringbuffer;
 struct Hrtf;
 struct HrtfEntry;
+struct DirectHrtfState;
+struct FrontStablizer;
 struct Compressor;
+struct ALCbackend;
+struct ALbuffer;
+struct ALeffect;
+struct ALfilter;
+struct ALsource;
+struct ALcontextProps;
+struct ALlistenerProps;
+struct ALvoiceProps;
+struct ALeffectslotProps;
 
 
 #define DEFAULT_OUTPUT_RATE  (44100)
@@ -409,24 +200,6 @@ inline size_t RoundUp(size_t value, size_t r)
     return value - (value%r);
 }
 
-/* Scales the given value using 64-bit integer math, rounding the result. */
-inline ALuint64 ScaleRound(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale)
-{
-    return (val*new_scale + old_scale/2) / old_scale;
-}
-
-/* Scales the given value using 64-bit integer math, flooring the result. */
-inline ALuint64 ScaleFloor(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale)
-{
-    return val * new_scale / old_scale;
-}
-
-/* Scales the given value using 64-bit integer math, ceiling the result. */
-inline ALuint64 ScaleCeil(ALuint64 val, ALuint64 new_scale, ALuint64 old_scale)
-{
-    return (val*new_scale + old_scale-1) / old_scale;
-}
-
 /* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
  * mode. */
 inline ALint fastf2i(ALfloat f)
@@ -449,8 +222,6 @@ enum DevProbe {
     CAPTURE_DEVICE_PROBE
 };
 
-struct ALCbackend;
-
 
 enum DistanceModel {
     InverseDistanceClamped  = AL_INVERSE_DISTANCE_CLAMPED,
@@ -556,14 +327,6 @@ enum AmbiNorm {
 };
 
 
-extern const struct EffectList {
-    const char *name;
-    int type;
-    const char *ename;
-    ALenum val;
-} EffectList[];
-
-
 enum DeviceType {
     Playback,
     Capture,
@@ -614,34 +377,36 @@ typedef union AmbiConfig {
 } AmbiConfig;
 
 
-#define HRTF_HISTORY_BITS   (6)
-#define HRTF_HISTORY_LENGTH (1<<HRTF_HISTORY_BITS)
-#define HRTF_HISTORY_MASK   (HRTF_HISTORY_LENGTH-1)
-
-#define HRIR_BITS        (7)
-#define HRIR_LENGTH      (1<<HRIR_BITS)
-#define HRIR_MASK        (HRIR_LENGTH-1)
-
-typedef struct HrtfState {
-    alignas(16) ALfloat History[HRTF_HISTORY_LENGTH];
-    alignas(16) ALfloat Values[HRIR_LENGTH][2];
-} HrtfState;
+typedef struct BufferSubList {
+    ALuint64 FreeMask;
+    struct ALbuffer *Buffers; /* 64 */
+} BufferSubList;
+TYPEDEF_VECTOR(BufferSubList, vector_BufferSubList)
+
+typedef struct EffectSubList {
+    ALuint64 FreeMask;
+    struct ALeffect *Effects; /* 64 */
+} EffectSubList;
+TYPEDEF_VECTOR(EffectSubList, vector_EffectSubList)
+
+typedef struct FilterSubList {
+    ALuint64 FreeMask;
+    struct ALfilter *Filters; /* 64 */
+} FilterSubList;
+TYPEDEF_VECTOR(FilterSubList, vector_FilterSubList)
+
+typedef struct SourceSubList {
+    ALuint64 FreeMask;
+    struct ALsource *Sources; /* 64 */
+} SourceSubList;
+TYPEDEF_VECTOR(SourceSubList, vector_SourceSubList)
+
+/* Effect slots are rather large, and apps aren't likely to have more than one
+ * or two (let alone 64), so hold them individually.
+ */
+typedef struct ALeffectslot *ALeffectslotPtr;
+TYPEDEF_VECTOR(ALeffectslotPtr, vector_ALeffectslotPtr)
 
-typedef struct HrtfParams {
-    alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
-    ALsizei Delay[2];
-    ALfloat Gain;
-} HrtfParams;
-
-typedef struct DirectHrtfState {
-    /* HRTF filter state for dry buffer content */
-    ALsizei Offset;
-    ALsizei IrSize;
-    struct {
-        alignas(16) ALfloat Values[HRIR_LENGTH][2];
-        alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
-    } Chan[];
-} DirectHrtfState;
 
 typedef struct EnumeratedHrtf {
     al_string name;
@@ -667,11 +432,41 @@ typedef struct DistanceComp {
  */
 #define BUFFERSIZE 2048
 
-struct ALCdevice_struct
-{
+typedef struct DryMixParams {
+    AmbiConfig Ambi;
+    /* Number of coefficients in each Ambi.Coeffs to mix together (4 for first-
+     * order, 9 for second-order, etc). If the count is 0, Ambi.Map is used
+     * instead to map each output to a coefficient index.
+     */
+    ALsizei CoeffCount;
+
+    ALfloat (*Buffer)[BUFFERSIZE];
+    ALsizei NumChannels;
+    ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1];
+} DryMixParams;
+
+typedef struct BFMixParams {
+    AmbiConfig Ambi;
+    /* Will only be 4 or 0. */
+    ALsizei CoeffCount;
+
+    ALfloat (*Buffer)[BUFFERSIZE];
+    ALsizei NumChannels;
+} BFMixParams;
+
+typedef struct RealMixParams {
+    enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
+
+    ALfloat (*Buffer)[BUFFERSIZE];
+    ALsizei NumChannels;
+} RealMixParams;
+
+typedef void (*POSTPROCESS)(ALCdevice *device, ALsizei SamplesToDo);
+
+struct ALCdevice_struct {
     RefCount ref;
 
-    ALCboolean Connected;
+    ATOMIC(ALenum) Connected;
     enum DeviceType Type;
 
     ALuint Frequency;
@@ -701,16 +496,21 @@ struct ALCdevice_struct
     ALsizei NumAuxSends;
 
     // Map of Buffers for this device
-    UIntMap BufferMap;
+    vector_BufferSubList BufferList;
+    almtx_t BufferLock;
 
     // Map of Effects for this device
-    UIntMap EffectMap;
+    vector_EffectSubList EffectList;
+    almtx_t EffectLock;
 
     // Map of Filters for this device
-    UIntMap FilterMap;
+    vector_FilterSubList FilterList;
+    almtx_t FilterLock;
+
+    POSTPROCESS PostProcess;
 
     /* HRTF state and info */
-    DirectHrtfState *Hrtf;
+    struct DirectHrtfState *Hrtf;
     al_string HrtfName;
     struct Hrtf *HrtfHandle;
     vector_EnumeratedHrtf HrtfList;
@@ -737,45 +537,21 @@ struct ALCdevice_struct
     ALuint64 ClockBase;
     ALuint SamplesDone;
 
-    /* Temp storage used for each source when mixing. */
-    alignas(16) ALfloat SourceData[BUFFERSIZE];
-    alignas(16) ALfloat ResampledData[BUFFERSIZE];
-    alignas(16) ALfloat FilteredData[BUFFERSIZE];
-    alignas(16) ALfloat NFCtrlData[BUFFERSIZE];
+    /* Temp storage used for mixer processing. */
+    alignas(16) ALfloat TempBuffer[4][BUFFERSIZE];
 
     /* The "dry" path corresponds to the main output. */
-    struct {
-        AmbiConfig Ambi;
-        /* Number of coefficients in each Ambi.Coeffs to mix together (4 for
-         * first-order, 9 for second-order, etc). If the count is 0, Ambi.Map
-         * is used instead to map each output to a coefficient index.
-         */
-        ALsizei CoeffCount;
-
-        ALfloat (*Buffer)[BUFFERSIZE];
-        ALsizei NumChannels;
-        ALsizei NumChannelsPerOrder[MAX_AMBI_ORDER+1];
-    } Dry;
+    DryMixParams Dry;
 
     /* First-order ambisonics output, to be upsampled to the dry buffer if different. */
-    struct {
-        AmbiConfig Ambi;
-        /* Will only be 4 or 0. */
-        ALsizei CoeffCount;
-
-        ALfloat (*Buffer)[BUFFERSIZE];
-        ALsizei NumChannels;
-    } FOAOut;
+    BFMixParams FOAOut;
 
     /* "Real" output, which will be written to the device buffer. May alias the
      * dry buffer.
      */
-    struct {
-        enum Channel ChannelName[MAX_OUTPUT_CHANNELS];
+    RealMixParams RealOut;
 
-        ALfloat (*Buffer)[BUFFERSIZE];
-        ALsizei NumChannels;
-    } RealOut;
+    struct FrontStablizer *Stablizer;
 
     struct Compressor *Limiter;
 
@@ -804,7 +580,7 @@ struct ALCdevice_struct
     almtx_t BackendLock;
     struct ALCbackend *Backend;
 
-    ALCdevice *volatile next;
+    ATOMIC(ALCdevice*) next;
 };
 
 // Frequency was requested by the app or config file
@@ -832,13 +608,34 @@ struct ALCdevice_struct
 #define RECORD_THREAD_NAME "alsoft-record"
 
 
+enum {
+    EventType_SourceStateChange = 1<<0,
+    EventType_BufferCompleted   = 1<<1,
+    EventType_Error             = 1<<2,
+    EventType_Performance       = 1<<3,
+    EventType_Deprecated        = 1<<4,
+    EventType_Disconnected      = 1<<5,
+};
+
+typedef struct AsyncEvent {
+    unsigned int EnumType;
+    ALenum Type;
+    ALuint ObjectId;
+    ALuint Param;
+    ALchar Message[1008];
+} AsyncEvent;
+
 struct ALCcontext_struct {
     RefCount ref;
 
     struct ALlistener *Listener;
 
-    UIntMap SourceMap;
-    UIntMap EffectSlotMap;
+    vector_SourceSubList SourceList;
+    ALuint NumSources;
+    almtx_t SourceLock;
+
+    vector_ALeffectslotPtr EffectSlotList;
+    almtx_t EffectSlotLock;
 
     ATOMIC(ALenum) LastError;
 
@@ -848,9 +645,12 @@ struct ALCcontext_struct {
     ALfloat DopplerFactor;
     ALfloat DopplerVelocity;
     ALfloat SpeedOfSound;
+    ALfloat MetersPerUnit;
+
+    ATOMIC_FLAG PropsClean;
     ATOMIC(ALenum) DeferUpdates;
 
-    RWLock PropLock;
+    almtx_t PropLock;
 
     /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
      * indicates if updates are currently happening).
@@ -860,19 +660,38 @@ struct ALCcontext_struct {
 
     ALfloat GainBoost;
 
+    ATOMIC(struct ALcontextProps*) Update;
+
+    /* Linked lists of unused property containers, free to use for future
+     * updates.
+     */
+    ATOMIC(struct ALcontextProps*) FreeContextProps;
+    ATOMIC(struct ALlistenerProps*) FreeListenerProps;
+    ATOMIC(struct ALvoiceProps*) FreeVoiceProps;
+    ATOMIC(struct ALeffectslotProps*) FreeEffectslotProps;
+
     struct ALvoice **Voices;
     ALsizei VoiceCount;
     ALsizei MaxVoices;
 
     ATOMIC(struct ALeffectslotArray*) ActiveAuxSlots;
 
+    almtx_t EventThrdLock;
+    althrd_t EventThread;
+    alsem_t EventSem;
+    struct ll_ringbuffer *AsyncEvents;
+    ATOMIC(ALbitfieldSOFT) EnabledEvts;
+    almtx_t EventCbLock;
+    ALEVENTPROCSOFT EventCb;
+    void *EventParam;
+
     /* Default effect slot */
     struct ALeffectslot *DefaultSlot;
 
     ALCdevice  *Device;
     const ALCchar *ExtensionList;
 
-    ALCcontext *volatile next;
+    ATOMIC(ALCcontext*) next;
 
     /* Memory space used by the listener (and possibly default effect slot) */
     alignas(16) ALCbyte _listener_mem[];
@@ -880,79 +699,18 @@ struct ALCcontext_struct {
 
 ALCcontext *GetContextRef(void);
 
-void ALCcontext_IncRef(ALCcontext *context);
 void ALCcontext_DecRef(ALCcontext *context);
 
+void ALCcontext_DeferUpdates(ALCcontext *context);
+void ALCcontext_ProcessUpdates(ALCcontext *context);
+
 void AllocateVoices(ALCcontext *context, ALsizei num_voices, ALsizei old_sends);
 
 void AppendAllDevicesList(const ALCchar *name);
 void AppendCaptureDeviceList(const ALCchar *name);
 
-void ALCdevice_Lock(ALCdevice *device);
-void ALCdevice_Unlock(ALCdevice *device);
-
-void ALCcontext_DeferUpdates(ALCcontext *context);
-void ALCcontext_ProcessUpdates(ALCcontext *context);
-
-
-typedef struct {
-#ifdef HAVE_FENV_H
-    DERIVE_FROM_TYPE(fenv_t);
-#ifdef _WIN32
-    int round_mode;
-#endif
-#else
-    int state;
-#endif
-#ifdef HAVE_SSE
-    int sse_state;
-#endif
-} FPUCtl;
-void SetMixerFPUMode(FPUCtl *ctl);
-void RestoreFPUMode(const FPUCtl *ctl);
-#ifdef __GNUC__
-/* Use an alternate macro set with GCC to avoid accidental continue or break
- * statements within the mixer mode.
- */
-#define START_MIXER_MODE() __extension__({ FPUCtl _oldMode; SetMixerFPUMode(&_oldMode);
-#define END_MIXER_MODE() RestoreFPUMode(&_oldMode); })
-#else
-#define START_MIXER_MODE() do { FPUCtl _oldMode; SetMixerFPUMode(&_oldMode);
-#define END_MIXER_MODE() RestoreFPUMode(&_oldMode); } while(0)
-#endif
-#define LEAVE_MIXER_MODE() RestoreFPUMode(&_oldMode)
-
-
-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 FreeALConfig(void);
-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);
 
+extern ALint RTPrioLevel;
 void SetRTPriority(void);
 
 void SetDefaultChannelOrder(ALCdevice *device);
@@ -961,12 +719,6 @@ void SetDefaultWFXChannelOrder(ALCdevice *device);
 const ALCchar *DevFmtTypeString(enum DevFmtType type);
 const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans);
 
-/**
- * GetChannelIdxByName
- *
- * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
- * doesn't exist.
- */
 inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan)
 {
     ALint i;
@@ -977,107 +729,33 @@ inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum
     }
     return -1;
 }
-#define GetChannelIdxByName(x, c) GetChannelIndex((x).ChannelName, (c))
-
-extern FILE *LogFile;
-
-#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__)
-#else
-void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4);
-#define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__)
-#endif
-
-#ifdef __ANDROID__
-#include <android/log.h>
-#define LOG_ANDROID(T, MSG, ...) __android_log_print(T, "openal", "AL lib: %s: "MSG, __FUNCTION__ , ## __VA_ARGS__)
-#else
-#define LOG_ANDROID(T, MSG, ...) ((void)0)
-#endif
-
-enum LogLevel {
-    NoLog,
-    LogError,
-    LogWarning,
-    LogTrace,
-    LogRef
-};
-extern enum LogLevel LogLevel;
-
-#define TRACEREF(...) do {                                                    \
-    if(LogLevel >= LogRef)                                                    \
-        AL_PRINT("(--)", __VA_ARGS__);                                        \
-} while(0)
-
-#define TRACE(...) do {                                                       \
-    if(LogLevel >= LogTrace)                                                  \
-        AL_PRINT("(II)", __VA_ARGS__);                                        \
-    LOG_ANDROID(ANDROID_LOG_DEBUG, __VA_ARGS__);                              \
-} while(0)
-
-#define WARN(...) do {                                                        \
-    if(LogLevel >= LogWarning)                                                \
-        AL_PRINT("(WW)", __VA_ARGS__);                                        \
-    LOG_ANDROID(ANDROID_LOG_WARN, __VA_ARGS__);                               \
-} while(0)
+/**
+ * GetChannelIdxByName
+ *
+ * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it
+ * doesn't exist.
+ */
+inline ALint GetChannelIdxByName(const RealMixParams *real, enum Channel chan)
+{ return GetChannelIndex(real->ChannelName, chan); }
 
-#define ERR(...) do {                                                         \
-    if(LogLevel >= LogError)                                                  \
-        AL_PRINT("(EE)", __VA_ARGS__);                                        \
-    LOG_ANDROID(ANDROID_LOG_ERROR, __VA_ARGS__);                              \
-} while(0)
 
+inline void LockBufferList(ALCdevice *device) { almtx_lock(&device->BufferLock); }
+inline void UnlockBufferList(ALCdevice *device) { almtx_unlock(&device->BufferLock); }
 
-extern ALint RTPrioLevel;
+inline void LockEffectList(ALCdevice *device) { almtx_lock(&device->EffectLock); }
+inline void UnlockEffectList(ALCdevice *device) { almtx_unlock(&device->EffectLock); }
 
+inline void LockFilterList(ALCdevice *device) { almtx_lock(&device->FilterLock); }
+inline void UnlockFilterList(ALCdevice *device) { almtx_unlock(&device->FilterLock); }
 
-extern ALuint CPUCapFlags;
-enum {
-    CPU_CAP_SSE    = 1<<0,
-    CPU_CAP_SSE2   = 1<<1,
-    CPU_CAP_SSE3   = 1<<2,
-    CPU_CAP_SSE4_1 = 1<<3,
-    CPU_CAP_NEON   = 1<<4,
-};
+inline void LockEffectSlotList(ALCcontext *context)
+{ almtx_lock(&context->EffectSlotLock); }
+inline void UnlockEffectSlotList(ALCcontext *context)
+{ almtx_unlock(&context->EffectSlotLock); }
 
-void FillCPUCaps(ALuint capfilter);
 
 vector_al_string SearchDataFiles(const char *match, const char *subdir);
 
-/* Small hack to use a pointer-to-array types as a normal argument type.
- * Shouldn't be used directly.
- */
-typedef ALfloat ALfloatBUFFERSIZE[BUFFERSIZE];
-typedef ALfloat ALfloat2[2];
-
-
-/* The compressor requires the following information for proper
- * initialization:
- *
- *   PreGainDb      - Gain applied before detection (in dB).
- *   PostGainDb     - Gain applied after compression (in dB).
- *   SummedLink     - Whether to use summed (true) or maxed (false) linking.
- *   RmsSensing     - Whether to use RMS (true) or Peak (false) sensing.
- *   AttackTimeMin  - Minimum attack time (in seconds).
- *   AttackTimeMax  - Maximum attack time.  Automates when min != max.
- *   ReleaseTimeMin - Minimum release time (in seconds).
- *   ReleaseTimeMax - Maximum release time.  Automates when min != max.
- *   Ratio          - Compression ratio (x:1).  Set to 0 for true limiter.
- *   ThresholdDb    - Triggering threshold (in dB).
- *   KneeDb         - Knee width (below threshold; in dB).
- *   SampleRate     - Sample rate to process.
- */
-struct Compressor *CompressorInit(const ALfloat PreGainDb, const ALfloat PostGainDb,
-    const ALboolean SummedLink, const ALboolean RmsSensing, const ALfloat AttackTimeMin,
-    const ALfloat AttackTimeMax, const ALfloat ReleaseTimeMin, const ALfloat ReleaseTimeMax,
-    const ALfloat Ratio, const ALfloat ThresholdDb, const ALfloat KneeDb,
-    const ALuint SampleRate);
-
-ALuint GetCompressorSampleRate(const struct Compressor *Comp);
-
-void ApplyCompression(struct Compressor *Comp, const ALsizei NumChans, const ALsizei SamplesToDo,
-                      ALfloat (*restrict OutBuffer)[BUFFERSIZE]);
-
 #ifdef __cplusplus
 }
 #endif

+ 9 - 17
libs/openal-soft/OpenAL32/Include/alSource.h

@@ -19,8 +19,10 @@ struct ALsource;
 
 
 typedef struct ALbufferlistitem {
-    struct ALbuffer *buffer;
     ATOMIC(struct ALbufferlistitem*) next;
+    ALsizei max_samples;
+    ALsizei num_buffers;
+    struct ALbuffer *buffers[];
 } ALbufferlistitem;
 
 
@@ -91,32 +93,22 @@ typedef struct ALsource {
     ALint SourceType;
 
     /** Source state (initial, playing, paused, or stopped) */
-    ATOMIC(ALenum) state;
+    ALenum state;
 
     /** Source Buffer Queue head. */
-    RWLock queue_lock;
     ALbufferlistitem *queue;
 
     ATOMIC_FLAG PropsClean;
 
+    /* Index into the context's Voices array. Lazily updated, only checked and
+     * reset when looking up the voice.
+     */
+    ALint VoiceIdx;
+
     /** Self ID */
     ALuint id;
 } ALsource;
 
-inline void LockSourcesRead(ALCcontext *context)
-{ LockUIntMapRead(&context->SourceMap); }
-inline void UnlockSourcesRead(ALCcontext *context)
-{ UnlockUIntMapRead(&context->SourceMap); }
-inline void LockSourcesWrite(ALCcontext *context)
-{ LockUIntMapWrite(&context->SourceMap); }
-inline void UnlockSourcesWrite(ALCcontext *context)
-{ UnlockUIntMapWrite(&context->SourceMap); }
-
-inline struct ALsource *LookupSource(ALCcontext *context, ALuint id)
-{ return (struct ALsource*)LookupUIntMapKeyNoLock(&context->SourceMap, id); }
-inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id)
-{ return (struct ALsource*)RemoveUIntMapKeyNoLock(&context->SourceMap, id); }
-
 void UpdateAllSourceProps(ALCcontext *context);
 
 ALvoid ReleaseALSources(ALCcontext *Context);

+ 0 - 20
libs/openal-soft/OpenAL32/Include/alThunk.h

@@ -1,20 +0,0 @@
-#ifndef ALTHUNK_H
-#define ALTHUNK_H
-
-#include "alMain.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void ThunkInit(void);
-void ThunkExit(void);
-ALenum NewThunkEntry(ALuint *index);
-void FreeThunkEntry(ALuint index);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif //ALTHUNK_H
-

+ 80 - 72
libs/openal-soft/OpenAL32/Include/alu.h

@@ -12,28 +12,27 @@
 
 #include "alMain.h"
 #include "alBuffer.h"
-#include "alFilter.h"
-#include "alAuxEffectSlot.h"
 
 #include "hrtf.h"
 #include "align.h"
-#include "nfcfilter.h"
 #include "math_defs.h"
+#include "filters/defs.h"
+#include "filters/nfc.h"
 
 
 #define MAX_PITCH  (255)
 
-/* 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
+/* Maximum number of samples to pad on either end of a buffer for resampling.
+ * Note that both the beginning and end need padding!
+ */
+#define MAX_RESAMPLE_PADDING 24
 
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+struct BSincTable;
 struct ALsource;
 struct ALbufferlistitem;
 struct ALvoice;
@@ -53,13 +52,16 @@ enum Resampler {
     PointResampler,
     LinearResampler,
     FIR4Resampler,
-    BSincResampler,
+    BSinc12Resampler,
+    BSinc24Resampler,
 
-    ResamplerMax = BSincResampler
+    ResamplerMax = BSinc24Resampler
 };
 extern enum Resampler ResamplerDefault;
 
-/* The number of distinct scale and phase intervals within the filter table. */
+/* The number of distinct scale and phase intervals within the bsinc filter
+ * table.
+ */
 #define BSINC_SCALE_BITS  4
 #define BSINC_SCALE_COUNT (1<<BSINC_SCALE_BITS)
 #define BSINC_PHASE_BITS  4
@@ -71,27 +73,29 @@ extern enum Resampler ResamplerDefault;
  */
 typedef struct BsincState {
     ALfloat sf; /* Scale interpolation factor. */
-    ALuint m;   /* Coefficient count. */
+    ALsizei 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];
+    /* Filter coefficients, followed by the scale, phase, and scale-phase
+     * delta coefficients. Starting at phase index 0, each subsequent phase
+     * index follows contiguously.
+     */
+    const ALfloat *filter;
 } BsincState;
 
 typedef union InterpState {
     BsincState bsinc;
 } InterpState;
 
-ALboolean BsincPrepare(const ALuint increment, BsincState *state);
-
 typedef const ALfloat* (*ResamplerFunc)(const InterpState *state,
     const ALfloat *restrict src, ALsizei frac, ALint increment,
     ALfloat *restrict dst, ALsizei dstlen
 );
 
+void BsincPrepare(const ALuint increment, BsincState *state, const struct BSincTable *table);
+
+extern const struct BSincTable bsinc12;
+extern const struct BSincTable bsinc24;
+
 
 typedef union aluVector {
     alignas(16) ALfloat v[4];
@@ -149,10 +153,10 @@ typedef struct MixHrtfParams {
 
 
 typedef struct DirectParams {
-    ALfilterState LowPass;
-    ALfilterState HighPass;
+    BiquadState LowPass;
+    BiquadState HighPass;
 
-    NfcFilter NFCtrlFilter[MAX_AMBI_ORDER];
+    NfcFilter NFCtrlFilter;
 
     struct {
         HrtfParams Old;
@@ -167,8 +171,8 @@ typedef struct DirectParams {
 } DirectParams;
 
 typedef struct SendParams {
-    ALfilterState LowPass;
-    ALfilterState HighPass;
+    BiquadState LowPass;
+    BiquadState HighPass;
 
     struct {
         ALfloat Current[MAX_OUTPUT_CHANNELS];
@@ -231,16 +235,15 @@ struct ALvoiceProps {
     } Send[];
 };
 
-/* If not 'fading', gain targets are used directly without fading. */
-#define VOICE_IS_FADING (1<<0)
-#define VOICE_HAS_HRTF  (1<<1)
-#define VOICE_HAS_NFC   (1<<2)
+#define VOICE_IS_STATIC (1<<0)
+#define VOICE_IS_FADING (1<<1) /* Fading sources use gain stepping for smooth transitions. */
+#define VOICE_HAS_HRTF  (1<<2)
+#define VOICE_HAS_NFC   (1<<3)
 
 typedef struct ALvoice {
     struct ALvoiceProps *Props;
 
     ATOMIC(struct ALvoiceProps*) Update;
-    ATOMIC(struct ALvoiceProps*) FreeList;
 
     ATOMIC(struct ALsource*) Source;
     ATOMIC(bool) Playing;
@@ -277,7 +280,7 @@ typedef struct ALvoice {
 
     ALuint Offset; /* Number of output samples mixed since starting. */
 
-    alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES];
+    alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_RESAMPLE_PADDING];
 
     InterpState ResampleState;
 
@@ -381,19 +384,26 @@ inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
 inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
 { return minu64(max, maxu64(min, val)); }
 
-
-extern alignas(16) const ALfloat bsincTab[18840];
-extern alignas(16) const ALfloat sinc4Tab[FRACTIONONE][4];
+inline size_t minz(size_t a, size_t b)
+{ return ((a > b) ? b : a); }
+inline size_t maxz(size_t a, size_t b)
+{ return ((a > b) ? a : b); }
+inline size_t clampz(size_t val, size_t min, size_t max)
+{ return minz(max, maxz(min, val)); }
 
 
 inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
 {
     return val1 + (val2-val1)*mu;
 }
-inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac)
+inline ALfloat cubic(ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat mu)
 {
-    return sinc4Tab[frac][0]*val0 + sinc4Tab[frac][1]*val1 +
-           sinc4Tab[frac][2]*val2 + sinc4Tab[frac][3]*val3;
+    ALfloat mu2 = mu*mu, mu3 = mu2*mu;
+    ALfloat a0 = -0.5f*mu3 +       mu2 + -0.5f*mu;
+    ALfloat a1 =  1.5f*mu3 + -2.5f*mu2            + 1.0f;
+    ALfloat a2 = -1.5f*mu3 +  2.0f*mu2 +  0.5f*mu;
+    ALfloat a3 =  0.5f*mu3 + -0.5f*mu2;
+    return val1*a0 + val2*a1 + val3*a2 + val4*a3;
 }
 
 
@@ -403,10 +413,10 @@ enum HrtfRequestMode {
     Hrtf_Disable = 2,
 };
 
+void aluInit(void);
+
 void aluInitMixer(void);
 
-MixerFunc SelectMixer(void);
-RowMixerFunc SelectRowMixer(void);
 ResamplerFunc SelectResampler(enum Resampler resampler);
 
 /* aluInitRenderer
@@ -418,6 +428,8 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
 
 void aluInitEffectPanning(struct ALeffectslot *slot);
 
+void aluSelectPostProcess(ALCdevice *device);
+
 /**
  * CalcDirectionCoeffs
  *
@@ -454,35 +466,26 @@ inline void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread,
  */
 void CalcAnglePairwiseCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]);
 
-/**
- * ComputeAmbientGains
- *
- * Computes channel gains for ambient, omni-directional sounds.
- */
-#define ComputeAmbientGains(b, g, o) do {                                     \
-    if((b).CoeffCount > 0)                                                    \
-        ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o);        \
-    else                                                                      \
-        ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o);           \
-} while (0)
-void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
-void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
 
+void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
 /**
- * ComputePanningGains
+ * ComputeDryPanGains
  *
  * Computes panning gains using the given channel decoder coefficients and the
  * pre-calculated direction or angle coefficients.
  */
-#define ComputePanningGains(b, c, g, o) do {                                  \
-    if((b).CoeffCount > 0)                                                    \
-        ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\
-    else                                                                      \
-        ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o);        \
-} while (0)
-void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, ALsizei numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
-void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+inline void ComputeDryPanGains(const DryMixParams *dry, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+{
+    if(dry->CoeffCount > 0)
+        ComputePanningGainsMC(dry->Ambi.Coeffs, dry->NumChannels, dry->CoeffCount,
+                              coeffs, ingain, gains);
+    else
+        ComputePanningGainsBF(dry->Ambi.Map, dry->NumChannels, coeffs, ingain, gains);
+}
 
+void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
 /**
  * ComputeFirstOrderGains
  *
@@ -490,24 +493,29 @@ void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, con
  * a 1x4 'slice' of a transform matrix for the input channel, used to scale and
  * orient the sound samples.
  */
-#define ComputeFirstOrderGains(b, m, g, o) do {                               \
-    if((b).CoeffCount > 0)                                                    \
-        ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o);  \
-    else                                                                      \
-        ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o);     \
-} while (0)
-void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
-void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALsizei numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]);
+inline void ComputeFirstOrderGains(const BFMixParams *foa, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS])
+{
+    if(foa->CoeffCount > 0)
+        ComputeFirstOrderGainsMC(foa->Ambi.Coeffs, foa->NumChannels, mtx, ingain, gains);
+    else
+        ComputeFirstOrderGainsBF(foa->Ambi.Map, foa->NumChannels, mtx, ingain, gains);
+}
 
 
-ALboolean MixSource(struct ALvoice *voice, struct ALsource *Source, ALCdevice *Device, ALsizei SamplesToDo);
+ALboolean MixSource(struct ALvoice *voice, ALuint SourceID, ALCcontext *Context, ALsizei SamplesToDo);
 
 void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples);
-/* Caller must lock the device. */
-void aluHandleDisconnect(ALCdevice *device);
+/* Caller must lock the device, and the mixer must not be running. */
+void aluHandleDisconnect(ALCdevice *device, const char *msg, ...) DECL_FORMAT(printf, 2, 3);
+
+void UpdateContextProps(ALCcontext *context);
+
+extern MixerFunc MixSamples;
+extern RowMixerFunc MixRowSamples;
 
 extern ALfloat ConeScale;
 extern ALfloat ZScale;
+extern ALboolean OverrideReverbSpeedOfSound;
 
 #ifdef __cplusplus
 }

+ 7 - 1
libs/openal-soft/OpenAL32/Include/sample_cvt.h

@@ -4,6 +4,12 @@
 #include "AL/al.h"
 #include "alBuffer.h"
 
-void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align);
+extern const ALshort muLawDecompressionTable[256];
+extern const ALshort aLawDecompressionTable[256];
+
+void Convert_ALshort_ALima4(ALshort *dst, const ALubyte *src, ALsizei numchans, ALsizei len,
+                            ALsizei align);
+void Convert_ALshort_ALmsadpcm(ALshort *dst, const ALubyte *src, ALsizei numchans, ALsizei len,
+                               ALsizei align);
 
 #endif /* SAMPLE_CVT_H */

+ 276 - 207
libs/openal-soft/OpenAL32/alAuxEffectSlot.c

@@ -27,36 +27,79 @@
 #include "AL/alc.h"
 #include "alMain.h"
 #include "alAuxEffectSlot.h"
-#include "alThunk.h"
 #include "alError.h"
 #include "alListener.h"
 #include "alSource.h"
 
+#include "fpu_modes.h"
 #include "almalloc.h"
 
 
-extern inline void LockEffectSlotsRead(ALCcontext *context);
-extern inline void UnlockEffectSlotsRead(ALCcontext *context);
-extern inline void LockEffectSlotsWrite(ALCcontext *context);
-extern inline void UnlockEffectSlotsWrite(ALCcontext *context);
-extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id);
-extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id);
-
-static UIntMap EffectStateFactoryMap;
-static inline ALeffectStateFactory *getFactoryByType(ALenum type)
+extern inline void LockEffectSlotList(ALCcontext *context);
+extern inline void UnlockEffectSlotList(ALCcontext *context);
+
+static void AddActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *context);
+static void RemoveActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *context);
+
+static const struct {
+    ALenum Type;
+    EffectStateFactory* (*GetFactory)(void);
+} FactoryList[] = {
+    { AL_EFFECT_NULL, NullStateFactory_getFactory },
+    { AL_EFFECT_EAXREVERB, ReverbStateFactory_getFactory },
+    { AL_EFFECT_REVERB, ReverbStateFactory_getFactory },
+    { AL_EFFECT_CHORUS, ChorusStateFactory_getFactory },
+    { AL_EFFECT_COMPRESSOR, CompressorStateFactory_getFactory },
+    { AL_EFFECT_DISTORTION, DistortionStateFactory_getFactory },
+    { AL_EFFECT_ECHO, EchoStateFactory_getFactory },
+    { AL_EFFECT_EQUALIZER, EqualizerStateFactory_getFactory },
+    { AL_EFFECT_FLANGER, FlangerStateFactory_getFactory },
+    { AL_EFFECT_RING_MODULATOR, ModulatorStateFactory_getFactory },
+    { AL_EFFECT_PITCH_SHIFTER, PshifterStateFactory_getFactory},
+    { AL_EFFECT_DEDICATED_DIALOGUE, DedicatedStateFactory_getFactory },
+    { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, DedicatedStateFactory_getFactory }
+};
+
+static inline EffectStateFactory *getFactoryByType(ALenum type)
 {
-    ALeffectStateFactory* (*getFactory)(void) = LookupUIntMapKey(&EffectStateFactoryMap, type);
-    if(getFactory != NULL)
-        return getFactory();
+    size_t i;
+    for(i = 0;i < COUNTOF(FactoryList);i++)
+    {
+        if(FactoryList[i].Type == type)
+            return FactoryList[i].GetFactory();
+    }
     return NULL;
 }
 
 static void ALeffectState_IncRef(ALeffectState *state);
-static void ALeffectState_DecRef(ALeffectState *state);
+
+
+static inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)
+{
+    id--;
+    if(UNLIKELY(id >= VECTOR_SIZE(context->EffectSlotList)))
+        return NULL;
+    return VECTOR_ELEM(context->EffectSlotList, id);
+}
+
+static inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
+{
+    EffectSubList *sublist;
+    ALuint lidx = (id-1) >> 6;
+    ALsizei slidx = (id-1) & 0x3f;
+
+    if(UNLIKELY(lidx >= VECTOR_SIZE(device->EffectList)))
+        return NULL;
+    sublist = &VECTOR_ELEM(device->EffectList, lidx);
+    if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
+        return NULL;
+    return sublist->Effects + slidx;
+}
+
 
 #define DO_UPDATEPROPS() do {                                                 \
     if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))          \
-        UpdateEffectSlotProps(slot);                                          \
+        UpdateEffectSlotProps(slot, context);                                 \
     else                                                                      \
         ATOMIC_FLAG_CLEAR(&slot->PropsClean, almemory_order_release);         \
 } while(0)
@@ -64,77 +107,62 @@ static void ALeffectState_DecRef(ALeffectState *state);
 
 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
 {
+    ALCdevice *device;
     ALCcontext *context;
-    ALeffectslot **tmpslots = NULL;
     ALsizei cur;
-    ALenum err;
 
     context = GetContextRef();
     if(!context) return;
 
     if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    tmpslots = al_malloc(DEF_ALIGN, sizeof(ALeffectslot*)*n);
+        SETERR_GOTO(context, AL_INVALID_VALUE, done, "Generating %d effect slots", n);
+    if(n == 0) goto done;
 
-    LockEffectSlotsWrite(context);
+    LockEffectSlotList(context);
+    device = context->Device;
+    if(device->AuxiliaryEffectSlotMax - VECTOR_SIZE(context->EffectSlotList) < (ALuint)n)
+    {
+        UnlockEffectSlotList(context);
+        SETERR_GOTO(context, AL_OUT_OF_MEMORY, done, "Exceeding %u auxiliary effect slot limit",
+                    device->AuxiliaryEffectSlotMax);
+    }
     for(cur = 0;cur < n;cur++)
     {
-        ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
-        err = AL_OUT_OF_MEMORY;
-        if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
-        {
-            al_free(slot);
-            UnlockEffectSlotsWrite(context);
+        ALeffectslotPtr *iter = VECTOR_BEGIN(context->EffectSlotList);
+        ALeffectslotPtr *end = VECTOR_END(context->EffectSlotList);
+        ALeffectslot *slot = NULL;
+        ALenum err = AL_OUT_OF_MEMORY;
 
-            alDeleteAuxiliaryEffectSlots(cur, effectslots);
-            SET_ERROR_AND_GOTO(context, err, done);
+        for(;iter != end;iter++)
+        {
+            if(!*iter)
+                break;
         }
-
-        err = NewThunkEntry(&slot->id);
-        if(err == AL_NO_ERROR)
-            err = InsertUIntMapEntryNoLock(&context->EffectSlotMap, slot->id, slot);
-        if(err != AL_NO_ERROR)
+        if(iter == end)
+        {
+            VECTOR_PUSH_BACK(context->EffectSlotList, NULL);
+            iter = &VECTOR_BACK(context->EffectSlotList);
+        }
+        slot = al_calloc(16, sizeof(ALeffectslot));
+        if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
         {
-            FreeThunkEntry(slot->id);
-            ALeffectState_DecRef(slot->Effect.State);
-            if(slot->Params.EffectState)
-                ALeffectState_DecRef(slot->Params.EffectState);
             al_free(slot);
-            UnlockEffectSlotsWrite(context);
+            UnlockEffectSlotList(context);
 
             alDeleteAuxiliaryEffectSlots(cur, effectslots);
-            SET_ERROR_AND_GOTO(context, err, done);
+            SETERR_GOTO(context, err, done, "Effect slot object allocation failed");
         }
-
         aluInitEffectPanning(slot);
 
-        tmpslots[cur] = slot;
-        effectslots[cur] = slot->id;
-    }
-    if(n > 0)
-    {
-        struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
-        struct ALeffectslotArray *newarray = NULL;
-        ALsizei newcount = curarray->count + n;
-        ALCdevice *device;
-
-        newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
-        newarray->count = newcount;
-        memcpy(newarray->slot, tmpslots, sizeof(ALeffectslot*)*n);
-        if(curarray)
-            memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count);
+        slot->id = (iter - VECTOR_BEGIN(context->EffectSlotList)) + 1;
+        *iter = slot;
 
-        newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
-                                       almemory_order_acq_rel);
-        device = context->Device;
-        while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
-            althrd_yield();
-        al_free(newarray);
+        effectslots[cur] = slot->id;
     }
-    UnlockEffectSlotsWrite(context);
+    AddActiveEffectSlots(effectslots, n, context);
+    UnlockEffectSlotList(context);
 
 done:
-    al_free(tmpslots);
     ALCcontext_DecRef(context);
 }
 
@@ -147,54 +175,28 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *
     context = GetContextRef();
     if(!context) return;
 
-    LockEffectSlotsWrite(context);
+    LockEffectSlotList(context);
     if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+        SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d effect slots", n);
+    if(n == 0) goto done;
+
     for(i = 0;i < n;i++)
     {
         if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+            SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u",
+                        effectslots[i]);
         if(ReadRef(&slot->ref) != 0)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
+            SETERR_GOTO(context, AL_INVALID_NAME, done, "Deleting in-use effect slot %u",
+                        effectslots[i]);
     }
 
     // All effectslots are valid
-    if(n > 0)
-    {
-        struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
-        struct ALeffectslotArray *newarray = NULL;
-        ALsizei newcount = curarray->count - n;
-        ALCdevice *device;
-        ALsizei j, k;
-
-        assert(newcount >= 0);
-        newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
-        newarray->count = newcount;
-        for(i = j = 0;i < newarray->count;)
-        {
-            slot = curarray->slot[j++];
-            for(k = 0;k < n;k++)
-            {
-                if(slot->id == effectslots[k])
-                    break;
-            }
-            if(k == n)
-                newarray->slot[i++] = slot;
-        }
-
-        newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
-                                       almemory_order_acq_rel);
-        device = context->Device;
-        while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
-            althrd_yield();
-        al_free(newarray);
-    }
-
+    RemoveActiveEffectSlots(effectslots, n, context);
     for(i = 0;i < n;i++)
     {
-        if((slot=RemoveEffectSlot(context, effectslots[i])) == NULL)
+        if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
             continue;
-        FreeThunkEntry(slot->id);
+        VECTOR_ELEM(context->EffectSlotList, effectslots[i]-1) = NULL;
 
         DeinitEffectSlot(slot);
 
@@ -203,7 +205,7 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *
     }
 
 done:
-    UnlockEffectSlotsWrite(context);
+    UnlockEffectSlotList(context);
     ALCcontext_DecRef(context);
 }
 
@@ -215,9 +217,9 @@ AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
     context = GetContextRef();
     if(!context) return AL_FALSE;
 
-    LockEffectSlotsRead(context);
+    LockEffectSlotList(context);
     ret = (LookupEffectSlot(context, effectslot) ? AL_TRUE : AL_FALSE);
-    UnlockEffectSlotsRead(context);
+    UnlockEffectSlotList(context);
 
     ALCcontext_DecRef(context);
 
@@ -235,43 +237,45 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
-    LockEffectSlotsRead(context);
+    almtx_lock(&context->PropLock);
+    LockEffectSlotList(context);
     if((slot=LookupEffectSlot(context, effectslot)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
     switch(param)
     {
     case AL_EFFECTSLOT_EFFECT:
         device = context->Device;
 
-        LockEffectsRead(device);
+        LockEffectList(device);
         effect = (value ? LookupEffect(device, value) : NULL);
         if(!(value == 0 || effect != NULL))
         {
-            UnlockEffectsRead(device);
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+            UnlockEffectList(device);
+            SETERR_GOTO(context, AL_INVALID_VALUE, done, "Invalid effect ID %u", value);
         }
-        err = InitializeEffect(device, slot, effect);
-        UnlockEffectsRead(device);
+        err = InitializeEffect(context, slot, effect);
+        UnlockEffectList(device);
 
         if(err != AL_NO_ERROR)
-            SET_ERROR_AND_GOTO(context, err, done);
+            SETERR_GOTO(context, err, done, "Effect initialization failed");
         break;
 
     case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
         if(!(value == AL_TRUE || value == AL_FALSE))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+            SETERR_GOTO(context, AL_INVALID_VALUE, done,
+                        "Effect slot auxiliary send auto out of range");
         slot->AuxSendAuto = value;
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        SETERR_GOTO(context, AL_INVALID_ENUM, done, "Invalid effect slot integer property 0x%04x",
+                    param);
     }
     DO_UPDATEPROPS();
 
 done:
-    UnlockEffectSlotsRead(context);
-    WriteUnlock(&context->PropLock);
+    UnlockEffectSlotList(context);
+    almtx_unlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -290,17 +294,18 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum para
     context = GetContextRef();
     if(!context) return;
 
-    LockEffectSlotsRead(context);
+    LockEffectSlotList(context);
     if(LookupEffectSlot(context, effectslot) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
     switch(param)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid effect slot integer-vector property 0x%04x",
+                   param);
     }
 
 done:
-    UnlockEffectSlotsRead(context);
+    UnlockEffectSlotList(context);
     ALCcontext_DecRef(context);
 }
 
@@ -312,26 +317,27 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
-    LockEffectSlotsRead(context);
+    almtx_lock(&context->PropLock);
+    LockEffectSlotList(context);
     if((slot=LookupEffectSlot(context, effectslot)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
     switch(param)
     {
     case AL_EFFECTSLOT_GAIN:
         if(!(value >= 0.0f && value <= 1.0f))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+            SETERR_GOTO(context, AL_INVALID_VALUE, done, "Effect slot gain out of range");
         slot->Gain = value;
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        SETERR_GOTO(context, AL_INVALID_ENUM, done, "Invalid effect slot float property 0x%04x",
+                    param);
     }
     DO_UPDATEPROPS();
 
 done:
-    UnlockEffectSlotsRead(context);
-    WriteUnlock(&context->PropLock);
+    UnlockEffectSlotList(context);
+    almtx_unlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -349,17 +355,18 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum para
     context = GetContextRef();
     if(!context) return;
 
-    LockEffectSlotsRead(context);
+    LockEffectSlotList(context);
     if(LookupEffectSlot(context, effectslot) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
     switch(param)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid effect slot float-vector property 0x%04x",
+                   param);
     }
 
 done:
-    UnlockEffectSlotsRead(context);
+    UnlockEffectSlotList(context);
     ALCcontext_DecRef(context);
 }
 
@@ -371,9 +378,9 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum pa
     context = GetContextRef();
     if(!context) return;
 
-    LockEffectSlotsRead(context);
+    LockEffectSlotList(context);
     if((slot=LookupEffectSlot(context, effectslot)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
     switch(param)
     {
     case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
@@ -381,11 +388,11 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum pa
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", param);
     }
 
 done:
-    UnlockEffectSlotsRead(context);
+    UnlockEffectSlotList(context);
     ALCcontext_DecRef(context);
 }
 
@@ -404,17 +411,18 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum p
     context = GetContextRef();
     if(!context) return;
 
-    LockEffectSlotsRead(context);
+    LockEffectSlotList(context);
     if(LookupEffectSlot(context, effectslot) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
     switch(param)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid effect slot integer-vector property 0x%04x",
+                   param);
     }
 
 done:
-    UnlockEffectSlotsRead(context);
+    UnlockEffectSlotList(context);
     ALCcontext_DecRef(context);
 }
 
@@ -426,9 +434,9 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum pa
     context = GetContextRef();
     if(!context) return;
 
-    LockEffectSlotsRead(context);
+    LockEffectSlotList(context);
     if((slot=LookupEffectSlot(context, effectslot)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
     switch(param)
     {
     case AL_EFFECTSLOT_GAIN:
@@ -436,11 +444,11 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum pa
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", param);
     }
 
 done:
-    UnlockEffectSlotsRead(context);
+    UnlockEffectSlotList(context);
     ALCcontext_DecRef(context);
 }
 
@@ -458,54 +466,32 @@ AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum p
     context = GetContextRef();
     if(!context) return;
 
-    LockEffectSlotsRead(context);
+    LockEffectSlotList(context);
     if(LookupEffectSlot(context, effectslot) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+        SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect slot ID %u", effectslot);
     switch(param)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid effect slot float-vector property 0x%04x",
+                   param);
     }
 
 done:
-    UnlockEffectSlotsRead(context);
+    UnlockEffectSlotList(context);
     ALCcontext_DecRef(context);
 }
 
 
-void InitEffectFactoryMap(void)
-{
-    InitUIntMap(&EffectStateFactoryMap, INT_MAX);
-
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_NULL, ALnullStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EAXREVERB, ALreverbStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_REVERB, ALreverbStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_CHORUS, ALchorusStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_COMPRESSOR, ALcompressorStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DISTORTION, ALdistortionStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_ECHO, ALechoStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EQUALIZER, ALequalizerStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_FLANGER, ALflangerStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_RING_MODULATOR, ALmodulatorStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_DIALOGUE, ALdedicatedStateFactory_getFactory);
-    InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, ALdedicatedStateFactory_getFactory);
-}
-
-void DeinitEffectFactoryMap(void)
-{
-    ResetUIntMap(&EffectStateFactoryMap);
-}
-
-
-ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
+ALenum InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect)
 {
+    ALCdevice *Device = Context->Device;
     ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
     struct ALeffectslotProps *props;
     ALeffectState *State;
 
     if(newtype != EffectSlot->Effect.Type)
     {
-        ALeffectStateFactory *factory;
+        EffectStateFactory *factory;
 
         factory = getFactoryByType(newtype);
         if(!factory)
@@ -513,7 +499,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
             ERR("Failed to find factory for effect type 0x%04x\n", newtype);
             return AL_INVALID_ENUM;
         }
-        State = V0(factory,create)();
+        State = EffectStateFactory_create(factory);
         if(!State) return AL_OUT_OF_MEMORY;
 
         START_MIXER_MODE();
@@ -548,7 +534,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e
         EffectSlot->Effect.Props = effect->Props;
 
     /* Remove state references from old effect slot property updates. */
-    props = ATOMIC_LOAD_SEQ(&EffectSlot->FreeList);
+    props = ATOMIC_LOAD_SEQ(&Context->FreeEffectslotProps);
     while(props)
     {
         if(props->State)
@@ -568,7 +554,7 @@ static void ALeffectState_IncRef(ALeffectState *state)
     TRACEREF("%p increasing refcount to %u\n", state, ref);
 }
 
-static void ALeffectState_DecRef(ALeffectState *state)
+void ALeffectState_DecRef(ALeffectState *state)
 {
     uint ref;
     ref = DecrementRef(&state->Ref);
@@ -590,15 +576,103 @@ void ALeffectState_Destruct(ALeffectState *UNUSED(state))
 }
 
 
+static void AddActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *context)
+{
+    struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots,
+                                                     almemory_order_acquire);
+    struct ALeffectslotArray *newarray = NULL;
+    ALsizei newcount = curarray->count + count;
+    ALCdevice *device = context->Device;
+    ALsizei i, j;
+
+    /* Insert the new effect slots into the head of the array, followed by the
+     * existing ones.
+     */
+    newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
+    newarray->count = newcount;
+    for(i = 0;i < count;i++)
+        newarray->slot[i] = LookupEffectSlot(context, slotids[i]);
+    for(j = 0;i < newcount;)
+        newarray->slot[i++] = curarray->slot[j++];
+    /* Remove any duplicates (first instance of each will be kept). */
+    for(i = 1;i < newcount;i++)
+    {
+        for(j = i;j != 0;)
+        {
+            if(UNLIKELY(newarray->slot[i] == newarray->slot[--j]))
+            {
+                newcount--;
+                for(j = i;j < newcount;j++)
+                    newarray->slot[j] = newarray->slot[j+1];
+                i--;
+                break;
+            }
+        }
+    }
+
+    /* Reallocate newarray if the new size ended up smaller from duplicate
+     * removal.
+     */
+    if(UNLIKELY(newcount < newarray->count))
+    {
+        struct ALeffectslotArray *tmpnewarray = al_calloc(DEF_ALIGN,
+            FAM_SIZE(struct ALeffectslotArray, slot, newcount));
+        memcpy(tmpnewarray, newarray, FAM_SIZE(struct ALeffectslotArray, slot, newcount));
+        al_free(newarray);
+        newarray = tmpnewarray;
+        newarray->count = newcount;
+    }
+
+    curarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray, almemory_order_acq_rel);
+    while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
+        althrd_yield();
+    al_free(curarray);
+}
+
+static void RemoveActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *context)
+{
+    struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots,
+                                                     almemory_order_acquire);
+    struct ALeffectslotArray *newarray = NULL;
+    ALCdevice *device = context->Device;
+    ALsizei i, j;
+
+    /* Don't shrink the allocated array size since we don't know how many (if
+     * any) of the effect slots to remove are in the array.
+     */
+    newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, curarray->count));
+    newarray->count = 0;
+    for(i = 0;i < curarray->count;i++)
+    {
+        /* Insert this slot into the new array only if it's not one to remove. */
+        ALeffectslot *slot = curarray->slot[i];
+        for(j = count;j != 0;)
+        {
+            if(slot->id == slotids[--j])
+                goto skip_ins;
+        }
+        newarray->slot[newarray->count++] = slot;
+    skip_ins: ;
+    }
+
+    /* TODO: Could reallocate newarray now that we know it's needed size. */
+
+    curarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray, almemory_order_acq_rel);
+    while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
+        althrd_yield();
+    al_free(curarray);
+}
+
+
 ALenum InitEffectSlot(ALeffectslot *slot)
 {
-    ALeffectStateFactory *factory;
+    EffectStateFactory *factory;
 
     slot->Effect.Type = AL_EFFECT_NULL;
 
     factory = getFactoryByType(AL_EFFECT_NULL);
-    if(!(slot->Effect.State=V0(factory,create)()))
-        return AL_OUT_OF_MEMORY;
+    slot->Effect.State = EffectStateFactory_create(factory);
+    if(!slot->Effect.State) return AL_OUT_OF_MEMORY;
 
     slot->Gain = 1.0;
     slot->AuxSendAuto = AL_TRUE;
@@ -606,7 +680,6 @@ ALenum InitEffectSlot(ALeffectslot *slot)
     InitRef(&slot->ref, 0);
 
     ATOMIC_INIT(&slot->Update, NULL);
-    ATOMIC_INIT(&slot->FreeList, NULL);
 
     slot->Params.Gain = 1.0f;
     slot->Params.AuxSendAuto = AL_TRUE;
@@ -614,6 +687,7 @@ ALenum InitEffectSlot(ALeffectslot *slot)
     slot->Params.EffectState = slot->Effect.State;
     slot->Params.RoomRolloff = 0.0f;
     slot->Params.DecayTime = 0.0f;
+    slot->Params.DecayLFRatio = 0.0f;
     slot->Params.DecayHFRatio = 0.0f;
     slot->Params.DecayHFLimit = AL_FALSE;
     slot->Params.AirAbsorptionGainHF = 1.0f;
@@ -624,7 +698,6 @@ ALenum InitEffectSlot(ALeffectslot *slot)
 void DeinitEffectSlot(ALeffectslot *slot)
 {
     struct ALeffectslotProps *props;
-    size_t count = 0;
 
     props = ATOMIC_LOAD_SEQ(&slot->Update);
     if(props)
@@ -633,29 +706,19 @@ void DeinitEffectSlot(ALeffectslot *slot)
         TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
         al_free(props);
     }
-    props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
-    while(props)
-    {
-        struct ALeffectslotProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
-        if(props->State) ALeffectState_DecRef(props->State);
-        al_free(props);
-        props = next;
-        ++count;
-    }
-    TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
 
     ALeffectState_DecRef(slot->Effect.State);
     if(slot->Params.EffectState)
         ALeffectState_DecRef(slot->Params.EffectState);
 }
 
-void UpdateEffectSlotProps(ALeffectslot *slot)
+void UpdateEffectSlotProps(ALeffectslot *slot, ALCcontext *context)
 {
     struct ALeffectslotProps *props;
     ALeffectState *oldstate;
 
     /* Get an unused property container, or allocate a new one as needed. */
-    props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
+    props = ATOMIC_LOAD(&context->FreeEffectslotProps, almemory_order_relaxed);
     if(!props)
         props = al_calloc(16, sizeof(*props));
     else
@@ -663,7 +726,7 @@ void UpdateEffectSlotProps(ALeffectslot *slot)
         struct ALeffectslotProps *next;
         do {
             next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
-        } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&slot->FreeList, &props, next,
+        } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeEffectslotProps, &props, next,
                 almemory_order_seq_cst, almemory_order_acquire) == 0);
     }
 
@@ -687,7 +750,7 @@ void UpdateEffectSlotProps(ALeffectslot *slot)
         /* If there was an unused update container, put it back in the
          * freelist.
          */
-        ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &slot->FreeList, props);
+        ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &context->FreeEffectslotProps, props);
     }
 
     if(oldstate)
@@ -699,29 +762,35 @@ void UpdateAllEffectSlotProps(ALCcontext *context)
     struct ALeffectslotArray *auxslots;
     ALsizei i;
 
-    LockEffectSlotsRead(context);
+    LockEffectSlotList(context);
     auxslots = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
     for(i = 0;i < auxslots->count;i++)
     {
         ALeffectslot *slot = auxslots->slot[i];
         if(!ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_acq_rel))
-            UpdateEffectSlotProps(slot);
+            UpdateEffectSlotProps(slot, context);
     }
-    UnlockEffectSlotsRead(context);
+    UnlockEffectSlotList(context);
 }
 
-ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
+ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *context)
 {
-    ALsizei pos;
-    for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
+    ALeffectslotPtr *iter = VECTOR_BEGIN(context->EffectSlotList);
+    ALeffectslotPtr *end = VECTOR_END(context->EffectSlotList);
+    size_t leftover = 0;
+
+    for(;iter != end;iter++)
     {
-        ALeffectslot *temp = Context->EffectSlotMap.values[pos];
-        Context->EffectSlotMap.values[pos] = NULL;
+        ALeffectslot *slot = *iter;
+        if(!slot) continue;
+        *iter = NULL;
 
-        DeinitEffectSlot(temp);
+        DeinitEffectSlot(slot);
 
-        FreeThunkEntry(temp->id);
-        memset(temp, 0, sizeof(ALeffectslot));
-        al_free(temp);
+        memset(slot, 0, sizeof(*slot));
+        al_free(slot);
+        ++leftover;
     }
+    if(leftover > 0)
+        WARN("(%p) Deleted "SZFMT" AuxiliaryEffectSlot%s\n", context, leftover, (leftover==1)?"":"s");
 }

File diff suppressed because it is too large
+ 331 - 433
libs/openal-soft/OpenAL32/alBuffer.c


+ 199 - 111
libs/openal-soft/OpenAL32/alEffect.c

@@ -28,26 +28,51 @@
 #include "AL/alc.h"
 #include "alMain.h"
 #include "alEffect.h"
-#include "alThunk.h"
 #include "alError.h"
 
 
-ALboolean DisabledEffects[MAX_EFFECTS];
-
-extern inline void LockEffectsRead(ALCdevice *device);
-extern inline void UnlockEffectsRead(ALCdevice *device);
-extern inline void LockEffectsWrite(ALCdevice *device);
-extern inline void UnlockEffectsWrite(ALCdevice *device);
-extern inline struct ALeffect *LookupEffect(ALCdevice *device, ALuint id);
-extern inline struct ALeffect *RemoveEffect(ALCdevice *device, ALuint id);
+extern inline void LockEffectList(ALCdevice *device);
+extern inline void UnlockEffectList(ALCdevice *device);
 extern inline ALboolean IsReverbEffect(ALenum type);
 
+const struct EffectList EffectList[EFFECTLIST_SIZE] = {
+    { "eaxreverb",  EAXREVERB_EFFECT,  AL_EFFECT_EAXREVERB },
+    { "reverb",     REVERB_EFFECT,     AL_EFFECT_REVERB },
+    { "chorus",     CHORUS_EFFECT,     AL_EFFECT_CHORUS },
+    { "compressor", COMPRESSOR_EFFECT, AL_EFFECT_COMPRESSOR },
+    { "distortion", DISTORTION_EFFECT, AL_EFFECT_DISTORTION },
+    { "echo",       ECHO_EFFECT,       AL_EFFECT_ECHO },
+    { "equalizer",  EQUALIZER_EFFECT,  AL_EFFECT_EQUALIZER },
+    { "flanger",    FLANGER_EFFECT,    AL_EFFECT_FLANGER },
+    { "modulator",  MODULATOR_EFFECT,  AL_EFFECT_RING_MODULATOR },
+    { "pshifter",   PSHIFTER_EFFECT,   AL_EFFECT_PITCH_SHIFTER },
+    { "dedicated",  DEDICATED_EFFECT,  AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
+    { "dedicated",  DEDICATED_EFFECT,  AL_EFFECT_DEDICATED_DIALOGUE },
+};
+
+ALboolean DisabledEffects[MAX_EFFECTS];
+
+static ALeffect *AllocEffect(ALCcontext *context);
+static void FreeEffect(ALCdevice *device, ALeffect *effect);
 static void InitEffectParams(ALeffect *effect, ALenum type);
 
+static inline ALeffect *LookupEffect(ALCdevice *device, ALuint id)
+{
+    EffectSubList *sublist;
+    ALuint lidx = (id-1) >> 6;
+    ALsizei slidx = (id-1) & 0x3f;
+
+    if(UNLIKELY(lidx >= VECTOR_SIZE(device->EffectList)))
+        return NULL;
+    sublist = &VECTOR_ELEM(device->EffectList, lidx);
+    if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
+        return NULL;
+    return sublist->Effects + slidx;
+}
+
 
 AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
 {
-    ALCdevice *device;
     ALCcontext *context;
     ALsizei cur;
 
@@ -55,37 +80,18 @@ AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects)
     if(!context) return;
 
     if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    for(cur = 0;cur < n;cur++)
+        alSetError(context, AL_INVALID_VALUE, "Generating %d effects", n);
+    else for(cur = 0;cur < n;cur++)
     {
-        ALeffect *effect = al_calloc(16, sizeof(ALeffect));
-        ALenum err = AL_OUT_OF_MEMORY;
-        if(!effect || (err=InitEffect(effect)) != AL_NO_ERROR)
+        ALeffect *effect = AllocEffect(context);
+        if(!effect)
         {
-            al_free(effect);
             alDeleteEffects(cur, effects);
-            SET_ERROR_AND_GOTO(context, err, done);
+            break;
         }
-
-        err = NewThunkEntry(&effect->id);
-        if(err == AL_NO_ERROR)
-            err = InsertUIntMapEntry(&device->EffectMap, effect->id, effect);
-        if(err != AL_NO_ERROR)
-        {
-            FreeThunkEntry(effect->id);
-            memset(effect, 0, sizeof(ALeffect));
-            al_free(effect);
-
-            alDeleteEffects(cur, effects);
-            SET_ERROR_AND_GOTO(context, err, done);
-        }
-
         effects[cur] = effect->id;
     }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -100,26 +106,22 @@ AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects)
     if(!context) return;
 
     device = context->Device;
-    LockEffectsWrite(device);
+    LockEffectList(device);
     if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+        SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d effects", n);
     for(i = 0;i < n;i++)
     {
         if(effects[i] && LookupEffect(device, effects[i]) == NULL)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+            SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid effect ID %u", effects[i]);
     }
     for(i = 0;i < n;i++)
     {
-        if((effect=RemoveEffect(device, effects[i])) == NULL)
-            continue;
-        FreeThunkEntry(effect->id);
-
-        memset(effect, 0, sizeof(*effect));
-        al_free(effect);
+        if((effect=LookupEffect(device, effects[i])) != NULL)
+            FreeEffect(device, effect);
     }
 
 done:
-    UnlockEffectsWrite(device);
+    UnlockEffectList(device);
     ALCcontext_DecRef(context);
 }
 
@@ -131,10 +133,10 @@ AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect)
     Context = GetContextRef();
     if(!Context) return AL_FALSE;
 
-    LockEffectsRead(Context->Device);
+    LockEffectList(Context->Device);
     result = ((!effect || LookupEffect(Context->Device, effect)) ?
               AL_TRUE : AL_FALSE);
-    UnlockEffectsRead(Context->Device);
+    UnlockEffectList(Context->Device);
 
     ALCcontext_DecRef(Context);
 
@@ -151,16 +153,16 @@ AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
     if(!Context) return;
 
     Device = Context->Device;
-    LockEffectsWrite(Device);
+    LockEffectList(Device);
     if((ALEffect=LookupEffect(Device, effect)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid effect ID %u", effect);
     else
     {
         if(param == AL_EFFECT_TYPE)
         {
             ALboolean isOk = (value == AL_EFFECT_NULL);
             ALint i;
-            for(i = 0;!isOk && EffectList[i].val;i++)
+            for(i = 0;!isOk && i < EFFECTLIST_SIZE;i++)
             {
                 if(value == EffectList[i].val &&
                    !DisabledEffects[EffectList[i].type])
@@ -170,15 +172,15 @@ AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value)
             if(isOk)
                 InitEffectParams(ALEffect, value);
             else
-                alSetError(Context, AL_INVALID_VALUE);
+                alSetError(Context, AL_INVALID_VALUE, "Effect type 0x%04x not supported", value);
         }
         else
         {
             /* Call the appropriate handler */
-            V(ALEffect,setParami)(Context, param, value);
+            ALeffect_setParami(ALEffect, Context, param, value);
         }
     }
-    UnlockEffectsWrite(Device);
+    UnlockEffectList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -200,15 +202,15 @@ AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *v
     if(!Context) return;
 
     Device = Context->Device;
-    LockEffectsWrite(Device);
+    LockEffectList(Device);
     if((ALEffect=LookupEffect(Device, effect)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid effect ID %u", effect);
     else
     {
         /* Call the appropriate handler */
-        V(ALEffect,setParamiv)(Context, param, values);
+        ALeffect_setParamiv(ALEffect, Context, param, values);
     }
-    UnlockEffectsWrite(Device);
+    UnlockEffectList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -223,15 +225,15 @@ AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value)
     if(!Context) return;
 
     Device = Context->Device;
-    LockEffectsWrite(Device);
+    LockEffectList(Device);
     if((ALEffect=LookupEffect(Device, effect)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid effect ID %u", effect);
     else
     {
         /* Call the appropriate handler */
-        V(ALEffect,setParamf)(Context, param, value);
+        ALeffect_setParamf(ALEffect, Context, param, value);
     }
-    UnlockEffectsWrite(Device);
+    UnlockEffectList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -246,15 +248,15 @@ AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat
     if(!Context) return;
 
     Device = Context->Device;
-    LockEffectsWrite(Device);
+    LockEffectList(Device);
     if((ALEffect=LookupEffect(Device, effect)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid effect ID %u", effect);
     else
     {
         /* Call the appropriate handler */
-        V(ALEffect,setParamfv)(Context, param, values);
+        ALeffect_setParamfv(ALEffect, Context, param, values);
     }
-    UnlockEffectsWrite(Device);
+    UnlockEffectList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -269,9 +271,9 @@ AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value
     if(!Context) return;
 
     Device = Context->Device;
-    LockEffectsRead(Device);
+    LockEffectList(Device);
     if((ALEffect=LookupEffect(Device, effect)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid effect ID %u", effect);
     else
     {
         if(param == AL_EFFECT_TYPE)
@@ -279,10 +281,10 @@ AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value
         else
         {
             /* Call the appropriate handler */
-            V(ALEffect,getParami)(Context, param, value);
+            ALeffect_getParami(ALEffect, Context, param, value);
         }
     }
-    UnlockEffectsRead(Device);
+    UnlockEffectList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -304,15 +306,15 @@ AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *valu
     if(!Context) return;
 
     Device = Context->Device;
-    LockEffectsRead(Device);
+    LockEffectList(Device);
     if((ALEffect=LookupEffect(Device, effect)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid effect ID %u", effect);
     else
     {
         /* Call the appropriate handler */
-        V(ALEffect,getParamiv)(Context, param, values);
+        ALeffect_getParamiv(ALEffect, Context, param, values);
     }
-    UnlockEffectsRead(Device);
+    UnlockEffectList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -327,15 +329,15 @@ AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *val
     if(!Context) return;
 
     Device = Context->Device;
-    LockEffectsRead(Device);
+    LockEffectList(Device);
     if((ALEffect=LookupEffect(Device, effect)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid effect ID %u", effect);
     else
     {
         /* Call the appropriate handler */
-        V(ALEffect,getParamf)(Context, param, value);
+        ALeffect_getParamf(ALEffect, Context, param, value);
     }
-    UnlockEffectsRead(Device);
+    UnlockEffectList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -350,39 +352,120 @@ AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *va
     if(!Context) return;
 
     Device = Context->Device;
-    LockEffectsRead(Device);
+    LockEffectList(Device);
     if((ALEffect=LookupEffect(Device, effect)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid effect ID %u", effect);
     else
     {
         /* Call the appropriate handler */
-        V(ALEffect,getParamfv)(Context, param, values);
+        ALeffect_getParamfv(ALEffect, Context, param, values);
     }
-    UnlockEffectsRead(Device);
+    UnlockEffectList(Device);
 
     ALCcontext_DecRef(Context);
 }
 
 
-ALenum InitEffect(ALeffect *effect)
+void InitEffect(ALeffect *effect)
 {
     InitEffectParams(effect, AL_EFFECT_NULL);
-    return AL_NO_ERROR;
 }
 
-ALvoid ReleaseALEffects(ALCdevice *device)
+static ALeffect *AllocEffect(ALCcontext *context)
 {
-    ALsizei i;
-    for(i = 0;i < device->EffectMap.size;i++)
+    ALCdevice *device = context->Device;
+    EffectSubList *sublist, *subend;
+    ALeffect *effect = NULL;
+    ALsizei lidx = 0;
+    ALsizei slidx;
+
+    almtx_lock(&device->EffectLock);
+    sublist = VECTOR_BEGIN(device->EffectList);
+    subend = VECTOR_END(device->EffectList);
+    for(;sublist != subend;++sublist)
+    {
+        if(sublist->FreeMask)
+        {
+            slidx = CTZ64(sublist->FreeMask);
+            effect = sublist->Effects + slidx;
+            break;
+        }
+        ++lidx;
+    }
+    if(UNLIKELY(!effect))
     {
-        ALeffect *temp = device->EffectMap.values[i];
-        device->EffectMap.values[i] = NULL;
+        const EffectSubList empty_sublist = { 0, NULL };
+        /* Don't allocate so many list entries that the 32-bit ID could
+         * overflow...
+         */
+        if(UNLIKELY(VECTOR_SIZE(device->EffectList) >= 1<<25))
+        {
+            almtx_unlock(&device->EffectLock);
+            alSetError(context, AL_OUT_OF_MEMORY, "Too many effects allocated");
+            return NULL;
+        }
+        lidx = (ALsizei)VECTOR_SIZE(device->EffectList);
+        VECTOR_PUSH_BACK(device->EffectList, empty_sublist);
+        sublist = &VECTOR_BACK(device->EffectList);
+        sublist->FreeMask = ~U64(0);
+        sublist->Effects = al_calloc(16, sizeof(ALeffect)*64);
+        if(UNLIKELY(!sublist->Effects))
+        {
+            VECTOR_POP_BACK(device->EffectList);
+            almtx_unlock(&device->EffectLock);
+            alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate effect batch");
+            return NULL;
+        }
 
-        // Release effect structure
-        FreeThunkEntry(temp->id);
-        memset(temp, 0, sizeof(ALeffect));
-        al_free(temp);
+        slidx = 0;
+        effect = sublist->Effects + slidx;
     }
+
+    memset(effect, 0, sizeof(*effect));
+    InitEffectParams(effect, AL_EFFECT_NULL);
+
+    /* Add 1 to avoid effect ID 0. */
+    effect->id = ((lidx<<6) | slidx) + 1;
+
+    sublist->FreeMask &= ~(U64(1)<<slidx);
+    almtx_unlock(&device->EffectLock);
+
+    return effect;
+}
+
+static void FreeEffect(ALCdevice *device, ALeffect *effect)
+{
+    ALuint id = effect->id - 1;
+    ALsizei lidx = id >> 6;
+    ALsizei slidx = id & 0x3f;
+
+    memset(effect, 0, sizeof(*effect));
+
+    VECTOR_ELEM(device->EffectList, lidx).FreeMask |= U64(1) << slidx;
+}
+
+void ReleaseALEffects(ALCdevice *device)
+{
+    EffectSubList *sublist = VECTOR_BEGIN(device->EffectList);
+    EffectSubList *subend = VECTOR_END(device->EffectList);
+    size_t leftover = 0;
+    for(;sublist != subend;++sublist)
+    {
+        ALuint64 usemask = ~sublist->FreeMask;
+        while(usemask)
+        {
+            ALsizei idx = CTZ64(usemask);
+            ALeffect *effect = sublist->Effects + idx;
+
+            memset(effect, 0, sizeof(*effect));
+            ++leftover;
+
+            usemask &= ~(U64(1) << idx);
+        }
+        sublist->FreeMask = ~usemask;
+    }
+    if(leftover > 0)
+        WARN("(%p) Deleted "SZFMT" Effect%s\n", device, leftover, (leftover==1)?"":"s");
 }
 
 
@@ -418,7 +501,7 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
         effect->Props.Reverb.LFReference = AL_EAXREVERB_DEFAULT_LFREFERENCE;
         effect->Props.Reverb.RoomRolloffFactor = AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR;
         effect->Props.Reverb.DecayHFLimit = AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT;
-        SET_VTABLE1(ALeaxreverb, effect);
+        effect->vtab = &ALeaxreverb_vtable;
         break;
     case AL_EFFECT_REVERB:
         effect->Props.Reverb.Density   = AL_REVERB_DEFAULT_DENSITY;
@@ -448,7 +531,7 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
         effect->Props.Reverb.LFReference = 250.0f;
         effect->Props.Reverb.RoomRolloffFactor = AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR;
         effect->Props.Reverb.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT;
-        SET_VTABLE1(ALreverb, effect);
+        effect->vtab = &ALreverb_vtable;
         break;
     case AL_EFFECT_CHORUS:
         effect->Props.Chorus.Waveform = AL_CHORUS_DEFAULT_WAVEFORM;
@@ -457,11 +540,11 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
         effect->Props.Chorus.Depth = AL_CHORUS_DEFAULT_DEPTH;
         effect->Props.Chorus.Feedback = AL_CHORUS_DEFAULT_FEEDBACK;
         effect->Props.Chorus.Delay = AL_CHORUS_DEFAULT_DELAY;
-        SET_VTABLE1(ALchorus, effect);
+        effect->vtab = &ALchorus_vtable;
         break;
     case AL_EFFECT_COMPRESSOR:
         effect->Props.Compressor.OnOff = AL_COMPRESSOR_DEFAULT_ONOFF;
-        SET_VTABLE1(ALcompressor, effect);
+        effect->vtab = &ALcompressor_vtable;
         break;
     case AL_EFFECT_DISTORTION:
         effect->Props.Distortion.Edge = AL_DISTORTION_DEFAULT_EDGE;
@@ -469,7 +552,7 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
         effect->Props.Distortion.LowpassCutoff = AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF;
         effect->Props.Distortion.EQCenter = AL_DISTORTION_DEFAULT_EQCENTER;
         effect->Props.Distortion.EQBandwidth = AL_DISTORTION_DEFAULT_EQBANDWIDTH;
-        SET_VTABLE1(ALdistortion, effect);
+        effect->vtab = &ALdistortion_vtable;
         break;
     case AL_EFFECT_ECHO:
         effect->Props.Echo.Delay    = AL_ECHO_DEFAULT_DELAY;
@@ -477,7 +560,7 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
         effect->Props.Echo.Damping  = AL_ECHO_DEFAULT_DAMPING;
         effect->Props.Echo.Feedback = AL_ECHO_DEFAULT_FEEDBACK;
         effect->Props.Echo.Spread   = AL_ECHO_DEFAULT_SPREAD;
-        SET_VTABLE1(ALecho, effect);
+        effect->vtab = &ALecho_vtable;
         break;
     case AL_EFFECT_EQUALIZER:
         effect->Props.Equalizer.LowCutoff = AL_EQUALIZER_DEFAULT_LOW_CUTOFF;
@@ -490,30 +573,35 @@ static void InitEffectParams(ALeffect *effect, ALenum type)
         effect->Props.Equalizer.Mid2Width = AL_EQUALIZER_DEFAULT_MID2_WIDTH;
         effect->Props.Equalizer.HighCutoff = AL_EQUALIZER_DEFAULT_HIGH_CUTOFF;
         effect->Props.Equalizer.HighGain = AL_EQUALIZER_DEFAULT_HIGH_GAIN;
-        SET_VTABLE1(ALequalizer, effect);
+        effect->vtab = &ALequalizer_vtable;
         break;
     case AL_EFFECT_FLANGER:
-        effect->Props.Flanger.Waveform = AL_FLANGER_DEFAULT_WAVEFORM;
-        effect->Props.Flanger.Phase = AL_FLANGER_DEFAULT_PHASE;
-        effect->Props.Flanger.Rate = AL_FLANGER_DEFAULT_RATE;
-        effect->Props.Flanger.Depth = AL_FLANGER_DEFAULT_DEPTH;
-        effect->Props.Flanger.Feedback = AL_FLANGER_DEFAULT_FEEDBACK;
-        effect->Props.Flanger.Delay = AL_FLANGER_DEFAULT_DELAY;
-        SET_VTABLE1(ALflanger, effect);
+        effect->Props.Chorus.Waveform = AL_FLANGER_DEFAULT_WAVEFORM;
+        effect->Props.Chorus.Phase = AL_FLANGER_DEFAULT_PHASE;
+        effect->Props.Chorus.Rate = AL_FLANGER_DEFAULT_RATE;
+        effect->Props.Chorus.Depth = AL_FLANGER_DEFAULT_DEPTH;
+        effect->Props.Chorus.Feedback = AL_FLANGER_DEFAULT_FEEDBACK;
+        effect->Props.Chorus.Delay = AL_FLANGER_DEFAULT_DELAY;
+        effect->vtab = &ALflanger_vtable;
         break;
     case AL_EFFECT_RING_MODULATOR:
         effect->Props.Modulator.Frequency      = AL_RING_MODULATOR_DEFAULT_FREQUENCY;
         effect->Props.Modulator.HighPassCutoff = AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF;
         effect->Props.Modulator.Waveform       = AL_RING_MODULATOR_DEFAULT_WAVEFORM;
-        SET_VTABLE1(ALmodulator, effect);
+        effect->vtab = &ALmodulator_vtable;
+        break;
+    case AL_EFFECT_PITCH_SHIFTER:
+        effect->Props.Pshifter.CoarseTune      = AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE;
+        effect->Props.Pshifter.FineTune        = AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE;
+        effect->vtab = &ALpshifter_vtable;
         break;
     case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT:
     case AL_EFFECT_DEDICATED_DIALOGUE:
         effect->Props.Dedicated.Gain = 1.0f;
-        SET_VTABLE1(ALdedicated, effect);
+        effect->vtab = &ALdedicated_vtable;
         break;
     default:
-        SET_VTABLE1(ALnull, effect);
+        effect->vtab = &ALnull_vtable;
         break;
     }
     effect->type = type;
@@ -656,7 +744,7 @@ static const struct {
 };
 #undef DECL
 
-ALvoid LoadReverbPreset(const char *name, ALeffect *effect)
+void LoadReverbPreset(const char *name, ALeffect *effect)
 {
     size_t i;
 
@@ -667,9 +755,9 @@ ALvoid LoadReverbPreset(const char *name, ALeffect *effect)
         return;
     }
 
-    if(!DisabledEffects[AL__EAXREVERB])
+    if(!DisabledEffects[EAXREVERB_EFFECT])
         InitEffectParams(effect, AL_EFFECT_EAXREVERB);
-    else if(!DisabledEffects[AL__REVERB])
+    else if(!DisabledEffects[REVERB_EFFECT])
         InitEffectParams(effect, AL_EFFECT_REVERB);
     else
         InitEffectParams(effect, AL_EFFECT_NULL);

+ 43 - 12
libs/openal-soft/OpenAL32/alError.c

@@ -21,6 +21,7 @@
 #include "config.h"
 
 #include <signal.h>
+#include <stdarg.h>
 
 #ifdef HAVE_WINDOWS_H
 #define WIN32_LEAN_AND_MEAN
@@ -33,11 +34,32 @@
 
 ALboolean TrapALError = AL_FALSE;
 
-ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
+void alSetError(ALCcontext *context, ALenum errorCode, const char *msg, ...)
 {
     ALenum curerr = AL_NO_ERROR;
+    char message[1024] = { 0 };
+    va_list args;
+    int msglen;
 
-    WARN("Error generated on context %p, code 0x%04x\n", Context, errorCode);
+    va_start(args, msg);
+    msglen = vsnprintf(message, sizeof(message), msg, args);
+    va_end(args);
+
+    if(msglen < 0 || (size_t)msglen >= sizeof(message))
+    {
+        message[sizeof(message)-1] = 0;
+        msglen = (int)strlen(message);
+    }
+    if(msglen > 0)
+        msg = message;
+    else
+    {
+        msg = "<internal error constructing message>";
+        msglen = (int)strlen(msg);
+    }
+
+    WARN("Error generated on context %p, code 0x%04x, \"%s\"\n",
+         context, errorCode, message);
     if(TrapALError)
     {
 #ifdef _WIN32
@@ -49,19 +71,29 @@ ALvoid alSetError(ALCcontext *Context, ALenum errorCode)
 #endif
     }
 
-    (void)(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&Context->LastError, &curerr, errorCode));
+    ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&context->LastError, &curerr, errorCode);
+    if((ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed)&EventType_Error))
+    {
+        ALbitfieldSOFT enabledevts;
+        almtx_lock(&context->EventCbLock);
+        enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
+        if((enabledevts&EventType_Error) && context->EventCb)
+            (*context->EventCb)(AL_EVENT_TYPE_ERROR_SOFT, 0, errorCode, msglen, msg,
+                                context->EventParam);
+        almtx_unlock(&context->EventCbLock);
+    }
 }
 
 AL_API ALenum AL_APIENTRY alGetError(void)
 {
-    ALCcontext *Context;
+    ALCcontext *context;
     ALenum errorCode;
 
-    Context = GetContextRef();
-    if(!Context)
+    context = GetContextRef();
+    if(!context)
     {
-        WARN("Querying error state on null context (implicitly 0x%04x)\n",
-             AL_INVALID_OPERATION);
+        const ALenum deferror = AL_INVALID_OPERATION;
+        WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror);
         if(TrapALError)
         {
 #ifdef _WIN32
@@ -71,12 +103,11 @@ AL_API ALenum AL_APIENTRY alGetError(void)
             raise(SIGTRAP);
 #endif
         }
-        return AL_INVALID_OPERATION;
+        return deferror;
     }
 
-    errorCode = ATOMIC_EXCHANGE_SEQ(&Context->LastError, AL_NO_ERROR);
-
-    ALCcontext_DecRef(Context);
+    errorCode = ATOMIC_EXCHANGE_SEQ(&context->LastError, AL_NO_ERROR);
 
+    ALCcontext_DecRef(context);
     return errorCode;
 }

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

@@ -35,22 +35,6 @@
 #include "AL/alc.h"
 
 
-const struct EffectList EffectList[] = {
-    { "eaxreverb",  AL__EAXREVERB,  "AL_EFFECT_EAXREVERB",      AL_EFFECT_EAXREVERB },
-    { "reverb",     AL__REVERB,     "AL_EFFECT_REVERB",         AL_EFFECT_REVERB },
-    { "chorus",     AL__CHORUS,     "AL_EFFECT_CHORUS",         AL_EFFECT_CHORUS },
-    { "compressor", AL__COMPRESSOR, "AL_EFFECT_COMPRESSOR",     AL_EFFECT_COMPRESSOR },
-    { "distortion", AL__DISTORTION, "AL_EFFECT_DISTORTION",     AL_EFFECT_DISTORTION },
-    { "echo",       AL__ECHO,       "AL_EFFECT_ECHO",           AL_EFFECT_ECHO },
-    { "equalizer",  AL__EQUALIZER,  "AL_EFFECT_EQUALIZER",      AL_EFFECT_EQUALIZER },
-    { "flanger",    AL__FLANGER,    "AL_EFFECT_FLANGER",        AL_EFFECT_FLANGER },
-    { "modulator",  AL__MODULATOR,  "AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR },
-    { "dedicated",  AL__DEDICATED,  "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT },
-    { "dedicated",  AL__DEDICATED,  "AL_EFFECT_DEDICATED_DIALOGUE", AL_EFFECT_DEDICATED_DIALOGUE },
-    { NULL, 0, NULL, (ALenum)0 }
-};
-
-
 AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
 {
     ALboolean ret = AL_FALSE;
@@ -61,8 +45,8 @@ AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName)
     context = GetContextRef();
     if(!context) return AL_FALSE;
 
-    if(!(extName))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(!extName)
+        SETERR_GOTO(context, AL_INVALID_VALUE, done, "NULL pointer");
 
     len = strlen(extName);
     ptr = context->ExtensionList;

+ 239 - 290
libs/openal-soft/OpenAL32/alFilter.c

@@ -25,66 +25,53 @@
 #include "alMain.h"
 #include "alu.h"
 #include "alFilter.h"
-#include "alThunk.h"
 #include "alError.h"
 
 
-extern inline void LockFiltersRead(ALCdevice *device);
-extern inline void UnlockFiltersRead(ALCdevice *device);
-extern inline void LockFiltersWrite(ALCdevice *device);
-extern inline void UnlockFiltersWrite(ALCdevice *device);
-extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id);
-extern inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id);
-extern inline void ALfilterState_clear(ALfilterState *filter);
-extern inline void ALfilterState_copyParams(ALfilterState *restrict dst, const ALfilterState *restrict src);
-extern inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *restrict src, ALsizei numsamples);
-extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope);
-extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat freq_mult, ALfloat bandwidth);
+extern inline void LockFilterList(ALCdevice *device);
+extern inline void UnlockFilterList(ALCdevice *device);
 
+static ALfilter *AllocFilter(ALCcontext *context);
+static void FreeFilter(ALCdevice *device, ALfilter *filter);
 static void InitFilterParams(ALfilter *filter, ALenum type);
 
+static inline ALfilter *LookupFilter(ALCdevice *device, ALuint id)
+{
+    FilterSubList *sublist;
+    ALuint lidx = (id-1) >> 6;
+    ALsizei slidx = (id-1) & 0x3f;
+
+    if(UNLIKELY(lidx >= VECTOR_SIZE(device->FilterList)))
+        return NULL;
+    sublist = &VECTOR_ELEM(device->FilterList, lidx);
+    if(UNLIKELY(sublist->FreeMask & (U64(1)<<slidx)))
+        return NULL;
+    return sublist->Filters + slidx;
+}
+
 
 AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters)
 {
-    ALCdevice *device;
     ALCcontext *context;
     ALsizei cur = 0;
-    ALenum err;
 
     context = GetContextRef();
     if(!context) return;
 
     if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    for(cur = 0;cur < n;cur++)
+        alSetError(context, AL_INVALID_VALUE, "Generating %d filters", n);
+    else for(cur = 0;cur < n;cur++)
     {
-        ALfilter *filter = al_calloc(16, sizeof(ALfilter));
+        ALfilter *filter = AllocFilter(context);
         if(!filter)
         {
             alDeleteFilters(cur, filters);
-            SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
-        }
-        InitFilterParams(filter, AL_FILTER_NULL);
-
-        err = NewThunkEntry(&filter->id);
-        if(err == AL_NO_ERROR)
-            err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter);
-        if(err != AL_NO_ERROR)
-        {
-            FreeThunkEntry(filter->id);
-            memset(filter, 0, sizeof(ALfilter));
-            al_free(filter);
-
-            alDeleteFilters(cur, filters);
-            SET_ERROR_AND_GOTO(context, err, done);
+            break;
         }
 
         filters[cur] = filter->id;
     }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -99,26 +86,22 @@ AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters)
     if(!context) return;
 
     device = context->Device;
-    LockFiltersWrite(device);
+    LockFilterList(device);
     if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+        SETERR_GOTO(context, AL_INVALID_VALUE, done, "Deleting %d filters", n);
     for(i = 0;i < n;i++)
     {
         if(filters[i] && LookupFilter(device, filters[i]) == NULL)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
+            SETERR_GOTO(context, AL_INVALID_NAME, done, "Invalid filter ID %u", filters[i]);
     }
     for(i = 0;i < n;i++)
     {
-        if((filter=RemoveFilter(device, filters[i])) == NULL)
-            continue;
-        FreeThunkEntry(filter->id);
-
-        memset(filter, 0, sizeof(*filter));
-        al_free(filter);
+        if((filter=LookupFilter(device, filters[i])) != NULL)
+            FreeFilter(device, filter);
     }
 
 done:
-    UnlockFiltersWrite(device);
+    UnlockFilterList(device);
     ALCcontext_DecRef(context);
 }
 
@@ -130,10 +113,10 @@ AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter)
     Context = GetContextRef();
     if(!Context) return AL_FALSE;
 
-    LockFiltersRead(Context->Device);
+    LockFilterList(Context->Device);
     result = ((!filter || LookupFilter(Context->Device, filter)) ?
               AL_TRUE : AL_FALSE);
-    UnlockFiltersRead(Context->Device);
+    UnlockFilterList(Context->Device);
 
     ALCcontext_DecRef(Context);
 
@@ -150,9 +133,9 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
     if(!Context) return;
 
     Device = Context->Device;
-    LockFiltersWrite(Device);
+    LockFilterList(Device);
     if((ALFilter=LookupFilter(Device, filter)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
     else
     {
         if(param == AL_FILTER_TYPE)
@@ -161,15 +144,15 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value)
                value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS)
                 InitFilterParams(ALFilter, value);
             else
-                alSetError(Context, AL_INVALID_VALUE);
+                alSetError(Context, AL_INVALID_VALUE, "Invalid filter type 0x%04x", value);
         }
         else
         {
             /* Call the appropriate handler */
-            ALfilter_SetParami(ALFilter, Context, param, value);
+            ALfilter_setParami(ALFilter, Context, param, value);
         }
     }
-    UnlockFiltersWrite(Device);
+    UnlockFilterList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -191,15 +174,15 @@ AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *v
     if(!Context) return;
 
     Device = Context->Device;
-    LockFiltersWrite(Device);
+    LockFilterList(Device);
     if((ALFilter=LookupFilter(Device, filter)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
     else
     {
         /* Call the appropriate handler */
-        ALfilter_SetParamiv(ALFilter, Context, param, values);
+        ALfilter_setParamiv(ALFilter, Context, param, values);
     }
-    UnlockFiltersWrite(Device);
+    UnlockFilterList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -214,15 +197,15 @@ AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value)
     if(!Context) return;
 
     Device = Context->Device;
-    LockFiltersWrite(Device);
+    LockFilterList(Device);
     if((ALFilter=LookupFilter(Device, filter)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
     else
     {
         /* Call the appropriate handler */
-        ALfilter_SetParamf(ALFilter, Context, param, value);
+        ALfilter_setParamf(ALFilter, Context, param, value);
     }
-    UnlockFiltersWrite(Device);
+    UnlockFilterList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -237,15 +220,15 @@ AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat
     if(!Context) return;
 
     Device = Context->Device;
-    LockFiltersWrite(Device);
+    LockFilterList(Device);
     if((ALFilter=LookupFilter(Device, filter)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
     else
     {
         /* Call the appropriate handler */
-        ALfilter_SetParamfv(ALFilter, Context, param, values);
+        ALfilter_setParamfv(ALFilter, Context, param, values);
     }
-    UnlockFiltersWrite(Device);
+    UnlockFilterList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -260,9 +243,9 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value
     if(!Context) return;
 
     Device = Context->Device;
-    LockFiltersRead(Device);
+    LockFilterList(Device);
     if((ALFilter=LookupFilter(Device, filter)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
     else
     {
         if(param == AL_FILTER_TYPE)
@@ -270,10 +253,10 @@ AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value
         else
         {
             /* Call the appropriate handler */
-            ALfilter_GetParami(ALFilter, Context, param, value);
+            ALfilter_getParami(ALFilter, Context, param, value);
         }
     }
-    UnlockFiltersRead(Device);
+    UnlockFilterList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -295,15 +278,15 @@ AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *valu
     if(!Context) return;
 
     Device = Context->Device;
-    LockFiltersRead(Device);
+    LockFilterList(Device);
     if((ALFilter=LookupFilter(Device, filter)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
     else
     {
         /* Call the appropriate handler */
-        ALfilter_GetParamiv(ALFilter, Context, param, values);
+        ALfilter_getParamiv(ALFilter, Context, param, values);
     }
-    UnlockFiltersRead(Device);
+    UnlockFilterList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -318,15 +301,15 @@ AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *val
     if(!Context) return;
 
     Device = Context->Device;
-    LockFiltersRead(Device);
+    LockFilterList(Device);
     if((ALFilter=LookupFilter(Device, filter)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
     else
     {
         /* Call the appropriate handler */
-        ALfilter_GetParamf(ALFilter, Context, param, value);
+        ALfilter_getParamf(ALFilter, Context, param, value);
     }
-    UnlockFiltersRead(Device);
+    UnlockFilterList(Device);
 
     ALCcontext_DecRef(Context);
 }
@@ -341,134 +324,52 @@ AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *va
     if(!Context) return;
 
     Device = Context->Device;
-    LockFiltersRead(Device);
+    LockFilterList(Device);
     if((ALFilter=LookupFilter(Device, filter)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
+        alSetError(Context, AL_INVALID_NAME, "Invalid filter ID %u", filter);
     else
     {
         /* Call the appropriate handler */
-        ALfilter_GetParamfv(ALFilter, Context, param, values);
+        ALfilter_getParamfv(ALFilter, Context, param, values);
     }
-    UnlockFiltersRead(Device);
+    UnlockFilterList(Device);
 
     ALCcontext_DecRef(Context);
 }
 
 
-void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat rcpQ)
-{
-    ALfloat alpha, sqrtgain_alpha_2;
-    ALfloat w0, sin_w0, cos_w0;
-    ALfloat a[3] = { 1.0f, 0.0f, 0.0f };
-    ALfloat b[3] = { 1.0f, 0.0f, 0.0f };
-
-    // Limit gain to -100dB
-    assert(gain > 0.00001f);
-
-    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 */
-    switch(type)
-    {
-        case ALfilterType_HighShelf:
-            sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
-            b[0] =       gain*((gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
-            b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cos_w0                   );
-            b[2] =       gain*((gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
-            a[0] =             (gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2;
-            a[1] =  2.0f*     ((gain-1.0f) - (gain+1.0f)*cos_w0                   );
-            a[2] =             (gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
-            break;
-        case ALfilterType_LowShelf:
-            sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha;
-            b[0] =       gain*((gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2);
-            b[1] =  2.0f*gain*((gain-1.0f) - (gain+1.0f)*cos_w0                   );
-            b[2] =       gain*((gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2);
-            a[0] =             (gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2;
-            a[1] = -2.0f*     ((gain-1.0f) + (gain+1.0f)*cos_w0                   );
-            a[2] =             (gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2;
-            break;
-        case ALfilterType_Peaking:
-            gain = sqrtf(gain);
-            b[0] =  1.0f + alpha * gain;
-            b[1] = -2.0f * cos_w0;
-            b[2] =  1.0f - alpha * gain;
-            a[0] =  1.0f + alpha / gain;
-            a[1] = -2.0f * cos_w0;
-            a[2] =  1.0f - alpha / gain;
-            break;
-
-        case ALfilterType_LowPass:
-            b[0] = (1.0f - cos_w0) / 2.0f;
-            b[1] =  1.0f - cos_w0;
-            b[2] = (1.0f - cos_w0) / 2.0f;
-            a[0] =  1.0f + alpha;
-            a[1] = -2.0f * cos_w0;
-            a[2] =  1.0f - alpha;
-            break;
-        case ALfilterType_HighPass:
-            b[0] =  (1.0f + cos_w0) / 2.0f;
-            b[1] = -(1.0f + cos_w0);
-            b[2] =  (1.0f + cos_w0) / 2.0f;
-            a[0] =   1.0f + alpha;
-            a[1] =  -2.0f * cos_w0;
-            a[2] =   1.0f - alpha;
-            break;
-        case ALfilterType_BandPass:
-            b[0] =  alpha;
-            b[1] =  0;
-            b[2] = -alpha;
-            a[0] =  1.0f + alpha;
-            a[1] = -2.0f * cos_w0;
-            a[2] =  1.0f - alpha;
-            break;
-    }
-
-    filter->a1 = a[1] / a[0];
-    filter->a2 = a[2] / a[0];
-    filter->b0 = b[0] / a[0];
-    filter->b1 = b[1] / a[0];
-    filter->b2 = b[2] / a[0];
-}
-
-
-static void lp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void lp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
+static void ALlowpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param); }
+static void ALlowpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x", param); }
+static void ALlowpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
 {
     switch(param)
     {
         case AL_LOWPASS_GAIN:
             if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Low-pass gain %f out of range", val);
             filter->Gain = val;
             break;
 
         case AL_LOWPASS_GAINHF:
             if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Low-pass gainhf %f out of range", val);
             filter->GainHF = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param);
     }
 }
-static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    lp_SetParamf(filter, context, param, vals[0]);
-}
-
-static void lp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void lp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
+static void ALlowpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
+{ ALlowpass_setParamf(filter, context, param, vals[0]); }
+
+static void ALlowpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param); }
+static void ALlowpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid low-pass integer-vector property 0x%04x", param); }
+static void ALlowpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
 {
     switch(param)
     {
@@ -481,49 +382,47 @@ static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, AL
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param);
     }
 }
-static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    lp_GetParamf(filter, context, param, vals);
-}
+static void ALlowpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
+{ ALlowpass_getParamf(filter, context, param, vals); }
+
+DEFINE_ALFILTER_VTABLE(ALlowpass);
 
 
-static void hp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void hp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void hp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
+static void ALhighpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param); }
+static void ALhighpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer-vector property 0x%04x", param); }
+static void ALhighpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
 {
     switch(param)
     {
         case AL_HIGHPASS_GAIN:
             if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "High-pass gain out of range");
             filter->Gain = val;
             break;
 
         case AL_HIGHPASS_GAINLF:
             if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "High-pass gainlf out of range");
             filter->GainLF = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param);
     }
 }
-static void hp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    hp_SetParamf(filter, context, param, vals[0]);
-}
-
-static void hp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void hp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void hp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
+static void ALhighpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
+{ ALhighpass_setParamf(filter, context, param, vals[0]); }
+
+static void ALhighpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param); }
+static void ALhighpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid high-pass integer-vector property 0x%04x", param); }
+static void ALhighpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
 {
     switch(param)
     {
@@ -536,55 +435,53 @@ static void hp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, AL
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param);
     }
 }
-static void hp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    hp_GetParamf(filter, context, param, vals);
-}
+static void ALhighpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
+{ ALhighpass_getParamf(filter, context, param, vals); }
+
+DEFINE_ALFILTER_VTABLE(ALhighpass);
 
 
-static void bp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void bp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void bp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
+static void ALbandpass_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param); }
+static void ALbandpass_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer-vector property 0x%04x", param); }
+static void ALbandpass_setParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val)
 {
     switch(param)
     {
         case AL_BANDPASS_GAIN:
             if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gain out of range");
             filter->Gain = val;
             break;
 
         case AL_BANDPASS_GAINHF:
             if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gainhf out of range");
             filter->GainHF = val;
             break;
 
         case AL_BANDPASS_GAINLF:
             if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
+                SETERR_RETURN(context, AL_INVALID_VALUE,, "Band-pass gainlf out of range");
             filter->GainLF = val;
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param);
     }
 }
-static void bp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    bp_SetParamf(filter, context, param, vals[0]);
-}
-
-static void bp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void bp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void bp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
+static void ALbandpass_setParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals)
+{ ALbandpass_setParamf(filter, context, param, vals[0]); }
+
+static void ALbandpass_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param); }
+static void ALbandpass_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid band-pass integer-vector property 0x%04x", param); }
+static void ALbandpass_getParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val)
 {
     switch(param)
     {
@@ -601,47 +498,131 @@ static void bp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, AL
             break;
 
         default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
+            alSetError(context, AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param);
     }
 }
-static void bp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
+static void ALbandpass_getParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals)
+{ ALbandpass_getParamf(filter, context, param, vals); }
+
+DEFINE_ALFILTER_VTABLE(ALbandpass);
+
+
+static void ALnullfilter_setParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
+static void ALnullfilter_setParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
+static void ALnullfilter_setParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
+static void ALnullfilter_setParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, const ALfloat *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
+
+static void ALnullfilter_getParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
+static void ALnullfilter_getParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALint *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
+static void ALnullfilter_getParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat *UNUSED(val))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
+static void ALnullfilter_getParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum param, ALfloat *UNUSED(vals))
+{ alSetError(context, AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param); }
+
+DEFINE_ALFILTER_VTABLE(ALnullfilter);
+
+
+static ALfilter *AllocFilter(ALCcontext *context)
 {
-    bp_GetParamf(filter, context, param, vals);
-}
+    ALCdevice *device = context->Device;
+    FilterSubList *sublist, *subend;
+    ALfilter *filter = NULL;
+    ALsizei lidx = 0;
+    ALsizei slidx;
+
+    almtx_lock(&device->FilterLock);
+    sublist = VECTOR_BEGIN(device->FilterList);
+    subend = VECTOR_END(device->FilterList);
+    for(;sublist != subend;++sublist)
+    {
+        if(sublist->FreeMask)
+        {
+            slidx = CTZ64(sublist->FreeMask);
+            filter = sublist->Filters + slidx;
+            break;
+        }
+        ++lidx;
+    }
+    if(UNLIKELY(!filter))
+    {
+        const FilterSubList empty_sublist = { 0, NULL };
+        /* Don't allocate so many list entries that the 32-bit ID could
+         * overflow...
+         */
+        if(UNLIKELY(VECTOR_SIZE(device->FilterList) >= 1<<25))
+        {
+            almtx_unlock(&device->FilterLock);
+            alSetError(context, AL_OUT_OF_MEMORY, "Too many filters allocated");
+            return NULL;
+        }
+        lidx = (ALsizei)VECTOR_SIZE(device->FilterList);
+        VECTOR_PUSH_BACK(device->FilterList, empty_sublist);
+        sublist = &VECTOR_BACK(device->FilterList);
+        sublist->FreeMask = ~U64(0);
+        sublist->Filters = al_calloc(16, sizeof(ALfilter)*64);
+        if(UNLIKELY(!sublist->Filters))
+        {
+            VECTOR_POP_BACK(device->FilterList);
+            almtx_unlock(&device->FilterLock);
+            alSetError(context, AL_OUT_OF_MEMORY, "Failed to allocate filter batch");
+            return NULL;
+        }
+
+        slidx = 0;
+        filter = sublist->Filters + slidx;
+    }
 
+    memset(filter, 0, sizeof(*filter));
+    InitFilterParams(filter, AL_FILTER_NULL);
 
-static void null_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void null_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void null_SetParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void null_SetParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALfloat *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+    /* Add 1 to avoid filter ID 0. */
+    filter->id = ((lidx<<6) | slidx) + 1;
 
-static void null_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void null_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void null_GetParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-static void null_GetParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(vals))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
+    sublist->FreeMask &= ~(U64(1)<<slidx);
+    almtx_unlock(&device->FilterLock);
 
+    return filter;
+}
 
-ALvoid ReleaseALFilters(ALCdevice *device)
+static void FreeFilter(ALCdevice *device, ALfilter *filter)
 {
-    ALsizei i;
-    for(i = 0;i < device->FilterMap.size;i++)
+    ALuint id = filter->id - 1;
+    ALsizei lidx = id >> 6;
+    ALsizei slidx = id & 0x3f;
+
+    memset(filter, 0, sizeof(*filter));
+
+    VECTOR_ELEM(device->FilterList, lidx).FreeMask |= U64(1) << slidx;
+}
+
+void ReleaseALFilters(ALCdevice *device)
+{
+    FilterSubList *sublist = VECTOR_BEGIN(device->FilterList);
+    FilterSubList *subend = VECTOR_END(device->FilterList);
+    size_t leftover = 0;
+    for(;sublist != subend;++sublist)
     {
-        ALfilter *temp = device->FilterMap.values[i];
-        device->FilterMap.values[i] = NULL;
+        ALuint64 usemask = ~sublist->FreeMask;
+        while(usemask)
+        {
+            ALsizei idx = CTZ64(usemask);
+            ALfilter *filter = sublist->Filters + idx;
+
+            memset(filter, 0, sizeof(*filter));
+            ++leftover;
 
-        // Release filter structure
-        FreeThunkEntry(temp->id);
-        memset(temp, 0, sizeof(ALfilter));
-        al_free(temp);
+            usemask &= ~(U64(1) << idx);
+        }
+        sublist->FreeMask = ~usemask;
     }
+    if(leftover > 0)
+        WARN("(%p) Deleted "SZFMT" Filter%s\n", device, leftover, (leftover==1)?"":"s");
 }
 
 
@@ -654,15 +635,7 @@ static void InitFilterParams(ALfilter *filter, ALenum type)
         filter->HFReference = LOWPASSFREQREF;
         filter->GainLF = 1.0f;
         filter->LFReference = HIGHPASSFREQREF;
-
-        filter->SetParami  = lp_SetParami;
-        filter->SetParamiv = lp_SetParamiv;
-        filter->SetParamf  = lp_SetParamf;
-        filter->SetParamfv = lp_SetParamfv;
-        filter->GetParami  = lp_GetParami;
-        filter->GetParamiv = lp_GetParamiv;
-        filter->GetParamf  = lp_GetParamf;
-        filter->GetParamfv = lp_GetParamfv;
+        filter->vtab = &ALlowpass_vtable;
     }
     else if(type == AL_FILTER_HIGHPASS)
     {
@@ -671,15 +644,7 @@ static void InitFilterParams(ALfilter *filter, ALenum type)
         filter->HFReference = LOWPASSFREQREF;
         filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF;
         filter->LFReference = HIGHPASSFREQREF;
-
-        filter->SetParami  = hp_SetParami;
-        filter->SetParamiv = hp_SetParamiv;
-        filter->SetParamf  = hp_SetParamf;
-        filter->SetParamfv = hp_SetParamfv;
-        filter->GetParami  = hp_GetParami;
-        filter->GetParamiv = hp_GetParamiv;
-        filter->GetParamf  = hp_GetParamf;
-        filter->GetParamfv = hp_GetParamfv;
+        filter->vtab = &ALhighpass_vtable;
     }
     else if(type == AL_FILTER_BANDPASS)
     {
@@ -688,15 +653,7 @@ static void InitFilterParams(ALfilter *filter, ALenum type)
         filter->HFReference = LOWPASSFREQREF;
         filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF;
         filter->LFReference = HIGHPASSFREQREF;
-
-        filter->SetParami  = bp_SetParami;
-        filter->SetParamiv = bp_SetParamiv;
-        filter->SetParamf  = bp_SetParamf;
-        filter->SetParamfv = bp_SetParamfv;
-        filter->GetParami  = bp_GetParami;
-        filter->GetParamiv = bp_GetParamiv;
-        filter->GetParamf  = bp_GetParamf;
-        filter->GetParamfv = bp_GetParamfv;
+        filter->vtab = &ALbandpass_vtable;
     }
     else
     {
@@ -705,15 +662,7 @@ static void InitFilterParams(ALfilter *filter, ALenum type)
         filter->HFReference = LOWPASSFREQREF;
         filter->GainLF = 1.0f;
         filter->LFReference = HIGHPASSFREQREF;
-
-        filter->SetParami  = null_SetParami;
-        filter->SetParamiv = null_SetParamiv;
-        filter->SetParamf  = null_SetParamf;
-        filter->SetParamfv = null_SetParamfv;
-        filter->GetParami  = null_GetParami;
-        filter->GetParamiv = null_GetParamiv;
-        filter->GetParamf  = null_GetParamf;
-        filter->GetParamfv = null_GetParamfv;
+        filter->vtab = &ALnullfilter_vtable;
     }
     filter->type = type;
 }

+ 105 - 113
libs/openal-soft/OpenAL32/alListener.c

@@ -21,85 +21,101 @@
 #include "config.h"
 
 #include "alMain.h"
-#include "AL/alc.h"
+#include "alu.h"
 #include "alError.h"
 #include "alListener.h"
 #include "alSource.h"
 
+#define DO_UPDATEPROPS() do {                                                 \
+    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))          \
+        UpdateListenerProps(context);                                         \
+    else                                                                      \
+        ATOMIC_FLAG_CLEAR(&listener->PropsClean, almemory_order_release);     \
+} while(0)
+
+
 AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value)
 {
+    ALlistener *listener;
     ALCcontext *context;
 
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
+    listener = context->Listener;
+    almtx_lock(&context->PropLock);
     switch(param)
     {
     case AL_GAIN:
         if(!(value >= 0.0f && isfinite(value)))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-        context->Listener->Gain = value;
+            SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener gain out of range");
+        listener->Gain = value;
+        DO_UPDATEPROPS();
         break;
 
     case AL_METERS_PER_UNIT:
-        if(!(value >= 0.0f && isfinite(value)))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-        context->Listener->MetersPerUnit = value;
+        if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT))
+            SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener meters per unit out of range");
+        context->MetersPerUnit = value;
+        if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
+            UpdateContextProps(context);
+        else
+            ATOMIC_FLAG_CLEAR(&context->PropsClean, almemory_order_release);
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener float property");
     }
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
 
 done:
-    WriteUnlock(&context->PropLock);
+    almtx_unlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
 
 AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
 {
+    ALlistener *listener;
     ALCcontext *context;
 
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
+    listener = context->Listener;
+    almtx_lock(&context->PropLock);
     switch(param)
     {
     case AL_POSITION:
         if(!(isfinite(value1) && isfinite(value2) && isfinite(value3)))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-        context->Listener->Position[0] = value1;
-        context->Listener->Position[1] = value2;
-        context->Listener->Position[2] = value3;
+            SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener position out of range");
+        listener->Position[0] = value1;
+        listener->Position[1] = value2;
+        listener->Position[2] = value3;
+        DO_UPDATEPROPS();
         break;
 
     case AL_VELOCITY:
         if(!(isfinite(value1) && isfinite(value2) && isfinite(value3)))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-        context->Listener->Velocity[0] = value1;
-        context->Listener->Velocity[1] = value2;
-        context->Listener->Velocity[2] = value3;
+            SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener velocity out of range");
+        listener->Velocity[0] = value1;
+        listener->Velocity[1] = value2;
+        listener->Velocity[2] = value3;
+        DO_UPDATEPROPS();
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener 3-float property");
     }
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
 
 done:
-    WriteUnlock(&context->PropLock);
+    almtx_unlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
 
 AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
 {
+    ALlistener *listener;
     ALCcontext *context;
 
     if(values)
@@ -121,32 +137,31 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values)
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
-    if(!(values))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    listener = context->Listener;
+    almtx_lock(&context->PropLock);
+    if(!values) SETERR_GOTO(context, AL_INVALID_VALUE, done, "NULL pointer");
     switch(param)
     {
     case AL_ORIENTATION:
         if(!(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) &&
              isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5])))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+            SETERR_GOTO(context, AL_INVALID_VALUE, done, "Listener orientation out of range");
         /* AT then UP */
-        context->Listener->Forward[0] = values[0];
-        context->Listener->Forward[1] = values[1];
-        context->Listener->Forward[2] = values[2];
-        context->Listener->Up[0] = values[3];
-        context->Listener->Up[1] = values[4];
-        context->Listener->Up[2] = values[5];
+        listener->Forward[0] = values[0];
+        listener->Forward[1] = values[1];
+        listener->Forward[2] = values[2];
+        listener->Up[0] = values[3];
+        listener->Up[1] = values[4];
+        listener->Up[2] = values[5];
+        DO_UPDATEPROPS();
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener float-vector property");
     }
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
 
 done:
-    WriteUnlock(&context->PropLock);
+    almtx_unlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -158,17 +173,14 @@ AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint UNUSED(value))
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
+    almtx_lock(&context->PropLock);
     switch(param)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener integer property");
     }
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
+    almtx_unlock(&context->PropLock);
 
-done:
-    WriteUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -188,17 +200,14 @@ AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, A
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
+    almtx_lock(&context->PropLock);
     switch(param)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener 3-integer property");
     }
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
+    almtx_unlock(&context->PropLock);
 
-done:
-    WriteUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -232,19 +241,16 @@ AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values)
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
-    if(!(values))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    switch(param)
+    almtx_lock(&context->PropLock);
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+    else switch(param)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener integer-vector property");
     }
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
+    almtx_unlock(&context->PropLock);
 
-done:
-    WriteUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -256,25 +262,24 @@ AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value)
     context = GetContextRef();
     if(!context) return;
 
-    ReadLock(&context->PropLock);
-    if(!(value))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    switch(param)
+    almtx_lock(&context->PropLock);
+    if(!value)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+    else switch(param)
     {
     case AL_GAIN:
         *value = context->Listener->Gain;
         break;
 
     case AL_METERS_PER_UNIT:
-        *value = context->Listener->MetersPerUnit;
+        *value = context->MetersPerUnit;
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener float property");
     }
+    almtx_unlock(&context->PropLock);
 
-done:
-    ReadUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -286,10 +291,10 @@ AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat
     context = GetContextRef();
     if(!context) return;
 
-    ReadLock(&context->PropLock);
-    if(!(value1 && value2 && value3))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    switch(param)
+    almtx_lock(&context->PropLock);
+    if(!value1 || !value2 || !value3)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+    else switch(param)
     {
     case AL_POSITION:
         *value1 = context->Listener->Position[0];
@@ -304,11 +309,10 @@ AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener 3-float property");
     }
+    almtx_unlock(&context->PropLock);
 
-done:
-    ReadUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -333,10 +337,10 @@ AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
     context = GetContextRef();
     if(!context) return;
 
-    ReadLock(&context->PropLock);
-    if(!(values))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    switch(param)
+    almtx_lock(&context->PropLock);
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+    else switch(param)
     {
     case AL_ORIENTATION:
         // AT then UP
@@ -349,11 +353,10 @@ AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener float-vector property");
     }
+    almtx_unlock(&context->PropLock);
 
-done:
-    ReadUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -365,17 +368,16 @@ AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value)
     context = GetContextRef();
     if(!context) return;
 
-    ReadLock(&context->PropLock);
-    if(!(value))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    switch(param)
+    almtx_lock(&context->PropLock);
+    if(!value)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+    else switch(param)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener integer property");
     }
+    almtx_unlock(&context->PropLock);
 
-done:
-    ReadUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -387,10 +389,10 @@ AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *valu
     context = GetContextRef();
     if(!context) return;
 
-    ReadLock(&context->PropLock);
-    if(!(value1 && value2 && value3))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    switch (param)
+    almtx_lock(&context->PropLock);
+    if(!value1 || !value2 || !value3)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+    else switch(param)
     {
     case AL_POSITION:
         *value1 = (ALint)context->Listener->Position[0];
@@ -405,11 +407,10 @@ AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *valu
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener 3-integer property");
     }
+    almtx_unlock(&context->PropLock);
 
-done:
-    ReadUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -429,10 +430,10 @@ AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
     context = GetContextRef();
     if(!context) return;
 
-    ReadLock(&context->PropLock);
-    if(!(values))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    switch(param)
+    almtx_lock(&context->PropLock);
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+    else switch(param)
     {
     case AL_ORIENTATION:
         // AT then UP
@@ -445,11 +446,10 @@ AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_ENUM, "Invalid listener integer-vector property");
     }
+    almtx_unlock(&context->PropLock);
 
-done:
-    ReadUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -460,7 +460,7 @@ void UpdateListenerProps(ALCcontext *context)
     struct ALlistenerProps *props;
 
     /* Get an unused proprty container, or allocate a new one as needed. */
-    props = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire);
+    props = ATOMIC_LOAD(&context->FreeListenerProps, almemory_order_acquire);
     if(!props)
         props = al_calloc(16, sizeof(*props));
     else
@@ -468,7 +468,7 @@ void UpdateListenerProps(ALCcontext *context)
         struct ALlistenerProps *next;
         do {
             next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
-        } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&listener->FreeList, &props, next,
+        } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeListenerProps, &props, next,
                 almemory_order_seq_cst, almemory_order_acquire) == 0);
     }
 
@@ -489,14 +489,6 @@ void UpdateListenerProps(ALCcontext *context)
     props->Up[2] = listener->Up[2];
 
     props->Gain = listener->Gain;
-    props->MetersPerUnit = listener->MetersPerUnit;
-
-    props->DopplerFactor = context->DopplerFactor;
-    props->DopplerVelocity = context->DopplerVelocity;
-    props->SpeedOfSound = context->SpeedOfSound;
-
-    props->SourceDistanceModel = context->SourceDistanceModel;
-    props->DistanceModel = context->DistanceModel;;
 
     /* Set the new container for updating internal parameters. */
     props = ATOMIC_EXCHANGE_PTR(&listener->Update, props, almemory_order_acq_rel);
@@ -505,6 +497,6 @@ void UpdateListenerProps(ALCcontext *context)
         /* If there was an unused update container, put it back in the
          * freelist.
          */
-        ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &listener->FreeList, props);
+        ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &context->FreeListenerProps, props);
     }
 }

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


+ 208 - 87
libs/openal-soft/OpenAL32/alState.c

@@ -50,8 +50,27 @@ static const ALchar alErrOutOfMemory[] = "Out of Memory";
 /* Resampler strings */
 static const ALchar alPointResampler[] = "Nearest";
 static const ALchar alLinearResampler[] = "Linear";
-static const ALchar alSinc4Resampler[] = "4-Point Sinc";
-static const ALchar alBSincResampler[] = "Band-limited Sinc (12/24)";
+static const ALchar alCubicResampler[] = "Cubic";
+static const ALchar alBSinc12Resampler[] = "11th order Sinc";
+static const ALchar alBSinc24Resampler[] = "23rd order Sinc";
+
+/* WARNING: Non-standard export! Not part of any extension, or exposed in the
+ * alcFunctions list.
+ */
+AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
+{
+    const char *spoof = getenv("ALSOFT_SPOOF_VERSION");
+    if(spoof && spoof[0] != '\0') return spoof;
+    return ALSOFT_VERSION;
+}
+
+#define DO_UPDATEPROPS() do {                                                 \
+    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))          \
+        UpdateContextProps(context);                                          \
+    else                                                                      \
+        ATOMIC_FLAG_CLEAR(&context->PropsClean, almemory_order_release);      \
+} while(0)
+
 
 AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
 {
@@ -60,21 +79,19 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
+    almtx_lock(&context->PropLock);
     switch(capability)
     {
     case AL_SOURCE_DISTANCE_MODEL:
         context->SourceDistanceModel = AL_TRUE;
+        DO_UPDATEPROPS();
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
     }
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
+    almtx_unlock(&context->PropLock);
 
-done:
-    WriteUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -85,21 +102,19 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
     context = GetContextRef();
     if(!context) return;
 
-    WriteLock(&context->PropLock);
+    almtx_lock(&context->PropLock);
     switch(capability)
     {
     case AL_SOURCE_DISTANCE_MODEL:
         context->SourceDistanceModel = AL_FALSE;
+        DO_UPDATEPROPS();
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
     }
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
+    almtx_unlock(&context->PropLock);
 
-done:
-    WriteUnlock(&context->PropLock);
     ALCcontext_DecRef(context);
 }
 
@@ -111,6 +126,7 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
     context = GetContextRef();
     if(!context) return AL_FALSE;
 
+    almtx_lock(&context->PropLock);
     switch(capability)
     {
     case AL_SOURCE_DISTANCE_MODEL:
@@ -118,12 +134,11 @@ AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
     }
+    almtx_unlock(&context->PropLock);
 
-done:
     ALCcontext_DecRef(context);
-
     return value;
 }
 
@@ -135,6 +150,7 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
     context = GetContextRef();
     if(!context) return AL_FALSE;
 
+    almtx_lock(&context->PropLock);
     switch(pname)
     {
     case AL_DOPPLER_FACTOR:
@@ -177,12 +193,11 @@ AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
     }
+    almtx_unlock(&context->PropLock);
 
-done:
     ALCcontext_DecRef(context);
-
     return value;
 }
 
@@ -194,6 +209,7 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
     context = GetContextRef();
     if(!context) return 0.0;
 
+    almtx_lock(&context->PropLock);
     switch(pname)
     {
     case AL_DOPPLER_FACTOR:
@@ -230,12 +246,11 @@ AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
     }
+    almtx_unlock(&context->PropLock);
 
-done:
     ALCcontext_DecRef(context);
-
     return value;
 }
 
@@ -247,6 +262,7 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
     context = GetContextRef();
     if(!context) return 0.0f;
 
+    almtx_lock(&context->PropLock);
     switch(pname)
     {
     case AL_DOPPLER_FACTOR:
@@ -283,12 +299,11 @@ AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
     }
+    almtx_unlock(&context->PropLock);
 
-done:
     ALCcontext_DecRef(context);
-
     return value;
 }
 
@@ -300,6 +315,7 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
     context = GetContextRef();
     if(!context) return 0;
 
+    almtx_lock(&context->PropLock);
     switch(pname)
     {
     case AL_DOPPLER_FACTOR:
@@ -336,12 +352,11 @@ AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
     }
+    almtx_unlock(&context->PropLock);
 
-done:
     ALCcontext_DecRef(context);
-
     return value;
 }
 
@@ -353,6 +368,7 @@ AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
     context = GetContextRef();
     if(!context) return 0;
 
+    almtx_lock(&context->PropLock);
     switch(pname)
     {
     case AL_DOPPLER_FACTOR:
@@ -389,12 +405,39 @@ AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
     }
+    almtx_unlock(&context->PropLock);
 
-done:
     ALCcontext_DecRef(context);
+    return value;
+}
+
+AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
+{
+    ALCcontext *context;
+    void *value = NULL;
 
+    context = GetContextRef();
+    if(!context) return NULL;
+
+    almtx_lock(&context->PropLock);
+    switch(pname)
+    {
+    case AL_EVENT_CALLBACK_FUNCTION_SOFT:
+        value = context->EventCb;
+        break;
+
+    case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
+        value = context->EventParam;
+        break;
+
+    default:
+        alSetError(context, AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
+    }
+    almtx_unlock(&context->PropLock);
+
+    ALCcontext_DecRef(context);
     return value;
 }
 
@@ -422,15 +465,14 @@ AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
     context = GetContextRef();
     if(!context) return;
 
-    if(!(values))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
     switch(pname)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
     }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -458,15 +500,14 @@ AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
     context = GetContextRef();
     if(!context) return;
 
-    if(!(values))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
     switch(pname)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
     }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -494,15 +535,14 @@ AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
     context = GetContextRef();
     if(!context) return;
 
-    if(!(values))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
     switch(pname)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
     }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -530,13 +570,14 @@ AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
     context = GetContextRef();
     if(!context) return;
 
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
     switch(pname)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
     }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -564,13 +605,43 @@ AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
     context = GetContextRef();
     if(!context) return;
 
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
     switch(pname)
     {
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
+    }
+
+    ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
+{
+    ALCcontext *context;
+
+    if(values)
+    {
+        switch(pname)
+        {
+            case AL_EVENT_CALLBACK_FUNCTION_SOFT:
+            case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
+                values[0] = alGetPointerSOFT(pname);
+                return;
+        }
+    }
+
+    context = GetContextRef();
+    if(!context) return;
+
+    if(!values)
+        alSetError(context, AL_INVALID_VALUE, "NULL pointer");
+    switch(pname)
+    {
+    default:
+        alSetError(context, AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
     }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -625,12 +696,10 @@ AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
     }
 
-done:
     ALCcontext_DecRef(context);
-
     return value;
 }
 
@@ -642,15 +711,15 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
     if(!context) return;
 
     if(!(value >= 0.0f && isfinite(value)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    WriteLock(&context->PropLock);
-    context->DopplerFactor = value;
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
-    WriteUnlock(&context->PropLock);
+        alSetError(context, AL_INVALID_VALUE, "Doppler factor %f out of range", value);
+    else
+    {
+        almtx_lock(&context->PropLock);
+        context->DopplerFactor = value;
+        DO_UPDATEPROPS();
+        almtx_unlock(&context->PropLock);
+    }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -661,16 +730,30 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
     context = GetContextRef();
     if(!context) return;
 
-    if(!(value >= 0.0f && isfinite(value)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+    if((ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed)&EventType_Deprecated))
+    {
+        static const ALCchar msg[] =
+            "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
+        const ALsizei msglen = (ALsizei)strlen(msg);
+        ALbitfieldSOFT enabledevts;
+        almtx_lock(&context->EventCbLock);
+        enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
+        if((enabledevts&EventType_Deprecated) && context->EventCb)
+            (*context->EventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
+                                context->EventParam);
+        almtx_unlock(&context->EventCbLock);
+    }
 
-    WriteLock(&context->PropLock);
-    context->DopplerVelocity = value;
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
-    WriteUnlock(&context->PropLock);
+    if(!(value >= 0.0f && isfinite(value)))
+        alSetError(context, AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
+    else
+    {
+        almtx_lock(&context->PropLock);
+        context->DopplerVelocity = value;
+        DO_UPDATEPROPS();
+        almtx_unlock(&context->PropLock);
+    }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -682,15 +765,15 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
     if(!context) return;
 
     if(!(value > 0.0f && isfinite(value)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    WriteLock(&context->PropLock);
-    context->SpeedOfSound = value;
-    if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-        UpdateListenerProps(context);
-    WriteUnlock(&context->PropLock);
+        alSetError(context, AL_INVALID_VALUE, "Speed of sound %f out of range", value);
+    else
+    {
+        almtx_lock(&context->PropLock);
+        context->SpeedOfSound = value;
+        DO_UPDATEPROPS();
+        almtx_unlock(&context->PropLock);
+    }
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -705,18 +788,16 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
          value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
          value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
          value == AL_NONE))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    WriteLock(&context->PropLock);
-    context->DistanceModel = value;
-    if(!context->SourceDistanceModel)
+        alSetError(context, AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
+    else
     {
-        if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire))
-            UpdateListenerProps(context);
+        almtx_lock(&context->PropLock);
+        context->DistanceModel = value;
+        if(!context->SourceDistanceModel)
+            DO_UPDATEPROPS();
+        almtx_unlock(&context->PropLock);
     }
-    WriteUnlock(&context->PropLock);
 
-done:
     ALCcontext_DecRef(context);
 }
 
@@ -750,7 +831,8 @@ AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
 {
     const char *ResamplerNames[] = {
         alPointResampler, alLinearResampler,
-        alSinc4Resampler, alBSincResampler,
+        alCubicResampler, alBSinc12Resampler,
+        alBSinc24Resampler,
     };
     const ALchar *value = NULL;
     ALCcontext *context;
@@ -764,16 +846,55 @@ AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
     {
     case AL_RESAMPLER_NAME_SOFT:
         if(index < 0 || (size_t)index >= COUNTOF(ResamplerNames))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
+            SETERR_GOTO(context, AL_INVALID_VALUE, done, "Resampler name index %d out of range",
+                        index);
         value = ResamplerNames[index];
         break;
 
     default:
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
+        alSetError(context, AL_INVALID_VALUE, "Invalid string indexed property");
     }
 
 done:
     ALCcontext_DecRef(context);
-
     return value;
 }
+
+
+void UpdateContextProps(ALCcontext *context)
+{
+    struct ALcontextProps *props;
+
+    /* Get an unused proprty container, or allocate a new one as needed. */
+    props = ATOMIC_LOAD(&context->FreeContextProps, almemory_order_acquire);
+    if(!props)
+        props = al_calloc(16, sizeof(*props));
+    else
+    {
+        struct ALcontextProps *next;
+        do {
+            next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+        } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&context->FreeContextProps, &props, next,
+                almemory_order_seq_cst, almemory_order_acquire) == 0);
+    }
+
+    /* Copy in current property values. */
+    props->MetersPerUnit = context->MetersPerUnit;
+
+    props->DopplerFactor = context->DopplerFactor;
+    props->DopplerVelocity = context->DopplerVelocity;
+    props->SpeedOfSound = context->SpeedOfSound;
+
+    props->SourceDistanceModel = context->SourceDistanceModel;
+    props->DistanceModel = context->DistanceModel;
+
+    /* Set the new container for updating internal parameters. */
+    props = ATOMIC_EXCHANGE_PTR(&context->Update, props, almemory_order_acq_rel);
+    if(props)
+    {
+        /* If there was an unused update container, put it back in the
+         * freelist.
+         */
+        ATOMIC_REPLACE_HEAD(struct ALcontextProps*, &context->FreeContextProps, props);
+    }
+}

+ 0 - 108
libs/openal-soft/OpenAL32/alThunk.c

@@ -1,108 +0,0 @@
-/**
- * OpenAL cross platform audio library
- * Copyright (C) 1999-2007 by authors.
- * This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc.,
- *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "alMain.h"
-#include "alThunk.h"
-
-#include "almalloc.h"
-
-
-static ATOMIC_FLAG *ThunkArray;
-static ALsizei      ThunkArraySize;
-static RWLock ThunkLock;
-
-void ThunkInit(void)
-{
-    RWLockInit(&ThunkLock);
-    ThunkArraySize = 1024;
-    ThunkArray = al_calloc(16, ThunkArraySize * sizeof(*ThunkArray));
-}
-
-void ThunkExit(void)
-{
-    al_free(ThunkArray);
-    ThunkArray = NULL;
-    ThunkArraySize = 0;
-}
-
-ALenum NewThunkEntry(ALuint *index)
-{
-    void *NewList;
-    ALsizei i;
-
-    ReadLock(&ThunkLock);
-    for(i = 0;i < ThunkArraySize;i++)
-    {
-        if(!ATOMIC_FLAG_TEST_AND_SET(&ThunkArray[i], almemory_order_acq_rel))
-        {
-            ReadUnlock(&ThunkLock);
-            *index = i+1;
-            return AL_NO_ERROR;
-        }
-    }
-    ReadUnlock(&ThunkLock);
-
-    WriteLock(&ThunkLock);
-    /* 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_FLAG_TEST_AND_SET(&ThunkArray[i], almemory_order_acq_rel))
-        {
-            WriteUnlock(&ThunkLock);
-            *index = i+1;
-            return AL_NO_ERROR;
-        }
-    }
-
-    NewList = al_calloc(16, ThunkArraySize*2 * sizeof(*ThunkArray));
-    if(!NewList)
-    {
-        WriteUnlock(&ThunkLock);
-        ERR("Realloc failed to increase to %u entries!\n", ThunkArraySize*2);
-        return AL_OUT_OF_MEMORY;
-    }
-    memcpy(NewList, ThunkArray, ThunkArraySize*sizeof(*ThunkArray));
-    al_free(ThunkArray);
-    ThunkArray = NewList;
-    ThunkArraySize *= 2;
-
-    ATOMIC_FLAG_TEST_AND_SET(&ThunkArray[i], almemory_order_seq_cst);
-    *index = ++i;
-
-    for(;i < ThunkArraySize;i++)
-        ATOMIC_FLAG_CLEAR(&ThunkArray[i], almemory_order_relaxed);
-    WriteUnlock(&ThunkLock);
-
-    return AL_NO_ERROR;
-}
-
-void FreeThunkEntry(ALuint index)
-{
-    ReadLock(&ThunkLock);
-    if(index > 0 && (ALsizei)index <= ThunkArraySize)
-        ATOMIC_FLAG_CLEAR(&ThunkArray[index-1], almemory_order_release);
-    ReadUnlock(&ThunkLock);
-}

+ 140 - 0
libs/openal-soft/OpenAL32/event.c

@@ -0,0 +1,140 @@
+
+#include "config.h"
+
+#include "AL/alc.h"
+#include "AL/al.h"
+#include "AL/alext.h"
+#include "alMain.h"
+#include "alError.h"
+#include "ringbuffer.h"
+
+
+static int EventThread(void *arg)
+{
+    ALCcontext *context = arg;
+
+    /* Clear all pending posts on the semaphore. */
+    while(alsem_trywait(&context->EventSem) == althrd_success)
+    {
+    }
+
+    while(1)
+    {
+        ALbitfieldSOFT enabledevts;
+        AsyncEvent evt;
+
+        if(ll_ringbuffer_read(context->AsyncEvents, (char*)&evt, 1) == 0)
+        {
+            alsem_wait(&context->EventSem);
+            continue;
+        }
+        if(!evt.EnumType)
+            break;
+
+        almtx_lock(&context->EventCbLock);
+        enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_acquire);
+        if(context->EventCb && (enabledevts&evt.EnumType) == evt.EnumType)
+            context->EventCb(evt.Type, evt.ObjectId, evt.Param, (ALsizei)strlen(evt.Message),
+                             evt.Message, context->EventParam);
+        almtx_unlock(&context->EventCbLock);
+    }
+    return 0;
+}
+
+AL_API void AL_APIENTRY alEventControlSOFT(ALsizei count, const ALenum *types, ALboolean enable)
+{
+    ALCcontext *context;
+    ALbitfieldSOFT enabledevts;
+    ALbitfieldSOFT flags = 0;
+    bool isrunning;
+    ALsizei i;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    if(count < 0) SETERR_GOTO(context, AL_INVALID_VALUE, done, "Controlling %d events", count);
+    if(count == 0) goto done;
+    if(!types) SETERR_GOTO(context, AL_INVALID_VALUE, done, "NULL pointer");
+
+    for(i = 0;i < count;i++)
+    {
+        if(types[i] == AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT)
+            flags |= EventType_BufferCompleted;
+        else if(types[i] == AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT)
+            flags |= EventType_SourceStateChange;
+        else if(types[i] == AL_EVENT_TYPE_ERROR_SOFT)
+            flags |= EventType_Error;
+        else if(types[i] == AL_EVENT_TYPE_PERFORMANCE_SOFT)
+            flags |= EventType_Performance;
+        else if(types[i] == AL_EVENT_TYPE_DEPRECATED_SOFT)
+            flags |= EventType_Deprecated;
+        else if(types[i] == AL_EVENT_TYPE_DISCONNECTED_SOFT)
+            flags |= EventType_Disconnected;
+        else
+            SETERR_GOTO(context, AL_INVALID_ENUM, done, "Invalid event type 0x%04x", types[i]);
+    }
+
+    almtx_lock(&context->EventThrdLock);
+    if(enable)
+    {
+        if(!context->AsyncEvents)
+            context->AsyncEvents = ll_ringbuffer_create(63, sizeof(AsyncEvent), false);
+        enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
+        isrunning = !!enabledevts;
+        while(ATOMIC_COMPARE_EXCHANGE_WEAK(&context->EnabledEvts, &enabledevts, enabledevts|flags,
+                                           almemory_order_acq_rel, almemory_order_acquire) == 0)
+        {
+            /* enabledevts is (re-)filled with the current value on failure, so
+             * just try again.
+             */
+        }
+        if(!isrunning && flags)
+            althrd_create(&context->EventThread, EventThread, context);
+    }
+    else
+    {
+        enabledevts = ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed);
+        isrunning = !!enabledevts;
+        while(ATOMIC_COMPARE_EXCHANGE_WEAK(&context->EnabledEvts, &enabledevts, enabledevts&~flags,
+                                           almemory_order_acq_rel, almemory_order_acquire) == 0)
+        {
+        }
+        if(isrunning && !(enabledevts&~flags))
+        {
+            static const AsyncEvent kill_evt = { 0 };
+            while(ll_ringbuffer_write(context->AsyncEvents, (const char*)&kill_evt, 1) == 0)
+                althrd_yield();
+            alsem_post(&context->EventSem);
+            althrd_join(context->EventThread, NULL);
+        }
+        else
+        {
+            /* Wait to ensure the event handler sees the changed flags before
+             * returning.
+             */
+            almtx_lock(&context->EventCbLock);
+            almtx_unlock(&context->EventCbLock);
+        }
+    }
+    almtx_unlock(&context->EventThrdLock);
+
+done:
+    ALCcontext_DecRef(context);
+}
+
+AL_API void AL_APIENTRY alEventCallbackSOFT(ALEVENTPROCSOFT callback, void *userParam)
+{
+    ALCcontext *context;
+
+    context = GetContextRef();
+    if(!context) return;
+
+    almtx_lock(&context->PropLock);
+    almtx_lock(&context->EventCbLock);
+    context->EventCb = callback;
+    context->EventParam = userParam;
+    almtx_unlock(&context->EventCbLock);
+    almtx_unlock(&context->PropLock);
+
+    ALCcontext_DecRef(context);
+}

+ 60 - 788
libs/openal-soft/OpenAL32/sample_cvt.c

@@ -3,13 +3,6 @@
 
 #include "sample_cvt.h"
 
-#ifdef HAVE_ALLOCA_H
-#include <alloca.h>
-#endif
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
-
 #include "AL/al.h"
 #include "alu.h"
 #include "alBuffer.h"
@@ -61,7 +54,7 @@ static const int MSADPCMAdaptionCoeff[7][2] = {
 
 /* A quick'n'dirty lookup table to decode a muLaw-encoded byte sample into a
  * signed 16-bit sample */
-static const ALshort muLawDecompressionTable[256] = {
+const ALshort muLawDecompressionTable[256] = {
     -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956,
     -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764,
     -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412,
@@ -96,32 +89,10 @@ static const ALshort muLawDecompressionTable[256] = {
         56,    48,    40,    32,    24,    16,     8,     0
 };
 
-/* Values used when encoding a muLaw sample */
-static const int muLawBias = 0x84;
-static const int muLawClip = 32635;
-static const char muLawCompressTable[256] = {
-     0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
-     4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
-     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-     5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-     6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-     7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-};
-
 
 /* A quick'n'dirty lookup table to decode an aLaw-encoded byte sample into a
  * signed 16-bit sample */
-static const ALshort aLawDecompressionTable[256] = {
+const ALshort aLawDecompressionTable[256] = {
      -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
      -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
      -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
@@ -156,84 +127,13 @@ static const ALshort aLawDecompressionTable[256] = {
        944,   912,  1008,   976,   816,   784,   880,   848
 };
 
-/* Values used when encoding an aLaw sample */
-static const int aLawClip = 32635;
-static const char aLawCompressTable[128] = {
-    1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,
-    5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-    7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-};
-
-
-typedef ALubyte ALmulaw;
-typedef ALubyte ALalaw;
-typedef ALubyte ALima4;
-typedef ALubyte ALmsadpcm;
-
-static inline ALshort DecodeMuLaw(ALmulaw val)
-{ return muLawDecompressionTable[val]; }
-
-static ALmulaw EncodeMuLaw(ALshort val)
-{
-    ALint mant, exp, sign;
-
-    sign = (val>>8) & 0x80;
-    if(sign)
-    {
-        /* -32768 doesn't properly negate on a short; it results in itself.
-         * So clamp to -32767 */
-        val = maxi(val, -32767);
-        val = -val;
-    }
-
-    val = mini(val, muLawClip);
-    val += muLawBias;
-
-    exp = muLawCompressTable[(val>>7) & 0xff];
-    mant = (val >> (exp+3)) & 0x0f;
-
-    return ~(sign | (exp<<4) | mant);
-}
-
-static inline ALshort DecodeALaw(ALalaw val)
-{ return aLawDecompressionTable[val]; }
-
-static ALalaw EncodeALaw(ALshort val)
-{
-    ALint mant, exp, sign;
-
-    sign = ((~val) >> 8) & 0x80;
-    if(!sign)
-    {
-        val = maxi(val, -32767);
-        val = -val;
-    }
-    val = mini(val, aLawClip);
-
-    if(val >= 256)
-    {
-        exp = aLawCompressTable[(val>>8) & 0x7f];
-        mant = (val >> (exp+3)) & 0x0f;
-    }
-    else
-    {
-        exp = 0;
-        mant = val >> 4;
-    }
 
-    return ((exp<<4) | mant) ^ (sign^0x55);
-}
-
-static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans, ALsizei align)
+static void DecodeIMA4Block(ALshort *dst, const ALubyte *src, ALint numchans, ALsizei align)
 {
-    ALint sample[MAX_INPUT_CHANNELS], index[MAX_INPUT_CHANNELS];
-    ALuint code[MAX_INPUT_CHANNELS];
-    ALsizei j,k,c;
+    ALint sample[MAX_INPUT_CHANNELS] = { 0 };
+    ALint index[MAX_INPUT_CHANNELS] = { 0 };
+    ALuint code[MAX_INPUT_CHANNELS] = { 0 };
+    ALsizei c, i;
 
     for(c = 0;c < numchans;c++)
     {
@@ -249,143 +149,77 @@ static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans, ALs
         dst[c] = sample[c];
     }
 
-    for(j = 1;j < align;j += 8)
+    for(i = 1;i < align;i++)
     {
-        for(c = 0;c < numchans;c++)
-        {
-            code[c]  = *(src++);
-            code[c] |= *(src++) << 8;
-            code[c] |= *(src++) << 16;
-            code[c] |= *(src++) << 24;
-        }
-
-        for(k = 0;k < 8;k++)
+        if((i&7) == 1)
         {
             for(c = 0;c < numchans;c++)
             {
-                int nibble = code[c]&0xf;
-                code[c] >>= 4;
-
-                sample[c] += IMA4Codeword[nibble] * IMAStep_size[index[c]] / 8;
-                sample[c] = clampi(sample[c], -32768, 32767);
-
-                index[c] += IMA4Index_adjust[nibble];
-                index[c] = clampi(index[c], 0, 88);
-
-                dst[(j+k)*numchans + c] = sample[c];
+                code[c]  = *(src++);
+                code[c] |= *(src++) << 8;
+                code[c] |= *(src++) << 16;
+                code[c] |= *(src++) << 24;
             }
         }
-    }
-}
-
-static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALint *index, ALint numchans, ALsizei align)
-{
-    ALsizei j,k,c;
-
-    for(c = 0;c < numchans;c++)
-    {
-        int diff = src[c] - sample[c];
-        int step = IMAStep_size[index[c]];
-        int nibble;
-
-        nibble = 0;
-        if(diff < 0)
-        {
-            nibble = 0x8;
-            diff = -diff;
-        }
-
-        diff = mini(step*2, diff);
-        nibble |= (diff*8/step - 1) / 2;
-
-        sample[c] += IMA4Codeword[nibble] * step / 8;
-        sample[c] = clampi(sample[c], -32768, 32767);
-
-        index[c] += IMA4Index_adjust[nibble];
-        index[c] = clampi(index[c], 0, 88);
 
-        *(dst++) = sample[c] & 0xff;
-        *(dst++) = (sample[c]>>8) & 0xff;
-        *(dst++) = index[c] & 0xff;
-        *(dst++) = (index[c]>>8) & 0xff;
-    }
-
-    for(j = 1;j < align;j += 8)
-    {
         for(c = 0;c < numchans;c++)
         {
-            for(k = 0;k < 8;k++)
-            {
-                int diff = src[(j+k)*numchans + c] - sample[c];
-                int step = IMAStep_size[index[c]];
-                int nibble;
+            int nibble = code[c]&0xf;
+            code[c] >>= 4;
 
-                nibble = 0;
-                if(diff < 0)
-                {
-                    nibble = 0x8;
-                    diff = -diff;
-                }
+            sample[c] += IMA4Codeword[nibble] * IMAStep_size[index[c]] / 8;
+            sample[c] = clampi(sample[c], -32768, 32767);
 
-                diff = mini(step*2, diff);
-                nibble |= (diff*8/step - 1) / 2;
+            index[c] += IMA4Index_adjust[nibble];
+            index[c] = clampi(index[c], 0, 88);
 
-                sample[c] += IMA4Codeword[nibble] * step / 8;
-                sample[c] = clampi(sample[c], -32768, 32767);
-
-                index[c] += IMA4Index_adjust[nibble];
-                index[c] = clampi(index[c], 0, 88);
-
-                if(!(k&1)) *dst = nibble;
-                else *(dst++) |= nibble<<4;
-            }
+            *(dst++) = sample[c];
         }
     }
 }
 
-
-static void DecodeMSADPCMBlock(ALshort *dst, const ALmsadpcm *src, ALint numchans, ALsizei align)
+static void DecodeMSADPCMBlock(ALshort *dst, const ALubyte *src, ALint numchans, ALsizei align)
 {
-    ALubyte blockpred[MAX_INPUT_CHANNELS];
-    ALint delta[MAX_INPUT_CHANNELS];
-    ALshort samples[MAX_INPUT_CHANNELS][2];
-    ALint i, j;
+    ALubyte blockpred[MAX_INPUT_CHANNELS] = { 0 };
+    ALint delta[MAX_INPUT_CHANNELS] = { 0 };
+    ALshort samples[MAX_INPUT_CHANNELS][2] = { { 0, 0 } };
+    ALint c, i;
 
-    for(i = 0;i < numchans;i++)
+    for(c = 0;c < numchans;c++)
     {
-        blockpred[i] = *(src++);
-        blockpred[i] = minu(blockpred[i], 6);
+        blockpred[c] = *(src++);
+        blockpred[c] = minu(blockpred[c], 6);
     }
-    for(i = 0;i < numchans;i++)
+    for(c = 0;c < numchans;c++)
     {
-        delta[i]  = *(src++);
-        delta[i] |= *(src++) << 8;
-        delta[i]  = (delta[i]^0x8000) - 0x8000;
+        delta[c]  = *(src++);
+        delta[c] |= *(src++) << 8;
+        delta[c]  = (delta[c]^0x8000) - 32768;
     }
-    for(i = 0;i < numchans;i++)
+    for(c = 0;c < numchans;c++)
     {
-        samples[i][0]  = *(src++);
-        samples[i][0] |= *(src++) << 8;
-        samples[i][0]  = (samples[i][0]^0x8000) - 0x8000;
+        samples[c][0]  = *(src++);
+        samples[c][0] |= *(src++) << 8;
+        samples[c][0]  = (samples[c][0]^0x8000) - 32768;
     }
-    for(i = 0;i < numchans;i++)
+    for(c = 0;c < numchans;c++)
     {
-        samples[i][1]  = *(src++);
-        samples[i][1] |= *(src++) << 8;
-        samples[i][1]  = (samples[i][1]^0x8000) - 0x8000;
+        samples[c][1]  = *(src++);
+        samples[c][1] |= *(src++) << 8;
+        samples[c][1]  = (samples[c][1]^0x8000) - 0x8000;
     }
 
     /* Second sample is written first. */
-    for(i = 0;i < numchans;i++)
-        *(dst++) = samples[i][1];
-    for(i = 0;i < numchans;i++)
-        *(dst++) = samples[i][0];
+    for(c = 0;c < numchans;c++)
+        *(dst++) = samples[c][1];
+    for(c = 0;c < numchans;c++)
+        *(dst++) = samples[c][0];
 
-    for(j = 2;j < align;j++)
+    for(i = 2;i < align;i++)
     {
-        for(i = 0;i < numchans;i++)
+        for(c = 0;c < numchans;c++)
         {
-            const ALint num = (j*numchans) + i;
+            const ALint num = (i*numchans) + c;
             ALint nibble, pred;
 
             /* Read the nibble (first is in the upper bits). */
@@ -394,310 +228,28 @@ static void DecodeMSADPCMBlock(ALshort *dst, const ALmsadpcm *src, ALint numchan
             else
                 nibble = (*(src++))&0x0f;
 
-            pred  = (samples[i][0]*MSADPCMAdaptionCoeff[blockpred[i]][0] +
-                     samples[i][1]*MSADPCMAdaptionCoeff[blockpred[i]][1]) / 256;
-            pred += ((nibble^0x08) - 0x08) * delta[i];
+            pred  = (samples[c][0]*MSADPCMAdaptionCoeff[blockpred[c]][0] +
+                     samples[c][1]*MSADPCMAdaptionCoeff[blockpred[c]][1]) / 256;
+            pred += ((nibble^0x08) - 0x08) * delta[c];
             pred  = clampi(pred, -32768, 32767);
 
-            samples[i][1] = samples[i][0];
-            samples[i][0] = pred;
+            samples[c][1] = samples[c][0];
+            samples[c][0] = pred;
 
-            delta[i] = (MSADPCMAdaption[nibble] * delta[i]) / 256;
-            delta[i] = maxi(16, delta[i]);
+            delta[c] = (MSADPCMAdaption[nibble] * delta[c]) / 256;
+            delta[c] = maxi(16, delta[c]);
 
             *(dst++) = pred;
         }
     }
 }
 
-/* NOTE: This encoder is pretty dumb/simplistic. Some kind of pre-processing
- * that tries to find the optimal block predictors would be nice, at least. A
- * multi-pass method that can generate better deltas would be good, too. */
-static void EncodeMSADPCMBlock(ALmsadpcm *dst, const ALshort *src, ALint *sample, ALint numchans, ALsizei align)
-{
-    ALubyte blockpred[MAX_INPUT_CHANNELS];
-    ALint delta[MAX_INPUT_CHANNELS];
-    ALshort samples[MAX_INPUT_CHANNELS][2];
-    ALint i, j;
 
-    /* Block predictor */
-    for(i = 0;i < numchans;i++)
-    {
-        /* FIXME: Calculate something better. */
-        blockpred[i] = 0;
-        *(dst++) = blockpred[i];
-    }
-    /* Initial delta */
-    for(i = 0;i < numchans;i++)
-    {
-        delta[i] = 16;
-        *(dst++) = (delta[i]   ) & 0xff;
-        *(dst++) = (delta[i]>>8) & 0xff;
-    }
-    /* Initial sample 1 */
-    for(i = 0;i < numchans;i++)
-    {
-        samples[i][0] = src[1*numchans + i];
-        *(dst++) = (samples[i][0]   ) & 0xff;
-        *(dst++) = (samples[i][0]>>8) & 0xff;
-    }
-    /* Initial sample 2 */
-    for(i = 0;i < numchans;i++)
-    {
-        samples[i][1] = src[i];
-        *(dst++) = (samples[i][1]   ) & 0xff;
-        *(dst++) = (samples[i][1]>>8) & 0xff;
-    }
-
-    for(j = 2;j < align;j++)
-    {
-        for(i = 0;i < numchans;i++)
-        {
-            const ALint num = (j*numchans) + i;
-            ALint nibble = 0;
-            ALint bias;
-
-            sample[i] = (samples[i][0]*MSADPCMAdaptionCoeff[blockpred[i]][0] +
-                         samples[i][1]*MSADPCMAdaptionCoeff[blockpred[i]][1]) / 256;
-
-            nibble = src[num] - sample[i];
-            if(nibble >= 0)
-                bias = delta[i] / 2;
-            else
-                bias = -delta[i] / 2;
-
-            nibble = (nibble + bias) / delta[i];
-            nibble = clampi(nibble, -8, 7)&0x0f;
-
-            sample[i] += ((nibble^0x08)-0x08) * delta[i];
-            sample[i]  = clampi(sample[i], -32768, 32767);
-
-            samples[i][1] = samples[i][0];
-            samples[i][0] = sample[i];
-
-            delta[i] = (MSADPCMAdaption[nibble] * delta[i]) / 256;
-            delta[i] = maxi(16, delta[i]);
-
-            if(!(num&1))
-                *dst = nibble << 4;
-            else
-            {
-                *dst |= nibble;
-                dst++;
-            }
-        }
-    }
-}
-
-
-/* Define same-type pass-through sample conversion functions (excludes ADPCM,
- * which are block-based). */
-#define DECL_TEMPLATE(T) \
-static inline T Conv_##T##_##T(T val) { return val; }
-
-DECL_TEMPLATE(ALbyte);
-DECL_TEMPLATE(ALubyte);
-DECL_TEMPLATE(ALshort);
-DECL_TEMPLATE(ALushort);
-DECL_TEMPLATE(ALint);
-DECL_TEMPLATE(ALuint);
-DECL_TEMPLATE(ALalaw);
-DECL_TEMPLATE(ALmulaw);
-
-/* Slightly special handling for floats and doubles (converts NaN to 0, and
- * allows float<->double pass-through).
- */
-static inline ALfloat Conv_ALfloat_ALfloat(ALfloat val)
-{ return (val==val) ? val : 0.0f; }
-static inline ALfloat Conv_ALfloat_ALdouble(ALdouble val)
-{ return (val==val) ? (ALfloat)val : 0.0f; }
-static inline ALdouble Conv_ALdouble_ALfloat(ALfloat val)
-{ return (val==val) ? (ALdouble)val : 0.0; }
-static inline ALdouble Conv_ALdouble_ALdouble(ALdouble val)
-{ return (val==val) ? val : 0.0; }
-
-#undef DECL_TEMPLATE
-
-/* Define alternate-sign functions. */
-#define DECL_TEMPLATE(T1, T2, O)                                  \
-static inline T1 Conv_##T1##_##T2(T2 val) { return (T1)val - O; } \
-static inline T2 Conv_##T2##_##T1(T1 val) { return (T2)val + O; }
-
-DECL_TEMPLATE(ALbyte, ALubyte, 128);
-DECL_TEMPLATE(ALshort, ALushort, 32768);
-DECL_TEMPLATE(ALint, ALuint, 2147483648u);
-
-#undef DECL_TEMPLATE
-
-/* Define int-type to int-type functions */
-#define DECL_TEMPLATE(T, ST, UT, SH)                                          \
-static inline T Conv_##T##_##ST(ST val){ return val >> SH; }                  \
-static inline T Conv_##T##_##UT(UT val){ return Conv_##ST##_##UT(val) >> SH; }\
-static inline ST Conv_##ST##_##T(T val){ return val << SH; }                  \
-static inline UT Conv_##UT##_##T(T val){ return Conv_##UT##_##ST(val << SH); }
-
-#define DECL_TEMPLATE2(T1, T2, SH)          \
-DECL_TEMPLATE(AL##T1, AL##T2, ALu##T2, SH)  \
-DECL_TEMPLATE(ALu##T1, ALu##T2, AL##T2, SH)
-
-DECL_TEMPLATE2(byte,  short, 8)
-DECL_TEMPLATE2(short, int,   16)
-DECL_TEMPLATE2(byte,  int,   24)
-
-#undef DECL_TEMPLATE2
-#undef DECL_TEMPLATE
-
-/* Define int-type to fp functions */
-#define DECL_TEMPLATE(T, ST, UT, OP)                                          \
-static inline T Conv_##T##_##ST(ST val) { return (T)val * OP; }               \
-static inline T Conv_##T##_##UT(UT val) { return (T)Conv_##ST##_##UT(val) * OP; }
-
-#define DECL_TEMPLATE2(T1, T2, OP)     \
-DECL_TEMPLATE(T1, AL##T2, ALu##T2, OP)
-
-DECL_TEMPLATE2(ALfloat, byte, (1.0f/128.0f))
-DECL_TEMPLATE2(ALdouble, byte, (1.0/128.0))
-DECL_TEMPLATE2(ALfloat, short, (1.0f/32768.0f))
-DECL_TEMPLATE2(ALdouble, short, (1.0/32768.0))
-DECL_TEMPLATE2(ALdouble, int, (1.0/2147483648.0))
-
-/* Special handling for int32 to float32, since it would overflow. */
-static inline ALfloat Conv_ALfloat_ALint(ALint val)
-{ return (ALfloat)(val>>7) * (1.0f/16777216.0f); }
-static inline ALfloat Conv_ALfloat_ALuint(ALuint val)
-{ return (ALfloat)(Conv_ALint_ALuint(val)>>7) * (1.0f/16777216.0f); }
-
-#undef DECL_TEMPLATE2
-#undef DECL_TEMPLATE
-
-/* Define fp to int-type functions */
-#define DECL_TEMPLATE(FT, T, smin, smax)        \
-static inline AL##T Conv_AL##T##_##FT(FT val)   \
-{                                               \
-    val *= (FT)smax + 1;                        \
-    if(val >= (FT)smax) return smax;            \
-    if(val <= (FT)smin) return smin;            \
-    return (AL##T)val;                          \
-}                                               \
-static inline ALu##T Conv_ALu##T##_##FT(FT val) \
-{ return Conv_ALu##T##_AL##T(Conv_AL##T##_##FT(val)); }
-
-DECL_TEMPLATE(ALfloat, byte, -128, 127)
-DECL_TEMPLATE(ALdouble, byte, -128, 127)
-DECL_TEMPLATE(ALfloat, short, -32768, 32767)
-DECL_TEMPLATE(ALdouble, short, -32768, 32767)
-DECL_TEMPLATE(ALdouble, int, -2147483647-1, 2147483647)
-
-/* Special handling for float32 to int32, since it would overflow. */
-static inline ALint Conv_ALint_ALfloat(ALfloat val)
-{
-    val *= 16777216.0f;
-    if(val >= 16777215.0f) return 0x7fffff80/*16777215 << 7*/;
-    if(val <= -16777216.0f) return 0x80000000/*-16777216 << 7*/;
-    return (ALint)val << 7;
-}
-static inline ALuint Conv_ALuint_ALfloat(ALfloat val)
-{ return Conv_ALuint_ALint(Conv_ALint_ALfloat(val)); }
-
-#undef DECL_TEMPLATE
-
-/* Define muLaw and aLaw functions (goes through short functions). */
-#define DECL_TEMPLATE(T)                                                      \
-static inline ALmulaw Conv_ALmulaw_##T(T val)                                 \
-{ return EncodeMuLaw(Conv_ALshort_##T(val)); }                                \
-static inline T Conv_##T##_ALmulaw(ALmulaw val)                               \
-{ return Conv_##T##_ALshort(DecodeMuLaw(val)); }                              \
-                                                                              \
-static inline ALalaw Conv_ALalaw_##T(T val)                                   \
-{ return EncodeALaw(Conv_ALshort_##T(val)); }                                 \
-static inline T Conv_##T##_ALalaw(ALalaw val)                                 \
-{ return Conv_##T##_ALshort(DecodeALaw(val)); }
-
-DECL_TEMPLATE(ALbyte)
-DECL_TEMPLATE(ALubyte)
-DECL_TEMPLATE(ALshort)
-DECL_TEMPLATE(ALushort)
-DECL_TEMPLATE(ALint)
-DECL_TEMPLATE(ALuint)
-DECL_TEMPLATE(ALfloat)
-DECL_TEMPLATE(ALdouble)
-
-#undef DECL_TEMPLATE
-
-/* Define muLaw <-> aLaw functions. */
-static inline ALalaw Conv_ALalaw_ALmulaw(ALmulaw val)
-{ return EncodeALaw(DecodeMuLaw(val)); }
-static inline ALmulaw Conv_ALmulaw_ALalaw(ALalaw val)
-{ return EncodeMuLaw(DecodeALaw(val)); }
-
-
-#define DECL_TEMPLATE(T1, T2)                                                 \
-static void Convert_##T1##_##T2(T1 *dst, const T2 *src, ALuint numchans,      \
-                                ALuint len, ALsizei UNUSED(align))            \
-{                                                                             \
-    ALuint i, j;                                                              \
-    for(i = 0;i < len;i++)                                                    \
-    {                                                                         \
-        for(j = 0;j < numchans;j++)                                           \
-            *(dst++) = Conv_##T1##_##T2(*(src++));                            \
-    }                                                                         \
-}
-
-#define DECL_TEMPLATE2(T)  \
-DECL_TEMPLATE(T, ALbyte)   \
-DECL_TEMPLATE(T, ALubyte)  \
-DECL_TEMPLATE(T, ALshort)  \
-DECL_TEMPLATE(T, ALushort) \
-DECL_TEMPLATE(T, ALint)    \
-DECL_TEMPLATE(T, ALuint)   \
-DECL_TEMPLATE(T, ALfloat)  \
-DECL_TEMPLATE(T, ALdouble) \
-DECL_TEMPLATE(T, ALmulaw)  \
-DECL_TEMPLATE(T, ALalaw)
-
-DECL_TEMPLATE2(ALbyte)
-DECL_TEMPLATE2(ALubyte)
-DECL_TEMPLATE2(ALshort)
-DECL_TEMPLATE2(ALushort)
-DECL_TEMPLATE2(ALint)
-DECL_TEMPLATE2(ALuint)
-DECL_TEMPLATE2(ALfloat)
-DECL_TEMPLATE2(ALdouble)
-DECL_TEMPLATE2(ALmulaw)
-DECL_TEMPLATE2(ALalaw)
-
-#undef DECL_TEMPLATE2
-#undef DECL_TEMPLATE
-
-#define DECL_TEMPLATE(T)                                                      \
-static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans,  \
-                                 ALuint len, ALuint align)                    \
-{                                                                             \
-    ALsizei byte_align = ((align-1)/2 + 4) * numchans;                        \
-    DECL_VLA(ALshort, tmp, align*numchans);                                   \
-    ALuint i, j, k;                                                           \
-                                                                              \
-    assert(align > 0 && (len%align) == 0);                                    \
-    for(i = 0;i < len;i += align)                                             \
-    {                                                                         \
-        DecodeIMA4Block(tmp, src, numchans, align);                           \
-        src += byte_align;                                                    \
-                                                                              \
-        for(j = 0;j < align;j++)                                              \
-        {                                                                     \
-            for(k = 0;k < numchans;k++)                                       \
-                *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]);           \
-        }                                                                     \
-    }                                                                         \
-}
-
-DECL_TEMPLATE(ALbyte)
-DECL_TEMPLATE(ALubyte)
-static void Convert_ALshort_ALima4(ALshort *dst, const ALima4 *src, ALuint numchans,
-                                   ALuint len, ALuint align)
+void Convert_ALshort_ALima4(ALshort *dst, const ALubyte *src, ALsizei numchans, ALsizei len,
+                            ALsizei align)
 {
     ALsizei byte_align = ((align-1)/2 + 4) * numchans;
-    ALuint i;
+    ALsizei i;
 
     assert(align > 0 && (len%align) == 0);
     for(i = 0;i < len;i += align)
@@ -707,99 +259,12 @@ static void Convert_ALshort_ALima4(ALshort *dst, const ALima4 *src, ALuint numch
         dst += align*numchans;
     }
 }
-DECL_TEMPLATE(ALushort)
-DECL_TEMPLATE(ALint)
-DECL_TEMPLATE(ALuint)
-DECL_TEMPLATE(ALfloat)
-DECL_TEMPLATE(ALdouble)
-DECL_TEMPLATE(ALmulaw)
-DECL_TEMPLATE(ALalaw)
-
-#undef DECL_TEMPLATE
-
-#define DECL_TEMPLATE(T)                                                      \
-static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans,    \
-                               ALuint len, ALuint align)                      \
-{                                                                             \
-    ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};                     \
-    ALint index[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};                      \
-    ALsizei byte_align = ((align-1)/2 + 4) * numchans;                        \
-    DECL_VLA(ALshort, tmp, align*numchans);                                   \
-    ALuint i, j, k;                                                           \
-                                                                              \
-    assert(align > 0 && (len%align) == 0);                                    \
-    for(i = 0;i < len;i += align)                                             \
-    {                                                                         \
-        for(j = 0;j < align;j++)                                              \
-        {                                                                     \
-            for(k = 0;k < numchans;k++)                                       \
-                tmp[j*numchans + k] = Conv_ALshort_##T(*(src++));             \
-        }                                                                     \
-        EncodeIMA4Block(dst, tmp, sample, index, numchans, align);            \
-        dst += byte_align;                                                    \
-    }                                                                         \
-}
 
-DECL_TEMPLATE(ALbyte)
-DECL_TEMPLATE(ALubyte)
-static void Convert_ALima4_ALshort(ALima4 *dst, const ALshort *src,
-                                   ALuint numchans, ALuint len, ALuint align)
-{
-    ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};
-    ALint index[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};
-    ALsizei byte_align = ((align-1)/2 + 4) * numchans;
-    ALuint i;
-
-    assert(align > 0 && (len%align) == 0);
-    for(i = 0;i < len;i += align)
-    {
-        EncodeIMA4Block(dst, src, sample, index, numchans, align);
-        src += align*numchans;
-        dst += byte_align;
-    }
-}
-DECL_TEMPLATE(ALushort)
-DECL_TEMPLATE(ALint)
-DECL_TEMPLATE(ALuint)
-DECL_TEMPLATE(ALfloat)
-DECL_TEMPLATE(ALdouble)
-DECL_TEMPLATE(ALmulaw)
-DECL_TEMPLATE(ALalaw)
-
-#undef DECL_TEMPLATE
-
-
-#define DECL_TEMPLATE(T)                                                      \
-static void Convert_##T##_ALmsadpcm(T *dst, const ALmsadpcm *src,             \
-                                    ALuint numchans, ALuint len,              \
-                                    ALuint align)                             \
-{                                                                             \
-    ALsizei byte_align = ((align-2)/2 + 7) * numchans;                        \
-    DECL_VLA(ALshort, tmp, align*numchans);                                   \
-    ALuint i, j, k;                                                           \
-                                                                              \
-    assert(align > 1 && (len%align) == 0);                                    \
-    for(i = 0;i < len;i += align)                                             \
-    {                                                                         \
-        DecodeMSADPCMBlock(tmp, src, numchans, align);                        \
-        src += byte_align;                                                    \
-                                                                              \
-        for(j = 0;j < align;j++)                                              \
-        {                                                                     \
-            for(k = 0;k < numchans;k++)                                       \
-                *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]);           \
-        }                                                                     \
-    }                                                                         \
-}
-
-DECL_TEMPLATE(ALbyte)
-DECL_TEMPLATE(ALubyte)
-static void Convert_ALshort_ALmsadpcm(ALshort *dst, const ALmsadpcm *src,
-                                      ALuint numchans, ALuint len,
-                                      ALuint align)
+void Convert_ALshort_ALmsadpcm(ALshort *dst, const ALubyte *src, ALsizei numchans, ALsizei len,
+                               ALsizei align)
 {
     ALsizei byte_align = ((align-2)/2 + 7) * numchans;
-    ALuint i;
+    ALsizei i;
 
     assert(align > 1 && (len%align) == 0);
     for(i = 0;i < len;i += align)
@@ -809,196 +274,3 @@ static void Convert_ALshort_ALmsadpcm(ALshort *dst, const ALmsadpcm *src,
         dst += align*numchans;
     }
 }
-DECL_TEMPLATE(ALushort)
-DECL_TEMPLATE(ALint)
-DECL_TEMPLATE(ALuint)
-DECL_TEMPLATE(ALfloat)
-DECL_TEMPLATE(ALdouble)
-DECL_TEMPLATE(ALmulaw)
-DECL_TEMPLATE(ALalaw)
-
-#undef DECL_TEMPLATE
-
-#define DECL_TEMPLATE(T)                                                      \
-static void Convert_ALmsadpcm_##T(ALmsadpcm *dst, const T *src,               \
-                                  ALuint numchans, ALuint len, ALuint align)  \
-{                                                                             \
-    ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};                     \
-    ALsizei byte_align = ((align-2)/2 + 7) * numchans;                        \
-    DECL_VLA(ALshort, tmp, align*numchans);                                   \
-    ALuint i, j, k;                                                           \
-                                                                              \
-    assert(align > 1 && (len%align) == 0);                                    \
-    for(i = 0;i < len;i += align)                                             \
-    {                                                                         \
-        for(j = 0;j < align;j++)                                              \
-        {                                                                     \
-            for(k = 0;k < numchans;k++)                                       \
-                tmp[j*numchans + k] = Conv_ALshort_##T(*(src++));             \
-        }                                                                     \
-        EncodeMSADPCMBlock(dst, tmp, sample, numchans, align);                \
-        dst += byte_align;                                                    \
-    }                                                                         \
-}
-
-DECL_TEMPLATE(ALbyte)
-DECL_TEMPLATE(ALubyte)
-static void Convert_ALmsadpcm_ALshort(ALmsadpcm *dst, const ALshort *src,
-                                      ALuint numchans, ALuint len, ALuint align)
-{
-    ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0};
-    ALsizei byte_align = ((align-2)/2 + 7) * numchans;
-    ALuint i;
-
-    assert(align > 1 && (len%align) == 0);
-    for(i = 0;i < len;i += align)
-    {
-        EncodeMSADPCMBlock(dst, src, sample, numchans, align);
-        src += align*numchans;
-        dst += byte_align;
-    }
-}
-DECL_TEMPLATE(ALushort)
-DECL_TEMPLATE(ALint)
-DECL_TEMPLATE(ALuint)
-DECL_TEMPLATE(ALfloat)
-DECL_TEMPLATE(ALdouble)
-DECL_TEMPLATE(ALmulaw)
-DECL_TEMPLATE(ALalaw)
-
-#undef DECL_TEMPLATE
-
-/* NOTE: We don't store compressed samples internally, so these conversions
- * should never happen. */
-static void Convert_ALima4_ALima4(ALima4* UNUSED(dst), const ALima4* UNUSED(src),
-                                  ALuint UNUSED(numchans), ALuint UNUSED(len),
-                                  ALuint UNUSED(align))
-{
-    ERR("Unexpected IMA4-to-IMA4 conversion!\n");
-}
-
-static void Convert_ALmsadpcm_ALmsadpcm(ALmsadpcm* UNUSED(dst), const ALmsadpcm* UNUSED(src),
-                                        ALuint UNUSED(numchans), ALuint UNUSED(len),
-                                        ALuint UNUSED(align))
-{
-    ERR("Unexpected MSADPCM-to-MSADPCM conversion!\n");
-}
-
-static void Convert_ALmsadpcm_ALima4(ALmsadpcm* UNUSED(dst), const ALima4* UNUSED(src),
-                                     ALuint UNUSED(numchans), ALuint UNUSED(len),
-                                     ALuint UNUSED(align))
-{
-    ERR("Unexpected IMA4-to-MSADPCM conversion!\n");
-}
-
-static void Convert_ALima4_ALmsadpcm(ALima4* UNUSED(dst), const ALmsadpcm* UNUSED(src),
-                                     ALuint UNUSED(numchans), ALuint UNUSED(len),
-                                     ALuint UNUSED(align))
-{
-    ERR("Unexpected MSADPCM-to-IMA4 conversion!\n");
-}
-
-
-#define DECL_TEMPLATE(T)                                                      \
-static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType,  \
-                        ALsizei numchans, ALsizei len, ALsizei align)         \
-{                                                                             \
-    switch(srcType)                                                           \
-    {                                                                         \
-        case UserFmtByte:                                                     \
-            Convert_##T##_ALbyte(dst, src, numchans, len, align);             \
-            break;                                                            \
-        case UserFmtUByte:                                                    \
-            Convert_##T##_ALubyte(dst, src, numchans, len, align);            \
-            break;                                                            \
-        case UserFmtShort:                                                    \
-            Convert_##T##_ALshort(dst, src, numchans, len, align);            \
-            break;                                                            \
-        case UserFmtUShort:                                                   \
-            Convert_##T##_ALushort(dst, src, numchans, len, align);           \
-            break;                                                            \
-        case UserFmtInt:                                                      \
-            Convert_##T##_ALint(dst, src, numchans, len, align);              \
-            break;                                                            \
-        case UserFmtUInt:                                                     \
-            Convert_##T##_ALuint(dst, src, numchans, len, align);             \
-            break;                                                            \
-        case UserFmtFloat:                                                    \
-            Convert_##T##_ALfloat(dst, src, numchans, len, align);            \
-            break;                                                            \
-        case UserFmtDouble:                                                   \
-            Convert_##T##_ALdouble(dst, src, numchans, len, align);           \
-            break;                                                            \
-        case UserFmtMulaw:                                                    \
-            Convert_##T##_ALmulaw(dst, src, numchans, len, align);            \
-            break;                                                            \
-        case UserFmtAlaw:                                                     \
-            Convert_##T##_ALalaw(dst, src, numchans, len, align);             \
-            break;                                                            \
-        case UserFmtIMA4:                                                     \
-            Convert_##T##_ALima4(dst, src, numchans, len, align);             \
-            break;                                                            \
-        case UserFmtMSADPCM:                                                  \
-            Convert_##T##_ALmsadpcm(dst, src, numchans, len, align);          \
-            break;                                                            \
-    }                                                                         \
-}
-
-DECL_TEMPLATE(ALbyte)
-DECL_TEMPLATE(ALubyte)
-DECL_TEMPLATE(ALshort)
-DECL_TEMPLATE(ALushort)
-DECL_TEMPLATE(ALint)
-DECL_TEMPLATE(ALuint)
-DECL_TEMPLATE(ALfloat)
-DECL_TEMPLATE(ALdouble)
-DECL_TEMPLATE(ALmulaw)
-DECL_TEMPLATE(ALalaw)
-DECL_TEMPLATE(ALima4)
-DECL_TEMPLATE(ALmsadpcm)
-
-#undef DECL_TEMPLATE
-
-
-void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align)
-{
-    switch(dstType)
-    {
-        case UserFmtByte:
-            Convert_ALbyte(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtUByte:
-            Convert_ALubyte(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtShort:
-            Convert_ALshort(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtUShort:
-            Convert_ALushort(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtInt:
-            Convert_ALint(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtUInt:
-            Convert_ALuint(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtFloat:
-            Convert_ALfloat(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtDouble:
-            Convert_ALdouble(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtMulaw:
-            Convert_ALmulaw(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtAlaw:
-            Convert_ALalaw(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtIMA4:
-            Convert_ALima4(dst, src, srcType, numchans, len, align);
-            break;
-        case UserFmtMSADPCM:
-            Convert_ALmsadpcm(dst, src, srcType, numchans, len, align);
-            break;
-    }
-}

+ 0 - 55
libs/openal-soft/README

@@ -1,55 +0,0 @@
-Source Install
-==============
-
-To install OpenAL Soft, use your favorite shell to go into the build/
-directory, and run:
-
-cmake ..
-
-Assuming configuration went well, you can then build it, typically using GNU
-Make (KDevelop, MSVC, and others are possible depending on your system setup
-and CMake configuration).
-
-Please Note: Double check that the appropriate backends were detected. Often,
-complaints of no sound, crashing, and missing devices can be solved by making
-sure the correct backends are being used. CMake's output will identify which
-backends were enabled.
-
-For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio
-were detected (if your target system uses them). For Windows, make sure
-DirectSound was detected.
-
-
-Utilities
-=========
-
-The source package comes with an informational utility, openal-info, and is
-built by default. It prints out information provided by the ALC and AL sub-
-systems, including discovered devices, version information, and extensions.
-
-
-Configuration
-=============
-
-OpenAL Soft can be configured on a per-user and per-system basis. This allows
-users and sysadmins to control information provided to applications, as well
-as application-agnostic behavior of the library. See alsoftrc.sample for
-available settings.
-
-
-Acknowledgements
-================
-
-Special thanks go to:
-
-Creative Labs for the original source code this is based off of.
-
-Christopher Fitzgerald for the current reverb effect implementation, and
-helping with the low-pass and HRTF filters.
-
-Christian Borss for the 3D panning code previous versions used as a base.
-
-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.

+ 61 - 0
libs/openal-soft/README.md

@@ -0,0 +1,61 @@
+OpenAL soft
+===========
+
+`master` branch CI status :  [![Build Status](https://travis-ci.org/kcat/openal-soft.svg?branch=master)](https://travis-ci.org/kcat/openal-soft) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)](https://ci.appveyor.com/api/projects/status/github/kcat/openal-soft?branch=master&svg=true)
+
+OpenAL Soft is an LGPL-licensed, cross-platform, software implementation of the OpenAL 3D audio API. It's forked from the open-sourced Windows version available originally from openal.org's SVN repository (now defunct).
+OpenAL provides capabilities for playing audio in a virtual 3D environment. Distance attenuation, doppler shift, and directional sound emitters are among the features handled by the API. More advanced effects, including air absorption, occlusion, and environmental reverb, are available through the EFX extension. It also facilitates streaming audio, multi-channel buffers, and audio capture.
+
+More information is available on the [official website](http://openal-soft.org/)
+
+Source Install
+-------------
+To install OpenAL Soft, use your favorite shell to go into the build/
+directory, and run:
+
+```bash
+cmake ..
+```
+
+Assuming configuration went well, you can then build it, typically using GNU
+Make (KDevelop, MSVC, and others are possible depending on your system setup
+and CMake configuration).
+
+Please Note: Double check that the appropriate backends were detected. Often,
+complaints of no sound, crashing, and missing devices can be solved by making
+sure the correct backends are being used. CMake's output will identify which
+backends were enabled.
+
+For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio
+were detected (if your target system uses them). For Windows, make sure
+DirectSound was detected.
+
+
+Utilities
+---------
+The source package comes with an informational utility, openal-info, and is
+built by default. It prints out information provided by the ALC and AL sub-
+systems, including discovered devices, version information, and extensions.
+
+
+Configuration
+-------------
+
+OpenAL Soft can be configured on a per-user and per-system basis. This allows
+users and sysadmins to control information provided to applications, as well
+as application-agnostic behavior of the library. See alsoftrc.sample for
+available settings.
+
+
+Acknowledgements
+----------------
+
+Special thanks go to:
+
+ - Creative Labs for the original source code this is based off of.
+ - Christopher Fitzgerald for the current reverb effect implementation, and
+helping with the low-pass and HRTF filters.
+ - Christian Borss for the 3D panning code previous versions used as a base.
+ - 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.

+ 17 - 14
libs/openal-soft/alsoftrc.sample

@@ -149,10 +149,11 @@
 #  Selects the resampler used when mixing sources. Valid values are:
 #  point - nearest sample, no interpolation
 #  linear - extrapolates samples using a linear slope between samples
-#  sinc4 - extrapolates samples using a 4-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).
+#  cubic - extrapolates samples using a Catmull-Rom spline
+#  bsinc12 - extrapolates samples using a band-limited Sinc filter (varying
+#            between 12 and 24 points, with anti-aliasing)
+#  bsinc24 - extrapolates samples using a band-limited Sinc filter (varying
+#            between 24 and 48 points, with anti-aliasing)
 #resampler = linear
 
 ## rt-prio: (global)
@@ -181,6 +182,14 @@
 #  than the default has no effect.
 #sends = 16
 
+## front-stablizer:
+#  Applies filters to "stablize" front sound imaging. A psychoacoustic method
+#  is used to generate a front-center channel signal from the front-left and
+#  front-right channels, improving the front response by reducing the combing
+#  artifacts and phase errors. Consequently, it will only work with channel
+#  configurations that include front-left, front-right, and front-center.
+#front-stablizer = false
+
 ## output-limiter:
 #  Applies a gain limiter on the final mixed output. This reduces the volume
 #  when the output samples would otherwise clamp, avoiding excessive clipping
@@ -211,7 +220,7 @@
 #  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
+#  distortion,echo,equalizer,flanger,modulator,dedicated,pshifter
 #excludefx =
 
 ## default-reverb: (global)
@@ -277,7 +286,7 @@ nfc = true
 nfc-ref-delay =
 
 ## quad:
-#  Decoder configuration file for Quadrophonic channel output. See
+#  Decoder configuration file for Quadraphonic channel output. See
 #  docs/ambdec.txt for a description of the file format.
 quad =
 
@@ -310,12 +319,6 @@ surround71 =
 #  value of 0 means no change.
 #boost = 0
 
-## emulate-eax: (global)
-#  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
-#  allows a simpler effect to be used at the loss of some quality.
-#emulate-eax = false
-
 ##
 ## PulseAudio backend stuff
 ##
@@ -441,9 +444,9 @@ surround71 =
 #buffer-size = 0
 
 ##
-## MMDevApi backend stuff
+## WASAPI backend stuff
 ##
-[mmdevapi]
+[wasapi]
 
 ##
 ## DirectSound backend stuff

+ 1 - 1
libs/openal-soft/appveyor.yml

@@ -14,6 +14,6 @@ install:
 
 build_script:
     - cd build
-    - cmake -G"%GEN%" -DALSOFT_REQUIRE_WINMM=ON -DALSOFT_REQUIRE_DSOUND=ON -DALSOFT_REQUIRE_MMDEVAPI=ON -DALSOFT_EMBED_HRTF_DATA=YES ..
+    - cmake -G"%GEN%" -DALSOFT_REQUIRE_WINMM=ON -DALSOFT_REQUIRE_DSOUND=ON -DALSOFT_REQUIRE_WASAPI=ON -DALSOFT_EMBED_HRTF_DATA=YES ..
     - cmake --build . --config %CFG% --clean-first
 

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