ソースを参照

Upgraded OpenAL-Soft to 0.18.2

Martin Felis 7 年 前
コミット
f40577c9cb
100 ファイル変更17497 行追加29153 行削除
  1. 2 2
      love/src/jni/love/Android.mk
  2. 0 1321
      love/src/jni/openal-soft-1.17.0/Alc/ALu.c
  3. 0 129
      love/src/jni/openal-soft-1.17.0/Alc/alcRing.c
  4. 0 45
      love/src/jni/openal-soft-1.17.0/Alc/alstring.h
  5. 0 232
      love/src/jni/openal-soft-1.17.0/Alc/backends/base.c
  6. 0 424
      love/src/jni/openal-soft-1.17.0/Alc/backends/opensl.c
  7. 0 469
      love/src/jni/openal-soft-1.17.0/Alc/backends/portaudio.c
  8. 0 295
      love/src/jni/openal-soft-1.17.0/Alc/backends/sndio.c
  9. 0 288
      love/src/jni/openal-soft-1.17.0/Alc/backends/solaris.c
  10. 0 377
      love/src/jni/openal-soft-1.17.0/Alc/backends/wave.c
  11. 0 716
      love/src/jni/openal-soft-1.17.0/Alc/backends/winmm.c
  12. 0 272
      love/src/jni/openal-soft-1.17.0/Alc/effects/autowah.c
  13. 0 1779
      love/src/jni/openal-soft-1.17.0/Alc/effects/reverb.c
  14. 0 31
      love/src/jni/openal-soft-1.17.0/Alc/evtqueue.h
  15. 0 814
      love/src/jni/openal-soft-1.17.0/Alc/helpers.c
  16. 0 820
      love/src/jni/openal-soft-1.17.0/Alc/hrtf.c
  17. 0 28
      love/src/jni/openal-soft-1.17.0/Alc/hrtf.h
  18. 0 244
      love/src/jni/openal-soft-1.17.0/Alc/midi/base.c
  19. 0 133
      love/src/jni/openal-soft-1.17.0/Alc/midi/base.h
  20. 0 76
      love/src/jni/openal-soft-1.17.0/Alc/midi/dummy.c
  21. 0 930
      love/src/jni/openal-soft-1.17.0/Alc/midi/fluidsynth.c
  22. 0 1377
      love/src/jni/openal-soft-1.17.0/Alc/midi/sf2load.c
  23. 0 140
      love/src/jni/openal-soft-1.17.0/Alc/midi/soft.c
  24. 0 510
      love/src/jni/openal-soft-1.17.0/Alc/mixer.c
  25. 0 126
      love/src/jni/openal-soft-1.17.0/Alc/mixer_c.c
  26. 0 65
      love/src/jni/openal-soft-1.17.0/Alc/mixer_defs.h
  27. 0 93
      love/src/jni/openal-soft-1.17.0/Alc/mixer_inc.c
  28. 0 118
      love/src/jni/openal-soft-1.17.0/Alc/mixer_neon.c
  29. 0 202
      love/src/jni/openal-soft-1.17.0/Alc/mixer_sse.c
  30. 0 82
      love/src/jni/openal-soft-1.17.0/Alc/mixer_sse41.c
  31. 0 450
      love/src/jni/openal-soft-1.17.0/Alc/panning.c
  32. 0 87
      love/src/jni/openal-soft-1.17.0/Alc/vector.h
  33. 0 112
      love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alFilter.h
  34. 0 28
      love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alListener.h
  35. 0 895
      love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alMain.h
  36. 0 172
      love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alMidi.h
  37. 0 147
      love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alSource.h
  38. 0 236
      love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alu.h
  39. 0 1008
      love/src/jni/openal-soft-1.17.0/OpenAL32/alFontsound.c
  40. 0 217
      love/src/jni/openal-soft-1.17.0/OpenAL32/alMidi.c
  41. 0 339
      love/src/jni/openal-soft-1.17.0/OpenAL32/alPreset.c
  42. 0 454
      love/src/jni/openal-soft-1.17.0/OpenAL32/alSoundfont.c
  43. 0 2912
      love/src/jni/openal-soft-1.17.0/OpenAL32/alSource.c
  44. 0 0
      love/src/jni/openal-soft-1.17.0/build/.empty
  45. 0 33
      love/src/jni/openal-soft-1.17.0/cmake/FindDSound.cmake
  46. 0 19
      love/src/jni/openal-soft-1.17.0/cmake/FindFluidSynth.cmake
  47. 0 380
      love/src/jni/openal-soft-1.17.0/cmake/FindSDL_sound.cmake
  48. 0 144
      love/src/jni/openal-soft-1.17.0/common/uintmap.c
  49. 0 1479
      love/src/jni/openal-soft-1.17.0/examples/alffplay.c
  50. 0 327
      love/src/jni/openal-soft-1.17.0/examples/common/alhelpers.c
  51. 0 51
      love/src/jni/openal-soft-1.17.0/examples/common/alhelpers.h
  52. 0 164
      love/src/jni/openal-soft-1.17.0/examples/common/sdl_sound.c
  53. 0 43
      love/src/jni/openal-soft-1.17.0/examples/common/sdl_sound.h
  54. BIN
      love/src/jni/openal-soft-1.17.0/hrtf/default-44100.mhr
  55. BIN
      love/src/jni/openal-soft-1.17.0/hrtf/default-48000.mhr
  56. 0 313
      love/src/jni/openal-soft-1.17.0/include/atomic.h
  57. 0 29
      love/src/jni/openal-soft-1.17.0/utils/alsoft-config/CMakeLists.txt
  58. 0 660
      love/src/jni/openal-soft-1.17.0/utils/alsoft-config/mainwindow.cpp
  59. 0 1464
      love/src/jni/openal-soft-1.17.0/utils/alsoft-config/mainwindow.ui
  60. 0 2749
      love/src/jni/openal-soft-1.17.0/utils/makehrtf.c
  61. 7 0
      love/src/jni/openal-soft-1.18.2/.gitignore
  62. 70 0
      love/src/jni/openal-soft-1.18.2/.travis.yml
  63. 365 277
      love/src/jni/openal-soft-1.18.2/Alc/ALc.c
  64. 1830 0
      love/src/jni/openal-soft-1.18.2/Alc/ALu.c
  65. 173 36
      love/src/jni/openal-soft-1.18.2/Alc/alcConfig.c
  66. 317 0
      love/src/jni/openal-soft-1.18.2/Alc/alcRing.c
  67. 49 0
      love/src/jni/openal-soft-1.18.2/Alc/alstring.h
  68. 566 0
      love/src/jni/openal-soft-1.18.2/Alc/ambdec.c
  69. 46 0
      love/src/jni/openal-soft-1.18.2/Alc/ambdec.h
  70. 142 92
      love/src/jni/openal-soft-1.18.2/Alc/backends/alsa.c
  71. 81 0
      love/src/jni/openal-soft-1.18.2/Alc/backends/base.c
  72. 28 6
      love/src/jni/openal-soft-1.18.2/Alc/backends/base.h
  73. 309 188
      love/src/jni/openal-soft-1.18.2/Alc/backends/coreaudio.c
  74. 147 141
      love/src/jni/openal-soft-1.18.2/Alc/backends/dsound.c
  75. 640 0
      love/src/jni/openal-soft-1.18.2/Alc/backends/jack.c
  76. 5 10
      love/src/jni/openal-soft-1.18.2/Alc/backends/loopback.c
  77. 1035 158
      love/src/jni/openal-soft-1.18.2/Alc/backends/mmdevapi.c
  78. 8 11
      love/src/jni/openal-soft-1.18.2/Alc/backends/null.c
  79. 1135 0
      love/src/jni/openal-soft-1.18.2/Alc/backends/opensl.c
  80. 375 139
      love/src/jni/openal-soft-1.18.2/Alc/backends/oss.c
  81. 575 0
      love/src/jni/openal-soft-1.18.2/Alc/backends/portaudio.c
  82. 340 189
      love/src/jni/openal-soft-1.18.2/Alc/backends/pulseaudio.c
  83. 351 443
      love/src/jni/openal-soft-1.18.2/Alc/backends/qsa.c
  84. 346 0
      love/src/jni/openal-soft-1.18.2/Alc/backends/sndio.c
  85. 363 0
      love/src/jni/openal-soft-1.18.2/Alc/backends/solaris.c
  86. 453 0
      love/src/jni/openal-soft-1.18.2/Alc/backends/wave.c
  87. 803 0
      love/src/jni/openal-soft-1.18.2/Alc/backends/winmm.c
  88. 612 0
      love/src/jni/openal-soft-1.18.2/Alc/bformatdec.c
  89. 75 0
      love/src/jni/openal-soft-1.18.2/Alc/bformatdec.h
  90. 62 18
      love/src/jni/openal-soft-1.18.2/Alc/bs2b.c
  91. 5081 0
      love/src/jni/openal-soft-1.18.2/Alc/bsinc.c
  92. 25 0
      love/src/jni/openal-soft-1.18.2/Alc/compat.h
  93. 466 0
      love/src/jni/openal-soft-1.18.2/Alc/converter.c
  94. 55 0
      love/src/jni/openal-soft-1.18.2/Alc/converter.h
  95. 121 108
      love/src/jni/openal-soft-1.18.2/Alc/effects/chorus.c
  96. 79 45
      love/src/jni/openal-soft-1.18.2/Alc/effects/compressor.c
  97. 68 29
      love/src/jni/openal-soft-1.18.2/Alc/effects/dedicated.c
  98. 89 89
      love/src/jni/openal-soft-1.18.2/Alc/effects/distortion.c
  99. 90 57
      love/src/jni/openal-soft-1.18.2/Alc/effects/echo.c
  100. 113 67
      love/src/jni/openal-soft-1.18.2/Alc/effects/equalizer.c

+ 2 - 2
love/src/jni/love/Android.mk

@@ -21,8 +21,8 @@ LOCAL_C_INCLUDES  :=  \
 	${LOCAL_PATH}/../libmng-1.0.10/ \
 	${LOCAL_PATH}/../lcms2-2.5/include \
 	${LOCAL_PATH}/../tiff-3.9.5/libtiff \
-	${LOCAL_PATH}/../openal-soft-1.17.0/include \
-	${LOCAL_PATH}/../openal-soft-1.17.0/OpenAL32/Include \
+	${LOCAL_PATH}/../openal-soft-1.18.2/include \
+	${LOCAL_PATH}/../openal-soft-1.18.2/OpenAL32/Include \
 	${LOCAL_PATH}/../freetype2-android/include \
 	${LOCAL_PATH}/../freetype2-android/src \
 	${LOCAL_PATH}/../physfs-3.0.1/src \

+ 0 - 1321
love/src/jni/openal-soft-1.17.0/Alc/ALu.c

@@ -1,1321 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "alMain.h"
-#include "alSource.h"
-#include "alBuffer.h"
-#include "alListener.h"
-#include "alAuxEffectSlot.h"
-#include "alu.h"
-#include "bs2b.h"
-#include "hrtf.h"
-#include "static_assert.h"
-
-#include "midi/base.h"
-
-
-static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
-              "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
-
-struct ChanMap {
-    enum Channel channel;
-    ALfloat angle;
-};
-
-/* Cone scalar */
-ALfloat ConeScale = 1.0f;
-
-/* Localized Z scalar for mono sources */
-ALfloat ZScale = 1.0f;
-
-extern inline ALfloat minf(ALfloat a, ALfloat b);
-extern inline ALfloat maxf(ALfloat a, ALfloat b);
-extern inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max);
-
-extern inline ALdouble mind(ALdouble a, ALdouble b);
-extern inline ALdouble maxd(ALdouble a, ALdouble b);
-extern inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max);
-
-extern inline ALuint minu(ALuint a, ALuint b);
-extern inline ALuint maxu(ALuint a, ALuint b);
-extern inline ALuint clampu(ALuint val, ALuint min, ALuint max);
-
-extern inline ALint mini(ALint a, ALint b);
-extern inline ALint maxi(ALint a, ALint b);
-extern inline ALint clampi(ALint val, ALint min, ALint max);
-
-extern inline ALint64 mini64(ALint64 a, ALint64 b);
-extern inline ALint64 maxi64(ALint64 a, ALint64 b);
-extern inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max);
-
-extern inline ALuint64 minu64(ALuint64 a, ALuint64 b);
-extern inline ALuint64 maxu64(ALuint64 a, ALuint64 b);
-extern inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max);
-
-extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu);
-extern inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat mu);
-
-
-static inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
-{
-    outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
-    outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
-    outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
-}
-
-static inline ALfloat aluDotproduct(const ALfloat *inVector1, const ALfloat *inVector2)
-{
-    return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] +
-           inVector1[2]*inVector2[2];
-}
-
-static inline void aluNormalize(ALfloat *inVector)
-{
-    ALfloat lengthsqr = aluDotproduct(inVector, inVector);
-    if(lengthsqr > 0.0f)
-    {
-        ALfloat inv_length = 1.0f/sqrtf(lengthsqr);
-        inVector[0] *= inv_length;
-        inVector[1] *= inv_length;
-        inVector[2] *= inv_length;
-    }
-}
-
-static inline ALvoid aluMatrixVector(ALfloat *vector, ALfloat w, ALfloat (*restrict matrix)[4])
-{
-    ALfloat temp[4] = {
-        vector[0], vector[1], vector[2], w
-    };
-
-    vector[0] = temp[0]*matrix[0][0] + temp[1]*matrix[1][0] + temp[2]*matrix[2][0] + temp[3]*matrix[3][0];
-    vector[1] = temp[0]*matrix[0][1] + temp[1]*matrix[1][1] + temp[2]*matrix[2][1] + temp[3]*matrix[3][1];
-    vector[2] = temp[0]*matrix[0][2] + temp[1]*matrix[1][2] + temp[2]*matrix[2][2] + temp[3]*matrix[3][2];
-}
-
-
-static ALvoid CalcListenerParams(ALlistener *Listener)
-{
-    ALfloat N[3], V[3], U[3], P[3];
-
-    /* AT then UP */
-    N[0] = Listener->Forward[0];
-    N[1] = Listener->Forward[1];
-    N[2] = Listener->Forward[2];
-    aluNormalize(N);
-    V[0] = Listener->Up[0];
-    V[1] = Listener->Up[1];
-    V[2] = Listener->Up[2];
-    aluNormalize(V);
-    /* Build and normalize right-vector */
-    aluCrossproduct(N, V, U);
-    aluNormalize(U);
-
-    Listener->Params.Matrix[0][0] =  U[0];
-    Listener->Params.Matrix[0][1] =  V[0];
-    Listener->Params.Matrix[0][2] = -N[0];
-    Listener->Params.Matrix[0][3] =  0.0f;
-    Listener->Params.Matrix[1][0] =  U[1];
-    Listener->Params.Matrix[1][1] =  V[1];
-    Listener->Params.Matrix[1][2] = -N[1];
-    Listener->Params.Matrix[1][3] =  0.0f;
-    Listener->Params.Matrix[2][0] =  U[2];
-    Listener->Params.Matrix[2][1] =  V[2];
-    Listener->Params.Matrix[2][2] = -N[2];
-    Listener->Params.Matrix[2][3] =  0.0f;
-    Listener->Params.Matrix[3][0] =  0.0f;
-    Listener->Params.Matrix[3][1] =  0.0f;
-    Listener->Params.Matrix[3][2] =  0.0f;
-    Listener->Params.Matrix[3][3] =  1.0f;
-
-    P[0] = Listener->Position[0];
-    P[1] = Listener->Position[1];
-    P[2] = Listener->Position[2];
-    aluMatrixVector(P, 1.0f, Listener->Params.Matrix);
-    Listener->Params.Matrix[3][0] = -P[0];
-    Listener->Params.Matrix[3][1] = -P[1];
-    Listener->Params.Matrix[3][2] = -P[2];
-
-    Listener->Params.Velocity[0] = Listener->Velocity[0];
-    Listener->Params.Velocity[1] = Listener->Velocity[1];
-    Listener->Params.Velocity[2] = Listener->Velocity[2];
-    aluMatrixVector(Listener->Params.Velocity, 0.0f, Listener->Params.Matrix);
-}
-
-ALvoid CalcNonAttnSourceParams(ALactivesource *src, const ALCcontext *ALContext)
-{
-    static const struct ChanMap MonoMap[1] = { { FrontCenter, 0.0f } };
-    static const struct ChanMap StereoMap[2] = {
-        { FrontLeft,  DEG2RAD(-30.0f) },
-        { FrontRight, DEG2RAD( 30.0f) }
-    };
-    static const struct ChanMap StereoWideMap[2] = {
-        { FrontLeft,  DEG2RAD(-90.0f) },
-        { FrontRight, DEG2RAD( 90.0f) }
-    };
-    static const struct ChanMap RearMap[2] = {
-        { BackLeft,  DEG2RAD(-150.0f) },
-        { BackRight, DEG2RAD( 150.0f) }
-    };
-    static const struct ChanMap QuadMap[4] = {
-        { FrontLeft,  DEG2RAD( -45.0f) },
-        { FrontRight, DEG2RAD(  45.0f) },
-        { BackLeft,   DEG2RAD(-135.0f) },
-        { BackRight,  DEG2RAD( 135.0f) }
-    };
-    static const struct ChanMap X51Map[6] = {
-        { FrontLeft,   DEG2RAD( -30.0f) },
-        { FrontRight,  DEG2RAD(  30.0f) },
-        { FrontCenter, DEG2RAD(   0.0f) },
-        { LFE, 0.0f },
-        { BackLeft,    DEG2RAD(-110.0f) },
-        { BackRight,   DEG2RAD( 110.0f) }
-    };
-    static const struct ChanMap X61Map[7] = {
-        { FrontLeft,    DEG2RAD(-30.0f) },
-        { FrontRight,   DEG2RAD( 30.0f) },
-        { FrontCenter,  DEG2RAD(  0.0f) },
-        { LFE, 0.0f },
-        { BackCenter,   DEG2RAD(180.0f) },
-        { SideLeft,     DEG2RAD(-90.0f) },
-        { SideRight,    DEG2RAD( 90.0f) }
-    };
-    static const struct ChanMap X71Map[8] = {
-        { FrontLeft,   DEG2RAD( -30.0f) },
-        { FrontRight,  DEG2RAD(  30.0f) },
-        { FrontCenter, DEG2RAD(   0.0f) },
-        { LFE, 0.0f },
-        { BackLeft,    DEG2RAD(-150.0f) },
-        { BackRight,   DEG2RAD( 150.0f) },
-        { SideLeft,    DEG2RAD( -90.0f) },
-        { SideRight,   DEG2RAD(  90.0f) }
-    };
-
-    ALCdevice *Device = ALContext->Device;
-    const ALsource *ALSource = src->Source;
-    ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume;
-    ALbufferlistitem *BufferListItem;
-    enum FmtChannels Channels;
-    ALfloat DryGain, DryGainHF, DryGainLF;
-    ALfloat WetGain[MAX_SENDS];
-    ALfloat WetGainHF[MAX_SENDS];
-    ALfloat WetGainLF[MAX_SENDS];
-    ALint NumSends, Frequency;
-    const struct ChanMap *chans = NULL;
-    ALint num_channels = 0;
-    ALboolean DirectChannels;
-    ALfloat hwidth = 0.0f;
-    ALfloat Pitch;
-    ALint i, j, c;
-
-    /* Get device properties */
-    NumSends  = Device->NumAuxSends;
-    Frequency = Device->Frequency;
-
-    /* Get listener properties */
-    ListenerGain = ALContext->Listener->Gain;
-
-    /* Get source properties */
-    SourceVolume    = ALSource->Gain;
-    MinVolume       = ALSource->MinGain;
-    MaxVolume       = ALSource->MaxGain;
-    Pitch           = ALSource->Pitch;
-    DirectChannels  = ALSource->DirectChannels;
-
-    src->Direct.OutBuffer = Device->DryBuffer;
-    for(i = 0;i < NumSends;i++)
-    {
-        ALeffectslot *Slot = ALSource->Send[i].Slot;
-        if(!Slot && i == 0)
-            Slot = Device->DefaultSlot;
-        if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
-            src->Send[i].OutBuffer = NULL;
-        else
-            src->Send[i].OutBuffer = Slot->WetBuffer;
-    }
-
-    /* Calculate the stepping value */
-    Channels = FmtMono;
-    BufferListItem = ATOMIC_LOAD(&ALSource->queue);
-    while(BufferListItem != NULL)
-    {
-        ALbuffer *ALBuffer;
-        if((ALBuffer=BufferListItem->buffer) != NULL)
-        {
-            Pitch = Pitch * ALBuffer->Frequency / Frequency;
-            if(Pitch > (ALfloat)MAX_PITCH)
-                src->Step = MAX_PITCH<<FRACTIONBITS;
-            else
-            {
-                src->Step = fastf2i(Pitch*FRACTIONONE);
-                if(src->Step == 0)
-                    src->Step = 1;
-            }
-
-            Channels = ALBuffer->FmtChannels;
-            break;
-        }
-        BufferListItem = BufferListItem->next;
-    }
-
-    /* Calculate gains */
-    DryGain  = clampf(SourceVolume, MinVolume, MaxVolume);
-    DryGain  *= ALSource->Direct.Gain * ListenerGain;
-    DryGainHF = ALSource->Direct.GainHF;
-    DryGainLF = ALSource->Direct.GainLF;
-    for(i = 0;i < NumSends;i++)
-    {
-        WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume);
-        WetGain[i]  *= ALSource->Send[i].Gain * ListenerGain;
-        WetGainHF[i] = ALSource->Send[i].GainHF;
-        WetGainLF[i] = ALSource->Send[i].GainLF;
-    }
-
-    switch(Channels)
-    {
-    case FmtMono:
-        chans = MonoMap;
-        num_channels = 1;
-        break;
-
-    case FmtStereo:
-        if(!(Device->Flags&DEVICE_WIDE_STEREO))
-        {
-            /* HACK: Place the stereo channels at +/-90 degrees when using non-
-             * HRTF stereo output. This helps reduce the "monoization" caused
-             * by them panning towards the center. */
-            if(Device->FmtChans == DevFmtStereo && !Device->Hrtf)
-                chans = StereoWideMap;
-            else
-                chans = StereoMap;
-        }
-        else
-        {
-            chans = StereoWideMap;
-            hwidth = DEG2RAD(60.0f);
-        }
-        num_channels = 2;
-        break;
-
-    case FmtRear:
-        chans = RearMap;
-        num_channels = 2;
-        break;
-
-    case FmtQuad:
-        chans = QuadMap;
-        num_channels = 4;
-        break;
-
-    case FmtX51:
-        chans = X51Map;
-        num_channels = 6;
-        break;
-
-    case FmtX61:
-        chans = X61Map;
-        num_channels = 7;
-        break;
-
-    case FmtX71:
-        chans = X71Map;
-        num_channels = 8;
-        break;
-    }
-
-    if(DirectChannels != AL_FALSE)
-    {
-        for(c = 0;c < num_channels;c++)
-        {
-            MixGains *gains = src->Direct.Mix.Gains[c];
-            for(j = 0;j < MaxChannels;j++)
-                gains[j].Target = 0.0f;
-        }
-
-        for(c = 0;c < num_channels;c++)
-        {
-            MixGains *gains = src->Direct.Mix.Gains[c];
-            for(i = 0;i < (ALint)Device->NumChan;i++)
-            {
-                enum Channel chan = Device->Speaker2Chan[i];
-                if(chan == chans[c].channel)
-                {
-                    gains[chan].Target = DryGain;
-                    break;
-                }
-            }
-        }
-
-        if(!src->Direct.Moving)
-        {
-            for(i = 0;i < num_channels;i++)
-            {
-                MixGains *gains = src->Direct.Mix.Gains[i];
-                for(j = 0;j < MaxChannels;j++)
-                {
-                    gains[j].Current = gains[j].Target;
-                    gains[j].Step = 1.0f;
-                }
-            }
-            src->Direct.Counter = 0;
-            src->Direct.Moving  = AL_TRUE;
-        }
-        else
-        {
-            for(i = 0;i < num_channels;i++)
-            {
-                MixGains *gains = src->Direct.Mix.Gains[i];
-                for(j = 0;j < MaxChannels;j++)
-                {
-                    ALfloat cur = maxf(gains[j].Current, FLT_EPSILON);
-                    ALfloat trg = maxf(gains[j].Target, FLT_EPSILON);
-                    if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD)
-                        gains[j].Step = powf(trg/cur, 1.0f/64.0f);
-                    else
-                        gains[j].Step = 1.0f;
-                    gains[j].Current = cur;
-                }
-            }
-            src->Direct.Counter = 64;
-        }
-
-        src->IsHrtf = AL_FALSE;
-    }
-    else if(Device->Hrtf)
-    {
-        for(c = 0;c < num_channels;c++)
-        {
-            if(chans[c].channel == LFE)
-            {
-                /* Skip LFE */
-                src->Direct.Mix.Hrtf.Params[c].Delay[0] = 0;
-                src->Direct.Mix.Hrtf.Params[c].Delay[1] = 0;
-                for(i = 0;i < HRIR_LENGTH;i++)
-                {
-                    src->Direct.Mix.Hrtf.Params[c].Coeffs[i][0] = 0.0f;
-                    src->Direct.Mix.Hrtf.Params[c].Coeffs[i][1] = 0.0f;
-                }
-            }
-            else
-            {
-                /* Get the static HRIR coefficients and delays for this
-                 * channel. */
-                GetLerpedHrtfCoeffs(Device->Hrtf,
-                                    0.0f, chans[c].angle, 1.0f, DryGain,
-                                    src->Direct.Mix.Hrtf.Params[c].Coeffs,
-                                    src->Direct.Mix.Hrtf.Params[c].Delay);
-            }
-        }
-        src->Direct.Counter = 0;
-        src->Direct.Moving  = AL_TRUE;
-        src->Direct.Mix.Hrtf.IrSize = GetHrtfIrSize(Device->Hrtf);
-
-        src->IsHrtf = AL_TRUE;
-    }
-    else
-    {
-        for(i = 0;i < num_channels;i++)
-        {
-            MixGains *gains = src->Direct.Mix.Gains[i];
-            for(j = 0;j < MaxChannels;j++)
-                gains[j].Target = 0.0f;
-        }
-
-        DryGain *= lerp(1.0f, 1.0f/sqrtf((float)Device->NumChan), hwidth/F_PI);
-        for(c = 0;c < num_channels;c++)
-        {
-            MixGains *gains = src->Direct.Mix.Gains[c];
-            ALfloat Target[MaxChannels];
-
-            /* Special-case LFE */
-            if(chans[c].channel == LFE)
-            {
-                gains[chans[c].channel].Target = DryGain;
-                continue;
-            }
-            ComputeAngleGains(Device, chans[c].angle, hwidth, DryGain, Target);
-            for(i = 0;i < MaxChannels;i++)
-                gains[i].Target = Target[i];
-        }
-
-        if(!src->Direct.Moving)
-        {
-            for(i = 0;i < num_channels;i++)
-            {
-                MixGains *gains = src->Direct.Mix.Gains[i];
-                for(j = 0;j < MaxChannels;j++)
-                {
-                    gains[j].Current = gains[j].Target;
-                    gains[j].Step = 1.0f;
-                }
-            }
-            src->Direct.Counter = 0;
-            src->Direct.Moving  = AL_TRUE;
-        }
-        else
-        {
-            for(i = 0;i < num_channels;i++)
-            {
-                MixGains *gains = src->Direct.Mix.Gains[i];
-                for(j = 0;j < MaxChannels;j++)
-                {
-                    ALfloat trg = maxf(gains[j].Target, FLT_EPSILON);
-                    ALfloat cur = maxf(gains[j].Current, FLT_EPSILON);
-                    if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD)
-                        gains[j].Step = powf(trg/cur, 1.0f/64.0f);
-                    else
-                        gains[j].Step = 1.0f;
-                    gains[j].Current = cur;
-                }
-            }
-            src->Direct.Counter = 64;
-        }
-
-        src->IsHrtf = AL_FALSE;
-    }
-    for(i = 0;i < NumSends;i++)
-    {
-        src->Send[i].Gain.Target = WetGain[i];
-        if(!src->Send[i].Moving)
-        {
-            src->Send[i].Gain.Current = src->Send[i].Gain.Target;
-            src->Send[i].Gain.Step = 1.0f;
-            src->Send[i].Counter = 0;
-            src->Send[i].Moving  = AL_TRUE;
-        }
-        else
-        {
-            ALfloat cur = maxf(src->Send[i].Gain.Current, FLT_EPSILON);
-            ALfloat trg = maxf(src->Send[i].Gain.Target, FLT_EPSILON);
-            if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD)
-                src->Send[i].Gain.Step = powf(trg/cur, 1.0f/64.0f);
-            else
-                src->Send[i].Gain.Step = 1.0f;
-            src->Send[i].Gain.Current = cur;
-            src->Send[i].Counter = 64;
-        }
-    }
-
-    {
-        ALfloat gainhf = maxf(0.01f, DryGainHF);
-        ALfloat gainlf = maxf(0.01f, DryGainLF);
-        ALfloat hfscale = ALSource->Direct.HFReference / Frequency;
-        ALfloat lfscale = ALSource->Direct.LFReference / Frequency;
-        for(c = 0;c < num_channels;c++)
-        {
-            src->Direct.Filters[c].ActiveType = AF_None;
-            if(gainhf != 1.0f) src->Direct.Filters[c].ActiveType |= AF_LowPass;
-            if(gainlf != 1.0f) src->Direct.Filters[c].ActiveType |= AF_HighPass;
-            ALfilterState_setParams(
-                &src->Direct.Filters[c].LowPass, ALfilterType_HighShelf, gainhf,
-                hfscale, 0.0f
-            );
-            ALfilterState_setParams(
-                &src->Direct.Filters[c].HighPass, ALfilterType_LowShelf, gainlf,
-                lfscale, 0.0f
-            );
-        }
-    }
-    for(i = 0;i < NumSends;i++)
-    {
-        ALfloat gainhf = maxf(0.01f, WetGainHF[i]);
-        ALfloat gainlf = maxf(0.01f, WetGainLF[i]);
-        ALfloat hfscale = ALSource->Send[i].HFReference / Frequency;
-        ALfloat lfscale = ALSource->Send[i].LFReference / Frequency;
-        for(c = 0;c < num_channels;c++)
-        {
-            src->Send[i].Filters[c].ActiveType = AF_None;
-            if(gainhf != 1.0f) src->Send[i].Filters[c].ActiveType |= AF_LowPass;
-            if(gainlf != 1.0f) src->Send[i].Filters[c].ActiveType |= AF_HighPass;
-            ALfilterState_setParams(
-                &src->Send[i].Filters[c].LowPass, ALfilterType_HighShelf, gainhf,
-                hfscale, 0.0f
-            );
-            ALfilterState_setParams(
-                &src->Send[i].Filters[c].HighPass, ALfilterType_LowShelf, gainlf,
-                lfscale, 0.0f
-            );
-        }
-    }
-}
-
-ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext)
-{
-    ALCdevice *Device = ALContext->Device;
-    const ALsource *ALSource = src->Source;
-    ALfloat Velocity[3],Direction[3],Position[3],SourceToListener[3];
-    ALfloat InnerAngle,OuterAngle,Angle,Distance,ClampedDist;
-    ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff;
-    ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain;
-    ALfloat DopplerFactor, SpeedOfSound;
-    ALfloat AirAbsorptionFactor;
-    ALfloat RoomAirAbsorption[MAX_SENDS];
-    ALbufferlistitem *BufferListItem;
-    ALfloat Attenuation;
-    ALfloat RoomAttenuation[MAX_SENDS];
-    ALfloat MetersPerUnit;
-    ALfloat RoomRolloffBase;
-    ALfloat RoomRolloff[MAX_SENDS];
-    ALfloat DecayDistance[MAX_SENDS];
-    ALfloat DryGain;
-    ALfloat DryGainHF;
-    ALfloat DryGainLF;
-    ALboolean DryGainHFAuto;
-    ALfloat WetGain[MAX_SENDS];
-    ALfloat WetGainHF[MAX_SENDS];
-    ALfloat WetGainLF[MAX_SENDS];
-    ALboolean WetGainAuto;
-    ALboolean WetGainHFAuto;
-    ALfloat Pitch;
-    ALuint Frequency;
-    ALint NumSends;
-    ALint i, j;
-
-    DryGainHF = 1.0f;
-    DryGainLF = 1.0f;
-    for(i = 0;i < MAX_SENDS;i++)
-    {
-        WetGainHF[i] = 1.0f;
-        WetGainLF[i] = 1.0f;
-    }
-
-    /* Get context/device properties */
-    DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor;
-    SpeedOfSound  = ALContext->SpeedOfSound * ALContext->DopplerVelocity;
-    NumSends      = Device->NumAuxSends;
-    Frequency     = Device->Frequency;
-
-    /* Get listener properties */
-    ListenerGain  = ALContext->Listener->Gain;
-    MetersPerUnit = ALContext->Listener->MetersPerUnit;
-
-    /* Get source properties */
-    SourceVolume   = ALSource->Gain;
-    MinVolume      = ALSource->MinGain;
-    MaxVolume      = ALSource->MaxGain;
-    Pitch          = ALSource->Pitch;
-    Position[0]    = ALSource->Position[0];
-    Position[1]    = ALSource->Position[1];
-    Position[2]    = ALSource->Position[2];
-    Direction[0]   = ALSource->Orientation[0];
-    Direction[1]   = ALSource->Orientation[1];
-    Direction[2]   = ALSource->Orientation[2];
-    Velocity[0]    = ALSource->Velocity[0];
-    Velocity[1]    = ALSource->Velocity[1];
-    Velocity[2]    = ALSource->Velocity[2];
-    MinDist        = ALSource->RefDistance;
-    MaxDist        = ALSource->MaxDistance;
-    Rolloff        = ALSource->RollOffFactor;
-    InnerAngle     = ALSource->InnerAngle;
-    OuterAngle     = ALSource->OuterAngle;
-    AirAbsorptionFactor = ALSource->AirAbsorptionFactor;
-    DryGainHFAuto   = ALSource->DryGainHFAuto;
-    WetGainAuto     = ALSource->WetGainAuto;
-    WetGainHFAuto   = ALSource->WetGainHFAuto;
-    RoomRolloffBase = ALSource->RoomRolloffFactor;
-
-    src->Direct.OutBuffer = Device->DryBuffer;
-    for(i = 0;i < NumSends;i++)
-    {
-        ALeffectslot *Slot = ALSource->Send[i].Slot;
-
-        if(!Slot && i == 0)
-            Slot = Device->DefaultSlot;
-        if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
-        {
-            Slot = NULL;
-            RoomRolloff[i] = 0.0f;
-            DecayDistance[i] = 0.0f;
-            RoomAirAbsorption[i] = 1.0f;
-        }
-        else if(Slot->AuxSendAuto)
-        {
-            RoomRolloff[i] = RoomRolloffBase;
-            if(IsReverbEffect(Slot->EffectType))
-            {
-                RoomRolloff[i] += Slot->EffectProps.Reverb.RoomRolloffFactor;
-                DecayDistance[i] = Slot->EffectProps.Reverb.DecayTime *
-                                   SPEEDOFSOUNDMETRESPERSEC;
-                RoomAirAbsorption[i] = Slot->EffectProps.Reverb.AirAbsorptionGainHF;
-            }
-            else
-            {
-                DecayDistance[i] = 0.0f;
-                RoomAirAbsorption[i] = 1.0f;
-            }
-        }
-        else
-        {
-            /* If the slot's auxiliary send auto is off, the data sent to the
-             * effect slot is the same as the dry path, sans filter effects */
-            RoomRolloff[i] = Rolloff;
-            DecayDistance[i] = 0.0f;
-            RoomAirAbsorption[i] = AIRABSORBGAINHF;
-        }
-
-        if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
-            src->Send[i].OutBuffer = NULL;
-        else
-            src->Send[i].OutBuffer = Slot->WetBuffer;
-    }
-
-    /* Transform source to listener space (convert to head relative) */
-    if(ALSource->HeadRelative == AL_FALSE)
-    {
-        ALfloat (*restrict Matrix)[4] = ALContext->Listener->Params.Matrix;
-        /* Transform source vectors */
-        aluMatrixVector(Position, 1.0f, Matrix);
-        aluMatrixVector(Direction, 0.0f, Matrix);
-        aluMatrixVector(Velocity, 0.0f, Matrix);
-    }
-    else
-    {
-        const ALfloat *ListenerVel = ALContext->Listener->Params.Velocity;
-        /* Offset the source velocity to be relative of the listener velocity */
-        Velocity[0] += ListenerVel[0];
-        Velocity[1] += ListenerVel[1];
-        Velocity[2] += ListenerVel[2];
-    }
-
-    SourceToListener[0] = -Position[0];
-    SourceToListener[1] = -Position[1];
-    SourceToListener[2] = -Position[2];
-    aluNormalize(SourceToListener);
-    aluNormalize(Direction);
-
-    /* Calculate distance attenuation */
-    Distance = sqrtf(aluDotproduct(Position, Position));
-    ClampedDist = Distance;
-
-    Attenuation = 1.0f;
-    for(i = 0;i < NumSends;i++)
-        RoomAttenuation[i] = 1.0f;
-    switch(ALContext->SourceDistanceModel ? ALSource->DistanceModel :
-                                            ALContext->DistanceModel)
-    {
-        case InverseDistanceClamped:
-            ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
-            if(MaxDist < MinDist)
-                break;
-            /*fall-through*/
-        case InverseDistance:
-            if(MinDist > 0.0f)
-            {
-                if((MinDist + (Rolloff * (ClampedDist - MinDist))) > 0.0f)
-                    Attenuation = MinDist / (MinDist + (Rolloff * (ClampedDist - MinDist)));
-                for(i = 0;i < NumSends;i++)
-                {
-                    if((MinDist + (RoomRolloff[i] * (ClampedDist - MinDist))) > 0.0f)
-                        RoomAttenuation[i] = MinDist / (MinDist + (RoomRolloff[i] * (ClampedDist - MinDist)));
-                }
-            }
-            break;
-
-        case LinearDistanceClamped:
-            ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
-            if(MaxDist < MinDist)
-                break;
-            /*fall-through*/
-        case LinearDistance:
-            if(MaxDist != MinDist)
-            {
-                Attenuation = 1.0f - (Rolloff*(ClampedDist-MinDist)/(MaxDist - MinDist));
-                Attenuation = maxf(Attenuation, 0.0f);
-                for(i = 0;i < NumSends;i++)
-                {
-                    RoomAttenuation[i] = 1.0f - (RoomRolloff[i]*(ClampedDist-MinDist)/(MaxDist - MinDist));
-                    RoomAttenuation[i] = maxf(RoomAttenuation[i], 0.0f);
-                }
-            }
-            break;
-
-        case ExponentDistanceClamped:
-            ClampedDist = clampf(ClampedDist, MinDist, MaxDist);
-            if(MaxDist < MinDist)
-                break;
-            /*fall-through*/
-        case ExponentDistance:
-            if(ClampedDist > 0.0f && MinDist > 0.0f)
-            {
-                Attenuation = powf(ClampedDist/MinDist, -Rolloff);
-                for(i = 0;i < NumSends;i++)
-                    RoomAttenuation[i] = powf(ClampedDist/MinDist, -RoomRolloff[i]);
-            }
-            break;
-
-        case DisableDistance:
-            ClampedDist = MinDist;
-            break;
-    }
-
-    /* Source Gain + Attenuation */
-    DryGain = SourceVolume * Attenuation;
-    for(i = 0;i < NumSends;i++)
-        WetGain[i] = SourceVolume * RoomAttenuation[i];
-
-    /* Distance-based air absorption */
-    if(AirAbsorptionFactor > 0.0f && ClampedDist > MinDist)
-    {
-        ALfloat meters = maxf(ClampedDist-MinDist, 0.0f) * MetersPerUnit;
-        DryGainHF *= powf(AIRABSORBGAINHF, AirAbsorptionFactor*meters);
-        for(i = 0;i < NumSends;i++)
-            WetGainHF[i] *= powf(RoomAirAbsorption[i], AirAbsorptionFactor*meters);
-    }
-
-    if(WetGainAuto)
-    {
-        ALfloat ApparentDist = 1.0f/maxf(Attenuation, 0.00001f) - 1.0f;
-
-        /* Apply a decay-time transformation to the wet path, based on the
-         * attenuation of the dry path.
-         *
-         * Using the apparent distance, based on the distance attenuation, the
-         * initial decay of the reverb effect is calculated and applied to the
-         * wet path.
-         */
-        for(i = 0;i < NumSends;i++)
-        {
-            if(DecayDistance[i] > 0.0f)
-                WetGain[i] *= powf(0.001f/*-60dB*/, ApparentDist/DecayDistance[i]);
-        }
-    }
-
-    /* Calculate directional soundcones */
-    Angle = RAD2DEG(acosf(aluDotproduct(Direction,SourceToListener)) * ConeScale) * 2.0f;
-    if(Angle > InnerAngle && Angle <= OuterAngle)
-    {
-        ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle);
-        ConeVolume = lerp(1.0f, ALSource->OuterGain, scale);
-        ConeHF = lerp(1.0f, ALSource->OuterGainHF, scale);
-    }
-    else if(Angle > OuterAngle)
-    {
-        ConeVolume = ALSource->OuterGain;
-        ConeHF = ALSource->OuterGainHF;
-    }
-    else
-    {
-        ConeVolume = 1.0f;
-        ConeHF = 1.0f;
-    }
-
-    DryGain *= ConeVolume;
-    if(WetGainAuto)
-    {
-        for(i = 0;i < NumSends;i++)
-            WetGain[i] *= ConeVolume;
-    }
-    if(DryGainHFAuto)
-        DryGainHF *= ConeHF;
-    if(WetGainHFAuto)
-    {
-        for(i = 0;i < NumSends;i++)
-            WetGainHF[i] *= ConeHF;
-    }
-
-    /* Clamp to Min/Max Gain */
-    DryGain = clampf(DryGain, MinVolume, MaxVolume);
-    for(i = 0;i < NumSends;i++)
-        WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume);
-
-    /* Apply gain and frequency filters */
-    DryGain   *= ALSource->Direct.Gain * ListenerGain;
-    DryGainHF *= ALSource->Direct.GainHF;
-    DryGainLF *= ALSource->Direct.GainLF;
-    for(i = 0;i < NumSends;i++)
-    {
-        WetGain[i]   *= ALSource->Send[i].Gain * ListenerGain;
-        WetGainHF[i] *= ALSource->Send[i].GainHF;
-        WetGainLF[i] *= ALSource->Send[i].GainLF;
-    }
-
-    /* Calculate velocity-based doppler effect */
-    if(DopplerFactor > 0.0f)
-    {
-        const ALfloat *ListenerVel = ALContext->Listener->Params.Velocity;
-        ALfloat VSS, VLS;
-
-        if(SpeedOfSound < 1.0f)
-        {
-            DopplerFactor *= 1.0f/SpeedOfSound;
-            SpeedOfSound   = 1.0f;
-        }
-
-        VSS = aluDotproduct(Velocity, SourceToListener) * DopplerFactor;
-        VLS = aluDotproduct(ListenerVel, SourceToListener) * DopplerFactor;
-
-        Pitch *= clampf(SpeedOfSound-VLS, 1.0f, SpeedOfSound*2.0f - 1.0f) /
-                 clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f);
-    }
-
-    BufferListItem = ATOMIC_LOAD(&ALSource->queue);
-    while(BufferListItem != NULL)
-    {
-        ALbuffer *ALBuffer;
-        if((ALBuffer=BufferListItem->buffer) != NULL)
-        {
-            /* Calculate fixed-point stepping value, based on the pitch, buffer
-             * frequency, and output frequency. */
-            Pitch = Pitch * ALBuffer->Frequency / Frequency;
-            if(Pitch > (ALfloat)MAX_PITCH)
-                src->Step = MAX_PITCH<<FRACTIONBITS;
-            else
-            {
-                src->Step = fastf2i(Pitch*FRACTIONONE);
-                if(src->Step == 0)
-                    src->Step = 1;
-            }
-
-            break;
-        }
-        BufferListItem = BufferListItem->next;
-    }
-
-    if(Device->Hrtf)
-    {
-        /* Use a binaural HRTF algorithm for stereo headphone playback */
-        ALfloat delta, ev = 0.0f, az = 0.0f;
-        ALfloat radius = ALSource->Radius;
-        ALfloat dirfact = 1.0f;
-
-        if(Distance > FLT_EPSILON)
-        {
-            ALfloat invlen = 1.0f/Distance;
-            Position[0] *= invlen;
-            Position[1] *= invlen;
-            Position[2] *= invlen;
-
-            /* Calculate elevation and azimuth only when the source is not at
-             * the listener. This prevents +0 and -0 Z from producing
-             * inconsistent panning. Also, clamp Y in case FP precision errors
-             * cause it to land outside of -1..+1. */
-            ev = asinf(clampf(Position[1], -1.0f, 1.0f));
-            az = atan2f(Position[0], -Position[2]*ZScale);
-        }
-        if(radius > Distance)
-            dirfact *= Distance / radius;
-
-        /* Check to see if the HRIR is already moving. */
-        if(src->Direct.Moving)
-        {
-            /* Calculate the normalized HRTF transition factor (delta). */
-            delta = CalcHrtfDelta(src->Direct.Mix.Hrtf.Gain, DryGain,
-                                  src->Direct.Mix.Hrtf.Dir, Position);
-            /* If the delta is large enough, get the moving HRIR target
-             * coefficients, target delays, steppping values, and counter. */
-            if(delta > 0.001f)
-            {
-                ALuint counter = GetMovingHrtfCoeffs(Device->Hrtf,
-                    ev, az, dirfact, DryGain, delta, src->Direct.Counter,
-                    src->Direct.Mix.Hrtf.Params[0].Coeffs, src->Direct.Mix.Hrtf.Params[0].Delay,
-                    src->Direct.Mix.Hrtf.Params[0].CoeffStep, src->Direct.Mix.Hrtf.Params[0].DelayStep
-                );
-                src->Direct.Counter = counter;
-                src->Direct.Mix.Hrtf.Gain = DryGain;
-                src->Direct.Mix.Hrtf.Dir[0] = Position[0];
-                src->Direct.Mix.Hrtf.Dir[1] = Position[1];
-                src->Direct.Mix.Hrtf.Dir[2] = Position[2];
-            }
-        }
-        else
-        {
-            /* Get the initial (static) HRIR coefficients and delays. */
-            GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, dirfact, DryGain,
-                                src->Direct.Mix.Hrtf.Params[0].Coeffs,
-                                src->Direct.Mix.Hrtf.Params[0].Delay);
-            src->Direct.Counter = 0;
-            src->Direct.Moving  = AL_TRUE;
-            src->Direct.Mix.Hrtf.Gain = DryGain;
-            src->Direct.Mix.Hrtf.Dir[0] = Position[0];
-            src->Direct.Mix.Hrtf.Dir[1] = Position[1];
-            src->Direct.Mix.Hrtf.Dir[2] = Position[2];
-        }
-        src->Direct.Mix.Hrtf.IrSize = GetHrtfIrSize(Device->Hrtf);
-
-        src->IsHrtf = AL_TRUE;
-    }
-    else
-    {
-        MixGains *gains = src->Direct.Mix.Gains[0];
-        ALfloat DirGain = 0.0f;
-        ALfloat AmbientGain;
-
-        for(j = 0;j < MaxChannels;j++)
-            gains[j].Target = 0.0f;
-
-        /* Normalize the length, and compute panned gains. */
-        if(Distance > FLT_EPSILON)
-        {
-            ALfloat radius = ALSource->Radius;
-            ALfloat Target[MaxChannels];
-            ALfloat invlen = 1.0f/maxf(Distance, radius);
-            Position[0] *= invlen;
-            Position[1] *= invlen;
-            Position[2] *= invlen;
-
-            DirGain = sqrtf(Position[0]*Position[0] + Position[2]*Position[2]);
-            ComputeAngleGains(Device, atan2f(Position[0], -Position[2]*ZScale), 0.0f,
-                              DryGain*DirGain, Target);
-            for(j = 0;j < MaxChannels;j++)
-                gains[j].Target = Target[j];
-        }
-
-        /* Adjustment for vertical offsets. Not the greatest, but simple
-         * enough. */
-        AmbientGain = DryGain * sqrtf(1.0f/Device->NumChan) * (1.0f-DirGain);
-        for(i = 0;i < (ALint)Device->NumChan;i++)
-        {
-            enum Channel chan = Device->Speaker2Chan[i];
-            gains[chan].Target = maxf(gains[chan].Target, AmbientGain);
-        }
-
-        if(!src->Direct.Moving)
-        {
-            for(j = 0;j < MaxChannels;j++)
-            {
-                gains[j].Current = gains[j].Target;
-                gains[j].Step = 1.0f;
-            }
-            src->Direct.Counter = 0;
-            src->Direct.Moving  = AL_TRUE;
-        }
-        else
-        {
-            for(j = 0;j < MaxChannels;j++)
-            {
-                ALfloat cur = maxf(gains[j].Current, FLT_EPSILON);
-                ALfloat trg = maxf(gains[j].Target, FLT_EPSILON);
-                if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD)
-                    gains[j].Step = powf(trg/cur, 1.0f/64.0f);
-                else
-                    gains[j].Step = 1.0f;
-                gains[j].Current = cur;
-            }
-            src->Direct.Counter = 64;
-        }
-
-        src->IsHrtf = AL_FALSE;
-    }
-    for(i = 0;i < NumSends;i++)
-    {
-        src->Send[i].Gain.Target = WetGain[i];
-        if(!src->Send[i].Moving)
-        {
-            src->Send[i].Gain.Current = src->Send[i].Gain.Target;
-            src->Send[i].Gain.Step = 1.0f;
-            src->Send[i].Counter = 0;
-            src->Send[i].Moving  = AL_TRUE;
-        }
-        else
-        {
-            ALfloat cur = maxf(src->Send[i].Gain.Current, FLT_EPSILON);
-            ALfloat trg = maxf(src->Send[i].Gain.Target, FLT_EPSILON);
-            if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD)
-                src->Send[i].Gain.Step = powf(trg/cur, 1.0f/64.0f);
-            else
-                src->Send[i].Gain.Step = 1.0f;
-            src->Send[i].Gain.Current = cur;
-            src->Send[i].Counter = 64;
-        }
-    }
-
-    {
-        ALfloat gainhf = maxf(0.01f, DryGainHF);
-        ALfloat gainlf = maxf(0.01f, DryGainLF);
-        ALfloat hfscale = ALSource->Direct.HFReference / Frequency;
-        ALfloat lfscale = ALSource->Direct.LFReference / Frequency;
-        src->Direct.Filters[0].ActiveType = AF_None;
-        if(gainhf != 1.0f) src->Direct.Filters[0].ActiveType |= AF_LowPass;
-        if(gainlf != 1.0f) src->Direct.Filters[0].ActiveType |= AF_HighPass;
-        ALfilterState_setParams(
-            &src->Direct.Filters[0].LowPass, ALfilterType_HighShelf, gainhf,
-            hfscale, 0.0f
-        );
-        ALfilterState_setParams(
-            &src->Direct.Filters[0].HighPass, ALfilterType_LowShelf, gainlf,
-            lfscale, 0.0f
-        );
-    }
-    for(i = 0;i < NumSends;i++)
-    {
-        ALfloat gainhf = maxf(0.01f, WetGainHF[i]);
-        ALfloat gainlf = maxf(0.01f, WetGainLF[i]);
-        ALfloat hfscale = ALSource->Send[i].HFReference / Frequency;
-        ALfloat lfscale = ALSource->Send[i].LFReference / Frequency;
-        src->Send[i].Filters[0].ActiveType = AF_None;
-        if(gainhf != 1.0f) src->Send[i].Filters[0].ActiveType |= AF_LowPass;
-        if(gainlf != 1.0f) src->Send[i].Filters[0].ActiveType |= AF_HighPass;
-        ALfilterState_setParams(
-            &src->Send[i].Filters[0].LowPass, ALfilterType_HighShelf, gainhf,
-            hfscale, 0.0f
-        );
-        ALfilterState_setParams(
-            &src->Send[i].Filters[0].HighPass, ALfilterType_LowShelf, gainlf,
-            lfscale, 0.0f
-        );
-    }
-}
-
-
-static inline ALint aluF2I25(ALfloat val)
-{
-    /* Clamp the value between -1 and +1. This handles that with only a single branch. */
-    if(fabsf(val) > 1.0f)
-        val = (ALfloat)((0.0f < val) - (val < 0.0f));
-    /* Convert to a signed integer, between -16777215 and +16777215. */
-    return fastf2i(val*16777215.0f);
-}
-
-static inline ALfloat aluF2F(ALfloat val)
-{ return val; }
-static inline ALint aluF2I(ALfloat val)
-{ return aluF2I25(val)<<7; }
-static inline ALuint aluF2UI(ALfloat val)
-{ return aluF2I(val)+2147483648u; }
-static inline ALshort aluF2S(ALfloat val)
-{ return aluF2I25(val)>>9; }
-static inline ALushort aluF2US(ALfloat val)
-{ return aluF2S(val)+32768; }
-static inline ALbyte aluF2B(ALfloat val)
-{ return aluF2I25(val)>>17; }
-static inline ALubyte aluF2UB(ALfloat val)
-{ return aluF2B(val)+128; }
-
-#define DECL_TEMPLATE(T, func)                                                \
-static void Write_##T(ALCdevice *device, ALvoid **buffer, ALuint SamplesToDo) \
-{                                                                             \
-    ALfloat (*restrict DryBuffer)[BUFFERSIZE] = device->DryBuffer;            \
-    const ALuint numchans = ChannelsFromDevFmt(device->FmtChans);             \
-    const ALuint *offsets = device->ChannelOffsets;                           \
-    ALuint i, j;                                                              \
-                                                                              \
-    for(j = 0;j < MaxChannels;j++)                                            \
-    {                                                                         \
-        T *restrict out;                                                      \
-                                                                              \
-        if(offsets[j] == INVALID_OFFSET)                                      \
-            continue;                                                         \
-                                                                              \
-        out = (T*)(*buffer) + offsets[j];                                     \
-        for(i = 0;i < SamplesToDo;i++)                                        \
-            out[i*numchans] = func(DryBuffer[j][i]);                          \
-    }                                                                         \
-    *buffer = (char*)(*buffer) + SamplesToDo*numchans*sizeof(T);              \
-}
-
-DECL_TEMPLATE(ALfloat, aluF2F)
-DECL_TEMPLATE(ALuint, aluF2UI)
-DECL_TEMPLATE(ALint, aluF2I)
-DECL_TEMPLATE(ALushort, aluF2US)
-DECL_TEMPLATE(ALshort, aluF2S)
-DECL_TEMPLATE(ALubyte, aluF2UB)
-DECL_TEMPLATE(ALbyte, aluF2B)
-
-#undef DECL_TEMPLATE
-
-
-ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
-{
-    ALuint SamplesToDo;
-    ALeffectslot **slot, **slot_end;
-    ALactivesource **src, **src_end;
-    ALCcontext *ctx;
-    FPUCtl oldMode;
-    ALuint i, c;
-
-    SetMixerFPUMode(&oldMode);
-
-    while(size > 0)
-    {
-        IncrementRef(&device->MixCount);
-
-        SamplesToDo = minu(size, BUFFERSIZE);
-        for(c = 0;c < MaxChannels;c++)
-            memset(device->DryBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
-
-        ALCdevice_Lock(device);
-        V(device->Synth,process)(SamplesToDo, device->DryBuffer);
-
-        ctx = ATOMIC_LOAD(&device->ContextList);
-        while(ctx)
-        {
-            ALenum DeferUpdates = ctx->DeferUpdates;
-            ALenum UpdateSources = AL_FALSE;
-
-            if(!DeferUpdates)
-                UpdateSources = ATOMIC_EXCHANGE(ALenum, &ctx->UpdateSources, AL_FALSE);
-
-            if(UpdateSources)
-                CalcListenerParams(ctx->Listener);
-
-            /* source processing */
-            src = ctx->ActiveSources;
-            src_end = src + ctx->ActiveSourceCount;
-            while(src != src_end)
-            {
-                ALsource *source = (*src)->Source;
-
-                if(source->state != AL_PLAYING && source->state != AL_PAUSED)
-                {
-                    ALactivesource *temp = *(--src_end);
-                    *src_end = *src;
-                    *src = temp;
-                    --(ctx->ActiveSourceCount);
-                    continue;
-                }
-
-                if(!DeferUpdates && (ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) ||
-                                     UpdateSources))
-                    (*src)->Update(*src, ctx);
-
-                if(source->state != AL_PAUSED)
-                    MixSource(*src, device, SamplesToDo);
-                src++;
-            }
-
-            /* effect slot processing */
-            slot = VECTOR_ITER_BEGIN(ctx->ActiveAuxSlots);
-            slot_end = VECTOR_ITER_END(ctx->ActiveAuxSlots);
-            while(slot != slot_end)
-            {
-                if(!DeferUpdates && ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
-                    V((*slot)->EffectState,update)(device, *slot);
-
-                V((*slot)->EffectState,process)(SamplesToDo, (*slot)->WetBuffer[0],
-                                                device->DryBuffer);
-
-                for(i = 0;i < SamplesToDo;i++)
-                    (*slot)->WetBuffer[0][i] = 0.0f;
-
-                slot++;
-            }
-
-            ctx = ctx->next;
-        }
-
-        slot = &device->DefaultSlot;
-        if(*slot != NULL)
-        {
-            if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE))
-                V((*slot)->EffectState,update)(device, *slot);
-
-            V((*slot)->EffectState,process)(SamplesToDo, (*slot)->WetBuffer[0],
-                                            device->DryBuffer);
-
-            for(i = 0;i < SamplesToDo;i++)
-                (*slot)->WetBuffer[0][i] = 0.0f;
-        }
-
-        /* Increment the clock time. Every second's worth of samples is
-         * converted and added to clock base so that large sample counts don't
-         * overflow during conversion. This also guarantees an exact, stable
-         * conversion. */
-        device->SamplesDone += SamplesToDo;
-        device->ClockBase += (device->SamplesDone/device->Frequency) * DEVICE_CLOCK_RES;
-        device->SamplesDone %= device->Frequency;
-        ALCdevice_Unlock(device);
-
-        if(device->Bs2b)
-        {
-            /* Apply binaural/crossfeed filter */
-            for(i = 0;i < SamplesToDo;i++)
-            {
-                float samples[2];
-                samples[0] = device->DryBuffer[FrontLeft][i];
-                samples[1] = device->DryBuffer[FrontRight][i];
-                bs2b_cross_feed(device->Bs2b, samples);
-                device->DryBuffer[FrontLeft][i] = samples[0];
-                device->DryBuffer[FrontRight][i] = samples[1];
-            }
-        }
-
-        if(buffer)
-        {
-            switch(device->FmtType)
-            {
-                case DevFmtByte:
-                    Write_ALbyte(device, &buffer, SamplesToDo);
-                    break;
-                case DevFmtUByte:
-                    Write_ALubyte(device, &buffer, SamplesToDo);
-                    break;
-                case DevFmtShort:
-                    Write_ALshort(device, &buffer, SamplesToDo);
-                    break;
-                case DevFmtUShort:
-                    Write_ALushort(device, &buffer, SamplesToDo);
-                    break;
-                case DevFmtInt:
-                    Write_ALint(device, &buffer, SamplesToDo);
-                    break;
-                case DevFmtUInt:
-                    Write_ALuint(device, &buffer, SamplesToDo);
-                    break;
-                case DevFmtFloat:
-                    Write_ALfloat(device, &buffer, SamplesToDo);
-                    break;
-            }
-        }
-
-        size -= SamplesToDo;
-        IncrementRef(&device->MixCount);
-    }
-
-    RestoreFPUMode(&oldMode);
-}
-
-
-ALvoid aluHandleDisconnect(ALCdevice *device)
-{
-    ALCcontext *Context;
-
-    device->Connected = ALC_FALSE;
-
-    Context = ATOMIC_LOAD(&device->ContextList);
-    while(Context)
-    {
-        ALactivesource **src, **src_end;
-
-        src = Context->ActiveSources;
-        src_end = src + Context->ActiveSourceCount;
-        while(src != src_end)
-        {
-            ALsource *source = (*src)->Source;
-            if(source->state == AL_PLAYING)
-            {
-                source->state = AL_STOPPED;
-                ATOMIC_STORE(&source->current_buffer, NULL);
-                source->position = 0;
-                source->position_fraction = 0;
-            }
-            src++;
-        }
-        Context->ActiveSourceCount = 0;
-
-        Context = Context->next;
-    }
-}

+ 0 - 129
love/src/jni/openal-soft-1.17.0/Alc/alcRing.c

@@ -1,129 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "alMain.h"
-#include "threads.h"
-#include "compat.h"
-
-
-struct RingBuffer {
-    ALubyte *mem;
-
-    ALsizei frame_size;
-    ALsizei length;
-    ALint read_pos;
-    ALint write_pos;
-
-    almtx_t mtx;
-};
-
-
-RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length)
-{
-    RingBuffer *ring = calloc(1, sizeof(*ring) + ((length+1) * frame_size));
-    if(ring)
-    {
-        ring->mem = (ALubyte*)(ring+1);
-
-        ring->frame_size = frame_size;
-        ring->length = length+1;
-        ring->read_pos = 0;
-        ring->write_pos = 0;
-
-        almtx_init(&ring->mtx, almtx_plain);
-    }
-    return ring;
-}
-
-void DestroyRingBuffer(RingBuffer *ring)
-{
-    if(ring)
-    {
-        almtx_destroy(&ring->mtx);
-        free(ring);
-    }
-}
-
-ALsizei RingBufferSize(RingBuffer *ring)
-{
-    ALsizei s;
-
-    almtx_lock(&ring->mtx);
-    s = (ring->write_pos-ring->read_pos+ring->length) % ring->length;
-    almtx_unlock(&ring->mtx);
-
-    return s;
-}
-
-void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len)
-{
-    int remain;
-
-    almtx_lock(&ring->mtx);
-
-    remain = (ring->read_pos-ring->write_pos-1+ring->length) % ring->length;
-    if(remain < len) len = remain;
-
-    if(len > 0)
-    {
-        remain = ring->length - ring->write_pos;
-        if(remain < len)
-        {
-            memcpy(ring->mem+(ring->write_pos*ring->frame_size), data,
-                   remain*ring->frame_size);
-            memcpy(ring->mem, data+(remain*ring->frame_size),
-                   (len-remain)*ring->frame_size);
-        }
-        else
-            memcpy(ring->mem+(ring->write_pos*ring->frame_size), data,
-                   len*ring->frame_size);
-
-        ring->write_pos += len;
-        ring->write_pos %= ring->length;
-    }
-
-    almtx_unlock(&ring->mtx);
-}
-
-void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len)
-{
-    int remain;
-
-    almtx_lock(&ring->mtx);
-
-    remain = ring->length - ring->read_pos;
-    if(remain < len)
-    {
-        memcpy(data, ring->mem+(ring->read_pos*ring->frame_size), remain*ring->frame_size);
-        memcpy(data+(remain*ring->frame_size), ring->mem, (len-remain)*ring->frame_size);
-    }
-    else
-        memcpy(data, ring->mem+(ring->read_pos*ring->frame_size), len*ring->frame_size);
-
-    ring->read_pos += len;
-    ring->read_pos %= ring->length;
-
-    almtx_unlock(&ring->mtx);
-}

+ 0 - 45
love/src/jni/openal-soft-1.17.0/Alc/alstring.h

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

+ 0 - 232
love/src/jni/openal-soft-1.17.0/Alc/backends/base.c

@@ -1,232 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "alMain.h"
-
-#include "backends/base.h"
-
-
-/* Base ALCbackend method implementations. */
-void ALCbackend_Construct(ALCbackend *self, ALCdevice *device)
-{
-    int ret;
-    self->mDevice = device;
-    ret = almtx_init(&self->mMutex, almtx_recursive);
-    assert(ret == althrd_success);
-}
-
-void ALCbackend_Destruct(ALCbackend *self)
-{
-    almtx_destroy(&self->mMutex);
-}
-
-ALCboolean ALCbackend_reset(ALCbackend* UNUSED(self))
-{
-    return ALC_FALSE;
-}
-
-ALCenum ALCbackend_captureSamples(ALCbackend* UNUSED(self), void* UNUSED(buffer), ALCuint UNUSED(samples))
-{
-    return ALC_INVALID_DEVICE;
-}
-
-ALCuint ALCbackend_availableSamples(ALCbackend* UNUSED(self))
-{
-    return 0;
-}
-
-ALint64 ALCbackend_getLatency(ALCbackend* UNUSED(self))
-{
-    return 0;
-}
-
-void ALCbackend_lock(ALCbackend *self)
-{
-    int ret = almtx_lock(&self->mMutex);
-    assert(ret == althrd_success);
-}
-
-void ALCbackend_unlock(ALCbackend *self)
-{
-    int ret = almtx_unlock(&self->mMutex);
-    assert(ret == althrd_success);
-}
-
-
-/* Base ALCbackendFactory method implementations. */
-void ALCbackendFactory_deinit(ALCbackendFactory* UNUSED(self))
-{
-}
-
-
-/* Wrappers to use an old-style backend with the new interface. */
-typedef struct PlaybackWrapper {
-    DERIVE_FROM_TYPE(ALCbackend);
-
-    const BackendFuncs *Funcs;
-} PlaybackWrapper;
-
-static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs);
-static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct)
-static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name);
-static void PlaybackWrapper_close(PlaybackWrapper *self);
-static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self);
-static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self);
-static void PlaybackWrapper_stop(PlaybackWrapper *self);
-static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
-static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples)
-static ALint64 PlaybackWrapper_getLatency(PlaybackWrapper *self);
-static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock)
-static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock)
-DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper)
-DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper);
-
-static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs)
-{
-    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
-    SET_VTABLE2(PlaybackWrapper, ALCbackend, self);
-
-    self->Funcs = funcs;
-}
-
-static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->OpenPlayback(device, name);
-}
-
-static void PlaybackWrapper_close(PlaybackWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    self->Funcs->ClosePlayback(device);
-}
-
-static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->ResetPlayback(device);
-}
-
-static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->StartPlayback(device);
-}
-
-static void PlaybackWrapper_stop(PlaybackWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    self->Funcs->StopPlayback(device);
-}
-
-static ALint64 PlaybackWrapper_getLatency(PlaybackWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->GetLatency(device);
-}
-
-
-typedef struct CaptureWrapper {
-    DERIVE_FROM_TYPE(ALCbackend);
-
-    const BackendFuncs *Funcs;
-} CaptureWrapper;
-
-static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs);
-static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct)
-static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name);
-static void CaptureWrapper_close(CaptureWrapper *self);
-static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ALCboolean, reset)
-static ALCboolean CaptureWrapper_start(CaptureWrapper *self);
-static void CaptureWrapper_stop(CaptureWrapper *self);
-static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples);
-static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self);
-static ALint64 CaptureWrapper_getLatency(CaptureWrapper *self);
-static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock)
-static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock)
-DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper)
-DEFINE_ALCBACKEND_VTABLE(CaptureWrapper);
-
-
-static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs)
-{
-    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
-    SET_VTABLE2(CaptureWrapper, ALCbackend, self);
-
-    self->Funcs = funcs;
-}
-
-static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->OpenCapture(device, name);
-}
-
-static void CaptureWrapper_close(CaptureWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    self->Funcs->CloseCapture(device);
-}
-
-static ALCboolean CaptureWrapper_start(CaptureWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    self->Funcs->StartCapture(device);
-    return ALC_TRUE;
-}
-
-static void CaptureWrapper_stop(CaptureWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    self->Funcs->StopCapture(device);
-}
-
-static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->CaptureSamples(device, buffer, samples);
-}
-
-static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->AvailableSamples(device);
-}
-
-static ALint64 CaptureWrapper_getLatency(CaptureWrapper *self)
-{
-    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return self->Funcs->GetLatency(device);
-}
-
-
-ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type)
-{
-    if(type == ALCbackend_Playback)
-    {
-        PlaybackWrapper *backend;
-
-        backend = PlaybackWrapper_New(sizeof(*backend));
-        if(!backend) return NULL;
-
-        PlaybackWrapper_Construct(backend, device, funcs);
-
-        return STATIC_CAST(ALCbackend, backend);
-    }
-
-    if(type == ALCbackend_Capture)
-    {
-        CaptureWrapper *backend;
-
-        backend = CaptureWrapper_New(sizeof(*backend));
-        if(!backend) return NULL;
-
-        CaptureWrapper_Construct(backend, device, funcs);
-
-        return STATIC_CAST(ALCbackend, backend);
-    }
-
-    return NULL;
-}

+ 0 - 424
love/src/jni/openal-soft-1.17.0/Alc/backends/opensl.c

@@ -1,424 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* This is an OpenAL backend for Android using the native audio APIs based on
- * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app
- * bundled with NDK.
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-
-#include "alMain.h"
-#include "alu.h"
-
-
-#include <SLES/OpenSLES.h>
-#include <SLES/OpenSLES_Android.h>
-
-/* Helper macros */
-#define VCALL(obj, func)  ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
-#define VCALL0(obj, func)  ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
-
-
-typedef struct {
-    /* engine interfaces */
-    SLObjectItf engineObject;
-    SLEngineItf engine;
-
-    /* output mix interfaces */
-    SLObjectItf outputMix;
-
-    /* buffer queue player interfaces */
-    SLObjectItf bufferQueueObject;
-
-    void *buffer;
-    ALuint bufferSize;
-    ALuint curBuffer;
-
-    ALuint frameSize;
-} osl_data;
-
-
-static const ALCchar opensl_device[] = "OpenSL";
-
-
-static SLuint32 GetChannelMask(enum DevFmtChannels chans)
-{
-    switch(chans)
-    {
-        case DevFmtMono: return SL_SPEAKER_FRONT_CENTER;
-        case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT;
-        case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
-                                SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
-        case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
-                               SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
-                               SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
-        case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
-                               SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
-                               SL_SPEAKER_BACK_CENTER|
-                               SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
-        case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
-                               SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
-                               SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
-                               SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
-        case DevFmtX51Side: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
-                                   SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
-                                   SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
-    }
-    return 0;
-}
-
-static const char *res_str(SLresult result)
-{
-    switch(result)
-    {
-        case SL_RESULT_SUCCESS: return "Success";
-        case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";
-        case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid";
-        case SL_RESULT_MEMORY_FAILURE: return "Memory failure";
-        case SL_RESULT_RESOURCE_ERROR: return "Resource error";
-        case SL_RESULT_RESOURCE_LOST: return "Resource lost";
-        case SL_RESULT_IO_ERROR: return "I/O error";
-        case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient";
-        case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted";
-        case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported";
-        case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found";
-        case SL_RESULT_PERMISSION_DENIED: return "Permission denied";
-        case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported";
-        case SL_RESULT_INTERNAL_ERROR: return "Internal error";
-        case SL_RESULT_UNKNOWN_ERROR: return "Unknown error";
-        case SL_RESULT_OPERATION_ABORTED: return "Operation aborted";
-        case SL_RESULT_CONTROL_LOST: return "Control lost";
-#ifdef SL_RESULT_READONLY
-        case SL_RESULT_READONLY: return "ReadOnly";
-#endif
-#ifdef SL_RESULT_ENGINEOPTION_UNSUPPORTED
-        case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported";
-#endif
-#ifdef SL_RESULT_SOURCE_SINK_INCOMPATIBLE
-        case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible";
-#endif
-    }
-    return "Unknown error code";
-}
-
-#define PRINTERR(x, s) do {                                                      \
-    if((x) != SL_RESULT_SUCCESS)                                                 \
-        ERR("%s: %s\n", (s), res_str((x)));                                      \
-} while(0)
-
-/* this callback handler is called every time a buffer finishes playing */
-static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *context)
-{
-    ALCdevice *Device = context;
-    osl_data *data = Device->ExtraData;
-    ALvoid *buf;
-    SLresult result;
-
-    buf = (ALbyte*)data->buffer + data->curBuffer*data->bufferSize;
-    aluMixData(Device, buf, data->bufferSize/data->frameSize);
-
-    result = VCALL(bq,Enqueue)(buf, data->bufferSize);
-    PRINTERR(result, "bq->Enqueue");
-
-    data->curBuffer = (data->curBuffer+1) % Device->NumUpdates;
-}
-
-
-static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName)
-{
-    osl_data *data = NULL;
-    SLresult result;
-
-    if(!deviceName)
-        deviceName = opensl_device;
-    else if(strcmp(deviceName, opensl_device) != 0)
-        return ALC_INVALID_VALUE;
-
-    data = calloc(1, sizeof(*data));
-    if(!data)
-        return ALC_OUT_OF_MEMORY;
-
-    // create engine
-    result = slCreateEngine(&data->engineObject, 0, NULL, 0, NULL, NULL);
-    PRINTERR(result, "slCreateEngine");
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(data->engineObject,Realize)(SL_BOOLEAN_FALSE);
-        PRINTERR(result, "engine->Realize");
-    }
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(data->engineObject,GetInterface)(SL_IID_ENGINE, &data->engine);
-        PRINTERR(result, "engine->GetInterface");
-    }
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(data->engine,CreateOutputMix)(&data->outputMix, 0, NULL, NULL);
-        PRINTERR(result, "engine->CreateOutputMix");
-    }
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(data->outputMix,Realize)(SL_BOOLEAN_FALSE);
-        PRINTERR(result, "outputMix->Realize");
-    }
-
-    if(SL_RESULT_SUCCESS != result)
-    {
-        if(data->outputMix != NULL)
-            VCALL0(data->outputMix,Destroy)();
-        data->outputMix = NULL;
-
-        if(data->engineObject != NULL)
-            VCALL0(data->engineObject,Destroy)();
-        data->engineObject = NULL;
-        data->engine = NULL;
-
-        free(data);
-        return ALC_INVALID_VALUE;
-    }
-
-    al_string_copy_cstr(&Device->DeviceName, deviceName);
-    Device->ExtraData = data;
-
-    return ALC_NO_ERROR;
-}
-
-
-static void opensl_close_playback(ALCdevice *Device)
-{
-    osl_data *data = Device->ExtraData;
-
-    if(data->bufferQueueObject != NULL)
-        VCALL0(data->bufferQueueObject,Destroy)();
-    data->bufferQueueObject = NULL;
-
-    VCALL0(data->outputMix,Destroy)();
-    data->outputMix = NULL;
-
-    VCALL0(data->engineObject,Destroy)();
-    data->engineObject = NULL;
-    data->engine = NULL;
-
-    free(data);
-    Device->ExtraData = NULL;
-}
-
-static ALCboolean opensl_reset_playback(ALCdevice *Device)
-{
-    osl_data *data = Device->ExtraData;
-    SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
-    SLDataLocator_OutputMix loc_outmix;
-    SLDataFormat_PCM format_pcm;
-    SLDataSource audioSrc;
-    SLDataSink audioSnk;
-    SLInterfaceID id;
-    SLboolean req;
-    SLresult result;
-
-
-    Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency;
-    Device->UpdateSize = Device->UpdateSize * Device->NumUpdates / 2;
-    Device->NumUpdates = 2;
-
-    Device->Frequency = 44100;
-    Device->FmtChans = DevFmtStereo;
-    Device->FmtType = DevFmtShort;
-
-    SetDefaultWFXChannelOrder(Device);
-
-
-    id  = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
-    req = SL_BOOLEAN_TRUE;
-
-    loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
-    loc_bufq.numBuffers = Device->NumUpdates;
-
-    format_pcm.formatType = SL_DATAFORMAT_PCM;
-    format_pcm.numChannels = ChannelsFromDevFmt(Device->FmtChans);
-    format_pcm.samplesPerSec = Device->Frequency * 1000;
-    format_pcm.bitsPerSample = BytesFromDevFmt(Device->FmtType) * 8;
-    format_pcm.containerSize = format_pcm.bitsPerSample;
-    format_pcm.channelMask = GetChannelMask(Device->FmtChans);
-    format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
-                                               SL_BYTEORDER_BIGENDIAN;
-
-    audioSrc.pLocator = &loc_bufq;
-    audioSrc.pFormat = &format_pcm;
-
-    loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
-    loc_outmix.outputMix = data->outputMix;
-    audioSnk.pLocator = &loc_outmix;
-    audioSnk.pFormat = NULL;
-
-
-    if(data->bufferQueueObject != NULL)
-        VCALL0(data->bufferQueueObject,Destroy)();
-    data->bufferQueueObject = NULL;
-
-    result = VCALL(data->engine,CreateAudioPlayer)(&data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req);
-    PRINTERR(result, "engine->CreateAudioPlayer");
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(data->bufferQueueObject,Realize)(SL_BOOLEAN_FALSE);
-        PRINTERR(result, "bufferQueue->Realize");
-    }
-
-    if(SL_RESULT_SUCCESS != result)
-    {
-        if(data->bufferQueueObject != NULL)
-            VCALL0(data->bufferQueueObject,Destroy)();
-        data->bufferQueueObject = NULL;
-
-        return ALC_FALSE;
-    }
-
-    return ALC_TRUE;
-}
-
-static ALCboolean opensl_start_playback(ALCdevice *Device)
-{
-    osl_data *data = Device->ExtraData;
-    SLAndroidSimpleBufferQueueItf bufferQueue;
-    SLPlayItf player;
-    SLresult result;
-    ALuint i;
-
-    result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue);
-    PRINTERR(result, "bufferQueue->GetInterface");
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(bufferQueue,RegisterCallback)(opensl_callback, Device);
-        PRINTERR(result, "bufferQueue->RegisterCallback");
-    }
-    if(SL_RESULT_SUCCESS == result)
-    {
-        data->frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
-        data->bufferSize = Device->UpdateSize * data->frameSize;
-        data->buffer = calloc(Device->NumUpdates, data->bufferSize);
-        if(!data->buffer)
-        {
-            result = SL_RESULT_MEMORY_FAILURE;
-            PRINTERR(result, "calloc");
-        }
-    }
-    /* enqueue the first buffer to kick off the callbacks */
-    for(i = 0;i < Device->NumUpdates;i++)
-    {
-        if(SL_RESULT_SUCCESS == result)
-        {
-            ALvoid *buf = (ALbyte*)data->buffer + i*data->bufferSize;
-            result = VCALL(bufferQueue,Enqueue)(buf, data->bufferSize);
-            PRINTERR(result, "bufferQueue->Enqueue");
-        }
-    }
-    data->curBuffer = 0;
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_PLAY, &player);
-        PRINTERR(result, "bufferQueue->GetInterface");
-    }
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING);
-        PRINTERR(result, "player->SetPlayState");
-    }
-
-    if(SL_RESULT_SUCCESS != result)
-    {
-        if(data->bufferQueueObject != NULL)
-            VCALL0(data->bufferQueueObject,Destroy)();
-        data->bufferQueueObject = NULL;
-
-        free(data->buffer);
-        data->buffer = NULL;
-        data->bufferSize = 0;
-
-        return ALC_FALSE;
-    }
-
-    return ALC_TRUE;
-}
-
-
-static void opensl_stop_playback(ALCdevice *Device)
-{
-    osl_data *data = Device->ExtraData;
-    SLPlayItf player;
-    SLAndroidSimpleBufferQueueItf bufferQueue;
-    SLresult result;
-
-    result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_PLAY, &player);
-    PRINTERR(result, "bufferQueue->GetInterface");
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL(player,SetPlayState)(SL_PLAYSTATE_STOPPED);
-        PRINTERR(result, "player->SetPlayState");
-    }
-
-    result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue);
-    PRINTERR(result, "bufferQueue->GetInterface");
-    if(SL_RESULT_SUCCESS == result)
-    {
-        result = VCALL0(bufferQueue,Clear)();
-        PRINTERR(result, "bufferQueue->Clear");
-    }
-
-    free(data->buffer);
-    data->buffer = NULL;
-    data->bufferSize = 0;
-}
-
-
-static const BackendFuncs opensl_funcs = {
-    opensl_open_playback,
-    opensl_close_playback,
-    opensl_reset_playback,
-    opensl_start_playback,
-    opensl_stop_playback,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    ALCdevice_GetLatencyDefault
-};
-
-
-ALCboolean alc_opensl_init(BackendFuncs *func_list)
-{
-    *func_list = opensl_funcs;
-    return ALC_TRUE;
-}
-
-void alc_opensl_deinit(void)
-{
-}
-
-void alc_opensl_probe(enum DevProbe type)
-{
-    switch(type)
-    {
-        case ALL_DEVICE_PROBE:
-            AppendAllDevicesList(opensl_device);
-            break;
-        case CAPTURE_DEVICE_PROBE:
-            break;
-    }
-}

+ 0 - 469
love/src/jni/openal-soft-1.17.0/Alc/backends/portaudio.c

@@ -1,469 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alMain.h"
-#include "alu.h"
-#include "compat.h"
-
-#include <portaudio.h>
-
-
-static const ALCchar pa_device[] = "PortAudio Default";
-
-
-#ifdef HAVE_DYNLOAD
-static void *pa_handle;
-#define MAKE_FUNC(x) static __typeof(x) * p##x
-MAKE_FUNC(Pa_Initialize);
-MAKE_FUNC(Pa_Terminate);
-MAKE_FUNC(Pa_GetErrorText);
-MAKE_FUNC(Pa_StartStream);
-MAKE_FUNC(Pa_StopStream);
-MAKE_FUNC(Pa_OpenStream);
-MAKE_FUNC(Pa_CloseStream);
-MAKE_FUNC(Pa_GetDefaultOutputDevice);
-MAKE_FUNC(Pa_GetDefaultInputDevice);
-MAKE_FUNC(Pa_GetStreamInfo);
-#undef MAKE_FUNC
-
-#define Pa_Initialize                  pPa_Initialize
-#define Pa_Terminate                   pPa_Terminate
-#define Pa_GetErrorText                pPa_GetErrorText
-#define Pa_StartStream                 pPa_StartStream
-#define Pa_StopStream                  pPa_StopStream
-#define Pa_OpenStream                  pPa_OpenStream
-#define Pa_CloseStream                 pPa_CloseStream
-#define Pa_GetDefaultOutputDevice      pPa_GetDefaultOutputDevice
-#define Pa_GetDefaultInputDevice       pPa_GetDefaultInputDevice
-#define Pa_GetStreamInfo               pPa_GetStreamInfo
-#endif
-
-static ALCboolean pa_load(void)
-{
-    PaError err;
-
-#ifdef HAVE_DYNLOAD
-    if(!pa_handle)
-    {
-#ifdef _WIN32
-# define PALIB "portaudio.dll"
-#elif defined(__APPLE__) && defined(__MACH__)
-# define PALIB "libportaudio.2.dylib"
-#elif defined(__OpenBSD__)
-# define PALIB "libportaudio.so"
-#else
-# define PALIB "libportaudio.so.2"
-#endif
-
-        pa_handle = LoadLib(PALIB);
-        if(!pa_handle)
-            return ALC_FALSE;
-
-#define LOAD_FUNC(f) do {                                                     \
-    p##f = GetSymbol(pa_handle, #f);                                          \
-    if(p##f == NULL)                                                          \
-    {                                                                         \
-        CloseLib(pa_handle);                                                  \
-        pa_handle = NULL;                                                     \
-        return ALC_FALSE;                                                     \
-    }                                                                         \
-} while(0)
-        LOAD_FUNC(Pa_Initialize);
-        LOAD_FUNC(Pa_Terminate);
-        LOAD_FUNC(Pa_GetErrorText);
-        LOAD_FUNC(Pa_StartStream);
-        LOAD_FUNC(Pa_StopStream);
-        LOAD_FUNC(Pa_OpenStream);
-        LOAD_FUNC(Pa_CloseStream);
-        LOAD_FUNC(Pa_GetDefaultOutputDevice);
-        LOAD_FUNC(Pa_GetDefaultInputDevice);
-        LOAD_FUNC(Pa_GetStreamInfo);
-#undef LOAD_FUNC
-
-        if((err=Pa_Initialize()) != paNoError)
-        {
-            ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
-            CloseLib(pa_handle);
-            pa_handle = NULL;
-            return ALC_FALSE;
-        }
-    }
-#else
-    if((err=Pa_Initialize()) != paNoError)
-    {
-        ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
-        return ALC_FALSE;
-    }
-#endif
-    return ALC_TRUE;
-}
-
-
-typedef struct {
-    PaStream *stream;
-    PaStreamParameters params;
-    ALuint update_size;
-
-    RingBuffer *ring;
-} pa_data;
-
-
-static int pa_callback(const void *UNUSED(inputBuffer), void *outputBuffer,
-                       unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
-                       const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
-{
-    ALCdevice *device = (ALCdevice*)userData;
-
-    aluMixData(device, outputBuffer, framesPerBuffer);
-    return 0;
-}
-
-static int pa_capture_cb(const void *inputBuffer, void *UNUSED(outputBuffer),
-                         unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
-                         const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
-{
-    ALCdevice *device = (ALCdevice*)userData;
-    pa_data *data = (pa_data*)device->ExtraData;
-
-    WriteRingBuffer(data->ring, inputBuffer, framesPerBuffer);
-    return 0;
-}
-
-
-static ALCenum pa_open_playback(ALCdevice *device, const ALCchar *deviceName)
-{
-    pa_data *data;
-    PaError err;
-
-    if(!deviceName)
-        deviceName = pa_device;
-    else if(strcmp(deviceName, pa_device) != 0)
-        return ALC_INVALID_VALUE;
-
-    data = (pa_data*)calloc(1, sizeof(pa_data));
-    data->update_size = device->UpdateSize;
-
-    data->params.device = -1;
-    if(!ConfigValueInt("port", "device", &data->params.device) ||
-       data->params.device < 0)
-        data->params.device = Pa_GetDefaultOutputDevice();
-    data->params.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
-                                    (float)device->Frequency;
-    data->params.hostApiSpecificStreamInfo = NULL;
-
-    data->params.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);
-
-    switch(device->FmtType)
-    {
-        case DevFmtByte:
-            data->params.sampleFormat = paInt8;
-            break;
-        case DevFmtUByte:
-            data->params.sampleFormat = paUInt8;
-            break;
-        case DevFmtUShort:
-            /* fall-through */
-        case DevFmtShort:
-            data->params.sampleFormat = paInt16;
-            break;
-        case DevFmtUInt:
-            /* fall-through */
-        case DevFmtInt:
-            data->params.sampleFormat = paInt32;
-            break;
-        case DevFmtFloat:
-            data->params.sampleFormat = paFloat32;
-            break;
-    }
-
-retry_open:
-    err = Pa_OpenStream(&data->stream, NULL, &data->params, device->Frequency,
-                        device->UpdateSize, paNoFlag, pa_callback, device);
-    if(err != paNoError)
-    {
-        if(data->params.sampleFormat == paFloat32)
-        {
-            data->params.sampleFormat = paInt16;
-            goto retry_open;
-        }
-        ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
-        free(data);
-        return ALC_INVALID_VALUE;
-    }
-
-    device->ExtraData = data;
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-
-    return ALC_NO_ERROR;
-}
-
-static void pa_close_playback(ALCdevice *device)
-{
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_CloseStream(data->stream);
-    if(err != paNoError)
-        ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
-
-    free(data);
-    device->ExtraData = NULL;
-}
-
-static ALCboolean pa_reset_playback(ALCdevice *device)
-{
-    pa_data *data = (pa_data*)device->ExtraData;
-    const PaStreamInfo *streamInfo;
-
-    streamInfo = Pa_GetStreamInfo(data->stream);
-    device->Frequency = streamInfo->sampleRate;
-    device->UpdateSize = data->update_size;
-
-    if(data->params.sampleFormat == paInt8)
-        device->FmtType = DevFmtByte;
-    else if(data->params.sampleFormat == paUInt8)
-        device->FmtType = DevFmtUByte;
-    else if(data->params.sampleFormat == paInt16)
-        device->FmtType = DevFmtShort;
-    else if(data->params.sampleFormat == paInt32)
-        device->FmtType = DevFmtInt;
-    else if(data->params.sampleFormat == paFloat32)
-        device->FmtType = DevFmtFloat;
-    else
-    {
-        ERR("Unexpected sample format: 0x%lx\n", data->params.sampleFormat);
-        return ALC_FALSE;
-    }
-
-    if(data->params.channelCount == 2)
-        device->FmtChans = DevFmtStereo;
-    else if(data->params.channelCount == 1)
-        device->FmtChans = DevFmtMono;
-    else
-    {
-        ERR("Unexpected channel count: %u\n", data->params.channelCount);
-        return ALC_FALSE;
-    }
-    SetDefaultChannelOrder(device);
-
-    return ALC_TRUE;
-}
-
-static ALCboolean pa_start_playback(ALCdevice *device)
-{
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_StartStream(data->stream);
-    if(err != paNoError)
-    {
-        ERR("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err));
-        return ALC_FALSE;
-    }
-
-    return ALC_TRUE;
-}
-
-static void pa_stop_playback(ALCdevice *device)
-{
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_StopStream(data->stream);
-    if(err != paNoError)
-        ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
-}
-
-
-static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName)
-{
-    ALuint frame_size;
-    pa_data *data;
-    PaError err;
-
-    if(!deviceName)
-        deviceName = pa_device;
-    else if(strcmp(deviceName, pa_device) != 0)
-        return ALC_INVALID_VALUE;
-
-    data = (pa_data*)calloc(1, sizeof(pa_data));
-    if(data == NULL)
-        return ALC_OUT_OF_MEMORY;
-
-    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-    data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates);
-    if(data->ring == NULL)
-        goto error;
-
-    data->params.device = -1;
-    if(!ConfigValueInt("port", "capture", &data->params.device) ||
-       data->params.device < 0)
-        data->params.device = Pa_GetDefaultInputDevice();
-    data->params.suggestedLatency = 0.0f;
-    data->params.hostApiSpecificStreamInfo = NULL;
-
-    switch(device->FmtType)
-    {
-        case DevFmtByte:
-            data->params.sampleFormat = paInt8;
-            break;
-        case DevFmtUByte:
-            data->params.sampleFormat = paUInt8;
-            break;
-        case DevFmtShort:
-            data->params.sampleFormat = paInt16;
-            break;
-        case DevFmtInt:
-            data->params.sampleFormat = paInt32;
-            break;
-        case DevFmtFloat:
-            data->params.sampleFormat = paFloat32;
-            break;
-        case DevFmtUInt:
-        case DevFmtUShort:
-            ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
-            goto error;
-    }
-    data->params.channelCount = ChannelsFromDevFmt(device->FmtChans);
-
-    err = Pa_OpenStream(&data->stream, &data->params, NULL, device->Frequency,
-                        paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device);
-    if(err != paNoError)
-    {
-        ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
-        goto error;
-    }
-
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-
-    device->ExtraData = data;
-    return ALC_NO_ERROR;
-
-error:
-    DestroyRingBuffer(data->ring);
-    free(data);
-    return ALC_INVALID_VALUE;
-}
-
-static void pa_close_capture(ALCdevice *device)
-{
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_CloseStream(data->stream);
-    if(err != paNoError)
-        ERR("Error closing stream: %s\n", Pa_GetErrorText(err));
-
-    DestroyRingBuffer(data->ring);
-    data->ring = NULL;
-
-    free(data);
-    device->ExtraData = NULL;
-}
-
-static void pa_start_capture(ALCdevice *device)
-{
-    pa_data *data = device->ExtraData;
-    PaError err;
-
-    err = Pa_StartStream(data->stream);
-    if(err != paNoError)
-        ERR("Error starting stream: %s\n", Pa_GetErrorText(err));
-}
-
-static void pa_stop_capture(ALCdevice *device)
-{
-    pa_data *data = (pa_data*)device->ExtraData;
-    PaError err;
-
-    err = Pa_StopStream(data->stream);
-    if(err != paNoError)
-        ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
-}
-
-static ALCenum pa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
-{
-    pa_data *data = device->ExtraData;
-    ReadRingBuffer(data->ring, buffer, samples);
-    return ALC_NO_ERROR;
-}
-
-static ALCuint pa_available_samples(ALCdevice *device)
-{
-    pa_data *data = device->ExtraData;
-    return RingBufferSize(data->ring);
-}
-
-
-static const BackendFuncs pa_funcs = {
-    pa_open_playback,
-    pa_close_playback,
-    pa_reset_playback,
-    pa_start_playback,
-    pa_stop_playback,
-    pa_open_capture,
-    pa_close_capture,
-    pa_start_capture,
-    pa_stop_capture,
-    pa_capture_samples,
-    pa_available_samples,
-    ALCdevice_GetLatencyDefault
-};
-
-ALCboolean alc_pa_init(BackendFuncs *func_list)
-{
-    if(!pa_load())
-        return ALC_FALSE;
-    *func_list = pa_funcs;
-    return ALC_TRUE;
-}
-
-void alc_pa_deinit(void)
-{
-#ifdef HAVE_DYNLOAD
-    if(pa_handle)
-    {
-        Pa_Terminate();
-        CloseLib(pa_handle);
-        pa_handle = NULL;
-    }
-#else
-    Pa_Terminate();
-#endif
-}
-
-void alc_pa_probe(enum DevProbe type)
-{
-    switch(type)
-    {
-        case ALL_DEVICE_PROBE:
-            AppendAllDevicesList(pa_device);
-            break;
-        case CAPTURE_DEVICE_PROBE:
-            AppendCaptureDeviceList(pa_device);
-            break;
-    }
-}

+ 0 - 295
love/src/jni/openal-soft-1.17.0/Alc/backends/sndio.c

@@ -1,295 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "alMain.h"
-#include "alu.h"
-#include "threads.h"
-
-#include <sndio.h>
-
-
-static const ALCchar sndio_device[] = "SndIO Default";
-
-
-static ALCboolean sndio_load(void)
-{
-    return ALC_TRUE;
-}
-
-
-typedef struct {
-    struct sio_hdl *sndHandle;
-
-    ALvoid *mix_data;
-    ALsizei data_size;
-
-    volatile int killNow;
-    althrd_t thread;
-} sndio_data;
-
-
-static int sndio_proc(void *ptr)
-{
-    ALCdevice *device = ptr;
-    sndio_data *data = device->ExtraData;
-    ALsizei frameSize;
-    size_t wrote;
-
-    SetRTPriority();
-    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
-
-    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-
-    while(!data->killNow && device->Connected)
-    {
-        ALsizei len = data->data_size;
-        ALubyte *WritePtr = data->mix_data;
-
-        aluMixData(device, WritePtr, len/frameSize);
-        while(len > 0 && !data->killNow)
-        {
-            wrote = sio_write(data->sndHandle, WritePtr, len);
-            if(wrote == 0)
-            {
-                ERR("sio_write failed\n");
-                ALCdevice_Lock(device);
-                aluHandleDisconnect(device);
-                ALCdevice_Unlock(device);
-                break;
-            }
-
-            len -= wrote;
-            WritePtr += wrote;
-        }
-    }
-
-    return 0;
-}
-
-
-
-static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName)
-{
-    sndio_data *data;
-
-    if(!deviceName)
-        deviceName = sndio_device;
-    else if(strcmp(deviceName, sndio_device) != 0)
-        return ALC_INVALID_VALUE;
-
-    data = calloc(1, sizeof(*data));
-    data->killNow = 0;
-
-    data->sndHandle = sio_open(NULL, SIO_PLAY, 0);
-    if(data->sndHandle == NULL)
-    {
-        free(data);
-        ERR("Could not open device\n");
-        return ALC_INVALID_VALUE;
-    }
-
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-    device->ExtraData = data;
-
-    return ALC_NO_ERROR;
-}
-
-static void sndio_close_playback(ALCdevice *device)
-{
-    sndio_data *data = device->ExtraData;
-
-    sio_close(data->sndHandle);
-    free(data);
-    device->ExtraData = NULL;
-}
-
-static ALCboolean sndio_reset_playback(ALCdevice *device)
-{
-    sndio_data *data = device->ExtraData;
-    struct sio_par par;
-
-    sio_initpar(&par);
-
-    par.rate = device->Frequency;
-    par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
-
-    switch(device->FmtType)
-    {
-        case DevFmtByte:
-            par.bits = 8;
-            par.sig = 1;
-            break;
-        case DevFmtUByte:
-            par.bits = 8;
-            par.sig = 0;
-            break;
-        case DevFmtFloat:
-        case DevFmtShort:
-            par.bits = 16;
-            par.sig = 1;
-            break;
-        case DevFmtUShort:
-            par.bits = 16;
-            par.sig = 0;
-            break;
-        case DevFmtInt:
-            par.bits = 32;
-            par.sig = 1;
-            break;
-        case DevFmtUInt:
-            par.bits = 32;
-            par.sig = 0;
-            break;
-    }
-    par.le = SIO_LE_NATIVE;
-
-    par.round = device->UpdateSize;
-    par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
-    if(!par.appbufsz) par.appbufsz = device->UpdateSize;
-
-    if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par))
-    {
-        ERR("Failed to set device parameters\n");
-        return ALC_FALSE;
-    }
-
-    if(par.bits != par.bps*8)
-    {
-        ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
-        return ALC_FALSE;
-    }
-
-    device->Frequency = par.rate;
-    device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
-
-    if(par.bits == 8 && par.sig == 1)
-        device->FmtType = DevFmtByte;
-    else if(par.bits == 8 && par.sig == 0)
-        device->FmtType = DevFmtUByte;
-    else if(par.bits == 16 && par.sig == 1)
-        device->FmtType = DevFmtShort;
-    else if(par.bits == 16 && par.sig == 0)
-        device->FmtType = DevFmtUShort;
-    else if(par.bits == 32 && par.sig == 1)
-        device->FmtType = DevFmtInt;
-    else if(par.bits == 32 && par.sig == 0)
-        device->FmtType = DevFmtUInt;
-    else
-    {
-        ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
-        return ALC_FALSE;
-    }
-
-    device->UpdateSize = par.round;
-    device->NumUpdates = (par.bufsz/par.round) + 1;
-
-    SetDefaultChannelOrder(device);
-
-    return ALC_TRUE;
-}
-
-static ALCboolean sndio_start_playback(ALCdevice *device)
-{
-    sndio_data *data = device->ExtraData;
-
-    if(!sio_start(data->sndHandle))
-    {
-        ERR("Error starting playback\n");
-        return ALC_FALSE;
-    }
-
-    data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-    data->mix_data = calloc(1, data->data_size);
-
-    data->killNow = 0;
-    if(althrd_create(&data->thread, sndio_proc, device) != althrd_success)
-    {
-        sio_stop(data->sndHandle);
-        free(data->mix_data);
-        data->mix_data = NULL;
-        return ALC_FALSE;
-    }
-
-    return ALC_TRUE;
-}
-
-static void sndio_stop_playback(ALCdevice *device)
-{
-    sndio_data *data = device->ExtraData;
-    int res;
-
-    if(data->killNow)
-        return;
-
-    data->killNow = 1;
-    althrd_join(data->thread, &res);
-
-    if(!sio_stop(data->sndHandle))
-        ERR("Error stopping device\n");
-
-    free(data->mix_data);
-    data->mix_data = NULL;
-}
-
-
-static const BackendFuncs sndio_funcs = {
-    sndio_open_playback,
-    sndio_close_playback,
-    sndio_reset_playback,
-    sndio_start_playback,
-    sndio_stop_playback,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    ALCdevice_GetLatencyDefault
-};
-
-ALCboolean alc_sndio_init(BackendFuncs *func_list)
-{
-    if(!sndio_load())
-        return ALC_FALSE;
-    *func_list = sndio_funcs;
-    return ALC_TRUE;
-}
-
-void alc_sndio_deinit(void)
-{
-}
-
-void alc_sndio_probe(enum DevProbe type)
-{
-    switch(type)
-    {
-        case ALL_DEVICE_PROBE:
-            AppendAllDevicesList(sndio_device);
-            break;
-        case CAPTURE_DEVICE_PROBE:
-            break;
-    }
-}

+ 0 - 288
love/src/jni/openal-soft-1.17.0/Alc/backends/solaris.c

@@ -1,288 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <memory.h>
-#include <unistd.h>
-#include <errno.h>
-#include <math.h>
-
-#include "alMain.h"
-#include "alu.h"
-#include "threads.h"
-#include "compat.h"
-
-#include <sys/audioio.h>
-
-
-static const ALCchar solaris_device[] = "Solaris Default";
-
-static const char *solaris_driver = "/dev/audio";
-
-typedef struct {
-    int fd;
-
-    ALubyte *mix_data;
-    int data_size;
-
-    volatile int killNow;
-    althrd_t thread;
-} solaris_data;
-
-
-static int SolarisProc(void *ptr)
-{
-    ALCdevice *Device = (ALCdevice*)ptr;
-    solaris_data *data = (solaris_data*)Device->ExtraData;
-    ALint frameSize;
-    int wrote;
-
-    SetRTPriority();
-    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
-
-    frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType);
-
-    while(!data->killNow && Device->Connected)
-    {
-        ALint len = data->data_size;
-        ALubyte *WritePtr = data->mix_data;
-
-        aluMixData(Device, WritePtr, len/frameSize);
-        while(len > 0 && !data->killNow)
-        {
-            wrote = write(data->fd, WritePtr, len);
-            if(wrote < 0)
-            {
-                if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
-                {
-                    ERR("write failed: %s\n", strerror(errno));
-                    ALCdevice_Lock(Device);
-                    aluHandleDisconnect(Device);
-                    ALCdevice_Unlock(Device);
-                    break;
-                }
-
-                al_nssleep(0, 1000000);
-                continue;
-            }
-
-            len -= wrote;
-            WritePtr += wrote;
-        }
-    }
-
-    return 0;
-}
-
-
-static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceName)
-{
-    solaris_data *data;
-
-    if(!deviceName)
-        deviceName = solaris_device;
-    else if(strcmp(deviceName, solaris_device) != 0)
-        return ALC_INVALID_VALUE;
-
-    data = (solaris_data*)calloc(1, sizeof(solaris_data));
-    data->killNow = 0;
-
-    data->fd = open(solaris_driver, O_WRONLY);
-    if(data->fd == -1)
-    {
-        free(data);
-        ERR("Could not open %s: %s\n", solaris_driver, strerror(errno));
-        return ALC_INVALID_VALUE;
-    }
-
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-    device->ExtraData = data;
-    return ALC_NO_ERROR;
-}
-
-static void solaris_close_playback(ALCdevice *device)
-{
-    solaris_data *data = (solaris_data*)device->ExtraData;
-
-    close(data->fd);
-    free(data);
-    device->ExtraData = NULL;
-}
-
-static ALCboolean solaris_reset_playback(ALCdevice *device)
-{
-    solaris_data *data = (solaris_data*)device->ExtraData;
-    audio_info_t info;
-    ALuint frameSize;
-    int numChannels;
-
-    AUDIO_INITINFO(&info);
-
-    info.play.sample_rate = device->Frequency;
-
-    if(device->FmtChans != DevFmtMono)
-        device->FmtChans = DevFmtStereo;
-    numChannels = ChannelsFromDevFmt(device->FmtChans);
-    info.play.channels = numChannels;
-
-    switch(device->FmtType)
-    {
-        case DevFmtByte:
-            info.play.precision = 8;
-            info.play.encoding = AUDIO_ENCODING_LINEAR;
-            break;
-        case DevFmtUByte:
-            info.play.precision = 8;
-            info.play.encoding = AUDIO_ENCODING_LINEAR8;
-            break;
-        case DevFmtUShort:
-        case DevFmtInt:
-        case DevFmtUInt:
-        case DevFmtFloat:
-            device->FmtType = DevFmtShort;
-            /* fall-through */
-        case DevFmtShort:
-            info.play.precision = 16;
-            info.play.encoding = AUDIO_ENCODING_LINEAR;
-            break;
-    }
-
-    frameSize = numChannels * BytesFromDevFmt(device->FmtType);
-    info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize;
-
-    if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0)
-    {
-        ERR("ioctl failed: %s\n", strerror(errno));
-        return ALC_FALSE;
-    }
-
-    if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels)
-    {
-        ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels);
-        return ALC_FALSE;
-    }
-
-    if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && device->FmtType == DevFmtUByte) ||
-         (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtByte) ||
-         (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtShort) ||
-         (info.play.precision == 32 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtInt)))
-    {
-        ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device->FmtType),
-            info.play.precision, info.play.encoding);
-        return ALC_FALSE;
-    }
-
-    device->Frequency = info.play.sample_rate;
-    device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1;
-
-    SetDefaultChannelOrder(device);
-
-    return ALC_TRUE;
-}
-
-static ALCboolean solaris_start_playback(ALCdevice *device)
-{
-    solaris_data *data = (solaris_data*)device->ExtraData;
-
-    data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-    data->mix_data = calloc(1, data->data_size);
-
-    data->killNow = 0;
-    if(althrd_create(&data->thread, SolarisProc, device) != althrd_success)
-    {
-        free(data->mix_data);
-        data->mix_data = NULL;
-        return ALC_FALSE;
-    }
-
-    return ALC_TRUE;
-}
-
-static void solaris_stop_playback(ALCdevice *device)
-{
-    solaris_data *data = (solaris_data*)device->ExtraData;
-    int res;
-
-    if(data->killNow)
-        return;
-
-    data->killNow = 1;
-    althrd_join(data->thread, &res);
-
-    if(ioctl(data->fd, AUDIO_DRAIN) < 0)
-        ERR("Error draining device: %s\n", strerror(errno));
-
-    free(data->mix_data);
-    data->mix_data = NULL;
-}
-
-
-static const BackendFuncs solaris_funcs = {
-    solaris_open_playback,
-    solaris_close_playback,
-    solaris_reset_playback,
-    solaris_start_playback,
-    solaris_stop_playback,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    ALCdevice_GetLatencyDefault
-};
-
-ALCboolean alc_solaris_init(BackendFuncs *func_list)
-{
-    ConfigValueStr("solaris", "device", &solaris_driver);
-
-    *func_list = solaris_funcs;
-    return ALC_TRUE;
-}
-
-void alc_solaris_deinit(void)
-{
-}
-
-void alc_solaris_probe(enum DevProbe type)
-{
-    switch(type)
-    {
-        case ALL_DEVICE_PROBE:
-        {
-#ifdef HAVE_STAT
-            struct stat buf;
-            if(stat(solaris_driver, &buf) == 0)
-#endif
-                AppendAllDevicesList(solaris_device);
-        }
-        break;
-
-        case CAPTURE_DEVICE_PROBE:
-            break;
-    }
-}

+ 0 - 377
love/src/jni/openal-soft-1.17.0/Alc/backends/wave.c

@@ -1,377 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <memory.h>
-#include <errno.h>
-#ifdef HAVE_WINDOWS_H
-#include <windows.h>
-#endif
-
-#include "alMain.h"
-#include "alu.h"
-#include "threads.h"
-#include "compat.h"
-
-
-typedef struct {
-    FILE *f;
-    long DataStart;
-
-    ALvoid *buffer;
-    ALuint size;
-
-    volatile int killNow;
-    althrd_t thread;
-} wave_data;
-
-
-static const ALCchar waveDevice[] = "Wave File Writer";
-
-static const ALubyte SUBTYPE_PCM[] = {
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
-    0x00, 0x38, 0x9b, 0x71
-};
-static const ALubyte SUBTYPE_FLOAT[] = {
-    0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
-    0x00, 0x38, 0x9b, 0x71
-};
-
-static const ALuint channel_masks[] = {
-    0, /* invalid */
-    0x4, /* Mono */
-    0x1 | 0x2, /* Stereo */
-    0, /* 3 channel */
-    0x1 | 0x2 | 0x10 | 0x20, /* Quad */
-    0, /* 5 channel */
-    0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20, /* 5.1 */
-    0x1 | 0x2 | 0x4 | 0x8 | 0x100 | 0x200 | 0x400, /* 6.1 */
-    0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x200 | 0x400, /* 7.1 */
-};
-
-
-static void fwrite16le(ALushort val, FILE *f)
-{
-    fputc(val&0xff, f);
-    fputc((val>>8)&0xff, f);
-}
-
-static void fwrite32le(ALuint val, FILE *f)
-{
-    fputc(val&0xff, f);
-    fputc((val>>8)&0xff, f);
-    fputc((val>>16)&0xff, f);
-    fputc((val>>24)&0xff, f);
-}
-
-
-static int WaveProc(void *ptr)
-{
-    ALCdevice *device = (ALCdevice*)ptr;
-    wave_data *data = (wave_data*)device->ExtraData;
-    struct timespec now, start;
-    ALint64 avail, done;
-    ALuint frameSize;
-    size_t fs;
-    const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 /
-                                 device->Frequency / 2);
-
-    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
-
-    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-
-    done = 0;
-    if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC)
-    {
-        ERR("Failed to get starting time\n");
-        return 1;
-    }
-    while(!data->killNow && device->Connected)
-    {
-        if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
-        {
-            ERR("Failed to get current time\n");
-            return 1;
-        }
-
-        avail  = (now.tv_sec - start.tv_sec) * device->Frequency;
-        avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000;
-        if(avail < done)
-        {
-            /* Oops, time skipped backwards. Reset the number of samples done
-             * with one update available since we (likely) just came back from
-             * sleeping. */
-            done = avail - device->UpdateSize;
-        }
-
-        if(avail-done < device->UpdateSize)
-            al_nssleep(0, restTime);
-        else while(avail-done >= device->UpdateSize)
-        {
-            aluMixData(device, data->buffer, device->UpdateSize);
-            done += device->UpdateSize;
-
-            if(!IS_LITTLE_ENDIAN)
-            {
-                ALuint bytesize = BytesFromDevFmt(device->FmtType);
-                ALubyte *bytes = data->buffer;
-                ALuint i;
-
-                if(bytesize == 1)
-                {
-                    for(i = 0;i < data->size;i++)
-                        fputc(bytes[i], data->f);
-                }
-                else if(bytesize == 2)
-                {
-                    for(i = 0;i < data->size;i++)
-                        fputc(bytes[i^1], data->f);
-                }
-                else if(bytesize == 4)
-                {
-                    for(i = 0;i < data->size;i++)
-                        fputc(bytes[i^3], data->f);
-                }
-            }
-            else
-            {
-                fs = fwrite(data->buffer, frameSize, device->UpdateSize,
-                            data->f);
-                (void)fs;
-            }
-            if(ferror(data->f))
-            {
-                ERR("Error writing to file\n");
-                ALCdevice_Lock(device);
-                aluHandleDisconnect(device);
-                ALCdevice_Unlock(device);
-                break;
-            }
-        }
-    }
-
-    return 0;
-}
-
-static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName)
-{
-    wave_data *data;
-    const char *fname;
-
-    fname = GetConfigValue("wave", "file", "");
-    if(!fname[0])
-        return ALC_INVALID_VALUE;
-
-    if(!deviceName)
-        deviceName = waveDevice;
-    else if(strcmp(deviceName, waveDevice) != 0)
-        return ALC_INVALID_VALUE;
-
-    data = (wave_data*)calloc(1, sizeof(wave_data));
-
-    data->f = al_fopen(fname, "wb");
-    if(!data->f)
-    {
-        free(data);
-        ERR("Could not open file '%s': %s\n", fname, strerror(errno));
-        return ALC_INVALID_VALUE;
-    }
-
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-    device->ExtraData = data;
-    return ALC_NO_ERROR;
-}
-
-static void wave_close_playback(ALCdevice *device)
-{
-    wave_data *data = (wave_data*)device->ExtraData;
-
-    fclose(data->f);
-    free(data);
-    device->ExtraData = NULL;
-}
-
-static ALCboolean wave_reset_playback(ALCdevice *device)
-{
-    wave_data *data = (wave_data*)device->ExtraData;
-    ALuint channels=0, bits=0;
-    size_t val;
-
-    fseek(data->f, 0, SEEK_SET);
-    clearerr(data->f);
-
-    switch(device->FmtType)
-    {
-        case DevFmtByte:
-            device->FmtType = DevFmtUByte;
-            break;
-        case DevFmtUShort:
-            device->FmtType = DevFmtShort;
-            break;
-        case DevFmtUInt:
-            device->FmtType = DevFmtInt;
-            break;
-        case DevFmtUByte:
-        case DevFmtShort:
-        case DevFmtInt:
-        case DevFmtFloat:
-            break;
-    }
-    bits = BytesFromDevFmt(device->FmtType) * 8;
-    channels = ChannelsFromDevFmt(device->FmtChans);
-
-    fprintf(data->f, "RIFF");
-    fwrite32le(0xFFFFFFFF, data->f); // 'RIFF' header len; filled in at close
-
-    fprintf(data->f, "WAVE");
-
-    fprintf(data->f, "fmt ");
-    fwrite32le(40, data->f); // 'fmt ' header len; 40 bytes for EXTENSIBLE
-
-    // 16-bit val, format type id (extensible: 0xFFFE)
-    fwrite16le(0xFFFE, data->f);
-    // 16-bit val, channel count
-    fwrite16le(channels, data->f);
-    // 32-bit val, frequency
-    fwrite32le(device->Frequency, data->f);
-    // 32-bit val, bytes per second
-    fwrite32le(device->Frequency * channels * bits / 8, data->f);
-    // 16-bit val, frame size
-    fwrite16le(channels * bits / 8, data->f);
-    // 16-bit val, bits per sample
-    fwrite16le(bits, data->f);
-    // 16-bit val, extra byte count
-    fwrite16le(22, data->f);
-    // 16-bit val, valid bits per sample
-    fwrite16le(bits, data->f);
-    // 32-bit val, channel mask
-    fwrite32le(channel_masks[channels], data->f);
-    // 16 byte GUID, sub-type format
-    val = fwrite(((bits==32) ? SUBTYPE_FLOAT : SUBTYPE_PCM), 1, 16, data->f);
-    (void)val;
-
-    fprintf(data->f, "data");
-    fwrite32le(0xFFFFFFFF, data->f); // 'data' header len; filled in at close
-
-    if(ferror(data->f))
-    {
-        ERR("Error writing header: %s\n", strerror(errno));
-        return ALC_FALSE;
-    }
-    data->DataStart = ftell(data->f);
-
-    SetDefaultWFXChannelOrder(device);
-
-    return ALC_TRUE;
-}
-
-static ALCboolean wave_start_playback(ALCdevice *device)
-{
-    wave_data *data = (wave_data*)device->ExtraData;
-
-    data->size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-    data->buffer = malloc(data->size);
-    if(!data->buffer)
-    {
-        ERR("Buffer malloc failed\n");
-        return ALC_FALSE;
-    }
-
-    data->killNow = 0;
-    if(althrd_create(&data->thread, WaveProc, device) != althrd_success)
-    {
-        free(data->buffer);
-        data->buffer = NULL;
-        return ALC_FALSE;
-    }
-
-    return ALC_TRUE;
-}
-
-static void wave_stop_playback(ALCdevice *device)
-{
-    wave_data *data = (wave_data*)device->ExtraData;
-    ALuint dataLen;
-    long size;
-    int res;
-
-    if(data->killNow)
-        return;
-
-    data->killNow = 1;
-    althrd_join(data->thread, &res);
-
-    free(data->buffer);
-    data->buffer = NULL;
-
-    size = ftell(data->f);
-    if(size > 0)
-    {
-        dataLen = size - data->DataStart;
-        if(fseek(data->f, data->DataStart-4, SEEK_SET) == 0)
-            fwrite32le(dataLen, data->f); // 'data' header len
-        if(fseek(data->f, 4, SEEK_SET) == 0)
-            fwrite32le(size-8, data->f); // 'WAVE' header len
-    }
-}
-
-
-static const BackendFuncs wave_funcs = {
-    wave_open_playback,
-    wave_close_playback,
-    wave_reset_playback,
-    wave_start_playback,
-    wave_stop_playback,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    NULL,
-    ALCdevice_GetLatencyDefault
-};
-
-ALCboolean alc_wave_init(BackendFuncs *func_list)
-{
-    *func_list = wave_funcs;
-    return ALC_TRUE;
-}
-
-void alc_wave_deinit(void)
-{
-}
-
-void alc_wave_probe(enum DevProbe type)
-{
-    if(!ConfigValueExists("wave", "file"))
-        return;
-
-    switch(type)
-    {
-        case ALL_DEVICE_PROBE:
-            AppendAllDevicesList(waveDevice);
-            break;
-        case CAPTURE_DEVICE_PROBE:
-            break;
-    }
-}

+ 0 - 716
love/src/jni/openal-soft-1.17.0/Alc/backends/winmm.c

@@ -1,716 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <memory.h>
-
-#include <windows.h>
-#include <mmsystem.h>
-
-#include "alMain.h"
-#include "alu.h"
-#include "threads.h"
-
-#ifndef WAVE_FORMAT_IEEE_FLOAT
-#define WAVE_FORMAT_IEEE_FLOAT  0x0003
-#endif
-
-
-typedef struct {
-    // MMSYSTEM Device
-    volatile ALboolean killNow;
-    althrd_t thread;
-
-    RefCount WaveBuffersCommitted;
-    WAVEHDR WaveBuffer[4];
-
-    union {
-        HWAVEIN  In;
-        HWAVEOUT Out;
-    } WaveHandle;
-
-    WAVEFORMATEX Format;
-
-    RingBuffer *Ring;
-} WinMMData;
-
-
-TYPEDEF_VECTOR(al_string, vector_al_string)
-static vector_al_string PlaybackDevices;
-static vector_al_string CaptureDevices;
-
-static void clear_devlist(vector_al_string *list)
-{
-    VECTOR_FOR_EACH(al_string, *list, al_string_deinit);
-    VECTOR_RESIZE(*list, 0);
-}
-
-
-static void ProbePlaybackDevices(void)
-{
-    al_string *iter, *end;
-    ALuint numdevs;
-    ALuint i;
-
-    clear_devlist(&PlaybackDevices);
-
-    numdevs = waveOutGetNumDevs();
-    VECTOR_RESERVE(PlaybackDevices, numdevs);
-    for(i = 0;i < numdevs;i++)
-    {
-        WAVEOUTCAPSW WaveCaps;
-        al_string dname;
-
-        AL_STRING_INIT(dname);
-        if(waveOutGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
-        {
-            ALuint count = 0;
-            do {
-                al_string_copy_wcstr(&dname, WaveCaps.szPname);
-                if(count != 0)
-                {
-                    char str[64];
-                    snprintf(str, sizeof(str), " #%d", count+1);
-                    al_string_append_cstr(&dname, str);
-                }
-                count++;
-
-                iter = VECTOR_ITER_BEGIN(PlaybackDevices);
-                end = VECTOR_ITER_END(PlaybackDevices);
-                for(;iter != end;iter++)
-                {
-                    if(al_string_cmp(*iter, dname) == 0)
-                        break;
-                }
-            } while(iter != end);
-
-            TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i);
-        }
-        VECTOR_PUSH_BACK(PlaybackDevices, dname);
-    }
-}
-
-static void ProbeCaptureDevices(void)
-{
-    al_string *iter, *end;
-    ALuint numdevs;
-    ALuint i;
-
-    clear_devlist(&CaptureDevices);
-
-    numdevs = waveInGetNumDevs();
-    VECTOR_RESERVE(CaptureDevices, numdevs);
-    for(i = 0;i < numdevs;i++)
-    {
-        WAVEINCAPSW WaveCaps;
-        al_string dname;
-
-        AL_STRING_INIT(dname);
-        if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
-        {
-            ALuint count = 0;
-            do {
-                al_string_copy_wcstr(&dname, WaveCaps.szPname);
-                if(count != 0)
-                {
-                    char str[64];
-                    snprintf(str, sizeof(str), " #%d", count+1);
-                    al_string_append_cstr(&dname, str);
-                }
-                count++;
-
-                iter = VECTOR_ITER_BEGIN(CaptureDevices);
-                end = VECTOR_ITER_END(CaptureDevices);
-                for(;iter != end;iter++)
-                {
-                    if(al_string_cmp(*iter, dname) == 0)
-                        break;
-                }
-            } while(iter != end);
-
-            TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i);
-        }
-        VECTOR_PUSH_BACK(CaptureDevices, dname);
-    }
-}
-
-
-/*
-    WaveOutProc
-
-    Posts a message to 'PlaybackThreadProc' everytime a WaveOut Buffer is completed and
-    returns to the application (for more data)
-*/
-static void CALLBACK WaveOutProc(HWAVEOUT UNUSED(device), UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR UNUSED(param2))
-{
-    ALCdevice *Device = (ALCdevice*)instance;
-    WinMMData *data = Device->ExtraData;
-
-    if(msg != WOM_DONE)
-        return;
-
-    DecrementRef(&data->WaveBuffersCommitted);
-    PostThreadMessage(data->thread, msg, 0, param1);
-}
-
-FORCE_ALIGN static int PlaybackThreadProc(void *arg)
-{
-    ALCdevice *Device = (ALCdevice*)arg;
-    WinMMData *data = Device->ExtraData;
-    WAVEHDR *WaveHdr;
-    MSG msg;
-
-    SetRTPriority();
-    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
-
-    while(GetMessage(&msg, NULL, 0, 0))
-    {
-        if(msg.message != WOM_DONE)
-            continue;
-
-        if(data->killNow)
-        {
-            if(ReadRef(&data->WaveBuffersCommitted) == 0)
-                break;
-            continue;
-        }
-
-        WaveHdr = ((WAVEHDR*)msg.lParam);
-        aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength /
-                                            data->Format.nBlockAlign);
-
-        // Send buffer back to play more data
-        waveOutWrite(data->WaveHandle.Out, WaveHdr, sizeof(WAVEHDR));
-        IncrementRef(&data->WaveBuffersCommitted);
-    }
-
-    return 0;
-}
-
-/*
-    WaveInProc
-
-    Posts a message to 'CaptureThreadProc' everytime a WaveIn Buffer is completed and
-    returns to the application (with more data)
-*/
-static void CALLBACK WaveInProc(HWAVEIN UNUSED(device), UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR UNUSED(param2))
-{
-    ALCdevice *Device = (ALCdevice*)instance;
-    WinMMData *data = Device->ExtraData;
-
-    if(msg != WIM_DATA)
-        return;
-
-    DecrementRef(&data->WaveBuffersCommitted);
-    PostThreadMessage(data->thread, msg, 0, param1);
-}
-
-static int CaptureThreadProc(void *arg)
-{
-    ALCdevice *Device = (ALCdevice*)arg;
-    WinMMData *data = Device->ExtraData;
-    WAVEHDR *WaveHdr;
-    MSG msg;
-
-    althrd_setname(althrd_current(), "alsoft-record");
-
-    while(GetMessage(&msg, NULL, 0, 0))
-    {
-        if(msg.message != WIM_DATA)
-            continue;
-        /* Don't wait for other buffers to finish before quitting. We're
-         * closing so we don't need them. */
-        if(data->killNow)
-            break;
-
-        WaveHdr = ((WAVEHDR*)msg.lParam);
-        WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData,
-                        WaveHdr->dwBytesRecorded/data->Format.nBlockAlign);
-
-        // Send buffer back to capture more data
-        waveInAddBuffer(data->WaveHandle.In, WaveHdr, sizeof(WAVEHDR));
-        IncrementRef(&data->WaveBuffersCommitted);
-    }
-
-    return 0;
-}
-
-
-static ALCenum WinMMOpenPlayback(ALCdevice *Device, const ALCchar *deviceName)
-{
-    WinMMData *data = NULL;
-    const al_string *iter, *end;
-    UINT DeviceID;
-    MMRESULT res;
-
-    if(VECTOR_SIZE(PlaybackDevices) == 0)
-        ProbePlaybackDevices();
-
-    // Find the Device ID matching the deviceName if valid
-    iter = VECTOR_ITER_BEGIN(PlaybackDevices);
-    end = VECTOR_ITER_END(PlaybackDevices);
-    for(;iter != end;iter++)
-    {
-        if(!al_string_empty(*iter) &&
-           (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0))
-        {
-            DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(PlaybackDevices));
-            break;
-        }
-    }
-    if(iter == end)
-        return ALC_INVALID_VALUE;
-
-    data = calloc(1, sizeof(*data));
-    if(!data)
-        return ALC_OUT_OF_MEMORY;
-    Device->ExtraData = data;
-
-retry_open:
-    memset(&data->Format, 0, sizeof(WAVEFORMATEX));
-    if(Device->FmtType == DevFmtFloat)
-    {
-        data->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
-        data->Format.wBitsPerSample = 32;
-    }
-    else
-    {
-        data->Format.wFormatTag = WAVE_FORMAT_PCM;
-        if(Device->FmtType == DevFmtUByte || Device->FmtType == DevFmtByte)
-            data->Format.wBitsPerSample = 8;
-        else
-            data->Format.wBitsPerSample = 16;
-    }
-    data->Format.nChannels = ((Device->FmtChans == DevFmtMono) ? 1 : 2);
-    data->Format.nBlockAlign = data->Format.wBitsPerSample *
-                               data->Format.nChannels / 8;
-    data->Format.nSamplesPerSec = Device->Frequency;
-    data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec *
-                                   data->Format.nBlockAlign;
-    data->Format.cbSize = 0;
-
-    if((res=waveOutOpen(&data->WaveHandle.Out, DeviceID, &data->Format, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
-    {
-        if(Device->FmtType == DevFmtFloat)
-        {
-            Device->FmtType = DevFmtShort;
-            goto retry_open;
-        }
-        ERR("waveOutOpen failed: %u\n", res);
-        goto failure;
-    }
-
-    al_string_copy(&Device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID));
-    return ALC_NO_ERROR;
-
-failure:
-    if(data->WaveHandle.Out)
-        waveOutClose(data->WaveHandle.Out);
-
-    free(data);
-    Device->ExtraData = NULL;
-    return ALC_INVALID_VALUE;
-}
-
-static void WinMMClosePlayback(ALCdevice *device)
-{
-    WinMMData *data = (WinMMData*)device->ExtraData;
-
-    // Close the Wave device
-    waveOutClose(data->WaveHandle.Out);
-    data->WaveHandle.Out = 0;
-
-    free(data);
-    device->ExtraData = NULL;
-}
-
-static ALCboolean WinMMResetPlayback(ALCdevice *device)
-{
-    WinMMData *data = (WinMMData*)device->ExtraData;
-
-    device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
-                                  data->Format.nSamplesPerSec /
-                                  device->Frequency);
-    device->UpdateSize = (device->UpdateSize*device->NumUpdates + 3) / 4;
-    device->NumUpdates = 4;
-    device->Frequency = data->Format.nSamplesPerSec;
-
-    if(data->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
-    {
-        if(data->Format.wBitsPerSample == 32)
-            device->FmtType = DevFmtFloat;
-        else
-        {
-            ERR("Unhandled IEEE float sample depth: %d\n", data->Format.wBitsPerSample);
-            return ALC_FALSE;
-        }
-    }
-    else if(data->Format.wFormatTag == WAVE_FORMAT_PCM)
-    {
-        if(data->Format.wBitsPerSample == 16)
-            device->FmtType = DevFmtShort;
-        else if(data->Format.wBitsPerSample == 8)
-            device->FmtType = DevFmtUByte;
-        else
-        {
-            ERR("Unhandled PCM sample depth: %d\n", data->Format.wBitsPerSample);
-            return ALC_FALSE;
-        }
-    }
-    else
-    {
-        ERR("Unhandled format tag: 0x%04x\n", data->Format.wFormatTag);
-        return ALC_FALSE;
-    }
-
-    if(data->Format.nChannels == 2)
-        device->FmtChans = DevFmtStereo;
-    else if(data->Format.nChannels == 1)
-        device->FmtChans = DevFmtMono;
-    else
-    {
-        ERR("Unhandled channel count: %d\n", data->Format.nChannels);
-        return ALC_FALSE;
-    }
-    SetDefaultWFXChannelOrder(device);
-
-    return ALC_TRUE;
-}
-
-static ALCboolean WinMMStartPlayback(ALCdevice *device)
-{
-    WinMMData *data = (WinMMData*)device->ExtraData;
-    ALbyte *BufferData;
-    ALint BufferSize;
-    ALuint i;
-
-    data->killNow = AL_FALSE;
-    if(althrd_create(&data->thread, PlaybackThreadProc, device) != althrd_success)
-        return ALC_FALSE;
-
-    InitRef(&data->WaveBuffersCommitted, 0);
-
-    // Create 4 Buffers
-    BufferSize  = device->UpdateSize*device->NumUpdates / 4;
-    BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-
-    BufferData = calloc(4, BufferSize);
-    for(i = 0;i < 4;i++)
-    {
-        memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
-        data->WaveBuffer[i].dwBufferLength = BufferSize;
-        data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData :
-                                      (data->WaveBuffer[i-1].lpData +
-                                       data->WaveBuffer[i-1].dwBufferLength));
-        waveOutPrepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        waveOutWrite(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        IncrementRef(&data->WaveBuffersCommitted);
-    }
-
-    return ALC_TRUE;
-}
-
-static void WinMMStopPlayback(ALCdevice *device)
-{
-    WinMMData *data = (WinMMData*)device->ExtraData;
-    void *buffer = NULL;
-    int i;
-
-    if(data->killNow)
-        return;
-
-    // Set flag to stop processing headers
-    data->killNow = AL_TRUE;
-    althrd_join(data->thread, &i);
-
-    // Release the wave buffers
-    for(i = 0;i < 4;i++)
-    {
-        waveOutUnprepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        if(i == 0) buffer = data->WaveBuffer[i].lpData;
-        data->WaveBuffer[i].lpData = NULL;
-    }
-    free(buffer);
-}
-
-
-static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName)
-{
-    const al_string *iter, *end;
-    ALbyte *BufferData = NULL;
-    DWORD CapturedDataSize;
-    WinMMData *data = NULL;
-    ALint BufferSize;
-    UINT DeviceID;
-    MMRESULT res;
-    ALuint i;
-
-    if(VECTOR_SIZE(CaptureDevices) == 0)
-        ProbeCaptureDevices();
-
-    // Find the Device ID matching the deviceName if valid
-    iter = VECTOR_ITER_BEGIN(CaptureDevices);
-    end = VECTOR_ITER_END(CaptureDevices);
-    for(;iter != end;iter++)
-    {
-        if(!al_string_empty(*iter) &&
-           (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0))
-        {
-            DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(CaptureDevices));
-            break;
-        }
-    }
-    if(iter == end)
-        return ALC_INVALID_VALUE;
-
-    switch(Device->FmtChans)
-    {
-        case DevFmtMono:
-        case DevFmtStereo:
-            break;
-
-        case DevFmtQuad:
-        case DevFmtX51:
-        case DevFmtX51Side:
-        case DevFmtX61:
-        case DevFmtX71:
-            return ALC_INVALID_ENUM;
-    }
-
-    switch(Device->FmtType)
-    {
-        case DevFmtUByte:
-        case DevFmtShort:
-        case DevFmtInt:
-        case DevFmtFloat:
-            break;
-
-        case DevFmtByte:
-        case DevFmtUShort:
-        case DevFmtUInt:
-            return ALC_INVALID_ENUM;
-    }
-
-    data = calloc(1, sizeof(*data));
-    if(!data)
-        return ALC_OUT_OF_MEMORY;
-    Device->ExtraData = data;
-
-    memset(&data->Format, 0, sizeof(WAVEFORMATEX));
-    data->Format.wFormatTag = ((Device->FmtType == DevFmtFloat) ?
-                               WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
-    data->Format.nChannels = ChannelsFromDevFmt(Device->FmtChans);
-    data->Format.wBitsPerSample = BytesFromDevFmt(Device->FmtType) * 8;
-    data->Format.nBlockAlign = data->Format.wBitsPerSample *
-                               data->Format.nChannels / 8;
-    data->Format.nSamplesPerSec = Device->Frequency;
-    data->Format.nAvgBytesPerSec = data->Format.nSamplesPerSec *
-                                   data->Format.nBlockAlign;
-    data->Format.cbSize = 0;
-
-    if((res=waveInOpen(&data->WaveHandle.In, DeviceID, &data->Format, (DWORD_PTR)&WaveInProc, (DWORD_PTR)Device, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
-    {
-        ERR("waveInOpen failed: %u\n", res);
-        goto failure;
-    }
-
-    // Allocate circular memory buffer for the captured audio
-    CapturedDataSize = Device->UpdateSize*Device->NumUpdates;
-
-    // Make sure circular buffer is at least 100ms in size
-    if(CapturedDataSize < (data->Format.nSamplesPerSec / 10))
-        CapturedDataSize = data->Format.nSamplesPerSec / 10;
-
-    data->Ring = CreateRingBuffer(data->Format.nBlockAlign, CapturedDataSize);
-    if(!data->Ring)
-        goto failure;
-
-    InitRef(&data->WaveBuffersCommitted, 0);
-
-    // Create 4 Buffers of 50ms each
-    BufferSize = data->Format.nAvgBytesPerSec / 20;
-    BufferSize -= (BufferSize % data->Format.nBlockAlign);
-
-    BufferData = calloc(4, BufferSize);
-    if(!BufferData)
-        goto failure;
-
-    for(i = 0;i < 4;i++)
-    {
-        memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR));
-        data->WaveBuffer[i].dwBufferLength = BufferSize;
-        data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData :
-                                      (data->WaveBuffer[i-1].lpData +
-                                       data->WaveBuffer[i-1].dwBufferLength));
-        data->WaveBuffer[i].dwFlags = 0;
-        data->WaveBuffer[i].dwLoops = 0;
-        waveInPrepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        waveInAddBuffer(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        IncrementRef(&data->WaveBuffersCommitted);
-    }
-
-    if(althrd_create(&data->thread, CaptureThreadProc, Device) != althrd_success)
-        goto failure;
-
-    al_string_copy(&Device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID));
-    return ALC_NO_ERROR;
-
-failure:
-    if(BufferData)
-    {
-        for(i = 0;i < 4;i++)
-            waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        free(BufferData);
-    }
-
-    if(data->Ring)
-        DestroyRingBuffer(data->Ring);
-
-    if(data->WaveHandle.In)
-        waveInClose(data->WaveHandle.In);
-
-    free(data);
-    Device->ExtraData = NULL;
-    return ALC_INVALID_VALUE;
-}
-
-static void WinMMCloseCapture(ALCdevice *Device)
-{
-    WinMMData *data = (WinMMData*)Device->ExtraData;
-    void *buffer = NULL;
-    int i;
-
-    /* Tell the processing thread to quit and wait for it to do so. */
-    data->killNow = AL_TRUE;
-    PostThreadMessage(data->thread, WM_QUIT, 0, 0);
-
-    althrd_join(data->thread, &i);
-
-    /* Make sure capture is stopped and all pending buffers are flushed. */
-    waveInReset(data->WaveHandle.In);
-
-    // Release the wave buffers
-    for(i = 0;i < 4;i++)
-    {
-        waveInUnprepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR));
-        if(i == 0) buffer = data->WaveBuffer[i].lpData;
-        data->WaveBuffer[i].lpData = NULL;
-    }
-    free(buffer);
-
-    DestroyRingBuffer(data->Ring);
-    data->Ring = NULL;
-
-    // Close the Wave device
-    waveInClose(data->WaveHandle.In);
-    data->WaveHandle.In = 0;
-
-    free(data);
-    Device->ExtraData = NULL;
-}
-
-static void WinMMStartCapture(ALCdevice *Device)
-{
-    WinMMData *data = (WinMMData*)Device->ExtraData;
-    waveInStart(data->WaveHandle.In);
-}
-
-static void WinMMStopCapture(ALCdevice *Device)
-{
-    WinMMData *data = (WinMMData*)Device->ExtraData;
-    waveInStop(data->WaveHandle.In);
-}
-
-static ALCenum WinMMCaptureSamples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples)
-{
-    WinMMData *data = (WinMMData*)Device->ExtraData;
-    ReadRingBuffer(data->Ring, Buffer, Samples);
-    return ALC_NO_ERROR;
-}
-
-static ALCuint WinMMAvailableSamples(ALCdevice *Device)
-{
-    WinMMData *data = (WinMMData*)Device->ExtraData;
-    return RingBufferSize(data->Ring);
-}
-
-
-static inline void AppendAllDevicesList2(const al_string *name)
-{
-    if(!al_string_empty(*name))
-        AppendAllDevicesList(al_string_get_cstr(*name));
-}
-static inline void AppendCaptureDeviceList2(const al_string *name)
-{
-    if(!al_string_empty(*name))
-        AppendCaptureDeviceList(al_string_get_cstr(*name));
-}
-
-static const BackendFuncs WinMMFuncs = {
-    WinMMOpenPlayback,
-    WinMMClosePlayback,
-    WinMMResetPlayback,
-    WinMMStartPlayback,
-    WinMMStopPlayback,
-    WinMMOpenCapture,
-    WinMMCloseCapture,
-    WinMMStartCapture,
-    WinMMStopCapture,
-    WinMMCaptureSamples,
-    WinMMAvailableSamples,
-    ALCdevice_GetLatencyDefault
-};
-
-ALCboolean alcWinMMInit(BackendFuncs *FuncList)
-{
-    VECTOR_INIT(PlaybackDevices);
-    VECTOR_INIT(CaptureDevices);
-
-    *FuncList = WinMMFuncs;
-    return ALC_TRUE;
-}
-
-void alcWinMMDeinit()
-{
-    clear_devlist(&PlaybackDevices);
-    VECTOR_DEINIT(PlaybackDevices);
-
-    clear_devlist(&CaptureDevices);
-    VECTOR_DEINIT(CaptureDevices);
-}
-
-void alcWinMMProbe(enum DevProbe type)
-{
-    switch(type)
-    {
-        case ALL_DEVICE_PROBE:
-            ProbePlaybackDevices();
-            VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2);
-            break;
-
-        case CAPTURE_DEVICE_PROBE:
-            ProbeCaptureDevices();
-            VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2);
-            break;
-    }
-}

+ 0 - 272
love/src/jni/openal-soft-1.17.0/Alc/effects/autowah.c

@@ -1,272 +0,0 @@
-/**
- * OpenAL cross platform audio library
- * Copyright (C) 2013 by Anis A. Hireche, Nasca Octavian Paul
- * This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include <stdlib.h>
-
-#include "config.h"
-#include "alu.h"
-#include "alFilter.h"
-#include "alError.h"
-#include "alMain.h"
-#include "alAuxEffectSlot.h"
-
-
-/* Auto-wah is simply a low-pass filter with a cutoff frequency that shifts up
- * or down depending on the input signal, and a resonant peak at the cutoff.
- *
- * Currently, we assume a cutoff frequency range of 500hz (no amplitude) to
- * 3khz (peak gain). Peak gain is assumed to be in normalized scale.
- */
-
-typedef struct ALautowahState {
-    DERIVE_FROM_TYPE(ALeffectState);
-
-    /* Effect gains for each channel */
-    ALfloat Gain[MaxChannels];
-
-    /* Effect parameters */
-    ALfloat AttackRate;
-    ALfloat ReleaseRate;
-    ALfloat Resonance;
-    ALfloat PeakGain;
-    ALfloat GainCtrl;
-    ALfloat Frequency;
-
-    /* Samples processing */
-    ALfilterState LowPass;
-} ALautowahState;
-
-static ALvoid ALautowahState_Destruct(ALautowahState *UNUSED(state))
-{
-}
-
-static ALboolean ALautowahState_deviceUpdate(ALautowahState *state, ALCdevice *device)
-{
-    state->Frequency = (ALfloat)device->Frequency;
-    return AL_TRUE;
-}
-
-static ALvoid ALautowahState_update(ALautowahState *state, ALCdevice *device, const ALeffectslot *slot)
-{
-    ALfloat attackTime, releaseTime;
-    ALfloat gain;
-
-    attackTime = slot->EffectProps.Autowah.AttackTime * state->Frequency;
-    releaseTime = slot->EffectProps.Autowah.ReleaseTime * state->Frequency;
-
-    state->AttackRate = powf(1.0f/GAIN_SILENCE_THRESHOLD, 1.0f/attackTime);
-    state->ReleaseRate = powf(GAIN_SILENCE_THRESHOLD/1.0f, 1.0f/releaseTime);
-    state->PeakGain = slot->EffectProps.Autowah.PeakGain;
-    state->Resonance = slot->EffectProps.Autowah.Resonance;
-
-    gain = sqrtf(1.0f / device->NumChan) * slot->Gain;
-    SetGains(device, gain, state->Gain);
-}
-
-static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE])
-{
-    ALuint it, kt;
-    ALuint base;
-
-    for(base = 0;base < SamplesToDo;)
-    {
-        ALfloat temps[64];
-        ALuint td = minu(SamplesToDo-base, 64);
-        ALfloat gain = state->GainCtrl;
-
-        for(it = 0;it < td;it++)
-        {
-            ALfloat smp = SamplesIn[it+base];
-            ALfloat alpha, w0;
-            ALfloat amplitude;
-            ALfloat cutoff;
-
-            /* Similar to compressor, we get the current amplitude of the
-             * incoming signal, and attack or release to reach it. */
-            amplitude = fabsf(smp);
-            if(amplitude > gain)
-                gain = minf(gain*state->AttackRate, amplitude);
-            else if(amplitude < gain)
-                gain = maxf(gain*state->ReleaseRate, amplitude);
-            gain = maxf(gain, GAIN_SILENCE_THRESHOLD);
-
-            /* FIXME: What range does the filter cover? */
-            cutoff = lerp(20.0f, 20000.0f, minf(gain/state->PeakGain, 1.0f));
-
-            /* The code below is like calling ALfilterState_setParams with
-             * ALfilterType_LowPass. However, instead of passing a bandwidth,
-             * we use the resonance property for Q. This also inlines the call.
-             */
-            w0 = F_2PI * cutoff / state->Frequency;
-
-            /* FIXME: Resonance controls the resonant peak, or Q. How? Not sure
-             * that Q = resonance*0.1. */
-            alpha = sinf(w0) / (2.0f * state->Resonance*0.1f);
-            state->LowPass.b[0] = (1.0f - cosf(w0)) / 2.0f;
-            state->LowPass.b[1] =  1.0f - cosf(w0);
-            state->LowPass.b[2] = (1.0f - cosf(w0)) / 2.0f;
-            state->LowPass.a[0] =  1.0f + alpha;
-            state->LowPass.a[1] = -2.0f * cosf(w0);
-            state->LowPass.a[2] =  1.0f - alpha;
-
-            state->LowPass.b[2] /= state->LowPass.a[0];
-            state->LowPass.b[1] /= state->LowPass.a[0];
-            state->LowPass.b[0] /= state->LowPass.a[0];
-            state->LowPass.a[2] /= state->LowPass.a[0];
-            state->LowPass.a[1] /= state->LowPass.a[0];
-            state->LowPass.a[0] /= state->LowPass.a[0];
-
-            temps[it] = ALfilterState_processSingle(&state->LowPass, smp);
-        }
-        state->GainCtrl = gain;
-
-        for(kt = 0;kt < MaxChannels;kt++)
-        {
-            ALfloat gain = state->Gain[kt];
-            if(!(gain > GAIN_SILENCE_THRESHOLD))
-                continue;
-
-            for(it = 0;it < td;it++)
-                SamplesOut[kt][base+it] += gain * temps[it];
-        }
-
-        base += td;
-    }
-}
-
-DECLARE_DEFAULT_ALLOCATORS(ALautowahState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALautowahState);
-
-
-typedef struct ALautowahStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALautowahStateFactory;
-
-static ALeffectState *ALautowahStateFactory_create(ALautowahStateFactory *UNUSED(factory))
-{
-    ALautowahState *state;
-
-    state = ALautowahState_New(sizeof(*state));
-    if(!state) return NULL;
-    SET_VTABLE2(ALautowahState, ALeffectState, state);
-
-    state->AttackRate = 1.0f;
-    state->ReleaseRate = 1.0f;
-    state->Resonance = 2.0f;
-    state->PeakGain = 1.0f;
-    state->GainCtrl = 1.0f;
-
-    ALfilterState_clear(&state->LowPass);
-
-    return STATIC_CAST(ALeffectState, state);
-}
-
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALautowahStateFactory);
-
-ALeffectStateFactory *ALautowahStateFactory_getFactory(void)
-{
-    static ALautowahStateFactory AutowahFactory = { { GET_VTABLE2(ALautowahStateFactory, ALeffectStateFactory) } };
-
-    return STATIC_CAST(ALeffectStateFactory, &AutowahFactory);
-}
-
-
-void ALautowah_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALautowah_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALautowah_setParami(effect, context, param, vals[0]);
-}
-void ALautowah_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
-{
-    ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_AUTOWAH_ATTACK_TIME:
-            if(!(val >= AL_AUTOWAH_MIN_ATTACK_TIME && val <= AL_AUTOWAH_MAX_ATTACK_TIME))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Autowah.AttackTime = val;
-            break;
-
-        case AL_AUTOWAH_RELEASE_TIME:
-            if(!(val >= AL_AUTOWAH_MIN_RELEASE_TIME && val <= AL_AUTOWAH_MAX_RELEASE_TIME))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Autowah.ReleaseTime = val;
-            break;
-
-        case AL_AUTOWAH_RESONANCE:
-            if(!(val >= AL_AUTOWAH_MIN_RESONANCE && val <= AL_AUTOWAH_MAX_RESONANCE))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Autowah.Resonance = val;
-            break;
-
-        case AL_AUTOWAH_PEAK_GAIN:
-            if(!(val >= AL_AUTOWAH_MIN_PEAK_GAIN && val <= AL_AUTOWAH_MAX_PEAK_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Autowah.PeakGain = val;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALautowah_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALautowah_setParamf(effect, context, param, vals[0]);
-}
-
-void ALautowah_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val))
-{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); }
-void ALautowah_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALautowah_getParami(effect, context, param, vals);
-}
-void ALautowah_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
-{
-    const ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_AUTOWAH_ATTACK_TIME:
-            *val = props->Autowah.AttackTime;
-            break;
-
-        case AL_AUTOWAH_RELEASE_TIME:
-            *val = props->Autowah.ReleaseTime;
-            break;
-
-        case AL_AUTOWAH_RESONANCE:
-            *val = props->Autowah.Resonance;
-            break;
-
-        case AL_AUTOWAH_PEAK_GAIN:
-            *val = props->Autowah.PeakGain;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALautowah_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALautowah_getParamf(effect, context, param, vals);
-}
-
-DEFINE_ALEFFECT_VTABLE(ALautowah);

+ 0 - 1779
love/src/jni/openal-soft-1.17.0/Alc/effects/reverb.c

@@ -1,1779 +0,0 @@
-/**
- * Reverb for the OpenAL cross platform audio library
- * Copyright (C) 2008-2009 by Christopher Fitzgerald.
- * This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <math.h>
-
-#include "alMain.h"
-#include "alu.h"
-#include "alAuxEffectSlot.h"
-#include "alEffect.h"
-#include "alFilter.h"
-#include "alError.h"
-
-
-typedef struct DelayLine
-{
-    // The delay lines use sample lengths that are powers of 2 to allow the
-    // use of bit-masking instead of a modulus for wrapping.
-    ALuint   Mask;
-    ALfloat *Line;
-} DelayLine;
-
-typedef struct ALreverbState {
-    DERIVE_FROM_TYPE(ALeffectState);
-
-    ALboolean IsEax;
-
-    // All delay lines are allocated as a single buffer to reduce memory
-    // fragmentation and management code.
-    ALfloat  *SampleBuffer;
-    ALuint    TotalSamples;
-
-    // Master effect filters
-    ALfilterState LpFilter;
-    ALfilterState HpFilter; // EAX only
-
-    struct {
-        // Modulator delay line.
-        DelayLine Delay;
-
-        // The vibrato time is tracked with an index over a modulus-wrapped
-        // range (in samples).
-        ALuint    Index;
-        ALuint    Range;
-
-        // The depth of frequency change (also in samples) and its filter.
-        ALfloat   Depth;
-        ALfloat   Coeff;
-        ALfloat   Filter;
-    } Mod;
-
-    // Initial effect delay.
-    DelayLine Delay;
-    // The tap points for the initial delay.  First tap goes to early
-    // reflections, the last to late reverb.
-    ALuint    DelayTap[2];
-
-    struct {
-        // Output gain for early reflections.
-        ALfloat   Gain;
-
-        // Early reflections are done with 4 delay lines.
-        ALfloat   Coeff[4];
-        DelayLine Delay[4];
-        ALuint    Offset[4];
-
-        // The gain for each output channel based on 3D panning (only for the
-        // EAX path).
-        ALfloat   PanGain[MaxChannels];
-    } Early;
-
-    // Decorrelator delay line.
-    DelayLine Decorrelator;
-    // There are actually 4 decorrelator taps, but the first occurs at the
-    // initial sample.
-    ALuint    DecoTap[3];
-
-    struct {
-        // Output gain for late reverb.
-        ALfloat   Gain;
-
-        // Attenuation to compensate for the modal density and decay rate of
-        // the late lines.
-        ALfloat   DensityGain;
-
-        // The feed-back and feed-forward all-pass coefficient.
-        ALfloat   ApFeedCoeff;
-
-        // Mixing matrix coefficient.
-        ALfloat   MixCoeff;
-
-        // Late reverb has 4 parallel all-pass filters.
-        ALfloat   ApCoeff[4];
-        DelayLine ApDelay[4];
-        ALuint    ApOffset[4];
-
-        // In addition to 4 cyclical delay lines.
-        ALfloat   Coeff[4];
-        DelayLine Delay[4];
-        ALuint    Offset[4];
-
-        // The cyclical delay lines are 1-pole low-pass filtered.
-        ALfloat   LpCoeff[4];
-        ALfloat   LpSample[4];
-
-        // The gain for each output channel based on 3D panning (only for the
-        // EAX path).
-        ALfloat   PanGain[MaxChannels];
-    } Late;
-
-    struct {
-        // Attenuation to compensate for the modal density and decay rate of
-        // the echo line.
-        ALfloat   DensityGain;
-
-        // Echo delay and all-pass lines.
-        DelayLine Delay;
-        DelayLine ApDelay;
-
-        ALfloat   Coeff;
-        ALfloat   ApFeedCoeff;
-        ALfloat   ApCoeff;
-
-        ALuint    Offset;
-        ALuint    ApOffset;
-
-        // The echo line is 1-pole low-pass filtered.
-        ALfloat   LpCoeff;
-        ALfloat   LpSample;
-
-        // Echo mixing coefficients.
-        ALfloat   MixCoeff[2];
-    } Echo;
-
-    // The current read offset for all delay lines.
-    ALuint Offset;
-
-    // The gain for each output channel (non-EAX path only; aliased from
-    // Late.PanGain)
-    ALfloat *Gain;
-
-    /* Temporary storage used when processing, before deinterlacing. */
-    ALfloat ReverbSamples[BUFFERSIZE][4];
-    ALfloat EarlySamples[BUFFERSIZE][4];
-} ALreverbState;
-
-/* This is a user config option for modifying the overall output of the reverb
- * effect.
- */
-ALfloat ReverbBoost = 1.0f;
-
-/* Specifies whether to use a standard reverb effect in place of EAX reverb */
-ALboolean EmulateEAXReverb = AL_FALSE;
-
-/* This coefficient is used to define the maximum frequency range controlled
- * by the modulation depth.  The current value of 0.1 will allow it to swing
- * from 0.9x to 1.1x.  This value must be below 1.  At 1 it will cause the
- * sampler to stall on the downswing, and above 1 it will cause it to sample
- * backwards.
- */
-static const ALfloat MODULATION_DEPTH_COEFF = 0.1f;
-
-/* A filter is used to avoid the terrible distortion caused by changing
- * modulation time and/or depth.  To be consistent across different sample
- * rates, the coefficient must be raised to a constant divided by the sample
- * rate:  coeff^(constant / rate).
- */
-static const ALfloat MODULATION_FILTER_COEFF = 0.048f;
-static const ALfloat MODULATION_FILTER_CONST = 100000.0f;
-
-// When diffusion is above 0, an all-pass filter is used to take the edge off
-// the echo effect.  It uses the following line length (in seconds).
-static const ALfloat ECHO_ALLPASS_LENGTH = 0.0133f;
-
-// Input into the late reverb is decorrelated between four channels.  Their
-// timings are dependent on a fraction and multiplier.  See the
-// UpdateDecorrelator() routine for the calculations involved.
-static const ALfloat DECO_FRACTION = 0.15f;
-static const ALfloat DECO_MULTIPLIER = 2.0f;
-
-// All delay line lengths are specified in seconds.
-
-// The lengths of the early delay lines.
-static const ALfloat EARLY_LINE_LENGTH[4] =
-{
-    0.0015f, 0.0045f, 0.0135f, 0.0405f
-};
-
-// The lengths of the late all-pass delay lines.
-static const ALfloat ALLPASS_LINE_LENGTH[4] =
-{
-    0.0151f, 0.0167f, 0.0183f, 0.0200f,
-};
-
-// The lengths of the late cyclical delay lines.
-static const ALfloat LATE_LINE_LENGTH[4] =
-{
-    0.0211f, 0.0311f, 0.0461f, 0.0680f
-};
-
-// The late cyclical delay lines have a variable length dependent on the
-// effect's density parameter (inverted for some reason) and this multiplier.
-static const ALfloat LATE_LINE_MULTIPLIER = 4.0f;
-
-
-// Basic delay line input/output routines.
-static inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset)
-{
-    return Delay->Line[offset&Delay->Mask];
-}
-
-static inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in)
-{
-    Delay->Line[offset&Delay->Mask] = in;
-}
-
-// Attenuated delay line output routine.
-static inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff)
-{
-    return coeff * Delay->Line[offset&Delay->Mask];
-}
-
-// Basic attenuated all-pass input/output routine.
-static inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff)
-{
-    ALfloat out, feed;
-
-    out = DelayLineOut(Delay, outOffset);
-    feed = feedCoeff * in;
-    DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in);
-
-    // The time-based attenuation is only applied to the delay output to
-    // keep it from affecting the feed-back path (which is already controlled
-    // by the all-pass feed coefficient).
-    return (coeff * out) - feed;
-}
-
-// Given an input sample, this function produces modulation for the late
-// reverb.
-static inline ALfloat EAXModulation(ALreverbState *State, ALfloat in)
-{
-    ALfloat sinus, frac;
-    ALuint offset;
-    ALfloat out0, out1;
-
-    // Calculate the sinus rythm (dependent on modulation time and the
-    // sampling rate).  The center of the sinus is moved to reduce the delay
-    // of the effect when the time or depth are low.
-    sinus = 1.0f - cosf(F_2PI * State->Mod.Index / State->Mod.Range);
-
-    // The depth determines the range over which to read the input samples
-    // from, so it must be filtered to reduce the distortion caused by even
-    // small parameter changes.
-    State->Mod.Filter = lerp(State->Mod.Filter, State->Mod.Depth,
-                             State->Mod.Coeff);
-
-    // Calculate the read offset and fraction between it and the next sample.
-    frac   = (1.0f + (State->Mod.Filter * sinus));
-    offset = fastf2u(frac);
-    frac  -= offset;
-
-    // Get the two samples crossed by the offset, and feed the delay line
-    // with the next input sample.
-    out0 = DelayLineOut(&State->Mod.Delay, State->Offset - offset);
-    out1 = DelayLineOut(&State->Mod.Delay, State->Offset - offset - 1);
-    DelayLineIn(&State->Mod.Delay, State->Offset, in);
-
-    // Step the modulation index forward, keeping it bound to its range.
-    State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range;
-
-    // The output is obtained by linearly interpolating the two samples that
-    // were acquired above.
-    return lerp(out0, out1, frac);
-}
-
-// Delay line output routine for early reflections.
-static inline ALfloat EarlyDelayLineOut(ALreverbState *State, ALuint index)
-{
-    return AttenuatedDelayLineOut(&State->Early.Delay[index],
-                                  State->Offset - State->Early.Offset[index],
-                                  State->Early.Coeff[index]);
-}
-
-// Given an input sample, this function produces four-channel output for the
-// early reflections.
-static inline ALvoid EarlyReflection(ALreverbState *State, ALfloat in, ALfloat *restrict out)
-{
-    ALfloat d[4], v, f[4];
-
-    // Obtain the decayed results of each early delay line.
-    d[0] = EarlyDelayLineOut(State, 0);
-    d[1] = EarlyDelayLineOut(State, 1);
-    d[2] = EarlyDelayLineOut(State, 2);
-    d[3] = EarlyDelayLineOut(State, 3);
-
-    /* The following uses a lossless scattering junction from waveguide
-     * theory.  It actually amounts to a householder mixing matrix, which
-     * will produce a maximally diffuse response, and means this can probably
-     * be considered a simple feed-back delay network (FDN).
-     *          N
-     *         ---
-     *         \
-     * v = 2/N /   d_i
-     *         ---
-     *         i=1
-     */
-    v = (d[0] + d[1] + d[2] + d[3]) * 0.5f;
-    // The junction is loaded with the input here.
-    v += in;
-
-    // Calculate the feed values for the delay lines.
-    f[0] = v - d[0];
-    f[1] = v - d[1];
-    f[2] = v - d[2];
-    f[3] = v - d[3];
-
-    // Re-feed the delay lines.
-    DelayLineIn(&State->Early.Delay[0], State->Offset, f[0]);
-    DelayLineIn(&State->Early.Delay[1], State->Offset, f[1]);
-    DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]);
-    DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]);
-
-    // Output the results of the junction for all four channels.
-    out[0] = State->Early.Gain * f[0];
-    out[1] = State->Early.Gain * f[1];
-    out[2] = State->Early.Gain * f[2];
-    out[3] = State->Early.Gain * f[3];
-}
-
-// All-pass input/output routine for late reverb.
-static inline ALfloat LateAllPassInOut(ALreverbState *State, ALuint index, ALfloat in)
-{
-    return AllpassInOut(&State->Late.ApDelay[index],
-                        State->Offset - State->Late.ApOffset[index],
-                        State->Offset, in, State->Late.ApFeedCoeff,
-                        State->Late.ApCoeff[index]);
-}
-
-// Delay line output routine for late reverb.
-static inline ALfloat LateDelayLineOut(ALreverbState *State, ALuint index)
-{
-    return AttenuatedDelayLineOut(&State->Late.Delay[index],
-                                  State->Offset - State->Late.Offset[index],
-                                  State->Late.Coeff[index]);
-}
-
-// Low-pass filter input/output routine for late reverb.
-static inline ALfloat LateLowPassInOut(ALreverbState *State, ALuint index, ALfloat in)
-{
-    in = lerp(in, State->Late.LpSample[index], State->Late.LpCoeff[index]);
-    State->Late.LpSample[index] = in;
-    return in;
-}
-
-// Given four decorrelated input samples, this function produces four-channel
-// output for the late reverb.
-static inline ALvoid LateReverb(ALreverbState *State, const ALfloat *restrict in, ALfloat *restrict out)
-{
-    ALfloat d[4], f[4];
-
-    // Obtain the decayed results of the cyclical delay lines, and add the
-    // corresponding input channels.  Then pass the results through the
-    // low-pass filters.
-
-    // This is where the feed-back cycles from line 0 to 1 to 3 to 2 and back
-    // to 0.
-    d[0] = LateLowPassInOut(State, 2, in[2] + LateDelayLineOut(State, 2));
-    d[1] = LateLowPassInOut(State, 0, in[0] + LateDelayLineOut(State, 0));
-    d[2] = LateLowPassInOut(State, 3, in[3] + LateDelayLineOut(State, 3));
-    d[3] = LateLowPassInOut(State, 1, in[1] + LateDelayLineOut(State, 1));
-
-    // To help increase diffusion, run each line through an all-pass filter.
-    // When there is no diffusion, the shortest all-pass filter will feed the
-    // shortest delay line.
-    d[0] = LateAllPassInOut(State, 0, d[0]);
-    d[1] = LateAllPassInOut(State, 1, d[1]);
-    d[2] = LateAllPassInOut(State, 2, d[2]);
-    d[3] = LateAllPassInOut(State, 3, d[3]);
-
-    /* Late reverb is done with a modified feed-back delay network (FDN)
-     * topology.  Four input lines are each fed through their own all-pass
-     * filter and then into the mixing matrix.  The four outputs of the
-     * mixing matrix are then cycled back to the inputs.  Each output feeds
-     * a different input to form a circlular feed cycle.
-     *
-     * The mixing matrix used is a 4D skew-symmetric rotation matrix derived
-     * using a single unitary rotational parameter:
-     *
-     *  [  d,  a,  b,  c ]          1 = a^2 + b^2 + c^2 + d^2
-     *  [ -a,  d,  c, -b ]
-     *  [ -b, -c,  d,  a ]
-     *  [ -c,  b, -a,  d ]
-     *
-     * The rotation is constructed from the effect's diffusion parameter,
-     * yielding:  1 = x^2 + 3 y^2; where a, b, and c are the coefficient y
-     * with differing signs, and d is the coefficient x.  The matrix is thus:
-     *
-     *  [  x,  y, -y,  y ]          n = sqrt(matrix_order - 1)
-     *  [ -y,  x,  y,  y ]          t = diffusion_parameter * atan(n)
-     *  [  y, -y,  x,  y ]          x = cos(t)
-     *  [ -y, -y, -y,  x ]          y = sin(t) / n
-     *
-     * To reduce the number of multiplies, the x coefficient is applied with
-     * the cyclical delay line coefficients.  Thus only the y coefficient is
-     * applied when mixing, and is modified to be:  y / x.
-     */
-    f[0] = d[0] + (State->Late.MixCoeff * (         d[1] + -d[2] + d[3]));
-    f[1] = d[1] + (State->Late.MixCoeff * (-d[0]         +  d[2] + d[3]));
-    f[2] = d[2] + (State->Late.MixCoeff * ( d[0] + -d[1]         + d[3]));
-    f[3] = d[3] + (State->Late.MixCoeff * (-d[0] + -d[1] + -d[2]       ));
-
-    // Output the results of the matrix for all four channels, attenuated by
-    // the late reverb gain (which is attenuated by the 'x' mix coefficient).
-    out[0] = State->Late.Gain * f[0];
-    out[1] = State->Late.Gain * f[1];
-    out[2] = State->Late.Gain * f[2];
-    out[3] = State->Late.Gain * f[3];
-
-    // Re-feed the cyclical delay lines.
-    DelayLineIn(&State->Late.Delay[0], State->Offset, f[0]);
-    DelayLineIn(&State->Late.Delay[1], State->Offset, f[1]);
-    DelayLineIn(&State->Late.Delay[2], State->Offset, f[2]);
-    DelayLineIn(&State->Late.Delay[3], State->Offset, f[3]);
-}
-
-// Given an input sample, this function mixes echo into the four-channel late
-// reverb.
-static inline ALvoid EAXEcho(ALreverbState *State, ALfloat in, ALfloat *restrict late)
-{
-    ALfloat out, feed;
-
-    // Get the latest attenuated echo sample for output.
-    feed = AttenuatedDelayLineOut(&State->Echo.Delay,
-                                  State->Offset - State->Echo.Offset,
-                                  State->Echo.Coeff);
-
-    // Mix the output into the late reverb channels.
-    out = State->Echo.MixCoeff[0] * feed;
-    late[0] = (State->Echo.MixCoeff[1] * late[0]) + out;
-    late[1] = (State->Echo.MixCoeff[1] * late[1]) + out;
-    late[2] = (State->Echo.MixCoeff[1] * late[2]) + out;
-    late[3] = (State->Echo.MixCoeff[1] * late[3]) + out;
-
-    // Mix the energy-attenuated input with the output and pass it through
-    // the echo low-pass filter.
-    feed += State->Echo.DensityGain * in;
-    feed = lerp(feed, State->Echo.LpSample, State->Echo.LpCoeff);
-    State->Echo.LpSample = feed;
-
-    // Then the echo all-pass filter.
-    feed = AllpassInOut(&State->Echo.ApDelay,
-                        State->Offset - State->Echo.ApOffset,
-                        State->Offset, feed, State->Echo.ApFeedCoeff,
-                        State->Echo.ApCoeff);
-
-    // Feed the delay with the mixed and filtered sample.
-    DelayLineIn(&State->Echo.Delay, State->Offset, feed);
-}
-
-// Perform the non-EAX reverb pass on a given input sample, resulting in
-// four-channel output.
-static inline ALvoid VerbPass(ALreverbState *State, ALfloat in, ALfloat *restrict out)
-{
-    ALfloat feed, late[4], taps[4];
-
-    // Filter the incoming sample.
-    in = ALfilterState_processSingle(&State->LpFilter, in);
-
-    // Feed the initial delay line.
-    DelayLineIn(&State->Delay, State->Offset, in);
-
-    // Calculate the early reflection from the first delay tap.
-    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
-    EarlyReflection(State, in, out);
-
-    // Feed the decorrelator from the energy-attenuated output of the second
-    // delay tap.
-    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
-    feed = in * State->Late.DensityGain;
-    DelayLineIn(&State->Decorrelator, State->Offset, feed);
-
-    // Calculate the late reverb from the decorrelator taps.
-    taps[0] = feed;
-    taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
-    taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
-    taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
-    LateReverb(State, taps, late);
-
-    // Mix early reflections and late reverb.
-    out[0] += late[0];
-    out[1] += late[1];
-    out[2] += late[2];
-    out[3] += late[3];
-
-    // Step all delays forward one sample.
-    State->Offset++;
-}
-
-// Perform the EAX reverb pass on a given input sample, resulting in four-
-// channel output.
-static inline ALvoid EAXVerbPass(ALreverbState *State, ALfloat in, ALfloat *restrict early, ALfloat *restrict late)
-{
-    ALfloat feed, taps[4];
-
-    // Low-pass filter the incoming sample.
-    in = ALfilterState_processSingle(&State->LpFilter, in);
-    in = ALfilterState_processSingle(&State->HpFilter, in);
-
-    // Perform any modulation on the input.
-    in = EAXModulation(State, in);
-
-    // Feed the initial delay line.
-    DelayLineIn(&State->Delay, State->Offset, in);
-
-    // Calculate the early reflection from the first delay tap.
-    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]);
-    EarlyReflection(State, in, early);
-
-    // Feed the decorrelator from the energy-attenuated output of the second
-    // delay tap.
-    in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]);
-    feed = in * State->Late.DensityGain;
-    DelayLineIn(&State->Decorrelator, State->Offset, feed);
-
-    // Calculate the late reverb from the decorrelator taps.
-    taps[0] = feed;
-    taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]);
-    taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]);
-    taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]);
-    LateReverb(State, taps, late);
-
-    // Calculate and mix in any echo.
-    EAXEcho(State, in, late);
-
-    // Step all delays forward one sample.
-    State->Offset++;
-}
-
-static ALvoid ALreverbState_processStandard(ALreverbState *State, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
-{
-    ALfloat (*restrict out)[4] = State->ReverbSamples;
-    ALuint index, c;
-
-    /* Process reverb for these samples. */
-    for(index = 0;index < SamplesToDo;index++)
-        VerbPass(State, SamplesIn[index], out[index]);
-
-    for(c = 0;c < MaxChannels;c++)
-    {
-        ALfloat gain = State->Gain[c];
-        if(!(gain > GAIN_SILENCE_THRESHOLD))
-            continue;
-
-        for(index = 0;index < SamplesToDo;index++)
-            SamplesOut[c][index] += gain * out[index][c&3];
-    }
-}
-
-static ALvoid ALreverbState_processEax(ALreverbState *State, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
-{
-    ALfloat (*restrict early)[4] = State->EarlySamples;
-    ALfloat (*restrict late)[4] = State->ReverbSamples;
-    ALuint index, c;
-
-    /* Process reverb for these samples. */
-    for(index = 0;index < SamplesToDo;index++)
-        EAXVerbPass(State, SamplesIn[index], early[index], late[index]);
-
-    for(c = 0;c < MaxChannels;c++)
-    {
-        ALfloat earlyGain, lateGain;
-
-        earlyGain = State->Early.PanGain[c];
-        if(earlyGain > GAIN_SILENCE_THRESHOLD)
-        {
-            for(index = 0;index < SamplesToDo;index++)
-                SamplesOut[c][index] += earlyGain*early[index][c&3];
-        }
-        lateGain = State->Late.PanGain[c];
-        if(lateGain > GAIN_SILENCE_THRESHOLD)
-        {
-            for(index = 0;index < SamplesToDo;index++)
-                SamplesOut[c][index] += lateGain*late[index][c&3];
-        }
-    }
-}
-
-static ALvoid ALreverbState_process(ALreverbState *State, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
-{
-    if(State->IsEax)
-        ALreverbState_processEax(State, SamplesToDo, SamplesIn, SamplesOut);
-    else
-        ALreverbState_processStandard(State, SamplesToDo, SamplesIn, SamplesOut);
-}
-
-// Given the allocated sample buffer, this function updates each delay line
-// offset.
-static inline ALvoid RealizeLineOffset(ALfloat *sampleBuffer, DelayLine *Delay)
-{
-    Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line];
-}
-
-// Calculate the length of a delay line and store its mask and offset.
-static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay)
-{
-    ALuint samples;
-
-    // All line lengths are powers of 2, calculated from their lengths, with
-    // an additional sample in case of rounding errors.
-    samples = NextPowerOf2(fastf2u(length * frequency) + 1);
-    // All lines share a single sample buffer.
-    Delay->Mask = samples - 1;
-    Delay->Line = (ALfloat*)offset;
-    // Return the sample count for accumulation.
-    return samples;
-}
-
-/* Calculates the delay line metrics and allocates the shared sample buffer
- * for all lines given the sample rate (frequency).  If an allocation failure
- * occurs, it returns AL_FALSE.
- */
-static ALboolean AllocLines(ALuint frequency, ALreverbState *State)
-{
-    ALuint totalSamples, index;
-    ALfloat length;
-    ALfloat *newBuffer = NULL;
-
-    // All delay line lengths are calculated to accomodate the full range of
-    // lengths given their respective paramters.
-    totalSamples = 0;
-
-    /* The modulator's line length is calculated from the maximum modulation
-     * time and depth coefficient, and halfed for the low-to-high frequency
-     * swing.  An additional sample is added to keep it stable when there is no
-     * modulation.
-     */
-    length = (AL_EAXREVERB_MAX_MODULATION_TIME*MODULATION_DEPTH_COEFF/2.0f) +
-             (1.0f / frequency);
-    totalSamples += CalcLineLength(length, totalSamples, frequency,
-                                   &State->Mod.Delay);
-
-    // The initial delay is the sum of the reflections and late reverb
-    // delays.
-    length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY +
-             AL_EAXREVERB_MAX_LATE_REVERB_DELAY;
-    totalSamples += CalcLineLength(length, totalSamples, frequency,
-                                   &State->Delay);
-
-    // The early reflection lines.
-    for(index = 0;index < 4;index++)
-        totalSamples += CalcLineLength(EARLY_LINE_LENGTH[index], totalSamples,
-                                       frequency, &State->Early.Delay[index]);
-
-    // The decorrelator line is calculated from the lowest reverb density (a
-    // parameter value of 1).
-    length = (DECO_FRACTION * DECO_MULTIPLIER * DECO_MULTIPLIER) *
-             LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER);
-    totalSamples += CalcLineLength(length, totalSamples, frequency,
-                                   &State->Decorrelator);
-
-    // The late all-pass lines.
-    for(index = 0;index < 4;index++)
-        totalSamples += CalcLineLength(ALLPASS_LINE_LENGTH[index], totalSamples,
-                                       frequency, &State->Late.ApDelay[index]);
-
-    // The late delay lines are calculated from the lowest reverb density.
-    for(index = 0;index < 4;index++)
-    {
-        length = LATE_LINE_LENGTH[index] * (1.0f + LATE_LINE_MULTIPLIER);
-        totalSamples += CalcLineLength(length, totalSamples, frequency,
-                                       &State->Late.Delay[index]);
-    }
-
-    // The echo all-pass and delay lines.
-    totalSamples += CalcLineLength(ECHO_ALLPASS_LENGTH, totalSamples,
-                                   frequency, &State->Echo.ApDelay);
-    totalSamples += CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME, totalSamples,
-                                   frequency, &State->Echo.Delay);
-
-    if(totalSamples != State->TotalSamples)
-    {
-        TRACE("New reverb buffer length: %u samples (%f sec)\n", totalSamples, totalSamples/(float)frequency);
-        newBuffer = realloc(State->SampleBuffer, sizeof(ALfloat) * totalSamples);
-        if(newBuffer == NULL)
-            return AL_FALSE;
-        State->SampleBuffer = newBuffer;
-        State->TotalSamples = totalSamples;
-    }
-
-    // Update all delays to reflect the new sample buffer.
-    RealizeLineOffset(State->SampleBuffer, &State->Delay);
-    RealizeLineOffset(State->SampleBuffer, &State->Decorrelator);
-    for(index = 0;index < 4;index++)
-    {
-        RealizeLineOffset(State->SampleBuffer, &State->Early.Delay[index]);
-        RealizeLineOffset(State->SampleBuffer, &State->Late.ApDelay[index]);
-        RealizeLineOffset(State->SampleBuffer, &State->Late.Delay[index]);
-    }
-    RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay);
-    RealizeLineOffset(State->SampleBuffer, &State->Echo.ApDelay);
-    RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay);
-
-    // Clear the sample buffer.
-    for(index = 0;index < State->TotalSamples;index++)
-        State->SampleBuffer[index] = 0.0f;
-
-    return AL_TRUE;
-}
-
-static ALboolean ALreverbState_deviceUpdate(ALreverbState *State, ALCdevice *Device)
-{
-    ALuint frequency = Device->Frequency, index;
-
-    // Allocate the delay lines.
-    if(!AllocLines(frequency, State))
-        return AL_FALSE;
-
-    // Calculate the modulation filter coefficient.  Notice that the exponent
-    // is calculated given the current sample rate.  This ensures that the
-    // resulting filter response over time is consistent across all sample
-    // rates.
-    State->Mod.Coeff = powf(MODULATION_FILTER_COEFF,
-                            MODULATION_FILTER_CONST / frequency);
-
-    // The early reflection and late all-pass filter line lengths are static,
-    // so their offsets only need to be calculated once.
-    for(index = 0;index < 4;index++)
-    {
-        State->Early.Offset[index] = fastf2u(EARLY_LINE_LENGTH[index] *
-                                             frequency);
-        State->Late.ApOffset[index] = fastf2u(ALLPASS_LINE_LENGTH[index] *
-                                              frequency);
-    }
-
-    // The echo all-pass filter line length is static, so its offset only
-    // needs to be calculated once.
-    State->Echo.ApOffset = fastf2u(ECHO_ALLPASS_LENGTH * frequency);
-
-    return AL_TRUE;
-}
-
-// Calculate a decay coefficient given the length of each cycle and the time
-// until the decay reaches -60 dB.
-static inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime)
-{
-    return powf(0.001f/*-60 dB*/, length/decayTime);
-}
-
-// Calculate a decay length from a coefficient and the time until the decay
-// reaches -60 dB.
-static inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime)
-{
-    return log10f(coeff) * decayTime / log10f(0.001f)/*-60 dB*/;
-}
-
-// Calculate an attenuation to be applied to the input of any echo models to
-// compensate for modal density and decay time.
-static inline ALfloat CalcDensityGain(ALfloat a)
-{
-    /* The energy of a signal can be obtained by finding the area under the
-     * squared signal.  This takes the form of Sum(x_n^2), where x is the
-     * amplitude for the sample n.
-     *
-     * Decaying feedback matches exponential decay of the form Sum(a^n),
-     * where a is the attenuation coefficient, and n is the sample.  The area
-     * under this decay curve can be calculated as:  1 / (1 - a).
-     *
-     * Modifying the above equation to find the squared area under the curve
-     * (for energy) yields:  1 / (1 - a^2).  Input attenuation can then be
-     * calculated by inverting the square root of this approximation,
-     * yielding:  1 / sqrt(1 / (1 - a^2)), simplified to: sqrt(1 - a^2).
-     */
-    return sqrtf(1.0f - (a * a));
-}
-
-// Calculate the mixing matrix coefficients given a diffusion factor.
-static inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y)
-{
-    ALfloat n, t;
-
-    // The matrix is of order 4, so n is sqrt (4 - 1).
-    n = sqrtf(3.0f);
-    t = diffusion * atanf(n);
-
-    // Calculate the first mixing matrix coefficient.
-    *x = cosf(t);
-    // Calculate the second mixing matrix coefficient.
-    *y = sinf(t) / n;
-}
-
-// Calculate the limited HF ratio for use with the late reverb low-pass
-// filters.
-static ALfloat CalcLimitedHfRatio(ALfloat hfRatio, ALfloat airAbsorptionGainHF, ALfloat decayTime)
-{
-    ALfloat limitRatio;
-
-    /* Find the attenuation due to air absorption in dB (converting delay
-     * time to meters using the speed of sound).  Then reversing the decay
-     * equation, solve for HF ratio.  The delay length is cancelled out of
-     * the equation, so it can be calculated once for all lines.
-     */
-    limitRatio = 1.0f / (CalcDecayLength(airAbsorptionGainHF, decayTime) *
-                         SPEEDOFSOUNDMETRESPERSEC);
-    /* Using the limit calculated above, apply the upper bound to the HF
-     * ratio. Also need to limit the result to a minimum of 0.1, just like the
-     * HF ratio parameter. */
-    return clampf(limitRatio, 0.1f, hfRatio);
-}
-
-// Calculate the coefficient for a HF (and eventually LF) decay damping
-// filter.
-static inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw)
-{
-    ALfloat coeff, g;
-
-    // Eventually this should boost the high frequencies when the ratio
-    // exceeds 1.
-    coeff = 0.0f;
-    if (hfRatio < 1.0f)
-    {
-        // Calculate the low-pass coefficient by dividing the HF decay
-        // coefficient by the full decay coefficient.
-        g = CalcDecayCoeff(length, decayTime * hfRatio) / decayCoeff;
-
-        // Damping is done with a 1-pole filter, so g needs to be squared.
-        g *= g;
-        if(g < 0.9999f) /* 1-epsilon */
-        {
-            /* Be careful with gains < 0.001, as that causes the coefficient
-             * head towards 1, which will flatten the signal. */
-            g = maxf(g, 0.001f);
-            coeff = (1 - g*cw - sqrtf(2*g*(1-cw) - g*g*(1 - cw*cw))) /
-                    (1 - g);
-        }
-
-        // Very low decay times will produce minimal output, so apply an
-        // upper bound to the coefficient.
-        coeff = minf(coeff, 0.98f);
-    }
-    return coeff;
-}
-
-// Update the EAX modulation index, range, and depth.  Keep in mind that this
-// kind of vibrato is additive and not multiplicative as one may expect.  The
-// downswing will sound stronger than the upswing.
-static ALvoid UpdateModulator(ALfloat modTime, ALfloat modDepth, ALuint frequency, ALreverbState *State)
-{
-    ALuint range;
-
-    /* Modulation is calculated in two parts.
-     *
-     * The modulation time effects the sinus applied to the change in
-     * frequency.  An index out of the current time range (both in samples)
-     * is incremented each sample.  The range is bound to a reasonable
-     * minimum (1 sample) and when the timing changes, the index is rescaled
-     * to the new range (to keep the sinus consistent).
-     */
-    range = maxu(fastf2u(modTime*frequency), 1);
-    State->Mod.Index = (ALuint)(State->Mod.Index * (ALuint64)range /
-                                State->Mod.Range);
-    State->Mod.Range = range;
-
-    /* The modulation depth effects the amount of frequency change over the
-     * range of the sinus.  It needs to be scaled by the modulation time so
-     * that a given depth produces a consistent change in frequency over all
-     * ranges of time.  Since the depth is applied to a sinus value, it needs
-     * to be halfed once for the sinus range and again for the sinus swing
-     * in time (half of it is spent decreasing the frequency, half is spent
-     * increasing it).
-     */
-    State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f /
-                       2.0f * frequency;
-}
-
-// Update the offsets for the initial effect delay line.
-static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALreverbState *State)
-{
-    // Calculate the initial delay taps.
-    State->DelayTap[0] = fastf2u(earlyDelay * frequency);
-    State->DelayTap[1] = fastf2u((earlyDelay + lateDelay) * frequency);
-}
-
-// Update the early reflections gain and line coefficients.
-static ALvoid UpdateEarlyLines(ALfloat reverbGain, ALfloat earlyGain, ALfloat lateDelay, ALreverbState *State)
-{
-    ALuint index;
-
-    // Calculate the early reflections gain (from the master effect gain, and
-    // reflections gain parameters) with a constant attenuation of 0.5.
-    State->Early.Gain = 0.5f * reverbGain * earlyGain;
-
-    // Calculate the gain (coefficient) for each early delay line using the
-    // late delay time.  This expands the early reflections to the start of
-    // the late reverb.
-    for(index = 0;index < 4;index++)
-        State->Early.Coeff[index] = CalcDecayCoeff(EARLY_LINE_LENGTH[index],
-                                                   lateDelay);
-}
-
-// Update the offsets for the decorrelator line.
-static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALreverbState *State)
-{
-    ALuint index;
-    ALfloat length;
-
-    /* The late reverb inputs are decorrelated to smooth the reverb tail and
-     * reduce harsh echos.  The first tap occurs immediately, while the
-     * remaining taps are delayed by multiples of a fraction of the smallest
-     * cyclical delay time.
-     *
-     * offset[index] = (FRACTION (MULTIPLIER^index)) smallest_delay
-     */
-    for(index = 0;index < 3;index++)
-    {
-        length = (DECO_FRACTION * powf(DECO_MULTIPLIER, (ALfloat)index)) *
-                 LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER));
-        State->DecoTap[index] = fastf2u(length * frequency);
-    }
-}
-
-// Update the late reverb gains, line lengths, and line coefficients.
-static ALvoid UpdateLateLines(ALfloat reverbGain, ALfloat lateGain, ALfloat xMix, ALfloat density, ALfloat decayTime, ALfloat diffusion, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALreverbState *State)
-{
-    ALfloat length;
-    ALuint index;
-
-    /* Calculate the late reverb gain (from the master effect gain, and late
-     * reverb gain parameters).  Since the output is tapped prior to the
-     * application of the next delay line coefficients, this gain needs to be
-     * attenuated by the 'x' mixing matrix coefficient as well.
-     */
-    State->Late.Gain = reverbGain * lateGain * xMix;
-
-    /* To compensate for changes in modal density and decay time of the late
-     * reverb signal, the input is attenuated based on the maximal energy of
-     * the outgoing signal.  This approximation is used to keep the apparent
-     * energy of the signal equal for all ranges of density and decay time.
-     *
-     * The average length of the cyclcical delay lines is used to calculate
-     * the attenuation coefficient.
-     */
-    length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] +
-              LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]) / 4.0f;
-    length *= 1.0f + (density * LATE_LINE_MULTIPLIER);
-    State->Late.DensityGain = CalcDensityGain(CalcDecayCoeff(length,
-                                                             decayTime));
-
-    // Calculate the all-pass feed-back and feed-forward coefficient.
-    State->Late.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
-
-    for(index = 0;index < 4;index++)
-    {
-        // Calculate the gain (coefficient) for each all-pass line.
-        State->Late.ApCoeff[index] = CalcDecayCoeff(ALLPASS_LINE_LENGTH[index],
-                                                    decayTime);
-
-        // Calculate the length (in seconds) of each cyclical delay line.
-        length = LATE_LINE_LENGTH[index] * (1.0f + (density *
-                                                    LATE_LINE_MULTIPLIER));
-
-        // Calculate the delay offset for each cyclical delay line.
-        State->Late.Offset[index] = fastf2u(length * frequency);
-
-        // Calculate the gain (coefficient) for each cyclical line.
-        State->Late.Coeff[index] = CalcDecayCoeff(length, decayTime);
-
-        // Calculate the damping coefficient for each low-pass filter.
-        State->Late.LpCoeff[index] =
-            CalcDampingCoeff(hfRatio, length, decayTime,
-                             State->Late.Coeff[index], cw);
-
-        // Attenuate the cyclical line coefficients by the mixing coefficient
-        // (x).
-        State->Late.Coeff[index] *= xMix;
-    }
-}
-
-// Update the echo gain, line offset, line coefficients, and mixing
-// coefficients.
-static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoTime, ALfloat decayTime, ALfloat diffusion, ALfloat echoDepth, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALreverbState *State)
-{
-    // Update the offset and coefficient for the echo delay line.
-    State->Echo.Offset = fastf2u(echoTime * frequency);
-
-    // Calculate the decay coefficient for the echo line.
-    State->Echo.Coeff = CalcDecayCoeff(echoTime, decayTime);
-
-    // Calculate the energy-based attenuation coefficient for the echo delay
-    // line.
-    State->Echo.DensityGain = CalcDensityGain(State->Echo.Coeff);
-
-    // Calculate the echo all-pass feed coefficient.
-    State->Echo.ApFeedCoeff = 0.5f * powf(diffusion, 2.0f);
-
-    // Calculate the echo all-pass attenuation coefficient.
-    State->Echo.ApCoeff = CalcDecayCoeff(ECHO_ALLPASS_LENGTH, decayTime);
-
-    // Calculate the damping coefficient for each low-pass filter.
-    State->Echo.LpCoeff = CalcDampingCoeff(hfRatio, echoTime, decayTime,
-                                           State->Echo.Coeff, cw);
-
-    /* Calculate the echo mixing coefficients.  The first is applied to the
-     * echo itself.  The second is used to attenuate the late reverb when
-     * echo depth is high and diffusion is low, so the echo is slightly
-     * stronger than the decorrelated echos in the reverb tail.
-     */
-    State->Echo.MixCoeff[0] = reverbGain * lateGain * echoDepth;
-    State->Echo.MixCoeff[1] = 1.0f - (echoDepth * 0.5f * (1.0f - diffusion));
-}
-
-// Update the early and late 3D panning gains.
-static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALreverbState *State)
-{
-    ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1],
-                            ReflectionsPan[2] };
-    ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1],
-                           LateReverbPan[2] };
-    ALfloat ambientGain;
-    ALfloat dirGain;
-    ALfloat length;
-
-    Gain *= ReverbBoost;
-
-    /* Attenuate reverb according to its coverage (dirGain=0 will give
-     * Gain*ambientGain, and dirGain=1 will give Gain). */
-    ambientGain = minf(sqrtf(2.0f/Device->NumChan), 1.0f);
-
-    length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2];
-    if(length > 1.0f)
-    {
-        length = 1.0f / sqrtf(length);
-        earlyPan[0] *= length;
-        earlyPan[1] *= length;
-        earlyPan[2] *= length;
-    }
-    length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2];
-    if(length > 1.0f)
-    {
-        length = 1.0f / sqrtf(length);
-        latePan[0] *= length;
-        latePan[1] *= length;
-        latePan[2] *= length;
-    }
-
-    dirGain = sqrtf(earlyPan[0]*earlyPan[0] + earlyPan[2]*earlyPan[2]);
-    ComputeAngleGains(Device, atan2f(earlyPan[0], earlyPan[2]), (1.0f-dirGain)*F_PI,
-                      lerp(ambientGain, 1.0f, dirGain) * Gain, State->Early.PanGain);
-
-    dirGain = sqrtf(latePan[0]*latePan[0] + latePan[2]*latePan[2]);
-    ComputeAngleGains(Device, atan2f(latePan[0], latePan[2]), (1.0f-dirGain)*F_PI,
-                      lerp(ambientGain, 1.0f, dirGain) * Gain, State->Late.PanGain);
-}
-
-static ALvoid ALreverbState_update(ALreverbState *State, ALCdevice *Device, const ALeffectslot *Slot)
-{
-    ALuint frequency = Device->Frequency;
-    ALfloat lfscale, hfscale, hfRatio;
-    ALfloat cw, x, y;
-
-    if(Slot->EffectType == AL_EFFECT_EAXREVERB && !EmulateEAXReverb)
-        State->IsEax = AL_TRUE;
-    else if(Slot->EffectType == AL_EFFECT_REVERB || EmulateEAXReverb)
-        State->IsEax = AL_FALSE;
-
-    // Calculate the master low-pass filter (from the master effect HF gain).
-    if(State->IsEax)
-    {
-        hfscale = Slot->EffectProps.Reverb.HFReference / frequency;
-        ALfilterState_setParams(&State->LpFilter, ALfilterType_HighShelf,
-                                Slot->EffectProps.Reverb.GainHF,
-                                hfscale, 0.0f);
-        lfscale = Slot->EffectProps.Reverb.LFReference / frequency;
-        ALfilterState_setParams(&State->HpFilter, ALfilterType_LowShelf,
-                                Slot->EffectProps.Reverb.GainLF,
-                                lfscale, 0.0f);
-    }
-    else
-    {
-        hfscale = LOWPASSFREQREF / frequency;
-        ALfilterState_setParams(&State->LpFilter, ALfilterType_HighShelf,
-                                Slot->EffectProps.Reverb.GainHF,
-                                hfscale, 0.0f);
-    }
-
-    if(State->IsEax)
-    {
-        // Update the modulator line.
-        UpdateModulator(Slot->EffectProps.Reverb.ModulationTime,
-                        Slot->EffectProps.Reverb.ModulationDepth,
-                        frequency, State);
-    }
-
-    // Update the initial effect delay.
-    UpdateDelayLine(Slot->EffectProps.Reverb.ReflectionsDelay,
-                    Slot->EffectProps.Reverb.LateReverbDelay,
-                    frequency, State);
-
-    // Update the early lines.
-    UpdateEarlyLines(Slot->EffectProps.Reverb.Gain,
-                     Slot->EffectProps.Reverb.ReflectionsGain,
-                     Slot->EffectProps.Reverb.LateReverbDelay, State);
-
-    // Update the decorrelator.
-    UpdateDecorrelator(Slot->EffectProps.Reverb.Density, frequency, State);
-
-    // Get the mixing matrix coefficients (x and y).
-    CalcMatrixCoeffs(Slot->EffectProps.Reverb.Diffusion, &x, &y);
-    // Then divide x into y to simplify the matrix calculation.
-    State->Late.MixCoeff = y / x;
-
-    // If the HF limit parameter is flagged, calculate an appropriate limit
-    // based on the air absorption parameter.
-    hfRatio = Slot->EffectProps.Reverb.DecayHFRatio;
-    if(Slot->EffectProps.Reverb.DecayHFLimit &&
-       Slot->EffectProps.Reverb.AirAbsorptionGainHF < 1.0f)
-        hfRatio = CalcLimitedHfRatio(hfRatio,
-                                     Slot->EffectProps.Reverb.AirAbsorptionGainHF,
-                                     Slot->EffectProps.Reverb.DecayTime);
-
-    cw = cosf(F_2PI * hfscale);
-    // Update the late lines.
-    UpdateLateLines(Slot->EffectProps.Reverb.Gain, Slot->EffectProps.Reverb.LateReverbGain,
-                    x, Slot->EffectProps.Reverb.Density, Slot->EffectProps.Reverb.DecayTime,
-                    Slot->EffectProps.Reverb.Diffusion, hfRatio, cw, frequency, State);
-
-    if(State->IsEax)
-    {
-        // Update the echo line.
-        UpdateEchoLine(Slot->EffectProps.Reverb.Gain, Slot->EffectProps.Reverb.LateReverbGain,
-                       Slot->EffectProps.Reverb.EchoTime, Slot->EffectProps.Reverb.DecayTime,
-                       Slot->EffectProps.Reverb.Diffusion, Slot->EffectProps.Reverb.EchoDepth,
-                       hfRatio, cw, frequency, State);
-
-        // Update early and late 3D panning.
-        Update3DPanning(Device, Slot->EffectProps.Reverb.ReflectionsPan,
-                        Slot->EffectProps.Reverb.LateReverbPan, Slot->Gain, State);
-    }
-    else
-    {
-        /* Update channel gains */
-        ALfloat gain = sqrtf(2.0f/Device->NumChan) * ReverbBoost * Slot->Gain;
-        SetGains(Device, gain, State->Gain);
-    }
-}
-
-
-static ALvoid ALreverbState_Destruct(ALreverbState *State)
-{
-    free(State->SampleBuffer);
-    State->SampleBuffer = NULL;
-}
-
-DECLARE_DEFAULT_ALLOCATORS(ALreverbState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALreverbState);
-
-
-typedef struct ALreverbStateFactory {
-    DERIVE_FROM_TYPE(ALeffectStateFactory);
-} ALreverbStateFactory;
-
-static ALeffectState *ALreverbStateFactory_create(ALreverbStateFactory* UNUSED(factory))
-{
-    ALreverbState *state;
-    ALuint index;
-
-    state = ALreverbState_New(sizeof(*state));
-    if(!state) return NULL;
-    SET_VTABLE2(ALreverbState, ALeffectState, state);
-
-    state->TotalSamples = 0;
-    state->SampleBuffer = NULL;
-
-    ALfilterState_clear(&state->LpFilter);
-    ALfilterState_clear(&state->HpFilter);
-
-    state->Mod.Delay.Mask = 0;
-    state->Mod.Delay.Line = NULL;
-    state->Mod.Index = 0;
-    state->Mod.Range = 1;
-    state->Mod.Depth = 0.0f;
-    state->Mod.Coeff = 0.0f;
-    state->Mod.Filter = 0.0f;
-
-    state->Delay.Mask = 0;
-    state->Delay.Line = NULL;
-    state->DelayTap[0] = 0;
-    state->DelayTap[1] = 0;
-
-    state->Early.Gain = 0.0f;
-    for(index = 0;index < 4;index++)
-    {
-        state->Early.Coeff[index] = 0.0f;
-        state->Early.Delay[index].Mask = 0;
-        state->Early.Delay[index].Line = NULL;
-        state->Early.Offset[index] = 0;
-    }
-
-    state->Decorrelator.Mask = 0;
-    state->Decorrelator.Line = NULL;
-    state->DecoTap[0] = 0;
-    state->DecoTap[1] = 0;
-    state->DecoTap[2] = 0;
-
-    state->Late.Gain = 0.0f;
-    state->Late.DensityGain = 0.0f;
-    state->Late.ApFeedCoeff = 0.0f;
-    state->Late.MixCoeff = 0.0f;
-    for(index = 0;index < 4;index++)
-    {
-        state->Late.ApCoeff[index] = 0.0f;
-        state->Late.ApDelay[index].Mask = 0;
-        state->Late.ApDelay[index].Line = NULL;
-        state->Late.ApOffset[index] = 0;
-
-        state->Late.Coeff[index] = 0.0f;
-        state->Late.Delay[index].Mask = 0;
-        state->Late.Delay[index].Line = NULL;
-        state->Late.Offset[index] = 0;
-
-        state->Late.LpCoeff[index] = 0.0f;
-        state->Late.LpSample[index] = 0.0f;
-    }
-
-    for(index = 0;index < MaxChannels;index++)
-    {
-        state->Early.PanGain[index] = 0.0f;
-        state->Late.PanGain[index] = 0.0f;
-    }
-
-    state->Echo.DensityGain = 0.0f;
-    state->Echo.Delay.Mask = 0;
-    state->Echo.Delay.Line = NULL;
-    state->Echo.ApDelay.Mask = 0;
-    state->Echo.ApDelay.Line = NULL;
-    state->Echo.Coeff = 0.0f;
-    state->Echo.ApFeedCoeff = 0.0f;
-    state->Echo.ApCoeff = 0.0f;
-    state->Echo.Offset = 0;
-    state->Echo.ApOffset = 0;
-    state->Echo.LpCoeff = 0.0f;
-    state->Echo.LpSample = 0.0f;
-    state->Echo.MixCoeff[0] = 0.0f;
-    state->Echo.MixCoeff[1] = 0.0f;
-
-    state->Offset = 0;
-
-    state->Gain = state->Late.PanGain;
-
-    return STATIC_CAST(ALeffectState, state);
-}
-
-DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALreverbStateFactory);
-
-ALeffectStateFactory *ALreverbStateFactory_getFactory(void)
-{
-    static ALreverbStateFactory ReverbFactory = { { GET_VTABLE2(ALreverbStateFactory, ALeffectStateFactory) } };
-
-    return STATIC_CAST(ALeffectStateFactory, &ReverbFactory);
-}
-
-
-void ALeaxreverb_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
-{
-    ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_EAXREVERB_DECAY_HFLIMIT:
-            if(!(val >= AL_EAXREVERB_MIN_DECAY_HFLIMIT && val <= AL_EAXREVERB_MAX_DECAY_HFLIMIT))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.DecayHFLimit = val;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALeaxreverb_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALeaxreverb_setParami(effect, context, param, vals[0]);
-}
-void ALeaxreverb_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
-{
-    ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_EAXREVERB_DENSITY:
-            if(!(val >= AL_EAXREVERB_MIN_DENSITY && val <= AL_EAXREVERB_MAX_DENSITY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.Density = val;
-            break;
-
-        case AL_EAXREVERB_DIFFUSION:
-            if(!(val >= AL_EAXREVERB_MIN_DIFFUSION && val <= AL_EAXREVERB_MAX_DIFFUSION))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.Diffusion = val;
-            break;
-
-        case AL_EAXREVERB_GAIN:
-            if(!(val >= AL_EAXREVERB_MIN_GAIN && val <= AL_EAXREVERB_MAX_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.Gain = val;
-            break;
-
-        case AL_EAXREVERB_GAINHF:
-            if(!(val >= AL_EAXREVERB_MIN_GAINHF && val <= AL_EAXREVERB_MAX_GAINHF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.GainHF = val;
-            break;
-
-        case AL_EAXREVERB_GAINLF:
-            if(!(val >= AL_EAXREVERB_MIN_GAINLF && val <= AL_EAXREVERB_MAX_GAINLF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.GainLF = val;
-            break;
-
-        case AL_EAXREVERB_DECAY_TIME:
-            if(!(val >= AL_EAXREVERB_MIN_DECAY_TIME && val <= AL_EAXREVERB_MAX_DECAY_TIME))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.DecayTime = val;
-            break;
-
-        case AL_EAXREVERB_DECAY_HFRATIO:
-            if(!(val >= AL_EAXREVERB_MIN_DECAY_HFRATIO && val <= AL_EAXREVERB_MAX_DECAY_HFRATIO))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.DecayHFRatio = val;
-            break;
-
-        case AL_EAXREVERB_DECAY_LFRATIO:
-            if(!(val >= AL_EAXREVERB_MIN_DECAY_LFRATIO && val <= AL_EAXREVERB_MAX_DECAY_LFRATIO))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.DecayLFRatio = val;
-            break;
-
-        case AL_EAXREVERB_REFLECTIONS_GAIN:
-            if(!(val >= AL_EAXREVERB_MIN_REFLECTIONS_GAIN && val <= AL_EAXREVERB_MAX_REFLECTIONS_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.ReflectionsGain = val;
-            break;
-
-        case AL_EAXREVERB_REFLECTIONS_DELAY:
-            if(!(val >= AL_EAXREVERB_MIN_REFLECTIONS_DELAY && val <= AL_EAXREVERB_MAX_REFLECTIONS_DELAY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.ReflectionsDelay = val;
-            break;
-
-        case AL_EAXREVERB_LATE_REVERB_GAIN:
-            if(!(val >= AL_EAXREVERB_MIN_LATE_REVERB_GAIN && val <= AL_EAXREVERB_MAX_LATE_REVERB_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.LateReverbGain = val;
-            break;
-
-        case AL_EAXREVERB_LATE_REVERB_DELAY:
-            if(!(val >= AL_EAXREVERB_MIN_LATE_REVERB_DELAY && val <= AL_EAXREVERB_MAX_LATE_REVERB_DELAY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.LateReverbDelay = val;
-            break;
-
-        case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
-            if(!(val >= AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF && val <= AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.AirAbsorptionGainHF = val;
-            break;
-
-        case AL_EAXREVERB_ECHO_TIME:
-            if(!(val >= AL_EAXREVERB_MIN_ECHO_TIME && val <= AL_EAXREVERB_MAX_ECHO_TIME))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.EchoTime = val;
-            break;
-
-        case AL_EAXREVERB_ECHO_DEPTH:
-            if(!(val >= AL_EAXREVERB_MIN_ECHO_DEPTH && val <= AL_EAXREVERB_MAX_ECHO_DEPTH))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.EchoDepth = val;
-            break;
-
-        case AL_EAXREVERB_MODULATION_TIME:
-            if(!(val >= AL_EAXREVERB_MIN_MODULATION_TIME && val <= AL_EAXREVERB_MAX_MODULATION_TIME))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.ModulationTime = val;
-            break;
-
-        case AL_EAXREVERB_MODULATION_DEPTH:
-            if(!(val >= AL_EAXREVERB_MIN_MODULATION_DEPTH && val <= AL_EAXREVERB_MAX_MODULATION_DEPTH))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.ModulationDepth = val;
-            break;
-
-        case AL_EAXREVERB_HFREFERENCE:
-            if(!(val >= AL_EAXREVERB_MIN_HFREFERENCE && val <= AL_EAXREVERB_MAX_HFREFERENCE))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.HFReference = val;
-            break;
-
-        case AL_EAXREVERB_LFREFERENCE:
-            if(!(val >= AL_EAXREVERB_MIN_LFREFERENCE && val <= AL_EAXREVERB_MAX_LFREFERENCE))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.LFReference = val;
-            break;
-
-        case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
-            if(!(val >= AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR && val <= AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.RoomRolloffFactor = val;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALeaxreverb_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_EAXREVERB_REFLECTIONS_PAN:
-            if(!(isfinite(vals[0]) && isfinite(vals[1]) && isfinite(vals[2])))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            LockContext(context);
-            props->Reverb.ReflectionsPan[0] = vals[0];
-            props->Reverb.ReflectionsPan[1] = vals[1];
-            props->Reverb.ReflectionsPan[2] = vals[2];
-            UnlockContext(context);
-            break;
-        case AL_EAXREVERB_LATE_REVERB_PAN:
-            if(!(isfinite(vals[0]) && isfinite(vals[1]) && isfinite(vals[2])))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            LockContext(context);
-            props->Reverb.LateReverbPan[0] = vals[0];
-            props->Reverb.LateReverbPan[1] = vals[1];
-            props->Reverb.LateReverbPan[2] = vals[2];
-            UnlockContext(context);
-            break;
-
-        default:
-            ALeaxreverb_setParamf(effect, context, param, vals[0]);
-            break;
-    }
-}
-
-void ALeaxreverb_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
-{
-    const ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_EAXREVERB_DECAY_HFLIMIT:
-            *val = props->Reverb.DecayHFLimit;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALeaxreverb_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALeaxreverb_getParami(effect, context, param, vals);
-}
-void ALeaxreverb_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
-{
-    const ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_EAXREVERB_DENSITY:
-            *val = props->Reverb.Density;
-            break;
-
-        case AL_EAXREVERB_DIFFUSION:
-            *val = props->Reverb.Diffusion;
-            break;
-
-        case AL_EAXREVERB_GAIN:
-            *val = props->Reverb.Gain;
-            break;
-
-        case AL_EAXREVERB_GAINHF:
-            *val = props->Reverb.GainHF;
-            break;
-
-        case AL_EAXREVERB_GAINLF:
-            *val = props->Reverb.GainLF;
-            break;
-
-        case AL_EAXREVERB_DECAY_TIME:
-            *val = props->Reverb.DecayTime;
-            break;
-
-        case AL_EAXREVERB_DECAY_HFRATIO:
-            *val = props->Reverb.DecayHFRatio;
-            break;
-
-        case AL_EAXREVERB_DECAY_LFRATIO:
-            *val = props->Reverb.DecayLFRatio;
-            break;
-
-        case AL_EAXREVERB_REFLECTIONS_GAIN:
-            *val = props->Reverb.ReflectionsGain;
-            break;
-
-        case AL_EAXREVERB_REFLECTIONS_DELAY:
-            *val = props->Reverb.ReflectionsDelay;
-            break;
-
-        case AL_EAXREVERB_LATE_REVERB_GAIN:
-            *val = props->Reverb.LateReverbGain;
-            break;
-
-        case AL_EAXREVERB_LATE_REVERB_DELAY:
-            *val = props->Reverb.LateReverbDelay;
-            break;
-
-        case AL_EAXREVERB_AIR_ABSORPTION_GAINHF:
-            *val = props->Reverb.AirAbsorptionGainHF;
-            break;
-
-        case AL_EAXREVERB_ECHO_TIME:
-            *val = props->Reverb.EchoTime;
-            break;
-
-        case AL_EAXREVERB_ECHO_DEPTH:
-            *val = props->Reverb.EchoDepth;
-            break;
-
-        case AL_EAXREVERB_MODULATION_TIME:
-            *val = props->Reverb.ModulationTime;
-            break;
-
-        case AL_EAXREVERB_MODULATION_DEPTH:
-            *val = props->Reverb.ModulationDepth;
-            break;
-
-        case AL_EAXREVERB_HFREFERENCE:
-            *val = props->Reverb.HFReference;
-            break;
-
-        case AL_EAXREVERB_LFREFERENCE:
-            *val = props->Reverb.LFReference;
-            break;
-
-        case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR:
-            *val = props->Reverb.RoomRolloffFactor;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALeaxreverb_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    const ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_EAXREVERB_REFLECTIONS_PAN:
-            LockContext(context);
-            vals[0] = props->Reverb.ReflectionsPan[0];
-            vals[1] = props->Reverb.ReflectionsPan[1];
-            vals[2] = props->Reverb.ReflectionsPan[2];
-            UnlockContext(context);
-            break;
-        case AL_EAXREVERB_LATE_REVERB_PAN:
-            LockContext(context);
-            vals[0] = props->Reverb.LateReverbPan[0];
-            vals[1] = props->Reverb.LateReverbPan[1];
-            vals[2] = props->Reverb.LateReverbPan[2];
-            UnlockContext(context);
-            break;
-
-        default:
-            ALeaxreverb_getParamf(effect, context, param, vals);
-            break;
-    }
-}
-
-DEFINE_ALEFFECT_VTABLE(ALeaxreverb);
-
-void ALreverb_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val)
-{
-    ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_REVERB_DECAY_HFLIMIT:
-            if(!(val >= AL_REVERB_MIN_DECAY_HFLIMIT && val <= AL_REVERB_MAX_DECAY_HFLIMIT))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.DecayHFLimit = val;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALreverb_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals)
-{
-    ALreverb_setParami(effect, context, param, vals[0]);
-}
-void ALreverb_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val)
-{
-    ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_REVERB_DENSITY:
-            if(!(val >= AL_REVERB_MIN_DENSITY && val <= AL_REVERB_MAX_DENSITY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.Density = val;
-            break;
-
-        case AL_REVERB_DIFFUSION:
-            if(!(val >= AL_REVERB_MIN_DIFFUSION && val <= AL_REVERB_MAX_DIFFUSION))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.Diffusion = val;
-            break;
-
-        case AL_REVERB_GAIN:
-            if(!(val >= AL_REVERB_MIN_GAIN && val <= AL_REVERB_MAX_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.Gain = val;
-            break;
-
-        case AL_REVERB_GAINHF:
-            if(!(val >= AL_REVERB_MIN_GAINHF && val <= AL_REVERB_MAX_GAINHF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.GainHF = val;
-            break;
-
-        case AL_REVERB_DECAY_TIME:
-            if(!(val >= AL_REVERB_MIN_DECAY_TIME && val <= AL_REVERB_MAX_DECAY_TIME))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.DecayTime = val;
-            break;
-
-        case AL_REVERB_DECAY_HFRATIO:
-            if(!(val >= AL_REVERB_MIN_DECAY_HFRATIO && val <= AL_REVERB_MAX_DECAY_HFRATIO))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.DecayHFRatio = val;
-            break;
-
-        case AL_REVERB_REFLECTIONS_GAIN:
-            if(!(val >= AL_REVERB_MIN_REFLECTIONS_GAIN && val <= AL_REVERB_MAX_REFLECTIONS_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.ReflectionsGain = val;
-            break;
-
-        case AL_REVERB_REFLECTIONS_DELAY:
-            if(!(val >= AL_REVERB_MIN_REFLECTIONS_DELAY && val <= AL_REVERB_MAX_REFLECTIONS_DELAY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.ReflectionsDelay = val;
-            break;
-
-        case AL_REVERB_LATE_REVERB_GAIN:
-            if(!(val >= AL_REVERB_MIN_LATE_REVERB_GAIN && val <= AL_REVERB_MAX_LATE_REVERB_GAIN))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.LateReverbGain = val;
-            break;
-
-        case AL_REVERB_LATE_REVERB_DELAY:
-            if(!(val >= AL_REVERB_MIN_LATE_REVERB_DELAY && val <= AL_REVERB_MAX_LATE_REVERB_DELAY))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.LateReverbDelay = val;
-            break;
-
-        case AL_REVERB_AIR_ABSORPTION_GAINHF:
-            if(!(val >= AL_REVERB_MIN_AIR_ABSORPTION_GAINHF && val <= AL_REVERB_MAX_AIR_ABSORPTION_GAINHF))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.AirAbsorptionGainHF = val;
-            break;
-
-        case AL_REVERB_ROOM_ROLLOFF_FACTOR:
-            if(!(val >= AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR && val <= AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            props->Reverb.RoomRolloffFactor = val;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALreverb_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals)
-{
-    ALreverb_setParamf(effect, context, param, vals[0]);
-}
-
-void ALreverb_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val)
-{
-    const ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_REVERB_DECAY_HFLIMIT:
-            *val = props->Reverb.DecayHFLimit;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALreverb_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals)
-{
-    ALreverb_getParami(effect, context, param, vals);
-}
-void ALreverb_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val)
-{
-    const ALeffectProps *props = &effect->Props;
-    switch(param)
-    {
-        case AL_REVERB_DENSITY:
-            *val = props->Reverb.Density;
-            break;
-
-        case AL_REVERB_DIFFUSION:
-            *val = props->Reverb.Diffusion;
-            break;
-
-        case AL_REVERB_GAIN:
-            *val = props->Reverb.Gain;
-            break;
-
-        case AL_REVERB_GAINHF:
-            *val = props->Reverb.GainHF;
-            break;
-
-        case AL_REVERB_DECAY_TIME:
-            *val = props->Reverb.DecayTime;
-            break;
-
-        case AL_REVERB_DECAY_HFRATIO:
-            *val = props->Reverb.DecayHFRatio;
-            break;
-
-        case AL_REVERB_REFLECTIONS_GAIN:
-            *val = props->Reverb.ReflectionsGain;
-            break;
-
-        case AL_REVERB_REFLECTIONS_DELAY:
-            *val = props->Reverb.ReflectionsDelay;
-            break;
-
-        case AL_REVERB_LATE_REVERB_GAIN:
-            *val = props->Reverb.LateReverbGain;
-            break;
-
-        case AL_REVERB_LATE_REVERB_DELAY:
-            *val = props->Reverb.LateReverbDelay;
-            break;
-
-        case AL_REVERB_AIR_ABSORPTION_GAINHF:
-            *val = props->Reverb.AirAbsorptionGainHF;
-            break;
-
-        case AL_REVERB_ROOM_ROLLOFF_FACTOR:
-            *val = props->Reverb.RoomRolloffFactor;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-void ALreverb_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals)
-{
-    ALreverb_getParamf(effect, context, param, vals);
-}
-
-DEFINE_ALEFFECT_VTABLE(ALreverb);

+ 0 - 31
love/src/jni/openal-soft-1.17.0/Alc/evtqueue.h

@@ -1,31 +0,0 @@
-#ifndef AL_EVTQUEUE_H
-#define AL_EVTQUEUE_H
-
-#include "AL/al.h"
-
-#include "alMain.h"
-
-typedef struct MidiEvent {
-    ALuint64 time;
-    ALuint event;
-    union {
-        ALuint val[2];
-        struct {
-            ALvoid *data;
-            ALsizei size;
-        } sysex;
-    } param;
-} MidiEvent;
-
-typedef struct EvtQueue {
-    MidiEvent *events;
-    ALsizei pos;
-    ALsizei size;
-    ALsizei maxsize;
-} EvtQueue;
-
-void InitEvtQueue(EvtQueue *queue);
-void ResetEvtQueue(EvtQueue *queue);
-ALenum InsertEvtQueue(EvtQueue *queue, const MidiEvent *evt);
-
-#endif /* AL_EVTQUEUE_H */

+ 0 - 814
love/src/jni/openal-soft-1.17.0/Alc/helpers.c

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

+ 0 - 820
love/src/jni/openal-soft-1.17.0/Alc/hrtf.c

@@ -1,820 +0,0 @@
-/**
- * OpenAL cross platform audio library
- * Copyright (C) 2011 by Chris Robinson
- * This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <ctype.h>
-
-#include "AL/al.h"
-#include "AL/alc.h"
-#include "alMain.h"
-#include "alSource.h"
-#include "alu.h"
-#include "hrtf.h"
-
-
-/* Current data set limits defined by the makehrtf utility. */
-#define MIN_IR_SIZE                  (8)
-#define MAX_IR_SIZE                  (128)
-#define MOD_IR_SIZE                  (8)
-
-#define MIN_EV_COUNT                 (5)
-#define MAX_EV_COUNT                 (128)
-
-#define MIN_AZ_COUNT                 (1)
-#define MAX_AZ_COUNT                 (128)
-
-struct Hrtf {
-    ALuint sampleRate;
-    ALuint irSize;
-    ALubyte evCount;
-
-    const ALubyte *azCount;
-    const ALushort *evOffset;
-    const ALshort *coeffs;
-    const ALubyte *delays;
-
-    struct Hrtf *next;
-};
-
-static const ALchar magicMarker00[8] = "MinPHR00";
-static const ALchar magicMarker01[8] = "MinPHR01";
-
-/* First value for pass-through coefficients (remaining are 0), used for omni-
- * directional sounds. */
-static const ALfloat PassthruCoeff = 32767.0f * 0.707106781187f/*sqrt(0.5)*/;
-
-static struct Hrtf *LoadedHrtfs = NULL;
-
-/* Calculate the elevation indices given the polar elevation in radians.
- * This will return two indices between 0 and (evcount - 1) and an
- * interpolation factor between 0.0 and 1.0.
- */
-static void CalcEvIndices(ALuint evcount, ALfloat ev, ALuint *evidx, ALfloat *evmu)
-{
-    ev = (F_PI_2 + ev) * (evcount-1) / F_PI;
-    evidx[0] = fastf2u(ev);
-    evidx[1] = minu(evidx[0] + 1, evcount-1);
-    *evmu = ev - evidx[0];
-}
-
-/* Calculate the azimuth indices given the polar azimuth in radians.  This
- * will return two indices between 0 and (azcount - 1) and an interpolation
- * factor between 0.0 and 1.0.
- */
-static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *azmu)
-{
-    az = (F_2PI + az) * azcount / (F_2PI);
-    azidx[0] = fastf2u(az) % azcount;
-    azidx[1] = (azidx[0] + 1) % azcount;
-    *azmu = az - floorf(az);
-}
-
-/* Calculates the normalized HRTF transition factor (delta) from the changes
- * in gain and listener to source angle between updates.  The result is a
- * normalized delta factor that can be used to calculate moving HRIR stepping
- * values.
- */
-ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3])
-{
-    ALfloat gainChange, angleChange, change;
-
-    // Calculate the normalized dB gain change.
-    newGain = maxf(newGain, 0.0001f);
-    oldGain = maxf(oldGain, 0.0001f);
-    gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f));
-
-    // Calculate the angle change only when there is enough gain to notice it.
-    angleChange = 0.0f;
-    if(gainChange > 0.0001f || newGain > 0.0001f)
-    {
-        // No angle change when the directions are equal or degenerate (when
-        // both have zero length).
-        if(newdir[0] != olddir[0] || newdir[1] != olddir[1] || newdir[2] != olddir[2])
-        {
-            ALfloat dotp = olddir[0]*newdir[0] + olddir[1]*newdir[1] + olddir[2]*newdir[2];
-            angleChange = acosf(clampf(dotp, -1.0f, 1.0f)) / F_PI;
-        }
-    }
-
-    // Use the largest of the two changes for the delta factor, and apply a
-    // significance shaping function to it.
-    change = maxf(angleChange * 25.0f, gainChange) * 2.0f;
-    return minf(change, 1.0f);
-}
-
-/* Calculates static HRIR coefficients and delays for the given polar
- * elevation and azimuth in radians.  Linear interpolation is used to
- * increase the apparent resolution of the HRIR data set.  The coefficients
- * are also normalized and attenuated by the specified gain.
- */
-void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
-{
-    ALuint evidx[2], lidx[4], ridx[4];
-    ALfloat mu[3], blend[4];
-    ALuint i;
-
-    /* Claculate elevation indices and interpolation factor. */
-    CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]);
-
-    for(i = 0;i < 2;i++)
-    {
-        ALuint azcount = Hrtf->azCount[evidx[i]];
-        ALuint evoffset = Hrtf->evOffset[evidx[i]];
-        ALuint azidx[2];
-
-        /* Calculate azimuth indices and interpolation factor for this elevation. */
-        CalcAzIndices(azcount, azimuth, azidx, &mu[i]);
-
-        /* Calculate a set of linear HRIR indices for left and right channels. */
-        lidx[i*2 + 0] = evoffset + azidx[0];
-        lidx[i*2 + 1] = evoffset + azidx[1];
-        ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount);
-        ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount);
-    }
-
-    /* Calculate 4 blending weights for 2D bilinear interpolation. */
-    blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
-    blend[1] = (     mu[0]) * (1.0f-mu[2]);
-    blend[2] = (1.0f-mu[1]) * (     mu[2]);
-    blend[3] = (     mu[1]) * (     mu[2]);
-
-    /* Calculate the HRIR delays using linear interpolation. */
-    delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
-                         Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) *
-                        dirfact + 0.5f) << HRTFDELAY_BITS;
-    delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
-                         Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
-                        dirfact + 0.5f) << HRTFDELAY_BITS;
-
-    /* Calculate the sample offsets for the HRIR indices. */
-    lidx[0] *= Hrtf->irSize;
-    lidx[1] *= Hrtf->irSize;
-    lidx[2] *= Hrtf->irSize;
-    lidx[3] *= Hrtf->irSize;
-    ridx[0] *= Hrtf->irSize;
-    ridx[1] *= Hrtf->irSize;
-    ridx[2] *= Hrtf->irSize;
-    ridx[3] *= Hrtf->irSize;
-
-    /* Calculate the normalized and attenuated HRIR coefficients using linear
-     * interpolation when there is enough gain to warrant it.  Zero the
-     * coefficients if gain is too low.
-     */
-    if(gain > 0.0001f)
-    {
-        ALfloat c;
-
-        gain *= 1.0f/32767.0f;
-
-        i = 0;
-        c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
-             Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
-        coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain;
-        c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
-             Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
-        coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain;
-
-        for(i = 1;i < Hrtf->irSize;i++)
-        {
-            c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
-                 Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
-            coeffs[i][0] = lerp(0.0f, c, dirfact) * gain;
-            c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
-                 Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
-            coeffs[i][1] = lerp(0.0f, c, dirfact) * gain;
-        }
-    }
-    else
-    {
-        for(i = 0;i < Hrtf->irSize;i++)
-        {
-            coeffs[i][0] = 0.0f;
-            coeffs[i][1] = 0.0f;
-        }
-    }
-}
-
-/* Calculates the moving HRIR target coefficients, target delays, and
- * stepping values for the given polar elevation and azimuth in radians.
- * Linear interpolation is used to increase the apparent resolution of the
- * HRIR data set.  The coefficients are also normalized and attenuated by the
- * specified gain.  Stepping resolution and count is determined using the
- * given delta factor between 0.0 and 1.0.
- */
-ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep)
-{
-    ALuint evidx[2], lidx[4], ridx[4];
-    ALfloat mu[3], blend[4];
-    ALfloat left, right;
-    ALfloat step;
-    ALuint i;
-
-    /* Claculate elevation indices and interpolation factor. */
-    CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]);
-
-    for(i = 0;i < 2;i++)
-    {
-        ALuint azcount = Hrtf->azCount[evidx[i]];
-        ALuint evoffset = Hrtf->evOffset[evidx[i]];
-        ALuint azidx[2];
-
-        /* Calculate azimuth indices and interpolation factor for this elevation. */
-        CalcAzIndices(azcount, azimuth, azidx, &mu[i]);
-
-        /* Calculate a set of linear HRIR indices for left and right channels. */
-        lidx[i*2 + 0] = evoffset + azidx[0];
-        lidx[i*2 + 1] = evoffset + azidx[1];
-        ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount);
-        ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount);
-    }
-
-    // Calculate the stepping parameters.
-    delta = maxf(floorf(delta*(Hrtf->sampleRate*0.015f) + 0.5f), 1.0f);
-    step = 1.0f / delta;
-
-    /* Calculate 4 blending weights for 2D bilinear interpolation. */
-    blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
-    blend[1] = (     mu[0]) * (1.0f-mu[2]);
-    blend[2] = (1.0f-mu[1]) * (     mu[2]);
-    blend[3] = (     mu[1]) * (     mu[2]);
-
-    /* Calculate the HRIR delays using linear interpolation.  Then calculate
-     * the delay stepping values using the target and previous running
-     * delays.
-     */
-    left = (ALfloat)(delays[0] - (delayStep[0] * counter));
-    right = (ALfloat)(delays[1] - (delayStep[1] * counter));
-
-    delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
-                         Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) *
-                        dirfact + 0.5f) << HRTFDELAY_BITS;
-    delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
-                         Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
-                        dirfact + 0.5f) << HRTFDELAY_BITS;
-
-    delayStep[0] = fastf2i(step * (delays[0] - left));
-    delayStep[1] = fastf2i(step * (delays[1] - right));
-
-    /* Calculate the sample offsets for the HRIR indices. */
-    lidx[0] *= Hrtf->irSize;
-    lidx[1] *= Hrtf->irSize;
-    lidx[2] *= Hrtf->irSize;
-    lidx[3] *= Hrtf->irSize;
-    ridx[0] *= Hrtf->irSize;
-    ridx[1] *= Hrtf->irSize;
-    ridx[2] *= Hrtf->irSize;
-    ridx[3] *= Hrtf->irSize;
-
-    /* Calculate the normalized and attenuated target HRIR coefficients using
-     * linear interpolation when there is enough gain to warrant it.  Zero
-     * the target coefficients if gain is too low.  Then calculate the
-     * coefficient stepping values using the target and previous running
-     * coefficients.
-     */
-    if(gain > 0.0001f)
-    {
-        ALfloat c;
-
-        gain *= 1.0f/32767.0f;
-
-        i = 0;
-        left = coeffs[i][0] - (coeffStep[i][0] * counter);
-        right = coeffs[i][1] - (coeffStep[i][1] * counter);
-
-        c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
-             Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
-        coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain;
-        c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
-             Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
-        coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain;
-
-        coeffStep[i][0] = step * (coeffs[i][0] - left);
-        coeffStep[i][1] = step * (coeffs[i][1] - right);
-
-        for(i = 1;i < Hrtf->irSize;i++)
-        {
-            left = coeffs[i][0] - (coeffStep[i][0] * counter);
-            right = coeffs[i][1] - (coeffStep[i][1] * counter);
-
-            c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
-                 Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
-            coeffs[i][0] = lerp(0.0f, c, dirfact) * gain;
-            c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
-                 Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
-            coeffs[i][1] = lerp(0.0f, c, dirfact) * gain;
-
-            coeffStep[i][0] = step * (coeffs[i][0] - left);
-            coeffStep[i][1] = step * (coeffs[i][1] - right);
-        }
-    }
-    else
-    {
-        for(i = 0;i < Hrtf->irSize;i++)
-        {
-            left = coeffs[i][0] - (coeffStep[i][0] * counter);
-            right = coeffs[i][1] - (coeffStep[i][1] * counter);
-
-            coeffs[i][0] = 0.0f;
-            coeffs[i][1] = 0.0f;
-
-            coeffStep[i][0] = step * -left;
-            coeffStep[i][1] = step * -right;
-        }
-    }
-
-    /* The stepping count is the number of samples necessary for the HRIR to
-     * complete its transition.  The mixer will only apply stepping for this
-     * many samples.
-     */
-    return fastf2u(delta);
-}
-
-
-static struct Hrtf *LoadHrtf00(FILE *f, ALuint deviceRate)
-{
-    const ALubyte maxDelay = SRC_HISTORY_LENGTH-1;
-    struct Hrtf *Hrtf = NULL;
-    ALboolean failed = AL_FALSE;
-    ALuint rate = 0, irCount = 0;
-    ALushort irSize = 0;
-    ALubyte evCount = 0;
-    ALubyte *azCount = NULL;
-    ALushort *evOffset = NULL;
-    ALshort *coeffs = NULL;
-    ALubyte *delays = NULL;
-    ALuint i, j;
-
-    rate  = fgetc(f);
-    rate |= fgetc(f)<<8;
-    rate |= fgetc(f)<<16;
-    rate |= fgetc(f)<<24;
-
-    irCount  = fgetc(f);
-    irCount |= fgetc(f)<<8;
-
-    irSize  = fgetc(f);
-    irSize |= fgetc(f)<<8;
-
-    evCount = fgetc(f);
-
-    if(rate != deviceRate)
-    {
-        ERR("HRIR rate does not match device rate: rate=%d (%d)\n",
-            rate, deviceRate);
-        failed = AL_TRUE;
-    }
-    if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
-    {
-        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(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;
-
-    azCount = malloc(sizeof(azCount[0])*evCount);
-    evOffset = malloc(sizeof(evOffset[0])*evCount);
-    if(azCount == NULL || evOffset == NULL)
-    {
-        ERR("Out of memory.\n");
-        failed = AL_TRUE;
-    }
-
-    if(!failed)
-    {
-        evOffset[0]  = fgetc(f);
-        evOffset[0] |= fgetc(f)<<8;
-        for(i = 1;i < evCount;i++)
-        {
-            evOffset[i]  = fgetc(f);
-            evOffset[i] |= fgetc(f)<<8;
-            if(evOffset[i] <= evOffset[i-1])
-            {
-                ERR("Invalid evOffset: evOffset[%d]=%d (last=%d)\n",
-                    i, evOffset[i], evOffset[i-1]);
-                failed = AL_TRUE;
-            }
-
-            azCount[i-1] = evOffset[i] - evOffset[i-1];
-            if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
-            {
-                ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
-                    i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
-                failed = AL_TRUE;
-            }
-        }
-        if(irCount <= evOffset[i-1])
-        {
-            ERR("Invalid evOffset: evOffset[%d]=%d (irCount=%d)\n",
-                i-1, evOffset[i-1], irCount);
-            failed = AL_TRUE;
-        }
-
-        azCount[i-1] = irCount - evOffset[i-1];
-        if(azCount[i-1] < MIN_AZ_COUNT || azCount[i-1] > MAX_AZ_COUNT)
-        {
-            ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
-                i-1, azCount[i-1], MIN_AZ_COUNT, MAX_AZ_COUNT);
-            failed = AL_TRUE;
-        }
-    }
-
-    if(!failed)
-    {
-        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)
-    {
-        for(i = 0;i < irCount*irSize;i+=irSize)
-        {
-            for(j = 0;j < irSize;j++)
-            {
-                ALshort coeff;
-                coeff  = fgetc(f);
-                coeff |= fgetc(f)<<8;
-                coeffs[i+j] = coeff;
-            }
-        }
-        for(i = 0;i < irCount;i++)
-        {
-            delays[i] = fgetc(f);
-            if(delays[i] > maxDelay)
-            {
-                ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
-                failed = AL_TRUE;
-            }
-        }
-
-        if(feof(f))
-        {
-            ERR("Premature end of data\n");
-            failed = AL_TRUE;
-        }
-    }
-
-    if(!failed)
-    {
-        Hrtf = malloc(sizeof(struct Hrtf));
-        if(Hrtf == NULL)
-        {
-            ERR("Out of memory.\n");
-            failed = AL_TRUE;
-        }
-    }
-
-    if(!failed)
-    {
-        Hrtf->sampleRate = rate;
-        Hrtf->irSize = irSize;
-        Hrtf->evCount = evCount;
-        Hrtf->azCount = azCount;
-        Hrtf->evOffset = evOffset;
-        Hrtf->coeffs = coeffs;
-        Hrtf->delays = delays;
-        Hrtf->next = NULL;
-        return Hrtf;
-    }
-
-    free(azCount);
-    free(evOffset);
-    free(coeffs);
-    free(delays);
-    return NULL;
-}
-
-
-static struct Hrtf *LoadHrtf01(FILE *f, ALuint deviceRate)
-{
-    const ALubyte maxDelay = SRC_HISTORY_LENGTH-1;
-    struct Hrtf *Hrtf = NULL;
-    ALboolean failed = AL_FALSE;
-    ALuint rate = 0, irCount = 0;
-    ALubyte irSize = 0, evCount = 0;
-    ALubyte *azCount = NULL;
-    ALushort *evOffset = NULL;
-    ALshort *coeffs = NULL;
-    ALubyte *delays = NULL;
-    ALuint i, j;
-
-    rate  = fgetc(f);
-    rate |= fgetc(f)<<8;
-    rate |= fgetc(f)<<16;
-    rate |= fgetc(f)<<24;
-
-    irSize = fgetc(f);
-
-    evCount = fgetc(f);
-
-    if(rate != deviceRate)
-    {
-        ERR("HRIR rate does not match device rate: rate=%d (%d)\n",
-                rate, deviceRate);
-        failed = AL_TRUE;
-    }
-    if(irSize < MIN_IR_SIZE || irSize > MAX_IR_SIZE || (irSize%MOD_IR_SIZE))
-    {
-        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(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;
-
-    azCount = malloc(sizeof(azCount[0])*evCount);
-    evOffset = malloc(sizeof(evOffset[0])*evCount);
-    if(azCount == NULL || evOffset == NULL)
-    {
-        ERR("Out of memory.\n");
-        failed = AL_TRUE;
-    }
-
-    if(!failed)
-    {
-        for(i = 0;i < evCount;i++)
-        {
-            azCount[i] = fgetc(f);
-            if(azCount[i] < MIN_AZ_COUNT || azCount[i] > MAX_AZ_COUNT)
-            {
-                ERR("Unsupported azimuth count: azCount[%d]=%d (%d to %d)\n",
-                    i, azCount[i], MIN_AZ_COUNT, MAX_AZ_COUNT);
-                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)
-    {
-        for(i = 0;i < irCount*irSize;i+=irSize)
-        {
-            for(j = 0;j < irSize;j++)
-            {
-                ALshort coeff;
-                coeff  = fgetc(f);
-                coeff |= fgetc(f)<<8;
-                coeffs[i+j] = coeff;
-            }
-        }
-        for(i = 0;i < irCount;i++)
-        {
-            delays[i] = fgetc(f);
-            if(delays[i] > maxDelay)
-            {
-                ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay);
-                failed = AL_TRUE;
-            }
-        }
-
-        if(feof(f))
-        {
-            ERR("Premature end of data\n");
-            failed = AL_TRUE;
-        }
-    }
-
-    if(!failed)
-    {
-        Hrtf = malloc(sizeof(struct Hrtf));
-        if(Hrtf == NULL)
-        {
-            ERR("Out of memory.\n");
-            failed = AL_TRUE;
-        }
-    }
-
-    if(!failed)
-    {
-        Hrtf->sampleRate = rate;
-        Hrtf->irSize = irSize;
-        Hrtf->evCount = evCount;
-        Hrtf->azCount = azCount;
-        Hrtf->evOffset = evOffset;
-        Hrtf->coeffs = coeffs;
-        Hrtf->delays = delays;
-        Hrtf->next = NULL;
-        return Hrtf;
-    }
-
-    free(azCount);
-    free(evOffset);
-    free(coeffs);
-    free(delays);
-    return NULL;
-}
-
-
-static struct Hrtf *LoadHrtf(ALuint deviceRate)
-{
-    const char *fnamelist = "default-%r.mhr";
-
-    ConfigValueStr(NULL, "hrtf_tables", &fnamelist);
-    while(*fnamelist != '\0')
-    {
-        struct Hrtf *Hrtf = NULL;
-        char fname[PATH_MAX];
-        const char *next;
-        ALchar magic[8];
-        ALuint i;
-        FILE *f;
-
-        i = 0;
-        while(isspace(*fnamelist) || *fnamelist == ',')
-            fnamelist++;
-        next = fnamelist;
-        while(*(fnamelist=next) != '\0' && *fnamelist != ',')
-        {
-            next = strpbrk(fnamelist, "%,");
-            while(fnamelist != next && *fnamelist && i < sizeof(fname))
-                fname[i++] = *(fnamelist++);
-
-            if(!next || *next == ',')
-                break;
-
-            /* *next == '%' */
-            next++;
-            if(*next == 'r')
-            {
-                int wrote = snprintf(&fname[i], sizeof(fname)-i, "%u", deviceRate);
-                i += minu(wrote, sizeof(fname)-i);
-                next++;
-            }
-            else if(*next == '%')
-            {
-                if(i < sizeof(fname))
-                    fname[i++] = '%';
-                next++;
-            }
-            else
-                ERR("Invalid marker '%%%c'\n", *next);
-        }
-        i = minu(i, sizeof(fname)-1);
-        fname[i] = '\0';
-        while(i > 0 && isspace(fname[i-1]))
-            i--;
-        fname[i] = '\0';
-
-        if(fname[0] == '\0')
-            continue;
-
-        TRACE("Loading %s...\n", fname);
-        f = OpenDataFile(fname, "openal/hrtf");
-        if(f == NULL)
-        {
-            ERR("Could not open %s\n", fname);
-            continue;
-        }
-
-        if(fread(magic, 1, sizeof(magic), f) != sizeof(magic))
-            ERR("Failed to read header from %s\n", fname);
-        else
-        {
-            if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0)
-            {
-                TRACE("Detected data set format v0\n");
-                Hrtf = LoadHrtf00(f, deviceRate);
-            }
-            else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0)
-            {
-                TRACE("Detected data set format v1\n");
-                Hrtf = LoadHrtf01(f, deviceRate);
-            }
-            else
-                ERR("Invalid header in %s: \"%.8s\"\n", fname, magic);
-        }
-
-        fclose(f);
-        f = NULL;
-
-        if(Hrtf)
-        {
-            Hrtf->next = LoadedHrtfs;
-            LoadedHrtfs = Hrtf;
-            TRACE("Loaded HRTF support for format: %s %uhz\n",
-                  DevFmtChannelsString(DevFmtStereo), Hrtf->sampleRate);
-            return Hrtf;
-        }
-
-        ERR("Failed to load %s\n", fname);
-    }
-
-    return NULL;
-}
-
-const struct Hrtf *GetHrtf(enum DevFmtChannels chans, ALCuint srate)
-{
-    if(chans == DevFmtStereo)
-    {
-        struct Hrtf *Hrtf = LoadedHrtfs;
-        while(Hrtf != NULL)
-        {
-            if(srate == Hrtf->sampleRate)
-                return Hrtf;
-            Hrtf = Hrtf->next;
-        }
-
-        Hrtf = LoadHrtf(srate);
-        if(Hrtf != NULL)
-            return Hrtf;
-    }
-    ERR("Incompatible format: %s %uhz\n", DevFmtChannelsString(chans), srate);
-    return NULL;
-}
-
-ALCboolean FindHrtfFormat(enum DevFmtChannels *chans, ALCuint *srate)
-{
-    const struct Hrtf *hrtf = LoadedHrtfs;
-    while(hrtf != NULL)
-    {
-        if(*srate == hrtf->sampleRate)
-            break;
-        hrtf = hrtf->next;
-    }
-
-    if(hrtf == NULL)
-    {
-        hrtf = LoadHrtf(*srate);
-        if(hrtf == NULL) return ALC_FALSE;
-    }
-
-    *chans = DevFmtStereo;
-    *srate = hrtf->sampleRate;
-    return ALC_TRUE;
-}
-
-void FreeHrtfs(void)
-{
-    struct Hrtf *Hrtf = NULL;
-
-    while((Hrtf=LoadedHrtfs) != NULL)
-    {
-        LoadedHrtfs = Hrtf->next;
-        free((void*)Hrtf->azCount);
-        free((void*)Hrtf->evOffset);
-        free((void*)Hrtf->coeffs);
-        free((void*)Hrtf->delays);
-        free(Hrtf);
-    }
-}
-
-ALuint GetHrtfIrSize (const struct Hrtf *Hrtf)
-{
-    return Hrtf->irSize;
-}

+ 0 - 28
love/src/jni/openal-soft-1.17.0/Alc/hrtf.h

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

+ 0 - 244
love/src/jni/openal-soft-1.17.0/Alc/midi/base.c

@@ -1,244 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "midi/base.h"
-
-#include "alMidi.h"
-#include "alMain.h"
-#include "alError.h"
-#include "alThunk.h"
-#include "evtqueue.h"
-#include "rwlock.h"
-#include "alu.h"
-
-
-extern inline ALboolean IsValidCtrlInput(int cc);
-
-extern inline size_t Reader_read(Reader *self, void *buf, size_t len);
-
-
-/* MIDI events */
-#define SYSEX_EVENT  (0xF0)
-
-
-void InitEvtQueue(EvtQueue *queue)
-{
-    queue->events = NULL;
-    queue->maxsize = 0;
-    queue->size = 0;
-    queue->pos = 0;
-}
-
-void ResetEvtQueue(EvtQueue *queue)
-{
-    ALsizei i;
-    for(i = 0;i < queue->size;i++)
-    {
-        if(queue->events[i].event == SYSEX_EVENT)
-        {
-            free(queue->events[i].param.sysex.data);
-            queue->events[i].param.sysex.data = NULL;
-        }
-    }
-
-    free(queue->events);
-    queue->events = NULL;
-    queue->maxsize = 0;
-    queue->size = 0;
-    queue->pos = 0;
-}
-
-ALenum InsertEvtQueue(EvtQueue *queue, const MidiEvent *evt)
-{
-    ALsizei pos;
-
-    if(queue->maxsize == queue->size)
-    {
-        if(queue->pos > 0)
-        {
-            /* Queue has some stale entries, remove them to make space for more
-             * events. */
-            for(pos = 0;pos < queue->pos;pos++)
-            {
-                if(queue->events[pos].event == SYSEX_EVENT)
-                {
-                    free(queue->events[pos].param.sysex.data);
-                    queue->events[pos].param.sysex.data = NULL;
-                }
-            }
-            memmove(&queue->events[0], &queue->events[queue->pos],
-                    (queue->size-queue->pos)*sizeof(queue->events[0]));
-            queue->size -= queue->pos;
-            queue->pos = 0;
-        }
-        else
-        {
-            /* Queue is full, double the allocated space. */
-            void *temp = NULL;
-            ALsizei newsize;
-
-            newsize = (queue->maxsize ? (queue->maxsize<<1) : 16);
-            if(newsize > queue->maxsize)
-                temp = realloc(queue->events, newsize * sizeof(queue->events[0]));
-            if(!temp)
-                return AL_OUT_OF_MEMORY;
-
-            queue->events = temp;
-            queue->maxsize = newsize;
-        }
-    }
-
-    pos = queue->pos;
-    if(queue->size > 0)
-    {
-        ALsizei high = queue->size - 1;
-        while(pos < high)
-        {
-            ALsizei mid = pos + (high-pos)/2;
-            if(queue->events[mid].time < evt->time)
-                pos = mid + 1;
-            else
-                high = mid;
-        }
-        while(pos < queue->size && queue->events[pos].time <= evt->time)
-            pos++;
-
-        if(pos < queue->size)
-            memmove(&queue->events[pos+1], &queue->events[pos],
-                    (queue->size-pos)*sizeof(queue->events[0]));
-    }
-
-    queue->events[pos] = *evt;
-    queue->size++;
-
-    return AL_NO_ERROR;
-}
-
-
-void MidiSynth_Construct(MidiSynth *self, ALCdevice *device)
-{
-    InitEvtQueue(&self->EventQueue);
-
-    RWLockInit(&self->Lock);
-
-    self->Soundfonts = NULL;
-    self->NumSoundfonts = 0;
-
-    self->Gain = 1.0f;
-    self->State = AL_INITIAL;
-
-    self->ClockBase = 0;
-    self->SamplesDone = 0;
-    self->SampleRate = device->Frequency;
-}
-
-void MidiSynth_Destruct(MidiSynth *self)
-{
-    ALsizei i;
-
-    for(i = 0;i < self->NumSoundfonts;i++)
-        DecrementRef(&self->Soundfonts[i]->ref);
-    free(self->Soundfonts);
-    self->Soundfonts = NULL;
-    self->NumSoundfonts = 0;
-
-    ResetEvtQueue(&self->EventQueue);
-}
-
-
-ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids)
-{
-    ALCdevice *device = context->Device;
-    ALsoundfont **sfonts;
-    ALsizei i;
-
-    if(self->State != AL_INITIAL && self->State != AL_STOPPED)
-        return AL_INVALID_OPERATION;
-
-    sfonts = calloc(1, count * sizeof(sfonts[0]));
-    if(!sfonts) return AL_OUT_OF_MEMORY;
-
-    for(i = 0;i < count;i++)
-    {
-        if(ids[i] == 0)
-            sfonts[i] = ALsoundfont_getDefSoundfont(context);
-        else if(!(sfonts[i]=LookupSfont(device, ids[i])))
-        {
-            free(sfonts);
-            return AL_INVALID_VALUE;
-        }
-    }
-
-    for(i = 0;i < count;i++)
-        IncrementRef(&sfonts[i]->ref);
-    sfonts = ExchangePtr((XchgPtr*)&self->Soundfonts, sfonts);
-    count = ExchangeInt(&self->NumSoundfonts, count);
-
-    for(i = 0;i < count;i++)
-        DecrementRef(&sfonts[i]->ref);
-    free(sfonts);
-
-    return AL_NO_ERROR;
-}
-
-extern inline void MidiSynth_setGain(MidiSynth *self, ALfloat gain);
-extern inline ALfloat MidiSynth_getGain(const MidiSynth *self);
-extern inline void MidiSynth_setState(MidiSynth *self, ALenum state);
-extern inline ALenum MidiSynth_getState(const MidiSynth *self);
-
-void MidiSynth_stop(MidiSynth *self)
-{
-    ResetEvtQueue(&self->EventQueue);
-
-    self->ClockBase = 0;
-    self->SamplesDone = 0;
-}
-
-extern inline void MidiSynth_reset(MidiSynth *self);
-extern inline ALuint64 MidiSynth_getTime(const MidiSynth *self);
-extern inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self);
-
-void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate)
-{
-    if(self->SampleRate != srate)
-    {
-        self->ClockBase += self->SamplesDone * MIDI_CLOCK_RES / self->SampleRate;
-        self->SamplesDone = 0;
-        self->SampleRate = srate;
-    }
-}
-
-extern inline void MidiSynth_update(MidiSynth *self, ALCdevice *device);
-
-ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2)
-{
-    MidiEvent entry;
-    entry.time = time;
-    entry.event = event;
-    entry.param.val[0] = param1;
-    entry.param.val[1] = param2;
-    return InsertEvtQueue(&self->EventQueue, &entry);
-}
-
-ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *data, ALsizei size)
-{
-    MidiEvent entry;
-    ALenum err;
-
-    entry.time = time;
-    entry.event = SYSEX_EVENT;
-    entry.param.sysex.size = size;
-    entry.param.sysex.data = malloc(size);
-    if(!entry.param.sysex.data)
-        return AL_OUT_OF_MEMORY;
-    memcpy(entry.param.sysex.data, data, size);
-
-    err = InsertEvtQueue(&self->EventQueue, &entry);
-    if(err != AL_NO_ERROR)
-        free(entry.param.sysex.data);
-    return err;
-}

+ 0 - 133
love/src/jni/openal-soft-1.17.0/Alc/midi/base.h

@@ -1,133 +0,0 @@
-#ifndef AL_MIDI_BASE_H
-#define AL_MIDI_BASE_H
-
-#include "alMain.h"
-#include "atomic.h"
-#include "evtqueue.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ALsoundfont;
-
-typedef size_t (*ReaderCb)(void *ptr, size_t size, void *stream);
-typedef struct Reader {
-    ReaderCb cb;
-    void *ptr;
-    int error;
-} Reader;
-inline size_t Reader_read(Reader *self, void *buf, size_t len)
-{
-    size_t got = (!self->error) ? self->cb(buf, len, self->ptr) : 0;
-    if(got < len) self->error = 1;
-    return got;
-}
-#define READERR(x_) ((x_)->error)
-
-ALboolean loadSf2(Reader *stream, struct ALsoundfont *sfont, ALCcontext *context);
-
-
-#define MIDI_CLOCK_RES  U64(1000000000)
-
-
-struct MidiSynthVtable;
-
-typedef struct MidiSynth {
-    EvtQueue EventQueue;
-
-    ALuint64 ClockBase;
-    ALuint SamplesDone;
-    ALuint SampleRate;
-
-    /* NOTE: This rwlock is for the state and soundfont. The EventQueue and
-     * related must instead use the device lock as they're used in the mixer
-     * thread.
-     */
-    RWLock Lock;
-
-    struct ALsoundfont **Soundfonts;
-    ALsizei NumSoundfonts;
-
-    volatile ALfloat Gain;
-    volatile ALenum State;
-
-    const struct MidiSynthVtable *vtbl;
-} MidiSynth;
-
-void MidiSynth_Construct(MidiSynth *self, ALCdevice *device);
-void MidiSynth_Destruct(MidiSynth *self);
-ALenum MidiSynth_selectSoundfonts(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
-inline void MidiSynth_setGain(MidiSynth *self, ALfloat gain) { self->Gain = gain; }
-inline ALfloat MidiSynth_getGain(const MidiSynth *self) { return self->Gain; }
-inline void MidiSynth_setState(MidiSynth *self, ALenum state) { ExchangeInt(&self->State, state); }
-inline ALenum MidiSynth_getState(const MidiSynth *self) { return self->State; }
-void MidiSynth_stop(MidiSynth *self);
-inline void MidiSynth_reset(MidiSynth *self) { MidiSynth_stop(self); }
-inline ALuint64 MidiSynth_getTime(const MidiSynth *self)
-{ return self->ClockBase + (self->SamplesDone*MIDI_CLOCK_RES/self->SampleRate); }
-inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self)
-{
-    if(self->EventQueue.pos == self->EventQueue.size)
-        return UINT64_MAX;
-    return self->EventQueue.events[self->EventQueue.pos].time;
-}
-void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate);
-inline void MidiSynth_update(MidiSynth *self, ALCdevice *device)
-{ MidiSynth_setSampleRate(self, device->Frequency); }
-ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2);
-ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *data, ALsizei size);
-
-
-struct MidiSynthVtable {
-    void (*const Destruct)(MidiSynth *self);
-
-    ALenum (*const selectSoundfonts)(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
-
-    void (*const setGain)(MidiSynth *self, ALfloat gain);
-
-    void (*const stop)(MidiSynth *self);
-    void (*const reset)(MidiSynth *self);
-
-    void (*const update)(MidiSynth *self, ALCdevice *device);
-    void (*const process)(MidiSynth *self, ALuint samples, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
-
-    void (*const Delete)(void *ptr);
-};
-
-#define DEFINE_MIDISYNTH_VTABLE(T)                                            \
-DECLARE_THUNK(T, MidiSynth, void, Destruct)                                   \
-DECLARE_THUNK3(T, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*) \
-DECLARE_THUNK1(T, MidiSynth, void, setGain, ALfloat)                          \
-DECLARE_THUNK(T, MidiSynth, void, stop)                                       \
-DECLARE_THUNK(T, MidiSynth, void, reset)                                      \
-DECLARE_THUNK1(T, MidiSynth, void, update, ALCdevice*)                        \
-DECLARE_THUNK2(T, MidiSynth, void, process, ALuint, ALfloatBUFFERSIZE*restrict) \
-static void T##_MidiSynth_Delete(void *ptr)                                   \
-{ T##_Delete(STATIC_UPCAST(T, MidiSynth, (MidiSynth*)ptr)); }                 \
-                                                                              \
-static const struct MidiSynthVtable T##_MidiSynth_vtable = {                  \
-    T##_MidiSynth_Destruct,                                                   \
-                                                                              \
-    T##_MidiSynth_selectSoundfonts,                                           \
-    T##_MidiSynth_setGain,                                                    \
-    T##_MidiSynth_stop,                                                       \
-    T##_MidiSynth_reset,                                                      \
-    T##_MidiSynth_update,                                                     \
-    T##_MidiSynth_process,                                                    \
-                                                                              \
-    T##_MidiSynth_Delete,                                                     \
-}
-
-
-MidiSynth *SSynth_create(ALCdevice *device);
-MidiSynth *FSynth_create(ALCdevice *device);
-MidiSynth *DSynth_create(ALCdevice *device);
-
-MidiSynth *SynthCreate(ALCdevice *device);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AL_MIDI_BASE_H */

+ 0 - 76
love/src/jni/openal-soft-1.17.0/Alc/midi/dummy.c

@@ -1,76 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "alMain.h"
-#include "alError.h"
-#include "evtqueue.h"
-#include "rwlock.h"
-#include "alu.h"
-
-#include "midi/base.h"
-
-typedef struct DSynth {
-    DERIVE_FROM_TYPE(MidiSynth);
-} DSynth;
-
-static void DSynth_Construct(DSynth *self, ALCdevice *device);
-static DECLARE_FORWARD(DSynth, MidiSynth, void, Destruct)
-static DECLARE_FORWARD3(DSynth, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*)
-static DECLARE_FORWARD1(DSynth, MidiSynth, void, setGain, ALfloat)
-static DECLARE_FORWARD(DSynth, MidiSynth, void, stop)
-static DECLARE_FORWARD(DSynth, MidiSynth, void, reset)
-static DECLARE_FORWARD1(DSynth, MidiSynth, void, update, ALCdevice*)
-static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
-DECLARE_DEFAULT_ALLOCATORS(DSynth)
-DEFINE_MIDISYNTH_VTABLE(DSynth);
-
-
-static void DSynth_Construct(DSynth *self, ALCdevice *device)
-{
-    MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device);
-    SET_VTABLE2(DSynth, MidiSynth, self);
-}
-
-
-static void DSynth_processQueue(DSynth *self, ALuint64 time)
-{
-    EvtQueue *queue = &STATIC_CAST(MidiSynth, self)->EventQueue;
-
-    while(queue->pos < queue->size && queue->events[queue->pos].time <= time)
-        queue->pos++;
-}
-
-static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloatBUFFERSIZE*restrict UNUSED(DryBuffer))
-{
-    MidiSynth *synth = STATIC_CAST(MidiSynth, self);
-    ALuint64 curtime;
-
-    if(synth->State != AL_PLAYING)
-        return;
-
-    synth->SamplesDone += SamplesToDo;
-    synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
-    synth->SamplesDone %= synth->SampleRate;
-
-    curtime = MidiSynth_getTime(synth);
-    DSynth_processQueue(self, maxi64(curtime-1, 0));
-}
-
-
-MidiSynth *DSynth_create(ALCdevice *device)
-{
-    DSynth *synth = DSynth_New(sizeof(*synth));
-    if(!synth)
-    {
-        ERR("Failed to allocate DSynth\n");
-        return NULL;
-    }
-    memset(synth, 0, sizeof(*synth));
-    DSynth_Construct(synth, device);
-    return STATIC_CAST(MidiSynth, synth);
-}

+ 0 - 930
love/src/jni/openal-soft-1.17.0/Alc/midi/fluidsynth.c

@@ -1,930 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "midi/base.h"
-
-#include "alMain.h"
-#include "alError.h"
-#include "alMidi.h"
-#include "alu.h"
-#include "compat.h"
-#include "evtqueue.h"
-#include "rwlock.h"
-
-#ifdef HAVE_FLUIDSYNTH
-
-#include <fluidsynth.h>
-
-
-#ifdef HAVE_DYNLOAD
-#define FLUID_FUNCS(MAGIC)                                                    \
-    MAGIC(new_fluid_synth);                                                   \
-    MAGIC(delete_fluid_synth);                                                \
-    MAGIC(new_fluid_settings);                                                \
-    MAGIC(delete_fluid_settings);                                             \
-    MAGIC(fluid_settings_setint);                                             \
-    MAGIC(fluid_settings_setnum);                                             \
-    MAGIC(fluid_synth_noteon);                                                \
-    MAGIC(fluid_synth_noteoff);                                               \
-    MAGIC(fluid_synth_program_change);                                        \
-    MAGIC(fluid_synth_pitch_bend);                                            \
-    MAGIC(fluid_synth_channel_pressure);                                      \
-    MAGIC(fluid_synth_cc);                                                    \
-    MAGIC(fluid_synth_sysex);                                                 \
-    MAGIC(fluid_synth_bank_select);                                           \
-    MAGIC(fluid_synth_set_channel_type);                                      \
-    MAGIC(fluid_synth_all_sounds_off);                                        \
-    MAGIC(fluid_synth_system_reset);                                          \
-    MAGIC(fluid_synth_set_gain);                                              \
-    MAGIC(fluid_synth_set_sample_rate);                                       \
-    MAGIC(fluid_synth_write_float);                                           \
-    MAGIC(fluid_synth_add_sfloader);                                          \
-    MAGIC(fluid_synth_sfload);                                                \
-    MAGIC(fluid_synth_sfunload);                                              \
-    MAGIC(fluid_synth_alloc_voice);                                           \
-    MAGIC(fluid_synth_start_voice);                                           \
-    MAGIC(fluid_voice_gen_set);                                               \
-    MAGIC(fluid_voice_add_mod);                                               \
-    MAGIC(fluid_mod_set_source1);                                             \
-    MAGIC(fluid_mod_set_source2);                                             \
-    MAGIC(fluid_mod_set_amount);                                              \
-    MAGIC(fluid_mod_set_dest);
-
-void *fsynth_handle = NULL;
-#define DECL_FUNC(x) __typeof(x) *p##x
-FLUID_FUNCS(DECL_FUNC)
-#undef DECL_FUNC
-
-#define new_fluid_synth pnew_fluid_synth
-#define delete_fluid_synth pdelete_fluid_synth
-#define new_fluid_settings pnew_fluid_settings
-#define delete_fluid_settings pdelete_fluid_settings
-#define fluid_settings_setint pfluid_settings_setint
-#define fluid_settings_setnum pfluid_settings_setnum
-#define fluid_synth_noteon pfluid_synth_noteon
-#define fluid_synth_noteoff pfluid_synth_noteoff
-#define fluid_synth_program_change pfluid_synth_program_change
-#define fluid_synth_pitch_bend pfluid_synth_pitch_bend
-#define fluid_synth_channel_pressure pfluid_synth_channel_pressure
-#define fluid_synth_cc pfluid_synth_cc
-#define fluid_synth_sysex pfluid_synth_sysex
-#define fluid_synth_bank_select pfluid_synth_bank_select
-#define fluid_synth_set_channel_type pfluid_synth_set_channel_type
-#define fluid_synth_all_sounds_off pfluid_synth_all_sounds_off
-#define fluid_synth_system_reset pfluid_synth_system_reset
-#define fluid_synth_set_gain pfluid_synth_set_gain
-#define fluid_synth_set_sample_rate pfluid_synth_set_sample_rate
-#define fluid_synth_write_float pfluid_synth_write_float
-#define fluid_synth_add_sfloader pfluid_synth_add_sfloader
-#define fluid_synth_sfload pfluid_synth_sfload
-#define fluid_synth_sfunload pfluid_synth_sfunload
-#define fluid_synth_alloc_voice pfluid_synth_alloc_voice
-#define fluid_synth_start_voice pfluid_synth_start_voice
-#define fluid_voice_gen_set pfluid_voice_gen_set
-#define fluid_voice_add_mod pfluid_voice_add_mod
-#define fluid_mod_set_source1 pfluid_mod_set_source1
-#define fluid_mod_set_source2 pfluid_mod_set_source2
-#define fluid_mod_set_amount pfluid_mod_set_amount
-#define fluid_mod_set_dest pfluid_mod_set_dest
-
-static ALboolean LoadFSynth(void)
-{
-    ALboolean ret = AL_TRUE;
-    if(!fsynth_handle)
-    {
-        fsynth_handle = LoadLib("libfluidsynth.so.1");
-        if(!fsynth_handle) return AL_FALSE;
-
-#define LOAD_FUNC(x) do {                                                     \
-     p##x = GetSymbol(fsynth_handle, #x);                                     \
-     if(!p##x) ret = AL_FALSE;                                                \
-} while(0)
-        FLUID_FUNCS(LOAD_FUNC)
-#undef LOAD_FUNC
-
-        if(ret == AL_FALSE)
-        {
-            CloseLib(fsynth_handle);
-            fsynth_handle = NULL;
-        }
-    }
-    return ret;
-}
-#else
-static inline ALboolean LoadFSynth(void) { return AL_TRUE; }
-#endif
-
-
-/* MIDI events */
-#define SYSEX_EVENT  (0xF0)
-
-/* MIDI controllers */
-#define CTRL_BANKSELECT_MSB  (0)
-#define CTRL_BANKSELECT_LSB  (32)
-#define CTRL_ALLNOTESOFF     (123)
-
-
-static int getModInput(ALenum input)
-{
-    switch(input)
-    {
-        case AL_ONE_SOFT: return FLUID_MOD_NONE;
-        case AL_NOTEON_VELOCITY_SOFT: return FLUID_MOD_VELOCITY;
-        case AL_NOTEON_KEY_SOFT: return FLUID_MOD_KEY;
-        case AL_KEYPRESSURE_SOFT: return FLUID_MOD_KEYPRESSURE;
-        case AL_CHANNELPRESSURE_SOFT: return FLUID_MOD_CHANNELPRESSURE;
-        case AL_PITCHBEND_SOFT: return FLUID_MOD_PITCHWHEEL;
-        case AL_PITCHBEND_SENSITIVITY_SOFT: return FLUID_MOD_PITCHWHEELSENS;
-    }
-    return input&0x7F;
-}
-
-static int getModFlags(ALenum input, ALenum type, ALenum form)
-{
-    int ret = 0;
-
-    switch(type)
-    {
-        case AL_UNORM_SOFT: ret |= FLUID_MOD_UNIPOLAR | FLUID_MOD_POSITIVE; break;
-        case AL_UNORM_REV_SOFT: ret |= FLUID_MOD_UNIPOLAR | FLUID_MOD_NEGATIVE; break;
-        case AL_SNORM_SOFT: ret |= FLUID_MOD_BIPOLAR | FLUID_MOD_POSITIVE; break;
-        case AL_SNORM_REV_SOFT: ret |= FLUID_MOD_BIPOLAR | FLUID_MOD_NEGATIVE; break;
-    }
-    switch(form)
-    {
-        case AL_LINEAR_SOFT: ret |= FLUID_MOD_LINEAR; break;
-        case AL_CONCAVE_SOFT: ret |= FLUID_MOD_CONCAVE; break;
-        case AL_CONVEX_SOFT: ret |= FLUID_MOD_CONVEX; break;
-        case AL_SWITCH_SOFT: ret |= FLUID_MOD_SWITCH; break;
-    }
-    /* Source input values less than 128 correspond to a MIDI continuous
-     * controller. Otherwise, it's a general controller. */
-    if(input < 128) ret |= FLUID_MOD_CC;
-    else ret |= FLUID_MOD_GC;
-
-    return ret;
-}
-
-static enum fluid_gen_type getModDest(ALenum gen)
-{
-    switch(gen)
-    {
-        case AL_MOD_LFO_TO_PITCH_SOFT: return GEN_MODLFOTOPITCH;
-        case AL_VIBRATO_LFO_TO_PITCH_SOFT: return GEN_VIBLFOTOPITCH;
-        case AL_MOD_ENV_TO_PITCH_SOFT: return GEN_MODENVTOPITCH;
-        case AL_FILTER_CUTOFF_SOFT: return GEN_FILTERFC;
-        case AL_FILTER_RESONANCE_SOFT: return GEN_FILTERQ;
-        case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT: return GEN_MODLFOTOFILTERFC;
-        case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT: return GEN_MODENVTOFILTERFC;
-        case AL_MOD_LFO_TO_VOLUME_SOFT: return GEN_MODLFOTOVOL;
-        case AL_CHORUS_SEND_SOFT: return GEN_CHORUSSEND;
-        case AL_REVERB_SEND_SOFT: return GEN_REVERBSEND;
-        case AL_PAN_SOFT: return GEN_PAN;
-        case AL_MOD_LFO_DELAY_SOFT: return GEN_MODLFODELAY;
-        case AL_MOD_LFO_FREQUENCY_SOFT: return GEN_MODLFOFREQ;
-        case AL_VIBRATO_LFO_DELAY_SOFT: return GEN_VIBLFODELAY;
-        case AL_VIBRATO_LFO_FREQUENCY_SOFT: return GEN_VIBLFOFREQ;
-        case AL_MOD_ENV_DELAYTIME_SOFT: return GEN_MODENVDELAY;
-        case AL_MOD_ENV_ATTACKTIME_SOFT: return GEN_MODENVATTACK;
-        case AL_MOD_ENV_HOLDTIME_SOFT: return GEN_MODENVHOLD;
-        case AL_MOD_ENV_DECAYTIME_SOFT: return GEN_MODENVDECAY;
-        case AL_MOD_ENV_SUSTAINVOLUME_SOFT: return GEN_MODENVSUSTAIN;
-        case AL_MOD_ENV_RELEASETIME_SOFT: return GEN_MODENVRELEASE;
-        case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT: return GEN_KEYTOMODENVHOLD;
-        case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT: return GEN_KEYTOMODENVDECAY;
-        case AL_VOLUME_ENV_DELAYTIME_SOFT: return GEN_VOLENVDELAY;
-        case AL_VOLUME_ENV_ATTACKTIME_SOFT: return GEN_VOLENVATTACK;
-        case AL_VOLUME_ENV_HOLDTIME_SOFT: return GEN_VOLENVHOLD;
-        case AL_VOLUME_ENV_DECAYTIME_SOFT: return GEN_VOLENVDECAY;
-        case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT: return GEN_VOLENVSUSTAIN;
-        case AL_VOLUME_ENV_RELEASETIME_SOFT: return GEN_VOLENVRELEASE;
-        case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT: return GEN_KEYTOVOLENVHOLD;
-        case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT: return GEN_KEYTOVOLENVDECAY;
-        case AL_ATTENUATION_SOFT: return GEN_ATTENUATION;
-        case AL_TUNING_COARSE_SOFT: return GEN_COARSETUNE;
-        case AL_TUNING_FINE_SOFT: return GEN_FINETUNE;
-        case AL_TUNING_SCALE_SOFT: return GEN_SCALETUNE;
-    }
-    ERR("Unhandled generator: 0x%04x\n", gen);
-    return 0;
-}
-
-static int getSf2LoopMode(ALenum mode)
-{
-    switch(mode)
-    {
-        case AL_NONE: return 0;
-        case AL_LOOP_CONTINUOUS_SOFT: return 1;
-        case AL_LOOP_UNTIL_RELEASE_SOFT: return 3;
-    }
-    return 0;
-}
-
-static int getSampleType(ALenum type)
-{
-    switch(type)
-    {
-        case AL_MONO_SOFT: return FLUID_SAMPLETYPE_MONO;
-        case AL_RIGHT_SOFT: return FLUID_SAMPLETYPE_RIGHT;
-        case AL_LEFT_SOFT: return FLUID_SAMPLETYPE_LEFT;
-    }
-    return FLUID_SAMPLETYPE_MONO;
-}
-
-typedef struct FSample {
-    DERIVE_FROM_TYPE(fluid_sample_t);
-
-    ALfontsound *Sound;
-
-    fluid_mod_t *Mods;
-    ALsizei NumMods;
-} FSample;
-
-static void FSample_Construct(FSample *self, ALfontsound *sound)
-{
-    fluid_sample_t *sample = STATIC_CAST(fluid_sample_t, self);
-    memset(sample->name, 0, sizeof(sample->name));
-    sample->start = sound->Start;
-    sample->end = sound->End;
-    sample->loopstart = sound->LoopStart;
-    sample->loopend = sound->LoopEnd;
-    sample->samplerate = sound->SampleRate;
-    sample->origpitch = sound->PitchKey;
-    sample->pitchadj = sound->PitchCorrection;
-    sample->sampletype = getSampleType(sound->SampleType);
-    sample->valid = !!sound->Buffer;
-    sample->data = sound->Buffer ? sound->Buffer->data : NULL;
-
-    sample->amplitude_that_reaches_noise_floor_is_valid = 0;
-    sample->amplitude_that_reaches_noise_floor = 0.0;
-
-    sample->refcount = 0;
-
-    sample->notify = NULL;
-
-    sample->userdata = self;
-
-    self->Sound = sound;
-
-    self->NumMods = 0;
-    self->Mods = calloc(sound->ModulatorMap.size*4, sizeof(fluid_mod_t[4]));
-    if(self->Mods)
-    {
-        ALsizei i, j, k;
-
-        for(i = j = 0;i < sound->ModulatorMap.size;i++)
-        {
-            ALsfmodulator *mod = sound->ModulatorMap.array[i].value;
-            for(k = 0;k < 4;k++,mod++)
-            {
-                if(mod->Dest == AL_NONE)
-                    continue;
-                fluid_mod_set_source1(&self->Mods[j], getModInput(mod->Source[0].Input),
-                                      getModFlags(mod->Source[0].Input, mod->Source[0].Type,
-                                                  mod->Source[0].Form));
-                fluid_mod_set_source2(&self->Mods[j], getModInput(mod->Source[1].Input),
-                                      getModFlags(mod->Source[1].Input, mod->Source[1].Type,
-                                                  mod->Source[1].Form));
-                fluid_mod_set_amount(&self->Mods[j], mod->Amount);
-                fluid_mod_set_dest(&self->Mods[j], getModDest(mod->Dest));
-                self->Mods[j++].next = NULL;
-            }
-        }
-        self->NumMods = j;
-    }
-}
-
-static void FSample_Destruct(FSample *self)
-{
-    free(self->Mods);
-    self->Mods = NULL;
-    self->NumMods = 0;
-}
-
-
-typedef struct FPreset {
-    DERIVE_FROM_TYPE(fluid_preset_t);
-
-    char Name[16];
-
-    int Preset;
-    int Bank;
-
-    FSample *Samples;
-    ALsizei NumSamples;
-} FPreset;
-
-static char* FPreset_getName(fluid_preset_t *preset);
-static int FPreset_getPreset(fluid_preset_t *preset);
-static int FPreset_getBank(fluid_preset_t *preset);
-static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int channel, int key, int velocity);
-
-static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t *parent)
-{
-    STATIC_CAST(fluid_preset_t, self)->data = self;
-    STATIC_CAST(fluid_preset_t, self)->sfont = parent;
-    STATIC_CAST(fluid_preset_t, self)->free = NULL;
-    STATIC_CAST(fluid_preset_t, self)->get_name = FPreset_getName;
-    STATIC_CAST(fluid_preset_t, self)->get_banknum = FPreset_getBank;
-    STATIC_CAST(fluid_preset_t, self)->get_num = FPreset_getPreset;
-    STATIC_CAST(fluid_preset_t, self)->noteon = FPreset_noteOn;
-    STATIC_CAST(fluid_preset_t, self)->notify = NULL;
-
-    memset(self->Name, 0, sizeof(self->Name));
-    self->Preset = preset->Preset;
-    self->Bank = preset->Bank;
-
-    self->NumSamples = 0;
-    self->Samples = calloc(1, preset->NumSounds * sizeof(self->Samples[0]));
-    if(self->Samples)
-    {
-        ALsizei i;
-        self->NumSamples = preset->NumSounds;
-        for(i = 0;i < self->NumSamples;i++)
-            FSample_Construct(&self->Samples[i], preset->Sounds[i]);
-    }
-}
-
-static void FPreset_Destruct(FPreset *self)
-{
-    ALsizei i;
-
-    for(i = 0;i < self->NumSamples;i++)
-        FSample_Destruct(&self->Samples[i]);
-    free(self->Samples);
-    self->Samples = NULL;
-    self->NumSamples = 0;
-}
-
-static ALboolean FPreset_canDelete(FPreset *self)
-{
-    ALsizei i;
-    for(i = 0;i < self->NumSamples;i++)
-    {
-        if(fluid_sample_refcount(STATIC_CAST(fluid_sample_t, &self->Samples[i])) != 0)
-            return AL_FALSE;
-    }
-    return AL_TRUE;
-}
-
-static char* FPreset_getName(fluid_preset_t *preset)
-{
-    return ((FPreset*)preset->data)->Name;
-}
-
-static int FPreset_getPreset(fluid_preset_t *preset)
-{
-    return ((FPreset*)preset->data)->Preset;
-}
-
-static int FPreset_getBank(fluid_preset_t *preset)
-{
-    return ((FPreset*)preset->data)->Bank;
-}
-
-static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int channel, int key, int vel)
-{
-    FPreset *self = ((FPreset*)preset->data);
-    ALsizei i;
-
-    for(i = 0;i < self->NumSamples;i++)
-    {
-        FSample *sample = &self->Samples[i];
-        ALfontsound *sound = sample->Sound;
-        fluid_voice_t *voice;
-        ALsizei m;
-
-        if(!(key >= sound->MinKey && key <= sound->MaxKey && vel >= sound->MinVelocity && vel <= sound->MaxVelocity))
-            continue;
-
-        voice = fluid_synth_alloc_voice(synth, STATIC_CAST(fluid_sample_t, sample), channel, key, vel);
-        if(voice == NULL) return FLUID_FAILED;
-
-        fluid_voice_gen_set(voice, GEN_MODLFOTOPITCH, sound->ModLfoToPitch);
-        fluid_voice_gen_set(voice, GEN_VIBLFOTOPITCH, sound->VibratoLfoToPitch);
-        fluid_voice_gen_set(voice, GEN_MODENVTOPITCH, sound->ModEnvToPitch);
-        fluid_voice_gen_set(voice, GEN_FILTERFC, sound->FilterCutoff);
-        fluid_voice_gen_set(voice, GEN_FILTERQ, sound->FilterQ);
-        fluid_voice_gen_set(voice, GEN_MODLFOTOFILTERFC, sound->ModLfoToFilterCutoff);
-        fluid_voice_gen_set(voice, GEN_MODENVTOFILTERFC, sound->ModEnvToFilterCutoff);
-        fluid_voice_gen_set(voice, GEN_MODLFOTOVOL, sound->ModLfoToVolume);
-        fluid_voice_gen_set(voice, GEN_CHORUSSEND, sound->ChorusSend);
-        fluid_voice_gen_set(voice, GEN_REVERBSEND, sound->ReverbSend);
-        fluid_voice_gen_set(voice, GEN_PAN, sound->Pan);
-        fluid_voice_gen_set(voice, GEN_MODLFODELAY, sound->ModLfo.Delay);
-        fluid_voice_gen_set(voice, GEN_MODLFOFREQ, sound->ModLfo.Frequency);
-        fluid_voice_gen_set(voice, GEN_VIBLFODELAY, sound->VibratoLfo.Delay);
-        fluid_voice_gen_set(voice, GEN_VIBLFOFREQ, sound->VibratoLfo.Frequency);
-        fluid_voice_gen_set(voice, GEN_MODENVDELAY, sound->ModEnv.DelayTime);
-        fluid_voice_gen_set(voice, GEN_MODENVATTACK, sound->ModEnv.AttackTime);
-        fluid_voice_gen_set(voice, GEN_MODENVHOLD, sound->ModEnv.HoldTime);
-        fluid_voice_gen_set(voice, GEN_MODENVDECAY, sound->ModEnv.DecayTime);
-        fluid_voice_gen_set(voice, GEN_MODENVSUSTAIN, sound->ModEnv.SustainAttn);
-        fluid_voice_gen_set(voice, GEN_MODENVRELEASE, sound->ModEnv.ReleaseTime);
-        fluid_voice_gen_set(voice, GEN_KEYTOMODENVHOLD, sound->ModEnv.KeyToHoldTime);
-        fluid_voice_gen_set(voice, GEN_KEYTOMODENVDECAY, sound->ModEnv.KeyToDecayTime);
-        fluid_voice_gen_set(voice, GEN_VOLENVDELAY, sound->VolEnv.DelayTime);
-        fluid_voice_gen_set(voice, GEN_VOLENVATTACK, sound->VolEnv.AttackTime);
-        fluid_voice_gen_set(voice, GEN_VOLENVHOLD, sound->VolEnv.HoldTime);
-        fluid_voice_gen_set(voice, GEN_VOLENVDECAY, sound->VolEnv.DecayTime);
-        fluid_voice_gen_set(voice, GEN_VOLENVSUSTAIN, sound->VolEnv.SustainAttn);
-        fluid_voice_gen_set(voice, GEN_VOLENVRELEASE, sound->VolEnv.ReleaseTime);
-        fluid_voice_gen_set(voice, GEN_KEYTOVOLENVHOLD, sound->VolEnv.KeyToHoldTime);
-        fluid_voice_gen_set(voice, GEN_KEYTOVOLENVDECAY, sound->VolEnv.KeyToDecayTime);
-        fluid_voice_gen_set(voice, GEN_ATTENUATION, sound->Attenuation);
-        fluid_voice_gen_set(voice, GEN_COARSETUNE, sound->CoarseTuning);
-        fluid_voice_gen_set(voice, GEN_FINETUNE, sound->FineTuning);
-        fluid_voice_gen_set(voice, GEN_SAMPLEMODE, getSf2LoopMode(sound->LoopMode));
-        fluid_voice_gen_set(voice, GEN_SCALETUNE, sound->TuningScale);
-        fluid_voice_gen_set(voice, GEN_EXCLUSIVECLASS, sound->ExclusiveClass);
-        for(m = 0;m < sample->NumMods;m++)
-            fluid_voice_add_mod(voice, &sample->Mods[m], FLUID_VOICE_OVERWRITE);
-
-        fluid_synth_start_voice(synth, voice);
-    }
-
-    return FLUID_OK;
-}
-
-
-typedef struct FSfont {
-    DERIVE_FROM_TYPE(fluid_sfont_t);
-
-    char Name[16];
-
-    FPreset *Presets;
-    ALsizei NumPresets;
-
-    ALsizei CurrentPos;
-} FSfont;
-
-static int FSfont_free(fluid_sfont_t *sfont);
-static char* FSfont_getName(fluid_sfont_t *sfont);
-static fluid_preset_t* FSfont_getPreset(fluid_sfont_t *sfont, unsigned int bank, unsigned int prenum);
-static void FSfont_iterStart(fluid_sfont_t *sfont);
-static int FSfont_iterNext(fluid_sfont_t *sfont, fluid_preset_t *preset);
-
-static void FSfont_Construct(FSfont *self, ALsoundfont *sfont)
-{
-    STATIC_CAST(fluid_sfont_t, self)->data = self;
-    STATIC_CAST(fluid_sfont_t, self)->id = FLUID_FAILED;
-    STATIC_CAST(fluid_sfont_t, self)->free = FSfont_free;
-    STATIC_CAST(fluid_sfont_t, self)->get_name = FSfont_getName;
-    STATIC_CAST(fluid_sfont_t, self)->get_preset = FSfont_getPreset;
-    STATIC_CAST(fluid_sfont_t, self)->iteration_start = FSfont_iterStart;
-    STATIC_CAST(fluid_sfont_t, self)->iteration_next = FSfont_iterNext;
-
-    memset(self->Name, 0, sizeof(self->Name));
-    self->CurrentPos = 0;
-    self->NumPresets = 0;
-    self->Presets = calloc(1, sfont->NumPresets * sizeof(self->Presets[0]));
-    if(self->Presets)
-    {
-        ALsizei i;
-        self->NumPresets = sfont->NumPresets;
-        for(i = 0;i < self->NumPresets;i++)
-            FPreset_Construct(&self->Presets[i], sfont->Presets[i], STATIC_CAST(fluid_sfont_t, self));
-    }
-}
-
-static void FSfont_Destruct(FSfont *self)
-{
-    ALsizei i;
-
-    for(i = 0;i < self->NumPresets;i++)
-        FPreset_Destruct(&self->Presets[i]);
-    free(self->Presets);
-    self->Presets = NULL;
-    self->NumPresets = 0;
-    self->CurrentPos = 0;
-}
-
-static int FSfont_free(fluid_sfont_t *sfont)
-{
-    FSfont *self = STATIC_UPCAST(FSfont, fluid_sfont_t, sfont);
-    ALsizei i;
-
-    for(i = 0;i < self->NumPresets;i++)
-    {
-        if(!FPreset_canDelete(&self->Presets[i]))
-            return 1;
-    }
-
-    FSfont_Destruct(self);
-    free(self);
-    return 0;
-}
-
-static char* FSfont_getName(fluid_sfont_t *sfont)
-{
-    return STATIC_UPCAST(FSfont, fluid_sfont_t, sfont)->Name;
-}
-
-static fluid_preset_t *FSfont_getPreset(fluid_sfont_t *sfont, unsigned int bank, unsigned int prenum)
-{
-    FSfont *self = STATIC_UPCAST(FSfont, fluid_sfont_t, sfont);
-    ALsizei i;
-
-    for(i = 0;i < self->NumPresets;i++)
-    {
-        FPreset *preset = &self->Presets[i];
-        if(preset->Bank == (int)bank && preset->Preset == (int)prenum)
-            return STATIC_CAST(fluid_preset_t, preset);
-    }
-
-    return NULL;
-}
-
-static void FSfont_iterStart(fluid_sfont_t *sfont)
-{
-    STATIC_UPCAST(FSfont, fluid_sfont_t, sfont)->CurrentPos = 0;
-}
-
-static int FSfont_iterNext(fluid_sfont_t *sfont, fluid_preset_t *preset)
-{
-    FSfont *self = STATIC_UPCAST(FSfont, fluid_sfont_t, sfont);
-    if(self->CurrentPos >= self->NumPresets)
-        return 0;
-    *preset = *STATIC_CAST(fluid_preset_t, &self->Presets[self->CurrentPos++]);
-    preset->free = NULL;
-    return 1;
-}
-
-
-typedef struct FSynth {
-    DERIVE_FROM_TYPE(MidiSynth);
-    DERIVE_FROM_TYPE(fluid_sfloader_t);
-
-    fluid_settings_t *Settings;
-    fluid_synth_t *Synth;
-    int *FontIDs;
-    ALsizei NumFontIDs;
-
-    ALboolean ForceGM2BankSelect;
-    ALfloat GainScale;
-} FSynth;
-
-static void FSynth_Construct(FSynth *self, ALCdevice *device);
-static void FSynth_Destruct(FSynth *self);
-static ALboolean FSynth_init(FSynth *self, ALCdevice *device);
-static ALenum FSynth_selectSoundfonts(FSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids);
-static void FSynth_setGain(FSynth *self, ALfloat gain);
-static void FSynth_stop(FSynth *self);
-static void FSynth_reset(FSynth *self);
-static void FSynth_update(FSynth *self, ALCdevice *device);
-static void FSynth_processQueue(FSynth *self, ALuint64 time);
-static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]);
-DECLARE_DEFAULT_ALLOCATORS(FSynth)
-DEFINE_MIDISYNTH_VTABLE(FSynth);
-
-static fluid_sfont_t *FSynth_loadSfont(fluid_sfloader_t *loader, const char *filename);
-
-
-static void FSynth_Construct(FSynth *self, ALCdevice *device)
-{
-    MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device);
-    SET_VTABLE2(FSynth, MidiSynth, self);
-
-    STATIC_CAST(fluid_sfloader_t, self)->data = self;
-    STATIC_CAST(fluid_sfloader_t, self)->free = NULL;
-    STATIC_CAST(fluid_sfloader_t, self)->load = FSynth_loadSfont;
-
-    self->Settings = NULL;
-    self->Synth = NULL;
-    self->FontIDs = NULL;
-    self->NumFontIDs = 0;
-    self->ForceGM2BankSelect = AL_FALSE;
-    self->GainScale = 0.2f;
-}
-
-static void FSynth_Destruct(FSynth *self)
-{
-    ALsizei i;
-
-    for(i = 0;i < self->NumFontIDs;i++)
-        fluid_synth_sfunload(self->Synth, self->FontIDs[i], 0);
-    free(self->FontIDs);
-    self->FontIDs = NULL;
-    self->NumFontIDs = 0;
-
-    if(self->Synth != NULL)
-        delete_fluid_synth(self->Synth);
-    self->Synth = NULL;
-
-    if(self->Settings != NULL)
-        delete_fluid_settings(self->Settings);
-    self->Settings = NULL;
-
-    MidiSynth_Destruct(STATIC_CAST(MidiSynth, self));
-}
-
-static ALboolean FSynth_init(FSynth *self, ALCdevice *device)
-{
-    ALfloat vol;
-
-    if(ConfigValueFloat("midi", "volume", &vol))
-    {
-        if(!(vol <= 0.0f))
-        {
-            ERR("MIDI volume %f clamped to 0\n", vol);
-            vol = 0.0f;
-        }
-        self->GainScale = powf(10.0f, vol / 20.0f);
-    }
-
-    self->Settings = new_fluid_settings();
-    if(!self->Settings)
-    {
-        ERR("Failed to create FluidSettings\n");
-        return AL_FALSE;
-    }
-
-    fluid_settings_setint(self->Settings, "synth.polyphony", 256);
-    fluid_settings_setnum(self->Settings, "synth.gain", self->GainScale);
-    fluid_settings_setnum(self->Settings, "synth.sample-rate", device->Frequency);
-
-    self->Synth = new_fluid_synth(self->Settings);
-    if(!self->Synth)
-    {
-        ERR("Failed to create FluidSynth\n");
-        return AL_FALSE;
-    }
-
-    fluid_synth_add_sfloader(self->Synth, STATIC_CAST(fluid_sfloader_t, self));
-
-    return AL_TRUE;
-}
-
-
-static fluid_sfont_t *FSynth_loadSfont(fluid_sfloader_t *loader, const char *filename)
-{
-    FSynth *self = STATIC_UPCAST(FSynth, fluid_sfloader_t, loader);
-    FSfont *sfont;
-    int idx;
-
-    if(!filename || sscanf(filename, "_al_internal %d", &idx) != 1)
-        return NULL;
-    if(idx < 0 || idx >= STATIC_CAST(MidiSynth, self)->NumSoundfonts)
-    {
-        ERR("Received invalid soundfont index %d (max: %d)\n", idx, STATIC_CAST(MidiSynth, self)->NumSoundfonts);
-        return NULL;
-    }
-
-    sfont = calloc(1, sizeof(sfont[0]));
-    if(!sfont) return NULL;
-
-    FSfont_Construct(sfont, STATIC_CAST(MidiSynth, self)->Soundfonts[idx]);
-    return STATIC_CAST(fluid_sfont_t, sfont);
-}
-
-static ALenum FSynth_selectSoundfonts(FSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids)
-{
-    int *fontid;
-    ALenum ret;
-    ALsizei i;
-
-    ret = MidiSynth_selectSoundfonts(STATIC_CAST(MidiSynth, self), context, count, ids);
-    if(ret != AL_NO_ERROR) return ret;
-
-    ALCdevice_Lock(context->Device);
-    for(i = 0;i < 16;i++)
-        fluid_synth_all_sounds_off(self->Synth, i);
-    ALCdevice_Unlock(context->Device);
-
-    fontid = malloc(count * sizeof(fontid[0]));
-    if(fontid)
-    {
-        for(i = 0;i < STATIC_CAST(MidiSynth, self)->NumSoundfonts;i++)
-        {
-            char name[16];
-            snprintf(name, sizeof(name), "_al_internal %d", i);
-
-            fontid[i] = fluid_synth_sfload(self->Synth, name, 0);
-            if(fontid[i] == FLUID_FAILED)
-                ERR("Failed to load selected soundfont %d\n", i);
-        }
-
-        fontid = ExchangePtr((XchgPtr*)&self->FontIDs, fontid);
-        count = ExchangeInt(&self->NumFontIDs, count);
-    }
-    else
-    {
-        ERR("Failed to allocate space for %d font IDs!\n", count);
-        fontid = ExchangePtr((XchgPtr*)&self->FontIDs, NULL);
-        count = ExchangeInt(&self->NumFontIDs, 0);
-    }
-
-    for(i = 0;i < count;i++)
-        fluid_synth_sfunload(self->Synth, fontid[i], 0);
-    free(fontid);
-
-    return ret;
-}
-
-
-static void FSynth_setGain(FSynth *self, ALfloat gain)
-{
-    fluid_settings_setnum(self->Settings, "synth.gain", self->GainScale * gain);
-    fluid_synth_set_gain(self->Synth, self->GainScale * gain);
-    MidiSynth_setGain(STATIC_CAST(MidiSynth, self), gain);
-}
-
-
-static void FSynth_stop(FSynth *self)
-{
-    MidiSynth *synth = STATIC_CAST(MidiSynth, self);
-    ALuint64 curtime;
-    ALsizei chan;
-
-    /* Make sure all pending events are processed. */
-    curtime = MidiSynth_getTime(synth);
-    FSynth_processQueue(self, curtime);
-
-    /* All notes off */
-    for(chan = 0;chan < 16;chan++)
-        fluid_synth_cc(self->Synth, chan, CTRL_ALLNOTESOFF, 0);
-
-    MidiSynth_stop(STATIC_CAST(MidiSynth, self));
-}
-
-static void FSynth_reset(FSynth *self)
-{
-    /* Reset to power-up status. */
-    fluid_synth_system_reset(self->Synth);
-
-    MidiSynth_reset(STATIC_CAST(MidiSynth, self));
-}
-
-
-static void FSynth_update(FSynth *self, ALCdevice *device)
-{
-    fluid_settings_setnum(self->Settings, "synth.sample-rate", device->Frequency);
-    fluid_synth_set_sample_rate(self->Synth, device->Frequency);
-    MidiSynth_update(STATIC_CAST(MidiSynth, self), device);
-}
-
-
-static void FSynth_processQueue(FSynth *self, ALuint64 time)
-{
-    EvtQueue *queue = &STATIC_CAST(MidiSynth, self)->EventQueue;
-
-    while(queue->pos < queue->size && queue->events[queue->pos].time <= time)
-    {
-        const MidiEvent *evt = &queue->events[queue->pos];
-
-        if(evt->event == SYSEX_EVENT)
-        {
-            static const ALbyte gm2_on[] = { 0x7E, 0x7F, 0x09, 0x03 };
-            static const ALbyte gm2_off[] = { 0x7E, 0x7F, 0x09, 0x02 };
-            int handled = 0;
-
-            fluid_synth_sysex(self->Synth, evt->param.sysex.data, evt->param.sysex.size, NULL, NULL, &handled, 0);
-            if(!handled && evt->param.sysex.size >= (ALsizei)sizeof(gm2_on))
-            {
-                if(memcmp(evt->param.sysex.data, gm2_on, sizeof(gm2_on)) == 0)
-                    self->ForceGM2BankSelect = AL_TRUE;
-                else if(memcmp(evt->param.sysex.data, gm2_off, sizeof(gm2_off)) == 0)
-                    self->ForceGM2BankSelect = AL_FALSE;
-            }
-        }
-        else switch((evt->event&0xF0))
-        {
-            case AL_NOTEOFF_SOFT:
-                fluid_synth_noteoff(self->Synth, (evt->event&0x0F), evt->param.val[0]);
-                break;
-            case AL_NOTEON_SOFT:
-                fluid_synth_noteon(self->Synth, (evt->event&0x0F), evt->param.val[0], evt->param.val[1]);
-                break;
-            case AL_KEYPRESSURE_SOFT:
-                break;
-
-            case AL_CONTROLLERCHANGE_SOFT:
-                if(self->ForceGM2BankSelect)
-                {
-                    int chan = (evt->event&0x0F);
-                    if(evt->param.val[0] == CTRL_BANKSELECT_MSB)
-                    {
-                        if(evt->param.val[1] == 120 && (chan == 9 || chan == 10))
-                            fluid_synth_set_channel_type(self->Synth, chan, CHANNEL_TYPE_DRUM);
-                        else if(evt->param.val[1] == 121)
-                            fluid_synth_set_channel_type(self->Synth, chan, CHANNEL_TYPE_MELODIC);
-                        break;
-                    }
-                    if(evt->param.val[0] == CTRL_BANKSELECT_LSB)
-                    {
-                        fluid_synth_bank_select(self->Synth, chan, evt->param.val[1]);
-                        break;
-                    }
-                }
-                fluid_synth_cc(self->Synth, (evt->event&0x0F), evt->param.val[0], evt->param.val[1]);
-                break;
-            case AL_PROGRAMCHANGE_SOFT:
-                fluid_synth_program_change(self->Synth, (evt->event&0x0F), evt->param.val[0]);
-                break;
-
-            case AL_CHANNELPRESSURE_SOFT:
-                fluid_synth_channel_pressure(self->Synth, (evt->event&0x0F), evt->param.val[0]);
-                break;
-
-            case AL_PITCHBEND_SOFT:
-                fluid_synth_pitch_bend(self->Synth, (evt->event&0x0F), (evt->param.val[0]&0x7F) |
-                                                                       ((evt->param.val[1]&0x7F)<<7));
-                break;
-        }
-
-        queue->pos++;
-    }
-}
-
-static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE])
-{
-    MidiSynth *synth = STATIC_CAST(MidiSynth, self);
-    ALenum state = synth->State;
-    ALuint64 curtime;
-    ALuint total = 0;
-
-    if(state == AL_INITIAL)
-        return;
-    if(state != AL_PLAYING)
-    {
-        fluid_synth_write_float(self->Synth, SamplesToDo, DryBuffer[FrontLeft], 0, 1,
-                                                          DryBuffer[FrontRight], 0, 1);
-        return;
-    }
-
-    curtime = MidiSynth_getTime(synth);
-    while(total < SamplesToDo)
-    {
-        ALuint64 time, diff;
-        ALint tonext;
-
-        time = MidiSynth_getNextEvtTime(synth);
-        diff = maxu64(time, curtime) - curtime;
-        if(diff >= MIDI_CLOCK_RES || time == UINT64_MAX)
-        {
-            /* If there's no pending event, or if it's more than 1 second
-             * away, do as many samples as we can. */
-            tonext = INT_MAX;
-        }
-        else
-        {
-            /* Figure out how many samples until the next event. */
-            tonext  = (ALint)((diff*synth->SampleRate + (MIDI_CLOCK_RES-1)) / MIDI_CLOCK_RES);
-            tonext -= total;
-        }
-
-        if(tonext > 0)
-        {
-            ALuint todo = minu(tonext, SamplesToDo-total);
-            fluid_synth_write_float(self->Synth, todo, DryBuffer[FrontLeft], total, 1,
-                                                       DryBuffer[FrontRight], total, 1);
-            total += todo;
-            tonext -= todo;
-        }
-        if(total < SamplesToDo && tonext <= 0)
-            FSynth_processQueue(self, time);
-    }
-
-    synth->SamplesDone += SamplesToDo;
-    synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES;
-    synth->SamplesDone %= synth->SampleRate;
-}
-
-
-MidiSynth *FSynth_create(ALCdevice *device)
-{
-    FSynth *synth;
-
-    if(!LoadFSynth())
-        return NULL;
-
-    synth = FSynth_New(sizeof(*synth));
-    if(!synth)
-    {
-        ERR("Failed to allocate FSynth\n");
-        return NULL;
-    }
-    memset(synth, 0, sizeof(*synth));
-    FSynth_Construct(synth, device);
-
-    if(FSynth_init(synth, device) == AL_FALSE)
-    {
-        DELETE_OBJ(STATIC_CAST(MidiSynth, synth));
-        return NULL;
-    }
-
-    return STATIC_CAST(MidiSynth, synth);
-}
-
-#else
-
-MidiSynth *FSynth_create(ALCdevice* UNUSED(device))
-{
-    return NULL;
-}
-
-#endif

+ 0 - 1377
love/src/jni/openal-soft-1.17.0/Alc/midi/sf2load.c

@@ -1,1377 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "alMain.h"
-#include "alMidi.h"
-#include "alError.h"
-#include "alu.h"
-
-#include "midi/base.h"
-
-
-static ALuint read_le32(Reader *stream)
-{
-    ALubyte buf[4];
-    if(Reader_read(stream, buf, 4) != 4)
-        return 0;
-    return (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0];
-}
-static ALushort read_le16(Reader *stream)
-{
-    ALubyte buf[2];
-    if(Reader_read(stream, buf, 2) != 2)
-        return 0;
-    return (buf[1]<<8) | buf[0];
-}
-static ALubyte read_8(Reader *stream)
-{
-    ALubyte buf[1];
-    if(Reader_read(stream, buf, 1) != 1)
-        return 0;
-    return buf[0];
-}
-static void skip(Reader *stream, ALuint amt)
-{
-    while(amt > 0 && !READERR(stream))
-    {
-        char buf[4096];
-        amt -= Reader_read(stream, buf, minu(sizeof(buf), amt));
-    }
-}
-
-typedef struct Generator {
-    ALushort mGenerator;
-    ALushort mAmount;
-} Generator;
-static void Generator_read(Generator *self, Reader *stream)
-{
-    self->mGenerator = read_le16(stream);
-    self->mAmount = read_le16(stream);
-}
-
-static const ALint DefaultGenValue[60] = {
-    0, /* 0 - startAddrOffset */
-    0, /* 1 - endAddrOffset */
-    0, /* 2 - startloopAddrOffset */
-    0, /* 3 - endloopAddrOffset */
-    0, /* 4 - startAddrCoarseOffset */
-    0, /* 5 - modLfoToPitch */
-    0, /* 6 - vibLfoToPitch */
-    0, /* 7 - modEnvToPitch */
-    13500, /* 8 - initialFilterFc */
-    0, /* 9 - initialFilterQ */
-    0, /* 10 - modLfoToFilterFc */
-    0, /* 11 - modEnvToFilterFc */
-    0, /* 12 - endAddrCoarseOffset */
-    0, /* 13 - modLfoToVolume */
-    0, /* 14 -  */
-    0, /* 15 - chorusEffectsSend */
-    0, /* 16 - reverbEffectsSend */
-    0, /* 17 - pan */
-    0, /* 18 -  */
-    0, /* 19 -  */
-    0, /* 20 -  */
-    -12000, /* 21 - delayModLFO */
-    0, /* 22 - freqModLFO */
-    -12000, /* 23 - delayVibLFO */
-    0, /* 24 - freqVibLFO */
-    -12000, /* 25 - delayModEnv */
-    -12000, /* 26 - attackModEnv */
-    -12000, /* 27 - holdModEnv */
-    -12000, /* 28 - decayModEnv */
-    0, /* 29 - sustainModEnv */
-    -12000, /* 30 - releaseModEnv */
-    0, /* 31 - keynumToModEnvHold */
-    0, /* 32 - keynumToModEnvDecay */
-    -12000, /* 33 - delayVolEnv */
-    -12000, /* 34 - attackVolEnv */
-    -12000, /* 35 - holdVolEnv */
-    -12000, /* 36 - decayVolEnv */
-    0, /* 37 - sustainVolEnv */
-    -12000, /* 38 - releaseVolEnv */
-    0, /* 39 - keynumToVolEnvHold */
-    0, /* 40 - keynumToVolEnvDecay */
-    0, /* 41 -  */
-    0, /* 42 -  */
-    0, /* 43 - keyRange */
-    0, /* 44 - velRange */
-    0, /* 45 - startloopAddrCoarseOffset */
-    0, /* 46 - keynum */
-    0, /* 47 - velocity */
-    0, /* 48 - initialAttenuation */
-    0, /* 49 -  */
-    0, /* 50 - endloopAddrCoarseOffset */
-    0, /* 51 - corseTune */
-    0, /* 52 - fineTune */
-    0, /* 53 -  */
-    0, /* 54 - sampleModes */
-    0, /* 55 -  */
-    100, /* 56 - scaleTuning */
-    0, /* 57 - exclusiveClass */
-    0, /* 58 - overridingRootKey */
-    0, /* 59 -  */
-};
-
-typedef struct Modulator {
-    ALushort mSrcOp;
-    ALushort mDstOp;
-    ALshort mAmount;
-    ALushort mAmtSrcOp;
-    ALushort mTransOp;
-} Modulator;
-static void Modulator_read(Modulator *self, Reader *stream)
-{
-    self->mSrcOp = read_le16(stream);
-    self->mDstOp = read_le16(stream);
-    self->mAmount = read_le16(stream);
-    self->mAmtSrcOp = read_le16(stream);
-    self->mTransOp = read_le16(stream);
-}
-
-typedef struct Zone {
-    ALushort mGenIdx;
-    ALushort mModIdx;
-} Zone;
-static void Zone_read(Zone *self, Reader *stream)
-{
-    self->mGenIdx = read_le16(stream);
-    self->mModIdx = read_le16(stream);
-}
-
-typedef struct PresetHeader {
-    ALchar mName[20];
-    ALushort mPreset; /* MIDI program number */
-    ALushort mBank;
-    ALushort mZoneIdx;
-    ALuint mLibrary;
-    ALuint mGenre;
-    ALuint mMorphology;
-} PresetHeader;
-static void PresetHeader_read(PresetHeader *self, Reader *stream)
-{
-    Reader_read(stream, self->mName, sizeof(self->mName));
-    self->mPreset = read_le16(stream);
-    self->mBank = read_le16(stream);
-    self->mZoneIdx = read_le16(stream);
-    self->mLibrary = read_le32(stream);
-    self->mGenre = read_le32(stream);
-    self->mMorphology = read_le32(stream);
-}
-
-typedef struct InstrumentHeader {
-    ALchar mName[20];
-    ALushort mZoneIdx;
-} InstrumentHeader;
-static void InstrumentHeader_read(InstrumentHeader *self, Reader *stream)
-{
-    Reader_read(stream, self->mName, sizeof(self->mName));
-    self->mZoneIdx = read_le16(stream);
-}
-
-typedef struct SampleHeader {
-    ALchar mName[20];
-    ALuint mStart;
-    ALuint mEnd;
-    ALuint mStartloop;
-    ALuint mEndloop;
-    ALuint mSampleRate;
-    ALubyte mOriginalKey;
-    ALbyte mCorrection;
-    ALushort mSampleLink;
-    ALushort mSampleType;
-} SampleHeader;
-static void SampleHeader_read(SampleHeader *self, Reader *stream)
-{
-    Reader_read(stream, self->mName, sizeof(self->mName));
-    self->mStart = read_le32(stream);
-    self->mEnd = read_le32(stream);
-    self->mStartloop = read_le32(stream);
-    self->mEndloop = read_le32(stream);
-    self->mSampleRate = read_le32(stream);
-    self->mOriginalKey = read_8(stream);
-    self->mCorrection = read_8(stream);
-    self->mSampleLink = read_le16(stream);
-    self->mSampleType = read_le16(stream);
-}
-
-
-typedef struct Soundfont {
-    ALuint ifil;
-    ALchar *irom;
-
-    PresetHeader *phdr;
-    ALsizei phdr_size;
-
-    Zone *pbag;
-    ALsizei pbag_size;
-    Modulator *pmod;
-    ALsizei pmod_size;
-    Generator *pgen;
-    ALsizei pgen_size;
-
-    InstrumentHeader *inst;
-    ALsizei inst_size;
-
-    Zone *ibag;
-    ALsizei ibag_size;
-    Modulator *imod;
-    ALsizei imod_size;
-    Generator *igen;
-    ALsizei igen_size;
-
-    SampleHeader *shdr;
-    ALsizei shdr_size;
-} Soundfont;
-
-static void Soundfont_Construct(Soundfont *self)
-{
-    self->ifil = 0;
-    self->irom = NULL;
-
-    self->phdr = NULL;
-    self->phdr_size = 0;
-
-    self->pbag = NULL;
-    self->pbag_size = 0;
-    self->pmod = NULL;
-    self->pmod_size = 0;
-    self->pgen = NULL;
-    self->pgen_size = 0;
-
-    self->inst = NULL;
-    self->inst_size = 0;
-
-    self->ibag = NULL;
-    self->ibag_size = 0;
-    self->imod = NULL;
-    self->imod_size = 0;
-    self->igen = NULL;
-    self->igen_size = 0;
-
-    self->shdr = NULL;
-    self->shdr_size = 0;
-}
-
-static void Soundfont_Destruct(Soundfont *self)
-{
-    free(self->irom);
-    self->irom = NULL;
-
-    free(self->phdr);
-    self->phdr = NULL;
-    self->phdr_size = 0;
-
-    free(self->pbag);
-    self->pbag = NULL;
-    self->pbag_size = 0;
-    free(self->pmod);
-    self->pmod = NULL;
-    self->pmod_size = 0;
-    free(self->pgen);
-    self->pgen = NULL;
-    self->pgen_size = 0;
-
-    free(self->inst);
-    self->inst = NULL;
-    self->inst_size = 0;
-
-    free(self->ibag);
-    self->ibag = NULL;
-    self->ibag_size = 0;
-    free(self->imod);
-    self->imod = NULL;
-    self->imod_size = 0;
-    free(self->igen);
-    self->igen = NULL;
-    self->igen_size = 0;
-
-    free(self->shdr);
-    self->shdr = NULL;
-    self->shdr_size = 0;
-}
-
-
-#define FOURCC(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24))
-#define FOURCCFMT     "%c%c%c%c"
-#define FOURCCARGS(x)  (char)((x)&0xff), (char)(((x)>>8)&0xff), (char)(((x)>>16)&0xff), (char)(((x)>>24)&0xff)
-typedef struct RiffHdr {
-    ALuint mCode;
-    ALuint mSize;
-} RiffHdr;
-static void RiffHdr_read(RiffHdr *self, Reader *stream)
-{
-    self->mCode = read_le32(stream);
-    self->mSize = read_le32(stream);
-}
-
-
-typedef struct GenModList {
-    VECTOR(Generator) gens;
-    VECTOR(Modulator) mods;
-} GenModList;
-
-static void GenModList_Construct(GenModList *self)
-{
-    VECTOR_INIT(self->gens);
-    VECTOR_INIT(self->mods);
-}
-
-static void GenModList_Destruct(GenModList *self)
-{
-    VECTOR_DEINIT(self->mods);
-    VECTOR_DEINIT(self->gens);
-}
-
-static GenModList GenModList_clone(const GenModList *self)
-{
-    GenModList ret;
-
-    GenModList_Construct(&ret);
-
-    VECTOR_INSERT(ret.gens, VECTOR_ITER_END(ret.gens),
-        VECTOR_ITER_BEGIN(self->gens), VECTOR_ITER_END(self->gens)
-    );
-    VECTOR_INSERT(ret.mods, VECTOR_ITER_END(ret.mods),
-        VECTOR_ITER_BEGIN(self->mods), VECTOR_ITER_END(self->mods)
-    );
-
-    return ret;
-}
-
-static void GenModList_insertGen(GenModList *self, const Generator *gen, ALboolean ispreset)
-{
-    Generator *i = VECTOR_ITER_BEGIN(self->gens);
-    Generator *end = VECTOR_ITER_END(self->gens);
-    for(;i != end;i++)
-    {
-        if(i->mGenerator == gen->mGenerator)
-        {
-            i->mAmount = gen->mAmount;
-            return;
-        }
-    }
-
-    if(ispreset &&
-       (gen->mGenerator == 0 || gen->mGenerator == 1 || gen->mGenerator == 2 ||
-        gen->mGenerator == 3 || gen->mGenerator == 4 || gen->mGenerator == 12 ||
-        gen->mGenerator == 45 || gen->mGenerator == 46 || gen->mGenerator == 47 ||
-        gen->mGenerator == 50 || gen->mGenerator == 54 || gen->mGenerator == 57 ||
-        gen->mGenerator == 58))
-        return;
-
-    if(VECTOR_PUSH_BACK(self->gens, *gen) == AL_FALSE)
-    {
-        ERR("Failed to insert generator (from %d elements)\n", VECTOR_SIZE(self->gens));
-        return;
-    }
-}
-static void GenModList_accumGen(GenModList *self, const Generator *gen)
-{
-    Generator *i = VECTOR_ITER_BEGIN(self->gens);
-    Generator *end = VECTOR_ITER_END(self->gens);
-    for(;i != end;i++)
-    {
-        if(i->mGenerator == gen->mGenerator)
-        {
-            if(gen->mGenerator == 43 || gen->mGenerator == 44)
-            {
-                /* Range generators accumulate by taking the intersection of
-                 * the two ranges.
-                 */
-                ALushort low = maxu(i->mAmount&0x00ff, gen->mAmount&0x00ff);
-                ALushort high = minu(i->mAmount&0xff00, gen->mAmount&0xff00);
-                i->mAmount = low | high;
-            }
-            else
-                i->mAmount += gen->mAmount;
-            return;
-        }
-    }
-
-    if(VECTOR_PUSH_BACK(self->gens, *gen) == AL_FALSE)
-    {
-        ERR("Failed to insert generator (from %d elements)\n", VECTOR_SIZE(self->gens));
-        return;
-    }
-    if(gen->mGenerator < 60)
-        VECTOR_BACK(self->gens).mAmount += DefaultGenValue[gen->mGenerator];
-}
-
-static void GenModList_insertMod(GenModList *self, const Modulator *mod)
-{
-    Modulator *i = VECTOR_ITER_BEGIN(self->mods);
-    Modulator *end = VECTOR_ITER_END(self->mods);
-    for(;i != end;i++)
-    {
-        if(i->mDstOp == mod->mDstOp && i->mSrcOp == mod->mSrcOp &&
-           i->mAmtSrcOp == mod->mAmtSrcOp && i->mTransOp == mod->mTransOp)
-        {
-            i->mAmount = mod->mAmount;
-            return;
-        }
-    }
-
-    if(VECTOR_PUSH_BACK(self->mods, *mod) == AL_FALSE)
-    {
-        ERR("Failed to insert modulator (from %d elements)\n", VECTOR_SIZE(self->mods));
-        return;
-    }
-}
-static void GenModList_accumMod(GenModList *self, const Modulator *mod)
-{
-    Modulator *i = VECTOR_ITER_BEGIN(self->mods);
-    Modulator *end = VECTOR_ITER_END(self->mods);
-    for(;i != end;i++)
-    {
-        if(i->mDstOp == mod->mDstOp && i->mSrcOp == mod->mSrcOp &&
-           i->mAmtSrcOp == mod->mAmtSrcOp && i->mTransOp == mod->mTransOp)
-        {
-            i->mAmount += mod->mAmount;
-            return;
-        }
-    }
-
-    if(VECTOR_PUSH_BACK(self->mods, *mod) == AL_FALSE)
-    {
-        ERR("Failed to insert modulator (from %d elements)\n", VECTOR_SIZE(self->mods));
-        return;
-    }
-
-    if(mod->mSrcOp == 0x0502 && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 960;
-    else if(mod->mSrcOp == 0x0102 && mod->mDstOp == 8 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += -2400;
-    else if(mod->mSrcOp == 0x000D && mod->mDstOp == 6 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 50;
-    else if(mod->mSrcOp == 0x0081 && mod->mDstOp == 6 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 50;
-    else if(mod->mSrcOp == 0x0582 && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 960;
-    else if(mod->mSrcOp == 0x028A && mod->mDstOp == 17 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 1000;
-    else if(mod->mSrcOp == 0x058B && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 960;
-    else if(mod->mSrcOp == 0x00DB && mod->mDstOp == 16 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 200;
-    else if(mod->mSrcOp == 0x00DD && mod->mDstOp == 15 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 200;
-    /*else if(mod->mSrcOp == 0x020E && mod->mDstOp == ?initialpitch? && mod->mAmtSrcOp == 0x0010 && mod->mTransOp == 0)
-        VECTOR_BACK(self->mods).mAmount += 12700;*/
-}
-
-
-#define ERROR_GOTO(lbl_, ...)  do {                                           \
-    ERR(__VA_ARGS__);                                                         \
-    goto lbl_;                                                                \
-} while(0)
-
-static ALboolean ensureFontSanity(const Soundfont *sfont)
-{
-    ALsizei i;
-
-    for(i = 0;i < sfont->phdr_size;i++)
-    {
-        if(sfont->phdr[i].mZoneIdx >= sfont->pbag_size)
-        {
-            WARN("Preset %d has invalid zone index %d (max: %d)\n", i,
-                 sfont->phdr[i].mZoneIdx, sfont->pbag_size);
-            return AL_FALSE;
-        }
-        if(i+1 < sfont->phdr_size && sfont->phdr[i+1].mZoneIdx < sfont->phdr[i].mZoneIdx)
-        {
-            WARN("Preset %d has invalid zone index (%d does not follow %d)\n", i+1,
-                 sfont->phdr[i+1].mZoneIdx, sfont->phdr[i].mZoneIdx);
-            return AL_FALSE;
-        }
-    }
-
-    for(i = 0;i < sfont->pbag_size;i++)
-    {
-        if(sfont->pbag[i].mGenIdx >= sfont->pgen_size)
-        {
-            WARN("Preset zone %d has invalid generator index %d (max: %d)\n", i,
-                 sfont->pbag[i].mGenIdx, sfont->pgen_size);
-            return AL_FALSE;
-        }
-        if(i+1 < sfont->pbag_size && sfont->pbag[i+1].mGenIdx < sfont->pbag[i].mGenIdx)
-        {
-            WARN("Preset zone %d has invalid generator index (%d does not follow %d)\n", i+1,
-                 sfont->pbag[i+1].mGenIdx, sfont->pbag[i].mGenIdx);
-            return AL_FALSE;
-        }
-        if(sfont->pbag[i].mModIdx >= sfont->pmod_size)
-        {
-            WARN("Preset zone %d has invalid modulator index %d (max: %d)\n", i,
-                 sfont->pbag[i].mModIdx, sfont->pmod_size);
-            return AL_FALSE;
-        }
-        if(i+1 < sfont->pbag_size && sfont->pbag[i+1].mModIdx < sfont->pbag[i].mModIdx)
-        {
-            WARN("Preset zone %d has invalid modulator index (%d does not follow %d)\n", i+1,
-                 sfont->pbag[i+1].mModIdx, sfont->pbag[i].mModIdx);
-            return AL_FALSE;
-        }
-    }
-
-
-    for(i = 0;i < sfont->inst_size;i++)
-    {
-        if(sfont->inst[i].mZoneIdx >= sfont->ibag_size)
-        {
-            WARN("Instrument %d has invalid zone index %d (max: %d)\n", i,
-                 sfont->inst[i].mZoneIdx, sfont->ibag_size);
-            return AL_FALSE;
-        }
-        if(i+1 < sfont->inst_size && sfont->inst[i+1].mZoneIdx < sfont->inst[i].mZoneIdx)
-        {
-            WARN("Instrument %d has invalid zone index (%d does not follow %d)\n", i+1,
-                 sfont->inst[i+1].mZoneIdx, sfont->inst[i].mZoneIdx);
-            return AL_FALSE;
-        }
-    }
-
-    for(i = 0;i < sfont->ibag_size;i++)
-    {
-        if(sfont->ibag[i].mGenIdx >= sfont->igen_size)
-        {
-            WARN("Instrument zone %d has invalid generator index %d (max: %d)\n", i,
-                 sfont->ibag[i].mGenIdx, sfont->igen_size);
-            return AL_FALSE;
-        }
-        if(i+1 < sfont->ibag_size && sfont->ibag[i+1].mGenIdx < sfont->ibag[i].mGenIdx)
-        {
-            WARN("Instrument zone %d has invalid generator index (%d does not follow %d)\n", i+1,
-                 sfont->ibag[i+1].mGenIdx, sfont->ibag[i].mGenIdx);
-            return AL_FALSE;
-        }
-        if(sfont->ibag[i].mModIdx >= sfont->imod_size)
-        {
-            WARN("Instrument zone %d has invalid modulator index %d (max: %d)\n", i,
-                 sfont->ibag[i].mModIdx, sfont->imod_size);
-            return AL_FALSE;
-        }
-        if(i+1 < sfont->ibag_size && sfont->ibag[i+1].mModIdx < sfont->ibag[i].mModIdx)
-        {
-            WARN("Instrument zone %d has invalid modulator index (%d does not follow %d)\n", i+1,
-                 sfont->ibag[i+1].mModIdx, sfont->ibag[i].mModIdx);
-            return AL_FALSE;
-        }
-    }
-
-
-    for(i = 0;i < sfont->shdr_size-1;i++)
-    {
-        if((sfont->shdr[i].mSampleType&0x8000) && sfont->irom == NULL)
-        {
-            WARN("Sample header %d has ROM sample type without an irom sub-chunk\n", i);
-            return AL_FALSE;
-        }
-    }
-
-
-    return AL_TRUE;
-}
-
-static ALboolean checkZone(const GenModList *zone, const PresetHeader *preset, const InstrumentHeader *inst, const SampleHeader *samp)
-{
-    Generator *gen = VECTOR_ITER_BEGIN(zone->gens);
-    Generator *gen_end = VECTOR_ITER_END(zone->gens);
-    for(;gen != gen_end;gen++)
-    {
-        if(gen->mGenerator == 43 || gen->mGenerator == 44)
-        {
-            int high = gen->mAmount>>8;
-            int low = gen->mAmount&0xff;
-
-            if(!(low >= 0 && high <= 127 && high >= low))
-            {
-                TRACE("Preset \"%s\", inst \"%s\", sample \"%s\": invalid %s range %d...%d\n",
-                      preset->mName, inst->mName, samp->mName,
-                      (gen->mGenerator == 43) ? "key" :
-                      (gen->mGenerator == 44) ? "velocity" : "(unknown)",
-                      low, high);
-                return AL_FALSE;
-            }
-        }
-    }
-
-    return AL_TRUE;
-}
-
-static ALenum getModSrcInput(int input)
-{
-    if(input == 0) return AL_ONE_SOFT;
-    if(input == 2) return AL_NOTEON_VELOCITY_SOFT;
-    if(input == 3) return AL_NOTEON_KEY_SOFT;
-    if(input == 10) return AL_KEYPRESSURE_SOFT;
-    if(input == 13) return AL_CHANNELPRESSURE_SOFT;
-    if(input == 14) return AL_PITCHBEND_SOFT;
-    if(input == 16) return AL_PITCHBEND_SENSITIVITY_SOFT;
-    if((input&0x80))
-    {
-        if(IsValidCtrlInput(input^0x80))
-            return input^0x80;
-    }
-    ERR("Unhandled modulator source input: 0x%02x\n", input);
-    return AL_INVALID;
-}
-
-static ALenum getModSrcType(int type)
-{
-    if(type == 0x0000) return AL_UNORM_SOFT;
-    if(type == 0x0100) return AL_UNORM_REV_SOFT;
-    if(type == 0x0200) return AL_SNORM_SOFT;
-    if(type == 0x0300) return AL_SNORM_REV_SOFT;
-    ERR("Unhandled modulator source type: 0x%04x\n", type);
-    return AL_INVALID;
-}
-
-static ALenum getModSrcForm(int form)
-{
-    if(form == 0x0000) return AL_LINEAR_SOFT;
-    if(form == 0x0400) return AL_CONCAVE_SOFT;
-    if(form == 0x0800) return AL_CONVEX_SOFT;
-    if(form == 0x0C00) return AL_SWITCH_SOFT;
-    ERR("Unhandled modulator source form: 0x%04x\n", form);
-    return AL_INVALID;
-}
-
-static ALenum getModTransOp(int op)
-{
-    if(op == 0) return AL_LINEAR_SOFT;
-    if(op == 2) return AL_ABSOLUTE_SOFT;
-    ERR("Unhandled modulator transform op: 0x%04x\n", op);
-    return AL_INVALID;
-}
-
-static ALenum getLoopMode(int mode)
-{
-    if(mode == 0) return AL_NONE;
-    if(mode == 1) return AL_LOOP_CONTINUOUS_SOFT;
-    if(mode == 3) return AL_LOOP_UNTIL_RELEASE_SOFT;
-    ERR("Unhandled loop mode: %d\n", mode);
-    return AL_NONE;
-}
-
-static ALenum getSampleType(int type)
-{
-    if(type == 1) return AL_MONO_SOFT;
-    if(type == 2) return AL_RIGHT_SOFT;
-    if(type == 4) return AL_LEFT_SOFT;
-    if(type == 8)
-    {
-        WARN("Sample type \"linked\" ignored; pretending mono\n");
-        return AL_MONO_SOFT;
-    }
-    ERR("Unhandled sample type: 0x%04x\n", type);
-    return AL_MONO_SOFT;
-}
-
-static void fillZone(ALfontsound *sound, ALCcontext *context, const GenModList *zone)
-{
-    static const ALenum Gen2Param[60] = {
-        0, /* 0 - startAddrOffset */
-        0, /* 1 - endAddrOffset */
-        0, /* 2 - startloopAddrOffset */
-        0, /* 3 - endloopAddrOffset */
-        0, /* 4 - startAddrCoarseOffset */
-        AL_MOD_LFO_TO_PITCH_SOFT, /* 5 - modLfoToPitch */
-        AL_VIBRATO_LFO_TO_PITCH_SOFT, /* 6 - vibLfoToPitch */
-        AL_MOD_ENV_TO_PITCH_SOFT, /* 7 - modEnvToPitch */
-        AL_FILTER_CUTOFF_SOFT, /* 8 - initialFilterFc */
-        AL_FILTER_RESONANCE_SOFT, /* 9 - initialFilterQ */
-        AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT, /* 10 - modLfoToFilterFc */
-        AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT, /* 11 - modEnvToFilterFc */
-        0, /* 12 - endAddrCoarseOffset */
-        AL_MOD_LFO_TO_VOLUME_SOFT, /* 13 - modLfoToVolume */
-        0, /* 14 -  */
-        AL_CHORUS_SEND_SOFT, /* 15 - chorusEffectsSend */
-        AL_REVERB_SEND_SOFT, /* 16 - reverbEffectsSend */
-        AL_PAN_SOFT, /* 17 - pan */
-        0, /* 18 -  */
-        0, /* 19 -  */
-        0, /* 20 -  */
-        AL_MOD_LFO_DELAY_SOFT, /* 21 - delayModLFO */
-        AL_MOD_LFO_FREQUENCY_SOFT, /* 22 - freqModLFO */
-        AL_VIBRATO_LFO_DELAY_SOFT, /* 23 - delayVibLFO */
-        AL_VIBRATO_LFO_FREQUENCY_SOFT, /* 24 - freqVibLFO */
-        AL_MOD_ENV_DELAYTIME_SOFT, /* 25 - delayModEnv */
-        AL_MOD_ENV_ATTACKTIME_SOFT, /* 26 - attackModEnv */
-        AL_MOD_ENV_HOLDTIME_SOFT, /* 27 - holdModEnv */
-        AL_MOD_ENV_DECAYTIME_SOFT, /* 28 - decayModEnv */
-        AL_MOD_ENV_SUSTAINVOLUME_SOFT, /* 29 - sustainModEnv */
-        AL_MOD_ENV_RELEASETIME_SOFT, /* 30 - releaseModEnv */
-        AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT, /* 31 - keynumToModEnvHold */
-        AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT, /* 32 - keynumToModEnvDecay */
-        AL_VOLUME_ENV_DELAYTIME_SOFT, /* 33 - delayVolEnv */
-        AL_VOLUME_ENV_ATTACKTIME_SOFT, /* 34 - attackVolEnv */
-        AL_VOLUME_ENV_HOLDTIME_SOFT, /* 35 - holdVolEnv */
-        AL_VOLUME_ENV_DECAYTIME_SOFT, /* 36 - decayVolEnv */
-        AL_VOLUME_ENV_SUSTAINVOLUME_SOFT, /* 37 - sustainVolEnv */
-        AL_VOLUME_ENV_RELEASETIME_SOFT, /* 38 - releaseVolEnv */
-        AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT, /* 39 - keynumToVolEnvHold */
-        AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT, /* 40 - keynumToVolEnvDecay */
-        0, /* 41 -  */
-        0, /* 42 -  */
-        AL_KEY_RANGE_SOFT, /* 43 - keyRange */
-        AL_VELOCITY_RANGE_SOFT, /* 44 - velRange */
-        0, /* 45 - startloopAddrCoarseOffset */
-        0, /* 46 - keynum */
-        0, /* 47 - velocity */
-        AL_ATTENUATION_SOFT, /* 48 - initialAttenuation */
-        0, /* 49 -  */
-        0, /* 50 - endloopAddrCoarseOffset */
-        AL_TUNING_COARSE_SOFT, /* 51 - corseTune */
-        AL_TUNING_FINE_SOFT, /* 52 - fineTune */
-        0, /* 53 -  */
-        AL_LOOP_MODE_SOFT, /* 54 - sampleModes */
-        0, /* 55 -  */
-        AL_TUNING_SCALE_SOFT, /* 56 - scaleTuning */
-        AL_EXCLUSIVE_CLASS_SOFT, /* 57 - exclusiveClass */
-        AL_BASE_KEY_SOFT, /* 58 - overridingRootKey */
-        0, /* 59 -  */
-    };
-    const Generator *gen, *gen_end;
-    const Modulator *mod, *mod_end;
-
-    mod = VECTOR_ITER_BEGIN(zone->mods);
-    mod_end = VECTOR_ITER_END(zone->mods);
-    for(;mod != mod_end;mod++)
-    {
-        ALenum src0in = getModSrcInput(mod->mSrcOp&0xFF);
-        ALenum src0type = getModSrcType(mod->mSrcOp&0x0300);
-        ALenum src0form = getModSrcForm(mod->mSrcOp&0xFC00);
-        ALenum src1in = getModSrcInput(mod->mAmtSrcOp&0xFF);
-        ALenum src1type = getModSrcType(mod->mAmtSrcOp&0x0300);
-        ALenum src1form = getModSrcForm(mod->mAmtSrcOp&0xFC00);
-        ALenum trans = getModTransOp(mod->mTransOp);
-        ALenum dst = (mod->mDstOp < 60) ? Gen2Param[mod->mDstOp] : 0;
-        if(!dst || dst == AL_KEY_RANGE_SOFT || dst == AL_VELOCITY_RANGE_SOFT ||
-           dst == AL_LOOP_MODE_SOFT || dst == AL_EXCLUSIVE_CLASS_SOFT ||
-           dst == AL_BASE_KEY_SOFT)
-            ERR("Unhandled modulator destination: %d\n", mod->mDstOp);
-        else if(src0in != AL_INVALID && src0form != AL_INVALID && src0type != AL_INVALID &&
-                src1in != AL_INVALID && src1form != AL_INVALID && src0type != AL_INVALID &&
-                trans != AL_INVALID)
-        {
-            ALsizei idx = (ALsizei)(mod - VECTOR_ITER_BEGIN(zone->mods));
-            ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_INPUT_SOFT, src0in);
-            ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_TYPE_SOFT, src0type);
-            ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_FORM_SOFT, src0form);
-            ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_INPUT_SOFT, src1in);
-            ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_TYPE_SOFT, src1type);
-            ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_FORM_SOFT, src1form);
-            ALfontsound_setModStagei(sound, context, idx, AL_AMOUNT_SOFT, mod->mAmount);
-            ALfontsound_setModStagei(sound, context, idx, AL_TRANSFORM_OP_SOFT, trans);
-            ALfontsound_setModStagei(sound, context, idx, AL_DESTINATION_SOFT, dst);
-        }
-    }
-
-    gen = VECTOR_ITER_BEGIN(zone->gens);
-    gen_end = VECTOR_ITER_END(zone->gens);
-    for(;gen != gen_end;gen++)
-    {
-        ALint value = (ALshort)gen->mAmount;
-        if(gen->mGenerator == 0)
-            sound->Start += value;
-        else if(gen->mGenerator == 1)
-            sound->End += value;
-        else if(gen->mGenerator == 2)
-            sound->LoopStart += value;
-        else if(gen->mGenerator == 3)
-            sound->LoopEnd += value;
-        else if(gen->mGenerator == 4)
-            sound->Start += value<<15;
-        else if(gen->mGenerator == 12)
-            sound->End += value<<15;
-        else if(gen->mGenerator == 45)
-            sound->LoopStart += value<<15;
-        else if(gen->mGenerator == 50)
-            sound->LoopEnd += value<<15;
-        else if(gen->mGenerator == 43)
-        {
-            sound->MinKey = mini((value&0xff), 127);
-            sound->MaxKey = mini(((value>>8)&0xff), 127);
-        }
-        else if(gen->mGenerator == 44)
-        {
-            sound->MinVelocity = mini((value&0xff), 127);
-            sound->MaxVelocity = mini(((value>>8)&0xff), 127);
-        }
-        else
-        {
-            ALenum param = 0;
-            if(gen->mGenerator < 60)
-                param = Gen2Param[gen->mGenerator];
-            if(param)
-            {
-                if(param == AL_BASE_KEY_SOFT)
-                {
-                    if(!(value >= 0 && value <= 127))
-                    {
-                        if(value != -1)
-                            WARN("Invalid overridingRootKey generator value %d\n", value);
-                        continue;
-                    }
-                }
-                if(param == AL_FILTER_RESONANCE_SOFT || param == AL_ATTENUATION_SOFT)
-                    value = maxi(0, value);
-                else if(param == AL_CHORUS_SEND_SOFT || param == AL_REVERB_SEND_SOFT)
-                    value = clampi(value, 0, 1000);
-                else if(param == AL_LOOP_MODE_SOFT)
-                    value = getLoopMode(value);
-                ALfontsound_setPropi(sound, context, param, value);
-            }
-            else
-            {
-                static ALuint warned[65536/32];
-                if(!(warned[gen->mGenerator/32]&(1<<(gen->mGenerator&31))))
-                {
-                    warned[gen->mGenerator/32] |= 1<<(gen->mGenerator&31);
-                    ERR("Unhandled generator %d\n", gen->mGenerator);
-                }
-            }
-        }
-    }
-}
-
-static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCcontext *context, ALbuffer *buffer, InstrumentHeader *inst, const PresetHeader *preset, const Soundfont *sfont, const GenModList *pzone)
-{
-    const Generator *gen, *gen_end;
-    const Modulator *mod, *mod_end;
-    const Zone *zone, *zone_end;
-    GenModList gzone;
-    ALvoid *temp;
-
-    if((inst+1)->mZoneIdx == inst->mZoneIdx)
-        ERR("Instrument with no zones!");
-
-    GenModList_Construct(&gzone);
-    zone = sfont->ibag + inst->mZoneIdx;
-    zone_end = sfont->ibag + (inst+1)->mZoneIdx;
-    if(zone_end-zone > 1)
-    {
-        gen = sfont->igen + zone->mGenIdx;
-        gen_end = sfont->igen + (zone+1)->mGenIdx;
-
-        // If no generators, or last generator is not a sample, this is a global zone
-        for(;gen != gen_end;gen++)
-        {
-            if(gen->mGenerator == 53)
-                break;
-        }
-
-        if(gen == gen_end)
-        {
-            gen = sfont->igen + zone->mGenIdx;
-            gen_end = sfont->igen + (zone+1)->mGenIdx;
-            for(;gen != gen_end;gen++)
-                GenModList_insertGen(&gzone, gen, AL_FALSE);
-
-            mod = sfont->imod + zone->mModIdx;
-            mod_end = sfont->imod + (zone+1)->mModIdx;
-            for(;mod != mod_end;mod++)
-                GenModList_insertMod(&gzone, mod);
-
-            zone++;
-        }
-    }
-
-    temp = realloc(*sounds, (zone_end-zone + *sounds_size)*sizeof((*sounds)[0]));
-    if(!temp)
-    {
-        ERR("Failed reallocating fontsound storage to %d elements (from %d)\n",
-            (ALsizei)(zone_end-zone) + *sounds_size, *sounds_size);
-        return;
-    }
-    *sounds = temp;
-    for(;zone != zone_end;zone++)
-    {
-        GenModList lzone = GenModList_clone(&gzone);
-        mod = sfont->imod + zone->mModIdx;
-        mod_end = sfont->imod + (zone+1)->mModIdx;
-        for(;mod != mod_end;mod++)
-            GenModList_insertMod(&lzone, mod);
-
-        gen = sfont->igen + zone->mGenIdx;
-        gen_end = sfont->igen + (zone+1)->mGenIdx;
-        for(;gen != gen_end;gen++)
-        {
-            if(gen->mGenerator == 53)
-            {
-                const SampleHeader *samp;
-                ALfontsound *sound;
-
-                if(gen->mAmount >= sfont->shdr_size-1)
-                {
-                    ERR("Generator %ld has invalid sample ID (%d of %d)\n",
-                        (long)(gen-sfont->igen), gen->mAmount, sfont->shdr_size-1);
-                    break;
-                }
-                samp = &sfont->shdr[gen->mAmount];
-
-                gen = VECTOR_ITER_BEGIN(pzone->gens);
-                gen_end = VECTOR_ITER_END(pzone->gens);
-                for(;gen != gen_end;gen++)
-                    GenModList_accumGen(&lzone, gen);
-
-                mod = VECTOR_ITER_BEGIN(pzone->mods);
-                mod_end = VECTOR_ITER_END(pzone->mods);
-                for(;mod != mod_end;mod++)
-                    GenModList_accumMod(&lzone, mod);
-
-                if(!checkZone(&lzone, preset, inst, samp))
-                    break;
-                /* Ignore ROM samples for now. */
-                if((samp->mSampleType&0x8000))
-                    break;
-
-                sound = NewFontsound(context);
-                (*sounds)[(*sounds_size)++] = sound;
-                ALfontsound_setPropi(sound, context, AL_BUFFER, buffer->id);
-                ALfontsound_setPropi(sound, context, AL_SAMPLE_START_SOFT, samp->mStart);
-                ALfontsound_setPropi(sound, context, AL_SAMPLE_END_SOFT, samp->mEnd);
-                ALfontsound_setPropi(sound, context, AL_SAMPLE_LOOP_START_SOFT, samp->mStartloop);
-                ALfontsound_setPropi(sound, context, AL_SAMPLE_LOOP_END_SOFT, samp->mEndloop);
-                ALfontsound_setPropi(sound, context, AL_SAMPLE_RATE_SOFT, samp->mSampleRate);
-                ALfontsound_setPropi(sound, context, AL_BASE_KEY_SOFT, (samp->mOriginalKey <= 127) ? samp->mOriginalKey : 60);
-                ALfontsound_setPropi(sound, context, AL_KEY_CORRECTION_SOFT, samp->mCorrection);
-                ALfontsound_setPropi(sound, context, AL_SAMPLE_TYPE_SOFT, getSampleType(samp->mSampleType&0x7fff));
-                fillZone(sound, context, &lzone);
-
-                break;
-            }
-            GenModList_insertGen(&lzone, gen, AL_FALSE);
-        }
-
-        GenModList_Destruct(&lzone);
-    }
-
-    GenModList_Destruct(&gzone);
-}
-
-static size_t printStringChunk(Reader *stream, const RiffHdr *chnk, const char *title)
-{
-    size_t len = 0;
-    if(chnk->mSize == 0 || (chnk->mSize&1))
-        ERR("Invalid "FOURCCFMT" size: %d\n", FOURCCARGS(chnk->mCode), chnk->mSize);
-    else
-    {
-        char *str = calloc(1, chnk->mSize+1);
-        len = Reader_read(stream, str, chnk->mSize);
-
-        TRACE("%s: %s\n", title, str);
-        free(str);
-    }
-    return len;
-}
-
-ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context)
-{
-    ALsfpreset **presets = NULL;
-    ALsizei presets_size = 0;
-    ALbuffer *buffer = NULL;
-    ALuint ltype;
-    Soundfont sfont;
-    RiffHdr riff;
-    RiffHdr list;
-    ALsizei i;
-
-    Soundfont_Construct(&sfont);
-
-    RiffHdr_read(&riff, stream);
-    if(riff.mCode != FOURCC('R','I','F','F'))
-        ERROR_GOTO(error, "Invalid Format, expected RIFF got '"FOURCCFMT"'\n", FOURCCARGS(riff.mCode));
-    if((ltype=read_le32(stream)) != FOURCC('s','f','b','k'))
-        ERROR_GOTO(error, "Invalid Format, expected sfbk got '"FOURCCFMT"'\n", FOURCCARGS(ltype));
-
-    if(READERR(stream) != 0)
-        ERROR_GOTO(error, "Error reading file header\n");
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('L','I','S','T'))
-        ERROR_GOTO(error, "Invalid Format, expected LIST (INFO) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((ltype=read_le32(stream)) != FOURCC('I','N','F','O'))
-        ERROR_GOTO(error, "Invalid Format, expected INFO got '"FOURCCFMT"'\n", FOURCCARGS(ltype));
-    list.mSize -= 4;
-    while(list.mSize > 0 && !READERR(stream))
-    {
-        RiffHdr chnk;
-
-        if(list.mSize < 8)
-        {
-            WARN("Unexpected end of INFO list (%u extra bytes)\n", list.mSize);
-            skip(stream, list.mSize);
-            list.mSize = 0;
-            break;
-        }
-
-        RiffHdr_read(&chnk, stream);
-        list.mSize -= 8;
-        if(list.mSize < chnk.mSize)
-        {
-            WARN("INFO sub-chunk '"FOURCCFMT"' has %u bytes, but only %u bytes remain\n",
-                 FOURCCARGS(chnk.mCode), chnk.mSize, list.mSize);
-            skip(stream, list.mSize);
-            list.mSize = 0;
-            break;
-        }
-        list.mSize -= chnk.mSize;
-
-        if(chnk.mCode == FOURCC('i','f','i','l'))
-        {
-            if(chnk.mSize != 4)
-                ERR("Invalid ifil chunk size: %d\n", chnk.mSize);
-            else
-            {
-                ALushort major = read_le16(stream);
-                ALushort minor = read_le16(stream);
-                chnk.mSize -= 4;
-
-                if(major != 2)
-                    ERROR_GOTO(error, "Unsupported SF2 format version: %d.%02d\n", major, minor);
-                TRACE("SF2 format version: %d.%02d\n", major, minor);
-
-                sfont.ifil = (major<<16) | minor;
-            }
-        }
-        else if(chnk.mCode == FOURCC('i','r','o','m'))
-        {
-            if(chnk.mSize == 0 || (chnk.mSize&1))
-                ERR("Invalid irom size: %d\n", chnk.mSize);
-            else
-            {
-                free(sfont.irom);
-                sfont.irom = calloc(1, chnk.mSize+1);
-                chnk.mSize -= Reader_read(stream, sfont.irom, chnk.mSize);
-
-                TRACE("SF2 ROM ID: %s\n", sfont.irom);
-            }
-        }
-        else
-        {
-            static const struct {
-                ALuint code;
-                char title[16];
-            } listinfos[] = {
-                { FOURCC('i','s','n','g'), "Engine ID" },
-                { FOURCC('I','N','A','M'), "Name" },
-                { FOURCC('I','C','R','D'), "Creation Date" },
-                { FOURCC('I','E','N','G'), "Creator" },
-                { FOURCC('I','P','R','D'), "Product ID" },
-                { FOURCC('I','C','O','P'), "Copyright" },
-                { FOURCC('I','C','M','T'), "Comment" },
-                { FOURCC('I','S','F','T'), "Created With" },
-                { 0, "" },
-            };
-
-            for(i = 0;listinfos[i].code;i++)
-            {
-                if(listinfos[i].code == chnk.mCode)
-                {
-                    chnk.mSize -= printStringChunk(stream, &chnk, listinfos[i].title);
-                    break;
-                }
-            }
-            if(!listinfos[i].code)
-                TRACE("Skipping INFO sub-chunk '"FOURCCFMT"' (%u bytes)\n", FOURCCARGS(chnk.mCode), chnk.mSize);
-        }
-        skip(stream, chnk.mSize);
-    }
-
-    if(READERR(stream) != 0)
-        ERROR_GOTO(error, "Error reading INFO chunk\n");
-    if(sfont.ifil == 0)
-        ERROR_GOTO(error, "Missing ifil sub-chunk\n");
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('L','I','S','T'))
-        ERROR_GOTO(error, "Invalid Format, expected LIST (sdta) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((ltype=read_le32(stream)) != FOURCC('s','d','t','a'))
-        ERROR_GOTO(error, "Invalid Format, expected sdta got '"FOURCCFMT"'\n", FOURCCARGS(ltype));
-    list.mSize -= 4;
-    {
-        ALbyte *ptr;
-        RiffHdr smpl;
-        ALenum err;
-
-        RiffHdr_read(&smpl, stream);
-        if(smpl.mCode != FOURCC('s','m','p','l'))
-            ERROR_GOTO(error, "Invalid Format, expected smpl got '"FOURCCFMT"'\n", FOURCCARGS(smpl.mCode));
-        list.mSize -= 8;
-
-        if(smpl.mSize > list.mSize)
-            ERROR_GOTO(error, "Invalid Format, sample chunk size mismatch\n");
-        list.mSize -= smpl.mSize;
-
-        buffer = NewBuffer(context);
-        if(!buffer)
-            SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, error);
-        /* Sample rate is unimportant, the individual fontsounds will specify it. */
-        if((err=LoadData(buffer, 22050, AL_MONO16_SOFT, smpl.mSize/2, UserFmtMono, UserFmtShort, NULL, 1, AL_FALSE)) != AL_NO_ERROR)
-            SET_ERROR_AND_GOTO(context, err, error);
-
-        ptr = buffer->data;
-        if(IS_LITTLE_ENDIAN)
-            smpl.mSize -= Reader_read(stream, ptr, smpl.mSize);
-        else
-        {
-            ALuint total = 0;
-            while(total < smpl.mSize && !READERR(stream))
-            {
-                ALbyte buf[4096];
-                ALuint todo = minu(smpl.mSize-total, sizeof(buf));
-                ALuint i;
-
-                smpl.mSize -= Reader_read(stream, buf, todo);
-                for(i = 0;i < todo;i++)
-                    ptr[total+i] = buf[i^1];
-
-                total += todo;
-            }
-        }
-
-        skip(stream, list.mSize);
-    }
-
-    if(READERR(stream) != 0)
-        ERROR_GOTO(error, "Error reading sdta chunk\n");
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('L','I','S','T'))
-        ERROR_GOTO(error, "Invalid Format, expected LIST (pdta) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((ltype=read_le32(stream)) != FOURCC('p','d','t','a'))
-        ERROR_GOTO(error, "Invalid Format, expected pdta got '"FOURCCFMT"'\n", FOURCCARGS(ltype));
-
-    //
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('p','h','d','r'))
-        ERROR_GOTO(error, "Invalid Format, expected phdr got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%38) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad phdr size: %u\n", list.mSize);
-    sfont.phdr_size = list.mSize/38;
-    sfont.phdr = calloc(sfont.phdr_size, sizeof(sfont.phdr[0]));
-    for(i = 0;i < sfont.phdr_size;i++)
-        PresetHeader_read(&sfont.phdr[i], stream);
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('p','b','a','g'))
-        ERROR_GOTO(error, "Invalid Format, expected pbag got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%4) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad pbag size: %u\n", list.mSize);
-    sfont.pbag_size = list.mSize/4;
-    sfont.pbag = calloc(sfont.pbag_size, sizeof(sfont.pbag[0]));
-    for(i = 0;i < sfont.pbag_size;i++)
-        Zone_read(&sfont.pbag[i], stream);
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('p','m','o','d'))
-        ERROR_GOTO(error, "Invalid Format, expected pmod got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%10) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad pmod size: %u\n", list.mSize);
-    sfont.pmod_size = list.mSize/10;
-    sfont.pmod = calloc(sfont.pmod_size, sizeof(sfont.pmod[0]));
-    for(i = 0;i < sfont.pmod_size;i++)
-        Modulator_read(&sfont.pmod[i], stream);
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('p','g','e','n'))
-        ERROR_GOTO(error, "Invalid Format, expected pgen got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%4) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad pgen size: %u\n", list.mSize);
-    sfont.pgen_size = list.mSize/4;
-    sfont.pgen = calloc(sfont.pgen_size, sizeof(sfont.pgen[0]));
-    for(i = 0;i < sfont.pgen_size;i++)
-        Generator_read(&sfont.pgen[i], stream);
-
-    //
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('i','n','s','t'))
-        ERROR_GOTO(error, "Invalid Format, expected inst got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%22) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad inst size: %u\n", list.mSize);
-    sfont.inst_size = list.mSize/22;
-    sfont.inst = calloc(sfont.inst_size, sizeof(sfont.inst[0]));
-    for(i = 0;i < sfont.inst_size;i++)
-        InstrumentHeader_read(&sfont.inst[i], stream);
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('i','b','a','g'))
-        ERROR_GOTO(error, "Invalid Format, expected ibag got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%4) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad ibag size: %u\n", list.mSize);
-    sfont.ibag_size = list.mSize/4;
-    sfont.ibag = calloc(sfont.ibag_size, sizeof(sfont.ibag[0]));
-    for(i = 0;i < sfont.ibag_size;i++)
-        Zone_read(&sfont.ibag[i], stream);
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('i','m','o','d'))
-        ERROR_GOTO(error, "Invalid Format, expected imod got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%10) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad imod size: %u\n", list.mSize);
-    sfont.imod_size = list.mSize/10;
-    sfont.imod = calloc(sfont.imod_size, sizeof(sfont.imod[0]));
-    for(i = 0;i < sfont.imod_size;i++)
-        Modulator_read(&sfont.imod[i], stream);
-
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('i','g','e','n'))
-        ERROR_GOTO(error, "Invalid Format, expected igen got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%4) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad igen size: %u\n", list.mSize);
-    sfont.igen_size = list.mSize/4;
-    sfont.igen = calloc(sfont.igen_size, sizeof(sfont.igen[0]));
-    for(i = 0;i < sfont.igen_size;i++)
-        Generator_read(&sfont.igen[i], stream);
-
-    //
-    RiffHdr_read(&list, stream);
-    if(list.mCode != FOURCC('s','h','d','r'))
-        ERROR_GOTO(error, "Invalid Format, expected shdr got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode));
-    if((list.mSize%46) != 0 || list.mSize == 0)
-        ERROR_GOTO(error, "Invalid Format, bad shdr size: %u\n", list.mSize);
-    sfont.shdr_size = list.mSize/46;
-    sfont.shdr = calloc(sfont.shdr_size, sizeof(sfont.shdr[0]));
-    for(i = 0;i < sfont.shdr_size;i++)
-        SampleHeader_read(&sfont.shdr[i], stream);
-
-    if(READERR(stream) != 0)
-        ERROR_GOTO(error, "Error reading pdta chunk\n");
-
-    if(!ensureFontSanity(&sfont))
-        goto error;
-
-    presets = calloc(1, (soundfont->NumPresets+sfont.phdr_size-1)*sizeof(presets[0]));
-    if(!presets)
-        ERROR_GOTO(error, "Error allocating presets\n");
-    memcpy(presets, soundfont->Presets, soundfont->NumPresets*sizeof(presets[0]));
-    presets_size = soundfont->NumPresets;
-
-    for(i = 0;i < sfont.phdr_size-1;i++)
-    {
-        const Generator *gen, *gen_end;
-        const Modulator *mod, *mod_end;
-        const Zone *zone, *zone_end;
-        ALfontsound **sounds = NULL;
-        ALsizei sounds_size = 0;
-        GenModList gzone;
-
-        if(sfont.phdr[i+1].mZoneIdx == sfont.phdr[i].mZoneIdx)
-            continue;
-
-        GenModList_Construct(&gzone);
-        zone = sfont.pbag + sfont.phdr[i].mZoneIdx;
-        zone_end = sfont.pbag + sfont.phdr[i+1].mZoneIdx;
-        if(zone_end-zone > 1)
-        {
-            gen = sfont.pgen + zone->mGenIdx;
-            gen_end = sfont.pgen + (zone+1)->mGenIdx;
-
-            // If no generators, or last generator is not an instrument, this is a global zone
-            for(;gen != gen_end;gen++)
-            {
-                if(gen->mGenerator == 41)
-                    break;
-            }
-
-            if(gen == gen_end)
-            {
-                gen = sfont.pgen + zone->mGenIdx;
-                gen_end = sfont.pgen + (zone+1)->mGenIdx;
-                for(;gen != gen_end;gen++)
-                    GenModList_insertGen(&gzone, gen, AL_TRUE);
-
-                mod = sfont.pmod + zone->mModIdx;
-                mod_end = sfont.pmod + (zone+1)->mModIdx;
-                for(;mod != mod_end;mod++)
-                    GenModList_insertMod(&gzone, mod);
-
-                zone++;
-            }
-        }
-
-        for(;zone != zone_end;zone++)
-        {
-            GenModList lzone = GenModList_clone(&gzone);
-
-            mod = sfont.pmod + zone->mModIdx;
-            mod_end = sfont.pmod + (zone+1)->mModIdx;
-            for(;mod != mod_end;mod++)
-                GenModList_insertMod(&lzone, mod);
-
-            gen = sfont.pgen + zone->mGenIdx;
-            gen_end = sfont.pgen + (zone+1)->mGenIdx;
-            for(;gen != gen_end;gen++)
-            {
-                if(gen->mGenerator == 41)
-                {
-                    if(gen->mAmount >= sfont.inst_size-1)
-                        ERR("Generator %ld has invalid instrument ID (%d of %d)\n",
-                            (long)(gen-sfont.pgen), gen->mAmount, sfont.inst_size-1);
-                    else
-                        processInstrument(
-                            &sounds, &sounds_size, context, buffer, &sfont.inst[gen->mAmount],
-                            &sfont.phdr[i], &sfont, &lzone
-                        );
-                    break;
-                }
-                GenModList_insertGen(&lzone, gen, AL_TRUE);
-            }
-            GenModList_Destruct(&lzone);
-        }
-
-        if(sounds_size > 0)
-        {
-            ALsizei j;
-
-            presets[presets_size] = NewPreset(context);
-            presets[presets_size]->Preset = sfont.phdr[i].mPreset;
-            presets[presets_size]->Bank = sfont.phdr[i].mBank;
-
-            for(j = 0;j < sounds_size;j++)
-                IncrementRef(&sounds[j]->ref);
-            sounds = ExchangePtr((XchgPtr*)&presets[presets_size]->Sounds, sounds);
-            ExchangeInt(&presets[presets_size]->NumSounds, sounds_size);
-            presets_size++;
-        }
-        free(sounds);
-
-        GenModList_Destruct(&gzone);
-    }
-
-    for(i = soundfont->NumPresets;i < presets_size;i++)
-        IncrementRef(&presets[i]->ref);
-    presets = ExchangePtr((XchgPtr*)&soundfont->Presets, presets);
-    ExchangeInt(&soundfont->NumPresets, presets_size);
-
-    free(presets);
-
-    Soundfont_Destruct(&sfont);
-    /* If the buffer ends up unused, delete it. */
-    if(ReadRef(&buffer->ref) == 0)
-    {
-        TRACE("Deleting unused buffer...\n");
-        DeleteBuffer(context->Device, buffer);
-    }
-
-    return AL_TRUE;
-
-error:
-    if(presets)
-    {
-        ALCdevice *device = context->Device;
-        for(i = soundfont->NumPresets;i < presets_size;i++)
-            DeletePreset(device, presets[i]);
-        free(presets);
-    }
-
-    Soundfont_Destruct(&sfont);
-    if(buffer)
-        DeleteBuffer(context->Device, buffer);
-
-    return AL_FALSE;
-}

+ 0 - 140
love/src/jni/openal-soft-1.17.0/Alc/midi/soft.c

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

+ 0 - 510
love/src/jni/openal-soft-1.17.0/Alc/mixer.c

@@ -1,510 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "alMain.h"
-#include "AL/al.h"
-#include "AL/alc.h"
-#include "alSource.h"
-#include "alBuffer.h"
-#include "alListener.h"
-#include "alAuxEffectSlot.h"
-#include "alu.h"
-
-#include "mixer_defs.h"
-
-
-extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
-
-
-static inline HrtfMixerFunc SelectHrtfMixer(void)
-{
-#ifdef HAVE_SSE
-    if((CPUCapFlags&CPU_CAP_SSE))
-        return MixHrtf_SSE;
-#endif
-#ifdef HAVE_NEON
-    if((CPUCapFlags&CPU_CAP_NEON))
-        return MixHrtf_Neon;
-#endif
-
-    return MixHrtf_C;
-}
-
-static inline MixerFunc SelectMixer(void)
-{
-#ifdef HAVE_SSE
-    if((CPUCapFlags&CPU_CAP_SSE))
-        return Mix_SSE;
-#endif
-#ifdef HAVE_NEON
-    if((CPUCapFlags&CPU_CAP_NEON))
-        return Mix_Neon;
-#endif
-
-    return Mix_C;
-}
-
-static inline ResamplerFunc SelectResampler(enum Resampler Resampler, ALuint increment)
-{
-    if(increment == FRACTIONONE)
-        return Resample_copy32_C;
-    switch(Resampler)
-    {
-        case PointResampler:
-            return Resample_point32_C;
-        case LinearResampler:
-#ifdef HAVE_SSE4_1
-            if((CPUCapFlags&CPU_CAP_SSE4_1))
-                return Resample_lerp32_SSE41;
-#endif
-#ifdef HAVE_SSE2
-            if((CPUCapFlags&CPU_CAP_SSE2))
-                return Resample_lerp32_SSE2;
-#endif
-            return Resample_lerp32_C;
-        case CubicResampler:
-            return Resample_cubic32_C;
-        case ResamplerMax:
-            /* Shouldn't happen */
-            break;
-    }
-
-    return Resample_point32_C;
-}
-
-
-static inline ALfloat Sample_ALbyte(ALbyte val)
-{ return val * (1.0f/127.0f); }
-
-static inline ALfloat Sample_ALshort(ALshort val)
-{ return val * (1.0f/32767.0f); }
-
-static inline ALfloat Sample_ALfloat(ALfloat val)
-{ return val; }
-
-#define DECL_TEMPLATE(T)                                                      \
-static void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
-{                                                                             \
-    ALuint i;                                                                 \
-    for(i = 0;i < samples;i++)                                                \
-        dst[i] = Sample_##T(src[i*srcstep]);                                  \
-}
-
-DECL_TEMPLATE(ALbyte)
-DECL_TEMPLATE(ALshort)
-DECL_TEMPLATE(ALfloat)
-
-#undef DECL_TEMPLATE
-
-static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
-{
-    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;
-    }
-}
-
-static void SilenceSamples(ALfloat *dst, ALuint samples)
-{
-    ALuint i;
-    for(i = 0;i < samples;i++)
-        dst[i] = 0.0f;
-}
-
-
-static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter,
-                                ALfloat *restrict dst, const ALfloat *restrict src,
-                                ALuint numsamples, enum ActiveFilters type)
-{
-    ALuint i;
-    switch(type)
-    {
-        case AF_None:
-            break;
-
-        case AF_LowPass:
-            ALfilterState_process(lpfilter, dst, src, numsamples);
-            return dst;
-        case AF_HighPass:
-            ALfilterState_process(hpfilter, dst, src, numsamples);
-            return dst;
-
-        case AF_BandPass:
-            for(i = 0;i < numsamples;)
-            {
-                ALfloat temp[64];
-                ALuint todo = minu(64, numsamples-i);
-
-                ALfilterState_process(lpfilter, temp, src+i, todo);
-                ALfilterState_process(hpfilter, dst+i, temp, todo);
-                i += todo;
-            }
-            return dst;
-    }
-    return src;
-}
-
-
-ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
-{
-    MixerFunc Mix;
-    HrtfMixerFunc HrtfMix;
-    ResamplerFunc Resample;
-    ALsource *Source = src->Source;
-    ALbufferlistitem *BufferListItem;
-    ALuint DataPosInt, DataPosFrac;
-    ALboolean Looping;
-    ALuint increment;
-    enum Resampler Resampler;
-    ALenum State;
-    ALuint OutPos;
-    ALuint NumChannels;
-    ALuint SampleSize;
-    ALint64 DataSize64;
-    ALuint chan, j;
-
-    /* Get source info */
-    State          = Source->state;
-    BufferListItem = ATOMIC_LOAD(&Source->current_buffer);
-    DataPosInt     = Source->position;
-    DataPosFrac    = Source->position_fraction;
-    Looping        = Source->Looping;
-    increment      = src->Step;
-    Resampler      = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
-    NumChannels    = Source->NumChannels;
-    SampleSize     = Source->SampleSize;
-
-    Mix = SelectMixer();
-    HrtfMix = SelectHrtfMixer();
-    Resample = SelectResampler(Resampler, increment);
-
-    OutPos = 0;
-    do {
-        const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
-        const ALuint BufferPadding = ResamplerPadding[Resampler];
-        ALuint SrcBufferSize, DstBufferSize;
-
-        /* Figure out how many buffer samples will be needed */
-        DataSize64  = SamplesToDo-OutPos;
-        DataSize64 *= increment;
-        DataSize64 += DataPosFrac+FRACTIONMASK;
-        DataSize64 >>= FRACTIONBITS;
-        DataSize64 += BufferPadding+BufferPrePadding;
-
-        SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
-
-        /* Figure out how many samples we can actually mix from this. */
-        DataSize64  = SrcBufferSize;
-        DataSize64 -= BufferPadding+BufferPrePadding;
-        DataSize64 <<= FRACTIONBITS;
-        DataSize64 -= DataPosFrac;
-
-        DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment);
-        DstBufferSize = minu(DstBufferSize, (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)
-            DstBufferSize &= ~3;
-
-        for(chan = 0;chan < NumChannels;chan++)
-        {
-            const ALfloat *ResampledData;
-            ALfloat *SrcData = Device->SourceData;
-            ALuint SrcDataSize = 0;
-
-            if(Source->SourceType == AL_STATIC)
-            {
-                const ALbuffer *ALBuffer = BufferListItem->buffer;
-                const ALubyte *Data = ALBuffer->data;
-                ALuint DataSize;
-                ALuint pos;
-
-                /* If current pos is beyond the loop range, do not loop */
-                if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
-                {
-                    Looping = AL_FALSE;
-
-                    if(DataPosInt >= BufferPrePadding)
-                        pos = DataPosInt - BufferPrePadding;
-                    else
-                    {
-                        DataSize = BufferPrePadding - DataPosInt;
-                        DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-
-                        SilenceSamples(&SrcData[SrcDataSize], DataSize);
-                        SrcDataSize += DataSize;
-
-                        pos = 0;
-                    }
-
-                    /* Copy what's left to play in the source buffer, and clear the
-                     * rest of the temp buffer */
-                    DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
-
-                    LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
-                                NumChannels, ALBuffer->FmtType, DataSize);
-                    SrcDataSize += DataSize;
-
-                    SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
-                    SrcDataSize += SrcBufferSize - SrcDataSize;
-                }
-                else
-                {
-                    ALuint LoopStart = ALBuffer->LoopStart;
-                    ALuint LoopEnd   = ALBuffer->LoopEnd;
-
-                    if(DataPosInt >= LoopStart)
-                    {
-                        pos = DataPosInt-LoopStart;
-                        while(pos < BufferPrePadding)
-                            pos += LoopEnd-LoopStart;
-                        pos -= BufferPrePadding;
-                        pos += LoopStart;
-                    }
-                    else if(DataPosInt >= BufferPrePadding)
-                        pos = DataPosInt - BufferPrePadding;
-                    else
-                    {
-                        DataSize = BufferPrePadding - DataPosInt;
-                        DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-
-                        SilenceSamples(&SrcData[SrcDataSize], DataSize);
-                        SrcDataSize += DataSize;
-
-                        pos = 0;
-                    }
-
-                    /* Copy what's left of this loop iteration, then copy repeats
-                     * of the loop section */
-                    DataSize = LoopEnd - pos;
-                    DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-
-                    LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
-                                NumChannels, ALBuffer->FmtType, DataSize);
-                    SrcDataSize += DataSize;
-
-                    DataSize = LoopEnd-LoopStart;
-                    while(SrcBufferSize > SrcDataSize)
-                    {
-                        DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-
-                        LoadSamples(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
-                                    NumChannels, ALBuffer->FmtType, DataSize);
-                        SrcDataSize += DataSize;
-                    }
-                }
-            }
-            else
-            {
-                /* Crawl the buffer queue to fill in the temp buffer */
-                ALbufferlistitem *tmpiter = BufferListItem;
-                ALuint pos;
-
-                if(DataPosInt >= BufferPrePadding)
-                    pos = DataPosInt - BufferPrePadding;
-                else
-                {
-                    pos = BufferPrePadding - DataPosInt;
-                    while(pos > 0)
-                    {
-                        ALbufferlistitem *prev;
-                        if((prev=tmpiter->prev) != NULL)
-                            tmpiter = prev;
-                        else if(Looping)
-                        {
-                            while(tmpiter->next)
-                                tmpiter = tmpiter->next;
-                        }
-                        else
-                        {
-                            ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
-
-                            SilenceSamples(&SrcData[SrcDataSize], DataSize);
-                            SrcDataSize += DataSize;
-
-                            pos = 0;
-                            break;
-                        }
-
-                        if(tmpiter->buffer)
-                        {
-                            if((ALuint)tmpiter->buffer->SampleLen > pos)
-                            {
-                                pos = tmpiter->buffer->SampleLen - pos;
-                                break;
-                            }
-                            pos -= tmpiter->buffer->SampleLen;
-                        }
-                    }
-                }
-
-                while(tmpiter && SrcBufferSize > SrcDataSize)
-                {
-                    const ALbuffer *ALBuffer;
-                    if((ALBuffer=tmpiter->buffer) != NULL)
-                    {
-                        const ALubyte *Data = ALBuffer->data;
-                        ALuint DataSize = ALBuffer->SampleLen;
-
-                        /* Skip the data already played */
-                        if(DataSize <= pos)
-                            pos -= DataSize;
-                        else
-                        {
-                            Data += (pos*NumChannels + chan)*SampleSize;
-                            DataSize -= pos;
-                            pos -= pos;
-
-                            DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-                            LoadSamples(&SrcData[SrcDataSize], Data, NumChannels,
-                                        ALBuffer->FmtType, DataSize);
-                            SrcDataSize += DataSize;
-                        }
-                    }
-                    tmpiter = tmpiter->next;
-                    if(!tmpiter && Looping)
-                        tmpiter = ATOMIC_LOAD(&Source->queue);
-                    else if(!tmpiter)
-                    {
-                        SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
-                        SrcDataSize += SrcBufferSize - SrcDataSize;
-                    }
-                }
-            }
-
-            /* Now resample, then filter and mix to the appropriate outputs. */
-            ResampledData = Resample(
-                &SrcData[BufferPrePadding], DataPosFrac, increment,
-                Device->ResampledData, DstBufferSize
-            );
-            {
-                DirectParams *parms = &src->Direct;
-                const ALfloat *samples;
-
-                samples = DoFilters(
-                    &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
-                    Device->FilteredData, ResampledData, DstBufferSize,
-                    parms->Filters[chan].ActiveType
-                );
-                if(!src->IsHrtf)
-                    Mix(samples, MaxChannels, parms->OutBuffer, parms->Mix.Gains[chan],
-                        parms->Counter, OutPos, DstBufferSize);
-                else
-                    HrtfMix(parms->OutBuffer, samples, parms->Counter, src->Offset,
-                            OutPos, parms->Mix.Hrtf.IrSize, &parms->Mix.Hrtf.Params[chan],
-                            &parms->Mix.Hrtf.State[chan], DstBufferSize);
-            }
-
-            for(j = 0;j < Device->NumAuxSends;j++)
-            {
-                SendParams *parms = &src->Send[j];
-                const ALfloat *samples;
-
-                if(!parms->OutBuffer)
-                    continue;
-
-                samples = DoFilters(
-                    &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass,
-                    Device->FilteredData, ResampledData, DstBufferSize,
-                    parms->Filters[chan].ActiveType
-                );
-                Mix(samples, 1, parms->OutBuffer, &parms->Gain,
-                    parms->Counter, OutPos, DstBufferSize);
-            }
-        }
-        /* Update positions */
-        DataPosFrac += increment*DstBufferSize;
-        DataPosInt  += DataPosFrac>>FRACTIONBITS;
-        DataPosFrac &= FRACTIONMASK;
-
-        OutPos += DstBufferSize;
-        src->Offset += DstBufferSize;
-        src->Direct.Counter = maxu(src->Direct.Counter, DstBufferSize) - DstBufferSize;
-        for(j = 0;j < Device->NumAuxSends;j++)
-            src->Send[j].Counter = maxu(src->Send[j].Counter, DstBufferSize) - DstBufferSize;
-
-        /* Handle looping sources */
-        while(1)
-        {
-            const ALbuffer *ALBuffer;
-            ALuint DataSize = 0;
-            ALuint LoopStart = 0;
-            ALuint LoopEnd = 0;
-
-            if((ALBuffer=BufferListItem->buffer) != NULL)
-            {
-                DataSize = ALBuffer->SampleLen;
-                LoopStart = ALBuffer->LoopStart;
-                LoopEnd = ALBuffer->LoopEnd;
-                if(LoopEnd > DataPosInt)
-                    break;
-            }
-
-            if(Looping && Source->SourceType == AL_STATIC)
-            {
-                assert(LoopEnd > LoopStart);
-                DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart;
-                break;
-            }
-
-            if(DataSize > DataPosInt)
-                break;
-
-            if(!(BufferListItem=BufferListItem->next))
-            {
-                if(Looping)
-                    BufferListItem = ATOMIC_LOAD(&Source->queue);
-                else
-                {
-                    State = AL_STOPPED;
-                    BufferListItem = NULL;
-                    DataPosInt = 0;
-                    DataPosFrac = 0;
-                    break;
-                }
-            }
-
-            DataPosInt -= DataSize;
-        }
-    } while(State == AL_PLAYING && OutPos < SamplesToDo);
-
-    /* Update source info */
-    Source->state             = State;
-    ATOMIC_STORE(&Source->current_buffer, BufferListItem);
-    Source->position          = DataPosInt;
-    Source->position_fraction = DataPosFrac;
-}

+ 0 - 126
love/src/jni/openal-soft-1.17.0/Alc/mixer_c.c

@@ -1,126 +0,0 @@
-#include "config.h"
-
-#include <assert.h>
-
-#include "alMain.h"
-#include "alu.h"
-#include "alSource.h"
-#include "alAuxEffectSlot.h"
-
-
-static inline ALfloat point32(const ALfloat *vals, ALuint UNUSED(frac))
-{ return vals[0]; }
-static inline ALfloat lerp32(const ALfloat *vals, ALuint frac)
-{ return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); }
-static inline ALfloat cubic32(const ALfloat *vals, ALuint frac)
-{ return cubic(vals[-1], vals[0], vals[1], vals[2], frac * (1.0f/FRACTIONONE)); }
-
-const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint UNUSED(frac),
-  ALuint increment, ALfloat *restrict dst, ALuint numsamples)
-{
-    assert(increment==FRACTIONONE);
-#if defined(HAVE_SSE) || defined(HAVE_NEON)
-    /* Avoid copying the source data if it's aligned like the destination. */
-    if((((intptr_t)src)&15) == (((intptr_t)dst)&15))
-        return src;
-#endif
-    memcpy(dst, src, numsamples*sizeof(ALfloat));
-    return dst;
-}
-
-#define DECL_TEMPLATE(Sampler)                                                \
-const ALfloat *Resample_##Sampler##_C(const ALfloat *src, ALuint frac,        \
-  ALuint increment, ALfloat *restrict dst, ALuint numsamples)                 \
-{                                                                             \
-    ALuint i;                                                                 \
-    for(i = 0;i < numsamples;i++)                                             \
-    {                                                                         \
-        dst[i] = Sampler(src, frac);                                          \
-                                                                              \
-        frac += increment;                                                    \
-        src  += frac>>FRACTIONBITS;                                           \
-        frac &= FRACTIONMASK;                                                 \
-    }                                                                         \
-    return dst;                                                               \
-}
-
-DECL_TEMPLATE(point32)
-DECL_TEMPLATE(lerp32)
-DECL_TEMPLATE(cubic32)
-
-#undef DECL_TEMPLATE
-
-
-void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples)
-{
-    ALuint i;
-    for(i = 0;i < numsamples;i++)
-        *(dst++) = ALfilterState_processSingle(filter, *(src++));
-}
-
-
-static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
-                                   const ALuint IrSize,
-                                   ALfloat (*restrict Coeffs)[2],
-                                   const ALfloat (*restrict CoeffStep)[2],
-                                   ALfloat left, ALfloat right)
-{
-    ALuint c;
-    for(c = 0;c < IrSize;c++)
-    {
-        const ALuint off = (Offset+c)&HRIR_MASK;
-        Values[off][0] += Coeffs[c][0] * left;
-        Values[off][1] += Coeffs[c][1] * right;
-        Coeffs[c][0] += CoeffStep[c][0];
-        Coeffs[c][1] += CoeffStep[c][1];
-    }
-}
-
-static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
-                               const ALuint IrSize,
-                               ALfloat (*restrict Coeffs)[2],
-                               ALfloat left, ALfloat right)
-{
-    ALuint c;
-    for(c = 0;c < IrSize;c++)
-    {
-        const ALuint off = (Offset+c)&HRIR_MASK;
-        Values[off][0] += Coeffs[c][0] * left;
-        Values[off][1] += Coeffs[c][1] * right;
-    }
-}
-
-#define SUFFIX C
-#include "mixer_inc.c"
-#undef SUFFIX
-
-
-void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
-           MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize)
-{
-    ALfloat gain, step;
-    ALuint c;
-
-    for(c = 0;c < OutChans;c++)
-    {
-        ALuint pos = 0;
-        gain = Gains[c].Current;
-        step = Gains[c].Step;
-        if(step != 1.0f && Counter > 0)
-        {
-            for(;pos < BufferSize && pos < Counter;pos++)
-            {
-                OutBuffer[c][OutPos+pos] += data[pos]*gain;
-                gain *= step;
-            }
-            if(pos == Counter)
-                gain = Gains[c].Target;
-            Gains[c].Current = gain;
-        }
-
-        if(!(gain > GAIN_SILENCE_THRESHOLD))
-            continue;
-        for(;pos < BufferSize;pos++)
-            OutBuffer[c][OutPos+pos] += data[pos]*gain;
-    }
-}

+ 0 - 65
love/src/jni/openal-soft-1.17.0/Alc/mixer_defs.h

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

+ 0 - 93
love/src/jni/openal-soft-1.17.0/Alc/mixer_inc.c

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

+ 0 - 118
love/src/jni/openal-soft-1.17.0/Alc/mixer_neon.c

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

+ 0 - 202
love/src/jni/openal-soft-1.17.0/Alc/mixer_sse.c

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

+ 0 - 82
love/src/jni/openal-soft-1.17.0/Alc/mixer_sse41.c

@@ -1,82 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <xmmintrin.h>
-#include <emmintrin.h>
-#include <smmintrin.h>
-
-#include "alu.h"
-#include "mixer_defs.h"
-
-
-const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint increment,
-                                     ALfloat *restrict dst, ALuint numsamples)
-{
-    const __m128i increment4 = _mm_set1_epi32(increment*4);
-    const __m128 fracOne4 = _mm_set1_ps(1.0f/FRACTIONONE);
-    const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK);
-    alignas(16) union { ALuint i[4]; float f[4]; } pos_;
-    alignas(16) union { ALuint i[4]; float f[4]; } frac_;
-    __m128i frac4, pos4;
-    ALuint pos;
-    ALuint i;
-
-    InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4);
-
-    frac4 = _mm_castps_si128(_mm_load_ps(frac_.f));
-    pos4 = _mm_castps_si128(_mm_load_ps(pos_.f));
-
-    for(i = 0;numsamples-i > 3;i += 4)
-    {
-        const __m128 val1 = _mm_setr_ps(src[pos_.i[0]], src[pos_.i[1]], src[pos_.i[2]], src[pos_.i[3]]);
-        const __m128 val2 = _mm_setr_ps(src[pos_.i[0]+1], src[pos_.i[1]+1], src[pos_.i[2]+1], src[pos_.i[3]+1]);
-
-        /* val1 + (val2-val1)*mu */
-        const __m128 r0 = _mm_sub_ps(val2, val1);
-        const __m128 mu = _mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4);
-        const __m128 out = _mm_add_ps(val1, _mm_mul_ps(mu, r0));
-
-        _mm_store_ps(&dst[i], out);
-
-        frac4 = _mm_add_epi32(frac4, increment4);
-        pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS));
-        frac4 = _mm_and_si128(frac4, fracMask4);
-
-        pos_.i[0] = _mm_extract_epi32(pos4, 0);
-        pos_.i[1] = _mm_extract_epi32(pos4, 1);
-        pos_.i[2] = _mm_extract_epi32(pos4, 2);
-        pos_.i[3] = _mm_extract_epi32(pos4, 3);
-    }
-
-    pos = pos_.i[0];
-    frac = _mm_cvtsi128_si32(frac4);
-
-    for(;i < numsamples;i++)
-    {
-        dst[i] = lerp(src[pos], src[pos+1], frac * (1.0f/FRACTIONONE));
-
-        frac += increment;
-        pos  += frac>>FRACTIONBITS;
-        frac &= FRACTIONMASK;
-    }
-    return dst;
-}

+ 0 - 450
love/src/jni/openal-soft-1.17.0/Alc/panning.c

@@ -1,450 +0,0 @@
-/**
- * OpenAL cross platform audio library
- * Copyright (C) 1999-2010 by authors.
- * This library is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU Library General Public
- *  License as published by the Free Software Foundation; either
- *  version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- *  Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <math.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <assert.h>
-
-#include "alMain.h"
-#include "AL/al.h"
-#include "AL/alc.h"
-#include "alu.h"
-
-extern inline void SetGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MaxChannels]);
-
-static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MaxChannels],
-                                  enum Channel Speaker2Chan[MaxChannels], ALint chans)
-{
-    char *confkey, *next;
-    char *layout_str;
-    char *sep, *end;
-    enum Channel val;
-    const char *str;
-    int i;
-
-    if(!ConfigValueStr(NULL, name, &str) && !ConfigValueStr(NULL, "layout", &str))
-        return;
-
-    layout_str = strdup(str);
-    next = confkey = layout_str;
-    while(next && *next)
-    {
-        confkey = next;
-        next = strchr(confkey, ',');
-        if(next)
-        {
-            *next = 0;
-            do {
-                next++;
-            } while(isspace(*next) || *next == ',');
-        }
-
-        sep = strchr(confkey, '=');
-        if(!sep || confkey == sep)
-        {
-            ERR("Malformed speaker key: %s\n", confkey);
-            continue;
-        }
-
-        end = sep - 1;
-        while(isspace(*end) && end != confkey)
-            end--;
-        *(++end) = 0;
-
-        if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0)
-            val = FrontLeft;
-        else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0)
-            val = FrontRight;
-        else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0)
-            val = FrontCenter;
-        else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0)
-            val = BackLeft;
-        else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0)
-            val = BackRight;
-        else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0)
-            val = BackCenter;
-        else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0)
-            val = SideLeft;
-        else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0)
-            val = SideRight;
-        else
-        {
-            ERR("Unknown speaker for %s: \"%s\"\n", name, confkey);
-            continue;
-        }
-
-        *(sep++) = 0;
-        while(isspace(*sep))
-            sep++;
-
-        for(i = 0;i < chans;i++)
-        {
-            if(Speaker2Chan[i] == val)
-            {
-                long angle = strtol(sep, NULL, 10);
-                if(angle >= -180 && angle <= 180)
-                    SpeakerAngle[i] = DEG2RAD(angle);
-                else
-                    ERR("Invalid angle for speaker \"%s\": %ld\n", confkey, angle);
-                break;
-            }
-        }
-    }
-    free(layout_str);
-    layout_str = NULL;
-
-    for(i = 0;i < chans;i++)
-    {
-        int min = i;
-        int i2;
-
-        for(i2 = i+1;i2 < chans;i2++)
-        {
-            if(SpeakerAngle[i2] < SpeakerAngle[min])
-                min = i2;
-        }
-
-        if(min != i)
-        {
-            ALfloat tmpf;
-            enum Channel tmpc;
-
-            tmpf = SpeakerAngle[i];
-            SpeakerAngle[i] = SpeakerAngle[min];
-            SpeakerAngle[min] = tmpf;
-
-            tmpc = Speaker2Chan[i];
-            Speaker2Chan[i] = Speaker2Chan[min];
-            Speaker2Chan[min] = tmpc;
-        }
-    }
-}
-
-
-void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat gains[MaxChannels])
-{
-    ALfloat tmpgains[MaxChannels] = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
-    enum Channel Speaker2Chan[MaxChannels];
-    ALfloat SpeakerAngle[MaxChannels];
-    ALfloat langle, rangle;
-    ALfloat a;
-    ALuint i;
-
-    for(i = 0;i < device->NumChan;i++)
-        Speaker2Chan[i] = device->Speaker2Chan[i];
-    for(i = 0;i < device->NumChan;i++)
-        SpeakerAngle[i] = device->SpeakerAngle[i];
-
-    /* Some easy special-cases first... */
-    if(device->NumChan <= 1 || hwidth >= F_PI)
-    {
-        /* Full coverage for all speakers. */
-        for(i = 0;i < MaxChannels;i++)
-            gains[i] = 0.0f;
-        for(i = 0;i < device->NumChan;i++)
-        {
-            enum Channel chan = Speaker2Chan[i];
-            gains[chan] = ingain;
-        }
-        return;
-    }
-    if(hwidth <= 0.0f)
-    {
-        /* Infinitely small sound point. */
-        for(i = 0;i < MaxChannels;i++)
-            gains[i] = 0.0f;
-        for(i = 0;i < device->NumChan-1;i++)
-        {
-            if(angle >= SpeakerAngle[i] && angle < SpeakerAngle[i+1])
-            {
-                /* Sound is between speakers i and i+1 */
-                a =             (angle-SpeakerAngle[i]) /
-                    (SpeakerAngle[i+1]-SpeakerAngle[i]);
-                gains[Speaker2Chan[i]]   = sqrtf(1.0f-a) * ingain;
-                gains[Speaker2Chan[i+1]] = sqrtf(     a) * ingain;
-                return;
-            }
-        }
-        /* Sound is between last and first speakers */
-        if(angle < SpeakerAngle[0])
-            angle += F_2PI;
-        a =                   (angle-SpeakerAngle[i]) /
-            (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
-        gains[Speaker2Chan[i]] = sqrtf(1.0f-a) * ingain;
-        gains[Speaker2Chan[0]] = sqrtf(     a) * ingain;
-        return;
-    }
-
-    if(fabsf(angle)+hwidth > F_PI)
-    {
-        /* The coverage area would go outside of -pi...+pi. Instead, rotate the
-         * speaker angles so it would be as if angle=0, and keep them wrapped
-         * within -pi...+pi. */
-        if(angle > 0.0f)
-        {
-            ALuint done;
-            ALuint i = 0;
-            while(i < device->NumChan && device->SpeakerAngle[i]-angle < -F_PI)
-                i++;
-            for(done = 0;i < device->NumChan;done++)
-            {
-                SpeakerAngle[done] = device->SpeakerAngle[i]-angle;
-                Speaker2Chan[done] = device->Speaker2Chan[i];
-                i++;
-            }
-            for(i = 0;done < device->NumChan;i++)
-            {
-                SpeakerAngle[done] = device->SpeakerAngle[i]-angle + F_2PI;
-                Speaker2Chan[done] = device->Speaker2Chan[i];
-                done++;
-            }
-        }
-        else
-        {
-            /* NOTE: '< device->NumChan' on the iterators is correct here since
-             * we need to handle index 0. Because the iterators are unsigned,
-             * they'll underflow and wrap to become 0xFFFFFFFF, which will
-             * break as expected. */
-            ALuint done;
-            ALuint i = device->NumChan-1;
-            while(i < device->NumChan && device->SpeakerAngle[i]-angle > F_PI)
-                i--;
-            for(done = device->NumChan-1;i < device->NumChan;done--)
-            {
-                SpeakerAngle[done] = device->SpeakerAngle[i]-angle;
-                Speaker2Chan[done] = device->Speaker2Chan[i];
-                i--;
-            }
-            for(i = device->NumChan-1;done < device->NumChan;i--)
-            {
-                SpeakerAngle[done] = device->SpeakerAngle[i]-angle - F_2PI;
-                Speaker2Chan[done] = device->Speaker2Chan[i];
-                done--;
-            }
-        }
-        angle = 0.0f;
-    }
-    langle = angle - hwidth;
-    rangle = angle + hwidth;
-
-    /* First speaker */
-    i = 0;
-    do {
-        ALuint last = device->NumChan-1;
-        enum Channel chan = Speaker2Chan[i];
-
-        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
-        {
-            tmpgains[chan] = 1.0f;
-            continue;
-        }
-
-        if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
-        {
-            a =            (langle-SpeakerAngle[i]) /
-                (SpeakerAngle[i+1]-SpeakerAngle[i]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
-        }
-        if(SpeakerAngle[i] > rangle)
-        {
-            a =          (F_2PI + rangle-SpeakerAngle[last]) /
-                (F_2PI + SpeakerAngle[i]-SpeakerAngle[last]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
-        }
-        else if(SpeakerAngle[last] < rangle)
-        {
-            a =                  (rangle-SpeakerAngle[last]) /
-                (F_2PI + SpeakerAngle[i]-SpeakerAngle[last]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
-        }
-    } while(0);
-
-    for(i = 1;i < device->NumChan-1;i++)
-    {
-        enum Channel chan = Speaker2Chan[i];
-        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
-        {
-            tmpgains[chan] = 1.0f;
-            continue;
-        }
-
-        if(SpeakerAngle[i] < langle && SpeakerAngle[i+1] > langle)
-        {
-            a =            (langle-SpeakerAngle[i]) /
-                (SpeakerAngle[i+1]-SpeakerAngle[i]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
-        }
-        if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
-        {
-            a =          (rangle-SpeakerAngle[i-1]) /
-                (SpeakerAngle[i]-SpeakerAngle[i-1]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
-        }
-    }
-
-    /* Last speaker */
-    i = device->NumChan-1;
-    do {
-        enum Channel chan = Speaker2Chan[i];
-        if(SpeakerAngle[i] >= langle && SpeakerAngle[i] <= rangle)
-        {
-            tmpgains[Speaker2Chan[i]] = 1.0f;
-            continue;
-        }
-        if(SpeakerAngle[i] > rangle && SpeakerAngle[i-1] < rangle)
-        {
-            a =          (rangle-SpeakerAngle[i-1]) /
-                (SpeakerAngle[i]-SpeakerAngle[i-1]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, a);
-        }
-        if(SpeakerAngle[i] < langle)
-        {
-            a =                  (langle-SpeakerAngle[i]) /
-                (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
-        }
-        else if(SpeakerAngle[0] > langle)
-        {
-            a =          (F_2PI + langle-SpeakerAngle[i]) /
-                (F_2PI + SpeakerAngle[0]-SpeakerAngle[i]);
-            tmpgains[chan] = lerp(tmpgains[chan], 1.0f, 1.0f-a);
-        }
-    } while(0);
-
-    for(i = 0;i < device->NumChan;i++)
-    {
-        enum Channel chan = device->Speaker2Chan[i];
-        gains[chan] = sqrtf(tmpgains[chan]) * ingain;
-    }
-}
-
-
-ALvoid aluInitPanning(ALCdevice *Device)
-{
-    const char *layoutname = NULL;
-    enum Channel *Speaker2Chan;
-    ALfloat *SpeakerAngle;
-
-    Speaker2Chan = Device->Speaker2Chan;
-    SpeakerAngle = Device->SpeakerAngle;
-    switch(Device->FmtChans)
-    {
-        case DevFmtMono:
-            Device->NumChan = 1;
-            Speaker2Chan[0] = FrontCenter;
-            SpeakerAngle[0] = DEG2RAD(0.0f);
-            layoutname = NULL;
-            break;
-
-        case DevFmtStereo:
-            Device->NumChan = 2;
-            Speaker2Chan[0] = FrontLeft;
-            Speaker2Chan[1] = FrontRight;
-            SpeakerAngle[0] = DEG2RAD(-90.0f);
-            SpeakerAngle[1] = DEG2RAD( 90.0f);
-            layoutname = "layout_stereo";
-            break;
-
-        case DevFmtQuad:
-            Device->NumChan = 4;
-            Speaker2Chan[0] = BackLeft;
-            Speaker2Chan[1] = FrontLeft;
-            Speaker2Chan[2] = FrontRight;
-            Speaker2Chan[3] = BackRight;
-            SpeakerAngle[0] = DEG2RAD(-135.0f);
-            SpeakerAngle[1] = DEG2RAD( -45.0f);
-            SpeakerAngle[2] = DEG2RAD(  45.0f);
-            SpeakerAngle[3] = DEG2RAD( 135.0f);
-            layoutname = "layout_quad";
-            break;
-
-        case DevFmtX51:
-            Device->NumChan = 5;
-            Speaker2Chan[0] = BackLeft;
-            Speaker2Chan[1] = FrontLeft;
-            Speaker2Chan[2] = FrontCenter;
-            Speaker2Chan[3] = FrontRight;
-            Speaker2Chan[4] = BackRight;
-            SpeakerAngle[0] = DEG2RAD(-110.0f);
-            SpeakerAngle[1] = DEG2RAD( -30.0f);
-            SpeakerAngle[2] = DEG2RAD(   0.0f);
-            SpeakerAngle[3] = DEG2RAD(  30.0f);
-            SpeakerAngle[4] = DEG2RAD( 110.0f);
-            layoutname = "layout_surround51";
-            break;
-
-        case DevFmtX51Side:
-            Device->NumChan = 5;
-            Speaker2Chan[0] = SideLeft;
-            Speaker2Chan[1] = FrontLeft;
-            Speaker2Chan[2] = FrontCenter;
-            Speaker2Chan[3] = FrontRight;
-            Speaker2Chan[4] = SideRight;
-            SpeakerAngle[0] = DEG2RAD(-90.0f);
-            SpeakerAngle[1] = DEG2RAD(-30.0f);
-            SpeakerAngle[2] = DEG2RAD(  0.0f);
-            SpeakerAngle[3] = DEG2RAD( 30.0f);
-            SpeakerAngle[4] = DEG2RAD( 90.0f);
-            layoutname = "layout_side51";
-            break;
-
-        case DevFmtX61:
-            Device->NumChan = 6;
-            Speaker2Chan[0] = SideLeft;
-            Speaker2Chan[1] = FrontLeft;
-            Speaker2Chan[2] = FrontCenter;
-            Speaker2Chan[3] = FrontRight;
-            Speaker2Chan[4] = SideRight;
-            Speaker2Chan[5] = BackCenter;
-            SpeakerAngle[0] = DEG2RAD(-90.0f);
-            SpeakerAngle[1] = DEG2RAD(-30.0f);
-            SpeakerAngle[2] = DEG2RAD(  0.0f);
-            SpeakerAngle[3] = DEG2RAD( 30.0f);
-            SpeakerAngle[4] = DEG2RAD( 90.0f);
-            SpeakerAngle[5] = DEG2RAD(180.0f);
-            layoutname = "layout_surround61";
-            break;
-
-        case DevFmtX71:
-            Device->NumChan = 7;
-            Speaker2Chan[0] = BackLeft;
-            Speaker2Chan[1] = SideLeft;
-            Speaker2Chan[2] = FrontLeft;
-            Speaker2Chan[3] = FrontCenter;
-            Speaker2Chan[4] = FrontRight;
-            Speaker2Chan[5] = SideRight;
-            Speaker2Chan[6] = BackRight;
-            SpeakerAngle[0] = DEG2RAD(-150.0f);
-            SpeakerAngle[1] = DEG2RAD( -90.0f);
-            SpeakerAngle[2] = DEG2RAD( -30.0f);
-            SpeakerAngle[3] = DEG2RAD(   0.0f);
-            SpeakerAngle[4] = DEG2RAD(  30.0f);
-            SpeakerAngle[5] = DEG2RAD(  90.0f);
-            SpeakerAngle[6] = DEG2RAD( 150.0f);
-            layoutname = "layout_surround71";
-            break;
-    }
-    if(layoutname && Device->Type != Loopback)
-        SetSpeakerArrangement(layoutname, SpeakerAngle, Speaker2Chan, Device->NumChan);
-}

+ 0 - 87
love/src/jni/openal-soft-1.17.0/Alc/vector.h

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

+ 0 - 112
love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alFilter.h

@@ -1,112 +0,0 @@
-#ifndef _AL_FILTER_H_
-#define _AL_FILTER_H_
-
-#include "alMain.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define LOWPASSFREQREF  (5000.0f)
-#define HIGHPASSFREQREF  (250.0f)
-
-
-/* Filters implementation is based on the "Cookbook formulae for audio   *
- * EQ biquad filter coefficients" by Robert Bristow-Johnson              *
- * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt                   */
-
-typedef enum ALfilterType {
-    /** EFX-style low-pass filter, specifying a gain and reference frequency. */
-    ALfilterType_HighShelf,
-    /** EFX-style high-pass filter, specifying a gain and reference frequency. */
-    ALfilterType_LowShelf,
-    /** Peaking filter, specifying a gain, reference frequency, and bandwidth. */
-    ALfilterType_Peaking,
-
-    /** Low-pass cut-off filter, specifying a cut-off frequency and bandwidth. */
-    ALfilterType_LowPass,
-    /** High-pass cut-off filter, specifying a cut-off frequency and bandwidth. */
-    ALfilterType_HighPass,
-    /** Band-pass filter, specifying a center frequency and bandwidth. */
-    ALfilterType_BandPass,
-} ALfilterType;
-
-typedef struct ALfilterState {
-    ALfloat x[2]; /* History of two last input samples  */
-    ALfloat y[2]; /* History of two last output samples */
-    ALfloat a[3]; /* Transfer function coefficients "a" */
-    ALfloat b[3]; /* Transfer function coefficients "b" */
-
-    void (*process)(struct ALfilterState *self, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples);
-} ALfilterState;
-#define ALfilterState_process(a, ...) ((a)->process((a), __VA_ARGS__))
-
-void ALfilterState_clear(ALfilterState *filter);
-void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat bandwidth);
-
-inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample)
-{
-    ALfloat outsmp;
-
-    outsmp = filter->b[0] * sample +
-             filter->b[1] * filter->x[0] +
-             filter->b[2] * filter->x[1] -
-             filter->a[1] * filter->y[0] -
-             filter->a[2] * filter->y[1];
-    filter->x[1] = filter->x[0];
-    filter->x[0] = sample;
-    filter->y[1] = filter->y[0];
-    filter->y[0] = outsmp;
-
-    return outsmp;
-}
-
-void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples);
-
-
-typedef struct ALfilter {
-    // Filter type (AL_FILTER_NULL, ...)
-    ALenum type;
-
-    ALfloat Gain;
-    ALfloat GainHF;
-    ALfloat HFReference;
-    ALfloat GainLF;
-    ALfloat LFReference;
-
-    void (*SetParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint val);
-    void (*SetParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals);
-    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);
-
-    /* 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 struct ALfilter *LookupFilter(ALCdevice *device, ALuint id)
-{ return (struct ALfilter*)LookupUIntMapKey(&device->FilterMap, id); }
-inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id)
-{ return (struct ALfilter*)RemoveUIntMapKey(&device->FilterMap, id); }
-
-ALvoid ReleaseALFilters(ALCdevice *device);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 28
love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alListener.h

@@ -1,28 +0,0 @@
-#ifndef _AL_LISTENER_H_
-#define _AL_LISTENER_H_
-
-#include "alMain.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct ALlistener {
-    volatile ALfloat Position[3];
-    volatile ALfloat Velocity[3];
-    volatile ALfloat Forward[3];
-    volatile ALfloat Up[3];
-    volatile ALfloat Gain;
-    volatile ALfloat MetersPerUnit;
-
-    struct {
-        ALfloat Matrix[4][4];
-        ALfloat Velocity[3];
-    } Params;
-} ALlistener;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 895
love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alMain.h

@@ -1,895 +0,0 @@
-#ifndef AL_MAIN_H
-#define AL_MAIN_H
-
-#include <string.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <math.h>
-#include <limits.h>
-
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-#ifdef HAVE_FENV_H
-#include <fenv.h>
-#endif
-
-#include "AL/al.h"
-#include "AL/alc.h"
-#include "AL/alext.h"
-
-
-#if defined(_WIN64)
-#define SZFMT "%I64u"
-#elif defined(_WIN32)
-#define SZFMT "%u"
-#else
-#define SZFMT "%zu"
-#endif
-
-
-#include "static_assert.h"
-#include "align.h"
-#include "atomic.h"
-#include "uintmap.h"
-#include "vector.h"
-#include "alstring.h"
-
-#ifndef ALC_SOFT_HRTF
-#define ALC_SOFT_HRTF 1
-#define ALC_HRTF_SOFT                            0x1992
-#endif
-
-#ifndef ALC_SOFT_midi_interface
-#define ALC_SOFT_midi_interface 1
-/* Global properties */
-#define AL_MIDI_CLOCK_SOFT                       0x9999
-#define AL_MIDI_STATE_SOFT                       0x9986
-#define AL_MIDI_GAIN_SOFT                        0x9998
-#define AL_SOUNDFONTS_SIZE_SOFT                  0x9995
-#define AL_SOUNDFONTS_SOFT                       0x9994
-
-/* Soundfont properties */
-#define AL_PRESETS_SIZE_SOFT                     0x9993
-#define AL_PRESETS_SOFT                          0x9992
-
-/* Preset properties */
-#define AL_MIDI_PRESET_SOFT                      0x9997
-#define AL_MIDI_BANK_SOFT                        0x9996
-#define AL_FONTSOUNDS_SIZE_SOFT                  0x9991
-#define AL_FONTSOUNDS_SOFT                       0x9990
-
-/* Fontsound properties */
-/* AL_BUFFER */
-#define AL_SAMPLE_START_SOFT                     0x2000
-#define AL_SAMPLE_END_SOFT                       0x2001
-#define AL_SAMPLE_LOOP_START_SOFT                0x2002
-#define AL_SAMPLE_LOOP_END_SOFT                  0x2003
-#define AL_SAMPLE_RATE_SOFT                      0x2004
-#define AL_BASE_KEY_SOFT                         0x2005
-#define AL_KEY_CORRECTION_SOFT                   0x2006
-#define AL_SAMPLE_TYPE_SOFT                      0x2007
-#define AL_FONTSOUND_LINK_SOFT                   0x2008
-#define AL_MOD_LFO_TO_PITCH_SOFT                 0x0005
-#define AL_VIBRATO_LFO_TO_PITCH_SOFT             0x0006
-#define AL_MOD_ENV_TO_PITCH_SOFT                 0x0007
-#define AL_FILTER_CUTOFF_SOFT                    0x0008
-#define AL_FILTER_RESONANCE_SOFT                 0x0009
-#define AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT         0x000A
-#define AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT         0x000B
-#define AL_MOD_LFO_TO_VOLUME_SOFT                0x000D
-#define AL_CHORUS_SEND_SOFT                      0x000F
-#define AL_REVERB_SEND_SOFT                      0x0010
-#define AL_PAN_SOFT                              0x0011
-#define AL_MOD_LFO_DELAY_SOFT                    0x0015
-#define AL_MOD_LFO_FREQUENCY_SOFT                0x0016
-#define AL_VIBRATO_LFO_DELAY_SOFT                0x0017
-#define AL_VIBRATO_LFO_FREQUENCY_SOFT            0x0018
-#define AL_MOD_ENV_DELAYTIME_SOFT                0x0019
-#define AL_MOD_ENV_ATTACKTIME_SOFT               0x001A
-#define AL_MOD_ENV_HOLDTIME_SOFT                 0x001B
-#define AL_MOD_ENV_DECAYTIME_SOFT                0x001C
-#define AL_MOD_ENV_SUSTAINVOLUME_SOFT            0x001D
-#define AL_MOD_ENV_RELEASETIME_SOFT              0x002E
-#define AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT          0x001F
-#define AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT         0x0020
-#define AL_VOLUME_ENV_DELAYTIME_SOFT             0x0021
-#define AL_VOLUME_ENV_ATTACKTIME_SOFT            0x0022
-#define AL_VOLUME_ENV_HOLDTIME_SOFT              0x0023
-#define AL_VOLUME_ENV_DECAYTIME_SOFT             0x0024
-#define AL_VOLUME_ENV_SUSTAINVOLUME_SOFT         0x0025
-#define AL_VOLUME_ENV_RELEASETIME_SOFT           0x0026
-#define AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT       0x0027
-#define AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT      0x0028
-#define AL_KEY_RANGE_SOFT                        0x002B
-#define AL_VELOCITY_RANGE_SOFT                   0x002C
-#define AL_ATTENUATION_SOFT                      0x0030
-#define AL_TUNING_COARSE_SOFT                    0x0033
-#define AL_TUNING_FINE_SOFT                      0x0034
-#define AL_LOOP_MODE_SOFT                        0x0036
-#define AL_TUNING_SCALE_SOFT                     0x0038
-#define AL_EXCLUSIVE_CLASS_SOFT                  0x0039
-
-/* Sample Types */
-/* AL_MONO_SOFT */
-#define AL_RIGHT_SOFT                            0x0002
-#define AL_LEFT_SOFT                             0x0004
-
-/* Loop Modes */
-/* AL_NONE */
-#define AL_LOOP_CONTINUOUS_SOFT                  0x0001
-#define AL_LOOP_UNTIL_RELEASE_SOFT               0x0003
-
-/* Fontsound modulator stage properties */
-#define AL_SOURCE0_INPUT_SOFT                    0x998F
-#define AL_SOURCE0_TYPE_SOFT                     0x998E
-#define AL_SOURCE0_FORM_SOFT                     0x998D
-#define AL_SOURCE1_INPUT_SOFT                    0x998C
-#define AL_SOURCE1_TYPE_SOFT                     0x998B
-#define AL_SOURCE1_FORM_SOFT                     0x998A
-#define AL_AMOUNT_SOFT                           0x9989
-#define AL_TRANSFORM_OP_SOFT                     0x9988
-#define AL_DESTINATION_SOFT                      0x9987
-
-/* Sounce Inputs */
-#define AL_ONE_SOFT                              0x0080
-#define AL_NOTEON_VELOCITY_SOFT                  0x0082
-#define AL_NOTEON_KEY_SOFT                       0x0083
-/* AL_KEYPRESSURE_SOFT */
-/* AL_CHANNELPRESSURE_SOFT */
-/* AL_PITCHBEND_SOFT */
-#define AL_PITCHBEND_SENSITIVITY_SOFT            0x0090
-/* CC 0...127 */
-
-/* Source Types */
-#define AL_UNORM_SOFT                            0x0000
-#define AL_UNORM_REV_SOFT                        0x0100
-#define AL_SNORM_SOFT                            0x0200
-#define AL_SNORM_REV_SOFT                        0x0300
-
-/* Source Forms */
-#define AL_LINEAR_SOFT                           0x0000
-#define AL_CONCAVE_SOFT                          0x0400
-#define AL_CONVEX_SOFT                           0x0800
-#define AL_SWITCH_SOFT                           0x0C00
-
-/* Transform Ops */
-/* AL_LINEAR_SOFT */
-#define AL_ABSOLUTE_SOFT                         0x0002
-
-/* Events */
-#define AL_NOTEOFF_SOFT                          0x0080
-#define AL_NOTEON_SOFT                           0x0090
-#define AL_KEYPRESSURE_SOFT                      0x00A0
-#define AL_CONTROLLERCHANGE_SOFT                 0x00B0
-#define AL_PROGRAMCHANGE_SOFT                    0x00C0
-#define AL_CHANNELPRESSURE_SOFT                  0x00D0
-#define AL_PITCHBEND_SOFT                        0x00E0
-
-typedef void (AL_APIENTRY*LPALGENSOUNDFONTSSOFT)(ALsizei n, ALuint *ids);
-typedef void (AL_APIENTRY*LPALDELETESOUNDFONTSSOFT)(ALsizei n, const ALuint *ids);
-typedef ALboolean (AL_APIENTRY*LPALISSOUNDFONTSOFT)(ALuint id);
-typedef void (AL_APIENTRY*LPALGETSOUNDFONTIVSOFT)(ALuint id, ALenum param, ALint *values);
-typedef void (AL_APIENTRY*LPALSOUNDFONTPRESETSSOFT)(ALuint id, ALsizei count, const ALuint *pids);
-typedef void (AL_APIENTRY*LPALGENPRESETSSOFT)(ALsizei n, ALuint *ids);
-typedef void (AL_APIENTRY*LPALDELETEPRESETSSOFT)(ALsizei n, const ALuint *ids);
-typedef ALboolean (AL_APIENTRY*LPALISPRESETSOFT)(ALuint id);
-typedef void (AL_APIENTRY*LPALPRESETISOFT)(ALuint id, ALenum param, ALint value);
-typedef void (AL_APIENTRY*LPALPRESETIVSOFT)(ALuint id, ALenum param, const ALint *values);
-typedef void (AL_APIENTRY*LPALPRESETFONTSOUNDSSOFT)(ALuint id, ALsizei count, const ALuint *fsids);
-typedef void (AL_APIENTRY*LPALGETPRESETIVSOFT)(ALuint id, ALenum param, ALint *values);
-typedef void (AL_APIENTRY*LPALGENFONTSOUNDSSOFT)(ALsizei n, ALuint *ids);
-typedef void (AL_APIENTRY*LPALDELETEFONTSOUNDSSOFT)(ALsizei n, const ALuint *ids);
-typedef ALboolean (AL_APIENTRY*LPALISFONTSOUNDSOFT)(ALuint id);
-typedef void (AL_APIENTRY*LPALFONTSOUNDISOFT)(ALuint id, ALenum param, ALint value);
-typedef void (AL_APIENTRY*LPALFONTSOUND2ISOFT)(ALuint id, ALenum param, ALint value1, ALint value2);
-typedef void (AL_APIENTRY*LPALFONTSOUNDIVSOFT)(ALuint id, ALenum param, const ALint *values);
-typedef void (AL_APIENTRY*LPALGETFONTSOUNDIVSOFT)(ALuint id, ALenum param, ALint *values);
-typedef void (AL_APIENTRY*LPALFONTSOUNDMOFULATORISOFT)(ALuint id, ALsizei stage, ALenum param, ALint value);
-typedef void (AL_APIENTRY*LPALGETFONTSOUNDMODULATORIVSOFT)(ALuint id, ALsizei stage, ALenum param, ALint *values);
-typedef void (AL_APIENTRY*LPALMIDISOUNDFONTSOFT)(ALuint id);
-typedef void (AL_APIENTRY*LPALMIDISOUNDFONTVSOFT)(ALsizei count, const ALuint *ids);
-typedef void (AL_APIENTRY*LPALMIDIEVENTSOFT)(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2);
-typedef void (AL_APIENTRY*LPALMIDISYSEXSOFT)(ALuint64SOFT time, const ALbyte *data, ALsizei size);
-typedef void (AL_APIENTRY*LPALMIDIPLAYSOFT)(void);
-typedef void (AL_APIENTRY*LPALMIDIPAUSESOFT)(void);
-typedef void (AL_APIENTRY*LPALMIDISTOPSOFT)(void);
-typedef void (AL_APIENTRY*LPALMIDIRESETSOFT)(void);
-typedef void (AL_APIENTRY*LPALMIDIGAINSOFT)(ALfloat value);
-typedef ALint64SOFT (AL_APIENTRY*LPALGETINTEGER64SOFT)(ALenum pname);
-typedef void (AL_APIENTRY*LPALGETINTEGER64VSOFT)(ALenum pname, ALint64SOFT *values);
-typedef void (AL_APIENTRY*LPALLOADSOUNDFONTSOFT)(ALuint id, size_t(*cb)(ALvoid*,size_t,ALvoid*), ALvoid *user);
-#ifdef AL_ALEXT_PROTOTYPES
-AL_API void AL_APIENTRY alGenSoundfontsSOFT(ALsizei n, ALuint *ids);
-AL_API void AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids);
-AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(ALuint id);
-AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *values);
-AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const ALuint *pids);
-
-AL_API void AL_APIENTRY alGenPresetsSOFT(ALsizei n, ALuint *ids);
-AL_API void AL_APIENTRY alDeletePresetsSOFT(ALsizei n, const ALuint *ids);
-AL_API ALboolean AL_APIENTRY alIsPresetSOFT(ALuint id);
-AL_API void AL_APIENTRY alPresetiSOFT(ALuint id, ALenum param, ALint value);
-AL_API void AL_APIENTRY alPresetivSOFT(ALuint id, ALenum param, const ALint *values);
-AL_API void AL_APIENTRY alGetPresetivSOFT(ALuint id, ALenum param, ALint *values);
-AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const ALuint *fsids);
-
-AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids);
-AL_API void AL_APIENTRY alDeleteFontsoundsSOFT(ALsizei n, const ALuint *ids);
-AL_API ALboolean AL_APIENTRY alIsFontsoundSOFT(ALuint id);
-AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value);
-AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1, ALint value2);
-AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint *values);
-AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *values);
-AL_API void AL_APIENTRY alFontsoundModulatoriSOFT(ALuint id, ALsizei stage, ALenum param, ALint value);
-AL_API void AL_APIENTRY alGetFontsoundModulatorivSOFT(ALuint id, ALsizei stage, ALenum param, ALint *values);
-
-AL_API void AL_APIENTRY alMidiSoundfontSOFT(ALuint id);
-AL_API void AL_APIENTRY alMidiSoundfontvSOFT(ALsizei count, const ALuint *ids);
-AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2);
-AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, ALsizei size);
-AL_API void AL_APIENTRY alMidiPlaySOFT(void);
-AL_API void AL_APIENTRY alMidiPauseSOFT(void);
-AL_API void AL_APIENTRY alMidiStopSOFT(void);
-AL_API void AL_APIENTRY alMidiResetSOFT(void);
-AL_API void AL_APIENTRY alMidiGainSOFT(ALfloat value);
-AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname);
-AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values);
-AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_t,ALvoid*), ALvoid *user);
-#endif
-#endif
-
-#ifndef ALC_SOFT_device_clock
-#define ALC_SOFT_device_clock 1
-typedef int64_t ALCint64SOFT;
-typedef uint64_t ALCuint64SOFT;
-#define ALC_DEVICE_CLOCK_SOFT                    0x1600
-typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
-#ifdef AL_ALEXT_PROTOTYPES
-ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values);
-#endif
-#endif
-
-
-#ifdef IN_IDE_PARSER
-/* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but
- * recent versions (at least 4.5.1) do recognize GCC's __restrict. */
-#define restrict __restrict
-#endif
-
-
-typedef ALint64SOFT ALint64;
-typedef ALuint64SOFT ALuint64;
-
-typedef ptrdiff_t ALintptrEXT;
-typedef ptrdiff_t ALsizeiptrEXT;
-
-#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
-
-#ifndef UINT64_MAX
-#define UINT64_MAX U64(18446744073709551615)
-#endif
-
-#ifndef UNUSED
-#if defined(__cplusplus)
-#define UNUSED(x)
-#elif defined(__GNUC__)
-#define UNUSED(x) UNUSED_##x __attribute__((unused))
-#elif defined(__LCLINT__)
-#define UNUSED(x) /*@unused@*/ x
-#else
-#define UNUSED(x) x
-#endif
-#endif
-
-#ifdef __GNUC__
-#define DECL_CONST __attribute__((const))
-#define DECL_FORMAT(x, y, z) __attribute__((format(x, (y), (z))))
-#else
-#define DECL_CONST
-#define DECL_FORMAT(x, y, z)
-#endif
-
-#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))
-#endif
-
-#ifndef PATH_MAX
-#ifdef MAX_PATH
-#define PATH_MAX MAX_PATH
-#else
-#define PATH_MAX 4096
-#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((x)[0]))
-
-
-#define DERIVE_FROM_TYPE(t)          t t##_parent
-#define STATIC_CAST(to, obj)         (&(obj)->to##_parent)
-#ifdef __GNUC__
-#define STATIC_UPCAST(to, from, obj) __extension__({                          \
-    static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))),       \
-                  "Invalid upcast object from type");                         \
-    (to*)((char*)(obj) - offsetof(to, from##_parent));                        \
-})
-#else
-#define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent)))
-#endif
-
-#define DECLARE_FORWARD(T1, T2, rettype, func)                                \
-rettype T1##_##func(T1 *obj)                                                  \
-{ 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); }
-
-
-#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_DEFAULT_ALLOCATORS(T)                                         \
-static void* T##_New(size_t size) { return malloc(size); }                    \
-static void T##_Delete(void *ptr) { free(ptr); }
-
-/* Helper to extract an argument list for VCALL. Not used directly. */
-#define EXTRACT_VCALL_ARGS(...)  __VA_ARGS__))
-
-/* 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
-
-#define DELETE_OBJ(obj) do {                                                  \
-    if((obj) != NULL)                                                         \
-    {                                                                         \
-        V0((obj),Destruct)();                                                 \
-        V0((obj),Delete)();                                                   \
-    }                                                                         \
-} while(0)
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct Hrtf;
-
-
-#define DEFAULT_OUTPUT_RATE  (44100)
-#define MIN_OUTPUT_RATE      (8000)
-
-
-/* Find the next power-of-2 for non-power-of-2 numbers. */
-inline ALuint NextPowerOf2(ALuint value)
-{
-    if(value > 0)
-    {
-        value--;
-        value |= value>>1;
-        value |= value>>2;
-        value |= value>>4;
-        value |= value>>8;
-        value |= value>>16;
-    }
-    return value+1;
-}
-
-/* Fast float-to-int conversion. Assumes the FPU is already in round-to-zero
- * mode. */
-inline ALint fastf2i(ALfloat f)
-{
-#ifdef HAVE_LRINTF
-    return lrintf(f);
-#elif defined(_MSC_VER) && defined(_M_IX86)
-    ALint i;
-    __asm fld f
-    __asm fistp i
-    return i;
-#else
-    return (ALint)f;
-#endif
-}
-
-/* Fast float-to-uint conversion. Assumes the FPU is already in round-to-zero
- * mode. */
-inline ALuint fastf2u(ALfloat f)
-{ return fastf2i(f); }
-
-
-enum DevProbe {
-    ALL_DEVICE_PROBE,
-    CAPTURE_DEVICE_PROBE
-};
-
-typedef struct {
-    ALCenum (*OpenPlayback)(ALCdevice*, const ALCchar*);
-    void (*ClosePlayback)(ALCdevice*);
-    ALCboolean (*ResetPlayback)(ALCdevice*);
-    ALCboolean (*StartPlayback)(ALCdevice*);
-    void (*StopPlayback)(ALCdevice*);
-
-    ALCenum (*OpenCapture)(ALCdevice*, const ALCchar*);
-    void (*CloseCapture)(ALCdevice*);
-    void (*StartCapture)(ALCdevice*);
-    void (*StopCapture)(ALCdevice*);
-    ALCenum (*CaptureSamples)(ALCdevice*, void*, ALCuint);
-    ALCuint (*AvailableSamples)(ALCdevice*);
-
-    ALint64 (*GetLatency)(ALCdevice*);
-} BackendFuncs;
-
-ALCboolean alc_solaris_init(BackendFuncs *func_list);
-void alc_solaris_deinit(void);
-void alc_solaris_probe(enum DevProbe type);
-ALCboolean alc_sndio_init(BackendFuncs *func_list);
-void alc_sndio_deinit(void);
-void alc_sndio_probe(enum DevProbe type);
-ALCboolean alcWinMMInit(BackendFuncs *FuncList);
-void alcWinMMDeinit(void);
-void alcWinMMProbe(enum DevProbe type);
-ALCboolean alc_pa_init(BackendFuncs *func_list);
-void alc_pa_deinit(void);
-void alc_pa_probe(enum DevProbe type);
-ALCboolean alc_wave_init(BackendFuncs *func_list);
-void alc_wave_deinit(void);
-void alc_wave_probe(enum DevProbe type);
-ALCboolean alc_ca_init(BackendFuncs *func_list);
-void alc_ca_deinit(void);
-void alc_ca_probe(enum DevProbe type);
-ALCboolean alc_opensl_init(BackendFuncs *func_list);
-void alc_opensl_deinit(void);
-void alc_opensl_probe(enum DevProbe type);
-ALCboolean alc_qsa_init(BackendFuncs *func_list);
-void alc_qsa_deinit(void);
-void alc_qsa_probe(enum DevProbe type);
-
-struct ALCbackend;
-
-
-enum DistanceModel {
-    InverseDistanceClamped  = AL_INVERSE_DISTANCE_CLAMPED,
-    LinearDistanceClamped   = AL_LINEAR_DISTANCE_CLAMPED,
-    ExponentDistanceClamped = AL_EXPONENT_DISTANCE_CLAMPED,
-    InverseDistance  = AL_INVERSE_DISTANCE,
-    LinearDistance   = AL_LINEAR_DISTANCE,
-    ExponentDistance = AL_EXPONENT_DISTANCE,
-    DisableDistance  = AL_NONE,
-
-    DefaultDistanceModel = InverseDistanceClamped
-};
-
-enum Resampler {
-    PointResampler,
-    LinearResampler,
-    CubicResampler,
-
-    ResamplerMax,
-};
-
-enum Channel {
-    FrontLeft = 0,
-    FrontRight,
-    FrontCenter,
-    LFE,
-    BackLeft,
-    BackRight,
-    BackCenter,
-    SideLeft,
-    SideRight,
-
-    MaxChannels,
-};
-
-
-/* Device formats */
-enum DevFmtType {
-    DevFmtByte   = ALC_BYTE_SOFT,
-    DevFmtUByte  = ALC_UNSIGNED_BYTE_SOFT,
-    DevFmtShort  = ALC_SHORT_SOFT,
-    DevFmtUShort = ALC_UNSIGNED_SHORT_SOFT,
-    DevFmtInt    = ALC_INT_SOFT,
-    DevFmtUInt   = ALC_UNSIGNED_INT_SOFT,
-    DevFmtFloat  = ALC_FLOAT_SOFT,
-
-    DevFmtTypeDefault = DevFmtFloat
-};
-enum DevFmtChannels {
-    DevFmtMono   = ALC_MONO_SOFT,
-    DevFmtStereo = ALC_STEREO_SOFT,
-    DevFmtQuad   = ALC_QUAD_SOFT,
-    DevFmtX51    = ALC_5POINT1_SOFT,
-    DevFmtX61    = ALC_6POINT1_SOFT,
-    DevFmtX71    = ALC_7POINT1_SOFT,
-
-    /* Similar to 5.1, except using the side channels instead of back */
-    DevFmtX51Side = 0x80000000,
-
-    DevFmtChannelsDefault = DevFmtStereo
-};
-
-ALuint BytesFromDevFmt(enum DevFmtType type) DECL_CONST;
-ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) DECL_CONST;
-inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type)
-{
-    return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type);
-}
-
-
-extern const struct EffectList {
-    const char *name;
-    int type;
-    const char *ename;
-    ALenum val;
-} EffectList[];
-
-
-enum DeviceType {
-    Playback,
-    Capture,
-    Loopback
-};
-
-
-/* Size for temporary storage of buffer data, in ALfloats. Larger values need
- * more memory, while smaller values may need more iterations. The value needs
- * to be a sensible size, however, as it constrains the max stepping value used
- * for mixing, as well as the maximum number of samples per mixing iteration.
- */
-#define BUFFERSIZE (2048u)
-
-
-struct ALCdevice_struct
-{
-    RefCount ref;
-
-    ALCboolean Connected;
-    enum DeviceType Type;
-
-    ALuint       Frequency;
-    ALuint       UpdateSize;
-    ALuint       NumUpdates;
-    enum DevFmtChannels FmtChans;
-    enum DevFmtType     FmtType;
-
-    al_string DeviceName;
-
-    ATOMIC(ALCenum) LastError;
-
-    // Maximum number of sources that can be created
-    ALuint       MaxNoOfSources;
-    // Maximum number of slots that can be created
-    ALuint       AuxiliaryEffectSlotMax;
-
-    ALCuint      NumMonoSources;
-    ALCuint      NumStereoSources;
-    ALuint       NumAuxSends;
-
-    // Map of Buffers for this device
-    UIntMap BufferMap;
-
-    // Map of Effects for this device
-    UIntMap EffectMap;
-
-    // Map of Filters for this device
-    UIntMap FilterMap;
-
-    // Map of Soundfonts for this device
-    UIntMap SfontMap;
-
-    // Map of Presets for this device
-    UIntMap PresetMap;
-
-    // Map of Fontsounds for this device
-    UIntMap FontsoundMap;
-
-    /* Default soundfont (accessible as ID 0) */
-    struct ALsoundfont *DefaultSfont;
-
-    /* MIDI synth engine */
-    struct MidiSynth *Synth;
-
-    /* HRTF filter tables */
-    const struct Hrtf *Hrtf;
-
-    // Stereo-to-binaural filter
-    struct bs2b *Bs2b;
-    ALCint       Bs2bLevel;
-
-    // Device flags
-    ALuint       Flags;
-
-    ALuint ChannelOffsets[MaxChannels];
-
-    enum Channel Speaker2Chan[MaxChannels];
-    ALfloat SpeakerAngle[MaxChannels];
-    ALuint  NumChan;
-
-    ALuint64 ClockBase;
-    ALuint SamplesDone;
-
-    /* Temp storage used for each source when mixing. */
-    alignas(16) ALfloat SourceData[BUFFERSIZE];
-    alignas(16) ALfloat ResampledData[BUFFERSIZE];
-    alignas(16) ALfloat FilteredData[BUFFERSIZE];
-
-    // Dry path buffer mix
-    alignas(16) ALfloat DryBuffer[MaxChannels][BUFFERSIZE];
-
-    /* Running count of the mixer invocations, in 31.1 fixed point. This
-     * actually increments *twice* when mixing, first at the start and then at
-     * the end, so the bottom bit indicates if the device is currently mixing
-     * and the upper bits indicates how many mixes have been done.
-     */
-    RefCount MixCount;
-
-    /* Default effect slot */
-    struct ALeffectslot *DefaultSlot;
-
-    // Contexts created on this device
-    ATOMIC(ALCcontext*) ContextList;
-
-    struct ALCbackend *Backend;
-
-    void *ExtraData; // For the backend's use
-
-    ALCdevice *volatile next;
-
-    /* Memory space used by the default slot (Playback devices only) */
-    alignas(16) ALCbyte _slot_mem[];
-};
-
-// Frequency was requested by the app or config file
-#define DEVICE_FREQUENCY_REQUEST                 (1<<1)
-// Channel configuration was requested by the config file
-#define DEVICE_CHANNELS_REQUEST                  (1<<2)
-// Sample type was requested by the config file
-#define DEVICE_SAMPLE_TYPE_REQUEST               (1<<3)
-// HRTF was requested by the app
-#define DEVICE_HRTF_REQUEST                      (1<<4)
-
-// Stereo sources cover 120-degree angles around +/-90
-#define DEVICE_WIDE_STEREO                       (1<<16)
-
-// Specifies if the DSP is paused at user request
-#define DEVICE_PAUSED                            (1<<30)
-
-// Specifies if the device is currently running
-#define DEVICE_RUNNING                           (1<<31)
-
-/* Invalid channel offset */
-#define INVALID_OFFSET                           (~0u)
-
-
-/* Nanosecond resolution for the device clock time. */
-#define DEVICE_CLOCK_RES  U64(1000000000)
-
-
-/* Must be less than 15 characters (16 including terminating null) for
- * compatibility with pthread_setname_np limitations. */
-#define MIXER_THREAD_NAME "alsoft-mixer"
-
-
-struct ALCcontext_struct
-{
-    RefCount ref;
-
-    struct ALlistener *Listener;
-
-    UIntMap SourceMap;
-    UIntMap EffectSlotMap;
-
-    ATOMIC(ALenum) LastError;
-
-    ATOMIC(ALenum) UpdateSources;
-
-    volatile enum DistanceModel DistanceModel;
-    volatile ALboolean SourceDistanceModel;
-
-    volatile ALfloat DopplerFactor;
-    volatile ALfloat DopplerVelocity;
-    volatile ALfloat SpeedOfSound;
-    volatile ALenum  DeferUpdates;
-
-    struct ALactivesource **ActiveSources;
-    ALsizei ActiveSourceCount;
-    ALsizei MaxActiveSources;
-
-    VECTOR(struct ALeffectslot*) ActiveAuxSlots;
-
-    ALCdevice  *Device;
-    const ALCchar *ExtensionList;
-
-    ALCcontext *volatile next;
-
-    /* Memory space used by the listener */
-    alignas(16) ALCbyte _listener_mem[];
-};
-
-ALCcontext *GetContextRef(void);
-
-void ALCcontext_IncRef(ALCcontext *context);
-void ALCcontext_DecRef(ALCcontext *context);
-
-void AppendAllDevicesList(const ALCchar *name);
-void AppendCaptureDeviceList(const ALCchar *name);
-
-ALint64 ALCdevice_GetLatencyDefault(ALCdevice *device);
-
-void ALCdevice_Lock(ALCdevice *device);
-void ALCdevice_Unlock(ALCdevice *device);
-ALint64 ALCdevice_GetLatency(ALCdevice *device);
-
-inline void LockContext(ALCcontext *context)
-{ ALCdevice_Lock(context->Device); }
-
-inline void UnlockContext(ALCcontext *context)
-{ ALCdevice_Unlock(context->Device); }
-
-
-void *al_malloc(size_t alignment, size_t size);
-void *al_calloc(size_t alignment, size_t size);
-void al_free(void *ptr);
-
-
-typedef struct {
-#ifdef HAVE_FENV_H
-    DERIVE_FROM_TYPE(fenv_t);
-#else
-    int state;
-#endif
-#ifdef HAVE_SSE
-    int sse_state;
-#endif
-} FPUCtl;
-void SetMixerFPUMode(FPUCtl *ctl);
-void RestoreFPUMode(const FPUCtl *ctl);
-
-
-typedef struct RingBuffer RingBuffer;
-RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length);
-void DestroyRingBuffer(RingBuffer *ring);
-ALsizei RingBufferSize(RingBuffer *ring);
-void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len);
-void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len);
-
-void ReadALConfig(void);
-void FreeALConfig(void);
-int ConfigValueExists(const char *blockName, const char *keyName);
-const char *GetConfigValue(const char *blockName, const char *keyName, const char *def);
-int GetConfigValueBool(const char *blockName, const char *keyName, int def);
-int ConfigValueStr(const char *blockName, const char *keyName, const char **ret);
-int ConfigValueInt(const char *blockName, const char *keyName, int *ret);
-int ConfigValueUInt(const char *blockName, const char *keyName, unsigned int *ret);
-int ConfigValueFloat(const char *blockName, const char *keyName, float *ret);
-
-void SetRTPriority(void);
-
-void SetDefaultChannelOrder(ALCdevice *device);
-void SetDefaultWFXChannelOrder(ALCdevice *device);
-
-const ALCchar *DevFmtTypeString(enum DevFmtType type) DECL_CONST;
-const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) DECL_CONST;
-
-
-extern FILE *LogFile;
-
-#if defined(__GNUC__) && !defined(IN_IDE_PARSER)
-#define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: "MSG, T, __FUNCTION__ , ## __VA_ARGS__)
-#else
-void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4);
-#define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__)
-#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__);                                        \
-} while(0)
-
-#define WARN(...) do {                                                        \
-    if(LogLevel >= LogWarning)                                                \
-        AL_PRINT("(WW)", __VA_ARGS__);                                        \
-} while(0)
-
-#define ERR(...) do {                                                         \
-    if(LogLevel >= LogError)                                                  \
-        AL_PRINT("(EE)", __VA_ARGS__);                                        \
-} while(0)
-
-
-extern ALint RTPrioLevel;
-
-
-extern ALuint CPUCapFlags;
-enum {
-    CPU_CAP_SSE    = 1<<0,
-    CPU_CAP_SSE2   = 1<<1,
-    CPU_CAP_SSE4_1 = 1<<2,
-    CPU_CAP_NEON   = 1<<3,
-};
-
-void FillCPUCaps(ALuint capfilter);
-
-FILE *OpenDataFile(const char *fname, const char *subdir);
-
-/* Small hack to use a pointer-to-array type as a normal argument type.
- * Shouldn't be used directly. */
-typedef ALfloat ALfloatBUFFERSIZE[BUFFERSIZE];
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 172
love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alMidi.h

@@ -1,172 +0,0 @@
-#ifndef ALMIDI_H
-#define ALMIDI_H
-
-#include "alMain.h"
-#include "atomic.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct ALsfmodulator {
-    struct {
-        ALenum Input;
-        ALenum Type;
-        ALenum Form;
-    } Source[2];
-    ALint Amount;
-    ALenum TransformOp;
-    ALenum Dest;
-} ALsfmodulator;
-
-typedef struct ALenvelope {
-    ALint DelayTime;
-    ALint AttackTime;
-    ALint HoldTime;
-    ALint DecayTime;
-    ALint SustainAttn;
-    ALint ReleaseTime;
-    ALint KeyToHoldTime;
-    ALint KeyToDecayTime;
-} ALenvelope;
-
-
-typedef struct ALfontsound {
-    RefCount ref;
-
-    struct ALbuffer *Buffer;
-
-    ALint MinKey, MaxKey;
-    ALint MinVelocity, MaxVelocity;
-
-    ALint ModLfoToPitch;
-    ALint VibratoLfoToPitch;
-    ALint ModEnvToPitch;
-
-    ALint FilterCutoff;
-    ALint FilterQ;
-    ALint ModLfoToFilterCutoff;
-    ALint ModEnvToFilterCutoff;
-    ALint ModLfoToVolume;
-
-    ALint ChorusSend;
-    ALint ReverbSend;
-
-    ALint Pan;
-
-    struct {
-        ALint Delay;
-        ALint Frequency;
-    } ModLfo;
-    struct {
-        ALint Delay;
-        ALint Frequency;
-    } VibratoLfo;
-
-    ALenvelope ModEnv;
-    ALenvelope VolEnv;
-
-    ALint Attenuation;
-
-    ALint CoarseTuning;
-    ALint FineTuning;
-
-    ALenum LoopMode;
-
-    ALint TuningScale;
-
-    ALint ExclusiveClass;
-
-    ALuint Start;
-    ALuint End;
-    ALuint LoopStart;
-    ALuint LoopEnd;
-    ALuint SampleRate;
-    ALubyte PitchKey;
-    ALbyte PitchCorrection;
-    ALenum SampleType;
-    struct ALfontsound *Link;
-
-    /* NOTE: Each map entry contains *four* (4) ALsfmodulator objects. */
-    UIntMap ModulatorMap;
-
-    ALuint id;
-} ALfontsound;
-
-void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value);
-void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value);
-
-ALfontsound *NewFontsound(ALCcontext *context);
-void DeleteFontsound(ALCdevice *device, ALfontsound *sound);
-
-inline struct ALfontsound *LookupFontsound(ALCdevice *device, ALuint id)
-{ return (struct ALfontsound*)LookupUIntMapKey(&device->FontsoundMap, id); }
-inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id)
-{ return (struct ALfontsound*)RemoveUIntMapKey(&device->FontsoundMap, id); }
-
-void ReleaseALFontsounds(ALCdevice *device);
-
-
-typedef struct ALsfpreset {
-    RefCount ref;
-
-    ALint Preset; /* a.k.a. MIDI program number */
-    ALint Bank; /* MIDI bank 0...127, or percussion (bank 128) */
-
-    ALfontsound **Sounds;
-    ALsizei NumSounds;
-
-    ALuint id;
-} ALsfpreset;
-
-ALsfpreset *NewPreset(ALCcontext *context);
-void DeletePreset(ALCdevice *device, ALsfpreset *preset);
-
-inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id)
-{ return (struct ALsfpreset*)LookupUIntMapKey(&device->PresetMap, id); }
-inline struct ALsfpreset *RemovePreset(ALCdevice *device, ALuint id)
-{ return (struct ALsfpreset*)RemoveUIntMapKey(&device->PresetMap, id); }
-
-void ReleaseALPresets(ALCdevice *device);
-
-
-typedef struct ALsoundfont {
-    RefCount ref;
-
-    ALsfpreset **Presets;
-    ALsizei NumPresets;
-
-    RWLock Lock;
-
-    ALuint id;
-} ALsoundfont;
-
-ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context);
-void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device);
-
-inline struct ALsoundfont *LookupSfont(ALCdevice *device, ALuint id)
-{ return (struct ALsoundfont*)LookupUIntMapKey(&device->SfontMap, id); }
-inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id)
-{ return (struct ALsoundfont*)RemoveUIntMapKey(&device->SfontMap, id); }
-
-void ReleaseALSoundfonts(ALCdevice *device);
-
-
-inline ALboolean IsValidCtrlInput(int cc)
-{
-    /* These correspond to MIDI functions, not real controller values. */
-    if(cc == 0 || cc == 6 || cc == 32 || cc == 38 || (cc >= 98 && cc <= 101) || cc >= 120)
-        return AL_FALSE;
-    /* These are the LSB components of CC0...CC31, which are automatically used when
-     * reading the MSB controller value. */
-    if(cc >= 32 && cc <= 63)
-        return AL_FALSE;
-    /* All the rest are okay! */
-    return AL_TRUE;
-}
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* ALMIDI_H */

+ 0 - 147
love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alSource.h

@@ -1,147 +0,0 @@
-#ifndef _AL_SOURCE_H_
-#define _AL_SOURCE_H_
-
-#define MAX_SENDS                 4
-
-#include "alMain.h"
-#include "alu.h"
-#include "hrtf.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern enum Resampler DefaultResampler;
-
-extern const ALsizei ResamplerPadding[ResamplerMax];
-extern const ALsizei ResamplerPrePadding[ResamplerMax];
-
-
-typedef struct ALbufferlistitem {
-    struct ALbuffer *buffer;
-    struct ALbufferlistitem *volatile next;
-    struct ALbufferlistitem *volatile prev;
-} ALbufferlistitem;
-
-
-typedef struct ALactivesource {
-    struct ALsource *Source;
-
-    /** Method to update mixing parameters. */
-    ALvoid (*Update)(struct ALactivesource *self, const ALCcontext *context);
-
-    /** Current target parameters used for mixing. */
-    ALint Step;
-
-    ALboolean IsHrtf;
-
-    ALuint Offset; /* Number of output samples mixed since starting. */
-
-    DirectParams Direct;
-    SendParams Send[MAX_SENDS];
-} ALactivesource;
-
-
-typedef struct ALsource {
-    /** Source properties. */
-    volatile ALfloat   Pitch;
-    volatile ALfloat   Gain;
-    volatile ALfloat   OuterGain;
-    volatile ALfloat   MinGain;
-    volatile ALfloat   MaxGain;
-    volatile ALfloat   InnerAngle;
-    volatile ALfloat   OuterAngle;
-    volatile ALfloat   RefDistance;
-    volatile ALfloat   MaxDistance;
-    volatile ALfloat   RollOffFactor;
-    volatile ALfloat   Position[3];
-    volatile ALfloat   Velocity[3];
-    volatile ALfloat   Orientation[3];
-    volatile ALboolean HeadRelative;
-    volatile ALboolean Looping;
-    volatile enum DistanceModel DistanceModel;
-    volatile ALboolean DirectChannels;
-
-    volatile ALboolean DryGainHFAuto;
-    volatile ALboolean WetGainAuto;
-    volatile ALboolean WetGainHFAuto;
-    volatile ALfloat   OuterGainHF;
-
-    volatile ALfloat AirAbsorptionFactor;
-    volatile ALfloat RoomRolloffFactor;
-    volatile ALfloat DopplerFactor;
-
-    volatile ALfloat Radius;
-
-    enum Resampler Resampler;
-
-    /**
-     * Last user-specified offset, and the offset type (bytes, samples, or
-     * seconds).
-     */
-    ALdouble Offset;
-    ALenum   OffsetType;
-
-    /** Source type (static, streaming, or undetermined) */
-    volatile ALint SourceType;
-
-    /** Source state (initial, playing, paused, or stopped) */
-    volatile ALenum state;
-    ALenum new_state;
-
-    /**
-     * Source offset in samples, relative to the currently playing buffer, NOT
-     * the whole queue, and the fractional (fixed-point) offset to the next
-     * sample.
-     */
-    ALuint position;
-    ALuint position_fraction;
-
-    /** Source Buffer Queue info. */
-    ATOMIC(ALbufferlistitem*) queue;
-    ATOMIC(ALbufferlistitem*) current_buffer;
-    RWLock queue_lock;
-
-    /** Current buffer sample info. */
-    ALuint NumChannels;
-    ALuint SampleSize;
-
-    /** Direct filter and auxiliary send info. */
-    struct {
-        ALfloat Gain;
-        ALfloat GainHF;
-        ALfloat HFReference;
-        ALfloat GainLF;
-        ALfloat LFReference;
-    } Direct;
-    struct {
-        struct ALeffectslot *Slot;
-        ALfloat Gain;
-        ALfloat GainHF;
-        ALfloat HFReference;
-        ALfloat GainLF;
-        ALfloat LFReference;
-    } Send[MAX_SENDS];
-
-    /** Source needs to update its mixing parameters. */
-    ATOMIC(ALenum) NeedsUpdate;
-
-    /** Self ID */
-    ALuint id;
-} ALsource;
-
-inline struct ALsource *LookupSource(ALCcontext *context, ALuint id)
-{ return (struct ALsource*)LookupUIntMapKey(&context->SourceMap, id); }
-inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id)
-{ return (struct ALsource*)RemoveUIntMapKey(&context->SourceMap, id); }
-
-ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state);
-ALboolean ApplyOffset(ALsource *Source);
-
-ALvoid ReleaseALSources(ALCcontext *Context);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 0 - 236
love/src/jni/openal-soft-1.17.0/OpenAL32/Include/alu.h

@@ -1,236 +0,0 @@
-#ifndef _ALU_H_
-#define _ALU_H_
-
-#include <limits.h>
-#include <math.h>
-#ifdef HAVE_FLOAT_H
-#include <float.h>
-#endif
-#ifdef HAVE_IEEEFP_H
-#include <ieeefp.h>
-#endif
-
-#include "alMain.h"
-#include "alBuffer.h"
-#include "alFilter.h"
-
-#include "hrtf.h"
-#include "align.h"
-
-
-#define F_PI    (3.14159265358979323846f)
-#define F_PI_2  (1.57079632679489661923f)
-#define F_2PI   (6.28318530717958647692f)
-
-#ifndef FLT_EPSILON
-#define FLT_EPSILON (1.19209290e-07f)
-#endif
-
-#define DEG2RAD(x)  ((ALfloat)(x) * (F_PI/180.0f))
-#define RAD2DEG(x)  ((ALfloat)(x) * (180.0f/F_PI))
-
-
-#define SRC_HISTORY_BITS   (6)
-#define SRC_HISTORY_LENGTH (1<<SRC_HISTORY_BITS)
-#define SRC_HISTORY_MASK   (SRC_HISTORY_LENGTH-1)
-
-#define MAX_PITCH  (10)
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum ActiveFilters {
-    AF_None = 0,
-    AF_LowPass = 1,
-    AF_HighPass = 2,
-    AF_BandPass = AF_LowPass | AF_HighPass
-};
-
-
-typedef struct HrtfState {
-    alignas(16) ALfloat History[SRC_HISTORY_LENGTH];
-    alignas(16) ALfloat Values[HRIR_LENGTH][2];
-} HrtfState;
-
-typedef struct HrtfParams {
-    alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
-    alignas(16) ALfloat CoeffStep[HRIR_LENGTH][2];
-    ALuint Delay[2];
-    ALint DelayStep[2];
-} HrtfParams;
-
-
-typedef struct MixGains {
-    ALfloat Current;
-    ALfloat Step;
-    ALfloat Target;
-} MixGains;
-
-
-typedef struct DirectParams {
-    ALfloat (*OutBuffer)[BUFFERSIZE];
-
-    /* If not 'moving', gain/coefficients are set directly without fading. */
-    ALboolean Moving;
-    /* Stepping counter for gain/coefficient fading. */
-    ALuint Counter;
-
-    struct {
-        enum ActiveFilters ActiveType;
-        ALfilterState LowPass;
-        ALfilterState HighPass;
-    } Filters[MAX_INPUT_CHANNELS];
-
-    union {
-        struct {
-            HrtfParams Params[MAX_INPUT_CHANNELS];
-            HrtfState State[MAX_INPUT_CHANNELS];
-            ALuint IrSize;
-            ALfloat Gain;
-            ALfloat Dir[3];
-        } Hrtf;
-
-        MixGains Gains[MAX_INPUT_CHANNELS][MaxChannels];
-    } Mix;
-} DirectParams;
-
-typedef struct SendParams {
-    ALfloat (*OutBuffer)[BUFFERSIZE];
-
-    ALboolean Moving;
-    ALuint Counter;
-
-    struct {
-        enum ActiveFilters ActiveType;
-        ALfilterState LowPass;
-        ALfilterState HighPass;
-    } Filters[MAX_INPUT_CHANNELS];
-
-    /* Gain control, which applies to all input channels to a single (mono)
-     * output buffer. */
-    MixGains Gain;
-} SendParams;
-
-
-typedef const ALfloat* (*ResamplerFunc)(const ALfloat *src, ALuint frac, ALuint increment,
-                                        ALfloat *restrict dst, ALuint dstlen);
-
-typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
-                          ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
-                          ALuint Counter, ALuint OutPos, ALuint BufferSize);
-typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
-                              ALuint Counter, ALuint Offset, ALuint OutPos,
-                              const ALuint IrSize, const HrtfParams *hrtfparams,
-                              HrtfState *hrtfstate, ALuint BufferSize);
-
-
-#define GAIN_SILENCE_THRESHOLD  (0.00001f) /* -100dB */
-
-#define SPEEDOFSOUNDMETRESPERSEC  (343.3f)
-#define AIRABSORBGAINHF           (0.99426f) /* -0.05dB */
-
-#define FRACTIONBITS (14)
-#define FRACTIONONE  (1<<FRACTIONBITS)
-#define FRACTIONMASK (FRACTIONONE-1)
-
-
-inline ALfloat minf(ALfloat a, ALfloat b)
-{ return ((a > b) ? b : a); }
-inline ALfloat maxf(ALfloat a, ALfloat b)
-{ return ((a > b) ? a : b); }
-inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max)
-{ return minf(max, maxf(min, val)); }
-
-inline ALdouble mind(ALdouble a, ALdouble b)
-{ return ((a > b) ? b : a); }
-inline ALdouble maxd(ALdouble a, ALdouble b)
-{ return ((a > b) ? a : b); }
-inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max)
-{ return mind(max, maxd(min, val)); }
-
-inline ALuint minu(ALuint a, ALuint b)
-{ return ((a > b) ? b : a); }
-inline ALuint maxu(ALuint a, ALuint b)
-{ return ((a > b) ? a : b); }
-inline ALuint clampu(ALuint val, ALuint min, ALuint max)
-{ return minu(max, maxu(min, val)); }
-
-inline ALint mini(ALint a, ALint b)
-{ return ((a > b) ? b : a); }
-inline ALint maxi(ALint a, ALint b)
-{ return ((a > b) ? a : b); }
-inline ALint clampi(ALint val, ALint min, ALint max)
-{ return mini(max, maxi(min, val)); }
-
-inline ALint64 mini64(ALint64 a, ALint64 b)
-{ return ((a > b) ? b : a); }
-inline ALint64 maxi64(ALint64 a, ALint64 b)
-{ return ((a > b) ? a : b); }
-inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max)
-{ return mini64(max, maxi64(min, val)); }
-
-inline ALuint64 minu64(ALuint64 a, ALuint64 b)
-{ return ((a > b) ? b : a); }
-inline ALuint64 maxu64(ALuint64 a, ALuint64 b)
-{ return ((a > b) ? a : b); }
-inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max)
-{ return minu64(max, maxu64(min, val)); }
-
-
-inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu)
-{
-    return val1 + (val2-val1)*mu;
-}
-inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat mu)
-{
-    ALfloat mu2 = mu*mu;
-    ALfloat a0 = -0.5f*val0 +  1.5f*val1 + -1.5f*val2 +  0.5f*val3;
-    ALfloat a1 =       val0 + -2.5f*val1 +  2.0f*val2 + -0.5f*val3;
-    ALfloat a2 = -0.5f*val0              +  0.5f*val2;
-    ALfloat a3 =                    val1;
-
-    return a0*mu*mu2 + a1*mu2 + a2*mu + a3;
-}
-
-
-ALvoid aluInitPanning(ALCdevice *Device);
-
-/**
- * ComputeAngleGains
- *
- * Sets channel gains based on a given source's angle and its half-width. The
- * angle and hwidth parameters are in radians.
- */
-void ComputeAngleGains(const ALCdevice *device, ALfloat angle, ALfloat hwidth, ALfloat ingain, ALfloat gains[MaxChannels]);
-
-/**
- * SetGains
- *
- * Helper to set the appropriate channels to the specified gain.
- */
-inline void SetGains(const ALCdevice *device, ALfloat ingain, ALfloat gains[MaxChannels])
-{
-    ComputeAngleGains(device, 0.0f, F_PI, ingain, gains);
-}
-
-
-ALvoid CalcSourceParams(struct ALactivesource *src, const ALCcontext *ALContext);
-ALvoid CalcNonAttnSourceParams(struct ALactivesource *src, const ALCcontext *ALContext);
-
-ALvoid MixSource(struct ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo);
-
-ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size);
-/* Caller must lock the device. */
-ALvoid aluHandleDisconnect(ALCdevice *device);
-
-extern ALfloat ConeScale;
-extern ALfloat ZScale;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-

+ 0 - 1008
love/src/jni/openal-soft-1.17.0/OpenAL32/alFontsound.c

@@ -1,1008 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "alMain.h"
-#include "alMidi.h"
-#include "alError.h"
-#include "alThunk.h"
-#include "alBuffer.h"
-
-#include "midi/base.h"
-
-
-extern inline struct ALfontsound *LookupFontsound(ALCdevice *device, ALuint id);
-extern inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id);
-
-
-static void ALfontsound_Construct(ALfontsound *self);
-static void ALfontsound_Destruct(ALfontsound *self);
-void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value);
-static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage);
-void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value);
-static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values);
-
-static inline struct ALsfmodulator *LookupModulator(ALfontsound *sound, ALuint id)
-{
-    ALsfmodulator *mod = LookupUIntMapKey(&sound->ModulatorMap, id>>2);
-    if(mod) mod += id&3;
-    return mod;
-}
-
-
-AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids)
-{
-    ALCcontext *context;
-    ALsizei cur = 0;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    for(cur = 0;cur < n;cur++)
-    {
-        ALfontsound *sound = NewFontsound(context);
-        if(!sound)
-        {
-            alDeleteFontsoundsSOFT(cur, ids);
-            break;
-        }
-
-        ids[cur] = sound->id;
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALvoid AL_APIENTRY alDeleteFontsoundsSOFT(ALsizei n, const ALuint *ids)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALfontsound *inst;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    for(i = 0;i < n;i++)
-    {
-        /* Check for valid ID */
-        if((inst=LookupFontsound(device, ids[i])) == NULL)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-        if(ReadRef(&inst->ref) != 0)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    }
-
-    for(i = 0;i < n;i++)
-    {
-        if((inst=LookupFontsound(device, ids[i])) != NULL)
-            DeleteFontsound(device, inst);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALboolean AL_APIENTRY alIsFontsoundSOFT(ALuint id)
-{
-    ALCcontext *context;
-    ALboolean ret;
-
-    context = GetContextRef();
-    if(!context) return AL_FALSE;
-
-    ret = LookupFontsound(context->Device, id) ? AL_TRUE : AL_FALSE;
-
-    ALCcontext_DecRef(context);
-
-    return ret;
-}
-
-AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALfontsound *sound;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(!(sound=LookupFontsound(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(ReadRef(&sound->ref) != 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-
-    ALfontsound_setPropi(sound, context, param, value);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1, ALint value2)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALfontsound *sound;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(!(sound=LookupFontsound(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(ReadRef(&sound->ref) != 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    switch(param)
-    {
-        case AL_KEY_RANGE_SOFT:
-            if(!(value1 >= 0 && value1 <= 127 && value2 >= 0 && value2 <= 127 && value2 >= value1))
-                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-            sound->MinKey = value1;
-            sound->MaxKey = value2;
-            break;
-
-        case AL_VELOCITY_RANGE_SOFT:
-            if(!(value1 >= 0 && value1 <= 127 && value2 >= 0 && value2 <= 127 && value2 >= value1))
-                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-            sound->MinVelocity = value1;
-            sound->MaxVelocity = value2;
-            break;
-
-        default:
-            SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint *values)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALfontsound *sound;
-
-    switch(param)
-    {
-        case AL_KEY_RANGE_SOFT:
-        case AL_VELOCITY_RANGE_SOFT:
-            alFontsound2iSOFT(id, param, values[0], values[1]);
-            return;
-
-        case AL_MOD_LFO_TO_PITCH_SOFT:
-        case AL_VIBRATO_LFO_TO_PITCH_SOFT:
-        case AL_MOD_ENV_TO_PITCH_SOFT:
-        case AL_FILTER_CUTOFF_SOFT:
-        case AL_FILTER_RESONANCE_SOFT:
-        case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
-        case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
-        case AL_MOD_LFO_TO_VOLUME_SOFT:
-        case AL_CHORUS_SEND_SOFT:
-        case AL_REVERB_SEND_SOFT:
-        case AL_PAN_SOFT:
-        case AL_MOD_LFO_DELAY_SOFT:
-        case AL_MOD_LFO_FREQUENCY_SOFT:
-        case AL_VIBRATO_LFO_DELAY_SOFT:
-        case AL_VIBRATO_LFO_FREQUENCY_SOFT:
-        case AL_MOD_ENV_DELAYTIME_SOFT:
-        case AL_MOD_ENV_ATTACKTIME_SOFT:
-        case AL_MOD_ENV_HOLDTIME_SOFT:
-        case AL_MOD_ENV_DECAYTIME_SOFT:
-        case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
-        case AL_MOD_ENV_RELEASETIME_SOFT:
-        case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
-        case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
-        case AL_VOLUME_ENV_DELAYTIME_SOFT:
-        case AL_VOLUME_ENV_ATTACKTIME_SOFT:
-        case AL_VOLUME_ENV_HOLDTIME_SOFT:
-        case AL_VOLUME_ENV_DECAYTIME_SOFT:
-        case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
-        case AL_VOLUME_ENV_RELEASETIME_SOFT:
-        case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
-        case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
-        case AL_ATTENUATION_SOFT:
-        case AL_TUNING_COARSE_SOFT:
-        case AL_TUNING_FINE_SOFT:
-        case AL_LOOP_MODE_SOFT:
-        case AL_TUNING_SCALE_SOFT:
-        case AL_EXCLUSIVE_CLASS_SOFT:
-        case AL_SAMPLE_START_SOFT:
-        case AL_SAMPLE_END_SOFT:
-        case AL_SAMPLE_LOOP_START_SOFT:
-        case AL_SAMPLE_LOOP_END_SOFT:
-        case AL_SAMPLE_RATE_SOFT:
-        case AL_BASE_KEY_SOFT:
-        case AL_KEY_CORRECTION_SOFT:
-        case AL_SAMPLE_TYPE_SOFT:
-        case AL_FONTSOUND_LINK_SOFT:
-            alFontsoundiSOFT(id, param, values[0]);
-            return;
-    }
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(!(sound=LookupFontsound(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(ReadRef(&sound->ref) != 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    switch(param)
-    {
-        default:
-            SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *values)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    const ALfontsound *sound;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(!(sound=LookupFontsound(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    switch(param)
-    {
-        case AL_BUFFER:
-            values[0] = (sound->Buffer ? sound->Buffer->id : 0);
-            break;
-
-        case AL_MOD_LFO_TO_PITCH_SOFT:
-            values[0] = sound->ModLfoToPitch;
-            break;
-
-        case AL_VIBRATO_LFO_TO_PITCH_SOFT:
-            values[0] = sound->VibratoLfoToPitch;
-            break;
-
-        case AL_MOD_ENV_TO_PITCH_SOFT:
-            values[0] = sound->ModEnvToPitch;
-            break;
-
-        case AL_FILTER_CUTOFF_SOFT:
-            values[0] = sound->FilterCutoff;
-            break;
-
-        case AL_FILTER_RESONANCE_SOFT:
-            values[0] = sound->FilterQ;
-            break;
-
-        case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
-            values[0] = sound->ModLfoToFilterCutoff;
-            break;
-
-        case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
-            values[0] = sound->ModEnvToFilterCutoff;
-            break;
-
-        case AL_MOD_LFO_TO_VOLUME_SOFT:
-            values[0] = sound->ModLfoToVolume;
-            break;
-
-        case AL_CHORUS_SEND_SOFT:
-            values[0] = sound->ChorusSend;
-            break;
-
-        case AL_REVERB_SEND_SOFT:
-            values[0] = sound->ReverbSend;
-            break;
-
-        case AL_PAN_SOFT:
-            values[0] = sound->Pan;
-            break;
-
-        case AL_MOD_LFO_DELAY_SOFT:
-            values[0] = sound->ModLfo.Delay;
-            break;
-        case AL_MOD_LFO_FREQUENCY_SOFT:
-            values[0] = sound->ModLfo.Frequency;
-            break;
-
-        case AL_VIBRATO_LFO_DELAY_SOFT:
-            values[0] = sound->VibratoLfo.Delay;
-            break;
-        case AL_VIBRATO_LFO_FREQUENCY_SOFT:
-            values[0] = sound->VibratoLfo.Frequency;
-            break;
-
-        case AL_MOD_ENV_DELAYTIME_SOFT:
-            values[0] = sound->ModEnv.DelayTime;
-            break;
-        case AL_MOD_ENV_ATTACKTIME_SOFT:
-            values[0] = sound->ModEnv.AttackTime;
-            break;
-        case AL_MOD_ENV_HOLDTIME_SOFT:
-            values[0] = sound->ModEnv.HoldTime;
-            break;
-        case AL_MOD_ENV_DECAYTIME_SOFT:
-            values[0] = sound->ModEnv.DecayTime;
-            break;
-        case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
-            values[0] = sound->ModEnv.SustainAttn;
-            break;
-        case AL_MOD_ENV_RELEASETIME_SOFT:
-            values[0] = sound->ModEnv.ReleaseTime;
-            break;
-        case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
-            values[0] = sound->ModEnv.KeyToHoldTime;
-            break;
-        case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
-            values[0] = sound->ModEnv.KeyToDecayTime;
-            break;
-
-        case AL_VOLUME_ENV_DELAYTIME_SOFT:
-            values[0] = sound->VolEnv.DelayTime;
-            break;
-        case AL_VOLUME_ENV_ATTACKTIME_SOFT:
-            values[0] = sound->VolEnv.AttackTime;
-            break;
-        case AL_VOLUME_ENV_HOLDTIME_SOFT:
-            values[0] = sound->VolEnv.HoldTime;
-            break;
-        case AL_VOLUME_ENV_DECAYTIME_SOFT:
-            values[0] = sound->VolEnv.DecayTime;
-            break;
-        case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
-            values[0] = sound->VolEnv.SustainAttn;
-            break;
-        case AL_VOLUME_ENV_RELEASETIME_SOFT:
-            values[0] = sound->VolEnv.ReleaseTime;
-            break;
-        case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
-            values[0] = sound->VolEnv.KeyToHoldTime;
-            break;
-        case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
-            values[0] = sound->VolEnv.KeyToDecayTime;
-            break;
-
-        case AL_KEY_RANGE_SOFT:
-            values[0] = sound->MinKey;
-            values[1] = sound->MaxKey;
-            break;
-
-        case AL_VELOCITY_RANGE_SOFT:
-            values[0] = sound->MinVelocity;
-            values[1] = sound->MaxVelocity;
-            break;
-
-        case AL_ATTENUATION_SOFT:
-            values[0] = sound->Attenuation;
-            break;
-
-        case AL_TUNING_COARSE_SOFT:
-            values[0] = sound->CoarseTuning;
-            break;
-        case AL_TUNING_FINE_SOFT:
-            values[0] = sound->FineTuning;
-            break;
-
-        case AL_LOOP_MODE_SOFT:
-            values[0] = sound->LoopMode;
-            break;
-
-        case AL_TUNING_SCALE_SOFT:
-            values[0] = sound->TuningScale;
-            break;
-
-        case AL_EXCLUSIVE_CLASS_SOFT:
-            values[0] = sound->ExclusiveClass;
-            break;
-
-        case AL_SAMPLE_START_SOFT:
-            values[0] = sound->Start;
-            break;
-
-        case AL_SAMPLE_END_SOFT:
-            values[0] = sound->End;
-            break;
-
-        case AL_SAMPLE_LOOP_START_SOFT:
-            values[0] = sound->LoopStart;
-            break;
-
-        case AL_SAMPLE_LOOP_END_SOFT:
-            values[0] = sound->LoopEnd;
-            break;
-
-        case AL_SAMPLE_RATE_SOFT:
-            values[0] = sound->SampleRate;
-            break;
-
-        case AL_BASE_KEY_SOFT:
-            values[0] = sound->PitchKey;
-            break;
-
-        case AL_KEY_CORRECTION_SOFT:
-            values[0] = sound->PitchCorrection;
-            break;
-
-        case AL_SAMPLE_TYPE_SOFT:
-            values[0] = sound->SampleType;
-            break;
-
-        case AL_FONTSOUND_LINK_SOFT:
-            values[0] = (sound->Link ? sound->Link->id : 0);
-            break;
-
-        default:
-            SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alFontsoundModulatoriSOFT(ALuint id, ALsizei stage, ALenum param, ALint value)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALfontsound *sound;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(!(sound=LookupFontsound(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    ALfontsound_setModStagei(sound, context, stage, param, value);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alGetFontsoundModulatorivSOFT(ALuint id, ALsizei stage, ALenum param, ALint *values)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALfontsound *sound;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(!(sound=LookupFontsound(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    ALfontsound_getModStagei(sound, context, stage, param, values);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-ALfontsound *NewFontsound(ALCcontext *context)
-{
-    ALCdevice *device = context->Device;
-    ALfontsound *sound;
-    ALenum  err;
-
-    sound = calloc(1, sizeof(*sound));
-    if(!sound)
-        SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
-    ALfontsound_Construct(sound);
-
-    err = NewThunkEntry(&sound->id);
-    if(err == AL_NO_ERROR)
-        err = InsertUIntMapEntry(&device->FontsoundMap, sound->id, sound);
-    if(err != AL_NO_ERROR)
-    {
-        ALfontsound_Destruct(sound);
-        memset(sound, 0, sizeof(*sound));
-        free(sound);
-
-        SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
-    }
-
-    return sound;
-}
-
-void DeleteFontsound(ALCdevice *device, ALfontsound *sound)
-{
-    RemoveFontsound(device, sound->id);
-
-    ALfontsound_Destruct(sound);
-
-    memset(sound, 0, sizeof(*sound));
-    free(sound);
-}
-
-
-static void ALfontsound_Construct(ALfontsound *self)
-{
-    InitRef(&self->ref, 0);
-
-    self->Buffer = NULL;
-
-    self->MinKey = 0;
-    self->MaxKey = 127;
-    self->MinVelocity = 0;
-    self->MaxVelocity = 127;
-
-    self->ModLfoToPitch = 0;
-    self->VibratoLfoToPitch = 0;
-    self->ModEnvToPitch = 0;
-
-    self->FilterCutoff = 13500;
-    self->FilterQ = 0;
-    self->ModLfoToFilterCutoff = 0;
-    self->ModEnvToFilterCutoff = 0;
-    self->ModLfoToVolume = 0;
-
-    self->ChorusSend = 0;
-    self->ReverbSend = 0;
-
-    self->Pan = 0;
-
-    self->ModLfo.Delay = 0;
-    self->ModLfo.Frequency = 0;
-
-    self->VibratoLfo.Delay = 0;
-    self->VibratoLfo.Frequency = 0;
-
-    self->ModEnv.DelayTime = -12000;
-    self->ModEnv.AttackTime = -12000;
-    self->ModEnv.HoldTime = -12000;
-    self->ModEnv.DecayTime = -12000;
-    self->ModEnv.SustainAttn = 0;
-    self->ModEnv.ReleaseTime = -12000;
-    self->ModEnv.KeyToHoldTime = 0;
-    self->ModEnv.KeyToDecayTime = 0;
-
-    self->VolEnv.DelayTime = -12000;
-    self->VolEnv.AttackTime = -12000;
-    self->VolEnv.HoldTime = -12000;
-    self->VolEnv.DecayTime = -12000;
-    self->VolEnv.SustainAttn = 0;
-    self->VolEnv.ReleaseTime = -12000;
-    self->VolEnv.KeyToHoldTime = 0;
-    self->VolEnv.KeyToDecayTime = 0;
-
-    self->Attenuation = 0;
-
-    self->CoarseTuning = 0;
-    self->FineTuning = 0;
-
-    self->LoopMode = AL_NONE;
-
-    self->TuningScale = 100;
-
-    self->ExclusiveClass = 0;
-
-    self->Start = 0;
-    self->End = 0;
-    self->LoopStart = 0;
-    self->LoopEnd = 0;
-    self->SampleRate = 0;
-    self->PitchKey = 0;
-    self->PitchCorrection = 0;
-    self->SampleType = AL_MONO_SOFT;
-    self->Link = NULL;
-
-    InitUIntMap(&self->ModulatorMap, ~0);
-
-    self->id = 0;
-}
-
-static void ALfontsound_Destruct(ALfontsound *self)
-{
-    ALsizei i;
-
-    FreeThunkEntry(self->id);
-    self->id = 0;
-
-    if(self->Buffer)
-        DecrementRef(&self->Buffer->ref);
-    self->Buffer = NULL;
-    if(self->Link)
-        DecrementRef(&self->Link->ref);
-    self->Link = NULL;
-
-    for(i = 0;i < self->ModulatorMap.size;i++)
-    {
-        free(self->ModulatorMap.array[i].value);
-        self->ModulatorMap.array[i].value = NULL;
-    }
-    ResetUIntMap(&self->ModulatorMap);
-}
-
-void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value)
-{
-    ALfontsound *link;
-    ALbuffer *buffer;
-
-    switch(param)
-    {
-        case AL_BUFFER:
-            buffer = value ? LookupBuffer(context->Device, value) : NULL;
-            if(value && !buffer)
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            else if(buffer)
-            {
-                /* Buffer must have a non-0 length, and must be mono. */
-                if(buffer->SampleLen <= 0 || buffer->FmtChannels != FmtMono)
-                    SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            }
-
-            if(buffer) IncrementRef(&buffer->ref);
-            if((buffer=ExchangePtr((XchgPtr*)&self->Buffer, buffer)) != NULL)
-                DecrementRef(&buffer->ref);
-            break;
-
-        case AL_MOD_LFO_TO_PITCH_SOFT:
-            self->ModLfoToPitch = value;
-            break;
-
-        case AL_VIBRATO_LFO_TO_PITCH_SOFT:
-            self->VibratoLfoToPitch = value;
-            break;
-
-        case AL_MOD_ENV_TO_PITCH_SOFT:
-            self->ModEnvToPitch = value;
-            break;
-
-        case AL_FILTER_CUTOFF_SOFT:
-            self->FilterCutoff = value;
-            break;
-
-        case AL_FILTER_RESONANCE_SOFT:
-            if(!(value >= 0))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->FilterQ = value;
-            break;
-
-        case AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT:
-            self->ModLfoToFilterCutoff = value;
-            break;
-
-        case AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT:
-            self->ModEnvToFilterCutoff = value;
-            break;
-
-        case AL_MOD_LFO_TO_VOLUME_SOFT:
-            self->ModLfoToVolume = value;
-            break;
-
-        case AL_CHORUS_SEND_SOFT:
-            if(!(value >= 0 && value <= 1000))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->ChorusSend = value;
-            break;
-        case AL_REVERB_SEND_SOFT:
-            if(!(value >= 0 && value <= 1000))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->ReverbSend = value;
-            break;
-
-        case AL_PAN_SOFT:
-            self->Pan = value;
-            break;
-
-        case AL_MOD_LFO_DELAY_SOFT:
-            self->ModLfo.Delay = value;
-            break;
-        case AL_MOD_LFO_FREQUENCY_SOFT:
-            self->ModLfo.Frequency = value;
-            break;
-
-        case AL_VIBRATO_LFO_DELAY_SOFT:
-            self->VibratoLfo.Delay = value;
-            break;
-        case AL_VIBRATO_LFO_FREQUENCY_SOFT:
-            self->VibratoLfo.Frequency = value;
-            break;
-
-        case AL_MOD_ENV_DELAYTIME_SOFT:
-            self->ModEnv.DelayTime = value;
-            break;
-        case AL_MOD_ENV_ATTACKTIME_SOFT:
-            self->ModEnv.AttackTime = value;
-            break;
-        case AL_MOD_ENV_HOLDTIME_SOFT:
-            self->ModEnv.HoldTime = value;
-            break;
-        case AL_MOD_ENV_DECAYTIME_SOFT:
-            self->ModEnv.DecayTime = value;
-            break;
-        case AL_MOD_ENV_SUSTAINVOLUME_SOFT:
-            self->ModEnv.SustainAttn = value;
-            break;
-        case AL_MOD_ENV_RELEASETIME_SOFT:
-            self->ModEnv.ReleaseTime = value;
-            break;
-        case AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT:
-            self->ModEnv.KeyToHoldTime = value;
-            break;
-        case AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT:
-            self->ModEnv.KeyToDecayTime = value;
-            break;
-
-        case AL_VOLUME_ENV_DELAYTIME_SOFT:
-            self->VolEnv.DelayTime = value;
-            break;
-        case AL_VOLUME_ENV_ATTACKTIME_SOFT:
-            self->VolEnv.AttackTime = value;
-            break;
-        case AL_VOLUME_ENV_HOLDTIME_SOFT:
-            self->VolEnv.HoldTime = value;
-            break;
-        case AL_VOLUME_ENV_DECAYTIME_SOFT:
-            self->VolEnv.DecayTime = value;
-            break;
-        case AL_VOLUME_ENV_SUSTAINVOLUME_SOFT:
-            self->VolEnv.SustainAttn = value;
-            break;
-        case AL_VOLUME_ENV_RELEASETIME_SOFT:
-            self->VolEnv.ReleaseTime = value;
-            break;
-        case AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT:
-            self->VolEnv.KeyToHoldTime = value;
-            break;
-        case AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT:
-            self->VolEnv.KeyToDecayTime = value;
-            break;
-
-        case AL_ATTENUATION_SOFT:
-            if(!(value >= 0))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->Attenuation = value;
-            break;
-
-        case AL_TUNING_COARSE_SOFT:
-            self->CoarseTuning = value;
-            break;
-        case AL_TUNING_FINE_SOFT:
-            self->FineTuning = value;
-            break;
-
-        case AL_LOOP_MODE_SOFT:
-            if(!(value == AL_NONE || value == AL_LOOP_CONTINUOUS_SOFT ||
-                 value == AL_LOOP_UNTIL_RELEASE_SOFT))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->LoopMode = value;
-            break;
-
-        case AL_TUNING_SCALE_SOFT:
-            self->TuningScale = value;
-            break;
-
-        case AL_EXCLUSIVE_CLASS_SOFT:
-            self->ExclusiveClass = value;
-            break;
-
-        case AL_SAMPLE_START_SOFT:
-            self->Start = value;
-            break;
-
-        case AL_SAMPLE_END_SOFT:
-            self->End = value;
-            break;
-
-        case AL_SAMPLE_LOOP_START_SOFT:
-            self->LoopStart = value;
-            break;
-
-        case AL_SAMPLE_LOOP_END_SOFT:
-            self->LoopEnd = value;
-            break;
-
-        case AL_SAMPLE_RATE_SOFT:
-            if(!(value > 0))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->SampleRate = value;
-            break;
-
-        case AL_BASE_KEY_SOFT:
-            if(!((value >= 0 && value <= 127) || value == 255))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->PitchKey = value;
-            break;
-
-        case AL_KEY_CORRECTION_SOFT:
-            if(!(value >= -99 && value <= 99))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->PitchCorrection = value;
-            break;
-
-        case AL_SAMPLE_TYPE_SOFT:
-            if(!(value == AL_MONO_SOFT || value == AL_RIGHT_SOFT || value == AL_LEFT_SOFT))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            self->SampleType = value;
-            break;
-
-        case AL_FONTSOUND_LINK_SOFT:
-            link = value ? LookupFontsound(context->Device, value) : NULL;
-            if(value && !link)
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-
-            if(link) IncrementRef(&link->ref);
-            if((link=ExchangePtr((XchgPtr*)&self->Link, link)) != NULL)
-                DecrementRef(&link->ref);
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-
-static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage)
-{
-    ALsfmodulator *ret = LookupModulator(self, stage);
-    if(!ret)
-    {
-        static const ALsfmodulator moddef = {
-            { { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT },
-              { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT } },
-            0,
-            AL_LINEAR_SOFT,
-            AL_NONE
-        };
-        ret = malloc(sizeof(ALsfmodulator[4]));
-        ret[0] = moddef;
-        ret[1] = moddef;
-        ret[2] = moddef;
-        ret[3] = moddef;
-        InsertUIntMapEntry(&self->ModulatorMap, stage>>2, ret);
-        ret += stage&3;
-    }
-    return ret;
-}
-
-void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value)
-{
-    ALint srcidx = 0;
-
-    if(ReadRef(&self->ref) != 0)
-        SET_ERROR_AND_RETURN(context, AL_INVALID_OPERATION);
-    switch(param)
-    {
-        case AL_SOURCE1_INPUT_SOFT:
-            srcidx++;
-            /* fall-through */
-        case AL_SOURCE0_INPUT_SOFT:
-            if(!(value == AL_ONE_SOFT || value == AL_NOTEON_VELOCITY_SOFT ||
-                 value == AL_NOTEON_KEY_SOFT || value == AL_KEYPRESSURE_SOFT ||
-                 value == AL_CHANNELPRESSURE_SOFT || value == AL_PITCHBEND_SOFT ||
-                 value == AL_PITCHBEND_SENSITIVITY_SOFT ||
-                 IsValidCtrlInput(value)))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            ALfontsound_getModStage(self, stage)->Source[srcidx].Input = value;
-            break;
-
-        case AL_SOURCE1_TYPE_SOFT:
-            srcidx++;
-            /* fall-through */
-        case AL_SOURCE0_TYPE_SOFT:
-            if(!(value == AL_UNORM_SOFT || value == AL_UNORM_REV_SOFT ||
-                 value == AL_SNORM_SOFT || value == AL_SNORM_REV_SOFT))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            ALfontsound_getModStage(self, stage)->Source[srcidx].Type = value;
-            break;
-
-        case AL_SOURCE1_FORM_SOFT:
-            srcidx++;
-            /* fall-through */
-        case AL_SOURCE0_FORM_SOFT:
-            if(!(value == AL_LINEAR_SOFT || value == AL_CONCAVE_SOFT ||
-                 value == AL_CONVEX_SOFT || value == AL_SWITCH_SOFT))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            ALfontsound_getModStage(self, stage)->Source[srcidx].Form = value;
-            break;
-
-        case AL_AMOUNT_SOFT:
-            ALfontsound_getModStage(self, stage)->Amount = value;
-            break;
-
-        case AL_TRANSFORM_OP_SOFT:
-            if(!(value == AL_LINEAR_SOFT || value == AL_ABSOLUTE_SOFT))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            ALfontsound_getModStage(self, stage)->TransformOp = value;
-            break;
-
-        case AL_DESTINATION_SOFT:
-            if(!(value == AL_MOD_LFO_TO_PITCH_SOFT || value == AL_VIBRATO_LFO_TO_PITCH_SOFT ||
-                 value == AL_MOD_ENV_TO_PITCH_SOFT || value == AL_FILTER_CUTOFF_SOFT ||
-                 value == AL_FILTER_RESONANCE_SOFT || value == AL_MOD_LFO_TO_FILTER_CUTOFF_SOFT ||
-                 value == AL_MOD_ENV_TO_FILTER_CUTOFF_SOFT || value == AL_MOD_LFO_TO_VOLUME_SOFT ||
-                 value == AL_CHORUS_SEND_SOFT || value == AL_REVERB_SEND_SOFT || value == AL_PAN_SOFT ||
-                 value == AL_MOD_LFO_DELAY_SOFT || value == AL_MOD_LFO_FREQUENCY_SOFT ||
-                 value == AL_VIBRATO_LFO_DELAY_SOFT || value == AL_VIBRATO_LFO_FREQUENCY_SOFT ||
-                 value == AL_MOD_ENV_DELAYTIME_SOFT || value == AL_MOD_ENV_ATTACKTIME_SOFT ||
-                 value == AL_MOD_ENV_HOLDTIME_SOFT || value == AL_MOD_ENV_DECAYTIME_SOFT ||
-                 value == AL_MOD_ENV_SUSTAINVOLUME_SOFT || value == AL_MOD_ENV_RELEASETIME_SOFT ||
-                 value == AL_MOD_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_MOD_ENV_KEY_TO_DECAYTIME_SOFT ||
-                 value == AL_VOLUME_ENV_DELAYTIME_SOFT || value == AL_VOLUME_ENV_ATTACKTIME_SOFT ||
-                 value == AL_VOLUME_ENV_HOLDTIME_SOFT || value == AL_VOLUME_ENV_DECAYTIME_SOFT ||
-                 value == AL_VOLUME_ENV_SUSTAINVOLUME_SOFT || value == AL_VOLUME_ENV_RELEASETIME_SOFT ||
-                 value == AL_VOLUME_ENV_KEY_TO_HOLDTIME_SOFT || value == AL_VOLUME_ENV_KEY_TO_DECAYTIME_SOFT ||
-                 value == AL_ATTENUATION_SOFT || value == AL_TUNING_COARSE_SOFT ||
-                 value == AL_TUNING_FINE_SOFT || value == AL_TUNING_SCALE_SOFT))
-                SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE);
-            ALfontsound_getModStage(self, stage)->Dest = value;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-
-static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values)
-{
-    ALsfmodulator *mod = LookupModulator(self, stage);
-    ALint srcidx = 0;
-
-    switch(param)
-    {
-        case AL_SOURCE1_INPUT_SOFT:
-            srcidx++;
-            /* fall-through */
-        case AL_SOURCE0_INPUT_SOFT:
-            values[0] = mod ? mod->Source[srcidx].Input : AL_ONE_SOFT;
-            break;
-
-        case AL_SOURCE1_TYPE_SOFT:
-            srcidx++;
-            /* fall-through */
-        case AL_SOURCE0_TYPE_SOFT:
-            values[0] = mod ? mod->Source[srcidx].Type : AL_UNORM_SOFT;
-            break;
-
-        case AL_SOURCE1_FORM_SOFT:
-            srcidx++;
-            /* fall-through */
-        case AL_SOURCE0_FORM_SOFT:
-            values[0] = mod ? mod->Source[srcidx].Form : AL_LINEAR_SOFT;
-            break;
-
-        case AL_AMOUNT_SOFT:
-            values[0] = mod ? mod->Amount : 0;
-            break;
-
-        case AL_TRANSFORM_OP_SOFT:
-            values[0] = mod ? mod->TransformOp : AL_LINEAR_SOFT;
-            break;
-
-        case AL_DESTINATION_SOFT:
-            values[0] = mod ? mod->Dest : AL_NONE;
-            break;
-
-        default:
-            SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM);
-    }
-}
-
-
-/* ReleaseALFontsounds
- *
- * Called to destroy any fontsounds that still exist on the device
- */
-void ReleaseALFontsounds(ALCdevice *device)
-{
-    ALsizei i;
-    for(i = 0;i < device->FontsoundMap.size;i++)
-    {
-        ALfontsound *temp = device->FontsoundMap.array[i].value;
-        device->FontsoundMap.array[i].value = NULL;
-
-        ALfontsound_Destruct(temp);
-
-        memset(temp, 0, sizeof(*temp));
-        free(temp);
-    }
-}

+ 0 - 217
love/src/jni/openal-soft-1.17.0/OpenAL32/alMidi.c

@@ -1,217 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-
-#include "alMain.h"
-#include "alMidi.h"
-#include "alError.h"
-#include "alThunk.h"
-#include "evtqueue.h"
-#include "rwlock.h"
-#include "alu.h"
-
-#include "midi/base.h"
-
-
-MidiSynth *SynthCreate(ALCdevice *device)
-{
-    MidiSynth *synth = NULL;
-    if(!synth) synth = SSynth_create(device);
-    if(!synth) synth = FSynth_create(device);
-    if(!synth) synth = DSynth_create(device);
-    return synth;
-}
-
-
-AL_API void AL_APIENTRY alMidiSoundfontSOFT(ALuint id)
-{
-    alMidiSoundfontvSOFT(1, &id);
-}
-
-AL_API void AL_APIENTRY alMidiSoundfontvSOFT(ALsizei count, const ALuint *ids)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    MidiSynth *synth;
-    ALenum err;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(count < 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    synth = device->Synth;
-
-    WriteLock(&synth->Lock);
-    if(synth->State == AL_PLAYING || synth->State == AL_PAUSED)
-        alSetError(context, AL_INVALID_OPERATION);
-    else
-    {
-        err = V(synth,selectSoundfonts)(context, count, ids);
-        if(err != AL_NO_ERROR)
-            alSetError(context, err);
-    }
-    WriteUnlock(&synth->Lock);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-AL_API void AL_APIENTRY alMidiEventSOFT(ALuint64SOFT time, ALenum event, ALsizei channel, ALsizei param1, ALsizei param2)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALenum err;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(event == AL_NOTEOFF_SOFT || event == AL_NOTEON_SOFT ||
-         event == AL_KEYPRESSURE_SOFT || event == AL_CONTROLLERCHANGE_SOFT ||
-         event == AL_PROGRAMCHANGE_SOFT || event == AL_CHANNELPRESSURE_SOFT ||
-         event == AL_PITCHBEND_SOFT))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
-    if(!(channel >= 0 && channel <= 15))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    if(!(param1 >= 0 && param1 <= 127))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    if(!(param2 >= 0 && param2 <= 127))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    ALCdevice_Lock(device);
-    err = MidiSynth_insertEvent(device->Synth, time, event|channel, param1, param2);
-    ALCdevice_Unlock(device);
-    if(err != AL_NO_ERROR)
-        alSetError(context, err);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, ALsizei size)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALenum err;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!data || size < 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    ALCdevice_Lock(device);
-    err = MidiSynth_insertSysExEvent(device->Synth, time, data, size);
-    ALCdevice_Unlock(device);
-    if(err != AL_NO_ERROR)
-        alSetError(context, err);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alMidiPlaySOFT(void)
-{
-    ALCcontext *context;
-    MidiSynth *synth;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    synth = context->Device->Synth;
-    WriteLock(&synth->Lock);
-    MidiSynth_setState(synth, AL_PLAYING);
-    WriteUnlock(&synth->Lock);
-
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alMidiPauseSOFT(void)
-{
-    ALCcontext *context;
-    MidiSynth *synth;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    synth = context->Device->Synth;
-    WriteLock(&synth->Lock);
-    MidiSynth_setState(synth, AL_PAUSED);
-    WriteUnlock(&synth->Lock);
-
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alMidiStopSOFT(void)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    MidiSynth *synth;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    synth = device->Synth;
-
-    WriteLock(&synth->Lock);
-    MidiSynth_setState(synth, AL_STOPPED);
-
-    ALCdevice_Lock(device);
-    V0(synth,stop)();
-    ALCdevice_Unlock(device);
-    WriteUnlock(&synth->Lock);
-
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alMidiResetSOFT(void)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    MidiSynth *synth;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    synth = device->Synth;
-
-    WriteLock(&synth->Lock);
-    MidiSynth_setState(synth, AL_INITIAL);
-
-    ALCdevice_Lock(device);
-    V0(synth,reset)();
-    ALCdevice_Unlock(device);
-    WriteUnlock(&synth->Lock);
-
-    ALCcontext_DecRef(context);
-}
-
-
-AL_API void AL_APIENTRY alMidiGainSOFT(ALfloat value)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(value >= 0.0f && isfinite(value)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    V(device->Synth,setGain)(value);
-
-done:
-    ALCcontext_DecRef(context);
-}

+ 0 - 339
love/src/jni/openal-soft-1.17.0/OpenAL32/alPreset.c

@@ -1,339 +0,0 @@
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "alMain.h"
-#include "alMidi.h"
-#include "alError.h"
-#include "alThunk.h"
-
-#include "midi/base.h"
-
-
-extern inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id);
-extern inline struct ALsfpreset *RemovePreset(ALCdevice *device, ALuint id);
-
-static void ALsfpreset_Construct(ALsfpreset *self);
-static void ALsfpreset_Destruct(ALsfpreset *self);
-
-
-AL_API void AL_APIENTRY alGenPresetsSOFT(ALsizei n, ALuint *ids)
-{
-    ALCcontext *context;
-    ALsizei cur = 0;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    for(cur = 0;cur < n;cur++)
-    {
-        ALsfpreset *preset = NewPreset(context);
-        if(!preset)
-        {
-            alDeletePresetsSOFT(cur, ids);
-            break;
-        }
-
-        ids[cur] = preset->id;
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALvoid AL_APIENTRY alDeletePresetsSOFT(ALsizei n, const ALuint *ids)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsfpreset *preset;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    for(i = 0;i < n;i++)
-    {
-        /* Check for valid ID */
-        if((preset=LookupPreset(device, ids[i])) == NULL)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-        if(ReadRef(&preset->ref) != 0)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    }
-
-    for(i = 0;i < n;i++)
-    {
-        if((preset=LookupPreset(device, ids[i])) != NULL)
-            DeletePreset(device, preset);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALboolean AL_APIENTRY alIsPresetSOFT(ALuint id)
-{
-    ALCcontext *context;
-    ALboolean ret;
-
-    context = GetContextRef();
-    if(!context) return AL_FALSE;
-
-    ret = LookupPreset(context->Device, id) ? AL_TRUE : AL_FALSE;
-
-    ALCcontext_DecRef(context);
-
-    return ret;
-}
-
-AL_API void AL_APIENTRY alPresetiSOFT(ALuint id, ALenum param, ALint value)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsfpreset *preset;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if((preset=LookupPreset(device, id)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(ReadRef(&preset->ref) != 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    switch(param)
-    {
-        case AL_MIDI_PRESET_SOFT:
-            if(!(value >= 0 && value <= 127))
-                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-            preset->Preset = value;
-            break;
-
-        case AL_MIDI_BANK_SOFT:
-            if(!(value >= 0 && value <= 128))
-                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-            preset->Bank = value;
-            break;
-
-        default:
-            SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alPresetivSOFT(ALuint id, ALenum param, const ALint *values)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsfpreset *preset;
-
-    switch(param)
-    {
-        case AL_MIDI_PRESET_SOFT:
-        case AL_MIDI_BANK_SOFT:
-            alPresetiSOFT(id, param, values[0]);
-            return;
-    }
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if((preset=LookupPreset(device, id)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(ReadRef(&preset->ref) != 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    switch(param)
-    {
-        default:
-            SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alGetPresetivSOFT(ALuint id, ALenum param, ALint *values)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsfpreset *preset;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if((preset=LookupPreset(device, id)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    switch(param)
-    {
-        case AL_MIDI_PRESET_SOFT:
-            values[0] = preset->Preset;
-            break;
-
-        case AL_MIDI_BANK_SOFT:
-            values[0] = preset->Bank;
-            break;
-
-        case AL_FONTSOUNDS_SIZE_SOFT:
-            values[0] = preset->NumSounds;
-            break;
-
-        case AL_FONTSOUNDS_SOFT:
-            for(i = 0;i < preset->NumSounds;i++)
-                values[i] = preset->Sounds[i]->id;
-            break;
-
-        default:
-            SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const ALuint *fsids)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsfpreset *preset;
-    ALfontsound **sounds;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(!(preset=LookupPreset(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(count < 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    if(ReadRef(&preset->ref) != 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-
-    if(count == 0)
-        sounds = NULL;
-    else
-    {
-        sounds = calloc(count, sizeof(sounds[0]));
-        if(!sounds)
-            SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
-
-        for(i = 0;i < count;i++)
-        {
-            if(!(sounds[i]=LookupFontsound(device, fsids[i])))
-            {
-                free(sounds);
-                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-            }
-        }
-    }
-
-    for(i = 0;i < count;i++)
-        IncrementRef(&sounds[i]->ref);
-
-    sounds = ExchangePtr((XchgPtr*)&preset->Sounds, sounds);
-    count = ExchangeInt(&preset->NumSounds, count);
-
-    for(i = 0;i < count;i++)
-        DecrementRef(&sounds[i]->ref);
-    free(sounds);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-ALsfpreset *NewPreset(ALCcontext *context)
-{
-    ALCdevice *device = context->Device;
-    ALsfpreset *preset;
-    ALenum err;
-
-    preset = calloc(1, sizeof(*preset));
-    if(!preset)
-        SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL);
-    ALsfpreset_Construct(preset);
-
-    err = NewThunkEntry(&preset->id);
-    if(err == AL_NO_ERROR)
-        err = InsertUIntMapEntry(&device->PresetMap, preset->id, preset);
-    if(err != AL_NO_ERROR)
-    {
-        ALsfpreset_Destruct(preset);
-        memset(preset, 0, sizeof(*preset));
-        free(preset);
-
-        SET_ERROR_AND_RETURN_VALUE(context, err, NULL);
-    }
-
-    return preset;
-}
-
-void DeletePreset(ALCdevice *device, ALsfpreset *preset)
-{
-    RemovePreset(device, preset->id);
-
-    ALsfpreset_Destruct(preset);
-    memset(preset, 0, sizeof(*preset));
-    free(preset);
-}
-
-
-static void ALsfpreset_Construct(ALsfpreset *self)
-{
-    InitRef(&self->ref, 0);
-
-    self->Preset = 0;
-    self->Bank = 0;
-
-    self->Sounds = NULL;
-    self->NumSounds = 0;
-
-    self->id = 0;
-}
-
-static void ALsfpreset_Destruct(ALsfpreset *self)
-{
-    ALsizei i;
-
-    FreeThunkEntry(self->id);
-    self->id = 0;
-
-    for(i = 0;i < self->NumSounds;i++)
-        DecrementRef(&self->Sounds[i]->ref);
-    free(self->Sounds);
-    self->Sounds = NULL;
-    self->NumSounds = 0;
-}
-
-
-/* ReleaseALPresets
- *
- * Called to destroy any presets that still exist on the device
- */
-void ReleaseALPresets(ALCdevice *device)
-{
-    ALsizei i;
-    for(i = 0;i < device->PresetMap.size;i++)
-    {
-        ALsfpreset *temp = device->PresetMap.array[i].value;
-        device->PresetMap.array[i].value = NULL;
-
-        ALsfpreset_Destruct(temp);
-
-        memset(temp, 0, sizeof(*temp));
-        free(temp);
-    }
-}

+ 0 - 454
love/src/jni/openal-soft-1.17.0/OpenAL32/alSoundfont.c

@@ -1,454 +0,0 @@
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-
-#include "alMain.h"
-#include "alMidi.h"
-#include "alThunk.h"
-#include "alError.h"
-#include <alBuffer.h>
-
-#include "midi/base.h"
-
-
-extern inline struct ALsoundfont *LookupSfont(ALCdevice *device, ALuint id);
-extern inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id);
-
-static void ALsoundfont_Construct(ALsoundfont *self);
-static void ALsoundfont_Destruct(ALsoundfont *self);
-void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device);
-ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context);
-static size_t ALsoundfont_read(ALvoid *buf, size_t bytes, ALvoid *ptr);
-
-
-AL_API void AL_APIENTRY alGenSoundfontsSOFT(ALsizei n, ALuint *ids)
-{
-    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++)
-    {
-        ALsoundfont *sfont = calloc(1, sizeof(ALsoundfont));
-        if(!sfont)
-        {
-            alDeleteSoundfontsSOFT(cur, ids);
-            SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
-        }
-        ALsoundfont_Construct(sfont);
-
-        err = NewThunkEntry(&sfont->id);
-        if(err == AL_NO_ERROR)
-            err = InsertUIntMapEntry(&device->SfontMap, sfont->id, sfont);
-        if(err != AL_NO_ERROR)
-        {
-            ALsoundfont_Destruct(sfont);
-            memset(sfont, 0, sizeof(ALsoundfont));
-            free(sfont);
-
-            alDeleteSoundfontsSOFT(cur, ids);
-            SET_ERROR_AND_GOTO(context, err, done);
-        }
-
-        ids[cur] = sfont->id;
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALvoid AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsoundfont *sfont;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    device = context->Device;
-    for(i = 0;i < n;i++)
-    {
-        /* Check for valid soundfont ID */
-        if(ids[i] == 0)
-        {
-            if(!(sfont=device->DefaultSfont))
-                continue;
-        }
-        else if((sfont=LookupSfont(device, ids[i])) == NULL)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-        if(ReadRef(&sfont->ref) != 0)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    }
-
-    for(i = 0;i < n;i++)
-    {
-        if(ids[i] == 0)
-        {
-            MidiSynth *synth = device->Synth;
-            WriteLock(&synth->Lock);
-            if(device->DefaultSfont != NULL)
-                ALsoundfont_deleteSoundfont(device->DefaultSfont, device);
-            device->DefaultSfont = NULL;
-            WriteUnlock(&synth->Lock);
-            continue;
-        }
-        else if((sfont=RemoveSfont(device, ids[i])) == NULL)
-            continue;
-
-        ALsoundfont_Destruct(sfont);
-
-        memset(sfont, 0, sizeof(*sfont));
-        free(sfont);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(ALuint id)
-{
-    ALCcontext *context;
-    ALboolean ret;
-
-    context = GetContextRef();
-    if(!context) return AL_FALSE;
-
-    ret = ((!id || LookupSfont(context->Device, id)) ?
-           AL_TRUE : AL_FALSE);
-
-    ALCcontext_DecRef(context);
-
-    return ret;
-}
-
-AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *values)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsoundfont *sfont;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(id == 0)
-        sfont = ALsoundfont_getDefSoundfont(context);
-    else if(!(sfont=LookupSfont(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    switch(param)
-    {
-        case AL_PRESETS_SIZE_SOFT:
-            values[0] = sfont->NumPresets;
-            break;
-
-        case AL_PRESETS_SOFT:
-            for(i = 0;i < sfont->NumPresets;i++)
-                values[i] = sfont->Presets[i]->id;
-            break;
-
-        default:
-            SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const ALuint *pids)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsoundfont *sfont;
-    ALsfpreset **presets;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(id == 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    if(!(sfont=LookupSfont(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    if(count < 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    WriteLock(&sfont->Lock);
-    if(ReadRef(&sfont->ref) != 0)
-    {
-        WriteUnlock(&sfont->Lock);
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    }
-
-    if(count == 0)
-        presets = NULL;
-    else
-    {
-        presets = calloc(count, sizeof(presets[0]));
-        if(!presets)
-        {
-            WriteUnlock(&sfont->Lock);
-            SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
-        }
-
-        for(i = 0;i < count;i++)
-        {
-            if(!(presets[i]=LookupPreset(device, pids[i])))
-            {
-                free(presets);
-                WriteUnlock(&sfont->Lock);
-                SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-            }
-        }
-    }
-
-    for(i = 0;i < count;i++)
-        IncrementRef(&presets[i]->ref);
-
-    presets = ExchangePtr((XchgPtr*)&sfont->Presets, presets);
-    count = ExchangeInt(&sfont->NumPresets, count);
-    WriteUnlock(&sfont->Lock);
-
-    for(i = 0;i < count;i++)
-        DecrementRef(&presets[i]->ref);
-    free(presets);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_t,ALvoid*), ALvoid *user)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsoundfont *sfont;
-    Reader reader;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-    if(id == 0)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    if(!(sfont=LookupSfont(device, id)))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-
-    WriteLock(&sfont->Lock);
-    if(ReadRef(&sfont->ref) != 0)
-    {
-        WriteUnlock(&sfont->Lock);
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    }
-    if(sfont->NumPresets > 0)
-    {
-        WriteUnlock(&sfont->Lock);
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    }
-
-    reader.cb = cb;
-    reader.ptr = user;
-    reader.error = 0;
-    loadSf2(&reader, sfont, context);
-    WriteUnlock(&sfont->Lock);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-static void ALsoundfont_Construct(ALsoundfont *self)
-{
-    InitRef(&self->ref, 0);
-
-    self->Presets = NULL;
-    self->NumPresets = 0;
-
-    RWLockInit(&self->Lock);
-
-    self->id = 0;
-}
-
-static void ALsoundfont_Destruct(ALsoundfont *self)
-{
-    ALsizei i;
-
-    FreeThunkEntry(self->id);
-    self->id = 0;
-
-    for(i = 0;i < self->NumPresets;i++)
-    {
-        DecrementRef(&self->Presets[i]->ref);
-        self->Presets[i] = NULL;
-    }
-    free(self->Presets);
-    self->Presets = NULL;
-    self->NumPresets = 0;
-}
-
-ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context)
-{
-    ALCdevice *device = context->Device;
-    al_string fname = AL_STRING_INIT_STATIC();
-    const char *namelist;
-
-    if(device->DefaultSfont)
-        return device->DefaultSfont;
-
-    device->DefaultSfont = calloc(1, sizeof(device->DefaultSfont[0]));
-    ALsoundfont_Construct(device->DefaultSfont);
-
-    namelist = getenv("ALSOFT_SOUNDFONT");
-    if(!namelist || !namelist[0])
-        ConfigValueStr("midi", "soundfont", &namelist);
-    while(namelist && namelist[0])
-    {
-        const char *next, *end;
-        FILE *f;
-
-        while(*namelist && (isspace(*namelist) || *namelist == ','))
-            namelist++;
-        if(!*namelist)
-            break;
-        next = strchr(namelist, ',');
-        end = next ? next++ : (namelist+strlen(namelist));
-        while(--end != namelist && isspace(*end)) {
-        }
-        if(end == namelist)
-            continue;
-        al_string_append_range(&fname, namelist, end+1);
-        namelist = next;
-
-        f = OpenDataFile(al_string_get_cstr(fname), "openal/soundfonts");
-        if(f == NULL)
-            ERR("Failed to open %s\n", al_string_get_cstr(fname));
-        else
-        {
-            Reader reader;
-            reader.cb = ALsoundfont_read;
-            reader.ptr = f;
-            reader.error = 0;
-            TRACE("Loading %s\n", al_string_get_cstr(fname));
-            loadSf2(&reader, device->DefaultSfont, context);
-            fclose(f);
-        }
-
-        al_string_clear(&fname);
-    }
-    AL_STRING_DEINIT(fname);
-
-    return device->DefaultSfont;
-}
-
-void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device)
-{
-    ALsfpreset **presets;
-    ALsizei num_presets;
-    VECTOR(ALbuffer*) buffers;
-    ALsizei i;
-
-    VECTOR_INIT(buffers);
-    presets = ExchangePtr((XchgPtr*)&self->Presets, NULL);
-    num_presets = ExchangeInt(&self->NumPresets, 0);
-
-    for(i = 0;i < num_presets;i++)
-    {
-        ALsfpreset *preset = presets[i];
-        ALfontsound **sounds;
-        ALsizei num_sounds;
-        ALboolean deleting;
-        ALsizei j;
-
-        sounds = ExchangePtr((XchgPtr*)&preset->Sounds, NULL);
-        num_sounds = ExchangeInt(&preset->NumSounds, 0);
-
-        DeletePreset(device, preset);
-        preset = NULL;
-
-        for(j = 0;j < num_sounds;j++)
-            DecrementRef(&sounds[j]->ref);
-        /* Some fontsounds may not be immediately deletable because they're
-         * linked to another fontsound. When those fontsounds are deleted
-         * they should become deletable, so use a loop until all fontsounds
-         * are deleted. */
-        do {
-            deleting = AL_FALSE;
-            for(j = 0;j < num_sounds;j++)
-            {
-                if(sounds[j] && ReadRef(&sounds[j]->ref) == 0)
-                {
-                    deleting = AL_TRUE;
-                    if(sounds[j]->Buffer)
-                    {
-                        ALbuffer *buffer = sounds[j]->Buffer;
-                        ALbuffer **iter;
-
-#define MATCH_BUFFER(_i) (buffer == *(_i))
-                        VECTOR_FIND_IF(iter, ALbuffer*, buffers, MATCH_BUFFER);
-                        if(iter == VECTOR_ITER_END(buffers))
-                            VECTOR_PUSH_BACK(buffers, buffer);
-#undef MATCH_BUFFER
-                    }
-                    DeleteFontsound(device, sounds[j]);
-                    sounds[j] = NULL;
-                }
-            }
-        } while(deleting);
-        free(sounds);
-    }
-
-    ALsoundfont_Destruct(self);
-    free(self);
-
-#define DELETE_BUFFER(iter) do {           \
-    assert(ReadRef(&(*(iter))->ref) == 0); \
-    DeleteBuffer(device, *(iter));         \
-} while(0)
-    VECTOR_FOR_EACH(ALbuffer*, buffers, DELETE_BUFFER);
-    VECTOR_DEINIT(buffers);
-#undef DELETE_BUFFER
-}
-
-
-static size_t ALsoundfont_read(ALvoid *buf, size_t bytes, ALvoid *ptr)
-{
-    return fread(buf, 1, bytes, (FILE*)ptr);
-}
-
-
-/* ReleaseALSoundfonts
- *
- * Called to destroy any soundfonts that still exist on the device
- */
-void ReleaseALSoundfonts(ALCdevice *device)
-{
-    ALsizei i;
-    for(i = 0;i < device->SfontMap.size;i++)
-    {
-        ALsoundfont *temp = device->SfontMap.array[i].value;
-        device->SfontMap.array[i].value = NULL;
-
-        ALsoundfont_Destruct(temp);
-
-        memset(temp, 0, sizeof(*temp));
-        free(temp);
-    }
-}

+ 0 - 2912
love/src/jni/openal-soft-1.17.0/OpenAL32/alSource.c

@@ -1,2912 +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., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
- * Or go to http://www.gnu.org/copyleft/lgpl.html
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <math.h>
-#include <float.h>
-
-#include "AL/al.h"
-#include "AL/alc.h"
-#include "alMain.h"
-#include "alError.h"
-#include "alSource.h"
-#include "alBuffer.h"
-#include "alThunk.h"
-#include "alAuxEffectSlot.h"
-
-#include "threads.h"
-
-
-enum Resampler DefaultResampler = LinearResampler;
-const ALsizei ResamplerPadding[ResamplerMax] = {
-    0, /* Point */
-    1, /* Linear */
-    2, /* Cubic */
-};
-const ALsizei ResamplerPrePadding[ResamplerMax] = {
-    0, /* Point */
-    0, /* Linear */
-    1, /* Cubic */
-};
-
-
-extern inline struct ALsource *LookupSource(ALCcontext *context, ALuint id);
-extern inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id);
-
-static ALvoid InitSourceParams(ALsource *Source);
-static ALint64 GetSourceOffset(const ALsource *Source);
-static ALdouble GetSourceSecOffset(const ALsource *Source);
-static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offsets, ALdouble updateLen);
-static ALint GetSampleOffset(ALsource *Source);
-
-typedef enum SrcFloatProp {
-    sfPitch = AL_PITCH,
-    sfGain = AL_GAIN,
-    sfMinGain = AL_MIN_GAIN,
-    sfMaxGain = AL_MAX_GAIN,
-    sfMaxDistance = AL_MAX_DISTANCE,
-    sfRolloffFactor = AL_ROLLOFF_FACTOR,
-    sfDopplerFactor = AL_DOPPLER_FACTOR,
-    sfConeOuterGain = AL_CONE_OUTER_GAIN,
-    sfSecOffset = AL_SEC_OFFSET,
-    sfSampleOffset = AL_SAMPLE_OFFSET,
-    sfByteOffset = AL_BYTE_OFFSET,
-    sfConeInnerAngle = AL_CONE_INNER_ANGLE,
-    sfConeOuterAngle = AL_CONE_OUTER_ANGLE,
-    sfRefDistance = AL_REFERENCE_DISTANCE,
-
-    sfPosition = AL_POSITION,
-    sfVelocity = AL_VELOCITY,
-    sfDirection = AL_DIRECTION,
-
-    sfSourceRelative = AL_SOURCE_RELATIVE,
-    sfLooping = AL_LOOPING,
-    sfBuffer = AL_BUFFER,
-    sfSourceState = AL_SOURCE_STATE,
-    sfBuffersQueued = AL_BUFFERS_QUEUED,
-    sfBuffersProcessed = AL_BUFFERS_PROCESSED,
-    sfSourceType = AL_SOURCE_TYPE,
-
-    /* ALC_EXT_EFX */
-    sfConeOuterGainHF = AL_CONE_OUTER_GAINHF,
-    sfAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR,
-    sfRoomRolloffFactor =  AL_ROOM_ROLLOFF_FACTOR,
-    sfDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
-    sfAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
-    sfAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
-
-    /* AL_SOFT_direct_channels */
-    sfDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
-
-    /* AL_EXT_source_distance_model */
-    sfDistanceModel = AL_DISTANCE_MODEL,
-
-    sfSecLength = AL_SEC_LENGTH_SOFT,
-
-    /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
-    sfSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
-    sfByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
-
-    /* AL_SOFT_source_latency */
-    sfSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT,
-} SrcFloatProp;
-
-typedef enum SrcIntProp {
-    siMaxDistance = AL_MAX_DISTANCE,
-    siRolloffFactor = AL_ROLLOFF_FACTOR,
-    siRefDistance = AL_REFERENCE_DISTANCE,
-    siSourceRelative = AL_SOURCE_RELATIVE,
-    siConeInnerAngle = AL_CONE_INNER_ANGLE,
-    siConeOuterAngle = AL_CONE_OUTER_ANGLE,
-    siLooping = AL_LOOPING,
-    siBuffer = AL_BUFFER,
-    siSourceState = AL_SOURCE_STATE,
-    siBuffersQueued = AL_BUFFERS_QUEUED,
-    siBuffersProcessed = AL_BUFFERS_PROCESSED,
-    siSourceType = AL_SOURCE_TYPE,
-    siSecOffset = AL_SEC_OFFSET,
-    siSampleOffset = AL_SAMPLE_OFFSET,
-    siByteOffset = AL_BYTE_OFFSET,
-    siDopplerFactor = AL_DOPPLER_FACTOR,
-    siPosition = AL_POSITION,
-    siVelocity = AL_VELOCITY,
-    siDirection = AL_DIRECTION,
-
-    /* ALC_EXT_EFX */
-    siDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO,
-    siAuxSendFilterGainAutio = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO,
-    siAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO,
-    siDirectFilter = AL_DIRECT_FILTER,
-    siAuxSendFilter = AL_AUXILIARY_SEND_FILTER,
-
-    /* AL_SOFT_direct_channels */
-    siDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT,
-
-    /* AL_EXT_source_distance_model */
-    siDistanceModel = AL_DISTANCE_MODEL,
-
-    siByteLength = AL_BYTE_LENGTH_SOFT,
-    siSampleLength = AL_SAMPLE_LENGTH_SOFT,
-
-    /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */
-    siSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT,
-    siByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT,
-
-    /* AL_SOFT_source_latency */
-    siSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT,
-} SrcIntProp;
-
-static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values);
-static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values);
-static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values);
-
-static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values);
-static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values);
-static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values);
-
-static ALint FloatValsByProp(ALenum prop)
-{
-    if(prop != (ALenum)((SrcFloatProp)prop))
-        return 0;
-    switch((SrcFloatProp)prop)
-    {
-        case sfPitch:
-        case sfGain:
-        case sfMinGain:
-        case sfMaxGain:
-        case sfMaxDistance:
-        case sfRolloffFactor:
-        case sfDopplerFactor:
-        case sfConeOuterGain:
-        case sfSecOffset:
-        case sfSampleOffset:
-        case sfByteOffset:
-        case sfConeInnerAngle:
-        case sfConeOuterAngle:
-        case sfRefDistance:
-        case sfConeOuterGainHF:
-        case sfAirAbsorptionFactor:
-        case sfRoomRolloffFactor:
-        case sfDirectFilterGainHFAuto:
-        case sfAuxSendFilterGainAuto:
-        case sfAuxSendFilterGainHFAuto:
-        case sfDirectChannelsSOFT:
-        case sfDistanceModel:
-        case sfSourceRelative:
-        case sfLooping:
-        case sfBuffer:
-        case sfSourceState:
-        case sfBuffersQueued:
-        case sfBuffersProcessed:
-        case sfSourceType:
-        case sfSecLength:
-            return 1;
-
-        case sfSampleRWOffsetsSOFT:
-        case sfByteRWOffsetsSOFT:
-            return 2;
-
-        case sfPosition:
-        case sfVelocity:
-        case sfDirection:
-            return 3;
-
-        case sfSecOffsetLatencySOFT:
-            break; /* Double only */
-    }
-    return 0;
-}
-static ALint DoubleValsByProp(ALenum prop)
-{
-    if(prop != (ALenum)((SrcFloatProp)prop))
-        return 0;
-    switch((SrcFloatProp)prop)
-    {
-        case sfPitch:
-        case sfGain:
-        case sfMinGain:
-        case sfMaxGain:
-        case sfMaxDistance:
-        case sfRolloffFactor:
-        case sfDopplerFactor:
-        case sfConeOuterGain:
-        case sfSecOffset:
-        case sfSampleOffset:
-        case sfByteOffset:
-        case sfConeInnerAngle:
-        case sfConeOuterAngle:
-        case sfRefDistance:
-        case sfConeOuterGainHF:
-        case sfAirAbsorptionFactor:
-        case sfRoomRolloffFactor:
-        case sfDirectFilterGainHFAuto:
-        case sfAuxSendFilterGainAuto:
-        case sfAuxSendFilterGainHFAuto:
-        case sfDirectChannelsSOFT:
-        case sfDistanceModel:
-        case sfSourceRelative:
-        case sfLooping:
-        case sfBuffer:
-        case sfSourceState:
-        case sfBuffersQueued:
-        case sfBuffersProcessed:
-        case sfSourceType:
-        case sfSecLength:
-            return 1;
-
-        case sfSampleRWOffsetsSOFT:
-        case sfByteRWOffsetsSOFT:
-        case sfSecOffsetLatencySOFT:
-            return 2;
-
-        case sfPosition:
-        case sfVelocity:
-        case sfDirection:
-            return 3;
-    }
-    return 0;
-}
-
-static ALint IntValsByProp(ALenum prop)
-{
-    if(prop != (ALenum)((SrcIntProp)prop))
-        return 0;
-    switch((SrcIntProp)prop)
-    {
-        case siMaxDistance:
-        case siRolloffFactor:
-        case siRefDistance:
-        case siSourceRelative:
-        case siConeInnerAngle:
-        case siConeOuterAngle:
-        case siLooping:
-        case siBuffer:
-        case siSourceState:
-        case siBuffersQueued:
-        case siBuffersProcessed:
-        case siSourceType:
-        case siSecOffset:
-        case siSampleOffset:
-        case siByteOffset:
-        case siDopplerFactor:
-        case siDirectFilterGainHFAuto:
-        case siAuxSendFilterGainAutio:
-        case siAuxSendFilterGainHFAuto:
-        case siDirectFilter:
-        case siDirectChannelsSOFT:
-        case siDistanceModel:
-        case siByteLength:
-        case siSampleLength:
-            return 1;
-
-        case siSampleRWOffsetsSOFT:
-        case siByteRWOffsetsSOFT:
-            return 2;
-
-        case siPosition:
-        case siVelocity:
-        case siDirection:
-        case siAuxSendFilter:
-            return 3;
-
-        case siSampleOffsetLatencySOFT:
-            break; /* i64 only */
-    }
-    return 0;
-}
-static ALint Int64ValsByProp(ALenum prop)
-{
-    if(prop != (ALenum)((SrcIntProp)prop))
-        return 0;
-    switch((SrcIntProp)prop)
-    {
-        case siMaxDistance:
-        case siRolloffFactor:
-        case siRefDistance:
-        case siSourceRelative:
-        case siConeInnerAngle:
-        case siConeOuterAngle:
-        case siLooping:
-        case siBuffer:
-        case siSourceState:
-        case siBuffersQueued:
-        case siBuffersProcessed:
-        case siSourceType:
-        case siSecOffset:
-        case siSampleOffset:
-        case siByteOffset:
-        case siDopplerFactor:
-        case siDirectFilterGainHFAuto:
-        case siAuxSendFilterGainAutio:
-        case siAuxSendFilterGainHFAuto:
-        case siDirectFilter:
-        case siDirectChannelsSOFT:
-        case siDistanceModel:
-        case siByteLength:
-        case siSampleLength:
-            return 1;
-
-        case siSampleRWOffsetsSOFT:
-        case siByteRWOffsetsSOFT:
-        case siSampleOffsetLatencySOFT:
-            return 2;
-
-        case siPosition:
-        case siVelocity:
-        case siDirection:
-        case siAuxSendFilter:
-            return 3;
-    }
-    return 0;
-}
-
-
-#define CHECKVAL(x) do {                                                      \
-    if(!(x))                                                                  \
-        SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE);      \
-} while(0)
-
-static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, const ALfloat *values)
-{
-    ALint ival;
-
-    switch(prop)
-    {
-        case AL_PITCH:
-            CHECKVAL(*values >= 0.0f);
-
-            Source->Pitch = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_CONE_INNER_ANGLE:
-            CHECKVAL(*values >= 0.0f && *values <= 360.0f);
-
-            Source->InnerAngle = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_CONE_OUTER_ANGLE:
-            CHECKVAL(*values >= 0.0f && *values <= 360.0f);
-
-            Source->OuterAngle = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_GAIN:
-            CHECKVAL(*values >= 0.0f);
-
-            Source->Gain = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_MAX_DISTANCE:
-            CHECKVAL(*values >= 0.0f);
-
-            Source->MaxDistance = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_ROLLOFF_FACTOR:
-            CHECKVAL(*values >= 0.0f);
-
-            Source->RollOffFactor = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_REFERENCE_DISTANCE:
-            CHECKVAL(*values >= 0.0f);
-
-            Source->RefDistance = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_MIN_GAIN:
-            CHECKVAL(*values >= 0.0f && *values <= 1.0f);
-
-            Source->MinGain = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_MAX_GAIN:
-            CHECKVAL(*values >= 0.0f && *values <= 1.0f);
-
-            Source->MaxGain = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_CONE_OUTER_GAIN:
-            CHECKVAL(*values >= 0.0f && *values <= 1.0f);
-
-            Source->OuterGain = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_CONE_OUTER_GAINHF:
-            CHECKVAL(*values >= 0.0f && *values <= 1.0f);
-
-            Source->OuterGainHF = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_AIR_ABSORPTION_FACTOR:
-            CHECKVAL(*values >= 0.0f && *values <= 10.0f);
-
-            Source->AirAbsorptionFactor = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_ROOM_ROLLOFF_FACTOR:
-            CHECKVAL(*values >= 0.0f && *values <= 10.0f);
-
-            Source->RoomRolloffFactor = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_DOPPLER_FACTOR:
-            CHECKVAL(*values >= 0.0f && *values <= 1.0f);
-
-            Source->DopplerFactor = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_SEC_OFFSET:
-        case AL_SAMPLE_OFFSET:
-        case AL_BYTE_OFFSET:
-            CHECKVAL(*values >= 0.0f);
-
-            LockContext(Context);
-            Source->OffsetType = prop;
-            Source->Offset = *values;
-
-            if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
-               !Context->DeferUpdates)
-            {
-                if(ApplyOffset(Source) == AL_FALSE)
-                {
-                    UnlockContext(Context);
-                    SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE);
-                }
-            }
-            UnlockContext(Context);
-            return AL_TRUE;
-
-
-        case sfSecLength:
-        case AL_SEC_OFFSET_LATENCY_SOFT:
-            /* Query only */
-            SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE);
-
-
-        case AL_POSITION:
-            CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
-
-            LockContext(Context);
-            Source->Position[0] = values[0];
-            Source->Position[1] = values[1];
-            Source->Position[2] = values[2];
-            UnlockContext(Context);
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_VELOCITY:
-            CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
-
-            LockContext(Context);
-            Source->Velocity[0] = values[0];
-            Source->Velocity[1] = values[1];
-            Source->Velocity[2] = values[2];
-            UnlockContext(Context);
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_DIRECTION:
-            CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]));
-
-            LockContext(Context);
-            Source->Orientation[0] = values[0];
-            Source->Orientation[1] = values[1];
-            Source->Orientation[2] = values[2];
-            UnlockContext(Context);
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-
-        case sfSampleRWOffsetsSOFT:
-        case sfByteRWOffsetsSOFT:
-            SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE);
-
-
-        case sfSourceRelative:
-        case sfLooping:
-        case sfSourceState:
-        case sfSourceType:
-        case sfDistanceModel:
-        case sfDirectFilterGainHFAuto:
-        case sfAuxSendFilterGainAuto:
-        case sfAuxSendFilterGainHFAuto:
-        case sfDirectChannelsSOFT:
-            ival = (ALint)values[0];
-            return SetSourceiv(Source, Context, (SrcIntProp)prop, &ival);
-
-        case sfBuffer:
-        case sfBuffersQueued:
-        case sfBuffersProcessed:
-            ival = (ALint)((ALuint)values[0]);
-            return SetSourceiv(Source, Context, (SrcIntProp)prop, &ival);
-    }
-
-    ERR("Unexpected property: 0x%04x\n", prop);
-    SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE);
-}
-
-static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values)
-{
-    ALCdevice *device = Context->Device;
-    ALbuffer  *buffer = NULL;
-    ALfilter  *filter = NULL;
-    ALeffectslot *slot = NULL;
-    ALbufferlistitem *oldlist;
-    ALbufferlistitem *newlist;
-    ALfloat fvals[3];
-
-    switch(prop)
-    {
-        case AL_SOURCE_RELATIVE:
-            CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
-
-            Source->HeadRelative = (ALboolean)*values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_LOOPING:
-            CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
-
-            Source->Looping = (ALboolean)*values;
-            return AL_TRUE;
-
-        case AL_BUFFER:
-            CHECKVAL(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL);
-
-            WriteLock(&Source->queue_lock);
-            if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL))
-            {
-                WriteUnlock(&Source->queue_lock);
-                SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE);
-            }
-
-            if(buffer != NULL)
-            {
-                /* Add the selected buffer to a one-item queue */
-                newlist = malloc(sizeof(ALbufferlistitem));
-                newlist->buffer = buffer;
-                newlist->next = NULL;
-                newlist->prev = NULL;
-                IncrementRef(&buffer->ref);
-
-                /* Source is now Static */
-                Source->SourceType = AL_STATIC;
-
-                ReadLock(&buffer->lock);
-                Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
-                Source->SampleSize  = BytesFromFmt(buffer->FmtType);
-                ReadUnlock(&buffer->lock);
-            }
-            else
-            {
-                /* Source is now Undetermined */
-                Source->SourceType = AL_UNDETERMINED;
-                newlist = NULL;
-            }
-            oldlist = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, newlist);
-            ATOMIC_STORE(&Source->current_buffer, newlist);
-            WriteUnlock(&Source->queue_lock);
-
-            /* Delete all elements in the previous queue */
-            while(oldlist != NULL)
-            {
-                ALbufferlistitem *temp = oldlist;
-                oldlist = temp->next;
-
-                if(temp->buffer)
-                    DecrementRef(&temp->buffer->ref);
-                free(temp);
-            }
-            return AL_TRUE;
-
-        case siSourceState:
-        case siSourceType:
-        case siBuffersQueued:
-        case siBuffersProcessed:
-            /* Query only */
-            SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE);
-
-        case AL_SEC_OFFSET:
-        case AL_SAMPLE_OFFSET:
-        case AL_BYTE_OFFSET:
-            CHECKVAL(*values >= 0);
-
-            LockContext(Context);
-            Source->OffsetType = prop;
-            Source->Offset = *values;
-
-            if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) &&
-                !Context->DeferUpdates)
-            {
-                if(ApplyOffset(Source) == AL_FALSE)
-                {
-                    UnlockContext(Context);
-                    SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE);
-                }
-            }
-            UnlockContext(Context);
-            return AL_TRUE;
-
-
-        case siByteLength:
-        case siSampleLength:
-        case siSampleRWOffsetsSOFT:
-        case siByteRWOffsetsSOFT:
-            /* Query only */
-            SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE);
-
-
-        case AL_DIRECT_FILTER:
-            CHECKVAL(*values == 0 || (filter=LookupFilter(device, *values)) != NULL);
-
-            LockContext(Context);
-            if(!filter)
-            {
-                Source->Direct.Gain = 1.0f;
-                Source->Direct.GainHF = 1.0f;
-                Source->Direct.HFReference = LOWPASSFREQREF;
-                Source->Direct.GainLF = 1.0f;
-                Source->Direct.LFReference = HIGHPASSFREQREF;
-            }
-            else
-            {
-                Source->Direct.Gain = filter->Gain;
-                Source->Direct.GainHF = filter->GainHF;
-                Source->Direct.HFReference = filter->HFReference;
-                Source->Direct.GainLF = filter->GainLF;
-                Source->Direct.LFReference = filter->LFReference;
-            }
-            UnlockContext(Context);
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_DIRECT_FILTER_GAINHF_AUTO:
-            CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
-
-            Source->DryGainHFAuto = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
-            CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
-
-            Source->WetGainAuto = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
-            CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
-
-            Source->WetGainHFAuto = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_DIRECT_CHANNELS_SOFT:
-            CHECKVAL(*values == AL_FALSE || *values == AL_TRUE);
-
-            Source->DirectChannels = *values;
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-        case AL_DISTANCE_MODEL:
-            CHECKVAL(*values == AL_NONE ||
-                     *values == AL_INVERSE_DISTANCE ||
-                     *values == AL_INVERSE_DISTANCE_CLAMPED ||
-                     *values == AL_LINEAR_DISTANCE ||
-                     *values == AL_LINEAR_DISTANCE_CLAMPED ||
-                     *values == AL_EXPONENT_DISTANCE ||
-                     *values == AL_EXPONENT_DISTANCE_CLAMPED);
-
-            Source->DistanceModel = *values;
-            if(Context->SourceDistanceModel)
-                ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-
-        case AL_AUXILIARY_SEND_FILTER:
-            LockContext(Context);
-            if(!((ALuint)values[1] < device->NumAuxSends &&
-                 (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) &&
-                 (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL)))
-            {
-                UnlockContext(Context);
-                SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE);
-            }
-
-            /* Add refcount on the new slot, and release the previous slot */
-            if(slot) IncrementRef(&slot->ref);
-            slot = ExchangePtr((XchgPtr*)&Source->Send[values[1]].Slot, slot);
-            if(slot) DecrementRef(&slot->ref);
-
-            if(!filter)
-            {
-                /* Disable filter */
-                Source->Send[values[1]].Gain = 1.0f;
-                Source->Send[values[1]].GainHF = 1.0f;
-                Source->Send[values[1]].HFReference = LOWPASSFREQREF;
-                Source->Send[values[1]].GainLF = 1.0f;
-                Source->Send[values[1]].LFReference = HIGHPASSFREQREF;
-            }
-            else
-            {
-                Source->Send[values[1]].Gain = filter->Gain;
-                Source->Send[values[1]].GainHF = filter->GainHF;
-                Source->Send[values[1]].HFReference = filter->HFReference;
-                Source->Send[values[1]].GainLF = filter->GainLF;
-                Source->Send[values[1]].LFReference = filter->LFReference;
-            }
-            UnlockContext(Context);
-            ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-            return AL_TRUE;
-
-
-        case AL_MAX_DISTANCE:
-        case AL_ROLLOFF_FACTOR:
-        case AL_CONE_INNER_ANGLE:
-        case AL_CONE_OUTER_ANGLE:
-        case AL_REFERENCE_DISTANCE:
-        case siDopplerFactor:
-            fvals[0] = (ALfloat)*values;
-            return SetSourcefv(Source, Context, (int)prop, fvals);
-
-        case AL_POSITION:
-        case AL_VELOCITY:
-        case AL_DIRECTION:
-            fvals[0] = (ALfloat)values[0];
-            fvals[1] = (ALfloat)values[1];
-            fvals[2] = (ALfloat)values[2];
-            return SetSourcefv(Source, Context, (int)prop, fvals);
-
-        case siSampleOffsetLatencySOFT:
-            /* i64 only */
-            break;
-    }
-
-    ERR("Unexpected property: 0x%04x\n", prop);
-    SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE);
-}
-
-static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values)
-{
-    ALfloat fvals[3];
-    ALint   ivals[3];
-
-    switch(prop)
-    {
-        case siSampleRWOffsetsSOFT:
-        case siByteRWOffsetsSOFT:
-        case siSampleOffsetLatencySOFT:
-            /* Query only */
-            SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE);
-
-
-        /* 1x int */
-        case AL_SOURCE_RELATIVE:
-        case AL_LOOPING:
-        case AL_SOURCE_STATE:
-        case AL_BYTE_OFFSET:
-        case AL_SAMPLE_OFFSET:
-        case siByteLength:
-        case siSampleLength:
-        case siSourceType:
-        case siBuffersQueued:
-        case siBuffersProcessed:
-        case AL_DIRECT_FILTER_GAINHF_AUTO:
-        case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
-        case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
-        case AL_DIRECT_CHANNELS_SOFT:
-        case AL_DISTANCE_MODEL:
-            CHECKVAL(*values <= INT_MAX && *values >= INT_MIN);
-
-            ivals[0] = (ALint)*values;
-            return SetSourceiv(Source, Context, (int)prop, ivals);
-
-        /* 1x uint */
-        case AL_BUFFER:
-        case AL_DIRECT_FILTER:
-            CHECKVAL(*values <= UINT_MAX && *values >= 0);
-
-            ivals[0] = (ALuint)*values;
-            return SetSourceiv(Source, Context, (int)prop, ivals);
-
-        /* 3x uint */
-        case AL_AUXILIARY_SEND_FILTER:
-            CHECKVAL(values[0] <= UINT_MAX && values[0] >= 0 &&
-                     values[1] <= UINT_MAX && values[1] >= 0 &&
-                     values[2] <= UINT_MAX && values[2] >= 0);
-
-            ivals[0] = (ALuint)values[0];
-            ivals[1] = (ALuint)values[1];
-            ivals[2] = (ALuint)values[2];
-            return SetSourceiv(Source, Context, (int)prop, ivals);
-
-        /* 1x float */
-        case AL_MAX_DISTANCE:
-        case AL_ROLLOFF_FACTOR:
-        case AL_CONE_INNER_ANGLE:
-        case AL_CONE_OUTER_ANGLE:
-        case AL_REFERENCE_DISTANCE:
-        case AL_SEC_OFFSET:
-        case siDopplerFactor:
-            fvals[0] = (ALfloat)*values;
-            return SetSourcefv(Source, Context, (int)prop, fvals);
-
-        /* 3x float */
-        case AL_POSITION:
-        case AL_VELOCITY:
-        case AL_DIRECTION:
-            fvals[0] = (ALfloat)values[0];
-            fvals[1] = (ALfloat)values[1];
-            fvals[2] = (ALfloat)values[2];
-            return SetSourcefv(Source, Context, (int)prop, fvals);
-    }
-
-    ERR("Unexpected property: 0x%04x\n", prop);
-    SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE);
-}
-
-#undef CHECKVAL
-
-
-static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values)
-{
-    ALbufferlistitem *BufferList;
-    ALdouble offsets[2];
-    ALdouble updateLen;
-    ALint ivals[3];
-    ALboolean err;
-
-    switch(prop)
-    {
-        case AL_GAIN:
-            *values = Source->Gain;
-            return AL_TRUE;
-
-        case AL_PITCH:
-            *values = Source->Pitch;
-            return AL_TRUE;
-
-        case AL_MAX_DISTANCE:
-            *values = Source->MaxDistance;
-            return AL_TRUE;
-
-        case AL_ROLLOFF_FACTOR:
-            *values = Source->RollOffFactor;
-            return AL_TRUE;
-
-        case AL_REFERENCE_DISTANCE:
-            *values = Source->RefDistance;
-            return AL_TRUE;
-
-        case AL_CONE_INNER_ANGLE:
-            *values = Source->InnerAngle;
-            return AL_TRUE;
-
-        case AL_CONE_OUTER_ANGLE:
-            *values = Source->OuterAngle;
-            return AL_TRUE;
-
-        case AL_MIN_GAIN:
-            *values = Source->MinGain;
-            return AL_TRUE;
-
-        case AL_MAX_GAIN:
-            *values = Source->MaxGain;
-            return AL_TRUE;
-
-        case AL_CONE_OUTER_GAIN:
-            *values = Source->OuterGain;
-            return AL_TRUE;
-
-        case AL_SEC_OFFSET:
-        case AL_SAMPLE_OFFSET:
-        case AL_BYTE_OFFSET:
-            LockContext(Context);
-            ReadLock(&Source->queue_lock);
-            GetSourceOffsets(Source, prop, offsets, 0.0);
-            ReadUnlock(&Source->queue_lock);
-            UnlockContext(Context);
-            *values = offsets[0];
-            return AL_TRUE;
-
-        case AL_CONE_OUTER_GAINHF:
-            *values = Source->OuterGainHF;
-            return AL_TRUE;
-
-        case AL_AIR_ABSORPTION_FACTOR:
-            *values = Source->AirAbsorptionFactor;
-            return AL_TRUE;
-
-        case AL_ROOM_ROLLOFF_FACTOR:
-            *values = Source->RoomRolloffFactor;
-            return AL_TRUE;
-
-        case AL_DOPPLER_FACTOR:
-            *values = Source->DopplerFactor;
-            return AL_TRUE;
-
-        case sfSecLength:
-            ReadLock(&Source->queue_lock);
-            if(!(BufferList=ATOMIC_LOAD(&Source->queue)))
-                *values = 0;
-            else
-            {
-                ALint length = 0;
-                ALsizei freq = 1;
-                do {
-                    ALbuffer *buffer = BufferList->buffer;
-                    if(buffer && buffer->SampleLen > 0)
-                    {
-                        freq = buffer->Frequency;
-                        length += buffer->SampleLen;
-                    }
-                } while((BufferList=BufferList->next) != NULL);
-                *values = (ALdouble)length / (ALdouble)freq;
-            }
-            ReadUnlock(&Source->queue_lock);
-            return AL_TRUE;
-
-        case AL_SAMPLE_RW_OFFSETS_SOFT:
-        case AL_BYTE_RW_OFFSETS_SOFT:
-            LockContext(Context);
-            ReadLock(&Source->queue_lock);
-            updateLen = (ALdouble)Context->Device->UpdateSize /
-                        Context->Device->Frequency;
-            GetSourceOffsets(Source, prop, values, updateLen);
-            ReadUnlock(&Source->queue_lock);
-            UnlockContext(Context);
-            return AL_TRUE;
-
-        case AL_SEC_OFFSET_LATENCY_SOFT:
-            LockContext(Context);
-            ReadLock(&Source->queue_lock);
-            values[0] = GetSourceSecOffset(Source);
-            ReadUnlock(&Source->queue_lock);
-            values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) /
-                        1000000000.0;
-            UnlockContext(Context);
-            return AL_TRUE;
-
-        case AL_POSITION:
-            LockContext(Context);
-            values[0] = Source->Position[0];
-            values[1] = Source->Position[1];
-            values[2] = Source->Position[2];
-            UnlockContext(Context);
-            return AL_TRUE;
-
-        case AL_VELOCITY:
-            LockContext(Context);
-            values[0] = Source->Velocity[0];
-            values[1] = Source->Velocity[1];
-            values[2] = Source->Velocity[2];
-            UnlockContext(Context);
-            return AL_TRUE;
-
-        case AL_DIRECTION:
-            LockContext(Context);
-            values[0] = Source->Orientation[0];
-            values[1] = Source->Orientation[1];
-            values[2] = Source->Orientation[2];
-            UnlockContext(Context);
-            return AL_TRUE;
-
-        case AL_SOURCE_RELATIVE:
-        case AL_LOOPING:
-        case AL_BUFFER:
-        case AL_SOURCE_STATE:
-        case AL_BUFFERS_QUEUED:
-        case AL_BUFFERS_PROCESSED:
-        case AL_SOURCE_TYPE:
-        case AL_DIRECT_FILTER_GAINHF_AUTO:
-        case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
-        case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
-        case AL_DIRECT_CHANNELS_SOFT:
-        case AL_DISTANCE_MODEL:
-            if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE)
-                *values = (ALdouble)ivals[0];
-            return err;
-    }
-
-    ERR("Unexpected property: 0x%04x\n", prop);
-    SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE);
-}
-
-static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values)
-{
-    ALbufferlistitem *BufferList;
-    ALdouble dvals[3];
-    ALboolean err;
-
-    switch(prop)
-    {
-        case AL_SOURCE_RELATIVE:
-            *values = Source->HeadRelative;
-            return AL_TRUE;
-
-        case AL_LOOPING:
-            *values = Source->Looping;
-            return AL_TRUE;
-
-        case AL_BUFFER:
-            ReadLock(&Source->queue_lock);
-            BufferList = (Source->SourceType == AL_STATIC) ? ATOMIC_LOAD(&Source->queue) :
-                                                             ATOMIC_LOAD(&Source->current_buffer);
-            *values = (BufferList && BufferList->buffer) ? BufferList->buffer->id : 0;
-            ReadUnlock(&Source->queue_lock);
-            return AL_TRUE;
-
-        case AL_SOURCE_STATE:
-            *values = Source->state;
-            return AL_TRUE;
-
-        case siByteLength:
-            ReadLock(&Source->queue_lock);
-            if(!(BufferList=ATOMIC_LOAD(&Source->queue)))
-                *values = 0;
-            else
-            {
-                ALint length = 0;
-                do {
-                    ALbuffer *buffer = BufferList->buffer;
-                    if(buffer && buffer->SampleLen > 0)
-                    {
-                        ALuint byte_align, sample_align;
-                        if(buffer->OriginalType == UserFmtIMA4)
-                        {
-                            ALsizei align = (buffer->OriginalAlign-1)/2 + 4;
-                            byte_align = align * ChannelsFromFmt(buffer->FmtChannels);
-                            sample_align = buffer->OriginalAlign;
-                        }
-                        else if(buffer->OriginalType == UserFmtMSADPCM)
-                        {
-                            ALsizei align = (buffer->OriginalAlign-2)/2 + 7;
-                            byte_align = align * ChannelsFromFmt(buffer->FmtChannels);
-                            sample_align = buffer->OriginalAlign;
-                        }
-                        else
-                        {
-                            ALsizei align = buffer->OriginalAlign;
-                            byte_align = align * ChannelsFromFmt(buffer->FmtChannels);
-                            sample_align = buffer->OriginalAlign;
-                        }
-
-                        length += buffer->SampleLen / sample_align * byte_align;
-                    }
-                } while((BufferList=BufferList->next) != NULL);
-                *values = length;
-            }
-            ReadUnlock(&Source->queue_lock);
-            return AL_TRUE;
-
-        case siSampleLength:
-            ReadLock(&Source->queue_lock);
-            if(!(BufferList=ATOMIC_LOAD(&Source->queue)))
-                *values = 0;
-            else
-            {
-                ALint length = 0;
-                do {
-                    ALbuffer *buffer = BufferList->buffer;
-                    if(buffer) length += buffer->SampleLen;
-                } while((BufferList=BufferList->next) != NULL);
-                *values = length;
-            }
-            ReadUnlock(&Source->queue_lock);
-            return AL_TRUE;
-
-        case AL_BUFFERS_QUEUED:
-            ReadLock(&Source->queue_lock);
-            if(!(BufferList=ATOMIC_LOAD(&Source->queue)))
-                *values = 0;
-            else
-            {
-                ALsizei count = 0;
-                do {
-                    ++count;
-                } while((BufferList=BufferList->next) != NULL);
-                *values = count;
-            }
-            ReadUnlock(&Source->queue_lock);
-            return AL_TRUE;
-
-        case AL_BUFFERS_PROCESSED:
-            ReadLock(&Source->queue_lock);
-            if(Source->Looping || Source->SourceType != AL_STREAMING)
-            {
-                /* Buffers on a looping source are in a perpetual state of
-                 * PENDING, so don't report any as PROCESSED */
-                *values = 0;
-            }
-            else
-            {
-                const ALbufferlistitem *BufferList = ATOMIC_LOAD(&Source->queue);
-                const ALbufferlistitem *Current = ATOMIC_LOAD(&Source->current_buffer);
-                ALsizei played = 0;
-                while(BufferList && BufferList != Current)
-                {
-                    played++;
-                    BufferList = BufferList->next;
-                }
-                *values = played;
-            }
-            ReadUnlock(&Source->queue_lock);
-            return AL_TRUE;
-
-        case AL_SOURCE_TYPE:
-            *values = Source->SourceType;
-            return AL_TRUE;
-
-        case AL_DIRECT_FILTER_GAINHF_AUTO:
-            *values = Source->DryGainHFAuto;
-            return AL_TRUE;
-
-        case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
-            *values = Source->WetGainAuto;
-            return AL_TRUE;
-
-        case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
-            *values = Source->WetGainHFAuto;
-            return AL_TRUE;
-
-        case AL_DIRECT_CHANNELS_SOFT:
-            *values = Source->DirectChannels;
-            return AL_TRUE;
-
-        case AL_DISTANCE_MODEL:
-            *values = Source->DistanceModel;
-            return AL_TRUE;
-
-        case AL_MAX_DISTANCE:
-        case AL_ROLLOFF_FACTOR:
-        case AL_REFERENCE_DISTANCE:
-        case AL_CONE_INNER_ANGLE:
-        case AL_CONE_OUTER_ANGLE:
-        case AL_SEC_OFFSET:
-        case AL_SAMPLE_OFFSET:
-        case AL_BYTE_OFFSET:
-        case AL_DOPPLER_FACTOR:
-            if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE)
-                *values = (ALint)dvals[0];
-            return err;
-
-        case AL_SAMPLE_RW_OFFSETS_SOFT:
-        case AL_BYTE_RW_OFFSETS_SOFT:
-            if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE)
-            {
-                values[0] = (ALint)dvals[0];
-                values[1] = (ALint)dvals[1];
-            }
-            return err;
-
-        case AL_POSITION:
-        case AL_VELOCITY:
-        case AL_DIRECTION:
-            if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE)
-            {
-                values[0] = (ALint)dvals[0];
-                values[1] = (ALint)dvals[1];
-                values[2] = (ALint)dvals[2];
-            }
-            return err;
-
-        case siSampleOffsetLatencySOFT:
-            /* i64 only */
-            break;
-
-        case siDirectFilter:
-        case siAuxSendFilter:
-            /* ??? */
-            break;
-    }
-
-    ERR("Unexpected property: 0x%04x\n", prop);
-    SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE);
-}
-
-static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values)
-{
-    ALdouble dvals[3];
-    ALint ivals[3];
-    ALboolean err;
-
-    switch(prop)
-    {
-        case AL_SAMPLE_OFFSET_LATENCY_SOFT:
-            LockContext(Context);
-            ReadLock(&Source->queue_lock);
-            values[0] = GetSourceOffset(Source);
-            ReadUnlock(&Source->queue_lock);
-            values[1] = ALCdevice_GetLatency(Context->Device);
-            UnlockContext(Context);
-            return AL_TRUE;
-
-        case AL_MAX_DISTANCE:
-        case AL_ROLLOFF_FACTOR:
-        case AL_REFERENCE_DISTANCE:
-        case AL_CONE_INNER_ANGLE:
-        case AL_CONE_OUTER_ANGLE:
-        case AL_SEC_OFFSET:
-        case AL_SAMPLE_OFFSET:
-        case AL_BYTE_OFFSET:
-        case AL_DOPPLER_FACTOR:
-            if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE)
-                *values = (ALint64)dvals[0];
-            return err;
-
-        case AL_SAMPLE_RW_OFFSETS_SOFT:
-        case AL_BYTE_RW_OFFSETS_SOFT:
-            if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE)
-            {
-                values[0] = (ALint64)dvals[0];
-                values[1] = (ALint64)dvals[1];
-            }
-            return err;
-
-        case AL_POSITION:
-        case AL_VELOCITY:
-        case AL_DIRECTION:
-            if((err=GetSourcedv(Source, Context, (int)prop, dvals)) != AL_FALSE)
-            {
-                values[0] = (ALint64)dvals[0];
-                values[1] = (ALint64)dvals[1];
-                values[2] = (ALint64)dvals[2];
-            }
-            return err;
-
-        case AL_SOURCE_RELATIVE:
-        case AL_LOOPING:
-        case AL_SOURCE_STATE:
-        case AL_BUFFERS_QUEUED:
-        case AL_BUFFERS_PROCESSED:
-        case siByteLength:
-        case siSampleLength:
-        case AL_SOURCE_TYPE:
-        case AL_DIRECT_FILTER_GAINHF_AUTO:
-        case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO:
-        case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO:
-        case AL_DIRECT_CHANNELS_SOFT:
-        case AL_DISTANCE_MODEL:
-            if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE)
-                *values = ivals[0];
-            return err;
-
-        case siBuffer:
-        case siDirectFilter:
-            if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE)
-                *values = (ALuint)ivals[0];
-            return err;
-
-        case siAuxSendFilter:
-            if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE)
-            {
-                values[0] = (ALuint)ivals[0];
-                values[1] = (ALuint)ivals[1];
-                values[2] = (ALuint)ivals[2];
-            }
-            return err;
-    }
-
-    ERR("Unexpected property: 0x%04x\n", prop);
-    SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE);
-}
-
-
-AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n, ALuint *sources)
-{
-    ALCcontext *context;
-    ALsizei cur = 0;
-    ALenum err;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    for(cur = 0;cur < n;cur++)
-    {
-        ALsource *source = al_calloc(16, sizeof(ALsource));
-        if(!source)
-        {
-            alDeleteSources(cur, sources);
-            SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
-        }
-        InitSourceParams(source);
-
-        err = NewThunkEntry(&source->id);
-        if(err == AL_NO_ERROR)
-            err = InsertUIntMapEntry(&context->SourceMap, source->id, source);
-        if(err != AL_NO_ERROR)
-        {
-            FreeThunkEntry(source->id);
-            memset(source, 0, sizeof(ALsource));
-            al_free(source);
-
-            alDeleteSources(cur, sources);
-            SET_ERROR_AND_GOTO(context, err, done);
-        }
-
-        sources[cur] = source->id;
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources)
-{
-    ALCcontext *context;
-    ALbufferlistitem *BufferList;
-    ALsource *Source;
-    ALsizei i, j;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    /* Check that all Sources are valid */
-    for(i = 0;i < n;i++)
-    {
-        if(LookupSource(context, sources[i]) == NULL)
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    }
-    for(i = 0;i < n;i++)
-    {
-        ALactivesource **srclist, **srclistend;
-
-        if((Source=RemoveSource(context, sources[i])) == NULL)
-            continue;
-        FreeThunkEntry(Source->id);
-
-        LockContext(context);
-        srclist = context->ActiveSources;
-        srclistend = srclist + context->ActiveSourceCount;
-        while(srclist != srclistend)
-        {
-            if((*srclist)->Source == Source)
-            {
-                ALactivesource *temp = *(--srclistend);
-                *srclistend = *srclist;
-                *srclist = temp;
-                --(context->ActiveSourceCount);
-                break;
-            }
-            srclist++;
-        }
-        UnlockContext(context);
-
-        BufferList = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, NULL);
-        while(BufferList != NULL)
-        {
-            ALbufferlistitem *next = BufferList->next;
-            if(BufferList->buffer != NULL)
-                DecrementRef(&BufferList->buffer->ref);
-            free(BufferList);
-            BufferList = next;
-        }
-
-        for(j = 0;j < MAX_SENDS;++j)
-        {
-            if(Source->Send[j].Slot)
-                DecrementRef(&Source->Send[j].Slot->ref);
-            Source->Send[j].Slot = NULL;
-        }
-
-        memset(Source, 0, sizeof(*Source));
-        al_free(Source);
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-AL_API ALboolean AL_APIENTRY alIsSource(ALuint source)
-{
-    ALCcontext *context;
-    ALboolean ret;
-
-    context = GetContextRef();
-    if(!context) return AL_FALSE;
-
-    ret = (LookupSource(context, source) ? AL_TRUE : AL_FALSE);
-
-    ALCcontext_DecRef(context);
-
-    return ret;
-}
-
-
-AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(FloatValsByProp(param) == 1))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        SetSourcefv(Source, Context, param, &value);
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(FloatValsByProp(param) == 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALfloat fvals[3] = { value1, value2, value3 };
-        SetSourcefv(Source, Context, param, fvals);
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!values)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(FloatValsByProp(param) > 0))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        SetSourcefv(Source, Context, param, values);
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(DoubleValsByProp(param) == 1))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALfloat fval = (ALfloat)value;
-        SetSourcefv(Source, Context, param, &fval);
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API ALvoid AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(DoubleValsByProp(param) == 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALfloat fvals[3] = { (ALfloat)value1, (ALfloat)value2, (ALfloat)value3 };
-        SetSourcefv(Source, Context, param, fvals);
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API ALvoid AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-    ALint      count;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!values)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!((count=DoubleValsByProp(param)) > 0 && count <= 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALfloat fvals[3];
-        ALint i;
-
-        for(i = 0;i < count;i++)
-            fvals[i] = (ALfloat)values[i];
-        SetSourcefv(Source, Context, param, fvals);
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(IntValsByProp(param) == 1))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        SetSourceiv(Source, Context, param, &value);
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(IntValsByProp(param) == 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALint ivals[3] = { value1, value2, value3 };
-        SetSourceiv(Source, Context, param, ivals);
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!values)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(IntValsByProp(param) > 0))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        SetSourceiv(Source, Context, param, values);
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(Int64ValsByProp(param) == 1))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        SetSourcei64v(Source, Context, param, &value);
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(Int64ValsByProp(param) == 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALint64SOFT i64vals[3] = { value1, value2, value3 };
-        SetSourcei64v(Source, Context, param, i64vals);
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!values)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(Int64ValsByProp(param) > 0))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        SetSourcei64v(Source, Context, param, values);
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!value)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(FloatValsByProp(param) == 1))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALdouble dval;
-        if(GetSourcedv(Source, Context, param, &dval))
-            *value = (ALfloat)dval;
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(value1 && value2 && value3))
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(FloatValsByProp(param) == 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALdouble dvals[3];
-        if(GetSourcedv(Source, Context, param, dvals))
-        {
-            *value1 = (ALfloat)dvals[0];
-            *value2 = (ALfloat)dvals[1];
-            *value3 = (ALfloat)dvals[2];
-        }
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-    ALint      count;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!values)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!((count=FloatValsByProp(param)) > 0 && count <= 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALdouble dvals[3];
-        if(GetSourcedv(Source, Context, param, dvals))
-        {
-            ALint i;
-            for(i = 0;i < count;i++)
-                values[i] = (ALfloat)dvals[i];
-        }
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!value)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(DoubleValsByProp(param) == 1))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        GetSourcedv(Source, Context, param, value);
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(value1 && value2 && value3))
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(DoubleValsByProp(param) == 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALdouble dvals[3];
-        if(GetSourcedv(Source, Context, param, dvals))
-        {
-            *value1 = dvals[0];
-            *value2 = dvals[1];
-            *value3 = dvals[2];
-        }
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!values)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(DoubleValsByProp(param) > 0))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        GetSourcedv(Source, Context, param, values);
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!value)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(IntValsByProp(param) == 1))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        GetSourceiv(Source, Context, param, value);
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(value1 && value2 && value3))
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(IntValsByProp(param) == 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALint ivals[3];
-        if(GetSourceiv(Source, Context, param, ivals))
-        {
-            *value1 = ivals[0];
-            *value2 = ivals[1];
-            *value3 = ivals[2];
-        }
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!values)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(IntValsByProp(param) > 0))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        GetSourceiv(Source, Context, param, values);
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!value)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(Int64ValsByProp(param) == 1))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        GetSourcei64v(Source, Context, param, value);
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!(value1 && value2 && value3))
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(Int64ValsByProp(param) == 3))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-    {
-        ALint64 i64vals[3];
-        if(GetSourcei64v(Source, Context, param, i64vals))
-        {
-            *value1 = i64vals[0];
-            *value2 = i64vals[1];
-            *value3 = i64vals[2];
-        }
-    }
-
-    ALCcontext_DecRef(Context);
-}
-
-AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values)
-{
-    ALCcontext *Context;
-    ALsource   *Source;
-
-    Context = GetContextRef();
-    if(!Context) return;
-
-    if((Source=LookupSource(Context, source)) == NULL)
-        alSetError(Context, AL_INVALID_NAME);
-    else if(!values)
-        alSetError(Context, AL_INVALID_VALUE);
-    else if(!(Int64ValsByProp(param) > 0))
-        alSetError(Context, AL_INVALID_ENUM);
-    else
-        GetSourcei64v(Source, Context, param, values);
-
-    ALCcontext_DecRef(Context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source)
-{
-    alSourcePlayv(1, &source);
-}
-AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources)
-{
-    ALCcontext *context;
-    ALsource *source;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    for(i = 0;i < n;i++)
-    {
-        if(!LookupSource(context, sources[i]))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    }
-
-    LockContext(context);
-    while(n > context->MaxActiveSources-context->ActiveSourceCount)
-    {
-        ALactivesource **temp = NULL;
-        ALsizei newcount;
-
-        newcount = context->MaxActiveSources << 1;
-        if(newcount > 0)
-            temp = realloc(context->ActiveSources,
-                           newcount * sizeof(context->ActiveSources[0]));
-        if(!temp)
-        {
-            UnlockContext(context);
-            SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done);
-        }
-        for(i = context->MaxActiveSources;i < newcount;i++)
-            temp[i] = NULL;
-
-        context->ActiveSources = temp;
-        context->MaxActiveSources = newcount;
-    }
-
-    for(i = 0;i < n;i++)
-    {
-        source = LookupSource(context, sources[i]);
-        if(context->DeferUpdates) source->new_state = AL_PLAYING;
-        else SetSourceState(source, context, AL_PLAYING);
-    }
-    UnlockContext(context);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source)
-{
-    alSourcePausev(1, &source);
-}
-AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources)
-{
-    ALCcontext *context;
-    ALsource *source;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    for(i = 0;i < n;i++)
-    {
-        if(!LookupSource(context, sources[i]))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    }
-
-    LockContext(context);
-    for(i = 0;i < n;i++)
-    {
-        source = LookupSource(context, sources[i]);
-        if(context->DeferUpdates) source->new_state = AL_PAUSED;
-        else SetSourceState(source, context, AL_PAUSED);
-    }
-    UnlockContext(context);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source)
-{
-    alSourceStopv(1, &source);
-}
-AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources)
-{
-    ALCcontext *context;
-    ALsource *source;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    for(i = 0;i < n;i++)
-    {
-        if(!LookupSource(context, sources[i]))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    }
-
-    LockContext(context);
-    for(i = 0;i < n;i++)
-    {
-        source = LookupSource(context, sources[i]);
-        source->new_state = AL_NONE;
-        SetSourceState(source, context, AL_STOPPED);
-    }
-    UnlockContext(context);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source)
-{
-    alSourceRewindv(1, &source);
-}
-AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources)
-{
-    ALCcontext *context;
-    ALsource *source;
-    ALsizei i;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(n >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    for(i = 0;i < n;i++)
-    {
-        if(!LookupSource(context, sources[i]))
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-    }
-
-    LockContext(context);
-    for(i = 0;i < n;i++)
-    {
-        source = LookupSource(context, sources[i]);
-        source->new_state = AL_NONE;
-        SetSourceState(source, context, AL_INITIAL);
-    }
-    UnlockContext(context);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALuint *buffers)
-{
-    ALCdevice *device;
-    ALCcontext *context;
-    ALsource *source;
-    ALsizei i;
-    ALbufferlistitem *BufferListStart;
-    ALbufferlistitem *BufferList;
-    ALbuffer *BufferFmt = NULL;
-
-    if(nb == 0)
-        return;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    device = context->Device;
-
-    if(!(nb >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    if((source=LookupSource(context, src)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-
-    WriteLock(&source->queue_lock);
-    if(source->SourceType == AL_STATIC)
-    {
-        WriteUnlock(&source->queue_lock);
-        /* Can't queue on a Static Source */
-        SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
-    }
-
-    /* Check for a valid Buffer, for its frequency and format */
-    BufferList = ATOMIC_LOAD(&source->queue);
-    while(BufferList)
-    {
-        if(BufferList->buffer)
-        {
-            BufferFmt = BufferList->buffer;
-            break;
-        }
-        BufferList = BufferList->next;
-    }
-
-    BufferListStart = NULL;
-    BufferList = NULL;
-    for(i = 0;i < nb;i++)
-    {
-        ALbuffer *buffer = NULL;
-        if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL)
-        {
-            WriteUnlock(&source->queue_lock);
-            SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, buffer_error);
-        }
-
-        if(!BufferListStart)
-        {
-            BufferListStart = malloc(sizeof(ALbufferlistitem));
-            BufferListStart->buffer = buffer;
-            BufferListStart->next = NULL;
-            BufferListStart->prev = NULL;
-            BufferList = BufferListStart;
-        }
-        else
-        {
-            BufferList->next = malloc(sizeof(ALbufferlistitem));
-            BufferList->next->buffer = buffer;
-            BufferList->next->next = NULL;
-            BufferList->next->prev = BufferList;
-            BufferList = BufferList->next;
-        }
-        if(!buffer) continue;
-
-        /* Hold a read lock on each buffer being queued while checking all
-         * provided buffers. This is done so other threads don't see an extra
-         * reference on some buffers if this operation ends up failing. */
-        ReadLock(&buffer->lock);
-        IncrementRef(&buffer->ref);
-
-        if(BufferFmt == NULL)
-        {
-            BufferFmt = buffer;
-
-            source->NumChannels = ChannelsFromFmt(buffer->FmtChannels);
-            source->SampleSize  = BytesFromFmt(buffer->FmtType);
-        }
-        else if(BufferFmt->Frequency != buffer->Frequency ||
-                BufferFmt->OriginalChannels != buffer->OriginalChannels ||
-                BufferFmt->OriginalType != buffer->OriginalType)
-        {
-            WriteUnlock(&source->queue_lock);
-            SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, buffer_error);
-
-        buffer_error:
-            /* A buffer failed (invalid ID or format), so unlock and release
-             * each buffer we had. */
-            while(BufferList != NULL)
-            {
-                ALbufferlistitem *prev = BufferList->prev;
-                if((buffer=BufferList->buffer) != NULL)
-                {
-                    DecrementRef(&buffer->ref);
-                    ReadUnlock(&buffer->lock);
-                }
-                free(BufferList);
-                BufferList = prev;
-            }
-            goto done;
-        }
-    }
-    /* All buffers good, unlock them now. */
-    while(BufferList != NULL)
-    {
-        ALbuffer *buffer = BufferList->buffer;
-        if(buffer) ReadUnlock(&buffer->lock);
-        BufferList = BufferList->prev;
-    }
-
-    /* Source is now streaming */
-    source->SourceType = AL_STREAMING;
-
-    BufferList = NULL;
-    if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->queue, &BufferList, BufferListStart))
-    {
-        /* Queue head is not NULL, append to the end of the queue */
-        while(BufferList->next != NULL)
-            BufferList = BufferList->next;
-
-        BufferListStart->prev = BufferList;
-        BufferList->next = BufferListStart;
-    }
-    BufferList = NULL;
-    ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->current_buffer, &BufferList, BufferListStart);
-    WriteUnlock(&source->queue_lock);
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint *buffers)
-{
-    ALCcontext *context;
-    ALsource *source;
-    ALbufferlistitem *NewHead;
-    ALbufferlistitem *OldHead;
-    ALbufferlistitem *Current;
-    ALsizei i;
-
-    if(nb == 0)
-        return;
-
-    context = GetContextRef();
-    if(!context) return;
-
-    if(!(nb >= 0))
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-
-    if((source=LookupSource(context, src)) == NULL)
-        SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
-
-    WriteLock(&source->queue_lock);
-    /* Find the new buffer queue head */
-    NewHead = ATOMIC_LOAD(&source->queue);
-    Current = ATOMIC_LOAD(&source->current_buffer);
-    for(i = 0;i < nb && NewHead;i++)
-    {
-        if(NewHead == Current)
-            break;
-        NewHead = NewHead->next;
-    }
-    if(source->Looping || source->SourceType != AL_STREAMING || i != nb)
-    {
-        WriteUnlock(&source->queue_lock);
-        /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */
-        SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
-    }
-
-    /* Swap it, and cut the new head from the old. */
-    OldHead = ATOMIC_EXCHANGE(ALbufferlistitem*, &source->queue, NewHead);
-    if(NewHead)
-    {
-        ALCdevice *device = context->Device;
-        ALbufferlistitem *OldTail = NewHead->prev;
-        uint count;
-
-        /* Cut the new head's link back to the old body. The mixer is robust
-         * enough to handle the link back going away. Once the active mix (if
-         * any) is complete, it's safe to finish cutting the old tail from the
-         * new head. */
-        NewHead->prev = NULL;
-        if(((count=ReadRef(&device->MixCount))&1) != 0)
-        {
-            while(count == ReadRef(&device->MixCount))
-                althrd_yield();
-        }
-        OldTail->next = NULL;
-    }
-    WriteUnlock(&source->queue_lock);
-
-    while(OldHead != NULL)
-    {
-        ALbufferlistitem *next = OldHead->next;
-        ALbuffer *buffer = OldHead->buffer;
-
-        if(!buffer)
-            *(buffers++) = 0;
-        else
-        {
-            *(buffers++) = buffer->id;
-            DecrementRef(&buffer->ref);
-        }
-
-        free(OldHead);
-        OldHead = next;
-    }
-
-done:
-    ALCcontext_DecRef(context);
-}
-
-
-static ALvoid InitSourceParams(ALsource *Source)
-{
-    ALuint i;
-
-    RWLockInit(&Source->queue_lock);
-
-    Source->InnerAngle = 360.0f;
-    Source->OuterAngle = 360.0f;
-    Source->Pitch = 1.0f;
-    Source->Position[0] = 0.0f;
-    Source->Position[1] = 0.0f;
-    Source->Position[2] = 0.0f;
-    Source->Orientation[0] = 0.0f;
-    Source->Orientation[1] = 0.0f;
-    Source->Orientation[2] = 0.0f;
-    Source->Velocity[0] = 0.0f;
-    Source->Velocity[1] = 0.0f;
-    Source->Velocity[2] = 0.0f;
-    Source->RefDistance = 1.0f;
-    Source->MaxDistance = FLT_MAX;
-    Source->RollOffFactor = 1.0f;
-    Source->Looping = AL_FALSE;
-    Source->Gain = 1.0f;
-    Source->MinGain = 0.0f;
-    Source->MaxGain = 1.0f;
-    Source->OuterGain = 0.0f;
-    Source->OuterGainHF = 1.0f;
-
-    Source->DryGainHFAuto = AL_TRUE;
-    Source->WetGainAuto = AL_TRUE;
-    Source->WetGainHFAuto = AL_TRUE;
-    Source->AirAbsorptionFactor = 0.0f;
-    Source->RoomRolloffFactor = 0.0f;
-    Source->DopplerFactor = 1.0f;
-    Source->DirectChannels = AL_FALSE;
-
-    Source->Radius = 0.0f;
-
-    Source->DistanceModel = DefaultDistanceModel;
-
-    Source->Resampler = DefaultResampler;
-
-    Source->state = AL_INITIAL;
-    Source->new_state = AL_NONE;
-    Source->SourceType = AL_UNDETERMINED;
-    Source->Offset = -1.0;
-
-    ATOMIC_INIT(&Source->queue, NULL);
-    ATOMIC_INIT(&Source->current_buffer, NULL);
-
-    Source->Direct.Gain = 1.0f;
-    Source->Direct.GainHF = 1.0f;
-    Source->Direct.HFReference = LOWPASSFREQREF;
-    Source->Direct.GainLF = 1.0f;
-    Source->Direct.LFReference = HIGHPASSFREQREF;
-    for(i = 0;i < MAX_SENDS;i++)
-    {
-        Source->Send[i].Gain = 1.0f;
-        Source->Send[i].GainHF = 1.0f;
-        Source->Send[i].HFReference = LOWPASSFREQREF;
-        Source->Send[i].GainLF = 1.0f;
-        Source->Send[i].LFReference = HIGHPASSFREQREF;
-    }
-
-    ATOMIC_INIT(&Source->NeedsUpdate, AL_TRUE);
-}
-
-
-/* SetSourceState
- *
- * Sets the source's new play state given its current state.
- */
-ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
-{
-    ReadLock(&Source->queue_lock);
-    if(state == AL_PLAYING)
-    {
-        ALCdevice *device = Context->Device;
-        ALbufferlistitem *BufferList;
-        ALactivesource *src = NULL;
-        ALsizei j, k;
-
-        /* Check that there is a queue containing at least one valid, non zero
-         * length Buffer. */
-        BufferList = ATOMIC_LOAD(&Source->queue);
-        while(BufferList)
-        {
-            ALbuffer *buffer;
-            if((buffer=BufferList->buffer) != NULL && buffer->SampleLen > 0)
-                break;
-            BufferList = BufferList->next;
-        }
-
-        if(Source->state != AL_PAUSED)
-        {
-            Source->state = AL_PLAYING;
-            Source->position = 0;
-            Source->position_fraction = 0;
-            ATOMIC_STORE(&Source->current_buffer, BufferList);
-        }
-        else
-            Source->state = AL_PLAYING;
-
-        // Check if an Offset has been set
-        if(Source->Offset >= 0.0)
-            ApplyOffset(Source);
-
-        /* If there's nothing to play, or device is disconnected, go right to
-         * stopped */
-        if(!BufferList || !device->Connected)
-            goto do_stop;
-
-        for(j = 0;j < Context->ActiveSourceCount;j++)
-        {
-            if(Context->ActiveSources[j]->Source == Source)
-            {
-                src = Context->ActiveSources[j];
-                break;
-            }
-        }
-        if(src == NULL)
-        {
-            src = Context->ActiveSources[Context->ActiveSourceCount];
-            if(src == NULL)
-            {
-                src = al_malloc(16, sizeof(src[0]));
-                Context->ActiveSources[Context->ActiveSourceCount] = src;
-            }
-            memset(src, 0, sizeof(*src));
-            Context->ActiveSourceCount++;
-
-            src->Source = Source;
-        }
-        else
-        {
-            ALuint i;
-
-            src->Direct.Moving = AL_FALSE;
-            src->Direct.Counter = 0;
-            for(j = 0;j < MAX_INPUT_CHANNELS;j++)
-            {
-                for(k = 0;k < SRC_HISTORY_LENGTH;k++)
-                    src->Direct.Mix.Hrtf.State[j].History[k] = 0.0f;
-                for(k = 0;k < HRIR_LENGTH;k++)
-                {
-                    src->Direct.Mix.Hrtf.State[j].Values[k][0] = 0.0f;
-                    src->Direct.Mix.Hrtf.State[j].Values[k][1] = 0.0f;
-                }
-            }
-            for(i = 0;i < device->NumAuxSends;i++)
-            {
-                src->Send[i].Counter = 0;
-                src->Send[i].Moving  = AL_FALSE;
-            }
-        }
-
-        if(BufferList->buffer->FmtChannels == FmtMono)
-            src->Update = CalcSourceParams;
-        else
-            src->Update = CalcNonAttnSourceParams;
-
-        ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE);
-    }
-    else if(state == AL_PAUSED)
-    {
-        if(Source->state == AL_PLAYING)
-            Source->state = AL_PAUSED;
-    }
-    else if(state == AL_STOPPED)
-    {
-    do_stop:
-        if(Source->state != AL_INITIAL)
-        {
-            Source->state = AL_STOPPED;
-            ATOMIC_STORE(&Source->current_buffer, NULL);
-        }
-        Source->Offset = -1.0;
-    }
-    else if(state == AL_INITIAL)
-    {
-        if(Source->state != AL_INITIAL)
-        {
-            Source->state = AL_INITIAL;
-            Source->position = 0;
-            Source->position_fraction = 0;
-            ATOMIC_STORE(&Source->current_buffer, ATOMIC_LOAD(&Source->queue));
-        }
-        Source->Offset = -1.0;
-    }
-    ReadUnlock(&Source->queue_lock);
-}
-
-/* GetSourceOffset
- *
- * Gets the current read offset for the given Source, in 32.32 fixed-point
- * samples. The offset is relative to the start of the queue (not the start of
- * the current buffer).
- */
-static ALint64 GetSourceOffset(const ALsource *Source)
-{
-    const ALbufferlistitem *BufferList;
-    const ALbufferlistitem *Current;
-    ALuint64 readPos;
-
-    if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
-        return 0;
-
-    /* NOTE: This is the offset into the *current* buffer, so add the length of
-     * any played buffers */
-    readPos  = (ALuint64)Source->position << 32;
-    readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS);
-    BufferList = ATOMIC_LOAD(&Source->queue);
-    Current = ATOMIC_LOAD(&Source->current_buffer);
-    while(BufferList && BufferList != Current)
-    {
-        if(BufferList->buffer)
-            readPos += (ALuint64)BufferList->buffer->SampleLen << 32;
-        BufferList = BufferList->next;
-    }
-
-    return (ALint64)minu64(readPos, U64(0x7fffffffffffffff));
-}
-
-/* GetSourceSecOffset
- *
- * Gets the current read offset for the given Source, in seconds. The offset is
- * relative to the start of the queue (not the start of the current buffer).
- */
-static ALdouble GetSourceSecOffset(const ALsource *Source)
-{
-    const ALbufferlistitem *BufferList;
-    const ALbufferlistitem *Current;
-    const ALbuffer *Buffer = NULL;
-    ALuint64 readPos;
-
-    if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
-        return 0.0;
-
-    /* NOTE: This is the offset into the *current* buffer, so add the length of
-     * any played buffers */
-    readPos  = (ALuint64)Source->position << FRACTIONBITS;
-    readPos |= (ALuint64)Source->position_fraction;
-    BufferList = ATOMIC_LOAD(&Source->queue);
-    Current = ATOMIC_LOAD(&Source->current_buffer);
-    while(BufferList && BufferList != Current)
-    {
-        const ALbuffer *buffer = BufferList->buffer;
-        if(buffer != NULL)
-        {
-            if(!Buffer) Buffer = buffer;
-            readPos += (ALuint64)buffer->SampleLen << FRACTIONBITS;
-        }
-        BufferList = BufferList->next;
-    }
-
-    while(BufferList && !Buffer)
-    {
-        Buffer = BufferList->buffer;
-        BufferList = BufferList->next;
-    }
-    assert(Buffer != NULL);
-
-    return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency;
-}
-
-/* GetSourceOffsets
- *
- * Gets the current read and write offsets for the given Source, in the
- * appropriate format (Bytes, Samples or Seconds). The offsets are relative to
- * the start of the queue (not the start of the current buffer).
- */
-static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen)
-{
-    const ALbufferlistitem *BufferList;
-    const ALbufferlistitem *Current;
-    const ALbuffer *Buffer = NULL;
-    ALboolean readFin = AL_FALSE;
-    ALuint readPos, writePos;
-    ALuint totalBufferLen;
-
-    if(Source->state != AL_PLAYING && Source->state != AL_PAUSED)
-    {
-        offset[0] = 0.0;
-        offset[1] = 0.0;
-        return;
-    }
-
-    if(updateLen > 0.0 && updateLen < 0.015)
-        updateLen = 0.015;
-
-    /* NOTE: This is the offset into the *current* buffer, so add the length of
-     * any played buffers */
-    totalBufferLen = 0;
-    readPos = Source->position;
-    BufferList = ATOMIC_LOAD(&Source->queue);
-    Current = ATOMIC_LOAD(&Source->current_buffer);
-    while(BufferList != NULL)
-    {
-        const ALbuffer *buffer;
-        readFin = readFin || (BufferList == Current);
-        if((buffer=BufferList->buffer) != NULL)
-        {
-            if(!Buffer) Buffer = buffer;
-            totalBufferLen += buffer->SampleLen;
-            if(!readFin) readPos += buffer->SampleLen;
-        }
-        BufferList = BufferList->next;
-    }
-    assert(Buffer != NULL);
-
-    if(Source->state == AL_PLAYING)
-        writePos = readPos + (ALuint)(updateLen*Buffer->Frequency);
-    else
-        writePos = readPos;
-
-    if(Source->Looping)
-    {
-        readPos %= totalBufferLen;
-        writePos %= totalBufferLen;
-    }
-    else
-    {
-        /* Wrap positions back to 0 */
-        if(readPos >= totalBufferLen)
-            readPos = 0;
-        if(writePos >= totalBufferLen)
-            writePos = 0;
-    }
-
-    switch(name)
-    {
-        case AL_SEC_OFFSET:
-            offset[0] = (ALdouble)readPos / Buffer->Frequency;
-            offset[1] = (ALdouble)writePos / Buffer->Frequency;
-            break;
-
-        case AL_SAMPLE_OFFSET:
-        case AL_SAMPLE_RW_OFFSETS_SOFT:
-            offset[0] = (ALdouble)readPos;
-            offset[1] = (ALdouble)writePos;
-            break;
-
-        case AL_BYTE_OFFSET:
-        case AL_BYTE_RW_OFFSETS_SOFT:
-            if(Buffer->OriginalType == UserFmtIMA4)
-            {
-                ALsizei align = (Buffer->OriginalAlign-1)/2 + 4;
-                ALuint BlockSize = align * ChannelsFromFmt(Buffer->FmtChannels);
-                ALuint FrameBlockSize = Buffer->OriginalAlign;
-
-                /* Round down to nearest ADPCM block */
-                offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
-                if(Source->state != AL_PLAYING)
-                    offset[1] = offset[0];
-                else
-                {
-                    /* Round up to nearest ADPCM block */
-                    offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
-                                           FrameBlockSize * BlockSize);
-                }
-            }
-            else if(Buffer->OriginalType == UserFmtMSADPCM)
-            {
-                ALsizei align = (Buffer->OriginalAlign-2)/2 + 7;
-                ALuint BlockSize = align * ChannelsFromFmt(Buffer->FmtChannels);
-                ALuint FrameBlockSize = Buffer->OriginalAlign;
-
-                /* Round down to nearest ADPCM block */
-                offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize);
-                if(Source->state != AL_PLAYING)
-                    offset[1] = offset[0];
-                else
-                {
-                    /* Round up to nearest ADPCM block */
-                    offset[1] = (ALdouble)((writePos+FrameBlockSize-1) /
-                                           FrameBlockSize * BlockSize);
-                }
-            }
-            else
-            {
-                ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
-                offset[0] = (ALdouble)(readPos * FrameSize);
-                offset[1] = (ALdouble)(writePos * FrameSize);
-            }
-            break;
-    }
-}
-
-
-/* ApplyOffset
- *
- * Apply the stored playback offset to the Source. This function will update
- * the number of buffers "played" given the stored offset.
- */
-ALboolean ApplyOffset(ALsource *Source)
-{
-    ALbufferlistitem *BufferList;
-    const ALbuffer *Buffer;
-    ALint bufferLen, totalBufferLen;
-    ALint offset;
-
-    /* Get sample frame offset */
-    offset = GetSampleOffset(Source);
-    if(offset == -1)
-        return AL_FALSE;
-
-    totalBufferLen = 0;
-    BufferList = ATOMIC_LOAD(&Source->queue);
-    while(BufferList && totalBufferLen <= offset)
-    {
-        Buffer = BufferList->buffer;
-        bufferLen = Buffer ? Buffer->SampleLen : 0;
-
-        if(bufferLen > offset-totalBufferLen)
-        {
-            /* Offset is in this buffer */
-            ATOMIC_STORE(&Source->current_buffer, BufferList);
-
-            Source->position = offset - totalBufferLen;
-            Source->position_fraction = 0;
-            return AL_TRUE;
-        }
-
-        totalBufferLen += bufferLen;
-
-        BufferList = BufferList->next;
-    }
-
-    /* Offset is out of range of the queue */
-    return AL_FALSE;
-}
-
-
-/* GetSampleOffset
- *
- * Returns the sample offset into the Source's queue (from the Sample, Byte or
- * Second offset supplied by the application). This takes into account the fact
- * that the buffer format may have been modifed since.
- */
-static ALint GetSampleOffset(ALsource *Source)
-{
-    const ALbuffer *Buffer = NULL;
-    const ALbufferlistitem *BufferList;
-    ALint Offset = -1;
-
-    /* Find the first valid Buffer in the Queue */
-    BufferList = ATOMIC_LOAD(&Source->queue);
-    while(BufferList)
-    {
-        if(BufferList->buffer)
-        {
-            Buffer = BufferList->buffer;
-            break;
-        }
-        BufferList = BufferList->next;
-    }
-
-    if(!Buffer)
-    {
-        Source->Offset = -1.0;
-        return -1;
-    }
-
-    switch(Source->OffsetType)
-    {
-    case AL_BYTE_OFFSET:
-        /* Determine the ByteOffset (and ensure it is block aligned) */
-        Offset = (ALint)Source->Offset;
-        if(Buffer->OriginalType == UserFmtIMA4)
-        {
-            ALsizei align = (Buffer->OriginalAlign-1)/2 + 4;
-            Offset /= align * ChannelsFromUserFmt(Buffer->OriginalChannels);
-            Offset *= Buffer->OriginalAlign;
-        }
-        else if(Buffer->OriginalType == UserFmtMSADPCM)
-        {
-            ALsizei align = (Buffer->OriginalAlign-2)/2 + 7;
-            Offset /= align * ChannelsFromUserFmt(Buffer->OriginalChannels);
-            Offset *= Buffer->OriginalAlign;
-        }
-        else
-            Offset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType);
-        break;
-
-    case AL_SAMPLE_OFFSET:
-        Offset = (ALint)Source->Offset;
-        break;
-
-    case AL_SEC_OFFSET:
-        Offset = (ALint)(Source->Offset * Buffer->Frequency);
-        break;
-    }
-    Source->Offset = -1.0;
-
-    return Offset;
-}
-
-
-/* ReleaseALSources
- *
- * Destroys all sources in the source map.
- */
-ALvoid ReleaseALSources(ALCcontext *Context)
-{
-    ALbufferlistitem *item;
-    ALsizei pos;
-    ALuint j;
-    for(pos = 0;pos < Context->SourceMap.size;pos++)
-    {
-        ALsource *temp = Context->SourceMap.array[pos].value;
-        Context->SourceMap.array[pos].value = NULL;
-
-        item = ATOMIC_EXCHANGE(ALbufferlistitem*, &temp->queue, NULL);
-        while(item != NULL)
-        {
-            ALbufferlistitem *next = item->next;
-            if(item->buffer != NULL)
-                DecrementRef(&item->buffer->ref);
-            free(item);
-            item = next;
-        }
-
-        for(j = 0;j < MAX_SENDS;++j)
-        {
-            if(temp->Send[j].Slot)
-                DecrementRef(&temp->Send[j].Slot->ref);
-            temp->Send[j].Slot = NULL;
-        }
-
-        FreeThunkEntry(temp->id);
-        memset(temp, 0, sizeof(*temp));
-        al_free(temp);
-    }
-}

+ 0 - 0
love/src/jni/openal-soft-1.17.0/build/.empty


+ 0 - 33
love/src/jni/openal-soft-1.17.0/cmake/FindDSound.cmake

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

+ 0 - 19
love/src/jni/openal-soft-1.17.0/cmake/FindFluidSynth.cmake

@@ -1,19 +0,0 @@
-# - Find fluidsynth
-# Find the native fluidsynth includes and library
-#
-#  FLUIDSYNTH_INCLUDE_DIR - where to find fluidsynth.h
-#  FLUIDSYNTH_LIBRARIES   - List of libraries when using fluidsynth.
-#  FLUIDSYNTH_FOUND       - True if fluidsynth found.
-
-
-FIND_PATH(FLUIDSYNTH_INCLUDE_DIR fluidsynth.h)
-
-FIND_LIBRARY(FLUIDSYNTH_LIBRARIES NAMES fluidsynth )
-MARK_AS_ADVANCED( FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR )
-
-# handle the QUIETLY and REQUIRED arguments and set FLUIDSYNTH_FOUND to TRUE if 
-# all listed variables are TRUE
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(FluidSynth
-                                  REQUIRED_VARS FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR)
-

+ 0 - 380
love/src/jni/openal-soft-1.17.0/cmake/FindSDL_sound.cmake

@@ -1,380 +0,0 @@
-# - Locates the SDL_sound library
-#
-# This module depends on SDL being found and
-# must be called AFTER FindSDL.cmake or FindSDL2.cmake is called.
-#
-# This module defines
-#  SDL_SOUND_INCLUDE_DIR, where to find SDL_sound.h
-#  SDL_SOUND_FOUND, if false, do not try to link to SDL_sound
-#  SDL_SOUND_LIBRARIES, this contains the list of libraries that you need
-#    to link against. This is a read-only variable and is marked INTERNAL.
-#  SDL_SOUND_EXTRAS, this is an optional variable for you to add your own
-#    flags to SDL_SOUND_LIBRARIES. This is prepended to SDL_SOUND_LIBRARIES.
-#    This is available mostly for cases this module failed to anticipate for
-#    and you must add additional flags. This is marked as ADVANCED.
-#  SDL_SOUND_VERSION_STRING, human-readable string containing the version of SDL_sound
-#
-# This module also defines (but you shouldn't need to use directly)
-#   SDL_SOUND_LIBRARY, the name of just the SDL_sound library you would link
-#   against. Use SDL_SOUND_LIBRARIES for you link instructions and not this one.
-# And might define the following as needed
-#   MIKMOD_LIBRARY
-#   MODPLUG_LIBRARY
-#   OGG_LIBRARY
-#   VORBIS_LIBRARY
-#   SMPEG_LIBRARY
-#   FLAC_LIBRARY
-#   SPEEX_LIBRARY
-#
-# Typically, you should not use these variables directly, and you should use
-# SDL_SOUND_LIBRARIES which contains SDL_SOUND_LIBRARY and the other audio libraries
-# (if needed) to successfully compile on your system.
-#
-# Created by Eric Wing.
-# This module is a bit more complicated than the other FindSDL* family modules.
-# The reason is that SDL_sound can be compiled in a large variety of different ways
-# which are independent of platform. SDL_sound may dynamically link against other 3rd
-# party libraries to get additional codec support, such as Ogg Vorbis, SMPEG, ModPlug,
-# MikMod, FLAC, Speex, and potentially others.
-# Under some circumstances which I don't fully understand,
-# there seems to be a requirement
-# that dependent libraries of libraries you use must also be explicitly
-# linked against in order to successfully compile. SDL_sound does not currently
-# have any system in place to know how it was compiled.
-# So this CMake module does the hard work in trying to discover which 3rd party
-# libraries are required for building (if any).
-# This module uses a brute force approach to create a test program that uses SDL_sound,
-# and then tries to build it. If the build fails, it parses the error output for
-# known symbol names to figure out which libraries are needed.
-#
-# Responds to the $SDLDIR and $SDLSOUNDDIR environmental variable that would
-# correspond to the ./configure --prefix=$SDLDIR used in building SDL.
-#
-# On OSX, this will prefer the Framework version (if found) over others.
-# People will have to manually change the cache values of
-# SDL_LIBRARY or SDL2_LIBRARY to override this selection or set the CMake
-# environment CMAKE_INCLUDE_PATH to modify the search paths.
-
-#=============================================================================
-# Copyright 2005-2009 Kitware, Inc.
-# Copyright 2012 Benjamin Eikel
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-#  License text for the above reference.)
-
-set(SDL_SOUND_EXTRAS "" CACHE STRING "SDL_sound extra flags")
-mark_as_advanced(SDL_SOUND_EXTRAS)
-
-# Find SDL_sound.h
-find_path(SDL_SOUND_INCLUDE_DIR SDL_sound.h
-    HINTS
-        ENV SDLSOUNDDIR
-        ENV SDLDIR
-    PATH_SUFFIXES SDL SDL12 SDL11
-)
-
-find_library(SDL_SOUND_LIBRARY
-    NAMES SDL_sound
-    HINTS
-        ENV SDLSOUNDDIR
-        ENV SDLDIR
-)
-
-if(SDL2_FOUND OR SDL_FOUND)
-    if(SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY)
-        # CMake is giving me problems using TRY_COMPILE with the CMAKE_FLAGS
-        # for the :STRING syntax if I have multiple values contained in a
-        # single variable. This is a problem for the SDL2_LIBRARY variable
-        # because it does just that. When I feed this variable to the command,
-        # only the first value gets the appropriate modifier (e.g. -I) and
-        # the rest get dropped.
-        # To get multiple single variables to work, I must separate them with a "\;"
-        # I could go back and modify the FindSDL2.cmake module, but that's kind of painful.
-        # The solution would be to try something like:
-        # set(SDL2_TRY_COMPILE_LIBRARY_LIST "${SDL2_TRY_COMPILE_LIBRARY_LIST}\;${CMAKE_THREAD_LIBS_INIT}")
-        # Instead, it was suggested on the mailing list to write a temporary CMakeLists.txt
-        # with a temporary test project and invoke that with TRY_COMPILE.
-        # See message thread "Figuring out dependencies for a library in order to build"
-        # 2005-07-16
-        #     try_compile(
-        #             MY_RESULT
-        #             ${CMAKE_BINARY_DIR}
-        #             ${PROJECT_SOURCE_DIR}/DetermineSoundLibs.c
-        #             CMAKE_FLAGS
-        #                     -DINCLUDE_DIRECTORIES:STRING=${SDL2_INCLUDE_DIR}\;${SDL_SOUND_INCLUDE_DIR}
-        #                     -DLINK_LIBRARIES:STRING=${SDL_SOUND_LIBRARY}\;${SDL2_LIBRARY}
-        #             OUTPUT_VARIABLE MY_OUTPUT
-        #     )
-
-        # To minimize external dependencies, create a sdlsound test program
-        # which will be used to figure out if additional link dependencies are
-        # required for the link phase.
-        file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/DetermineSoundLibs.c
-            "#include \"SDL_sound.h\"
-            #include \"SDL.h\"
-            int main(int argc, char* argv[])
-            {
-                Sound_AudioInfo desired;
-                Sound_Sample* sample;
-
-                SDL_Init(0);
-                Sound_Init();
-
-                /* This doesn't actually have to work, but Init() is a no-op
-                 * for some of the decoders, so this should force more symbols
-                 * to be pulled in.
-                 */
-                sample = Sound_NewSampleFromFile(argv[1], &desired, 4096);
-
-                Sound_Quit();
-                SDL_Quit();
-                return 0;
-            }"
-        )
-
-        # Calling
-        # target_link_libraries(DetermineSoundLibs "${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY})
-        # causes problems when SDL2_LIBRARY looks like
-        # /Library/Frameworks/SDL2.framework;-framework Cocoa
-        # The ;-framework Cocoa seems to be confusing CMake once the OS X
-        # framework support was added. I was told that breaking up the list
-        # would fix the problem.
-        set(TMP_TRY_LIBS)
-        if(SDL2_FOUND)
-            foreach(lib ${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY})
-                set(TMP_TRY_LIBS "${TMP_TRY_LIBS} \"${lib}\"")
-            endforeach()
-            set(TMP_INCLUDE_DIRS ${SDL2_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR})
-        else()
-            foreach(lib ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY})
-                set(TMP_TRY_LIBS "${TMP_TRY_LIBS} \"${lib}\"")
-            endforeach()
-            set(TMP_INCLUDE_DIRS ${SDL_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR})
-        endif()
-
-        # message("TMP_TRY_LIBS ${TMP_TRY_LIBS}")
-
-        # Write the CMakeLists.txt and test project
-        # Weird, this is still sketchy. If I don't quote the variables
-        # in the TARGET_LINK_LIBRARIES, I seem to loose everything
-        # in the SDL2_LIBRARY string after the "-framework".
-        # But if I quote the stuff in INCLUDE_DIRECTORIES, it doesn't work.
-        file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/CMakeLists.txt
-            "cmake_minimum_required(VERSION 2.8)
-            project(DetermineSoundLibs C)
-            include_directories(${TMP_INCLUDE_DIRS})
-            add_executable(DetermineSoundLibs DetermineSoundLibs.c)
-            target_link_libraries(DetermineSoundLibs ${TMP_TRY_LIBS})"
-        )
-        unset(TMP_INCLUDE_DIRS)
-        unset(TMP_TRY_LIBS)
-
-        try_compile(
-            MY_RESULT
-            ${PROJECT_BINARY_DIR}/CMakeTmp
-            ${PROJECT_BINARY_DIR}/CMakeTmp
-            DetermineSoundLibs
-            OUTPUT_VARIABLE MY_OUTPUT
-        )
-        # message("${MY_RESULT}")
-        # message(${MY_OUTPUT})
-
-        if(NOT MY_RESULT)
-            # I expect that MPGLIB, VOC, WAV, AIFF, and SHN are compiled in statically.
-            # I think Timidity is also compiled in statically.
-            # I've never had to explcitly link against Quicktime, so I'll skip that for now.
-
-            set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY})
-
-            # Find MikMod
-            if("${MY_OUTPUT}" MATCHES "MikMod_")
-                find_library(MIKMOD_LIBRARY
-                    NAMES libmikmod-coreaudio mikmod
-                    PATHS
-                        ENV MIKMODDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(MIKMOD_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MIKMOD_LIBRARY})
-                endif(MIKMOD_LIBRARY)
-            endif("${MY_OUTPUT}" MATCHES "MikMod_")
-
-            # Find ModPlug
-            if("${MY_OUTPUT}" MATCHES "MODPLUG_")
-                find_library(MODPLUG_LIBRARY
-                    NAMES modplug
-                    PATHS
-                        ENV MODPLUGDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(MODPLUG_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MODPLUG_LIBRARY})
-                endif()
-            endif()
-
-            # Find Ogg and Vorbis
-            if("${MY_OUTPUT}" MATCHES "ov_")
-                find_library(VORBIS_LIBRARY
-                    NAMES vorbis Vorbis VORBIS
-                    PATHS
-                        ENV VORBISDIR
-                        ENV OGGDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(VORBIS_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBIS_LIBRARY})
-                endif()
-                find_library(OGG_LIBRARY
-                    NAMES ogg Ogg OGG
-                    PATHS
-                        ENV OGGDIR
-                        ENV VORBISDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(OGG_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY})
-                endif()
-            endif()
-
-            # Find SMPEG
-            if("${MY_OUTPUT}" MATCHES "SMPEG_")
-                find_library(SMPEG_LIBRARY
-                    NAMES smpeg SMPEG Smpeg SMpeg
-                    PATHS
-                        ENV SMPEGDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(SMPEG_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SMPEG_LIBRARY})
-                endif()
-            endif()
-
-
-            # Find FLAC
-            if("${MY_OUTPUT}" MATCHES "FLAC_")
-                find_library(FLAC_LIBRARY
-                    NAMES flac FLAC
-                    PATHS
-                        ENV FLACDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(FLAC_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${FLAC_LIBRARY})
-                endif()
-            endif()
-
-
-            # Hmmm...Speex seems to depend on Ogg. This might be a problem if
-            # the TRY_COMPILE attempt gets blocked at SPEEX before it can pull
-            # in the Ogg symbols. I'm not sure if I should duplicate the ogg stuff
-            # above for here or if two ogg entries will screw up things.
-            if("${MY_OUTPUT}" MATCHES "speex_")
-                find_library(SPEEX_LIBRARY
-                    NAMES speex SPEEX
-                    PATHS
-                        ENV SPEEXDIR
-                        ENV SDLSOUNDDIR
-                        ENV SDLDIR
-                        /sw
-                        /opt/local
-                        /opt/csw
-                        /opt
-                    PATH_SUFFIXES lib
-                )
-                if(SPEEX_LIBRARY)
-                    set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SPEEX_LIBRARY})
-                endif()
-
-                # Find OGG (needed for Speex)
-                # We might have already found Ogg for Vorbis, so skip it if so.
-                if(NOT OGG_LIBRARY)
-                    find_library(OGG_LIBRARY
-                        NAMES ogg Ogg OGG
-                        PATHS
-                            ENV OGGDIR
-                            ENV VORBISDIR
-                            ENV SPEEXDIR
-                            ENV SDLSOUNDDIR
-                            ENV SDLDIR
-                            /sw
-                            /opt/local
-                            /opt/csw
-                            /opt
-                        PATH_SUFFIXES lib
-                    )
-                    if(OGG_LIBRARY)
-                        set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY})
-                    endif()
-                endif()
-            endif()
-
-            set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARIES_TMP} CACHE INTERNAL "SDL_sound and dependent libraries")
-        else()
-            set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARY} CACHE INTERNAL "SDL_sound and dependent libraries")
-        endif()
-    endif()
-endif()
-
-if(SDL_SOUND_INCLUDE_DIR AND EXISTS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h")
-  file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SOUND_VER_MAJOR[ \t]+[0-9]+$")
-  file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_MINOR_LINE REGEX "^#define[ \t]+SOUND_VER_MINOR[ \t]+[0-9]+$")
-  file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_PATCH_LINE REGEX "^#define[ \t]+SOUND_VER_PATCH[ \t]+[0-9]+$")
-  string(REGEX REPLACE "^#define[ \t]+SOUND_VER_MAJOR[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_MAJOR "${SDL_SOUND_VERSION_MAJOR_LINE}")
-  string(REGEX REPLACE "^#define[ \t]+SOUND_VER_MINOR[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_MINOR "${SDL_SOUND_VERSION_MINOR_LINE}")
-  string(REGEX REPLACE "^#define[ \t]+SOUND_VER_PATCH[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_PATCH "${SDL_SOUND_VERSION_PATCH_LINE}")
-  set(SDL_SOUND_VERSION_STRING ${SDL_SOUND_VERSION_MAJOR}.${SDL_SOUND_VERSION_MINOR}.${SDL_SOUND_VERSION_PATCH})
-  unset(SDL_SOUND_VERSION_MAJOR_LINE)
-  unset(SDL_SOUND_VERSION_MINOR_LINE)
-  unset(SDL_SOUND_VERSION_PATCH_LINE)
-  unset(SDL_SOUND_VERSION_MAJOR)
-  unset(SDL_SOUND_VERSION_MINOR)
-  unset(SDL_SOUND_VERSION_PATCH)
-endif()
-
-include(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL_sound
-                                  REQUIRED_VARS SDL_SOUND_LIBRARIES SDL_SOUND_INCLUDE_DIR
-                                  VERSION_VAR SDL_SOUND_VERSION_STRING)

+ 0 - 144
love/src/jni/openal-soft-1.17.0/common/uintmap.c

@@ -1,144 +0,0 @@
-
-#include "config.h"
-
-#include "uintmap.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-
-extern inline void LockUIntMapRead(UIntMap *map);
-extern inline void UnlockUIntMapRead(UIntMap *map);
-extern inline void LockUIntMapWrite(UIntMap *map);
-extern inline void UnlockUIntMapWrite(UIntMap *map);
-
-
-void InitUIntMap(UIntMap *map, ALsizei limit)
-{
-    map->array = NULL;
-    map->size = 0;
-    map->maxsize = 0;
-    map->limit = limit;
-    RWLockInit(&map->lock);
-}
-
-void ResetUIntMap(UIntMap *map)
-{
-    WriteLock(&map->lock);
-    free(map->array);
-    map->array = NULL;
-    map->size = 0;
-    map->maxsize = 0;
-    WriteUnlock(&map->lock);
-}
-
-ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value)
-{
-    ALsizei pos = 0;
-
-    WriteLock(&map->lock);
-    if(map->size > 0)
-    {
-        ALsizei low = 0;
-        ALsizei high = map->size - 1;
-        while(low < high)
-        {
-            ALsizei mid = low + (high-low)/2;
-            if(map->array[mid].key < key)
-                low = mid + 1;
-            else
-                high = mid;
-        }
-        if(map->array[low].key < key)
-            low++;
-        pos = low;
-    }
-
-    if(pos == map->size || map->array[pos].key != key)
-    {
-        if(map->size == map->limit)
-        {
-            WriteUnlock(&map->lock);
-            return AL_OUT_OF_MEMORY;
-        }
-
-        if(map->size == map->maxsize)
-        {
-            ALvoid *temp = NULL;
-            ALsizei newsize;
-
-            newsize = (map->maxsize ? (map->maxsize<<1) : 4);
-            if(newsize >= map->maxsize)
-                temp = realloc(map->array, newsize*sizeof(map->array[0]));
-            if(!temp)
-            {
-                WriteUnlock(&map->lock);
-                return AL_OUT_OF_MEMORY;
-            }
-            map->array = temp;
-            map->maxsize = newsize;
-        }
-
-        if(pos < map->size)
-            memmove(&map->array[pos+1], &map->array[pos],
-                    (map->size-pos)*sizeof(map->array[0]));
-        map->size++;
-    }
-    map->array[pos].key = key;
-    map->array[pos].value = value;
-    WriteUnlock(&map->lock);
-
-    return AL_NO_ERROR;
-}
-
-ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key)
-{
-    ALvoid *ptr = NULL;
-    WriteLock(&map->lock);
-    if(map->size > 0)
-    {
-        ALsizei low = 0;
-        ALsizei high = map->size - 1;
-        while(low < high)
-        {
-            ALsizei mid = low + (high-low)/2;
-            if(map->array[mid].key < key)
-                low = mid + 1;
-            else
-                high = mid;
-        }
-        if(map->array[low].key == key)
-        {
-            ptr = map->array[low].value;
-            if(low < map->size-1)
-                memmove(&map->array[low], &map->array[low+1],
-                        (map->size-1-low)*sizeof(map->array[0]));
-            map->size--;
-        }
-    }
-    WriteUnlock(&map->lock);
-    return ptr;
-}
-
-ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key)
-{
-    ALvoid *ptr = NULL;
-    ReadLock(&map->lock);
-    if(map->size > 0)
-    {
-        ALsizei low = 0;
-        ALsizei high = map->size - 1;
-        while(low < high)
-        {
-            ALsizei mid = low + (high-low)/2;
-            if(map->array[mid].key < key)
-                low = mid + 1;
-            else
-                high = mid;
-        }
-        if(map->array[low].key == key)
-            ptr = map->array[low].value;
-    }
-    ReadUnlock(&map->lock);
-    return ptr;
-}

+ 0 - 1479
love/src/jni/openal-soft-1.17.0/examples/alffplay.c

@@ -1,1479 +0,0 @@
-/*
- * alffplay.c
- *
- * A pedagogical video player that really works! Now with seeking features.
- *
- * Code based on FFplay, Copyright (c) 2003 Fabrice Bellard, and a tutorial by
- * Martin Bohme <[email protected]>.
- *
- * Requires C99.
- */
-
-#include <stdio.h>
-#include <math.h>
-
-#include <libavcodec/avcodec.h>
-#include <libavformat/avformat.h>
-#include <libavformat/avio.h>
-#include <libavutil/time.h>
-#include <libavutil/avstring.h>
-#include <libavutil/channel_layout.h>
-#include <libswscale/swscale.h>
-#include <libswresample/swresample.h>
-
-#include <SDL.h>
-#include <SDL_thread.h>
-#include <SDL_video.h>
-
-#include "threads.h"
-#include "bool.h"
-
-#include "AL/al.h"
-#include "AL/alc.h"
-#include "AL/alext.h"
-
-
-static bool has_latency_check = false;
-static LPALGETSOURCEDVSOFT alGetSourcedvSOFT;
-
-#define AUDIO_BUFFER_TIME 100 /* In milliseconds, per-buffer */
-#define AUDIO_BUFFER_QUEUE_SIZE 8 /* Number of buffers to queue */
-#define MAX_AUDIOQ_SIZE (5 * 16 * 1024) /* Bytes of compressed audio data to keep queued */
-#define MAX_VIDEOQ_SIZE (5 * 256 * 1024) /* Bytes of compressed video data to keep queued */
-#define AV_SYNC_THRESHOLD 0.01
-#define AV_NOSYNC_THRESHOLD 10.0
-#define SAMPLE_CORRECTION_MAX_DIFF 0.1
-#define AUDIO_DIFF_AVG_NB 20
-#define VIDEO_PICTURE_QUEUE_SIZE 16
-
-enum {
-    FF_UPDATE_EVENT = SDL_USEREVENT,
-    FF_REFRESH_EVENT,
-    FF_QUIT_EVENT
-};
-
-
-typedef struct PacketQueue {
-    AVPacketList *first_pkt, *last_pkt;
-    volatile int nb_packets;
-    volatile int size;
-    volatile bool flushing;
-    almtx_t mutex;
-    alcnd_t cond;
-} PacketQueue;
-
-typedef struct VideoPicture {
-    SDL_Texture *bmp;
-    int width, height; /* Logical image size (actual size may be larger) */
-    volatile bool updated;
-    double pts;
-} VideoPicture;
-
-typedef struct AudioState {
-    AVStream *st;
-
-    PacketQueue q;
-    AVPacket    pkt;
-
-    /* Used for clock difference average computation */
-    double diff_accum;
-    double diff_avg_coef;
-    double diff_threshold;
-
-    /* Time (in seconds) of the next sample to be buffered */
-    double current_pts;
-
-    /* Decompressed sample frame, and swresample context for conversion */
-    AVFrame           *decoded_aframe;
-    struct SwrContext *swres_ctx;
-
-    /* Conversion format, for what gets fed to OpenAL */
-    int                 dst_ch_layout;
-    enum AVSampleFormat dst_sample_fmt;
-
-    /* Storage of converted samples */
-    uint8_t *samples;
-    ssize_t samples_len; /* In samples */
-    ssize_t samples_pos;
-    int     samples_max;
-
-    /* OpenAL format */
-    ALenum  format;
-    ALint   frame_size;
-
-    ALuint  source;
-    ALuint  buffer[AUDIO_BUFFER_QUEUE_SIZE];
-    ALuint  buffer_idx;
-    almtx_t src_mutex;
-
-    althrd_t thread;
-} AudioState;
-
-typedef struct VideoState {
-    AVStream *st;
-
-    PacketQueue q;
-
-    double  clock;
-    double  frame_timer;
-    double  frame_last_pts;
-    double  frame_last_delay;
-    double  current_pts;
-    /* time (av_gettime) at which we updated current_pts - used to have running video pts */
-    int64_t current_pts_time;
-
-    /* Decompressed video frame, and swscale context for conversion */
-    AVFrame           *decoded_vframe;
-    struct SwsContext *swscale_ctx;
-
-    VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE];
-    int          pictq_size, pictq_rindex, pictq_windex;
-    almtx_t      pictq_mutex;
-    alcnd_t      pictq_cond;
-
-    althrd_t thread;
-} VideoState;
-
-typedef struct MovieState {
-    AVFormatContext *pFormatCtx;
-    int             videoStream, audioStream;
-
-    volatile bool seek_req;
-    int64_t       seek_pos;
-
-    int av_sync_type;
-
-    int64_t external_clock_base;
-
-    AudioState audio;
-    VideoState video;
-
-    althrd_t parse_thread;
-
-    char filename[1024];
-
-    volatile bool quit;
-} MovieState;
-
-enum {
-    AV_SYNC_AUDIO_MASTER,
-    AV_SYNC_VIDEO_MASTER,
-    AV_SYNC_EXTERNAL_MASTER,
-
-    DEFAULT_AV_SYNC_TYPE = AV_SYNC_EXTERNAL_MASTER
-};
-
-static AVPacket flush_pkt = { .data = (uint8_t*)"FLUSH" };
-
-static void packet_queue_init(PacketQueue *q)
-{
-    memset(q, 0, sizeof(PacketQueue));
-    almtx_init(&q->mutex, almtx_plain);
-    alcnd_init(&q->cond);
-}
-static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
-{
-    AVPacketList *pkt1;
-    if(pkt != &flush_pkt && !pkt->buf && av_dup_packet(pkt) < 0)
-        return -1;
-
-    pkt1 = av_malloc(sizeof(AVPacketList));
-    if(!pkt1) return -1;
-    pkt1->pkt = *pkt;
-    pkt1->next = NULL;
-
-    almtx_lock(&q->mutex);
-    if(!q->last_pkt)
-        q->first_pkt = pkt1;
-    else
-        q->last_pkt->next = pkt1;
-    q->last_pkt = pkt1;
-    q->nb_packets++;
-    q->size += pkt1->pkt.size;
-    almtx_unlock(&q->mutex);
-
-    alcnd_signal(&q->cond);
-    return 0;
-}
-static int packet_queue_get(PacketQueue *q, AVPacket *pkt, MovieState *state)
-{
-    AVPacketList *pkt1;
-    int ret = -1;
-
-    almtx_lock(&q->mutex);
-    while(!state->quit)
-    {
-        pkt1 = q->first_pkt;
-        if(pkt1)
-        {
-            q->first_pkt = pkt1->next;
-            if(!q->first_pkt)
-                q->last_pkt = NULL;
-            q->nb_packets--;
-            q->size -= pkt1->pkt.size;
-            *pkt = pkt1->pkt;
-            av_free(pkt1);
-            ret = 1;
-            break;
-        }
-
-        if(q->flushing)
-        {
-            ret = 0;
-            break;
-        }
-        alcnd_wait(&q->cond, &q->mutex);
-    }
-    almtx_unlock(&q->mutex);
-    return ret;
-}
-static void packet_queue_clear(PacketQueue *q)
-{
-    AVPacketList *pkt, *pkt1;
-
-    almtx_lock(&q->mutex);
-    for(pkt = q->first_pkt;pkt != NULL;pkt = pkt1)
-    {
-        pkt1 = pkt->next;
-        if(pkt->pkt.data != flush_pkt.data)
-            av_free_packet(&pkt->pkt);
-        av_freep(&pkt);
-    }
-    q->last_pkt = NULL;
-    q->first_pkt = NULL;
-    q->nb_packets = 0;
-    q->size = 0;
-    almtx_unlock(&q->mutex);
-}
-static void packet_queue_flush(PacketQueue *q)
-{
-    almtx_lock(&q->mutex);
-    q->flushing = true;
-    almtx_unlock(&q->mutex);
-    alcnd_signal(&q->cond);
-}
-static void packet_queue_deinit(PacketQueue *q)
-{
-    packet_queue_clear(q);
-    alcnd_destroy(&q->cond);
-    almtx_destroy(&q->mutex);
-}
-
-
-static double get_audio_clock(AudioState *state)
-{
-    double pts;
-
-    almtx_lock(&state->src_mutex);
-    /* The audio clock is the timestamp of the sample currently being heard.
-     * It's based on 4 components:
-     * 1 - The timestamp of the next sample to buffer (state->current_pts)
-     * 2 - The length of the source's buffer queue (AL_SEC_LENGTH_SOFT)
-     * 3 - The offset OpenAL is currently at in the source (the first value
-     *     from AL_SEC_OFFSET_LATENCY_SOFT)
-     * 4 - The latency between OpenAL and the DAC (the second value from
-     *     AL_SEC_OFFSET_LATENCY_SOFT)
-     *
-     * Subtracting the length of the source queue from the next sample's
-     * timestamp gives the timestamp of the sample at start of the source
-     * queue. Adding the source offset to that results in the timestamp for
-     * OpenAL's current position, and subtracting the source latency from that
-     * gives the timestamp of the sample currently at the DAC.
-     */
-    pts = state->current_pts;
-    if(state->source)
-    {
-        ALdouble offset[2] = { 0.0, 0.0 };
-        ALdouble queue_len = 0.0;
-        ALint status;
-
-        /* NOTE: The source state must be checked last, in case an underrun
-         * occurs and the source stops between retrieving the offset+latency
-         * and getting the state. */
-        if(has_latency_check)
-        {
-            alGetSourcedvSOFT(state->source, AL_SEC_OFFSET_LATENCY_SOFT, offset);
-            alGetSourcedvSOFT(state->source, AL_SEC_LENGTH_SOFT, &queue_len);
-        }
-        else
-        {
-            ALint ioffset, ilen;
-            alGetSourcei(state->source, AL_SAMPLE_OFFSET, &ioffset);
-            alGetSourcei(state->source, AL_SAMPLE_LENGTH_SOFT, &ilen);
-            offset[0] = (double)ioffset / state->st->codec->sample_rate;
-            queue_len = (double)ilen / state->st->codec->sample_rate;
-        }
-        alGetSourcei(state->source, AL_SOURCE_STATE, &status);
-
-        /* If the source is AL_STOPPED, then there was an underrun and all
-         * buffers are processed, so ignore the source queue. The audio thread
-         * will put the source into an AL_INITIAL state and clear the queue
-         * when it starts recovery. */
-        if(status != AL_STOPPED)
-            pts = pts - queue_len + offset[0];
-        if(status == AL_PLAYING)
-            pts = pts - offset[1];
-    }
-    almtx_unlock(&state->src_mutex);
-
-    return (pts >= 0.0) ? pts : 0.0;
-}
-static double get_video_clock(VideoState *state)
-{
-    double delta = (av_gettime() - state->current_pts_time) / 1000000.0;
-    return state->current_pts + delta;
-}
-static double get_external_clock(MovieState *movState)
-{
-    return (av_gettime()-movState->external_clock_base) / 1000000.0;
-}
-
-double get_master_clock(MovieState *movState)
-{
-    if(movState->av_sync_type == AV_SYNC_VIDEO_MASTER)
-        return get_video_clock(&movState->video);
-    if(movState->av_sync_type == AV_SYNC_AUDIO_MASTER)
-        return get_audio_clock(&movState->audio);
-    return get_external_clock(movState);
-}
-
-/* Return how many samples to skip to maintain sync (negative means to
- * duplicate samples). */
-static int synchronize_audio(MovieState *movState)
-{
-    double diff, avg_diff;
-    double ref_clock;
-
-    if(movState->av_sync_type == AV_SYNC_AUDIO_MASTER)
-        return 0;
-
-    ref_clock = get_master_clock(movState);
-    diff = ref_clock - get_audio_clock(&movState->audio);
-
-    if(!(diff < AV_NOSYNC_THRESHOLD))
-    {
-        /* Difference is TOO big; reset diff stuff */
-        movState->audio.diff_accum = 0.0;
-        return 0;
-    }
-
-    /* Accumulate the diffs */
-    movState->audio.diff_accum = movState->audio.diff_accum*movState->audio.diff_avg_coef + diff;
-    avg_diff = movState->audio.diff_accum*(1.0 - movState->audio.diff_avg_coef);
-    if(fabs(avg_diff) < movState->audio.diff_threshold)
-        return 0;
-
-    /* Constrain the per-update difference to avoid exceedingly large skips */
-    if(!(diff <= SAMPLE_CORRECTION_MAX_DIFF))
-        diff = SAMPLE_CORRECTION_MAX_DIFF;
-    else if(!(diff >= -SAMPLE_CORRECTION_MAX_DIFF))
-        diff = -SAMPLE_CORRECTION_MAX_DIFF;
-    return (int)(diff*movState->audio.st->codec->sample_rate);
-}
-
-static int audio_decode_frame(MovieState *movState)
-{
-    AVPacket *pkt = &movState->audio.pkt;
-
-    while(!movState->quit)
-    {
-        while(!movState->quit && pkt->size == 0)
-        {
-            av_free_packet(pkt);
-
-            /* Get the next packet */
-            int err;
-            if((err=packet_queue_get(&movState->audio.q, pkt, movState)) <= 0)
-            {
-                if(err == 0)
-                    break;
-                return err;
-            }
-            if(pkt->data == flush_pkt.data)
-            {
-                avcodec_flush_buffers(movState->audio.st->codec);
-                movState->audio.diff_accum = 0.0;
-                movState->audio.current_pts = av_q2d(movState->audio.st->time_base)*pkt->pts;
-
-                alSourceRewind(movState->audio.source);
-                alSourcei(movState->audio.source, AL_BUFFER, 0);
-
-                av_new_packet(pkt, 0);
-
-                return -1;
-            }
-
-            /* If provided, update w/ pts */
-            if(pkt->pts != AV_NOPTS_VALUE)
-                movState->audio.current_pts = av_q2d(movState->audio.st->time_base)*pkt->pts;
-        }
-
-        AVFrame *frame = movState->audio.decoded_aframe;
-        int got_frame = 0;
-        int len1 = avcodec_decode_audio4(movState->audio.st->codec, frame,
-                                         &got_frame, pkt);
-        if(len1 < 0) break;
-
-        if(len1 <= pkt->size)
-        {
-            /* Move the unread data to the front and clear the end bits */
-            int remaining = pkt->size - len1;
-            memmove(pkt->data, &pkt->data[len1], remaining);
-            av_shrink_packet(pkt, remaining);
-        }
-
-        if(!got_frame || frame->nb_samples <= 0)
-        {
-            av_frame_unref(frame);
-            continue;
-        }
-
-        if(frame->nb_samples > movState->audio.samples_max)
-        {
-            av_freep(&movState->audio.samples);
-            av_samples_alloc(
-                &movState->audio.samples, NULL, movState->audio.st->codec->channels,
-                frame->nb_samples, movState->audio.dst_sample_fmt, 0
-            );
-            movState->audio.samples_max = frame->nb_samples;
-        }
-        /* Return the amount of sample frames converted */
-        int data_size = swr_convert(movState->audio.swres_ctx,
-            &movState->audio.samples, frame->nb_samples,
-            (const uint8_t**)frame->data, frame->nb_samples
-        );
-
-        av_frame_unref(frame);
-        return data_size;
-    }
-
-    return -1;
-}
-
-static int read_audio(MovieState *movState, uint8_t *samples, int length)
-{
-    int sample_skip = synchronize_audio(movState);
-    int audio_size = 0;
-
-    /* Read the next chunk of data, refill the buffer, and queue it
-     * on the source */
-    length /= movState->audio.frame_size;
-    while(audio_size < length)
-    {
-        if(movState->audio.samples_len <= 0 || movState->audio.samples_pos >= movState->audio.samples_len)
-        {
-            int frame_len = audio_decode_frame(movState);
-            if(frame_len < 0) return -1;
-
-            movState->audio.samples_len = frame_len;
-            if(movState->audio.samples_len == 0)
-                break;
-
-            movState->audio.samples_pos = (movState->audio.samples_len < sample_skip) ?
-                                          movState->audio.samples_len : sample_skip;
-            sample_skip -= movState->audio.samples_pos;
-
-            movState->audio.current_pts += (double)movState->audio.samples_pos /
-                                           (double)movState->audio.st->codec->sample_rate;
-            continue;
-        }
-
-        int rem = length - audio_size;
-        if(movState->audio.samples_pos >= 0)
-        {
-            int n = movState->audio.frame_size;
-            int len = movState->audio.samples_len - movState->audio.samples_pos;
-            if(rem > len) rem = len;
-            memcpy(samples + audio_size*n,
-                   movState->audio.samples + movState->audio.samples_pos*n,
-                   rem*n);
-        }
-        else
-        {
-            int n = movState->audio.frame_size;
-            int len = -movState->audio.samples_pos;
-            if(rem > len) rem = len;
-
-            /* Add samples by copying the first sample */
-            if(n == 1)
-            {
-                uint8_t sample = ((uint8_t*)movState->audio.samples)[0];
-                uint8_t *q = (uint8_t*)samples + audio_size;
-                for(int i = 0;i < rem;i++)
-                    *(q++) = sample;
-            }
-            else if(n == 2)
-            {
-                uint16_t sample = ((uint16_t*)movState->audio.samples)[0];
-                uint16_t *q = (uint16_t*)samples + audio_size;
-                for(int i = 0;i < rem;i++)
-                    *(q++) = sample;
-            }
-            else if(n == 4)
-            {
-                uint32_t sample = ((uint32_t*)movState->audio.samples)[0];
-                uint32_t *q = (uint32_t*)samples + audio_size;
-                for(int i = 0;i < rem;i++)
-                    *(q++) = sample;
-            }
-            else if(n == 8)
-            {
-                uint64_t sample = ((uint64_t*)movState->audio.samples)[0];
-                uint64_t *q = (uint64_t*)samples + audio_size;
-                for(int i = 0;i < rem;i++)
-                    *(q++) = sample;
-            }
-            else
-            {
-                uint8_t *sample = movState->audio.samples;
-                uint8_t *q = samples + audio_size*n;
-                for(int i = 0;i < rem;i++)
-                {
-                    memcpy(q, sample, n);
-                    q += n;
-                }
-            }
-        }
-
-        movState->audio.samples_pos += rem;
-        movState->audio.current_pts += (double)rem / movState->audio.st->codec->sample_rate;
-        audio_size += rem;
-    }
-
-    return audio_size * movState->audio.frame_size;
-}
-
-static int audio_thread(void *userdata)
-{
-    MovieState *movState = (MovieState*)userdata;
-    uint8_t *samples = NULL;
-    ALsizei buffer_len;
-
-    alGenBuffers(AUDIO_BUFFER_QUEUE_SIZE, movState->audio.buffer);
-    alGenSources(1, &movState->audio.source);
-
-    alSourcei(movState->audio.source, AL_SOURCE_RELATIVE, AL_TRUE);
-    alSourcei(movState->audio.source, AL_ROLLOFF_FACTOR, 0);
-
-    av_new_packet(&movState->audio.pkt, 0);
-
-    /* Find a suitable format for OpenAL. Currently does not handle surround
-     * sound (everything non-mono becomes stereo). */
-    if(movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_U8 ||
-       movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_U8P)
-    {
-        movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_U8;
-        movState->audio.frame_size = 1;
-        if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
-        {
-            movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
-            movState->audio.frame_size *= 1;
-            movState->audio.format = AL_FORMAT_MONO8;
-        }
-        else
-        {
-            movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
-            movState->audio.frame_size *= 2;
-            movState->audio.format = AL_FORMAT_STEREO8;
-        }
-    }
-    else if((movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_FLT ||
-             movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) &&
-            alIsExtensionPresent("AL_EXT_FLOAT32"))
-    {
-        movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_FLT;
-        movState->audio.frame_size = 4;
-        if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
-        {
-            movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
-            movState->audio.frame_size *= 1;
-            movState->audio.format = AL_FORMAT_MONO_FLOAT32;
-        }
-        else
-        {
-            movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
-            movState->audio.frame_size *= 2;
-            movState->audio.format = AL_FORMAT_STEREO_FLOAT32;
-        }
-    }
-    else
-    {
-        movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_S16;
-        movState->audio.frame_size = 2;
-        if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO)
-        {
-            movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO;
-            movState->audio.frame_size *= 1;
-            movState->audio.format = AL_FORMAT_MONO16;
-        }
-        else
-        {
-            movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO;
-            movState->audio.frame_size *= 2;
-            movState->audio.format = AL_FORMAT_STEREO16;
-        }
-    }
-    buffer_len = AUDIO_BUFFER_TIME * movState->audio.st->codec->sample_rate / 1000 *
-                 movState->audio.frame_size;
-    samples = av_malloc(buffer_len);
-
-    movState->audio.samples = NULL;
-    movState->audio.samples_max = 0;
-    movState->audio.samples_pos = 0;
-    movState->audio.samples_len = 0;
-
-    if(!(movState->audio.decoded_aframe=av_frame_alloc()))
-    {
-        fprintf(stderr, "Failed to allocate audio frame\n");
-        goto finish;
-    }
-
-    movState->audio.swres_ctx = swr_alloc_set_opts(NULL,
-        movState->audio.dst_ch_layout,
-        movState->audio.dst_sample_fmt,
-        movState->audio.st->codec->sample_rate,
-        movState->audio.st->codec->channel_layout,
-        movState->audio.st->codec->sample_fmt,
-        movState->audio.st->codec->sample_rate,
-        0, NULL
-    );
-    if(!movState->audio.swres_ctx || swr_init(movState->audio.swres_ctx) != 0)
-    {
-        fprintf(stderr, "Failed to initialize audio converter\n");
-        goto finish;
-    }
-
-    almtx_lock(&movState->audio.src_mutex);
-    while(alGetError() == AL_NO_ERROR && !movState->quit)
-    {
-        /* First remove any processed buffers. */
-        ALint processed;
-        alGetSourcei(movState->audio.source, AL_BUFFERS_PROCESSED, &processed);
-        alSourceUnqueueBuffers(movState->audio.source, processed, (ALuint[AUDIO_BUFFER_QUEUE_SIZE]){});
-
-        /* Refill the buffer queue. */
-        ALint queued;
-        alGetSourcei(movState->audio.source, AL_BUFFERS_QUEUED, &queued);
-        while(queued < AUDIO_BUFFER_QUEUE_SIZE)
-        {
-            int audio_size;
-
-            /* Read the next chunk of data, fill the buffer, and queue it on
-             * the source */
-            audio_size = read_audio(movState, samples, buffer_len);
-            if(audio_size < 0) break;
-
-            ALuint bufid = movState->audio.buffer[movState->audio.buffer_idx++];
-            movState->audio.buffer_idx %= AUDIO_BUFFER_QUEUE_SIZE;
-
-            alBufferData(bufid, movState->audio.format, samples, audio_size,
-                         movState->audio.st->codec->sample_rate);
-            alSourceQueueBuffers(movState->audio.source, 1, &bufid);
-            queued++;
-        }
-
-        /* Check that the source is playing. */
-        ALint state;
-        alGetSourcei(movState->audio.source, AL_SOURCE_STATE, &state);
-        if(state == AL_STOPPED)
-        {
-            /* AL_STOPPED means there was an underrun. Double-check that all
-             * processed buffers are removed, then rewind the source to get it
-             * back into an AL_INITIAL state. */
-            alGetSourcei(movState->audio.source, AL_BUFFERS_PROCESSED, &processed);
-            alSourceUnqueueBuffers(movState->audio.source, processed, (ALuint[AUDIO_BUFFER_QUEUE_SIZE]){});
-            alSourceRewind(movState->audio.source);
-            continue;
-        }
-
-        almtx_unlock(&movState->audio.src_mutex);
-
-        /* (re)start the source if needed, and wait for a buffer to finish */
-        if(state != AL_PLAYING && state != AL_PAUSED)
-        {
-            alGetSourcei(movState->audio.source, AL_BUFFERS_QUEUED, &queued);
-            if(queued > 0) alSourcePlay(movState->audio.source);
-        }
-        SDL_Delay(AUDIO_BUFFER_TIME);
-
-        almtx_lock(&movState->audio.src_mutex);
-    }
-    almtx_unlock(&movState->audio.src_mutex);
-
-finish:
-    av_frame_free(&movState->audio.decoded_aframe);
-    swr_free(&movState->audio.swres_ctx);
-
-    av_freep(&samples);
-    av_freep(&movState->audio.samples);
-
-    alDeleteSources(1, &movState->audio.source);
-    alDeleteBuffers(AUDIO_BUFFER_QUEUE_SIZE, movState->audio.buffer);
-
-    return 0;
-}
-
-
-static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)
-{
-    (void)interval;
-
-    SDL_PushEvent(&(SDL_Event){ .user={.type=FF_REFRESH_EVENT, .data1=opaque} });
-    return 0; /* 0 means stop timer */
-}
-
-/* Schedule a video refresh in 'delay' ms */
-static void schedule_refresh(MovieState *movState, int delay)
-{
-    SDL_AddTimer(delay, sdl_refresh_timer_cb, movState);
-}
-
-static void video_display(MovieState *movState, SDL_Window *screen, SDL_Renderer *renderer)
-{
-    VideoPicture *vp = &movState->video.pictq[movState->video.pictq_rindex];
-
-    if(!vp->bmp)
-        return;
-
-    float aspect_ratio;
-    int win_w, win_h;
-    int w, h, x, y;
-
-    if(movState->video.st->codec->sample_aspect_ratio.num == 0)
-        aspect_ratio = 0.0f;
-    else
-    {
-        aspect_ratio = av_q2d(movState->video.st->codec->sample_aspect_ratio) *
-                       movState->video.st->codec->width /
-                       movState->video.st->codec->height;
-    }
-    if(aspect_ratio <= 0.0f)
-    {
-        aspect_ratio = (float)movState->video.st->codec->width /
-                       (float)movState->video.st->codec->height;
-    }
-
-    SDL_GetWindowSize(screen, &win_w, &win_h);
-    h = win_h;
-    w = ((int)rint(h * aspect_ratio) + 3) & ~3;
-    if(w > win_w)
-    {
-        w = win_w;
-        h = ((int)rint(w / aspect_ratio) + 3) & ~3;
-    }
-    x = (win_w - w) / 2;
-    y = (win_h - h) / 2;
-
-    SDL_RenderCopy(renderer, vp->bmp,
-        &(SDL_Rect){ .x=0, .y=0, .w=vp->width, .h=vp->height },
-        &(SDL_Rect){ .x=x, .y=y, .w=w, .h=h }
-    );
-    SDL_RenderPresent(renderer);
-}
-
-static void video_refresh_timer(MovieState *movState, SDL_Window *screen, SDL_Renderer *renderer)
-{
-    if(!movState->video.st)
-    {
-        schedule_refresh(movState, 100);
-        return;
-    }
-
-    almtx_lock(&movState->video.pictq_mutex);
-retry:
-    if(movState->video.pictq_size == 0)
-        schedule_refresh(movState, 1);
-    else
-    {
-        VideoPicture *vp = &movState->video.pictq[movState->video.pictq_rindex];
-        double actual_delay, delay, sync_threshold, ref_clock, diff;
-
-        movState->video.current_pts = vp->pts;
-        movState->video.current_pts_time = av_gettime();
-
-        delay = vp->pts - movState->video.frame_last_pts; /* the pts from last time */
-        if(delay <= 0 || delay >= 1.0)
-        {
-            /* if incorrect delay, use previous one */
-            delay = movState->video.frame_last_delay;
-        }
-        /* save for next time */
-        movState->video.frame_last_delay = delay;
-        movState->video.frame_last_pts = vp->pts;
-
-        /* Update delay to sync to clock if not master source. */
-        if(movState->av_sync_type != AV_SYNC_VIDEO_MASTER)
-        {
-            ref_clock = get_master_clock(movState);
-            diff = vp->pts - ref_clock;
-
-            /* Skip or repeat the frame. Take delay into account. */
-            sync_threshold = (delay > AV_SYNC_THRESHOLD) ? delay : AV_SYNC_THRESHOLD;
-            if(fabs(diff) < AV_NOSYNC_THRESHOLD)
-            {
-                if(diff <= -sync_threshold)
-                    delay = 0;
-                else if(diff >= sync_threshold)
-                    delay = 2 * delay;
-            }
-        }
-
-        movState->video.frame_timer += delay;
-        /* Compute the REAL delay. */
-        actual_delay = movState->video.frame_timer - (av_gettime() / 1000000.0);
-        if(!(actual_delay >= 0.010))
-        {
-            /* We don't have time to handle this picture, just skip to the next one. */
-            movState->video.pictq_rindex = (movState->video.pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE;
-            movState->video.pictq_size--;
-            alcnd_signal(&movState->video.pictq_cond);
-            goto retry;
-        }
-        schedule_refresh(movState, (int)(actual_delay*1000.0 + 0.5));
-
-        /* Show the picture! */
-        video_display(movState, screen, renderer);
-
-        /* Update queue for next picture. */
-        movState->video.pictq_rindex = (movState->video.pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE;
-        movState->video.pictq_size--;
-        alcnd_signal(&movState->video.pictq_cond);
-    }
-    almtx_unlock(&movState->video.pictq_mutex);
-}
-
-
-static void update_picture(MovieState *movState, bool *first_update, SDL_Window *screen, SDL_Renderer *renderer)
-{
-    VideoPicture *vp = &movState->video.pictq[movState->video.pictq_windex];
-
-    /* allocate or resize the buffer! */
-    if(!vp->bmp || vp->width != movState->video.st->codec->width ||
-                   vp->height != movState->video.st->codec->height)
-    {
-        if(vp->bmp)
-            SDL_DestroyTexture(vp->bmp);
-        vp->bmp = SDL_CreateTexture(
-            renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING,
-            movState->video.st->codec->coded_width, movState->video.st->codec->coded_height
-        );
-        if(!vp->bmp)
-            fprintf(stderr, "Failed to create YV12 texture!\n");
-        vp->width = movState->video.st->codec->width;
-        vp->height = movState->video.st->codec->height;
-
-        if(*first_update && vp->width > 0 && vp->height > 0)
-        {
-            /* For the first update, set the window size to the video size. */
-            *first_update = false;
-
-            int w = vp->width;
-            int h = vp->height;
-            if(movState->video.st->codec->sample_aspect_ratio.num != 0 &&
-               movState->video.st->codec->sample_aspect_ratio.den != 0)
-            {
-                double aspect_ratio = av_q2d(movState->video.st->codec->sample_aspect_ratio);
-                if(aspect_ratio >= 1.0)
-                    w = (int)(w*aspect_ratio + 0.5);
-                else if(aspect_ratio > 0.0)
-                    h = (int)(h/aspect_ratio + 0.5);
-            }
-            SDL_SetWindowSize(screen, w, h);
-        }
-    }
-
-    if(vp->bmp)
-    {
-        AVFrame *frame = movState->video.decoded_vframe;
-        void *pixels = NULL;
-        int pitch = 0;
-
-        if(movState->video.st->codec->pix_fmt == PIX_FMT_YUV420P)
-            SDL_UpdateYUVTexture(vp->bmp, NULL,
-                frame->data[0], frame->linesize[0],
-                frame->data[1], frame->linesize[1],
-                frame->data[2], frame->linesize[2]
-            );
-        else if(SDL_LockTexture(vp->bmp, NULL, &pixels, &pitch) != 0)
-            fprintf(stderr, "Failed to lock texture\n");
-        else
-        {
-            // Convert the image into YUV format that SDL uses
-            int coded_w = movState->video.st->codec->coded_width;
-            int coded_h = movState->video.st->codec->coded_height;
-            int w = movState->video.st->codec->width;
-            int h = movState->video.st->codec->height;
-            if(!movState->video.swscale_ctx)
-                movState->video.swscale_ctx = sws_getContext(
-                    w, h, movState->video.st->codec->pix_fmt,
-                    w, h, PIX_FMT_YUV420P, SWS_X, NULL, NULL, NULL
-                );
-
-            /* point pict at the queue */
-            AVPicture pict;
-            pict.data[0] = pixels;
-            pict.data[2] = pict.data[0] + coded_w*coded_h;
-            pict.data[1] = pict.data[2] + coded_w*coded_h/4;
-
-            pict.linesize[0] = pitch;
-            pict.linesize[2] = pitch / 2;
-            pict.linesize[1] = pitch / 2;
-
-            sws_scale(movState->video.swscale_ctx, (const uint8_t**)frame->data,
-                      frame->linesize, 0, h, pict.data, pict.linesize);
-            SDL_UnlockTexture(vp->bmp);
-        }
-    }
-
-    almtx_lock(&movState->video.pictq_mutex);
-    vp->updated = true;
-    almtx_unlock(&movState->video.pictq_mutex);
-    alcnd_signal(&movState->video.pictq_cond);
-}
-
-static int queue_picture(MovieState *movState, double pts)
-{
-    /* Wait until we have space for a new pic */
-    almtx_lock(&movState->video.pictq_mutex);
-    while(movState->video.pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !movState->quit)
-        alcnd_wait(&movState->video.pictq_cond, &movState->video.pictq_mutex);
-    almtx_unlock(&movState->video.pictq_mutex);
-
-    if(movState->quit)
-        return -1;
-
-    VideoPicture *vp = &movState->video.pictq[movState->video.pictq_windex];
-
-    /* We have to create/update the picture in the main thread  */
-    vp->updated = false;
-    SDL_PushEvent(&(SDL_Event){ .user={.type=FF_UPDATE_EVENT, .data1=movState} });
-
-    /* Wait until the picture is updated. */
-    almtx_lock(&movState->video.pictq_mutex);
-    while(!vp->updated && !movState->quit)
-        alcnd_wait(&movState->video.pictq_cond, &movState->video.pictq_mutex);
-    almtx_unlock(&movState->video.pictq_mutex);
-    if(movState->quit)
-        return -1;
-    vp->pts = pts;
-
-    movState->video.pictq_windex = (movState->video.pictq_windex+1)%VIDEO_PICTURE_QUEUE_SIZE;
-    almtx_lock(&movState->video.pictq_mutex);
-    movState->video.pictq_size++;
-    almtx_unlock(&movState->video.pictq_mutex);
-
-    return 0;
-}
-
-static double synchronize_video(MovieState *movState, double pts)
-{
-    double frame_delay;
-
-    if(pts == 0.0) /* if we aren't given a pts, set it to the clock */
-        pts = movState->video.clock;
-    else /* if we have pts, set video clock to it */
-        movState->video.clock = pts;
-
-    /* update the video clock */
-    frame_delay = av_q2d(movState->video.st->codec->time_base);
-    /* if we are repeating a frame, adjust clock accordingly */
-    frame_delay += movState->video.decoded_vframe->repeat_pict * (frame_delay * 0.5);
-    movState->video.clock += frame_delay;
-    return pts;
-}
-
-int video_thread(void *arg)
-{
-    MovieState *movState = (MovieState*)arg;
-    AVPacket *packet = (AVPacket[1]){};
-    int64_t saved_pts, pkt_pts;
-    int frameFinished;
-
-    movState->video.decoded_vframe = av_frame_alloc();
-    while(packet_queue_get(&movState->video.q, packet, movState) >= 0)
-    {
-        if(packet->data == flush_pkt.data)
-        {
-            avcodec_flush_buffers(movState->video.st->codec);
-
-            almtx_lock(&movState->video.pictq_mutex);
-            movState->video.pictq_size = 0;
-            movState->video.pictq_rindex = 0;
-            movState->video.pictq_windex = 0;
-            almtx_unlock(&movState->video.pictq_mutex);
-
-            movState->video.clock = av_q2d(movState->video.st->time_base)*packet->pts;
-            movState->video.current_pts = movState->video.clock;
-            movState->video.current_pts_time = av_gettime();
-            continue;
-        }
-
-        pkt_pts = packet->pts;
-
-        /* Decode video frame */
-        avcodec_decode_video2(movState->video.st->codec, movState->video.decoded_vframe,
-                              &frameFinished, packet);
-        if(pkt_pts != AV_NOPTS_VALUE && !movState->video.decoded_vframe->opaque)
-        {
-            /* Store the packet's original pts in the frame, in case the frame
-             * is not finished decoding yet. */
-            saved_pts = pkt_pts;
-            movState->video.decoded_vframe->opaque = &saved_pts;
-        }
-
-        av_free_packet(packet);
-
-        if(frameFinished)
-        {
-            double pts = av_q2d(movState->video.st->time_base);
-            if(packet->dts != AV_NOPTS_VALUE)
-                pts *= packet->dts;
-            else if(movState->video.decoded_vframe->opaque)
-                pts *= *(int64_t*)movState->video.decoded_vframe->opaque;
-            else
-                pts *= 0.0;
-            movState->video.decoded_vframe->opaque = NULL;
-
-            pts = synchronize_video(movState, pts);
-            if(queue_picture(movState, pts) < 0)
-                break;
-        }
-    }
-
-    sws_freeContext(movState->video.swscale_ctx);
-    movState->video.swscale_ctx = NULL;
-    av_frame_free(&movState->video.decoded_vframe);
-    return 0;
-}
-
-
-static int stream_component_open(MovieState *movState, int stream_index)
-{
-    AVFormatContext *pFormatCtx = movState->pFormatCtx;
-    AVCodecContext *codecCtx;
-    AVCodec *codec;
-
-    if(stream_index < 0 || (unsigned int)stream_index >= pFormatCtx->nb_streams)
-        return -1;
-
-    /* Get a pointer to the codec context for the video stream, and open the
-     * associated codec */
-    codecCtx = pFormatCtx->streams[stream_index]->codec;
-
-    codec = avcodec_find_decoder(codecCtx->codec_id);
-    if(!codec || avcodec_open2(codecCtx, codec, NULL) < 0)
-    {
-        fprintf(stderr, "Unsupported codec!\n");
-        return -1;
-    }
-
-    /* Initialize and start the media type handler */
-    switch(codecCtx->codec_type)
-    {
-        case AVMEDIA_TYPE_AUDIO:
-            movState->audioStream = stream_index;
-            movState->audio.st = pFormatCtx->streams[stream_index];
-
-            /* Averaging filter for audio sync */
-            movState->audio.diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB);
-            /* Correct audio only if larger error than this */
-            movState->audio.diff_threshold = 2.0 * 0.050/* 50 ms */;
-
-            memset(&movState->audio.pkt, 0, sizeof(movState->audio.pkt));
-            if(althrd_create(&movState->audio.thread, audio_thread, movState) != althrd_success)
-            {
-                movState->audioStream = -1;
-                movState->audio.st = NULL;
-            }
-            break;
-
-        case AVMEDIA_TYPE_VIDEO:
-            movState->videoStream = stream_index;
-            movState->video.st = pFormatCtx->streams[stream_index];
-
-            movState->video.current_pts_time = av_gettime();
-            movState->video.frame_timer = (double)movState->video.current_pts_time /
-                                          1000000.0;
-            movState->video.frame_last_delay = 40e-3;
-
-            if(althrd_create(&movState->video.thread, video_thread, movState) != althrd_success)
-            {
-                movState->videoStream = -1;
-                movState->video.st = NULL;
-            }
-            break;
-
-        default:
-            break;
-    }
-
-    return 0;
-}
-
-static int decode_interrupt_cb(void *ctx)
-{
-    return ((MovieState*)ctx)->quit;
-}
-
-int decode_thread(void *arg)
-{
-    MovieState *movState = (MovieState *)arg;
-    AVFormatContext *fmtCtx = movState->pFormatCtx;
-    AVPacket *packet = (AVPacket[1]){};
-    int video_index = -1;
-    int audio_index = -1;
-
-    movState->videoStream = -1;
-    movState->audioStream = -1;
-
-    /* Dump information about file onto standard error */
-    av_dump_format(fmtCtx, 0, movState->filename, 0);
-
-    /* Find the first video and audio streams */
-    for(unsigned int i = 0;i < fmtCtx->nb_streams;i++)
-    {
-        if(fmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && video_index < 0)
-            video_index = i;
-        else if(fmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_index < 0)
-            audio_index = i;
-    }
-    movState->external_clock_base = av_gettime();
-    if(audio_index >= 0)
-        stream_component_open(movState, audio_index);
-    if(video_index >= 0)
-        stream_component_open(movState, video_index);
-
-    if(movState->videoStream < 0 && movState->audioStream < 0)
-    {
-        fprintf(stderr, "%s: could not open codecs\n", movState->filename);
-        goto fail;
-    }
-
-    /* Main packet handling loop */
-    while(!movState->quit)
-    {
-        if(movState->seek_req)
-        {
-            int64_t seek_target = movState->seek_pos;
-            int stream_index= -1;
-
-            /* Prefer seeking on the video stream. */
-            if(movState->videoStream >= 0)
-                stream_index = movState->videoStream;
-            else if(movState->audioStream >= 0)
-                stream_index = movState->audioStream;
-
-            /* Get a seek timestamp for the appropriate stream. */
-            int64_t timestamp = seek_target;
-            if(stream_index >= 0)
-                timestamp = av_rescale_q(seek_target, AV_TIME_BASE_Q, fmtCtx->streams[stream_index]->time_base);
-
-            if(av_seek_frame(movState->pFormatCtx, stream_index, timestamp, 0) < 0)
-                fprintf(stderr, "%s: error while seeking\n", movState->pFormatCtx->filename);
-            else
-            {
-                /* Seek successful, clear the packet queues and send a special
-                 * 'flush' packet with the new stream clock time. */
-                if(movState->audioStream >= 0)
-                {
-                    packet_queue_clear(&movState->audio.q);
-                    flush_pkt.pts = av_rescale_q(seek_target, AV_TIME_BASE_Q,
-                        fmtCtx->streams[movState->audioStream]->time_base
-                    );
-                    packet_queue_put(&movState->audio.q, &flush_pkt);
-                }
-                if(movState->videoStream >= 0)
-                {
-                    packet_queue_clear(&movState->video.q);
-                    flush_pkt.pts = av_rescale_q(seek_target, AV_TIME_BASE_Q,
-                        fmtCtx->streams[movState->videoStream]->time_base
-                    );
-                    packet_queue_put(&movState->video.q, &flush_pkt);
-                }
-                movState->external_clock_base = av_gettime() - seek_target;
-            }
-            movState->seek_req = false;
-        }
-
-        if(movState->audio.q.size >= MAX_AUDIOQ_SIZE ||
-           movState->video.q.size >= MAX_VIDEOQ_SIZE)
-        {
-            SDL_Delay(10);
-            continue;
-        }
-
-        if(av_read_frame(movState->pFormatCtx, packet) < 0)
-        {
-            packet_queue_flush(&movState->video.q);
-            packet_queue_flush(&movState->audio.q);
-            break;
-        }
-
-        /* Place the packet in the queue it's meant for, or discard it. */
-        if(packet->stream_index == movState->videoStream)
-            packet_queue_put(&movState->video.q, packet);
-        else if(packet->stream_index == movState->audioStream)
-            packet_queue_put(&movState->audio.q, packet);
-        else
-            av_free_packet(packet);
-    }
-
-    /* all done - wait for it */
-    while(!movState->quit)
-    {
-        if(movState->audio.q.nb_packets == 0 && movState->video.q.nb_packets == 0)
-            break;
-        SDL_Delay(100);
-    }
-
-fail:
-    movState->quit = true;
-    packet_queue_flush(&movState->video.q);
-    packet_queue_flush(&movState->audio.q);
-
-    if(movState->videoStream >= 0)
-        althrd_join(movState->video.thread, NULL);
-    if(movState->audioStream >= 0)
-        althrd_join(movState->audio.thread, NULL);
-
-    SDL_PushEvent(&(SDL_Event){ .user={.type=FF_QUIT_EVENT, .data1=movState} });
-
-    return 0;
-}
-
-
-static void stream_seek(MovieState *movState, double incr)
-{
-    if(!movState->seek_req)
-    {
-        double newtime = get_master_clock(movState)+incr;
-        if(newtime <= 0.0) movState->seek_pos = 0;
-        else movState->seek_pos = (int64_t)(newtime * AV_TIME_BASE);
-        movState->seek_req = true;
-    }
-}
-
-int main(int argc, char *argv[])
-{
-    SDL_Event event;
-    MovieState *movState;
-    bool first_update = true;
-    SDL_Window   *screen;
-    SDL_Renderer *renderer;
-    ALCdevice  *device;
-    ALCcontext *context;
-
-    if(argc < 2)
-    {
-        fprintf(stderr, "Usage: %s <file>\n", argv[0]);
-        return 1;
-    }
-    /* Register all formats and codecs */
-    av_register_all();
-    /* Initialize networking protocols */
-    avformat_network_init();
-
-    if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER))
-    {
-        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
-        return 1;
-    }
-
-    /* Make a window to put our video */
-    screen = SDL_CreateWindow("alffplay", 0, 0, 640, 480, SDL_WINDOW_RESIZABLE);
-    if(!screen)
-    {
-        fprintf(stderr, "SDL: could not set video mode - exiting\n");
-        return 1;
-    }
-    /* Make a renderer to handle the texture image surface and rendering. */
-    renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
-    if(renderer)
-    {
-        SDL_RendererInfo rinf;
-        bool ok = false;
-
-        /* Make sure the renderer supports YV12 textures. If not, fallback to a
-         * software renderer. */
-        if(SDL_GetRendererInfo(renderer, &rinf) == 0)
-        {
-            for(Uint32 i = 0;!ok && i < rinf.num_texture_formats;i++)
-                ok = (rinf.texture_formats[i] == SDL_PIXELFORMAT_YV12);
-        }
-        if(!ok)
-        {
-            fprintf(stderr, "YV12 pixelformat textures not supported on renderer %s\n", rinf.name);
-            SDL_DestroyRenderer(renderer);
-            renderer = NULL;
-        }
-    }
-    if(!renderer)
-        renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_SOFTWARE);
-    if(!renderer)
-    {
-        fprintf(stderr, "SDL: could not create renderer - exiting\n");
-        return 1;
-    }
-    SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
-    SDL_RenderFillRect(renderer, NULL);
-    SDL_RenderPresent(renderer);
-
-    /* Open an audio device */
-    device = alcOpenDevice(NULL);
-    if(!device)
-    {
-        fprintf(stderr, "OpenAL: could not open device - exiting\n");
-        return 1;
-    }
-    context = alcCreateContext(device, NULL);
-    if(!context)
-    {
-        fprintf(stderr, "OpenAL: could not create context - exiting\n");
-        return 1;
-    }
-    if(alcMakeContextCurrent(context) == ALC_FALSE)
-    {
-        fprintf(stderr, "OpenAL: could not make context current - exiting\n");
-        return 1;
-    }
-
-    if(!alIsExtensionPresent("AL_SOFT_source_length"))
-    {
-        fprintf(stderr, "Required AL_SOFT_source_length not supported - exiting\n");
-        return 1;
-    }
-
-    if(!alIsExtensionPresent("AL_SOFT_source_latency"))
-        fprintf(stderr, "AL_SOFT_source_latency not supported, audio may be a bit laggy.\n");
-    else
-    {
-        alGetSourcedvSOFT = alGetProcAddress("alGetSourcedvSOFT");
-        has_latency_check = true;
-    }
-
-
-    movState = av_mallocz(sizeof(MovieState));
-
-    av_strlcpy(movState->filename, argv[1], sizeof(movState->filename));
-
-    packet_queue_init(&movState->audio.q);
-    packet_queue_init(&movState->video.q);
-
-    almtx_init(&movState->video.pictq_mutex, almtx_plain);
-    alcnd_init(&movState->video.pictq_cond);
-    almtx_init(&movState->audio.src_mutex, almtx_recursive);
-
-    movState->av_sync_type = DEFAULT_AV_SYNC_TYPE;
-
-    movState->pFormatCtx = avformat_alloc_context();
-    movState->pFormatCtx->interrupt_callback = (AVIOInterruptCB){.callback=decode_interrupt_cb, .opaque=movState};
-
-    if(avio_open2(&movState->pFormatCtx->pb, movState->filename, AVIO_FLAG_READ,
-                  &movState->pFormatCtx->interrupt_callback, NULL))
-    {
-        fprintf(stderr, "Failed to open %s\n", movState->filename);
-        return 1;
-    }
-
-    /* Open movie file */
-    if(avformat_open_input(&movState->pFormatCtx, movState->filename, NULL, NULL) != 0)
-    {
-        fprintf(stderr, "Failed to open %s\n", movState->filename);
-        return 1;
-    }
-
-    /* Retrieve stream information */
-    if(avformat_find_stream_info(movState->pFormatCtx, NULL) < 0)
-    {
-        fprintf(stderr, "%s: failed to find stream info\n", movState->filename);
-        return 1;
-    }
-
-    schedule_refresh(movState, 40);
-
-
-    if(althrd_create(&movState->parse_thread, decode_thread, movState) != althrd_success)
-    {
-        fprintf(stderr, "Failed to create parse thread!\n");
-        return 1;
-    }
-    while(SDL_WaitEvent(&event) == 1)
-    {
-        switch(event.type)
-        {
-            case SDL_KEYDOWN:
-                switch(event.key.keysym.sym)
-                {
-                    case SDLK_ESCAPE:
-                        movState->quit = true;
-                        break;
-
-                    case SDLK_LEFT:
-                        stream_seek(movState, -10.0);
-                        break;
-                    case SDLK_RIGHT:
-                        stream_seek(movState, 10.0);
-                        break;
-                    case SDLK_UP:
-                        stream_seek(movState, 30.0);
-                        break;
-                    case SDLK_DOWN:
-                        stream_seek(movState, -30.0);
-                        break;
-
-                    default:
-                        break;
-                }
-                break;
-
-            case SDL_WINDOWEVENT:
-                switch(event.window.event)
-                {
-                    case SDL_WINDOWEVENT_RESIZED:
-                        SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
-                        SDL_RenderFillRect(renderer, NULL);
-                        break;
-
-                    default:
-                        break;
-                }
-                break;
-
-            case SDL_QUIT:
-                movState->quit = true;
-                break;
-
-            case FF_UPDATE_EVENT:
-                update_picture(event.user.data1, &first_update, screen, renderer);
-                break;
-
-            case FF_REFRESH_EVENT:
-                video_refresh_timer(event.user.data1, screen, renderer);
-                break;
-
-            case FF_QUIT_EVENT:
-                althrd_join(movState->parse_thread, NULL);
-
-                avformat_close_input(&movState->pFormatCtx);
-
-                almtx_destroy(&movState->audio.src_mutex);
-                almtx_destroy(&movState->video.pictq_mutex);
-                alcnd_destroy(&movState->video.pictq_cond);
-                packet_queue_deinit(&movState->video.q);
-                packet_queue_deinit(&movState->audio.q);
-
-                alcMakeContextCurrent(NULL);
-                alcDestroyContext(context);
-                alcCloseDevice(device);
-
-                SDL_Quit();
-                exit(0);
-
-            default:
-                break;
-        }
-    }
-
-    fprintf(stderr, "SDL_WaitEvent error - %s\n", SDL_GetError());
-    return 1;
-}

+ 0 - 327
love/src/jni/openal-soft-1.17.0/examples/common/alhelpers.c

@@ -1,327 +0,0 @@
-/*
- * OpenAL Helpers
- *
- * Copyright (c) 2011 by Chris Robinson <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/* This file contains routines to help with some menial OpenAL-related tasks,
- * such as opening a device and setting up a context, closing the device and
- * destroying its context, converting between frame counts and byte lengths,
- * finding an appropriate buffer format, and getting readable strings for
- * channel configs and sample types. */
-
-#include <stdio.h>
-
-#include "AL/al.h"
-#include "AL/alc.h"
-#include "AL/alext.h"
-
-#include "alhelpers.h"
-
-
-/* InitAL opens the default device and sets up a context using default
- * attributes, making the program ready to call OpenAL functions. */
-int InitAL(void)
-{
-    ALCdevice *device;
-    ALCcontext *ctx;
-
-    /* Open and initialize a device with default settings */
-    device = alcOpenDevice(NULL);
-    if(!device)
-    {
-        fprintf(stderr, "Could not open a device!\n");
-        return 1;
-    }
-
-    ctx = alcCreateContext(device, NULL);
-    if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE)
-    {
-        if(ctx != NULL)
-            alcDestroyContext(ctx);
-        alcCloseDevice(device);
-        fprintf(stderr, "Could not set a context!\n");
-        return 1;
-    }
-
-    printf("Opened \"%s\"\n", alcGetString(device, ALC_DEVICE_SPECIFIER));
-    return 0;
-}
-
-/* CloseAL closes the device belonging to the current context, and destroys the
- * context. */
-void CloseAL(void)
-{
-    ALCdevice *device;
-    ALCcontext *ctx;
-
-    ctx = alcGetCurrentContext();
-    if(ctx == NULL)
-        return;
-
-    device = alcGetContextsDevice(ctx);
-
-    alcMakeContextCurrent(NULL);
-    alcDestroyContext(ctx);
-    alcCloseDevice(device);
-}
-
-
-/* GetFormat retrieves a compatible buffer format given the channel config and
- * sample type. If an alIsBufferFormatSupportedSOFT-compatible function is
- * provided, it will be called to find the closest-matching format from
- * AL_SOFT_buffer_samples. Returns AL_NONE (0) if no supported format can be
- * found. */
-ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT)
-{
-    ALenum format = AL_NONE;
-
-    /* If using AL_SOFT_buffer_samples, try looking through its formats */
-    if(palIsBufferFormatSupportedSOFT)
-    {
-        /* AL_SOFT_buffer_samples is more lenient with matching formats. The
-         * specified sample type does not need to match the returned format,
-         * but it is nice to try to get something close. */
-        if(type == AL_UNSIGNED_BYTE_SOFT || type == AL_BYTE_SOFT)
-        {
-            if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
-            else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
-            else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
-            else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
-            else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
-            else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
-        }
-        else if(type == AL_UNSIGNED_SHORT_SOFT || type == AL_SHORT_SOFT)
-        {
-            if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
-            else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
-            else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
-            else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
-            else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
-            else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
-        }
-        else if(type == AL_UNSIGNED_BYTE3_SOFT || type == AL_BYTE3_SOFT ||
-                type == AL_UNSIGNED_INT_SOFT || type == AL_INT_SOFT ||
-                type == AL_FLOAT_SOFT || type == AL_DOUBLE_SOFT)
-        {
-            if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
-            else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
-            else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
-            else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
-            else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
-            else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
-        }
-
-        if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
-            format = AL_NONE;
-
-        /* A matching format was not found or supported. Try 32-bit float. */
-        if(format == AL_NONE)
-        {
-            if(channels == AL_MONO_SOFT) format = AL_MONO32F_SOFT;
-            else if(channels == AL_STEREO_SOFT) format = AL_STEREO32F_SOFT;
-            else if(channels == AL_QUAD_SOFT) format = AL_QUAD32F_SOFT;
-            else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_32F_SOFT;
-            else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_32F_SOFT;
-            else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_32F_SOFT;
-
-            if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
-                format = AL_NONE;
-        }
-        /* 32-bit float not supported. Try 16-bit int. */
-        if(format == AL_NONE)
-        {
-            if(channels == AL_MONO_SOFT) format = AL_MONO16_SOFT;
-            else if(channels == AL_STEREO_SOFT) format = AL_STEREO16_SOFT;
-            else if(channels == AL_QUAD_SOFT) format = AL_QUAD16_SOFT;
-            else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_16_SOFT;
-            else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_16_SOFT;
-            else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_16_SOFT;
-
-            if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
-                format = AL_NONE;
-        }
-        /* 16-bit int not supported. Try 8-bit int. */
-        if(format == AL_NONE)
-        {
-            if(channels == AL_MONO_SOFT) format = AL_MONO8_SOFT;
-            else if(channels == AL_STEREO_SOFT) format = AL_STEREO8_SOFT;
-            else if(channels == AL_QUAD_SOFT) format = AL_QUAD8_SOFT;
-            else if(channels == AL_5POINT1_SOFT) format = AL_5POINT1_8_SOFT;
-            else if(channels == AL_6POINT1_SOFT) format = AL_6POINT1_8_SOFT;
-            else if(channels == AL_7POINT1_SOFT) format = AL_7POINT1_8_SOFT;
-
-            if(format != AL_NONE && !palIsBufferFormatSupportedSOFT(format))
-                format = AL_NONE;
-        }
-
-        return format;
-    }
-
-    /* We use the AL_EXT_MCFORMATS extension to provide output of Quad, 5.1,
-     * and 7.1 channel configs, AL_EXT_FLOAT32 for 32-bit float samples, and
-     * AL_EXT_DOUBLE for 64-bit float samples. */
-    if(type == AL_UNSIGNED_BYTE_SOFT)
-    {
-        if(channels == AL_MONO_SOFT)
-            format = AL_FORMAT_MONO8;
-        else if(channels == AL_STEREO_SOFT)
-            format = AL_FORMAT_STEREO8;
-        else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
-        {
-            if(channels == AL_QUAD_SOFT)
-                format = alGetEnumValue("AL_FORMAT_QUAD8");
-            else if(channels == AL_5POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_51CHN8");
-            else if(channels == AL_6POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_61CHN8");
-            else if(channels == AL_7POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_71CHN8");
-        }
-    }
-    else if(type == AL_SHORT_SOFT)
-    {
-        if(channels == AL_MONO_SOFT)
-            format = AL_FORMAT_MONO16;
-        else if(channels == AL_STEREO_SOFT)
-            format = AL_FORMAT_STEREO16;
-        else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
-        {
-            if(channels == AL_QUAD_SOFT)
-                format = alGetEnumValue("AL_FORMAT_QUAD16");
-            else if(channels == AL_5POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_51CHN16");
-            else if(channels == AL_6POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_61CHN16");
-            else if(channels == AL_7POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_71CHN16");
-        }
-    }
-    else if(type == AL_FLOAT_SOFT && alIsExtensionPresent("AL_EXT_FLOAT32"))
-    {
-        if(channels == AL_MONO_SOFT)
-            format = alGetEnumValue("AL_FORMAT_MONO_FLOAT32");
-        else if(channels == AL_STEREO_SOFT)
-            format = alGetEnumValue("AL_FORMAT_STEREO_FLOAT32");
-        else if(alIsExtensionPresent("AL_EXT_MCFORMATS"))
-        {
-            if(channels == AL_QUAD_SOFT)
-                format = alGetEnumValue("AL_FORMAT_QUAD32");
-            else if(channels == AL_5POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_51CHN32");
-            else if(channels == AL_6POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_61CHN32");
-            else if(channels == AL_7POINT1_SOFT)
-                format = alGetEnumValue("AL_FORMAT_71CHN32");
-        }
-    }
-    else if(type == AL_DOUBLE_SOFT && alIsExtensionPresent("AL_EXT_DOUBLE"))
-    {
-        if(channels == AL_MONO_SOFT)
-            format = alGetEnumValue("AL_FORMAT_MONO_DOUBLE");
-        else if(channels == AL_STEREO_SOFT)
-            format = alGetEnumValue("AL_FORMAT_STEREO_DOUBLE");
-    }
-
-    /* NOTE: It seems OSX returns -1 from alGetEnumValue for unknown enums, as
-     * opposed to 0. Correct it. */
-    if(format == -1)
-        format = 0;
-
-    return format;
-}
-
-
-void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
-                                    ALenum internalformat, ALsizei samples,
-                                    ALenum channels, ALenum type,
-                                    const ALvoid *data)
-{
-    alBufferData(buffer, internalformat, data,
-                 FramesToBytes(samples, channels, type),
-                 samplerate);
-}
-
-
-const char *ChannelsName(ALenum chans)
-{
-    switch(chans)
-    {
-    case AL_MONO_SOFT: return "Mono";
-    case AL_STEREO_SOFT: return "Stereo";
-    case AL_REAR_SOFT: return "Rear";
-    case AL_QUAD_SOFT: return "Quadraphonic";
-    case AL_5POINT1_SOFT: return "5.1 Surround";
-    case AL_6POINT1_SOFT: return "6.1 Surround";
-    case AL_7POINT1_SOFT: return "7.1 Surround";
-    }
-    return "Unknown Channels";
-}
-
-const char *TypeName(ALenum type)
-{
-    switch(type)
-    {
-    case AL_BYTE_SOFT: return "S8";
-    case AL_UNSIGNED_BYTE_SOFT: return "U8";
-    case AL_SHORT_SOFT: return "S16";
-    case AL_UNSIGNED_SHORT_SOFT: return "U16";
-    case AL_INT_SOFT: return "S32";
-    case AL_UNSIGNED_INT_SOFT: return "U32";
-    case AL_FLOAT_SOFT: return "Float32";
-    case AL_DOUBLE_SOFT: return "Float64";
-    }
-    return "Unknown Type";
-}
-
-
-ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type)
-{
-    switch(channels)
-    {
-    case AL_MONO_SOFT:    size *= 1; break;
-    case AL_STEREO_SOFT:  size *= 2; break;
-    case AL_REAR_SOFT:    size *= 2; break;
-    case AL_QUAD_SOFT:    size *= 4; break;
-    case AL_5POINT1_SOFT: size *= 6; break;
-    case AL_6POINT1_SOFT: size *= 7; break;
-    case AL_7POINT1_SOFT: size *= 8; break;
-    }
-
-    switch(type)
-    {
-    case AL_BYTE_SOFT:           size *= sizeof(ALbyte); break;
-    case AL_UNSIGNED_BYTE_SOFT:  size *= sizeof(ALubyte); break;
-    case AL_SHORT_SOFT:          size *= sizeof(ALshort); break;
-    case AL_UNSIGNED_SHORT_SOFT: size *= sizeof(ALushort); break;
-    case AL_INT_SOFT:            size *= sizeof(ALint); break;
-    case AL_UNSIGNED_INT_SOFT:   size *= sizeof(ALuint); break;
-    case AL_FLOAT_SOFT:          size *= sizeof(ALfloat); break;
-    case AL_DOUBLE_SOFT:         size *= sizeof(ALdouble); break;
-    }
-
-    return size;
-}
-
-ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type)
-{
-    return size / FramesToBytes(1, channels, type);
-}

+ 0 - 51
love/src/jni/openal-soft-1.17.0/examples/common/alhelpers.h

@@ -1,51 +0,0 @@
-#ifndef ALHELPERS_H
-#define ALHELPERS_H
-
-#ifndef _WIN32
-#include <unistd.h>
-#define Sleep(x) usleep((x)*1000)
-#else
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-
-#include "AL/alc.h"
-#include "AL/al.h"
-#include "AL/alext.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Some helper functions to get the name from the channel and type enums. */
-const char *ChannelsName(ALenum chans);
-const char *TypeName(ALenum type);
-
-/* Helpers to convert frame counts and byte lengths. */
-ALsizei FramesToBytes(ALsizei size, ALenum channels, ALenum type);
-ALsizei BytesToFrames(ALsizei size, ALenum channels, ALenum type);
-
-/* Retrieves a compatible buffer format given the channel configuration and
- * sample type. If an alIsBufferFormatSupportedSOFT-compatible function is
- * provided, it will be called to find the closest-matching format from
- * AL_SOFT_buffer_samples. Returns AL_NONE (0) if no supported format can be
- * found. */
-ALenum GetFormat(ALenum channels, ALenum type, LPALISBUFFERFORMATSUPPORTEDSOFT palIsBufferFormatSupportedSOFT);
-
-/* Loads samples into a buffer using the standard alBufferData call, but with a
- * LPALBUFFERSAMPLESSOFT-compatible prototype. Assumes internalformat is valid
- * for alBufferData, and that channels and type match it. */
-void AL_APIENTRY wrap_BufferSamples(ALuint buffer, ALuint samplerate,
-                                    ALenum internalformat, ALsizei samples,
-                                    ALenum channels, ALenum type,
-                                    const ALvoid *data);
-
-/* Easy device init/deinit functions. InitAL returns 0 on success. */
-int InitAL(void);
-void CloseAL(void);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ALHELPERS_H */

+ 0 - 164
love/src/jni/openal-soft-1.17.0/examples/common/sdl_sound.c

@@ -1,164 +0,0 @@
-/*
- * SDL_sound Decoder Helpers
- *
- * Copyright (c) 2013 by Chris Robinson <[email protected]>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-/* This file contains routines for helping to decode audio using SDL_sound.
- * There's very little OpenAL-specific code here.
- */
-#include "sdl_sound.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-#include <assert.h>
-
-#include <SDL_sound.h>
-
-#include "AL/al.h"
-#include "AL/alc.h"
-#include "AL/alext.h"
-
-#include "alhelpers.h"
-
-
-static int done_init = 0;
-
-FilePtr openAudioFile(const char *fname, size_t buftime_ms)
-{
-    FilePtr file;
-    ALuint rate;
-    Uint32 bufsize;
-    ALenum chans, type;
-
-    /* We need to make sure SDL_sound is initialized. */
-    if(!done_init)
-    {
-        Sound_Init();
-        done_init = 1;
-    }
-
-    file = Sound_NewSampleFromFile(fname, NULL, 0);
-    if(!file)
-    {
-        fprintf(stderr, "Failed to open %s: %s\n", fname, Sound_GetError());
-        return NULL;
-    }
-
-    if(getAudioInfo(file, &rate, &chans, &type) != 0)
-    {
-        Sound_FreeSample(file);
-        return NULL;
-    }
-
-    bufsize = FramesToBytes((ALsizei)(buftime_ms/1000.0*rate), chans, type);
-    if(Sound_SetBufferSize(file, bufsize) == 0)
-    {
-        fprintf(stderr, "Failed to set buffer size to %u bytes: %s\n", bufsize, Sound_GetError());
-        Sound_FreeSample(file);
-        return NULL;
-    }
-
-    return file;
-}
-
-void closeAudioFile(FilePtr file)
-{
-    if(file)
-        Sound_FreeSample(file);
-}
-
-
-int getAudioInfo(FilePtr file, ALuint *rate, ALenum *channels, ALenum *type)
-{
-    if(file->actual.channels == 1)
-        *channels = AL_MONO_SOFT;
-    else if(file->actual.channels == 2)
-        *channels = AL_STEREO_SOFT;
-    else
-    {
-        fprintf(stderr, "Unsupported channel count: %d\n", file->actual.channels);
-        return 1;
-    }
-
-    if(file->actual.format == AUDIO_U8)
-        *type = AL_UNSIGNED_BYTE_SOFT;
-    else if(file->actual.format == AUDIO_S8)
-        *type = AL_BYTE_SOFT;
-    else if(file->actual.format == AUDIO_U16LSB || file->actual.format == AUDIO_U16MSB)
-        *type = AL_UNSIGNED_SHORT_SOFT;
-    else if(file->actual.format == AUDIO_S16LSB || file->actual.format == AUDIO_S16MSB)
-        *type = AL_SHORT_SOFT;
-    else
-    {
-        fprintf(stderr, "Unsupported sample format: 0x%04x\n", file->actual.format);
-        return 1;
-    }
-
-    *rate = file->actual.rate;
-
-    return 0;
-}
-
-
-uint8_t *getAudioData(FilePtr file, size_t *length)
-{
-    *length = Sound_Decode(file);
-    if(*length == 0)
-        return NULL;
-    if((file->actual.format == AUDIO_U16LSB && AUDIO_U16LSB != AUDIO_U16SYS) ||
-       (file->actual.format == AUDIO_U16MSB && AUDIO_U16MSB != AUDIO_U16SYS) ||
-       (file->actual.format == AUDIO_S16LSB && AUDIO_S16LSB != AUDIO_S16SYS) ||
-       (file->actual.format == AUDIO_S16MSB && AUDIO_S16MSB != AUDIO_S16SYS))
-    {
-        /* Swap bytes if the decoded endianness doesn't match the system. */
-        char *buffer = file->buffer;
-        size_t i;
-        for(i = 0;i < *length;i+=2)
-        {
-            char b = buffer[i];
-            buffer[i] = buffer[i+1];
-            buffer[i+1] = b;
-        }
-    }
-    return file->buffer;
-}
-
-void *decodeAudioStream(FilePtr file, size_t *length)
-{
-    Uint32 got;
-    char *mem;
-
-    got = Sound_DecodeAll(file);
-    if(got == 0)
-    {
-        *length = 0;
-        return NULL;
-    }
-
-    mem = malloc(got);
-    memcpy(mem, file->buffer, got);
-
-    *length = got;
-    return mem;
-}

+ 0 - 43
love/src/jni/openal-soft-1.17.0/examples/common/sdl_sound.h

@@ -1,43 +0,0 @@
-#ifndef EXAMPLES_SDL_SOUND_H
-#define EXAMPLES_SDL_SOUND_H
-
-#include "AL/al.h"
-
-#include <SDL_sound.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Opaque handles to files and streams. Apps don't need to concern themselves
- * with the internals */
-typedef Sound_Sample *FilePtr;
-
-/* Opens a file with SDL_sound, and specifies the size of the sample buffer in
- * milliseconds. */
-FilePtr openAudioFile(const char *fname, size_t buftime_ms);
-
-/* Closes/frees an opened file */
-void closeAudioFile(FilePtr file);
-
-/* Returns information about the given audio stream. Returns 0 on success. */
-int getAudioInfo(FilePtr file, ALuint *rate, ALenum *channels, ALenum *type);
-
-/* Returns a pointer to the next available chunk of decoded audio. The size (in
- * bytes) of the returned data buffer is stored in 'length', and the returned
- * pointer is only valid until the next call to getAudioData. */
-uint8_t *getAudioData(FilePtr file, size_t *length);
-
-/* Decodes all remaining data from the stream and returns a buffer containing
- * the audio data, with the size stored in 'length'. The returned pointer must
- * be freed with a call to free(). Note that since this decodes the whole
- * stream, using it on lengthy streams (eg, music) will use a lot of memory.
- * Such streams are better handled using getAudioData to keep smaller chunks in
- * memory at any given time. */
-void *decodeAudioStream(FilePtr, size_t *length);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* EXAMPLES_SDL_SOUND_H */

BIN
love/src/jni/openal-soft-1.17.0/hrtf/default-44100.mhr


BIN
love/src/jni/openal-soft-1.17.0/hrtf/default-48000.mhr


+ 0 - 313
love/src/jni/openal-soft-1.17.0/include/atomic.h

@@ -1,313 +0,0 @@
-#ifndef AL_ATOMIC_H
-#define AL_ATOMIC_H
-
-#include "static_assert.h"
-#include "bool.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef void *volatile XchgPtr;
-
-/* Atomics using C11 */
-#ifdef HAVE_C11_ATOMIC
-
-#include <stdatomic.h>
-
-inline int ExchangeInt(volatile int *ptr, int newval)
-{ return atomic_exchange(ptr, newval); }
-inline void *ExchangePtr(XchgPtr *ptr, void *newval)
-{ return atomic_exchange(ptr, newval); }
-
-
-#define ATOMIC(T)  struct { T _Atomic value; }
-
-#define ATOMIC_INIT(_val, _newval) atomic_init(&(_val)->value, (_newval))
-#define ATOMIC_INIT_STATIC(_newval) {ATOMIC_VAR_INIT(_newval)}
-
-#define ATOMIC_LOAD(_val)            atomic_load(&(_val)->value)
-#define ATOMIC_STORE(_val, _newval)  atomic_store(&(_val)->value, (_newval))
-
-#define ATOMIC_ADD(T, _val, _incr) atomic_fetch_add(&(_val)->value, (_incr))
-#define ATOMIC_SUB(T, _val, _decr) atomic_fetch_sub(&(_val)->value, (_decr))
-
-#define ATOMIC_EXCHANGE(T, _val, _newval) atomic_exchange(&(_val)->value, (_newval))
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval)             \
-    atomic_compare_exchange_strong(&(_val)->value, (_oldval), (_newval))
-#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, _val, _oldval, _newval)               \
-    atomic_compare_exchange_weak(&(_val)->value, (_oldval), (_newval))
-
-/* Atomics using GCC intrinsics */
-#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__QNXNTO__)
-
-inline int ExchangeInt(volatile int *ptr, int newval)
-{ return __sync_lock_test_and_set(ptr, newval); }
-inline void *ExchangePtr(XchgPtr *ptr, void *newval)
-{ return __sync_lock_test_and_set(ptr, newval); }
-
-
-#define ATOMIC(T)  struct { T volatile value; }
-
-#define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
-#define ATOMIC_INIT_STATIC(_newval) {(_newval)}
-
-#define ATOMIC_LOAD(_val)  __extension__({      \
-    __typeof((_val)->value) _r = (_val)->value; \
-    __asm__ __volatile__("" ::: "memory");      \
-    _r;                                         \
-})
-#define ATOMIC_STORE(_val, _newval)  do {  \
-    __asm__ __volatile__("" ::: "memory"); \
-    (_val)->value = (_newval);             \
-} while(0)
-
-#define ATOMIC_ADD(T, _val, _incr)  __extension__({                           \
-    static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
-    __sync_fetch_and_add(&(_val)->value, (_incr));                            \
-})
-#define ATOMIC_SUB(T, _val, _decr)  __extension__({                           \
-    static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
-    __sync_fetch_and_sub(&(_val)->value, (_decr));                            \
-})
-
-#define ATOMIC_EXCHANGE(T, _val, _newval)  __extension__({                    \
-    static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
-    __sync_lock_test_and_set(&(_val)->value, (_newval));                      \
-})
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) __extension__({ \
-    static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
-    T _o = *(_oldval);                                                        \
-    *(_oldval) = __sync_val_compare_and_swap(&(_val)->value, _o, (_newval));  \
-    *(_oldval) == _o;                                                         \
-})
-
-/* Atomics using x86/x86-64 GCC inline assembly */
-#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-
-#define WRAP_ADD(ret, dest, incr) __asm__ __volatile__(                       \
-    "lock; xaddl %0,(%1)"                                                     \
-    : "=r" (ret)                                                              \
-    : "r" (dest), "0" (incr)                                                  \
-    : "memory"                                                                \
-)
-#define WRAP_SUB(ret, dest, decr) __asm__ __volatile__(                       \
-    "lock; xaddl %0,(%1)"                                                     \
-    : "=r" (ret)                                                              \
-    : "r" (dest), "0" (-(decr))                                               \
-    : "memory"                                                                \
-)
-
-#define WRAP_XCHG(S, ret, dest, newval) __asm__ __volatile__(                 \
-    "lock; xchg"S" %0,(%1)"                                                   \
-    : "=r" (ret)                                                              \
-    : "r" (dest), "0" (newval)                                                \
-    : "memory"                                                                \
-)
-#define WRAP_CMPXCHG(S, ret, dest, oldval, newval) __asm__ __volatile__(      \
-    "lock; cmpxchg"S" %2,(%1)"                                                \
-    : "=a" (ret)                                                              \
-    : "r" (dest), "r" (newval), "0" (oldval)                                  \
-    : "memory"                                                                \
-)
-
-
-inline int ExchangeInt(volatile int *dest, int newval)
-{ int ret; WRAP_XCHG("l", ret, dest, newval); return ret; }
-
-#ifdef __i386__
-inline void *ExchangePtr(XchgPtr *dest, void *newval)
-{ void *ret; WRAP_XCHG("l", ret, dest, newval); return ret; }
-#else
-inline void *ExchangePtr(XchgPtr *dest, void *newval)
-{ void *ret; WRAP_XCHG("q", ret, dest, newval); return ret; }
-#endif
-
-
-#define ATOMIC(T)  struct { T volatile value; }
-
-#define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
-#define ATOMIC_INIT_STATIC(_newval) {(_newval)}
-
-#define ATOMIC_LOAD(_val)  __extension__({      \
-    __typeof((_val)->value) _r = (_val)->value; \
-    __asm__ __volatile__("" ::: "memory");      \
-    _r;                                         \
-})
-#define ATOMIC_STORE(_val, _newval)  do {  \
-    __asm__ __volatile__("" ::: "memory"); \
-    (_val)->value = (_newval);             \
-} while(0)
-
-#define ATOMIC_ADD(T, _val, _incr)  __extension__({                           \
-    static_assert(sizeof(T)==4, "Type "#T" has incorrect size!");             \
-    static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
-    T _r;                                                                     \
-    WRAP_ADD(_r, &(_val)->value, (T)(_incr));                                 \
-    _r;                                                                       \
-})
-#define ATOMIC_SUB(T, _val, _decr)  __extension__({                           \
-    static_assert(sizeof(T)==4, "Type "#T" has incorrect size!");             \
-    static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
-    T _r;                                                                     \
-    WRAP_SUB(_r, &(_val)->value, (T)(_decr));                                 \
-    _r;                                                                       \
-})
-
-#define ATOMIC_EXCHANGE(T, _val, _newval)  __extension__({                    \
-    static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \
-    static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
-    T _r;                                                                     \
-    if(sizeof(T) == 4) WRAP_XCHG("l", _r, &(_val)->value, (T)(_newval));      \
-    else if(sizeof(T) == 8) WRAP_XCHG("q", _r, &(_val)->value, (T)(_newval)); \
-    _r;                                                                       \
-})
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) __extension__({ \
-    static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \
-    static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \
-    T _old = *(_oldval);                                                      \
-    if(sizeof(T) == 4) WRAP_CMPXCHG("l", *(_oldval), &(_val)->value, _old, (T)(_newval)); \
-    else if(sizeof(T) == 8) WRAP_CMPXCHG("q", *(_oldval), &(_val)->value, _old, (T)(_newval)); \
-    *(_oldval) == _old;                                                       \
-})
-
-/* Atomics using Windows methods */
-#elif defined(_WIN32)
-
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-
-/* NOTE: This mess is *extremely* noisy, at least on GCC. It works by wrapping
- * Windows' 32-bit and 64-bit atomic methods, which are then casted to use the
- * given type based on its size (e.g. int and float use 32-bit atomics). This
- * is fine for the swap and compare-and-swap methods, although the add and
- * subtract methods only work properly for integer types.
- *
- * Despite how noisy it is, it's unfortunately the only way that doesn't rely
- * on C99 (damn MSVC).
- */
-
-inline LONG AtomicAdd32(volatile LONG *dest, LONG incr)
-{
-    return InterlockedExchangeAdd(dest, incr);
-}
-inline LONG AtomicSub32(volatile LONG *dest, LONG decr)
-{
-    return InterlockedExchangeAdd(dest, -decr);
-}
-
-inline LONG AtomicSwap32(volatile LONG *dest, LONG newval)
-{
-    return InterlockedExchange(dest, newval);
-}
-inline LONGLONG AtomicSwap64(volatile LONGLONG *dest, LONGLONG newval)
-{
-    return InterlockedExchange64(dest, newval);
-}
-
-inline bool CompareAndSwap32(volatile LONG *dest, LONG newval, LONG *oldval)
-{
-    LONG old = *oldval;
-    *oldval = InterlockedCompareExchange(dest, newval, *oldval);
-    return old == *oldval;
-}
-inline bool CompareAndSwap64(volatile LONGLONG *dest, LONGLONG newval, LONGLONG *oldval)
-{
-    LONGLONG old = *oldval;
-    *oldval = InterlockedCompareExchange64(dest, newval, *oldval);
-    return old == *oldval;
-}
-
-#define WRAP_ADDSUB(T, _func, _ptr, _amnt)  ((T(*)(T volatile*,T))_func)((_ptr), (_amnt))
-#define WRAP_XCHG(T, _func, _ptr, _newval)  ((T(*)(T volatile*,T))_func)((_ptr), (_newval))
-#define WRAP_CMPXCHG(T, _func, _ptr, _newval, _oldval) ((bool(*)(T volatile*,T,T*))_func)((_ptr), (_newval), (_oldval))
-
-inline int ExchangeInt(volatile int *ptr, int newval)
-{ return WRAP_XCHG(int,AtomicSwap32,ptr,newval); }
-
-#ifdef _WIN64
-inline void *ExchangePtr(XchgPtr *ptr, void *newval)
-{ return WRAP_XCHG(void*,AtomicSwap64,ptr,newval); }
-#else
-inline void *ExchangePtr(XchgPtr *ptr, void *newval)
-{ return WRAP_XCHG(void*,AtomicSwap32,ptr,newval); }
-#endif
-
-
-#define ATOMIC(T)  struct { T volatile value; }
-
-#define ATOMIC_INIT(_val, _newval)  do { (_val)->value = (_newval); } while(0)
-#define ATOMIC_INIT_STATIC(_newval) {(_newval)}
-
-#define ATOMIC_LOAD(_val)  ((_val)->value)
-#define ATOMIC_STORE(_val, _newval)  do {  \
-    (_val)->value = (_newval);             \
-} while(0)
-
-int _al_invalid_atomic_size(); /* not defined */
-
-#define ATOMIC_ADD(T, _val, _incr)                                            \
-    ((sizeof(T)==4) ? WRAP_ADDSUB(T, AtomicAdd32, &(_val)->value, (_incr)) :  \
-     (T)_al_invalid_atomic_size())
-#define ATOMIC_SUB(T, _val, _decr)                                            \
-    ((sizeof(T)==4) ? WRAP_ADDSUB(T, AtomicSub32, &(_val)->value, (_decr)) :  \
-     (T)_al_invalid_atomic_size())
-
-#define ATOMIC_EXCHANGE(T, _val, _newval)                                     \
-    ((sizeof(T)==4) ? WRAP_XCHG(T, AtomicSwap32, &(_val)->value, (_newval)) : \
-     (sizeof(T)==8) ? WRAP_XCHG(T, AtomicSwap64, &(_val)->value, (_newval)) : \
-     (T)_al_invalid_atomic_size())
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval)             \
-    ((sizeof(T)==4) ? WRAP_CMPXCHG(T, CompareAndSwap32, &(_val)->value, (_newval), (_oldval)) : \
-     (sizeof(T)==8) ? WRAP_CMPXCHG(T, CompareAndSwap64, &(_val)->value, (_newval), (_oldval)) : \
-     (bool)_al_invalid_atomic_size())
-
-#else
-
-#error "No atomic functions available on this platform!"
-
-#define ATOMIC(T)  T
-
-#define ATOMIC_INIT_STATIC(_newval) (0)
-
-#define ATOMIC_LOAD_UNSAFE(_val)  (0)
-#define ATOMIC_STORE_UNSAFE(_val, _newval)  ((void)0)
-
-#define ATOMIC_LOAD(_val)  (0)
-#define ATOMIC_STORE(_val, _newval)  ((void)0)
-
-#define ATOMIC_ADD(T, _val, _incr)  (0)
-#define ATOMIC_SUB(T, _val, _decr)  (0)
-
-#define ATOMIC_EXCHANGE(T, _val, _newval)  (0)
-#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) (0)
-#endif
-
-/* If no weak cmpxchg is provided (not all systems will have one), substitute a
- * strong cmpxchg. */
-#ifndef ATOMIC_COMPARE_EXCHANGE_WEAK
-#define ATOMIC_COMPARE_EXCHANGE_WEAK(a, b, c, d) ATOMIC_COMPARE_EXCHANGE_STRONG(a, b, c, d)
-#endif
-
-/* This is *NOT* atomic, but is a handy utility macro to compare-and-swap non-
- * atomic variables. */
-#define COMPARE_EXCHANGE(_val, _oldval, _newval)  ((*(_val) == *(_oldval)) ? ((*(_val)=(_newval)),true) : ((*(_oldval)=*(_val)),false))
-
-
-typedef unsigned int uint;
-typedef ATOMIC(uint) RefCount;
-
-inline void InitRef(RefCount *ptr, uint value)
-{ ATOMIC_INIT(ptr, value); }
-inline uint ReadRef(RefCount *ptr)
-{ return ATOMIC_LOAD(ptr); }
-inline uint IncrementRef(RefCount *ptr)
-{ return ATOMIC_ADD(uint, ptr, 1)+1; }
-inline uint DecrementRef(RefCount *ptr)
-{ return ATOMIC_SUB(uint, ptr, 1)-1; }
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* AL_ATOMIC_H */

+ 0 - 29
love/src/jni/openal-soft-1.17.0/utils/alsoft-config/CMakeLists.txt

@@ -1,29 +0,0 @@
-project(alsoft-config)
-
-include_directories("${alsoft-config_BINARY_DIR}")
-
-# Need Qt 4.8.0 or newer for the iconset theme attribute to work
-find_package(Qt4 4.8.0 COMPONENTS QtCore QtGui)
-if(QT4_FOUND)
-    include(${QT_USE_FILE})
-
-    set(alsoft-config_SRCS  main.cpp
-                            mainwindow.cpp
-        )
-
-    set(alsoft-config_UIS  mainwindow.ui)
-    QT4_WRAP_UI(UIS ${alsoft-config_UIS})
-
-    set(alsoft-config_MOCS  mainwindow.h)
-    QT4_WRAP_CPP(MOCS ${alsoft-config_MOCS})
-
-    add_executable(alsoft-config ${alsoft-config_SRCS} ${UIS} ${RSCS} ${TRS} ${MOCS})
-    target_link_libraries(alsoft-config ${QT_LIBRARIES})
-    set_target_properties(alsoft-config PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${OpenAL_BINARY_DIR})
-
-    install(TARGETS alsoft-config
-            RUNTIME DESTINATION bin
-            LIBRARY DESTINATION "lib${LIB_SUFFIX}"
-            ARCHIVE DESTINATION "lib${LIB_SUFFIX}"
-    )
-endif()

+ 0 - 660
love/src/jni/openal-soft-1.17.0/utils/alsoft-config/mainwindow.cpp

@@ -1,660 +0,0 @@
-#include <QFileDialog>
-#include <QMessageBox>
-#include <QSettings>
-#include <QtGlobal>
-#include "mainwindow.h"
-#include "ui_mainwindow.h"
-
-namespace {
-static const struct {
-    char backend_name[16];
-    char menu_string[32];
-} backendMenuList[] = {
-#ifdef Q_OS_WIN32
-    { "mmdevapi", "Add MMDevAPI" },
-    { "dsound", "Add DirectSound" },
-    { "winmm", "Add Windows Multimedia" },
-#endif
-#ifdef Q_OS_MAC
-    { "core", "Add CoreAudio" },
-#endif
-    { "pulse", "Add PulseAudio" },
-#ifdef Q_OS_UNIX
-    { "alsa", "Add ALSA" },
-    { "oss", "Add OSS" },
-    { "solaris", "Add Solaris" },
-    { "sndio", "Add SndIO" },
-    { "qsa", "Add QSA" },
-#endif
-    { "port", "Add PortAudio" },
-    { "opensl", "Add OpenSL" },
-    { "null", "Add Null Output" },
-    { "wave", "Add Wave Writer" },
-    { "", "" }
-};
-
-static QString getDefaultConfigName()
-{
-#ifdef Q_OS_WIN32
-    static const char fname[] = "alsoft.ini";
-    QByteArray base = qgetenv("AppData");
-#else
-    static const char fname[] = "alsoft.conf";
-    QByteArray base = qgetenv("XDG_CONFIG_HOME");
-    if(base.isEmpty())
-    {
-        base = qgetenv("HOME");
-        if(base.isEmpty() == false)
-            base += "/.config";
-    }
-#endif
-    if(base.isEmpty() == false)
-        return base +'/'+ fname;
-    return fname;
-}
-
-static QString getBaseDataPath()
-{
-#ifdef Q_OS_WIN32
-    QByteArray base = qgetenv("AppData");
-#else
-    QByteArray base = qgetenv("XDG_DATA_HOME");
-    if(base.isEmpty())
-    {
-        base = qgetenv("HOME");
-        if(!base.isEmpty())
-            base += "/.local/share";
-    }
-#endif
-    return base;
-}
-
-static QStringList getAllDataPaths(QString append=QString())
-{
-    QStringList list;
-    list.append(getBaseDataPath());
-#ifdef Q_OS_WIN32
-    // TODO: Common AppData path
-#else
-    QString paths = qgetenv("XDG_DATA_DIRS");
-    if(paths.isEmpty())
-        paths = "/usr/local/share/:/usr/share/";
-    list += paths.split(QChar(':'), QString::SkipEmptyParts);
-#endif
-    QStringList::iterator iter = list.begin();
-    while(iter != list.end())
-    {
-        if(iter->isEmpty())
-            iter = list.erase(iter);
-        else
-        {
-            iter->append(append);
-            iter++;
-        }
-    }
-    return list;
-}
-}
-
-MainWindow::MainWindow(QWidget *parent) :
-    QMainWindow(parent),
-    ui(new Ui::MainWindow),
-    mPeriodSizeValidator(NULL),
-    mPeriodCountValidator(NULL),
-    mSourceCountValidator(NULL),
-    mEffectSlotValidator(NULL),
-    mSourceSendValidator(NULL),
-    mSampleRateValidator(NULL),
-    mReverbBoostValidator(NULL)
-{
-    ui->setupUi(this);
-
-    mPeriodSizeValidator = new QIntValidator(64, 8192, this);
-    ui->periodSizeEdit->setValidator(mPeriodSizeValidator);
-    mPeriodCountValidator = new QIntValidator(2, 16, this);
-    ui->periodCountEdit->setValidator(mPeriodCountValidator);
-
-    mSourceCountValidator = new QIntValidator(0, 256, this);
-    ui->srcCountLineEdit->setValidator(mSourceCountValidator);
-    mEffectSlotValidator = new QIntValidator(0, 16, this);
-    ui->effectSlotLineEdit->setValidator(mEffectSlotValidator);
-    mSourceSendValidator = new QIntValidator(0, 4, this);
-    ui->srcSendLineEdit->setValidator(mSourceSendValidator);
-    mSampleRateValidator = new QIntValidator(8000, 192000, this);
-    ui->sampleRateCombo->lineEdit()->setValidator(mSampleRateValidator);
-
-    mReverbBoostValidator = new QDoubleValidator(-12.0, +12.0, 1, this);
-    ui->reverbBoostEdit->setValidator(mReverbBoostValidator);
-
-    connect(ui->actionLoad, SIGNAL(triggered()), this, SLOT(loadConfigFromFile()));
-    connect(ui->actionSave_As, SIGNAL(triggered()), this, SLOT(saveConfigAsFile()));
-
-    connect(ui->applyButton, SIGNAL(clicked()), this, SLOT(saveCurrentConfig()));
-
-    connect(ui->periodSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(updatePeriodSizeEdit(int)));
-    connect(ui->periodSizeEdit, SIGNAL(editingFinished()), this, SLOT(updatePeriodSizeSlider()));
-    connect(ui->periodCountSlider, SIGNAL(valueChanged(int)), this, SLOT(updatePeriodCountEdit(int)));
-    connect(ui->periodCountEdit, SIGNAL(editingFinished()), this, SLOT(updatePeriodCountSlider()));
-
-    connect(ui->hrtfAddButton, SIGNAL(clicked()), this, SLOT(addHrtfFile()));
-    connect(ui->hrtfRemoveButton, SIGNAL(clicked()), this, SLOT(removeHrtfFile()));
-    connect(ui->hrtfFileList, SIGNAL(itemSelectionChanged()), this, SLOT(updateHrtfRemoveButton()));
-
-    ui->enabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(ui->enabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showEnabledBackendMenu(QPoint)));
-
-    ui->disabledBackendList->setContextMenuPolicy(Qt::CustomContextMenu);
-    connect(ui->disabledBackendList, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showDisabledBackendMenu(QPoint)));
-
-    connect(ui->reverbBoostSlider, SIGNAL(valueChanged(int)), this, SLOT(updateReverbBoostEdit(int)));
-    connect(ui->reverbBoostEdit, SIGNAL(textEdited(QString)), this, SLOT(updateReverbBoostSlider(QString)));
-
-    loadConfig(getDefaultConfigName());
-}
-
-MainWindow::~MainWindow()
-{
-    delete ui;
-    delete mPeriodSizeValidator;
-    delete mPeriodCountValidator;
-    delete mSourceCountValidator;
-    delete mEffectSlotValidator;
-    delete mSourceSendValidator;
-    delete mSampleRateValidator;
-    delete mReverbBoostValidator;
-}
-
-void MainWindow::loadConfigFromFile()
-{
-    QString fname = QFileDialog::getOpenFileName(this, tr("Select Files"));
-    if(fname.isEmpty() == false)
-        loadConfig(fname);
-}
-
-void MainWindow::loadConfig(const QString &fname)
-{
-    QSettings settings(fname, QSettings::IniFormat);
-
-    QString sampletype = settings.value("sample-type").toString();
-    ui->sampleFormatCombo->setCurrentIndex(0);
-    if(sampletype.isEmpty() == false)
-    {
-        for(int i = 1;i < ui->sampleFormatCombo->count();i++)
-        {
-            QString item = ui->sampleFormatCombo->itemText(i);
-            if(item.startsWith(sampletype))
-            {
-                ui->sampleFormatCombo->setCurrentIndex(i);
-                break;
-            }
-        }
-    }
-
-    QString channelconfig = settings.value("channels").toString();
-    ui->channelConfigCombo->setCurrentIndex(0);
-    if(channelconfig.isEmpty() == false)
-    {
-        for(int i = 1;i < ui->channelConfigCombo->count();i++)
-        {
-            QString item = ui->channelConfigCombo->itemText(i);
-            if(item.startsWith(channelconfig))
-            {
-                ui->channelConfigCombo->setCurrentIndex(i);
-                break;
-            }
-        }
-    }
-
-    QString srate = settings.value("frequency").toString();
-    if(srate.isEmpty())
-        ui->sampleRateCombo->setCurrentIndex(0);
-    else
-    {
-        ui->sampleRateCombo->lineEdit()->clear();
-        ui->sampleRateCombo->lineEdit()->insert(srate);
-    }
-
-    ui->srcCountLineEdit->clear();
-    ui->srcCountLineEdit->insert(settings.value("sources").toString());
-    ui->effectSlotLineEdit->clear();
-    ui->effectSlotLineEdit->insert(settings.value("slots").toString());
-    ui->srcSendLineEdit->clear();
-    ui->srcSendLineEdit->insert(settings.value("sends").toString());
-
-    QString resampler = settings.value("resampler").toString().trimmed();
-    if(resampler.isEmpty())
-        ui->resamplerComboBox->setCurrentIndex(0);
-    else
-    {
-        for(int i = 1;i < ui->resamplerComboBox->count();i++)
-        {
-            QString item = ui->resamplerComboBox->itemText(i);
-            int end = item.indexOf(' ');
-            if(end < 0) end = item.size();
-            if(resampler.size() == end && resampler.compare(item.leftRef(end), Qt::CaseInsensitive) == 0)
-            {
-                ui->resamplerComboBox->setCurrentIndex(i);
-                break;
-            }
-        }
-    }
-
-    int periodsize = settings.value("period_size").toInt();
-    ui->periodSizeEdit->clear();
-    if(periodsize >= 64)
-    {
-        ui->periodSizeEdit->insert(QString::number(periodsize));
-        updatePeriodSizeSlider();
-    }
-
-    int periodcount = settings.value("periods").toInt();
-    ui->periodCountEdit->clear();
-    if(periodcount >= 2)
-    {
-        ui->periodCountEdit->insert(QString::number(periodcount));
-        updatePeriodCountSlider();
-    }
-
-    QStringList disabledCpuExts = settings.value("disable-cpu-exts").toStringList();
-    if(disabledCpuExts.size() == 1)
-        disabledCpuExts = disabledCpuExts[0].split(QChar(','));
-    std::transform(disabledCpuExts.begin(), disabledCpuExts.end(),
-                   disabledCpuExts.begin(), std::mem_fun_ref(&QString::trimmed));
-    ui->enableSSECheckBox->setChecked(!disabledCpuExts.contains("sse", Qt::CaseInsensitive));
-    ui->enableSSE2CheckBox->setChecked(!disabledCpuExts.contains("sse2", Qt::CaseInsensitive));
-    ui->enableSSE41CheckBox->setChecked(!disabledCpuExts.contains("sse4.1", Qt::CaseInsensitive));
-    ui->enableNeonCheckBox->setChecked(!disabledCpuExts.contains("neon", Qt::CaseInsensitive));
-
-    if(settings.value("hrtf").toString() == QString())
-        ui->hrtfEnableButton->setChecked(true);
-    else
-    {
-        if(settings.value("hrtf", true).toBool())
-            ui->hrtfForceButton->setChecked(true);
-        else
-            ui->hrtfDisableButton->setChecked(true);
-    }
-
-    QStringList hrtf_tables = settings.value("hrtf_tables").toStringList();
-    if(hrtf_tables.size() == 1)
-        hrtf_tables = hrtf_tables[0].split(QChar(','));
-    std::transform(hrtf_tables.begin(), hrtf_tables.end(),
-                   hrtf_tables.begin(), std::mem_fun_ref(&QString::trimmed));
-    ui->hrtfFileList->clear();
-    ui->hrtfFileList->addItems(hrtf_tables);
-    updateHrtfRemoveButton();
-
-    ui->enabledBackendList->clear();
-    ui->disabledBackendList->clear();
-    QStringList drivers = settings.value("drivers").toStringList();
-    if(drivers.size() == 0)
-        ui->backendCheckBox->setChecked(true);
-    else
-    {
-        if(drivers.size() == 1)
-            drivers = drivers[0].split(QChar(','));
-        std::transform(drivers.begin(), drivers.end(),
-                       drivers.begin(), std::mem_fun_ref(&QString::trimmed));
-
-        bool lastWasEmpty = false;
-        foreach(const QString &backend, drivers)
-        {
-            lastWasEmpty = backend.isEmpty();
-            if(!backend.startsWith(QChar('-')) && !lastWasEmpty)
-                ui->enabledBackendList->addItem(backend);
-            else if(backend.size() > 1)
-                ui->disabledBackendList->addItem(backend.right(backend.size()-1));
-        }
-        ui->backendCheckBox->setChecked(lastWasEmpty);
-    }
-
-    QString defaultreverb = settings.value("default-reverb").toString().toLower();
-    ui->defaultReverbComboBox->setCurrentIndex(0);
-    if(defaultreverb.isEmpty() == false)
-    {
-        for(int i = 0;i < ui->defaultReverbComboBox->count();i++)
-        {
-            if(defaultreverb.compare(ui->defaultReverbComboBox->itemText(i).toLower()) == 0)
-            {
-                ui->defaultReverbComboBox->setCurrentIndex(i);
-                break;
-            }
-        }
-    }
-
-    ui->emulateEaxCheckBox->setChecked(settings.value("reverb/emulate-eax", false).toBool());
-    ui->reverbBoostEdit->clear();
-    ui->reverbBoostEdit->insert(settings.value("reverb/boost").toString());
-
-    QStringList excludefx = settings.value("excludefx").toStringList();
-    if(excludefx.size() == 1)
-        excludefx = excludefx[0].split(QChar(','));
-    std::transform(excludefx.begin(), excludefx.end(),
-                   excludefx.begin(), std::mem_fun_ref(&QString::trimmed));
-    ui->enableEaxReverbCheck->setChecked(!excludefx.contains("eaxreverb", Qt::CaseInsensitive));
-    ui->enableStdReverbCheck->setChecked(!excludefx.contains("reverb", Qt::CaseInsensitive));
-    ui->enableChorusCheck->setChecked(!excludefx.contains("chorus", Qt::CaseInsensitive));
-    ui->enableCompressorCheck->setChecked(!excludefx.contains("compressor", Qt::CaseInsensitive));
-    ui->enableDistortionCheck->setChecked(!excludefx.contains("distortion", Qt::CaseInsensitive));
-    ui->enableEchoCheck->setChecked(!excludefx.contains("echo", Qt::CaseInsensitive));
-    ui->enableEqualizerCheck->setChecked(!excludefx.contains("equalizer", Qt::CaseInsensitive));
-    ui->enableFlangerCheck->setChecked(!excludefx.contains("flanger", Qt::CaseInsensitive));
-    ui->enableModulatorCheck->setChecked(!excludefx.contains("modulator", Qt::CaseInsensitive));
-    ui->enableDedicatedCheck->setChecked(!excludefx.contains("dedicated", Qt::CaseInsensitive));
-}
-
-void MainWindow::saveCurrentConfig()
-{
-    saveConfig(getDefaultConfigName());
-    QMessageBox::information(this, tr("Information"),
-                             tr("Applications using OpenAL need to be restarted for changes to take effect."));
-}
-
-void MainWindow::saveConfigAsFile()
-{
-    QString fname = QFileDialog::getOpenFileName(this, tr("Select Files"));
-    if(fname.isEmpty() == false)
-        saveConfig(fname);
-}
-
-void MainWindow::saveConfig(const QString &fname) const
-{
-    QSettings settings(fname, QSettings::IniFormat);
-
-    /* HACK: Compound any stringlist values into a comma-separated string. */
-    QStringList allkeys = settings.allKeys();
-    foreach(const QString &key, allkeys)
-    {
-        QStringList vals = settings.value(key).toStringList();
-        if(vals.size() > 1)
-            settings.setValue(key, vals.join(QChar(',')));
-    }
-
-    QString str = ui->sampleFormatCombo->currentText();
-    str.truncate(str.indexOf('-'));
-    settings.setValue("sample-type", str.trimmed());
-
-    str = ui->channelConfigCombo->currentText();
-    str.truncate(str.indexOf('-'));
-    settings.setValue("channels", str.trimmed());
-
-    uint rate = ui->sampleRateCombo->currentText().toUInt();
-    if(rate == 0)
-        settings.setValue("frequency", QString());
-    else
-        settings.setValue("frequency", rate);
-
-    settings.setValue("period_size", ui->periodSizeEdit->text());
-    settings.setValue("periods", ui->periodCountEdit->text());
-
-    settings.setValue("sources", ui->srcCountLineEdit->text());
-    settings.setValue("slots", ui->effectSlotLineEdit->text());
-
-    if(ui->resamplerComboBox->currentIndex() == 0)
-        settings.setValue("resampler", QString());
-    else
-    {
-        str = ui->resamplerComboBox->currentText();
-        settings.setValue("resampler", str.split(' ').first().toLower());
-    }
-
-    QStringList strlist;
-    if(!ui->enableSSECheckBox->isChecked())
-        strlist.append("sse");
-    if(!ui->enableSSE2CheckBox->isChecked())
-        strlist.append("sse2");
-    if(!ui->enableSSE41CheckBox->isChecked())
-        strlist.append("sse4.1");
-    if(!ui->enableNeonCheckBox->isChecked())
-        strlist.append("neon");
-    settings.setValue("disable-cpu-exts", strlist.join(QChar(',')));
-
-    if(ui->hrtfForceButton->isChecked())
-        settings.setValue("hrtf", "true");
-    else if(ui->hrtfDisableButton->isChecked())
-        settings.setValue("hrtf", "false");
-    else
-        settings.setValue("hrtf", QString());
-
-    strlist.clear();
-    QList<QListWidgetItem*> items = ui->hrtfFileList->findItems("*", Qt::MatchWildcard);
-    foreach(const QListWidgetItem *item, items)
-        strlist.append(item->text());
-    settings.setValue("hrtf_tables", strlist.join(QChar(',')));
-
-    strlist.clear();
-    items = ui->enabledBackendList->findItems("*", Qt::MatchWildcard);
-    foreach(const QListWidgetItem *item, items)
-        strlist.append(item->text());
-    items = ui->disabledBackendList->findItems("*", Qt::MatchWildcard);
-    foreach(const QListWidgetItem *item, items)
-        strlist.append(QChar('-')+item->text());
-    if(strlist.size() == 0 && !ui->backendCheckBox->isChecked())
-        strlist.append("-all");
-    else if(ui->backendCheckBox->isChecked())
-        strlist.append(QString());
-    settings.setValue("drivers", strlist.join(QChar(',')));
-
-    // TODO: Remove check when we can properly match global values.
-    if(ui->defaultReverbComboBox->currentIndex() == 0)
-        settings.setValue("default-reverb", QString());
-    else
-    {
-        str = ui->defaultReverbComboBox->currentText().toLower();
-        settings.setValue("default-reverb", str);
-    }
-
-    if(ui->emulateEaxCheckBox->isChecked())
-        settings.setValue("reverb/emulate-eax", "true");
-    else
-        settings.setValue("reverb/emulate-eax", QString()/*"false"*/);
-
-    // TODO: Remove check when we can properly match global values.
-    if(ui->reverbBoostSlider->sliderPosition() == 0)
-        settings.setValue("reverb/boost", QString());
-    else
-        settings.setValue("reverb/boost", ui->reverbBoostEdit->text());
-
-    strlist.clear();
-    if(!ui->enableEaxReverbCheck->isChecked())
-        strlist.append("eaxreverb");
-    if(!ui->enableStdReverbCheck->isChecked())
-        strlist.append("reverb");
-    if(!ui->enableChorusCheck->isChecked())
-        strlist.append("chorus");
-    if(!ui->enableDistortionCheck->isChecked())
-        strlist.append("distortion");
-    if(!ui->enableCompressorCheck->isChecked())
-        strlist.append("compressor");
-    if(!ui->enableEchoCheck->isChecked())
-        strlist.append("echo");
-    if(!ui->enableEqualizerCheck->isChecked())
-        strlist.append("equalizer");
-    if(!ui->enableFlangerCheck->isChecked())
-        strlist.append("flanger");
-    if(!ui->enableModulatorCheck->isChecked())
-        strlist.append("modulator");
-    if(!ui->enableDedicatedCheck->isChecked())
-        strlist.append("dedicated");
-    settings.setValue("excludefx", strlist.join(QChar(',')));
-
-    /* Remove empty keys
-     * FIXME: Should only remove keys whose value matches the globally-specified value.
-     */
-    allkeys = settings.allKeys();
-    foreach(const QString &key, allkeys)
-    {
-        str = settings.value(key).toString();
-        if(str == QString())
-            settings.remove(key);
-    }
-}
-
-
-void MainWindow::updatePeriodSizeEdit(int size)
-{
-    ui->periodSizeEdit->clear();
-    if(size >= 64)
-    {
-        size = (size+32)&~0x3f;
-        ui->periodSizeEdit->insert(QString::number(size));
-    }
-}
-
-void MainWindow::updatePeriodSizeSlider()
-{
-    int pos = ui->periodSizeEdit->text().toInt();
-    if(pos >= 64)
-    {
-        if(pos > 8192)
-            pos = 8192;
-        ui->periodSizeSlider->setSliderPosition(pos);
-    }
-}
-
-void MainWindow::updatePeriodCountEdit(int count)
-{
-    ui->periodCountEdit->clear();
-    if(count >= 2)
-        ui->periodCountEdit->insert(QString::number(count));
-}
-
-void MainWindow::updatePeriodCountSlider()
-{
-    int pos = ui->periodCountEdit->text().toInt();
-    if(pos < 2)
-        pos = 0;
-    else if(pos > 16)
-        pos = 16;
-    ui->periodCountSlider->setSliderPosition(pos);
-}
-
-
-void MainWindow::addHrtfFile()
-{
-    const QStringList datapaths = getAllDataPaths("/openal/hrtf");
-    QStringList fnames = QFileDialog::getOpenFileNames(this, tr("Select Files"),
-                                                       datapaths.empty() ? QString() : datapaths[0],
-                                                       "HRTF Datasets(*.mhr);;All Files(*.*)");
-    if(fnames.isEmpty() == false)
-    {
-        for(QStringList::iterator iter = fnames.begin();iter != fnames.end();iter++)
-        {
-            QStringList::const_iterator path = datapaths.constBegin();
-            for(;path != datapaths.constEnd();path++)
-            {
-                QDir hrtfdir(*path);
-                if(!hrtfdir.isAbsolute())
-                    continue;
-
-                const QString relname = hrtfdir.relativeFilePath(*iter);
-                if(!relname.startsWith(".."))
-                {
-                    // If filename is within this path, use the relative pathname
-                    ui->hrtfFileList->addItem(relname);
-                    break;
-                }
-            }
-            if(path == datapaths.constEnd())
-            {
-                // Filename is not within any data path, use the absolute pathname
-                ui->hrtfFileList->addItem(*iter);
-            }
-        }
-    }
-}
-
-void MainWindow::removeHrtfFile()
-{
-    QList<QListWidgetItem*> selected = ui->hrtfFileList->selectedItems();
-    foreach(QListWidgetItem *item, selected)
-        delete item;
-}
-
-void MainWindow::updateHrtfRemoveButton()
-{
-    ui->hrtfRemoveButton->setEnabled(ui->hrtfFileList->selectedItems().size() != 0);
-}
-
-void MainWindow::showEnabledBackendMenu(QPoint pt)
-{
-    QMap<QAction*,QString> actionMap;
-
-    pt = ui->enabledBackendList->mapToGlobal(pt);
-
-    QMenu ctxmenu;
-    QAction *removeAction = ctxmenu.addAction(QIcon::fromTheme("list-remove"), "Remove");
-    if(ui->enabledBackendList->selectedItems().size() == 0)
-        removeAction->setEnabled(false);
-    ctxmenu.addSeparator();
-    for(size_t i = 0;backendMenuList[i].backend_name[0];i++)
-    {
-        QAction *action = ctxmenu.addAction(backendMenuList[i].menu_string);
-        actionMap[action] = backendMenuList[i].backend_name;
-        if(ui->enabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0 ||
-           ui->disabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0)
-            action->setEnabled(false);
-    }
-
-    QAction *gotAction = ctxmenu.exec(pt);
-    if(gotAction == removeAction)
-    {
-        QList<QListWidgetItem*> selected = ui->enabledBackendList->selectedItems();
-        foreach(QListWidgetItem *item, selected)
-            delete item;
-    }
-    else if(gotAction != NULL)
-    {
-        QMap<QAction*,QString>::const_iterator iter = actionMap.find(gotAction);
-        if(iter != actionMap.end())
-            ui->enabledBackendList->addItem(iter.value());
-    }
-}
-
-void MainWindow::showDisabledBackendMenu(QPoint pt)
-{
-    QMap<QAction*,QString> actionMap;
-
-    pt = ui->disabledBackendList->mapToGlobal(pt);
-
-    QMenu ctxmenu;
-    QAction *removeAction = ctxmenu.addAction(QIcon::fromTheme("list-remove"), "Remove");
-    if(ui->disabledBackendList->selectedItems().size() == 0)
-        removeAction->setEnabled(false);
-    ctxmenu.addSeparator();
-    for(size_t i = 0;backendMenuList[i].backend_name[0];i++)
-    {
-        QAction *action = ctxmenu.addAction(backendMenuList[i].menu_string);
-        actionMap[action] = backendMenuList[i].backend_name;
-        if(ui->disabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0 ||
-           ui->enabledBackendList->findItems(backendMenuList[i].backend_name, Qt::MatchFixedString).size() != 0)
-            action->setEnabled(false);
-    }
-
-    QAction *gotAction = ctxmenu.exec(pt);
-    if(gotAction == removeAction)
-    {
-        QList<QListWidgetItem*> selected = ui->disabledBackendList->selectedItems();
-        foreach(QListWidgetItem *item, selected)
-            delete item;
-    }
-    else if(gotAction != NULL)
-    {
-        QMap<QAction*,QString>::const_iterator iter = actionMap.find(gotAction);
-        if(iter != actionMap.end())
-            ui->disabledBackendList->addItem(iter.value());
-    }
-}
-
-void MainWindow::updateReverbBoostEdit(int value)
-{
-    ui->reverbBoostEdit->clear();
-    if(value != 0)
-        ui->reverbBoostEdit->insert(QString::number(value/10.0, 'f', 1));
-}
-
-void MainWindow::updateReverbBoostSlider(QString value)
-{
-    int pos = int(value.toFloat()*10.0f);
-    ui->reverbBoostSlider->setSliderPosition(pos);
-}

+ 0 - 1464
love/src/jni/openal-soft-1.17.0/utils/alsoft-config/mainwindow.ui

@@ -1,1464 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
-  <property name="geometry">
-   <rect>
-    <x>0</x>
-    <y>0</y>
-    <width>564</width>
-    <height>454</height>
-   </rect>
-  </property>
-  <property name="windowTitle">
-   <string>OpenAL Soft Configuration</string>
-  </property>
-  <property name="windowIcon">
-   <iconset theme="preferences-desktop-sound">
-    <normaloff/>
-   </iconset>
-  </property>
-  <widget class="QWidget" name="centralWidget">
-   <widget class="QPushButton" name="applyButton">
-    <property name="geometry">
-     <rect>
-      <x>470</x>
-      <y>405</y>
-      <width>81</width>
-      <height>25</height>
-     </rect>
-    </property>
-    <property name="text">
-     <string>Apply</string>
-    </property>
-    <property name="icon">
-     <iconset theme="dialog-ok-apply">
-      <normaloff/>
-     </iconset>
-    </property>
-   </widget>
-   <widget class="QTabWidget" name="tabWidget">
-    <property name="geometry">
-     <rect>
-      <x>10</x>
-      <y>0</y>
-      <width>541</width>
-      <height>401</height>
-     </rect>
-    </property>
-    <property name="currentIndex">
-     <number>0</number>
-    </property>
-    <widget class="QWidget" name="tab_3">
-     <attribute name="title">
-      <string>Playback</string>
-     </attribute>
-     <widget class="QComboBox" name="sampleFormatCombo">
-      <property name="geometry">
-       <rect>
-        <x>120</x>
-        <y>20</y>
-        <width>188</width>
-        <height>22</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>The output sample type. Currently, all mixing is done with 32-bit
-float and converted to the output sample type as needed.</string>
-      </property>
-      <property name="sizeAdjustPolicy">
-       <enum>QComboBox::AdjustToContents</enum>
-      </property>
-      <item>
-       <property name="text">
-        <string>- Autodetect -</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>int8 - signed 8-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>uint8 - unsigned 8-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>int16 - signed 16-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>uint16 - unsigned 16-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>int32 - signed 32-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>uint32 - unsigned 32-bit int</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>float32 - 32-bit float</string>
-       </property>
-      </item>
-     </widget>
-     <widget class="QLabel" name="label_5">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>20</y>
-        <width>101</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Sample Format:</string>
-      </property>
-      <property name="alignment">
-       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-      </property>
-     </widget>
-     <widget class="QLabel" name="label_6">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>50</y>
-        <width>101</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Channels:</string>
-      </property>
-      <property name="alignment">
-       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-      </property>
-     </widget>
-     <widget class="QComboBox" name="channelConfigCombo">
-      <property name="geometry">
-       <rect>
-        <x>120</x>
-        <y>50</y>
-        <width>227</width>
-        <height>22</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>The output channel configuration. Note that not all backends
-can properly detect the channel configuration and may default
-to stereo output.</string>
-      </property>
-      <property name="sizeAdjustPolicy">
-       <enum>QComboBox::AdjustToContents</enum>
-      </property>
-      <item>
-       <property name="text">
-        <string>- Autodetect -</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>mono - 1-channel Mono</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>stereo - 2-channel Stereo</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>quad - 4-channel Quadraphonic</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>surround51 - 5.1 Surround Sound</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>surround61 - 6.1 Surround Sound</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>surround71 - 7.1 Surround Sound</string>
-       </property>
-      </item>
-     </widget>
-     <widget class="QComboBox" name="sampleRateCombo">
-      <property name="geometry">
-       <rect>
-        <x>120</x>
-        <y>80</y>
-        <width>111</width>
-        <height>22</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>The playback/mixing sample rate.</string>
-      </property>
-      <property name="editable">
-       <bool>true</bool>
-      </property>
-      <property name="insertPolicy">
-       <enum>QComboBox::NoInsert</enum>
-      </property>
-      <property name="sizeAdjustPolicy">
-       <enum>QComboBox::AdjustToContents</enum>
-      </property>
-      <item>
-       <property name="text">
-        <string>- Autodetect -</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>96000</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>48000</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>44100</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>32000</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>22050</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>16000</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>11025</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>8000</string>
-       </property>
-      </item>
-     </widget>
-     <widget class="QLabel" name="label_7">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>80</y>
-        <width>101</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Sample Rate:</string>
-      </property>
-      <property name="alignment">
-       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-      </property>
-     </widget>
-     <widget class="QGroupBox" name="groupBox">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>200</y>
-        <width>511</width>
-        <height>161</height>
-       </rect>
-      </property>
-      <property name="title">
-       <string>HRTF (Stereo only)</string>
-      </property>
-      <widget class="QRadioButton" name="hrtfEnableButton">
-       <property name="geometry">
-        <rect>
-         <x>20</x>
-         <y>30</y>
-         <width>71</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>Allows applications to request HRTF mixing.</string>
-       </property>
-       <property name="text">
-        <string>Enable</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QRadioButton" name="hrtfDisableButton">
-       <property name="geometry">
-        <rect>
-         <x>20</x>
-         <y>50</y>
-         <width>71</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>Does not allow HRTF mixing, even when requested.</string>
-       </property>
-       <property name="text">
-        <string>Disable</string>
-       </property>
-      </widget>
-      <widget class="QRadioButton" name="hrtfForceButton">
-       <property name="geometry">
-        <rect>
-         <x>20</x>
-         <y>70</y>
-         <width>71</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>Attempts to force HRTF mixing, even if applications request not
-to do it. This may override the channel configuration and
-sample rate.</string>
-       </property>
-       <property name="text">
-        <string>Force</string>
-       </property>
-      </widget>
-      <widget class="QListWidget" name="hrtfFileList">
-       <property name="geometry">
-        <rect>
-         <x>110</x>
-         <y>30</y>
-         <width>301</width>
-         <height>121</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>A list of files containing HRTF data sets. The listed data sets
-are used in place of the default sets. The filenames may
-contain these markers, which will be replaced as needed:
-%r - Device sampling rate
-%% - Percent sign (%)</string>
-       </property>
-       <property name="dragEnabled">
-        <bool>false</bool>
-       </property>
-       <property name="dragDropMode">
-        <enum>QAbstractItemView::InternalMove</enum>
-       </property>
-       <property name="alternatingRowColors">
-        <bool>true</bool>
-       </property>
-       <property name="selectionMode">
-        <enum>QAbstractItemView::ExtendedSelection</enum>
-       </property>
-       <property name="textElideMode">
-        <enum>Qt::ElideNone</enum>
-       </property>
-      </widget>
-      <widget class="QPushButton" name="hrtfAddButton">
-       <property name="geometry">
-        <rect>
-         <x>419</x>
-         <y>30</y>
-         <width>81</width>
-         <height>25</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Add...</string>
-       </property>
-       <property name="icon">
-        <iconset theme="list-add">
-         <normaloff/>
-        </iconset>
-       </property>
-       <property name="flat">
-        <bool>false</bool>
-       </property>
-      </widget>
-      <widget class="QPushButton" name="hrtfRemoveButton">
-       <property name="geometry">
-        <rect>
-         <x>419</x>
-         <y>60</y>
-         <width>81</width>
-         <height>25</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Remove</string>
-       </property>
-       <property name="icon">
-        <iconset theme="list-remove">
-         <normaloff/>
-        </iconset>
-       </property>
-      </widget>
-     </widget>
-     <widget class="QGroupBox" name="groupBox_3">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>110</y>
-        <width>511</width>
-        <height>91</height>
-       </rect>
-      </property>
-      <property name="title">
-       <string>Buffer Metrics</string>
-      </property>
-      <widget class="QWidget" name="widget" native="true">
-       <property name="geometry">
-        <rect>
-         <x>260</x>
-         <y>20</y>
-         <width>241</width>
-         <height>51</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>The number of update periods. Higher values create a larger
-mix ahead, which helps protect against skips when the CPU is
-under load, but increases the delay between a sound getting
-mixed and being heard.</string>
-       </property>
-       <widget class="QLabel" name="label_11">
-        <property name="geometry">
-         <rect>
-          <x>20</x>
-          <y>0</y>
-          <width>201</width>
-          <height>21</height>
-         </rect>
-        </property>
-        <property name="text">
-         <string>Period Count</string>
-        </property>
-        <property name="alignment">
-         <set>Qt::AlignCenter</set>
-        </property>
-       </widget>
-       <widget class="QSlider" name="periodCountSlider">
-        <property name="geometry">
-         <rect>
-          <x>70</x>
-          <y>20</y>
-          <width>160</width>
-          <height>23</height>
-         </rect>
-        </property>
-        <property name="minimum">
-         <number>1</number>
-        </property>
-        <property name="maximum">
-         <number>16</number>
-        </property>
-        <property name="singleStep">
-         <number>1</number>
-        </property>
-        <property name="pageStep">
-         <number>2</number>
-        </property>
-        <property name="value">
-         <number>1</number>
-        </property>
-        <property name="tracking">
-         <bool>true</bool>
-        </property>
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-        <property name="tickPosition">
-         <enum>QSlider::TicksBelow</enum>
-        </property>
-        <property name="tickInterval">
-         <number>1</number>
-        </property>
-       </widget>
-       <widget class="QLineEdit" name="periodCountEdit">
-        <property name="geometry">
-         <rect>
-          <x>20</x>
-          <y>20</y>
-          <width>51</width>
-          <height>22</height>
-         </rect>
-        </property>
-        <property name="placeholderText">
-         <string>4</string>
-        </property>
-       </widget>
-      </widget>
-      <widget class="QWidget" name="widget_2" native="true">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>20</y>
-         <width>241</width>
-         <height>51</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>The update period size, in sample frames. This is the number of
-frames needed for each mixing update.</string>
-       </property>
-       <widget class="QSlider" name="periodSizeSlider">
-        <property name="geometry">
-         <rect>
-          <x>60</x>
-          <y>20</y>
-          <width>160</width>
-          <height>23</height>
-         </rect>
-        </property>
-        <property name="minimum">
-         <number>0</number>
-        </property>
-        <property name="maximum">
-         <number>8192</number>
-        </property>
-        <property name="singleStep">
-         <number>64</number>
-        </property>
-        <property name="pageStep">
-         <number>1024</number>
-        </property>
-        <property name="value">
-         <number>0</number>
-        </property>
-        <property name="tracking">
-         <bool>true</bool>
-        </property>
-        <property name="orientation">
-         <enum>Qt::Horizontal</enum>
-        </property>
-        <property name="tickPosition">
-         <enum>QSlider::TicksBelow</enum>
-        </property>
-        <property name="tickInterval">
-         <number>512</number>
-        </property>
-       </widget>
-       <widget class="QLabel" name="label_10">
-        <property name="geometry">
-         <rect>
-          <x>10</x>
-          <y>0</y>
-          <width>201</width>
-          <height>21</height>
-         </rect>
-        </property>
-        <property name="text">
-         <string>Period Samples</string>
-        </property>
-        <property name="alignment">
-         <set>Qt::AlignCenter</set>
-        </property>
-       </widget>
-       <widget class="QLineEdit" name="periodSizeEdit">
-        <property name="geometry">
-         <rect>
-          <x>10</x>
-          <y>20</y>
-          <width>51</width>
-          <height>22</height>
-         </rect>
-        </property>
-        <property name="placeholderText">
-         <string>1024</string>
-        </property>
-       </widget>
-      </widget>
-     </widget>
-    </widget>
-    <widget class="QWidget" name="tab_2">
-     <attribute name="title">
-      <string>Resources</string>
-     </attribute>
-     <widget class="QLineEdit" name="srcCountLineEdit">
-      <property name="geometry">
-       <rect>
-        <x>190</x>
-        <y>20</y>
-        <width>51</width>
-        <height>22</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>The maximum number of allocatable sources. Lower values may
-help for systems with apps that try to play more sounds than
-the CPU can handle.</string>
-      </property>
-      <property name="inputMask">
-       <string/>
-      </property>
-      <property name="maxLength">
-       <number>3</number>
-      </property>
-      <property name="frame">
-       <bool>true</bool>
-      </property>
-      <property name="placeholderText">
-       <string>256</string>
-      </property>
-     </widget>
-     <widget class="QLabel" name="label_3">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>20</y>
-        <width>171</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Number of Sound Sources:</string>
-      </property>
-      <property name="alignment">
-       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-      </property>
-     </widget>
-     <widget class="QLabel" name="label_4">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>50</y>
-        <width>171</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Number of Effect Slots:</string>
-      </property>
-      <property name="alignment">
-       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-      </property>
-     </widget>
-     <widget class="QLineEdit" name="effectSlotLineEdit">
-      <property name="geometry">
-       <rect>
-        <x>190</x>
-        <y>50</y>
-        <width>51</width>
-        <height>22</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>The maximum number of Auxiliary Effect Slots an app can
-create. A slot can use a non-negligible amount of CPU time if
-an effect is set on it even if no sources are feeding it, so this
-may help when apps use more than the system can handle.</string>
-      </property>
-      <property name="inputMask">
-       <string/>
-      </property>
-      <property name="maxLength">
-       <number>1</number>
-      </property>
-      <property name="frame">
-       <bool>true</bool>
-      </property>
-      <property name="placeholderText">
-       <string>4</string>
-      </property>
-     </widget>
-     <widget class="QLabel" name="label_8">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>80</y>
-        <width>171</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Number of Source Sends:</string>
-      </property>
-      <property name="alignment">
-       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-      </property>
-     </widget>
-     <widget class="QLineEdit" name="srcSendLineEdit">
-      <property name="geometry">
-       <rect>
-        <x>190</x>
-        <y>80</y>
-        <width>51</width>
-        <height>22</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>The number of auxiliary sends per source. When not specified,
-it allows the app to request how many it wants. The maximum
-value currently possible is 4.</string>
-      </property>
-      <property name="maxLength">
-       <number>1</number>
-      </property>
-      <property name="placeholderText">
-       <string>Auto</string>
-      </property>
-     </widget>
-     <widget class="QLabel" name="label_9">
-      <property name="geometry">
-       <rect>
-        <x>30</x>
-        <y>120</y>
-        <width>71</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Resampler:</string>
-      </property>
-     </widget>
-     <widget class="QComboBox" name="resamplerComboBox">
-      <property name="geometry">
-       <rect>
-        <x>110</x>
-        <y>120</y>
-        <width>185</width>
-        <height>22</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>The resampling method used when mixing sources.</string>
-      </property>
-      <property name="sizeAdjustPolicy">
-       <enum>QComboBox::AdjustToContents</enum>
-      </property>
-      <item>
-       <property name="text">
-        <string>- Default -</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Point (low quality, fast)</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Linear (basic quality, fast)</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Cubic Spline (good quality)</string>
-       </property>
-      </item>
-     </widget>
-     <widget class="QGroupBox" name="groupBox_2">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>150</y>
-        <width>511</width>
-        <height>91</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>Enables use of specific CPU extensions. Certain methods may
-utilize CPU extensions when detected, and disabling these can
-be useful for preventing those extensions from being used.</string>
-      </property>
-      <property name="title">
-       <string>CPU Extensions</string>
-      </property>
-      <widget class="QCheckBox" name="enableSSECheckBox">
-       <property name="geometry">
-        <rect>
-         <x>180</x>
-         <y>20</y>
-         <width>71</width>
-         <height>31</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>SSE</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableSSE2CheckBox">
-       <property name="geometry">
-        <rect>
-         <x>180</x>
-         <y>50</y>
-         <width>71</width>
-         <height>31</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>SSE2</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableNeonCheckBox">
-       <property name="geometry">
-        <rect>
-         <x>260</x>
-         <y>50</y>
-         <width>71</width>
-         <height>31</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Neon</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableSSE41CheckBox">
-       <property name="geometry">
-        <rect>
-         <x>260</x>
-         <y>20</y>
-         <width>71</width>
-         <height>31</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>SSE4.1</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-     </widget>
-    </widget>
-    <widget class="QWidget" name="tab">
-     <attribute name="title">
-      <string>Backends</string>
-     </attribute>
-     <widget class="QCheckBox" name="backendCheckBox">
-      <property name="geometry">
-       <rect>
-        <x>170</x>
-        <y>200</y>
-        <width>161</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>When checked, allows all other available backends not listed in the priority or disabled lists.</string>
-      </property>
-      <property name="text">
-       <string>Allow Other Backends</string>
-      </property>
-      <property name="checked">
-       <bool>true</bool>
-      </property>
-     </widget>
-     <widget class="QListWidget" name="enabledBackendList">
-      <property name="geometry">
-       <rect>
-        <x>40</x>
-        <y>40</y>
-        <width>191</width>
-        <height>151</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>The backend driver list order. Unknown backends and
-duplicated names are ignored.</string>
-      </property>
-      <property name="dragDropMode">
-       <enum>QAbstractItemView::InternalMove</enum>
-      </property>
-     </widget>
-     <widget class="QLabel" name="label">
-      <property name="geometry">
-       <rect>
-        <x>40</x>
-        <y>20</y>
-        <width>191</width>
-        <height>20</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Priority Backends:</string>
-      </property>
-     </widget>
-     <widget class="QListWidget" name="disabledBackendList">
-      <property name="geometry">
-       <rect>
-        <x>270</x>
-        <y>40</y>
-        <width>191</width>
-        <height>151</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>Disabled backend driver list.</string>
-      </property>
-     </widget>
-     <widget class="QLabel" name="label_2">
-      <property name="geometry">
-       <rect>
-        <x>270</x>
-        <y>20</y>
-        <width>191</width>
-        <height>20</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Disabled Backends:</string>
-      </property>
-     </widget>
-    </widget>
-    <widget class="QWidget" name="tab_4">
-     <attribute name="title">
-      <string>Effects</string>
-     </attribute>
-     <widget class="QCheckBox" name="emulateEaxCheckBox">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>60</y>
-        <width>161</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>Uses a simpler reverb method to emulate the EAX reverb
-effect. This may slightly improve performance at the cost of
-some quality.</string>
-      </property>
-      <property name="layoutDirection">
-       <enum>Qt::RightToLeft</enum>
-      </property>
-      <property name="text">
-       <string>Emulate EAX Reverb:</string>
-      </property>
-     </widget>
-     <widget class="QGroupBox" name="groupBox_4">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>100</y>
-        <width>511</width>
-        <height>61</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>Global amplification for reverb output, expressed in decibels.
-+6 will be a scale of (approximately) 2x, +12 will be a scale of
-4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A
-value of 0 means no change.</string>
-      </property>
-      <property name="title">
-       <string>Reverb Boost</string>
-      </property>
-      <widget class="QSlider" name="reverbBoostSlider">
-       <property name="geometry">
-        <rect>
-         <x>10</x>
-         <y>30</y>
-         <width>391</width>
-         <height>23</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string/>
-       </property>
-       <property name="minimum">
-        <number>-120</number>
-       </property>
-       <property name="maximum">
-        <number>120</number>
-       </property>
-       <property name="orientation">
-        <enum>Qt::Horizontal</enum>
-       </property>
-       <property name="tickPosition">
-        <enum>QSlider::TicksBelow</enum>
-       </property>
-       <property name="tickInterval">
-        <number>10</number>
-       </property>
-      </widget>
-      <widget class="QLineEdit" name="reverbBoostEdit">
-       <property name="geometry">
-        <rect>
-         <x>410</x>
-         <y>30</y>
-         <width>51</width>
-         <height>22</height>
-        </rect>
-       </property>
-       <property name="alignment">
-        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-       </property>
-       <property name="placeholderText">
-        <string>0.0</string>
-       </property>
-      </widget>
-      <widget class="QLabel" name="label_12">
-       <property name="geometry">
-        <rect>
-         <x>460</x>
-         <y>30</y>
-         <width>31</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>dB</string>
-       </property>
-      </widget>
-     </widget>
-     <widget class="QGroupBox" name="groupBox_5">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>170</y>
-        <width>511</width>
-        <height>191</height>
-       </rect>
-      </property>
-      <property name="toolTip">
-       <string>Specifies which effects apps can recognize. Disabling effects
-can help for apps that try to use ones that are too intensive
-for the system to handle.</string>
-      </property>
-      <property name="title">
-       <string>Enabled Effects</string>
-      </property>
-      <widget class="QCheckBox" name="enableEaxReverbCheck">
-       <property name="geometry">
-        <rect>
-         <x>70</x>
-         <y>30</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>EAX Reverb</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableStdReverbCheck">
-       <property name="geometry">
-        <rect>
-         <x>70</x>
-         <y>60</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Standard Reverb</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableChorusCheck">
-       <property name="geometry">
-        <rect>
-         <x>70</x>
-         <y>90</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Chorus</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableDistortionCheck">
-       <property name="geometry">
-        <rect>
-         <x>70</x>
-         <y>150</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Distortion</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableEchoCheck">
-       <property name="geometry">
-        <rect>
-         <x>320</x>
-         <y>30</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Echo</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableEqualizerCheck">
-       <property name="geometry">
-        <rect>
-         <x>320</x>
-         <y>60</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Equalizer</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableFlangerCheck">
-       <property name="geometry">
-        <rect>
-         <x>320</x>
-         <y>90</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Flanger</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableModulatorCheck">
-       <property name="geometry">
-        <rect>
-         <x>320</x>
-         <y>120</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Ring Modulator</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableDedicatedCheck">
-       <property name="geometry">
-        <rect>
-         <x>320</x>
-         <y>150</y>
-         <width>131</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="toolTip">
-        <string>Enables both the Dedicated Dialog and Dedicated LFE effects
-added by the ALC_EXT_DEDICATED extension.</string>
-       </property>
-       <property name="text">
-        <string>Dedicated ...</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-      <widget class="QCheckBox" name="enableCompressorCheck">
-       <property name="geometry">
-        <rect>
-         <x>70</x>
-         <y>120</y>
-         <width>111</width>
-         <height>21</height>
-        </rect>
-       </property>
-       <property name="text">
-        <string>Compressor</string>
-       </property>
-       <property name="checked">
-        <bool>true</bool>
-       </property>
-      </widget>
-     </widget>
-     <widget class="QLabel" name="label_13">
-      <property name="geometry">
-       <rect>
-        <x>10</x>
-        <y>20</y>
-        <width>141</width>
-        <height>21</height>
-       </rect>
-      </property>
-      <property name="text">
-       <string>Default Reverb Effect:</string>
-      </property>
-      <property name="alignment">
-       <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
-      </property>
-     </widget>
-     <widget class="QComboBox" name="defaultReverbComboBox">
-      <property name="geometry">
-       <rect>
-        <x>160</x>
-        <y>20</y>
-        <width>131</width>
-        <height>22</height>
-       </rect>
-      </property>
-      <property name="sizeAdjustPolicy">
-       <enum>QComboBox::AdjustToContents</enum>
-      </property>
-      <item>
-       <property name="text">
-        <string>None</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Generic</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>PaddedCell</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Room</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Bathroom</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Livingroom</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Stoneroom</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Auditorium</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>ConcertHall</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Cave</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Arena</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Hangar</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>CarpetedHallway</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Hallway</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>StoneCorridor</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Alley</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Forest</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>City</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Mountains</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Quarry</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Plain</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>ParkingLot</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>SewerPipe</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Underwater</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Drugged</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Dizzy</string>
-       </property>
-      </item>
-      <item>
-       <property name="text">
-        <string>Psychotic</string>
-       </property>
-      </item>
-     </widget>
-    </widget>
-   </widget>
-  </widget>
-  <widget class="QMenuBar" name="menuBar">
-   <property name="geometry">
-    <rect>
-     <x>0</x>
-     <y>0</y>
-     <width>564</width>
-     <height>19</height>
-    </rect>
-   </property>
-   <widget class="QMenu" name="menuFile">
-    <property name="title">
-     <string>&amp;File</string>
-    </property>
-    <addaction name="actionLoad"/>
-    <addaction name="actionSave_As"/>
-    <addaction name="separator"/>
-    <addaction name="actionQuit"/>
-   </widget>
-   <addaction name="menuFile"/>
-  </widget>
-  <action name="actionQuit">
-   <property name="icon">
-    <iconset theme="application-exit">
-     <normaloff/>
-    </iconset>
-   </property>
-   <property name="text">
-    <string>&amp;Quit</string>
-   </property>
-  </action>
-  <action name="actionSave_As">
-   <property name="icon">
-    <iconset theme="document-save-as">
-     <normaloff/>
-    </iconset>
-   </property>
-   <property name="text">
-    <string>Save &amp;As...</string>
-   </property>
-   <property name="toolTip">
-    <string>Save Configuration As</string>
-   </property>
-  </action>
-  <action name="actionLoad">
-   <property name="icon">
-    <iconset theme="document-open">
-     <normaloff/>
-    </iconset>
-   </property>
-   <property name="text">
-    <string>&amp;Load...</string>
-   </property>
-   <property name="toolTip">
-    <string>Load Configuration File</string>
-   </property>
-  </action>
- </widget>
- <layoutdefault spacing="6" margin="11"/>
- <resources/>
- <connections>
-  <connection>
-   <sender>actionQuit</sender>
-   <signal>activated()</signal>
-   <receiver>MainWindow</receiver>
-   <slot>close()</slot>
-   <hints>
-    <hint type="sourcelabel">
-     <x>-1</x>
-     <y>-1</y>
-    </hint>
-    <hint type="destinationlabel">
-     <x>267</x>
-     <y>181</y>
-    </hint>
-   </hints>
-  </connection>
- </connections>
- <slots>
-  <slot>ShowHRTFContextMenu(QPoint)</slot>
- </slots>
-</ui>

+ 0 - 2749
love/src/jni/openal-soft-1.17.0/utils/makehrtf.c

@@ -1,2749 +0,0 @@
-/*
- * HRTF utility for producing and demonstrating the process of creating an
- * OpenAL Soft compatible HRIR data set.
- *
- * Copyright (C) 2011-2014  Christopher Fitzgerald
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Or visit:  http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
- *
- * --------------------------------------------------------------------------
- *
- * A big thanks goes out to all those whose work done in the field of
- * binaural sound synthesis using measured HRTFs makes this utility and the
- * OpenAL Soft implementation possible.
- *
- * The algorithm for diffuse-field equalization was adapted from the work
- * done by Rio Emmanuel and Larcher Veronique of IRCAM and Bill Gardner of
- * MIT Media Laboratory.  It operates as follows:
- *
- *  1.  Take the FFT of each HRIR and only keep the magnitude responses.
- *  2.  Calculate the diffuse-field power-average of all HRIRs weighted by
- *      their contribution to the total surface area covered by their
- *      measurement.
- *  3.  Take the diffuse-field average and limit its magnitude range.
- *  4.  Equalize the responses by using the inverse of the diffuse-field
- *      average.
- *  5.  Reconstruct the minimum-phase responses.
- *  5.  Zero the DC component.
- *  6.  IFFT the result and truncate to the desired-length minimum-phase FIR.
- *
- * The spherical head algorithm for calculating propagation delay was adapted
- * from the paper:
- *
- *  Modeling Interaural Time Difference Assuming a Spherical Head
- *  Joel David Miller
- *  Music 150, Musical Acoustics, Stanford University
- *  December 2, 2001
- *
- * The formulae for calculating the Kaiser window metrics are from the
- * the textbook:
- *
- *  Discrete-Time Signal Processing
- *  Alan V. Oppenheim and Ronald W. Schafer
- *  Prentice-Hall Signal Processing Series
- *  1999
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-
-// Rely (if naively) on OpenAL's header for the types used for serialization.
-#include "AL/al.h"
-#include "AL/alext.h"
-
-#ifndef M_PI
-#define M_PI                         (3.14159265358979323846)
-#endif
-
-#ifndef HUGE_VAL
-#define HUGE_VAL                     (1.0 / 0.0)
-#endif
-
-// The epsilon used to maintain signal stability.
-#define EPSILON                      (1e-15)
-
-// Constants for accessing the token reader's ring buffer.
-#define TR_RING_BITS                 (16)
-#define TR_RING_SIZE                 (1 << TR_RING_BITS)
-#define TR_RING_MASK                 (TR_RING_SIZE - 1)
-
-// The token reader's load interval in bytes.
-#define TR_LOAD_SIZE                 (TR_RING_SIZE >> 2)
-
-// The maximum identifier length used when processing the data set
-// definition.
-#define MAX_IDENT_LEN                (16)
-
-// The maximum path length used when processing filenames.
-#define MAX_PATH_LEN                 (256)
-
-// The limits for the sample 'rate' metric in the data set definition and for
-// resampling.
-#define MIN_RATE                     (32000)
-#define MAX_RATE                     (96000)
-
-// The limits for the HRIR 'points' metric in the data set definition.
-#define MIN_POINTS                   (16)
-#define MAX_POINTS                   (8192)
-
-// The limits to the number of 'azimuths' listed in the data set definition.
-#define MIN_EV_COUNT                 (5)
-#define MAX_EV_COUNT                 (128)
-
-// The limits for each of the 'azimuths' listed in the data set definition.
-#define MIN_AZ_COUNT                 (1)
-#define MAX_AZ_COUNT                 (128)
-
-// The limits for the listener's head 'radius' in the data set definition.
-#define MIN_RADIUS                   (0.05)
-#define MAX_RADIUS                   (0.15)
-
-// The limits for the 'distance' from source to listener in the definition
-// file.
-#define MIN_DISTANCE                 (0.5)
-#define MAX_DISTANCE                 (2.5)
-
-// The maximum number of channels that can be addressed for a WAVE file
-// source listed in the data set definition.
-#define MAX_WAVE_CHANNELS            (65535)
-
-// The limits to the byte size for a binary source listed in the definition
-// file.
-#define MIN_BIN_SIZE                 (2)
-#define MAX_BIN_SIZE                 (4)
-
-// The minimum number of significant bits for binary sources listed in the
-// data set definition.  The maximum is calculated from the byte size.
-#define MIN_BIN_BITS                 (16)
-
-// The limits to the number of significant bits for an ASCII source listed in
-// the data set definition.
-#define MIN_ASCII_BITS               (16)
-#define MAX_ASCII_BITS               (32)
-
-// The limits to the FFT window size override on the command line.
-#define MIN_FFTSIZE                  (512)
-#define MAX_FFTSIZE                  (16384)
-
-// The limits to the equalization range limit on the command line.
-#define MIN_LIMIT                    (2.0)
-#define MAX_LIMIT                    (120.0)
-
-// The limits to the truncation window size on the command line.
-#define MIN_TRUNCSIZE                (8)
-#define MAX_TRUNCSIZE                (128)
-
-// The limits to the custom head radius on the command line.
-#define MIN_CUSTOM_RADIUS            (0.05)
-#define MAX_CUSTOM_RADIUS            (0.15)
-
-// The truncation window size must be a multiple of the below value to allow
-// for vectorized convolution.
-#define MOD_TRUNCSIZE                (8)
-
-// The defaults for the command line options.
-#define DEFAULT_EQUALIZE             (1)
-#define DEFAULT_SURFACE              (1)
-#define DEFAULT_LIMIT                (24.0)
-#define DEFAULT_TRUNCSIZE            (32)
-#define DEFAULT_HEAD_MODEL           (HM_DATASET)
-#define DEFAULT_CUSTOM_RADIUS        (0.0)
-
-// The four-character-codes for RIFF/RIFX WAVE file chunks.
-#define FOURCC_RIFF                  (0x46464952) // 'RIFF'
-#define FOURCC_RIFX                  (0x58464952) // 'RIFX'
-#define FOURCC_WAVE                  (0x45564157) // 'WAVE'
-#define FOURCC_FMT                   (0x20746D66) // 'fmt '
-#define FOURCC_DATA                  (0x61746164) // 'data'
-#define FOURCC_LIST                  (0x5453494C) // 'LIST'
-#define FOURCC_WAVL                  (0x6C766177) // 'wavl'
-#define FOURCC_SLNT                  (0x746E6C73) // 'slnt'
-
-// The supported wave formats.
-#define WAVE_FORMAT_PCM              (0x0001)
-#define WAVE_FORMAT_IEEE_FLOAT       (0x0003)
-#define WAVE_FORMAT_EXTENSIBLE       (0xFFFE)
-
-// The maximum propagation delay value supported by OpenAL Soft.
-#define MAX_HRTD                     (63.0)
-
-// The OpenAL Soft HRTF format marker.  It stands for minimum-phase head
-// response protocol 01.
-#define MHR_FORMAT                   ("MinPHR01")
-
-// Byte order for the serialization routines.
-enum ByteOrderT {
-  BO_NONE   = 0,
-  BO_LITTLE    ,
-  BO_BIG
-};
-
-// Source format for the references listed in the data set definition.
-enum SourceFormatT {
-  SF_NONE   = 0,
-  SF_WAVE      ,  // RIFF/RIFX WAVE file.
-  SF_BIN_LE    ,  // Little-endian binary file.
-  SF_BIN_BE    ,  // Big-endian binary file.
-  SF_ASCII        // ASCII text file.
-};
-
-// Element types for the references listed in the data set definition.
-enum ElementTypeT {
-  ET_NONE = 0,
-  ET_INT     ,    // Integer elements.
-  ET_FP           // Floating-point elements.
-};
-
-// Head model used for calculating the impulse delays.
-enum HeadModelT {
-  HM_NONE    = 0,
-  HM_DATASET    , // Measure the onset from the dataset.
-  HM_SPHERE       // Calculate the onset using a spherical head model.
-};
-
-// Desired output format from the command line.
-enum OutputFormatT {
-  OF_NONE  = 0,
-  OF_MHR      ,   // OpenAL Soft MHR data set file.
-  OF_TABLE        // OpenAL Soft built-in table file (used when compiling).
-};
-
-// Unsigned integer type.
-typedef unsigned int                 uint;
-
-// Serialization types.  The trailing digit indicates the number of bits.
-typedef ALubyte                      uint8;
-
-typedef ALint                        int32;
-typedef ALuint                       uint32;
-typedef ALuint64SOFT                 uint64;
-
-typedef enum ByteOrderT              ByteOrderT;
-typedef enum SourceFormatT           SourceFormatT;
-typedef enum ElementTypeT            ElementTypeT;
-typedef enum HeadModelT              HeadModelT;
-typedef enum OutputFormatT           OutputFormatT;
-
-typedef struct TokenReaderT          TokenReaderT;
-typedef struct SourceRefT            SourceRefT;
-typedef struct HrirDataT             HrirDataT;
-typedef struct ResamplerT            ResamplerT;
-
-// Token reader state for parsing the data set definition.
-struct TokenReaderT {
-  FILE                             * mFile;
-  const char                       * mName;
-  uint                               mLine,
-                                     mColumn;
-  char                               mRing [TR_RING_SIZE];
-  size_t                             mIn,
-                                     mOut;
-};
-
-// Source reference state used when loading sources.
-struct SourceRefT {
-  SourceFormatT                      mFormat;
-  ElementTypeT                       mType;
-  uint                               mSize;
-  int                                mBits;
-  uint                               mChannel,
-                                     mSkip,
-                                     mOffset;
-  char                               mPath [MAX_PATH_LEN + 1];
-};
-
-// The HRIR metrics and data set used when loading, processing, and storing
-// the resulting HRTF.
-struct HrirDataT {
-  uint                               mIrRate,
-                                     mIrCount,
-                                     mIrSize,
-                                     mIrPoints,
-                                     mFftSize,
-                                     mEvCount,
-                                     mEvStart,
-                                     mAzCount [MAX_EV_COUNT],
-                                     mEvOffset [MAX_EV_COUNT];
-  double                             mRadius,
-                                     mDistance,
-                                   * mHrirs,
-                                   * mHrtds,
-                                     mMaxHrtd;
-};
-
-// The resampler metrics and FIR filter.
-struct ResamplerT {
-  uint                               mP,
-                                     mQ,
-                                     mM,
-                                     mL;
-  double                           * mF;
-};
-
-/* Token reader routines for parsing text files.  Whitespace is not
- * significant.  It can process tokens as identifiers, numbers (integer and
- * floating-point), strings, and operators.  Strings must be encapsulated by
- * double-quotes and cannot span multiple lines.
- */
-
-// Setup the reader on the given file.  The filename can be NULL if no error
-// output is desired.
-static void TrSetup (FILE * fp, const char * filename, TokenReaderT * tr) {
-  const char * name = NULL;
-  char ch;
-
-  tr -> mFile = fp;
-  name = filename;
-  // If a filename was given, store a pointer to the base name.
-  if (filename != NULL) {
-     while ((ch = (* filename)) != '\0') {
-       if ((ch == '/') || (ch == '\\'))
-          name = filename + 1;
-       filename ++;
-     }
-  }
-  tr -> mName = name;
-  tr -> mLine = 1;
-  tr -> mColumn = 1;
-  tr -> mIn = 0;
-  tr -> mOut = 0;
-}
-
-// Prime the reader's ring buffer, and return a result indicating that there
-// is text to process.
-static int TrLoad (TokenReaderT * tr) {
-  size_t toLoad, in, count;
-
-  toLoad = TR_RING_SIZE - (tr -> mIn - tr -> mOut);
-  if ((toLoad >= TR_LOAD_SIZE) && (! feof (tr -> mFile))) {
-     // Load TR_LOAD_SIZE (or less if at the end of the file) per read.
-     toLoad = TR_LOAD_SIZE;
-     in = tr -> mIn & TR_RING_MASK;
-     count = TR_RING_SIZE - in;
-     if (count < toLoad) {
-        tr -> mIn += fread (& tr -> mRing [in], 1, count, tr -> mFile);
-        tr -> mIn += fread (& tr -> mRing [0], 1, toLoad - count, tr -> mFile);
-     } else {
-        tr -> mIn += fread (& tr -> mRing [in], 1, toLoad, tr -> mFile);
-     }
-     if (tr -> mOut >= TR_RING_SIZE) {
-        tr -> mOut -= TR_RING_SIZE;
-        tr -> mIn -= TR_RING_SIZE;
-     }
-  }
-  if (tr -> mIn > tr -> mOut)
-     return (1);
-  return (0);
-}
-
-// Error display routine.  Only displays when the base name is not NULL.
-static void TrErrorVA (const TokenReaderT * tr, uint line, uint column, const char * format, va_list argPtr) {
-  if (tr -> mName != NULL) {
-     fprintf (stderr, "Error (%s:%u:%u):  ", tr -> mName, line, column);
-     vfprintf (stderr, format, argPtr);
-  }
-}
-
-// Used to display an error at a saved line/column.
-static void TrErrorAt (const TokenReaderT * tr, uint line, uint column, const char * format, ...) {
-  va_list argPtr;
-
-  va_start (argPtr, format);
-  TrErrorVA (tr, line, column, format, argPtr);
-  va_end (argPtr);
-}
-
-// Used to display an error at the current line/column.
-static void TrError (const TokenReaderT * tr, const char * format, ...) {
-  va_list argPtr;
-
-  va_start (argPtr, format);
-  TrErrorVA (tr, tr -> mLine, tr -> mColumn, format, argPtr);
-  va_end (argPtr);
-}
-
-// Skips to the next line.
-static void TrSkipLine (TokenReaderT * tr) {
-  char ch;
-
-  while (TrLoad (tr)) {
-    ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-    tr -> mOut ++;
-    if (ch == '\n') {
-       tr -> mLine ++;
-       tr -> mColumn = 1;
-       break;
-    }
-    tr -> mColumn ++;
-  }
-}
-
-// Skips to the next token.
-static int TrSkipWhitespace (TokenReaderT * tr) {
-  char ch;
-
-  while (TrLoad (tr)) {
-    ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-    if (isspace (ch)) {
-       tr -> mOut ++;
-       if (ch == '\n') {
-          tr -> mLine ++;
-          tr -> mColumn = 1;
-       } else {
-          tr -> mColumn ++;
-       }
-    } else if (ch == '#') {
-       TrSkipLine (tr);
-    } else {
-       return (1);
-    }
-  }
-  return (0);
-}
-
-// Get the line and/or column of the next token (or the end of input).
-static void TrIndication (TokenReaderT * tr, uint * line, uint * column) {
-  TrSkipWhitespace (tr);
-  if (line != NULL)
-     (* line) = tr -> mLine;
-  if (column != NULL)
-     (* column) = tr -> mColumn;
-}
-
-// Checks to see if a token is the given operator.  It does not display any
-// errors and will not proceed to the next token.
-static int TrIsOperator (TokenReaderT * tr, const char * op) {
-  size_t out, len;
-  char ch;
-
-  if (! TrSkipWhitespace (tr))
-     return (0);
-  out = tr -> mOut;
-  len = 0;
-  while ((op [len] != '\0') && (out < tr -> mIn)) {
-    ch = tr -> mRing [out & TR_RING_MASK];
-    if (ch != op [len])
-       break;
-    len ++;
-    out ++;
-  }
-  if (op [len] == '\0')
-     return (1);
-  return (0);
-}
-
-/* The TrRead*() routines obtain the value of a matching token type.  They
- * display type, form, and boundary errors and will proceed to the next
- * token.
- */
-
-// Reads and validates an identifier token.
-static int TrReadIdent (TokenReaderT * tr, const uint maxLen, char * ident) {
-  uint col, len;
-  char ch;
-
-  col = tr -> mColumn;
-  if (TrSkipWhitespace (tr)) {
-     col = tr -> mColumn;
-     ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-     if ((ch == '_') || isalpha (ch)) {
-        len = 0;
-        do {
-          if (len < maxLen)
-             ident [len] = ch;
-          len ++;
-          tr -> mOut ++;
-          if (! TrLoad (tr))
-             break;
-          ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-        } while ((ch == '_') || isdigit (ch) || isalpha (ch));
-        tr -> mColumn += len;
-        if (len > maxLen) {
-           TrErrorAt (tr, tr -> mLine, col, "Identifier is too long.\n");
-           return (0);
-        }
-        ident [len] = '\0';
-        return (1);
-     }
-  }
-  TrErrorAt (tr, tr -> mLine, col, "Expected an identifier.\n");
-  return (0);
-}
-
-// Reads and validates (including bounds) an integer token.
-static int TrReadInt (TokenReaderT * tr, const int loBound, const int hiBound, int * value) {
-  uint col, digis, len;
-  char ch, temp [64 + 1];
-
-  col = tr -> mColumn;
-  if (TrSkipWhitespace (tr)) {
-     col = tr -> mColumn;
-     len = 0;
-     ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-     if ((ch == '+') || (ch == '-')) {
-        temp [len] = ch;
-        len ++;
-        tr -> mOut ++;
-     }
-     digis = 0;
-     while (TrLoad (tr)) {
-       ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-       if (! isdigit (ch))
-          break;
-       if (len < 64)
-          temp [len] = ch;
-       len ++;
-       digis ++;
-       tr -> mOut ++;
-     }
-     tr -> mColumn += len;
-     if ((digis > 0) && (ch != '.') && (! isalpha (ch))) {
-        if (len > 64) {
-           TrErrorAt (tr, tr -> mLine, col, "Integer is too long.");
-           return (0);
-        }
-        temp [len] = '\0';
-        (* value) = strtol (temp, NULL, 10);
-        if (((* value) < loBound) || ((* value) > hiBound)) {
-           TrErrorAt (tr, tr -> mLine, col, "Expected a value from %d to %d.\n", loBound, hiBound);
-           return (0);
-        }
-        return (1);
-     }
-  }
-  TrErrorAt (tr, tr -> mLine, col, "Expected an integer.\n");
-  return (0);
-}
-
-// Reads and validates (including bounds) a float token.
-static int TrReadFloat (TokenReaderT * tr, const double loBound, const double hiBound, double * value) {
-  uint col, digis, len;
-  char ch, temp [64 + 1];
-
-  col = tr -> mColumn;
-  if (TrSkipWhitespace (tr)) {
-     col = tr -> mColumn;
-     len = 0;
-     ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-     if ((ch == '+') || (ch == '-')) {
-        temp [len] = ch;
-        len ++;
-        tr -> mOut ++;
-     }
-     digis = 0;
-     while (TrLoad (tr)) {
-       ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-       if (! isdigit (ch))
-          break;
-       if (len < 64)
-          temp [len] = ch;
-       len ++;
-       digis ++;
-       tr -> mOut ++;
-     }
-     if (ch == '.') {
-        if (len < 64)
-           temp [len] = ch;
-        len ++;
-        tr -> mOut ++;
-     }
-     while (TrLoad (tr)) {
-       ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-       if (! isdigit (ch))
-          break;
-       if (len < 64)
-          temp [len] = ch;
-       len ++;
-       digis ++;
-       tr -> mOut ++;
-     }
-     if (digis > 0) {
-        if ((ch == 'E') || (ch == 'e')) {
-           if (len < 64)
-              temp [len] = ch;
-           len ++;
-           digis = 0;
-           tr -> mOut ++;
-           if ((ch == '+') || (ch == '-')) {
-              if (len < 64)
-                 temp [len] = ch;
-              len ++;
-              tr -> mOut ++;
-           }
-           while (TrLoad (tr)) {
-             ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-             if (! isdigit (ch))
-                break;
-             if (len < 64)
-                temp [len] = ch;
-             len ++;
-             digis ++;
-             tr -> mOut ++;
-           }
-        }
-        tr -> mColumn += len;
-        if ((digis > 0) && (ch != '.') && (! isalpha (ch))) {
-           if (len > 64) {
-              TrErrorAt (tr, tr -> mLine, col, "Float is too long.");
-              return (0);
-           }
-           temp [len] = '\0';
-           (* value) = strtod (temp, NULL);
-           if (((* value) < loBound) || ((* value) > hiBound)) {
-              TrErrorAt (tr, tr -> mLine, col, "Expected a value from %f to %f.\n", loBound, hiBound);
-              return (0);
-           }
-           return (1);
-        }
-     } else {
-        tr -> mColumn += len;
-     }
-  }
-  TrErrorAt (tr, tr -> mLine, col, "Expected a float.\n");
-  return (0);
-}
-
-// Reads and validates a string token.
-static int TrReadString (TokenReaderT * tr, const uint maxLen, char * text) {
-  uint col, len;
-  char ch;
-
-  col = tr -> mColumn;
-  if (TrSkipWhitespace (tr)) {
-     col = tr -> mColumn;
-     ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-     if (ch == '\"') {
-        tr -> mOut ++;
-        len = 0;
-        while (TrLoad (tr)) {
-          ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-          tr -> mOut ++;
-          if (ch == '\"')
-             break;
-          if (ch == '\n') {
-             TrErrorAt (tr, tr -> mLine, col, "Unterminated string at end of line.\n");
-             return (0);
-          }
-          if (len < maxLen)
-             text [len] = ch;
-          len ++;
-        }
-        if (ch != '\"') {
-           tr -> mColumn += 1 + len;
-           TrErrorAt (tr, tr -> mLine, col, "Unterminated string at end of input.\n");
-           return (0);
-        }
-        tr -> mColumn += 2 + len;
-        if (len > maxLen) {
-           TrErrorAt (tr, tr -> mLine, col, "String is too long.\n");
-           return (0);
-        }
-        text [len] = '\0';
-        return (1);
-     }
-  }
-  TrErrorAt (tr, tr -> mLine, col, "Expected a string.\n");
-  return (0);
-}
-
-// Reads and validates the given operator.
-static int TrReadOperator (TokenReaderT * tr, const char * op) {
-  uint col, len;
-  char ch;
-
-  col = tr -> mColumn;
-  if (TrSkipWhitespace (tr)) {
-     col = tr -> mColumn;
-     len = 0;
-     while ((op [len] != '\0') && TrLoad (tr)) {
-       ch = tr -> mRing [tr -> mOut & TR_RING_MASK];
-       if (ch != op [len])
-          break;
-       len ++;
-       tr -> mOut ++;
-     }
-     tr -> mColumn += len;
-     if (op [len] == '\0')
-        return (1);
-  }
-  TrErrorAt (tr, tr -> mLine, col, "Expected '%s' operator.\n", op);
-  return (0);
-}
-
-/* Performs a string substitution.  Any case-insensitive occurrences of the
- * pattern string are replaced with the replacement string.  The result is
- * truncated if necessary.
- */
-static int StrSubst (const char * in, const char * pat, const char * rep, const size_t maxLen, char * out) {
-  size_t inLen, patLen, repLen;
-  size_t si, di;
-  int truncated;
-
-  inLen = strlen (in);
-  patLen = strlen (pat);
-  repLen = strlen (rep);
-  si = 0;
-  di = 0;
-  truncated = 0;
-  while ((si < inLen) && (di < maxLen)) {
-    if (patLen <= (inLen - si)) {
-       if (strncasecmp (& in [si], pat, patLen) == 0) {
-          if (repLen > (maxLen - di)) {
-             repLen = maxLen - di;
-             truncated = 1;
-          }
-          strncpy (& out [di], rep, repLen);
-          si += patLen;
-          di += repLen;
-       }
-    }
-    out [di] = in [si];
-    si ++;
-    di ++;
-  }
-  if (si < inLen)
-     truncated = 1;
-  out [di] = '\0';
-  return (! truncated);
-}
-
-// Provide missing math routines for MSVC versions < 1800 (Visual Studio 2013).
-#if defined(_MSC_VER) && _MSC_VER < 1800
-static double round (double val) {
-  if (val < 0.0)
-     return (ceil (val - 0.5));
-  return (floor (val + 0.5));
-}
-
-static double fmin (double a, double b) {
-  return ((a < b) ? a : b);
-}
-
-static double fmax (double a, double b) {
-  return ((a > b) ? a : b);
-}
-#endif
-
-// Simple clamp routine.
-static double Clamp (const double val, const double lower, const double upper) {
-  return (fmin (fmax (val, lower), upper));
-}
-
-// Performs linear interpolation.
-static double Lerp (const double a, const double b, const double f) {
-  return (a + (f * (b - a)));
-}
-
-// Performs a high-passed triangular probability density function dither from
-// a double to an integer.  It assumes the input sample is already scaled.
-static int HpTpdfDither (const double in, int * hpHist) {
-  const double PRNG_SCALE = 1.0 / (RAND_MAX + 1.0);
-  int prn;
-  double out;
-
-  prn = rand ();
-  out = round (in + (PRNG_SCALE * (prn - (* hpHist))));
-  (* hpHist) = prn;
-  return ((int) out);
-}
-
-// Allocates an array of doubles.
-static double *CreateArray(size_t n)
-{
-    double *a;
-
-    if(n == 0) n = 1;
-    a = calloc(n, sizeof(double));
-    if(a == NULL)
-    {
-        fprintf(stderr, "Error:  Out of memory.\n");
-        exit(-1);
-    }
-    return a;
-}
-
-// Frees an array of doubles.
-static void DestroyArray(double *a)
-{ free(a); }
-
-// Complex number routines.  All outputs must be non-NULL.
-
-// Magnitude/absolute value.
-static double ComplexAbs (const double r, const double i) {
-  return (sqrt ((r * r) + (i * i)));
-}
-
-// Multiply.
-static void ComplexMul (const double aR, const double aI, const double bR, const double bI, double * outR, double * outI) {
-  (* outR) = (aR * bR) - (aI * bI);
-  (* outI) = (aI * bR) + (aR * bI);
-}
-
-// Base-e exponent.
-static void ComplexExp (const double inR, const double inI, double * outR, double * outI) {
-  double e;
-
-  e = exp (inR);
-  (* outR) = e * cos (inI);
-  (* outI) = e * sin (inI);
-}
-
-/* Fast Fourier transform routines.  The number of points must be a power of
- * two.  In-place operation is possible only if both the real and imaginary
- * parts are in-place together.
- */
-
-// Performs bit-reversal ordering.
-static void FftArrange (const uint n, const double * inR, const double * inI, double * outR, double * outI) {
-  uint rk, k, m;
-  double tempR, tempI;
-
-  if ((inR == outR) && (inI == outI)) {
-     // Handle in-place arrangement.
-     rk = 0;
-     for (k = 0; k < n; k ++) {
-         if (rk > k) {
-            tempR = inR [rk];
-            tempI = inI [rk];
-            outR [rk] = inR [k];
-            outI [rk] = inI [k];
-            outR [k] = tempR;
-            outI [k] = tempI;
-         }
-         m = n;
-         while (rk & (m >>= 1))
-           rk &= ~m;
-         rk |= m;
-     }
-  } else {
-     // Handle copy arrangement.
-     rk = 0;
-     for (k = 0; k < n; k ++) {
-         outR [rk] = inR [k];
-         outI [rk] = inI [k];
-         m = n;
-         while (rk & (m >>= 1))
-           rk &= ~m;
-         rk |= m;
-     }
-  }
-}
-
-// Performs the summation.
-static void FftSummation (const uint n, const double s, double * re, double * im) {
-  double pi;
-  uint m, m2;
-  double vR, vI, wR, wI;
-  uint i, k, mk;
-  double tR, tI;
-
-  pi = s * M_PI;
-  for (m = 1, m2 = 2; m < n; m <<= 1, m2 <<= 1) {
-      // v = Complex (-2.0 * sin (0.5 * pi / m) * sin (0.5 * pi / m), -sin (pi / m))
-      vR = sin (0.5 * pi / m);
-      vR = -2.0 * vR * vR;
-      vI = -sin (pi / m);
-      // w = Complex (1.0, 0.0)
-      wR = 1.0;
-      wI = 0.0;
-      for (i = 0; i < m; i ++) {
-          for (k = i; k < n; k += m2) {
-              mk = k + m;
-              // t = ComplexMul (w, out [km2])
-              tR = (wR * re [mk]) - (wI * im [mk]);
-              tI = (wR * im [mk]) + (wI * re [mk]);
-              // out [mk] = ComplexSub (out [k], t)
-              re [mk] = re [k] - tR;
-              im [mk] = im [k] - tI;
-              // out [k] = ComplexAdd (out [k], t)
-              re [k] += tR;
-              im [k] += tI;
-          }
-          // t = ComplexMul (v, w)
-          tR = (vR * wR) - (vI * wI);
-          tI = (vR * wI) + (vI * wR);
-          // w = ComplexAdd (w, t)
-          wR += tR;
-          wI += tI;
-      }
-  }
-}
-
-// Performs a forward FFT.
-static void FftForward (const uint n, const double * inR, const double * inI, double * outR, double * outI) {
-  FftArrange (n, inR, inI, outR, outI);
-  FftSummation (n, 1.0, outR, outI);
-}
-
-// Performs an inverse FFT.
-static void FftInverse (const uint n, const double * inR, const double * inI, double * outR, double * outI) {
-  double f;
-  uint i;
-
-  FftArrange (n, inR, inI, outR, outI);
-  FftSummation (n, -1.0, outR, outI);
-  f = 1.0 / n;
-  for (i = 0; i < n; i ++) {
-      outR [i] *= f;
-      outI [i] *= f;
-  }
-}
-
-/* Calculate the complex helical sequence (or discrete-time analytical
- * signal) of the given input using the Hilbert transform.  Given the
- * negative natural logarithm of a signal's magnitude response, the imaginary
- * components can be used as the angles for minimum-phase reconstruction.
- */
-static void Hilbert (const uint n, const double * in, double * outR, double * outI) {
-  uint i;
-
-  if (in == outR) {
-     // Handle in-place operation.
-     for (i = 0; i < n; i ++)
-         outI [i] = 0.0;
-  } else {
-     // Handle copy operation.
-     for (i = 0; i < n; i ++) {
-         outR [i] = in [i];
-         outI [i] = 0.0;
-     }
-  }
-  FftForward (n, outR, outI, outR, outI);
-  /* Currently the Fourier routines operate only on point counts that are
-   * powers of two.  If that changes and n is odd, the following conditional
-   * should be:  i < (n + 1) / 2.
-   */
-  for (i = 1; i < (n / 2); i ++) {
-      outR [i] *= 2.0;
-      outI [i] *= 2.0;
-  }
-  // If n is odd, the following increment should be skipped.
-  i ++;
-  for (; i < n; i ++) {
-      outR [i] = 0.0;
-      outI [i] = 0.0;
-  }
-  FftInverse (n, outR, outI, outR, outI);
-}
-
-/* Calculate the magnitude response of the given input.  This is used in
- * place of phase decomposition, since the phase residuals are discarded for
- * minimum phase reconstruction.  The mirrored half of the response is also
- * discarded.
- */
-static void MagnitudeResponse (const uint n, const double * inR, const double * inI, double * out) {
-  const uint m = 1 + (n / 2);
-  uint i;
-
-  for (i = 0; i < m; i ++)
-      out [i] = fmax (ComplexAbs (inR [i], inI [i]), EPSILON);
-}
-
-/* Apply a range limit (in dB) to the given magnitude response.  This is used
- * to adjust the effects of the diffuse-field average on the equalization
- * process.
- */
-static void LimitMagnitudeResponse (const uint n, const double limit, const double * in, double * out) {
-  const uint m = 1 + (n / 2);
-  double halfLim;
-  uint i, lower, upper;
-  double ave;
-
-  halfLim = limit / 2.0;
-  // Convert the response to dB.
-  for (i = 0; i < m; i ++)
-      out [i] = 20.0 * log10 (in [i]);
-  // Use six octaves to calculate the average magnitude of the signal.
-  lower = ((uint) ceil (n / pow (2.0, 8.0))) - 1;
-  upper = ((uint) floor (n / pow (2.0, 2.0))) - 1;
-  ave = 0.0;
-  for (i = lower; i <= upper; i ++)
-      ave += out [i];
-  ave /= upper - lower + 1;
-  // Keep the response within range of the average magnitude.
-  for (i = 0; i < m; i ++)
-      out [i] = Clamp (out [i], ave - halfLim, ave + halfLim);
-  // Convert the response back to linear magnitude.
-  for (i = 0; i < m; i ++)
-      out [i] = pow (10.0, out [i] / 20.0);
-}
-
-/* Reconstructs the minimum-phase component for the given magnitude response
- * of a signal.  This is equivalent to phase recomposition, sans the missing
- * residuals (which were discarded).  The mirrored half of the response is
- * reconstructed.
- */
-static void MinimumPhase (const uint n, const double * in, double * outR, double * outI) {
-  const uint m = 1 + (n / 2);
-  double * mags = NULL;
-  uint i;
-  double aR, aI;
-
-  mags = CreateArray (n);
-  for (i = 0; i < m; i ++) {
-      mags [i] = fmax (in [i], EPSILON);
-      outR [i] = -log (mags [i]);
-  }
-  for (; i < n; i ++) {
-      mags [i] = mags [n - i];
-      outR [i] = outR [n - i];
-  }
-  Hilbert (n, outR, outR, outI);
-  // Remove any DC offset the filter has.
-  outR [0] = 0.0;
-  outI [0] = 0.0;
-  for (i = 1; i < n; i ++) {
-      ComplexExp (0.0, outI [i], & aR, & aI);
-      ComplexMul (mags [i], 0.0, aR, aI, & outR [i], & outI [i]);
-  }
-  DestroyArray (mags);
-}
-
-/* This is the normalized cardinal sine (sinc) function.
- *
- *   sinc(x) = { 1,                   x = 0
- *             { sin(pi x) / (pi x),  otherwise.
- */
-static double Sinc (const double x) {
-  if (fabs (x) < EPSILON)
-     return (1.0);
-  return (sin (M_PI * x) / (M_PI * x));
-}
-
-/* The zero-order modified Bessel function of the first kind, used for the
- * Kaiser window.
- *
- *   I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
- *          = sum_{k=0}^inf ((x / 2)^k / k!)^2
- */
-static double BesselI_0 (const double x) {
-  double term, sum, x2, y, last_sum;
-  int k;
-
-  // Start at k=1 since k=0 is trivial.
-  term = 1.0;
-  sum = 1.0;
-  x2 = x / 2.0;
-  k = 1;
-  // Let the integration converge until the term of the sum is no longer
-  // significant.
-  do {
-    y = x2 / k;
-    k ++;
-    last_sum = sum;
-    term *= y * y;
-    sum += term;
-  } while (sum != last_sum);
-  return (sum);
-}
-
-/* Calculate a Kaiser window from the given beta value and a normalized k
- * [-1, 1].
- *
- *   w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B),  -1 <= k <= 1
- *          { 0,                              elsewhere.
- *
- * Where k can be calculated as:
- *
- *   k = i / l,         where -l <= i <= l.
- *
- * or:
- *
- *   k = 2 i / M - 1,   where 0 <= i <= M.
- */
-static double Kaiser (const double b, const double k) {
-  double k2;
-
-  k2 = Clamp (k, -1.0, 1.0);
-  if ((k < -1.0) || (k > 1.0))
-     return (0.0);
-  k2 *= k2;
-  return (BesselI_0 (b * sqrt (1.0 - k2)) / BesselI_0 (b));
-}
-
-// Calculates the greatest common divisor of a and b.
-static uint Gcd (const uint a, const uint b) {
-  uint x, y, z;
-
-  x = a;
-  y = b;
-  while (y > 0) {
-    z = y;
-    y = x % y;
-    x = z;
-  }
-  return (x);
-}
-
-/* Calculates the size (order) of the Kaiser window.  Rejection is in dB and
- * the transition width is normalized frequency (0.5 is nyquist).
- *
- *   M = { ceil((r - 7.95) / (2.285 2 pi f_t)),  r > 21
- *       { ceil(5.79 / 2 pi f_t),                r <= 21.
- *
- */
-static uint CalcKaiserOrder (const double rejection, const double transition) {
-  double w_t;
-
-  w_t = 2.0 * M_PI * transition;
-  if (rejection > 21.0)
-     return ((uint) ceil ((rejection - 7.95) / (2.285 * w_t)));
-  return ((uint) ceil (5.79 / w_t));
-}
-
-// Calculates the beta value of the Kaiser window.  Rejection is in dB.
-static double CalcKaiserBeta (const double rejection) {
-  if (rejection > 50.0)
-     return (0.1102 * (rejection - 8.7));
-  else if (rejection >= 21.0)
-     return ((0.5842 * pow (rejection - 21.0, 0.4)) +
-             (0.07886 * (rejection - 21.0)));
-  else
-     return (0.0);
-}
-
-/* Calculates a point on the Kaiser-windowed sinc filter for the given half-
- * width, beta, gain, and cutoff.  The point is specified in non-normalized
- * samples, from 0 to M, where M = (2 l + 1).
- *
- *   w(k) 2 p f_t sinc(2 f_t x)
- *
- *   x    -- centered sample index (i - l)
- *   k    -- normalized and centered window index (x / l)
- *   w(k) -- window function (Kaiser)
- *   p    -- gain compensation factor when sampling
- *   f_t  -- normalized center frequency (or cutoff; 0.5 is nyquist)
- */
-static double SincFilter (const int l, const double b, const double gain, const double cutoff, const int i) {
-  return (Kaiser (b, ((double) (i - l)) / l) * 2.0 * gain * cutoff * Sinc (2.0 * cutoff * (i - l)));
-}
-
-/* This is a polyphase sinc-filtered resampler.
- *
- *              Upsample                      Downsample
- *
- *              p/q = 3/2                     p/q = 3/5
- *
- *          M-+-+-+->                     M-+-+-+->
- *         -------------------+          ---------------------+
- *   p  s * f f f f|f|        |    p  s * f f f f f           |
- *   |  0 *   0 0 0|0|0       |    |  0 *   0 0 0 0|0|        |
- *   v  0 *     0 0|0|0 0     |    v  0 *     0 0 0|0|0       |
- *      s *       f|f|f f f   |       s *       f f|f|f f     |
- *      0 *        |0|0 0 0 0 |       0 *         0|0|0 0 0   |
- *         --------+=+--------+       0 *          |0|0 0 0 0 |
- *          d . d .|d|. d . d            ----------+=+--------+
- *                                        d . . . .|d|. . . .
- *          q->
- *                                        q-+-+-+->
- *
- *   P_f(i,j) = q i mod p + pj
- *   P_s(i,j) = floor(q i / p) - j
- *   d[i=0..N-1] = sum_{j=0}^{floor((M - 1) / p)} {
- *                   { f[P_f(i,j)] s[P_s(i,j)],  P_f(i,j) < M
- *                   { 0,                        P_f(i,j) >= M. }
- */
-
-// Calculate the resampling metrics and build the Kaiser-windowed sinc filter
-// that's used to cut frequencies above the destination nyquist.
-static void ResamplerSetup (ResamplerT * rs, const uint srcRate, const uint dstRate) {
-  uint gcd, l;
-  double cutoff, width, beta;
-  int i;
-
-  gcd = Gcd (srcRate, dstRate);
-  rs -> mP = dstRate / gcd;
-  rs -> mQ = srcRate / gcd;
-  /* The cutoff is adjusted by half the transition width, so the transition
-   * ends before the nyquist (0.5).  Both are scaled by the downsampling
-   * factor.
-   */
-  if (rs -> mP > rs -> mQ) {
-     cutoff = 0.45 / rs -> mP;
-     width = 0.1 / rs -> mP;
-  } else {
-     cutoff = 0.45 / rs -> mQ;
-     width = 0.1 / rs -> mQ;
-  }
-  // A rejection of -180 dB is used for the stop band.
-  l = CalcKaiserOrder (180.0, width) / 2;
-  beta = CalcKaiserBeta (180.0);
-  rs -> mM = (2 * l) + 1;
-  rs -> mL = l;
-  rs -> mF = CreateArray (rs -> mM);
-  for (i = 0; i < ((int) rs -> mM); i ++)
-      rs -> mF [i] = SincFilter ((int) l, beta, rs -> mP, cutoff, i);
-}
-
-// Clean up after the resampler.
-static void ResamplerClear (ResamplerT * rs) {
-  DestroyArray (rs -> mF);
-  rs -> mF = NULL;
-}
-
-// Perform the upsample-filter-downsample resampling operation using a
-// polyphase filter implementation.
-static void ResamplerRun (ResamplerT * rs, const uint inN, const double * in, const uint outN, double * out) {
-  const uint p = rs -> mP, q = rs -> mQ, m = rs -> mM, l = rs -> mL;
-  const double * f = rs -> mF;
-  double * work = NULL;
-  uint i;
-  double r;
-  uint j_f, j_s;
-
-  if (outN == 0)
-     return;
-
-  // Handle in-place operation.
-  if (in == out)
-     work = CreateArray (outN);
-  else
-     work = out;
-  // Resample the input.
-  for (i = 0; i < outN; i ++) {
-      r = 0.0;
-      // Input starts at l to compensate for the filter delay.  This will
-      // drop any build-up from the first half of the filter.
-      j_f = (l + (q * i)) % p;
-      j_s = (l + (q * i)) / p;
-      while (j_f < m) {
-        // Only take input when 0 <= j_s < inN.  This single unsigned
-        // comparison catches both cases.
-        if (j_s < inN)
-           r += f [j_f] * in [j_s];
-        j_f += p;
-        j_s --;
-      }
-      work [i] = r;
-  }
-  // Clean up after in-place operation.
-  if (in == out) {
-     for (i = 0; i < outN; i ++)
-         out [i] = work [i];
-     DestroyArray (work);
-  }
-}
-
-// Read a binary value of the specified byte order and byte size from a file,
-// storing it as a 32-bit unsigned integer.
-static int ReadBin4 (FILE * fp, const char * filename, const ByteOrderT order, const uint bytes, uint32 * out) {
-  uint8 in [4];
-  uint32 accum;
-  uint i;
-
-  if (fread (in, 1, bytes, fp) != bytes) {
-     fprintf (stderr, "Error:  Bad read from file '%s'.\n", filename);
-     return (0);
-  }
-  accum = 0;
-  switch (order) {
-    case BO_LITTLE :
-      for (i = 0; i < bytes; i ++)
-          accum = (accum << 8) | in [bytes - i - 1];
-    break;
-    case BO_BIG :
-      for (i = 0; i < bytes; i ++)
-          accum = (accum << 8) | in [i];
-    break;
-    default :
-    break;
-  }
-  (* out) = accum;
-  return (1);
-}
-
-// Read a binary value of the specified byte order from a file, storing it as
-// a 64-bit unsigned integer.
-static int ReadBin8 (FILE * fp, const char * filename, const ByteOrderT order, uint64 * out) {
-  uint8 in [8];
-  uint64 accum;
-  uint i;
-
-  if (fread (in, 1, 8, fp) != 8) {
-     fprintf (stderr, "Error:  Bad read from file '%s'.\n", filename);
-     return (0);
-  }
-  accum = 0ULL;
-  switch (order) {
-    case BO_LITTLE :
-      for (i = 0; i < 8; i ++)
-          accum = (accum << 8) | in [8 - i - 1];
-    break;
-    case BO_BIG :
-      for (i = 0; i < 8; i ++)
-          accum = (accum << 8) | in [i];
-    break;
-    default :
-    break;
-  }
-  (* out) = accum;
-  return (1);
-}
-
-// Write an ASCII string to a file.
-static int WriteAscii (const char * out, FILE * fp, const char * filename) {
-  size_t len;
-
-  len = strlen (out);
-  if (fwrite (out, 1, len, fp) != len) {
-     fclose (fp);
-     fprintf (stderr, "Error:  Bad write to file '%s'.\n", filename);
-     return (0);
-  }
-  return (1);
-}
-
-// Write a binary value of the given byte order and byte size to a file,
-// loading it from a 32-bit unsigned integer.
-static int WriteBin4 (const ByteOrderT order, const uint bytes, const uint32 in, FILE * fp, const char * filename) {
-  uint8 out [4];
-  uint i;
-
-  switch (order) {
-    case BO_LITTLE :
-      for (i = 0; i < bytes; i ++)
-          out [i] = (in >> (i * 8)) & 0x000000FF;
-    break;
-    case BO_BIG :
-      for (i = 0; i < bytes; i ++)
-          out [bytes - i - 1] = (in >> (i * 8)) & 0x000000FF;
-    break;
-    default :
-    break;
-  }
-  if (fwrite (out, 1, bytes, fp) != bytes) {
-     fprintf (stderr, "Error:  Bad write to file '%s'.\n", filename);
-     return (0);
-  }
-  return (1);
-}
-
-/* Read a binary value of the specified type, byte order, and byte size from
- * a file, converting it to a double.  For integer types, the significant
- * bits are used to normalize the result.  The sign of bits determines
- * whether they are padded toward the MSB (negative) or LSB (positive).
- * Floating-point types are not normalized.
- */
-static int ReadBinAsDouble (FILE * fp, const char * filename, const ByteOrderT order, const ElementTypeT type, const uint bytes, const int bits, double * out) {
-  union {
-    uint32 ui;
-    int32 i;
-    float f;
-  } v4;
-  union {
-    uint64 ui;
-    double f;
-  } v8;
-
-  (* out) = 0.0;
-  if (bytes > 4) {
-     if (! ReadBin8 (fp, filename, order, & v8 . ui))
-        return (0);
-     if (type == ET_FP)
-        (* out) = v8 . f;
-  } else {
-     if (! ReadBin4 (fp, filename, order, bytes, & v4 . ui))
-        return (0);
-     if (type == ET_FP) {
-        (* out) = (double) v4 . f;
-     } else {
-        if (bits > 0)
-           v4 . ui >>= (8 * bytes) - ((uint) bits);
-        else
-           v4 . ui &= (0xFFFFFFFF >> (32 + bits));
-        if (v4 . ui & ((uint) (1 << (abs (bits) - 1))))
-           v4 . ui |= (0xFFFFFFFF << abs (bits));
-        (* out) = v4 . i / ((double) (1 << (abs (bits) - 1)));
-     }
-  }
-  return (1);
-}
-
-/* Read an ascii value of the specified type from a file, converting it to a
- * double.  For integer types, the significant bits are used to normalize the
- * result.  The sign of the bits should always be positive.  This also skips
- * up to one separator character before the element itself.
- */
-static int ReadAsciiAsDouble (TokenReaderT * tr, const char * filename, const ElementTypeT type, const uint bits, double * out) {
-  int v;
-
-  if (TrIsOperator (tr, ","))
-     TrReadOperator (tr, ",");
-  else if (TrIsOperator (tr, ":"))
-     TrReadOperator (tr, ":");
-  else if (TrIsOperator (tr, ";"))
-     TrReadOperator (tr, ";");
-  else if (TrIsOperator (tr, "|"))
-     TrReadOperator (tr, "|");
-  if (type == ET_FP) {
-     if (! TrReadFloat (tr, -HUGE_VAL, HUGE_VAL, out)) {
-        fprintf (stderr, "Error:  Bad read from file '%s'.\n", filename);
-        return (0);
-     }
-  } else {
-     if (! TrReadInt (tr, -(1 << (bits - 1)), (1 << (bits - 1)) - 1, & v)) {
-        fprintf (stderr, "Error:  Bad read from file '%s'.\n", filename);
-        return (0);
-     }
-     (* out) = v / ((double) ((1 << (bits - 1)) - 1));
-  }
-  return (1);
-}
-
-// Read the RIFF/RIFX WAVE format chunk from a file, validating it against
-// the source parameters and data set metrics.
-static int ReadWaveFormat (FILE * fp, const ByteOrderT order, const uint hrirRate, SourceRefT * src) {
-  uint32 fourCC, chunkSize;
-  uint32 format, channels, rate, dummy, block, size, bits;
-
-  chunkSize = 0;
-  do {
-    if (chunkSize > 0)
-       fseek (fp, (long) chunkSize, SEEK_CUR);
-    if ((! ReadBin4 (fp, src -> mPath, BO_LITTLE, 4, & fourCC)) ||
-        (! ReadBin4 (fp, src -> mPath, order, 4, & chunkSize)))
-       return (0);
-  } while (fourCC != FOURCC_FMT);
-  if ((! ReadBin4 (fp, src -> mPath, order, 2, & format)) ||
-      (! ReadBin4 (fp, src -> mPath, order, 2, & channels)) ||
-      (! ReadBin4 (fp, src -> mPath, order, 4, & rate)) ||
-      (! ReadBin4 (fp, src -> mPath, order, 4, & dummy)) ||
-      (! ReadBin4 (fp, src -> mPath, order, 2, & block)))
-     return (0);
-  block /= channels;
-  if (chunkSize > 14) {
-     if (! ReadBin4 (fp, src -> mPath, order, 2, & size))
-        return (0);
-     size /= 8;
-     if (block > size)
-        size = block;
-  } else {
-     size = block;
-  }
-  if (format == WAVE_FORMAT_EXTENSIBLE) {
-     fseek (fp, 2, SEEK_CUR);
-     if (! ReadBin4 (fp, src -> mPath, order, 2, & bits))
-        return (0);
-     if (bits == 0)
-        bits = 8 * size;
-     fseek (fp, 4, SEEK_CUR);
-     if (! ReadBin4 (fp, src -> mPath, order, 2, & format))
-        return (0);
-     fseek (fp, (long) (chunkSize - 26), SEEK_CUR);
-  } else {
-     bits = 8 * size;
-     if (chunkSize > 14)
-        fseek (fp, (long) (chunkSize - 16), SEEK_CUR);
-     else
-        fseek (fp, (long) (chunkSize - 14), SEEK_CUR);
-  }
-  if ((format != WAVE_FORMAT_PCM) && (format != WAVE_FORMAT_IEEE_FLOAT)) {
-     fprintf (stderr, "Error:  Unsupported WAVE format in file '%s'.\n", src -> mPath);
-     return (0);
-  }
-  if (src -> mChannel >= channels) {
-     fprintf (stderr, "Error:  Missing source channel in WAVE file '%s'.\n", src -> mPath);
-     return (0);
-  }
-  if (rate != hrirRate) {
-     fprintf (stderr, "Error:  Mismatched source sample rate in WAVE file '%s'.\n", src -> mPath);
-     return (0);
-  }
-  if (format == WAVE_FORMAT_PCM) {
-     if ((size < 2) || (size > 4)) {
-        fprintf (stderr, "Error:  Unsupported sample size in WAVE file '%s'.\n", src -> mPath);
-        return (0);
-     }
-     if ((bits < 16) || (bits > (8 * size))) {
-        fprintf (stderr, "Error:  Bad significant bits in WAVE file '%s'.\n", src -> mPath);
-        return (0);
-     }
-     src -> mType = ET_INT;
-  } else {
-     if ((size != 4) && (size != 8)) {
-        fprintf (stderr, "Error:  Unsupported sample size in WAVE file '%s'.\n", src -> mPath);
-        return (0);
-     }
-     src -> mType = ET_FP;
-  }
-  src -> mSize = size;
-  src -> mBits = (int) bits;
-  src -> mSkip = channels;
-  return (1);
-}
-
-// Read a RIFF/RIFX WAVE data chunk, converting all elements to doubles.
-static int ReadWaveData (FILE * fp, const SourceRefT * src, const ByteOrderT order, const uint n, double * hrir) {
-  int pre, post, skip;
-  uint i;
-
-  pre = (int) (src -> mSize * src -> mChannel);
-  post = (int) (src -> mSize * (src -> mSkip - src -> mChannel - 1));
-  skip = 0;
-  for (i = 0; i < n; i ++) {
-      skip += pre;
-      if (skip > 0)
-         fseek (fp, skip, SEEK_CUR);
-      if (! ReadBinAsDouble (fp, src -> mPath, order, src -> mType, src -> mSize, src -> mBits, & hrir [i]))
-         return (0);
-      skip = post;
-  }
-  if (skip > 0)
-     fseek (fp, skip, SEEK_CUR);
-  return (1);
-}
-
-// Read the RIFF/RIFX WAVE list or data chunk, converting all elements to
-// doubles.
-static int ReadWaveList (FILE * fp, const SourceRefT * src, const ByteOrderT order, const uint n, double * hrir) {
-  uint32 fourCC, chunkSize, listSize, count;
-  uint block, skip, offset, i;
-  double lastSample;
-
-  for (;;) {
-      if ((! ReadBin4 (fp, src -> mPath, BO_LITTLE, 4, & fourCC)) ||
-          (! ReadBin4 (fp, src -> mPath, order, 4, & chunkSize)))
-         return (0);
-      if (fourCC == FOURCC_DATA) {
-         block = src -> mSize * src -> mSkip;
-         count = chunkSize / block;
-         if (count < (src -> mOffset + n)) {
-            fprintf (stderr, "Error:  Bad read from file '%s'.\n", src -> mPath);
-            return (0);
-         }
-         fseek (fp, (long) (src -> mOffset * block), SEEK_CUR);
-         if (! ReadWaveData (fp, src, order, n, & hrir [0]))
-            return (0);
-         return (1);
-      } else if (fourCC == FOURCC_LIST) {
-         if (! ReadBin4 (fp, src -> mPath, BO_LITTLE, 4, & fourCC))
-            return (0);
-         chunkSize -= 4;
-         if (fourCC == FOURCC_WAVL)
-            break;
-      }
-      if (chunkSize > 0)
-         fseek (fp, (long) chunkSize, SEEK_CUR);
-  }
-  listSize = chunkSize;
-  block = src -> mSize * src -> mSkip;
-  skip = src -> mOffset;
-  offset = 0;
-  lastSample = 0.0;
-  while ((offset < n) && (listSize > 8)) {
-    if ((! ReadBin4 (fp, src -> mPath, BO_LITTLE, 4, & fourCC)) ||
-        (! ReadBin4 (fp, src -> mPath, order, 4, & chunkSize)))
-       return (0);
-    listSize -= 8 + chunkSize;
-    if (fourCC == FOURCC_DATA) {
-       count = chunkSize / block;
-       if (count > skip) {
-          fseek (fp, (long) (skip * block), SEEK_CUR);
-          chunkSize -= skip * block;
-          count -= skip;
-          skip = 0;
-          if (count > (n - offset))
-             count = n - offset;
-          if (! ReadWaveData (fp, src, order, count, & hrir [offset]))
-             return (0);
-          chunkSize -= count * block;
-          offset += count;
-          lastSample = hrir [offset - 1];
-       } else {
-          skip -= count;
-          count = 0;
-       }
-    } else if (fourCC == FOURCC_SLNT) {
-       if (! ReadBin4 (fp, src -> mPath, order, 4, & count))
-          return (0);
-       chunkSize -= 4;
-       if (count > skip) {
-          count -= skip;
-          skip = 0;
-          if (count > (n - offset))
-             count = n - offset;
-          for (i = 0; i < count; i ++)
-              hrir [offset + i] = lastSample;
-          offset += count;
-       } else {
-          skip -= count;
-          count = 0;
-       }
-    }
-    if (chunkSize > 0)
-       fseek (fp, (long) chunkSize, SEEK_CUR);
-  }
-  if (offset < n) {
-     fprintf (stderr, "Error:  Bad read from file '%s'.\n", src -> mPath);
-     return (0);
-  }
-  return (1);
-}
-
-// Load a source HRIR from a RIFF/RIFX WAVE file.
-static int LoadWaveSource (FILE * fp, SourceRefT * src, const uint hrirRate, const uint n, double * hrir) {
-  uint32 fourCC, dummy;
-  ByteOrderT order;
-
-  if ((! ReadBin4 (fp, src -> mPath, BO_LITTLE, 4, & fourCC)) ||
-      (! ReadBin4 (fp, src -> mPath, BO_LITTLE, 4, & dummy)))
-     return (0);
-  if (fourCC == FOURCC_RIFF) {
-     order = BO_LITTLE;
-  } else if (fourCC == FOURCC_RIFX) {
-     order = BO_BIG;
-  } else {
-     fprintf (stderr, "Error:  No RIFF/RIFX chunk in file '%s'.\n", src -> mPath);
-     return (0);
-  }
-  if (! ReadBin4 (fp, src -> mPath, BO_LITTLE, 4, & fourCC))
-     return (0);
-  if (fourCC != FOURCC_WAVE) {
-     fprintf (stderr, "Error:  Not a RIFF/RIFX WAVE file '%s'.\n", src -> mPath);
-     return (0);
-  }
-  if (! ReadWaveFormat (fp, order, hrirRate, src))
-     return (0);
-  if (! ReadWaveList (fp, src, order, n, hrir))
-     return (0);
-  return (1);
-}
-
-// Load a source HRIR from a binary file.
-static int LoadBinarySource (FILE * fp, const SourceRefT * src, const ByteOrderT order, const uint n, double * hrir) {
-  uint i;
-
-  fseek (fp, (long) src -> mOffset, SEEK_SET);
-  for (i = 0; i < n; i ++) {
-      if (! ReadBinAsDouble (fp, src -> mPath, order, src -> mType, src -> mSize, src -> mBits, & hrir [i]))
-         return (0);
-      if (src -> mSkip > 0)
-         fseek (fp, (long) src -> mSkip, SEEK_CUR);
-  }
-  return (1);
-}
-
-// Load a source HRIR from an ASCII text file containing a list of elements
-// separated by whitespace or common list operators (',', ';', ':', '|').
-static int LoadAsciiSource (FILE * fp, const SourceRefT * src, const uint n, double * hrir) {
-  TokenReaderT tr;
-  uint i, j;
-  double dummy;
-
-  TrSetup (fp, NULL, & tr);
-  for (i = 0; i < src -> mOffset; i ++) {
-      if (! ReadAsciiAsDouble (& tr, src -> mPath, src -> mType, (uint) src -> mBits, & dummy))
-         return (0);
-  }
-  for (i = 0; i < n; i ++) {
-      if (! ReadAsciiAsDouble (& tr, src -> mPath, src -> mType, (uint) src -> mBits, & hrir [i]))
-         return (0);
-      for (j = 0; j < src -> mSkip; j ++) {
-          if (! ReadAsciiAsDouble (& tr, src -> mPath, src -> mType, (uint) src -> mBits, & dummy))
-             return (0);
-      }
-  }
-  return (1);
-}
-
-// Load a source HRIR from a supported file type.
-static int LoadSource (SourceRefT * src, const uint hrirRate, const uint n, double * hrir) {
-  FILE * fp = NULL;
-  int result;
-
-  if (src -> mFormat == SF_ASCII)
-     fp = fopen (src -> mPath, "r");
-  else
-     fp = fopen (src -> mPath, "rb");
-  if (fp == NULL) {
-     fprintf (stderr, "Error:  Could not open source file '%s'.\n", src -> mPath);
-     return (0);
-  }
-  if (src -> mFormat == SF_WAVE)
-     result = LoadWaveSource (fp, src, hrirRate, n, hrir);
-  else if (src -> mFormat == SF_BIN_LE)
-     result = LoadBinarySource (fp, src, BO_LITTLE, n, hrir);
-  else if (src -> mFormat == SF_BIN_BE)
-     result = LoadBinarySource (fp, src, BO_BIG, n, hrir);
-  else
-     result = LoadAsciiSource (fp, src, n, hrir);
-  fclose (fp);
-  return (result);
-}
-
-// Calculate the onset time of an HRIR and average it with any existing
-// timing for its elevation and azimuth.
-static void AverageHrirOnset (const double * hrir, const double f, const uint ei, const uint ai, const HrirDataT * hData) {
-  double mag;
-  uint n, i, j;
-
-  mag = 0.0;
-  n = hData -> mIrPoints;
-  for (i = 0; i < n; i ++)
-      mag = fmax (fabs (hrir [i]), mag);
-  mag *= 0.15;
-  for (i = 0; i < n; i ++) {
-      if (fabs (hrir [i]) >= mag)
-         break;
-  }
-  j = hData -> mEvOffset [ei] + ai;
-  hData -> mHrtds [j] = Lerp (hData -> mHrtds [j], ((double) i) / hData -> mIrRate, f);
-}
-
-// Calculate the magnitude response of an HRIR and average it with any
-// existing responses for its elevation and azimuth.
-static void AverageHrirMagnitude (const double * hrir, const double f, const uint ei, const uint ai, const HrirDataT * hData) {
-  double * re = NULL, * im = NULL;
-  uint n, m, i, j;
-
-  n = hData -> mFftSize;
-  re = CreateArray (n);
-  im = CreateArray (n);
-  for (i = 0; i < hData -> mIrPoints; i ++) {
-      re [i] = hrir [i];
-      im [i] = 0.0;
-  }
-  for (; i < n; i ++) {
-      re [i] = 0.0;
-      im [i] = 0.0;
-  }
-  FftForward (n, re, im, re, im);
-  MagnitudeResponse (n, re, im, re);
-  m = 1 + (n / 2);
-  j = (hData -> mEvOffset [ei] + ai) * hData -> mIrSize;
-  for (i = 0; i < m; i ++)
-      hData -> mHrirs [j + i] = Lerp (hData -> mHrirs [j + i], re [i], f);
-  DestroyArray (im);
-  DestroyArray (re);
-}
-
-/* Calculate the contribution of each HRIR to the diffuse-field average based
- * on the area of its surface patch.  All patches are centered at the HRIR
- * coordinates on the unit sphere and are measured by solid angle.
- */
-static void CalculateDfWeights (const HrirDataT * hData, double * weights) {
-  uint ei;
-  double evs, sum, ev, up_ev, down_ev, solidAngle;
-
-  evs = 90.0 / (hData -> mEvCount - 1);
-  sum = 0.0;
-  for (ei = hData -> mEvStart; ei < hData -> mEvCount; ei ++) {
-      // For each elevation, calculate the upper and lower limits of the
-      // patch band.
-      ev = -90.0 + (ei * 2.0 * evs);
-      if (ei < (hData -> mEvCount - 1))
-         up_ev = (ev + evs) * M_PI / 180.0;
-      else
-         up_ev = M_PI / 2.0;
-      if (ei > 0)
-         down_ev = (ev - evs) * M_PI / 180.0;
-      else
-         down_ev = -M_PI / 2.0;
-      // Calculate the area of the patch band.
-      solidAngle = 2.0 * M_PI * (sin (up_ev) - sin (down_ev));
-      // Each weight is the area of one patch.
-      weights [ei] = solidAngle / hData -> mAzCount [ei];
-      // Sum the total surface area covered by the HRIRs.
-      sum += solidAngle;
-  }
-  // Normalize the weights given the total surface coverage.
-  for (ei = hData -> mEvStart; ei < hData -> mEvCount; ei ++)
-      weights [ei] /= sum;
-}
-
-/* Calculate the diffuse-field average from the given magnitude responses of
- * the HRIR set.  Weighting can be applied to compensate for the varying
- * surface area covered by each HRIR.  The final average can then be limited
- * by the specified magnitude range (in positive dB; 0.0 to skip).
- */
-static void CalculateDiffuseFieldAverage (const HrirDataT * hData, const int weighted, const double limit, double * dfa) {
-  double * weights = NULL;
-  uint ei, ai, count, step, start, end, m, j, i;
-  double weight;
-
-  weights = CreateArray (hData -> mEvCount);
-  if (weighted) {
-     // Use coverage weighting to calculate the average.
-     CalculateDfWeights (hData, weights);
-  } else {
-     // If coverage weighting is not used, the weights still need to be
-     // averaged by the number of HRIRs.
-     count = 0;
-     for (ei = hData -> mEvStart; ei < hData -> mEvCount; ei ++)
-         count += hData -> mAzCount [ei];
-     for (ei = hData -> mEvStart; ei < hData -> mEvCount; ei ++)
-         weights [ei] = 1.0 / count;
-  }
-  ei = hData -> mEvStart;
-  ai = 0;
-  step = hData -> mIrSize;
-  start = hData -> mEvOffset [ei] * step;
-  end = hData -> mIrCount * step;
-  m = 1 + (hData -> mFftSize / 2);
-  for (i = 0; i < m; i ++)
-      dfa [i] = 0.0;
-  for (j = start; j < end; j += step) {
-      // Get the weight for this HRIR's contribution.
-      weight = weights [ei];
-      // Add this HRIR's weighted power average to the total.
-      for (i = 0; i < m; i ++)
-          dfa [i] += weight * hData -> mHrirs [j + i] * hData -> mHrirs [j + i];
-      // Determine the next weight to use.
-      ai ++;
-      if (ai >= hData -> mAzCount [ei]) {
-         ei ++;
-         ai = 0;
-      }
-  }
-  // Finish the average calculation and keep it from being too small.
-  for (i = 0; i < m; i ++)
-      dfa [i] = fmax (sqrt (dfa [i]), EPSILON);
-  // Apply a limit to the magnitude range of the diffuse-field average if
-  // desired.
-  if (limit > 0.0)
-     LimitMagnitudeResponse (hData -> mFftSize, limit, dfa, dfa);
-  DestroyArray (weights);
-}
-
-// Perform diffuse-field equalization on the magnitude responses of the HRIR
-// set using the given average response.
-static void DiffuseFieldEqualize (const double * dfa, const HrirDataT * hData) {
-  uint step, start, end, m, j, i;
-
-  step = hData -> mIrSize;
-  start = hData -> mEvOffset [hData -> mEvStart] * step;
-  end = hData -> mIrCount * step;
-  m = 1 + (hData -> mFftSize / 2);
-  for (j = start; j < end; j += step) {
-      for (i = 0; i < m; i ++)
-          hData -> mHrirs [j + i] /= dfa [i];
-  }
-}
-
-// Perform minimum-phase reconstruction using the magnitude responses of the
-// HRIR set.
-static void ReconstructHrirs (const HrirDataT * hData) {
-  double * re = NULL, * im = NULL;
-  uint step, start, end, n, j, i;
-
-  step = hData -> mIrSize;
-  start = hData -> mEvOffset [hData -> mEvStart] * step;
-  end = hData -> mIrCount * step;
-  n = hData -> mFftSize;
-  re = CreateArray (n);
-  im = CreateArray (n);
-  for (j = start; j < end; j += step) {
-      MinimumPhase (n, & hData -> mHrirs [j], re, im);
-      FftInverse (n, re, im, re, im);
-      for (i = 0; i < hData -> mIrPoints; i ++)
-          hData -> mHrirs [j + i] = re [i];
-  }
-  DestroyArray (im);
-  DestroyArray (re);
-}
-
-// Resamples the HRIRs for use at the given sampling rate.
-static void ResampleHrirs (const uint rate, HrirDataT * hData) {
-  ResamplerT rs;
-  uint n, step, start, end, j;
-
-  ResamplerSetup (& rs, hData -> mIrRate, rate);
-  n = hData -> mIrPoints;
-  step = hData -> mIrSize;
-  start = hData -> mEvOffset [hData -> mEvStart] * step;
-  end = hData -> mIrCount * step;
-  for (j = start; j < end; j += step)
-      ResamplerRun (& rs, n, & hData -> mHrirs [j], n, & hData -> mHrirs [j]);
-  ResamplerClear (& rs);
-  hData -> mIrRate = rate;
-}
-
-/* Given an elevation index and an azimuth, calculate the indices of the two
- * HRIRs that bound the coordinate along with a factor for calculating the
- * continous HRIR using interpolation.
- */
-static void CalcAzIndices (const HrirDataT * hData, const uint ei, const double az, uint * j0, uint * j1, double * jf) {
-  double af;
-  uint ai;
-
-  af = ((2.0 * M_PI) + az) * hData -> mAzCount [ei] / (2.0 * M_PI);
-  ai = ((uint) af) % hData -> mAzCount [ei];
-  af -= floor (af);
-  (* j0) = hData -> mEvOffset [ei] + ai;
-  (* j1) = hData -> mEvOffset [ei] + ((ai + 1) % hData -> mAzCount [ei]);
-  (* jf) = af;
-}
-
-// Synthesize any missing onset timings at the bottom elevations.  This just
-// blends between slightly exaggerated known onsets.  Not an accurate model.
-static void SynthesizeOnsets (HrirDataT * hData) {
-  uint oi, e, a, j0, j1;
-  double t, of, jf;
-
-  oi = hData -> mEvStart;
-  t = 0.0;
-  for (a = 0; a < hData -> mAzCount [oi]; a ++)
-      t += hData -> mHrtds [hData -> mEvOffset [oi] + a];
-  hData -> mHrtds [0] = 1.32e-4 + (t / hData -> mAzCount [oi]);
-  for (e = 1; e < hData -> mEvStart; e ++) {
-      of = ((double) e) / hData -> mEvStart;
-      for (a = 0; a < hData -> mAzCount [e]; a ++) {
-          CalcAzIndices (hData, oi, a * 2.0 * M_PI / hData -> mAzCount [e], & j0, & j1, & jf);
-          hData -> mHrtds [hData -> mEvOffset [e] + a] = Lerp (hData -> mHrtds [0], Lerp (hData -> mHrtds [j0], hData -> mHrtds [j1], jf), of);
-      }
-  }
-}
-
-/* Attempt to synthesize any missing HRIRs at the bottom elevations.  Right
- * now this just blends the lowest elevation HRIRs together and applies some
- * attenuation and high frequency damping.  It is a simple, if inaccurate
- * model.
- */
-static void SynthesizeHrirs (HrirDataT * hData) {
-  uint oi, a, e, step, n, i, j;
-  double of, b;
-  uint j0, j1;
-  double jf;
-  double lp [4], s0, s1;
-
-  if (hData -> mEvStart <= 0)
-     return;
-  step = hData -> mIrSize;
-  oi = hData -> mEvStart;
-  n = hData -> mIrPoints;
-  for (i = 0; i < n; i ++)
-      hData -> mHrirs [i] = 0.0;
-  for (a = 0; a < hData -> mAzCount [oi]; a ++) {
-      j = (hData -> mEvOffset [oi] + a) * step;
-      for (i = 0; i < n; i ++)
-          hData -> mHrirs [i] += hData -> mHrirs [j + i] / hData -> mAzCount [oi];
-  }
-  for (e = 1; e < hData -> mEvStart; e ++) {
-      of = ((double) e) / hData -> mEvStart;
-      b = (1.0 - of) * (3.5e-6 * hData -> mIrRate);
-      for (a = 0; a < hData -> mAzCount [e]; a ++) {
-          j = (hData -> mEvOffset [e] + a) * step;
-          CalcAzIndices (hData, oi, a * 2.0 * M_PI / hData -> mAzCount [e], & j0, & j1, & jf);
-          j0 *= step;
-          j1 *= step;
-          lp [0] = 0.0;
-          lp [1] = 0.0;
-          lp [2] = 0.0;
-          lp [3] = 0.0;
-          for (i = 0; i < n; i ++) {
-              s0 = hData -> mHrirs [i];
-              s1 = Lerp (hData -> mHrirs [j0 + i], hData -> mHrirs [j1 + i], jf);
-              s0 = Lerp (s0, s1, of);
-              lp [0] = Lerp (s0, lp [0], b);
-              lp [1] = Lerp (lp [0], lp [1], b);
-              lp [2] = Lerp (lp [1], lp [2], b);
-              lp [3] = Lerp (lp [2], lp [3], b);
-              hData -> mHrirs [j + i] = lp [3];
-          }
-      }
-  }
-  b = 3.5e-6 * hData -> mIrRate;
-  lp [0] = 0.0;
-  lp [1] = 0.0;
-  lp [2] = 0.0;
-  lp [3] = 0.0;
-  for (i = 0; i < n; i ++) {
-      s0 = hData -> mHrirs [i];
-      lp [0] = Lerp (s0, lp [0], b);
-      lp [1] = Lerp (lp [0], lp [1], b);
-      lp [2] = Lerp (lp [1], lp [2], b);
-      lp [3] = Lerp (lp [2], lp [3], b);
-      hData -> mHrirs [i] = lp [3];
-  }
-  hData -> mEvStart = 0;
-}
-
-// The following routines assume a full set of HRIRs for all elevations.
-
-// Normalize the HRIR set and slightly attenuate the result.
-static void NormalizeHrirs (const HrirDataT * hData) {
-  uint step, end, n, j, i;
-  double maxLevel;
-
-  step = hData -> mIrSize;
-  end = hData -> mIrCount * step;
-  n = hData -> mIrPoints;
-  maxLevel = 0.0;
-  for (j = 0; j < end; j += step) {
-      for (i = 0; i < n; i ++)
-          maxLevel = fmax (fabs (hData -> mHrirs [j + i]), maxLevel);
-  }
-  maxLevel = 1.01 * maxLevel;
-  for (j = 0; j < end; j += step) {
-      for (i = 0; i < n; i ++)
-          hData -> mHrirs [j + i] /= maxLevel;
-  }
-}
-
-// Calculate the left-ear time delay using a spherical head model.
-static double CalcLTD (const double ev, const double az, const double rad, const double dist) {
-  double azp, dlp, l, al;
-
-  azp = asin (cos (ev) * sin (az));
-  dlp = sqrt ((dist * dist) + (rad * rad) + (2.0 * dist * rad * sin (azp)));
-  l = sqrt ((dist * dist) - (rad * rad));
-  al = (0.5 * M_PI) + azp;
-  if (dlp > l)
-     dlp = l + (rad * (al - acos (rad / dist)));
-  return (dlp / 343.3);
-}
-
-// Calculate the effective head-related time delays for each minimum-phase
-// HRIR.
-static void CalculateHrtds (const HeadModelT model, const double radius, HrirDataT * hData) {
-  double minHrtd, maxHrtd;
-  uint e, a, j;
-  double t;
-
-  minHrtd = 1000.0;
-  maxHrtd = -1000.0;
-  for (e = 0; e < hData -> mEvCount; e ++) {
-      for (a = 0; a < hData -> mAzCount [e]; a ++) {
-          j = hData -> mEvOffset [e] + a;
-          if (model == HM_DATASET) {
-             t = hData -> mHrtds [j] * radius / hData -> mRadius;
-          } else {
-             t = CalcLTD ((-90.0 + (e * 180.0 / (hData -> mEvCount - 1))) * M_PI / 180.0,
-                          (a * 360.0 / hData -> mAzCount [e]) * M_PI / 180.0,
-                          radius, hData -> mDistance);
-          }
-          hData -> mHrtds [j] = t;
-          maxHrtd = fmax (t, maxHrtd);
-          minHrtd = fmin (t, minHrtd);
-      }
-  }
-  maxHrtd -= minHrtd;
-  for (j = 0; j < hData -> mIrCount; j ++)
-      hData -> mHrtds [j] -= minHrtd;
-  hData -> mMaxHrtd = maxHrtd;
-}
-
-// Store the OpenAL Soft HRTF data set.
-static int StoreMhr (const HrirDataT * hData, const char * filename) {
-  FILE * fp = NULL;
-  uint e, step, end, n, j, i;
-  int hpHist, v;
-
-  if ((fp = fopen (filename, "wb")) == NULL) {
-     fprintf (stderr, "Error:  Could not open MHR file '%s'.\n", filename);
-     return (0);
-  }
-  if (! WriteAscii (MHR_FORMAT, fp, filename))
-     return (0);
-  if (! WriteBin4 (BO_LITTLE, 4, (uint32) hData -> mIrRate, fp, filename))
-     return (0);
-  if (! WriteBin4 (BO_LITTLE, 1, (uint32) hData -> mIrPoints, fp, filename))
-     return (0);
-  if (! WriteBin4 (BO_LITTLE, 1, (uint32) hData -> mEvCount, fp, filename))
-     return (0);
-  for (e = 0; e < hData -> mEvCount; e ++) {
-      if (! WriteBin4 (BO_LITTLE, 1, (uint32) hData -> mAzCount [e], fp, filename))
-         return (0);
-  }
-  step = hData -> mIrSize;
-  end = hData -> mIrCount * step;
-  n = hData -> mIrPoints;
-  srand (0x31DF840C);
-  for (j = 0; j < end; j += step) {
-      hpHist = 0;
-      for (i = 0; i < n; i ++) {
-          v = HpTpdfDither (32767.0 * hData -> mHrirs [j + i], & hpHist);
-          if (! WriteBin4 (BO_LITTLE, 2, (uint32) v, fp, filename))
-             return (0);
-      }
-  }
-  for (j = 0; j < hData -> mIrCount; j ++) {
-      v = (int) fmin (round (hData -> mIrRate * hData -> mHrtds [j]), MAX_HRTD);
-      if (! WriteBin4 (BO_LITTLE, 1, (uint32) v, fp, filename))
-         return (0);
-  }
-  fclose (fp);
-  return (1);
-}
-
-// Store the OpenAL Soft built-in table.
-static int StoreTable (const HrirDataT * hData, const char * filename) {
-  FILE * fp = NULL;
-  uint step, end, n, j, i;
-  int hpHist, v;
-  char text [128 + 1];
-
-  if ((fp = fopen (filename, "wb")) == NULL) {
-     fprintf (stderr, "Error:  Could not open table file '%s'.\n", filename);
-     return (0);
-  }
-  snprintf (text, 128, "/* Elevation metrics */\n"
-                       "static const ALubyte defaultAzCount[%u] = { ", hData -> mEvCount);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  for (i = 0; i < hData -> mEvCount; i ++) {
-      snprintf (text, 128, "%u, ", hData -> mAzCount [i]);
-      if (! WriteAscii (text, fp, filename))
-         return (0);
-  }
-  snprintf (text, 128, "};\n"
-                       "static const ALushort defaultEvOffset[%u] = { ", hData -> mEvCount);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  for (i = 0; i < hData -> mEvCount; i ++) {
-      snprintf (text, 128, "%u, ", hData -> mEvOffset [i]);
-      if (! WriteAscii (text, fp, filename))
-         return (0);
-  }
-  step = hData -> mIrSize;
-  end = hData -> mIrCount * step;
-  n = hData -> mIrPoints;
-  snprintf (text, 128, "};\n\n"
-                       "/* HRIR Coefficients */\n"
-                       "static const ALshort defaultCoeffs[%u] =\n{\n", hData -> mIrCount * n);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  srand (0x31DF840C);
-  for (j = 0; j < end; j += step) {
-      if (! WriteAscii ("   ", fp, filename))
-         return (0);
-      hpHist = 0;
-      for (i = 0; i < n; i ++) {
-          v = HpTpdfDither (32767.0 * hData -> mHrirs [j + i], & hpHist);
-          snprintf (text, 128, " %+d,", v);
-          if (! WriteAscii (text, fp, filename))
-             return (0);
-      }
-      if (! WriteAscii ("\n", fp, filename))
-         return (0);
-  }
-  snprintf (text, 128, "};\n\n"
-                       "/* HRIR Delays */\n"
-                       "static const ALubyte defaultDelays[%u] =\n{\n"
-                       "   ", hData -> mIrCount);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  for (j = 0; j < hData -> mIrCount; j ++) {
-      v = (int) fmin (round (hData -> mIrRate * hData -> mHrtds [j]), MAX_HRTD);
-      snprintf (text, 128, " %d,", v);
-      if (! WriteAscii (text, fp, filename))
-         return (0);
-  }
-  if (! WriteAscii ("\n};\n\n"
-                    "/* Default HRTF Definition */\n", fp, filename))
-     return (0);
-  snprintf (text, 128, "static const struct Hrtf DefaultHrtf = {\n"
-                       "    %u, %u, %u, defaultAzCount, defaultEvOffset,\n",
-                       hData -> mIrRate, hData -> mIrPoints, hData -> mEvCount);
-  if (! WriteAscii (text, fp, filename))
-     return (0);
-  if (! WriteAscii ("    defaultCoeffs, defaultDelays, NULL\n"
-                    "};\n", fp, filename))
-     return (0);
-  fclose (fp);
-  return (1);
-}
-
-// Process the data set definition to read and validate the data set metrics.
-static int ProcessMetrics (TokenReaderT * tr, const uint fftSize, const uint truncSize, HrirDataT * hData) {
-  char ident [MAX_IDENT_LEN + 1];
-  uint line, col;
-  int intVal;
-  uint points;
-  double fpVal;
-  int hasRate = 0, hasPoints = 0, hasAzimuths = 0;
-  int hasRadius = 0, hasDistance = 0;
-
-  while (! (hasRate && hasPoints && hasAzimuths && hasRadius && hasDistance)) {
-    TrIndication (tr, & line, & col);
-    if (! TrReadIdent (tr, MAX_IDENT_LEN, ident))
-       return (0);
-    if (strcasecmp (ident, "rate") == 0) {
-       if (hasRate) {
-          TrErrorAt (tr, line, col, "Redefinition of 'rate'.\n");
-          return (0);
-       }
-       if (! TrReadOperator (tr, "="))
-          return (0);
-       if (! TrReadInt (tr, MIN_RATE, MAX_RATE, & intVal))
-          return (0);
-       hData -> mIrRate = (uint) intVal;
-       hasRate = 1;
-    } else if (strcasecmp (ident, "points") == 0) {
-       if (hasPoints) {
-          TrErrorAt (tr, line, col, "Redefinition of 'points'.\n");
-          return (0);
-       }
-       if (! TrReadOperator (tr, "="))
-          return (0);
-       TrIndication (tr, & line, & col);
-       if (! TrReadInt (tr, MIN_POINTS, MAX_POINTS, & intVal))
-          return (0);
-       points = (uint) intVal;
-       if ((fftSize > 0) && (points > fftSize)) {
-          TrErrorAt (tr, line, col, "Value exceeds the overridden FFT size.\n");
-          return (0);
-       }
-       if (points < truncSize) {
-          TrErrorAt (tr, line, col, "Value is below the truncation size.\n");
-          return (0);
-       }
-       hData -> mIrPoints = points;
-       hData -> mFftSize = fftSize;
-       if (fftSize <= 0) {
-          points = 1;
-          while (points < (4 * hData -> mIrPoints))
-            points <<= 1;
-          hData -> mFftSize = points;
-          hData -> mIrSize = 1 + (points / 2);
-       } else {
-          hData -> mFftSize = fftSize;
-          hData -> mIrSize = 1 + (fftSize / 2);
-          if (points > hData -> mIrSize)
-             hData -> mIrSize = points;
-       }
-       hasPoints = 1;
-    } else if (strcasecmp (ident, "azimuths") == 0) {
-       if (hasAzimuths) {
-          TrErrorAt (tr, line, col, "Redefinition of 'azimuths'.\n");
-          return (0);
-       }
-       if (! TrReadOperator (tr, "="))
-          return (0);
-       hData -> mIrCount = 0;
-       hData -> mEvCount = 0;
-       hData -> mEvOffset [0] = 0;
-       for (;;) {
-           if (! TrReadInt (tr, MIN_AZ_COUNT, MAX_AZ_COUNT, & intVal))
-              return (0);
-           hData -> mAzCount [hData -> mEvCount] = (uint) intVal;
-           hData -> mIrCount += (uint) intVal;
-           hData -> mEvCount ++;
-           if (! TrIsOperator (tr, ","))
-              break;
-           if (hData -> mEvCount >= MAX_EV_COUNT) {
-              TrError (tr, "Exceeded the maximum of %d elevations.\n", MAX_EV_COUNT);
-              return (0);
-           }
-           hData -> mEvOffset [hData -> mEvCount] = hData -> mEvOffset [hData -> mEvCount - 1] + ((uint) intVal);
-           TrReadOperator (tr, ",");
-       }
-       if (hData -> mEvCount < MIN_EV_COUNT) {
-          TrErrorAt (tr, line, col, "Did not reach the minimum of %d azimuth counts.\n", MIN_EV_COUNT);
-          return (0);
-       }
-       hasAzimuths = 1;
-    } else if (strcasecmp (ident, "radius") == 0) {
-       if (hasRadius) {
-          TrErrorAt (tr, line, col, "Redefinition of 'radius'.\n");
-          return (0);
-       }
-       if (! TrReadOperator (tr, "="))
-          return (0);
-       if (! TrReadFloat (tr, MIN_RADIUS, MAX_RADIUS, & fpVal))
-          return (0);
-       hData -> mRadius = fpVal;
-       hasRadius = 1;
-    } else if (strcasecmp (ident, "distance") == 0) {
-       if (hasDistance) {
-          TrErrorAt (tr, line, col, "Redefinition of 'distance'.\n");
-          return (0);
-       }
-       if (! TrReadOperator (tr, "="))
-          return (0);
-       if (! TrReadFloat (tr, MIN_DISTANCE, MAX_DISTANCE, & fpVal))
-          return (0);
-       hData -> mDistance = fpVal;
-       hasDistance = 1;
-    } else {
-       TrErrorAt (tr, line, col, "Expected a metric name.\n");
-       return (0);
-    }
-    TrSkipWhitespace (tr);
-  }
-  return (1);
-}
-
-// Parse an index pair from the data set definition.
-static int ReadIndexPair (TokenReaderT * tr, const HrirDataT * hData, uint * ei, uint * ai) {
-  int intVal;
-
-  if (! TrReadInt (tr, 0, (int) hData -> mEvCount, & intVal))
-     return (0);
-  (* ei) = (uint) intVal;
-  if (! TrReadOperator (tr, ","))
-     return (0);
-  if (! TrReadInt (tr, 0, (int) hData -> mAzCount [(* ei)], & intVal))
-     return (0);
-  (* ai) = (uint) intVal;
-  return (1);
-}
-
-// Match the source format from a given identifier.
-static SourceFormatT MatchSourceFormat (const char * ident) {
-  if (strcasecmp (ident, "wave") == 0)
-     return (SF_WAVE);
-  else if (strcasecmp (ident, "bin_le") == 0)
-     return (SF_BIN_LE);
-  else if (strcasecmp (ident, "bin_be") == 0)
-     return (SF_BIN_BE);
-  else if (strcasecmp (ident, "ascii") == 0)
-     return (SF_ASCII);
-  return (SF_NONE);
-}
-
-// Match the source element type from a given identifier.
-static ElementTypeT MatchElementType (const char * ident) {
-  if (strcasecmp (ident, "int") == 0)
-     return (ET_INT);
-  else if (strcasecmp (ident, "fp") == 0)
-     return (ET_FP);
-  return (ET_NONE);
-}
-
-// Parse and validate a source reference from the data set definition.
-static int ReadSourceRef (TokenReaderT * tr, SourceRefT * src) {
-  uint line, col;
-  char ident [MAX_IDENT_LEN + 1];
-  int intVal;
-
-  TrIndication (tr, & line, & col);
-  if (! TrReadIdent (tr, MAX_IDENT_LEN, ident))
-     return (0);
-  src -> mFormat = MatchSourceFormat (ident);
-  if (src -> mFormat == SF_NONE) {
-     TrErrorAt (tr, line, col, "Expected a source format.\n");
-     return (0);
-  }
-  if (! TrReadOperator (tr, "("))
-     return (0);
-  if (src -> mFormat == SF_WAVE) {
-     if (! TrReadInt (tr, 0, MAX_WAVE_CHANNELS, & intVal))
-        return (0);
-     src -> mType = ET_NONE;
-     src -> mSize = 0;
-     src -> mBits = 0;
-     src -> mChannel = (uint) intVal;
-     src -> mSkip = 0;
-  } else {
-     TrIndication (tr, & line, & col);
-     if (! TrReadIdent (tr, MAX_IDENT_LEN, ident))
-        return (0);
-     src -> mType = MatchElementType (ident);
-     if (src -> mType == ET_NONE) {
-        TrErrorAt (tr, line, col, "Expected a source element type.\n");
-        return (0);
-     }
-     if ((src -> mFormat == SF_BIN_LE) || (src -> mFormat == SF_BIN_BE)) {
-        if (! TrReadOperator (tr, ","))
-           return (0);
-        if (src -> mType == ET_INT) {
-           if (! TrReadInt (tr, MIN_BIN_SIZE, MAX_BIN_SIZE, & intVal))
-              return (0);
-           src -> mSize = (uint) intVal;
-           if (TrIsOperator (tr, ",")) {
-              TrReadOperator (tr, ",");
-              TrIndication (tr, & line, & col);
-              if (! TrReadInt (tr, -2147483647 - 1, 2147483647, & intVal))
-                 return (0);
-              if ((abs (intVal) < MIN_BIN_BITS) || (((uint) abs (intVal)) > (8 * src -> mSize))) {
-                 TrErrorAt (tr, line, col, "Expected a value of (+/-) %d to %d.\n", MIN_BIN_BITS, 8 * src -> mSize);
-                 return (0);
-              }
-              src -> mBits = intVal;
-           } else {
-              src -> mBits = (int) (8 * src -> mSize);
-           }
-        } else {
-           TrIndication (tr, & line, & col);
-           if (! TrReadInt (tr, -2147483647 - 1, 2147483647, & intVal))
-              return (0);
-           if ((intVal != 4) && (intVal != 8)) {
-              TrErrorAt (tr, line, col, "Expected a value of 4 or 8.\n");
-              return (0);
-           }
-           src -> mSize = (uint) intVal;
-           src -> mBits = 0;
-        }
-     } else if ((src -> mFormat == SF_ASCII) && (src -> mType == ET_INT)) {
-        if (! TrReadOperator (tr, ","))
-           return (0);
-        if (! TrReadInt (tr, MIN_ASCII_BITS, MAX_ASCII_BITS, & intVal))
-           return (0);
-        src -> mSize = 0;
-        src -> mBits = intVal;
-     } else {
-        src -> mSize = 0;
-        src -> mBits = 0;
-     }
-     if (TrIsOperator (tr, ";")) {
-        TrReadOperator (tr, ";");
-        if (! TrReadInt (tr, 0, 0x7FFFFFFF, & intVal))
-           return (0);
-        src -> mSkip = (uint) intVal;
-     } else {
-        src -> mSkip = 0;
-     }
-  }
-  if (! TrReadOperator (tr, ")"))
-     return (0);
-  if (TrIsOperator (tr, "@")) {
-     TrReadOperator (tr, "@");
-     if (! TrReadInt (tr, 0, 0x7FFFFFFF, & intVal))
-        return (0);
-     src -> mOffset = (uint) intVal;
-  } else {
-     src -> mOffset = 0;
-  }
-  if (! TrReadOperator (tr, ":"))
-     return (0);
-  if (! TrReadString (tr, MAX_PATH_LEN, src -> mPath))
-     return (0);
-  return (1);
-}
-
-// Process the list of sources in the data set definition.
-static int ProcessSources (const HeadModelT model, TokenReaderT * tr, HrirDataT * hData) {
-  uint * setCount = NULL, * setFlag = NULL;
-  double * hrir = NULL;
-  uint line, col, ei, ai;
-  SourceRefT src;
-  double factor;
-
-  setCount = (uint *) calloc (hData -> mEvCount, sizeof (uint));
-  setFlag = (uint *) calloc (hData -> mIrCount, sizeof (uint));
-  hrir = CreateArray (hData -> mIrPoints);
-  while (TrIsOperator (tr, "[")) {
-    TrIndication (tr, & line, & col);
-    TrReadOperator (tr, "[");
-    if (ReadIndexPair (tr, hData, & ei, & ai)) {
-       if (TrReadOperator (tr, "]")) {
-          if (! setFlag [hData -> mEvOffset [ei] + ai]) {
-             if (TrReadOperator (tr, "=")) {
-                factor = 1.0;
-                for (;;) {
-                    if (ReadSourceRef (tr, & src)) {
-                       if (LoadSource (& src, hData -> mIrRate, hData -> mIrPoints, hrir)) {
-                          if (model == HM_DATASET)
-                             AverageHrirOnset (hrir, 1.0 / factor, ei, ai, hData);
-                          AverageHrirMagnitude (hrir, 1.0 / factor, ei, ai, hData);
-                          factor += 1.0;
-                          if (! TrIsOperator (tr, "+"))
-                             break;
-                          TrReadOperator (tr, "+");
-                          continue;
-                       }
-                    }
-                    DestroyArray (hrir);
-                    free (setFlag);
-                    free (setCount);
-                    return (0);
-                }
-                setFlag [hData -> mEvOffset [ei] + ai] = 1;
-                setCount [ei] ++;
-                continue;
-             }
-          } else {
-             TrErrorAt (tr, line, col, "Redefinition of source.\n");
-          }
-       }
-    }
-    DestroyArray (hrir);
-    free (setFlag);
-    free (setCount);
-    return (0);
-  }
-  ei = 0;
-  while ((ei < hData -> mEvCount) && (setCount [ei] < 1))
-    ei ++;
-  if (ei < hData -> mEvCount) {
-     hData -> mEvStart = ei;
-     while ((ei < hData -> mEvCount) && (setCount [ei] == hData -> mAzCount [ei]))
-       ei ++;
-     if (ei >= hData -> mEvCount) {
-        if (! TrLoad (tr)) {
-           DestroyArray (hrir);
-           free (setFlag);
-           free (setCount);
-           return (1);
-        } else {
-           TrError (tr, "Errant data at end of source list.\n");
-        }
-     } else {
-        TrError (tr, "Missing sources for elevation index %d.\n", ei);
-     }
-  } else {
-     TrError (tr, "Missing source references.\n");
-  }
-  DestroyArray (hrir);
-  free (setFlag);
-  free (setCount);
-  return (0);
-}
-
-/* Parse the data set definition and process the source data, storing the
- * resulting data set as desired.  If the input name is NULL it will read
- * from standard input.
- */
-static int ProcessDefinition (const char * inName, const uint outRate, const uint fftSize, const int equalize, const int surface, const double limit, const uint truncSize, const HeadModelT model, const double radius, const OutputFormatT outFormat, const char * outName) {
-  FILE * fp = NULL;
-  TokenReaderT tr;
-  HrirDataT hData;
-  double * dfa = NULL;
-  char rateStr [8 + 1], expName [MAX_PATH_LEN];
-
-  hData . mIrRate = 0;
-  hData . mIrPoints = 0;
-  hData . mFftSize = 0;
-  hData . mIrSize = 0;
-  hData . mIrCount = 0;
-  hData . mEvCount = 0;
-  hData . mRadius = 0;
-  hData . mDistance = 0;
-  fprintf (stdout, "Reading HRIR definition...\n");
-  if (inName != NULL) {
-     fp = fopen (inName, "r");
-     if (fp == NULL) {
-        fprintf (stderr, "Error:  Could not open definition file '%s'\n", inName);
-        return (0);
-     }
-     TrSetup (fp, inName, & tr);
-  } else {
-     fp = stdin;
-     TrSetup (fp, "<stdin>", & tr);
-  }
-  if (! ProcessMetrics (& tr, fftSize, truncSize, & hData)) {
-     if (inName != NULL)
-        fclose (fp);
-     return (0);
-  }
-  hData . mHrirs = CreateArray (hData . mIrCount * hData . mIrSize);
-  hData . mHrtds = CreateArray (hData . mIrCount);
-  if (! ProcessSources (model, & tr, & hData)) {
-     DestroyArray (hData . mHrtds);
-     DestroyArray (hData . mHrirs);
-     if (inName != NULL)
-        fclose (fp);
-     return (0);
-  }
-  if (inName != NULL)
-     fclose (fp);
-  if (equalize) {
-     dfa = CreateArray (1 + (hData . mFftSize / 2));
-     fprintf (stdout, "Calculating diffuse-field average...\n");
-     CalculateDiffuseFieldAverage (& hData, surface, limit, dfa);
-     fprintf (stdout, "Performing diffuse-field equalization...\n");
-     DiffuseFieldEqualize (dfa, & hData);
-     DestroyArray (dfa);
-  }
-  fprintf (stdout, "Performing minimum phase reconstruction...\n");
-  ReconstructHrirs (& hData);
-  if ((outRate != 0) && (outRate != hData . mIrRate)) {
-     fprintf (stdout, "Resampling HRIRs...\n");
-     ResampleHrirs (outRate, & hData);
-  }
-  fprintf (stdout, "Truncating minimum-phase HRIRs...\n");
-  hData . mIrPoints = truncSize;
-  fprintf (stdout, "Synthesizing missing elevations...\n");
-  if (model == HM_DATASET)
-     SynthesizeOnsets (& hData);
-  SynthesizeHrirs (& hData);
-  fprintf (stdout, "Normalizing final HRIRs...\n");
-  NormalizeHrirs (& hData);
-  fprintf (stdout, "Calculating impulse delays...\n");
-  CalculateHrtds (model, (radius > DEFAULT_CUSTOM_RADIUS) ? radius : hData . mRadius, & hData);
-  snprintf (rateStr, 8, "%u", hData . mIrRate);
-  StrSubst (outName, "%r", rateStr, MAX_PATH_LEN, expName);
-  switch (outFormat) {
-    case OF_MHR :
-      fprintf (stdout, "Creating MHR data set file...\n");
-      if (! StoreMhr (& hData, expName))
-         return (0);
-    break;
-    case OF_TABLE :
-      fprintf (stderr, "Creating OpenAL Soft table file...\n");
-      if (! StoreTable (& hData, expName))
-         return (0);
-    break;
-    default :
-    break;
-  }
-  DestroyArray (hData . mHrtds);
-  DestroyArray (hData . mHrirs);
-  return (1);
-}
-
-// Standard command line dispatch.
-int main (const int argc, const char * argv []) {
-  const char * inName = NULL, * outName = NULL;
-  OutputFormatT outFormat;
-  int argi;
-  uint outRate, fftSize;
-  int equalize, surface;
-  double limit;
-  uint truncSize;
-  HeadModelT model;
-  double radius;
-  char * end = NULL;
-
-  if (argc < 2) {
-     fprintf (stderr, "Error:  No command specified.  See '%s -h' for help.\n", argv [0]);
-     return (-1);
-  }
-  if ((strcmp (argv [1], "--help") == 0) || (strcmp (argv [1], "-h") == 0)) {
-     fprintf (stdout, "HRTF Processing and Composition Utility\n\n");
-     fprintf (stdout, "Usage:  %s <command> [<option>...]\n\n", argv [0]);
-     fprintf (stdout, "Commands:\n");
-     fprintf (stdout, " -m, --make-mhr  Makes an OpenAL Soft compatible HRTF data set.\n");
-     fprintf (stdout, "                 Defaults output to: ./oalsoft_hrtf_%%r.mhr\n");
-     fprintf (stdout, " -t, --make-tab  Makes the built-in table used when compiling OpenAL Soft.\n");
-     fprintf (stdout, "                 Defaults output to: ./hrtf_tables.inc\n");
-     fprintf (stdout, " -h, --help      Displays this help information.\n\n");
-     fprintf (stdout, "Options:\n");
-     fprintf (stdout, " -r=<rate>       Change the data set sample rate to the specified value and\n");
-     fprintf (stdout, "                 resample the HRIRs accordingly.\n");
-     fprintf (stdout, " -f=<points>     Override the FFT window size (defaults to the first power-\n");
-     fprintf (stdout, "                 of-two that fits four times the number of HRIR points).\n");
-     fprintf (stdout, " -e={on|off}     Toggle diffuse-field equalization (default: %s).\n", (DEFAULT_EQUALIZE ? "on" : "off"));
-     fprintf (stdout, " -s={on|off}     Toggle surface-weighted diffuse-field average (default: %s).\n", (DEFAULT_SURFACE ? "on" : "off"));
-     fprintf (stdout, " -l={<dB>|none}  Specify a limit to the magnitude range of the diffuse-field\n");
-     fprintf (stdout, "                 average (default: %.2f).\n", DEFAULT_LIMIT);
-     fprintf (stdout, " -w=<points>     Specify the size of the truncation window that's applied\n");
-     fprintf (stdout, "                 after minimum-phase reconstruction (default: %u).\n", DEFAULT_TRUNCSIZE);
-     fprintf (stdout, " -d={dataset|    Specify the model used for calculating the head-delay timing\n");
-     fprintf (stdout, "     sphere}     values (default: %s).\n", ((DEFAULT_HEAD_MODEL == HM_DATASET) ? "dataset" : "sphere"));
-     fprintf (stdout, " -c=<size>       Use a customized head radius measured ear-to-ear in meters.\n");
-     fprintf (stdout, " -i=<filename>   Specify an HRIR definition file to use (defaults to stdin).\n");
-     fprintf (stdout, " -o=<filename>   Specify an output file.  Overrides command-selected default.\n");
-     fprintf (stdout, "                 Use of '%%r' will be substituted with the data set sample rate.\n");
-     return (0);
-  }
-  if ((strcmp (argv [1], "--make-mhr") == 0) || (strcmp (argv [1], "-m") == 0)) {
-     if (argc > 3)
-        outName = argv [3];
-     else
-        outName = "./oalsoft_hrtf_%r.mhr";
-     outFormat = OF_MHR;
-  } else if ((strcmp (argv [1], "--make-tab") == 0) || (strcmp (argv [1], "-t") == 0)) {
-     if (argc > 3)
-        outName = argv [3];
-     else
-        outName = "./hrtf_tables.inc";
-     outFormat = OF_TABLE;
-  } else {
-     fprintf (stderr, "Error:  Invalid command '%s'.\n", argv [1]);
-     return (-1);
-  }
-  argi = 2;
-  outRate = 0;
-  fftSize = 0;
-  equalize = DEFAULT_EQUALIZE;
-  surface = DEFAULT_SURFACE;
-  limit = DEFAULT_LIMIT;
-  truncSize = DEFAULT_TRUNCSIZE;
-  model = DEFAULT_HEAD_MODEL;
-  radius = DEFAULT_CUSTOM_RADIUS;
-  while (argi < argc) {
-    if (strncmp (argv [argi], "-r=", 3) == 0) {
-       outRate = strtoul (& argv [argi] [3], & end, 10);
-       if ((end [0] != '\0') || (outRate < MIN_RATE) || (outRate > MAX_RATE)) {
-          fprintf (stderr, "Error:  Expected a value from %u to %u for '-r'.\n", MIN_RATE, MAX_RATE);
-          return (-1);
-       }
-    } else if (strncmp (argv [argi], "-f=", 3) == 0) {
-       fftSize = strtoul (& argv [argi] [3], & end, 10);
-       if ((end [0] != '\0') || (fftSize & (fftSize - 1)) || (fftSize < MIN_FFTSIZE) || (fftSize > MAX_FFTSIZE)) {
-          fprintf (stderr, "Error:  Expected a power-of-two value from %u to %u for '-f'.\n", MIN_FFTSIZE, MAX_FFTSIZE);
-          return (-1);
-       }
-    } else if (strncmp (argv [argi], "-e=", 3) == 0) {
-       if (strcmp (& argv [argi] [3], "on") == 0) {
-          equalize = 1;
-       } else if (strcmp (& argv [argi] [3], "off") == 0) {
-          equalize = 0;
-       } else {
-          fprintf (stderr, "Error:  Expected 'on' or 'off' for '-e'.\n");
-          return (-1);
-       }
-    } else if (strncmp (argv [argi], "-s=", 3) == 0) {
-       if (strcmp (& argv [argi] [3], "on") == 0) {
-          surface = 1;
-       } else if (strcmp (& argv [argi] [3], "off") == 0) {
-          surface = 0;
-       } else {
-          fprintf (stderr, "Error:  Expected 'on' or 'off' for '-s'.\n");
-          return (-1);
-       }
-    } else if (strncmp (argv [argi], "-l=", 3) == 0) {
-       if (strcmp (& argv [argi] [3], "none") == 0) {
-          limit = 0.0;
-       } else {
-          limit = strtod (& argv [argi] [3], & end);
-          if ((end [0] != '\0') || (limit < MIN_LIMIT) || (limit > MAX_LIMIT)) {
-             fprintf (stderr, "Error:  Expected 'none' or a value from %.2f to %.2f for '-l'.\n", MIN_LIMIT, MAX_LIMIT);
-             return (-1);
-          }
-       }
-    } else if (strncmp (argv [argi], "-w=", 3) == 0) {
-       truncSize = strtoul (& argv [argi] [3], & end, 10);
-       if ((end [0] != '\0') || (truncSize < MIN_TRUNCSIZE) || (truncSize > MAX_TRUNCSIZE) || (truncSize % MOD_TRUNCSIZE)) {
-          fprintf (stderr, "Error:  Expected a value from %u to %u in multiples of %u for '-w'.\n", MIN_TRUNCSIZE, MAX_TRUNCSIZE, MOD_TRUNCSIZE);
-          return (-1);
-       }
-    } else if (strncmp (argv [argi], "-d=", 3) == 0) {
-       if (strcmp (& argv [argi] [3], "dataset") == 0) {
-          model = HM_DATASET;
-       } else if (strcmp (& argv [argi] [3], "sphere") == 0) {
-          model = HM_SPHERE;
-       } else {
-          fprintf (stderr, "Error:  Expected 'dataset' or 'sphere' for '-d'.\n");
-          return (-1);
-       }
-    } else if (strncmp (argv [argi], "-c=", 3) == 0) {
-       radius = strtod (& argv [argi] [3], & end);
-       if ((end [0] != '\0') || (radius < MIN_CUSTOM_RADIUS) || (radius > MAX_CUSTOM_RADIUS)) {
-          fprintf (stderr, "Error:  Expected a value from %.2f to %.2f for '-c'.\n", MIN_CUSTOM_RADIUS, MAX_CUSTOM_RADIUS);
-          return (-1);
-       }
-    } else if (strncmp (argv [argi], "-i=", 3) == 0) {
-       inName = & argv [argi] [3];
-    } else if (strncmp (argv [argi], "-o=", 3) == 0) {
-       outName = & argv [argi] [3];
-    } else {
-       fprintf (stderr, "Error:  Invalid option '%s'.\n", argv [argi]);
-       return (-1);
-    }
-    argi ++;
-  }
-  if (! ProcessDefinition (inName, outRate, fftSize, equalize, surface, limit, truncSize, model, radius, outFormat, outName))
-     return (-1);
-  fprintf (stdout, "Operation completed.\n");
-  return (0);
-}
-
-
-
-

+ 7 - 0
love/src/jni/openal-soft-1.18.2/.gitignore

@@ -0,0 +1,7 @@
+build
+winbuild
+win64build
+include/SLES
+include/sndio.h
+include/sys
+openal-soft.kdev4

+ 70 - 0
love/src/jni/openal-soft-1.18.2/.travis.yml

@@ -0,0 +1,70 @@
+language: c
+matrix:
+  include:
+    - os: linux
+      dist: trusty
+    - os: linux
+      dist: trusty
+      env:
+        - BUILD_ANDROID=true
+    - os: osx
+sudo: required
+cache:
+  directories:
+    - $HOME/android-ndk-r14
+install:
+  - >
+    if [[ "${TRAVIS_OS_NAME}" == "linux" && -z "${BUILD_ANDROID}" ]]; then
+      # Install pulseaudio, portaudio, ALSA, JACK dependencies for
+      # corresponding backends.
+      # Install Qt5 dependency for alsoft-config.
+      sudo apt-get install -qq \
+        libpulse-dev \
+        portaudio19-dev \
+        libasound2-dev \
+        libjack-dev \
+        qtbase5-dev
+    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
+    fi
+script:
+  - >
+    if [[ "${TRAVIS_OS_NAME}" == "linux" && -z "${BUILD_ANDROID}" ]]; then
+      cmake \
+        -DALSOFT_REQUIRE_ALSA=ON \
+        -DALSOFT_REQUIRE_OSS=ON \
+        -DALSOFT_REQUIRE_PORTAUDIO=ON \
+        -DALSOFT_REQUIRE_PULSEAUDIO=ON \
+        -DALSOFT_REQUIRE_JACK=ON \
+        -DALSOFT_EMBED_HRTF_DATA=YES \
+        .
+    fi
+  - >
+    if [[ "${TRAVIS_OS_NAME}" == "linux" && "${BUILD_ANDROID}" == "true" ]]; then
+      cmake \
+        -DCMAKE_TOOLCHAIN_FILE=~/android-ndk-r14/build/cmake/android.toolchain.cmake \
+        -DALSOFT_REQUIRE_OPENSL=ON \
+        -DALSOFT_EMBED_HRTF_DATA=YES \
+        .
+    fi
+  - >
+    if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
+      cmake \
+        -DALSOFT_REQUIRE_COREAUDIO=ON \
+        -DALSOFT_EMBED_HRTF_DATA=YES \
+        .
+    fi
+  - make -j2

ファイルの差分が大きいため隠しています
+ 365 - 277
love/src/jni/openal-soft-1.18.2/Alc/ALc.c


+ 1830 - 0
love/src/jni/openal-soft-1.18.2/Alc/ALu.c

@@ -0,0 +1,1830 @@
+/**
+ * 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 <math.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "alMain.h"
+#include "alSource.h"
+#include "alBuffer.h"
+#include "alListener.h"
+#include "alAuxEffectSlot.h"
+#include "alu.h"
+#include "bs2b.h"
+#include "hrtf.h"
+#include "uhjfilter.h"
+#include "bformatdec.h"
+#include "static_assert.h"
+
+#include "mixer_defs.h"
+
+#include "backends/base.h"
+
+
+struct ChanMap {
+    enum Channel channel;
+    ALfloat angle;
+    ALfloat elevation;
+};
+
+/* Cone scalar */
+ALfloat ConeScale = 1.0f;
+
+/* Localized Z scalar for mono sources */
+ALfloat ZScale = 1.0f;
+
+extern inline ALfloat minf(ALfloat a, ALfloat b);
+extern inline ALfloat maxf(ALfloat a, ALfloat b);
+extern inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max);
+
+extern inline ALdouble mind(ALdouble a, ALdouble b);
+extern inline ALdouble maxd(ALdouble a, ALdouble b);
+extern inline ALdouble clampd(ALdouble val, ALdouble min, ALdouble max);
+
+extern inline ALuint minu(ALuint a, ALuint b);
+extern inline ALuint maxu(ALuint a, ALuint b);
+extern inline ALuint clampu(ALuint val, ALuint min, ALuint max);
+
+extern inline ALint mini(ALint a, ALint b);
+extern inline ALint maxi(ALint a, ALint b);
+extern inline ALint clampi(ALint val, ALint min, ALint max);
+
+extern inline ALint64 mini64(ALint64 a, ALint64 b);
+extern inline ALint64 maxi64(ALint64 a, ALint64 b);
+extern inline ALint64 clampi64(ALint64 val, ALint64 min, ALint64 max);
+
+extern inline ALuint64 minu64(ALuint64 a, ALuint64 b);
+extern inline ALuint64 maxu64(ALuint64 a, ALuint64 b);
+extern inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max);
+
+extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu);
+extern inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALsizei frac);
+
+extern inline void aluVectorSet(aluVector *restrict vector, ALfloat x, ALfloat y, ALfloat z, ALfloat w);
+
+extern inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row,
+                                    ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3);
+extern inline void aluMatrixfSet(aluMatrixf *matrix,
+                                 ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03,
+                                 ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13,
+                                 ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23,
+                                 ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33);
+
+const aluMatrixf IdentityMatrixf = {{
+    { 1.0f, 0.0f, 0.0f, 0.0f },
+    { 0.0f, 1.0f, 0.0f, 0.0f },
+    { 0.0f, 0.0f, 1.0f, 0.0f },
+    { 0.0f, 0.0f, 0.0f, 1.0f },
+}};
+
+
+void DeinitVoice(ALvoice *voice)
+{
+    struct ALvoiceProps *props;
+    size_t count = 0;
+
+    props = ATOMIC_EXCHANGE_PTR_SEQ(&voice->Update, NULL);
+    if(props) al_free(props);
+
+    props = ATOMIC_EXCHANGE_PTR(&voice->FreeList, NULL, almemory_order_relaxed);
+    while(props)
+    {
+        struct ALvoiceProps *next;
+        next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
+        al_free(props);
+        props = next;
+        ++count;
+    }
+    /* This is excessively spammy if it traces every voice destruction, so just
+     * warn if it was unexpectedly large.
+     */
+    if(count > 3)
+        WARN("Freed "SZFMT" voice property objects\n", count);
+}
+
+
+static inline HrtfDirectMixerFunc SelectHrtfMixer(void)
+{
+#ifdef HAVE_NEON
+    if((CPUCapFlags&CPU_CAP_NEON))
+        return MixDirectHrtf_Neon;
+#endif
+#ifdef HAVE_SSE
+    if((CPUCapFlags&CPU_CAP_SSE))
+        return MixDirectHrtf_SSE;
+#endif
+
+    return MixDirectHrtf_C;
+}
+
+
+/* Prior to VS2013, MSVC lacks the round() family of functions. */
+#if defined(_MSC_VER) && _MSC_VER < 1800
+static float roundf(float val)
+{
+    if(val < 0.0f)
+        return ceilf(val-0.5f);
+    return floorf(val+0.5f);
+}
+#endif
+
+/* This RNG method was created based on the math found in opusdec. It's quick,
+ * and starting with a seed value of 22222, is suitable for generating
+ * whitenoise.
+ */
+static inline ALuint dither_rng(ALuint *seed)
+{
+    *seed = (*seed * 96314165) + 907633515;
+    return *seed;
+}
+
+
+static inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
+{
+    outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
+    outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2];
+    outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0];
+}
+
+static inline ALfloat aluDotproduct(const aluVector *vec1, const aluVector *vec2)
+{
+    return vec1->v[0]*vec2->v[0] + vec1->v[1]*vec2->v[1] + vec1->v[2]*vec2->v[2];
+}
+
+static ALfloat aluNormalize(ALfloat *vec)
+{
+    ALfloat length = sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]);
+    if(length > 0.0f)
+    {
+        ALfloat inv_length = 1.0f/length;
+        vec[0] *= inv_length;
+        vec[1] *= inv_length;
+        vec[2] *= inv_length;
+    }
+    return length;
+}
+
+static void aluMatrixfFloat3(ALfloat *vec, ALfloat w, const aluMatrixf *mtx)
+{
+    ALfloat v[4] = { vec[0], vec[1], vec[2], w };
+
+    vec[0] = v[0]*mtx->m[0][0] + v[1]*mtx->m[1][0] + v[2]*mtx->m[2][0] + v[3]*mtx->m[3][0];
+    vec[1] = v[0]*mtx->m[0][1] + v[1]*mtx->m[1][1] + v[2]*mtx->m[2][1] + v[3]*mtx->m[3][1];
+    vec[2] = v[0]*mtx->m[0][2] + v[1]*mtx->m[1][2] + v[2]*mtx->m[2][2] + v[3]*mtx->m[3][2];
+}
+
+static aluVector aluMatrixfVector(const aluMatrixf *mtx, const aluVector *vec)
+{
+    aluVector v;
+    v.v[0] = vec->v[0]*mtx->m[0][0] + vec->v[1]*mtx->m[1][0] + vec->v[2]*mtx->m[2][0] + vec->v[3]*mtx->m[3][0];
+    v.v[1] = vec->v[0]*mtx->m[0][1] + vec->v[1]*mtx->m[1][1] + vec->v[2]*mtx->m[2][1] + vec->v[3]*mtx->m[3][1];
+    v.v[2] = vec->v[0]*mtx->m[0][2] + vec->v[1]*mtx->m[1][2] + vec->v[2]*mtx->m[2][2] + vec->v[3]*mtx->m[3][2];
+    v.v[3] = vec->v[0]*mtx->m[0][3] + vec->v[1]*mtx->m[1][3] + vec->v[2]*mtx->m[2][3] + vec->v[3]*mtx->m[3][3];
+    return v;
+}
+
+
+/* Prepares the interpolator for a given rate (determined by increment).  A
+ * result of AL_FALSE indicates that the filter output will completely cut
+ * the input signal.
+ *
+ * With a bit of work, and a trade of memory for CPU cost, this could be
+ * modified for use with an interpolated increment for buttery-smooth pitch
+ * changes.
+ */
+ALboolean BsincPrepare(const ALuint increment, BsincState *state)
+{
+    static const ALfloat scaleBase = 1.510578918e-01f, scaleRange = 1.177936623e+00f;
+    static const ALuint m[BSINC_SCALE_COUNT] = { 24, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 12 };
+    static const ALuint to[4][BSINC_SCALE_COUNT] =
+    {
+        { 0, 24, 408, 792, 1176, 1560, 1944, 2328, 2648, 2968, 3288, 3544, 3800, 4056, 4248, 4440 },
+        { 4632, 5016, 5400, 5784, 6168, 6552, 6936, 7320, 7640, 7960, 8280, 8536, 8792, 9048, 9240, 0 },
+        { 0, 9432, 9816, 10200, 10584, 10968, 11352, 11736, 12056, 12376, 12696, 12952, 13208, 13464, 13656, 13848 },
+        { 14040, 14424, 14808, 15192, 15576, 15960, 16344, 16728, 17048, 17368, 17688, 17944, 18200, 18456, 18648, 0 }
+    };
+    static const ALuint tm[2][BSINC_SCALE_COUNT] =
+    {
+        { 0, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 12 },
+        { 24, 24, 24, 24, 24, 24, 24, 20, 20, 20, 16, 16, 16, 12, 12, 0 }
+    };
+    ALfloat sf;
+    ALsizei si, pi;
+    ALboolean uncut = AL_TRUE;
+
+    if(increment > FRACTIONONE)
+    {
+        sf = (ALfloat)FRACTIONONE / increment;
+        if(sf < scaleBase)
+        {
+            /* Signal has been completely cut.  The return result can be used
+             * to skip the filter (and output zeros) as an optimization.
+             */
+            sf = 0.0f;
+            si = 0;
+            uncut = AL_FALSE;
+        }
+        else
+        {
+            sf = (BSINC_SCALE_COUNT - 1) * (sf - scaleBase) * scaleRange;
+            si = fastf2i(sf);
+            /* The interpolation factor is fit to this diagonally-symmetric
+             * curve to reduce the transition ripple caused by interpolating
+             * different scales of the sinc function.
+             */
+            sf = 1.0f - cosf(asinf(sf - si));
+        }
+    }
+    else
+    {
+        sf = 0.0f;
+        si = BSINC_SCALE_COUNT - 1;
+    }
+
+    state->sf = sf;
+    state->m = m[si];
+    state->l = -(ALint)((m[si] / 2) - 1);
+    /* The CPU cost of this table re-mapping could be traded for the memory
+     * cost of a complete table map (1024 elements large).
+     */
+    for(pi = 0;pi < BSINC_PHASE_COUNT;pi++)
+    {
+        state->coeffs[pi].filter  = &bsincTab[to[0][si] + tm[0][si]*pi];
+        state->coeffs[pi].scDelta = &bsincTab[to[1][si] + tm[1][si]*pi];
+        state->coeffs[pi].phDelta = &bsincTab[to[2][si] + tm[0][si]*pi];
+        state->coeffs[pi].spDelta = &bsincTab[to[3][si] + tm[1][si]*pi];
+    }
+    return uncut;
+}
+
+
+static ALboolean CalcListenerParams(ALCcontext *Context)
+{
+    ALlistener *Listener = Context->Listener;
+    ALfloat N[3], V[3], U[3], P[3];
+    struct ALlistenerProps *props;
+    aluVector vel;
+
+    props = ATOMIC_EXCHANGE_PTR(&Listener->Update, NULL, almemory_order_acq_rel);
+    if(!props) return AL_FALSE;
+
+    /* AT then UP */
+    N[0] = props->Forward[0];
+    N[1] = props->Forward[1];
+    N[2] = props->Forward[2];
+    aluNormalize(N);
+    V[0] = props->Up[0];
+    V[1] = props->Up[1];
+    V[2] = props->Up[2];
+    aluNormalize(V);
+    /* Build and normalize right-vector */
+    aluCrossproduct(N, V, U);
+    aluNormalize(U);
+
+    aluMatrixfSet(&Listener->Params.Matrix,
+        U[0], V[0], -N[0], 0.0,
+        U[1], V[1], -N[1], 0.0,
+        U[2], V[2], -N[2], 0.0,
+         0.0,  0.0,   0.0, 1.0
+    );
+
+    P[0] = props->Position[0];
+    P[1] = props->Position[1];
+    P[2] = props->Position[2];
+    aluMatrixfFloat3(P, 1.0, &Listener->Params.Matrix);
+    aluMatrixfSetRow(&Listener->Params.Matrix, 3, -P[0], -P[1], -P[2], 1.0f);
+
+    aluVectorSet(&vel, props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f);
+    Listener->Params.Velocity = aluMatrixfVector(&Listener->Params.Matrix, &vel);
+
+    Listener->Params.Gain = props->Gain * Context->GainBoost;
+    Listener->Params.MetersPerUnit = props->MetersPerUnit;
+
+    Listener->Params.DopplerFactor = props->DopplerFactor;
+    Listener->Params.SpeedOfSound = props->SpeedOfSound * props->DopplerVelocity;
+
+    Listener->Params.SourceDistanceModel = props->SourceDistanceModel;
+    Listener->Params.DistanceModel = props->DistanceModel;
+
+    ATOMIC_REPLACE_HEAD(struct ALlistenerProps*, &Listener->FreeList, props);
+    return AL_TRUE;
+}
+
+static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device)
+{
+    struct ALeffectslotProps *props;
+    ALeffectState *state;
+
+    props = ATOMIC_EXCHANGE_PTR(&slot->Update, NULL, almemory_order_acq_rel);
+    if(!props) return AL_FALSE;
+
+    slot->Params.Gain = props->Gain;
+    slot->Params.AuxSendAuto = props->AuxSendAuto;
+    slot->Params.EffectType = props->Type;
+    if(IsReverbEffect(slot->Params.EffectType))
+    {
+        slot->Params.RoomRolloff = props->Props.Reverb.RoomRolloffFactor;
+        slot->Params.DecayTime = props->Props.Reverb.DecayTime;
+        slot->Params.DecayHFRatio = props->Props.Reverb.DecayHFRatio;
+        slot->Params.DecayHFLimit = props->Props.Reverb.DecayHFLimit;
+        slot->Params.AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF;
+    }
+    else
+    {
+        slot->Params.RoomRolloff = 0.0f;
+        slot->Params.DecayTime = 0.0f;
+        slot->Params.DecayHFRatio = 0.0f;
+        slot->Params.DecayHFLimit = AL_FALSE;
+        slot->Params.AirAbsorptionGainHF = 1.0f;
+    }
+
+    /* Swap effect states. No need to play with the ref counts since they keep
+     * the same number of refs.
+     */
+    state = props->State;
+    props->State = slot->Params.EffectState;
+    slot->Params.EffectState = state;
+
+    V(state,update)(device, slot, &props->Props);
+
+    ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &slot->FreeList, props);
+    return AL_TRUE;
+}
+
+
+static const struct ChanMap MonoMap[1] = {
+    { FrontCenter, 0.0f, 0.0f }
+}, RearMap[2] = {
+    { BackLeft,  DEG2RAD(-150.0f), DEG2RAD(0.0f) },
+    { BackRight, DEG2RAD( 150.0f), DEG2RAD(0.0f) }
+}, QuadMap[4] = {
+    { FrontLeft,  DEG2RAD( -45.0f), DEG2RAD(0.0f) },
+    { FrontRight, DEG2RAD(  45.0f), DEG2RAD(0.0f) },
+    { BackLeft,   DEG2RAD(-135.0f), DEG2RAD(0.0f) },
+    { BackRight,  DEG2RAD( 135.0f), DEG2RAD(0.0f) }
+}, X51Map[6] = {
+    { FrontLeft,   DEG2RAD( -30.0f), DEG2RAD(0.0f) },
+    { FrontRight,  DEG2RAD(  30.0f), DEG2RAD(0.0f) },
+    { FrontCenter, DEG2RAD(   0.0f), DEG2RAD(0.0f) },
+    { LFE, 0.0f, 0.0f },
+    { SideLeft,    DEG2RAD(-110.0f), DEG2RAD(0.0f) },
+    { SideRight,   DEG2RAD( 110.0f), DEG2RAD(0.0f) }
+}, X61Map[7] = {
+    { FrontLeft,    DEG2RAD(-30.0f), DEG2RAD(0.0f) },
+    { FrontRight,   DEG2RAD( 30.0f), DEG2RAD(0.0f) },
+    { FrontCenter,  DEG2RAD(  0.0f), DEG2RAD(0.0f) },
+    { LFE, 0.0f, 0.0f },
+    { BackCenter,   DEG2RAD(180.0f), DEG2RAD(0.0f) },
+    { SideLeft,     DEG2RAD(-90.0f), DEG2RAD(0.0f) },
+    { SideRight,    DEG2RAD( 90.0f), DEG2RAD(0.0f) }
+}, X71Map[8] = {
+    { FrontLeft,   DEG2RAD( -30.0f), DEG2RAD(0.0f) },
+    { FrontRight,  DEG2RAD(  30.0f), DEG2RAD(0.0f) },
+    { FrontCenter, DEG2RAD(   0.0f), DEG2RAD(0.0f) },
+    { LFE, 0.0f, 0.0f },
+    { BackLeft,    DEG2RAD(-150.0f), DEG2RAD(0.0f) },
+    { BackRight,   DEG2RAD( 150.0f), DEG2RAD(0.0f) },
+    { SideLeft,    DEG2RAD( -90.0f), DEG2RAD(0.0f) },
+    { SideRight,   DEG2RAD(  90.0f), DEG2RAD(0.0f) }
+};
+
+static void CalcPanningAndFilters(ALvoice *voice, const ALfloat Distance, const ALfloat *Dir,
+                                  const ALfloat Spread, const ALfloat DryGain,
+                                  const ALfloat DryGainHF, const ALfloat DryGainLF,
+                                  const ALfloat *WetGain, const ALfloat *WetGainLF,
+                                  const ALfloat *WetGainHF, ALeffectslot **SendSlots,
+                                  const ALbuffer *Buffer, const struct ALvoiceProps *props,
+                                  const ALlistener *Listener, const ALCdevice *Device)
+{
+    struct ChanMap StereoMap[2] = {
+        { FrontLeft,  DEG2RAD(-30.0f), DEG2RAD(0.0f) },
+        { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) }
+    };
+    bool DirectChannels = props->DirectChannels;
+    const ALsizei NumSends = Device->NumAuxSends;
+    const ALuint Frequency = Device->Frequency;
+    const struct ChanMap *chans = NULL;
+    ALsizei num_channels = 0;
+    bool isbformat = false;
+    ALfloat downmix_gain = 1.0f;
+    ALsizei c, i, j;
+
+    switch(Buffer->FmtChannels)
+    {
+    case FmtMono:
+        chans = MonoMap;
+        num_channels = 1;
+        /* Mono buffers are never played direct. */
+        DirectChannels = false;
+        break;
+
+    case FmtStereo:
+        /* Convert counter-clockwise to clockwise. */
+        StereoMap[0].angle = -props->StereoPan[0];
+        StereoMap[1].angle = -props->StereoPan[1];
+
+        chans = StereoMap;
+        num_channels = 2;
+        downmix_gain = 1.0f / 2.0f;
+        break;
+
+    case FmtRear:
+        chans = RearMap;
+        num_channels = 2;
+        downmix_gain = 1.0f / 2.0f;
+        break;
+
+    case FmtQuad:
+        chans = QuadMap;
+        num_channels = 4;
+        downmix_gain = 1.0f / 4.0f;
+        break;
+
+    case FmtX51:
+        chans = X51Map;
+        num_channels = 6;
+        /* NOTE: Excludes LFE. */
+        downmix_gain = 1.0f / 5.0f;
+        break;
+
+    case FmtX61:
+        chans = X61Map;
+        num_channels = 7;
+        /* NOTE: Excludes LFE. */
+        downmix_gain = 1.0f / 6.0f;
+        break;
+
+    case FmtX71:
+        chans = X71Map;
+        num_channels = 8;
+        /* NOTE: Excludes LFE. */
+        downmix_gain = 1.0f / 7.0f;
+        break;
+
+    case FmtBFormat2D:
+        num_channels = 3;
+        isbformat = true;
+        DirectChannels = false;
+        break;
+
+    case FmtBFormat3D:
+        num_channels = 4;
+        isbformat = true;
+        DirectChannels = false;
+        break;
+    }
+
+    voice->Flags &= ~(VOICE_HAS_HRTF | VOICE_HAS_NFC);
+    if(isbformat)
+    {
+        /* Special handling for B-Format sources. */
+
+        if(Distance > FLT_EPSILON)
+        {
+            /* Panning a B-Format sound toward some direction is easy. Just pan
+             * the first (W) channel as a normal mono sound and silence the
+             * others.
+             */
+            ALfloat coeffs[MAX_AMBI_COEFFS];
+
+            if(Device->AvgSpeakerDist > 0.0f && Listener->Params.MetersPerUnit > 0.0f)
+            {
+                ALfloat mdist = Distance * Listener->Params.MetersPerUnit;
+                ALfloat w0 = SPEEDOFSOUNDMETRESPERSEC /
+                             (mdist * (ALfloat)Device->Frequency);
+                ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
+                             (Device->AvgSpeakerDist * (ALfloat)Device->Frequency);
+                /* Clamp w0 for really close distances, to prevent excessive
+                 * bass.
+                 */
+                w0 = minf(w0, w1*4.0f);
+
+                /* Only need to adjust the first channel of a B-Format source. */
+                NfcFilterAdjust1(&voice->Direct.Params[0].NFCtrlFilter[0], w0);
+                NfcFilterAdjust2(&voice->Direct.Params[0].NFCtrlFilter[1], w0);
+                NfcFilterAdjust3(&voice->Direct.Params[0].NFCtrlFilter[2], w0);
+
+                for(i = 0;i < MAX_AMBI_ORDER+1;i++)
+                    voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
+                voice->Flags |= VOICE_HAS_NFC;
+            }
+
+            if(Device->Render_Mode == StereoPair)
+            {
+                ALfloat ev = asinf(Dir[1]);
+                ALfloat az = atan2f(Dir[0], -Dir[2]);
+                CalcAnglePairwiseCoeffs(az, ev, Spread, coeffs);
+            }
+            else
+                CalcDirectionCoeffs(Dir, Spread, coeffs);
+
+            /* NOTE: W needs to be scaled by sqrt(2) due to FuMa normalization. */
+            ComputePanningGains(Device->Dry, coeffs, DryGain*1.414213562f,
+                                voice->Direct.Params[0].Gains.Target);
+            for(c = 1;c < num_channels;c++)
+            {
+                for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
+                    voice->Direct.Params[c].Gains.Target[j] = 0.0f;
+            }
+
+            for(i = 0;i < NumSends;i++)
+            {
+                const ALeffectslot *Slot = SendSlots[i];
+                if(Slot)
+                    ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
+                        coeffs, WetGain[i]*1.414213562f, voice->Send[i].Params[0].Gains.Target
+                    );
+                else
+                    for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                        voice->Send[i].Params[0].Gains.Target[j] = 0.0f;
+                for(c = 1;c < num_channels;c++)
+                {
+                    for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                        voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                }
+            }
+        }
+        else
+        {
+            /* Local B-Format sources have their XYZ channels rotated according
+             * to the orientation.
+             */
+            ALfloat N[3], V[3], U[3];
+            aluMatrixf matrix;
+            ALfloat scale;
+
+            if(Device->AvgSpeakerDist > 0.0f)
+            {
+                /* NOTE: The NFCtrlFilters were created with a w0 of 0, which
+                 * is what we want for FOA input. The first channel may have
+                 * been previously re-adjusted if panned, so reset it.
+                 */
+                NfcFilterAdjust1(&voice->Direct.Params[0].NFCtrlFilter[0], 0.0f);
+                NfcFilterAdjust2(&voice->Direct.Params[0].NFCtrlFilter[1], 0.0f);
+                NfcFilterAdjust3(&voice->Direct.Params[0].NFCtrlFilter[2], 0.0f);
+
+                voice->Direct.ChannelsPerOrder[0] = 1;
+                voice->Direct.ChannelsPerOrder[1] = mini(voice->Direct.Channels-1, 3);
+                for(i = 2;i < MAX_AMBI_ORDER+1;i++)
+                    voice->Direct.ChannelsPerOrder[2] = 0;
+                voice->Flags |= VOICE_HAS_NFC;
+            }
+
+            /* AT then UP */
+            N[0] = props->Orientation[0][0];
+            N[1] = props->Orientation[0][1];
+            N[2] = props->Orientation[0][2];
+            aluNormalize(N);
+            V[0] = props->Orientation[1][0];
+            V[1] = props->Orientation[1][1];
+            V[2] = props->Orientation[1][2];
+            aluNormalize(V);
+            if(!props->HeadRelative)
+            {
+                const aluMatrixf *lmatrix = &Listener->Params.Matrix;
+                aluMatrixfFloat3(N, 0.0f, lmatrix);
+                aluMatrixfFloat3(V, 0.0f, lmatrix);
+            }
+            /* Build and normalize right-vector */
+            aluCrossproduct(N, V, U);
+            aluNormalize(U);
+
+            /* Build a rotate + conversion matrix (FuMa -> ACN+N3D). */
+            scale = 1.732050808f;
+            aluMatrixfSet(&matrix,
+                1.414213562f,        0.0f,        0.0f,        0.0f,
+                        0.0f, -N[0]*scale,  N[1]*scale, -N[2]*scale,
+                        0.0f,  U[0]*scale, -U[1]*scale,  U[2]*scale,
+                        0.0f, -V[0]*scale,  V[1]*scale, -V[2]*scale
+            );
+
+            voice->Direct.Buffer = Device->FOAOut.Buffer;
+            voice->Direct.Channels = Device->FOAOut.NumChannels;
+            for(c = 0;c < num_channels;c++)
+                ComputeFirstOrderGains(Device->FOAOut, matrix.m[c], DryGain,
+                                       voice->Direct.Params[c].Gains.Target);
+            for(i = 0;i < NumSends;i++)
+            {
+                const ALeffectslot *Slot = SendSlots[i];
+                if(Slot)
+                {
+                    for(c = 0;c < num_channels;c++)
+                        ComputeFirstOrderGainsBF(Slot->ChanMap, Slot->NumChannels,
+                            matrix.m[c], WetGain[i], voice->Send[i].Params[c].Gains.Target
+                        );
+                }
+                else
+                {
+                    for(c = 0;c < num_channels;c++)
+                        for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                            voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                }
+            }
+        }
+    }
+    else if(DirectChannels)
+    {
+        /* Direct source channels always play local. Skip the virtual channels
+         * and write inputs to the matching real outputs.
+         */
+        voice->Direct.Buffer = Device->RealOut.Buffer;
+        voice->Direct.Channels = Device->RealOut.NumChannels;
+
+        for(c = 0;c < num_channels;c++)
+        {
+            int idx;
+            for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
+                voice->Direct.Params[c].Gains.Target[j] = 0.0f;
+            if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1)
+                voice->Direct.Params[c].Gains.Target[idx] = DryGain;
+        }
+
+        /* Auxiliary sends still use normal channel panning since they mix to
+         * B-Format, which can't channel-match.
+         */
+        for(c = 0;c < num_channels;c++)
+        {
+            ALfloat coeffs[MAX_AMBI_COEFFS];
+            CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs);
+
+            for(i = 0;i < NumSends;i++)
+            {
+                const ALeffectslot *Slot = SendSlots[i];
+                if(Slot)
+                    ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
+                        coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
+                    );
+                else
+                    for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                        voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+            }
+        }
+    }
+    else if(Device->Render_Mode == HrtfRender)
+    {
+        /* Full HRTF rendering. Skip the virtual channels and render to the
+         * real outputs.
+         */
+        voice->Direct.Buffer = Device->RealOut.Buffer;
+        voice->Direct.Channels = Device->RealOut.NumChannels;
+
+        if(Distance > FLT_EPSILON)
+        {
+            ALfloat coeffs[MAX_AMBI_COEFFS];
+            ALfloat ev, az;
+
+            ev = asinf(Dir[1]);
+            az = atan2f(Dir[0], -Dir[2]);
+
+            /* Get the HRIR coefficients and delays just once, for the given
+             * source direction.
+             */
+            GetHrtfCoeffs(Device->HrtfHandle, ev, az, Spread,
+                          voice->Direct.Params[0].Hrtf.Target.Coeffs,
+                          voice->Direct.Params[0].Hrtf.Target.Delay);
+            voice->Direct.Params[0].Hrtf.Target.Gain = DryGain * downmix_gain;
+
+            /* Remaining channels use the same results as the first. */
+            for(c = 1;c < num_channels;c++)
+            {
+                /* Skip LFE */
+                if(chans[c].channel == LFE)
+                    memset(&voice->Direct.Params[c].Hrtf.Target, 0,
+                           sizeof(voice->Direct.Params[c].Hrtf.Target));
+                else
+                    voice->Direct.Params[c].Hrtf.Target = voice->Direct.Params[0].Hrtf.Target;
+            }
+
+            /* Calculate the directional coefficients once, which apply to all
+             * input channels of the source sends.
+             */
+            CalcDirectionCoeffs(Dir, Spread, coeffs);
+
+            for(i = 0;i < NumSends;i++)
+            {
+                const ALeffectslot *Slot = SendSlots[i];
+                if(Slot)
+                    for(c = 0;c < num_channels;c++)
+                    {
+                        /* Skip LFE */
+                        if(chans[c].channel == LFE)
+                            for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                                voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                        else
+                            ComputePanningGainsBF(Slot->ChanMap,
+                                Slot->NumChannels, coeffs, WetGain[i] * downmix_gain,
+                                voice->Send[i].Params[c].Gains.Target
+                            );
+                    }
+                else
+                    for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                        voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+            }
+        }
+        else
+        {
+            /* Local sources on HRTF play with each channel panned to its
+             * relative location around the listener, providing "virtual
+             * speaker" responses.
+             */
+            for(c = 0;c < num_channels;c++)
+            {
+                ALfloat coeffs[MAX_AMBI_COEFFS];
+
+                if(chans[c].channel == LFE)
+                {
+                    /* Skip LFE */
+                    memset(&voice->Direct.Params[c].Hrtf.Target, 0,
+                           sizeof(voice->Direct.Params[c].Hrtf.Target));
+                    for(i = 0;i < NumSends;i++)
+                    {
+                        for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                            voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                    }
+                    continue;
+                }
+
+                /* Get the HRIR coefficients and delays for this channel
+                 * position.
+                 */
+                GetHrtfCoeffs(Device->HrtfHandle,
+                    chans[c].elevation, chans[c].angle, Spread,
+                    voice->Direct.Params[c].Hrtf.Target.Coeffs,
+                    voice->Direct.Params[c].Hrtf.Target.Delay
+                );
+                voice->Direct.Params[c].Hrtf.Target.Gain = DryGain;
+
+                /* Normal panning for auxiliary sends. */
+                CalcAngleCoeffs(chans[c].angle, chans[c].elevation, Spread, coeffs);
+
+                for(i = 0;i < NumSends;i++)
+                {
+                    const ALeffectslot *Slot = SendSlots[i];
+                    if(Slot)
+                        ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
+                            coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
+                        );
+                    else
+                        for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                            voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                }
+            }
+        }
+
+        voice->Flags |= VOICE_HAS_HRTF;
+    }
+    else
+    {
+        /* Non-HRTF rendering. Use normal panning to the output. */
+
+        if(Distance > FLT_EPSILON)
+        {
+            ALfloat coeffs[MAX_AMBI_COEFFS];
+            ALfloat w0 = 0.0f;
+
+            /* Calculate NFC filter coefficient if needed. */
+            if(Device->AvgSpeakerDist > 0.0f && Listener->Params.MetersPerUnit > 0.0f)
+            {
+                ALfloat mdist = Distance * Listener->Params.MetersPerUnit;
+                ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
+                             (Device->AvgSpeakerDist * (ALfloat)Device->Frequency);
+                w0 = SPEEDOFSOUNDMETRESPERSEC /
+                     (mdist * (ALfloat)Device->Frequency);
+                /* Clamp w0 for really close distances, to prevent excessive
+                 * bass.
+                 */
+                w0 = minf(w0, w1*4.0f);
+
+                for(i = 0;i < MAX_AMBI_ORDER+1;i++)
+                    voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
+                voice->Flags |= VOICE_HAS_NFC;
+            }
+
+            /* Calculate the directional coefficients once, which apply to all
+             * input channels.
+             */
+            if(Device->Render_Mode == StereoPair)
+            {
+                ALfloat ev = asinf(Dir[1]);
+                ALfloat az = atan2f(Dir[0], -Dir[2]);
+                CalcAnglePairwiseCoeffs(az, ev, Spread, coeffs);
+            }
+            else
+                CalcDirectionCoeffs(Dir, Spread, coeffs);
+
+            for(c = 0;c < num_channels;c++)
+            {
+                /* Adjust NFC filters if needed. */
+                if((voice->Flags&VOICE_HAS_NFC))
+                {
+                    NfcFilterAdjust1(&voice->Direct.Params[c].NFCtrlFilter[0], w0);
+                    NfcFilterAdjust2(&voice->Direct.Params[c].NFCtrlFilter[1], w0);
+                    NfcFilterAdjust3(&voice->Direct.Params[c].NFCtrlFilter[2], w0);
+                }
+
+                /* Special-case LFE */
+                if(chans[c].channel == LFE)
+                {
+                    for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
+                        voice->Direct.Params[c].Gains.Target[j] = 0.0f;
+                    if(Device->Dry.Buffer == Device->RealOut.Buffer)
+                    {
+                        int idx = GetChannelIdxByName(Device->RealOut, chans[c].channel);
+                        if(idx != -1) voice->Direct.Params[c].Gains.Target[idx] = DryGain;
+                    }
+                    continue;
+                }
+
+                ComputePanningGains(Device->Dry,
+                    coeffs, DryGain * downmix_gain, voice->Direct.Params[c].Gains.Target
+                );
+            }
+
+            for(i = 0;i < NumSends;i++)
+            {
+                const ALeffectslot *Slot = SendSlots[i];
+                if(Slot)
+                    for(c = 0;c < num_channels;c++)
+                    {
+                        /* Skip LFE */
+                        if(chans[c].channel == LFE)
+                            for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                                voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                        else
+                            ComputePanningGainsBF(Slot->ChanMap,
+                                Slot->NumChannels, coeffs, WetGain[i] * downmix_gain,
+                                voice->Send[i].Params[c].Gains.Target
+                            );
+                    }
+                else
+                    for(c = 0;c < num_channels;c++)
+                    {
+                        for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                            voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                    }
+            }
+        }
+        else
+        {
+            ALfloat w0 = 0.0f;
+
+            if(Device->AvgSpeakerDist > 0.0f)
+            {
+                /* If the source distance is 0, set w0 to w1 to act as a pass-
+                 * through. We still want to pass the signal through the
+                 * filters so they keep an appropriate history, in case the
+                 * source moves away from the listener.
+                 */
+                w0 = SPEEDOFSOUNDMETRESPERSEC /
+                     (Device->AvgSpeakerDist * (ALfloat)Device->Frequency);
+
+                for(i = 0;i < MAX_AMBI_ORDER+1;i++)
+                    voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
+                voice->Flags |= VOICE_HAS_NFC;
+            }
+
+            for(c = 0;c < num_channels;c++)
+            {
+                ALfloat coeffs[MAX_AMBI_COEFFS];
+
+                if((voice->Flags&VOICE_HAS_NFC))
+                {
+                    NfcFilterAdjust1(&voice->Direct.Params[c].NFCtrlFilter[0], w0);
+                    NfcFilterAdjust2(&voice->Direct.Params[c].NFCtrlFilter[1], w0);
+                    NfcFilterAdjust3(&voice->Direct.Params[c].NFCtrlFilter[2], w0);
+                }
+
+                /* Special-case LFE */
+                if(chans[c].channel == LFE)
+                {
+                    for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
+                        voice->Direct.Params[c].Gains.Target[j] = 0.0f;
+                    if(Device->Dry.Buffer == Device->RealOut.Buffer)
+                    {
+                        int idx = GetChannelIdxByName(Device->RealOut, chans[c].channel);
+                        if(idx != -1) voice->Direct.Params[c].Gains.Target[idx] = DryGain;
+                    }
+
+                    for(i = 0;i < NumSends;i++)
+                    {
+                        for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                            voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                    }
+                    continue;
+                }
+
+                if(Device->Render_Mode == StereoPair)
+                    CalcAnglePairwiseCoeffs(chans[c].angle, chans[c].elevation, Spread, coeffs);
+                else
+                    CalcAngleCoeffs(chans[c].angle, chans[c].elevation, Spread, coeffs);
+                ComputePanningGains(Device->Dry,
+                    coeffs, DryGain, voice->Direct.Params[c].Gains.Target
+                );
+
+                for(i = 0;i < NumSends;i++)
+                {
+                    const ALeffectslot *Slot = SendSlots[i];
+                    if(Slot)
+                        ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels,
+                            coeffs, WetGain[i], voice->Send[i].Params[c].Gains.Target
+                        );
+                    else
+                        for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+                            voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
+                }
+            }
+        }
+    }
+
+    {
+        ALfloat hfScale = props->Direct.HFReference / Frequency;
+        ALfloat lfScale = props->Direct.LFReference / Frequency;
+        ALfloat gainHF = maxf(DryGainHF, 0.001f); /* Limit -60dB */
+        ALfloat gainLF = maxf(DryGainLF, 0.001f);
+
+        voice->Direct.FilterType = AF_None;
+        if(gainHF != 1.0f) voice->Direct.FilterType |= AF_LowPass;
+        if(gainLF != 1.0f) voice->Direct.FilterType |= AF_HighPass;
+        ALfilterState_setParams(
+            &voice->Direct.Params[0].LowPass, ALfilterType_HighShelf,
+            gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
+        );
+        ALfilterState_setParams(
+            &voice->Direct.Params[0].HighPass, ALfilterType_LowShelf,
+            gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
+        );
+        for(c = 1;c < num_channels;c++)
+        {
+            ALfilterState_copyParams(&voice->Direct.Params[c].LowPass,
+                                     &voice->Direct.Params[0].LowPass);
+            ALfilterState_copyParams(&voice->Direct.Params[c].HighPass,
+                                     &voice->Direct.Params[0].HighPass);
+        }
+    }
+    for(i = 0;i < NumSends;i++)
+    {
+        ALfloat hfScale = props->Send[i].HFReference / Frequency;
+        ALfloat lfScale = props->Send[i].LFReference / Frequency;
+        ALfloat gainHF = maxf(WetGainHF[i], 0.001f);
+        ALfloat gainLF = maxf(WetGainLF[i], 0.001f);
+
+        voice->Send[i].FilterType = AF_None;
+        if(gainHF != 1.0f) voice->Send[i].FilterType |= AF_LowPass;
+        if(gainLF != 1.0f) voice->Send[i].FilterType |= AF_HighPass;
+        ALfilterState_setParams(
+            &voice->Send[i].Params[0].LowPass, ALfilterType_HighShelf,
+            gainHF, hfScale, calc_rcpQ_from_slope(gainHF, 1.0f)
+        );
+        ALfilterState_setParams(
+            &voice->Send[i].Params[0].HighPass, ALfilterType_LowShelf,
+            gainLF, lfScale, calc_rcpQ_from_slope(gainLF, 1.0f)
+        );
+        for(c = 1;c < num_channels;c++)
+        {
+            ALfilterState_copyParams(&voice->Send[i].Params[c].LowPass,
+                                     &voice->Send[i].Params[0].LowPass);
+            ALfilterState_copyParams(&voice->Send[i].Params[c].HighPass,
+                                     &voice->Send[i].Params[0].HighPass);
+        }
+    }
+}
+
+static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
+{
+    static const ALfloat dir[3] = { 0.0f, 0.0f, -1.0f };
+    const ALCdevice *Device = ALContext->Device;
+    const ALlistener *Listener = ALContext->Listener;
+    ALfloat DryGain, DryGainHF, DryGainLF;
+    ALfloat WetGain[MAX_SENDS];
+    ALfloat WetGainHF[MAX_SENDS];
+    ALfloat WetGainLF[MAX_SENDS];
+    ALeffectslot *SendSlots[MAX_SENDS];
+    ALfloat Pitch;
+    ALsizei i;
+
+    voice->Direct.Buffer = Device->Dry.Buffer;
+    voice->Direct.Channels = Device->Dry.NumChannels;
+    for(i = 0;i < Device->NumAuxSends;i++)
+    {
+        SendSlots[i] = props->Send[i].Slot;
+        if(!SendSlots[i] && i == 0)
+            SendSlots[i] = ALContext->DefaultSlot;
+        if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
+        {
+            SendSlots[i] = NULL;
+            voice->Send[i].Buffer = NULL;
+            voice->Send[i].Channels = 0;
+        }
+        else
+        {
+            voice->Send[i].Buffer = SendSlots[i]->WetBuffer;
+            voice->Send[i].Channels = SendSlots[i]->NumChannels;
+        }
+    }
+
+    /* Calculate the stepping value */
+    Pitch = (ALfloat)ALBuffer->Frequency/(ALfloat)Device->Frequency * props->Pitch;
+    if(Pitch > (ALfloat)MAX_PITCH)
+        voice->Step = MAX_PITCH<<FRACTIONBITS;
+    else
+        voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
+    BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
+    voice->Resampler = SelectResampler(props->Resampler);
+
+    /* Calculate gains */
+    DryGain  = clampf(props->Gain, props->MinGain, props->MaxGain);
+    DryGain *= props->Direct.Gain * Listener->Params.Gain;
+    DryGain  = minf(DryGain, GAIN_MIX_MAX);
+    DryGainHF = props->Direct.GainHF;
+    DryGainLF = props->Direct.GainLF;
+    for(i = 0;i < Device->NumAuxSends;i++)
+    {
+        WetGain[i]  = clampf(props->Gain, props->MinGain, props->MaxGain);
+        WetGain[i] *= props->Send[i].Gain * Listener->Params.Gain;
+        WetGain[i]  = minf(WetGain[i], GAIN_MIX_MAX);
+        WetGainHF[i] = props->Send[i].GainHF;
+        WetGainLF[i] = props->Send[i].GainLF;
+    }
+
+    CalcPanningAndFilters(voice, 0.0f, dir, 0.0f, DryGain, DryGainHF, DryGainLF, WetGain,
+                          WetGainLF, WetGainHF, SendSlots, ALBuffer, props, Listener, Device);
+}
+
+static void CalcAttnSourceParams(ALvoice *voice, const struct ALvoiceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext)
+{
+    const ALCdevice *Device = ALContext->Device;
+    const ALlistener *Listener = ALContext->Listener;
+    const ALsizei NumSends = Device->NumAuxSends;
+    aluVector Position, Velocity, Direction, SourceToListener;
+    ALfloat Distance, ClampedDist, DopplerFactor;
+    ALeffectslot *SendSlots[MAX_SENDS];
+    ALfloat RoomRolloff[MAX_SENDS];
+    ALfloat DecayDistance[MAX_SENDS];
+    ALfloat DecayHFDistance[MAX_SENDS];
+    ALfloat DryGain, DryGainHF, DryGainLF;
+    ALfloat WetGain[MAX_SENDS];
+    ALfloat WetGainHF[MAX_SENDS];
+    ALfloat WetGainLF[MAX_SENDS];
+    bool directional;
+    ALfloat dir[3];
+    ALfloat spread;
+    ALfloat Pitch;
+    ALint i;
+
+    /* Set mixing buffers and get send parameters. */
+    voice->Direct.Buffer = Device->Dry.Buffer;
+    voice->Direct.Channels = Device->Dry.NumChannels;
+    for(i = 0;i < NumSends;i++)
+    {
+        SendSlots[i] = props->Send[i].Slot;
+        if(!SendSlots[i] && i == 0)
+            SendSlots[i] = ALContext->DefaultSlot;
+        if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL)
+        {
+            SendSlots[i] = NULL;
+            RoomRolloff[i] = 0.0f;
+            DecayDistance[i] = 0.0f;
+            DecayHFDistance[i] = 0.0f;
+        }
+        else if(SendSlots[i]->Params.AuxSendAuto)
+        {
+            RoomRolloff[i] = SendSlots[i]->Params.RoomRolloff + props->RoomRolloffFactor;
+            DecayDistance[i] = SendSlots[i]->Params.DecayTime * SPEEDOFSOUNDMETRESPERSEC;
+            DecayHFDistance[i] = DecayDistance[i] * SendSlots[i]->Params.DecayHFRatio;
+            if(SendSlots[i]->Params.DecayHFLimit)
+            {
+                ALfloat airAbsorption = SendSlots[i]->Params.AirAbsorptionGainHF;
+                if(airAbsorption < 1.0f)
+                {
+                    ALfloat limitRatio = log10f(REVERB_DECAY_GAIN) / log10f(airAbsorption);
+                    DecayHFDistance[i] = minf(limitRatio, DecayHFDistance[i]);
+                }
+            }
+        }
+        else
+        {
+            /* If the slot's auxiliary send auto is off, the data sent to the
+             * effect slot is the same as the dry path, sans filter effects */
+            RoomRolloff[i] = props->RolloffFactor;
+            DecayDistance[i] = 0.0f;
+            DecayHFDistance[i] = 0.0f;
+        }
+
+        if(!SendSlots[i])
+        {
+            voice->Send[i].Buffer = NULL;
+            voice->Send[i].Channels = 0;
+        }
+        else
+        {
+            voice->Send[i].Buffer = SendSlots[i]->WetBuffer;
+            voice->Send[i].Channels = SendSlots[i]->NumChannels;
+        }
+    }
+
+    /* Transform source to listener space (convert to head relative) */
+    aluVectorSet(&Position, props->Position[0], props->Position[1], props->Position[2], 1.0f);
+    aluVectorSet(&Direction, props->Direction[0], props->Direction[1], props->Direction[2], 0.0f);
+    aluVectorSet(&Velocity, props->Velocity[0], props->Velocity[1], props->Velocity[2], 0.0f);
+    if(props->HeadRelative == AL_FALSE)
+    {
+        const aluMatrixf *Matrix = &Listener->Params.Matrix;
+        /* Transform source vectors */
+        Position = aluMatrixfVector(Matrix, &Position);
+        Velocity = aluMatrixfVector(Matrix, &Velocity);
+        Direction = aluMatrixfVector(Matrix, &Direction);
+    }
+    else
+    {
+        const aluVector *lvelocity = &Listener->Params.Velocity;
+        /* Offset the source velocity to be relative of the listener velocity */
+        Velocity.v[0] += lvelocity->v[0];
+        Velocity.v[1] += lvelocity->v[1];
+        Velocity.v[2] += lvelocity->v[2];
+    }
+
+    directional = aluNormalize(Direction.v) > FLT_EPSILON;
+    SourceToListener.v[0] = -Position.v[0];
+    SourceToListener.v[1] = -Position.v[1];
+    SourceToListener.v[2] = -Position.v[2];
+    SourceToListener.v[3] = 0.0f;
+    Distance = aluNormalize(SourceToListener.v);
+
+    /* Initial source gain */
+    DryGain = props->Gain;
+    DryGainHF = 1.0f;
+    DryGainLF = 1.0f;
+    for(i = 0;i < NumSends;i++)
+    {
+        WetGain[i] = props->Gain;
+        WetGainHF[i] = 1.0f;
+        WetGainLF[i] = 1.0f;
+    }
+
+    /* Calculate distance attenuation */
+    ClampedDist = Distance;
+
+    switch(Listener->Params.SourceDistanceModel ?
+           props->DistanceModel : Listener->Params.DistanceModel)
+    {
+        case InverseDistanceClamped:
+            ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
+            if(props->MaxDistance < props->RefDistance)
+                break;
+            /*fall-through*/
+        case InverseDistance:
+            if(!(props->RefDistance > 0.0f))
+                ClampedDist = props->RefDistance;
+            else
+            {
+                ALfloat dist = lerp(props->RefDistance, ClampedDist, props->RolloffFactor);
+                if(dist > 0.0f) DryGain *= props->RefDistance / dist;
+                for(i = 0;i < NumSends;i++)
+                {
+                    dist = lerp(props->RefDistance, ClampedDist, RoomRolloff[i]);
+                    if(dist > 0.0f) WetGain[i] *= props->RefDistance / dist;
+                }
+            }
+            break;
+
+        case LinearDistanceClamped:
+            ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
+            if(props->MaxDistance < props->RefDistance)
+                break;
+            /*fall-through*/
+        case LinearDistance:
+            if(!(props->MaxDistance != props->RefDistance))
+                ClampedDist = props->RefDistance;
+            else
+            {
+                ALfloat attn = props->RolloffFactor * (ClampedDist-props->RefDistance) /
+                               (props->MaxDistance-props->RefDistance);
+                DryGain *= maxf(1.0f - attn, 0.0f);
+                for(i = 0;i < NumSends;i++)
+                {
+                    attn = RoomRolloff[i] * (ClampedDist-props->RefDistance) /
+                           (props->MaxDistance-props->RefDistance);
+                    WetGain[i] *= maxf(1.0f - attn, 0.0f);
+                }
+            }
+            break;
+
+        case ExponentDistanceClamped:
+            ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance);
+            if(props->MaxDistance < props->RefDistance)
+                break;
+            /*fall-through*/
+        case ExponentDistance:
+            if(!(ClampedDist > 0.0f && props->RefDistance > 0.0f))
+                ClampedDist = props->RefDistance;
+            else
+            {
+                DryGain *= powf(ClampedDist/props->RefDistance, -props->RolloffFactor);
+                for(i = 0;i < NumSends;i++)
+                    WetGain[i] *= powf(ClampedDist/props->RefDistance, -RoomRolloff[i]);
+            }
+            break;
+
+        case DisableDistance:
+            ClampedDist = props->RefDistance;
+            break;
+    }
+
+    /* Distance-based air absorption */
+    if(ClampedDist > props->RefDistance && props->RolloffFactor > 0.0f)
+    {
+        ALfloat meters_base = (ClampedDist-props->RefDistance) * props->RolloffFactor *
+                              Listener->Params.MetersPerUnit;
+        if(props->AirAbsorptionFactor > 0.0f)
+        {
+            ALfloat hfattn = powf(AIRABSORBGAINHF, meters_base * props->AirAbsorptionFactor);
+            DryGainHF *= hfattn;
+            for(i = 0;i < NumSends;i++)
+                WetGainHF[i] *= hfattn;
+        }
+
+        if(props->WetGainAuto)
+        {
+            /* Apply a decay-time transformation to the wet path, based on the
+             * source distance in meters. The initial decay of the reverb
+             * effect is calculated and applied to the wet path.
+             */
+            for(i = 0;i < NumSends;i++)
+            {
+                ALfloat gain;
+
+                if(!(DecayDistance[i] > 0.0f))
+                    continue;
+
+                gain = powf(REVERB_DECAY_GAIN, meters_base/DecayDistance[i]);
+                WetGain[i] *= gain;
+                /* Yes, the wet path's air absorption is applied with
+                 * WetGainAuto on, rather than WetGainHFAuto.
+                 */
+                if(gain > 0.0f)
+                {
+                    ALfloat gainhf = powf(REVERB_DECAY_GAIN, meters_base/DecayHFDistance[i]);
+                    WetGainHF[i] *= minf(gainhf / gain, 1.0f);
+                }
+            }
+        }
+    }
+
+    /* Calculate directional soundcones */
+    if(directional && props->InnerAngle < 360.0f)
+    {
+        ALfloat ConeVolume;
+        ALfloat ConeHF;
+        ALfloat Angle;
+
+        Angle = acosf(aluDotproduct(&Direction, &SourceToListener));
+        Angle = RAD2DEG(Angle * ConeScale * 2.0f);
+        if(!(Angle > props->InnerAngle))
+        {
+            ConeVolume = 1.0f;
+            ConeHF = 1.0f;
+        }
+        else if(Angle < props->OuterAngle)
+        {
+            ALfloat scale = (            Angle-props->InnerAngle) /
+                            (props->OuterAngle-props->InnerAngle);
+            ConeVolume = lerp(1.0f, props->OuterGain, scale);
+            ConeHF = lerp(1.0f, props->OuterGainHF, scale);
+        }
+        else
+        {
+            ConeVolume = props->OuterGain;
+            ConeHF = props->OuterGainHF;
+        }
+
+        DryGain *= ConeVolume;
+        if(props->DryGainHFAuto)
+            DryGainHF *= ConeHF;
+        if(props->WetGainAuto)
+        {
+            for(i = 0;i < NumSends;i++)
+                WetGain[i] *= ConeVolume;
+        }
+        if(props->WetGainHFAuto)
+        {
+            for(i = 0;i < NumSends;i++)
+                WetGainHF[i] *= ConeHF;
+        }
+    }
+
+    /* Apply gain and frequency filters */
+    DryGain  = clampf(DryGain, props->MinGain, props->MaxGain);
+    DryGain  = minf(DryGain*props->Direct.Gain*Listener->Params.Gain, GAIN_MIX_MAX);
+    DryGainHF *= props->Direct.GainHF;
+    DryGainLF *= props->Direct.GainLF;
+    for(i = 0;i < NumSends;i++)
+    {
+        WetGain[i]  = clampf(WetGain[i], props->MinGain, props->MaxGain);
+        WetGain[i]  = minf(WetGain[i]*props->Send[i].Gain*Listener->Params.Gain, GAIN_MIX_MAX);
+        WetGainHF[i] *= props->Send[i].GainHF;
+        WetGainLF[i] *= props->Send[i].GainLF;
+    }
+
+
+    /* Initial source pitch */
+    Pitch = props->Pitch;
+
+    /* Calculate velocity-based doppler effect */
+    DopplerFactor = props->DopplerFactor * Listener->Params.DopplerFactor;
+    if(DopplerFactor > 0.0f)
+    {
+        const aluVector *lvelocity = &Listener->Params.Velocity;
+        const ALfloat SpeedOfSound = Listener->Params.SpeedOfSound;
+        ALfloat vss, vls;
+
+        vss = aluDotproduct(&Velocity, &SourceToListener) * DopplerFactor;
+        vls = aluDotproduct(lvelocity, &SourceToListener) * DopplerFactor;
+
+        if(!(vls < SpeedOfSound))
+        {
+            /* Listener moving away from the source at the speed of sound.
+             * Sound waves can't catch it.
+             */
+            Pitch = 0.0f;
+        }
+        else if(!(vss < SpeedOfSound))
+        {
+            /* Source moving toward the listener at the speed of sound. Sound
+             * waves bunch up to extreme frequencies.
+             */
+            Pitch = HUGE_VALF;
+        }
+        else
+        {
+            /* Source and listener movement is nominal. Calculate the proper
+             * doppler shift.
+             */
+            Pitch *= (SpeedOfSound-vls) / (SpeedOfSound-vss);
+        }
+    }
+
+    /* Adjust pitch based on the buffer and output frequencies, and calculate
+     * fixed-point stepping value.
+     */
+    Pitch *= (ALfloat)ALBuffer->Frequency/(ALfloat)Device->Frequency;
+    if(Pitch > (ALfloat)MAX_PITCH)
+        voice->Step = MAX_PITCH<<FRACTIONBITS;
+    else
+        voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
+    BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
+    voice->Resampler = SelectResampler(props->Resampler);
+
+    if(Distance > FLT_EPSILON)
+    {
+        dir[0] = -SourceToListener.v[0];
+        /* Clamp Y, in case rounding errors caused it to end up outside of
+         * -1...+1.
+         */
+        dir[1] = clampf(-SourceToListener.v[1], -1.0f, 1.0f);
+        dir[2] = -SourceToListener.v[2] * ZScale;
+    }
+    else
+    {
+        dir[0] =  0.0f;
+        dir[1] =  0.0f;
+        dir[2] = -1.0f;
+    }
+    if(props->Radius > Distance)
+        spread = F_TAU - Distance/props->Radius*F_PI;
+    else if(Distance > FLT_EPSILON)
+        spread = asinf(props->Radius / Distance) * 2.0f;
+    else
+        spread = 0.0f;
+
+    CalcPanningAndFilters(voice, Distance, dir, spread, DryGain, DryGainHF, DryGainLF, WetGain,
+                          WetGainLF, WetGainHF, SendSlots, ALBuffer, props, Listener, Device);
+}
+
+static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean force)
+{
+    ALbufferlistitem *BufferListItem;
+    struct ALvoiceProps *props;
+
+    props = ATOMIC_EXCHANGE_PTR(&voice->Update, NULL, almemory_order_acq_rel);
+    if(!props && !force) return;
+
+    if(props)
+    {
+        memcpy(voice->Props, props,
+            FAM_SIZE(struct ALvoiceProps, Send, context->Device->NumAuxSends)
+        );
+
+        ATOMIC_REPLACE_HEAD(struct ALvoiceProps*, &voice->FreeList, props);
+    }
+    props = voice->Props;
+
+    BufferListItem = ATOMIC_LOAD(&voice->current_buffer, almemory_order_relaxed);
+    while(BufferListItem != NULL)
+    {
+        const ALbuffer *buffer;
+        if((buffer=BufferListItem->buffer) != NULL)
+        {
+            if(props->SpatializeMode == SpatializeOn ||
+               (props->SpatializeMode == SpatializeAuto && buffer->FmtChannels == FmtMono))
+                CalcAttnSourceParams(voice, props, buffer, context);
+            else
+                CalcNonAttnSourceParams(voice, props, buffer, context);
+            break;
+        }
+        BufferListItem = ATOMIC_LOAD(&BufferListItem->next, almemory_order_acquire);
+    }
+}
+
+
+static void UpdateContextSources(ALCcontext *ctx, const struct ALeffectslotArray *slots)
+{
+    ALvoice **voice, **voice_end;
+    ALsource *source;
+    ALsizei i;
+
+    IncrementRef(&ctx->UpdateCount);
+    if(!ATOMIC_LOAD(&ctx->HoldUpdates, almemory_order_acquire))
+    {
+        ALboolean force = CalcListenerParams(ctx);
+        for(i = 0;i < slots->count;i++)
+            force |= CalcEffectSlotParams(slots->slot[i], ctx->Device);
+
+        voice = ctx->Voices;
+        voice_end = voice + ctx->VoiceCount;
+        for(;voice != voice_end;++voice)
+        {
+            source = ATOMIC_LOAD(&(*voice)->Source, almemory_order_acquire);
+            if(source) CalcSourceParams(*voice, ctx, force);
+        }
+    }
+    IncrementRef(&ctx->UpdateCount);
+}
+
+
+static void ApplyDistanceComp(ALfloatBUFFERSIZE *restrict Samples, DistanceComp *distcomp,
+                              ALfloat *restrict Values, ALsizei SamplesToDo, ALsizei numchans)
+{
+    ALsizei i, c;
+
+    Values = ASSUME_ALIGNED(Values, 16);
+    for(c = 0;c < numchans;c++)
+    {
+        ALfloat *restrict inout = ASSUME_ALIGNED(Samples[c], 16);
+        const ALfloat gain = distcomp[c].Gain;
+        const ALsizei base = distcomp[c].Length;
+        ALfloat *restrict distbuf = ASSUME_ALIGNED(distcomp[c].Buffer, 16);
+
+        if(base == 0)
+        {
+            if(gain < 1.0f)
+            {
+                for(i = 0;i < SamplesToDo;i++)
+                    inout[i] *= gain;
+            }
+            continue;
+        }
+
+        if(SamplesToDo >= base)
+        {
+            for(i = 0;i < base;i++)
+                Values[i] = distbuf[i];
+            for(;i < SamplesToDo;i++)
+                Values[i] = inout[i-base];
+            memcpy(distbuf, &inout[SamplesToDo-base], base*sizeof(ALfloat));
+        }
+        else
+        {
+            for(i = 0;i < SamplesToDo;i++)
+                Values[i] = distbuf[i];
+            memmove(distbuf, distbuf+SamplesToDo, (base-SamplesToDo)*sizeof(ALfloat));
+            memcpy(distbuf+base-SamplesToDo, inout, SamplesToDo*sizeof(ALfloat));
+        }
+        for(i = 0;i < SamplesToDo;i++)
+            inout[i] = Values[i]*gain;
+    }
+}
+
+static void ApplyDither(ALfloatBUFFERSIZE *restrict Samples, ALuint *dither_seed,
+                        const ALfloat quant_scale, const ALsizei SamplesToDo,
+                        const ALsizei numchans)
+{
+    const ALfloat invscale = 1.0f / quant_scale;
+    ALuint seed = *dither_seed;
+    ALsizei c, i;
+
+    /* Dithering. Step 1, generate whitenoise (uniform distribution of random
+     * values between -1 and +1). Step 2 is to add the noise to the samples,
+     * before rounding and after scaling up to the desired quantization depth.
+     */
+    for(c = 0;c < numchans;c++)
+    {
+        ALfloat *restrict samples = Samples[c];
+        for(i = 0;i < SamplesToDo;i++)
+        {
+            ALfloat val = samples[i] * quant_scale;
+            ALuint rng0 = dither_rng(&seed);
+            ALuint rng1 = dither_rng(&seed);
+            val += (ALfloat)(rng0*(1.0/UINT_MAX) - rng1*(1.0/UINT_MAX));
+            samples[i] = roundf(val) * invscale;
+        }
+    }
+    *dither_seed = seed;
+}
+
+
+static inline ALfloat Conv_ALfloat(ALfloat val)
+{ return val; }
+static inline ALint Conv_ALint(ALfloat val)
+{
+    /* Floats only have a 24-bit mantissa, so [-16777216, +16777216] is the max
+     * integer range normalized floats can be safely converted to (a bit of the
+     * exponent helps out, effectively giving 25 bits).
+     */
+    return fastf2i(clampf(val*16777216.0f, -16777216.0f, 16777215.0f))<<7;
+}
+static inline ALshort Conv_ALshort(ALfloat val)
+{ return fastf2i(clampf(val*32768.0f, -32768.0f, 32767.0f)); }
+static inline ALbyte Conv_ALbyte(ALfloat val)
+{ return fastf2i(clampf(val*128.0f, -128.0f, 127.0f)); }
+
+/* Define unsigned output variations. */
+#define DECL_TEMPLATE(T, func, O)                             \
+static inline T Conv_##T(ALfloat val) { return func(val)+O; }
+
+DECL_TEMPLATE(ALubyte, Conv_ALbyte, 128)
+DECL_TEMPLATE(ALushort, Conv_ALshort, 32768)
+DECL_TEMPLATE(ALuint, Conv_ALint, 2147483648u)
+
+#undef DECL_TEMPLATE
+
+#define DECL_TEMPLATE(T, A)                                                   \
+static void Write##A(const ALfloatBUFFERSIZE *InBuffer, ALvoid *OutBuffer,    \
+                     ALsizei Offset, ALsizei SamplesToDo, ALsizei numchans)   \
+{                                                                             \
+    ALsizei i, j;                                                             \
+    for(j = 0;j < numchans;j++)                                               \
+    {                                                                         \
+        const ALfloat *restrict in = ASSUME_ALIGNED(InBuffer[j], 16);         \
+        T *restrict out = (T*)OutBuffer + Offset*numchans + j;                \
+                                                                              \
+        for(i = 0;i < SamplesToDo;i++)                                        \
+            out[i*numchans] = Conv_##T(in[i]);                                \
+    }                                                                         \
+}
+
+DECL_TEMPLATE(ALfloat, F32)
+DECL_TEMPLATE(ALuint, UI32)
+DECL_TEMPLATE(ALint, I32)
+DECL_TEMPLATE(ALushort, UI16)
+DECL_TEMPLATE(ALshort, I16)
+DECL_TEMPLATE(ALubyte, UI8)
+DECL_TEMPLATE(ALbyte, I8)
+
+#undef DECL_TEMPLATE
+
+
+void aluMixData(ALCdevice *device, ALvoid *OutBuffer, ALsizei NumSamples)
+{
+    ALsizei SamplesToDo;
+    ALsizei SamplesDone;
+    ALCcontext *ctx;
+    ALsizei i, c;
+
+    START_MIXER_MODE();
+    for(SamplesDone = 0;SamplesDone < NumSamples;)
+    {
+        SamplesToDo = mini(NumSamples-SamplesDone, BUFFERSIZE);
+        for(c = 0;c < device->Dry.NumChannels;c++)
+            memset(device->Dry.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
+        if(device->Dry.Buffer != device->FOAOut.Buffer)
+            for(c = 0;c < device->FOAOut.NumChannels;c++)
+                memset(device->FOAOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
+        if(device->Dry.Buffer != device->RealOut.Buffer)
+            for(c = 0;c < device->RealOut.NumChannels;c++)
+                memset(device->RealOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat));
+
+        IncrementRef(&device->MixCount);
+
+        ctx = ATOMIC_LOAD(&device->ContextList, almemory_order_acquire);
+        while(ctx)
+        {
+            const struct ALeffectslotArray *auxslots;
+
+            auxslots = ATOMIC_LOAD(&ctx->ActiveAuxSlots, almemory_order_acquire);
+            UpdateContextSources(ctx, auxslots);
+
+            for(i = 0;i < auxslots->count;i++)
+            {
+                ALeffectslot *slot = auxslots->slot[i];
+                for(c = 0;c < slot->NumChannels;c++)
+                    memset(slot->WetBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
+            }
+
+            /* source processing */
+            for(i = 0;i < ctx->VoiceCount;i++)
+            {
+                ALvoice *voice = ctx->Voices[i];
+                ALsource *source = ATOMIC_LOAD(&voice->Source, almemory_order_acquire);
+                if(source && ATOMIC_LOAD(&voice->Playing, almemory_order_relaxed) &&
+                   voice->Step > 0)
+                {
+                    if(!MixSource(voice, source, device, SamplesToDo))
+                    {
+                        ATOMIC_STORE(&voice->Source, NULL, almemory_order_relaxed);
+                        ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
+                    }
+                }
+            }
+
+            /* effect slot processing */
+            for(i = 0;i < auxslots->count;i++)
+            {
+                const ALeffectslot *slot = auxslots->slot[i];
+                ALeffectState *state = slot->Params.EffectState;
+                V(state,process)(SamplesToDo, slot->WetBuffer, state->OutBuffer,
+                                 state->OutChannels);
+            }
+
+            ctx = ctx->next;
+        }
+
+        /* Increment the clock time. Every second's worth of samples is
+         * converted and added to clock base so that large sample counts don't
+         * overflow during conversion. This also guarantees an exact, stable
+         * conversion. */
+        device->SamplesDone += SamplesToDo;
+        device->ClockBase += (device->SamplesDone/device->Frequency) * DEVICE_CLOCK_RES;
+        device->SamplesDone %= device->Frequency;
+        IncrementRef(&device->MixCount);
+
+        if(device->HrtfHandle)
+        {
+            HrtfDirectMixerFunc HrtfMix;
+            DirectHrtfState *state;
+            int lidx, ridx;
+
+            if(device->AmbiUp)
+                ambiup_process(device->AmbiUp,
+                    device->Dry.Buffer, device->Dry.NumChannels,
+                    SAFE_CONST(ALfloatBUFFERSIZE*,device->FOAOut.Buffer), SamplesToDo
+                );
+
+            lidx = GetChannelIdxByName(device->RealOut, FrontLeft);
+            ridx = GetChannelIdxByName(device->RealOut, FrontRight);
+            assert(lidx != -1 && ridx != -1);
+
+            HrtfMix = SelectHrtfMixer();
+            state = device->Hrtf;
+            for(c = 0;c < device->Dry.NumChannels;c++)
+            {
+                HrtfMix(device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
+                    device->Dry.Buffer[c], state->Offset, state->IrSize,
+                    SAFE_CONST(ALfloat2*,state->Chan[c].Coeffs),
+                    state->Chan[c].Values, SamplesToDo
+                );
+            }
+            state->Offset += SamplesToDo;
+        }
+        else if(device->AmbiDecoder)
+        {
+            if(device->Dry.Buffer != device->FOAOut.Buffer)
+                bformatdec_upSample(device->AmbiDecoder,
+                    device->Dry.Buffer, SAFE_CONST(ALfloatBUFFERSIZE*,device->FOAOut.Buffer),
+                    device->FOAOut.NumChannels, SamplesToDo
+                );
+            bformatdec_process(device->AmbiDecoder,
+                device->RealOut.Buffer, device->RealOut.NumChannels,
+                SAFE_CONST(ALfloatBUFFERSIZE*,device->Dry.Buffer), SamplesToDo
+            );
+        }
+        else if(device->AmbiUp)
+        {
+            ambiup_process(device->AmbiUp,
+                device->RealOut.Buffer, device->RealOut.NumChannels,
+                SAFE_CONST(ALfloatBUFFERSIZE*,device->FOAOut.Buffer), SamplesToDo
+            );
+        }
+        else if(device->Uhj_Encoder)
+        {
+            int lidx = GetChannelIdxByName(device->RealOut, FrontLeft);
+            int ridx = GetChannelIdxByName(device->RealOut, FrontRight);
+            if(lidx != -1 && ridx != -1)
+            {
+                /* Encode to stereo-compatible 2-channel UHJ output. */
+                EncodeUhj2(device->Uhj_Encoder,
+                    device->RealOut.Buffer[lidx], device->RealOut.Buffer[ridx],
+                    device->Dry.Buffer, SamplesToDo
+                );
+            }
+        }
+        else if(device->Bs2b)
+        {
+            int lidx = GetChannelIdxByName(device->RealOut, FrontLeft);
+            int ridx = GetChannelIdxByName(device->RealOut, FrontRight);
+            if(lidx != -1 && ridx != -1)
+            {
+                /* Apply binaural/crossfeed filter */
+                bs2b_cross_feed(device->Bs2b, device->RealOut.Buffer[lidx],
+                                device->RealOut.Buffer[ridx], SamplesToDo);
+            }
+        }
+
+        if(OutBuffer)
+        {
+            ALfloat (*Buffer)[BUFFERSIZE] = device->RealOut.Buffer;
+            ALsizei Channels = device->RealOut.NumChannels;
+
+            /* Use NFCtrlData for temp value storage. */
+            ApplyDistanceComp(Buffer, device->ChannelDelay, device->NFCtrlData,
+                              SamplesToDo, Channels);
+
+            if(device->Limiter)
+                ApplyCompression(device->Limiter, Channels, SamplesToDo, Buffer);
+
+            if(device->DitherDepth > 0.0f)
+                ApplyDither(Buffer, &device->DitherSeed, device->DitherDepth, SamplesToDo,
+                            Channels);
+
+            switch(device->FmtType)
+            {
+                case DevFmtByte:
+                    WriteI8(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
+                    break;
+                case DevFmtUByte:
+                    WriteUI8(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
+                    break;
+                case DevFmtShort:
+                    WriteI16(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
+                    break;
+                case DevFmtUShort:
+                    WriteUI16(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
+                    break;
+                case DevFmtInt:
+                    WriteI32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
+                    break;
+                case DevFmtUInt:
+                    WriteUI32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
+                    break;
+                case DevFmtFloat:
+                    WriteF32(Buffer, OutBuffer, SamplesDone, SamplesToDo, Channels);
+                    break;
+            }
+        }
+
+        SamplesDone += SamplesToDo;
+    }
+    END_MIXER_MODE();
+}
+
+
+void aluHandleDisconnect(ALCdevice *device)
+{
+    ALCcontext *ctx;
+
+    device->Connected = ALC_FALSE;
+
+    ctx = ATOMIC_LOAD_SEQ(&device->ContextList);
+    while(ctx)
+    {
+        ALsizei i;
+        for(i = 0;i < ctx->VoiceCount;i++)
+        {
+            ALvoice *voice = ctx->Voices[i];
+            ALsource *source;
+
+            source = ATOMIC_EXCHANGE_PTR(&voice->Source, NULL, almemory_order_acq_rel);
+            ATOMIC_STORE(&voice->Playing, false, almemory_order_release);
+
+            if(source)
+            {
+                ALenum playing = AL_PLAYING;
+                (void)(ATOMIC_COMPARE_EXCHANGE_STRONG_SEQ(&source->state, &playing, AL_STOPPED));
+            }
+        }
+        ctx->VoiceCount = 0;
+
+        ctx = ctx->next;
+    }
+}

+ 173 - 36
love/src/jni/openal-soft-1.17.0/Alc/alcConfig.c → love/src/jni/openal-soft-1.18.2/Alc/alcConfig.c

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

+ 317 - 0
love/src/jni/openal-soft-1.18.2/Alc/alcRing.c

@@ -0,0 +1,317 @@
+/**
+ * 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 <string.h>
+#include <stdlib.h>
+
+#include "alMain.h"
+#include "threads.h"
+#include "almalloc.h"
+#include "compat.h"
+
+
+/* NOTE: This lockless ringbuffer implementation is copied from JACK, extended
+ * to include an element size. Consequently, parameters and return values for a
+ * size or count is in 'elements', not bytes. Additionally, it only supports
+ * single-consumer/single-provider operation. */
+struct ll_ringbuffer {
+    ATOMIC(size_t) write_ptr;
+    ATOMIC(size_t) read_ptr;
+    size_t size;
+    size_t size_mask;
+    size_t elem_size;
+    int mlocked;
+
+    alignas(16) char buf[];
+};
+
+/* Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes.
+ * The number of elements is rounded up to the next power of two. */
+ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz)
+{
+    ll_ringbuffer_t *rb;
+    ALuint power_of_two;
+
+    power_of_two = NextPowerOf2(sz);
+    if(power_of_two < sz)
+        return NULL;
+
+    rb = al_malloc(16, sizeof(*rb) + power_of_two*elem_sz);
+    if(!rb) return NULL;
+
+    ATOMIC_INIT(&rb->write_ptr, 0);
+    ATOMIC_INIT(&rb->read_ptr, 0);
+    rb->size = power_of_two;
+    rb->size_mask = rb->size - 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;
+}
+
+/* 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);
+}
+
+/* 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;
+}
+
+/* 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;
+    size_t free_cnt;
+    size_t cnt2;
+    size_t to_read;
+    size_t n1, n2;
+
+    free_cnt = ll_ringbuffer_read_space(rb);
+    if(free_cnt == 0) return 0;
+
+    to_read = (cnt > free_cnt) ? free_cnt : cnt;
+    read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask;
+
+    cnt2 = read_ptr + to_read;
+    if(cnt2 > rb->size)
+    {
+        n1 = rb->size - read_ptr;
+        n2 = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        n1 = to_read;
+        n2 = 0;
+    }
+
+    memcpy(dest, &rb->buf[read_ptr*rb->elem_size], n1*rb->elem_size);
+    read_ptr += n1;
+    if(n2)
+    {
+        memcpy(dest + n1*rb->elem_size, &rb->buf[(read_ptr&rb->size_mask)*rb->elem_size],
+               n2*rb->elem_size);
+        read_ptr += n2;
+    }
+    ATOMIC_STORE(&rb->read_ptr, read_ptr, almemory_order_release);
+    return to_read;
+}
+
+/* The copying data reader w/o read pointer advance. Copy at most `cnt'
+ * elements from `rb' to `dest'. Returns the actual number of elements copied.
+ */
+size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt)
+{
+    size_t free_cnt;
+    size_t cnt2;
+    size_t to_read;
+    size_t n1, n2;
+    size_t read_ptr;
+
+    free_cnt = ll_ringbuffer_read_space(rb);
+    if(free_cnt == 0) return 0;
+
+    to_read = (cnt > free_cnt) ? free_cnt : cnt;
+    read_ptr = ATOMIC_LOAD(&rb->read_ptr, almemory_order_relaxed) & rb->size_mask;
+
+    cnt2 = read_ptr + to_read;
+    if(cnt2 > rb->size)
+    {
+        n1 = rb->size - read_ptr;
+        n2 = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        n1 = to_read;
+        n2 = 0;
+    }
+
+    memcpy(dest, &rb->buf[read_ptr*rb->elem_size], n1*rb->elem_size);
+    if(n2)
+    {
+        read_ptr += n1;
+        memcpy(dest + n1*rb->elem_size, &rb->buf[(read_ptr&rb->size_mask)*rb->elem_size],
+               n2*rb->elem_size);
+    }
+    return to_read;
+}
+
+/* The copying data writer. Copy at most `cnt' elements to `rb' from `src'.
+ * Returns the actual number of elements copied. */
+size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt)
+{
+    size_t write_ptr;
+    size_t free_cnt;
+    size_t cnt2;
+    size_t to_write;
+    size_t n1, n2;
+
+    free_cnt = ll_ringbuffer_write_space(rb);
+    if(free_cnt == 0) return 0;
+
+    to_write = (cnt > free_cnt) ? free_cnt : cnt;
+    write_ptr = ATOMIC_LOAD(&rb->write_ptr, almemory_order_relaxed) & rb->size_mask;
+
+    cnt2 = write_ptr + to_write;
+    if(cnt2 > rb->size)
+    {
+        n1 = rb->size - write_ptr;
+        n2 = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        n1 = to_write;
+        n2 = 0;
+    }
+
+    memcpy(&rb->buf[write_ptr*rb->elem_size], src, n1*rb->elem_size);
+    write_ptr += n1;
+    if(n2)
+    {
+        memcpy(&rb->buf[(write_ptr&rb->size_mask)*rb->elem_size], src + n1*rb->elem_size,
+               n2*rb->elem_size);
+        write_ptr += n2;
+    }
+    ATOMIC_STORE(&rb->write_ptr, write_ptr, almemory_order_release);
+    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)
+{
+    size_t free_cnt;
+    size_t cnt2;
+    size_t w, r;
+
+    w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire);
+    r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire);
+    w &= rb->size_mask;
+    r &= rb->size_mask;
+    free_cnt = (w-r) & rb->size_mask;
+
+    cnt2 = r + free_cnt;
+    if(cnt2 > rb->size)
+    {
+        /* Two part vector: the rest of the buffer after the current write ptr,
+         * plus some from the start of the buffer. */
+        vec[0].buf = (char*)&rb->buf[r*rb->elem_size];
+        vec[0].len = rb->size - r;
+        vec[1].buf = (char*)rb->buf;
+        vec[1].len = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        /* Single part vector: just the rest of the buffer */
+        vec[0].buf = (char*)&rb->buf[r*rb->elem_size];
+        vec[0].len = free_cnt;
+        vec[1].buf = NULL;
+        vec[1].len = 0;
+    }
+}
+
+/* The non-copying data writer. `vec' is an array of two places. Set the values
+ * at `vec' to hold the current writeable data at `rb'. If the writeable data
+ * is in one segment the second segment has zero length. */
+void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec)
+{
+    size_t free_cnt;
+    size_t cnt2;
+    size_t w, r;
+
+    w = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->write_ptr, almemory_order_acquire);
+    r = ATOMIC_LOAD(&CONST_CAST(ll_ringbuffer_t*,rb)->read_ptr, almemory_order_acquire);
+    w &= rb->size_mask;
+    r &= rb->size_mask;
+    free_cnt = (r-w-1) & rb->size_mask;
+
+    cnt2 = w + free_cnt;
+    if(cnt2 > rb->size)
+    {
+        /* Two part vector: the rest of the buffer after the current write ptr,
+         * plus some from the start of the buffer. */
+        vec[0].buf = (char*)&rb->buf[w*rb->elem_size];
+        vec[0].len = rb->size - w;
+        vec[1].buf = (char*)rb->buf;
+        vec[1].len = cnt2 & rb->size_mask;
+    }
+    else
+    {
+        vec[0].buf = (char*)&rb->buf[w*rb->elem_size];
+        vec[0].len = free_cnt;
+        vec[1].buf = NULL;
+        vec[1].len = 0;
+    }
+}

+ 49 - 0
love/src/jni/openal-soft-1.18.2/Alc/alstring.h

@@ -0,0 +1,49 @@
+#ifndef ALSTRING_H
+#define ALSTRING_H
+
+#include <string.h>
+
+#include "vector.h"
+
+
+typedef char al_string_char_type;
+TYPEDEF_VECTOR(al_string_char_type, al_string)
+TYPEDEF_VECTOR(al_string, vector_al_string)
+
+inline void alstr_reset(al_string *str)
+{ VECTOR_DEINIT(*str); }
+#define AL_STRING_INIT(_x)       do { (_x) = (al_string)NULL; } while(0)
+#define AL_STRING_INIT_STATIC()  ((al_string)NULL)
+#define AL_STRING_DEINIT(_x)     alstr_reset(&(_x))
+
+inline size_t alstr_length(const_al_string str)
+{ return VECTOR_SIZE(str); }
+
+inline ALboolean alstr_empty(const_al_string str)
+{ return alstr_length(str) == 0; }
+
+inline const al_string_char_type *alstr_get_cstr(const_al_string str)
+{ return str ? &VECTOR_FRONT(str) : ""; }
+
+void alstr_clear(al_string *str);
+
+int alstr_cmp(const_al_string str1, const_al_string str2);
+int alstr_cmp_cstr(const_al_string str1, const al_string_char_type *str2);
+
+void alstr_copy(al_string *str, const_al_string from);
+void alstr_copy_cstr(al_string *str, const al_string_char_type *from);
+void alstr_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to);
+
+void alstr_append_char(al_string *str, const al_string_char_type c);
+void alstr_append_cstr(al_string *str, const al_string_char_type *from);
+void alstr_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to);
+
+#ifdef _WIN32
+#include <wchar.h>
+/* Windows-only methods to deal with WideChar strings. */
+void alstr_copy_wcstr(al_string *str, const wchar_t *from);
+void alstr_append_wcstr(al_string *str, const wchar_t *from);
+void alstr_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to);
+#endif
+
+#endif /* ALSTRING_H */

+ 566 - 0
love/src/jni/openal-soft-1.18.2/Alc/ambdec.c

@@ -0,0 +1,566 @@
+
+#include "config.h"
+
+#include "ambdec.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "compat.h"
+
+
+static char *lstrip(char *line)
+{
+    while(isspace(line[0]))
+        line++;
+    return line;
+}
+
+static char *rstrip(char *line)
+{
+    size_t len = strlen(line);
+    while(len > 0 && isspace(line[len-1]))
+        len--;
+    line[len] = 0;
+    return line;
+}
+
+static int readline(FILE *f, char **output, size_t *maxlen)
+{
+    size_t len = 0;
+    int c;
+
+    while((c=fgetc(f)) != EOF && (c == '\r' || c == '\n'))
+        ;
+    if(c == EOF)
+        return 0;
+
+    do {
+        if(len+1 >= *maxlen)
+        {
+            void *temp = NULL;
+            size_t newmax;
+
+            newmax = (*maxlen ? (*maxlen)<<1 : 32);
+            if(newmax > *maxlen)
+                temp = realloc(*output, newmax);
+            if(!temp)
+            {
+                ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, *maxlen);
+                return 0;
+            }
+
+            *output = temp;
+            *maxlen = newmax;
+        }
+        (*output)[len++] = c;
+        (*output)[len] = '\0';
+    } while((c=fgetc(f)) != EOF && c != '\r' && c != '\n');
+
+    return 1;
+}
+
+
+/* Custom strtok_r, since we can't rely on it existing. */
+static char *my_strtok_r(char *str, const char *delim, char **saveptr)
+{
+    /* Sanity check and update internal pointer. */
+    if(!saveptr || !delim) return NULL;
+    if(str) *saveptr = str;
+    str = *saveptr;
+
+    /* Nothing more to do with this string. */
+    if(!str) return NULL;
+
+    /* Find the first non-delimiter character. */
+    while(*str != '\0' && strchr(delim, *str) != NULL)
+        str++;
+    if(*str == '\0')
+    {
+        /* End of string. */
+        *saveptr = NULL;
+        return NULL;
+    }
+
+    /* Find the next delimiter character. */
+    *saveptr = strpbrk(str, delim);
+    if(*saveptr) *((*saveptr)++) = '\0';
+
+    return str;
+}
+
+static char *read_int(ALint *num, const char *line, int base)
+{
+    char *end;
+    *num = strtol(line, &end, base);
+    if(end && *end != '\0')
+        end = lstrip(end);
+    return end;
+}
+
+static char *read_uint(ALuint *num, const char *line, int base)
+{
+    char *end;
+    *num = strtoul(line, &end, base);
+    if(end && *end != '\0')
+        end = lstrip(end);
+    return end;
+}
+
+static char *read_float(ALfloat *num, const char *line)
+{
+    char *end;
+#ifdef HAVE_STRTOF
+    *num = strtof(line, &end);
+#else
+    *num = (ALfloat)strtod(line, &end);
+#endif
+    if(end && *end != '\0')
+        end = lstrip(end);
+    return end;
+}
+
+
+char *read_clipped_line(FILE *f, char **buffer, size_t *maxlen)
+{
+    while(readline(f, buffer, maxlen))
+    {
+        char *line, *comment;
+
+        line = lstrip(*buffer);
+        comment = strchr(line, '#');
+        if(comment) *(comment++) = 0;
+
+        line = rstrip(line);
+        if(line[0]) return line;
+    }
+    return NULL;
+}
+
+static int load_ambdec_speakers(AmbDecConf *conf, FILE *f, char **buffer, size_t *maxlen, char **saveptr)
+{
+    ALsizei cur = 0;
+    while(cur < conf->NumSpeakers)
+    {
+        const char *cmd = my_strtok_r(NULL, " \t", saveptr);
+        if(!cmd)
+        {
+            char *line = read_clipped_line(f, buffer, maxlen);
+            if(!line)
+            {
+                ERR("Unexpected end of file\n");
+                return 0;
+            }
+            cmd = my_strtok_r(line, " \t", saveptr);
+        }
+
+        if(strcmp(cmd, "add_spkr") == 0)
+        {
+            const char *name = my_strtok_r(NULL, " \t", saveptr);
+            const char *dist = my_strtok_r(NULL, " \t", saveptr);
+            const char *az = my_strtok_r(NULL, " \t", saveptr);
+            const char *elev = my_strtok_r(NULL, " \t", saveptr);
+            const char *conn = my_strtok_r(NULL, " \t", saveptr);
+
+            if(!name) WARN("Name not specified for speaker %u\n", cur+1);
+            else alstr_copy_cstr(&conf->Speakers[cur].Name, name);
+            if(!dist) WARN("Distance not specified for speaker %u\n", cur+1);
+            else read_float(&conf->Speakers[cur].Distance, dist);
+            if(!az) WARN("Azimuth not specified for speaker %u\n", cur+1);
+            else read_float(&conf->Speakers[cur].Azimuth, az);
+            if(!elev) WARN("Elevation not specified for speaker %u\n", cur+1);
+            else read_float(&conf->Speakers[cur].Elevation, elev);
+            if(!conn) TRACE("Connection not specified for speaker %u\n", cur+1);
+            else alstr_copy_cstr(&conf->Speakers[cur].Connection, conn);
+
+            cur++;
+        }
+        else
+        {
+            ERR("Unexpected speakers command: %s\n", cmd);
+            return 0;
+        }
+
+        cmd = my_strtok_r(NULL, " \t", saveptr);
+        if(cmd)
+        {
+            ERR("Unexpected junk on line: %s\n", cmd);
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+static int load_ambdec_matrix(ALfloat *gains, ALfloat (*matrix)[MAX_AMBI_COEFFS], ALsizei maxrow, FILE *f, char **buffer, size_t *maxlen, char **saveptr)
+{
+    int gotgains = 0;
+    ALsizei cur = 0;
+    while(cur < maxrow)
+    {
+        const char *cmd = my_strtok_r(NULL, " \t", saveptr);
+        if(!cmd)
+        {
+            char *line = read_clipped_line(f, buffer, maxlen);
+            if(!line)
+            {
+                ERR("Unexpected end of file\n");
+                return 0;
+            }
+            cmd = my_strtok_r(line, " \t", saveptr);
+        }
+
+        if(strcmp(cmd, "order_gain") == 0)
+        {
+            ALuint curgain = 0;
+            char *line;
+            while((line=my_strtok_r(NULL, " \t", saveptr)) != NULL)
+            {
+                ALfloat value;
+                line = read_float(&value, line);
+                if(line && *line != '\0')
+                {
+                    ERR("Extra junk on gain %u: %s\n", curgain+1, line);
+                    return 0;
+                }
+                if(curgain < MAX_AMBI_ORDER+1)
+                    gains[curgain] = value;
+                curgain++;
+            }
+            while(curgain < MAX_AMBI_ORDER+1)
+                gains[curgain++] = 0.0f;
+            gotgains = 1;
+        }
+        else if(strcmp(cmd, "add_row") == 0)
+        {
+            ALuint curidx = 0;
+            char *line;
+            while((line=my_strtok_r(NULL, " \t", saveptr)) != NULL)
+            {
+                ALfloat value;
+                line = read_float(&value, line);
+                if(line && *line != '\0')
+                {
+                    ERR("Extra junk on matrix element %ux%u: %s\n", cur, curidx, line);
+                    return 0;
+                }
+                if(curidx < MAX_AMBI_COEFFS)
+                    matrix[cur][curidx] = value;
+                curidx++;
+            }
+            while(curidx < MAX_AMBI_COEFFS)
+                matrix[cur][curidx++] = 0.0f;
+            cur++;
+        }
+        else
+        {
+            ERR("Unexpected speakers command: %s\n", cmd);
+            return 0;
+        }
+
+        cmd = my_strtok_r(NULL, " \t", saveptr);
+        if(cmd)
+        {
+            ERR("Unexpected junk on line: %s\n", cmd);
+            return 0;
+        }
+    }
+
+    if(!gotgains)
+    {
+        ERR("Matrix order_gain not specified\n");
+        return 0;
+    }
+
+    return 1;
+}
+
+void ambdec_init(AmbDecConf *conf)
+{
+    ALsizei i;
+
+    memset(conf, 0, sizeof(*conf));
+    AL_STRING_INIT(conf->Description);
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+    {
+        AL_STRING_INIT(conf->Speakers[i].Name);
+        AL_STRING_INIT(conf->Speakers[i].Connection);
+    }
+}
+
+void ambdec_deinit(AmbDecConf *conf)
+{
+    ALsizei i;
+
+    alstr_reset(&conf->Description);
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+    {
+        alstr_reset(&conf->Speakers[i].Name);
+        alstr_reset(&conf->Speakers[i].Connection);
+    }
+    memset(conf, 0, sizeof(*conf));
+}
+
+int ambdec_load(AmbDecConf *conf, const char *fname)
+{
+    char *buffer = NULL;
+    size_t maxlen = 0;
+    char *line;
+    FILE *f;
+
+    f = al_fopen(fname, "r");
+    if(!f)
+    {
+        ERR("Failed to open: %s\n", fname);
+        return 0;
+    }
+
+    while((line=read_clipped_line(f, &buffer, &maxlen)) != NULL)
+    {
+        char *saveptr;
+        char *command;
+
+        command = my_strtok_r(line, "/ \t", &saveptr);
+        if(!command)
+        {
+            ERR("Malformed line: %s\n", line);
+            goto fail;
+        }
+
+        if(strcmp(command, "description") == 0)
+        {
+            char *value = my_strtok_r(NULL, "", &saveptr);
+            alstr_copy_cstr(&conf->Description, lstrip(value));
+        }
+        else if(strcmp(command, "version") == 0)
+        {
+            line = my_strtok_r(NULL, "", &saveptr);
+            line = read_uint(&conf->Version, line, 10);
+            if(line && *line != '\0')
+            {
+                ERR("Extra junk after version: %s\n", line);
+                goto fail;
+            }
+            if(conf->Version != 3)
+            {
+                ERR("Unsupported version: %u\n", conf->Version);
+                goto fail;
+            }
+        }
+        else if(strcmp(command, "dec") == 0)
+        {
+            const char *dec = my_strtok_r(NULL, "/ \t", &saveptr);
+            if(strcmp(dec, "chan_mask") == 0)
+            {
+                line = my_strtok_r(NULL, "", &saveptr);
+                line = read_uint(&conf->ChanMask, line, 16);
+                if(line && *line != '\0')
+                {
+                    ERR("Extra junk after mask: %s\n", line);
+                    goto fail;
+                }
+            }
+            else if(strcmp(dec, "freq_bands") == 0)
+            {
+                line = my_strtok_r(NULL, "", &saveptr);
+                line = read_uint(&conf->FreqBands, line, 10);
+                if(line && *line != '\0')
+                {
+                    ERR("Extra junk after freq_bands: %s\n", line);
+                    goto fail;
+                }
+                if(conf->FreqBands != 1 && conf->FreqBands != 2)
+                {
+                    ERR("Invalid freq_bands value: %u\n", conf->FreqBands);
+                    goto fail;
+                }
+            }
+            else if(strcmp(dec, "speakers") == 0)
+            {
+                line = my_strtok_r(NULL, "", &saveptr);
+                line = read_int(&conf->NumSpeakers, line, 10);
+                if(line && *line != '\0')
+                {
+                    ERR("Extra junk after speakers: %s\n", line);
+                    goto fail;
+                }
+                if(conf->NumSpeakers > MAX_OUTPUT_CHANNELS)
+                {
+                    ERR("Unsupported speaker count: %u\n", conf->NumSpeakers);
+                    goto fail;
+                }
+            }
+            else if(strcmp(dec, "coeff_scale") == 0)
+            {
+                line = my_strtok_r(NULL, " \t", &saveptr);
+                if(strcmp(line, "n3d") == 0)
+                    conf->CoeffScale = ADS_N3D;
+                else if(strcmp(line, "sn3d") == 0)
+                    conf->CoeffScale = ADS_SN3D;
+                else if(strcmp(line, "fuma") == 0)
+                    conf->CoeffScale = ADS_FuMa;
+                else
+                {
+                    ERR("Unsupported coeff scale: %s\n", line);
+                    goto fail;
+                }
+            }
+            else
+            {
+                ERR("Unexpected /dec option: %s\n", dec);
+                goto fail;
+            }
+        }
+        else if(strcmp(command, "opt") == 0)
+        {
+            const char *opt = my_strtok_r(NULL, "/ \t", &saveptr);
+            if(strcmp(opt, "xover_freq") == 0)
+            {
+                line = my_strtok_r(NULL, "", &saveptr);
+                line = read_float(&conf->XOverFreq, line);
+                if(line && *line != '\0')
+                {
+                    ERR("Extra junk after xover_freq: %s\n", line);
+                    goto fail;
+                }
+            }
+            else if(strcmp(opt, "xover_ratio") == 0)
+            {
+                line = my_strtok_r(NULL, "", &saveptr);
+                line = read_float(&conf->XOverRatio, line);
+                if(line && *line != '\0')
+                {
+                    ERR("Extra junk after xover_ratio: %s\n", line);
+                    goto fail;
+                }
+            }
+            else if(strcmp(opt, "input_scale") == 0 || strcmp(opt, "nfeff_comp") == 0 ||
+                    strcmp(opt, "delay_comp") == 0 || strcmp(opt, "level_comp") == 0)
+            {
+                /* Unused */
+                my_strtok_r(NULL, " \t", &saveptr);
+            }
+            else
+            {
+                ERR("Unexpected /opt option: %s\n", opt);
+                goto fail;
+            }
+        }
+        else if(strcmp(command, "speakers") == 0)
+        {
+            const char *value = my_strtok_r(NULL, "/ \t", &saveptr);
+            if(strcmp(value, "{") != 0)
+            {
+                ERR("Expected { after %s command, got %s\n", command, value);
+                goto fail;
+            }
+            if(!load_ambdec_speakers(conf, f, &buffer, &maxlen, &saveptr))
+                goto fail;
+            value = my_strtok_r(NULL, "/ \t", &saveptr);
+            if(!value)
+            {
+                line = read_clipped_line(f, &buffer, &maxlen);
+                if(!line)
+                {
+                    ERR("Unexpected end of file\n");
+                    goto fail;
+                }
+                value = my_strtok_r(line, "/ \t", &saveptr);
+            }
+            if(strcmp(value, "}") != 0)
+            {
+                ERR("Expected } after speaker definitions, got %s\n", value);
+                goto fail;
+            }
+        }
+        else if(strcmp(command, "lfmatrix") == 0 || strcmp(command, "hfmatrix") == 0 ||
+                strcmp(command, "matrix") == 0)
+        {
+            const char *value = my_strtok_r(NULL, "/ \t", &saveptr);
+            if(strcmp(value, "{") != 0)
+            {
+                ERR("Expected { after %s command, got %s\n", command, value);
+                goto fail;
+            }
+            if(conf->FreqBands == 1)
+            {
+                if(strcmp(command, "matrix") != 0)
+                {
+                    ERR("Unexpected \"%s\" type for a single-band decoder\n", command);
+                    goto fail;
+                }
+                if(!load_ambdec_matrix(conf->HFOrderGain, conf->HFMatrix, conf->NumSpeakers,
+                                       f, &buffer, &maxlen, &saveptr))
+                    goto fail;
+            }
+            else
+            {
+                if(strcmp(command, "lfmatrix") == 0)
+                {
+                    if(!load_ambdec_matrix(conf->LFOrderGain, conf->LFMatrix, conf->NumSpeakers,
+                                           f, &buffer, &maxlen, &saveptr))
+                        goto fail;
+                }
+                else if(strcmp(command, "hfmatrix") == 0)
+                {
+                    if(!load_ambdec_matrix(conf->HFOrderGain, conf->HFMatrix, conf->NumSpeakers,
+                                           f, &buffer, &maxlen, &saveptr))
+                        goto fail;
+                }
+                else
+                {
+                    ERR("Unexpected \"%s\" type for a dual-band decoder\n", command);
+                    goto fail;
+                }
+            }
+            value = my_strtok_r(NULL, "/ \t", &saveptr);
+            if(!value)
+            {
+                line = read_clipped_line(f, &buffer, &maxlen);
+                if(!line)
+                {
+                    ERR("Unexpected end of file\n");
+                    goto fail;
+                }
+                value = my_strtok_r(line, "/ \t", &saveptr);
+            }
+            if(strcmp(value, "}") != 0)
+            {
+                ERR("Expected } after matrix definitions, got %s\n", value);
+                goto fail;
+            }
+        }
+        else if(strcmp(command, "end") == 0)
+        {
+            line = my_strtok_r(NULL, "/ \t", &saveptr);
+            if(line)
+            {
+                ERR("Unexpected junk on end: %s\n", line);
+                goto fail;
+            }
+
+            fclose(f);
+            free(buffer);
+            return 1;
+        }
+        else
+        {
+            ERR("Unexpected command: %s\n", command);
+            goto fail;
+        }
+
+        line = my_strtok_r(NULL, "/ \t", &saveptr);
+        if(line)
+        {
+            ERR("Unexpected junk on line: %s\n", line);
+            goto fail;
+        }
+    }
+    ERR("Unexpected end of file\n");
+
+fail:
+    fclose(f);
+    free(buffer);
+    return 0;
+}

+ 46 - 0
love/src/jni/openal-soft-1.18.2/Alc/ambdec.h

@@ -0,0 +1,46 @@
+#ifndef AMBDEC_H
+#define AMBDEC_H
+
+#include "alstring.h"
+#include "alMain.h"
+
+/* Helpers to read .ambdec configuration files. */
+
+enum AmbDecScaleType {
+    ADS_N3D,
+    ADS_SN3D,
+    ADS_FuMa,
+};
+typedef struct AmbDecConf {
+    al_string Description;
+    ALuint Version; /* Must be 3 */
+
+    ALuint ChanMask;
+    ALuint FreqBands; /* Must be 1 or 2 */
+    ALsizei NumSpeakers;
+    enum AmbDecScaleType CoeffScale;
+
+    ALfloat XOverFreq;
+    ALfloat XOverRatio;
+
+    struct {
+        al_string Name;
+        ALfloat Distance;
+        ALfloat Azimuth;
+        ALfloat Elevation;
+        al_string Connection;
+    } Speakers[MAX_OUTPUT_CHANNELS];
+
+    /* Unused when FreqBands == 1 */
+    ALfloat LFOrderGain[MAX_AMBI_ORDER+1];
+    ALfloat LFMatrix[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
+
+    ALfloat HFOrderGain[MAX_AMBI_ORDER+1];
+    ALfloat HFMatrix[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
+} AmbDecConf;
+
+void ambdec_init(AmbDecConf *conf);
+void ambdec_deinit(AmbDecConf *conf);
+int ambdec_load(AmbDecConf *conf, const char *fname);
+
+#endif /* AMBDEC_H */

+ 142 - 92
love/src/jni/openal-soft-1.17.0/Alc/backends/alsa.c → love/src/jni/openal-soft-1.18.2/Alc/backends/alsa.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -199,15 +199,21 @@ static ALCboolean alsa_load(void)
 #ifdef HAVE_DYNLOAD
     if(!alsa_handle)
     {
+        al_string missing_funcs = AL_STRING_INIT_STATIC();
+
         alsa_handle = LoadLib("libasound.so.2");
         if(!alsa_handle)
+        {
+            WARN("Failed to load %s\n", "libasound.so.2");
             return ALC_FALSE;
+        }
 
         error = ALC_FALSE;
 #define LOAD_FUNC(f) do {                                                     \
     p##f = GetSymbol(alsa_handle, #f);                                        \
     if(p##f == NULL) {                                                        \
         error = ALC_TRUE;                                                     \
+        alstr_append_cstr(&missing_funcs, "\n" #f);                           \
     }                                                                         \
 } while(0)
         ALSA_FUNCS(LOAD_FUNC);
@@ -215,10 +221,11 @@ static ALCboolean alsa_load(void)
 
         if(error)
         {
+            WARN("Missing expected functions:%s\n", alstr_get_cstr(missing_funcs));
             CloseLib(alsa_handle);
             alsa_handle = NULL;
-            return ALC_FALSE;
         }
+        alstr_reset(&missing_funcs);
     }
 #endif
 
@@ -237,16 +244,13 @@ static vector_DevMap CaptureDevices;
 
 static void clear_devlist(vector_DevMap *devlist)
 {
-    DevMap *iter, *end;
-
-    iter = VECTOR_ITER_BEGIN(*devlist);
-    end = VECTOR_ITER_END(*devlist);
-    for(;iter != end;iter++)
-    {
-        AL_STRING_DEINIT(iter->name);
-        AL_STRING_DEINIT(iter->device_name);
-    }
-    VECTOR_RESIZE(*devlist, 0);
+#define FREE_DEV(i) do {                                                      \
+    AL_STRING_DEINIT((i)->name);                                              \
+    AL_STRING_DEINIT((i)->device_name);                                       \
+} while(0)
+    VECTOR_FOR_EACH(DevMap, *devlist, FREE_DEV);
+    VECTOR_RESIZE(*devlist, 0, 0);
+#undef FREE_DEV
 }
 
 
@@ -272,15 +276,49 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
 
     AL_STRING_INIT(entry.name);
     AL_STRING_INIT(entry.device_name);
-    al_string_copy_cstr(&entry.name, alsaDevice);
-    al_string_copy_cstr(&entry.device_name, GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ?
-                                                           "device" : "capture", "default"));
+    alstr_copy_cstr(&entry.name, alsaDevice);
+    alstr_copy_cstr(&entry.device_name, GetConfigValue(
+        NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? "device" : "capture", "default"
+    ));
     VECTOR_PUSH_BACK(*DeviceList, entry);
 
+    if(stream == SND_PCM_STREAM_PLAYBACK)
+    {
+        const char *customdevs, *sep, *next;
+        next = GetConfigValue(NULL, "alsa", "custom-devices", "");
+        while((customdevs=next) != NULL && customdevs[0])
+        {
+            next = strchr(customdevs, ';');
+            sep = strchr(customdevs, '=');
+            if(!sep)
+            {
+                al_string spec = AL_STRING_INIT_STATIC();
+                if(next)
+                    alstr_copy_range(&spec, customdevs, next++);
+                else
+                    alstr_copy_cstr(&spec, customdevs);
+                ERR("Invalid ALSA device specification \"%s\"\n", alstr_get_cstr(spec));
+                alstr_reset(&spec);
+                continue;
+            }
+
+            AL_STRING_INIT(entry.name);
+            AL_STRING_INIT(entry.device_name);
+            alstr_copy_range(&entry.name, customdevs, sep++);
+            if(next)
+                alstr_copy_range(&entry.device_name, sep, next++);
+            else
+                alstr_copy_cstr(&entry.device_name, sep);
+            TRACE("Got device \"%s\", \"%s\"\n", alstr_get_cstr(entry.name),
+                  alstr_get_cstr(entry.device_name));
+            VECTOR_PUSH_BACK(*DeviceList, entry);
+        }
+    }
+
     card = -1;
     if((err=snd_card_next(&card)) < 0)
         ERR("Failed to find a card: %s\n", snd_strerror(err));
-    ConfigValueStr("alsa", prefix_name(stream), &main_prefix);
+    ConfigValueStr(NULL, "alsa", prefix_name(stream), &main_prefix);
     while(card >= 0)
     {
         const char *card_prefix = main_prefix;
@@ -304,7 +342,7 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
         cardid = snd_ctl_card_info_get_id(info);
 
         snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid);
-        ConfigValueStr("alsa", name, &card_prefix);
+        ConfigValueStr(NULL, "alsa", name, &card_prefix);
 
         dev = -1;
         while(1)
@@ -321,7 +359,8 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
             snd_pcm_info_set_device(pcminfo, dev);
             snd_pcm_info_set_subdevice(pcminfo, 0);
             snd_pcm_info_set_stream(pcminfo, stream);
-            if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
+            if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0)
+            {
                 if(err != -ENOENT)
                     ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err));
                 continue;
@@ -330,18 +369,18 @@ static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList)
             devname = snd_pcm_info_get_name(pcminfo);
 
             snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev);
-            ConfigValueStr("alsa", name, &device_prefix);
+            ConfigValueStr(NULL, "alsa", name, &device_prefix);
 
             snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)",
-                        cardname, devname, cardid, dev);
+                     cardname, devname, cardid, dev);
             snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d",
-                        device_prefix, cardid, dev);
+                     device_prefix, cardid, dev);
 
             TRACE("Got device \"%s\", \"%s\"\n", name, device);
             AL_STRING_INIT(entry.name);
             AL_STRING_INIT(entry.device_name);
-            al_string_copy_cstr(&entry.name, name);
-            al_string_copy_cstr(&entry.device_name, device);
+            alstr_copy_cstr(&entry.name, name);
+            alstr_copy_cstr(&entry.device_name, device);
             VECTOR_PUSH_BACK(*DeviceList, entry);
         }
         snd_ctl_close(handle);
@@ -413,7 +452,7 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self);
 static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self);
 static DECLARE_FORWARD2(ALCplaybackAlsa, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
 static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, ALCuint, availableSamples)
-static ALint64 ALCplaybackAlsa_getLatency(ALCplaybackAlsa *self);
+static ClockLatency ALCplaybackAlsa_getClockLatency(ALCplaybackAlsa *self);
 static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCplaybackAlsa)
@@ -588,7 +627,9 @@ static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr)
             {
             case -EAGAIN:
                 continue;
+#if ESTRPIPE != EPIPE
             case -ESTRPIPE:
+#endif
             case -EPIPE:
             case -EINTR:
                 ret = snd_pcm_recover(self->pcmHandle, ret, 1);
@@ -630,17 +671,17 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name)
         if(VECTOR_SIZE(PlaybackDevices) == 0)
             probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices);
 
-#define MATCH_NAME(i)  (al_string_cmp_cstr((i)->name, name) == 0)
+#define MATCH_NAME(i)  (alstr_cmp_cstr((i)->name, name) == 0)
         VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
 #undef MATCH_NAME
-        if(iter == VECTOR_ITER_END(PlaybackDevices))
+        if(iter == VECTOR_END(PlaybackDevices))
             return ALC_INVALID_VALUE;
-        driver = al_string_get_cstr(iter->device_name);
+        driver = alstr_get_cstr(iter->device_name);
     }
     else
     {
         name = alsaDevice;
-        driver = GetConfigValue("alsa", "device", "default");
+        driver = GetConfigValue(NULL, "alsa", "device", "default");
     }
 
     TRACE("Opening device \"%s\"\n", driver);
@@ -654,7 +695,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name)
     /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */
     snd_config_update_free_global();
 
-    al_string_copy_cstr(&device->DeviceName, name);
+    alstr_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 }
@@ -677,6 +718,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
     unsigned int rate;
     const char *funcerr;
     int allowmmap;
+    int dir;
     int err;
 
     switch(device->FmtType)
@@ -704,7 +746,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
             break;
     }
 
-    allowmmap = GetConfigValueBool("alsa", "mmap", 1);
+    allowmmap = GetConfigValueBool(alstr_get_cstr(device->DeviceName), "alsa", "mmap", 1);
     periods = device->NumUpdates;
     periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency;
     bufferLen = periodLen * periods;
@@ -748,7 +790,7 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
     }
     CHECK(snd_pcm_hw_params_set_format(self->pcmHandle, hp, format));
     /* test and set channels (implicitly sets frame bits) */
-    if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)) < 0)
+    if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder)) < 0)
     {
         static const enum DevFmtChannels channellist[] = {
             DevFmtStereo,
@@ -761,17 +803,24 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
 
         for(k = 0;k < COUNTOF(channellist);k++)
         {
-            if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(channellist[k])) >= 0)
+            if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(channellist[k], 0)) >= 0)
             {
                 device->FmtChans = channellist[k];
+                device->AmbiOrder = 0;
                 break;
             }
         }
     }
-    CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)));
+    CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder)));
     /* set rate (implicitly constrains period/buffer parameters) */
-    if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 0) < 0)
-        ERR("Failed to disable ALSA resampler\n");
+    if(!GetConfigValueBool(alstr_get_cstr(device->DeviceName), "alsa", "allow-resampler", 0) ||
+       !(device->Flags&DEVICE_FREQUENCY_REQUEST))
+    {
+        if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 0) < 0)
+            ERR("Failed to disable ALSA resampler\n");
+    }
+    else if(snd_pcm_hw_params_set_rate_resample(self->pcmHandle, hp, 1) < 0)
+        ERR("Failed to enable ALSA resampler\n");
     CHECK(snd_pcm_hw_params_set_rate_near(self->pcmHandle, hp, &rate, NULL));
     /* set buffer time (implicitly constrains period/buffer parameters) */
     if((err=snd_pcm_hw_params_set_buffer_time_near(self->pcmHandle, hp, &bufferLen, NULL)) < 0)
@@ -784,7 +833,9 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self)
     /* retrieve configuration info */
     CHECK(snd_pcm_hw_params_get_access(hp, &access));
     CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL));
-    CHECK(snd_pcm_hw_params_get_periods(hp, &periods, NULL));
+    CHECK(snd_pcm_hw_params_get_periods(hp, &periods, &dir));
+    if(dir != 0)
+        WARN("Inexact period count: %u (%d)\n", periods, dir);
 
     snd_pcm_hw_params_free(hp);
     hp = NULL;
@@ -834,7 +885,7 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self)
     self->size = snd_pcm_frames_to_bytes(self->pcmHandle, device->UpdateSize);
     if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
     {
-        self->buffer = malloc(self->size);
+        self->buffer = al_malloc(16, self->size);
         if(!self->buffer)
         {
             ERR("buffer malloc failed\n");
@@ -856,7 +907,7 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self)
     if(althrd_create(&self->thread, thread_func, self) != althrd_success)
     {
         ERR("Could not create playback thread\n");
-        free(self->buffer);
+        al_free(self->buffer);
         self->buffer = NULL;
         return ALC_FALSE;
     }
@@ -879,22 +930,29 @@ static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self)
     self->killNow = 1;
     althrd_join(self->thread, &res);
 
-    free(self->buffer);
+    al_free(self->buffer);
     self->buffer = NULL;
 }
 
-static ALint64 ALCplaybackAlsa_getLatency(ALCplaybackAlsa *self)
+static ClockLatency ALCplaybackAlsa_getClockLatency(ALCplaybackAlsa *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     snd_pcm_sframes_t delay = 0;
+    ClockLatency ret;
     int err;
 
+    ALCplaybackAlsa_lock(self);
+    ret.ClockTime = GetDeviceClockTime(device);
     if((err=snd_pcm_delay(self->pcmHandle, &delay)) < 0)
     {
         ERR("Failed to get pcm delay: %s\n", snd_strerror(err));
-        return 0;
+        delay = 0;
     }
-    return maxi64((ALint64)delay*1000000000/device->Frequency, 0);
+    if(delay < 0) delay = 0;
+    ret.Latency = delay * DEVICE_CLOCK_RES / device->Frequency;
+    ALCplaybackAlsa_unlock(self);
+
+    return ret;
 }
 
 
@@ -907,7 +965,7 @@ typedef struct ALCcaptureAlsa {
     ALsizei size;
 
     ALboolean doCapture;
-    RingBuffer *ring;
+    ll_ringbuffer_t *ring;
 
     snd_pcm_sframes_t last_avail;
 } ALCcaptureAlsa;
@@ -921,7 +979,7 @@ static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self);
 static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self);
 static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buffer, ALCuint samples);
 static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self);
-static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self);
+static ClockLatency ALCcaptureAlsa_getClockLatency(ALCcaptureAlsa *self);
 static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCcaptureAlsa)
@@ -955,17 +1013,17 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
         if(VECTOR_SIZE(CaptureDevices) == 0)
             probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices);
 
-#define MATCH_NAME(i)  (al_string_cmp_cstr((i)->name, name) == 0)
+#define MATCH_NAME(i)  (alstr_cmp_cstr((i)->name, name) == 0)
         VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
 #undef MATCH_NAME
-        if(iter == VECTOR_ITER_END(CaptureDevices))
+        if(iter == VECTOR_END(CaptureDevices))
             return ALC_INVALID_VALUE;
-        driver = al_string_get_cstr(iter->device_name);
+        driver = alstr_get_cstr(iter->device_name);
     }
     else
     {
         name = alsaDevice;
-        driver = GetConfigValue("alsa", "capture", "default");
+        driver = GetConfigValue(NULL, "alsa", "capture", "default");
     }
 
     TRACE("Opening device \"%s\"\n", driver);
@@ -1017,7 +1075,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
     /* set format (implicitly sets sample bits) */
     CHECK(snd_pcm_hw_params_set_format(self->pcmHandle, hp, format));
     /* set channels (implicitly sets frame bits) */
-    CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans)));
+    CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder)));
     /* set rate (implicitly constrains period/buffer parameters) */
     CHECK(snd_pcm_hw_params_set_rate(self->pcmHandle, hp, device->Frequency, 0));
     /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */
@@ -1039,24 +1097,18 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name)
 
     if(needring)
     {
-        self->ring = CreateRingBuffer(FrameSizeFromDevFmt(device->FmtChans, device->FmtType),
-                                      device->UpdateSize*device->NumUpdates);
+        self->ring = ll_ringbuffer_create(
+            device->UpdateSize*device->NumUpdates + 1,
+            FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
+        );
         if(!self->ring)
         {
             ERR("ring buffer create failed\n");
             goto error2;
         }
-
-        self->size = snd_pcm_frames_to_bytes(self->pcmHandle, periodSizeInFrames);
-        self->buffer = malloc(self->size);
-        if(!self->buffer)
-        {
-            ERR("buffer malloc failed\n");
-            goto error2;
-        }
     }
 
-    al_string_copy_cstr(&device->DeviceName, name);
+    alstr_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 
@@ -1065,9 +1117,7 @@ error:
     if(hp) snd_pcm_hw_params_free(hp);
 
 error2:
-    free(self->buffer);
-    self->buffer = NULL;
-    DestroyRingBuffer(self->ring);
+    ll_ringbuffer_free(self->ring);
     self->ring = NULL;
     snd_pcm_close(self->pcmHandle);
 
@@ -1077,9 +1127,9 @@ error2:
 static void ALCcaptureAlsa_close(ALCcaptureAlsa *self)
 {
     snd_pcm_close(self->pcmHandle);
-    DestroyRingBuffer(self->ring);
+    ll_ringbuffer_free(self->ring);
 
-    free(self->buffer);
+    al_free(self->buffer);
     self->buffer = NULL;
 }
 
@@ -1114,11 +1164,11 @@ static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self)
         void *ptr;
 
         size = snd_pcm_frames_to_bytes(self->pcmHandle, avail);
-        ptr = malloc(size);
+        ptr = al_malloc(16, size);
         if(ptr)
         {
             ALCcaptureAlsa_captureSamples(self, ptr, avail);
-            free(self->buffer);
+            al_free(self->buffer);
             self->buffer = ptr;
             self->size = size;
         }
@@ -1135,7 +1185,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff
 
     if(self->ring)
     {
-        ReadRingBuffer(self->ring, buffer, samples);
+        ll_ringbuffer_read(self->ring, buffer, samples);
         return ALC_NO_ERROR;
     }
 
@@ -1160,7 +1210,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff
             }
             else
             {
-                free(self->buffer);
+                al_free(self->buffer);
                 self->buffer = NULL;
                 self->size = 0;
             }
@@ -1238,12 +1288,15 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self)
 
     while(avail > 0)
     {
+        ll_ringbuffer_data_t vec[2];
         snd_pcm_sframes_t amt;
 
-        amt = snd_pcm_bytes_to_frames(self->pcmHandle, self->size);
-        if(avail < amt) amt = avail;
+        ll_ringbuffer_get_write_vector(self->ring, vec);
+        if(vec[0].len == 0) break;
 
-        amt = snd_pcm_readi(self->pcmHandle, self->buffer, amt);
+        amt = (vec[0].len < (snd_pcm_uframes_t)avail) ?
+              vec[0].len : (snd_pcm_uframes_t)avail;
+        amt = snd_pcm_readi(self->pcmHandle, vec[0].buf, amt);
         if(amt < 0)
         {
             ERR("read error: %s\n", snd_strerror(amt));
@@ -1267,32 +1320,39 @@ static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self)
             continue;
         }
 
-        WriteRingBuffer(self->ring, self->buffer, amt);
+        ll_ringbuffer_write_advance(self->ring, amt);
         avail -= amt;
     }
 
-    return RingBufferSize(self->ring);
+    return ll_ringbuffer_read_space(self->ring);
 }
 
-static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self)
+static ClockLatency ALCcaptureAlsa_getClockLatency(ALCcaptureAlsa *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
     snd_pcm_sframes_t delay = 0;
+    ClockLatency ret;
     int err;
 
+    ALCcaptureAlsa_lock(self);
+    ret.ClockTime = GetDeviceClockTime(device);
     if((err=snd_pcm_delay(self->pcmHandle, &delay)) < 0)
     {
         ERR("Failed to get pcm delay: %s\n", snd_strerror(err));
-        return 0;
+        delay = 0;
     }
-    return maxi64((ALint64)delay*1000000000/device->Frequency, 0);
+    if(delay < 0) delay = 0;
+    ret.Latency = delay * DEVICE_CLOCK_RES / device->Frequency;
+    ALCcaptureAlsa_unlock(self);
+
+    return ret;
 }
 
 
 static inline void AppendAllDevicesList2(const DevMap *entry)
-{ AppendAllDevicesList(al_string_get_cstr(entry->name)); }
+{ AppendAllDevicesList(alstr_get_cstr(entry->name)); }
 static inline void AppendCaptureDeviceList2(const DevMap *entry)
-{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); }
+{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); }
 
 typedef struct ALCalsaBackendFactory {
     DERIVE_FROM_TYPE(ALCbackendFactory);
@@ -1352,25 +1412,15 @@ static ALCbackend* ALCalsaBackendFactory_createBackend(ALCalsaBackendFactory* UN
     if(type == ALCbackend_Playback)
     {
         ALCplaybackAlsa *backend;
-
-        backend = ALCplaybackAlsa_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCplaybackAlsa)(device);
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCplaybackAlsa_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
     }
     if(type == ALCbackend_Capture)
     {
         ALCcaptureAlsa *backend;
-
-        backend = ALCcaptureAlsa_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCcaptureAlsa)(device);
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCcaptureAlsa_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
     }
 

+ 81 - 0
love/src/jni/openal-soft-1.18.2/Alc/backends/base.c

@@ -0,0 +1,81 @@
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include "alMain.h"
+#include "alu.h"
+
+#include "backends/base.h"
+
+
+extern inline ALuint64 GetDeviceClockTime(ALCdevice *device);
+
+/* Base ALCbackend method implementations. */
+void ALCbackend_Construct(ALCbackend *self, ALCdevice *device)
+{
+    int ret = almtx_init(&self->mMutex, almtx_recursive);
+    assert(ret == althrd_success);
+    self->mDevice = device;
+}
+
+void ALCbackend_Destruct(ALCbackend *self)
+{
+    almtx_destroy(&self->mMutex);
+}
+
+ALCboolean ALCbackend_reset(ALCbackend* UNUSED(self))
+{
+    return ALC_FALSE;
+}
+
+ALCenum ALCbackend_captureSamples(ALCbackend* UNUSED(self), void* UNUSED(buffer), ALCuint UNUSED(samples))
+{
+    return ALC_INVALID_DEVICE;
+}
+
+ALCuint ALCbackend_availableSamples(ALCbackend* UNUSED(self))
+{
+    return 0;
+}
+
+ClockLatency ALCbackend_getClockLatency(ALCbackend *self)
+{
+    ALCdevice *device = self->mDevice;
+    ALuint refcount;
+    ClockLatency ret;
+
+    do {
+        while(((refcount=ATOMIC_LOAD(&device->MixCount, almemory_order_acquire))&1))
+            althrd_yield();
+        ret.ClockTime = GetDeviceClockTime(device);
+        ATOMIC_THREAD_FENCE(almemory_order_acquire);
+    } while(refcount != ATOMIC_LOAD(&device->MixCount, almemory_order_relaxed));
+
+    /* NOTE: The device will generally have about all but one periods filled at
+     * any given time during playback. Without a more accurate measurement from
+     * the output, this is an okay approximation.
+     */
+    ret.Latency = device->UpdateSize * DEVICE_CLOCK_RES / device->Frequency *
+                  maxu(device->NumUpdates-1, 1);
+
+    return ret;
+}
+
+void ALCbackend_lock(ALCbackend *self)
+{
+    int ret = almtx_lock(&self->mMutex);
+    assert(ret == althrd_success);
+}
+
+void ALCbackend_unlock(ALCbackend *self)
+{
+    int ret = almtx_unlock(&self->mMutex);
+    assert(ret == althrd_success);
+}
+
+
+/* Base ALCbackendFactory method implementations. */
+void ALCbackendFactory_deinit(ALCbackendFactory* UNUSED(self))
+{
+}

+ 28 - 6
love/src/jni/openal-soft-1.17.0/Alc/backends/base.h → love/src/jni/openal-soft-1.18.2/Alc/backends/base.h

@@ -5,6 +5,21 @@
 #include "threads.h"
 
 
+typedef struct ClockLatency {
+    ALint64 ClockTime;
+    ALint64 Latency;
+} ClockLatency;
+
+/* Helper to get the current clock time from the device's ClockBase, and
+ * SamplesDone converted from the sample rate.
+ */
+inline ALuint64 GetDeviceClockTime(ALCdevice *device)
+{
+    return device->ClockBase + (device->SamplesDone * DEVICE_CLOCK_RES /
+                                device->Frequency);
+}
+
+
 struct ALCbackendVtable;
 
 typedef struct ALCbackend {
@@ -20,7 +35,7 @@ void ALCbackend_Destruct(ALCbackend *self);
 ALCboolean ALCbackend_reset(ALCbackend *self);
 ALCenum ALCbackend_captureSamples(ALCbackend *self, void *buffer, ALCuint samples);
 ALCuint ALCbackend_availableSamples(ALCbackend *self);
-ALint64 ALCbackend_getLatency(ALCbackend *self);
+ClockLatency ALCbackend_getClockLatency(ALCbackend *self);
 void ALCbackend_lock(ALCbackend *self);
 void ALCbackend_unlock(ALCbackend *self);
 
@@ -37,7 +52,7 @@ struct ALCbackendVtable {
     ALCenum (*const captureSamples)(ALCbackend*, void*, ALCuint);
     ALCuint (*const availableSamples)(ALCbackend*);
 
-    ALint64 (*const getLatency)(ALCbackend*);
+    ClockLatency (*const getClockLatency)(ALCbackend*);
 
     void (*const lock)(ALCbackend*);
     void (*const unlock)(ALCbackend*);
@@ -54,7 +69,7 @@ DECLARE_THUNK(T, ALCbackend, ALCboolean, start)                               \
 DECLARE_THUNK(T, ALCbackend, void, stop)                                      \
 DECLARE_THUNK2(T, ALCbackend, ALCenum, captureSamples, void*, ALCuint)        \
 DECLARE_THUNK(T, ALCbackend, ALCuint, availableSamples)                       \
-DECLARE_THUNK(T, ALCbackend, ALint64, getLatency)                             \
+DECLARE_THUNK(T, ALCbackend, ClockLatency, getClockLatency)                   \
 DECLARE_THUNK(T, ALCbackend, void, lock)                                      \
 DECLARE_THUNK(T, ALCbackend, void, unlock)                                    \
 static void T##_ALCbackend_Delete(void *ptr)                                  \
@@ -70,7 +85,7 @@ static const struct ALCbackendVtable T##_ALCbackend_vtable = {                \
     T##_ALCbackend_stop,                                                      \
     T##_ALCbackend_captureSamples,                                            \
     T##_ALCbackend_availableSamples,                                          \
-    T##_ALCbackend_getLatency,                                                \
+    T##_ALCbackend_getClockLatency,                                           \
     T##_ALCbackend_lock,                                                      \
     T##_ALCbackend_unlock,                                                    \
                                                                               \
@@ -122,12 +137,19 @@ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = {  \
 
 ALCbackendFactory *ALCpulseBackendFactory_getFactory(void);
 ALCbackendFactory *ALCalsaBackendFactory_getFactory(void);
+ALCbackendFactory *ALCcoreAudioBackendFactory_getFactory(void);
 ALCbackendFactory *ALCossBackendFactory_getFactory(void);
+ALCbackendFactory *ALCjackBackendFactory_getFactory(void);
+ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void);
+ALCbackendFactory *ALCsndioBackendFactory_getFactory(void);
+ALCbackendFactory *ALCqsaBackendFactory_getFactory(void);
 ALCbackendFactory *ALCmmdevBackendFactory_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 *ALCloopbackFactory_getFactory(void);
 
-ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type);
-
 #endif /* AL_BACKENDS_BASE_H */

+ 309 - 188
love/src/jni/openal-soft-1.17.0/Alc/backends/coreaudio.c → love/src/jni/openal-soft-1.18.2/Alc/backends/coreaudio.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -33,6 +33,8 @@
 #include <AudioUnit/AudioUnit.h>
 #include <AudioToolbox/AudioToolbox.h>
 
+#include "backends/base.h"
+
 
 typedef struct {
     AudioUnit audioUnit;
@@ -45,23 +47,12 @@ typedef struct {
     AudioBufferList *bufferList;           // Buffer for data coming from the input device
     ALCvoid *resampleBuffer;               // Buffer for returned RingBuffer data when resampling
 
-    RingBuffer *ring;
+    ll_ringbuffer_t *ring;
 } ca_data;
 
 static const ALCchar ca_device[] = "CoreAudio Default";
 
 
-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);
-    }
-}
-
 static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSize)
 {
     AudioBufferList *list;
@@ -83,68 +74,85 @@ static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSiz
     return list;
 }
 
-static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp,
-                            UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData)
+static void destroy_buffer_list(AudioBufferList* list)
 {
-    ALCdevice *device = (ALCdevice*)inRefCon;
-    ca_data *data = (ca_data*)device->ExtraData;
-
-    aluMixData(device, ioData->mBuffers[0].mData,
-               ioData->mBuffers[0].mDataByteSize / data->frameSize);
-
-    return noErr;
+    if(list)
+    {
+        UInt32 i;
+        for(i = 0;i < list->mNumberBuffers;i++)
+            free(list->mBuffers[i].mData);
+        free(list);
+    }
 }
 
-static OSStatus ca_capture_conversion_callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets,
-        AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void* inUserData)
-{
-    ALCdevice *device = (ALCdevice*)inUserData;
-    ca_data *data = (ca_data*)device->ExtraData;
 
-    // Read from the ring buffer and store temporarily in a large buffer
-    ReadRingBuffer(data->ring, data->resampleBuffer, (ALsizei)(*ioNumberDataPackets));
+typedef struct ALCcoreAudioPlayback {
+    DERIVE_FROM_TYPE(ALCbackend);
 
-    // Set the input data
-    ioData->mNumberBuffers = 1;
-    ioData->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame;
-    ioData->mBuffers[0].mData = data->resampleBuffer;
-    ioData->mBuffers[0].mDataByteSize = (*ioNumberDataPackets) * data->format.mBytesPerFrame;
+    AudioUnit audioUnit;
 
-    return noErr;
+    ALuint frameSize;
+    AudioStreamBasicDescription format;    // This is the OpenAL format as a CoreAudio ASBD
+} 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);
+static DECLARE_FORWARD2(ALCcoreAudioPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCcoreAudioPlayback, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCcoreAudioPlayback, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCcoreAudioPlayback, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCcoreAudioPlayback, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioPlayback)
+
+DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioPlayback);
+
+
+static void ALCcoreAudioPlayback_Construct(ALCcoreAudioPlayback *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCcoreAudioPlayback, ALCbackend, self);
+
+    self->frameSize = 0;
+    memset(&self->format, 0, sizeof(self->format));
 }
 
-static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags,
-                                    const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
-                                    UInt32 inNumberFrames, AudioBufferList *ioData)
+static void ALCcoreAudioPlayback_Destruct(ALCcoreAudioPlayback *self)
 {
-    ALCdevice *device = (ALCdevice*)inRefCon;
-    ca_data *data = (ca_data*)device->ExtraData;
-    AudioUnitRenderActionFlags flags = 0;
-    OSStatus err;
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
 
-    // fill the bufferList with data from the input device
-    err = AudioUnitRender(data->audioUnit, &flags, inTimeStamp, 1, inNumberFrames, data->bufferList);
-    if(err != noErr)
-    {
-        ERR("AudioUnitRender error: %d\n", err);
-        return err;
-    }
 
-    WriteRingBuffer(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames);
+static OSStatus ALCcoreAudioPlayback_MixerProc(void *inRefCon,
+  AudioUnitRenderActionFlags* UNUSED(ioActionFlags), const AudioTimeStamp* UNUSED(inTimeStamp),
+  UInt32 UNUSED(inBusNumber), UInt32 UNUSED(inNumberFrames), AudioBufferList *ioData)
+{
+    ALCcoreAudioPlayback *self = inRefCon;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+
+    ALCdevice_Lock(device);
+    aluMixData(device, ioData->mBuffers[0].mData,
+               ioData->mBuffers[0].mDataByteSize / self->frameSize);
+    ALCdevice_Unlock(device);
 
     return noErr;
 }
 
-static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
+
+static ALCenum ALCcoreAudioPlayback_open(ALCcoreAudioPlayback *self, const ALCchar *name)
 {
-    ComponentDescription desc;
-    Component comp;
-    ca_data *data;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    AudioComponentDescription desc;
+    AudioComponent comp;
     OSStatus err;
 
-    if(!deviceName)
-        deviceName = ca_device;
-    else if(strcmp(deviceName, ca_device) != 0)
+    if(!name)
+        name = ca_device;
+    else if(strcmp(name, ca_device) != 0)
         return ALC_INVALID_VALUE;
 
     /* open the default output unit */
@@ -154,64 +162,54 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName)
     desc.componentFlags = 0;
     desc.componentFlagsMask = 0;
 
-    comp = FindNextComponent(NULL, &desc);
+    comp = AudioComponentFindNext(NULL, &desc);
     if(comp == NULL)
     {
-        ERR("FindNextComponent failed\n");
+        ERR("AudioComponentFindNext failed\n");
         return ALC_INVALID_VALUE;
     }
 
-    data = calloc(1, sizeof(*data));
-
-    err = OpenAComponent(comp, &data->audioUnit);
+    err = AudioComponentInstanceNew(comp, &self->audioUnit);
     if(err != noErr)
     {
-        ERR("OpenAComponent failed\n");
-        free(data);
+        ERR("AudioComponentInstanceNew failed\n");
         return ALC_INVALID_VALUE;
     }
 
     /* init and start the default audio unit... */
-    err = AudioUnitInitialize(data->audioUnit);
+    err = AudioUnitInitialize(self->audioUnit);
     if(err != noErr)
     {
         ERR("AudioUnitInitialize failed\n");
-        CloseComponent(data->audioUnit);
-        free(data);
+        AudioComponentInstanceDispose(self->audioUnit);
         return ALC_INVALID_VALUE;
     }
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-    device->ExtraData = data;
+    alstr_copy_cstr(&device->DeviceName, name);
     return ALC_NO_ERROR;
 }
 
-static void ca_close_playback(ALCdevice *device)
+static void ALCcoreAudioPlayback_close(ALCcoreAudioPlayback *self)
 {
-    ca_data *data = (ca_data*)device->ExtraData;
-
-    AudioUnitUninitialize(data->audioUnit);
-    CloseComponent(data->audioUnit);
-
-    free(data);
-    device->ExtraData = NULL;
+    AudioUnitUninitialize(self->audioUnit);
+    AudioComponentInstanceDispose(self->audioUnit);
 }
 
-static ALCboolean ca_reset_playback(ALCdevice *device)
+static ALCboolean ALCcoreAudioPlayback_reset(ALCcoreAudioPlayback *self)
 {
-    ca_data *data = (ca_data*)device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
     AudioStreamBasicDescription streamFormat;
     AURenderCallbackStruct input;
     OSStatus err;
     UInt32 size;
 
-    err = AudioUnitUninitialize(data->audioUnit);
+    err = AudioUnitUninitialize(self->audioUnit);
     if(err != noErr)
         ERR("-- AudioUnitUninitialize failed.\n");
 
     /* retrieve default output unit's properties (output side) */
     size = sizeof(AudioStreamBasicDescription);
-    err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size);
+    err = AudioUnitGetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size);
     if(err != noErr || size != sizeof(AudioStreamBasicDescription))
     {
         ERR("AudioUnitGetProperty failed\n");
@@ -229,7 +227,7 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
 #endif
 
     /* set default output unit's input side to match output side */
-    err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size);
+    err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size);
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed\n");
@@ -238,7 +236,7 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
 
     if(device->Frequency != streamFormat.mSampleRate)
     {
-        device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
+        device->NumUpdates = (ALuint)((ALuint64)device->NumUpdates *
                                       streamFormat.mSampleRate /
                                       device->Frequency);
         device->Frequency = streamFormat.mSampleRate;
@@ -313,7 +311,7 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
     streamFormat.mFormatFlags |= kAudioFormatFlagsNativeEndian |
                                  kLinearPCMFormatFlagIsPacked;
 
-    err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription));
+    err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription));
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed\n");
@@ -321,11 +319,11 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
     }
 
     /* setup callback */
-    data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
-    input.inputProc = ca_callback;
-    input.inputProcRefCon = device;
+    self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+    input.inputProc = ALCcoreAudioPlayback_MixerProc;
+    input.inputProcRefCon = self;
 
-    err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct));
+    err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct));
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed\n");
@@ -333,7 +331,7 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
     }
 
     /* init the default audio unit... */
-    err = AudioUnitInitialize(data->audioUnit);
+    err = AudioUnitInitialize(self->audioUnit);
     if(err != noErr)
     {
         ERR("AudioUnitInitialize failed\n");
@@ -343,12 +341,9 @@ static ALCboolean ca_reset_playback(ALCdevice *device)
     return ALC_TRUE;
 }
 
-static ALCboolean ca_start_playback(ALCdevice *device)
+static ALCboolean ALCcoreAudioPlayback_start(ALCcoreAudioPlayback *self)
 {
-    ca_data *data = (ca_data*)device->ExtraData;
-    OSStatus err;
-
-    err = AudioOutputUnitStart(data->audioUnit);
+    OSStatus err = AudioOutputUnitStart(self->audioUnit);
     if(err != noErr)
     {
         ERR("AudioOutputUnitStart failed\n");
@@ -358,31 +353,125 @@ static ALCboolean ca_start_playback(ALCdevice *device)
     return ALC_TRUE;
 }
 
-static void ca_stop_playback(ALCdevice *device)
+static void ALCcoreAudioPlayback_stop(ALCcoreAudioPlayback *self)
+{
+    OSStatus err = AudioOutputUnitStop(self->audioUnit);
+    if(err != noErr)
+        ERR("AudioOutputUnitStop failed\n");
+}
+
+
+
+
+typedef struct ALCcoreAudioCapture {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    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;
+} 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);
+static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALCuint ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture *self);
+static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCcoreAudioCapture, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCcoreAudioCapture)
+
+DEFINE_ALCBACKEND_VTABLE(ALCcoreAudioCapture);
+
+
+static void ALCcoreAudioCapture_Construct(ALCcoreAudioCapture *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCcoreAudioCapture, ALCbackend, self);
+
+}
+
+static void ALCcoreAudioCapture_Destruct(ALCcoreAudioCapture *self)
+{
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static OSStatus ALCcoreAudioCapture_RecordProc(void *inRefCon,
+  AudioUnitRenderActionFlags* UNUSED(ioActionFlags),
+  const AudioTimeStamp *inTimeStamp, UInt32 UNUSED(inBusNumber),
+  UInt32 inNumberFrames, AudioBufferList* UNUSED(ioData))
 {
-    ca_data *data = (ca_data*)device->ExtraData;
+    ALCcoreAudioCapture *self = inRefCon;
+    AudioUnitRenderActionFlags flags = 0;
     OSStatus err;
 
-    err = AudioOutputUnitStop(data->audioUnit);
+    // fill the bufferList with data from the input device
+    err = AudioUnitRender(self->audioUnit, &flags, inTimeStamp, 1, inNumberFrames, self->bufferList);
     if(err != noErr)
-        ERR("AudioOutputUnitStop failed\n");
+    {
+        ERR("AudioUnitRender error: %d\n", err);
+        return err;
+    }
+
+    ll_ringbuffer_write(self->ring, self->bufferList->mBuffers[0].mData, inNumberFrames);
+
+    return noErr;
+}
+
+static OSStatus ALCcoreAudioCapture_ConvertCallback(AudioConverterRef UNUSED(inAudioConverter),
+  UInt32 *ioNumberDataPackets, AudioBufferList *ioData,
+  AudioStreamPacketDescription** UNUSED(outDataPacketDescription),
+  void *inUserData)
+{
+    ALCcoreAudioCapture *self = inUserData;
+
+    // Read from the ring buffer and store temporarily in a large buffer
+    ll_ringbuffer_read(self->ring, self->resampleBuffer, *ioNumberDataPackets);
+
+    // Set the input data
+    ioData->mNumberBuffers = 1;
+    ioData->mBuffers[0].mNumberChannels = self->format.mChannelsPerFrame;
+    ioData->mBuffers[0].mData = self->resampleBuffer;
+    ioData->mBuffers[0].mDataByteSize = (*ioNumberDataPackets) * self->format.mBytesPerFrame;
+
+    return noErr;
 }
 
-static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
+
+static ALCenum ALCcoreAudioCapture_open(ALCcoreAudioCapture *self, const ALCchar *name)
 {
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
     AudioStreamBasicDescription requestedFormat;  // The application requested format
     AudioStreamBasicDescription hardwareFormat;   // The hardware format
     AudioStreamBasicDescription outputFormat;     // The AudioUnit output format
     AURenderCallbackStruct input;
-    ComponentDescription desc;
+    AudioComponentDescription desc;
     AudioDeviceID inputDevice;
     UInt32 outputFrameCount;
     UInt32 propertySize;
+    AudioObjectPropertyAddress propertyAddress;
     UInt32 enableIO;
-    Component comp;
-    ca_data *data;
+    AudioComponent comp;
     OSStatus err;
 
+    if(!name)
+        name = ca_device;
+    else if(strcmp(name, ca_device) != 0)
+        return ALC_INVALID_VALUE;
+
     desc.componentType = kAudioUnitType_Output;
     desc.componentSubType = kAudioUnitSubType_HALOutput;
     desc.componentManufacturer = kAudioUnitManufacturer_Apple;
@@ -390,27 +479,24 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     desc.componentFlagsMask = 0;
 
     // Search for component with given description
-    comp = FindNextComponent(NULL, &desc);
+    comp = AudioComponentFindNext(NULL, &desc);
     if(comp == NULL)
     {
-        ERR("FindNextComponent failed\n");
+        ERR("AudioComponentFindNext failed\n");
         return ALC_INVALID_VALUE;
     }
 
-    data = calloc(1, sizeof(*data));
-    device->ExtraData = data;
-
     // Open the component
-    err = OpenAComponent(comp, &data->audioUnit);
+    err = AudioComponentInstanceNew(comp, &self->audioUnit);
     if(err != noErr)
     {
-        ERR("OpenAComponent failed\n");
+        ERR("AudioComponentInstanceNew failed\n");
         goto error;
     }
 
     // Turn off AudioUnit output
     enableIO = 0;
-    err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint));
+    err = AudioUnitSetProperty(self->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint));
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed\n");
@@ -419,7 +505,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
 
     // Turn on AudioUnit input
     enableIO = 1;
-    err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint));
+    err = AudioUnitSetProperty(self->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint));
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed\n");
@@ -427,11 +513,16 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     }
 
     // Get the default input device
+
     propertySize = sizeof(AudioDeviceID);
-    err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &inputDevice);
+    propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
+    propertyAddress.mScope = kAudioObjectPropertyScopeGlobal;
+    propertyAddress.mElement = kAudioObjectPropertyElementMaster;
+
+    err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, &inputDevice);
     if(err != noErr)
     {
-        ERR("AudioHardwareGetProperty failed\n");
+        ERR("AudioObjectGetPropertyData failed\n");
         goto error;
     }
 
@@ -442,7 +533,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     }
 
     // Track the input device
-    err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID));
+    err = AudioUnitSetProperty(self->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID));
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed\n");
@@ -450,10 +541,10 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     }
 
     // set capture callback
-    input.inputProc = ca_capture_callback;
-    input.inputProcRefCon = device;
+    input.inputProc = ALCcoreAudioCapture_RecordProc;
+    input.inputProcRefCon = self;
 
-    err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct));
+    err = AudioUnitSetProperty(self->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct));
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed\n");
@@ -461,7 +552,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     }
 
     // Initialize the device
-    err = AudioUnitInitialize(data->audioUnit);
+    err = AudioUnitInitialize(self->audioUnit);
     if(err != noErr)
     {
         ERR("AudioUnitInitialize failed\n");
@@ -470,7 +561,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
 
     // Get the hardware format
     propertySize = sizeof(AudioStreamBasicDescription);
-    err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize);
+    err = AudioUnitGetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize);
     if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription))
     {
         ERR("AudioUnitGetProperty failed\n");
@@ -514,9 +605,10 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
 
         case DevFmtQuad:
         case DevFmtX51:
-        case DevFmtX51Side:
+        case DevFmtX51Rear:
         case DevFmtX61:
         case DevFmtX71:
+        case DevFmtAmbi3D:
             ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans));
             goto error;
     }
@@ -529,8 +621,8 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     requestedFormat.mFramesPerPacket = 1;
 
     // save requested format description for later use
-    data->format = requestedFormat;
-    data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->format = requestedFormat;
+    self->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
     // Use intermediate format for sample rate conversion (outputFormat)
     // Set sample rate to the same as hardware for resampling later
@@ -538,11 +630,11 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     outputFormat.mSampleRate = hardwareFormat.mSampleRate;
 
     // Determine sample rate ratio for resampling
-    data->sampleRateRatio = outputFormat.mSampleRate / device->Frequency;
+    self->sampleRateRatio = outputFormat.mSampleRate / device->Frequency;
 
     // The output format should be the requested format, but using the hardware sample rate
     // This is because the AudioUnit will automatically scale other properties, except for sample rate
-    err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat));
+    err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat));
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed\n");
@@ -550,8 +642,8 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     }
 
     // Set the AudioUnit output format frame count
-    outputFrameCount = device->UpdateSize * data->sampleRateRatio;
-    err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount));
+    outputFrameCount = device->UpdateSize * self->sampleRateRatio;
+    err = AudioUnitSetProperty(self->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount));
     if(err != noErr)
     {
         ERR("AudioUnitSetProperty failed: %d\n", err);
@@ -559,7 +651,7 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     }
 
     // Set up sample converter
-    err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter);
+    err = AudioConverterNew(&outputFormat, &requestedFormat, &self->audioConverter);
     if(err != noErr)
     {
         ERR("AudioConverterNew failed: %d\n", err);
@@ -567,71 +659,71 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName)
     }
 
     // Create a buffer for use in the resample callback
-    data->resampleBuffer = malloc(device->UpdateSize * data->frameSize * data->sampleRateRatio);
+    self->resampleBuffer = malloc(device->UpdateSize * self->frameSize * self->sampleRateRatio);
 
     // Allocate buffer for the AudioUnit output
-    data->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * data->frameSize * data->sampleRateRatio);
-    if(data->bufferList == NULL)
+    self->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * self->frameSize * self->sampleRateRatio);
+    if(self->bufferList == NULL)
         goto error;
 
-    data->ring = CreateRingBuffer(data->frameSize, (device->UpdateSize * data->sampleRateRatio) * device->NumUpdates);
-    if(data->ring == NULL)
-        goto error;
+    self->ring = ll_ringbuffer_create(
+        device->UpdateSize*self->sampleRateRatio*device->NumUpdates + 1,
+        self->frameSize
+    );
+    if(!self->ring) goto error;
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
+    alstr_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 
 error:
-    DestroyRingBuffer(data->ring);
-    free(data->resampleBuffer);
-    destroy_buffer_list(data->bufferList);
+    ll_ringbuffer_free(self->ring);
+    self->ring = NULL;
+    free(self->resampleBuffer);
+    destroy_buffer_list(self->bufferList);
 
-    if(data->audioConverter)
-        AudioConverterDispose(data->audioConverter);
-    if(data->audioUnit)
-        CloseComponent(data->audioUnit);
-
-    free(data);
-    device->ExtraData = NULL;
+    if(self->audioConverter)
+        AudioConverterDispose(self->audioConverter);
+    if(self->audioUnit)
+        AudioComponentInstanceDispose(self->audioUnit);
 
     return ALC_INVALID_VALUE;
 }
 
-static void ca_close_capture(ALCdevice *device)
+
+static void ALCcoreAudioCapture_close(ALCcoreAudioCapture *self)
 {
-    ca_data *data = (ca_data*)device->ExtraData;
+    ll_ringbuffer_free(self->ring);
+    self->ring = NULL;
 
-    DestroyRingBuffer(data->ring);
-    free(data->resampleBuffer);
-    destroy_buffer_list(data->bufferList);
+    free(self->resampleBuffer);
 
-    AudioConverterDispose(data->audioConverter);
-    CloseComponent(data->audioUnit);
+    destroy_buffer_list(self->bufferList);
 
-    free(data);
-    device->ExtraData = NULL;
+    AudioConverterDispose(self->audioConverter);
+    AudioComponentInstanceDispose(self->audioUnit);
 }
 
-static void ca_start_capture(ALCdevice *device)
+static ALCboolean ALCcoreAudioCapture_start(ALCcoreAudioCapture *self)
 {
-    ca_data *data = (ca_data*)device->ExtraData;
-    OSStatus err = AudioOutputUnitStart(data->audioUnit);
+    OSStatus err = AudioOutputUnitStart(self->audioUnit);
     if(err != noErr)
+    {
         ERR("AudioOutputUnitStart failed\n");
+        return ALC_FALSE;
+    }
+    return ALC_TRUE;
 }
 
-static void ca_stop_capture(ALCdevice *device)
+static void ALCcoreAudioCapture_stop(ALCcoreAudioCapture *self)
 {
-    ca_data *data = (ca_data*)device->ExtraData;
-    OSStatus err = AudioOutputUnitStop(data->audioUnit);
+    OSStatus err = AudioOutputUnitStop(self->audioUnit);
     if(err != noErr)
         ERR("AudioOutputUnitStop failed\n");
 }
 
-static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
+static ALCenum ALCcoreAudioCapture_captureSamples(ALCcoreAudioCapture *self, ALCvoid *buffer, ALCuint samples)
 {
-    ca_data *data = (ca_data*)device->ExtraData;
     AudioBufferList *list;
     UInt32 frameCount;
     OSStatus err;
@@ -645,14 +737,15 @@ static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint sa
 
     // Point the resampling buffer to the capture buffer
     list->mNumberBuffers = 1;
-    list->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame;
-    list->mBuffers[0].mDataByteSize = samples * data->frameSize;
+    list->mBuffers[0].mNumberChannels = self->format.mChannelsPerFrame;
+    list->mBuffers[0].mDataByteSize = samples * self->frameSize;
     list->mBuffers[0].mData = buffer;
 
     // Resample into another AudioBufferList
     frameCount = samples;
-    err = AudioConverterFillComplexBuffer(data->audioConverter, ca_capture_conversion_callback,
-                                          device, &frameCount, list, NULL);
+    err = AudioConverterFillComplexBuffer(self->audioConverter,
+        ALCcoreAudioCapture_ConvertCallback, self, &frameCount, list, NULL
+    );
     if(err != noErr)
     {
         ERR("AudioConverterFillComplexBuffer error: %d\n", err);
@@ -661,39 +754,47 @@ static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint sa
     return ALC_NO_ERROR;
 }
 
-static ALCuint ca_available_samples(ALCdevice *device)
+static ALCuint ALCcoreAudioCapture_availableSamples(ALCcoreAudioCapture *self)
 {
-    ca_data *data = device->ExtraData;
-    return RingBufferSize(data->ring) / data->sampleRateRatio;
+    return ll_ringbuffer_read_space(self->ring) / self->sampleRateRatio;
 }
 
 
-static const BackendFuncs ca_funcs = {
-    ca_open_playback,
-    ca_close_playback,
-    ca_reset_playback,
-    ca_start_playback,
-    ca_stop_playback,
-    ca_open_capture,
-    ca_close_capture,
-    ca_start_capture,
-    ca_stop_capture,
-    ca_capture_samples,
-    ca_available_samples,
-    ALCdevice_GetLatencyDefault
-};
-
-ALCboolean alc_ca_init(BackendFuncs *func_list)
+typedef struct ALCcoreAudioBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCcoreAudioBackendFactory;
+#define ALCCOREAUDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCcoreAudioBackendFactory, ALCbackendFactory) } }
+
+ALCbackendFactory *ALCcoreAudioBackendFactory_getFactory(void);
+
+static ALCboolean ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory *self);
+static DECLARE_FORWARD(ALCcoreAudioBackendFactory, ALCbackendFactory, void, deinit)
+static ALCboolean ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory *self, ALCbackend_Type type);
+static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCcoreAudioBackendFactory);
+
+
+ALCbackendFactory *ALCcoreAudioBackendFactory_getFactory(void)
+{
+    static ALCcoreAudioBackendFactory factory = ALCCOREAUDIOBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}
+
+
+static ALCboolean ALCcoreAudioBackendFactory_init(ALCcoreAudioBackendFactory* UNUSED(self))
 {
-    *func_list = ca_funcs;
     return ALC_TRUE;
 }
 
-void alc_ca_deinit(void)
+static ALCboolean ALCcoreAudioBackendFactory_querySupport(ALCcoreAudioBackendFactory* UNUSED(self), ALCbackend_Type type)
 {
+    if(type == ALCbackend_Playback || ALCbackend_Capture)
+        return ALC_TRUE;
+    return ALC_FALSE;
 }
 
-void alc_ca_probe(enum DevProbe type)
+static void ALCcoreAudioBackendFactory_probe(ALCcoreAudioBackendFactory* UNUSED(self), enum DevProbe type)
 {
     switch(type)
     {
@@ -705,3 +806,23 @@ void alc_ca_probe(enum DevProbe type)
             break;
     }
 }
+
+static ALCbackend* ALCcoreAudioBackendFactory_createBackend(ALCcoreAudioBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCcoreAudioPlayback *backend;
+        NEW_OBJ(backend, ALCcoreAudioPlayback)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+    if(type == ALCbackend_Capture)
+    {
+        ALCcoreAudioCapture *backend;
+        NEW_OBJ(backend, ALCcoreAudioCapture)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}

+ 147 - 141
love/src/jni/openal-soft-1.17.0/Alc/backends/dsound.c → love/src/jni/openal-soft-1.18.2/Alc/backends/dsound.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -43,6 +43,9 @@
 #ifndef DSSPEAKER_5POINT1
 #   define DSSPEAKER_5POINT1          0x00000006
 #endif
+#ifndef DSSPEAKER_5POINT1_BACK
+#   define DSSPEAKER_5POINT1_BACK     0x00000006
+#endif
 #ifndef DSSPEAKER_7POINT1
 #   define DSSPEAKER_7POINT1          0x00000007
 #endif
@@ -57,6 +60,8 @@
 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 
+#define DEVNAME_HEAD "OpenAL Soft on "
+
 
 #ifdef HAVE_DYNLOAD
 static void *ds_handle;
@@ -118,15 +123,14 @@ static void clear_devlist(vector_DevMap *list)
 {
 #define DEINIT_STR(i) AL_STRING_DEINIT((i)->name)
     VECTOR_FOR_EACH(DevMap, *list, DEINIT_STR);
+    VECTOR_RESIZE(*list, 0, 0);
 #undef DEINIT_STR
-    VECTOR_RESIZE(*list, 0);
 }
 
 static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data)
 {
     vector_DevMap *devices = data;
     OLECHAR *guidstr = NULL;
-    DevMap *iter, *end;
     DevMap entry;
     HRESULT hr;
     int count;
@@ -137,30 +141,31 @@ static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHA
     AL_STRING_INIT(entry.name);
 
     count = 0;
-    do {
-        al_string_copy_wcstr(&entry.name, desc);
+    while(1)
+    {
+        const DevMap *iter;
+
+        alstr_copy_cstr(&entry.name, DEVNAME_HEAD);
+        alstr_append_wcstr(&entry.name, desc);
         if(count != 0)
         {
             char str[64];
             snprintf(str, sizeof(str), " #%d", count+1);
-            al_string_append_cstr(&entry.name, str);
+            alstr_append_cstr(&entry.name, str);
         }
-        count++;
 
-        iter = VECTOR_ITER_BEGIN(*devices);
-        end = VECTOR_ITER_END(*devices);
-        for(;iter != end;++iter)
-        {
-            if(al_string_cmp(entry.name, iter->name) == 0)
-                break;
-        }
-    } while(iter != end);
+#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, *devices, MATCH_ENTRY);
+        if(iter == VECTOR_END(*devices)) break;
+#undef MATCH_ENTRY
+        count++;
+    }
     entry.guid = *guid;
 
     hr = StringFromCLSID(guid, &guidstr);
     if(SUCCEEDED(hr))
     {
-        TRACE("Got device \"%s\", GUID \"%ls\"\n", al_string_get_cstr(entry.name), guidstr);
+        TRACE("Got device \"%s\", GUID \"%ls\"\n", alstr_get_cstr(entry.name), guidstr);
         CoTaskMemFree(guidstr);
     }
 
@@ -194,7 +199,7 @@ static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self);
 static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self);
 static DECLARE_FORWARD2(ALCdsoundPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
 static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALCuint, availableSamples)
-static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ClockLatency, getClockLatency)
 static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCdsoundPlayback)
@@ -239,7 +244,7 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
         return 1;
     }
 
-    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     FragSize = device->UpdateSize * FrameSize;
 
     IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL);
@@ -294,8 +299,10 @@ FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr)
         if(SUCCEEDED(err))
         {
             // If we have an active context, mix data directly into output buffer otherwise fill with silence
+            ALCdevice_Lock(device);
             aluMixData(device, WritePtr1, WriteCnt1/FrameSize);
             aluMixData(device, WritePtr2, WriteCnt2/FrameSize);
+            ALCdevice_Unlock(device);
 
             // Unlock output buffer only when successfully locked
             IDirectSoundBuffer_Unlock(self->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2);
@@ -336,23 +343,23 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de
 
     if(!deviceName && VECTOR_SIZE(PlaybackDevices) > 0)
     {
-        deviceName = al_string_get_cstr(VECTOR_FRONT(PlaybackDevices).name);
+        deviceName = alstr_get_cstr(VECTOR_FRONT(PlaybackDevices).name);
         guid = &VECTOR_FRONT(PlaybackDevices).guid;
     }
     else
     {
         const DevMap *iter;
 
-#define MATCH_NAME(i)  (al_string_cmp_cstr((i)->name, deviceName) == 0)
+#define MATCH_NAME(i)  (alstr_cmp_cstr((i)->name, deviceName) == 0)
         VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
 #undef MATCH_NAME
-        if(iter == VECTOR_ITER_END(PlaybackDevices))
+        if(iter == VECTOR_END(PlaybackDevices))
             return ALC_INVALID_VALUE;
         guid = &iter->guid;
     }
 
     hr = DS_OK;
-    self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
     if(self->NotifyEvent == NULL)
         hr = E_FAIL;
 
@@ -374,7 +381,7 @@ static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *de
         return ALC_INVALID_VALUE;
     }
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
+    alstr_copy_cstr(&device->DeviceName, deviceName);
 
     return ALC_NO_ERROR;
 }
@@ -441,28 +448,35 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
     hr = IDirectSound_GetSpeakerConfig(self->DS, &speakers);
     if(SUCCEEDED(hr))
     {
+        speakers = DSSPEAKER_CONFIG(speakers);
         if(!(device->Flags&DEVICE_CHANNELS_REQUEST))
         {
-            speakers = DSSPEAKER_CONFIG(speakers);
             if(speakers == DSSPEAKER_MONO)
                 device->FmtChans = DevFmtMono;
             else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE)
                 device->FmtChans = DevFmtStereo;
             else if(speakers == DSSPEAKER_QUAD)
                 device->FmtChans = DevFmtQuad;
-            else if(speakers == DSSPEAKER_5POINT1 || speakers == DSSPEAKER_5POINT1_SURROUND)
+            else if(speakers == DSSPEAKER_5POINT1_SURROUND)
                 device->FmtChans = DevFmtX51;
+            else if(speakers == DSSPEAKER_5POINT1_BACK)
+                device->FmtChans = DevFmtX51Rear;
             else if(speakers == DSSPEAKER_7POINT1 || speakers == DSSPEAKER_7POINT1_SURROUND)
                 device->FmtChans = DevFmtX71;
             else
                 ERR("Unknown system speaker config: 0x%lx\n", speakers);
         }
+        device->IsHeadphones = (device->FmtChans == DevFmtStereo &&
+                                speakers == DSSPEAKER_HEADPHONE);
 
         switch(device->FmtChans)
         {
             case DevFmtMono:
                 OutputType.dwChannelMask = SPEAKER_FRONT_CENTER;
                 break;
+            case DevFmtAmbi3D:
+                device->FmtChans = DevFmtStereo;
+                /*fall-through*/
             case DevFmtStereo:
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                            SPEAKER_FRONT_RIGHT;
@@ -478,16 +492,16 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
                                            SPEAKER_FRONT_RIGHT |
                                            SPEAKER_FRONT_CENTER |
                                            SPEAKER_LOW_FREQUENCY |
-                                           SPEAKER_BACK_LEFT |
-                                           SPEAKER_BACK_RIGHT;
+                                           SPEAKER_SIDE_LEFT |
+                                           SPEAKER_SIDE_RIGHT;
                 break;
-            case DevFmtX51Side:
+            case DevFmtX51Rear:
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
                                            SPEAKER_FRONT_RIGHT |
                                            SPEAKER_FRONT_CENTER |
                                            SPEAKER_LOW_FREQUENCY |
-                                           SPEAKER_SIDE_LEFT |
-                                           SPEAKER_SIDE_RIGHT;
+                                           SPEAKER_BACK_LEFT |
+                                           SPEAKER_BACK_RIGHT;
                 break;
             case DevFmtX61:
                 OutputType.dwChannelMask = SPEAKER_FRONT_LEFT |
@@ -513,7 +527,7 @@ static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self)
 retry_open:
         hr = S_OK;
         OutputType.Format.wFormatTag = WAVE_FORMAT_PCM;
-        OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
+        OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
         OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
         OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8;
         OutputType.Format.nSamplesPerSec = device->Frequency;
@@ -641,7 +655,8 @@ typedef struct ALCdsoundCapture {
     IDirectSoundCaptureBuffer *DSCbuffer;
     DWORD BufferBytes;
     DWORD Cursor;
-    RingBuffer *Ring;
+
+    ll_ringbuffer_t *Ring;
 } ALCdsoundCapture;
 
 static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device);
@@ -653,7 +668,7 @@ static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self);
 static void ALCdsoundCapture_stop(ALCdsoundCapture *self);
 static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples);
 static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self);
-static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ClockLatency, getClockLatency)
 static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCdsoundCapture)
@@ -689,17 +704,17 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
 
     if(!deviceName && VECTOR_SIZE(CaptureDevices) > 0)
     {
-        deviceName = al_string_get_cstr(VECTOR_FRONT(CaptureDevices).name);
+        deviceName = alstr_get_cstr(VECTOR_FRONT(CaptureDevices).name);
         guid = &VECTOR_FRONT(CaptureDevices).guid;
     }
     else
     {
         const DevMap *iter;
 
-#define MATCH_NAME(i)  (al_string_cmp_cstr((i)->name, deviceName) == 0)
+#define MATCH_NAME(i)  (alstr_cmp_cstr((i)->name, deviceName) == 0)
         VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
 #undef MATCH_NAME
-        if(iter == VECTOR_ITER_END(CaptureDevices))
+        if(iter == VECTOR_END(CaptureDevices))
             return ALC_INVALID_VALUE;
         guid = &iter->guid;
     }
@@ -719,97 +734,98 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
             break;
     }
 
-    //DirectSoundCapture Init code
-    hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL);
-    if(SUCCEEDED(hr))
+    memset(&InputType, 0, sizeof(InputType));
+    switch(device->FmtChans)
     {
-        memset(&InputType, 0, sizeof(InputType));
-
-        switch(device->FmtChans)
-        {
-            case DevFmtMono:
-                InputType.dwChannelMask = SPEAKER_FRONT_CENTER;
-                break;
-            case DevFmtStereo:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT;
-                break;
-            case DevFmtQuad:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_BACK_LEFT |
-                                          SPEAKER_BACK_RIGHT;
-                break;
-            case DevFmtX51:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_FRONT_CENTER |
-                                          SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_BACK_LEFT |
-                                          SPEAKER_BACK_RIGHT;
-                break;
-            case DevFmtX51Side:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_FRONT_CENTER |
-                                          SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_SIDE_LEFT |
-                                          SPEAKER_SIDE_RIGHT;
-                break;
-            case DevFmtX61:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_FRONT_CENTER |
-                                          SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_BACK_CENTER |
-                                          SPEAKER_SIDE_LEFT |
-                                          SPEAKER_SIDE_RIGHT;
-                break;
-            case DevFmtX71:
-                InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
-                                          SPEAKER_FRONT_RIGHT |
-                                          SPEAKER_FRONT_CENTER |
-                                          SPEAKER_LOW_FREQUENCY |
-                                          SPEAKER_BACK_LEFT |
-                                          SPEAKER_BACK_RIGHT |
-                                          SPEAKER_SIDE_LEFT |
-                                          SPEAKER_SIDE_RIGHT;
-                break;
-        }
+        case DevFmtMono:
+            InputType.dwChannelMask = SPEAKER_FRONT_CENTER;
+            break;
+        case DevFmtStereo:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT;
+            break;
+        case DevFmtQuad:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_BACK_LEFT |
+                                      SPEAKER_BACK_RIGHT;
+            break;
+        case DevFmtX51:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_FRONT_CENTER |
+                                      SPEAKER_LOW_FREQUENCY |
+                                      SPEAKER_SIDE_LEFT |
+                                      SPEAKER_SIDE_RIGHT;
+            break;
+        case DevFmtX51Rear:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_FRONT_CENTER |
+                                      SPEAKER_LOW_FREQUENCY |
+                                      SPEAKER_BACK_LEFT |
+                                      SPEAKER_BACK_RIGHT;
+            break;
+        case DevFmtX61:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_FRONT_CENTER |
+                                      SPEAKER_LOW_FREQUENCY |
+                                      SPEAKER_BACK_CENTER |
+                                      SPEAKER_SIDE_LEFT |
+                                      SPEAKER_SIDE_RIGHT;
+            break;
+        case DevFmtX71:
+            InputType.dwChannelMask = SPEAKER_FRONT_LEFT |
+                                      SPEAKER_FRONT_RIGHT |
+                                      SPEAKER_FRONT_CENTER |
+                                      SPEAKER_LOW_FREQUENCY |
+                                      SPEAKER_BACK_LEFT |
+                                      SPEAKER_BACK_RIGHT |
+                                      SPEAKER_SIDE_LEFT |
+                                      SPEAKER_SIDE_RIGHT;
+            break;
+        case DevFmtAmbi3D:
+            WARN("%s capture not supported\n", DevFmtChannelsString(device->FmtChans));
+            return ALC_INVALID_ENUM;
+    }
 
-        InputType.Format.wFormatTag = WAVE_FORMAT_PCM;
-        InputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans);
-        InputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
-        InputType.Format.nBlockAlign = InputType.Format.nChannels*InputType.Format.wBitsPerSample/8;
-        InputType.Format.nSamplesPerSec = device->Frequency;
-        InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec*InputType.Format.nBlockAlign;
-        InputType.Format.cbSize = 0;
+    InputType.Format.wFormatTag = WAVE_FORMAT_PCM;
+    InputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    InputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
+    InputType.Format.nBlockAlign = InputType.Format.nChannels*InputType.Format.wBitsPerSample/8;
+    InputType.Format.nSamplesPerSec = device->Frequency;
+    InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec*InputType.Format.nBlockAlign;
+    InputType.Format.cbSize = 0;
+    InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample;
+    if(device->FmtType == DevFmtFloat)
+        InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+    else
+        InputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
 
-        if(InputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat)
-        {
-            InputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
-            InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
-            InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample;
-            if(device->FmtType == DevFmtFloat)
-                InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
-            else
-                InputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
-        }
+    if(InputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat)
+    {
+        InputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+        InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
+    }
 
-        samples = device->UpdateSize * device->NumUpdates;
-        samples = maxu(samples, 100 * device->Frequency / 1000);
+    samples = device->UpdateSize * device->NumUpdates;
+    samples = maxu(samples, 100 * device->Frequency / 1000);
 
-        memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC));
-        DSCBDescription.dwSize = sizeof(DSCBUFFERDESC);
-        DSCBDescription.dwFlags = 0;
-        DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign;
-        DSCBDescription.lpwfxFormat = &InputType.Format;
+    memset(&DSCBDescription, 0, sizeof(DSCBUFFERDESC));
+    DSCBDescription.dwSize = sizeof(DSCBUFFERDESC);
+    DSCBDescription.dwFlags = 0;
+    DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign;
+    DSCBDescription.lpwfxFormat = &InputType.Format;
 
+    //DirectSoundCapture Init code
+    hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL);
+    if(SUCCEEDED(hr))
         hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL);
-    }
     if(SUCCEEDED(hr))
     {
-         self->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates);
+         self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1,
+                                           InputType.Format.nBlockAlign);
          if(self->Ring == NULL)
              hr = DSERR_OUTOFMEMORY;
     }
@@ -818,7 +834,7 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
     {
         ERR("Device init failed: 0x%08lx\n", hr);
 
-        DestroyRingBuffer(self->Ring);
+        ll_ringbuffer_free(self->Ring);
         self->Ring = NULL;
         if(self->DSCbuffer != NULL)
             IDirectSoundCaptureBuffer_Release(self->DSCbuffer);
@@ -833,14 +849,14 @@ static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *devi
     self->BufferBytes = DSCBDescription.dwBufferBytes;
     SetDefaultWFXChannelOrder(device);
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
+    alstr_copy_cstr(&device->DeviceName, deviceName);
 
     return ALC_NO_ERROR;
 }
 
 static void ALCdsoundCapture_close(ALCdsoundCapture *self)
 {
-    DestroyRingBuffer(self->Ring);
+    ll_ringbuffer_free(self->Ring);
     self->Ring = NULL;
 
     if(self->DSCbuffer != NULL)
@@ -883,7 +899,7 @@ static void ALCdsoundCapture_stop(ALCdsoundCapture *self)
 
 static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples)
 {
-    ReadRingBuffer(self->Ring, buffer, samples);
+    ll_ringbuffer_read(self->Ring, buffer, samples);
     return ALC_NO_ERROR;
 }
 
@@ -899,7 +915,7 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
     if(!device->Connected)
         goto done;
 
-    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     BufferBytes = self->BufferBytes;
     LastCursor = self->Cursor;
 
@@ -915,9 +931,9 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
     }
     if(SUCCEEDED(hr))
     {
-        WriteRingBuffer(self->Ring, ReadPtr1, ReadCnt1/FrameSize);
+        ll_ringbuffer_write(self->Ring, ReadPtr1, ReadCnt1/FrameSize);
         if(ReadPtr2 != NULL)
-            WriteRingBuffer(self->Ring, ReadPtr2, ReadCnt2/FrameSize);
+            ll_ringbuffer_write(self->Ring, ReadPtr2, ReadCnt2/FrameSize);
         hr = IDirectSoundCaptureBuffer_Unlock(self->DSCbuffer,
                                               ReadPtr1, ReadCnt1,
                                               ReadPtr2, ReadCnt2);
@@ -931,14 +947,14 @@ static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self)
     }
 
 done:
-    return RingBufferSize(self->Ring);
+    return ll_ringbuffer_read_space(self->Ring);
 }
 
 
 static inline void AppendAllDevicesList2(const DevMap *entry)
-{ AppendAllDevicesList(al_string_get_cstr(entry->name)); }
+{ AppendAllDevicesList(alstr_get_cstr(entry->name)); }
 static inline void AppendCaptureDeviceList2(const DevMap *entry)
-{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); }
+{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); }
 
 typedef struct ALCdsoundBackendFactory {
     DERIVE_FROM_TYPE(ALCbackendFactory);
@@ -1027,26 +1043,16 @@ static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory
     if(type == ALCbackend_Playback)
     {
         ALCdsoundPlayback *backend;
-
-        backend = ALCdsoundPlayback_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCdsoundPlayback)(device);
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCdsoundPlayback_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
     }
 
     if(type == ALCbackend_Capture)
     {
         ALCdsoundCapture *backend;
-
-        backend = ALCdsoundCapture_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCdsoundCapture)(device);
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCdsoundCapture_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
     }
 

+ 640 - 0
love/src/jni/openal-soft-1.18.2/Alc/backends/jack.c

@@ -0,0 +1,640 @@
+/**
+ * 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 <stdio.h>
+#include <memory.h>
+
+#include "alMain.h"
+#include "alu.h"
+#include "threads.h"
+#include "compat.h"
+
+#include "backends/base.h"
+
+#include <jack/jack.h>
+#include <jack/ringbuffer.h>
+
+
+static const ALCchar jackDevice[] = "JACK Default";
+
+
+#ifdef HAVE_DYNLOAD
+#define JACK_FUNCS(MAGIC)          \
+    MAGIC(jack_client_open);       \
+    MAGIC(jack_client_close);      \
+    MAGIC(jack_client_name_size);  \
+    MAGIC(jack_get_client_name);   \
+    MAGIC(jack_connect);           \
+    MAGIC(jack_activate);          \
+    MAGIC(jack_deactivate);        \
+    MAGIC(jack_port_register);     \
+    MAGIC(jack_port_unregister);   \
+    MAGIC(jack_port_get_buffer);   \
+    MAGIC(jack_port_name);         \
+    MAGIC(jack_get_ports);         \
+    MAGIC(jack_free);              \
+    MAGIC(jack_get_sample_rate);   \
+    MAGIC(jack_set_error_function); \
+    MAGIC(jack_set_process_callback); \
+    MAGIC(jack_set_buffer_size_callback); \
+    MAGIC(jack_set_buffer_size);   \
+    MAGIC(jack_get_buffer_size);
+
+static void *jack_handle;
+#define MAKE_FUNC(f) static __typeof(f) * p##f
+JACK_FUNCS(MAKE_FUNC);
+static __typeof(jack_error_callback) * pjack_error_callback;
+#undef MAKE_FUNC
+
+#define jack_client_open pjack_client_open
+#define jack_client_close pjack_client_close
+#define jack_client_name_size pjack_client_name_size
+#define jack_get_client_name pjack_get_client_name
+#define jack_connect pjack_connect
+#define jack_activate pjack_activate
+#define jack_deactivate pjack_deactivate
+#define jack_port_register pjack_port_register
+#define jack_port_unregister pjack_port_unregister
+#define jack_port_get_buffer pjack_port_get_buffer
+#define jack_port_name pjack_port_name
+#define jack_get_ports pjack_get_ports
+#define jack_free pjack_free
+#define jack_get_sample_rate pjack_get_sample_rate
+#define jack_set_error_function pjack_set_error_function
+#define jack_set_process_callback pjack_set_process_callback
+#define jack_set_buffer_size_callback pjack_set_buffer_size_callback
+#define jack_set_buffer_size pjack_set_buffer_size
+#define jack_get_buffer_size pjack_get_buffer_size
+#define jack_error_callback (*pjack_error_callback)
+#endif
+
+
+static jack_options_t ClientOptions = JackNullOption;
+
+static ALCboolean jack_load(void)
+{
+    ALCboolean error = ALC_FALSE;
+
+#ifdef HAVE_DYNLOAD
+    if(!jack_handle)
+    {
+        al_string missing_funcs = AL_STRING_INIT_STATIC();
+
+#ifdef _WIN32
+#define JACKLIB "libjack.dll"
+#else
+#define JACKLIB "libjack.so.0"
+#endif
+        jack_handle = LoadLib(JACKLIB);
+        if(!jack_handle)
+        {
+            WARN("Failed to load %s\n", JACKLIB);
+            return ALC_FALSE;
+        }
+
+        error = ALC_FALSE;
+#define LOAD_FUNC(f) do {                                                     \
+    p##f = GetSymbol(jack_handle, #f);                                        \
+    if(p##f == NULL) {                                                        \
+        error = ALC_TRUE;                                                     \
+        alstr_append_cstr(&missing_funcs, "\n" #f);                           \
+    }                                                                         \
+} while(0)
+        JACK_FUNCS(LOAD_FUNC);
+#undef LOAD_FUNC
+        /* Optional symbols. These don't exist in all versions of JACK. */
+#define LOAD_SYM(f) p##f = GetSymbol(jack_handle, #f)
+        LOAD_SYM(jack_error_callback);
+#undef LOAD_SYM
+
+        if(error)
+        {
+            WARN("Missing expected functions:%s\n", alstr_get_cstr(missing_funcs));
+            CloseLib(jack_handle);
+            jack_handle = NULL;
+        }
+        alstr_reset(&missing_funcs);
+    }
+#endif
+
+    return !error;
+}
+
+
+typedef struct ALCjackPlayback {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    jack_client_t *Client;
+    jack_port_t *Port[MAX_OUTPUT_CHANNELS];
+
+    ll_ringbuffer_t *Ring;
+    alcnd_t Cond;
+
+    volatile int killNow;
+    althrd_t thread;
+} ALCjackPlayback;
+
+static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg);
+
+static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg);
+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);
+static DECLARE_FORWARD2(ALCjackPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, ALCuint, availableSamples)
+static ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self);
+static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCjackPlayback, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCjackPlayback)
+
+DEFINE_ALCBACKEND_VTABLE(ALCjackPlayback);
+
+
+static void ALCjackPlayback_Construct(ALCjackPlayback *self, ALCdevice *device)
+{
+    ALuint i;
+
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCjackPlayback, ALCbackend, self);
+
+    alcnd_init(&self->Cond);
+
+    self->Client = NULL;
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+        self->Port[i] = NULL;
+    self->Ring = NULL;
+
+    self->killNow = 1;
+}
+
+static void ALCjackPlayback_Destruct(ALCjackPlayback *self)
+{
+    ALuint i;
+
+    if(self->Client)
+    {
+        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;
+    }
+
+    alcnd_destroy(&self->Cond);
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static int ALCjackPlayback_bufferSizeNotify(jack_nframes_t numframes, void *arg)
+{
+    ALCjackPlayback *self = arg;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    ALuint bufsize;
+
+    ALCjackPlayback_lock(self);
+    device->UpdateSize = numframes;
+    device->NumUpdates = 2;
+
+    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;
+
+    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)
+    );
+    if(!self->Ring)
+    {
+        ERR("Failed to reallocate ringbuffer\n");
+        aluHandleDisconnect(device);
+    }
+    ALCjackPlayback_unlock(self);
+    return 0;
+}
+
+
+static int ALCjackPlayback_process(jack_nframes_t numframes, void *arg)
+{
+    ALCjackPlayback *self = arg;
+    jack_default_audio_sample_t *out[MAX_OUTPUT_CHANNELS];
+    ll_ringbuffer_data_t data[2];
+    jack_nframes_t total = 0;
+    jack_nframes_t todo;
+    ALsizei i, c, numchans;
+
+    ll_ringbuffer_get_read_vector(self->Ring, data);
+
+    for(c = 0;c < MAX_OUTPUT_CHANNELS && self->Port[c];c++)
+        out[c] = jack_port_get_buffer(self->Port[c], numframes);
+    numchans = c;
+
+    todo = minu(numframes, data[0].len);
+    for(c = 0;c < numchans;c++)
+    {
+        const ALfloat *restrict in = ((ALfloat*)data[0].buf) + c;
+        for(i = 0;(jack_nframes_t)i < todo;i++)
+            out[c][i] = in[i*numchans];
+        out[c] += todo;
+    }
+    total += todo;
+
+    todo = minu(numframes-total, data[1].len);
+    if(todo > 0)
+    {
+        for(c = 0;c < numchans;c++)
+        {
+            const ALfloat *restrict in = ((ALfloat*)data[1].buf) + c;
+            for(i = 0;(jack_nframes_t)i < todo;i++)
+                out[c][i] = in[i*numchans];
+            out[c] += todo;
+        }
+        total += todo;
+    }
+
+    ll_ringbuffer_read_advance(self->Ring, total);
+    alcnd_signal(&self->Cond);
+
+    if(numframes > total)
+    {
+        todo = numframes-total;
+        for(c = 0;c < numchans;c++)
+        {
+            for(i = 0;(jack_nframes_t)i < todo;i++)
+                out[c][i] = 0.0f;
+        }
+    }
+
+    return 0;
+}
+
+static int ALCjackPlayback_mixerProc(void *arg)
+{
+    ALCjackPlayback *self = arg;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    ll_ringbuffer_data_t data[2];
+
+    SetRTPriority();
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
+
+    ALCjackPlayback_lock(self);
+    while(!self->killNow && device->Connected)
+    {
+        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);
+            continue;
+        }
+
+        ll_ringbuffer_get_write_vector(self->Ring, data);
+        todo  = data[0].len + data[1].len;
+        todo -= todo%device->UpdateSize;
+
+        len1 = minu(data[0].len, todo);
+        len2 = minu(data[1].len, todo-len1);
+
+        aluMixData(device, data[0].buf, len1);
+        if(len2 > 0)
+            aluMixData(device, data[1].buf, len2);
+        ll_ringbuffer_write_advance(self->Ring, todo);
+    }
+    ALCjackPlayback_unlock(self);
+
+    return 0;
+}
+
+
+static ALCenum ALCjackPlayback_open(ALCjackPlayback *self, const ALCchar *name)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    const char *client_name = "alsoft";
+    jack_status_t status;
+
+    if(!name)
+        name = jackDevice;
+    else if(strcmp(name, jackDevice) != 0)
+        return ALC_INVALID_VALUE;
+
+    self->Client = jack_client_open(client_name, ClientOptions, &status, NULL);
+    if(self->Client == NULL)
+    {
+        ERR("jack_client_open() failed, status = 0x%02x\n", status);
+        return ALC_INVALID_VALUE;
+    }
+    if((status&JackServerStarted))
+        TRACE("JACK server started\n");
+    if((status&JackNameNotUnique))
+    {
+        client_name = jack_get_client_name(self->Client);
+        TRACE("Client name not unique, got `%s' instead\n", client_name);
+    }
+
+    jack_set_process_callback(self->Client, ALCjackPlayback_process, self);
+    jack_set_buffer_size_callback(self->Client, ALCjackPlayback_bufferSizeNotify, self);
+
+    alstr_copy_cstr(&device->DeviceName, 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;
+    ALsizei numchans, i;
+    ALuint bufsize;
+
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+    {
+        if(self->Port[i])
+            jack_port_unregister(self->Client, self->Port[i]);
+        self->Port[i] = NULL;
+    }
+
+    /* 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.
+     */
+    device->Frequency = jack_get_sample_rate(self->Client);
+    device->UpdateSize = jack_get_buffer_size(self->Client);
+    device->NumUpdates = 2;
+
+    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;
+
+    /* Force 32-bit float output. */
+    device->FmtType = DevFmtFloat;
+
+    numchans = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    for(i = 0;i < numchans;i++)
+    {
+        char name[64];
+        snprintf(name, sizeof(name), "channel_%d", i+1);
+        self->Port[i] = jack_port_register(self->Client, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+        if(self->Port[i] == NULL)
+        {
+            ERR("Not enough JACK ports available for %s output\n", DevFmtChannelsString(device->FmtChans));
+            if(i == 0) return ALC_FALSE;
+            break;
+        }
+    }
+    if(i < numchans)
+    {
+        if(i == 1)
+            device->FmtChans = DevFmtMono;
+        else
+        {
+            for(--i;i >= 2;i--)
+            {
+                jack_port_unregister(self->Client, self->Port[i]);
+                self->Port[i] = NULL;
+            }
+            device->FmtChans = DevFmtStereo;
+        }
+    }
+
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = ll_ringbuffer_create(bufsize,
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
+    );
+    if(!self->Ring)
+    {
+        ERR("Failed to allocate ringbuffer\n");
+        return ALC_FALSE;
+    }
+
+    SetDefaultChannelOrder(device);
+
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCjackPlayback_start(ALCjackPlayback *self)
+{
+    const char **ports;
+    ALsizei i;
+
+    if(jack_activate(self->Client))
+    {
+        ERR("Failed to activate client\n");
+        return ALC_FALSE;
+    }
+
+    ports = jack_get_ports(self->Client, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
+    if(ports == NULL)
+    {
+        ERR("No physical playback ports found\n");
+        jack_deactivate(self->Client);
+        return ALC_FALSE;
+    }
+    for(i = 0;i < MAX_OUTPUT_CHANNELS && self->Port[i];i++)
+    {
+        if(!ports[i])
+        {
+            ERR("No physical playback port for \"%s\"\n", jack_port_name(self->Port[i]));
+            break;
+        }
+        if(jack_connect(self->Client, jack_port_name(self->Port[i]), ports[i]))
+            ERR("Failed to connect output port \"%s\" to \"%s\"\n", jack_port_name(self->Port[i]), ports[i]);
+    }
+    jack_free(ports);
+
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCjackPlayback_mixerProc, self) != althrd_success)
+    {
+        jack_deactivate(self->Client);
+        return ALC_FALSE;
+    }
+
+    return ALC_TRUE;
+}
+
+static void ALCjackPlayback_stop(ALCjackPlayback *self)
+{
+    int res;
+
+    if(self->killNow)
+        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);
+    althrd_join(self->thread, &res);
+
+    jack_deactivate(self->Client);
+}
+
+
+static ClockLatency ALCjackPlayback_getClockLatency(ALCjackPlayback *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ClockLatency ret;
+
+    ALCjackPlayback_lock(self);
+    ret.ClockTime = GetDeviceClockTime(device);
+    ret.Latency = ll_ringbuffer_read_space(self->Ring) * DEVICE_CLOCK_RES /
+                  device->Frequency;
+    ALCjackPlayback_unlock(self);
+
+    return ret;
+}
+
+
+static void jack_msg_handler(const char *message)
+{
+    WARN("%s\n", message);
+}
+
+typedef struct ALCjackBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCjackBackendFactory;
+#define ALCJACKBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCjackBackendFactory, ALCbackendFactory) } }
+
+static ALCboolean ALCjackBackendFactory_init(ALCjackBackendFactory* UNUSED(self))
+{
+    void (*old_error_cb)(const char*);
+    jack_client_t *client;
+    jack_status_t status;
+
+    if(!jack_load())
+        return ALC_FALSE;
+
+    if(!GetConfigValueBool(NULL, "jack", "spawn-server", 0))
+        ClientOptions |= JackNoStartServer;
+
+    old_error_cb = (&jack_error_callback ? jack_error_callback : NULL);
+    jack_set_error_function(jack_msg_handler);
+    client = jack_client_open("alsoft", ClientOptions, &status, NULL);
+    jack_set_error_function(old_error_cb);
+    if(client == NULL)
+    {
+        WARN("jack_client_open() failed, 0x%02x\n", status);
+        if((status&JackServerFailed) && !(ClientOptions&JackNoStartServer))
+            ERR("Unable to connect to JACK server\n");
+        return ALC_FALSE;
+    }
+
+    jack_client_close(client);
+    return ALC_TRUE;
+}
+
+static void ALCjackBackendFactory_deinit(ALCjackBackendFactory* UNUSED(self))
+{
+#ifdef HAVE_DYNLOAD
+    if(jack_handle)
+        CloseLib(jack_handle);
+    jack_handle = NULL;
+#endif
+}
+
+static ALCboolean ALCjackBackendFactory_querySupport(ALCjackBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCjackBackendFactory_probe(ALCjackBackendFactory* UNUSED(self), enum DevProbe type)
+{
+    switch(type)
+    {
+        case ALL_DEVICE_PROBE:
+            AppendAllDevicesList(jackDevice);
+            break;
+
+        case CAPTURE_DEVICE_PROBE:
+            break;
+    }
+}
+
+static ALCbackend* ALCjackBackendFactory_createBackend(ALCjackBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCjackPlayback *backend;
+        NEW_OBJ(backend, ALCjackPlayback)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}
+
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCjackBackendFactory);
+
+
+ALCbackendFactory *ALCjackBackendFactory_getFactory(void)
+{
+    static ALCjackBackendFactory factory = ALCJACKBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}

+ 5 - 10
love/src/jni/openal-soft-1.17.0/Alc/backends/loopback.c → love/src/jni/openal-soft-1.18.2/Alc/backends/loopback.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -41,7 +41,7 @@ static ALCboolean ALCloopback_start(ALCloopback *self);
 static void ALCloopback_stop(ALCloopback *self);
 static DECLARE_FORWARD2(ALCloopback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
 static DECLARE_FORWARD(ALCloopback, ALCbackend, ALCuint, availableSamples)
-static DECLARE_FORWARD(ALCloopback, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCloopback, ALCbackend, ClockLatency, getClockLatency)
 static DECLARE_FORWARD(ALCloopback, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCloopback, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCloopback)
@@ -59,7 +59,7 @@ static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
 
-    al_string_copy_cstr(&device->DeviceName, name);
+    alstr_copy_cstr(&device->DeviceName, name);
     return ALC_NO_ERROR;
 }
 
@@ -124,13 +124,8 @@ static ALCbackend* ALCloopbackFactory_createBackend(ALCloopbackFactory* UNUSED(s
     if(type == ALCbackend_Loopback)
     {
         ALCloopback *backend;
-
-        backend = ALCloopback_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCloopback)(device);
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCloopback_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
     }
 

+ 1035 - 158
love/src/jni/openal-soft-1.17.0/Alc/backends/mmdevapi.c → love/src/jni/openal-soft-1.18.2/Alc/backends/mmdevapi.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <memory.h>
 
+#include <wtypes.h>
 #include <mmdeviceapi.h>
 #include <audioclient.h>
 #include <cguid.h>
@@ -43,6 +44,7 @@
 #include "threads.h"
 #include "compat.h"
 #include "alstring.h"
+#include "converter.h"
 
 #include "backends/base.h"
 
@@ -51,34 +53,41 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x
 DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);
 
 DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14);
+DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0);
+DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23,0xe0, 0xc0,0xff,0xee,0x7f,0x0e, 4 );
 
 #define MONO SPEAKER_FRONT_CENTER
 #define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT)
 #define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
-#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
-#define X5DOT1SIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X5DOT1REAR (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT)
 #define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
 #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT)
+#define X7DOT1_WIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_FRONT_LEFT_OF_CENTER|SPEAKER_FRONT_RIGHT_OF_CENTER)
+
+#define REFTIME_PER_SEC ((REFERENCE_TIME)10000000)
+
+#define DEVNAME_HEAD "OpenAL Soft on "
 
 
 typedef struct {
     al_string name;
+    al_string endpoint_guid; // obtained from PKEY_AudioEndpoint_GUID , set to "Unknown device GUID" if absent.
     WCHAR *devid;
 } DevMap;
 TYPEDEF_VECTOR(DevMap, vector_DevMap)
 
 static void clear_devlist(vector_DevMap *list)
 {
-    DevMap *iter, *end;
-
-    iter = VECTOR_ITER_BEGIN(*list);
-    end = VECTOR_ITER_END(*list);
-    for(;iter != end;iter++)
-    {
-        AL_STRING_DEINIT(iter->name);
-        free(iter->devid);
-    }
-    VECTOR_RESIZE(*list, 0);
+#define CLEAR_DEVMAP(i) do {     \
+    AL_STRING_DEINIT((i)->name); \
+    AL_STRING_DEINIT((i)->endpoint_guid); \
+    free((i)->devid);            \
+    (i)->devid = NULL;           \
+} while(0)
+    VECTOR_FOR_EACH(DevMap, *list, CLEAR_DEVMAP);
+    VECTOR_RESIZE(*list, 0, 0);
+#undef CLEAR_DEVMAP
 }
 
 static vector_DevMap PlaybackDevices;
@@ -102,6 +111,15 @@ typedef struct {
 #define WM_USER_Enumerate   (WM_USER+5)
 #define WM_USER_Last        (WM_USER+5)
 
+static const char MessageStr[WM_USER_Last+1-WM_USER][20] = {
+    "Open Device",
+    "Reset Device",
+    "Start Device",
+    "Stop Device",
+    "Close Device",
+    "Enumerate Devices",
+};
+
 static inline void ReturnMsgResponse(ThreadRequest *req, HRESULT res)
 {
     req->result = res;
@@ -117,16 +135,21 @@ static HRESULT WaitForResponse(ThreadRequest *req)
 }
 
 
-static void get_device_name(IMMDevice *device, al_string *name)
+static void get_device_name_and_guid(IMMDevice *device, al_string *name, al_string *guid)
 {
     IPropertyStore *ps;
     PROPVARIANT pvname;
+    PROPVARIANT pvguid;
     HRESULT hr;
 
+    alstr_copy_cstr(name, DEVNAME_HEAD);
+
     hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
     if(FAILED(hr))
     {
         WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
+        alstr_append_cstr(name, "Unknown Device Name");
+        if(guid!=NULL)alstr_copy_cstr(guid, "Unknown Device GUID");
         return;
     }
 
@@ -134,39 +157,130 @@ static void get_device_name(IMMDevice *device, al_string *name)
 
     hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname);
     if(FAILED(hr))
-        WARN("GetValue failed: 0x%08lx\n", hr);
+    {
+        WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr);
+        alstr_append_cstr(name, "Unknown Device Name");
+    }
+    else if(pvname.vt == VT_LPWSTR)
+        alstr_append_wcstr(name, pvname.pwszVal);
     else
-        al_string_copy_wcstr(name, pvname.pwszVal);
-
+    {
+        WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt);
+        alstr_append_cstr(name, "Unknown Device Name");
+    }
     PropVariantClear(&pvname);
+
+    if(guid!=NULL){
+        PropVariantInit(&pvguid);
+
+        hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&PKEY_AudioEndpoint_GUID, &pvguid);
+        if(FAILED(hr))
+        {
+            WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr);
+            alstr_copy_cstr(guid, "Unknown Device GUID");
+        }
+        else if(pvguid.vt == VT_LPWSTR)
+            alstr_copy_wcstr(guid, pvguid.pwszVal);
+        else
+        {
+            WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt);
+            alstr_copy_cstr(guid, "Unknown Device GUID");
+        }
+
+        PropVariantClear(&pvguid);
+    }
+
     IPropertyStore_Release(ps);
 }
 
-static void add_device(IMMDevice *device, vector_DevMap *list)
+static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfactor)
 {
-    LPWSTR devid;
+    IPropertyStore *ps;
+    PROPVARIANT pvform;
     HRESULT hr;
 
-    hr = IMMDevice_GetId(device, &devid);
-    if(SUCCEEDED(hr))
+    hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps);
+    if(FAILED(hr))
+    {
+        WARN("OpenPropertyStore failed: 0x%08lx\n", hr);
+        return;
+    }
+
+    PropVariantInit(&pvform);
+
+    hr = IPropertyStore_GetValue(ps, &PKEY_AudioEndpoint_FormFactor, &pvform);
+    if(FAILED(hr))
+        WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr);
+    else if(pvform.vt == VT_UI4)
+        *formfactor = pvform.ulVal;
+    else if(pvform.vt == VT_EMPTY)
+        *formfactor = UnknownFormFactor;
+    else
+        WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform.vt);
+
+    PropVariantClear(&pvform);
+    IPropertyStore_Release(ps);
+}
+
+
+static void add_device(IMMDevice *device, const WCHAR *devid, vector_DevMap *list)
+{
+    int count = 0;
+    al_string tmpname;
+    DevMap entry;
+
+    AL_STRING_INIT(tmpname);
+    AL_STRING_INIT(entry.name);
+    AL_STRING_INIT(entry.endpoint_guid);
+
+    entry.devid = strdupW(devid);
+    get_device_name_and_guid(device, &tmpname, &entry.endpoint_guid);
+
+    while(1)
     {
-        DevMap entry;
-        AL_STRING_INIT(entry.name);
+        const DevMap *iter;
+
+        alstr_copy(&entry.name, tmpname);
+        if(count != 0)
+        {
+            char str[64];
+            snprintf(str, sizeof(str), " #%d", count+1);
+            alstr_append_cstr(&entry.name, str);
+        }
+
+#define MATCH_ENTRY(i) (alstr_cmp(entry.name, (i)->name) == 0)
+        VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY);
+        if(iter == VECTOR_END(*list)) break;
+#undef MATCH_ENTRY
+        count++;
+    }
+
+    TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", alstr_get_cstr(entry.name), alstr_get_cstr(entry.endpoint_guid), entry.devid);
+    VECTOR_PUSH_BACK(*list, entry);
 
-        entry.devid = strdupW(devid);
-        get_device_name(device, &entry.name);
+    AL_STRING_DEINIT(tmpname);
+}
 
-        CoTaskMemFree(devid);
+static WCHAR *get_device_id(IMMDevice *device)
+{
+    WCHAR *devid;
+    HRESULT hr;
 
-        TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), entry.devid);
-        VECTOR_PUSH_BACK(*list, entry);
+    hr = IMMDevice_GetId(device, &devid);
+    if(FAILED(hr))
+    {
+        ERR("Failed to get device id: %lx\n", hr);
+        return NULL;
     }
+
+    return devid;
 }
 
 static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list)
 {
     IMMDeviceCollection *coll;
     IMMDevice *defdev = NULL;
+    WCHAR *defdevid = NULL;
     HRESULT hr;
     UINT count;
     UINT i;
@@ -183,32 +297,38 @@ static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ve
     if(SUCCEEDED(hr) && count > 0)
     {
         clear_devlist(list);
-        if(!VECTOR_RESERVE(*list, count+1))
-        {
-            IMMDeviceCollection_Release(coll);
-            return E_OUTOFMEMORY;
-        }
+        VECTOR_RESIZE(*list, 0, count);
 
         hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir,
                                                          eMultimedia, &defdev);
     }
     if(SUCCEEDED(hr) && defdev != NULL)
-        add_device(defdev, list);
+    {
+        defdevid = get_device_id(defdev);
+        if(defdevid)
+            add_device(defdev, defdevid, list);
+    }
 
     for(i = 0;i < count;++i)
     {
         IMMDevice *device;
+        WCHAR *devid;
 
-        if(FAILED(IMMDeviceCollection_Item(coll, i, &device)))
-            continue;
-
-        if(device != defdev)
-            add_device(device, list);
+        hr = IMMDeviceCollection_Item(coll, i, &device);
+        if(FAILED(hr)) continue;
 
+        devid = get_device_id(device);
+        if(devid)
+        {
+            if(wcscmp(devid, defdevid) != 0)
+                add_device(device, devid, list);
+            CoTaskMemFree(devid);
+        }
         IMMDevice_Release(device);
     }
 
     if(defdev) IMMDevice_Release(defdev);
+    if(defdevid) CoTaskMemFree(defdevid);
     IMMDeviceCollection_Release(coll);
 
     return S_OK;
@@ -294,7 +414,11 @@ static DWORD CALLBACK ALCmmdevProxy_messageHandler(void *ptr)
     TRACE("Starting message loop\n");
     while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last))
     {
-        TRACE("Got message %u\n", msg.message);
+        TRACE("Got message \"%s\" (0x%04x, lparam=%p, wparam=%p)\n",
+            (msg.message >= WM_USER && msg.message <= WM_USER_Last) ?
+            MessageStr[msg.message-WM_USER] : "Unknown",
+            msg.message, (void*)msg.lParam, (void*)msg.wParam
+        );
         switch(msg.message)
         {
         case WM_USER_OpenDevice:
@@ -423,7 +547,7 @@ static void ALCmmdevPlayback_stop(ALCmmdevPlayback *self);
 static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self);
 static DECLARE_FORWARD2(ALCmmdevPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
 static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, ALCuint, availableSamples)
-static ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self);
+static ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self);
 static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCmmdevPlayback)
@@ -483,9 +607,9 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg)
     if(FAILED(hr))
     {
         ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr);
-        ALCdevice_Lock(device);
+        V0(device->Backend,lock)();
         aluHandleDisconnect(device);
-        ALCdevice_Unlock(device);
+        V0(device->Backend,unlock)();
         return 1;
     }
 
@@ -500,9 +624,9 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg)
         if(FAILED(hr))
         {
             ERR("Failed to get padding: 0x%08lx\n", hr);
-            ALCdevice_Lock(device);
+            V0(device->Backend,lock)();
             aluHandleDisconnect(device);
-            ALCdevice_Unlock(device);
+            V0(device->Backend,unlock)();
             break;
         }
         self->Padding = written;
@@ -521,18 +645,18 @@ FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg)
         hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer);
         if(SUCCEEDED(hr))
         {
-            ALCdevice_Lock(device);
+            ALCmmdevPlayback_lock(self);
             aluMixData(device, buffer, len);
             self->Padding = written + len;
-            ALCdevice_Unlock(device);
+            ALCmmdevPlayback_unlock(self);
             hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0);
         }
         if(FAILED(hr))
         {
             ERR("Failed to buffer data: 0x%08lx\n", hr);
-            ALCdevice_Lock(device);
+            V0(device->Backend,lock)();
             aluHandleDisconnect(device);
-            ALCdevice_Unlock(device);
+            V0(device->Backend,unlock)();
             break;
         }
     }
@@ -582,13 +706,12 @@ static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *
     return ALC_TRUE;
 }
 
-
 static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *deviceName)
 {
     HRESULT hr = S_OK;
 
-    self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
-    self->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
+    self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
     if(self->NotifyEvent == NULL || self->MsgEvent == NULL)
     {
         ERR("Failed to create message events: %lu\n", GetLastError());
@@ -599,7 +722,7 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi
     {
         if(deviceName)
         {
-            const DevMap *iter, *end;
+            const DevMap *iter;
 
             if(VECTOR_SIZE(PlaybackDevices) == 0)
             {
@@ -609,19 +732,32 @@ static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *devi
             }
 
             hr = E_FAIL;
-            iter = VECTOR_ITER_BEGIN(PlaybackDevices);
-            end = VECTOR_ITER_END(PlaybackDevices);
-            for(;iter != end;iter++)
+#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 ||        \
+                       alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0)
+            VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
+#undef MATCH_NAME
+            if(iter == VECTOR_END(PlaybackDevices))
             {
-                if(al_string_cmp_cstr(iter->name, deviceName) == 0)
+                int len;
+                if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0)
                 {
-                    self->devid = strdupW(iter->devid);
-                    hr = S_OK;
-                    break;
+                    WCHAR *wname = calloc(sizeof(WCHAR), len);
+                    MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len);
+#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0)
+                    VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME);
+#undef MATCH_NAME
+                    free(wname);
                 }
             }
-            if(FAILED(hr))
+            if(iter == VECTOR_END(PlaybackDevices))
                 WARN("Failed to find device name matching \"%s\"\n", deviceName);
+            else
+            {
+                ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+                self->devid = strdupW(iter->devid);
+                alstr_copy(&device->DeviceName, iter->name);
+                hr = S_OK;
+            }
         }
     }
 
@@ -677,7 +813,8 @@ static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self)
     if(SUCCEEDED(hr))
     {
         self->client = ptr;
-        get_device_name(self->mmdev, &device->DeviceName);
+        if(alstr_empty(device->DeviceName))
+            get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL);
     }
 
     if(FAILED(hr))
@@ -734,6 +871,7 @@ static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self)
 static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    EndpointFormFactor formfactor = UnknownFormFactor;
     WAVEFORMATEXTENSIBLE OutputType;
     WAVEFORMATEX *wfx = NULL;
     REFERENCE_TIME min_per, buf_time;
@@ -768,8 +906,8 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
     CoTaskMemFree(wfx);
     wfx = NULL;
 
-    buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 +
-                                device->Frequency-1) / device->Frequency;
+    buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC,
+                         device->Frequency);
 
     if(!(device->Flags&DEVICE_FREQUENCY_REQUEST))
         device->Frequency = OutputType.Format.nSamplesPerSec;
@@ -783,11 +921,11 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             device->FmtChans = DevFmtQuad;
         else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1)
             device->FmtChans = DevFmtX51;
-        else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE)
-            device->FmtChans = DevFmtX51Side;
+        else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1REAR)
+            device->FmtChans = DevFmtX51Rear;
         else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1)
             device->FmtChans = DevFmtX61;
-        else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1)
+        else if(OutputType.Format.nChannels == 8 && (OutputType.dwChannelMask == X7DOT1 || OutputType.dwChannelMask == X7DOT1_WIDE))
             device->FmtChans = DevFmtX71;
         else
             ERR("Unhandled channel config: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask);
@@ -799,6 +937,9 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             OutputType.Format.nChannels = 1;
             OutputType.dwChannelMask = MONO;
             break;
+        case DevFmtAmbi3D:
+            device->FmtChans = DevFmtStereo;
+            /*fall-through*/
         case DevFmtStereo:
             OutputType.Format.nChannels = 2;
             OutputType.dwChannelMask = STEREO;
@@ -811,9 +952,9 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             OutputType.Format.nChannels = 6;
             OutputType.dwChannelMask = X5DOT1;
             break;
-        case DevFmtX51Side:
+        case DevFmtX51Rear:
             OutputType.Format.nChannels = 6;
-            OutputType.dwChannelMask = X5DOT1SIDE;
+            OutputType.dwChannelMask = X5DOT1REAR;
             break;
         case DevFmtX61:
             OutputType.Format.nChannels = 7;
@@ -894,11 +1035,11 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
             device->FmtChans = DevFmtQuad;
         else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1)
             device->FmtChans = DevFmtX51;
-        else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE)
-            device->FmtChans = DevFmtX51Side;
+        else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1REAR)
+            device->FmtChans = DevFmtX51Rear;
         else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1)
             device->FmtChans = DevFmtX61;
-        else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1)
+        else if(OutputType.Format.nChannels == 8 && (OutputType.dwChannelMask == X7DOT1 || OutputType.dwChannelMask == X7DOT1_WIDE))
             device->FmtChans = DevFmtX71;
         else
         {
@@ -936,6 +1077,10 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
         }
         OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
     }
+    get_device_formfactor(self->mmdev, &formfactor);
+    device->IsHeadphones = (device->FmtChans == DevFmtStereo &&
+                            (formfactor == Headphones || formfactor == Headset)
+                           );
 
     SetDefaultWFXChannelOrder(device);
 
@@ -951,7 +1096,7 @@ static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self)
     hr = IAudioClient_GetDevicePeriod(self->client, &min_per, NULL);
     if(SUCCEEDED(hr))
     {
-        min_len = (UINT32)((min_per*device->Frequency + 10000000-1) / 10000000);
+        min_len = (UINT32)ScaleCeil(min_per, device->Frequency, REFTIME_PER_SEC);
         /* Find the nearest multiple of the period size to the update size */
         if(min_len < device->UpdateSize)
             min_len *= (device->UpdateSize + min_len/2)/min_len;
@@ -1048,127 +1193,859 @@ static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self)
 }
 
 
-static ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self)
+static ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    return (ALint64)self->Padding * 1000000000 / device->Frequency;
+    ClockLatency ret;
+
+    ALCmmdevPlayback_lock(self);
+    ret.ClockTime = GetDeviceClockTime(device);
+    ret.Latency = self->Padding * DEVICE_CLOCK_RES / device->Frequency;
+    ALCmmdevPlayback_unlock(self);
+
+    return ret;
 }
 
 
-static inline void AppendAllDevicesList2(const DevMap *entry)
-{ AppendAllDevicesList(al_string_get_cstr(entry->name)); }
-static inline void AppendCaptureDeviceList2(const DevMap *entry)
-{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); }
+typedef struct ALCmmdevCapture {
+    DERIVE_FROM_TYPE(ALCbackend);
+    DERIVE_FROM_TYPE(ALCmmdevProxy);
 
-typedef struct ALCmmdevBackendFactory {
-    DERIVE_FROM_TYPE(ALCbackendFactory);
-} ALCmmdevBackendFactory;
-#define ALCMMDEVBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCmmdevBackendFactory, ALCbackendFactory) } }
+    WCHAR *devid;
 
-static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory *self);
-static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory *self);
-static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory *self, ALCbackend_Type type);
-static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory *self, enum DevProbe type);
-static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+    IMMDevice *mmdev;
+    IAudioClient *client;
+    IAudioCaptureClient *capture;
+    HANDLE NotifyEvent;
 
-DEFINE_ALCBACKENDFACTORY_VTABLE(ALCmmdevBackendFactory);
+    HANDLE MsgEvent;
 
+    ChannelConverter *ChannelConv;
+    SampleConverter *SampleConv;
+    ll_ringbuffer_t *Ring;
 
-static BOOL MMDevApiLoad(void)
+    volatile int killNow;
+    althrd_t thread;
+} ALCmmdevCapture;
+
+static int ALCmmdevCapture_recordProc(void *arg);
+
+static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device);
+static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self);
+static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *name);
+static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self);
+static void ALCmmdevCapture_close(ALCmmdevCapture *self);
+static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self);
+static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ALCboolean, reset)
+static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self);
+static ALCboolean ALCmmdevCapture_start(ALCmmdevCapture *self);
+static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self);
+static void ALCmmdevCapture_stop(ALCmmdevCapture *self);
+static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self);
+static ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self);
+static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCmmdevCapture)
+
+DEFINE_ALCMMDEVPROXY_VTABLE(ALCmmdevCapture);
+DEFINE_ALCBACKEND_VTABLE(ALCmmdevCapture);
+
+
+static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device)
 {
-    static HRESULT InitResult;
-    if(!ThreadHdl)
-    {
-        ThreadRequest req;
-        InitResult = E_FAIL;
+    SET_VTABLE2(ALCmmdevCapture, ALCbackend, self);
+    SET_VTABLE2(ALCmmdevCapture, ALCmmdevProxy, self);
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    ALCmmdevProxy_Construct(STATIC_CAST(ALCmmdevProxy, self));
 
-        req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
-        if(req.FinishedEvt == NULL)
-            ERR("Failed to create event: %lu\n", GetLastError());
-        else
-        {
-            ThreadHdl = CreateThread(NULL, 0, ALCmmdevProxy_messageHandler, &req, 0, &ThreadID);
-            if(ThreadHdl != NULL)
-                InitResult = WaitForResponse(&req);
-            CloseHandle(req.FinishedEvt);
-        }
-    }
-    return SUCCEEDED(InitResult);
-}
+    self->devid = NULL;
 
-static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory* UNUSED(self))
-{
-    VECTOR_INIT(PlaybackDevices);
-    VECTOR_INIT(CaptureDevices);
+    self->mmdev = NULL;
+    self->client = NULL;
+    self->capture = NULL;
+    self->NotifyEvent = NULL;
 
-    if(!MMDevApiLoad())
-        return ALC_FALSE;
-    return ALC_TRUE;
+    self->MsgEvent = NULL;
+
+    self->ChannelConv = NULL;
+    self->SampleConv = NULL;
+    self->Ring = NULL;
+
+    self->killNow = 0;
 }
 
-static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory* UNUSED(self))
+static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self)
 {
-    clear_devlist(&PlaybackDevices);
-    VECTOR_DEINIT(PlaybackDevices);
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = NULL;
 
-    clear_devlist(&CaptureDevices);
-    VECTOR_DEINIT(CaptureDevices);
+    DestroySampleConverter(&self->SampleConv);
+    DestroyChannelConverter(&self->ChannelConv);
 
-    if(ThreadHdl)
-    {
-        TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID);
-        PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
-        CloseHandle(ThreadHdl);
-        ThreadHdl = NULL;
-    }
-}
+    if(self->NotifyEvent != NULL)
+        CloseHandle(self->NotifyEvent);
+    self->NotifyEvent = NULL;
+    if(self->MsgEvent != NULL)
+        CloseHandle(self->MsgEvent);
+    self->MsgEvent = NULL;
 
-static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UNUSED(self), ALCbackend_Type type)
-{
-    if(type == ALCbackend_Playback)
-        return ALC_TRUE;
-    return ALC_FALSE;
+    free(self->devid);
+    self->devid = NULL;
+
+    ALCmmdevProxy_Destruct(STATIC_CAST(ALCmmdevProxy, self));
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
 }
 
-static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory* UNUSED(self), enum DevProbe type)
+
+FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg)
 {
-    ThreadRequest req = { NULL, 0 };
+    ALCmmdevCapture *self = arg;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ALfloat *samples = NULL;
+    size_t samplesmax = 0;
+    HRESULT hr;
 
-    req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL);
-    if(req.FinishedEvt == NULL)
-        ERR("Failed to create event: %lu\n", GetLastError());
-    else
+    hr = CoInitialize(NULL);
+    if(FAILED(hr))
     {
-        HRESULT hr = E_FAIL;
-        if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type))
-            hr = WaitForResponse(&req);
-        if(SUCCEEDED(hr)) switch(type)
+        ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr);
+        V0(device->Backend,lock)();
+        aluHandleDisconnect(device);
+        V0(device->Backend,unlock)();
+        return 1;
+    }
+
+    althrd_setname(althrd_current(), RECORD_THREAD_NAME);
+
+    while(!self->killNow)
+    {
+        UINT32 avail;
+        DWORD res;
+
+        hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail);
+        if(FAILED(hr))
+            ERR("Failed to get next packet size: 0x%08lx\n", hr);
+        else if(avail > 0)
         {
-        case ALL_DEVICE_PROBE:
-            VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2);
-            break;
+            UINT32 numsamples;
+            DWORD flags;
+            BYTE *rdata;
 
-        case CAPTURE_DEVICE_PROBE:
-            VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2);
+            hr = IAudioCaptureClient_GetBuffer(self->capture,
+                &rdata, &numsamples, &flags, NULL, NULL
+            );
+            if(FAILED(hr))
+                ERR("Failed to get capture buffer: 0x%08lx\n", hr);
+            else
+            {
+                ll_ringbuffer_data_t data[2];
+                size_t dstframes = 0;
+
+                if(self->ChannelConv)
+                {
+                    if(samplesmax < numsamples)
+                    {
+                        size_t newmax = RoundUp(numsamples, 4096);
+                        ALfloat *tmp = al_calloc(DEF_ALIGN, newmax*2*sizeof(ALfloat));
+                        al_free(samples);
+                        samples = tmp;
+                        samplesmax = newmax;
+                    }
+                    ChannelConverterInput(self->ChannelConv, rdata, samples, numsamples);
+                    rdata = (BYTE*)samples;
+                }
+
+                ll_ringbuffer_get_write_vector(self->Ring, data);
+
+                if(self->SampleConv)
+                {
+                    const ALvoid *srcdata = rdata;
+                    ALsizei srcframes = numsamples;
+
+                    dstframes = SampleConverterInput(self->SampleConv,
+                        &srcdata, &srcframes, data[0].buf, data[0].len
+                    );
+                    if(srcframes > 0 && dstframes == data[0].len && data[1].len > 0)
+                    {
+                        /* If some source samples remain, all of the first dest
+                         * block was filled, and there's space in the second
+                         * dest block, do another run for the second block.
+                         */
+                        dstframes += SampleConverterInput(self->SampleConv,
+                            &srcdata, &srcframes, data[1].buf, data[1].len
+                        );
+                    }
+                }
+                else
+                {
+                    size_t framesize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType,
+                                                           device->AmbiOrder);
+                    ALuint len1 = minu(data[0].len, numsamples);
+                    ALuint len2 = minu(data[1].len, numsamples-len1);
+
+                    memcpy(data[0].buf, rdata, len1*framesize);
+                    if(len2 > 0)
+                        memcpy(data[1].buf, rdata+len1*framesize, len2*framesize);
+                    dstframes = len1 + len2;
+                }
+
+                ll_ringbuffer_write_advance(self->Ring, dstframes);
+
+                hr = IAudioCaptureClient_ReleaseBuffer(self->capture, numsamples);
+                if(FAILED(hr)) ERR("Failed to release capture buffer: 0x%08lx\n", hr);
+            }
+        }
+
+        if(FAILED(hr))
+        {
+            V0(device->Backend,lock)();
+            aluHandleDisconnect(device);
+            V0(device->Backend,unlock)();
             break;
         }
-        CloseHandle(req.FinishedEvt);
-        req.FinishedEvt = NULL;
+
+        res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE);
+        if(res != WAIT_OBJECT_0)
+            ERR("WaitForSingleObjectEx error: 0x%lx\n", res);
     }
+
+    al_free(samples);
+    samples = NULL;
+    samplesmax = 0;
+
+    CoUninitialize();
+    return 0;
 }
 
-static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+
+static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *deviceName)
 {
-    if(type == ALCbackend_Playback)
+    HRESULT hr = S_OK;
+
+    self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    self->MsgEvent = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if(self->NotifyEvent == NULL || self->MsgEvent == NULL)
     {
-        ALCmmdevPlayback *backend;
+        ERR("Failed to create message events: %lu\n", GetLastError());
+        hr = E_FAIL;
+    }
 
-        backend = ALCmmdevPlayback_New(sizeof(*backend));
-        if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
+    if(SUCCEEDED(hr))
+    {
+        if(deviceName)
+        {
+            const DevMap *iter;
+
+            if(VECTOR_SIZE(CaptureDevices) == 0)
+            {
+                ThreadRequest req = { self->MsgEvent, 0 };
+                if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, CAPTURE_DEVICE_PROBE))
+                    (void)WaitForResponse(&req);
+            }
+
+            hr = E_FAIL;
+#define MATCH_NAME(i) (alstr_cmp_cstr((i)->name, deviceName) == 0 ||        \
+                       alstr_cmp_cstr((i)->endpoint_guid, deviceName) == 0)
+            VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
+#undef MATCH_NAME
+            if(iter == VECTOR_END(CaptureDevices))
+            {
+                int len;
+                if((len=MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, NULL, 0)) > 0)
+                {
+                    WCHAR *wname = calloc(sizeof(WCHAR), len);
+                    MultiByteToWideChar(CP_UTF8, 0, deviceName, -1, wname, len);
+#define MATCH_NAME(i) (wcscmp((i)->devid, wname) == 0)
+                    VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME);
+#undef MATCH_NAME
+                    free(wname);
+                }
+            }
+            if(iter == VECTOR_END(CaptureDevices))
+                WARN("Failed to find device name matching \"%s\"\n", deviceName);
+            else
+            {
+                ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+                self->devid = strdupW(iter->devid);
+                alstr_copy(&device->DeviceName, iter->name);
+                hr = S_OK;
+            }
+        }
+    }
 
-        ALCmmdevPlayback_Construct(backend, device);
+    if(SUCCEEDED(hr))
+    {
+        ThreadRequest req = { self->MsgEvent, 0 };
 
+        hr = E_FAIL;
+        if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+            hr = WaitForResponse(&req);
+        else
+            ERR("Failed to post thread message: %lu\n", GetLastError());
+    }
+
+    if(FAILED(hr))
+    {
+        if(self->NotifyEvent != NULL)
+            CloseHandle(self->NotifyEvent);
+        self->NotifyEvent = NULL;
+        if(self->MsgEvent != NULL)
+            CloseHandle(self->MsgEvent);
+        self->MsgEvent = NULL;
+
+        free(self->devid);
+        self->devid = NULL;
+
+        ERR("Device init failed: 0x%08lx\n", hr);
+        return ALC_INVALID_VALUE;
+    }
+    else
+    {
+        ThreadRequest req = { self->MsgEvent, 0 };
+
+        hr = E_FAIL;
+        if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+            hr = WaitForResponse(&req);
+        else
+            ERR("Failed to post thread message: %lu\n", GetLastError());
+
+        if(FAILED(hr))
+        {
+            ALCmmdevCapture_close(self);
+            if(hr == E_OUTOFMEMORY)
+               return ALC_OUT_OF_MEMORY;
+            return ALC_INVALID_VALUE;
+        }
+    }
+
+    return ALC_NO_ERROR;
+}
+
+static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    void *ptr;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr);
+    if(SUCCEEDED(hr))
+    {
+        IMMDeviceEnumerator *Enumerator = ptr;
+        if(!self->devid)
+            hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eCapture, eMultimedia, &self->mmdev);
+        else
+            hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev);
+        IMMDeviceEnumerator_Release(Enumerator);
+        Enumerator = NULL;
+    }
+    if(SUCCEEDED(hr))
+        hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
+    if(SUCCEEDED(hr))
+    {
+        self->client = ptr;
+        if(alstr_empty(device->DeviceName))
+            get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL);
+    }
+
+    if(FAILED(hr))
+    {
+        if(self->mmdev)
+            IMMDevice_Release(self->mmdev);
+        self->mmdev = NULL;
+    }
+
+    return hr;
+}
+
+
+static void ALCmmdevCapture_close(ALCmmdevCapture *self)
+{
+    ThreadRequest req = { self->MsgEvent, 0 };
+
+    if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+        (void)WaitForResponse(&req);
+
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = NULL;
+
+    CloseHandle(self->MsgEvent);
+    self->MsgEvent = NULL;
+
+    CloseHandle(self->NotifyEvent);
+    self->NotifyEvent = NULL;
+
+    free(self->devid);
+    self->devid = NULL;
+}
+
+static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self)
+{
+    if(self->client)
+        IAudioClient_Release(self->client);
+    self->client = NULL;
+
+    if(self->mmdev)
+        IMMDevice_Release(self->mmdev);
+    self->mmdev = NULL;
+}
+
+
+static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    WAVEFORMATEXTENSIBLE OutputType;
+    WAVEFORMATEX *wfx = NULL;
+    enum DevFmtType srcType;
+    REFERENCE_TIME buf_time;
+    UINT32 buffer_len;
+    void *ptr = NULL;
+    HRESULT hr;
+
+    if(self->client)
+        IAudioClient_Release(self->client);
+    self->client = NULL;
+
+    hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr);
+    if(FAILED(hr))
+    {
+        ERR("Failed to reactivate audio client: 0x%08lx\n", hr);
+        return hr;
+    }
+    self->client = ptr;
+
+    buf_time = ScaleCeil(device->UpdateSize*device->NumUpdates, REFTIME_PER_SEC,
+                         device->Frequency);
+    // Make sure buffer is at least 100ms in size
+    buf_time = maxu64(buf_time, REFTIME_PER_SEC/10);
+    device->UpdateSize = (ALuint)ScaleCeil(buf_time, device->Frequency, REFTIME_PER_SEC) /
+                         device->NumUpdates;
+
+    OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
+    switch(device->FmtChans)
+    {
+        case DevFmtMono:
+            OutputType.Format.nChannels = 1;
+            OutputType.dwChannelMask = MONO;
+            break;
+        case DevFmtStereo:
+            OutputType.Format.nChannels = 2;
+            OutputType.dwChannelMask = STEREO;
+            break;
+        case DevFmtQuad:
+            OutputType.Format.nChannels = 4;
+            OutputType.dwChannelMask = QUAD;
+            break;
+        case DevFmtX51:
+            OutputType.Format.nChannels = 6;
+            OutputType.dwChannelMask = X5DOT1;
+            break;
+        case DevFmtX51Rear:
+            OutputType.Format.nChannels = 6;
+            OutputType.dwChannelMask = X5DOT1REAR;
+            break;
+        case DevFmtX61:
+            OutputType.Format.nChannels = 7;
+            OutputType.dwChannelMask = X6DOT1;
+            break;
+        case DevFmtX71:
+            OutputType.Format.nChannels = 8;
+            OutputType.dwChannelMask = X7DOT1;
+            break;
+
+        case DevFmtAmbi3D:
+            return E_FAIL;
+    }
+    switch(device->FmtType)
+    {
+        /* NOTE: Signedness doesn't matter, the converter will handle it. */
+        case DevFmtByte:
+        case DevFmtUByte:
+            OutputType.Format.wBitsPerSample = 8;
+            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+            break;
+        case DevFmtShort:
+        case DevFmtUShort:
+            OutputType.Format.wBitsPerSample = 16;
+            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+            break;
+        case DevFmtInt:
+        case DevFmtUInt:
+            OutputType.Format.wBitsPerSample = 32;
+            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM;
+            break;
+        case DevFmtFloat:
+            OutputType.Format.wBitsPerSample = 32;
+            OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
+            break;
+    }
+    OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample;
+    OutputType.Format.nSamplesPerSec = device->Frequency;
+
+    OutputType.Format.nBlockAlign = OutputType.Format.nChannels *
+                                    OutputType.Format.wBitsPerSample / 8;
+    OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec *
+                                        OutputType.Format.nBlockAlign;
+    OutputType.Format.cbSize = sizeof(OutputType) - sizeof(OutputType.Format);
+
+    hr = IAudioClient_IsFormatSupported(self->client,
+        AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx
+    );
+    if(FAILED(hr))
+    {
+        ERR("Failed to check format support: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    DestroySampleConverter(&self->SampleConv);
+    DestroyChannelConverter(&self->ChannelConv);
+
+    if(wfx != NULL)
+    {
+        if(!(wfx->nChannels == OutputType.Format.nChannels ||
+             (wfx->nChannels == 1 && OutputType.Format.nChannels == 2) ||
+             (wfx->nChannels == 2 && OutputType.Format.nChannels == 1)))
+        {
+            ERR("Failed to get matching format, wanted: %s %s %uhz, got: %d channel%s %d-bit %luhz\n",
+                DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
+                device->Frequency, wfx->nChannels, (wfx->nChannels==1)?"":"s", wfx->wBitsPerSample,
+                wfx->nSamplesPerSec);
+            CoTaskMemFree(wfx);
+            return E_FAIL;
+        }
+
+        if(!MakeExtensible(&OutputType, wfx))
+        {
+            CoTaskMemFree(wfx);
+            return E_FAIL;
+        }
+        CoTaskMemFree(wfx);
+        wfx = NULL;
+    }
+
+    if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM))
+    {
+        if(OutputType.Format.wBitsPerSample == 8)
+            srcType = DevFmtUByte;
+        else if(OutputType.Format.wBitsPerSample == 16)
+            srcType = DevFmtShort;
+        else if(OutputType.Format.wBitsPerSample == 32)
+            srcType = DevFmtInt;
+        else
+        {
+            ERR("Unhandled integer bit depth: %d\n", OutputType.Format.wBitsPerSample);
+            return E_FAIL;
+        }
+    }
+    else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT))
+    {
+        if(OutputType.Format.wBitsPerSample == 32)
+            srcType = DevFmtFloat;
+        else
+        {
+            ERR("Unhandled float bit depth: %d\n", OutputType.Format.wBitsPerSample);
+            return E_FAIL;
+        }
+    }
+    else
+    {
+        ERR("Unhandled format sub-type\n");
+        return E_FAIL;
+    }
+
+    if(device->FmtChans == DevFmtMono && OutputType.Format.nChannels == 2)
+    {
+        self->ChannelConv = CreateChannelConverter(srcType, DevFmtStereo,
+                                                   device->FmtChans);
+        if(!self->ChannelConv)
+        {
+            ERR("Failed to create %s stereo-to-mono converter\n", DevFmtTypeString(srcType));
+            return E_FAIL;
+        }
+        TRACE("Created %s stereo-to-mono converter\n", DevFmtTypeString(srcType));
+        /* The channel converter always outputs float, so change the input type
+         * for the resampler/type-converter.
+         */
+        srcType = DevFmtFloat;
+    }
+    else if(device->FmtChans == DevFmtStereo && OutputType.Format.nChannels == 1)
+    {
+        self->ChannelConv = CreateChannelConverter(srcType, DevFmtMono,
+                                                   device->FmtChans);
+        if(!self->ChannelConv)
+        {
+            ERR("Failed to create %s mono-to-stereo converter\n", DevFmtTypeString(srcType));
+            return E_FAIL;
+        }
+        TRACE("Created %s mono-to-stereo converter\n", DevFmtTypeString(srcType));
+        srcType = DevFmtFloat;
+    }
+
+    if(device->Frequency != OutputType.Format.nSamplesPerSec || device->FmtType != srcType)
+    {
+        self->SampleConv = CreateSampleConverter(
+            srcType, device->FmtType, ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder),
+            OutputType.Format.nSamplesPerSec, device->Frequency
+        );
+        if(!self->SampleConv)
+        {
+            ERR("Failed to create converter for %s format, dst: %s %uhz, src: %s %luhz\n",
+                DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
+                device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec);
+            return E_FAIL;
+        }
+        TRACE("Created converter for %s format, dst: %s %uhz, src: %s %luhz\n",
+              DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType),
+              device->Frequency, DevFmtTypeString(srcType), OutputType.Format.nSamplesPerSec);
+    }
+
+    hr = IAudioClient_Initialize(self->client,
+        AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK,
+        buf_time, 0, &OutputType.Format, NULL
+    );
+    if(FAILED(hr))
+    {
+        ERR("Failed to initialize audio client: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    hr = IAudioClient_GetBufferSize(self->client, &buffer_len);
+    if(FAILED(hr))
+    {
+        ERR("Failed to get buffer size: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    buffer_len = maxu(device->UpdateSize*device->NumUpdates + 1, buffer_len);
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = ll_ringbuffer_create(buffer_len,
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder)
+    );
+    if(!self->Ring)
+    {
+        ERR("Failed to allocate capture ring buffer\n");
+        return E_OUTOFMEMORY;
+    }
+
+    hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent);
+    if(FAILED(hr))
+    {
+        ERR("Failed to set event handle: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    return hr;
+}
+
+
+static ALCboolean ALCmmdevCapture_start(ALCmmdevCapture *self)
+{
+    ThreadRequest req = { self->MsgEvent, 0 };
+    HRESULT hr = E_FAIL;
+
+    if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+        hr = WaitForResponse(&req);
+
+    return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
+}
+
+static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self)
+{
+    HRESULT hr;
+    void *ptr;
+
+    ResetEvent(self->NotifyEvent);
+    hr = IAudioClient_Start(self->client);
+    if(FAILED(hr))
+    {
+        ERR("Failed to start audio client: 0x%08lx\n", hr);
+        return hr;
+    }
+
+    hr = IAudioClient_GetService(self->client, &IID_IAudioCaptureClient, &ptr);
+    if(SUCCEEDED(hr))
+    {
+        self->capture = ptr;
+        self->killNow = 0;
+        if(althrd_create(&self->thread, ALCmmdevCapture_recordProc, self) != althrd_success)
+        {
+            ERR("Failed to start thread\n");
+            IAudioCaptureClient_Release(self->capture);
+            self->capture = NULL;
+            hr = E_FAIL;
+        }
+    }
+
+    if(FAILED(hr))
+    {
+        IAudioClient_Stop(self->client);
+        IAudioClient_Reset(self->client);
+    }
+
+    return hr;
+}
+
+
+static void ALCmmdevCapture_stop(ALCmmdevCapture *self)
+{
+    ThreadRequest req = { self->MsgEvent, 0 };
+    if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self)))
+        (void)WaitForResponse(&req);
+}
+
+static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self)
+{
+    int res;
+
+    if(!self->capture)
+        return;
+
+    self->killNow = 1;
+    althrd_join(self->thread, &res);
+
+    IAudioCaptureClient_Release(self->capture);
+    self->capture = NULL;
+    IAudioClient_Stop(self->client);
+    IAudioClient_Reset(self->client);
+}
+
+
+ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self)
+{
+    return (ALuint)ll_ringbuffer_read_space(self->Ring);
+}
+
+ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples)
+{
+    if(ALCmmdevCapture_availableSamples(self) < samples)
+        return ALC_INVALID_VALUE;
+    ll_ringbuffer_read(self->Ring, buffer, samples);
+    return ALC_NO_ERROR;
+}
+
+
+static inline void AppendAllDevicesList2(const DevMap *entry)
+{ AppendAllDevicesList(alstr_get_cstr(entry->name)); }
+static inline void AppendCaptureDeviceList2(const DevMap *entry)
+{ AppendCaptureDeviceList(alstr_get_cstr(entry->name)); }
+
+typedef struct ALCmmdevBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCmmdevBackendFactory;
+#define ALCMMDEVBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCmmdevBackendFactory, ALCbackendFactory) } }
+
+static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory *self);
+static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory *self);
+static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory *self, ALCbackend_Type type);
+static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCmmdevBackendFactory);
+
+
+static BOOL MMDevApiLoad(void)
+{
+    static HRESULT InitResult;
+    if(!ThreadHdl)
+    {
+        ThreadRequest req;
+        InitResult = E_FAIL;
+
+        req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL);
+        if(req.FinishedEvt == NULL)
+            ERR("Failed to create event: %lu\n", GetLastError());
+        else
+        {
+            ThreadHdl = CreateThread(NULL, 0, ALCmmdevProxy_messageHandler, &req, 0, &ThreadID);
+            if(ThreadHdl != NULL)
+                InitResult = WaitForResponse(&req);
+            CloseHandle(req.FinishedEvt);
+        }
+    }
+    return SUCCEEDED(InitResult);
+}
+
+static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory* UNUSED(self))
+{
+    VECTOR_INIT(PlaybackDevices);
+    VECTOR_INIT(CaptureDevices);
+
+    if(!MMDevApiLoad())
+        return ALC_FALSE;
+    return ALC_TRUE;
+}
+
+static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory* UNUSED(self))
+{
+    clear_devlist(&PlaybackDevices);
+    VECTOR_DEINIT(PlaybackDevices);
+
+    clear_devlist(&CaptureDevices);
+    VECTOR_DEINIT(CaptureDevices);
+
+    if(ThreadHdl)
+    {
+        TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID);
+        PostThreadMessage(ThreadID, WM_QUIT, 0, 0);
+        CloseHandle(ThreadHdl);
+        ThreadHdl = NULL;
+    }
+}
+
+static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    /* TODO: Disable capture with mmdevapi for now, since it doesn't do any
+     * rechanneling or resampling; if the device is configured for 48000hz
+     * stereo input, for example, and the app asks for 22050hz mono,
+     * initialization will fail.
+     */
+    if(type == ALCbackend_Playback || type == ALCbackend_Capture)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory* UNUSED(self), enum DevProbe type)
+{
+    ThreadRequest req = { NULL, 0 };
+
+    req.FinishedEvt = CreateEventW(NULL, FALSE, FALSE, NULL);
+    if(req.FinishedEvt == NULL)
+        ERR("Failed to create event: %lu\n", GetLastError());
+    else
+    {
+        HRESULT hr = E_FAIL;
+        if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type))
+            hr = WaitForResponse(&req);
+        if(SUCCEEDED(hr)) switch(type)
+        {
+        case ALL_DEVICE_PROBE:
+            VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2);
+            break;
+
+        case CAPTURE_DEVICE_PROBE:
+            VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2);
+            break;
+        }
+        CloseHandle(req.FinishedEvt);
+        req.FinishedEvt = NULL;
+    }
+}
+
+static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCmmdevPlayback *backend;
+        NEW_OBJ(backend, ALCmmdevPlayback)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+    if(type == ALCbackend_Capture)
+    {
+        ALCmmdevCapture *backend;
+        NEW_OBJ(backend, ALCmmdevCapture)(device);
+        if(!backend) return NULL;
         return STATIC_CAST(ALCbackend, backend);
     }
 

+ 8 - 11
love/src/jni/openal-soft-1.17.0/Alc/backends/null.c → love/src/jni/openal-soft-1.18.2/Alc/backends/null.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -51,7 +51,7 @@ static ALCboolean ALCnullBackend_start(ALCnullBackend *self);
 static void ALCnullBackend_stop(ALCnullBackend *self);
 static DECLARE_FORWARD2(ALCnullBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALCuint, availableSamples)
-static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ClockLatency, getClockLatency)
 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCnullBackend)
@@ -106,10 +106,12 @@ static int ALCnullBackend_mixerProc(void *ptr)
         }
 
         if(avail-done < device->UpdateSize)
-            al_nssleep(0, restTime);
+            al_nssleep(restTime);
         else while(avail-done >= device->UpdateSize)
         {
+            ALCnullBackend_lock(self);
             aluMixData(device, NULL, device->UpdateSize);
+            ALCnullBackend_unlock(self);
             done += device->UpdateSize;
         }
     }
@@ -128,7 +130,7 @@ static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name)
         return ALC_INVALID_VALUE;
 
     device = STATIC_CAST(ALCbackend, self)->mDevice;
-    al_string_copy_cstr(&device->DeviceName, name);
+    alstr_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 }
@@ -214,13 +216,8 @@ static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UN
     if(type == ALCbackend_Playback)
     {
         ALCnullBackend *backend;
-
-        backend = ALCnullBackend_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCnullBackend)(device);
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCnullBackend_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
     }
 

+ 1135 - 0
love/src/jni/openal-soft-1.18.2/Alc/backends/opensl.c

@@ -0,0 +1,1135 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* This is an OpenAL backend for Android using the native audio APIs based on
+ * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app
+ * bundled with NDK.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <jni.h>
+
+#include "alMain.h"
+#include "alu.h"
+#include "compat.h"
+#include "threads.h"
+
+#include "backends/base.h"
+
+#include <SLES/OpenSLES.h>
+#include <SLES/OpenSLES_Android.h>
+#include <SLES/OpenSLES_AndroidConfiguration.h>
+
+/* Helper macros */
+#define VCALL(obj, func)  ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
+#define VCALL0(obj, func)  ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
+
+
+static const ALCchar opensl_device[] = "OpenSL";
+
+
+static SLuint32 GetChannelMask(enum DevFmtChannels chans)
+{
+    switch(chans)
+    {
+        case DevFmtMono: return SL_SPEAKER_FRONT_CENTER;
+        case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT;
+        case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
+                                SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
+        case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
+                               SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
+                               SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
+        case DevFmtX51Rear: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
+                                   SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
+                                   SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT;
+        case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
+                               SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
+                               SL_SPEAKER_BACK_CENTER|
+                               SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
+        case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT|
+                               SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY|
+                               SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT|
+                               SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT;
+        case DevFmtAmbi3D:
+            break;
+    }
+    return 0;
+}
+
+#ifdef SL_DATAFORMAT_PCM_EX
+static SLuint32 GetTypeRepresentation(enum DevFmtType type)
+{
+    switch(type)
+    {
+        case DevFmtUByte:
+        case DevFmtUShort:
+        case DevFmtUInt:
+            return SL_PCM_REPRESENTATION_UNSIGNED_INT;
+        case DevFmtByte:
+        case DevFmtShort:
+        case DevFmtInt:
+            return SL_PCM_REPRESENTATION_SIGNED_INT;
+        case DevFmtFloat:
+            return SL_PCM_REPRESENTATION_FLOAT;
+    }
+    return 0;
+}
+#endif
+
+static const char *res_str(SLresult result)
+{
+    switch(result)
+    {
+        case SL_RESULT_SUCCESS: return "Success";
+        case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated";
+        case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid";
+        case SL_RESULT_MEMORY_FAILURE: return "Memory failure";
+        case SL_RESULT_RESOURCE_ERROR: return "Resource error";
+        case SL_RESULT_RESOURCE_LOST: return "Resource lost";
+        case SL_RESULT_IO_ERROR: return "I/O error";
+        case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient";
+        case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted";
+        case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported";
+        case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found";
+        case SL_RESULT_PERMISSION_DENIED: return "Permission denied";
+        case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported";
+        case SL_RESULT_INTERNAL_ERROR: return "Internal error";
+        case SL_RESULT_UNKNOWN_ERROR: return "Unknown error";
+        case SL_RESULT_OPERATION_ABORTED: return "Operation aborted";
+        case SL_RESULT_CONTROL_LOST: return "Control lost";
+#ifdef SL_RESULT_READONLY
+        case SL_RESULT_READONLY: return "ReadOnly";
+#endif
+#ifdef SL_RESULT_ENGINEOPTION_UNSUPPORTED
+        case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported";
+#endif
+#ifdef SL_RESULT_SOURCE_SINK_INCOMPATIBLE
+        case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible";
+#endif
+    }
+    return "Unknown error code";
+}
+
+#define PRINTERR(x, s) do {                                                      \
+    if((x) != SL_RESULT_SUCCESS)                                                 \
+        ERR("%s: %s\n", (s), res_str((x)));                                      \
+} while(0)
+
+
+typedef struct ALCopenslPlayback {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    /* engine interfaces */
+    SLObjectItf mEngineObj;
+    SLEngineItf mEngine;
+
+    /* output mix interfaces */
+    SLObjectItf mOutputMix;
+
+    /* buffer queue player interfaces */
+    SLObjectItf mBufferQueueObj;
+
+    ll_ringbuffer_t *mRing;
+    alcnd_t mCond;
+
+    ALsizei mFrameSize;
+
+    ATOMIC(ALenum) mKillNow;
+    althrd_t mThread;
+} ALCopenslPlayback;
+
+static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf bq, void *context);
+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);
+static DECLARE_FORWARD2(ALCopenslPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, ALCuint, availableSamples)
+static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self);
+static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCopenslPlayback, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCopenslPlayback)
+
+DEFINE_ALCBACKEND_VTABLE(ALCopenslPlayback);
+
+
+static void ALCopenslPlayback_Construct(ALCopenslPlayback *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCopenslPlayback, ALCbackend, self);
+
+    self->mEngineObj = NULL;
+    self->mEngine = NULL;
+    self->mOutputMix = NULL;
+    self->mBufferQueueObj = NULL;
+
+    self->mRing = NULL;
+    alcnd_init(&self->mCond);
+
+    self->mFrameSize = 0;
+
+    ATOMIC_INIT(&self->mKillNow, AL_FALSE);
+}
+
+static void ALCopenslPlayback_Destruct(ALCopenslPlayback* self)
+{
+    if(self->mBufferQueueObj != NULL)
+        VCALL0(self->mBufferQueueObj,Destroy)();
+    self->mBufferQueueObj = NULL;
+
+    if(self->mOutputMix != NULL)
+        VCALL0(self->mOutputMix,Destroy)();
+    self->mOutputMix = NULL;
+
+    if(self->mEngineObj != NULL)
+        VCALL0(self->mEngineObj,Destroy)();
+    self->mEngineObj = NULL;
+    self->mEngine = NULL;
+
+    ll_ringbuffer_free(self->mRing);
+    self->mRing = NULL;
+
+    alcnd_destroy(&self->mCond);
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+/* this callback handler is called every time a buffer finishes playing */
+static void ALCopenslPlayback_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), void *context)
+{
+    ALCopenslPlayback *self = context;
+
+    /* A note on the ringbuffer usage: The buffer queue seems to hold on to the
+     * pointer passed to the Enqueue method, rather than copying the audio.
+     * Consequently, the ringbuffer contains the audio that is currently queued
+     * and waiting to play. This process() callback is called when a buffer is
+     * finished, so we simply move the read pointer up to indicate the space is
+     * available for writing again, and wake up the mixer thread to mix and
+     * queue more audio.
+     */
+    ll_ringbuffer_read_advance(self->mRing, 1);
+
+    alcnd_signal(&self->mCond);
+}
+
+
+static int ALCopenslPlayback_mixerProc(void *arg)
+{
+    ALCopenslPlayback *self = arg;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    SLAndroidSimpleBufferQueueItf bufferQueue;
+    ll_ringbuffer_data_t data[2];
+    SLPlayItf player;
+    SLresult result;
+    size_t padding;
+
+    SetRTPriority();
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
+
+    result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
+                                                       &bufferQueue);
+    PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDSIMPLEBUFFERQUEUE");
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
+        PRINTERR(result, "bufferQueue->GetInterface SL_IID_PLAY");
+    }
+    if(SL_RESULT_SUCCESS != result)
+    {
+        ALCopenslPlayback_lock(self);
+        aluHandleDisconnect(device);
+        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)
+    {
+        size_t todo, len0, len1;
+
+        if(ll_ringbuffer_write_space(self->mRing) <= padding)
+        {
+            SLuint32 state = 0;
+
+            result = VCALL(player,GetPlayState)(&state);
+            PRINTERR(result, "player->GetPlayState");
+            if(SL_RESULT_SUCCESS == result && state != SL_PLAYSTATE_PLAYING)
+            {
+                result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING);
+                PRINTERR(result, "player->SetPlayState");
+            }
+            if(SL_RESULT_SUCCESS != result)
+            {
+                aluHandleDisconnect(device);
+                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)
+            {
+                alcnd_wait(&self->mCond, &STATIC_CAST(ALCbackend,self)->mMutex);
+                continue;
+            }
+        }
+
+        ll_ringbuffer_get_write_vector(self->mRing, data);
+        todo = data[0].len+data[1].len - padding;
+
+        len0 = minu(todo, data[0].len);
+        len1 = minu(todo-len0, data[1].len);
+
+        aluMixData(device, data[0].buf, len0*device->UpdateSize);
+        for(size_t i = 0;i < len0;i++)
+        {
+            result = VCALL(bufferQueue,Enqueue)(data[0].buf, device->UpdateSize*self->mFrameSize);
+            PRINTERR(result, "bufferQueue->Enqueue");
+            if(SL_RESULT_SUCCESS == result)
+                ll_ringbuffer_write_advance(self->mRing, 1);
+
+            data[0].buf += device->UpdateSize*self->mFrameSize;
+        }
+
+        if(len1 > 0)
+        {
+            aluMixData(device, data[1].buf, len1*device->UpdateSize);
+            for(size_t i = 0;i < len1;i++)
+            {
+                result = VCALL(bufferQueue,Enqueue)(data[1].buf, device->UpdateSize*self->mFrameSize);
+                PRINTERR(result, "bufferQueue->Enqueue");
+                if(SL_RESULT_SUCCESS == result)
+                    ll_ringbuffer_write_advance(self->mRing, 1);
+
+                data[1].buf += device->UpdateSize*self->mFrameSize;
+            }
+        }
+    }
+    ALCopenslPlayback_unlock(self);
+
+    return 0;
+}
+
+
+static ALCenum ALCopenslPlayback_open(ALCopenslPlayback *self, const ALCchar *name)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    SLresult result;
+
+    if(!name)
+        name = opensl_device;
+    else if(strcmp(name, opensl_device) != 0)
+        return ALC_INVALID_VALUE;
+
+    // create engine
+    result = slCreateEngine(&self->mEngineObj, 0, NULL, 0, NULL, NULL);
+    PRINTERR(result, "slCreateEngine");
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mEngineObj,Realize)(SL_BOOLEAN_FALSE);
+        PRINTERR(result, "engine->Realize");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mEngineObj,GetInterface)(SL_IID_ENGINE, &self->mEngine);
+        PRINTERR(result, "engine->GetInterface");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mEngine,CreateOutputMix)(&self->mOutputMix, 0, NULL, NULL);
+        PRINTERR(result, "engine->CreateOutputMix");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mOutputMix,Realize)(SL_BOOLEAN_FALSE);
+        PRINTERR(result, "outputMix->Realize");
+    }
+
+    if(SL_RESULT_SUCCESS != result)
+    {
+        if(self->mOutputMix != NULL)
+            VCALL0(self->mOutputMix,Destroy)();
+        self->mOutputMix = NULL;
+
+        if(self->mEngineObj != NULL)
+            VCALL0(self->mEngineObj,Destroy)();
+        self->mEngineObj = NULL;
+        self->mEngine = NULL;
+
+        return ALC_INVALID_VALUE;
+    }
+
+    alstr_copy_cstr(&device->DeviceName, name);
+
+    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;
+    SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
+    SLDataLocator_OutputMix loc_outmix;
+    SLDataSource audioSrc;
+    SLDataSink audioSnk;
+    ALuint sampleRate;
+    SLInterfaceID ids[2];
+    SLboolean reqs[2];
+    SLresult result;
+    JNIEnv *env;
+
+    if(self->mBufferQueueObj != NULL)
+        VCALL0(self->mBufferQueueObj,Destroy)();
+    self->mBufferQueueObj = NULL;
+
+    sampleRate = device->Frequency;
+    if(!(device->Flags&DEVICE_FREQUENCY_REQUEST) && (env=Android_GetJNIEnv()) != NULL)
+    {
+        /* FIXME: Disabled until I figure out how to get the Context needed for
+         * the getSystemService call.
+         */
+#if 0
+        /* Get necessary stuff for using java.lang.Integer,
+         * android.content.Context, and android.media.AudioManager.
+         */
+        jclass int_cls = JCALL(env,FindClass)("java/lang/Integer");
+        jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls,
+            "parseInt", "(Ljava/lang/String;)I"
+        );
+        TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint);
+
+        jclass ctx_cls = JCALL(env,FindClass)("android/content/Context");
+        jfieldID ctx_audsvc = JCALL(env,GetStaticFieldID)(ctx_cls,
+            "AUDIO_SERVICE", "Ljava/lang/String;"
+        );
+        jmethodID ctx_getSysSvc = JCALL(env,GetMethodID)(ctx_cls,
+            "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"
+        );
+        TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n",
+              ctx_cls, ctx_audsvc, ctx_getSysSvc);
+
+        jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager");
+        jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls,
+            "PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;"
+        );
+        jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls,
+            "getProperty", "(Ljava/lang/String;)Ljava/lang/String;"
+        );
+        TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n",
+              audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty);
+
+        const char *strchars;
+        jstring strobj;
+
+        /* Now make the calls. */
+        //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
+        strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc);
+        jobject audMgr = JCALL(env,CallObjectMethod)(ctx_cls, ctx_getSysSvc, strobj);
+        strchars = JCALL(env,GetStringUTFChars)(strobj, NULL);
+        TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr);
+        JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
+
+        //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE);
+        strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate);
+        jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj);
+        strchars = JCALL(env,GetStringUTFChars)(strobj, NULL);
+        TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr);
+        JCALL(env,ReleaseStringUTFChars)(strobj, strchars);
+
+        //int sampleRate = Integer.parseInt(srateStr);
+        sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr);
+
+        strchars = JCALL(env,GetStringUTFChars)(srateStr, NULL);
+        TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars);
+        JCALL(env,ReleaseStringUTFChars)(srateStr, strchars);
+
+        if(!sampleRate) sampleRate = device->Frequency;
+        else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE);
+#endif
+    }
+
+    if(sampleRate != device->Frequency)
+    {
+        device->NumUpdates = (device->NumUpdates*sampleRate + (device->Frequency>>1)) /
+                             device->Frequency;
+        device->NumUpdates = maxu(device->NumUpdates, 2);
+        device->Frequency = sampleRate;
+    }
+
+    device->FmtChans = DevFmtStereo;
+    device->FmtType = DevFmtShort;
+
+    SetDefaultWFXChannelOrder(device);
+    self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+
+
+    loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
+    loc_bufq.numBuffers = device->NumUpdates;
+
+#ifdef SL_DATAFORMAT_PCM_EX
+    SLDataFormat_PCM_EX format_pcm;
+    format_pcm.formatType = SL_DATAFORMAT_PCM_EX;
+    format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    format_pcm.sampleRate = device->Frequency * 1000;
+    format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
+    format_pcm.containerSize = format_pcm.bitsPerSample;
+    format_pcm.channelMask = GetChannelMask(device->FmtChans);
+    format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
+                                               SL_BYTEORDER_BIGENDIAN;
+    format_pcm.representation = GetTypeRepresentation(device->FmtType);
+#else
+    SLDataFormat_PCM format_pcm;
+    format_pcm.formatType = SL_DATAFORMAT_PCM;
+    format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    format_pcm.samplesPerSec = device->Frequency * 1000;
+    format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
+    format_pcm.containerSize = format_pcm.bitsPerSample;
+    format_pcm.channelMask = GetChannelMask(device->FmtChans);
+    format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
+                                               SL_BYTEORDER_BIGENDIAN;
+#endif
+
+    audioSrc.pLocator = &loc_bufq;
+    audioSrc.pFormat = &format_pcm;
+
+    loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX;
+    loc_outmix.outputMix = self->mOutputMix;
+    audioSnk.pLocator = &loc_outmix;
+    audioSnk.pFormat = NULL;
+
+
+    ids[0]  = SL_IID_ANDROIDSIMPLEBUFFERQUEUE;
+    reqs[0] = SL_BOOLEAN_TRUE;
+    ids[1]  = SL_IID_ANDROIDCONFIGURATION;
+    reqs[1] = SL_BOOLEAN_FALSE;
+
+    result = VCALL(self->mEngine,CreateAudioPlayer)(&self->mBufferQueueObj,
+        &audioSrc, &audioSnk, COUNTOF(ids), ids, reqs
+    );
+    PRINTERR(result, "engine->CreateAudioPlayer");
+    if(SL_RESULT_SUCCESS == result)
+    {
+        /* Set the stream type to "media" (games, music, etc), if possible. */
+        SLAndroidConfigurationItf config;
+        result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
+        PRINTERR(result, "bufferQueue->GetInterface SL_IID_ANDROIDCONFIGURATION");
+        if(SL_RESULT_SUCCESS == result)
+        {
+            SLint32 streamType = SL_ANDROID_STREAM_MEDIA;
+            result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_STREAM_TYPE,
+                &streamType, sizeof(streamType)
+            );
+            PRINTERR(result, "config->SetConfiguration");
+        }
+
+        /* Clear any error since this was optional. */
+        result = SL_RESULT_SUCCESS;
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mBufferQueueObj,Realize)(SL_BOOLEAN_FALSE);
+        PRINTERR(result, "bufferQueue->Realize");
+    }
+
+    if(SL_RESULT_SUCCESS != result)
+    {
+        if(self->mBufferQueueObj != NULL)
+            VCALL0(self->mBufferQueueObj,Destroy)();
+        self->mBufferQueueObj = NULL;
+
+        return ALC_FALSE;
+    }
+
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCopenslPlayback_start(ALCopenslPlayback *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    SLAndroidSimpleBufferQueueItf bufferQueue;
+    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);
+
+    result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
+                                                       &bufferQueue);
+    PRINTERR(result, "bufferQueue->GetInterface");
+    if(SL_RESULT_SUCCESS != result)
+        return ALC_FALSE;
+
+    result = VCALL(bufferQueue,RegisterCallback)(ALCopenslPlayback_process, self);
+    PRINTERR(result, "bufferQueue->RegisterCallback");
+    if(SL_RESULT_SUCCESS != result)
+        return ALC_FALSE;
+
+    ATOMIC_STORE_SEQ(&self->mKillNow, AL_FALSE);
+    if(althrd_create(&self->mThread, ALCopenslPlayback_mixerProc, self) != althrd_success)
+    {
+        ERR("Failed to start mixer thread\n");
+        return ALC_FALSE;
+    }
+
+    return ALC_TRUE;
+}
+
+
+static void ALCopenslPlayback_stop(ALCopenslPlayback *self)
+{
+    SLAndroidSimpleBufferQueueItf bufferQueue;
+    SLPlayItf player;
+    SLresult result;
+    int res;
+
+    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);
+    althrd_join(self->mThread, &res);
+
+    result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_PLAY, &player);
+    PRINTERR(result, "bufferQueue->GetInterface");
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(player,SetPlayState)(SL_PLAYSTATE_STOPPED);
+        PRINTERR(result, "player->SetPlayState");
+    }
+
+    result = VCALL(self->mBufferQueueObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
+                                                       &bufferQueue);
+    PRINTERR(result, "bufferQueue->GetInterface");
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL0(bufferQueue,Clear)();
+        PRINTERR(result, "bufferQueue->Clear");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(bufferQueue,RegisterCallback)(NULL, NULL);
+        PRINTERR(result, "bufferQueue->RegisterCallback");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        SLAndroidSimpleBufferQueueState state;
+        do {
+            althrd_yield();
+            result = VCALL(bufferQueue,GetState)(&state);
+        } while(SL_RESULT_SUCCESS == result && state.count > 0);
+        PRINTERR(result, "bufferQueue->GetState");
+    }
+
+    ll_ringbuffer_free(self->mRing);
+    self->mRing = NULL;
+}
+
+static ClockLatency ALCopenslPlayback_getClockLatency(ALCopenslPlayback *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ClockLatency ret;
+
+    ALCopenslPlayback_lock(self);
+    ret.ClockTime = GetDeviceClockTime(device);
+    ret.Latency = ll_ringbuffer_read_space(self->mRing)*device->UpdateSize *
+                  DEVICE_CLOCK_RES / device->Frequency;
+    ALCopenslPlayback_unlock(self);
+
+    return ret;
+}
+
+
+typedef struct ALCopenslCapture {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    /* engine interfaces */
+    SLObjectItf mEngineObj;
+    SLEngineItf mEngine;
+
+    /* recording interfaces */
+    SLObjectItf mRecordObj;
+
+    ll_ringbuffer_t *mRing;
+    ALCuint mSplOffset;
+
+    ALsizei mFrameSize;
+} ALCopenslCapture;
+
+static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf bq, void *context);
+
+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);
+static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALCuint ALCopenslCapture_availableSamples(ALCopenslCapture *self);
+static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCopenslCapture, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCopenslCapture)
+DEFINE_ALCBACKEND_VTABLE(ALCopenslCapture);
+
+
+static void ALCopenslCapture_process(SLAndroidSimpleBufferQueueItf UNUSED(bq), void *context)
+{
+    ALCopenslCapture *self = context;
+    /* A new chunk has been written into the ring buffer, advance it. */
+    ll_ringbuffer_write_advance(self->mRing, 1);
+}
+
+
+static void ALCopenslCapture_Construct(ALCopenslCapture *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCopenslCapture, ALCbackend, self);
+
+    self->mEngineObj = NULL;
+    self->mEngine = NULL;
+
+    self->mRecordObj = NULL;
+
+    self->mRing = NULL;
+    self->mSplOffset = 0;
+
+    self->mFrameSize = 0;
+}
+
+static void ALCopenslCapture_Destruct(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;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+static ALCenum ALCopenslCapture_open(ALCopenslCapture *self, const ALCchar *name)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    SLDataLocator_AndroidSimpleBufferQueue loc_bq;
+    SLAndroidSimpleBufferQueueItf bufferQueue;
+    SLDataLocator_IODevice loc_dev;
+    SLDataSource audioSrc;
+    SLDataSink audioSnk;
+    SLresult result;
+
+    if(!name)
+        name = opensl_device;
+    else if(strcmp(name, opensl_device) != 0)
+        return ALC_INVALID_VALUE;
+
+    result = slCreateEngine(&self->mEngineObj, 0, NULL, 0, NULL, NULL);
+    PRINTERR(result, "slCreateEngine");
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mEngineObj,Realize)(SL_BOOLEAN_FALSE);
+        PRINTERR(result, "engine->Realize");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mEngineObj,GetInterface)(SL_IID_ENGINE, &self->mEngine);
+        PRINTERR(result, "engine->GetInterface");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        /* Ensure the total length is at least 100ms */
+        ALsizei length = maxi(device->NumUpdates * device->UpdateSize,
+                              device->Frequency / 10);
+        /* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */
+        ALsizei update_len = clampi(device->NumUpdates*device->UpdateSize / 3,
+                                    device->Frequency / 100,
+                                    device->Frequency / 100 * 5);
+
+        device->UpdateSize = update_len;
+        device->NumUpdates = (length+update_len-1) / update_len;
+
+        self->mFrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+    }
+    loc_dev.locatorType = SL_DATALOCATOR_IODEVICE;
+    loc_dev.deviceType = SL_IODEVICE_AUDIOINPUT;
+    loc_dev.deviceID = SL_DEFAULTDEVICEID_AUDIOINPUT;
+    loc_dev.device = NULL;
+
+    audioSrc.pLocator = &loc_dev;
+    audioSrc.pFormat = NULL;
+
+    loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE;
+    loc_bq.numBuffers = device->NumUpdates;
+
+#ifdef SL_DATAFORMAT_PCM_EX
+    SLDataFormat_PCM_EX format_pcm;
+    format_pcm.formatType = SL_DATAFORMAT_PCM_EX;
+    format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    format_pcm.sampleRate = device->Frequency * 1000;
+    format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
+    format_pcm.containerSize = format_pcm.bitsPerSample;
+    format_pcm.channelMask = GetChannelMask(device->FmtChans);
+    format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
+                                               SL_BYTEORDER_BIGENDIAN;
+    format_pcm.representation = GetTypeRepresentation(device->FmtType);
+#else
+    SLDataFormat_PCM format_pcm;
+    format_pcm.formatType = SL_DATAFORMAT_PCM;
+    format_pcm.numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    format_pcm.samplesPerSec = device->Frequency * 1000;
+    format_pcm.bitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
+    format_pcm.containerSize = format_pcm.bitsPerSample;
+    format_pcm.channelMask = GetChannelMask(device->FmtChans);
+    format_pcm.endianness = IS_LITTLE_ENDIAN ? SL_BYTEORDER_LITTLEENDIAN :
+                                               SL_BYTEORDER_BIGENDIAN;
+#endif
+
+    audioSnk.pLocator = &loc_bq;
+    audioSnk.pFormat = &format_pcm;
+
+    if(SL_RESULT_SUCCESS == result)
+    {
+        const SLInterfaceID ids[2] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE, SL_IID_ANDROIDCONFIGURATION };
+        const SLboolean reqs[2] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_FALSE };
+
+        result = VCALL(self->mEngine,CreateAudioRecorder)(&self->mRecordObj,
+            &audioSrc, &audioSnk, COUNTOF(ids), ids, reqs
+        );
+        PRINTERR(result, "engine->CreateAudioRecorder");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        /* Set the record preset to "generic", if possible. */
+        SLAndroidConfigurationItf config;
+        result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDCONFIGURATION, &config);
+        PRINTERR(result, "recordObj->GetInterface SL_IID_ANDROIDCONFIGURATION");
+        if(SL_RESULT_SUCCESS == result)
+        {
+            SLuint32 preset = SL_ANDROID_RECORDING_PRESET_GENERIC;
+            result = VCALL(config,SetConfiguration)(SL_ANDROID_KEY_RECORDING_PRESET,
+                &preset, sizeof(preset)
+            );
+            PRINTERR(result, "config->SetConfiguration");
+        }
+
+        /* Clear any error since this was optional. */
+        result = SL_RESULT_SUCCESS;
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(self->mRecordObj,Realize)(SL_BOOLEAN_FALSE);
+        PRINTERR(result, "recordObj->Realize");
+    }
+
+    if(SL_RESULT_SUCCESS == result)
+    {
+        self->mRing = ll_ringbuffer_create(device->NumUpdates + 1,
+                                           device->UpdateSize * self->mFrameSize);
+
+        result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
+                                                      &bufferQueue);
+        PRINTERR(result, "recordObj->GetInterface");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(bufferQueue,RegisterCallback)(ALCopenslCapture_process, self);
+        PRINTERR(result, "bufferQueue->RegisterCallback");
+    }
+    if(SL_RESULT_SUCCESS == result)
+    {
+        ALsizei chunk_size = device->UpdateSize * self->mFrameSize;
+        ll_ringbuffer_data_t data[2];
+        size_t i;
+
+        ll_ringbuffer_get_write_vector(self->mRing, data);
+        for(i = 0;i < data[0].len && SL_RESULT_SUCCESS == result;i++)
+        {
+            result = VCALL(bufferQueue,Enqueue)(data[0].buf + chunk_size*i, chunk_size);
+            PRINTERR(result, "bufferQueue->Enqueue");
+        }
+        for(i = 0;i < data[1].len && SL_RESULT_SUCCESS == result;i++)
+        {
+            result = VCALL(bufferQueue,Enqueue)(data[1].buf + chunk_size*i, chunk_size);
+            PRINTERR(result, "bufferQueue->Enqueue");
+        }
+    }
+
+    if(SL_RESULT_SUCCESS != result)
+    {
+        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;
+
+        return ALC_INVALID_VALUE;
+    }
+
+    alstr_copy_cstr(&device->DeviceName, 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;
+    SLresult result;
+
+    result = VCALL(self->mRecordObj,GetInterface)(SL_IID_RECORD, &record);
+    PRINTERR(result, "recordObj->GetInterface");
+
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(record,SetRecordState)(SL_RECORDSTATE_RECORDING);
+        PRINTERR(result, "record->SetRecordState");
+    }
+
+    if(SL_RESULT_SUCCESS != result)
+    {
+        ALCopenslCapture_lock(self);
+        aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice);
+        ALCopenslCapture_unlock(self);
+        return ALC_FALSE;
+    }
+
+    return ALC_TRUE;
+}
+
+static void ALCopenslCapture_stop(ALCopenslCapture *self)
+{
+    SLRecordItf record;
+    SLresult result;
+
+    result = VCALL(self->mRecordObj,GetInterface)(SL_IID_RECORD, &record);
+    PRINTERR(result, "recordObj->GetInterface");
+
+    if(SL_RESULT_SUCCESS == result)
+    {
+        result = VCALL(record,SetRecordState)(SL_RECORDSTATE_PAUSED);
+        PRINTERR(result, "record->SetRecordState");
+    }
+}
+
+static ALCenum ALCopenslCapture_captureSamples(ALCopenslCapture *self, ALCvoid *buffer, ALCuint samples)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ALsizei chunk_size = device->UpdateSize * self->mFrameSize;
+    SLAndroidSimpleBufferQueueItf bufferQueue;
+    ll_ringbuffer_data_t data[2];
+    SLresult result;
+    size_t advance;
+    ALCuint i;
+
+    /* Read the desired samples from the ring buffer then advance its read
+     * pointer.
+     */
+    ll_ringbuffer_get_read_vector(self->mRing, data);
+    advance = 0;
+    for(i = 0;i < samples;)
+    {
+        ALCuint rem = minu(samples - i, device->UpdateSize - self->mSplOffset);
+        memcpy((ALCbyte*)buffer + i*self->mFrameSize,
+               data[0].buf + self->mSplOffset*self->mFrameSize,
+               rem * self->mFrameSize);
+
+        self->mSplOffset += rem;
+        if(self->mSplOffset == device->UpdateSize)
+        {
+            /* Finished a chunk, reset the offset and advance the read pointer. */
+            self->mSplOffset = 0;
+            advance++;
+
+            data[0].len--;
+            if(!data[0].len)
+                data[0] = data[1];
+            else
+                data[0].buf += chunk_size;
+        }
+
+        i += rem;
+    }
+    ll_ringbuffer_read_advance(self->mRing, advance);
+
+    result = VCALL(self->mRecordObj,GetInterface)(SL_IID_ANDROIDSIMPLEBUFFERQUEUE,
+                                                  &bufferQueue);
+    PRINTERR(result, "recordObj->GetInterface");
+
+    /* Enqueue any newly-writable chunks in the ring buffer. */
+    ll_ringbuffer_get_write_vector(self->mRing, data);
+    for(i = 0;i < data[0].len && SL_RESULT_SUCCESS == result;i++)
+    {
+        result = VCALL(bufferQueue,Enqueue)(data[0].buf + chunk_size*i, chunk_size);
+        PRINTERR(result, "bufferQueue->Enqueue");
+    }
+    for(i = 0;i < data[1].len && SL_RESULT_SUCCESS == result;i++)
+    {
+        result = VCALL(bufferQueue,Enqueue)(data[1].buf + chunk_size*i, chunk_size);
+        PRINTERR(result, "bufferQueue->Enqueue");
+    }
+
+    if(SL_RESULT_SUCCESS != result)
+    {
+        ALCopenslCapture_lock(self);
+        aluHandleDisconnect(device);
+        ALCopenslCapture_unlock(self);
+        return ALC_INVALID_DEVICE;
+    }
+
+    return ALC_NO_ERROR;
+}
+
+static ALCuint ALCopenslCapture_availableSamples(ALCopenslCapture *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    return ll_ringbuffer_read_space(self->mRing) * device->UpdateSize;
+}
+
+
+typedef struct ALCopenslBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCopenslBackendFactory;
+#define ALCOPENSLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCopenslBackendFactory, ALCbackendFactory) } }
+
+static ALCboolean ALCopenslBackendFactory_init(ALCopenslBackendFactory* UNUSED(self))
+{
+    return ALC_TRUE;
+}
+
+static void ALCopenslBackendFactory_deinit(ALCopenslBackendFactory* UNUSED(self))
+{
+}
+
+static ALCboolean ALCopenslBackendFactory_querySupport(ALCopenslBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback || type == ALCbackend_Capture)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCopenslBackendFactory_probe(ALCopenslBackendFactory* UNUSED(self), enum DevProbe type)
+{
+    switch(type)
+    {
+        case ALL_DEVICE_PROBE:
+            AppendAllDevicesList(opensl_device);
+            break;
+
+        case CAPTURE_DEVICE_PROBE:
+            AppendAllDevicesList(opensl_device);
+            break;
+    }
+}
+
+static ALCbackend* ALCopenslBackendFactory_createBackend(ALCopenslBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCopenslPlayback *backend;
+        NEW_OBJ(backend, ALCopenslPlayback)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+    if(type == ALCbackend_Capture)
+    {
+        ALCopenslCapture *backend;
+        NEW_OBJ(backend, ALCopenslCapture)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}
+
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCopenslBackendFactory);
+
+
+ALCbackendFactory *ALCopenslBackendFactory_getFactory(void)
+{
+    static ALCopenslBackendFactory factory = ALCOPENSLBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}

+ 375 - 139
love/src/jni/openal-soft-1.17.0/Alc/backends/oss.c → love/src/jni/openal-soft-1.18.2/Alc/backends/oss.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -22,10 +22,12 @@
 
 #include <sys/ioctl.h>
 #include <sys/types.h>
+#include <sys/time.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <string.h>
 #include <memory.h>
 #include <unistd.h>
 #include <errno.h>
@@ -51,11 +53,176 @@
 #define SOUND_MIXER_WRITE MIXER_WRITE
 #endif
 
+#if defined(SOUND_VERSION) && (SOUND_VERSION < 0x040000)
+#define ALC_OSS_COMPAT
+#endif
+#ifndef SNDCTL_AUDIOINFO
+#define ALC_OSS_COMPAT
+#endif
+
+/*
+ * FreeBSD strongly discourages the use of specific devices,
+ * such as those returned in oss_audioinfo.devnode
+ */
+#ifdef __FreeBSD__
+#define ALC_OSS_DEVNODE_TRUC
+#endif
 
-static const ALCchar oss_device[] = "OSS Default";
+struct oss_device {
+    const ALCchar *handle;
+    const char *path;
+    struct oss_device *next;
+};
+
+static struct oss_device oss_playback = {
+    "OSS Default",
+    "/dev/dsp",
+    NULL
+};
+
+static struct oss_device oss_capture = {
+    "OSS Default",
+    "/dev/dsp",
+    NULL
+};
+
+#ifdef ALC_OSS_COMPAT
+
+#define DSP_CAP_OUTPUT 0x00020000
+#define DSP_CAP_INPUT 0x00010000
+static void ALCossListPopulate(struct oss_device *UNUSED(devlist), int UNUSED(type_flag))
+{
+}
 
-static const char *oss_driver = "/dev/dsp";
-static const char *oss_capture = "/dev/dsp";
+#else
+
+#ifndef HAVE_STRNLEN
+static size_t strnlen(const char *str, size_t maxlen)
+{
+    const char *end = memchr(str, 0, maxlen);
+    if(!end) return maxlen;
+    return end - str;
+}
+#endif
+
+static void ALCossListAppend(struct oss_device *list, const char *handle, size_t hlen, const char *path, size_t plen)
+{
+    struct oss_device *next;
+    struct oss_device *last;
+    size_t i;
+
+    /* skip the first item "OSS Default" */
+    last = list;
+    next = list->next;
+#ifdef ALC_OSS_DEVNODE_TRUC
+    for(i = 0;i < plen;i++)
+    {
+        if(path[i] == '.')
+        {
+            if(strncmp(path + i, handle + hlen + i - plen, plen - i) == 0)
+                hlen = hlen + i - plen;
+            plen = i;
+        }
+    }
+#else
+    (void)i;
+#endif
+    if(handle[0] == '\0')
+    {
+        handle = path;
+        hlen = plen;
+    }
+
+    while(next != NULL)
+    {
+        if(strncmp(next->path, path, plen) == 0)
+            return;
+        last = next;
+        next = next->next;
+    }
+
+    next = (struct oss_device*)malloc(sizeof(struct oss_device) + hlen + plen + 2);
+    next->handle = (char*)(next + 1);
+    next->path = next->handle + hlen + 1;
+    next->next = NULL;
+    last->next = next;
+
+    strncpy((char*)next->handle, handle, hlen);
+    ((char*)next->handle)[hlen] = '\0';
+    strncpy((char*)next->path, path, plen);
+    ((char*)next->path)[plen] = '\0';
+
+    TRACE("Got device \"%s\", \"%s\"\n", next->handle, next->path);
+}
+
+static void ALCossListPopulate(struct oss_device *devlist, int type_flag)
+{
+    struct oss_sysinfo si;
+    struct oss_audioinfo ai;
+    int fd, i;
+
+    if((fd=open("/dev/mixer", O_RDONLY)) < 0)
+    {
+        TRACE("Could not open /dev/mixer: %s\n", strerror(errno));
+        return;
+    }
+    if(ioctl(fd, SNDCTL_SYSINFO, &si) == -1)
+    {
+        TRACE("SNDCTL_SYSINFO failed: %s\n", strerror(errno));
+        goto done;
+    }
+    for(i = 0;i < si.numaudios;i++)
+    {
+        const char *handle;
+        size_t len;
+
+        ai.dev = i;
+        if(ioctl(fd, SNDCTL_AUDIOINFO, &ai) == -1)
+        {
+            ERR("SNDCTL_AUDIOINFO (%d) failed: %s\n", i, strerror(errno));
+            continue;
+        }
+        if(ai.devnode[0] == '\0')
+            continue;
+
+        if(ai.handle[0] != '\0')
+        {
+            len = strnlen(ai.handle, sizeof(ai.handle));
+            handle = ai.handle;
+        }
+        else
+        {
+            len = strnlen(ai.name, sizeof(ai.name));
+            handle = ai.name;
+        }
+        if((ai.caps&type_flag))
+            ALCossListAppend(devlist, handle, len, ai.devnode,
+                             strnlen(ai.devnode, sizeof(ai.devnode)));
+    }
+
+done:
+    close(fd);
+}
+
+#endif
+
+static void ALCossListFree(struct oss_device *list)
+{
+    struct oss_device *cur;
+    if(list == NULL)
+        return;
+
+    /* skip the first item "OSS Default" */
+    cur = list->next;
+    list->next = NULL;
+
+    while(cur != NULL)
+    {
+        struct oss_device *next = cur->next;
+        free(cur);
+        cur = next;
+    }
+}
 
 static int log2i(ALCuint x)
 {
@@ -68,7 +235,6 @@ static int log2i(ALCuint x)
     return y;
 }
 
-
 typedef struct ALCplaybackOSS {
     DERIVE_FROM_TYPE(ALCbackend);
 
@@ -77,7 +243,7 @@ typedef struct ALCplaybackOSS {
     ALubyte *mix_data;
     int data_size;
 
-    volatile int killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } ALCplaybackOSS;
 
@@ -92,7 +258,7 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self);
 static void ALCplaybackOSS_stop(ALCplaybackOSS *self);
 static DECLARE_FORWARD2(ALCplaybackOSS, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
 static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALCuint, availableSamples)
-static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ClockLatency, getClockLatency)
 static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCplaybackOSS)
@@ -103,42 +269,64 @@ static int ALCplaybackOSS_mixerProc(void *ptr)
 {
     ALCplaybackOSS *self = (ALCplaybackOSS*)ptr;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    ALint frameSize;
+    struct timeval timeout;
+    ALubyte *write_ptr;
+    ALint frame_size;
+    ALint to_write;
     ssize_t wrote;
+    fd_set wfds;
+    int sret;
 
     SetRTPriority();
     althrd_setname(althrd_current(), MIXER_THREAD_NAME);
 
-    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
-    while(!self->killNow && device->Connected)
+    ALCplaybackOSS_lock(self);
+    while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected)
     {
-        ALint len = self->data_size;
-        ALubyte *WritePtr = self->mix_data;
+        FD_ZERO(&wfds);
+        FD_SET(self->fd, &wfds);
+        timeout.tv_sec = 1;
+        timeout.tv_usec = 0;
+
+        ALCplaybackOSS_unlock(self);
+        sret = select(self->fd+1, NULL, &wfds, NULL, &timeout);
+        ALCplaybackOSS_lock(self);
+        if(sret < 0)
+        {
+            if(errno == EINTR)
+                continue;
+            ERR("select failed: %s\n", strerror(errno));
+            aluHandleDisconnect(device);
+            break;
+        }
+        else if(sret == 0)
+        {
+            WARN("select timeout\n");
+            continue;
+        }
 
-        aluMixData(device, WritePtr, len/frameSize);
-        while(len > 0 && !self->killNow)
+        write_ptr = self->mix_data;
+        to_write = self->data_size;
+        aluMixData(device, write_ptr, to_write/frame_size);
+        while(to_write > 0 && !ATOMIC_LOAD_SEQ(&self->killNow))
         {
-            wrote = write(self->fd, WritePtr, len);
+            wrote = write(self->fd, write_ptr, to_write);
             if(wrote < 0)
             {
-                if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR)
-                {
-                    ERR("write failed: %s\n", strerror(errno));
-                    ALCplaybackOSS_lock(self);
-                    aluHandleDisconnect(device);
-                    ALCplaybackOSS_unlock(self);
-                    break;
-                }
-
-                al_nssleep(0, 1000000);
-                continue;
+                if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+                    continue;
+                ERR("write failed: %s\n", strerror(errno));
+                aluHandleDisconnect(device);
+                break;
             }
 
-            len -= wrote;
-            WritePtr += wrote;
+            to_write -= wrote;
+            write_ptr += wrote;
         }
     }
+    ALCplaybackOSS_unlock(self);
 
     return 0;
 }
@@ -148,27 +336,45 @@ static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCplaybackOSS, ALCbackend, self);
+
+    ATOMIC_INIT(&self->killNow, AL_FALSE);
 }
 
 static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name)
 {
+    struct oss_device *dev = &oss_playback;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
 
-    if(!name)
-        name = oss_device;
-    else if(strcmp(name, oss_device) != 0)
-        return ALC_INVALID_VALUE;
-
-    self->killNow = 0;
+    if(!name || strcmp(name, dev->handle) == 0)
+        name = dev->handle;
+    else
+    {
+        if(!dev->next)
+        {
+            ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT);
+            dev = &oss_playback;
+        }
+        while(dev != NULL)
+        {
+            if (strcmp(dev->handle, name) == 0)
+                break;
+            dev = dev->next;
+        }
+        if(dev == NULL)
+        {
+            WARN("Could not find \"%s\" in device list\n", name);
+            return ALC_INVALID_VALUE;
+        }
+    }
 
-    self->fd = open(oss_driver, O_WRONLY);
+    self->fd = open(dev->path, O_WRONLY);
     if(self->fd == -1)
     {
-        ERR("Could not open %s: %s\n", oss_driver, strerror(errno));
+        ERR("Could not open %s: %s\n", dev->path, strerror(errno));
         return ALC_INVALID_VALUE;
     }
 
-    al_string_copy_cstr(&device->DeviceName, name);
+    alstr_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 }
@@ -212,18 +418,11 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self)
     }
 
     periods = device->NumUpdates;
-    numChannels = ChannelsFromDevFmt(device->FmtChans);
-    frameSize = numChannels * BytesFromDevFmt(device->FmtType);
-
+    numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     ossSpeed = device->Frequency;
-    log2FragmentSize = log2i(device->UpdateSize * frameSize);
-
-    /* according to the OSS spec, 16 bytes are the minimum */
-    if (log2FragmentSize < 4)
-        log2FragmentSize = 4;
-    /* Subtract one period since the temp mixing buffer counts as one. Still
-     * need at least two on the card, though. */
-    if(periods > 2) periods--;
+    frameSize = numChannels * BytesFromDevFmt(device->FmtType);
+    /* According to the OSS spec, 16 bytes (log2(16)) is the minimum. */
+    log2FragmentSize = maxi(log2i(device->UpdateSize*frameSize), 4);
     numFragmentsLogSize = (periods << 16) | log2FragmentSize;
 
 #define CHECKERR(func) if((func) < 0) {                                       \
@@ -245,7 +444,7 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self)
     }
 #undef CHECKERR
 
-    if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels)
+    if((int)ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != numChannels)
     {
         ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels);
         return ALC_FALSE;
@@ -261,7 +460,7 @@ static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self)
 
     device->Frequency = ossSpeed;
     device->UpdateSize = info.fragsize / frameSize;
-    device->NumUpdates = info.fragments + 1;
+    device->NumUpdates = info.fragments;
 
     SetDefaultChannelOrder(device);
 
@@ -272,10 +471,12 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
 
-    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
     self->mix_data = calloc(1, self->data_size);
 
-    self->killNow = 0;
+    ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);
     if(althrd_create(&self->thread, ALCplaybackOSS_mixerProc, self) != althrd_success)
     {
         free(self->mix_data);
@@ -290,10 +491,8 @@ static void ALCplaybackOSS_stop(ALCplaybackOSS *self)
 {
     int res;
 
-    if(self->killNow)
+    if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE))
         return;
-
-    self->killNow = 1;
     althrd_join(self->thread, &res);
 
     if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0)
@@ -309,13 +508,9 @@ typedef struct ALCcaptureOSS {
 
     int fd;
 
-    ALubyte *read_data;
-    int data_size;
-
-    RingBuffer *ring;
-    int doCapture;
+    ll_ringbuffer_t *ring;
 
-    volatile int killNow;
+    ATOMIC(ALenum) killNow;
     althrd_t thread;
 } ALCcaptureOSS;
 
@@ -330,7 +525,7 @@ static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self);
 static void ALCcaptureOSS_stop(ALCcaptureOSS *self);
 static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples);
 static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self);
-static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALint64, getLatency)
+static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ClockLatency, getClockLatency)
 static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, lock)
 static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, unlock)
 DECLARE_DEFAULT_ALLOCATORS(ALCcaptureOSS)
@@ -341,32 +536,55 @@ static int ALCcaptureOSS_recordProc(void *ptr)
 {
     ALCcaptureOSS *self = (ALCcaptureOSS*)ptr;
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
-    int frameSize;
-    int amt;
+    struct timeval timeout;
+    int frame_size;
+    fd_set rfds;
+    ssize_t amt;
+    int sret;
 
     SetRTPriority();
-    althrd_setname(althrd_current(), "alsoft-record");
+    althrd_setname(althrd_current(), RECORD_THREAD_NAME);
 
-    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
 
-    while(!self->killNow)
+    while(!ATOMIC_LOAD_SEQ(&self->killNow))
     {
-        amt = read(self->fd, self->read_data, self->data_size);
-        if(amt < 0)
+        ll_ringbuffer_data_t vec[2];
+
+        FD_ZERO(&rfds);
+        FD_SET(self->fd, &rfds);
+        timeout.tv_sec = 1;
+        timeout.tv_usec = 0;
+
+        sret = select(self->fd+1, &rfds, NULL, NULL, &timeout);
+        if(sret < 0)
         {
-            ERR("read failed: %s\n", strerror(errno));
-            ALCcaptureOSS_lock(self);
+            if(errno == EINTR)
+                continue;
+            ERR("select failed: %s\n", strerror(errno));
             aluHandleDisconnect(device);
-            ALCcaptureOSS_unlock(self);
             break;
         }
-        if(amt == 0)
+        else if(sret == 0)
         {
-            al_nssleep(0, 1000000);
+            WARN("select timeout\n");
             continue;
         }
-        if(self->doCapture)
-            WriteRingBuffer(self->ring, self->read_data, amt/frameSize);
+
+        ll_ringbuffer_get_write_vector(self->ring, vec);
+        if(vec[0].len > 0)
+        {
+            amt = read(self->fd, vec[0].buf, vec[0].len*frame_size);
+            if(amt < 0)
+            {
+                ERR("read failed: %s\n", strerror(errno));
+                ALCcaptureOSS_lock(self);
+                aluHandleDisconnect(device);
+                ALCcaptureOSS_unlock(self);
+                break;
+            }
+            ll_ringbuffer_write_advance(self->ring, amt/frame_size);
+        }
     }
 
     return 0;
@@ -377,11 +595,14 @@ static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device)
 {
     ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
     SET_VTABLE2(ALCcaptureOSS, ALCbackend, self);
+
+    ATOMIC_INIT(&self->killNow, AL_FALSE);
 }
 
 static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
 {
     ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    struct oss_device *dev = &oss_capture;
     int numFragmentsLogSize;
     int log2FragmentSize;
     unsigned int periods;
@@ -392,15 +613,32 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
     int ossSpeed;
     char *err;
 
-    if(!name)
-        name = oss_device;
-    else if(strcmp(name, oss_device) != 0)
-        return ALC_INVALID_VALUE;
+    if(!name || strcmp(name, dev->handle) == 0)
+        name = dev->handle;
+    else
+    {
+        if(!dev->next)
+        {
+            ALCossListPopulate(&oss_capture, DSP_CAP_INPUT);
+            dev = &oss_capture;
+        }
+        while(dev != NULL)
+        {
+            if (strcmp(dev->handle, name) == 0)
+                break;
+            dev = dev->next;
+        }
+        if(dev == NULL)
+        {
+            WARN("Could not find \"%s\" in device list\n", name);
+            return ALC_INVALID_VALUE;
+        }
+    }
 
-    self->fd = open(oss_capture, O_RDONLY);
+    self->fd = open(dev->path, O_RDONLY);
     if(self->fd == -1)
     {
-        ERR("Could not open %s: %s\n", oss_capture, strerror(errno));
+        ERR("Could not open %s: %s\n", dev->path, strerror(errno));
         return ALC_INVALID_VALUE;
     }
 
@@ -424,7 +662,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
     }
 
     periods = 4;
-    numChannels = ChannelsFromDevFmt(device->FmtChans);
+    numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     frameSize = numChannels * BytesFromDevFmt(device->FmtType);
     ossSpeed = device->Frequency;
     log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates *
@@ -454,7 +692,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
     }
 #undef CHECKERR
 
-    if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels)
+    if((int)ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != numChannels)
     {
         ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels);
         close(self->fd);
@@ -472,7 +710,7 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
         return ALC_INVALID_VALUE;
     }
 
-    self->ring = CreateRingBuffer(frameSize, device->UpdateSize * device->NumUpdates);
+    self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, frameSize);
     if(!self->ring)
     {
         ERR("Ring buffer create failed\n");
@@ -481,60 +719,50 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name)
         return ALC_OUT_OF_MEMORY;
     }
 
-    self->data_size = info.fragsize;
-    self->read_data = calloc(1, self->data_size);
-
-    self->killNow = 0;
-    if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success)
-    {
-        device->ExtraData = NULL;
-        close(self->fd);
-        self->fd = -1;
-        return ALC_OUT_OF_MEMORY;
-    }
-
-    al_string_copy_cstr(&device->DeviceName, name);
+    alstr_copy_cstr(&device->DeviceName, name);
 
     return ALC_NO_ERROR;
 }
 
 static void ALCcaptureOSS_close(ALCcaptureOSS *self)
 {
-    int res;
-
-    self->killNow = 1;
-    althrd_join(self->thread, &res);
-
     close(self->fd);
     self->fd = -1;
 
-    DestroyRingBuffer(self->ring);
+    ll_ringbuffer_free(self->ring);
     self->ring = NULL;
-
-    free(self->read_data);
-    self->read_data = NULL;
 }
 
 static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self)
 {
-    self->doCapture = 1;
+    ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);
+    if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success)
+        return ALC_FALSE;
     return ALC_TRUE;
 }
 
 static void ALCcaptureOSS_stop(ALCcaptureOSS *self)
 {
-    self->doCapture = 0;
+    int res;
+
+    if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE))
+        return;
+
+    althrd_join(self->thread, &res);
+
+    if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0)
+        ERR("Error resetting device: %s\n", strerror(errno));
 }
 
 static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples)
 {
-    ReadRingBuffer(self->ring, buffer, samples);
+    ll_ringbuffer_read(self->ring, buffer, samples);
     return ALC_NO_ERROR;
 }
 
 static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self)
 {
-    return RingBufferSize(self->ring);
+    return ll_ringbuffer_read_space(self->ring);
 }
 
 
@@ -546,7 +774,7 @@ typedef struct ALCossBackendFactory {
 ALCbackendFactory *ALCossBackendFactory_getFactory(void);
 
 static ALCboolean ALCossBackendFactory_init(ALCossBackendFactory *self);
-static DECLARE_FORWARD(ALCossBackendFactory, ALCbackendFactory, void, deinit)
+static void ALCossBackendFactory_deinit(ALCossBackendFactory *self);
 static ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory *self, ALCbackend_Type type);
 static void ALCossBackendFactory_probe(ALCossBackendFactory *self, enum DevProbe type);
 static ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
@@ -562,12 +790,19 @@ ALCbackendFactory *ALCossBackendFactory_getFactory(void)
 
 ALCboolean ALCossBackendFactory_init(ALCossBackendFactory* UNUSED(self))
 {
-    ConfigValueStr("oss", "device", &oss_driver);
-    ConfigValueStr("oss", "capture", &oss_capture);
+    ConfigValueStr(NULL, "oss", "device", &oss_playback.path);
+    ConfigValueStr(NULL, "oss", "capture", &oss_capture.path);
 
     return ALC_TRUE;
 }
 
+void  ALCossBackendFactory_deinit(ALCossBackendFactory* UNUSED(self))
+{
+    ALCossListFree(&oss_playback);
+    ALCossListFree(&oss_capture);
+}
+
+
 ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory* UNUSED(self), ALCbackend_Type type)
 {
     if(type == ALCbackend_Playback || type == ALCbackend_Capture)
@@ -577,27 +812,38 @@ ALCboolean ALCossBackendFactory_querySupport(ALCossBackendFactory* UNUSED(self),
 
 void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProbe type)
 {
+    struct oss_device *cur;
     switch(type)
     {
         case ALL_DEVICE_PROBE:
-        {
+            ALCossListFree(&oss_playback);
+            ALCossListPopulate(&oss_playback, DSP_CAP_OUTPUT);
+            cur = &oss_playback;
+            while(cur != NULL)
+            {
 #ifdef HAVE_STAT
-            struct stat buf;
-            if(stat(oss_driver, &buf) == 0)
+                struct stat buf;
+                if(stat(cur->path, &buf) == 0)
 #endif
-                AppendAllDevicesList(oss_device);
-        }
-        break;
+                    AppendAllDevicesList(cur->handle);
+                cur = cur->next;
+            }
+            break;
 
         case CAPTURE_DEVICE_PROBE:
-        {
+            ALCossListFree(&oss_capture);
+            ALCossListPopulate(&oss_capture, DSP_CAP_INPUT);
+            cur = &oss_capture;
+            while(cur != NULL)
+            {
 #ifdef HAVE_STAT
-            struct stat buf;
-            if(stat(oss_capture, &buf) == 0)
+                struct stat buf;
+                if(stat(cur->path, &buf) == 0)
 #endif
-                AppendCaptureDeviceList(oss_device);
-        }
-        break;
+                    AppendCaptureDeviceList(cur->handle);
+                cur = cur->next;
+            }
+            break;
     }
 }
 
@@ -606,25 +852,15 @@ ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory* UNUSED(self
     if(type == ALCbackend_Playback)
     {
         ALCplaybackOSS *backend;
-
-        backend = ALCplaybackOSS_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCplaybackOSS)(device);
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCplaybackOSS_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
     }
     if(type == ALCbackend_Capture)
     {
         ALCcaptureOSS *backend;
-
-        backend = ALCcaptureOSS_New(sizeof(*backend));
+        NEW_OBJ(backend, ALCcaptureOSS)(device);
         if(!backend) return NULL;
-        memset(backend, 0, sizeof(*backend));
-
-        ALCcaptureOSS_Construct(backend, device);
-
         return STATIC_CAST(ALCbackend, backend);
     }
 

+ 575 - 0
love/src/jni/openal-soft-1.18.2/Alc/backends/portaudio.c

@@ -0,0 +1,575 @@
+/**
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "alMain.h"
+#include "alu.h"
+#include "compat.h"
+
+#include "backends/base.h"
+
+#include <portaudio.h>
+
+
+static const ALCchar pa_device[] = "PortAudio Default";
+
+
+#ifdef HAVE_DYNLOAD
+static void *pa_handle;
+#define MAKE_FUNC(x) static __typeof(x) * p##x
+MAKE_FUNC(Pa_Initialize);
+MAKE_FUNC(Pa_Terminate);
+MAKE_FUNC(Pa_GetErrorText);
+MAKE_FUNC(Pa_StartStream);
+MAKE_FUNC(Pa_StopStream);
+MAKE_FUNC(Pa_OpenStream);
+MAKE_FUNC(Pa_CloseStream);
+MAKE_FUNC(Pa_GetDefaultOutputDevice);
+MAKE_FUNC(Pa_GetDefaultInputDevice);
+MAKE_FUNC(Pa_GetStreamInfo);
+#undef MAKE_FUNC
+
+#define Pa_Initialize                  pPa_Initialize
+#define Pa_Terminate                   pPa_Terminate
+#define Pa_GetErrorText                pPa_GetErrorText
+#define Pa_StartStream                 pPa_StartStream
+#define Pa_StopStream                  pPa_StopStream
+#define Pa_OpenStream                  pPa_OpenStream
+#define Pa_CloseStream                 pPa_CloseStream
+#define Pa_GetDefaultOutputDevice      pPa_GetDefaultOutputDevice
+#define Pa_GetDefaultInputDevice       pPa_GetDefaultInputDevice
+#define Pa_GetStreamInfo               pPa_GetStreamInfo
+#endif
+
+static ALCboolean pa_load(void)
+{
+    PaError err;
+
+#ifdef HAVE_DYNLOAD
+    if(!pa_handle)
+    {
+#ifdef _WIN32
+# define PALIB "portaudio.dll"
+#elif defined(__APPLE__) && defined(__MACH__)
+# define PALIB "libportaudio.2.dylib"
+#elif defined(__OpenBSD__)
+# define PALIB "libportaudio.so"
+#else
+# define PALIB "libportaudio.so.2"
+#endif
+
+        pa_handle = LoadLib(PALIB);
+        if(!pa_handle)
+            return ALC_FALSE;
+
+#define LOAD_FUNC(f) do {                                                     \
+    p##f = GetSymbol(pa_handle, #f);                                          \
+    if(p##f == NULL)                                                          \
+    {                                                                         \
+        CloseLib(pa_handle);                                                  \
+        pa_handle = NULL;                                                     \
+        return ALC_FALSE;                                                     \
+    }                                                                         \
+} while(0)
+        LOAD_FUNC(Pa_Initialize);
+        LOAD_FUNC(Pa_Terminate);
+        LOAD_FUNC(Pa_GetErrorText);
+        LOAD_FUNC(Pa_StartStream);
+        LOAD_FUNC(Pa_StopStream);
+        LOAD_FUNC(Pa_OpenStream);
+        LOAD_FUNC(Pa_CloseStream);
+        LOAD_FUNC(Pa_GetDefaultOutputDevice);
+        LOAD_FUNC(Pa_GetDefaultInputDevice);
+        LOAD_FUNC(Pa_GetStreamInfo);
+#undef LOAD_FUNC
+
+        if((err=Pa_Initialize()) != paNoError)
+        {
+            ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
+            CloseLib(pa_handle);
+            pa_handle = NULL;
+            return ALC_FALSE;
+        }
+    }
+#else
+    if((err=Pa_Initialize()) != paNoError)
+    {
+        ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err));
+        return ALC_FALSE;
+    }
+#endif
+    return ALC_TRUE;
+}
+
+
+typedef struct ALCportPlayback {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    PaStream *stream;
+    PaStreamParameters params;
+    ALuint update_size;
+} ALCportPlayback;
+
+static int ALCportPlayback_WriteCallback(const void *inputBuffer, void *outputBuffer,
+    unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
+    const PaStreamCallbackFlags statusFlags, void *userData);
+
+static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device);
+static void ALCportPlayback_Destruct(ALCportPlayback *self);
+static ALCenum ALCportPlayback_open(ALCportPlayback *self, const ALCchar *name);
+static void ALCportPlayback_close(ALCportPlayback *self);
+static ALCboolean ALCportPlayback_reset(ALCportPlayback *self);
+static ALCboolean ALCportPlayback_start(ALCportPlayback *self);
+static void ALCportPlayback_stop(ALCportPlayback *self);
+static DECLARE_FORWARD2(ALCportPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
+static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCportPlayback, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCportPlayback, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCportPlayback, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCportPlayback)
+
+DEFINE_ALCBACKEND_VTABLE(ALCportPlayback);
+
+
+static void ALCportPlayback_Construct(ALCportPlayback *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCportPlayback, ALCbackend, self);
+
+    self->stream = NULL;
+}
+
+static void ALCportPlayback_Destruct(ALCportPlayback *self)
+{
+    if(self->stream)
+        Pa_CloseStream(self->stream);
+    self->stream = NULL;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static int ALCportPlayback_WriteCallback(const void *UNUSED(inputBuffer), void *outputBuffer,
+    unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
+    const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
+{
+    ALCportPlayback *self = userData;
+
+    ALCportPlayback_lock(self);
+    aluMixData(STATIC_CAST(ALCbackend, self)->mDevice, outputBuffer, framesPerBuffer);
+    ALCportPlayback_unlock(self);
+    return 0;
+}
+
+
+static ALCenum ALCportPlayback_open(ALCportPlayback *self, const ALCchar *name)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    PaError err;
+
+    if(!name)
+        name = pa_device;
+    else if(strcmp(name, pa_device) != 0)
+        return ALC_INVALID_VALUE;
+
+    self->update_size = device->UpdateSize;
+
+    self->params.device = -1;
+    if(!ConfigValueInt(NULL, "port", "device", &self->params.device) ||
+       self->params.device < 0)
+        self->params.device = Pa_GetDefaultOutputDevice();
+    self->params.suggestedLatency = (device->UpdateSize*device->NumUpdates) /
+                                    (float)device->Frequency;
+    self->params.hostApiSpecificStreamInfo = NULL;
+
+    self->params.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2);
+
+    switch(device->FmtType)
+    {
+        case DevFmtByte:
+            self->params.sampleFormat = paInt8;
+            break;
+        case DevFmtUByte:
+            self->params.sampleFormat = paUInt8;
+            break;
+        case DevFmtUShort:
+            /* fall-through */
+        case DevFmtShort:
+            self->params.sampleFormat = paInt16;
+            break;
+        case DevFmtUInt:
+            /* fall-through */
+        case DevFmtInt:
+            self->params.sampleFormat = paInt32;
+            break;
+        case DevFmtFloat:
+            self->params.sampleFormat = paFloat32;
+            break;
+    }
+
+retry_open:
+    err = Pa_OpenStream(&self->stream, NULL, &self->params,
+        device->Frequency, device->UpdateSize, paNoFlag,
+        ALCportPlayback_WriteCallback, self
+    );
+    if(err != paNoError)
+    {
+        if(self->params.sampleFormat == paFloat32)
+        {
+            self->params.sampleFormat = paInt16;
+            goto retry_open;
+        }
+        ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
+        return ALC_INVALID_VALUE;
+    }
+
+    alstr_copy_cstr(&device->DeviceName, name);
+
+    return ALC_NO_ERROR;
+
+}
+
+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;
+    const PaStreamInfo *streamInfo;
+
+    streamInfo = Pa_GetStreamInfo(self->stream);
+    device->Frequency = streamInfo->sampleRate;
+    device->UpdateSize = self->update_size;
+
+    if(self->params.sampleFormat == paInt8)
+        device->FmtType = DevFmtByte;
+    else if(self->params.sampleFormat == paUInt8)
+        device->FmtType = DevFmtUByte;
+    else if(self->params.sampleFormat == paInt16)
+        device->FmtType = DevFmtShort;
+    else if(self->params.sampleFormat == paInt32)
+        device->FmtType = DevFmtInt;
+    else if(self->params.sampleFormat == paFloat32)
+        device->FmtType = DevFmtFloat;
+    else
+    {
+        ERR("Unexpected sample format: 0x%lx\n", self->params.sampleFormat);
+        return ALC_FALSE;
+    }
+
+    if(self->params.channelCount == 2)
+        device->FmtChans = DevFmtStereo;
+    else if(self->params.channelCount == 1)
+        device->FmtChans = DevFmtMono;
+    else
+    {
+        ERR("Unexpected channel count: %u\n", self->params.channelCount);
+        return ALC_FALSE;
+    }
+    SetDefaultChannelOrder(device);
+
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCportPlayback_start(ALCportPlayback *self)
+{
+    PaError err;
+
+    err = Pa_StartStream(self->stream);
+    if(err != paNoError)
+    {
+        ERR("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err));
+        return ALC_FALSE;
+    }
+
+    return ALC_TRUE;
+}
+
+static void ALCportPlayback_stop(ALCportPlayback *self)
+{
+    PaError err = Pa_StopStream(self->stream);
+    if(err != paNoError)
+        ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
+}
+
+
+typedef struct ALCportCapture {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    PaStream *stream;
+    PaStreamParameters params;
+
+    ll_ringbuffer_t *ring;
+} ALCportCapture;
+
+static int ALCportCapture_ReadCallback(const void *inputBuffer, void *outputBuffer,
+    unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo,
+    const PaStreamCallbackFlags statusFlags, void *userData);
+
+static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device);
+static void ALCportCapture_Destruct(ALCportCapture *self);
+static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name);
+static void ALCportCapture_close(ALCportCapture *self);
+static DECLARE_FORWARD(ALCportCapture, ALCbackend, ALCboolean, reset)
+static ALCboolean ALCportCapture_start(ALCportCapture *self);
+static void ALCportCapture_stop(ALCportCapture *self);
+static ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALCuint ALCportCapture_availableSamples(ALCportCapture *self);
+static DECLARE_FORWARD(ALCportCapture, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCportCapture, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCportCapture, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCportCapture)
+
+DEFINE_ALCBACKEND_VTABLE(ALCportCapture);
+
+
+static void ALCportCapture_Construct(ALCportCapture *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCportCapture, ALCbackend, self);
+
+    self->stream = NULL;
+}
+
+static void ALCportCapture_Destruct(ALCportCapture *self)
+{
+    if(self->stream)
+        Pa_CloseStream(self->stream);
+    self->stream = NULL;
+
+    if(self->ring)
+        ll_ringbuffer_free(self->ring);
+    self->ring = NULL;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static int ALCportCapture_ReadCallback(const void *inputBuffer, void *UNUSED(outputBuffer),
+    unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *UNUSED(timeInfo),
+    const PaStreamCallbackFlags UNUSED(statusFlags), void *userData)
+{
+    ALCportCapture *self = userData;
+    size_t writable = ll_ringbuffer_write_space(self->ring);
+
+    if(framesPerBuffer > writable)
+        framesPerBuffer = writable;
+    ll_ringbuffer_write(self->ring, inputBuffer, framesPerBuffer);
+    return 0;
+}
+
+
+static ALCenum ALCportCapture_open(ALCportCapture *self, const ALCchar *name)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ALuint samples, frame_size;
+    PaError err;
+
+    if(!name)
+        name = pa_device;
+    else if(strcmp(name, pa_device) != 0)
+        return ALC_INVALID_VALUE;
+
+    samples = device->UpdateSize * device->NumUpdates;
+    samples = maxu(samples, 100 * device->Frequency / 1000);
+    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+
+    self->ring = ll_ringbuffer_create(samples, frame_size);
+    if(self->ring == NULL) return ALC_INVALID_VALUE;
+
+    self->params.device = -1;
+    if(!ConfigValueInt(NULL, "port", "capture", &self->params.device) ||
+       self->params.device < 0)
+        self->params.device = Pa_GetDefaultInputDevice();
+    self->params.suggestedLatency = 0.0f;
+    self->params.hostApiSpecificStreamInfo = NULL;
+
+    switch(device->FmtType)
+    {
+        case DevFmtByte:
+            self->params.sampleFormat = paInt8;
+            break;
+        case DevFmtUByte:
+            self->params.sampleFormat = paUInt8;
+            break;
+        case DevFmtShort:
+            self->params.sampleFormat = paInt16;
+            break;
+        case DevFmtInt:
+            self->params.sampleFormat = paInt32;
+            break;
+        case DevFmtFloat:
+            self->params.sampleFormat = paFloat32;
+            break;
+        case DevFmtUInt:
+        case DevFmtUShort:
+            ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType));
+            return ALC_INVALID_VALUE;
+    }
+    self->params.channelCount = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+
+    err = Pa_OpenStream(&self->stream, &self->params, NULL,
+        device->Frequency, paFramesPerBufferUnspecified, paNoFlag,
+        ALCportCapture_ReadCallback, self
+    );
+    if(err != paNoError)
+    {
+        ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err));
+        return ALC_INVALID_VALUE;
+    }
+
+    alstr_copy_cstr(&device->DeviceName, 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)
+{
+    PaError err = Pa_StartStream(self->stream);
+    if(err != paNoError)
+    {
+        ERR("Error starting stream: %s\n", Pa_GetErrorText(err));
+        return ALC_FALSE;
+    }
+    return ALC_TRUE;
+}
+
+static void ALCportCapture_stop(ALCportCapture *self)
+{
+    PaError err = Pa_StopStream(self->stream);
+    if(err != paNoError)
+        ERR("Error stopping stream: %s\n", Pa_GetErrorText(err));
+}
+
+
+static ALCuint ALCportCapture_availableSamples(ALCportCapture *self)
+{
+    return ll_ringbuffer_read_space(self->ring);
+}
+
+static ALCenum ALCportCapture_captureSamples(ALCportCapture *self, ALCvoid *buffer, ALCuint samples)
+{
+    ll_ringbuffer_read(self->ring, buffer, samples);
+    return ALC_NO_ERROR;
+}
+
+
+typedef struct ALCportBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCportBackendFactory;
+#define ALCPORTBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCportBackendFactory, ALCbackendFactory) } }
+
+static ALCboolean ALCportBackendFactory_init(ALCportBackendFactory *self);
+static void ALCportBackendFactory_deinit(ALCportBackendFactory *self);
+static ALCboolean ALCportBackendFactory_querySupport(ALCportBackendFactory *self, ALCbackend_Type type);
+static void ALCportBackendFactory_probe(ALCportBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCportBackendFactory_createBackend(ALCportBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCportBackendFactory);
+
+
+static ALCboolean ALCportBackendFactory_init(ALCportBackendFactory* UNUSED(self))
+{
+    if(!pa_load())
+        return ALC_FALSE;
+    return ALC_TRUE;
+}
+
+static void ALCportBackendFactory_deinit(ALCportBackendFactory* UNUSED(self))
+{
+#ifdef HAVE_DYNLOAD
+    if(pa_handle)
+    {
+        Pa_Terminate();
+        CloseLib(pa_handle);
+        pa_handle = NULL;
+    }
+#else
+    Pa_Terminate();
+#endif
+}
+
+static ALCboolean ALCportBackendFactory_querySupport(ALCportBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback || type == ALCbackend_Capture)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCportBackendFactory_probe(ALCportBackendFactory* UNUSED(self), enum DevProbe type)
+{
+    switch(type)
+    {
+        case ALL_DEVICE_PROBE:
+            AppendAllDevicesList(pa_device);
+            break;
+        case CAPTURE_DEVICE_PROBE:
+            AppendCaptureDeviceList(pa_device);
+            break;
+    }
+}
+
+static ALCbackend* ALCportBackendFactory_createBackend(ALCportBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCportPlayback *backend;
+        NEW_OBJ(backend, ALCportPlayback)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+    if(type == ALCbackend_Capture)
+    {
+        ALCportCapture *backend;
+        NEW_OBJ(backend, ALCportCapture)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}
+
+ALCbackendFactory *ALCportBackendFactory_getFactory(void)
+{
+    static ALCportBackendFactory factory = ALCPORTBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}

ファイルの差分が大きいため隠しています
+ 340 - 189
love/src/jni/openal-soft-1.18.2/Alc/backends/pulseaudio.c


+ 351 - 443
love/src/jni/openal-soft-1.17.0/Alc/backends/qsa.c → love/src/jni/openal-soft-1.18.2/Alc/backends/qsa.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -33,6 +33,8 @@
 #include "alu.h"
 #include "threads.h"
 
+#include "backends/base.h"
+
 
 typedef struct {
     snd_pcm_t* pcmHandle;
@@ -53,12 +55,12 @@ typedef struct {
     int card;
     int dev;
 } DevMap;
+TYPEDEF_VECTOR(DevMap, vector_DevMap)
+
+static vector_DevMap DeviceNameMap;
+static vector_DevMap CaptureNameMap;
 
 static const ALCchar qsaDevice[] = "QSA Default";
-static DevMap* allDevNameMap;
-static ALuint numDevNames;
-static DevMap* allCaptureDevNameMap;
-static ALuint numCaptureDevNames;
 
 static const struct {
     int32_t format;
@@ -104,83 +106,93 @@ static const struct {
     {0},
 };
 
-static DevMap *deviceList(int type, ALuint *count)
+static void deviceList(int type, vector_DevMap *devmap)
 {
     snd_ctl_t* handle;
     snd_pcm_info_t pcminfo;
-    int max_cards, card, err, dev, num_devices, idx;
-    DevMap* dev_list;
+    int max_cards, card, err, dev;
+    DevMap entry;
     char name[1024];
     struct snd_ctl_hw_info info;
-    void* temp;
 
-    idx=0;
-    num_devices=0;
-    max_cards=snd_cards();
+    max_cards = snd_cards();
+    if(max_cards < 0)
+        return;
 
-    if (max_cards<=0)
-    {
-        return 0;
-    }
+    VECTOR_RESIZE(*devmap, 0, max_cards+1);
 
-    dev_list=malloc(sizeof(DevMap)*1);
-    dev_list[0].name=strdup(qsaDevice);
-    num_devices=1;
+    entry.name = strdup(qsaDevice);
+    entry.card = 0;
+    entry.dev = 0;
+    VECTOR_PUSH_BACK(*devmap, entry);
 
-    for (card=0; card<max_cards; card++)
+    for(card = 0;card < max_cards;card++)
     {
-        if ((err=snd_ctl_open(&handle, card))<0)
-        {
+        if((err=snd_ctl_open(&handle, card)) < 0)
             continue;
-        }
-        if ((err=snd_ctl_hw_info(handle, &info))<0)
+
+        if((err=snd_ctl_hw_info(handle, &info)) < 0)
         {
             snd_ctl_close(handle);
             continue;
         }
 
-        for (dev=0; dev<(int)info.pcmdevs; dev++)
+        for(dev = 0;dev < (int)info.pcmdevs;dev++)
         {
-            if ((err=snd_ctl_pcm_info(handle, dev, &pcminfo)) < 0)
-            {
+            if((err=snd_ctl_pcm_info(handle, dev, &pcminfo)) < 0)
                 continue;
-            }
 
-            if ((type==SND_PCM_CHANNEL_PLAYBACK && (pcminfo.flags&SND_PCM_INFO_PLAYBACK)) ||
-                (type==SND_PCM_CHANNEL_CAPTURE && (pcminfo.flags&SND_PCM_INFO_CAPTURE)))
+            if((type==SND_PCM_CHANNEL_PLAYBACK && (pcminfo.flags&SND_PCM_INFO_PLAYBACK)) ||
+               (type==SND_PCM_CHANNEL_CAPTURE && (pcminfo.flags&SND_PCM_INFO_CAPTURE)))
             {
-                temp=realloc(dev_list, sizeof(DevMap)*(num_devices+1));
-                if (temp)
-                {
-                    dev_list=temp;
-                    snprintf(name, sizeof(name), "%s [%s] (hw:%d,%d)", info.name, pcminfo.name, card, dev);
-                    dev_list[num_devices].name=strdup(name);
-                    dev_list[num_devices].card=card;
-                    dev_list[num_devices].dev=dev;
-                    num_devices++;
-                }
+                snprintf(name, sizeof(name), "%s [%s] (hw:%d,%d)", info.name, pcminfo.name, card, dev);
+                entry.name = strdup(name);
+                entry.card = card;
+                entry.dev = dev;
+
+                VECTOR_PUSH_BACK(*devmap, entry);
+                TRACE("Got device \"%s\", card %d, dev %d\n", name, card, dev);
             }
         }
-        snd_ctl_close (handle);
+        snd_ctl_close(handle);
     }
-
-    *count=num_devices;
-
-    return dev_list;
 }
 
 
-FORCE_ALIGN static int qsa_proc_playback(void* ptr)
+/* Wrappers to use an old-style backend with the new interface. */
+typedef struct PlaybackWrapper {
+    DERIVE_FROM_TYPE(ALCbackend);
+    qsa_data *ExtraData;
+} PlaybackWrapper;
+
+static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device);
+static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct)
+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);
+static DECLARE_FORWARD2(PlaybackWrapper, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock)
+static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper)
+DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper);
+
+
+FORCE_ALIGN static int qsa_proc_playback(void *ptr)
 {
-    ALCdevice* device=(ALCdevice*)ptr;
-    qsa_data* data=(qsa_data*)device->ExtraData;
-    char* write_ptr;
-    int avail;
+    PlaybackWrapper *self = ptr;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    qsa_data *data = self->ExtraData;
     snd_pcm_channel_status_t status;
     struct sched_param param;
-    fd_set wfds;
-    int selectret;
     struct timeval timeout;
+    char* write_ptr;
+    fd_set wfds;
+    ALint len;
+    int sret;
 
     SetRTPriority();
     althrd_setname(althrd_current(), MIXER_THREAD_NAME);
@@ -190,59 +202,55 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr)
     param.sched_priority=param.sched_curpriority+1;
     SchedSet(0, 0, SCHED_NOCHANGE, &param);
 
-    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    const ALint frame_size = FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
 
-    while (!data->killNow)
+    V0(device->Backend,lock)();
+    while(!data->killNow)
     {
-        ALint len=data->size;
-        write_ptr=data->buffer;
-
-        avail=len/frame_size;
-        aluMixData(device, write_ptr, avail);
+        FD_ZERO(&wfds);
+        FD_SET(data->audio_fd, &wfds);
+        timeout.tv_sec=2;
+        timeout.tv_usec=0;
 
-        while (len>0 && !data->killNow)
+        /* Select also works like time slice to OS */
+        V0(device->Backend,unlock)();
+        sret = select(data->audio_fd+1, NULL, &wfds, NULL, &timeout);
+        V0(device->Backend,lock)();
+        if(sret == -1)
         {
-            FD_ZERO(&wfds);
-            FD_SET(data->audio_fd, &wfds);
-            timeout.tv_sec=2;
-            timeout.tv_usec=0;
-
-            /* Select also works like time slice to OS */
-            selectret=select(data->audio_fd+1, NULL, &wfds, NULL, &timeout);
-            switch (selectret)
-            {
-                case -1:
-                     aluHandleDisconnect(device);
-                     return 1;
-                case 0:
-                     break;
-                default:
-                     if (FD_ISSET(data->audio_fd, &wfds))
-                     {
-                         break;
-                     }
-                     break;
-            }
-
-            int wrote=snd_pcm_plugin_write(data->pcmHandle, write_ptr, len);
+            ERR("select error: %s\n", strerror(errno));
+            aluHandleDisconnect(device);
+            break;
+        }
+        if(sret == 0)
+        {
+            ERR("select timeout\n");
+            continue;
+        }
 
-            if (wrote<=0)
+        len = data->size;
+        write_ptr = data->buffer;
+        aluMixData(device, write_ptr, len/frame_size);
+        while(len>0 && !data->killNow)
+        {
+            int wrote = snd_pcm_plugin_write(data->pcmHandle, write_ptr, len);
+            if(wrote <= 0)
             {
-                if ((errno==EAGAIN) || (errno==EWOULDBLOCK))
-                {
+                if(errno==EAGAIN || errno==EWOULDBLOCK)
                     continue;
-                }
 
-                memset(&status, 0, sizeof (status));
-                status.channel=SND_PCM_CHANNEL_PLAYBACK;
+                memset(&status, 0, sizeof(status));
+                status.channel = SND_PCM_CHANNEL_PLAYBACK;
 
                 snd_pcm_plugin_status(data->pcmHandle, &status);
 
                 /* we need to reinitialize the sound channel if we've underrun the buffer */
-                if ((status.status==SND_PCM_STATUS_UNDERRUN) ||
-                    (status.status==SND_PCM_STATUS_READY))
+                if(status.status == SND_PCM_STATUS_UNDERRUN ||
+                   status.status == SND_PCM_STATUS_READY)
                 {
-                    if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0)
+                    if(snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK) < 0)
                     {
                         aluHandleDisconnect(device);
                         break;
@@ -251,11 +259,12 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr)
             }
             else
             {
-                write_ptr+=wrote;
-                len-=wrote;
+                write_ptr += wrote;
+                len -= wrote;
             }
         }
     }
+    V0(device->Backend,unlock)();
 
     return 0;
 }
@@ -264,86 +273,64 @@ FORCE_ALIGN static int qsa_proc_playback(void* ptr)
 /* Playback */
 /************/
 
-static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName)
+static ALCenum qsa_open_playback(PlaybackWrapper *self, const ALCchar* deviceName)
 {
-    qsa_data* data;
-    char driver[64];
-    int status;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    qsa_data *data;
     int card, dev;
+    int status;
 
-    strncpy(driver, GetConfigValue("qsa", "device", qsaDevice), sizeof(driver)-1);
-    driver[sizeof(driver)-1]=0;
-
-    data=(qsa_data*)calloc(1, sizeof(qsa_data));
-    if (data==NULL)
-    {
+    data = (qsa_data*)calloc(1, sizeof(qsa_data));
+    if(data == NULL)
         return ALC_OUT_OF_MEMORY;
-    }
 
-    if (!deviceName)
-    {
-        deviceName=driver;
-    }
-
-    if (strcmp(deviceName, qsaDevice)==0)
-    {
-        if (!deviceName)
-        {
-            deviceName=qsaDevice;
-        }
+    if(!deviceName)
+        deviceName = qsaDevice;
 
-        status=snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK);
-    }
+    if(strcmp(deviceName, qsaDevice) == 0)
+        status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK);
     else
     {
-        size_t idx;
+        const DevMap *iter;
 
-        if (!allDevNameMap)
-        {
-            allDevNameMap=deviceList(SND_PCM_CHANNEL_PLAYBACK, &numDevNames);
-        }
+        if(VECTOR_SIZE(DeviceNameMap) == 0)
+            deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap);
 
-        for (idx=0; idx<numDevNames; idx++)
-        {
-            if (allDevNameMap[idx].name && strcmp(deviceName, allDevNameMap[idx].name)==0)
-            {
-                if (idx>0)
-                {
-                    break;
-                }
-            }
-        }
-        if (idx==numDevNames)
+#define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0)
+        VECTOR_FIND_IF(iter, const DevMap, DeviceNameMap, MATCH_DEVNAME);
+#undef MATCH_DEVNAME
+        if(iter == VECTOR_END(DeviceNameMap))
         {
             free(data);
             return ALC_INVALID_DEVICE;
         }
 
-        status=snd_pcm_open(&data->pcmHandle, allDevNameMap[idx].card, allDevNameMap[idx].dev, SND_PCM_OPEN_PLAYBACK);
+        status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_PLAYBACK);
     }
 
-    if (status<0)
+    if(status < 0)
     {
         free(data);
         return ALC_INVALID_DEVICE;
     }
 
-    data->audio_fd=snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
-    if (data->audio_fd<0)
+    data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK);
+    if(data->audio_fd < 0)
     {
+        snd_pcm_close(data->pcmHandle);
         free(data);
         return ALC_INVALID_DEVICE;
     }
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-    device->ExtraData = data;
+    alstr_copy_cstr(&device->DeviceName, deviceName);
+    self->ExtraData = data;
 
     return ALC_NO_ERROR;
 }
 
-static void qsa_close_playback(ALCdevice* device)
+static void qsa_close_playback(PlaybackWrapper *self)
 {
-    qsa_data* data=(qsa_data*)device->ExtraData;
+    qsa_data *data = self->ExtraData;
 
     if (data->buffer!=NULL)
     {
@@ -354,12 +341,13 @@ static void qsa_close_playback(ALCdevice* device)
     snd_pcm_close(data->pcmHandle);
     free(data);
 
-    device->ExtraData=NULL;
+    self->ExtraData = NULL;
 }
 
-static ALCboolean qsa_reset_playback(ALCdevice* device)
+static ALCboolean qsa_reset_playback(PlaybackWrapper *self)
 {
-    qsa_data* data=(qsa_data*)device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    qsa_data *data = self->ExtraData;
     int32_t format=-1;
 
     switch(device->FmtType)
@@ -400,14 +388,14 @@ static ALCboolean qsa_reset_playback(ALCdevice* device)
     data->cparams.start_mode=SND_PCM_START_FULL;
     data->cparams.stop_mode=SND_PCM_STOP_STOP;
 
-    data->cparams.buf.block.frag_size=device->UpdateSize*
-        ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType);
+    data->cparams.buf.block.frag_size=device->UpdateSize *
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     data->cparams.buf.block.frags_max=device->NumUpdates;
     data->cparams.buf.block.frags_min=device->NumUpdates;
 
     data->cparams.format.interleave=1;
     data->cparams.format.rate=device->Frequency;
-    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
+    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     data->cparams.format.format=format;
 
     if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
@@ -591,7 +579,7 @@ static ALCboolean qsa_reset_playback(ALCdevice* device)
     SetDefaultChannelOrder(device);
 
     device->UpdateSize=data->csetup.buf.block.frag_size/
-        (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType));
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     device->NumUpdates=data->csetup.buf.block.frags;
 
     data->size=data->csetup.buf.block.frag_size;
@@ -604,20 +592,20 @@ static ALCboolean qsa_reset_playback(ALCdevice* device)
     return ALC_TRUE;
 }
 
-static ALCboolean qsa_start_playback(ALCdevice* device)
+static ALCboolean qsa_start_playback(PlaybackWrapper *self)
 {
-    qsa_data *data = (qsa_data*)device->ExtraData;
+    qsa_data *data = self->ExtraData;
 
     data->killNow = 0;
-    if(althrd_create(&data->thread, qsa_proc_playback, device) != althrd_success)
+    if(althrd_create(&data->thread, qsa_proc_playback, self) != althrd_success)
         return ALC_FALSE;
 
     return ALC_TRUE;
 }
 
-static void qsa_stop_playback(ALCdevice* device)
+static void qsa_stop_playback(PlaybackWrapper *self)
 {
-    qsa_data *data = (qsa_data*)device->ExtraData;
+    qsa_data *data = self->ExtraData;
     int res;
 
     if(data->killNow)
@@ -627,84 +615,121 @@ static void qsa_stop_playback(ALCdevice* device)
     althrd_join(data->thread, &res);
 }
 
+
+static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(PlaybackWrapper, ALCbackend, self);
+
+    self->ExtraData = NULL;
+}
+
+static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name)
+{
+    return qsa_open_playback(self, name);
+}
+
+static void PlaybackWrapper_close(PlaybackWrapper *self)
+{
+    qsa_close_playback(self);
+}
+
+static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self)
+{
+    return qsa_reset_playback(self);
+}
+
+static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self)
+{
+    return qsa_start_playback(self);
+}
+
+static void PlaybackWrapper_stop(PlaybackWrapper *self)
+{
+    qsa_stop_playback(self);
+}
+
+
+
 /***********/
 /* Capture */
 /***********/
 
-static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
+typedef struct CaptureWrapper {
+    DERIVE_FROM_TYPE(ALCbackend);
+    qsa_data *ExtraData;
+} CaptureWrapper;
+
+static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device);
+static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct)
+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);
+static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples);
+static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self);
+static DECLARE_FORWARD(CaptureWrapper, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock)
+static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper)
+DEFINE_ALCBACKEND_VTABLE(CaptureWrapper);
+
+
+static ALCenum qsa_open_capture(CaptureWrapper *self, const ALCchar *deviceName)
 {
-    qsa_data* data;
-    int format=-1;
-    char driver[64];
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    qsa_data *data;
     int card, dev;
+    int format=-1;
     int status;
 
-    strncpy(driver, GetConfigValue("qsa", "capture", qsaDevice), sizeof(driver)-1);
-    driver[sizeof(driver)-1]=0;
-
     data=(qsa_data*)calloc(1, sizeof(qsa_data));
     if (data==NULL)
     {
         return ALC_OUT_OF_MEMORY;
     }
 
-    if (!deviceName)
-    {
-        deviceName=driver;
-    }
-
-    if (strcmp(deviceName, qsaDevice)==0)
-    {
-        if (!deviceName)
-        {
-            deviceName=qsaDevice;
-        }
+    if(!deviceName)
+        deviceName = qsaDevice;
 
-        status=snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE);
-    }
+    if(strcmp(deviceName, qsaDevice) == 0)
+        status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE);
     else
     {
-        size_t idx;
+        const DevMap *iter;
 
-        if (!allCaptureDevNameMap)
-        {
-            allCaptureDevNameMap=deviceList(SND_PCM_CHANNEL_CAPTURE, &numDevNames);
-        }
+        if(VECTOR_SIZE(CaptureNameMap) == 0)
+            deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap);
 
-        for (idx=0; idx<numDevNames; idx++)
-        {
-            if (allCaptureDevNameMap[idx].name && strcmp(deviceName, allCaptureDevNameMap[idx].name)==0)
-            {
-                if (idx>0)
-                {
-                    break;
-                }
-            }
-        }
-        if (idx==numDevNames)
+#define MATCH_DEVNAME(iter) ((iter)->name && strcmp(deviceName, (iter)->name)==0)
+        VECTOR_FIND_IF(iter, const DevMap, CaptureNameMap, MATCH_DEVNAME);
+#undef MATCH_DEVNAME
+        if(iter == VECTOR_END(CaptureNameMap))
         {
             free(data);
             return ALC_INVALID_DEVICE;
         }
 
-        status=snd_pcm_open(&data->pcmHandle, allCaptureDevNameMap[idx].card, allCaptureDevNameMap[idx].dev, SND_PCM_OPEN_CAPTURE);
+        status = snd_pcm_open(&data->pcmHandle, iter->card, iter->dev, SND_PCM_OPEN_CAPTURE);
     }
 
-    if (status<0)
+    if(status < 0)
     {
         free(data);
         return ALC_INVALID_DEVICE;
     }
 
-    data->audio_fd=snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE);
-    if (data->audio_fd<0)
+    data->audio_fd = snd_pcm_file_descriptor(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE);
+    if(data->audio_fd < 0)
     {
+        snd_pcm_close(data->pcmHandle);
         free(data);
         return ALC_INVALID_DEVICE;
     }
 
-    al_string_copy_cstr(&device->DeviceName, deviceName);
-    device->ExtraData = data;
+    alstr_copy_cstr(&device->DeviceName, deviceName);
+    self->ExtraData = data;
 
     switch (device->FmtType)
     {
@@ -744,199 +769,40 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName)
     data->cparams.stop_mode=SND_PCM_STOP_STOP;
 
     data->cparams.buf.block.frag_size=device->UpdateSize*
-        ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType);
+        FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     data->cparams.buf.block.frags_max=device->NumUpdates;
     data->cparams.buf.block.frags_min=device->NumUpdates;
 
     data->cparams.format.interleave=1;
     data->cparams.format.rate=device->Frequency;
-    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans);
+    data->cparams.format.voices=ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
     data->cparams.format.format=format;
 
-    if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
-    {
-        int original_rate=data->cparams.format.rate;
-        int original_voices=data->cparams.format.voices;
-        int original_format=data->cparams.format.format;
-        int it;
-        int jt;
-
-        for (it=0; it<1; it++)
-        {
-            /* Check for second pass */
-            if (it==1)
-            {
-                original_rate=ratelist[0].rate;
-                original_voices=channellist[0].channels;
-                original_format=formatlist[0].format;
-            }
-
-            do {
-                /* At first downgrade sample format */
-                jt=0;
-                do {
-                    if (formatlist[jt].format==data->cparams.format.format)
-                    {
-                        data->cparams.format.format=formatlist[jt+1].format;
-                        break;
-                    }
-                    if (formatlist[jt].format==0)
-                    {
-                        data->cparams.format.format=0;
-                        break;
-                    }
-                    jt++;
-                } while(1);
-
-                if (data->cparams.format.format==0)
-                {
-                    data->cparams.format.format=original_format;
-
-                    /* At secod downgrade sample rate */
-                    jt=0;
-                    do {
-                        if (ratelist[jt].rate==data->cparams.format.rate)
-                        {
-                            data->cparams.format.rate=ratelist[jt+1].rate;
-                            break;
-                        }
-                        if (ratelist[jt].rate==0)
-                        {
-                            data->cparams.format.rate=0;
-                            break;
-                        }
-                        jt++;
-                    } while(1);
-
-                    if (data->cparams.format.rate==0)
-                    {
-                        data->cparams.format.rate=original_rate;
-                        data->cparams.format.format=original_format;
-
-                        /* At third downgrade channels number */
-                        jt=0;
-                        do {
-                            if(channellist[jt].channels==data->cparams.format.voices)
-                            {
-                                data->cparams.format.voices=channellist[jt+1].channels;
-                                break;
-                            }
-                            if (channellist[jt].channels==0)
-                            {
-                                data->cparams.format.voices=0;
-                                break;
-                            }
-                           jt++;
-                        } while(1);
-                    }
-
-                    if (data->cparams.format.voices==0)
-                    {
-                        break;
-                    }
-                }
-
-                data->cparams.buf.block.frag_size=device->UpdateSize*
-                    data->cparams.format.voices*
-                    snd_pcm_format_width(data->cparams.format.format)/8;
-                data->cparams.buf.block.frags_max=device->NumUpdates;
-                data->cparams.buf.block.frags_min=device->NumUpdates;
-                if ((snd_pcm_plugin_params(data->pcmHandle, &data->cparams))<0)
-                {
-                    continue;
-                }
-                else
-                {
-                    break;
-                }
-            } while(1);
-
-            if (data->cparams.format.voices!=0)
-            {
-                break;
-            }
-        }
-
-        if (data->cparams.format.voices==0)
-        {
-            return ALC_INVALID_VALUE;
-        }
-    }
-
-    /* now fill back to the our AL device */
-    device->Frequency=data->cparams.format.rate;
-
-    switch (data->cparams.format.voices)
+    if(snd_pcm_plugin_params(data->pcmHandle, &data->cparams) < 0)
     {
-        case 1:
-             device->FmtChans=DevFmtMono;
-             break;
-        case 2:
-             device->FmtChans=DevFmtStereo;
-             break;
-        case 4:
-             device->FmtChans=DevFmtQuad;
-             break;
-        case 6:
-             device->FmtChans=DevFmtX51;
-             break;
-        case 7:
-             device->FmtChans=DevFmtX61;
-             break;
-        case 8:
-             device->FmtChans=DevFmtX71;
-             break;
-        default:
-             device->FmtChans=DevFmtMono;
-             break;
-    }
+        snd_pcm_close(data->pcmHandle);
+        free(data);
 
-    switch (data->cparams.format.format)
-    {
-        case SND_PCM_SFMT_S8:
-             device->FmtType=DevFmtByte;
-             break;
-        case SND_PCM_SFMT_U8:
-             device->FmtType=DevFmtUByte;
-             break;
-        case SND_PCM_SFMT_S16_LE:
-             device->FmtType=DevFmtShort;
-             break;
-        case SND_PCM_SFMT_U16_LE:
-             device->FmtType=DevFmtUShort;
-             break;
-        case SND_PCM_SFMT_S32_LE:
-             device->FmtType=DevFmtInt;
-             break;
-        case SND_PCM_SFMT_U32_LE:
-             device->FmtType=DevFmtUInt;
-             break;
-        case SND_PCM_SFMT_FLOAT_LE:
-             device->FmtType=DevFmtFloat;
-             break;
-        default:
-             device->FmtType=DevFmtShort;
-             break;
+        return ALC_INVALID_VALUE;
     }
 
     return ALC_NO_ERROR;
 }
 
-static void qsa_close_capture(ALCdevice* device)
+static void qsa_close_capture(CaptureWrapper *self)
 {
-    qsa_data* data=(qsa_data*)device->ExtraData;
+    qsa_data *data = self->ExtraData;
 
     if (data->pcmHandle!=NULL)
-    {
         snd_pcm_close(data->pcmHandle);
-    }
+
     free(data);
-    device->ExtraData=NULL;
+    self->ExtraData = NULL;
 }
 
-static void qsa_start_capture(ALCdevice* device)
+static void qsa_start_capture(CaptureWrapper *self)
 {
-    qsa_data* data=(qsa_data*)device->ExtraData;
+    qsa_data *data = self->ExtraData;
     int rstatus;
 
     if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0)
@@ -954,24 +820,20 @@ static void qsa_start_capture(ALCdevice* device)
     }
 
     snd_pcm_capture_go(data->pcmHandle);
-
-    device->UpdateSize=data->csetup.buf.block.frag_size/
-        (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType));
-    device->NumUpdates=data->csetup.buf.block.frags;
 }
 
-static void qsa_stop_capture(ALCdevice* device)
+static void qsa_stop_capture(CaptureWrapper *self)
 {
-    qsa_data* data=(qsa_data*)device->ExtraData;
-
+    qsa_data *data = self->ExtraData;
     snd_pcm_capture_flush(data->pcmHandle);
 }
 
-static ALCuint qsa_available_samples(ALCdevice* device)
+static ALCuint qsa_available_samples(CaptureWrapper *self)
 {
-    qsa_data* data=(qsa_data*)device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    qsa_data *data = self->ExtraData;
     snd_pcm_channel_status_t status;
-    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    ALint frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     ALint free_size;
     int rstatus;
 
@@ -998,16 +860,17 @@ static ALCuint qsa_available_samples(ALCdevice* device)
     return free_size/frame_size;
 }
 
-static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples)
+static ALCenum qsa_capture_samples(CaptureWrapper *self, ALCvoid *buffer, ALCuint samples)
 {
-    qsa_data* data=(qsa_data*)device->ExtraData;
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+    qsa_data *data = self->ExtraData;
     char* read_ptr;
     snd_pcm_channel_status_t status;
     fd_set rfds;
     int selectret;
     struct timeval timeout;
     int bytes_read;
-    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
     ALint len=samples*frame_size;
     int rstatus;
 
@@ -1073,89 +936,134 @@ static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint s
     return ALC_NO_ERROR;
 }
 
-static ALint64 qsa_get_latency(ALCdevice* device)
+
+static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device)
 {
-    ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(CaptureWrapper, ALCbackend, self);
 
-    return (ALint64)(device->UpdateSize*device->NumUpdates/frame_size)*
-        1000000000/device->Frequency;
+    self->ExtraData = NULL;
 }
 
-BackendFuncs qsa_funcs=
+static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name)
 {
-    qsa_open_playback,
-    qsa_close_playback,
-    qsa_reset_playback,
-    qsa_start_playback,
-    qsa_stop_playback,
-    qsa_open_capture,
-    qsa_close_capture,
-    qsa_start_capture,
-    qsa_stop_capture,
-    qsa_capture_samples,
-    qsa_available_samples,
-    qsa_get_latency,
-};
+    return qsa_open_capture(self, name);
+}
 
-ALCboolean alc_qsa_init(BackendFuncs* func_list)
+static void CaptureWrapper_close(CaptureWrapper *self)
 {
-    *func_list=qsa_funcs;
+    qsa_close_capture(self);
+}
 
+static ALCboolean CaptureWrapper_start(CaptureWrapper *self)
+{
+    qsa_start_capture(self);
     return ALC_TRUE;
 }
 
-void alc_qsa_deinit(void)
+static void CaptureWrapper_stop(CaptureWrapper *self)
 {
-    ALuint i;
+    qsa_stop_capture(self);
+}
 
-    for (i=0; i<numDevNames; ++i)
-    {
-        free(allDevNameMap[i].name);
-    }
-    free(allDevNameMap);
-    allDevNameMap=NULL;
-    numDevNames=0;
+static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples)
+{
+    return qsa_capture_samples(self, buffer, samples);
+}
 
-    for (i=0; i<numCaptureDevNames; ++i)
-    {
-        free(allCaptureDevNameMap[i].name);
-    }
-    free(allCaptureDevNameMap);
-    allCaptureDevNameMap=NULL;
-    numCaptureDevNames=0;
+static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self)
+{
+    return qsa_available_samples(self);
+}
+
+
+typedef struct ALCqsaBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCqsaBackendFactory;
+#define ALCQSABACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCqsaBackendFactory, ALCbackendFactory) } }
+
+static ALCboolean ALCqsaBackendFactory_init(ALCqsaBackendFactory* UNUSED(self));
+static void ALCqsaBackendFactory_deinit(ALCqsaBackendFactory* UNUSED(self));
+static ALCboolean ALCqsaBackendFactory_querySupport(ALCqsaBackendFactory* UNUSED(self), ALCbackend_Type type);
+static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type);
+static ALCbackend* ALCqsaBackendFactory_createBackend(ALCqsaBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCqsaBackendFactory);
+
+static ALCboolean ALCqsaBackendFactory_init(ALCqsaBackendFactory* UNUSED(self))
+{
+    return ALC_TRUE;
 }
 
-void alc_qsa_probe(enum DevProbe type)
+static void ALCqsaBackendFactory_deinit(ALCqsaBackendFactory* UNUSED(self))
 {
-    ALuint i;
+#define FREE_NAME(iter) free((iter)->name)
+    VECTOR_FOR_EACH(DevMap, DeviceNameMap, FREE_NAME);
+    VECTOR_DEINIT(DeviceNameMap);
+
+    VECTOR_FOR_EACH(DevMap, CaptureNameMap, FREE_NAME);
+    VECTOR_DEINIT(CaptureNameMap);
+#undef FREE_NAME
+}
 
+static ALCboolean ALCqsaBackendFactory_querySupport(ALCqsaBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback || type == ALCbackend_Capture)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCqsaBackendFactory_probe(ALCqsaBackendFactory* UNUSED(self), enum DevProbe type)
+{
     switch (type)
     {
         case ALL_DEVICE_PROBE:
-             for (i=0; i<numDevNames; ++i)
-             {
-                 free(allDevNameMap[i].name);
-             }
-             free(allDevNameMap);
-
-             allDevNameMap=deviceList(SND_PCM_CHANNEL_PLAYBACK, &numDevNames);
-             for (i=0; i<numDevNames; ++i)
-             {
-                 AppendAllDevicesList(allDevNameMap[i].name);
-             }
-             break;
+#define FREE_NAME(iter) free((iter)->name)
+            VECTOR_FOR_EACH(DevMap, DeviceNameMap, FREE_NAME);
+            VECTOR_RESIZE(DeviceNameMap, 0, 0);
+#undef FREE_NAME
+
+            deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap);
+#define APPEND_DEVICE(iter) AppendAllDevicesList((iter)->name)
+            VECTOR_FOR_EACH(const DevMap, DeviceNameMap, APPEND_DEVICE);
+#undef APPEND_DEVICE
+            break;
+
         case CAPTURE_DEVICE_PROBE:
-             for (i=0; i<numCaptureDevNames; ++i)
-             {
-                 free(allCaptureDevNameMap[i].name);
-             }
-             free(allCaptureDevNameMap);
-
-             allCaptureDevNameMap=deviceList(SND_PCM_CHANNEL_CAPTURE, &numCaptureDevNames);
-             for (i=0; i<numCaptureDevNames; ++i)
-             {
-                 AppendCaptureDeviceList(allCaptureDevNameMap[i].name);
-             }
-             break;
+#define FREE_NAME(iter) free((iter)->name)
+            VECTOR_FOR_EACH(DevMap, CaptureNameMap, FREE_NAME);
+            VECTOR_RESIZE(CaptureNameMap, 0, 0);
+#undef FREE_NAME
+
+            deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap);
+#define APPEND_DEVICE(iter) AppendCaptureDeviceList((iter)->name)
+            VECTOR_FOR_EACH(const DevMap, CaptureNameMap, APPEND_DEVICE);
+#undef APPEND_DEVICE
+            break;
     }
 }
+
+static ALCbackend* ALCqsaBackendFactory_createBackend(ALCqsaBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        PlaybackWrapper *backend;
+        NEW_OBJ(backend, PlaybackWrapper)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+    if(type == ALCbackend_Capture)
+    {
+        CaptureWrapper *backend;
+        NEW_OBJ(backend, CaptureWrapper)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}
+
+ALCbackendFactory *ALCqsaBackendFactory_getFactory(void)
+{
+    static ALCqsaBackendFactory factory = ALCQSABACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}

+ 346 - 0
love/src/jni/openal-soft-1.18.2/Alc/backends/sndio.c

@@ -0,0 +1,346 @@
+/**
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "alMain.h"
+#include "alu.h"
+#include "threads.h"
+
+#include "backends/base.h"
+
+#include <sndio.h>
+
+
+
+
+typedef struct ALCsndioBackend {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    struct sio_hdl *sndHandle;
+
+    ALvoid *mix_data;
+    ALsizei data_size;
+
+    volatile int killNow;
+    althrd_t thread;
+} ALCsndioBackend;
+
+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);
+static DECLARE_FORWARD2(ALCsndioBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCsndioBackend, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCsndioBackend)
+
+DEFINE_ALCBACKEND_VTABLE(ALCsndioBackend);
+
+
+static const ALCchar sndio_device[] = "SndIO Default";
+
+
+static void ALCsndioBackend_Construct(ALCsndioBackend *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCsndioBackend, ALCbackend, self);
+}
+
+static void ALCsndioBackend_Destruct(ALCsndioBackend *self)
+{
+    if(self->sndHandle)
+        sio_close(self->sndHandle);
+    self->sndHandle = NULL;
+
+    al_free(self->mix_data);
+    self->mix_data = NULL;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static int ALCsndioBackend_mixerProc(void *ptr)
+{
+    ALCsndioBackend *self = (ALCsndioBackend*)ptr;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ALsizei frameSize;
+    size_t wrote;
+
+    SetRTPriority();
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
+
+    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+
+    while(!self->killNow && device->Connected)
+    {
+        ALsizei len = self->data_size;
+        ALubyte *WritePtr = self->mix_data;
+
+        ALCsndioBackend_lock(self);
+        aluMixData(device, WritePtr, len/frameSize);
+        ALCsndioBackend_unlock(self);
+        while(len > 0 && !self->killNow)
+        {
+            wrote = sio_write(self->sndHandle, WritePtr, len);
+            if(wrote == 0)
+            {
+                ERR("sio_write failed\n");
+                ALCdevice_Lock(device);
+                aluHandleDisconnect(device);
+                ALCdevice_Unlock(device);
+                break;
+            }
+
+            len -= wrote;
+            WritePtr += wrote;
+        }
+    }
+
+    return 0;
+}
+
+
+static ALCenum ALCsndioBackend_open(ALCsndioBackend *self, const ALCchar *name)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+
+    if(!name)
+        name = sndio_device;
+    else if(strcmp(name, sndio_device) != 0)
+        return ALC_INVALID_VALUE;
+
+    self->sndHandle = sio_open(NULL, SIO_PLAY, 0);
+    if(self->sndHandle == NULL)
+    {
+        ERR("Could not open device\n");
+        return ALC_INVALID_VALUE;
+    }
+
+    alstr_copy_cstr(&device->DeviceName, 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;
+    struct sio_par par;
+
+    sio_initpar(&par);
+
+    par.rate = device->Frequency;
+    par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1);
+
+    switch(device->FmtType)
+    {
+        case DevFmtByte:
+            par.bits = 8;
+            par.sig = 1;
+            break;
+        case DevFmtUByte:
+            par.bits = 8;
+            par.sig = 0;
+            break;
+        case DevFmtFloat:
+        case DevFmtShort:
+            par.bits = 16;
+            par.sig = 1;
+            break;
+        case DevFmtUShort:
+            par.bits = 16;
+            par.sig = 0;
+            break;
+        case DevFmtInt:
+            par.bits = 32;
+            par.sig = 1;
+            break;
+        case DevFmtUInt:
+            par.bits = 32;
+            par.sig = 0;
+            break;
+    }
+    par.le = SIO_LE_NATIVE;
+
+    par.round = device->UpdateSize;
+    par.appbufsz = device->UpdateSize * (device->NumUpdates-1);
+    if(!par.appbufsz) par.appbufsz = device->UpdateSize;
+
+    if(!sio_setpar(self->sndHandle, &par) || !sio_getpar(self->sndHandle, &par))
+    {
+        ERR("Failed to set device parameters\n");
+        return ALC_FALSE;
+    }
+
+    if(par.bits != par.bps*8)
+    {
+        ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8);
+        return ALC_FALSE;
+    }
+
+    device->Frequency = par.rate;
+    device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo);
+
+    if(par.bits == 8 && par.sig == 1)
+        device->FmtType = DevFmtByte;
+    else if(par.bits == 8 && par.sig == 0)
+        device->FmtType = DevFmtUByte;
+    else if(par.bits == 16 && par.sig == 1)
+        device->FmtType = DevFmtShort;
+    else if(par.bits == 16 && par.sig == 0)
+        device->FmtType = DevFmtUShort;
+    else if(par.bits == 32 && par.sig == 1)
+        device->FmtType = DevFmtInt;
+    else if(par.bits == 32 && par.sig == 0)
+        device->FmtType = DevFmtUInt;
+    else
+    {
+        ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits);
+        return ALC_FALSE;
+    }
+
+    device->UpdateSize = par.round;
+    device->NumUpdates = (par.bufsz/par.round) + 1;
+
+    SetDefaultChannelOrder(device);
+
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCsndioBackend_start(ALCsndioBackend *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice;
+
+    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
+    al_free(self->mix_data);
+    self->mix_data = al_calloc(16, self->data_size);
+
+    if(!sio_start(self->sndHandle))
+    {
+        ERR("Error starting playback\n");
+        return ALC_FALSE;
+    }
+
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCsndioBackend_mixerProc, self) != althrd_success)
+    {
+        sio_stop(self->sndHandle);
+        return ALC_FALSE;
+    }
+
+    return ALC_TRUE;
+}
+
+static void ALCsndioBackend_stop(ALCsndioBackend *self)
+{
+    int res;
+
+    if(self->killNow)
+        return;
+
+    self->killNow = 1;
+    althrd_join(self->thread, &res);
+
+    if(!sio_stop(self->sndHandle))
+        ERR("Error stopping device\n");
+
+    al_free(self->mix_data);
+    self->mix_data = NULL;
+}
+
+
+typedef struct ALCsndioBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCsndioBackendFactory;
+#define ALCSNDIOBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCsndioBackendFactory, ALCbackendFactory) } }
+
+ALCbackendFactory *ALCsndioBackendFactory_getFactory(void);
+
+static ALCboolean ALCsndioBackendFactory_init(ALCsndioBackendFactory *self);
+static DECLARE_FORWARD(ALCsndioBackendFactory, ALCbackendFactory, void, deinit)
+static ALCboolean ALCsndioBackendFactory_querySupport(ALCsndioBackendFactory *self, ALCbackend_Type type);
+static void ALCsndioBackendFactory_probe(ALCsndioBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCsndioBackendFactory_createBackend(ALCsndioBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsndioBackendFactory);
+
+
+ALCbackendFactory *ALCsndioBackendFactory_getFactory(void)
+{
+    static ALCsndioBackendFactory factory = ALCSNDIOBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}
+
+
+static ALCboolean ALCsndioBackendFactory_init(ALCsndioBackendFactory* UNUSED(self))
+{
+    /* No dynamic loading */
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCsndioBackendFactory_querySupport(ALCsndioBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCsndioBackendFactory_probe(ALCsndioBackendFactory* UNUSED(self), enum DevProbe type)
+{
+    switch(type)
+    {
+        case ALL_DEVICE_PROBE:
+            AppendAllDevicesList(sndio_device);
+            break;
+        case CAPTURE_DEVICE_PROBE:
+            break;
+    }
+}
+
+static ALCbackend* ALCsndioBackendFactory_createBackend(ALCsndioBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCsndioBackend *backend;
+        NEW_OBJ(backend, ALCsndioBackend)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}

+ 363 - 0
love/src/jni/openal-soft-1.18.2/Alc/backends/solaris.c

@@ -0,0 +1,363 @@
+/**
+ * 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 <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <memory.h>
+#include <unistd.h>
+#include <errno.h>
+#include <math.h>
+
+#include "alMain.h"
+#include "alu.h"
+#include "threads.h"
+#include "compat.h"
+
+#include "backends/base.h"
+
+#include <sys/audioio.h>
+
+
+typedef struct ALCsolarisBackend {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    int fd;
+
+    ALubyte *mix_data;
+    int data_size;
+
+    ATOMIC(ALenum) killNow;
+    althrd_t thread;
+} ALCsolarisBackend;
+
+static int ALCsolarisBackend_mixerProc(void *ptr);
+
+static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *device);
+static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self);
+static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name);
+static void ALCsolarisBackend_close(ALCsolarisBackend *self);
+static ALCboolean ALCsolarisBackend_reset(ALCsolarisBackend *self);
+static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self);
+static void ALCsolarisBackend_stop(ALCsolarisBackend *self);
+static DECLARE_FORWARD2(ALCsolarisBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCsolarisBackend, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCsolarisBackend)
+
+DEFINE_ALCBACKEND_VTABLE(ALCsolarisBackend);
+
+
+static const ALCchar solaris_device[] = "Solaris Default";
+
+static const char *solaris_driver = "/dev/audio";
+
+
+static void ALCsolarisBackend_Construct(ALCsolarisBackend *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCsolarisBackend, ALCbackend, self);
+
+    self->fd = -1;
+    ATOMIC_INIT(&self->killNow, AL_FALSE);
+}
+
+static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self)
+{
+    if(self->fd != -1)
+        close(self->fd);
+    self->fd = -1;
+
+    free(self->mix_data);
+    self->mix_data = NULL;
+    self->data_size = 0;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+static int ALCsolarisBackend_mixerProc(void *ptr)
+{
+    ALCsolarisBackend *self = ptr;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    struct timeval timeout;
+    ALubyte *write_ptr;
+    ALint frame_size;
+    ALint to_write;
+    ssize_t wrote;
+    fd_set wfds;
+    int sret;
+
+    SetRTPriority();
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
+
+    frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+
+    ALCsolarisBackend_lock(self);
+    while(!ATOMIC_LOAD_SEQ(&self->killNow) && device->Connected)
+    {
+        FD_ZERO(&wfds);
+        FD_SET(self->fd, &wfds);
+        timeout.tv_sec = 1;
+        timeout.tv_usec = 0;
+
+        ALCsolarisBackend_unlock(self);
+        sret = select(self->fd+1, NULL, &wfds, NULL, &timeout);
+        ALCsolarisBackend_lock(self);
+        if(sret < 0)
+        {
+            if(errno == EINTR)
+                continue;
+            ERR("select failed: %s\n", strerror(errno));
+            aluHandleDisconnect(device);
+            break;
+        }
+        else if(sret == 0)
+        {
+            WARN("select timeout\n");
+            continue;
+        }
+
+        write_ptr = self->mix_data;
+        to_write = self->data_size;
+        aluMixData(device, write_ptr, to_write/frame_size);
+        while(to_write > 0 && !ATOMIC_LOAD_SEQ(&self->killNow))
+        {
+            wrote = write(self->fd, write_ptr, to_write);
+            if(wrote < 0)
+            {
+                if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+                    continue;
+                ERR("write failed: %s\n", strerror(errno));
+                aluHandleDisconnect(device);
+                break;
+            }
+
+            to_write -= wrote;
+            write_ptr += wrote;
+        }
+    }
+    ALCsolarisBackend_unlock(self);
+
+    return 0;
+}
+
+
+static ALCenum ALCsolarisBackend_open(ALCsolarisBackend *self, const ALCchar *name)
+{
+    ALCdevice *device;
+
+    if(!name)
+        name = solaris_device;
+    else if(strcmp(name, solaris_device) != 0)
+        return ALC_INVALID_VALUE;
+
+    self->fd = open(solaris_driver, O_WRONLY);
+    if(self->fd == -1)
+    {
+        ERR("Could not open %s: %s\n", solaris_driver, strerror(errno));
+        return ALC_INVALID_VALUE;
+    }
+
+    device = STATIC_CAST(ALCbackend,self)->mDevice;
+    alstr_copy_cstr(&device->DeviceName, name);
+
+    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;
+    audio_info_t info;
+    ALsizei frameSize;
+    ALsizei numChannels;
+
+    AUDIO_INITINFO(&info);
+
+    info.play.sample_rate = device->Frequency;
+
+    if(device->FmtChans != DevFmtMono)
+        device->FmtChans = DevFmtStereo;
+    numChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    info.play.channels = numChannels;
+
+    switch(device->FmtType)
+    {
+        case DevFmtByte:
+            info.play.precision = 8;
+            info.play.encoding = AUDIO_ENCODING_LINEAR;
+            break;
+        case DevFmtUByte:
+            info.play.precision = 8;
+            info.play.encoding = AUDIO_ENCODING_LINEAR8;
+            break;
+        case DevFmtUShort:
+        case DevFmtInt:
+        case DevFmtUInt:
+        case DevFmtFloat:
+            device->FmtType = DevFmtShort;
+            /* fall-through */
+        case DevFmtShort:
+            info.play.precision = 16;
+            info.play.encoding = AUDIO_ENCODING_LINEAR;
+            break;
+    }
+
+    frameSize = numChannels * BytesFromDevFmt(device->FmtType);
+    info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize;
+
+    if(ioctl(self->fd, AUDIO_SETINFO, &info) < 0)
+    {
+        ERR("ioctl failed: %s\n", strerror(errno));
+        return ALC_FALSE;
+    }
+
+    if(ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder) != (ALsizei)info.play.channels)
+    {
+        ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), info.play.channels);
+        return ALC_FALSE;
+    }
+
+    if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && device->FmtType == DevFmtUByte) ||
+         (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtByte) ||
+         (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtShort) ||
+         (info.play.precision == 32 && info.play.encoding == AUDIO_ENCODING_LINEAR && device->FmtType == DevFmtInt)))
+    {
+        ERR("Could not set %s samples, got %d (0x%x)\n", DevFmtTypeString(device->FmtType),
+            info.play.precision, info.play.encoding);
+        return ALC_FALSE;
+    }
+
+    device->Frequency = info.play.sample_rate;
+    device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1;
+
+    SetDefaultChannelOrder(device);
+
+    free(self->mix_data);
+    self->data_size = device->UpdateSize * FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
+    self->mix_data = calloc(1, self->data_size);
+
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self)
+{
+    ATOMIC_STORE_SEQ(&self->killNow, AL_FALSE);
+    if(althrd_create(&self->thread, ALCsolarisBackend_mixerProc, self) != althrd_success)
+        return ALC_FALSE;
+    return ALC_TRUE;
+}
+
+static void ALCsolarisBackend_stop(ALCsolarisBackend *self)
+{
+    int res;
+
+    if(ATOMIC_EXCHANGE_SEQ(&self->killNow, AL_TRUE))
+        return;
+
+    althrd_join(self->thread, &res);
+
+    if(ioctl(self->fd, AUDIO_DRAIN) < 0)
+        ERR("Error draining device: %s\n", strerror(errno));
+}
+
+
+typedef struct ALCsolarisBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCsolarisBackendFactory;
+#define ALCSOLARISBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCsolarisBackendFactory, ALCbackendFactory) } }
+
+ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void);
+
+static ALCboolean ALCsolarisBackendFactory_init(ALCsolarisBackendFactory *self);
+static DECLARE_FORWARD(ALCsolarisBackendFactory, ALCbackendFactory, void, deinit)
+static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory *self, ALCbackend_Type type);
+static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCsolarisBackendFactory);
+
+
+ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void)
+{
+    static ALCsolarisBackendFactory factory = ALCSOLARISBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}
+
+
+static ALCboolean ALCsolarisBackendFactory_init(ALCsolarisBackendFactory* UNUSED(self))
+{
+    ConfigValueStr(NULL, "solaris", "device", &solaris_driver);
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCsolarisBackendFactory_querySupport(ALCsolarisBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCsolarisBackendFactory_probe(ALCsolarisBackendFactory* UNUSED(self), enum DevProbe type)
+{
+    switch(type)
+    {
+        case ALL_DEVICE_PROBE:
+        {
+#ifdef HAVE_STAT
+            struct stat buf;
+            if(stat(solaris_driver, &buf) == 0)
+#endif
+                AppendAllDevicesList(solaris_device);
+        }
+        break;
+
+        case CAPTURE_DEVICE_PROBE:
+            break;
+    }
+}
+
+ALCbackend* ALCsolarisBackendFactory_createBackend(ALCsolarisBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCsolarisBackend *backend;
+        NEW_OBJ(backend, ALCsolarisBackend)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}

+ 453 - 0
love/src/jni/openal-soft-1.18.2/Alc/backends/wave.c

@@ -0,0 +1,453 @@
+/**
+ * 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 <stdio.h>
+#include <memory.h>
+#include <errno.h>
+
+#include "alMain.h"
+#include "alu.h"
+#include "threads.h"
+#include "compat.h"
+
+#include "backends/base.h"
+
+
+static const ALCchar waveDevice[] = "Wave File Writer";
+
+static const ALubyte SUBTYPE_PCM[] = {
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
+    0x00, 0x38, 0x9b, 0x71
+};
+static const ALubyte SUBTYPE_FLOAT[] = {
+    0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa,
+    0x00, 0x38, 0x9b, 0x71
+};
+
+static const ALubyte SUBTYPE_BFORMAT_PCM[] = {
+    0x01, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
+    0xca, 0x00, 0x00, 0x00
+};
+
+static const ALubyte SUBTYPE_BFORMAT_FLOAT[] = {
+    0x03, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1,
+    0xca, 0x00, 0x00, 0x00
+};
+
+static void fwrite16le(ALushort val, FILE *f)
+{
+    ALubyte data[2] = { val&0xff, (val>>8)&0xff };
+    fwrite(data, 1, 2, f);
+}
+
+static void fwrite32le(ALuint val, FILE *f)
+{
+    ALubyte data[4] = { val&0xff, (val>>8)&0xff, (val>>16)&0xff, (val>>24)&0xff };
+    fwrite(data, 1, 4, f);
+}
+
+
+typedef struct ALCwaveBackend {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    FILE *mFile;
+    long mDataStart;
+
+    ALvoid *mBuffer;
+    ALuint mSize;
+
+    volatile int killNow;
+    althrd_t thread;
+} ALCwaveBackend;
+
+static int ALCwaveBackend_mixerProc(void *ptr);
+
+static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device);
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, Destruct)
+static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name);
+static void ALCwaveBackend_close(ALCwaveBackend *self);
+static ALCboolean ALCwaveBackend_reset(ALCwaveBackend *self);
+static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self);
+static void ALCwaveBackend_stop(ALCwaveBackend *self);
+static DECLARE_FORWARD2(ALCwaveBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCwaveBackend, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCwaveBackend)
+
+DEFINE_ALCBACKEND_VTABLE(ALCwaveBackend);
+
+
+static void ALCwaveBackend_Construct(ALCwaveBackend *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCwaveBackend, ALCbackend, self);
+
+    self->mFile = NULL;
+    self->mDataStart = -1;
+
+    self->mBuffer = NULL;
+    self->mSize = 0;
+
+    self->killNow = 1;
+}
+
+
+static int ALCwaveBackend_mixerProc(void *ptr)
+{
+    ALCwaveBackend *self = (ALCwaveBackend*)ptr;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    struct timespec now, start;
+    ALint64 avail, done;
+    ALuint frameSize;
+    size_t fs;
+    const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 /
+                                 device->Frequency / 2);
+
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
+
+    frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+
+    done = 0;
+    if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC)
+    {
+        ERR("Failed to get starting time\n");
+        return 1;
+    }
+    while(!self->killNow && device->Connected)
+    {
+        if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC)
+        {
+            ERR("Failed to get current time\n");
+            return 1;
+        }
+
+        avail  = (now.tv_sec - start.tv_sec) * device->Frequency;
+        avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000;
+        if(avail < done)
+        {
+            /* Oops, time skipped backwards. Reset the number of samples done
+             * with one update available since we (likely) just came back from
+             * sleeping. */
+            done = avail - device->UpdateSize;
+        }
+
+        if(avail-done < device->UpdateSize)
+            al_nssleep(restTime);
+        else while(avail-done >= device->UpdateSize)
+        {
+            ALCwaveBackend_lock(self);
+            aluMixData(device, self->mBuffer, device->UpdateSize);
+            ALCwaveBackend_unlock(self);
+            done += device->UpdateSize;
+
+            if(!IS_LITTLE_ENDIAN)
+            {
+                ALuint bytesize = BytesFromDevFmt(device->FmtType);
+                ALuint i;
+
+                if(bytesize == 2)
+                {
+                    ALushort *samples = self->mBuffer;
+                    ALuint len = self->mSize / 2;
+                    for(i = 0;i < len;i++)
+                    {
+                        ALushort samp = samples[i];
+                        samples[i] = (samp>>8) | (samp<<8);
+                    }
+                }
+                else if(bytesize == 4)
+                {
+                    ALuint *samples = self->mBuffer;
+                    ALuint len = self->mSize / 4;
+                    for(i = 0;i < len;i++)
+                    {
+                        ALuint samp = samples[i];
+                        samples[i] = (samp>>24) | ((samp>>8)&0x0000ff00) |
+                                     ((samp<<8)&0x00ff0000) | (samp<<24);
+                    }
+                }
+            }
+
+            fs = fwrite(self->mBuffer, frameSize, device->UpdateSize, self->mFile);
+            (void)fs;
+            if(ferror(self->mFile))
+            {
+                ERR("Error writing to file\n");
+                ALCdevice_Lock(device);
+                aluHandleDisconnect(device);
+                ALCdevice_Unlock(device);
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+static ALCenum ALCwaveBackend_open(ALCwaveBackend *self, const ALCchar *name)
+{
+    ALCdevice *device;
+    const char *fname;
+
+    fname = GetConfigValue(NULL, "wave", "file", "");
+    if(!fname[0]) return ALC_INVALID_VALUE;
+
+    if(!name)
+        name = waveDevice;
+    else if(strcmp(name, waveDevice) != 0)
+        return ALC_INVALID_VALUE;
+
+    self->mFile = al_fopen(fname, "wb");
+    if(!self->mFile)
+    {
+        ERR("Could not open file '%s': %s\n", fname, strerror(errno));
+        return ALC_INVALID_VALUE;
+    }
+
+    device = STATIC_CAST(ALCbackend, self)->mDevice;
+    alstr_copy_cstr(&device->DeviceName, 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;
+    ALuint channels=0, bits=0, chanmask=0;
+    int isbformat = 0;
+    size_t val;
+
+    fseek(self->mFile, 0, SEEK_SET);
+    clearerr(self->mFile);
+
+    if(GetConfigValueBool(NULL, "wave", "bformat", 0))
+    {
+        device->FmtChans = DevFmtAmbi3D;
+        device->AmbiOrder = 1;
+    }
+
+    switch(device->FmtType)
+    {
+        case DevFmtByte:
+            device->FmtType = DevFmtUByte;
+            break;
+        case DevFmtUShort:
+            device->FmtType = DevFmtShort;
+            break;
+        case DevFmtUInt:
+            device->FmtType = DevFmtInt;
+            break;
+        case DevFmtUByte:
+        case DevFmtShort:
+        case DevFmtInt:
+        case DevFmtFloat:
+            break;
+    }
+    switch(device->FmtChans)
+    {
+        case DevFmtMono:   chanmask = 0x04; break;
+        case DevFmtStereo: chanmask = 0x01 | 0x02; break;
+        case DevFmtQuad:   chanmask = 0x01 | 0x02 | 0x10 | 0x20; break;
+        case DevFmtX51: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x200 | 0x400; break;
+        case DevFmtX51Rear: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020; break;
+        case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break;
+        case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break;
+        case DevFmtAmbi3D:
+            /* .amb output requires FuMa */
+            device->AmbiLayout = AmbiLayout_FuMa;
+            device->AmbiScale = AmbiNorm_FuMa;
+            isbformat = 1;
+            chanmask = 0;
+            break;
+    }
+    bits = BytesFromDevFmt(device->FmtType) * 8;
+    channels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+
+    fputs("RIFF", self->mFile);
+    fwrite32le(0xFFFFFFFF, self->mFile); // 'RIFF' header len; filled in at close
+
+    fputs("WAVE", self->mFile);
+
+    fputs("fmt ", self->mFile);
+    fwrite32le(40, self->mFile); // 'fmt ' header len; 40 bytes for EXTENSIBLE
+
+    // 16-bit val, format type id (extensible: 0xFFFE)
+    fwrite16le(0xFFFE, self->mFile);
+    // 16-bit val, channel count
+    fwrite16le(channels, self->mFile);
+    // 32-bit val, frequency
+    fwrite32le(device->Frequency, self->mFile);
+    // 32-bit val, bytes per second
+    fwrite32le(device->Frequency * channels * bits / 8, self->mFile);
+    // 16-bit val, frame size
+    fwrite16le(channels * bits / 8, self->mFile);
+    // 16-bit val, bits per sample
+    fwrite16le(bits, self->mFile);
+    // 16-bit val, extra byte count
+    fwrite16le(22, self->mFile);
+    // 16-bit val, valid bits per sample
+    fwrite16le(bits, self->mFile);
+    // 32-bit val, channel mask
+    fwrite32le(chanmask, self->mFile);
+    // 16 byte GUID, sub-type format
+    val = fwrite((device->FmtType == DevFmtFloat) ?
+                 (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) :
+                 (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM), 1, 16, self->mFile);
+    (void)val;
+
+    fputs("data", self->mFile);
+    fwrite32le(0xFFFFFFFF, self->mFile); // 'data' header len; filled in at close
+
+    if(ferror(self->mFile))
+    {
+        ERR("Error writing header: %s\n", strerror(errno));
+        return ALC_FALSE;
+    }
+    self->mDataStart = ftell(self->mFile);
+
+    SetDefaultWFXChannelOrder(device);
+
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCwaveBackend_start(ALCwaveBackend *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+
+    self->mSize = device->UpdateSize * FrameSizeFromDevFmt(
+        device->FmtChans, device->FmtType, device->AmbiOrder
+    );
+    self->mBuffer = malloc(self->mSize);
+    if(!self->mBuffer)
+    {
+        ERR("Buffer malloc failed\n");
+        return ALC_FALSE;
+    }
+
+    self->killNow = 0;
+    if(althrd_create(&self->thread, ALCwaveBackend_mixerProc, self) != althrd_success)
+    {
+        free(self->mBuffer);
+        self->mBuffer = NULL;
+        self->mSize = 0;
+        return ALC_FALSE;
+    }
+
+    return ALC_TRUE;
+}
+
+static void ALCwaveBackend_stop(ALCwaveBackend *self)
+{
+    ALuint dataLen;
+    long size;
+    int res;
+
+    if(self->killNow)
+        return;
+
+    self->killNow = 1;
+    althrd_join(self->thread, &res);
+
+    free(self->mBuffer);
+    self->mBuffer = NULL;
+
+    size = ftell(self->mFile);
+    if(size > 0)
+    {
+        dataLen = size - self->mDataStart;
+        if(fseek(self->mFile, self->mDataStart-4, SEEK_SET) == 0)
+            fwrite32le(dataLen, self->mFile); // 'data' header len
+        if(fseek(self->mFile, 4, SEEK_SET) == 0)
+            fwrite32le(size-8, self->mFile); // 'WAVE' header len
+    }
+}
+
+
+typedef struct ALCwaveBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCwaveBackendFactory;
+#define ALCWAVEBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCwaveBackendFactory, ALCbackendFactory) } }
+
+ALCbackendFactory *ALCwaveBackendFactory_getFactory(void);
+
+static ALCboolean ALCwaveBackendFactory_init(ALCwaveBackendFactory *self);
+static DECLARE_FORWARD(ALCwaveBackendFactory, ALCbackendFactory, void, deinit)
+static ALCboolean ALCwaveBackendFactory_querySupport(ALCwaveBackendFactory *self, ALCbackend_Type type);
+static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCwaveBackendFactory_createBackend(ALCwaveBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwaveBackendFactory);
+
+
+ALCbackendFactory *ALCwaveBackendFactory_getFactory(void)
+{
+    static ALCwaveBackendFactory factory = ALCWAVEBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}
+
+
+static ALCboolean ALCwaveBackendFactory_init(ALCwaveBackendFactory* UNUSED(self))
+{
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCwaveBackendFactory_querySupport(ALCwaveBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+        return !!ConfigValueExists(NULL, "wave", "file");
+    return ALC_FALSE;
+}
+
+static void ALCwaveBackendFactory_probe(ALCwaveBackendFactory* UNUSED(self), enum DevProbe type)
+{
+    switch(type)
+    {
+        case ALL_DEVICE_PROBE:
+            AppendAllDevicesList(waveDevice);
+            break;
+        case CAPTURE_DEVICE_PROBE:
+            break;
+    }
+}
+
+static ALCbackend* ALCwaveBackendFactory_createBackend(ALCwaveBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCwaveBackend *backend;
+        NEW_OBJ(backend, ALCwaveBackend)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}

+ 803 - 0
love/src/jni/openal-soft-1.18.2/Alc/backends/winmm.c

@@ -0,0 +1,803 @@
+/**
+ * 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 <stdio.h>
+#include <memory.h>
+
+#include <windows.h>
+#include <mmsystem.h>
+
+#include "alMain.h"
+#include "alu.h"
+#include "threads.h"
+
+#include "backends/base.h"
+
+#ifndef WAVE_FORMAT_IEEE_FLOAT
+#define WAVE_FORMAT_IEEE_FLOAT  0x0003
+#endif
+
+#define DEVNAME_HEAD "OpenAL Soft on "
+
+
+static vector_al_string PlaybackDevices;
+static vector_al_string CaptureDevices;
+
+static void clear_devlist(vector_al_string *list)
+{
+    VECTOR_FOR_EACH(al_string, *list, alstr_reset);
+    VECTOR_RESIZE(*list, 0, 0);
+}
+
+
+static void ProbePlaybackDevices(void)
+{
+    ALuint numdevs;
+    ALuint i;
+
+    clear_devlist(&PlaybackDevices);
+
+    numdevs = waveOutGetNumDevs();
+    VECTOR_RESIZE(PlaybackDevices, 0, numdevs);
+    for(i = 0;i < numdevs;i++)
+    {
+        WAVEOUTCAPSW WaveCaps;
+        const al_string *iter;
+        al_string dname;
+
+        AL_STRING_INIT(dname);
+        if(waveOutGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
+        {
+            ALuint count = 0;
+            while(1)
+            {
+                alstr_copy_cstr(&dname, DEVNAME_HEAD);
+                alstr_append_wcstr(&dname, WaveCaps.szPname);
+                if(count != 0)
+                {
+                    char str[64];
+                    snprintf(str, sizeof(str), " #%d", count+1);
+                    alstr_append_cstr(&dname, str);
+                }
+                count++;
+
+#define MATCH_ENTRY(i) (alstr_cmp(dname, *(i)) == 0)
+                VECTOR_FIND_IF(iter, const al_string, PlaybackDevices, MATCH_ENTRY);
+                if(iter == VECTOR_END(PlaybackDevices)) break;
+#undef MATCH_ENTRY
+            }
+
+            TRACE("Got device \"%s\", ID %u\n", alstr_get_cstr(dname), i);
+        }
+        VECTOR_PUSH_BACK(PlaybackDevices, dname);
+    }
+}
+
+static void ProbeCaptureDevices(void)
+{
+    ALuint numdevs;
+    ALuint i;
+
+    clear_devlist(&CaptureDevices);
+
+    numdevs = waveInGetNumDevs();
+    VECTOR_RESIZE(CaptureDevices, 0, numdevs);
+    for(i = 0;i < numdevs;i++)
+    {
+        WAVEINCAPSW WaveCaps;
+        const al_string *iter;
+        al_string dname;
+
+        AL_STRING_INIT(dname);
+        if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR)
+        {
+            ALuint count = 0;
+            while(1)
+            {
+                alstr_copy_cstr(&dname, DEVNAME_HEAD);
+                alstr_append_wcstr(&dname, WaveCaps.szPname);
+                if(count != 0)
+                {
+                    char str[64];
+                    snprintf(str, sizeof(str), " #%d", count+1);
+                    alstr_append_cstr(&dname, str);
+                }
+                count++;
+
+#define MATCH_ENTRY(i) (alstr_cmp(dname, *(i)) == 0)
+                VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_ENTRY);
+                if(iter == VECTOR_END(CaptureDevices)) break;
+#undef MATCH_ENTRY
+            }
+
+            TRACE("Got device \"%s\", ID %u\n", alstr_get_cstr(dname), i);
+        }
+        VECTOR_PUSH_BACK(CaptureDevices, dname);
+    }
+}
+
+
+typedef struct ALCwinmmPlayback {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    RefCount WaveBuffersCommitted;
+    WAVEHDR WaveBuffer[4];
+
+    HWAVEOUT OutHdl;
+
+    WAVEFORMATEX Format;
+
+    volatile ALboolean killNow;
+    althrd_t thread;
+} ALCwinmmPlayback;
+
+static void ALCwinmmPlayback_Construct(ALCwinmmPlayback *self, ALCdevice *device);
+static void ALCwinmmPlayback_Destruct(ALCwinmmPlayback *self);
+
+static void CALLBACK ALCwinmmPlayback_waveOutProc(HWAVEOUT device, UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR param2);
+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);
+static DECLARE_FORWARD2(ALCwinmmPlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint)
+static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, ALCuint, availableSamples)
+static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCwinmmPlayback, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCwinmmPlayback)
+
+DEFINE_ALCBACKEND_VTABLE(ALCwinmmPlayback);
+
+
+static void ALCwinmmPlayback_Construct(ALCwinmmPlayback *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCwinmmPlayback, ALCbackend, self);
+
+    InitRef(&self->WaveBuffersCommitted, 0);
+    self->OutHdl = NULL;
+
+    self->killNow = AL_TRUE;
+}
+
+static void ALCwinmmPlayback_Destruct(ALCwinmmPlayback *self)
+{
+    if(self->OutHdl)
+        waveOutClose(self->OutHdl);
+    self->OutHdl = 0;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+/* ALCwinmmPlayback_waveOutProc
+ *
+ * Posts a message to 'ALCwinmmPlayback_mixerProc' everytime a WaveOut Buffer
+ * is completed and returns to the application (for more data)
+ */
+static void CALLBACK ALCwinmmPlayback_waveOutProc(HWAVEOUT UNUSED(device), UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR UNUSED(param2))
+{
+    ALCwinmmPlayback *self = (ALCwinmmPlayback*)instance;
+
+    if(msg != WOM_DONE)
+        return;
+
+    DecrementRef(&self->WaveBuffersCommitted);
+    PostThreadMessage(self->thread, msg, 0, param1);
+}
+
+FORCE_ALIGN static int ALCwinmmPlayback_mixerProc(void *arg)
+{
+    ALCwinmmPlayback *self = arg;
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    WAVEHDR *WaveHdr;
+    MSG msg;
+
+    SetRTPriority();
+    althrd_setname(althrd_current(), MIXER_THREAD_NAME);
+
+    while(GetMessage(&msg, NULL, 0, 0))
+    {
+        if(msg.message != WOM_DONE)
+            continue;
+
+        if(self->killNow)
+        {
+            if(ReadRef(&self->WaveBuffersCommitted) == 0)
+                break;
+            continue;
+        }
+
+        WaveHdr = ((WAVEHDR*)msg.lParam);
+        ALCwinmmPlayback_lock(self);
+        aluMixData(device, WaveHdr->lpData, WaveHdr->dwBufferLength /
+                                            self->Format.nBlockAlign);
+        ALCwinmmPlayback_unlock(self);
+
+        // Send buffer back to play more data
+        waveOutWrite(self->OutHdl, WaveHdr, sizeof(WAVEHDR));
+        IncrementRef(&self->WaveBuffersCommitted);
+    }
+
+    return 0;
+}
+
+
+static ALCenum ALCwinmmPlayback_open(ALCwinmmPlayback *self, const ALCchar *deviceName)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    const al_string *iter;
+    UINT DeviceID;
+    MMRESULT res;
+
+    if(VECTOR_SIZE(PlaybackDevices) == 0)
+        ProbePlaybackDevices();
+
+    // Find the Device ID matching the deviceName if valid
+#define MATCH_DEVNAME(iter) (!alstr_empty(*(iter)) && \
+                             (!deviceName || alstr_cmp_cstr(*(iter), deviceName) == 0))
+    VECTOR_FIND_IF(iter, const al_string, PlaybackDevices, MATCH_DEVNAME);
+    if(iter == VECTOR_END(PlaybackDevices))
+        return ALC_INVALID_VALUE;
+#undef MATCH_DEVNAME
+
+    DeviceID = (UINT)(iter - VECTOR_BEGIN(PlaybackDevices));
+
+retry_open:
+    memset(&self->Format, 0, sizeof(WAVEFORMATEX));
+    if(device->FmtType == DevFmtFloat)
+    {
+        self->Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+        self->Format.wBitsPerSample = 32;
+    }
+    else
+    {
+        self->Format.wFormatTag = WAVE_FORMAT_PCM;
+        if(device->FmtType == DevFmtUByte || device->FmtType == DevFmtByte)
+            self->Format.wBitsPerSample = 8;
+        else
+            self->Format.wBitsPerSample = 16;
+    }
+    self->Format.nChannels = ((device->FmtChans == DevFmtMono) ? 1 : 2);
+    self->Format.nBlockAlign = self->Format.wBitsPerSample *
+                               self->Format.nChannels / 8;
+    self->Format.nSamplesPerSec = device->Frequency;
+    self->Format.nAvgBytesPerSec = self->Format.nSamplesPerSec *
+                                   self->Format.nBlockAlign;
+    self->Format.cbSize = 0;
+
+    if((res=waveOutOpen(&self->OutHdl, DeviceID, &self->Format, (DWORD_PTR)&ALCwinmmPlayback_waveOutProc, (DWORD_PTR)self, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
+    {
+        if(device->FmtType == DevFmtFloat)
+        {
+            device->FmtType = DevFmtShort;
+            goto retry_open;
+        }
+        ERR("waveOutOpen failed: %u\n", res);
+        goto failure;
+    }
+
+    alstr_copy(&device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID));
+    return ALC_NO_ERROR;
+
+failure:
+    if(self->OutHdl)
+        waveOutClose(self->OutHdl);
+    self->OutHdl = NULL;
+
+    return ALC_INVALID_VALUE;
+}
+
+static void ALCwinmmPlayback_close(ALCwinmmPlayback* UNUSED(self))
+{ }
+
+static ALCboolean ALCwinmmPlayback_reset(ALCwinmmPlayback *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+
+    device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
+                                  self->Format.nSamplesPerSec /
+                                  device->Frequency);
+    device->UpdateSize = (device->UpdateSize*device->NumUpdates + 3) / 4;
+    device->NumUpdates = 4;
+    device->Frequency = self->Format.nSamplesPerSec;
+
+    if(self->Format.wFormatTag == WAVE_FORMAT_IEEE_FLOAT)
+    {
+        if(self->Format.wBitsPerSample == 32)
+            device->FmtType = DevFmtFloat;
+        else
+        {
+            ERR("Unhandled IEEE float sample depth: %d\n", self->Format.wBitsPerSample);
+            return ALC_FALSE;
+        }
+    }
+    else if(self->Format.wFormatTag == WAVE_FORMAT_PCM)
+    {
+        if(self->Format.wBitsPerSample == 16)
+            device->FmtType = DevFmtShort;
+        else if(self->Format.wBitsPerSample == 8)
+            device->FmtType = DevFmtUByte;
+        else
+        {
+            ERR("Unhandled PCM sample depth: %d\n", self->Format.wBitsPerSample);
+            return ALC_FALSE;
+        }
+    }
+    else
+    {
+        ERR("Unhandled format tag: 0x%04x\n", self->Format.wFormatTag);
+        return ALC_FALSE;
+    }
+
+    if(self->Format.nChannels == 2)
+        device->FmtChans = DevFmtStereo;
+    else if(self->Format.nChannels == 1)
+        device->FmtChans = DevFmtMono;
+    else
+    {
+        ERR("Unhandled channel count: %d\n", self->Format.nChannels);
+        return ALC_FALSE;
+    }
+    SetDefaultWFXChannelOrder(device);
+
+    return ALC_TRUE;
+}
+
+static ALCboolean ALCwinmmPlayback_start(ALCwinmmPlayback *self)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    ALbyte *BufferData;
+    ALint BufferSize;
+    ALuint i;
+
+    self->killNow = AL_FALSE;
+    if(althrd_create(&self->thread, ALCwinmmPlayback_mixerProc, self) != althrd_success)
+        return ALC_FALSE;
+
+    InitRef(&self->WaveBuffersCommitted, 0);
+
+    // Create 4 Buffers
+    BufferSize  = device->UpdateSize*device->NumUpdates / 4;
+    BufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType, device->AmbiOrder);
+
+    BufferData = calloc(4, BufferSize);
+    for(i = 0;i < 4;i++)
+    {
+        memset(&self->WaveBuffer[i], 0, sizeof(WAVEHDR));
+        self->WaveBuffer[i].dwBufferLength = BufferSize;
+        self->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData :
+                                      (self->WaveBuffer[i-1].lpData +
+                                       self->WaveBuffer[i-1].dwBufferLength));
+        waveOutPrepareHeader(self->OutHdl, &self->WaveBuffer[i], sizeof(WAVEHDR));
+        waveOutWrite(self->OutHdl, &self->WaveBuffer[i], sizeof(WAVEHDR));
+        IncrementRef(&self->WaveBuffersCommitted);
+    }
+
+    return ALC_TRUE;
+}
+
+static void ALCwinmmPlayback_stop(ALCwinmmPlayback *self)
+{
+    void *buffer = NULL;
+    int i;
+
+    if(self->killNow)
+        return;
+
+    // Set flag to stop processing headers
+    self->killNow = AL_TRUE;
+    althrd_join(self->thread, &i);
+
+    // Release the wave buffers
+    for(i = 0;i < 4;i++)
+    {
+        waveOutUnprepareHeader(self->OutHdl, &self->WaveBuffer[i], sizeof(WAVEHDR));
+        if(i == 0) buffer = self->WaveBuffer[i].lpData;
+        self->WaveBuffer[i].lpData = NULL;
+    }
+    free(buffer);
+}
+
+
+
+typedef struct ALCwinmmCapture {
+    DERIVE_FROM_TYPE(ALCbackend);
+
+    RefCount WaveBuffersCommitted;
+    WAVEHDR WaveBuffer[4];
+
+    HWAVEIN InHdl;
+
+    ll_ringbuffer_t *Ring;
+
+    WAVEFORMATEX Format;
+
+    volatile ALboolean killNow;
+    althrd_t thread;
+} ALCwinmmCapture;
+
+static void ALCwinmmCapture_Construct(ALCwinmmCapture *self, ALCdevice *device);
+static void ALCwinmmCapture_Destruct(ALCwinmmCapture *self);
+
+static void CALLBACK ALCwinmmCapture_waveInProc(HWAVEIN device, UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR param2);
+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);
+static ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *buffer, ALCuint samples);
+static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self);
+static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, ClockLatency, getClockLatency)
+static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, void, lock)
+static DECLARE_FORWARD(ALCwinmmCapture, ALCbackend, void, unlock)
+DECLARE_DEFAULT_ALLOCATORS(ALCwinmmCapture)
+
+DEFINE_ALCBACKEND_VTABLE(ALCwinmmCapture);
+
+
+static void ALCwinmmCapture_Construct(ALCwinmmCapture *self, ALCdevice *device)
+{
+    ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device);
+    SET_VTABLE2(ALCwinmmCapture, ALCbackend, self);
+
+    InitRef(&self->WaveBuffersCommitted, 0);
+    self->InHdl = NULL;
+
+    self->killNow = AL_TRUE;
+}
+
+static void ALCwinmmCapture_Destruct(ALCwinmmCapture *self)
+{
+    if(self->InHdl)
+        waveInClose(self->InHdl);
+    self->InHdl = 0;
+
+    ALCbackend_Destruct(STATIC_CAST(ALCbackend, self));
+}
+
+
+/* ALCwinmmCapture_waveInProc
+ *
+ * Posts a message to 'ALCwinmmCapture_captureProc' everytime a WaveIn Buffer
+ * is completed and returns to the application (with more data).
+ */
+static void CALLBACK ALCwinmmCapture_waveInProc(HWAVEIN UNUSED(device), UINT msg, DWORD_PTR instance, DWORD_PTR param1, DWORD_PTR UNUSED(param2))
+{
+    ALCwinmmCapture *self = (ALCwinmmCapture*)instance;
+
+    if(msg != WIM_DATA)
+        return;
+
+    DecrementRef(&self->WaveBuffersCommitted);
+    PostThreadMessage(self->thread, msg, 0, param1);
+}
+
+static int ALCwinmmCapture_captureProc(void *arg)
+{
+    ALCwinmmCapture *self = arg;
+    WAVEHDR *WaveHdr;
+    MSG msg;
+
+    althrd_setname(althrd_current(), RECORD_THREAD_NAME);
+
+    while(GetMessage(&msg, NULL, 0, 0))
+    {
+        if(msg.message != WIM_DATA)
+            continue;
+        /* Don't wait for other buffers to finish before quitting. We're
+         * closing so we don't need them. */
+        if(self->killNow)
+            break;
+
+        WaveHdr = ((WAVEHDR*)msg.lParam);
+        ll_ringbuffer_write(self->Ring, WaveHdr->lpData,
+            WaveHdr->dwBytesRecorded / self->Format.nBlockAlign
+        );
+
+        // Send buffer back to capture more data
+        waveInAddBuffer(self->InHdl, WaveHdr, sizeof(WAVEHDR));
+        IncrementRef(&self->WaveBuffersCommitted);
+    }
+
+    return 0;
+}
+
+
+static ALCenum ALCwinmmCapture_open(ALCwinmmCapture *self, const ALCchar *name)
+{
+    ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice;
+    const al_string *iter;
+    ALbyte *BufferData = NULL;
+    DWORD CapturedDataSize;
+    ALint BufferSize;
+    UINT DeviceID;
+    MMRESULT res;
+    ALuint i;
+
+    if(VECTOR_SIZE(CaptureDevices) == 0)
+        ProbeCaptureDevices();
+
+    // Find the Device ID matching the deviceName if valid
+#define MATCH_DEVNAME(iter) (!alstr_empty(*(iter)) && (!name || alstr_cmp_cstr(*iter, name) == 0))
+    VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_DEVNAME);
+    if(iter == VECTOR_END(CaptureDevices))
+        return ALC_INVALID_VALUE;
+#undef MATCH_DEVNAME
+
+    DeviceID = (UINT)(iter - VECTOR_BEGIN(CaptureDevices));
+
+    switch(device->FmtChans)
+    {
+        case DevFmtMono:
+        case DevFmtStereo:
+            break;
+
+        case DevFmtQuad:
+        case DevFmtX51:
+        case DevFmtX51Rear:
+        case DevFmtX61:
+        case DevFmtX71:
+        case DevFmtAmbi3D:
+            return ALC_INVALID_ENUM;
+    }
+
+    switch(device->FmtType)
+    {
+        case DevFmtUByte:
+        case DevFmtShort:
+        case DevFmtInt:
+        case DevFmtFloat:
+            break;
+
+        case DevFmtByte:
+        case DevFmtUShort:
+        case DevFmtUInt:
+            return ALC_INVALID_ENUM;
+    }
+
+    memset(&self->Format, 0, sizeof(WAVEFORMATEX));
+    self->Format.wFormatTag = ((device->FmtType == DevFmtFloat) ?
+                               WAVE_FORMAT_IEEE_FLOAT : WAVE_FORMAT_PCM);
+    self->Format.nChannels = ChannelsFromDevFmt(device->FmtChans, device->AmbiOrder);
+    self->Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8;
+    self->Format.nBlockAlign = self->Format.wBitsPerSample *
+                               self->Format.nChannels / 8;
+    self->Format.nSamplesPerSec = device->Frequency;
+    self->Format.nAvgBytesPerSec = self->Format.nSamplesPerSec *
+                                   self->Format.nBlockAlign;
+    self->Format.cbSize = 0;
+
+    if((res=waveInOpen(&self->InHdl, DeviceID, &self->Format, (DWORD_PTR)&ALCwinmmCapture_waveInProc, (DWORD_PTR)self, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR)
+    {
+        ERR("waveInOpen failed: %u\n", res);
+        goto failure;
+    }
+
+    // Allocate circular memory buffer for the captured audio
+    CapturedDataSize = device->UpdateSize*device->NumUpdates;
+
+    // Make sure circular buffer is at least 100ms in size
+    if(CapturedDataSize < (self->Format.nSamplesPerSec / 10))
+        CapturedDataSize = self->Format.nSamplesPerSec / 10;
+
+    self->Ring = ll_ringbuffer_create(CapturedDataSize+1, self->Format.nBlockAlign);
+    if(!self->Ring) goto failure;
+
+    InitRef(&self->WaveBuffersCommitted, 0);
+
+    // Create 4 Buffers of 50ms each
+    BufferSize = self->Format.nAvgBytesPerSec / 20;
+    BufferSize -= (BufferSize % self->Format.nBlockAlign);
+
+    BufferData = calloc(4, BufferSize);
+    if(!BufferData) goto failure;
+
+    for(i = 0;i < 4;i++)
+    {
+        memset(&self->WaveBuffer[i], 0, sizeof(WAVEHDR));
+        self->WaveBuffer[i].dwBufferLength = BufferSize;
+        self->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData :
+                                      (self->WaveBuffer[i-1].lpData +
+                                       self->WaveBuffer[i-1].dwBufferLength));
+        self->WaveBuffer[i].dwFlags = 0;
+        self->WaveBuffer[i].dwLoops = 0;
+        waveInPrepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR));
+        waveInAddBuffer(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR));
+        IncrementRef(&self->WaveBuffersCommitted);
+    }
+
+    self->killNow = AL_FALSE;
+    if(althrd_create(&self->thread, ALCwinmmCapture_captureProc, self) != althrd_success)
+        goto failure;
+
+    alstr_copy(&device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID));
+    return ALC_NO_ERROR;
+
+failure:
+    if(BufferData)
+    {
+        for(i = 0;i < 4;i++)
+            waveInUnprepareHeader(self->InHdl, &self->WaveBuffer[i], sizeof(WAVEHDR));
+        free(BufferData);
+    }
+
+    ll_ringbuffer_free(self->Ring);
+    self->Ring = NULL;
+
+    if(self->InHdl)
+        waveInClose(self->InHdl);
+    self->InHdl = NULL;
+
+    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);
+    return ALC_TRUE;
+}
+
+static void ALCwinmmCapture_stop(ALCwinmmCapture *self)
+{
+    waveInStop(self->InHdl);
+}
+
+static ALCenum ALCwinmmCapture_captureSamples(ALCwinmmCapture *self, ALCvoid *buffer, ALCuint samples)
+{
+    ll_ringbuffer_read(self->Ring, buffer, samples);
+    return ALC_NO_ERROR;
+}
+
+static ALCuint ALCwinmmCapture_availableSamples(ALCwinmmCapture *self)
+{
+    return ll_ringbuffer_read_space(self->Ring);
+}
+
+
+static inline void AppendAllDevicesList2(const al_string *name)
+{
+    if(!alstr_empty(*name))
+        AppendAllDevicesList(alstr_get_cstr(*name));
+}
+static inline void AppendCaptureDeviceList2(const al_string *name)
+{
+    if(!alstr_empty(*name))
+        AppendCaptureDeviceList(alstr_get_cstr(*name));
+}
+
+typedef struct ALCwinmmBackendFactory {
+    DERIVE_FROM_TYPE(ALCbackendFactory);
+} ALCwinmmBackendFactory;
+#define ALCWINMMBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCwinmmBackendFactory, ALCbackendFactory) } }
+
+static ALCboolean ALCwinmmBackendFactory_init(ALCwinmmBackendFactory *self);
+static void ALCwinmmBackendFactory_deinit(ALCwinmmBackendFactory *self);
+static ALCboolean ALCwinmmBackendFactory_querySupport(ALCwinmmBackendFactory *self, ALCbackend_Type type);
+static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory *self, enum DevProbe type);
+static ALCbackend* ALCwinmmBackendFactory_createBackend(ALCwinmmBackendFactory *self, ALCdevice *device, ALCbackend_Type type);
+
+DEFINE_ALCBACKENDFACTORY_VTABLE(ALCwinmmBackendFactory);
+
+
+static ALCboolean ALCwinmmBackendFactory_init(ALCwinmmBackendFactory* UNUSED(self))
+{
+    VECTOR_INIT(PlaybackDevices);
+    VECTOR_INIT(CaptureDevices);
+
+    return ALC_TRUE;
+}
+
+static void ALCwinmmBackendFactory_deinit(ALCwinmmBackendFactory* UNUSED(self))
+{
+    clear_devlist(&PlaybackDevices);
+    VECTOR_DEINIT(PlaybackDevices);
+
+    clear_devlist(&CaptureDevices);
+    VECTOR_DEINIT(CaptureDevices);
+}
+
+static ALCboolean ALCwinmmBackendFactory_querySupport(ALCwinmmBackendFactory* UNUSED(self), ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback || type == ALCbackend_Capture)
+        return ALC_TRUE;
+    return ALC_FALSE;
+}
+
+static void ALCwinmmBackendFactory_probe(ALCwinmmBackendFactory* UNUSED(self), enum DevProbe type)
+{
+    switch(type)
+    {
+        case ALL_DEVICE_PROBE:
+            ProbePlaybackDevices();
+            VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2);
+            break;
+
+        case CAPTURE_DEVICE_PROBE:
+            ProbeCaptureDevices();
+            VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2);
+            break;
+    }
+}
+
+static ALCbackend* ALCwinmmBackendFactory_createBackend(ALCwinmmBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type)
+{
+    if(type == ALCbackend_Playback)
+    {
+        ALCwinmmPlayback *backend;
+        NEW_OBJ(backend, ALCwinmmPlayback)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+    if(type == ALCbackend_Capture)
+    {
+        ALCwinmmCapture *backend;
+        NEW_OBJ(backend, ALCwinmmCapture)(device);
+        if(!backend) return NULL;
+        return STATIC_CAST(ALCbackend, backend);
+    }
+
+    return NULL;
+}
+
+ALCbackendFactory *ALCwinmmBackendFactory_getFactory(void)
+{
+    static ALCwinmmBackendFactory factory = ALCWINMMBACKENDFACTORY_INITIALIZER;
+    return STATIC_CAST(ALCbackendFactory, &factory);
+}

+ 612 - 0
love/src/jni/openal-soft-1.18.2/Alc/bformatdec.c

@@ -0,0 +1,612 @@
+
+#include "config.h"
+
+#include "bformatdec.h"
+#include "ambdec.h"
+#include "mixer_defs.h"
+#include "alu.h"
+
+#include "bool.h"
+#include "threads.h"
+#include "almalloc.h"
+
+
+void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult)
+{
+    ALfloat w = freq_mult * F_TAU;
+    ALfloat cw = cosf(w);
+    if(cw > FLT_EPSILON)
+        splitter->coeff = (sinf(w) - 1.0f) / cw;
+    else
+        splitter->coeff = cw * -0.5f;
+
+    splitter->lp_z1 = 0.0f;
+    splitter->lp_z2 = 0.0f;
+    splitter->hp_z1 = 0.0f;
+}
+
+void bandsplit_clear(BandSplitter *splitter)
+{
+    splitter->lp_z1 = 0.0f;
+    splitter->lp_z2 = 0.0f;
+    splitter->hp_z1 = 0.0f;
+}
+
+void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
+                       const ALfloat *input, ALsizei count)
+{
+    ALfloat coeff, d, x;
+    ALfloat z1, z2;
+    ALsizei i;
+
+    coeff = splitter->coeff*0.5f + 0.5f;
+    z1 = splitter->lp_z1;
+    z2 = splitter->lp_z2;
+    for(i = 0;i < count;i++)
+    {
+        x = input[i];
+
+        d = (x - z1) * coeff;
+        x = z1 + d;
+        z1 = x + d;
+
+        d = (x - z2) * coeff;
+        x = z2 + d;
+        z2 = x + d;
+
+        lpout[i] = x;
+    }
+    splitter->lp_z1 = z1;
+    splitter->lp_z2 = z2;
+
+    coeff = splitter->coeff;
+    z1 = splitter->hp_z1;
+    for(i = 0;i < count;i++)
+    {
+        x = input[i];
+
+        d = x - coeff*z1;
+        x = z1 + coeff*d;
+        z1 = d;
+
+        hpout[i] = x - lpout[i];
+    }
+    splitter->hp_z1 = z1;
+}
+
+
+void splitterap_init(SplitterAllpass *splitter, ALfloat freq_mult)
+{
+    ALfloat w = freq_mult * F_TAU;
+    ALfloat cw = cosf(w);
+    if(cw > FLT_EPSILON)
+        splitter->coeff = (sinf(w) - 1.0f) / cw;
+    else
+        splitter->coeff = cw * -0.5f;
+
+    splitter->z1 = 0.0f;
+}
+
+void splitterap_clear(SplitterAllpass *splitter)
+{
+    splitter->z1 = 0.0f;
+}
+
+void splitterap_process(SplitterAllpass *splitter, ALfloat *restrict samples, ALsizei count)
+{
+    ALfloat coeff, d, x;
+    ALfloat z1;
+    ALsizei i;
+
+    coeff = splitter->coeff;
+    z1 = splitter->z1;
+    for(i = 0;i < count;i++)
+    {
+        x = samples[i];
+
+        d = x - coeff*z1;
+        x = z1 + coeff*d;
+        z1 = d;
+
+        samples[i] = x;
+    }
+    splitter->z1 = z1;
+}
+
+
+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) */
+};
+
+
+enum FreqBand {
+    FB_HighFreq,
+    FB_LowFreq,
+    FB_Max
+};
+
+/* These points are in AL coordinates! */
+static const ALfloat Ambi3DPoints[8][3] = {
+    { -0.577350269f,  0.577350269f, -0.577350269f },
+    {  0.577350269f,  0.577350269f, -0.577350269f },
+    { -0.577350269f,  0.577350269f,  0.577350269f },
+    {  0.577350269f,  0.577350269f,  0.577350269f },
+    { -0.577350269f, -0.577350269f, -0.577350269f },
+    {  0.577350269f, -0.577350269f, -0.577350269f },
+    { -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 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];
+
+    union {
+        alignas(16) ALfloat Dual[MAX_OUTPUT_CHANNELS][FB_Max][MAX_AMBI_COEFFS];
+        alignas(16) ALfloat Single[MAX_OUTPUT_CHANNELS][MAX_AMBI_COEFFS];
+    } Matrix;
+
+    BandSplitter XOver[MAX_AMBI_COEFFS];
+
+    ALfloat (*Samples)[BUFFERSIZE];
+    /* These two alias into Samples */
+    ALfloat (*SamplesHF)[BUFFERSIZE];
+    ALfloat (*SamplesLF)[BUFFERSIZE];
+
+    alignas(16) ALfloat ChannelMix[BUFFERSIZE];
+
+    struct {
+        BandSplitter XOver;
+        ALfloat Gains[FB_Max];
+    } UpSampler[4];
+
+    ALsizei NumChannels;
+    ALboolean DualBand;
+} BFormatDec;
+
+BFormatDec *bformatdec_alloc()
+{
+    alcall_once(&bformatdec_inited, init_bformatdec);
+    return al_calloc(16, sizeof(BFormatDec));
+}
+
+void bformatdec_free(BFormatDec *dec)
+{
+    if(dec)
+    {
+        al_free(dec->Samples);
+        dec->Samples = NULL;
+        dec->SamplesHF = NULL;
+        dec->SamplesLF = NULL;
+
+        memset(dec, 0, sizeof(*dec));
+        al_free(dec);
+    }
+}
+
+void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALsizei chancount, ALuint srate, const ALsizei chanmap[MAX_OUTPUT_CHANNELS])
+{
+    static const ALsizei map2DTo3D[MAX_AMBI2D_COEFFS] = {
+        0,  1, 3,  4, 8,  9, 15
+    };
+    const ALfloat *coeff_scale = UnitScale;
+    bool periphonic;
+    ALfloat ratio;
+    ALsizei i;
+
+    al_free(dec->Samples);
+    dec->Samples = NULL;
+    dec->SamplesHF = NULL;
+    dec->SamplesLF = NULL;
+
+    dec->NumChannels = chancount;
+    dec->Samples = al_calloc(16, dec->NumChannels*2 * sizeof(dec->Samples[0]));
+    dec->SamplesHF = dec->Samples;
+    dec->SamplesLF = dec->SamplesHF + dec->NumChannels;
+
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+        dec->Enabled[i] = AL_FALSE;
+    for(i = 0;i < conf->NumSpeakers;i++)
+        dec->Enabled[chanmap[i]] = AL_TRUE;
+
+    if(conf->CoeffScale == ADS_SN3D)
+        coeff_scale = SN3D2N3DScale;
+    else if(conf->CoeffScale == ADS_FuMa)
+        coeff_scale = FuMa2N3DScale;
+
+    memset(dec->UpSampler, 0, sizeof(dec->UpSampler));
+    ratio = 400.0f / (ALfloat)srate;
+    for(i = 0;i < 4;i++)
+        bandsplit_init(&dec->UpSampler[i].XOver, ratio);
+    if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
+    {
+        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;
+        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;
+        }
+    }
+    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;
+        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[3].Gains[FB_HighFreq] = 0.0f;
+        dec->UpSampler[3].Gains[FB_LowFreq] = 0.0f;
+    }
+
+    memset(&dec->Matrix, 0, sizeof(dec->Matrix));
+    if(conf->FreqBands == 1)
+    {
+        dec->DualBand = AL_FALSE;
+        for(i = 0;i < conf->NumSpeakers;i++)
+        {
+            ALsizei chan = chanmap[i];
+            ALfloat gain;
+            ALsizei j, k;
+
+            if(!periphonic)
+            {
+                for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
+                {
+                    ALsizei l = map2DTo3D[j];
+                    if(j == 0) gain = conf->HFOrderGain[0];
+                    else if(j == 1) gain = conf->HFOrderGain[1];
+                    else if(j == 3) gain = conf->HFOrderGain[2];
+                    else if(j == 5) gain = conf->HFOrderGain[3];
+                    if((conf->ChanMask&(1<<l)))
+                        dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[l] *
+                                                      gain;
+                }
+            }
+            else
+            {
+                for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
+                {
+                    if(j == 0) gain = conf->HFOrderGain[0];
+                    else if(j == 1) gain = conf->HFOrderGain[1];
+                    else if(j == 4) gain = conf->HFOrderGain[2];
+                    else if(j == 9) gain = conf->HFOrderGain[3];
+                    if((conf->ChanMask&(1<<j)))
+                        dec->Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[j] *
+                                                      gain;
+                }
+            }
+        }
+    }
+    else
+    {
+        dec->DualBand = AL_TRUE;
+
+        ratio = conf->XOverFreq / (ALfloat)srate;
+        for(i = 0;i < MAX_AMBI_COEFFS;i++)
+            bandsplit_init(&dec->XOver[i], ratio);
+
+        ratio = powf(10.0f, conf->XOverRatio / 40.0f);
+        for(i = 0;i < conf->NumSpeakers;i++)
+        {
+            ALsizei chan = chanmap[i];
+            ALfloat gain;
+            ALsizei j, k;
+
+            if(!periphonic)
+            {
+                for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
+                {
+                    ALsizei l = map2DTo3D[j];
+                    if(j == 0) gain = conf->HFOrderGain[0] * ratio;
+                    else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
+                    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;
+                }
+                for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++)
+                {
+                    ALsizei l = map2DTo3D[j];
+                    if(j == 0) gain = conf->LFOrderGain[0] / ratio;
+                    else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
+                    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;
+                }
+            }
+            else
+            {
+                for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
+                {
+                    if(j == 0) gain = conf->HFOrderGain[0] * ratio;
+                    else if(j == 1) gain = conf->HFOrderGain[1] * ratio;
+                    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;
+                }
+                for(j = 0,k = 0;j < MAX_AMBI_COEFFS;j++)
+                {
+                    if(j == 0) gain = conf->LFOrderGain[0] / ratio;
+                    else if(j == 1) gain = conf->LFOrderGain[1] / ratio;
+                    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;
+                }
+            }
+        }
+    }
+}
+
+
+void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
+{
+    ALsizei chan, i;
+
+    OutBuffer = ASSUME_ALIGNED(OutBuffer, 16);
+    if(dec->DualBand)
+    {
+        for(i = 0;i < dec->NumChannels;i++)
+            bandsplit_process(&dec->XOver[i], dec->SamplesHF[i], dec->SamplesLF[i],
+                              InSamples[i], SamplesToDo);
+
+        for(chan = 0;chan < OutChannels;chan++)
+        {
+            if(!dec->Enabled[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
+            );
+            MixMatrixRow(dec->ChannelMix, dec->Matrix.Dual[chan][FB_LowFreq],
+                SAFE_CONST(ALfloatBUFFERSIZE*,dec->SamplesLF), dec->NumChannels, 0,
+                SamplesToDo
+            );
+
+            for(i = 0;i < SamplesToDo;i++)
+                OutBuffer[chan][i] += dec->ChannelMix[i];
+        }
+    }
+    else
+    {
+        for(chan = 0;chan < OutChannels;chan++)
+        {
+            if(!dec->Enabled[chan])
+                continue;
+
+            memset(dec->ChannelMix, 0, SamplesToDo*sizeof(ALfloat));
+            MixMatrixRow(dec->ChannelMix, dec->Matrix.Single[chan], InSamples,
+                         dec->NumChannels, 0, SamplesToDo);
+
+            for(i = 0;i < SamplesToDo;i++)
+                OutBuffer[chan][i] += dec->ChannelMix[i];
+        }
+    }
+}
+
+
+void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei InChannels, ALsizei SamplesToDo)
+{
+    ALsizei i;
+
+    /* This up-sampler leverages the differences observed in dual-band second-
+     * and third-order decoder matrices compared to first-order. For the same
+     * output channel configuration, the low-frequency matrix has identical
+     * coefficients in the shared input channels, while the high-frequency
+     * matrix has extra scalars applied to the W channel and X/Y/Z channels.
+     * Mixing the first-order content into the higher-order stream with the
+     * appropriate counter-scales applied to the HF response results in the
+     * subsequent higher-order decode generating the same response as a first-
+     * order decode.
+     */
+    for(i = 0;i < InChannels;i++)
+    {
+        /* First, split the first-order components into low and high frequency
+         * bands.
+         */
+        bandsplit_process(&dec->UpSampler[i].XOver,
+            dec->Samples[FB_HighFreq], dec->Samples[FB_LowFreq],
+            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
+        );
+    }
+}
+
+
+#define INVALID_UPSAMPLE_INDEX INT_MAX
+
+static ALsizei GetACNIndex(const BFChannelConfig *chans, ALsizei numchans, ALsizei acn)
+{
+    ALsizei i;
+    for(i = 0;i < numchans;i++)
+    {
+        if(chans[i].Index == acn)
+            return i;
+    }
+    return INVALID_UPSAMPLE_INDEX;
+}
+#define GetChannelForACN(b, a) GetACNIndex((b).Ambi.Map, (b).NumChannels, (a))
+
+typedef struct AmbiUpsampler {
+    alignas(16) ALfloat Samples[FB_Max][BUFFERSIZE];
+
+    BandSplitter XOver[4];
+
+    ALfloat Gains[4][MAX_OUTPUT_CHANNELS][FB_Max];
+} AmbiUpsampler;
+
+AmbiUpsampler *ambiup_alloc()
+{
+    alcall_once(&bformatdec_inited, init_bformatdec);
+    return al_calloc(16, sizeof(AmbiUpsampler));
+}
+
+void ambiup_free(struct AmbiUpsampler *ambiup)
+{
+    al_free(ambiup);
+}
+
+void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device)
+{
+    ALfloat ratio;
+    size_t i;
+
+    ratio = 400.0f / (ALfloat)device->Frequency;
+    for(i = 0;i < 4;i++)
+        bandsplit_init(&ambiup->XOver[i], ratio);
+
+    memset(ambiup->Gains, 0, sizeof(ambiup->Gains));
+    if(device->Dry.CoeffCount > 0)
+    {
+        ALfloat encgains[8][MAX_OUTPUT_CHANNELS];
+        ALsizei j;
+        size_t k;
+
+        for(i = 0;i < COUNTOF(Ambi3DPoints);i++)
+        {
+            ALfloat coeffs[MAX_AMBI_COEFFS] = { 0.0f };
+            CalcDirectionCoeffs(Ambi3DPoints[i], 0.0f, coeffs);
+            ComputePanningGains(device->Dry, coeffs, 1.0f, encgains[i]);
+        }
+
+        /* Combine the matrices that do the in->virt and virt->out conversions
+         * so we get a single in->out conversion. NOTE: the Encoder matrix
+         * (encgains) and output are transposed, so the input channels line up
+         * with the rows and the output channels line up with the columns.
+         */
+        for(i = 0;i < 4;i++)
+        {
+            for(j = 0;j < device->Dry.NumChannels;j++)
+            {
+                ALfloat hfgain=0.0f, lfgain=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;
+            }
+        }
+    }
+    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;
+            }
+        }
+    }
+}
+
+void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo)
+{
+    ALsizei i, j;
+
+    for(i = 0;i < 4;i++)
+    {
+        bandsplit_process(&ambiup->XOver[i],
+            ambiup->Samples[FB_HighFreq], ambiup->Samples[FB_LowFreq],
+            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
+            );
+    }
+}

+ 75 - 0
love/src/jni/openal-soft-1.18.2/Alc/bformatdec.h

@@ -0,0 +1,75 @@
+#ifndef BFORMATDEC_H
+#define BFORMATDEC_H
+
+#include "alMain.h"
+
+
+/* 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
+
+/* 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
+
+
+struct AmbDecConf;
+struct BFormatDec;
+struct AmbiUpsampler;
+
+
+struct BFormatDec *bformatdec_alloc();
+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. */
+void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
+
+/* Up-samples a first-order input to the decoder's configuration. */
+void bformatdec_upSample(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei InChannels, ALsizei SamplesToDo);
+
+
+/* Stand-alone first-order upsampler. Kept here because it shares some stuff
+ * with bformatdec.
+ */
+struct AmbiUpsampler *ambiup_alloc();
+void ambiup_free(struct AmbiUpsampler *ambiup);
+void ambiup_reset(struct AmbiUpsampler *ambiup, const ALCdevice *device);
+
+void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALsizei OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALsizei SamplesToDo);
+
+
+/* Band splitter. Splits a signal into two phase-matching frequency bands. */
+typedef struct BandSplitter {
+    ALfloat coeff;
+    ALfloat lp_z1;
+    ALfloat lp_z2;
+    ALfloat hp_z1;
+} BandSplitter;
+
+void bandsplit_init(BandSplitter *splitter, ALfloat freq_mult);
+void bandsplit_clear(BandSplitter *splitter);
+void bandsplit_process(BandSplitter *splitter, ALfloat *restrict hpout, ALfloat *restrict lpout,
+                       const ALfloat *input, ALsizei count);
+
+/* The all-pass portion of the band splitter. Applies the same phase shift
+ * without splitting the signal.
+ */
+typedef struct SplitterAllpass {
+    ALfloat coeff;
+    ALfloat z1;
+} SplitterAllpass;
+
+void splitterap_init(SplitterAllpass *splitter, ALfloat freq_mult);
+void splitterap_clear(SplitterAllpass *splitter);
+void splitterap_process(SplitterAllpass *splitter, ALfloat *restrict samples, ALsizei count);
+
+#endif /* BFORMATDEC_H */

+ 62 - 18
love/src/jni/openal-soft-1.17.0/Alc/bs2b.c → love/src/jni/openal-soft-1.18.2/Alc/bs2b.c

@@ -29,9 +29,6 @@
 #include "bs2b.h"
 #include "alu.h"
 
-#ifndef M_PI
-#define M_PI  3.14159265358979323846
-#endif
 
 /* Set up all data. */
 static void init(struct bs2b *bs2b)
@@ -40,8 +37,6 @@ static void init(struct bs2b *bs2b)
     float G_lo,  G_hi;
     float x, g;
 
-    bs2b->srate = clampi(bs2b->srate, 2000, 192000);
-
     switch(bs2b->level)
     {
     case BS2B_LOW_CLEVEL: /* Low crossfeed level */
@@ -105,31 +100,25 @@ static void init(struct bs2b *bs2b)
     bs2b->a1_hi = -x * g;
 } /* init */
 
+
 /* Exported functions.
  * See descriptions in "bs2b.h"
  */
 
-void bs2b_set_level(struct bs2b *bs2b, int level)
+void bs2b_set_params(struct bs2b *bs2b, int level, int srate)
 {
-    if(level == bs2b->level)
-        return;
+    if(srate <= 0) srate = 1;
+
     bs2b->level = level;
+    bs2b->srate = srate;
     init(bs2b);
-} /* bs2b_set_level */
+} /* bs2b_set_params */
 
 int bs2b_get_level(struct bs2b *bs2b)
 {
     return bs2b->level;
 } /* bs2b_get_level */
 
-void bs2b_set_srate(struct bs2b *bs2b, int srate)
-{
-    if (srate == bs2b->srate)
-        return;
-    bs2b->srate = srate;
-    init(bs2b);
-} /* bs2b_set_srate */
-
 int bs2b_get_srate(struct bs2b *bs2b)
 {
     return bs2b->srate;
@@ -140,4 +129,59 @@ void bs2b_clear(struct bs2b *bs2b)
     memset(&bs2b->last_sample, 0, sizeof(bs2b->last_sample));
 } /* bs2b_clear */
 
-extern inline void bs2b_cross_feed(struct bs2b *bs2b, float *restrict samples);
+void bs2b_cross_feed(struct bs2b *bs2b, float *restrict Left, float *restrict Right, int SamplesToDo)
+{
+    float lsamples[128][2];
+    float rsamples[128][2];
+    int base;
+
+    for(base = 0;base < SamplesToDo;)
+    {
+        int todo = mini(128, SamplesToDo-base);
+        int i;
+
+        /* Process left input */
+        lsamples[0][0] = bs2b->a0_lo*Left[0] +
+                         bs2b->b1_lo*bs2b->last_sample[0].lo;
+        lsamples[0][1] = bs2b->a0_hi*Left[0] +
+                         bs2b->a1_hi*bs2b->last_sample[0].asis +
+                         bs2b->b1_hi*bs2b->last_sample[0].hi;
+        for(i = 1;i < todo;i++)
+        {
+            lsamples[i][0] = bs2b->a0_lo*Left[i] +
+                             bs2b->b1_lo*lsamples[i-1][0];
+            lsamples[i][1] = bs2b->a0_hi*Left[i] +
+                             bs2b->a1_hi*Left[i-1] +
+                             bs2b->b1_hi*lsamples[i-1][1];
+        }
+        bs2b->last_sample[0].asis = Left[i-1];
+        bs2b->last_sample[0].lo = lsamples[i-1][0];
+        bs2b->last_sample[0].hi = lsamples[i-1][1];
+
+        /* Process right input */
+        rsamples[0][0] = bs2b->a0_lo*Right[0] +
+                         bs2b->b1_lo*bs2b->last_sample[1].lo;
+        rsamples[0][1] = bs2b->a0_hi*Right[0] +
+                         bs2b->a1_hi*bs2b->last_sample[1].asis +
+                         bs2b->b1_hi*bs2b->last_sample[1].hi;
+        for(i = 1;i < todo;i++)
+        {
+            rsamples[i][0] = bs2b->a0_lo*Right[i] +
+                             bs2b->b1_lo*rsamples[i-1][0];
+            rsamples[i][1] = bs2b->a0_hi*Right[i] +
+                             bs2b->a1_hi*Right[i-1] +
+                             bs2b->b1_hi*rsamples[i-1][1];
+        }
+        bs2b->last_sample[1].asis = Right[i-1];
+        bs2b->last_sample[1].lo = rsamples[i-1][0];
+        bs2b->last_sample[1].hi = rsamples[i-1][1];
+
+        /* Crossfeed */
+        for(i = 0;i < todo;i++)
+            *(Left++) = lsamples[i][1] + rsamples[i][0];
+        for(i = 0;i < todo;i++)
+            *(Right++) = rsamples[i][1] + lsamples[i][0];
+
+        base += todo;
+    }
+} /* bs2b_cross_feed */

+ 5081 - 0
love/src/jni/openal-soft-1.18.2/Alc/bsinc.c

@@ -0,0 +1,5081 @@
+
+#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 },
+};

+ 25 - 0
love/src/jni/openal-soft-1.17.0/Alc/compat.h → love/src/jni/openal-soft-1.18.2/Alc/compat.h

@@ -1,6 +1,8 @@
 #ifndef AL_COMPAT_H
 #define AL_COMPAT_H
 
+#include "alstring.h"
+
 #ifdef _WIN32
 
 #define WIN32_LEAN_AND_MEAN
@@ -23,10 +25,33 @@ FILE *al_fopen(const char *fname, const char *mode);
 
 #endif
 
+struct FileMapping {
+#ifdef _WIN32
+    HANDLE file;
+    HANDLE fmap;
+#else
+    int fd;
+#endif
+    void *ptr;
+    size_t len;
+};
+struct FileMapping MapFileToMem(const char *fname);
+void UnmapFileMem(const struct FileMapping *mapping);
+
+al_string GetProcPath(void);
+
 #ifdef HAVE_DYNLOAD
 void *LoadLib(const char *name);
 void CloseLib(void *handle);
 void *GetSymbol(void *handle, const char *name);
 #endif
 
+#ifdef __ANDROID__
+#define JCALL(obj, func)  ((*(obj))->func((obj), EXTRACT_VCALL_ARGS
+#define JCALL0(obj, func)  ((*(obj))->func((obj) EXTRACT_VCALL_ARGS
+
+/** Returns a JNIEnv*. */
+void *Android_GetJNIEnv(void);
+#endif
+
 #endif /* AL_COMPAT_H */

+ 466 - 0
love/src/jni/openal-soft-1.18.2/Alc/converter.c

@@ -0,0 +1,466 @@
+
+#include "config.h"
+
+#include "converter.h"
+
+#include "mixer_defs.h"
+
+
+SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType dstType, ALsizei numchans, ALsizei srcRate, ALsizei dstRate)
+{
+    SampleConverter *converter;
+    ALsizei step;
+
+    if(numchans <= 0 || srcRate <= 0 || dstRate <= 0)
+        return NULL;
+
+    converter = al_calloc(16, FAM_SIZE(SampleConverter, Chan, numchans));
+    converter->mSrcType = srcType;
+    converter->mDstType = dstType;
+    converter->mNumChannels = numchans;
+    converter->mSrcTypeSize = BytesFromDevFmt(srcType);
+    converter->mDstTypeSize = BytesFromDevFmt(dstType);
+
+    converter->mSrcPrepCount = 0;
+    converter->mFracOffset = 0;
+
+    /* 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);
+    converter->mIncrement = maxi(step, 1);
+    if(converter->mIncrement == FRACTIONONE)
+        converter->mResample = Resample_copy32_C;
+    else
+    {
+        /* TODO: Allow other resamplers. */
+        BsincPrepare(converter->mIncrement, &converter->mState.bsinc);
+        converter->mResample = SelectResampler(BSincResampler);
+    }
+    END_MIXER_MODE();
+
+    return converter;
+}
+
+void DestroySampleConverter(SampleConverter **converter)
+{
+    if(converter)
+    {
+        al_free(*converter);
+        *converter = NULL;
+    }
+}
+
+
+static inline ALfloat Sample_ALbyte(ALbyte val)
+{ return val * (1.0f/128.0f); }
+static inline ALfloat Sample_ALubyte(ALubyte val)
+{ return Sample_ALbyte((ALint)val - 128); }
+
+static inline ALfloat Sample_ALshort(ALshort val)
+{ return val * (1.0f/32768.0f); }
+static inline ALfloat Sample_ALushort(ALushort val)
+{ return Sample_ALshort((ALint)val - 32768); }
+
+static inline ALfloat Sample_ALint(ALint val)
+{ return (val>>7) * (1.0f/16777216.0f); }
+static inline ALfloat Sample_ALuint(ALuint val)
+{ return Sample_ALint(val - INT_MAX - 1); }
+
+static inline ALfloat Sample_ALfloat(ALfloat val)
+{ return val; }
+
+#define DECL_TEMPLATE(T)                                                      \
+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]);                                  \
+}
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+DECL_TEMPLATE(ALshort)
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+
+#undef DECL_TEMPLATE
+
+static void LoadSamples(ALfloat *dst, const ALvoid *src, ALint srcstep, enum DevFmtType srctype, ALsizei samples)
+{
+    switch(srctype)
+    {
+        case DevFmtByte:
+            Load_ALbyte(dst, src, srcstep, samples);
+            break;
+        case DevFmtUByte:
+            Load_ALubyte(dst, src, srcstep, samples);
+            break;
+        case DevFmtShort:
+            Load_ALshort(dst, src, srcstep, samples);
+            break;
+        case DevFmtUShort:
+            Load_ALushort(dst, src, srcstep, samples);
+            break;
+        case DevFmtInt:
+            Load_ALint(dst, src, srcstep, samples);
+            break;
+        case DevFmtUInt:
+            Load_ALuint(dst, src, srcstep, samples);
+            break;
+        case DevFmtFloat:
+            Load_ALfloat(dst, src, srcstep, samples);
+            break;
+    }
+}
+
+
+static inline ALbyte ALbyte_Sample(ALfloat val)
+{ return fastf2i(clampf(val*128.0f, -128.0f, 127.0f)); }
+static inline ALubyte ALubyte_Sample(ALfloat val)
+{ return ALbyte_Sample(val)+128; }
+
+static inline ALshort ALshort_Sample(ALfloat val)
+{ return fastf2i(clampf(val*32768.0f, -32768.0f, 32767.0f)); }
+static inline ALushort ALushort_Sample(ALfloat val)
+{ return ALshort_Sample(val)+32768; }
+
+static inline ALint ALint_Sample(ALfloat val)
+{ return fastf2i(clampf(val*16777216.0f, -16777216.0f, 16777215.0f)) << 7; }
+static inline ALuint ALuint_Sample(ALfloat val)
+{ return ALint_Sample(val)+INT_MAX+1; }
+
+static inline ALfloat ALfloat_Sample(ALfloat val)
+{ return val; }
+
+#define DECL_TEMPLATE(T)                                                      \
+static inline void Store_##T(T *restrict dst, const ALfloat *restrict src,    \
+                             ALint dststep, ALsizei samples)                  \
+{                                                                             \
+    ALsizei i;                                                                \
+    for(i = 0;i < samples;i++)                                                \
+        dst[i*dststep] = T##_Sample(src[i]);                                  \
+}
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+DECL_TEMPLATE(ALshort)
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+
+#undef DECL_TEMPLATE
+
+static void StoreSamples(ALvoid *dst, const ALfloat *src, ALint dststep, enum DevFmtType dsttype, ALsizei samples)
+{
+    switch(dsttype)
+    {
+        case DevFmtByte:
+            Store_ALbyte(dst, src, dststep, samples);
+            break;
+        case DevFmtUByte:
+            Store_ALubyte(dst, src, dststep, samples);
+            break;
+        case DevFmtShort:
+            Store_ALshort(dst, src, dststep, samples);
+            break;
+        case DevFmtUShort:
+            Store_ALushort(dst, src, dststep, samples);
+            break;
+        case DevFmtInt:
+            Store_ALint(dst, src, dststep, samples);
+            break;
+        case DevFmtUInt:
+            Store_ALuint(dst, src, dststep, samples);
+            break;
+        case DevFmtFloat:
+            Store_ALfloat(dst, src, dststep, samples);
+            break;
+    }
+}
+
+
+ALsizei SampleConverterAvailableOut(SampleConverter *converter, ALsizei srcframes)
+{
+    ALint prepcount = converter->mSrcPrepCount;
+    ALsizei increment = converter->mIncrement;
+    ALsizei DataPosFrac = converter->mFracOffset;
+    ALuint64 DataSize64;
+
+    if(prepcount < 0)
+    {
+        /* Negative prepcount means we need to skip that many input samples. */
+        if(-prepcount >= srcframes)
+            return 0;
+        srcframes += prepcount;
+        prepcount = 0;
+    }
+
+    if(srcframes < 1)
+    {
+        /* No output samples if there's no input samples. */
+        return 0;
+    }
+
+    if(prepcount < MAX_POST_SAMPLES+MAX_PRE_SAMPLES &&
+       MAX_POST_SAMPLES+MAX_PRE_SAMPLES-prepcount >= srcframes)
+    {
+        /* Not enough input samples to generate an output sample. */
+        return 0;
+    }
+
+    DataSize64  = prepcount;
+    DataSize64 += srcframes;
+    DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
+    DataSize64 <<= FRACTIONBITS;
+    DataSize64 -= DataPosFrac;
+
+    /* If we have a full prep, we can generate at least one sample. */
+    return (ALsizei)clampu64((DataSize64 + increment-1)/increment, 1, BUFFERSIZE);
+}
+
+
+ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALsizei *srcframes, ALvoid *dst, ALsizei dstframes)
+{
+    const ALsizei SrcFrameSize = converter->mNumChannels * converter->mSrcTypeSize;
+    const ALsizei DstFrameSize = converter->mNumChannels * converter->mDstTypeSize;
+    const ALsizei increment = converter->mIncrement;
+    ALsizei pos = 0;
+
+    START_MIXER_MODE();
+    while(pos < dstframes && *srcframes > 0)
+    {
+        ALfloat *restrict SrcData = ASSUME_ALIGNED(converter->mSrcSamples, 16);
+        ALfloat *restrict DstData = ASSUME_ALIGNED(converter->mDstSamples, 16);
+        ALint prepcount = converter->mSrcPrepCount;
+        ALsizei DataPosFrac = converter->mFracOffset;
+        ALuint64 DataSize64;
+        ALsizei DstSize;
+        ALint toread;
+        ALsizei chan;
+
+        if(prepcount < 0)
+        {
+            /* Negative prepcount means we need to skip that many input samples. */
+            if(-prepcount >= *srcframes)
+            {
+                converter->mSrcPrepCount = prepcount + *srcframes;
+                *srcframes = 0;
+                break;
+            }
+            *src = (const ALbyte*)*src + SrcFrameSize*-prepcount;
+            *srcframes += prepcount;
+            converter->mSrcPrepCount = 0;
+            continue;
+        }
+        toread = mini(*srcframes, BUFFERSIZE-(MAX_POST_SAMPLES+MAX_PRE_SAMPLES));
+
+        if(prepcount < MAX_POST_SAMPLES+MAX_PRE_SAMPLES &&
+           MAX_POST_SAMPLES+MAX_PRE_SAMPLES-prepcount >= toread)
+        {
+            /* Not enough input samples to generate an output sample. Store
+             * what we're given for later.
+             */
+            for(chan = 0;chan < converter->mNumChannels;chan++)
+                LoadSamples(&converter->Chan[chan].mPrevSamples[prepcount],
+                    (const ALbyte*)*src + converter->mSrcTypeSize*chan,
+                    converter->mNumChannels, converter->mSrcType, toread
+                );
+
+            converter->mSrcPrepCount = prepcount + toread;
+            *srcframes = 0;
+            break;
+        }
+
+        DataSize64  = prepcount;
+        DataSize64 += toread;
+        DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
+        DataSize64 <<= FRACTIONBITS;
+        DataSize64 -= DataPosFrac;
+
+        /* If we have a full prep, we can generate at least one sample. */
+        DstSize = (ALsizei)clampu64((DataSize64 + increment-1)/increment, 1, BUFFERSIZE);
+        DstSize = mini(DstSize, dstframes-pos);
+
+        for(chan = 0;chan < converter->mNumChannels;chan++)
+        {
+            const ALbyte *SrcSamples = (const ALbyte*)*src + converter->mSrcTypeSize*chan;
+            ALbyte *DstSamples = (ALbyte*)dst + converter->mDstTypeSize*chan;
+            const ALfloat *ResampledData;
+            ALsizei SrcDataEnd;
+
+            /* Load the previous samples into the source data first, then the
+             * new samples from the input buffer.
+             */
+            memcpy(SrcData, converter->Chan[chan].mPrevSamples,
+                   prepcount*sizeof(ALfloat));
+            LoadSamples(SrcData + prepcount, SrcSamples,
+                converter->mNumChannels, converter->mSrcType, toread
+            );
+
+            /* Store as many prep samples for next time as possible, given the
+             * number of output samples being generated.
+             */
+            SrcDataEnd = (DataPosFrac + increment*DstSize)>>FRACTIONBITS;
+            if(SrcDataEnd >= prepcount+toread)
+                memset(converter->Chan[chan].mPrevSamples, 0,
+                       sizeof(converter->Chan[chan].mPrevSamples));
+            else
+            {
+                size_t len = mini(MAX_PRE_SAMPLES+MAX_POST_SAMPLES, prepcount+toread-SrcDataEnd);
+                memcpy(converter->Chan[chan].mPrevSamples, &SrcData[SrcDataEnd],
+                       len*sizeof(ALfloat));
+                memset(converter->Chan[chan].mPrevSamples+len, 0,
+                       sizeof(converter->Chan[chan].mPrevSamples) - len*sizeof(ALfloat));
+            }
+
+            /* Now resample, and store the result in the output buffer. */
+            ResampledData = converter->mResample(&converter->mState,
+                SrcData+MAX_PRE_SAMPLES, DataPosFrac, increment,
+                DstData, DstSize
+            );
+
+            StoreSamples(DstSamples, ResampledData, converter->mNumChannels,
+                         converter->mDstType, DstSize);
+        }
+
+        /* Update the number of prep samples still available, as well as the
+         * fractional offset.
+         */
+        DataPosFrac += increment*DstSize;
+        converter->mSrcPrepCount = mini(MAX_PRE_SAMPLES+MAX_POST_SAMPLES,
+                                        prepcount+toread-(DataPosFrac>>FRACTIONBITS));
+        converter->mFracOffset = DataPosFrac & FRACTIONMASK;
+
+        /* Update the src and dst pointers in case there's still more to do. */
+        *src = (const ALbyte*)*src + SrcFrameSize*(DataPosFrac>>FRACTIONBITS);
+        *srcframes -= mini(*srcframes, (DataPosFrac>>FRACTIONBITS));
+
+        dst = (ALbyte*)dst + DstFrameSize*DstSize;
+        pos += DstSize;
+    }
+    END_MIXER_MODE();
+
+    return pos;
+}
+
+
+ChannelConverter *CreateChannelConverter(enum DevFmtType srcType, enum DevFmtChannels srcChans, enum DevFmtChannels dstChans)
+{
+    ChannelConverter *converter;
+
+    if(srcChans != dstChans && !((srcChans == DevFmtMono && dstChans == DevFmtStereo) ||
+                                 (srcChans == DevFmtStereo && dstChans == DevFmtMono)))
+        return NULL;
+
+    converter = al_calloc(DEF_ALIGN, sizeof(*converter));
+    converter->mSrcType = srcType;
+    converter->mSrcChans = srcChans;
+    converter->mDstChans = dstChans;
+
+    return converter;
+}
+
+void DestroyChannelConverter(ChannelConverter **converter)
+{
+    if(converter)
+    {
+        al_free(*converter);
+        *converter = NULL;
+    }
+}
+
+
+#define DECL_TEMPLATE(T)                                                       \
+static void Mono2Stereo##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
+{                                                                              \
+    ALsizei i;                                                                 \
+    for(i = 0;i < frames;i++)                                                  \
+        dst[i*2 + 1] = dst[i*2 + 0] = Sample_##T(src[i]) * 0.707106781187f;    \
+}                                                                              \
+                                                                               \
+static void Stereo2Mono##T(ALfloat *restrict dst, const T *src, ALsizei frames)\
+{                                                                              \
+    ALsizei i;                                                                 \
+    for(i = 0;i < frames;i++)                                                  \
+        dst[i] = (Sample_##T(src[i*2 + 0])+Sample_##T(src[i*2 + 1])) *         \
+                 0.707106781187f;                                              \
+}
+
+DECL_TEMPLATE(ALbyte)
+DECL_TEMPLATE(ALubyte)
+DECL_TEMPLATE(ALshort)
+DECL_TEMPLATE(ALushort)
+DECL_TEMPLATE(ALint)
+DECL_TEMPLATE(ALuint)
+DECL_TEMPLATE(ALfloat)
+
+#undef DECL_TEMPLATE
+
+void ChannelConverterInput(ChannelConverter *converter, const ALvoid *src, ALfloat *dst, ALsizei frames)
+{
+    if(converter->mSrcChans == converter->mDstChans)
+    {
+        LoadSamples(dst, src, 1, converter->mSrcType,
+                    frames*ChannelsFromDevFmt(converter->mSrcChans, 0));
+        return;
+    }
+
+    if(converter->mSrcChans == DevFmtStereo && converter->mDstChans == DevFmtMono)
+    {
+        switch(converter->mSrcType)
+        {
+            case DevFmtByte:
+                Stereo2MonoALbyte(dst, src, frames);
+                break;
+            case DevFmtUByte:
+                Stereo2MonoALubyte(dst, src, frames);
+                break;
+            case DevFmtShort:
+                Stereo2MonoALshort(dst, src, frames);
+                break;
+            case DevFmtUShort:
+                Stereo2MonoALushort(dst, src, frames);
+                break;
+            case DevFmtInt:
+                Stereo2MonoALint(dst, src, frames);
+                break;
+            case DevFmtUInt:
+                Stereo2MonoALuint(dst, src, frames);
+                break;
+            case DevFmtFloat:
+                Stereo2MonoALfloat(dst, src, frames);
+                break;
+        }
+    }
+    else /*if(converter->mSrcChans == DevFmtMono && converter->mDstChans == DevFmtStereo)*/
+    {
+        switch(converter->mSrcType)
+        {
+            case DevFmtByte:
+                Mono2StereoALbyte(dst, src, frames);
+                break;
+            case DevFmtUByte:
+                Mono2StereoALubyte(dst, src, frames);
+                break;
+            case DevFmtShort:
+                Mono2StereoALshort(dst, src, frames);
+                break;
+            case DevFmtUShort:
+                Mono2StereoALushort(dst, src, frames);
+                break;
+            case DevFmtInt:
+                Mono2StereoALint(dst, src, frames);
+                break;
+            case DevFmtUInt:
+                Mono2StereoALuint(dst, src, frames);
+                break;
+            case DevFmtFloat:
+                Mono2StereoALfloat(dst, src, frames);
+                break;
+        }
+    }
+}

+ 55 - 0
love/src/jni/openal-soft-1.18.2/Alc/converter.h

@@ -0,0 +1,55 @@
+#ifndef CONVERTER_H
+#define CONVERTER_H
+
+#include "alMain.h"
+#include "alu.h"
+
+#ifdef __cpluspluc
+extern "C" {
+#endif
+
+typedef struct SampleConverter {
+    enum DevFmtType mSrcType;
+    enum DevFmtType mDstType;
+    ALsizei mNumChannels;
+    ALsizei mSrcTypeSize;
+    ALsizei mDstTypeSize;
+
+    ALint mSrcPrepCount;
+
+    ALsizei mFracOffset;
+    ALsizei mIncrement;
+    InterpState mState;
+    ResamplerFunc mResample;
+
+    alignas(16) ALfloat mSrcSamples[BUFFERSIZE];
+    alignas(16) ALfloat mDstSamples[BUFFERSIZE];
+
+    struct {
+        alignas(16) ALfloat mPrevSamples[MAX_PRE_SAMPLES+MAX_POST_SAMPLES];
+    } Chan[];
+} SampleConverter;
+
+SampleConverter *CreateSampleConverter(enum DevFmtType srcType, enum DevFmtType dstType, ALsizei numchans, ALsizei srcRate, ALsizei dstRate);
+void DestroySampleConverter(SampleConverter **converter);
+
+ALsizei SampleConverterInput(SampleConverter *converter, const ALvoid **src, ALsizei *srcframes, ALvoid *dst, ALsizei dstframes);
+ALsizei SampleConverterAvailableOut(SampleConverter *converter, ALsizei srcframes);
+
+
+typedef struct ChannelConverter {
+    enum DevFmtType mSrcType;
+    enum DevFmtChannels mSrcChans;
+    enum DevFmtChannels mDstChans;
+} ChannelConverter;
+
+ChannelConverter *CreateChannelConverter(enum DevFmtType srcType, enum DevFmtChannels srcChans, enum DevFmtChannels dstChans);
+void DestroyChannelConverter(ChannelConverter **converter);
+
+void ChannelConverterInput(ChannelConverter *converter, const ALvoid *src, ALfloat *dst, ALsizei frames);
+
+#ifdef __cpluspluc
+}
+#endif
+
+#endif /* CONVERTER_H */

+ 121 - 108
love/src/jni/openal-soft-1.17.0/Alc/effects/chorus.c → love/src/jni/openal-soft-1.18.2/Alc/effects/chorus.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -39,14 +39,14 @@ typedef struct ALchorusState {
     DERIVE_FROM_TYPE(ALeffectState);
 
     ALfloat *SampleBuffer[2];
-    ALuint BufferLength;
-    ALuint offset;
-    ALuint lfo_range;
+    ALsizei BufferLength;
+    ALsizei offset;
+    ALsizei lfo_range;
     ALfloat lfo_scale;
     ALint lfo_disp;
 
     /* Gains for left and right sides */
-    ALfloat Gain[2][MaxChannels];
+    ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
 
     /* effect parameters */
     enum ChorusWaveForm waveform;
@@ -55,27 +55,51 @@ typedef struct ALchorusState {
     ALfloat feedback;
 } 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_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+DECLARE_DEFAULT_ALLOCATORS(ALchorusState)
+
+DEFINE_ALEFFECTSTATE_VTABLE(ALchorusState);
+
+
+static void ALchorusState_Construct(ALchorusState *state)
+{
+    ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
+    SET_VTABLE2(ALchorusState, ALeffectState, state);
+
+    state->BufferLength = 0;
+    state->SampleBuffer[0] = NULL;
+    state->SampleBuffer[1] = NULL;
+    state->offset = 0;
+    state->lfo_range = 1;
+    state->waveform = CWF_Triangle;
+}
+
 static ALvoid ALchorusState_Destruct(ALchorusState *state)
 {
-    free(state->SampleBuffer[0]);
+    al_free(state->SampleBuffer[0]);
     state->SampleBuffer[0] = NULL;
     state->SampleBuffer[1] = NULL;
+
+    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
 static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Device)
 {
-    ALuint maxlen;
-    ALuint it;
+    ALsizei maxlen;
+    ALsizei it;
 
-    maxlen = fastf2u(AL_CHORUS_MAX_DELAY * 3.0f * Device->Frequency) + 1;
+    maxlen = fastf2i(AL_CHORUS_MAX_DELAY * 2.0f * Device->Frequency) + 1;
     maxlen = NextPowerOf2(maxlen);
 
     if(maxlen != state->BufferLength)
     {
-        void *temp;
-
-        temp = realloc(state->SampleBuffer[0], maxlen * sizeof(ALfloat) * 2);
+        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;
 
@@ -91,13 +115,14 @@ static ALboolean ALchorusState_deviceUpdate(ALchorusState *state, ALCdevice *Dev
     return AL_TRUE;
 }
 
-static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, const ALeffectslot *Slot)
+static ALvoid ALchorusState_update(ALchorusState *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(Slot->EffectProps.Chorus.Waveform)
+    switch(props->Chorus.Waveform)
     {
         case AL_CHORUS_WAVEFORM_TRIANGLE:
             state->waveform = CWF_Triangle;
@@ -106,16 +131,19 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons
             state->waveform = CWF_Sinusoid;
             break;
     }
-    state->depth = Slot->EffectProps.Chorus.Depth;
-    state->feedback = Slot->EffectProps.Chorus.Feedback;
-    state->delay = fastf2i(Slot->EffectProps.Chorus.Delay * frequency);
+    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 */
-    ComputeAngleGains(Device, atan2f(-1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[0]);
-    ComputeAngleGains(Device, atan2f(+1.0f, 0.0f), 0.0f, Slot->Gain, state->Gain[1]);
+    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 = Slot->EffectProps.Chorus.Phase;
-    rate = Slot->EffectProps.Chorus.Rate;
+    phase = props->Chorus.Phase;
+    rate = props->Chorus.Rate;
     if(!(rate > 0.0f))
     {
         state->lfo_scale = 0.0f;
@@ -125,126 +153,119 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons
     else
     {
         /* Calculate LFO coefficient */
-        state->lfo_range = fastf2u(frequency/rate + 0.5f);
+        state->lfo_range = fastf2i(frequency/rate + 0.5f);
         switch(state->waveform)
         {
             case CWF_Triangle:
                 state->lfo_scale = 4.0f / state->lfo_range;
                 break;
             case CWF_Sinusoid:
-                state->lfo_scale = F_2PI / state->lfo_range;
+                state->lfo_scale = F_TAU / state->lfo_range;
                 break;
         }
 
         /* Calculate lfo phase displacement */
-        state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f));
+        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 inline void Triangle(ALint *delay_left, ALint *delay_right, ALuint offset, const ALchorusState *state)
+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)
 {
-    ALfloat lfo_value;
-
-    lfo_value = 2.0f - fabsf(2.0f - state->lfo_scale*(offset%state->lfo_range));
-    lfo_value *= state->depth * state->delay;
-    *delay_left = fastf2i(lfo_value) + state->delay;
-
-    offset += state->lfo_disp;
-    lfo_value = 2.0f - fabsf(2.0f - state->lfo_scale*(offset%state->lfo_range));
-    lfo_value *= state->depth * state->delay;
-    *delay_right = fastf2i(lfo_value) + state->delay;
+    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 inline void Sinusoid(ALint *delay_left, ALint *delay_right, ALuint offset, const ALchorusState *state)
+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)
 {
-    ALfloat lfo_value;
-
-    lfo_value = 1.0f + sinf(state->lfo_scale*(offset%state->lfo_range));
-    lfo_value *= state->depth * state->delay;
-    *delay_left = fastf2i(lfo_value) + state->delay;
-
-    offset += state->lfo_disp;
-    lfo_value = 1.0f + sinf(state->lfo_scale*(offset%state->lfo_range));
-    lfo_value *= state->depth * state->delay;
-    *delay_right = fastf2i(lfo_value) + state->delay;
-}
-
-#define DECL_TEMPLATE(Func)                                                   \
-static void Process##Func(ALchorusState *state, const ALuint SamplesToDo,     \
-  const ALfloat *restrict SamplesIn, ALfloat (*restrict out)[2])              \
-{                                                                             \
-    const ALuint bufmask = state->BufferLength-1;                             \
-    ALfloat *restrict leftbuf = state->SampleBuffer[0];                       \
-    ALfloat *restrict rightbuf = state->SampleBuffer[1];                      \
-    ALuint offset = state->offset;                                            \
-    const ALfloat feedback = state->feedback;                                 \
-    ALuint it;                                                                \
-                                                                              \
-    for(it = 0;it < SamplesToDo;it++)                                         \
-    {                                                                         \
-        ALint delay_left, delay_right;                                        \
-        Func(&delay_left, &delay_right, offset, state);                       \
-                                                                              \
-        out[it][0] = leftbuf[(offset-delay_left)&bufmask];                    \
-        leftbuf[offset&bufmask] = (out[it][0]+SamplesIn[it]) * feedback;      \
-                                                                              \
-        out[it][1] = rightbuf[(offset-delay_right)&bufmask];                  \
-        rightbuf[offset&bufmask] = (out[it][1]+SamplesIn[it]) * feedback;     \
-                                                                              \
-        offset++;                                                             \
-    }                                                                         \
-    state->offset = offset;                                                   \
+    ALsizei i;
+    for(i = 0;i < todo;i++)
+    {
+        delays[i] = fastf2i(sinf(lfo_scale*offset) * depth) + delay;
+        offset = (offset+1)%lfo_range;
+    }
 }
 
-DECL_TEMPLATE(Triangle)
-DECL_TEMPLATE(Sinusoid)
-
-#undef DECL_TEMPLATE
 
-static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALchorusState_process(ALchorusState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
-    ALuint it, kt;
-    ALuint base;
+    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;)
     {
-        ALfloat temps[64][2];
-        ALuint td = minu(SamplesToDo-base, 64);
+        const ALsizei todo = mini(128, SamplesToDo-base);
+        ALfloat temps[128][2];
+        ALint moddelays[2][128];
 
         switch(state->waveform)
         {
             case CWF_Triangle:
-                ProcessTriangle(state, td, SamplesIn+base, temps);
+                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:
-                ProcessSinusoid(state, td, SamplesIn+base, temps);
+                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(kt = 0;kt < MaxChannels;kt++)
+        for(i = 0;i < todo;i++)
         {
-            ALfloat gain = state->Gain[0][kt];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            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(it = 0;it < td;it++)
-                    SamplesOut[kt][it+base] += temps[it][0] * gain;
+                for(i = 0;i < todo;i++)
+                    SamplesOut[c][i+base] += temps[i][0] * gain;
             }
 
-            gain = state->Gain[1][kt];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            gain = state->Gain[1][c];
+            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
             {
-                for(it = 0;it < td;it++)
-                    SamplesOut[kt][it+base] += temps[it][1] * gain;
+                for(i = 0;i < todo;i++)
+                    SamplesOut[c][i+base] += temps[i][1] * gain;
             }
         }
 
-        base += td;
+        base += todo;
     }
-}
 
-DECLARE_DEFAULT_ALLOCATORS(ALchorusState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALchorusState);
+    state->offset = offset;
+}
 
 
 typedef struct ALchorusStateFactory {
@@ -255,16 +276,8 @@ static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(f
 {
     ALchorusState *state;
 
-    state = ALchorusState_New(sizeof(*state));
+    NEW_OBJ0(state, ALchorusState)();
     if(!state) return NULL;
-    SET_VTABLE2(ALchorusState, ALeffectState, state);
-
-    state->BufferLength = 0;
-    state->SampleBuffer[0] = NULL;
-    state->SampleBuffer[1] = NULL;
-    state->offset = 0;
-    state->lfo_range = 1;
-    state->waveform = CWF_Triangle;
 
     return STATIC_CAST(ALeffectState, state);
 }

+ 79 - 45
love/src/jni/openal-soft-1.17.0/Alc/effects/compressor.c → love/src/jni/openal-soft-1.18.2/Alc/effects/compressor.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -31,7 +31,7 @@ typedef struct ALcompressorState {
     DERIVE_FROM_TYPE(ALeffectState);
 
     /* Effect gains for each channel */
-    ALfloat Gain[MaxChannels];
+    ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS];
 
     /* Effect parameters */
     ALboolean Enabled;
@@ -40,8 +40,29 @@ typedef struct ALcompressorState {
     ALfloat GainCtrl;
 } ALcompressorState;
 
-static ALvoid ALcompressorState_Destruct(ALcompressorState *UNUSED(state))
+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_process(ALcompressorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+DECLARE_DEFAULT_ALLOCATORS(ALcompressorState)
+
+DEFINE_ALEFFECTSTATE_VTABLE(ALcompressorState);
+
+
+static void ALcompressorState_Construct(ALcompressorState *state)
+{
+    ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
+    SET_VTABLE2(ALcompressorState, ALeffectState, state);
+
+    state->Enabled = AL_TRUE;
+    state->AttackRate = 0.0f;
+    state->ReleaseRate = 0.0f;
+    state->GainCtrl = 1.0f;
+}
+
+static ALvoid ALcompressorState_Destruct(ALcompressorState *state)
 {
+    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
 static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdevice *device)
@@ -55,88 +76,107 @@ static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdev
     return AL_TRUE;
 }
 
-static ALvoid ALcompressorState_update(ALcompressorState *state, ALCdevice *Device, const ALeffectslot *Slot)
+static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props)
 {
-    ALfloat gain;
+    ALuint i;
 
-    state->Enabled = Slot->EffectProps.Compressor.OnOff;
+    state->Enabled = props->Compressor.OnOff;
 
-    gain = sqrtf(1.0f / Device->NumChan) * Slot->Gain;
-    SetGains(Device, gain, state->Gain);
+    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],
+                               slot->Params.Gain, state->Gain[i]);
 }
 
-static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[BUFFERSIZE])
+static ALvoid ALcompressorState_process(ALcompressorState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
-    ALuint it, kt;
-    ALuint base;
+    ALsizei i, j, k;
+    ALsizei base;
 
     for(base = 0;base < SamplesToDo;)
     {
-        ALfloat temps[64];
-        ALuint td = minu(SamplesToDo-base, 64);
+        ALfloat temps[64][4];
+        ALsizei td = mini(64, SamplesToDo-base);
+
+        /* Load samples into the temp buffer first. */
+        for(j = 0;j < 4;j++)
+        {
+            for(i = 0;i < td;i++)
+                temps[i][j] = SamplesIn[j][i+base];
+        }
 
         if(state->Enabled)
         {
-            ALfloat output, smp, amplitude;
             ALfloat gain = state->GainCtrl;
+            ALfloat output, amplitude;
 
-            for(it = 0;it < td;it++)
+            for(i = 0;i < td;i++)
             {
-                smp = SamplesIn[it+base];
-
-                amplitude = fabsf(smp);
+                /* Roughly calculate the maximum amplitude from the 4-channel
+                 * signal, and attack or release the gain control to reach it.
+                 */
+                amplitude = fabsf(temps[i][0]);
+                amplitude = maxf(amplitude + fabsf(temps[i][1]),
+                                 maxf(amplitude + fabsf(temps[i][2]),
+                                      amplitude + fabsf(temps[i][3])));
                 if(amplitude > gain)
                     gain = minf(gain+state->AttackRate, amplitude);
                 else if(amplitude < gain)
                     gain = maxf(gain-state->ReleaseRate, amplitude);
-                output = 1.0f / clampf(gain, 0.5f, 2.0f);
 
-                temps[it] = smp * output;
+                /* Apply the inverse of the gain control to normalize/compress
+                 * the volume. */
+                output = 1.0f / clampf(gain, 0.5f, 2.0f);
+                for(j = 0;j < 4;j++)
+                    temps[i][j] *= output;
             }
 
             state->GainCtrl = gain;
         }
         else
         {
-            ALfloat output, smp, amplitude;
             ALfloat gain = state->GainCtrl;
+            ALfloat output, amplitude;
 
-            for(it = 0;it < td;it++)
+            for(i = 0;i < td;i++)
             {
-                smp = SamplesIn[it+base];
-
+                /* Same as above, except the amplitude is forced to 1. This
+                 * helps ensure smooth gain changes when the compressor is
+                 * turned on and off.
+                 */
                 amplitude = 1.0f;
                 if(amplitude > gain)
                     gain = minf(gain+state->AttackRate, amplitude);
                 else if(amplitude < gain)
                     gain = maxf(gain-state->ReleaseRate, amplitude);
-                output = 1.0f / clampf(gain, 0.5f, 2.0f);
 
-                temps[it] = smp * output;
+                output = 1.0f / clampf(gain, 0.5f, 2.0f);
+                for(j = 0;j < 4;j++)
+                    temps[i][j] *= output;
             }
 
             state->GainCtrl = gain;
         }
 
-
-        for(kt = 0;kt < MaxChannels;kt++)
+        /* Now mix to the output. */
+        for(j = 0;j < 4;j++)
         {
-            ALfloat gain = state->Gain[kt];
-            if(!(gain > GAIN_SILENCE_THRESHOLD))
-                continue;
+            for(k = 0;k < NumChannels;k++)
+            {
+                ALfloat gain = state->Gain[j][k];
+                if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
+                    continue;
 
-            for(it = 0;it < td;it++)
-                SamplesOut[kt][base+it] += gain * temps[it];
+                for(i = 0;i < td;i++)
+                    SamplesOut[k][base+i] += gain * temps[i][j];
+            }
         }
 
         base += td;
     }
 }
 
-DECLARE_DEFAULT_ALLOCATORS(ALcompressorState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALcompressorState);
-
 
 typedef struct ALcompressorStateFactory {
     DERIVE_FROM_TYPE(ALeffectStateFactory);
@@ -146,14 +186,8 @@ static ALeffectState *ALcompressorStateFactory_create(ALcompressorStateFactory *
 {
     ALcompressorState *state;
 
-    state = ALcompressorState_New(sizeof(*state));
+    NEW_OBJ0(state, ALcompressorState)();
     if(!state) return NULL;
-    SET_VTABLE2(ALcompressorState, ALeffectState, state);
-
-    state->Enabled = AL_TRUE;
-    state->AttackRate = 0.0f;
-    state->ReleaseRate = 0.0f;
-    state->GainCtrl = 1.0f;
 
     return STATIC_CAST(ALeffectState, state);
 }

+ 68 - 29
love/src/jni/openal-soft-1.17.0/Alc/effects/dedicated.c → love/src/jni/openal-soft-1.18.2/Alc/effects/dedicated.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -32,12 +32,32 @@
 typedef struct ALdedicatedState {
     DERIVE_FROM_TYPE(ALeffectState);
 
-    ALfloat gains[MaxChannels];
+    ALfloat gains[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_process(ALdedicatedState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+DECLARE_DEFAULT_ALLOCATORS(ALdedicatedState)
+
+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 *UNUSED(state))
+static ALvoid ALdedicatedState_Destruct(ALdedicatedState *state)
 {
+    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
 static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *UNUSED(state), ALCdevice *UNUSED(device))
@@ -45,41 +65,65 @@ static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *UNUSED(state),
     return AL_TRUE;
 }
 
-static ALvoid ALdedicatedState_update(ALdedicatedState *state, ALCdevice *device, const ALeffectslot *Slot)
+static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCdevice *device, const ALeffectslot *Slot, const ALeffectProps *props)
 {
     ALfloat Gain;
-    ALsizei s;
+    ALuint i;
+
+    for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
+        state->gains[i] = 0.0f;
 
-    Gain = Slot->Gain * Slot->EffectProps.Dedicated.Gain;
-    if(Slot->EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
-        ComputeAngleGains(device, atan2f(0.0f, 1.0f), 0.0f, Gain, state->gains);
-    else if(Slot->EffectType == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT)
+    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)
+        {
+            STATIC_CAST(ALeffectState,state)->OutBuffer = device->RealOut.Buffer;
+            STATIC_CAST(ALeffectState,state)->OutChannels = device->RealOut.NumChannels;
+            state->gains[idx] = Gain;
+        }
+    }
+    else if(Slot->Params.EffectType == AL_EFFECT_DEDICATED_DIALOGUE)
     {
-        for(s = 0;s < MaxChannels;s++)
-            state->gains[s] = 0.0f;
-        state->gains[LFE] = Gain;
+        int idx;
+        /* Dialog goes to the front-center speaker if it exists, otherwise it
+         * plays from the front-center location. */
+        if((idx=GetChannelIdxByName(device->RealOut, FrontCenter)) != -1)
+        {
+            STATIC_CAST(ALeffectState,state)->OutBuffer = device->RealOut.Buffer;
+            STATIC_CAST(ALeffectState,state)->OutChannels = device->RealOut.NumChannels;
+            state->gains[idx] = Gain;
+        }
+        else
+        {
+            ALfloat coeffs[MAX_AMBI_COEFFS];
+            CalcAngleCoeffs(0.0f, 0.0f, 0.0f, coeffs);
+
+            STATIC_CAST(ALeffectState,state)->OutBuffer = device->Dry.Buffer;
+            STATIC_CAST(ALeffectState,state)->OutChannels = device->Dry.NumChannels;
+            ComputePanningGains(device->Dry, coeffs, Gain, state->gains);
+        }
     }
 }
 
-static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
-    const ALfloat *gains = state->gains;
-    ALuint i, c;
+    ALsizei i, c;
 
-    for(c = 0;c < MaxChannels;c++)
+    SamplesIn = ASSUME_ALIGNED(SamplesIn, 16);
+    SamplesOut = ASSUME_ALIGNED(SamplesOut, 16);
+    for(c = 0;c < NumChannels;c++)
     {
-        if(!(gains[c] > GAIN_SILENCE_THRESHOLD))
+        const ALfloat gain = state->gains[c];
+        if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
             continue;
 
         for(i = 0;i < SamplesToDo;i++)
-            SamplesOut[c][i] = SamplesIn[i] * gains[c];
+            SamplesOut[c][i] += SamplesIn[0][i] * gain;
     }
 }
 
-DECLARE_DEFAULT_ALLOCATORS(ALdedicatedState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALdedicatedState);
-
 
 typedef struct ALdedicatedStateFactory {
     DERIVE_FROM_TYPE(ALeffectStateFactory);
@@ -88,14 +132,9 @@ typedef struct ALdedicatedStateFactory {
 ALeffectState *ALdedicatedStateFactory_create(ALdedicatedStateFactory *UNUSED(factory))
 {
     ALdedicatedState *state;
-    ALsizei s;
 
-    state = ALdedicatedState_New(sizeof(*state));
+    NEW_OBJ0(state, ALdedicatedState)();
     if(!state) return NULL;
-    SET_VTABLE2(ALdedicatedState, ALeffectState, state);
-
-    for(s = 0;s < MaxChannels;s++)
-        state->gains[s] = 0.0f;
 
     return STATIC_CAST(ALeffectState, state);
 }

+ 89 - 89
love/src/jni/openal-soft-1.17.0/Alc/effects/distortion.c → love/src/jni/openal-soft-1.18.2/Alc/effects/distortion.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -34,7 +34,7 @@ typedef struct ALdistortionState {
     DERIVE_FROM_TYPE(ALeffectState);
 
     /* Effect gains for each channel */
-    ALfloat Gain[MaxChannels];
+    ALfloat Gain[MAX_OUTPUT_CHANNELS];
 
     /* Effect parameters */
     ALfilterState lowpass;
@@ -43,8 +43,27 @@ typedef struct ALdistortionState {
     ALfloat edge_coeff;
 } ALdistortionState;
 
-static ALvoid ALdistortionState_Destruct(ALdistortionState *UNUSED(state))
+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_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+DECLARE_DEFAULT_ALLOCATORS(ALdistortionState)
+
+DEFINE_ALEFFECTSTATE_VTABLE(ALdistortionState);
+
+
+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);
+}
+
+static ALvoid ALdistortionState_Destruct(ALdistortionState *state)
+{
+    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
 static ALboolean ALdistortionState_deviceUpdate(ALdistortionState *UNUSED(state), ALCdevice *UNUSED(device))
@@ -52,128 +71,113 @@ static ALboolean ALdistortionState_deviceUpdate(ALdistortionState *UNUSED(state)
     return AL_TRUE;
 }
 
-static ALvoid ALdistortionState_update(ALdistortionState *state, ALCdevice *Device, const ALeffectslot *Slot)
+static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props)
 {
     ALfloat frequency = (ALfloat)Device->Frequency;
     ALfloat bandwidth;
     ALfloat cutoff;
     ALfloat edge;
-    ALfloat gain;
 
-    /* Store distorted signal attenuation settings */
-    state->attenuation = Slot->EffectProps.Distortion.Gain;
+    /* Store distorted signal attenuation settings. */
+    state->attenuation = props->Distortion.Gain;
 
-    /* Store waveshaper edge settings */
-    edge = sinf(Slot->EffectProps.Distortion.Edge * (F_PI_2));
+    /* Store waveshaper edge settings. */
+    edge = sinf(props->Distortion.Edge * (F_PI_2));
     edge = minf(edge, 0.99f);
     state->edge_coeff = 2.0f * edge / (1.0f-edge);
 
-    /* Lowpass filter */
-    cutoff = Slot->EffectProps.Distortion.LowpassCutoff;
-    /* Bandwidth value is constant in octaves */
+    cutoff = props->Distortion.LowpassCutoff;
+    /* Bandwidth value is constant in octaves. */
     bandwidth = (cutoff / 2.0f) / (cutoff * 0.67f);
+    /* Multiply sampling frequency by the amount of oversampling done during
+     * processing.
+     */
     ALfilterState_setParams(&state->lowpass, ALfilterType_LowPass, 1.0f,
-                            cutoff / (frequency*4.0f), bandwidth);
+        cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
+    );
 
-    /* Bandpass filter */
-    cutoff = Slot->EffectProps.Distortion.EQCenter;
-    /* Convert bandwidth in Hz to octaves */
-    bandwidth = Slot->EffectProps.Distortion.EQBandwidth / (cutoff * 0.67f);
+    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,
-                            cutoff / (frequency*4.0f), bandwidth);
+        cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth)
+    );
 
-    gain = sqrtf(1.0f / Device->NumChan) * Slot->Gain;
-    SetGains(Device, gain, state->Gain);
+    ComputeAmbientGains(Device->Dry, Slot->Params.Gain, state->Gain);
 }
 
-static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALdistortionState_process(ALdistortionState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
     const ALfloat fc = state->edge_coeff;
-    float oversample_buffer[64][4];
-    ALuint base;
-    ALuint it;
-    ALuint ot;
-    ALuint kt;
+    ALsizei it, kt;
+    ALsizei base;
 
     for(base = 0;base < SamplesToDo;)
     {
-        ALfloat temps[64];
-        ALuint td = minu(SamplesToDo-base, 64);
+        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.   */
+        /* 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.
+         */
 
-        /* Fill oversample buffer using zero stuffing */
+        /* Fill oversample buffer using zero stuffing. */
         for(it = 0;it < td;it++)
         {
-            oversample_buffer[it][0] = SamplesIn[it+base];
-            oversample_buffer[it][1] = 0.0f;
-            oversample_buffer[it][2] = 0.0f;
-            oversample_buffer[it][3] = 0.0f;
+            /* 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;
         }
 
-        /* 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.                                              */
-        for(it = 0;it < td;it++)
+        /* 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);
+
+        /* 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(ot = 0;ot < 4;ot++)
-            {
-                ALfloat smp;
-                smp = ALfilterState_processSingle(&state->lowpass, oversample_buffer[it][ot]);
-
-                /* Restore signal power by multiplying sample by amount of oversampling */
-                oversample_buffer[it][ot] = smp * 4.0f;
-            }
-        }
+            ALfloat smp = buffer[1][it];
 
-        for(it = 0;it < td;it++)
-        {
-            /* 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(ot = 0;ot < 4;ot++)
-            {
-                ALfloat smp = oversample_buffer[it][ot];
-
-                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));
-
-                /* Third step, do bandpass filtering of distorted signal */
-                smp = ALfilterState_processSingle(&state->bandpass, smp);
-                oversample_buffer[it][ot] = smp;
-            }
-
-            /* Fourth step, final, do attenuation and perform decimation, */
-            /* store only one sample out of 4.                            */
-            temps[it] = oversample_buffer[it][0] * state->attenuation;
+            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;
         }
 
-        for(kt = 0;kt < MaxChannels;kt++)
+        /* Third step, do bandpass filtering of distorted signal. */
+        ALfilterState_process(&state->bandpass, buffer[1], buffer[0], td*4);
+
+        for(kt = 0;kt < NumChannels;kt++)
         {
-            ALfloat gain = state->Gain[kt];
-            if(!(gain > GAIN_SILENCE_THRESHOLD))
+            /* Fourth step, final, do attenuation and perform decimation,
+             * store only one sample out of 4.
+             */
+            ALfloat gain = state->Gain[kt] * state->attenuation;
+            if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
                 continue;
 
             for(it = 0;it < td;it++)
-                SamplesOut[kt][base+it] += gain * temps[it];
+                SamplesOut[kt][base+it] += gain * buffer[1][it*4];
         }
 
         base += td;
     }
 }
 
-DECLARE_DEFAULT_ALLOCATORS(ALdistortionState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALdistortionState);
-
 
 typedef struct ALdistortionStateFactory {
     DERIVE_FROM_TYPE(ALeffectStateFactory);
@@ -183,12 +187,8 @@ static ALeffectState *ALdistortionStateFactory_create(ALdistortionStateFactory *
 {
     ALdistortionState *state;
 
-    state = ALdistortionState_New(sizeof(*state));
+    NEW_OBJ0(state, ALdistortionState)();
     if(!state) return NULL;
-    SET_VTABLE2(ALdistortionState, ALeffectState, state);
-
-    ALfilterState_clear(&state->lowpass);
-    ALfilterState_clear(&state->bandpass);
 
     return STATIC_CAST(ALeffectState, state);
 }

+ 90 - 57
love/src/jni/openal-soft-1.17.0/Alc/effects/echo.c → love/src/jni/openal-soft-1.18.2/Alc/effects/echo.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -34,44 +34,69 @@ typedef struct ALechoState {
     DERIVE_FROM_TYPE(ALeffectState);
 
     ALfloat *SampleBuffer;
-    ALuint BufferLength;
+    ALsizei BufferLength;
 
     // The echo is two tap. The delay is the number of samples from before the
     // current offset
     struct {
-        ALuint delay;
+        ALsizei delay;
     } Tap[2];
-    ALuint Offset;
+    ALsizei Offset;
     /* The panning gains for the two taps */
-    ALfloat Gain[2][MaxChannels];
+    ALfloat Gain[2][MAX_OUTPUT_CHANNELS];
 
     ALfloat FeedGain;
 
     ALfilterState 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_process(ALechoState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+DECLARE_DEFAULT_ALLOCATORS(ALechoState)
+
+DEFINE_ALEFFECTSTATE_VTABLE(ALechoState);
+
+
+static void ALechoState_Construct(ALechoState *state)
+{
+    ALeffectState_Construct(STATIC_CAST(ALeffectState, state));
+    SET_VTABLE2(ALechoState, ALeffectState, state);
+
+    state->BufferLength = 0;
+    state->SampleBuffer = NULL;
+
+    state->Tap[0].delay = 0;
+    state->Tap[1].delay = 0;
+    state->Offset = 0;
+
+    ALfilterState_clear(&state->Filter);
+}
+
 static ALvoid ALechoState_Destruct(ALechoState *state)
 {
-    free(state->SampleBuffer);
+    al_free(state->SampleBuffer);
     state->SampleBuffer = NULL;
+    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
 static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device)
 {
-    ALuint maxlen, i;
+    ALsizei maxlen, i;
 
     // 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  = fastf2u(AL_ECHO_MAX_DELAY * Device->Frequency) + 1;
-    maxlen += fastf2u(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1;
+    maxlen  = fastf2i(AL_ECHO_MAX_DELAY * Device->Frequency) + 1;
+    maxlen += fastf2i(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1;
     maxlen  = NextPowerOf2(maxlen);
 
     if(maxlen != state->BufferLength)
     {
-        void *temp;
-
-        temp = realloc(state->SampleBuffer, maxlen * sizeof(ALfloat));
+        void *temp = al_calloc(16, maxlen * sizeof(ALfloat));
         if(!temp) return AL_FALSE;
+
+        al_free(state->SampleBuffer);
         state->SampleBuffer = temp;
         state->BufferLength = maxlen;
     }
@@ -81,48 +106,60 @@ static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device)
     return AL_TRUE;
 }
 
-static ALvoid ALechoState_update(ALechoState *state, ALCdevice *Device, const ALeffectslot *Slot)
+static ALvoid ALechoState_update(ALechoState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props)
 {
     ALuint frequency = Device->Frequency;
-    ALfloat lrpan, gain;
-    ALfloat dirGain;
+    ALfloat coeffs[MAX_AMBI_COEFFS];
+    ALfloat gain, lrpan, spread;
 
-    state->Tap[0].delay = fastf2u(Slot->EffectProps.Echo.Delay * frequency) + 1;
-    state->Tap[1].delay = fastf2u(Slot->EffectProps.Echo.LRDelay * frequency);
+    state->Tap[0].delay = fastf2i(props->Echo.Delay * frequency) + 1;
+    state->Tap[1].delay = fastf2i(props->Echo.LRDelay * frequency);
     state->Tap[1].delay += state->Tap[0].delay;
 
-    lrpan = Slot->EffectProps.Echo.Spread;
+    spread = props->Echo.Spread;
+    if(spread < 0.0f) lrpan = -1.0f;
+    else lrpan = 1.0f;
+    /* Convert echo spread (where 0 = omni, +/-1 = directional) to coverage
+     * spread (where 0 = point, tau = omni).
+     */
+    spread = asinf(1.0f - fabsf(spread))*4.0f;
 
-    state->FeedGain = Slot->EffectProps.Echo.Feedback;
+    state->FeedGain = props->Echo.Feedback;
 
+    gain = maxf(1.0f - props->Echo.Damping, 0.0625f); /* Limit -24dB */
     ALfilterState_setParams(&state->Filter, ALfilterType_HighShelf,
-                            1.0f - Slot->EffectProps.Echo.Damping,
-                            LOWPASSFREQREF/frequency, 0.0f);
+                            gain, LOWPASSFREQREF/frequency,
+                            calc_rcpQ_from_slope(gain, 1.0f));
 
-    gain = Slot->Gain;
-    dirGain = fabsf(lrpan);
+    gain = Slot->Params.Gain;
 
     /* First tap panning */
-    ComputeAngleGains(Device, atan2f(-lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[0]);
+    CalcAngleCoeffs(-F_PI_2*lrpan, 0.0f, spread, coeffs);
+    ComputePanningGains(Device->Dry, coeffs, gain, state->Gain[0]);
 
     /* Second tap panning */
-    ComputeAngleGains(Device, atan2f(+lrpan, 0.0f), (1.0f-dirGain)*F_PI, gain, state->Gain[1]);
+    CalcAngleCoeffs( F_PI_2*lrpan, 0.0f, spread, coeffs);
+    ComputePanningGains(Device->Dry, coeffs, gain, state->Gain[1]);
 }
 
-static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALechoState_process(ALechoState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
-    const ALuint mask = state->BufferLength-1;
-    const ALuint tap1 = state->Tap[0].delay;
-    const ALuint tap2 = state->Tap[1].delay;
-    ALuint offset = state->Offset;
-    ALfloat smp;
-    ALuint base;
-    ALuint i, k;
-
+    const ALsizei mask = state->BufferLength-1;
+    const ALsizei tap1 = state->Tap[0].delay;
+    const ALsizei tap2 = state->Tap[1].delay;
+    ALsizei offset = state->Offset;
+    ALfloat x[2], y[2], in, out;
+    ALsizei base, k;
+    ALsizei i;
+
+    x[0] = state->Filter.x[0];
+    x[1] = state->Filter.x[1];
+    y[0] = state->Filter.y[0];
+    y[1] = state->Filter.y[1];
     for(base = 0;base < SamplesToDo;)
     {
-        ALfloat temps[64][2];
-        ALuint td = minu(SamplesToDo-base, 64);
+        ALfloat temps[128][2];
+        ALsizei td = mini(128, SamplesToDo-base);
 
         for(i = 0;i < td;i++)
         {
@@ -133,22 +170,28 @@ static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const
 
             // Apply damping and feedback gain to the second tap, and mix in the
             // new sample
-            smp = ALfilterState_processSingle(&state->Filter, temps[i][1]+SamplesIn[i+base]);
-            state->SampleBuffer[offset&mask] = smp * state->FeedGain;
+            in = temps[i][1] + SamplesIn[0][i+base];
+            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;
             offset++;
         }
 
-        for(k = 0;k < MaxChannels;k++)
+        for(k = 0;k < NumChannels;k++)
         {
             ALfloat gain = state->Gain[0][k];
-            if(gain > GAIN_SILENCE_THRESHOLD)
+            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(gain > GAIN_SILENCE_THRESHOLD)
+            if(fabsf(gain) > GAIN_SILENCE_THRESHOLD)
             {
                 for(i = 0;i < td;i++)
                     SamplesOut[k][i+base] += temps[i][1] * gain;
@@ -157,14 +200,14 @@ static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const
 
         base += td;
     }
+    state->Filter.x[0] = x[0];
+    state->Filter.x[1] = x[1];
+    state->Filter.y[0] = y[0];
+    state->Filter.y[1] = y[1];
 
     state->Offset = offset;
 }
 
-DECLARE_DEFAULT_ALLOCATORS(ALechoState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALechoState);
-
 
 typedef struct ALechoStateFactory {
     DERIVE_FROM_TYPE(ALeffectStateFactory);
@@ -174,18 +217,8 @@ ALeffectState *ALechoStateFactory_create(ALechoStateFactory *UNUSED(factory))
 {
     ALechoState *state;
 
-    state = ALechoState_New(sizeof(*state));
+    NEW_OBJ0(state, ALechoState)();
     if(!state) return NULL;
-    SET_VTABLE2(ALechoState, ALeffectState, state);
-
-    state->BufferLength = 0;
-    state->SampleBuffer = NULL;
-
-    state->Tap[0].delay = 0;
-    state->Tap[1].delay = 0;
-    state->Offset = 0;
-
-    ALfilterState_clear(&state->Filter);
 
     return STATIC_CAST(ALeffectState, state);
 }

+ 113 - 67
love/src/jni/openal-soft-1.17.0/Alc/effects/equalizer.c → love/src/jni/openal-soft-1.18.2/Alc/effects/equalizer.c

@@ -13,8 +13,8 @@
  *
  * You should have received a copy of the GNU Library General Public
  *  License along with this library; if not, write to the
- *  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- *  Boston, MA  02111-1307, USA.
+ *  Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  * Or go to http://www.gnu.org/copyleft/lgpl.html
  */
 
@@ -71,18 +71,50 @@
  * filter coefficients" by Robert Bristow-Johnson                        *
  * 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[MaxChannels];
+    ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS];
 
     /* Effect parameters */
-    ALfilterState filter[4];
+    ALfilterState filter[4][MAX_EFFECT_CHANNELS];
+
+    ALfloat SampleBuffer[4][MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES];
 } ALequalizerState;
 
-static ALvoid ALequalizerState_Destruct(ALequalizerState *UNUSED(state))
+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_process(ALequalizerState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels);
+DECLARE_DEFAULT_ALLOCATORS(ALequalizerState)
+
+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)
+{
+    ALeffectState_Destruct(STATIC_CAST(ALeffectState,state));
 }
 
 static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *UNUSED(state), ALCdevice *UNUSED(device))
@@ -90,75 +122,96 @@ static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *UNUSED(state),
     return AL_TRUE;
 }
 
-static ALvoid ALequalizerState_update(ALequalizerState *state, ALCdevice *device, const ALeffectslot *slot)
+static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props)
 {
     ALfloat frequency = (ALfloat)device->Frequency;
-    ALfloat gain = sqrtf(1.0f / device->NumChan) * slot->Gain;
-
-    SetGains(device, gain, state->Gain);
-
-    /* Calculate coefficients for the each type of filter */
-    ALfilterState_setParams(&state->filter[0], ALfilterType_LowShelf,
-                            sqrtf(slot->EffectProps.Equalizer.LowGain),
-                            slot->EffectProps.Equalizer.LowCutoff/frequency,
-                            0.0f);
-
-    ALfilterState_setParams(&state->filter[1], ALfilterType_Peaking,
-                            sqrtf(slot->EffectProps.Equalizer.Mid1Gain),
-                            slot->EffectProps.Equalizer.Mid1Center/frequency,
-                            slot->EffectProps.Equalizer.Mid1Width);
-
-    ALfilterState_setParams(&state->filter[2], ALfilterType_Peaking,
-                            sqrtf(slot->EffectProps.Equalizer.Mid2Gain),
-                            slot->EffectProps.Equalizer.Mid2Center/frequency,
-                            slot->EffectProps.Equalizer.Mid2Width);
-
-    ALfilterState_setParams(&state->filter[3], ALfilterType_HighShelf,
-                            sqrtf(slot->EffectProps.Equalizer.HighGain),
-                            slot->EffectProps.Equalizer.HighCutoff/frequency,
-                            0.0f);
+    ALfloat gain, freq_mult;
+    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]);
+
+    /* 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)
+    );
+    /* 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
+        )
+    );
+    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
+        )
+    );
+    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)
+    );
+    for(i = 1;i < MAX_EFFECT_CHANNELS;i++)
+        ALfilterState_copyParams(&state->filter[3][i], &state->filter[3][0]);
 }
 
-static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesToDo, const ALfloat *restrict SamplesIn, ALfloat (*restrict SamplesOut)[BUFFERSIZE])
+static ALvoid ALequalizerState_process(ALequalizerState *state, ALsizei SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALsizei NumChannels)
 {
-    ALuint base;
-    ALuint it;
-    ALuint kt;
-    ALuint ft;
+    ALfloat (*Samples)[MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES] = state->SampleBuffer;
+    ALsizei it, kt, ft;
+    ALsizei base;
 
     for(base = 0;base < SamplesToDo;)
     {
-        ALfloat temps[64];
-        ALuint td = minu(SamplesToDo-base, 64);
-
-        for(it = 0;it < td;it++)
+        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++)
         {
-            ALfloat smp = SamplesIn[base+it];
-
-            for(ft = 0;ft < 4;ft++)
-                smp = ALfilterState_processSingle(&state->filter[ft], smp);
-
-            temps[it] = smp;
-        }
-
-        for(kt = 0;kt < MaxChannels;kt++)
-        {
-            ALfloat gain = state->Gain[kt];
-            if(!(gain > GAIN_SILENCE_THRESHOLD))
-                continue;
-
-            for(it = 0;it < td;it++)
-                SamplesOut[kt][base+it] += gain * temps[it];
+            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;
     }
 }
 
-DECLARE_DEFAULT_ALLOCATORS(ALequalizerState)
-
-DEFINE_ALEFFECTSTATE_VTABLE(ALequalizerState);
-
 
 typedef struct ALequalizerStateFactory {
     DERIVE_FROM_TYPE(ALeffectStateFactory);
@@ -167,16 +220,9 @@ typedef struct ALequalizerStateFactory {
 ALeffectState *ALequalizerStateFactory_create(ALequalizerStateFactory *UNUSED(factory))
 {
     ALequalizerState *state;
-    int it;
 
-    state = ALequalizerState_New(sizeof(*state));
+    NEW_OBJ0(state, ALequalizerState)();
     if(!state) return NULL;
-    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++)
-        ALfilterState_clear(&state->filter[it]);
 
     return STATIC_CAST(ALeffectState, state);
 }

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません