From 3a0a72011570b7876c6650039db727a4843449aa Mon Sep 17 00:00:00 2001 From: RexTimmy Date: Sat, 22 Oct 2016 09:22:33 +1000 Subject: [PATCH] OpenAL-soft for windows --- Engine/lib/openal-soft/.gitignore | 7 + Engine/lib/openal-soft/.travis.yml | 5 + Engine/lib/openal-soft/Alc/ALc.c | 4139 +++++++++++++++++ Engine/lib/openal-soft/Alc/ALu.c | 1657 +++++++ Engine/lib/openal-soft/Alc/alcConfig.c | 598 +++ Engine/lib/openal-soft/Alc/alcRing.c | 301 ++ Engine/lib/openal-soft/Alc/alstring.h | 49 + Engine/lib/openal-soft/Alc/ambdec.c | 557 +++ Engine/lib/openal-soft/Alc/ambdec.h | 46 + Engine/lib/openal-soft/Alc/backends/alsa.c | 1394 ++++++ Engine/lib/openal-soft/Alc/backends/base.c | 225 + Engine/lib/openal-soft/Alc/backends/base.h | 153 + .../lib/openal-soft/Alc/backends/coreaudio.c | 724 +++ Engine/lib/openal-soft/Alc/backends/dsound.c | 1064 +++++ Engine/lib/openal-soft/Alc/backends/jack.c | 627 +++ .../lib/openal-soft/Alc/backends/loopback.c | 133 + .../lib/openal-soft/Alc/backends/mmdevapi.c | 1911 ++++++++ Engine/lib/openal-soft/Alc/backends/null.c | 223 + Engine/lib/openal-soft/Alc/backends/opensl.c | 436 ++ Engine/lib/openal-soft/Alc/backends/oss.c | 821 ++++ .../lib/openal-soft/Alc/backends/portaudio.c | 573 +++ .../lib/openal-soft/Alc/backends/pulseaudio.c | 1847 ++++++++ Engine/lib/openal-soft/Alc/backends/qsa.c | 916 ++++ Engine/lib/openal-soft/Alc/backends/sndio.c | 294 ++ Engine/lib/openal-soft/Alc/backends/solaris.c | 339 ++ Engine/lib/openal-soft/Alc/backends/wave.c | 446 ++ Engine/lib/openal-soft/Alc/backends/winmm.c | 803 ++++ Engine/lib/openal-soft/Alc/bformatdec.c | 670 +++ Engine/lib/openal-soft/Alc/bformatdec.h | 49 + Engine/lib/openal-soft/Alc/bs2b.c | 187 + Engine/lib/openal-soft/Alc/bsinc.c | 981 ++++ Engine/lib/openal-soft/Alc/compat.h | 49 + Engine/lib/openal-soft/Alc/effects/chorus.c | 412 ++ .../lib/openal-soft/Alc/effects/compressor.c | 254 + .../lib/openal-soft/Alc/effects/dedicated.c | 201 + .../lib/openal-soft/Alc/effects/distortion.c | 298 ++ Engine/lib/openal-soft/Alc/effects/echo.c | 326 ++ .../lib/openal-soft/Alc/effects/equalizer.c | 404 ++ Engine/lib/openal-soft/Alc/effects/flanger.c | 411 ++ .../lib/openal-soft/Alc/effects/modulator.c | 311 ++ Engine/lib/openal-soft/Alc/effects/null.c | 179 + Engine/lib/openal-soft/Alc/effects/reverb.c | 1994 ++++++++ Engine/lib/openal-soft/Alc/helpers.c | 1127 +++++ Engine/lib/openal-soft/Alc/hrtf.c | 1054 +++++ Engine/lib/openal-soft/Alc/hrtf.h | 52 + Engine/lib/openal-soft/Alc/hrtf_res.h | 5 + Engine/lib/openal-soft/Alc/hrtf_res.rc | 4 + Engine/lib/openal-soft/Alc/mixer.c | 702 +++ Engine/lib/openal-soft/Alc/mixer_c.c | 228 + Engine/lib/openal-soft/Alc/mixer_defs.h | 110 + Engine/lib/openal-soft/Alc/mixer_inc.c | 149 + Engine/lib/openal-soft/Alc/mixer_neon.c | 173 + Engine/lib/openal-soft/Alc/mixer_sse.c | 292 ++ Engine/lib/openal-soft/Alc/mixer_sse2.c | 82 + Engine/lib/openal-soft/Alc/mixer_sse3.c | 164 + Engine/lib/openal-soft/Alc/mixer_sse41.c | 227 + Engine/lib/openal-soft/Alc/panning.c | 1037 +++++ Engine/lib/openal-soft/Alc/uhjfilter.c | 134 + Engine/lib/openal-soft/Alc/uhjfilter.h | 48 + Engine/lib/openal-soft/Alc/vector.h | 110 + Engine/lib/openal-soft/CMakeLists.txt | 1468 ++++++ Engine/lib/openal-soft/COPYING | 481 ++ Engine/lib/openal-soft/ChangeLog | 188 + .../OpenAL32/Include/alAuxEffectSlot.h | 183 + .../openal-soft/OpenAL32/Include/alBuffer.h | 130 + .../openal-soft/OpenAL32/Include/alEffect.h | 196 + .../openal-soft/OpenAL32/Include/alError.h | 33 + .../openal-soft/OpenAL32/Include/alFilter.h | 155 + .../openal-soft/OpenAL32/Include/alListener.h | 66 + .../lib/openal-soft/OpenAL32/Include/alMain.h | 967 ++++ .../openal-soft/OpenAL32/Include/alSource.h | 231 + .../openal-soft/OpenAL32/Include/alThunk.h | 20 + Engine/lib/openal-soft/OpenAL32/Include/alu.h | 363 ++ .../lib/openal-soft/OpenAL32/Include/bs2b.h | 94 + .../openal-soft/OpenAL32/Include/sample_cvt.h | 9 + .../openal-soft/OpenAL32/alAuxEffectSlot.c | 715 +++ Engine/lib/openal-soft/OpenAL32/alBuffer.c | 1415 ++++++ Engine/lib/openal-soft/OpenAL32/alEffect.c | 716 +++ Engine/lib/openal-soft/OpenAL32/alError.c | 77 + Engine/lib/openal-soft/OpenAL32/alExtension.c | 103 + Engine/lib/openal-soft/OpenAL32/alFilter.c | 718 +++ Engine/lib/openal-soft/OpenAL32/alListener.c | 515 ++ Engine/lib/openal-soft/OpenAL32/alSource.c | 3401 ++++++++++++++ Engine/lib/openal-soft/OpenAL32/alState.c | 687 +++ Engine/lib/openal-soft/OpenAL32/alThunk.c | 105 + Engine/lib/openal-soft/OpenAL32/sample_cvt.c | 1112 +++++ Engine/lib/openal-soft/README | 55 + Engine/lib/openal-soft/XCompile-Android.txt | 39 + Engine/lib/openal-soft/XCompile.txt | 37 + Engine/lib/openal-soft/alsoftrc.sample | 456 ++ Engine/lib/openal-soft/appveyor.yml | 14 + .../openal-soft/cmake/CheckFileOffsetBits.c | 9 + .../cmake/CheckFileOffsetBits.cmake | 39 + .../cmake/CheckSharedFunctionExists.cmake | 92 + Engine/lib/openal-soft/cmake/FindALSA.cmake | 73 + .../lib/openal-soft/cmake/FindAudioIO.cmake | 21 + Engine/lib/openal-soft/cmake/FindDSound.cmake | 35 + Engine/lib/openal-soft/cmake/FindFFmpeg.cmake | 173 + Engine/lib/openal-soft/cmake/FindJACK.cmake | 60 + Engine/lib/openal-soft/cmake/FindOSS.cmake | 21 + .../lib/openal-soft/cmake/FindPortAudio.cmake | 32 + .../openal-soft/cmake/FindPulseAudio.cmake | 43 + Engine/lib/openal-soft/cmake/FindQSA.cmake | 34 + Engine/lib/openal-soft/cmake/FindSDL2.cmake | 193 + .../lib/openal-soft/cmake/FindSDL_sound.cmake | 429 ++ .../lib/openal-soft/cmake/FindSoundIO.cmake | 32 + Engine/lib/openal-soft/common/almalloc.c | 62 + Engine/lib/openal-soft/common/atomic.c | 10 + Engine/lib/openal-soft/common/rwlock.c | 57 + Engine/lib/openal-soft/common/threads.c | 747 +++ Engine/lib/openal-soft/common/uintmap.c | 228 + Engine/lib/openal-soft/config.h.in | 204 + Engine/lib/openal-soft/include/AL/al.h | 656 +++ Engine/lib/openal-soft/include/AL/alc.h | 237 + Engine/lib/openal-soft/include/AL/alext.h | 443 ++ .../lib/openal-soft/include/AL/efx-creative.h | 3 + .../lib/openal-soft/include/AL/efx-presets.h | 402 ++ Engine/lib/openal-soft/include/AL/efx.h | 761 +++ Engine/lib/openal-soft/include/align.h | 21 + Engine/lib/openal-soft/include/almalloc.h | 18 + Engine/lib/openal-soft/include/atomic.h | 317 ++ Engine/lib/openal-soft/include/bool.h | 18 + Engine/lib/openal-soft/include/math_defs.h | 19 + Engine/lib/openal-soft/include/rwlock.h | 32 + .../lib/openal-soft/include/static_assert.h | 21 + Engine/lib/openal-soft/include/threads.h | 237 + Engine/lib/openal-soft/include/uintmap.h | 45 + Engine/lib/openal-soft/openal.pc.in | 11 + Engine/lib/openal/FreeBSD/al/al.h | 491 -- Engine/lib/openal/FreeBSD/al/al_func.h | 69 - Engine/lib/openal/FreeBSD/al/alc.h | 88 - Engine/lib/openal/FreeBSD/al/alc_func.h | 20 - Engine/lib/openal/FreeBSD/al/alctypes.h | 130 - Engine/lib/openal/FreeBSD/al/altypes.h | 332 -- Engine/lib/openal/FreeBSD/al/alu.h | 34 - Engine/lib/openal/FreeBSD/al/alut.h | 24 - Engine/lib/openal/FreeBSD/al/eax.h | 533 --- Engine/lib/openal/FreeBSD/al/eax_func.h | 3 - Engine/lib/openal/FreeBSD/al/eaxtypes.h | 462 -- Engine/lib/openal/FreeBSD/openALFn.h | 101 - Engine/lib/openal/LINUX/al/al.h | 491 -- Engine/lib/openal/LINUX/al/al_func.h | 69 - Engine/lib/openal/LINUX/al/alc.h | 88 - Engine/lib/openal/LINUX/al/alc_func.h | 20 - Engine/lib/openal/LINUX/al/alctypes.h | 130 - Engine/lib/openal/LINUX/al/altypes.h | 332 -- Engine/lib/openal/LINUX/al/alu.h | 34 - Engine/lib/openal/LINUX/al/alut.h | 24 - Engine/lib/openal/LINUX/al/eax.h | 533 --- Engine/lib/openal/LINUX/al/eax_func.h | 3 - Engine/lib/openal/LINUX/al/eaxtypes.h | 462 -- Engine/lib/openal/LINUX/libopenal.so | Bin 281812 -> 0 bytes Engine/lib/openal/LINUX/openALFn.h | 101 - Engine/lib/openal/LINUX/readme.txt | 10 - Engine/lib/openal/OpenBSD/AL/al.h | 523 --- Engine/lib/openal/OpenBSD/AL/alc.h | 71 - Engine/lib/openal/OpenBSD/AL/alctypes.h | 30 - Engine/lib/openal/OpenBSD/AL/altypes.h | 344 -- Engine/lib/openal/OpenBSD/AL/alu.h | 37 - Engine/lib/openal/OpenBSD/AL/alut.h | 53 - Engine/lib/openal/OpenBSD/AL/aluttypes.h | 5 - Engine/lib/openal/OpenBSD/AL/alutypes.h | 5 - Engine/lib/openal/OpenBSD/openALFn.h | 101 - Engine/lib/openal/X86UNIX/al/al.h | 523 --- Engine/lib/openal/X86UNIX/al/alc.h | 71 - Engine/lib/openal/X86UNIX/al/alctypes.h | 30 - Engine/lib/openal/X86UNIX/al/altypes.h | 344 -- Engine/lib/openal/X86UNIX/al/alu.h | 37 - Engine/lib/openal/X86UNIX/al/alut.h | 53 - Engine/lib/openal/X86UNIX/al/aluttypes.h | 5 - Engine/lib/openal/X86UNIX/al/alutypes.h | 5 - Engine/lib/openal/X86UNIX/openALFn.h | 101 - Engine/lib/openal/macCarb/al/al.h | 491 -- Engine/lib/openal/macCarb/al/al_func.h | 69 - Engine/lib/openal/macCarb/al/alc.h | 88 - Engine/lib/openal/macCarb/al/alc_func.h | 20 - Engine/lib/openal/macCarb/al/alctypes.h | 130 - Engine/lib/openal/macCarb/al/altypes.h | 336 -- Engine/lib/openal/macCarb/al/alu.h | 34 - Engine/lib/openal/macCarb/al/alut.h | 24 - Engine/lib/openal/macCarb/al/alut_func.h | 8 - Engine/lib/openal/macCarb/al/aluttypes.h | 5 - Engine/lib/openal/macCarb/al/alutypes.h | 5 - Engine/lib/openal/macCarb/al/eax.h | 533 --- Engine/lib/openal/macCarb/al/eax_func.h | 3 - Engine/lib/openal/macCarb/al/eaxtypes.h | 462 -- Engine/lib/openal/macCarb/openALFn.h | 80 - .../openal/macosx/OpenAL.framework/Headers | 1 - .../lib/openal/macosx/OpenAL.framework/OpenAL | 1 - .../openal/macosx/OpenAL.framework/Resources | 1 - .../OpenAL.framework/Versions/A/Headers/al.h | 498 -- .../OpenAL.framework/Versions/A/Headers/alc.h | 88 - .../Versions/A/Headers/alctypes.h | 165 - .../Versions/A/Headers/altypes.h | 336 -- .../Versions/A/Headers/alut.h | 55 - .../Versions/A/Headers/eaxtypes.h | 462 -- .../macosx/OpenAL.framework/Versions/A/OpenAL | Bin 400924 -> 0 bytes .../Resources/English.lproj/InfoPlist.strings | Bin 474 -> 0 bytes .../Versions/A/Resources/Info.plist | 26 - .../macosx/OpenAL.framework/Versions/Current | 1 - Engine/lib/openal/win32/al/EFX-Util.h | 422 -- Engine/lib/openal/win32/al/al.h | 750 --- Engine/lib/openal/win32/al/alc.h | 273 -- Engine/lib/openal/win32/al/efx-creative.h | 151 - Engine/lib/openal/win32/al/efx.h | 756 --- Engine/lib/openal/win32/al/xram.h | 94 - Tools/CMake/torque3d.cmake | 15 +- 207 files changed, 53310 insertions(+), 13291 deletions(-) create mode 100644 Engine/lib/openal-soft/.gitignore create mode 100644 Engine/lib/openal-soft/.travis.yml create mode 100644 Engine/lib/openal-soft/Alc/ALc.c create mode 100644 Engine/lib/openal-soft/Alc/ALu.c create mode 100644 Engine/lib/openal-soft/Alc/alcConfig.c create mode 100644 Engine/lib/openal-soft/Alc/alcRing.c create mode 100644 Engine/lib/openal-soft/Alc/alstring.h create mode 100644 Engine/lib/openal-soft/Alc/ambdec.c create mode 100644 Engine/lib/openal-soft/Alc/ambdec.h create mode 100644 Engine/lib/openal-soft/Alc/backends/alsa.c create mode 100644 Engine/lib/openal-soft/Alc/backends/base.c create mode 100644 Engine/lib/openal-soft/Alc/backends/base.h create mode 100644 Engine/lib/openal-soft/Alc/backends/coreaudio.c create mode 100644 Engine/lib/openal-soft/Alc/backends/dsound.c create mode 100644 Engine/lib/openal-soft/Alc/backends/jack.c create mode 100644 Engine/lib/openal-soft/Alc/backends/loopback.c create mode 100644 Engine/lib/openal-soft/Alc/backends/mmdevapi.c create mode 100644 Engine/lib/openal-soft/Alc/backends/null.c create mode 100644 Engine/lib/openal-soft/Alc/backends/opensl.c create mode 100644 Engine/lib/openal-soft/Alc/backends/oss.c create mode 100644 Engine/lib/openal-soft/Alc/backends/portaudio.c create mode 100644 Engine/lib/openal-soft/Alc/backends/pulseaudio.c create mode 100644 Engine/lib/openal-soft/Alc/backends/qsa.c create mode 100644 Engine/lib/openal-soft/Alc/backends/sndio.c create mode 100644 Engine/lib/openal-soft/Alc/backends/solaris.c create mode 100644 Engine/lib/openal-soft/Alc/backends/wave.c create mode 100644 Engine/lib/openal-soft/Alc/backends/winmm.c create mode 100644 Engine/lib/openal-soft/Alc/bformatdec.c create mode 100644 Engine/lib/openal-soft/Alc/bformatdec.h create mode 100644 Engine/lib/openal-soft/Alc/bs2b.c create mode 100644 Engine/lib/openal-soft/Alc/bsinc.c create mode 100644 Engine/lib/openal-soft/Alc/compat.h create mode 100644 Engine/lib/openal-soft/Alc/effects/chorus.c create mode 100644 Engine/lib/openal-soft/Alc/effects/compressor.c create mode 100644 Engine/lib/openal-soft/Alc/effects/dedicated.c create mode 100644 Engine/lib/openal-soft/Alc/effects/distortion.c create mode 100644 Engine/lib/openal-soft/Alc/effects/echo.c create mode 100644 Engine/lib/openal-soft/Alc/effects/equalizer.c create mode 100644 Engine/lib/openal-soft/Alc/effects/flanger.c create mode 100644 Engine/lib/openal-soft/Alc/effects/modulator.c create mode 100644 Engine/lib/openal-soft/Alc/effects/null.c create mode 100644 Engine/lib/openal-soft/Alc/effects/reverb.c create mode 100644 Engine/lib/openal-soft/Alc/helpers.c create mode 100644 Engine/lib/openal-soft/Alc/hrtf.c create mode 100644 Engine/lib/openal-soft/Alc/hrtf.h create mode 100644 Engine/lib/openal-soft/Alc/hrtf_res.h create mode 100644 Engine/lib/openal-soft/Alc/hrtf_res.rc create mode 100644 Engine/lib/openal-soft/Alc/mixer.c create mode 100644 Engine/lib/openal-soft/Alc/mixer_c.c create mode 100644 Engine/lib/openal-soft/Alc/mixer_defs.h create mode 100644 Engine/lib/openal-soft/Alc/mixer_inc.c create mode 100644 Engine/lib/openal-soft/Alc/mixer_neon.c create mode 100644 Engine/lib/openal-soft/Alc/mixer_sse.c create mode 100644 Engine/lib/openal-soft/Alc/mixer_sse2.c create mode 100644 Engine/lib/openal-soft/Alc/mixer_sse3.c create mode 100644 Engine/lib/openal-soft/Alc/mixer_sse41.c create mode 100644 Engine/lib/openal-soft/Alc/panning.c create mode 100644 Engine/lib/openal-soft/Alc/uhjfilter.c create mode 100644 Engine/lib/openal-soft/Alc/uhjfilter.h create mode 100644 Engine/lib/openal-soft/Alc/vector.h create mode 100644 Engine/lib/openal-soft/CMakeLists.txt create mode 100644 Engine/lib/openal-soft/COPYING create mode 100644 Engine/lib/openal-soft/ChangeLog create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alAuxEffectSlot.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alBuffer.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alEffect.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alError.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alFilter.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alListener.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alMain.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alSource.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alThunk.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/alu.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/bs2b.h create mode 100644 Engine/lib/openal-soft/OpenAL32/Include/sample_cvt.h create mode 100644 Engine/lib/openal-soft/OpenAL32/alAuxEffectSlot.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alBuffer.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alEffect.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alError.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alExtension.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alFilter.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alListener.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alSource.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alState.c create mode 100644 Engine/lib/openal-soft/OpenAL32/alThunk.c create mode 100644 Engine/lib/openal-soft/OpenAL32/sample_cvt.c create mode 100644 Engine/lib/openal-soft/README create mode 100644 Engine/lib/openal-soft/XCompile-Android.txt create mode 100644 Engine/lib/openal-soft/XCompile.txt create mode 100644 Engine/lib/openal-soft/alsoftrc.sample create mode 100644 Engine/lib/openal-soft/appveyor.yml create mode 100644 Engine/lib/openal-soft/cmake/CheckFileOffsetBits.c create mode 100644 Engine/lib/openal-soft/cmake/CheckFileOffsetBits.cmake create mode 100644 Engine/lib/openal-soft/cmake/CheckSharedFunctionExists.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindALSA.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindAudioIO.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindDSound.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindFFmpeg.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindJACK.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindOSS.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindPortAudio.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindPulseAudio.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindQSA.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindSDL2.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindSDL_sound.cmake create mode 100644 Engine/lib/openal-soft/cmake/FindSoundIO.cmake create mode 100644 Engine/lib/openal-soft/common/almalloc.c create mode 100644 Engine/lib/openal-soft/common/atomic.c create mode 100644 Engine/lib/openal-soft/common/rwlock.c create mode 100644 Engine/lib/openal-soft/common/threads.c create mode 100644 Engine/lib/openal-soft/common/uintmap.c create mode 100644 Engine/lib/openal-soft/config.h.in create mode 100644 Engine/lib/openal-soft/include/AL/al.h create mode 100644 Engine/lib/openal-soft/include/AL/alc.h create mode 100644 Engine/lib/openal-soft/include/AL/alext.h create mode 100644 Engine/lib/openal-soft/include/AL/efx-creative.h create mode 100644 Engine/lib/openal-soft/include/AL/efx-presets.h create mode 100644 Engine/lib/openal-soft/include/AL/efx.h create mode 100644 Engine/lib/openal-soft/include/align.h create mode 100644 Engine/lib/openal-soft/include/almalloc.h create mode 100644 Engine/lib/openal-soft/include/atomic.h create mode 100644 Engine/lib/openal-soft/include/bool.h create mode 100644 Engine/lib/openal-soft/include/math_defs.h create mode 100644 Engine/lib/openal-soft/include/rwlock.h create mode 100644 Engine/lib/openal-soft/include/static_assert.h create mode 100644 Engine/lib/openal-soft/include/threads.h create mode 100644 Engine/lib/openal-soft/include/uintmap.h create mode 100644 Engine/lib/openal-soft/openal.pc.in delete mode 100644 Engine/lib/openal/FreeBSD/al/al.h delete mode 100644 Engine/lib/openal/FreeBSD/al/al_func.h delete mode 100644 Engine/lib/openal/FreeBSD/al/alc.h delete mode 100644 Engine/lib/openal/FreeBSD/al/alc_func.h delete mode 100644 Engine/lib/openal/FreeBSD/al/alctypes.h delete mode 100644 Engine/lib/openal/FreeBSD/al/altypes.h delete mode 100644 Engine/lib/openal/FreeBSD/al/alu.h delete mode 100644 Engine/lib/openal/FreeBSD/al/alut.h delete mode 100644 Engine/lib/openal/FreeBSD/al/eax.h delete mode 100644 Engine/lib/openal/FreeBSD/al/eax_func.h delete mode 100644 Engine/lib/openal/FreeBSD/al/eaxtypes.h delete mode 100644 Engine/lib/openal/FreeBSD/openALFn.h delete mode 100644 Engine/lib/openal/LINUX/al/al.h delete mode 100644 Engine/lib/openal/LINUX/al/al_func.h delete mode 100644 Engine/lib/openal/LINUX/al/alc.h delete mode 100644 Engine/lib/openal/LINUX/al/alc_func.h delete mode 100644 Engine/lib/openal/LINUX/al/alctypes.h delete mode 100644 Engine/lib/openal/LINUX/al/altypes.h delete mode 100644 Engine/lib/openal/LINUX/al/alu.h delete mode 100644 Engine/lib/openal/LINUX/al/alut.h delete mode 100644 Engine/lib/openal/LINUX/al/eax.h delete mode 100644 Engine/lib/openal/LINUX/al/eax_func.h delete mode 100644 Engine/lib/openal/LINUX/al/eaxtypes.h delete mode 100644 Engine/lib/openal/LINUX/libopenal.so delete mode 100644 Engine/lib/openal/LINUX/openALFn.h delete mode 100644 Engine/lib/openal/LINUX/readme.txt delete mode 100644 Engine/lib/openal/OpenBSD/AL/al.h delete mode 100644 Engine/lib/openal/OpenBSD/AL/alc.h delete mode 100644 Engine/lib/openal/OpenBSD/AL/alctypes.h delete mode 100644 Engine/lib/openal/OpenBSD/AL/altypes.h delete mode 100644 Engine/lib/openal/OpenBSD/AL/alu.h delete mode 100644 Engine/lib/openal/OpenBSD/AL/alut.h delete mode 100644 Engine/lib/openal/OpenBSD/AL/aluttypes.h delete mode 100644 Engine/lib/openal/OpenBSD/AL/alutypes.h delete mode 100644 Engine/lib/openal/OpenBSD/openALFn.h delete mode 100644 Engine/lib/openal/X86UNIX/al/al.h delete mode 100644 Engine/lib/openal/X86UNIX/al/alc.h delete mode 100644 Engine/lib/openal/X86UNIX/al/alctypes.h delete mode 100644 Engine/lib/openal/X86UNIX/al/altypes.h delete mode 100644 Engine/lib/openal/X86UNIX/al/alu.h delete mode 100644 Engine/lib/openal/X86UNIX/al/alut.h delete mode 100644 Engine/lib/openal/X86UNIX/al/aluttypes.h delete mode 100644 Engine/lib/openal/X86UNIX/al/alutypes.h delete mode 100644 Engine/lib/openal/X86UNIX/openALFn.h delete mode 100644 Engine/lib/openal/macCarb/al/al.h delete mode 100644 Engine/lib/openal/macCarb/al/al_func.h delete mode 100644 Engine/lib/openal/macCarb/al/alc.h delete mode 100644 Engine/lib/openal/macCarb/al/alc_func.h delete mode 100644 Engine/lib/openal/macCarb/al/alctypes.h delete mode 100644 Engine/lib/openal/macCarb/al/altypes.h delete mode 100644 Engine/lib/openal/macCarb/al/alu.h delete mode 100644 Engine/lib/openal/macCarb/al/alut.h delete mode 100644 Engine/lib/openal/macCarb/al/alut_func.h delete mode 100644 Engine/lib/openal/macCarb/al/aluttypes.h delete mode 100644 Engine/lib/openal/macCarb/al/alutypes.h delete mode 100644 Engine/lib/openal/macCarb/al/eax.h delete mode 100644 Engine/lib/openal/macCarb/al/eax_func.h delete mode 100644 Engine/lib/openal/macCarb/al/eaxtypes.h delete mode 100644 Engine/lib/openal/macCarb/openALFn.h delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Headers delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/OpenAL delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Resources delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/al.h delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alc.h delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alctypes.h delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/altypes.h delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alut.h delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/eaxtypes.h delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/OpenAL delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Resources/English.lproj/InfoPlist.strings delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Resources/Info.plist delete mode 100644 Engine/lib/openal/macosx/OpenAL.framework/Versions/Current delete mode 100644 Engine/lib/openal/win32/al/EFX-Util.h delete mode 100644 Engine/lib/openal/win32/al/al.h delete mode 100644 Engine/lib/openal/win32/al/alc.h delete mode 100644 Engine/lib/openal/win32/al/efx-creative.h delete mode 100644 Engine/lib/openal/win32/al/efx.h delete mode 100644 Engine/lib/openal/win32/al/xram.h diff --git a/Engine/lib/openal-soft/.gitignore b/Engine/lib/openal-soft/.gitignore new file mode 100644 index 000000000..9aa081c61 --- /dev/null +++ b/Engine/lib/openal-soft/.gitignore @@ -0,0 +1,7 @@ +build +winbuild +win64build +include/SLES +include/sndio.h +include/sys +openal-soft.kdev4 diff --git a/Engine/lib/openal-soft/.travis.yml b/Engine/lib/openal-soft/.travis.yml new file mode 100644 index 000000000..dfae8e7a5 --- /dev/null +++ b/Engine/lib/openal-soft/.travis.yml @@ -0,0 +1,5 @@ +os: + - linux + - osx +language: c +script: cmake . && make -j2 diff --git a/Engine/lib/openal-soft/Alc/ALc.c b/Engine/lib/openal-soft/Alc/ALc.c new file mode 100644 index 000000000..7e220205c --- /dev/null +++ b/Engine/lib/openal-soft/Alc/ALc.c @@ -0,0 +1,4139 @@ +/** + * 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 +#include +#include +#include +#include +#include + +#include "alMain.h" +#include "alSource.h" +#include "alListener.h" +#include "alThunk.h" +#include "alSource.h" +#include "alBuffer.h" +#include "alAuxEffectSlot.h" +#include "alError.h" +#include "bformatdec.h" +#include "alu.h" + +#include "compat.h" +#include "threads.h" +#include "alstring.h" +#include "almalloc.h" + +#include "backends/base.h" + + +/************************************************ + * Backends + ************************************************/ +struct BackendInfo { + const char *name; + ALCbackendFactory* (*getFactory)(void); + ALCboolean (*Init)(BackendFuncs*); + void (*Deinit)(void); + void (*Probe)(enum DevProbe); + BackendFuncs Funcs; +}; + +#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } +static struct BackendInfo BackendList[] = { +#ifdef HAVE_JACK + { "jack", ALCjackBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_PULSEAUDIO + { "pulse", ALCpulseBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_ALSA + { "alsa", ALCalsaBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_COREAUDIO + { "core", NULL, alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs }, +#endif +#ifdef HAVE_OSS + { "oss", ALCossBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_SOLARIS + { "solaris", ALCsolarisBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_SNDIO + { "sndio", NULL, alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs }, +#endif +#ifdef HAVE_QSA + { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs }, +#endif +#ifdef HAVE_MMDEVAPI + { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_DSOUND + { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_WINMM + { "winmm", ALCwinmmBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_PORTAUDIO + { "port", ALCportBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif +#ifdef HAVE_OPENSL + { "opensl", NULL, alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs }, +#endif + + { "null", ALCnullBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#ifdef HAVE_WAVE + { "wave", ALCwaveBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, +#endif + + { NULL, NULL, NULL, NULL, NULL, EmptyFuncs } +}; +#undef EmptyFuncs + +static struct BackendInfo PlaybackBackend; +static struct BackendInfo CaptureBackend; + + +/************************************************ + * Functions, enums, and errors + ************************************************/ +typedef struct ALCfunction { + const ALCchar *funcName; + ALCvoid *address; +} ALCfunction; + +typedef struct ALCenums { + const ALCchar *enumName; + ALCenum value; +} ALCenums; + +#define DECL(x) { #x, (ALCvoid*)(x) } +static const ALCfunction alcFunctions[] = { + DECL(alcCreateContext), + DECL(alcMakeContextCurrent), + DECL(alcProcessContext), + DECL(alcSuspendContext), + DECL(alcDestroyContext), + DECL(alcGetCurrentContext), + DECL(alcGetContextsDevice), + DECL(alcOpenDevice), + DECL(alcCloseDevice), + DECL(alcGetError), + DECL(alcIsExtensionPresent), + DECL(alcGetProcAddress), + DECL(alcGetEnumValue), + DECL(alcGetString), + DECL(alcGetIntegerv), + DECL(alcCaptureOpenDevice), + DECL(alcCaptureCloseDevice), + DECL(alcCaptureStart), + DECL(alcCaptureStop), + DECL(alcCaptureSamples), + + DECL(alcSetThreadContext), + DECL(alcGetThreadContext), + + DECL(alcLoopbackOpenDeviceSOFT), + DECL(alcIsRenderFormatSupportedSOFT), + DECL(alcRenderSamplesSOFT), + + DECL(alcDevicePauseSOFT), + DECL(alcDeviceResumeSOFT), + + DECL(alcGetStringiSOFT), + DECL(alcResetDeviceSOFT), + + DECL(alcGetInteger64vSOFT), + + DECL(alEnable), + DECL(alDisable), + DECL(alIsEnabled), + DECL(alGetString), + DECL(alGetBooleanv), + DECL(alGetIntegerv), + DECL(alGetFloatv), + DECL(alGetDoublev), + DECL(alGetBoolean), + DECL(alGetInteger), + DECL(alGetFloat), + DECL(alGetDouble), + DECL(alGetError), + DECL(alIsExtensionPresent), + DECL(alGetProcAddress), + DECL(alGetEnumValue), + DECL(alListenerf), + DECL(alListener3f), + DECL(alListenerfv), + DECL(alListeneri), + DECL(alListener3i), + DECL(alListeneriv), + DECL(alGetListenerf), + DECL(alGetListener3f), + DECL(alGetListenerfv), + DECL(alGetListeneri), + DECL(alGetListener3i), + DECL(alGetListeneriv), + DECL(alGenSources), + DECL(alDeleteSources), + DECL(alIsSource), + DECL(alSourcef), + DECL(alSource3f), + DECL(alSourcefv), + DECL(alSourcei), + DECL(alSource3i), + DECL(alSourceiv), + DECL(alGetSourcef), + DECL(alGetSource3f), + DECL(alGetSourcefv), + DECL(alGetSourcei), + DECL(alGetSource3i), + DECL(alGetSourceiv), + DECL(alSourcePlayv), + DECL(alSourceStopv), + DECL(alSourceRewindv), + DECL(alSourcePausev), + DECL(alSourcePlay), + DECL(alSourceStop), + DECL(alSourceRewind), + DECL(alSourcePause), + DECL(alSourceQueueBuffers), + DECL(alSourceUnqueueBuffers), + DECL(alGenBuffers), + DECL(alDeleteBuffers), + DECL(alIsBuffer), + DECL(alBufferData), + DECL(alBufferf), + DECL(alBuffer3f), + DECL(alBufferfv), + DECL(alBufferi), + DECL(alBuffer3i), + DECL(alBufferiv), + DECL(alGetBufferf), + DECL(alGetBuffer3f), + DECL(alGetBufferfv), + DECL(alGetBufferi), + DECL(alGetBuffer3i), + DECL(alGetBufferiv), + DECL(alDopplerFactor), + DECL(alDopplerVelocity), + DECL(alSpeedOfSound), + DECL(alDistanceModel), + + DECL(alGenFilters), + DECL(alDeleteFilters), + DECL(alIsFilter), + DECL(alFilteri), + DECL(alFilteriv), + DECL(alFilterf), + DECL(alFilterfv), + DECL(alGetFilteri), + DECL(alGetFilteriv), + DECL(alGetFilterf), + DECL(alGetFilterfv), + DECL(alGenEffects), + DECL(alDeleteEffects), + DECL(alIsEffect), + DECL(alEffecti), + DECL(alEffectiv), + DECL(alEffectf), + DECL(alEffectfv), + DECL(alGetEffecti), + DECL(alGetEffectiv), + DECL(alGetEffectf), + DECL(alGetEffectfv), + DECL(alGenAuxiliaryEffectSlots), + DECL(alDeleteAuxiliaryEffectSlots), + DECL(alIsAuxiliaryEffectSlot), + DECL(alAuxiliaryEffectSloti), + DECL(alAuxiliaryEffectSlotiv), + DECL(alAuxiliaryEffectSlotf), + DECL(alAuxiliaryEffectSlotfv), + DECL(alGetAuxiliaryEffectSloti), + DECL(alGetAuxiliaryEffectSlotiv), + DECL(alGetAuxiliaryEffectSlotf), + DECL(alGetAuxiliaryEffectSlotfv), + + DECL(alDeferUpdatesSOFT), + DECL(alProcessUpdatesSOFT), + + DECL(alSourcedSOFT), + DECL(alSource3dSOFT), + DECL(alSourcedvSOFT), + DECL(alGetSourcedSOFT), + DECL(alGetSource3dSOFT), + DECL(alGetSourcedvSOFT), + DECL(alSourcei64SOFT), + DECL(alSource3i64SOFT), + DECL(alSourcei64vSOFT), + DECL(alGetSourcei64SOFT), + DECL(alGetSource3i64SOFT), + DECL(alGetSourcei64vSOFT), + + DECL(alBufferSamplesSOFT), + DECL(alGetBufferSamplesSOFT), + DECL(alIsBufferFormatSupportedSOFT), + + { NULL, NULL } +}; +#undef DECL + +#define DECL(x) { #x, (x) } +static const ALCenums enumeration[] = { + DECL(ALC_INVALID), + DECL(ALC_FALSE), + DECL(ALC_TRUE), + + DECL(ALC_MAJOR_VERSION), + DECL(ALC_MINOR_VERSION), + DECL(ALC_ATTRIBUTES_SIZE), + DECL(ALC_ALL_ATTRIBUTES), + DECL(ALC_DEFAULT_DEVICE_SPECIFIER), + DECL(ALC_DEVICE_SPECIFIER), + DECL(ALC_ALL_DEVICES_SPECIFIER), + DECL(ALC_DEFAULT_ALL_DEVICES_SPECIFIER), + DECL(ALC_EXTENSIONS), + DECL(ALC_FREQUENCY), + DECL(ALC_REFRESH), + DECL(ALC_SYNC), + DECL(ALC_MONO_SOURCES), + DECL(ALC_STEREO_SOURCES), + DECL(ALC_CAPTURE_DEVICE_SPECIFIER), + DECL(ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER), + DECL(ALC_CAPTURE_SAMPLES), + DECL(ALC_CONNECTED), + + DECL(ALC_EFX_MAJOR_VERSION), + DECL(ALC_EFX_MINOR_VERSION), + DECL(ALC_MAX_AUXILIARY_SENDS), + + DECL(ALC_FORMAT_CHANNELS_SOFT), + DECL(ALC_FORMAT_TYPE_SOFT), + + DECL(ALC_MONO_SOFT), + DECL(ALC_STEREO_SOFT), + DECL(ALC_QUAD_SOFT), + DECL(ALC_5POINT1_SOFT), + DECL(ALC_6POINT1_SOFT), + DECL(ALC_7POINT1_SOFT), + + DECL(ALC_BYTE_SOFT), + DECL(ALC_UNSIGNED_BYTE_SOFT), + DECL(ALC_SHORT_SOFT), + DECL(ALC_UNSIGNED_SHORT_SOFT), + DECL(ALC_INT_SOFT), + DECL(ALC_UNSIGNED_INT_SOFT), + DECL(ALC_FLOAT_SOFT), + + DECL(ALC_HRTF_SOFT), + DECL(ALC_DONT_CARE_SOFT), + DECL(ALC_HRTF_STATUS_SOFT), + DECL(ALC_HRTF_DISABLED_SOFT), + DECL(ALC_HRTF_ENABLED_SOFT), + DECL(ALC_HRTF_DENIED_SOFT), + DECL(ALC_HRTF_REQUIRED_SOFT), + DECL(ALC_HRTF_HEADPHONES_DETECTED_SOFT), + DECL(ALC_HRTF_UNSUPPORTED_FORMAT_SOFT), + DECL(ALC_NUM_HRTF_SPECIFIERS_SOFT), + DECL(ALC_HRTF_SPECIFIER_SOFT), + DECL(ALC_HRTF_ID_SOFT), + + DECL(ALC_NO_ERROR), + DECL(ALC_INVALID_DEVICE), + DECL(ALC_INVALID_CONTEXT), + DECL(ALC_INVALID_ENUM), + DECL(ALC_INVALID_VALUE), + DECL(ALC_OUT_OF_MEMORY), + + + DECL(AL_INVALID), + DECL(AL_NONE), + DECL(AL_FALSE), + DECL(AL_TRUE), + + DECL(AL_SOURCE_RELATIVE), + DECL(AL_CONE_INNER_ANGLE), + DECL(AL_CONE_OUTER_ANGLE), + DECL(AL_PITCH), + DECL(AL_POSITION), + DECL(AL_DIRECTION), + DECL(AL_VELOCITY), + DECL(AL_LOOPING), + DECL(AL_BUFFER), + DECL(AL_GAIN), + DECL(AL_MIN_GAIN), + DECL(AL_MAX_GAIN), + DECL(AL_ORIENTATION), + DECL(AL_REFERENCE_DISTANCE), + DECL(AL_ROLLOFF_FACTOR), + DECL(AL_CONE_OUTER_GAIN), + DECL(AL_MAX_DISTANCE), + DECL(AL_SEC_OFFSET), + DECL(AL_SAMPLE_OFFSET), + DECL(AL_BYTE_OFFSET), + DECL(AL_SOURCE_TYPE), + DECL(AL_STATIC), + DECL(AL_STREAMING), + DECL(AL_UNDETERMINED), + DECL(AL_METERS_PER_UNIT), + DECL(AL_LOOP_POINTS_SOFT), + DECL(AL_DIRECT_CHANNELS_SOFT), + + DECL(AL_DIRECT_FILTER), + DECL(AL_AUXILIARY_SEND_FILTER), + DECL(AL_AIR_ABSORPTION_FACTOR), + DECL(AL_ROOM_ROLLOFF_FACTOR), + DECL(AL_CONE_OUTER_GAINHF), + DECL(AL_DIRECT_FILTER_GAINHF_AUTO), + DECL(AL_AUXILIARY_SEND_FILTER_GAIN_AUTO), + DECL(AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO), + + DECL(AL_SOURCE_STATE), + DECL(AL_INITIAL), + DECL(AL_PLAYING), + DECL(AL_PAUSED), + DECL(AL_STOPPED), + + DECL(AL_BUFFERS_QUEUED), + DECL(AL_BUFFERS_PROCESSED), + + DECL(AL_FORMAT_MONO8), + DECL(AL_FORMAT_MONO16), + DECL(AL_FORMAT_MONO_FLOAT32), + DECL(AL_FORMAT_MONO_DOUBLE_EXT), + DECL(AL_FORMAT_STEREO8), + DECL(AL_FORMAT_STEREO16), + DECL(AL_FORMAT_STEREO_FLOAT32), + DECL(AL_FORMAT_STEREO_DOUBLE_EXT), + DECL(AL_FORMAT_MONO_IMA4), + DECL(AL_FORMAT_STEREO_IMA4), + DECL(AL_FORMAT_MONO_MSADPCM_SOFT), + DECL(AL_FORMAT_STEREO_MSADPCM_SOFT), + DECL(AL_FORMAT_QUAD8_LOKI), + DECL(AL_FORMAT_QUAD16_LOKI), + DECL(AL_FORMAT_QUAD8), + DECL(AL_FORMAT_QUAD16), + DECL(AL_FORMAT_QUAD32), + DECL(AL_FORMAT_51CHN8), + DECL(AL_FORMAT_51CHN16), + DECL(AL_FORMAT_51CHN32), + DECL(AL_FORMAT_61CHN8), + DECL(AL_FORMAT_61CHN16), + DECL(AL_FORMAT_61CHN32), + DECL(AL_FORMAT_71CHN8), + DECL(AL_FORMAT_71CHN16), + DECL(AL_FORMAT_71CHN32), + DECL(AL_FORMAT_REAR8), + DECL(AL_FORMAT_REAR16), + DECL(AL_FORMAT_REAR32), + DECL(AL_FORMAT_MONO_MULAW), + DECL(AL_FORMAT_MONO_MULAW_EXT), + DECL(AL_FORMAT_STEREO_MULAW), + DECL(AL_FORMAT_STEREO_MULAW_EXT), + DECL(AL_FORMAT_QUAD_MULAW), + DECL(AL_FORMAT_51CHN_MULAW), + DECL(AL_FORMAT_61CHN_MULAW), + DECL(AL_FORMAT_71CHN_MULAW), + DECL(AL_FORMAT_REAR_MULAW), + DECL(AL_FORMAT_MONO_ALAW_EXT), + DECL(AL_FORMAT_STEREO_ALAW_EXT), + + DECL(AL_FORMAT_BFORMAT2D_8), + DECL(AL_FORMAT_BFORMAT2D_16), + DECL(AL_FORMAT_BFORMAT2D_FLOAT32), + DECL(AL_FORMAT_BFORMAT2D_MULAW), + DECL(AL_FORMAT_BFORMAT3D_8), + DECL(AL_FORMAT_BFORMAT3D_16), + DECL(AL_FORMAT_BFORMAT3D_FLOAT32), + DECL(AL_FORMAT_BFORMAT3D_MULAW), + + DECL(AL_MONO8_SOFT), + DECL(AL_MONO16_SOFT), + DECL(AL_MONO32F_SOFT), + DECL(AL_STEREO8_SOFT), + DECL(AL_STEREO16_SOFT), + DECL(AL_STEREO32F_SOFT), + DECL(AL_QUAD8_SOFT), + DECL(AL_QUAD16_SOFT), + DECL(AL_QUAD32F_SOFT), + DECL(AL_REAR8_SOFT), + DECL(AL_REAR16_SOFT), + DECL(AL_REAR32F_SOFT), + DECL(AL_5POINT1_8_SOFT), + DECL(AL_5POINT1_16_SOFT), + DECL(AL_5POINT1_32F_SOFT), + DECL(AL_6POINT1_8_SOFT), + DECL(AL_6POINT1_16_SOFT), + DECL(AL_6POINT1_32F_SOFT), + DECL(AL_7POINT1_8_SOFT), + DECL(AL_7POINT1_16_SOFT), + DECL(AL_7POINT1_32F_SOFT), + DECL(AL_BFORMAT2D_8_SOFT), + DECL(AL_BFORMAT2D_16_SOFT), + DECL(AL_BFORMAT2D_32F_SOFT), + DECL(AL_BFORMAT3D_8_SOFT), + DECL(AL_BFORMAT3D_16_SOFT), + DECL(AL_BFORMAT3D_32F_SOFT), + + DECL(AL_MONO_SOFT), + DECL(AL_STEREO_SOFT), + DECL(AL_QUAD_SOFT), + DECL(AL_REAR_SOFT), + DECL(AL_5POINT1_SOFT), + DECL(AL_6POINT1_SOFT), + DECL(AL_7POINT1_SOFT), + DECL(AL_BFORMAT2D_SOFT), + DECL(AL_BFORMAT3D_SOFT), + + DECL(AL_BYTE_SOFT), + DECL(AL_UNSIGNED_BYTE_SOFT), + DECL(AL_SHORT_SOFT), + DECL(AL_UNSIGNED_SHORT_SOFT), + DECL(AL_INT_SOFT), + DECL(AL_UNSIGNED_INT_SOFT), + DECL(AL_FLOAT_SOFT), + DECL(AL_DOUBLE_SOFT), + DECL(AL_BYTE3_SOFT), + DECL(AL_UNSIGNED_BYTE3_SOFT), + DECL(AL_MULAW_SOFT), + + DECL(AL_FREQUENCY), + DECL(AL_BITS), + DECL(AL_CHANNELS), + DECL(AL_SIZE), + DECL(AL_INTERNAL_FORMAT_SOFT), + DECL(AL_BYTE_LENGTH_SOFT), + DECL(AL_SAMPLE_LENGTH_SOFT), + DECL(AL_SEC_LENGTH_SOFT), + DECL(AL_UNPACK_BLOCK_ALIGNMENT_SOFT), + DECL(AL_PACK_BLOCK_ALIGNMENT_SOFT), + + DECL(AL_SOURCE_RADIUS), + + DECL(AL_STEREO_ANGLES), + + DECL(AL_UNUSED), + DECL(AL_PENDING), + DECL(AL_PROCESSED), + + DECL(AL_NO_ERROR), + DECL(AL_INVALID_NAME), + DECL(AL_INVALID_ENUM), + DECL(AL_INVALID_VALUE), + DECL(AL_INVALID_OPERATION), + DECL(AL_OUT_OF_MEMORY), + + DECL(AL_VENDOR), + DECL(AL_VERSION), + DECL(AL_RENDERER), + DECL(AL_EXTENSIONS), + + DECL(AL_DOPPLER_FACTOR), + DECL(AL_DOPPLER_VELOCITY), + DECL(AL_DISTANCE_MODEL), + DECL(AL_SPEED_OF_SOUND), + DECL(AL_SOURCE_DISTANCE_MODEL), + DECL(AL_DEFERRED_UPDATES_SOFT), + DECL(AL_GAIN_LIMIT_SOFT), + + DECL(AL_INVERSE_DISTANCE), + DECL(AL_INVERSE_DISTANCE_CLAMPED), + DECL(AL_LINEAR_DISTANCE), + DECL(AL_LINEAR_DISTANCE_CLAMPED), + DECL(AL_EXPONENT_DISTANCE), + DECL(AL_EXPONENT_DISTANCE_CLAMPED), + + DECL(AL_FILTER_TYPE), + DECL(AL_FILTER_NULL), + DECL(AL_FILTER_LOWPASS), + DECL(AL_FILTER_HIGHPASS), + DECL(AL_FILTER_BANDPASS), + + DECL(AL_LOWPASS_GAIN), + DECL(AL_LOWPASS_GAINHF), + + DECL(AL_HIGHPASS_GAIN), + DECL(AL_HIGHPASS_GAINLF), + + DECL(AL_BANDPASS_GAIN), + DECL(AL_BANDPASS_GAINHF), + DECL(AL_BANDPASS_GAINLF), + + DECL(AL_EFFECT_TYPE), + DECL(AL_EFFECT_NULL), + DECL(AL_EFFECT_REVERB), + DECL(AL_EFFECT_EAXREVERB), + DECL(AL_EFFECT_CHORUS), + DECL(AL_EFFECT_DISTORTION), + DECL(AL_EFFECT_ECHO), + DECL(AL_EFFECT_FLANGER), +#if 0 + DECL(AL_EFFECT_FREQUENCY_SHIFTER), + DECL(AL_EFFECT_VOCAL_MORPHER), + DECL(AL_EFFECT_PITCH_SHIFTER), +#endif + DECL(AL_EFFECT_RING_MODULATOR), +#if 0 + DECL(AL_EFFECT_AUTOWAH), +#endif + DECL(AL_EFFECT_COMPRESSOR), + DECL(AL_EFFECT_EQUALIZER), + DECL(AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT), + DECL(AL_EFFECT_DEDICATED_DIALOGUE), + + DECL(AL_EAXREVERB_DENSITY), + DECL(AL_EAXREVERB_DIFFUSION), + DECL(AL_EAXREVERB_GAIN), + DECL(AL_EAXREVERB_GAINHF), + DECL(AL_EAXREVERB_GAINLF), + DECL(AL_EAXREVERB_DECAY_TIME), + DECL(AL_EAXREVERB_DECAY_HFRATIO), + DECL(AL_EAXREVERB_DECAY_LFRATIO), + DECL(AL_EAXREVERB_REFLECTIONS_GAIN), + DECL(AL_EAXREVERB_REFLECTIONS_DELAY), + DECL(AL_EAXREVERB_REFLECTIONS_PAN), + DECL(AL_EAXREVERB_LATE_REVERB_GAIN), + DECL(AL_EAXREVERB_LATE_REVERB_DELAY), + DECL(AL_EAXREVERB_LATE_REVERB_PAN), + DECL(AL_EAXREVERB_ECHO_TIME), + DECL(AL_EAXREVERB_ECHO_DEPTH), + DECL(AL_EAXREVERB_MODULATION_TIME), + DECL(AL_EAXREVERB_MODULATION_DEPTH), + DECL(AL_EAXREVERB_AIR_ABSORPTION_GAINHF), + DECL(AL_EAXREVERB_HFREFERENCE), + DECL(AL_EAXREVERB_LFREFERENCE), + DECL(AL_EAXREVERB_ROOM_ROLLOFF_FACTOR), + DECL(AL_EAXREVERB_DECAY_HFLIMIT), + + DECL(AL_REVERB_DENSITY), + DECL(AL_REVERB_DIFFUSION), + DECL(AL_REVERB_GAIN), + DECL(AL_REVERB_GAINHF), + DECL(AL_REVERB_DECAY_TIME), + DECL(AL_REVERB_DECAY_HFRATIO), + DECL(AL_REVERB_REFLECTIONS_GAIN), + DECL(AL_REVERB_REFLECTIONS_DELAY), + DECL(AL_REVERB_LATE_REVERB_GAIN), + DECL(AL_REVERB_LATE_REVERB_DELAY), + DECL(AL_REVERB_AIR_ABSORPTION_GAINHF), + DECL(AL_REVERB_ROOM_ROLLOFF_FACTOR), + DECL(AL_REVERB_DECAY_HFLIMIT), + + DECL(AL_CHORUS_WAVEFORM), + DECL(AL_CHORUS_PHASE), + DECL(AL_CHORUS_RATE), + DECL(AL_CHORUS_DEPTH), + DECL(AL_CHORUS_FEEDBACK), + DECL(AL_CHORUS_DELAY), + + DECL(AL_DISTORTION_EDGE), + DECL(AL_DISTORTION_GAIN), + DECL(AL_DISTORTION_LOWPASS_CUTOFF), + DECL(AL_DISTORTION_EQCENTER), + DECL(AL_DISTORTION_EQBANDWIDTH), + + DECL(AL_ECHO_DELAY), + DECL(AL_ECHO_LRDELAY), + DECL(AL_ECHO_DAMPING), + DECL(AL_ECHO_FEEDBACK), + DECL(AL_ECHO_SPREAD), + + DECL(AL_FLANGER_WAVEFORM), + DECL(AL_FLANGER_PHASE), + DECL(AL_FLANGER_RATE), + DECL(AL_FLANGER_DEPTH), + DECL(AL_FLANGER_FEEDBACK), + DECL(AL_FLANGER_DELAY), + + DECL(AL_RING_MODULATOR_FREQUENCY), + DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF), + DECL(AL_RING_MODULATOR_WAVEFORM), + + DECL(AL_COMPRESSOR_ONOFF), + + DECL(AL_EQUALIZER_LOW_GAIN), + DECL(AL_EQUALIZER_LOW_CUTOFF), + DECL(AL_EQUALIZER_MID1_GAIN), + DECL(AL_EQUALIZER_MID1_CENTER), + DECL(AL_EQUALIZER_MID1_WIDTH), + DECL(AL_EQUALIZER_MID2_GAIN), + DECL(AL_EQUALIZER_MID2_CENTER), + DECL(AL_EQUALIZER_MID2_WIDTH), + DECL(AL_EQUALIZER_HIGH_GAIN), + DECL(AL_EQUALIZER_HIGH_CUTOFF), + + DECL(AL_DEDICATED_GAIN), + + { NULL, (ALCenum)0 } +}; +#undef DECL + +static const ALCchar alcNoError[] = "No Error"; +static const ALCchar alcErrInvalidDevice[] = "Invalid Device"; +static const ALCchar alcErrInvalidContext[] = "Invalid Context"; +static const ALCchar alcErrInvalidEnum[] = "Invalid Enum"; +static const ALCchar alcErrInvalidValue[] = "Invalid Value"; +static const ALCchar alcErrOutOfMemory[] = "Out of Memory"; + + +/************************************************ + * Global variables + ************************************************/ + +/* Enumerated device names */ +static const ALCchar alcDefaultName[] = "OpenAL Soft\0"; + +static al_string alcAllDevicesList; +static al_string alcCaptureDeviceList; + +/* Default is always the first in the list */ +static ALCchar *alcDefaultAllDevicesSpecifier; +static ALCchar *alcCaptureDefaultDeviceSpecifier; + +/* Default context extensions */ +static const ALchar alExtList[] = + "AL_EXT_ALAW AL_EXT_BFORMAT AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE " + "AL_EXT_FLOAT32 AL_EXT_IMA4 AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS " + "AL_EXT_MULAW AL_EXT_MULAW_BFORMAT AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET " + "AL_EXT_source_distance_model AL_EXT_SOURCE_RADIUS AL_EXT_STEREO_ANGLES " + "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_deferred_updates " + "AL_SOFT_direct_channels AL_SOFT_gain_clamp_ex AL_SOFT_loop_points " + "AL_SOFT_MSADPCM AL_SOFT_source_latency AL_SOFT_source_length"; + +static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR); + +/* Thread-local current context */ +static altss_t LocalContext; +/* Process-wide current context */ +static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL); + +/* Mixing thread piority level */ +ALint RTPrioLevel; + +FILE *LogFile; +#ifdef _DEBUG +enum LogLevel LogLevel = LogWarning; +#else +enum LogLevel LogLevel = LogError; +#endif + +/* Flag to trap ALC device errors */ +static ALCboolean TrapALCError = ALC_FALSE; + +/* One-time configuration init control */ +static alonce_flag alc_config_once = AL_ONCE_FLAG_INIT; + +/* Default effect that applies to sources that don't have an effect on send 0 */ +static ALeffect DefaultEffect; + +/* Flag to specify if alcSuspendContext/alcProcessContext should defer/process + * updates. + */ +static ALCboolean SuspendDefers = ALC_TRUE; + + +/************************************************ + * ALC information + ************************************************/ +static const ALCchar alcNoDeviceExtList[] = + "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE " + "ALC_EXT_thread_local_context ALC_SOFT_loopback"; +static const ALCchar alcExtensionList[] = + "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE " + "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX " + "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFT_HRTF " + "ALC_SOFT_loopback ALC_SOFT_pause_device"; +static const ALCint alcMajorVersion = 1; +static const ALCint alcMinorVersion = 1; + +static const ALCint alcEFXMajorVersion = 1; +static const ALCint alcEFXMinorVersion = 0; + + +/************************************************ + * Device lists + ************************************************/ +static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL); + +static almtx_t ListLock; +static inline void LockLists(void) +{ + int ret = almtx_lock(&ListLock); + assert(ret == althrd_success); +} +static inline void UnlockLists(void) +{ + int ret = almtx_unlock(&ListLock); + assert(ret == althrd_success); +} + +/************************************************ + * Library initialization + ************************************************/ +#if defined(_WIN32) +static void alc_init(void); +static void alc_deinit(void); +static void alc_deinit_safe(void); + +#ifndef AL_LIBTYPE_STATIC +BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved) +{ + switch(reason) + { + case DLL_PROCESS_ATTACH: + /* Pin the DLL so we won't get unloaded until the process terminates */ + GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (WCHAR*)hModule, &hModule); + alc_init(); + break; + + case DLL_THREAD_DETACH: + break; + + case DLL_PROCESS_DETACH: + if(!lpReserved) + alc_deinit(); + else + alc_deinit_safe(); + break; + } + return TRUE; +} +#elif defined(_MSC_VER) +#pragma section(".CRT$XCU",read) +static void alc_constructor(void); +static void alc_destructor(void); +__declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor; + +static void alc_constructor(void) +{ + atexit(alc_destructor); + alc_init(); +} + +static void alc_destructor(void) +{ + alc_deinit(); +} +#elif defined(HAVE_GCC_DESTRUCTOR) +static void alc_init(void) __attribute__((constructor)); +static void alc_deinit(void) __attribute__((destructor)); +#else +#error "No static initialization available on this platform!" +#endif + +#elif defined(HAVE_GCC_DESTRUCTOR) + +static void alc_init(void) __attribute__((constructor)); +static void alc_deinit(void) __attribute__((destructor)); + +#else +#error "No global initialization available on this platform!" +#endif + +static void ReleaseThreadCtx(void *ptr); +static void alc_init(void) +{ + const char *str; + int ret; + + LogFile = stderr; + + AL_STRING_INIT(alcAllDevicesList); + AL_STRING_INIT(alcCaptureDeviceList); + + str = getenv("__ALSOFT_HALF_ANGLE_CONES"); + if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) + ConeScale *= 0.5f; + + str = getenv("__ALSOFT_REVERSE_Z"); + if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) + ZScale *= -1.0f; + + ret = altss_create(&LocalContext, ReleaseThreadCtx); + assert(ret == althrd_success); + + ret = almtx_init(&ListLock, almtx_recursive); + assert(ret == althrd_success); + + ThunkInit(); +} + +static void alc_initconfig(void) +{ + const char *devs, *str; + ALuint capfilter; + float valf; + int i, n; + + str = getenv("ALSOFT_LOGLEVEL"); + if(str) + { + long lvl = strtol(str, NULL, 0); + if(lvl >= NoLog && lvl <= LogRef) + LogLevel = lvl; + } + + str = getenv("ALSOFT_LOGFILE"); + if(str && str[0]) + { + FILE *logfile = al_fopen(str, "wt"); + if(logfile) LogFile = logfile; + else ERR("Failed to open log file '%s'\n", str); + } + + { + char buf[1024] = ""; + int len = snprintf(buf, sizeof(buf), "%s", BackendList[0].name); + for(i = 1;BackendList[i].name;i++) + len += snprintf(buf+len, sizeof(buf)-len, ", %s", BackendList[i].name); + TRACE("Supported backends: %s\n", buf); + } + ReadALConfig(); + + str = getenv("__ALSOFT_SUSPEND_CONTEXT"); + if(str && *str) + { + if(strcasecmp(str, "ignore") == 0) + { + SuspendDefers = ALC_FALSE; + TRACE("Selected context suspend behavior, \"ignore\"\n"); + } + else + ERR("Unhandled context suspend behavior setting: \"%s\"\n", str); + } + + capfilter = 0; +#if defined(HAVE_SSE4_1) + capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1; +#elif defined(HAVE_SSE3) + capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3; +#elif defined(HAVE_SSE2) + capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2; +#elif defined(HAVE_SSE) + capfilter |= CPU_CAP_SSE; +#endif +#ifdef HAVE_NEON + capfilter |= CPU_CAP_NEON; +#endif + if(ConfigValueStr(NULL, NULL, "disable-cpu-exts", &str)) + { + if(strcasecmp(str, "all") == 0) + capfilter = 0; + else + { + size_t len; + const char *next = str; + + do { + str = next; + while(isspace(str[0])) + str++; + next = strchr(str, ','); + + if(!str[0] || str[0] == ',') + continue; + + len = (next ? ((size_t)(next-str)) : strlen(str)); + while(len > 0 && isspace(str[len-1])) + len--; + if(len == 3 && strncasecmp(str, "sse", len) == 0) + capfilter &= ~CPU_CAP_SSE; + else if(len == 4 && strncasecmp(str, "sse2", len) == 0) + capfilter &= ~CPU_CAP_SSE2; + else if(len == 4 && strncasecmp(str, "sse3", len) == 0) + capfilter &= ~CPU_CAP_SSE3; + else if(len == 6 && strncasecmp(str, "sse4.1", len) == 0) + capfilter &= ~CPU_CAP_SSE4_1; + else if(len == 4 && strncasecmp(str, "neon", len) == 0) + capfilter &= ~CPU_CAP_NEON; + else + WARN("Invalid CPU extension \"%s\"\n", str); + } while(next++); + } + } + FillCPUCaps(capfilter); + +#ifdef _WIN32 + RTPrioLevel = 1; +#else + RTPrioLevel = 0; +#endif + ConfigValueInt(NULL, NULL, "rt-prio", &RTPrioLevel); + + aluInitMixer(); + + str = getenv("ALSOFT_TRAP_ERROR"); + if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) + { + TrapALError = AL_TRUE; + TrapALCError = AL_TRUE; + } + else + { + str = getenv("ALSOFT_TRAP_AL_ERROR"); + if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) + TrapALError = AL_TRUE; + TrapALError = GetConfigValueBool(NULL, NULL, "trap-al-error", TrapALError); + + str = getenv("ALSOFT_TRAP_ALC_ERROR"); + if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) + TrapALCError = ALC_TRUE; + TrapALCError = GetConfigValueBool(NULL, NULL, "trap-alc-error", TrapALCError); + } + + if(ConfigValueFloat(NULL, "reverb", "boost", &valf)) + ReverbBoost *= powf(10.0f, valf / 20.0f); + + EmulateEAXReverb = GetConfigValueBool(NULL, "reverb", "emulate-eax", AL_FALSE); + + if(((devs=getenv("ALSOFT_DRIVERS")) && devs[0]) || + ConfigValueStr(NULL, NULL, "drivers", &devs)) + { + int n; + size_t len; + const char *next = devs; + int endlist, delitem; + + i = 0; + do { + devs = next; + while(isspace(devs[0])) + devs++; + next = strchr(devs, ','); + + delitem = (devs[0] == '-'); + if(devs[0] == '-') devs++; + + if(!devs[0] || devs[0] == ',') + { + endlist = 0; + continue; + } + endlist = 1; + + len = (next ? ((size_t)(next-devs)) : strlen(devs)); + while(len > 0 && isspace(devs[len-1])) + len--; + for(n = i;BackendList[n].name;n++) + { + if(len == strlen(BackendList[n].name) && + strncmp(BackendList[n].name, devs, len) == 0) + { + if(delitem) + { + do { + BackendList[n] = BackendList[n+1]; + ++n; + } while(BackendList[n].name); + } + else + { + struct BackendInfo Bkp = BackendList[n]; + while(n > i) + { + BackendList[n] = BackendList[n-1]; + --n; + } + BackendList[n] = Bkp; + + i++; + } + break; + } + } + } while(next++); + + if(endlist) + { + BackendList[i].name = NULL; + BackendList[i].getFactory = NULL; + BackendList[i].Init = NULL; + BackendList[i].Deinit = NULL; + BackendList[i].Probe = NULL; + } + } + + for(i = 0;(BackendList[i].Init || BackendList[i].getFactory) && (!PlaybackBackend.name || !CaptureBackend.name);i++) + { + if(BackendList[i].getFactory) + { + ALCbackendFactory *factory = BackendList[i].getFactory(); + if(!V0(factory,init)()) + { + WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name); + continue; + } + + TRACE("Initialized backend \"%s\"\n", BackendList[i].name); + if(!PlaybackBackend.name && V(factory,querySupport)(ALCbackend_Playback)) + { + PlaybackBackend = BackendList[i]; + TRACE("Added \"%s\" for playback\n", PlaybackBackend.name); + } + if(!CaptureBackend.name && V(factory,querySupport)(ALCbackend_Capture)) + { + CaptureBackend = BackendList[i]; + TRACE("Added \"%s\" for capture\n", CaptureBackend.name); + } + + continue; + } + + if(!BackendList[i].Init(&BackendList[i].Funcs)) + { + WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name); + continue; + } + + TRACE("Initialized backend \"%s\"\n", BackendList[i].name); + if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name) + { + PlaybackBackend = BackendList[i]; + TRACE("Added \"%s\" for playback\n", PlaybackBackend.name); + } + if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name) + { + CaptureBackend = BackendList[i]; + TRACE("Added \"%s\" for capture\n", CaptureBackend.name); + } + } + { + ALCbackendFactory *factory = ALCloopbackFactory_getFactory(); + V0(factory,init)(); + } + + if(!PlaybackBackend.name) + WARN("No playback backend available!\n"); + if(!CaptureBackend.name) + WARN("No capture backend available!\n"); + + if(ConfigValueStr(NULL, NULL, "excludefx", &str)) + { + size_t len; + const char *next = str; + + do { + str = next; + next = strchr(str, ','); + + if(!str[0] || next == str) + continue; + + len = (next ? ((size_t)(next-str)) : strlen(str)); + for(n = 0;EffectList[n].name;n++) + { + if(len == strlen(EffectList[n].name) && + strncmp(EffectList[n].name, str, len) == 0) + DisabledEffects[EffectList[n].type] = AL_TRUE; + } + } while(next++); + } + + InitEffectFactoryMap(); + + InitEffect(&DefaultEffect); + str = getenv("ALSOFT_DEFAULT_REVERB"); + if((str && str[0]) || ConfigValueStr(NULL, NULL, "default-reverb", &str)) + LoadReverbPreset(str, &DefaultEffect); +} +#define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig) + + +/************************************************ + * Library deinitialization + ************************************************/ +static void alc_cleanup(void) +{ + ALCdevice *dev; + + AL_STRING_DEINIT(alcAllDevicesList); + AL_STRING_DEINIT(alcCaptureDeviceList); + + free(alcDefaultAllDevicesSpecifier); + alcDefaultAllDevicesSpecifier = NULL; + free(alcCaptureDefaultDeviceSpecifier); + alcCaptureDefaultDeviceSpecifier = NULL; + + if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL) + { + ALCuint num = 0; + do { + num++; + } while((dev=dev->next) != NULL); + ERR("%u device%s not closed\n", num, (num>1)?"s":""); + } + + DeinitEffectFactoryMap(); +} + +static void alc_deinit_safe(void) +{ + alc_cleanup(); + + FreeHrtfs(); + FreeALConfig(); + + ThunkExit(); + almtx_destroy(&ListLock); + altss_delete(LocalContext); + + if(LogFile != stderr) + fclose(LogFile); + LogFile = NULL; +} + +static void alc_deinit(void) +{ + int i; + + alc_cleanup(); + + memset(&PlaybackBackend, 0, sizeof(PlaybackBackend)); + memset(&CaptureBackend, 0, sizeof(CaptureBackend)); + + for(i = 0;BackendList[i].Deinit || BackendList[i].getFactory;i++) + { + if(!BackendList[i].getFactory) + BackendList[i].Deinit(); + else + { + ALCbackendFactory *factory = BackendList[i].getFactory(); + V0(factory,deinit)(); + } + } + { + ALCbackendFactory *factory = ALCloopbackFactory_getFactory(); + V0(factory,deinit)(); + } + + alc_deinit_safe(); +} + + +/************************************************ + * Device enumeration + ************************************************/ +static void ProbeDevices(al_string *list, struct BackendInfo *backendinfo, enum DevProbe type) +{ + DO_INITCONFIG(); + + LockLists(); + al_string_clear(list); + + if(backendinfo->Probe) + backendinfo->Probe(type); + else if(backendinfo->getFactory) + { + ALCbackendFactory *factory = backendinfo->getFactory(); + V(factory,probe)(type); + } + + UnlockLists(); +} +static void ProbeAllDevicesList(void) +{ ProbeDevices(&alcAllDevicesList, &PlaybackBackend, ALL_DEVICE_PROBE); } +static void ProbeCaptureDeviceList(void) +{ ProbeDevices(&alcCaptureDeviceList, &CaptureBackend, CAPTURE_DEVICE_PROBE); } + +static void AppendDevice(const ALCchar *name, al_string *devnames) +{ + size_t len = strlen(name); + if(len > 0) + al_string_append_range(devnames, name, name+len+1); +} +void AppendAllDevicesList(const ALCchar *name) +{ AppendDevice(name, &alcAllDevicesList); } +void AppendCaptureDeviceList(const ALCchar *name) +{ AppendDevice(name, &alcCaptureDeviceList); } + + +/************************************************ + * Device format information + ************************************************/ +const ALCchar *DevFmtTypeString(enum DevFmtType type) +{ + switch(type) + { + case DevFmtByte: return "Signed Byte"; + case DevFmtUByte: return "Unsigned Byte"; + case DevFmtShort: return "Signed Short"; + case DevFmtUShort: return "Unsigned Short"; + case DevFmtInt: return "Signed Int"; + case DevFmtUInt: return "Unsigned Int"; + case DevFmtFloat: return "Float"; + } + return "(unknown type)"; +} +const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) +{ + switch(chans) + { + case DevFmtMono: return "Mono"; + case DevFmtStereo: return "Stereo"; + case DevFmtQuad: return "Quadraphonic"; + case DevFmtX51: return "5.1 Surround"; + case DevFmtX51Rear: return "5.1 Surround (Rear)"; + case DevFmtX61: return "6.1 Surround"; + case DevFmtX71: return "7.1 Surround"; + case DevFmtAmbi1: return "Ambisonic (1st Order)"; + case DevFmtAmbi2: return "Ambisonic (2nd Order)"; + case DevFmtAmbi3: return "Ambisonic (3rd Order)"; + } + return "(unknown channels)"; +} + +extern inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type); +ALuint BytesFromDevFmt(enum DevFmtType type) +{ + switch(type) + { + case DevFmtByte: return sizeof(ALbyte); + case DevFmtUByte: return sizeof(ALubyte); + case DevFmtShort: return sizeof(ALshort); + case DevFmtUShort: return sizeof(ALushort); + case DevFmtInt: return sizeof(ALint); + case DevFmtUInt: return sizeof(ALuint); + case DevFmtFloat: return sizeof(ALfloat); + } + return 0; +} +ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) +{ + switch(chans) + { + case DevFmtMono: return 1; + case DevFmtStereo: return 2; + case DevFmtQuad: return 4; + case DevFmtX51: return 6; + case DevFmtX51Rear: return 6; + case DevFmtX61: return 7; + case DevFmtX71: return 8; + case DevFmtAmbi1: return 4; + case DevFmtAmbi2: return 9; + case DevFmtAmbi3: return 16; + } + return 0; +} + +static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans, + enum DevFmtType *type) +{ + static const struct { + ALenum format; + enum DevFmtChannels channels; + enum DevFmtType type; + } list[] = { + { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte }, + { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort }, + { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat }, + + { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte }, + { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort }, + { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat }, + + { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte }, + { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort }, + { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat }, + + { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte }, + { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort }, + { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat }, + + { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte }, + { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort }, + { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat }, + + { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte }, + { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort }, + { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat }, + }; + ALuint i; + + for(i = 0;i < COUNTOF(list);i++) + { + if(list[i].format == format) + { + *chans = list[i].channels; + *type = list[i].type; + return AL_TRUE; + } + } + + return AL_FALSE; +} + +static ALCboolean IsValidALCType(ALCenum type) +{ + switch(type) + { + case ALC_BYTE_SOFT: + case ALC_UNSIGNED_BYTE_SOFT: + case ALC_SHORT_SOFT: + case ALC_UNSIGNED_SHORT_SOFT: + case ALC_INT_SOFT: + case ALC_UNSIGNED_INT_SOFT: + case ALC_FLOAT_SOFT: + return ALC_TRUE; + } + return ALC_FALSE; +} + +static ALCboolean IsValidALCChannels(ALCenum channels) +{ + switch(channels) + { + case ALC_MONO_SOFT: + case ALC_STEREO_SOFT: + case ALC_QUAD_SOFT: + case ALC_5POINT1_SOFT: + case ALC_6POINT1_SOFT: + case ALC_7POINT1_SOFT: + return ALC_TRUE; + } + return ALC_FALSE; +} + + +/************************************************ + * Miscellaneous ALC helpers + ************************************************/ + +extern inline void LockContext(ALCcontext *context); +extern inline void UnlockContext(ALCcontext *context); + +void ALCdevice_Lock(ALCdevice *device) +{ + V0(device->Backend,lock)(); +} + +void ALCdevice_Unlock(ALCdevice *device) +{ + V0(device->Backend,unlock)(); +} + + +/* SetDefaultWFXChannelOrder + * + * Sets the default channel order used by WaveFormatEx. + */ +void SetDefaultWFXChannelOrder(ALCdevice *device) +{ + ALuint i; + + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + device->RealOut.ChannelName[i] = InvalidChannel; + + switch(device->FmtChans) + { + case DevFmtMono: + device->RealOut.ChannelName[0] = FrontCenter; + break; + case DevFmtStereo: + device->RealOut.ChannelName[0] = FrontLeft; + device->RealOut.ChannelName[1] = FrontRight; + break; + case DevFmtQuad: + device->RealOut.ChannelName[0] = FrontLeft; + device->RealOut.ChannelName[1] = FrontRight; + device->RealOut.ChannelName[2] = BackLeft; + device->RealOut.ChannelName[3] = BackRight; + break; + case DevFmtX51: + device->RealOut.ChannelName[0] = FrontLeft; + device->RealOut.ChannelName[1] = FrontRight; + device->RealOut.ChannelName[2] = FrontCenter; + device->RealOut.ChannelName[3] = LFE; + device->RealOut.ChannelName[4] = SideLeft; + device->RealOut.ChannelName[5] = SideRight; + break; + case DevFmtX51Rear: + device->RealOut.ChannelName[0] = FrontLeft; + device->RealOut.ChannelName[1] = FrontRight; + device->RealOut.ChannelName[2] = FrontCenter; + device->RealOut.ChannelName[3] = LFE; + device->RealOut.ChannelName[4] = BackLeft; + device->RealOut.ChannelName[5] = BackRight; + break; + case DevFmtX61: + device->RealOut.ChannelName[0] = FrontLeft; + device->RealOut.ChannelName[1] = FrontRight; + device->RealOut.ChannelName[2] = FrontCenter; + device->RealOut.ChannelName[3] = LFE; + device->RealOut.ChannelName[4] = BackCenter; + device->RealOut.ChannelName[5] = SideLeft; + device->RealOut.ChannelName[6] = SideRight; + break; + case DevFmtX71: + device->RealOut.ChannelName[0] = FrontLeft; + device->RealOut.ChannelName[1] = FrontRight; + device->RealOut.ChannelName[2] = FrontCenter; + device->RealOut.ChannelName[3] = LFE; + device->RealOut.ChannelName[4] = BackLeft; + device->RealOut.ChannelName[5] = BackRight; + device->RealOut.ChannelName[6] = SideLeft; + device->RealOut.ChannelName[7] = SideRight; + break; + case DevFmtAmbi1: + device->RealOut.ChannelName[0] = Aux0; + device->RealOut.ChannelName[1] = Aux1; + device->RealOut.ChannelName[2] = Aux2; + device->RealOut.ChannelName[3] = Aux3; + break; + case DevFmtAmbi2: + device->RealOut.ChannelName[0] = Aux0; + device->RealOut.ChannelName[1] = Aux1; + device->RealOut.ChannelName[2] = Aux2; + device->RealOut.ChannelName[3] = Aux3; + device->RealOut.ChannelName[4] = Aux4; + device->RealOut.ChannelName[5] = Aux5; + device->RealOut.ChannelName[6] = Aux6; + device->RealOut.ChannelName[7] = Aux7; + device->RealOut.ChannelName[8] = Aux8; + break; + case DevFmtAmbi3: + device->RealOut.ChannelName[0] = Aux0; + device->RealOut.ChannelName[1] = Aux1; + device->RealOut.ChannelName[2] = Aux2; + device->RealOut.ChannelName[3] = Aux3; + device->RealOut.ChannelName[4] = Aux4; + device->RealOut.ChannelName[5] = Aux5; + device->RealOut.ChannelName[6] = Aux6; + device->RealOut.ChannelName[7] = Aux7; + device->RealOut.ChannelName[8] = Aux8; + device->RealOut.ChannelName[9] = Aux9; + device->RealOut.ChannelName[10] = Aux10; + device->RealOut.ChannelName[11] = Aux11; + device->RealOut.ChannelName[12] = Aux12; + device->RealOut.ChannelName[13] = Aux13; + device->RealOut.ChannelName[14] = Aux14; + device->RealOut.ChannelName[15] = Aux15; + break; + } +} + +/* SetDefaultChannelOrder + * + * Sets the default channel order used by most non-WaveFormatEx-based APIs. + */ +void SetDefaultChannelOrder(ALCdevice *device) +{ + ALuint i; + + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + device->RealOut.ChannelName[i] = InvalidChannel; + + switch(device->FmtChans) + { + case DevFmtX51Rear: + device->RealOut.ChannelName[0] = FrontLeft; + device->RealOut.ChannelName[1] = FrontRight; + device->RealOut.ChannelName[2] = BackLeft; + device->RealOut.ChannelName[3] = BackRight; + device->RealOut.ChannelName[4] = FrontCenter; + device->RealOut.ChannelName[5] = LFE; + return; + case DevFmtX71: + device->RealOut.ChannelName[0] = FrontLeft; + device->RealOut.ChannelName[1] = FrontRight; + device->RealOut.ChannelName[2] = BackLeft; + device->RealOut.ChannelName[3] = BackRight; + device->RealOut.ChannelName[4] = FrontCenter; + device->RealOut.ChannelName[5] = LFE; + device->RealOut.ChannelName[6] = SideLeft; + device->RealOut.ChannelName[7] = SideRight; + return; + + /* Same as WFX order */ + case DevFmtMono: + case DevFmtStereo: + case DevFmtQuad: + case DevFmtX51: + case DevFmtX61: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + SetDefaultWFXChannelOrder(device); + break; + } +} + +extern inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan); + + +/* ALCcontext_DeferUpdates + * + * Defers/suspends updates for the given context's listener and sources. This + * does *NOT* stop mixing, but rather prevents certain property changes from + * taking effect. + */ +void ALCcontext_DeferUpdates(ALCcontext *context, ALenum type) +{ + ATOMIC_STORE(&context->DeferUpdates, type); +} + +/* ALCcontext_ProcessUpdates + * + * Resumes update processing after being deferred. + */ +void ALCcontext_ProcessUpdates(ALCcontext *context) +{ + ALCdevice *device = context->Device; + + ReadLock(&context->PropLock); + if(ATOMIC_EXCHANGE(ALenum, &context->DeferUpdates, AL_FALSE)) + { + ALsizei pos; + uint updates; + + /* Tell the mixer to stop applying updates, then wait for any active + * updating to finish, before providing updates. + */ + ATOMIC_STORE(&context->HoldUpdates, AL_TRUE); + while(((updates=ReadRef(&context->UpdateCount))&1) != 0) + althrd_yield(); + + UpdateListenerProps(context); + UpdateAllEffectSlotProps(context); + + LockUIntMapRead(&context->SourceMap); + V0(device->Backend,lock)(); + for(pos = 0;pos < context->SourceMap.size;pos++) + { + ALsource *Source = context->SourceMap.values[pos]; + ALenum new_state; + + if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && + Source->OffsetType != AL_NONE) + { + WriteLock(&Source->queue_lock); + ApplyOffset(Source); + WriteUnlock(&Source->queue_lock); + } + + new_state = Source->new_state; + Source->new_state = AL_NONE; + if(new_state) + SetSourceState(Source, context, new_state); + } + V0(device->Backend,unlock)(); + UnlockUIntMapRead(&context->SourceMap); + + UpdateAllSourceProps(context); + + /* Now with all updates declared, let the mixer continue applying them + * so they all happen at once. + */ + ATOMIC_STORE(&context->HoldUpdates, AL_FALSE); + } + ReadUnlock(&context->PropLock); +} + + +/* alcSetError + * + * Stores the latest ALC device error + */ +static void alcSetError(ALCdevice *device, ALCenum errorCode) +{ + if(TrapALCError) + { +#ifdef _WIN32 + /* DebugBreak() will cause an exception if there is no debugger */ + if(IsDebuggerPresent()) + DebugBreak(); +#elif defined(SIGTRAP) + raise(SIGTRAP); +#endif + } + + if(device) + ATOMIC_STORE(&device->LastError, errorCode); + else + ATOMIC_STORE(&LastNullDeviceError, errorCode); +} + + +/* UpdateClockBase + * + * Updates the device's base clock time with however many samples have been + * done. This is used so frequency changes on the device don't cause the time + * to jump forward or back. + */ +static inline void UpdateClockBase(ALCdevice *device) +{ + device->ClockBase += device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency; + device->SamplesDone = 0; +} + +/* UpdateDeviceParams + * + * Updates device parameters according to the attribute list (caller is + * responsible for holding the list lock). + */ +static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) +{ + ALCcontext *context; + enum HrtfRequestMode hrtf_appreq = Hrtf_Default; + enum HrtfRequestMode hrtf_userreq = Hrtf_Default; + enum DevFmtChannels oldChans; + enum DevFmtType oldType; + ALCuint oldFreq; + FPUCtl oldMode; + ALCsizei hrtf_id = -1; + size_t size; + + // Check for attributes + if(device->Type == Loopback) + { + enum { + GotFreq = 1<<0, + GotChans = 1<<1, + GotType = 1<<2, + GotAll = GotFreq|GotChans|GotType + }; + ALCuint freq, numMono, numStereo, numSends; + enum DevFmtChannels schans; + enum DevFmtType stype; + ALCuint attrIdx = 0; + ALCint gotFmt = 0; + + if(!attrList) + { + WARN("Missing attributes for loopback device\n"); + return ALC_INVALID_VALUE; + } + + numMono = device->NumMonoSources; + numStereo = device->NumStereoSources; + numSends = device->NumAuxSends; + schans = device->FmtChans; + stype = device->FmtType; + freq = device->Frequency; + +#define TRACE_ATTR(a, v) TRACE("Loopback %s = %d\n", #a, v) + while(attrList[attrIdx]) + { + if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT) + { + ALCint val = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_FORMAT_CHANNELS_SOFT, val); + if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val)) + return ALC_INVALID_VALUE; + schans = val; + gotFmt |= GotChans; + } + + if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT) + { + ALCint val = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_FORMAT_TYPE_SOFT, val); + if(!IsValidALCType(val) || !BytesFromDevFmt(val)) + return ALC_INVALID_VALUE; + stype = val; + gotFmt |= GotType; + } + + if(attrList[attrIdx] == ALC_FREQUENCY) + { + freq = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_FREQUENCY, freq); + if(freq < MIN_OUTPUT_RATE) + return ALC_INVALID_VALUE; + gotFmt |= GotFreq; + } + + if(attrList[attrIdx] == ALC_STEREO_SOURCES) + { + numStereo = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_STEREO_SOURCES, numStereo); + if(numStereo > device->SourcesMax) + numStereo = device->SourcesMax; + + numMono = device->SourcesMax - numStereo; + } + + if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS) + { + numSends = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends); + } + + if(attrList[attrIdx] == ALC_HRTF_SOFT) + { + TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]); + if(attrList[attrIdx + 1] == ALC_FALSE) + hrtf_appreq = Hrtf_Disable; + else if(attrList[attrIdx + 1] == ALC_TRUE) + hrtf_appreq = Hrtf_Enable; + else + hrtf_appreq = Hrtf_Default; + } + + if(attrList[attrIdx] == ALC_HRTF_ID_SOFT) + { + hrtf_id = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id); + } + + attrIdx += 2; + } +#undef TRACE_ATTR + + if(gotFmt != GotAll) + { + WARN("Missing format for loopback device\n"); + return ALC_INVALID_VALUE; + } + + ConfigValueUInt(NULL, NULL, "sends", &numSends); + numSends = minu(MAX_SENDS, numSends); + + if((device->Flags&DEVICE_RUNNING)) + V0(device->Backend,stop)(); + device->Flags &= ~DEVICE_RUNNING; + + UpdateClockBase(device); + + device->Frequency = freq; + device->FmtChans = schans; + device->FmtType = stype; + device->NumMonoSources = numMono; + device->NumStereoSources = numStereo; + device->NumAuxSends = numSends; + } + else if(attrList && attrList[0]) + { + ALCuint freq, numMono, numStereo, numSends; + ALCuint attrIdx = 0; + + /* If a context is already running on the device, stop playback so the + * device attributes can be updated. */ + if((device->Flags&DEVICE_RUNNING)) + V0(device->Backend,stop)(); + device->Flags &= ~DEVICE_RUNNING; + + freq = device->Frequency; + numMono = device->NumMonoSources; + numStereo = device->NumStereoSources; + numSends = device->NumAuxSends; + +#define TRACE_ATTR(a, v) TRACE("%s = %d\n", #a, v) + while(attrList[attrIdx]) + { + if(attrList[attrIdx] == ALC_FREQUENCY) + { + freq = attrList[attrIdx + 1]; + device->Flags |= DEVICE_FREQUENCY_REQUEST; + TRACE_ATTR(ALC_FREQUENCY, freq); + } + + if(attrList[attrIdx] == ALC_STEREO_SOURCES) + { + numStereo = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_STEREO_SOURCES, numStereo); + if(numStereo > device->SourcesMax) + numStereo = device->SourcesMax; + + numMono = device->SourcesMax - numStereo; + } + + if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS) + { + numSends = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_MAX_AUXILIARY_SENDS, numSends); + } + + if(attrList[attrIdx] == ALC_HRTF_SOFT) + { + TRACE_ATTR(ALC_HRTF_SOFT, attrList[attrIdx + 1]); + if(attrList[attrIdx + 1] == ALC_FALSE) + hrtf_appreq = Hrtf_Disable; + else if(attrList[attrIdx + 1] == ALC_TRUE) + hrtf_appreq = Hrtf_Enable; + else + hrtf_appreq = Hrtf_Default; + } + + if(attrList[attrIdx] == ALC_HRTF_ID_SOFT) + { + hrtf_id = attrList[attrIdx + 1]; + TRACE_ATTR(ALC_HRTF_ID_SOFT, hrtf_id); + } + + attrIdx += 2; + } +#undef TRACE_ATTR + + ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "frequency", &freq); + freq = maxu(freq, MIN_OUTPUT_RATE); + + ConfigValueUInt(al_string_get_cstr(device->DeviceName), NULL, "sends", &numSends); + numSends = minu(MAX_SENDS, numSends); + + UpdateClockBase(device); + + device->UpdateSize = (ALuint64)device->UpdateSize * freq / + device->Frequency; + /* SSE and Neon do best with the update size being a multiple of 4 */ + if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0) + device->UpdateSize = (device->UpdateSize+3)&~3; + + device->Frequency = freq; + device->NumMonoSources = numMono; + device->NumStereoSources = numStereo; + device->NumAuxSends = numSends; + } + + if((device->Flags&DEVICE_RUNNING)) + return ALC_NO_ERROR; + + al_free(device->Uhj_Encoder); + device->Uhj_Encoder = NULL; + + al_free(device->Bs2b); + device->Bs2b = NULL; + + al_free(device->Dry.Buffer); + device->Dry.Buffer = NULL; + device->Dry.NumChannels = 0; + device->FOAOut.Buffer = NULL; + device->FOAOut.NumChannels = 0; + device->RealOut.Buffer = NULL; + device->RealOut.NumChannels = 0; + + UpdateClockBase(device); + + /************************************************************************* + * Update device format request if HRTF is requested + */ + device->Hrtf.Status = ALC_HRTF_DISABLED_SOFT; + if(device->Type != Loopback) + { + const char *hrtf; + if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf", &hrtf)) + { + if(strcasecmp(hrtf, "true") == 0) + hrtf_userreq = Hrtf_Enable; + else if(strcasecmp(hrtf, "false") == 0) + hrtf_userreq = Hrtf_Disable; + else if(strcasecmp(hrtf, "auto") != 0) + ERR("Unexpected hrtf value: %s\n", hrtf); + } + + if(hrtf_userreq == Hrtf_Enable || (hrtf_userreq != Hrtf_Disable && hrtf_appreq == Hrtf_Enable)) + { + if(VECTOR_SIZE(device->Hrtf.List) == 0) + { + VECTOR_DEINIT(device->Hrtf.List); + device->Hrtf.List = EnumerateHrtf(device->DeviceName); + } + if(VECTOR_SIZE(device->Hrtf.List) > 0) + { + device->FmtChans = DevFmtStereo; + if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->Hrtf.List)) + device->Frequency = VECTOR_ELEM(device->Hrtf.List, hrtf_id).hrtf->sampleRate; + else + device->Frequency = VECTOR_ELEM(device->Hrtf.List, 0).hrtf->sampleRate; + device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_FREQUENCY_REQUEST; + } + else + { + hrtf_userreq = Hrtf_Default; + hrtf_appreq = Hrtf_Disable; + device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT; + } + } + } + else if(hrtf_appreq == Hrtf_Enable) + { + size_t i = VECTOR_SIZE(device->Hrtf.List); + /* Loopback device. We don't need to match to a specific HRTF entry + * here. If the requested ID matches, we'll pick that later, if not, + * we'll try to auto-select one anyway. Just make sure one exists + * that'll work. + */ + if(device->FmtChans == DevFmtStereo) + { + if(VECTOR_SIZE(device->Hrtf.List) == 0) + { + VECTOR_DEINIT(device->Hrtf.List); + device->Hrtf.List = EnumerateHrtf(device->DeviceName); + } + for(i = 0;i < VECTOR_SIZE(device->Hrtf.List);i++) + { + const struct Hrtf *hrtf = VECTOR_ELEM(device->Hrtf.List, i).hrtf; + if(hrtf->sampleRate == device->Frequency) + break; + } + } + if(i == VECTOR_SIZE(device->Hrtf.List)) + { + ERR("Requested format not HRTF compatible: %s, %uhz\n", + DevFmtChannelsString(device->FmtChans), device->Frequency); + hrtf_appreq = Hrtf_Disable; + device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT; + } + } + + oldFreq = device->Frequency; + oldChans = device->FmtChans; + oldType = device->FmtType; + + TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u update size x%d\n", + (device->Flags&DEVICE_CHANNELS_REQUEST)?"*":"", DevFmtChannelsString(device->FmtChans), + (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)?"*":"", DevFmtTypeString(device->FmtType), + (device->Flags&DEVICE_FREQUENCY_REQUEST)?"*":"", device->Frequency, + device->UpdateSize, device->NumUpdates + ); + + if(V0(device->Backend,reset)() == ALC_FALSE) + return ALC_INVALID_DEVICE; + + if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST)) + { + ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans), + DevFmtChannelsString(device->FmtChans)); + device->Flags &= ~DEVICE_CHANNELS_REQUEST; + } + if(device->FmtType != oldType && (device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)) + { + ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType), + DevFmtTypeString(device->FmtType)); + device->Flags &= ~DEVICE_SAMPLE_TYPE_REQUEST; + } + if(device->Frequency != oldFreq && (device->Flags&DEVICE_FREQUENCY_REQUEST)) + { + ERR("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency); + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; + } + + if((device->UpdateSize&3) != 0) + { + if((CPUCapFlags&CPU_CAP_SSE)) + WARN("SSE performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize); + if((CPUCapFlags&CPU_CAP_NEON)) + WARN("NEON performs best with multiple of 4 update sizes (%u)\n", device->UpdateSize); + } + + TRACE("Post-reset: %s, %s, %uhz, %u update size x%d\n", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->Frequency, device->UpdateSize, device->NumUpdates + ); + + aluInitRenderer(device, hrtf_id, hrtf_appreq, hrtf_userreq); + + /* Allocate extra channels for any post-filter output. */ + size = device->Dry.NumChannels * sizeof(device->Dry.Buffer[0]); + if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2)) + size += (ChannelsFromDevFmt(device->FmtChans)+4) * sizeof(device->Dry.Buffer[0]); + else if(device->Hrtf.Handle || device->Uhj_Encoder || device->AmbiDecoder) + size += ChannelsFromDevFmt(device->FmtChans) * sizeof(device->Dry.Buffer[0]); + else if(device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + size += 4 * sizeof(device->Dry.Buffer[0]); + device->Dry.Buffer = al_calloc(16, size); + if(!device->Dry.Buffer) + { + ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size); + return ALC_INVALID_DEVICE; + } + + if(device->Hrtf.Handle || device->Uhj_Encoder || device->AmbiDecoder) + { + device->RealOut.Buffer = device->Dry.Buffer + device->Dry.NumChannels; + device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans); + } + else + { + device->RealOut.Buffer = device->Dry.Buffer; + device->RealOut.NumChannels = device->Dry.NumChannels; + } + + if((device->AmbiDecoder && bformatdec_getOrder(device->AmbiDecoder) >= 2) || + (device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)) + { + /* Higher-order rendering requires upsampling first-order content, so + * make sure to mix it separately. + */ + device->FOAOut.Buffer = device->RealOut.Buffer + device->RealOut.NumChannels; + device->FOAOut.NumChannels = 4; + } + else + { + device->FOAOut.Buffer = device->Dry.Buffer; + device->FOAOut.NumChannels = device->Dry.NumChannels; + } + + SetMixerFPUMode(&oldMode); + if(device->DefaultSlot) + { + ALeffectslot *slot = device->DefaultSlot; + ALeffectState *state = slot->Effect.State; + + state->OutBuffer = device->Dry.Buffer; + state->OutChannels = device->Dry.NumChannels; + if(V(state,deviceUpdate)(device) == AL_FALSE) + { + RestoreFPUMode(&oldMode); + return ALC_INVALID_DEVICE; + } + UpdateEffectSlotProps(slot); + } + + context = ATOMIC_LOAD(&device->ContextList); + while(context) + { + ALsizei pos; + + ReadLock(&context->PropLock); + LockUIntMapRead(&context->EffectSlotMap); + for(pos = 0;pos < context->EffectSlotMap.size;pos++) + { + ALeffectslot *slot = context->EffectSlotMap.values[pos]; + ALeffectState *state = slot->Effect.State; + + state->OutBuffer = device->Dry.Buffer; + state->OutChannels = device->Dry.NumChannels; + if(V(state,deviceUpdate)(device) == AL_FALSE) + { + UnlockUIntMapRead(&context->EffectSlotMap); + ReadUnlock(&context->PropLock); + RestoreFPUMode(&oldMode); + return ALC_INVALID_DEVICE; + } + + UpdateEffectSlotProps(slot); + } + UnlockUIntMapRead(&context->EffectSlotMap); + + LockUIntMapRead(&context->SourceMap); + for(pos = 0;pos < context->SourceMap.size;pos++) + { + ALsource *source = context->SourceMap.values[pos]; + ALuint s = device->NumAuxSends; + while(s < MAX_SENDS) + { + if(source->Send[s].Slot) + DecrementRef(&source->Send[s].Slot->ref); + source->Send[s].Slot = NULL; + source->Send[s].Gain = 1.0f; + source->Send[s].GainHF = 1.0f; + source->Send[s].HFReference = LOWPASSFREQREF; + source->Send[s].GainLF = 1.0f; + source->Send[s].LFReference = HIGHPASSFREQREF; + s++; + } + } + UnlockUIntMapRead(&context->SourceMap); + + UpdateAllSourceProps(context); + ReadUnlock(&context->PropLock); + + context = context->next; + } + RestoreFPUMode(&oldMode); + + if(!(device->Flags&DEVICE_PAUSED)) + { + if(V0(device->Backend,start)() == ALC_FALSE) + return ALC_INVALID_DEVICE; + device->Flags |= DEVICE_RUNNING; + } + + return ALC_NO_ERROR; +} + +/* FreeDevice + * + * Frees the device structure, and destroys any objects the app failed to + * delete. Called once there's no more references on the device. + */ +static ALCvoid FreeDevice(ALCdevice *device) +{ + TRACE("%p\n", device); + + V0(device->Backend,close)(); + DELETE_OBJ(device->Backend); + device->Backend = NULL; + + almtx_destroy(&device->BackendLock); + + if(device->DefaultSlot) + { + DeinitEffectSlot(device->DefaultSlot); + device->DefaultSlot = NULL; + } + + if(device->BufferMap.size > 0) + { + WARN("(%p) Deleting %d Buffer%s\n", device, device->BufferMap.size, + (device->BufferMap.size==1)?"":"s"); + ReleaseALBuffers(device); + } + ResetUIntMap(&device->BufferMap); + + if(device->EffectMap.size > 0) + { + WARN("(%p) Deleting %d Effect%s\n", device, device->EffectMap.size, + (device->EffectMap.size==1)?"":"s"); + ReleaseALEffects(device); + } + ResetUIntMap(&device->EffectMap); + + if(device->FilterMap.size > 0) + { + WARN("(%p) Deleting %d Filter%s\n", device, device->FilterMap.size, + (device->FilterMap.size==1)?"":"s"); + ReleaseALFilters(device); + } + ResetUIntMap(&device->FilterMap); + + AL_STRING_DEINIT(device->Hrtf.Name); + FreeHrtfList(&device->Hrtf.List); + + al_free(device->Bs2b); + device->Bs2b = NULL; + + al_free(device->Uhj_Encoder); + device->Uhj_Encoder = NULL; + + bformatdec_free(device->AmbiDecoder); + device->AmbiDecoder = NULL; + + ambiup_free(device->AmbiUp); + device->AmbiUp = NULL; + + AL_STRING_DEINIT(device->DeviceName); + + al_free(device->Dry.Buffer); + device->Dry.Buffer = NULL; + device->Dry.NumChannels = 0; + device->FOAOut.Buffer = NULL; + device->FOAOut.NumChannels = 0; + device->RealOut.Buffer = NULL; + device->RealOut.NumChannels = 0; + + al_free(device); +} + + +void ALCdevice_IncRef(ALCdevice *device) +{ + uint ref; + ref = IncrementRef(&device->ref); + TRACEREF("%p increasing refcount to %u\n", device, ref); +} + +void ALCdevice_DecRef(ALCdevice *device) +{ + uint ref; + ref = DecrementRef(&device->ref); + TRACEREF("%p decreasing refcount to %u\n", device, ref); + if(ref == 0) FreeDevice(device); +} + +/* VerifyDevice + * + * Checks if the device handle is valid, and increments its ref count if so. + */ +static ALCboolean VerifyDevice(ALCdevice **device) +{ + ALCdevice *tmpDevice; + + LockLists(); + tmpDevice = ATOMIC_LOAD(&DeviceList); + while(tmpDevice) + { + if(tmpDevice == *device) + { + ALCdevice_IncRef(tmpDevice); + UnlockLists(); + return ALC_TRUE; + } + tmpDevice = tmpDevice->next; + } + UnlockLists(); + + *device = NULL; + return ALC_FALSE; +} + + +/* InitContext + * + * Initializes context fields + */ +static ALvoid InitContext(ALCcontext *Context) +{ + ALlistener *listener = Context->Listener; + + //Initialise listener + listener->Gain = 1.0f; + listener->MetersPerUnit = 1.0f; + listener->Position[0] = 0.0f; + listener->Position[1] = 0.0f; + listener->Position[2] = 0.0f; + listener->Velocity[0] = 0.0f; + listener->Velocity[1] = 0.0f; + listener->Velocity[2] = 0.0f; + listener->Forward[0] = 0.0f; + listener->Forward[1] = 0.0f; + listener->Forward[2] = -1.0f; + listener->Up[0] = 0.0f; + listener->Up[1] = 1.0f; + listener->Up[2] = 0.0f; + + aluMatrixfSet(&listener->Params.Matrix, + 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 + ); + aluVectorSet(&listener->Params.Velocity, 0.0f, 0.0f, 0.0f, 0.0f); + listener->Params.Gain = 1.0f; + listener->Params.MetersPerUnit = 1.0f; + listener->Params.DopplerFactor = 1.0f; + listener->Params.SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC; + + ATOMIC_INIT(&listener->Update, NULL); + ATOMIC_INIT(&listener->FreeList, NULL); + + //Validate Context + InitRef(&Context->UpdateCount, 0); + ATOMIC_INIT(&Context->HoldUpdates, AL_FALSE); + Context->GainBoost = 1.0f; + RWLockInit(&Context->PropLock); + ATOMIC_INIT(&Context->LastError, AL_NO_ERROR); + InitUIntMap(&Context->SourceMap, Context->Device->SourcesMax); + InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax); + + //Set globals + Context->DistanceModel = DefaultDistanceModel; + Context->SourceDistanceModel = AL_FALSE; + Context->DopplerFactor = 1.0f; + Context->DopplerVelocity = 1.0f; + Context->SpeedOfSound = SPEEDOFSOUNDMETRESPERSEC; + ATOMIC_INIT(&Context->DeferUpdates, AL_FALSE); + + Context->ExtensionList = alExtList; +} + + +/* FreeContext + * + * Cleans up the context, and destroys any remaining objects the app failed to + * delete. Called once there's no more references on the context. + */ +static void FreeContext(ALCcontext *context) +{ + ALlistener *listener = context->Listener; + struct ALlistenerProps *lprops; + size_t count; + + TRACE("%p\n", context); + + if(context->SourceMap.size > 0) + { + WARN("(%p) Deleting %d Source%s\n", context, context->SourceMap.size, + (context->SourceMap.size==1)?"":"s"); + ReleaseALSources(context); + } + ResetUIntMap(&context->SourceMap); + + if(context->EffectSlotMap.size > 0) + { + WARN("(%p) Deleting %d AuxiliaryEffectSlot%s\n", context, context->EffectSlotMap.size, + (context->EffectSlotMap.size==1)?"":"s"); + ReleaseALAuxiliaryEffectSlots(context); + } + ResetUIntMap(&context->EffectSlotMap); + + al_free(context->Voices); + context->Voices = NULL; + context->VoiceCount = 0; + context->MaxVoices = 0; + + if((lprops=ATOMIC_LOAD(&listener->Update, almemory_order_acquire)) != NULL) + { + TRACE("Freed unapplied listener update %p\n", lprops); + al_free(lprops); + } + count = 0; + lprops = ATOMIC_LOAD(&listener->FreeList, almemory_order_consume); + while(lprops) + { + struct ALlistenerProps *next = ATOMIC_LOAD(&lprops->next, almemory_order_consume); + al_free(lprops); + lprops = next; + ++count; + } + TRACE("Freed "SZFMT" listener property object%s\n", count, (count==1)?"":"s"); + + ALCdevice_DecRef(context->Device); + context->Device = NULL; + + //Invalidate context + memset(context, 0, sizeof(ALCcontext)); + al_free(context); +} + +/* ReleaseContext + * + * Removes the context reference from the given device and removes it from + * being current on the running thread or globally. + */ +static void ReleaseContext(ALCcontext *context, ALCdevice *device) +{ + ALCcontext *nextctx; + ALCcontext *origctx; + + if(altss_get(LocalContext) == context) + { + WARN("%p released while current on thread\n", context); + altss_set(LocalContext, NULL); + ALCcontext_DecRef(context); + } + + origctx = context; + if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL)) + ALCcontext_DecRef(context); + + ALCdevice_Lock(device); + origctx = context; + nextctx = context->next; + if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx)) + { + ALCcontext *list; + do { + list = origctx; + origctx = context; + } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx)); + } + ALCdevice_Unlock(device); + + ALCcontext_DecRef(context); +} + +void ALCcontext_IncRef(ALCcontext *context) +{ + uint ref = IncrementRef(&context->ref); + TRACEREF("%p increasing refcount to %u\n", context, ref); +} + +void ALCcontext_DecRef(ALCcontext *context) +{ + uint ref = DecrementRef(&context->ref); + TRACEREF("%p decreasing refcount to %u\n", context, ref); + if(ref == 0) FreeContext(context); +} + +static void ReleaseThreadCtx(void *ptr) +{ + ALCcontext *context = ptr; + uint ref = DecrementRef(&context->ref); + TRACEREF("%p decreasing refcount to %u\n", context, ref); + ERR("Context %p current for thread being destroyed, possible leak!\n", context); +} + +/* VerifyContext + * + * Checks that the given context is valid, and increments its reference count. + */ +static ALCboolean VerifyContext(ALCcontext **context) +{ + ALCdevice *dev; + + LockLists(); + dev = ATOMIC_LOAD(&DeviceList); + while(dev) + { + ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList); + while(ctx) + { + if(ctx == *context) + { + ALCcontext_IncRef(ctx); + UnlockLists(); + return ALC_TRUE; + } + ctx = ctx->next; + } + dev = dev->next; + } + UnlockLists(); + + *context = NULL; + return ALC_FALSE; +} + + +/* GetContextRef + * + * Returns the currently active context for this thread, and adds a reference + * without locking it. + */ +ALCcontext *GetContextRef(void) +{ + ALCcontext *context; + + context = altss_get(LocalContext); + if(context) + ALCcontext_IncRef(context); + else + { + LockLists(); + context = ATOMIC_LOAD(&GlobalContext); + if(context) + ALCcontext_IncRef(context); + UnlockLists(); + } + + return context; +} + + +/************************************************ + * Standard ALC functions + ************************************************/ + +/* alcGetError + * + * Return last ALC generated error code for the given device +*/ +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) +{ + ALCenum errorCode; + + if(VerifyDevice(&device)) + { + errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR); + ALCdevice_DecRef(device); + } + else + errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR); + + return errorCode; +} + + +/* alcSuspendContext + * + * Suspends updates for the given context + */ +ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *context) +{ + if(!SuspendDefers) + return; + + if(!VerifyContext(&context)) + alcSetError(NULL, ALC_INVALID_CONTEXT); + else + { + ALCcontext_DeferUpdates(context, DeferAllowPlay); + ALCcontext_DecRef(context); + } +} + +/* alcProcessContext + * + * Resumes processing updates for the given context + */ +ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *context) +{ + if(!SuspendDefers) + return; + + if(!VerifyContext(&context)) + alcSetError(NULL, ALC_INVALID_CONTEXT); + else + { + ALCcontext_ProcessUpdates(context); + ALCcontext_DecRef(context); + } +} + + +/* alcGetString + * + * Returns information about the device, and error strings + */ +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param) +{ + const ALCchar *value = NULL; + + switch(param) + { + case ALC_NO_ERROR: + value = alcNoError; + break; + + case ALC_INVALID_ENUM: + value = alcErrInvalidEnum; + break; + + case ALC_INVALID_VALUE: + value = alcErrInvalidValue; + break; + + case ALC_INVALID_DEVICE: + value = alcErrInvalidDevice; + break; + + case ALC_INVALID_CONTEXT: + value = alcErrInvalidContext; + break; + + case ALC_OUT_OF_MEMORY: + value = alcErrOutOfMemory; + break; + + case ALC_DEVICE_SPECIFIER: + value = alcDefaultName; + break; + + case ALC_ALL_DEVICES_SPECIFIER: + if(VerifyDevice(&Device)) + { + value = al_string_get_cstr(Device->DeviceName); + ALCdevice_DecRef(Device); + } + else + { + ProbeAllDevicesList(); + value = al_string_get_cstr(alcAllDevicesList); + } + break; + + case ALC_CAPTURE_DEVICE_SPECIFIER: + if(VerifyDevice(&Device)) + { + value = al_string_get_cstr(Device->DeviceName); + ALCdevice_DecRef(Device); + } + else + { + ProbeCaptureDeviceList(); + value = al_string_get_cstr(alcCaptureDeviceList); + } + break; + + /* Default devices are always first in the list */ + case ALC_DEFAULT_DEVICE_SPECIFIER: + value = alcDefaultName; + break; + + case ALC_DEFAULT_ALL_DEVICES_SPECIFIER: + if(al_string_empty(alcAllDevicesList)) + ProbeAllDevicesList(); + + VerifyDevice(&Device); + + free(alcDefaultAllDevicesSpecifier); + alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList)); + if(!alcDefaultAllDevicesSpecifier) + alcSetError(Device, ALC_OUT_OF_MEMORY); + + value = alcDefaultAllDevicesSpecifier; + if(Device) ALCdevice_DecRef(Device); + break; + + case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: + if(al_string_empty(alcCaptureDeviceList)) + ProbeCaptureDeviceList(); + + VerifyDevice(&Device); + + free(alcCaptureDefaultDeviceSpecifier); + alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcCaptureDeviceList)); + if(!alcCaptureDefaultDeviceSpecifier) + alcSetError(Device, ALC_OUT_OF_MEMORY); + + value = alcCaptureDefaultDeviceSpecifier; + if(Device) ALCdevice_DecRef(Device); + break; + + case ALC_EXTENSIONS: + if(!VerifyDevice(&Device)) + value = alcNoDeviceExtList; + else + { + value = alcExtensionList; + ALCdevice_DecRef(Device); + } + break; + + case ALC_HRTF_SPECIFIER_SOFT: + if(!VerifyDevice(&Device)) + alcSetError(NULL, ALC_INVALID_DEVICE); + else + { + almtx_lock(&Device->BackendLock); + value = (Device->Hrtf.Handle ? al_string_get_cstr(Device->Hrtf.Name) : ""); + almtx_unlock(&Device->BackendLock); + ALCdevice_DecRef(Device); + } + break; + + default: + VerifyDevice(&Device); + alcSetError(Device, ALC_INVALID_ENUM); + if(Device) ALCdevice_DecRef(Device); + break; + } + + return value; +} + + +static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) +{ + ALCsizei i; + + if(size <= 0 || values == NULL) + { + alcSetError(device, ALC_INVALID_VALUE); + return 0; + } + + if(!device) + { + switch(param) + { + case ALC_MAJOR_VERSION: + values[0] = alcMajorVersion; + return 1; + case ALC_MINOR_VERSION: + values[0] = alcMinorVersion; + return 1; + + case ALC_ATTRIBUTES_SIZE: + case ALC_ALL_ATTRIBUTES: + case ALC_FREQUENCY: + case ALC_REFRESH: + case ALC_SYNC: + case ALC_MONO_SOURCES: + case ALC_STEREO_SOURCES: + case ALC_CAPTURE_SAMPLES: + case ALC_FORMAT_CHANNELS_SOFT: + case ALC_FORMAT_TYPE_SOFT: + alcSetError(NULL, ALC_INVALID_DEVICE); + return 0; + + default: + alcSetError(NULL, ALC_INVALID_ENUM); + return 0; + } + return 0; + } + + if(device->Type == Capture) + { + switch(param) + { + case ALC_CAPTURE_SAMPLES: + almtx_lock(&device->BackendLock); + values[0] = V0(device->Backend,availableSamples)(); + almtx_unlock(&device->BackendLock); + return 1; + + case ALC_CONNECTED: + values[0] = device->Connected; + return 1; + + default: + alcSetError(device, ALC_INVALID_ENUM); + return 0; + } + return 0; + } + + /* render device */ + switch(param) + { + case ALC_MAJOR_VERSION: + values[0] = alcMajorVersion; + return 1; + + case ALC_MINOR_VERSION: + values[0] = alcMinorVersion; + return 1; + + case ALC_EFX_MAJOR_VERSION: + values[0] = alcEFXMajorVersion; + return 1; + + case ALC_EFX_MINOR_VERSION: + values[0] = alcEFXMinorVersion; + return 1; + + case ALC_ATTRIBUTES_SIZE: + values[0] = 17; + return 1; + + case ALC_ALL_ATTRIBUTES: + if(size < 17) + { + alcSetError(device, ALC_INVALID_VALUE); + return 0; + } + + i = 0; + almtx_lock(&device->BackendLock); + values[i++] = ALC_FREQUENCY; + values[i++] = device->Frequency; + + if(device->Type != Loopback) + { + values[i++] = ALC_REFRESH; + values[i++] = device->Frequency / device->UpdateSize; + + values[i++] = ALC_SYNC; + values[i++] = ALC_FALSE; + } + else + { + values[i++] = ALC_FORMAT_CHANNELS_SOFT; + values[i++] = device->FmtChans; + + values[i++] = ALC_FORMAT_TYPE_SOFT; + values[i++] = device->FmtType; + } + + values[i++] = ALC_MONO_SOURCES; + values[i++] = device->NumMonoSources; + + values[i++] = ALC_STEREO_SOURCES; + values[i++] = device->NumStereoSources; + + values[i++] = ALC_MAX_AUXILIARY_SENDS; + values[i++] = device->NumAuxSends; + + values[i++] = ALC_HRTF_SOFT; + values[i++] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE); + + values[i++] = ALC_HRTF_STATUS_SOFT; + values[i++] = device->Hrtf.Status; + almtx_unlock(&device->BackendLock); + + values[i++] = 0; + return i; + + case ALC_FREQUENCY: + values[0] = device->Frequency; + return 1; + + case ALC_REFRESH: + if(device->Type == Loopback) + { + alcSetError(device, ALC_INVALID_DEVICE); + return 0; + } + almtx_lock(&device->BackendLock); + values[0] = device->Frequency / device->UpdateSize; + almtx_unlock(&device->BackendLock); + return 1; + + case ALC_SYNC: + if(device->Type == Loopback) + { + alcSetError(device, ALC_INVALID_DEVICE); + return 0; + } + values[0] = ALC_FALSE; + return 1; + + case ALC_FORMAT_CHANNELS_SOFT: + if(device->Type != Loopback) + { + alcSetError(device, ALC_INVALID_DEVICE); + return 0; + } + values[0] = device->FmtChans; + return 1; + + case ALC_FORMAT_TYPE_SOFT: + if(device->Type != Loopback) + { + alcSetError(device, ALC_INVALID_DEVICE); + return 0; + } + values[0] = device->FmtType; + return 1; + + case ALC_MONO_SOURCES: + values[0] = device->NumMonoSources; + return 1; + + case ALC_STEREO_SOURCES: + values[0] = device->NumStereoSources; + return 1; + + case ALC_MAX_AUXILIARY_SENDS: + values[0] = device->NumAuxSends; + return 1; + + case ALC_CONNECTED: + values[0] = device->Connected; + return 1; + + case ALC_HRTF_SOFT: + values[0] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE); + return 1; + + case ALC_HRTF_STATUS_SOFT: + values[0] = device->Hrtf.Status; + return 1; + + case ALC_NUM_HRTF_SPECIFIERS_SOFT: + almtx_lock(&device->BackendLock); + FreeHrtfList(&device->Hrtf.List); + device->Hrtf.List = EnumerateHrtf(device->DeviceName); + values[0] = (ALCint)VECTOR_SIZE(device->Hrtf.List); + almtx_unlock(&device->BackendLock); + return 1; + + default: + alcSetError(device, ALC_INVALID_ENUM); + return 0; + } + return 0; +} + +/* alcGetIntegerv + * + * Returns information about the device and the version of OpenAL + */ +ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) +{ + VerifyDevice(&device); + if(size <= 0 || values == NULL) + alcSetError(device, ALC_INVALID_VALUE); + else + GetIntegerv(device, param, size, values); + if(device) ALCdevice_DecRef(device); +} + +ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALCsizei size, ALCint64SOFT *values) +{ + ALCint *ivals; + ALsizei i; + + VerifyDevice(&device); + if(size <= 0 || values == NULL) + alcSetError(device, ALC_INVALID_VALUE); + else if(!device || device->Type == Capture) + { + ivals = malloc(size * sizeof(ALCint)); + size = GetIntegerv(device, pname, size, ivals); + for(i = 0;i < size;i++) + values[i] = ivals[i]; + free(ivals); + } + else /* render device */ + { + ClockLatency clock; + ALuint64 basecount; + ALuint samplecount; + ALuint refcount; + + switch(pname) + { + case ALC_ATTRIBUTES_SIZE: + *values = 21; + break; + + case ALC_ALL_ATTRIBUTES: + if(size < 21) + alcSetError(device, ALC_INVALID_VALUE); + else + { + i = 0; + almtx_lock(&device->BackendLock); + values[i++] = ALC_FREQUENCY; + values[i++] = device->Frequency; + + if(device->Type != Loopback) + { + values[i++] = ALC_REFRESH; + values[i++] = device->Frequency / device->UpdateSize; + + values[i++] = ALC_SYNC; + values[i++] = ALC_FALSE; + } + else + { + values[i++] = ALC_FORMAT_CHANNELS_SOFT; + values[i++] = device->FmtChans; + + values[i++] = ALC_FORMAT_TYPE_SOFT; + values[i++] = device->FmtType; + } + + values[i++] = ALC_MONO_SOURCES; + values[i++] = device->NumMonoSources; + + values[i++] = ALC_STEREO_SOURCES; + values[i++] = device->NumStereoSources; + + values[i++] = ALC_MAX_AUXILIARY_SENDS; + values[i++] = device->NumAuxSends; + + values[i++] = ALC_HRTF_SOFT; + values[i++] = (device->Hrtf.Handle ? ALC_TRUE : ALC_FALSE); + + values[i++] = ALC_HRTF_STATUS_SOFT; + values[i++] = device->Hrtf.Status; + + clock = V0(device->Backend,getClockLatency)(); + values[i++] = ALC_DEVICE_CLOCK_SOFT; + values[i++] = clock.ClockTime; + + values[i++] = ALC_DEVICE_LATENCY_SOFT; + values[i++] = clock.Latency; + almtx_unlock(&device->BackendLock); + + values[i++] = 0; + } + break; + + case ALC_DEVICE_CLOCK_SOFT: + almtx_lock(&device->BackendLock); + do { + while(((refcount=ReadRef(&device->MixCount))&1) != 0) + althrd_yield(); + basecount = device->ClockBase; + samplecount = device->SamplesDone; + } while(refcount != ReadRef(&device->MixCount)); + *values = basecount + (samplecount*DEVICE_CLOCK_RES/device->Frequency); + almtx_unlock(&device->BackendLock); + break; + + case ALC_DEVICE_LATENCY_SOFT: + { + almtx_lock(&device->BackendLock); + clock = V0(device->Backend,getClockLatency)(); + almtx_unlock(&device->BackendLock); + *values = clock.Latency; + } + break; + + case ALC_DEVICE_CLOCK_LATENCY_SOFT: + if(size < 2) + alcSetError(device, ALC_INVALID_VALUE); + else + { + ClockLatency clock; + almtx_lock(&device->BackendLock); + clock = V0(device->Backend,getClockLatency)(); + almtx_unlock(&device->BackendLock); + values[0] = clock.ClockTime; + values[1] = clock.Latency; + } + break; + + default: + ivals = malloc(size * sizeof(ALCint)); + size = GetIntegerv(device, pname, size, ivals); + for(i = 0;i < size;i++) + values[i] = ivals[i]; + free(ivals); + break; + } + } + if(device) + ALCdevice_DecRef(device); +} + + +/* alcIsExtensionPresent + * + * Determines if there is support for a particular extension + */ +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName) +{ + ALCboolean bResult = ALC_FALSE; + + VerifyDevice(&device); + + if(!extName) + alcSetError(device, ALC_INVALID_VALUE); + else + { + size_t len = strlen(extName); + const char *ptr = (device ? alcExtensionList : alcNoDeviceExtList); + while(ptr && *ptr) + { + if(strncasecmp(ptr, extName, len) == 0 && + (ptr[len] == '\0' || isspace(ptr[len]))) + { + bResult = ALC_TRUE; + break; + } + if((ptr=strchr(ptr, ' ')) != NULL) + { + do { + ++ptr; + } while(isspace(*ptr)); + } + } + } + if(device) + ALCdevice_DecRef(device); + return bResult; +} + + +/* alcGetProcAddress + * + * Retrieves the function address for a particular extension function + */ +ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName) +{ + ALCvoid *ptr = NULL; + + if(!funcName) + { + VerifyDevice(&device); + alcSetError(device, ALC_INVALID_VALUE); + if(device) ALCdevice_DecRef(device); + } + else + { + ALsizei i = 0; + while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName, funcName) != 0) + i++; + ptr = alcFunctions[i].address; + } + + return ptr; +} + + +/* alcGetEnumValue + * + * Get the value for a particular ALC enumeration name + */ +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName) +{ + ALCenum val = 0; + + if(!enumName) + { + VerifyDevice(&device); + alcSetError(device, ALC_INVALID_VALUE); + if(device) ALCdevice_DecRef(device); + } + else + { + ALsizei i = 0; + while(enumeration[i].enumName && strcmp(enumeration[i].enumName, enumName) != 0) + i++; + val = enumeration[i].value; + } + + return val; +} + + +/* alcCreateContext + * + * Create and attach a context to the given device. + */ +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList) +{ + ALCcontext *ALContext; + ALfloat valf; + ALCenum err; + + LockLists(); + if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected) + { + UnlockLists(); + alcSetError(device, ALC_INVALID_DEVICE); + if(device) ALCdevice_DecRef(device); + return NULL; + } + almtx_lock(&device->BackendLock); + UnlockLists(); + + ATOMIC_STORE(&device->LastError, ALC_NO_ERROR); + + ALContext = al_calloc(16, sizeof(ALCcontext)+sizeof(ALlistener)); + if(ALContext) + { + InitRef(&ALContext->ref, 1); + ALContext->Listener = (ALlistener*)ALContext->_listener_mem; + + ATOMIC_INIT(&ALContext->ActiveAuxSlotList, NULL); + + ALContext->VoiceCount = 0; + ALContext->MaxVoices = 256; + ALContext->Voices = al_calloc(16, ALContext->MaxVoices * sizeof(ALContext->Voices[0])); + } + if(!ALContext || !ALContext->Voices) + { + almtx_unlock(&device->BackendLock); + + if(ALContext) + { + al_free(ALContext->Voices); + ALContext->Voices = NULL; + + al_free(ALContext); + ALContext = NULL; + } + + alcSetError(device, ALC_OUT_OF_MEMORY); + ALCdevice_DecRef(device); + return NULL; + } + + if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR) + { + almtx_unlock(&device->BackendLock); + + al_free(ALContext->Voices); + ALContext->Voices = NULL; + + al_free(ALContext); + ALContext = NULL; + + alcSetError(device, err); + if(err == ALC_INVALID_DEVICE) + { + V0(device->Backend,lock)(); + aluHandleDisconnect(device); + V0(device->Backend,unlock)(); + } + ALCdevice_DecRef(device); + return NULL; + } + + ALContext->Device = device; + ALCdevice_IncRef(device); + InitContext(ALContext); + + if(ConfigValueFloat(al_string_get_cstr(device->DeviceName), NULL, "volume-adjust", &valf)) + { + if(!isfinite(valf)) + ERR("volume-adjust must be finite: %f\n", valf); + else + { + ALfloat db = clampf(valf, -24.0f, 24.0f); + if(db != valf) + WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f); + ALContext->GainBoost = powf(10.0f, db/20.0f); + TRACE("volume-adjust gain: %f\n", ALContext->GainBoost); + } + } + UpdateListenerProps(ALContext); + + { + ALCcontext *head = ATOMIC_LOAD(&device->ContextList); + do { + ALContext->next = head; + } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext)); + } + almtx_unlock(&device->BackendLock); + + ALCdevice_DecRef(device); + + TRACE("Created context %p\n", ALContext); + return ALContext; +} + +/* alcDestroyContext + * + * Remove a context from its device + */ +ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context) +{ + ALCdevice *Device; + + LockLists(); + /* alcGetContextsDevice sets an error for invalid contexts */ + Device = alcGetContextsDevice(context); + if(Device) + { + almtx_lock(&Device->BackendLock); + ReleaseContext(context, Device); + if(!ATOMIC_LOAD(&Device->ContextList)) + { + V0(Device->Backend,stop)(); + Device->Flags &= ~DEVICE_RUNNING; + } + almtx_unlock(&Device->BackendLock); + } + UnlockLists(); +} + + +/* alcGetCurrentContext + * + * Returns the currently active context on the calling thread + */ +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) +{ + ALCcontext *Context = altss_get(LocalContext); + if(!Context) Context = ATOMIC_LOAD(&GlobalContext); + return Context; +} + +/* alcGetThreadContext + * + * Returns the currently active thread-local context + */ +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) +{ + return altss_get(LocalContext); +} + + +/* alcMakeContextCurrent + * + * Makes the given context the active process-wide context, and removes the + * thread-local context for the calling thread. + */ +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) +{ + /* context must be valid or NULL */ + if(context && !VerifyContext(&context)) + { + alcSetError(NULL, ALC_INVALID_CONTEXT); + return ALC_FALSE; + } + /* context's reference count is already incremented */ + context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context); + if(context) ALCcontext_DecRef(context); + + if((context=altss_get(LocalContext)) != NULL) + { + altss_set(LocalContext, NULL); + ALCcontext_DecRef(context); + } + + return ALC_TRUE; +} + +/* alcSetThreadContext + * + * Makes the given context the active context for the current thread + */ +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) +{ + ALCcontext *old; + + /* context must be valid or NULL */ + if(context && !VerifyContext(&context)) + { + alcSetError(NULL, ALC_INVALID_CONTEXT); + return ALC_FALSE; + } + /* context's reference count is already incremented */ + old = altss_get(LocalContext); + altss_set(LocalContext, context); + if(old) ALCcontext_DecRef(old); + + return ALC_TRUE; +} + + +/* alcGetContextsDevice + * + * Returns the device that a particular context is attached to + */ +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *Context) +{ + ALCdevice *Device; + + if(!VerifyContext(&Context)) + { + alcSetError(NULL, ALC_INVALID_CONTEXT); + return NULL; + } + Device = Context->Device; + ALCcontext_DecRef(Context); + + return Device; +} + + +/* alcOpenDevice + * + * Opens the named device. + */ +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) +{ + const ALCchar *fmt; + ALCdevice *device; + ALCenum err; + + DO_INITCONFIG(); + + if(!PlaybackBackend.name) + { + alcSetError(NULL, ALC_INVALID_VALUE); + return NULL; + } + + if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0 +#ifdef _WIN32 + /* Some old Windows apps hardcode these expecting OpenAL to use a + * specific audio API, even when they're not enumerated. Creative's + * router effectively ignores them too. + */ + || strcasecmp(deviceName, "DirectSound3D") == 0 || strcasecmp(deviceName, "DirectSound") == 0 + || strcasecmp(deviceName, "MMSYSTEM") == 0 +#endif + )) + deviceName = NULL; + + device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot)); + if(!device) + { + alcSetError(NULL, ALC_OUT_OF_MEMORY); + return NULL; + } + + //Validate device + InitRef(&device->ref, 1); + device->Connected = ALC_TRUE; + device->Type = Playback; + ATOMIC_INIT(&device->LastError, ALC_NO_ERROR); + + device->Flags = 0; + device->Bs2b = NULL; + device->Uhj_Encoder = NULL; + VECTOR_INIT(device->Hrtf.List); + AL_STRING_INIT(device->Hrtf.Name); + device->Render_Mode = NormalRender; + AL_STRING_INIT(device->DeviceName); + device->Dry.Buffer = NULL; + device->Dry.NumChannels = 0; + device->FOAOut.Buffer = NULL; + device->FOAOut.NumChannels = 0; + device->RealOut.Buffer = NULL; + device->RealOut.NumChannels = 0; + + ATOMIC_INIT(&device->ContextList, NULL); + + device->ClockBase = 0; + device->SamplesDone = 0; + + device->SourcesMax = 256; + device->AuxiliaryEffectSlotMax = 4; + device->NumAuxSends = MAX_SENDS; + + InitUIntMap(&device->BufferMap, ~0); + InitUIntMap(&device->EffectMap, ~0); + InitUIntMap(&device->FilterMap, ~0); + + //Set output format + device->FmtChans = DevFmtChannelsDefault; + device->FmtType = DevFmtTypeDefault; + device->Frequency = DEFAULT_OUTPUT_RATE; + device->IsHeadphones = AL_FALSE; + device->AmbiFmt = AmbiFormat_Default; + device->NumUpdates = 4; + device->UpdateSize = 1024; + + if(!PlaybackBackend.getFactory) + device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs, + ALCbackend_Playback); + else + { + ALCbackendFactory *factory = PlaybackBackend.getFactory(); + device->Backend = V(factory,createBackend)(device, ALCbackend_Playback); + } + if(!device->Backend) + { + al_free(device); + alcSetError(NULL, ALC_OUT_OF_MEMORY); + return NULL; + } + + + if(ConfigValueStr(deviceName, NULL, "channels", &fmt)) + { + static const struct { + const char name[16]; + enum DevFmtChannels chans; + } chanlist[] = { + { "mono", DevFmtMono }, + { "stereo", DevFmtStereo }, + { "quad", DevFmtQuad }, + { "surround51", DevFmtX51 }, + { "surround61", DevFmtX61 }, + { "surround71", DevFmtX71 }, + { "surround51rear", DevFmtX51Rear }, + { "ambi1", DevFmtAmbi1 }, + { "ambi2", DevFmtAmbi2 }, + { "ambi3", DevFmtAmbi3 }, + }; + size_t i; + + for(i = 0;i < COUNTOF(chanlist);i++) + { + if(strcasecmp(chanlist[i].name, fmt) == 0) + { + device->FmtChans = chanlist[i].chans; + device->Flags |= DEVICE_CHANNELS_REQUEST; + break; + } + } + if(i == COUNTOF(chanlist)) + ERR("Unsupported channels: %s\n", fmt); + } + if(ConfigValueStr(deviceName, NULL, "sample-type", &fmt)) + { + static const struct { + const char name[16]; + enum DevFmtType type; + } typelist[] = { + { "int8", DevFmtByte }, + { "uint8", DevFmtUByte }, + { "int16", DevFmtShort }, + { "uint16", DevFmtUShort }, + { "int32", DevFmtInt }, + { "uint32", DevFmtUInt }, + { "float32", DevFmtFloat }, + }; + size_t i; + + for(i = 0;i < COUNTOF(typelist);i++) + { + if(strcasecmp(typelist[i].name, fmt) == 0) + { + device->FmtType = typelist[i].type; + device->Flags |= DEVICE_SAMPLE_TYPE_REQUEST; + break; + } + } + if(i == COUNTOF(typelist)) + ERR("Unsupported sample-type: %s\n", fmt); + } + + if(ConfigValueUInt(deviceName, NULL, "frequency", &device->Frequency)) + { + device->Flags |= DEVICE_FREQUENCY_REQUEST; + if(device->Frequency < MIN_OUTPUT_RATE) + ERR("%uhz request clamped to %uhz minimum\n", device->Frequency, MIN_OUTPUT_RATE); + device->Frequency = maxu(device->Frequency, MIN_OUTPUT_RATE); + } + + ConfigValueUInt(deviceName, NULL, "periods", &device->NumUpdates); + device->NumUpdates = clampu(device->NumUpdates, 2, 16); + + ConfigValueUInt(deviceName, NULL, "period_size", &device->UpdateSize); + device->UpdateSize = clampu(device->UpdateSize, 64, 8192); + if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0) + device->UpdateSize = (device->UpdateSize+3)&~3; + + ConfigValueUInt(deviceName, NULL, "sources", &device->SourcesMax); + if(device->SourcesMax == 0) device->SourcesMax = 256; + + ConfigValueUInt(deviceName, NULL, "slots", &device->AuxiliaryEffectSlotMax); + if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4; + + ConfigValueUInt(deviceName, NULL, "sends", &device->NumAuxSends); + if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS; + + device->NumStereoSources = 1; + device->NumMonoSources = device->SourcesMax - device->NumStereoSources; + + // Find a playback device to open + if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR) + { + DELETE_OBJ(device->Backend); + al_free(device); + alcSetError(NULL, err); + return NULL; + } + almtx_init(&device->BackendLock, almtx_plain); + + if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "ambi-format", &fmt)) + { + if(strcasecmp(fmt, "fuma") == 0) + device->AmbiFmt = AmbiFormat_FuMa; + else if(strcasecmp(fmt, "acn+sn3d") == 0) + device->AmbiFmt = AmbiFormat_ACN_SN3D; + else if(strcasecmp(fmt, "acn+n3d") == 0) + device->AmbiFmt = AmbiFormat_ACN_N3D; + else + ERR("Unsupported ambi-format: %s\n", fmt); + } + + if(DefaultEffect.type != AL_EFFECT_NULL) + { + device->DefaultSlot = (ALeffectslot*)device->_slot_mem; + if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR) + { + device->DefaultSlot = NULL; + ERR("Failed to initialize the default effect slot\n"); + } + else + { + aluInitEffectPanning(device->DefaultSlot); + if(InitializeEffect(device, device->DefaultSlot, &DefaultEffect) != AL_NO_ERROR) + { + DeinitEffectSlot(device->DefaultSlot); + device->DefaultSlot = NULL; + ERR("Failed to initialize the default effect\n"); + } + } + } + + { + ALCdevice *head = ATOMIC_LOAD(&DeviceList); + do { + device->next = head; + } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device)); + } + + TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName)); + return device; +} + +/* alcCloseDevice + * + * Closes the given device. + */ +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) +{ + ALCdevice *list, *origdev, *nextdev; + ALCcontext *ctx; + + LockLists(); + list = ATOMIC_LOAD(&DeviceList); + do { + if(list == device) + break; + } while((list=list->next) != NULL); + if(!list || list->Type == Capture) + { + alcSetError(list, ALC_INVALID_DEVICE); + UnlockLists(); + return ALC_FALSE; + } + almtx_lock(&device->BackendLock); + + origdev = device; + nextdev = device->next; + if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &origdev, nextdev)) + { + do { + list = origdev; + origdev = device; + } while(!COMPARE_EXCHANGE(&list->next, &origdev, nextdev)); + } + UnlockLists(); + + ctx = ATOMIC_LOAD(&device->ContextList); + while(ctx != NULL) + { + ALCcontext *next = ctx->next; + WARN("Releasing context %p\n", ctx); + ReleaseContext(ctx, device); + ctx = next; + } + if((device->Flags&DEVICE_RUNNING)) + V0(device->Backend,stop)(); + device->Flags &= ~DEVICE_RUNNING; + almtx_unlock(&device->BackendLock); + + ALCdevice_DecRef(device); + + return ALC_TRUE; +} + + +/************************************************ + * ALC capture functions + ************************************************/ +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei samples) +{ + ALCdevice *device = NULL; + ALCenum err; + + DO_INITCONFIG(); + + if(!CaptureBackend.name) + { + alcSetError(NULL, ALC_INVALID_VALUE); + return NULL; + } + + if(samples <= 0) + { + alcSetError(NULL, ALC_INVALID_VALUE); + return NULL; + } + + if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0)) + deviceName = NULL; + + device = al_calloc(16, sizeof(ALCdevice)); + if(!device) + { + alcSetError(NULL, ALC_OUT_OF_MEMORY); + return NULL; + } + + //Validate device + InitRef(&device->ref, 1); + device->Connected = ALC_TRUE; + device->Type = Capture; + + VECTOR_INIT(device->Hrtf.List); + AL_STRING_INIT(device->Hrtf.Name); + + AL_STRING_INIT(device->DeviceName); + device->Dry.Buffer = NULL; + device->Dry.NumChannels = 0; + device->FOAOut.Buffer = NULL; + device->FOAOut.NumChannels = 0; + device->RealOut.Buffer = NULL; + device->RealOut.NumChannels = 0; + + InitUIntMap(&device->BufferMap, ~0); + InitUIntMap(&device->EffectMap, ~0); + InitUIntMap(&device->FilterMap, ~0); + + if(!CaptureBackend.getFactory) + device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs, + ALCbackend_Capture); + else + { + ALCbackendFactory *factory = CaptureBackend.getFactory(); + device->Backend = V(factory,createBackend)(device, ALCbackend_Capture); + } + if(!device->Backend) + { + al_free(device); + alcSetError(NULL, ALC_OUT_OF_MEMORY); + return NULL; + } + + device->Flags |= DEVICE_FREQUENCY_REQUEST; + device->Frequency = frequency; + + device->Flags |= DEVICE_CHANNELS_REQUEST | DEVICE_SAMPLE_TYPE_REQUEST; + if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE) + { + al_free(device); + alcSetError(NULL, ALC_INVALID_ENUM); + return NULL; + } + device->IsHeadphones = AL_FALSE; + device->AmbiFmt = AmbiFormat_Default; + + device->UpdateSize = samples; + device->NumUpdates = 1; + + if((err=V(device->Backend,open)(deviceName)) != ALC_NO_ERROR) + { + al_free(device); + alcSetError(NULL, err); + return NULL; + } + almtx_init(&device->BackendLock, almtx_plain); + + { + ALCdevice *head = ATOMIC_LOAD(&DeviceList); + do { + device->next = head; + } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device)); + } + + TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName)); + return device; +} + +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) +{ + ALCdevice *list, *next, *nextdev; + + LockLists(); + list = ATOMIC_LOAD(&DeviceList); + do { + if(list == device) + break; + } while((list=list->next) != NULL); + if(!list || list->Type != Capture) + { + alcSetError(list, ALC_INVALID_DEVICE); + UnlockLists(); + return ALC_FALSE; + } + + next = device; + nextdev = device->next; + if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCdevice*, &DeviceList, &next, nextdev)) + { + do { + list = next; + next = device; + } while(!COMPARE_EXCHANGE(&list->next, &next, nextdev)); + } + UnlockLists(); + + ALCdevice_DecRef(device); + + return ALC_TRUE; +} + +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) +{ + if(!VerifyDevice(&device) || device->Type != Capture) + alcSetError(device, ALC_INVALID_DEVICE); + else + { + almtx_lock(&device->BackendLock); + if(!device->Connected) + alcSetError(device, ALC_INVALID_DEVICE); + else if(!(device->Flags&DEVICE_RUNNING)) + { + if(V0(device->Backend,start)()) + device->Flags |= DEVICE_RUNNING; + else + { + aluHandleDisconnect(device); + alcSetError(device, ALC_INVALID_DEVICE); + } + } + almtx_unlock(&device->BackendLock); + } + + if(device) ALCdevice_DecRef(device); +} + +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) +{ + if(!VerifyDevice(&device) || device->Type != Capture) + alcSetError(device, ALC_INVALID_DEVICE); + else + { + almtx_lock(&device->BackendLock); + if((device->Flags&DEVICE_RUNNING)) + V0(device->Backend,stop)(); + device->Flags &= ~DEVICE_RUNNING; + almtx_unlock(&device->BackendLock); + } + + if(device) ALCdevice_DecRef(device); +} + +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) +{ + if(!VerifyDevice(&device) || device->Type != Capture) + alcSetError(device, ALC_INVALID_DEVICE); + else + { + ALCenum err = ALC_INVALID_VALUE; + + almtx_lock(&device->BackendLock); + if(samples >= 0 && V0(device->Backend,availableSamples)() >= (ALCuint)samples) + err = V(device->Backend,captureSamples)(buffer, samples); + almtx_unlock(&device->BackendLock); + + if(err != ALC_NO_ERROR) + alcSetError(device, err); + } + if(device) ALCdevice_DecRef(device); +} + + +/************************************************ + * ALC loopback functions + ************************************************/ + +/* alcLoopbackOpenDeviceSOFT + * + * Open a loopback device, for manual rendering. + */ +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName) +{ + ALCbackendFactory *factory; + ALCdevice *device; + + DO_INITCONFIG(); + + /* Make sure the device name, if specified, is us. */ + if(deviceName && strcmp(deviceName, alcDefaultName) != 0) + { + alcSetError(NULL, ALC_INVALID_VALUE); + return NULL; + } + + device = al_calloc(16, sizeof(ALCdevice)); + if(!device) + { + alcSetError(NULL, ALC_OUT_OF_MEMORY); + return NULL; + } + + //Validate device + InitRef(&device->ref, 1); + device->Connected = ALC_TRUE; + device->Type = Loopback; + ATOMIC_INIT(&device->LastError, ALC_NO_ERROR); + + device->Flags = 0; + VECTOR_INIT(device->Hrtf.List); + AL_STRING_INIT(device->Hrtf.Name); + device->Bs2b = NULL; + device->Uhj_Encoder = NULL; + device->Render_Mode = NormalRender; + AL_STRING_INIT(device->DeviceName); + device->Dry.Buffer = NULL; + device->Dry.NumChannels = 0; + device->FOAOut.Buffer = NULL; + device->FOAOut.NumChannels = 0; + device->RealOut.Buffer = NULL; + device->RealOut.NumChannels = 0; + + ATOMIC_INIT(&device->ContextList, NULL); + + device->ClockBase = 0; + device->SamplesDone = 0; + + device->SourcesMax = 256; + device->AuxiliaryEffectSlotMax = 4; + device->NumAuxSends = MAX_SENDS; + + InitUIntMap(&device->BufferMap, ~0); + InitUIntMap(&device->EffectMap, ~0); + InitUIntMap(&device->FilterMap, ~0); + + factory = ALCloopbackFactory_getFactory(); + device->Backend = V(factory,createBackend)(device, ALCbackend_Loopback); + if(!device->Backend) + { + al_free(device); + alcSetError(NULL, ALC_OUT_OF_MEMORY); + return NULL; + } + almtx_init(&device->BackendLock, almtx_plain); + + //Set output format + device->NumUpdates = 0; + device->UpdateSize = 0; + + device->Frequency = DEFAULT_OUTPUT_RATE; + device->FmtChans = DevFmtChannelsDefault; + device->FmtType = DevFmtTypeDefault; + device->IsHeadphones = AL_FALSE; + device->AmbiFmt = AmbiFormat_Default; + + ConfigValueUInt(NULL, NULL, "sources", &device->SourcesMax); + if(device->SourcesMax == 0) device->SourcesMax = 256; + + ConfigValueUInt(NULL, NULL, "slots", &device->AuxiliaryEffectSlotMax); + if(device->AuxiliaryEffectSlotMax == 0) device->AuxiliaryEffectSlotMax = 4; + + ConfigValueUInt(NULL, NULL, "sends", &device->NumAuxSends); + if(device->NumAuxSends > MAX_SENDS) device->NumAuxSends = MAX_SENDS; + + device->NumStereoSources = 1; + device->NumMonoSources = device->SourcesMax - device->NumStereoSources; + + // Open the "backend" + V(device->Backend,open)("Loopback"); + + { + ALCdevice *head = ATOMIC_LOAD(&DeviceList); + do { + device->next = head; + } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCdevice*, &DeviceList, &head, device)); + } + + TRACE("Created device %p\n", device); + return device; +} + +/* alcIsRenderFormatSupportedSOFT + * + * Determines if the loopback device supports the given format for rendering. + */ +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type) +{ + ALCboolean ret = ALC_FALSE; + + if(!VerifyDevice(&device) || device->Type != Loopback) + alcSetError(device, ALC_INVALID_DEVICE); + else if(freq <= 0) + alcSetError(device, ALC_INVALID_VALUE); + else + { + if(IsValidALCType(type) && BytesFromDevFmt(type) > 0 && + IsValidALCChannels(channels) && ChannelsFromDevFmt(channels) > 0 && + freq >= MIN_OUTPUT_RATE) + ret = ALC_TRUE; + } + if(device) ALCdevice_DecRef(device); + + return ret; +} + +/* alcRenderSamplesSOFT + * + * Renders some samples into a buffer, using the format last set by the + * attributes given to alcCreateContext. + */ +FORCE_ALIGN ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) +{ + if(!VerifyDevice(&device) || device->Type != Loopback) + alcSetError(device, ALC_INVALID_DEVICE); + else if(samples < 0 || (samples > 0 && buffer == NULL)) + alcSetError(device, ALC_INVALID_VALUE); + else + aluMixData(device, buffer, samples); + if(device) ALCdevice_DecRef(device); +} + + +/************************************************ + * ALC DSP pause/resume functions + ************************************************/ + +/* alcDevicePauseSOFT + * + * Pause the DSP to stop audio processing. + */ +ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device) +{ + if(!VerifyDevice(&device) || device->Type != Playback) + alcSetError(device, ALC_INVALID_DEVICE); + else + { + almtx_lock(&device->BackendLock); + if((device->Flags&DEVICE_RUNNING)) + V0(device->Backend,stop)(); + device->Flags &= ~DEVICE_RUNNING; + device->Flags |= DEVICE_PAUSED; + almtx_unlock(&device->BackendLock); + } + if(device) ALCdevice_DecRef(device); +} + +/* alcDeviceResumeSOFT + * + * Resume the DSP to restart audio processing. + */ +ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) +{ + if(!VerifyDevice(&device) || device->Type != Playback) + alcSetError(device, ALC_INVALID_DEVICE); + else + { + almtx_lock(&device->BackendLock); + if((device->Flags&DEVICE_PAUSED)) + { + device->Flags &= ~DEVICE_PAUSED; + if(ATOMIC_LOAD(&device->ContextList) != NULL) + { + if(V0(device->Backend,start)() != ALC_FALSE) + device->Flags |= DEVICE_RUNNING; + else + { + alcSetError(device, ALC_INVALID_DEVICE); + V0(device->Backend,lock)(); + aluHandleDisconnect(device); + V0(device->Backend,unlock)(); + } + } + } + almtx_unlock(&device->BackendLock); + } + if(device) ALCdevice_DecRef(device); +} + + +/************************************************ + * ALC HRTF functions + ************************************************/ + +/* alcGetStringiSOFT + * + * Gets a string parameter at the given index. + */ +ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index) +{ + const ALCchar *str = NULL; + + if(!VerifyDevice(&device) || device->Type == Capture) + alcSetError(device, ALC_INVALID_DEVICE); + else switch(paramName) + { + case ALC_HRTF_SPECIFIER_SOFT: + if(index >= 0 && (size_t)index < VECTOR_SIZE(device->Hrtf.List)) + str = al_string_get_cstr(VECTOR_ELEM(device->Hrtf.List, index).name); + else + alcSetError(device, ALC_INVALID_VALUE); + break; + + default: + alcSetError(device, ALC_INVALID_ENUM); + break; + } + if(device) ALCdevice_DecRef(device); + + return str; +} + +/* alcResetDeviceSOFT + * + * Resets the given device output, using the specified attribute list. + */ +ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs) +{ + ALCenum err; + + LockLists(); + if(!VerifyDevice(&device) || device->Type == Capture || !device->Connected) + { + UnlockLists(); + alcSetError(device, ALC_INVALID_DEVICE); + if(device) ALCdevice_DecRef(device); + return ALC_FALSE; + } + almtx_lock(&device->BackendLock); + UnlockLists(); + + err = UpdateDeviceParams(device, attribs); + almtx_unlock(&device->BackendLock); + + if(err != ALC_NO_ERROR) + { + alcSetError(device, err); + if(err == ALC_INVALID_DEVICE) + { + V0(device->Backend,lock)(); + aluHandleDisconnect(device); + V0(device->Backend,unlock)(); + } + ALCdevice_DecRef(device); + return ALC_FALSE; + } + ALCdevice_DecRef(device); + + return ALC_TRUE; +} diff --git a/Engine/lib/openal-soft/Alc/ALu.c b/Engine/lib/openal-soft/Alc/ALu.c new file mode 100644 index 000000000..cc01f3367 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/ALu.c @@ -0,0 +1,1657 @@ +/** + * 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 +#include +#include +#include +#include + +#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, ALuint frac); +extern inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint 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 }, +}}; + + +static inline HrtfDirectMixerFunc SelectHrtfMixer(void) +{ +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return MixDirectHrtf_SSE; +#endif +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return MixDirectHrtf_Neon; +#endif + + return MixDirectHrtf_C; +} + + +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. + */ +static 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; + ALuint 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 = fastf2u(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 *first; + struct ALlistenerProps *props; + aluVector vel; + + props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &Listener->Update, NULL, almemory_order_acq_rel); + if(!props) return AL_FALSE; + + /* AT then UP */ + N[0] = ATOMIC_LOAD(&props->Forward[0], almemory_order_relaxed); + N[1] = ATOMIC_LOAD(&props->Forward[1], almemory_order_relaxed); + N[2] = ATOMIC_LOAD(&props->Forward[2], almemory_order_relaxed); + aluNormalize(N); + V[0] = ATOMIC_LOAD(&props->Up[0], almemory_order_relaxed); + V[1] = ATOMIC_LOAD(&props->Up[1], almemory_order_relaxed); + V[2] = ATOMIC_LOAD(&props->Up[2], almemory_order_relaxed); + 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] = ATOMIC_LOAD(&props->Position[0], almemory_order_relaxed); + P[1] = ATOMIC_LOAD(&props->Position[1], almemory_order_relaxed); + P[2] = ATOMIC_LOAD(&props->Position[2], almemory_order_relaxed); + aluMatrixfFloat3(P, 1.0, &Listener->Params.Matrix); + aluMatrixfSetRow(&Listener->Params.Matrix, 3, -P[0], -P[1], -P[2], 1.0f); + + aluVectorSet(&vel, ATOMIC_LOAD(&props->Velocity[0], almemory_order_relaxed), + ATOMIC_LOAD(&props->Velocity[1], almemory_order_relaxed), + ATOMIC_LOAD(&props->Velocity[2], almemory_order_relaxed), + 0.0f); + Listener->Params.Velocity = aluMatrixfVector(&Listener->Params.Matrix, &vel); + + Listener->Params.Gain = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed) * Context->GainBoost; + Listener->Params.MetersPerUnit = ATOMIC_LOAD(&props->MetersPerUnit, almemory_order_relaxed); + + Listener->Params.DopplerFactor = ATOMIC_LOAD(&props->DopplerFactor, almemory_order_relaxed); + Listener->Params.SpeedOfSound = ATOMIC_LOAD(&props->SpeedOfSound, almemory_order_relaxed) * + ATOMIC_LOAD(&props->DopplerVelocity, almemory_order_relaxed); + + Listener->Params.SourceDistanceModel = ATOMIC_LOAD(&props->SourceDistanceModel, almemory_order_relaxed); + Listener->Params.DistanceModel = ATOMIC_LOAD(&props->DistanceModel, almemory_order_relaxed); + + /* WARNING: A livelock is theoretically possible if another thread keeps + * changing the freelist head without giving this a chance to actually swap + * in the old container (practically impossible with this little code, + * but...). + */ + first = ATOMIC_LOAD(&Listener->FreeList); + do { + ATOMIC_STORE(&props->next, first, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*, + &Listener->FreeList, &first, props) == 0); + + return AL_TRUE; +} + +static ALboolean CalcEffectSlotParams(ALeffectslot *slot, ALCdevice *device) +{ + struct ALeffectslotProps *first; + struct ALeffectslotProps *props; + ALeffectState *state; + + props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, NULL, almemory_order_acq_rel); + if(!props) return AL_FALSE; + + slot->Params.Gain = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed); + slot->Params.AuxSendAuto = ATOMIC_LOAD(&props->AuxSendAuto, almemory_order_relaxed); + slot->Params.EffectType = ATOMIC_LOAD(&props->Type, almemory_order_relaxed); + if(IsReverbEffect(slot->Params.EffectType)) + { + slot->Params.RoomRolloff = props->Props.Reverb.RoomRolloffFactor; + slot->Params.DecayTime = props->Props.Reverb.DecayTime; + slot->Params.AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF; + } + else + { + slot->Params.RoomRolloff = 0.0f; + slot->Params.DecayTime = 0.0f; + 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 = ATOMIC_EXCHANGE(ALeffectState*, &props->State, slot->Params.EffectState, + almemory_order_relaxed); + slot->Params.EffectState = state; + + V(state,update)(device, slot, &props->Props); + + /* WARNING: A livelock is theoretically possible if another thread keeps + * changing the freelist head without giving this a chance to actually swap + * in the old container (practically impossible with this little code, + * but...). + */ + first = ATOMIC_LOAD(&slot->FreeList); + do { + ATOMIC_STORE(&props->next, first, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, + &slot->FreeList, &first, props) == 0); + + return AL_TRUE; +} + + +static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext) +{ + 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) } + }; + + const ALCdevice *Device = ALContext->Device; + const ALlistener *Listener = ALContext->Listener; + ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume; + ALfloat DryGain, DryGainHF, DryGainLF; + ALfloat WetGain[MAX_SENDS]; + ALfloat WetGainHF[MAX_SENDS]; + ALfloat WetGainLF[MAX_SENDS]; + ALeffectslot *SendSlots[MAX_SENDS]; + ALuint NumSends, Frequency; + ALboolean Relative; + const struct ChanMap *chans = NULL; + struct ChanMap StereoMap[2] = { + { FrontLeft, DEG2RAD(-30.0f), DEG2RAD(0.0f) }, + { FrontRight, DEG2RAD( 30.0f), DEG2RAD(0.0f) } + }; + ALuint num_channels = 0; + ALboolean DirectChannels; + ALboolean isbformat = AL_FALSE; + ALfloat Pitch; + ALuint i, j, c; + + /* Get device properties */ + NumSends = Device->NumAuxSends; + Frequency = Device->Frequency; + + /* Get listener properties */ + ListenerGain = Listener->Params.Gain; + + /* Get source properties */ + SourceVolume = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed); + MinVolume = ATOMIC_LOAD(&props->MinGain, almemory_order_relaxed); + MaxVolume = ATOMIC_LOAD(&props->MaxGain, almemory_order_relaxed); + Pitch = ATOMIC_LOAD(&props->Pitch, almemory_order_relaxed); + Relative = ATOMIC_LOAD(&props->HeadRelative, almemory_order_relaxed); + DirectChannels = ATOMIC_LOAD(&props->DirectChannels, almemory_order_relaxed); + + /* Convert counter-clockwise to clockwise. */ + StereoMap[0].angle = -ATOMIC_LOAD(&props->StereoPan[0], almemory_order_relaxed); + StereoMap[1].angle = -ATOMIC_LOAD(&props->StereoPan[1], almemory_order_relaxed); + + voice->DirectOut.Buffer = Device->Dry.Buffer; + voice->DirectOut.Channels = Device->Dry.NumChannels; + for(i = 0;i < NumSends;i++) + { + SendSlots[i] = ATOMIC_LOAD(&props->Send[i].Slot, almemory_order_relaxed); + if(!SendSlots[i] && i == 0) + SendSlots[i] = Device->DefaultSlot; + if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL) + { + SendSlots[i] = NULL; + voice->SendOut[i].Buffer = NULL; + voice->SendOut[i].Channels = 0; + } + else + { + voice->SendOut[i].Buffer = SendSlots[i]->WetBuffer; + voice->SendOut[i].Channels = SendSlots[i]->NumChannels; + } + } + + /* Calculate the stepping value */ + Pitch *= (ALfloat)ALBuffer->Frequency / Frequency; + if(Pitch > (ALfloat)MAX_PITCH) + voice->Step = MAX_PITCH<Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1); + BsincPrepare(voice->Step, &voice->SincState); + + /* Calculate gains */ + DryGain = clampf(SourceVolume, MinVolume, MaxVolume); + DryGain *= ATOMIC_LOAD(&props->Direct.Gain, almemory_order_relaxed) * ListenerGain; + DryGain = minf(DryGain, GAIN_MIX_MAX); + DryGainHF = ATOMIC_LOAD(&props->Direct.GainHF, almemory_order_relaxed); + DryGainLF = ATOMIC_LOAD(&props->Direct.GainLF, almemory_order_relaxed); + for(i = 0;i < NumSends;i++) + { + WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume); + WetGain[i] *= ATOMIC_LOAD(&props->Send[i].Gain, almemory_order_relaxed) * ListenerGain; + WetGain[i] = minf(WetGain[i], GAIN_MIX_MAX); + WetGainHF[i] = ATOMIC_LOAD(&props->Send[i].GainHF, almemory_order_relaxed); + WetGainLF[i] = ATOMIC_LOAD(&props->Send[i].GainLF, almemory_order_relaxed); + } + + switch(ALBuffer->FmtChannels) + { + case FmtMono: + chans = MonoMap; + num_channels = 1; + break; + + case FmtStereo: + chans = StereoMap; + 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; + + case FmtBFormat2D: + num_channels = 3; + isbformat = AL_TRUE; + DirectChannels = AL_FALSE; + break; + + case FmtBFormat3D: + num_channels = 4; + isbformat = AL_TRUE; + DirectChannels = AL_FALSE; + break; + } + + if(isbformat) + { + ALfloat N[3], V[3], U[3]; + aluMatrixf matrix; + ALfloat scale; + + /* AT then UP */ + N[0] = ATOMIC_LOAD(&props->Orientation[0][0], almemory_order_relaxed); + N[1] = ATOMIC_LOAD(&props->Orientation[0][1], almemory_order_relaxed); + N[2] = ATOMIC_LOAD(&props->Orientation[0][2], almemory_order_relaxed); + aluNormalize(N); + V[0] = ATOMIC_LOAD(&props->Orientation[1][0], almemory_order_relaxed); + V[1] = ATOMIC_LOAD(&props->Orientation[1][1], almemory_order_relaxed); + V[2] = ATOMIC_LOAD(&props->Orientation[1][2], almemory_order_relaxed); + aluNormalize(V); + if(!Relative) + { + 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->DirectOut.Buffer = Device->FOAOut.Buffer; + voice->DirectOut.Channels = Device->FOAOut.NumChannels; + for(c = 0;c < num_channels;c++) + ComputeFirstOrderGains(Device->FOAOut, matrix.m[c], DryGain, + voice->Chan[c].Direct.Gains.Target); + + for(i = 0;i < NumSends;i++) + { + if(!SendSlots[i]) + { + for(c = 0;c < num_channels;c++) + { + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + voice->Chan[c].Send[i].Gains.Target[j] = 0.0f; + } + } + else + { + for(c = 0;c < num_channels;c++) + { + const ALeffectslot *Slot = SendSlots[i]; + ComputeFirstOrderGainsBF(Slot->ChanMap, Slot->NumChannels, matrix.m[c], + WetGain[i], voice->Chan[c].Send[i].Gains.Target); + } + } + } + + voice->IsHrtf = AL_FALSE; + } + else + { + ALfloat coeffs[MAX_AMBI_COEFFS]; + + if(DirectChannels) + { + /* Skip the virtual channels and write inputs to the real output. */ + voice->DirectOut.Buffer = Device->RealOut.Buffer; + voice->DirectOut.Channels = Device->RealOut.NumChannels; + for(c = 0;c < num_channels;c++) + { + int idx; + for(j = 0;j < MAX_OUTPUT_CHANNELS;j++) + voice->Chan[c].Direct.Gains.Target[j] = 0.0f; + if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1) + voice->Chan[c].Direct.Gains.Target[idx] = DryGain; + } + + /* Auxiliary sends still use normal panning since they mix to B-Format, which can't + * channel-match. */ + for(c = 0;c < num_channels;c++) + { + CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs); + + for(i = 0;i < NumSends;i++) + { + if(!SendSlots[i]) + { + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + voice->Chan[c].Send[i].Gains.Target[j] = 0.0f; + } + else + { + const ALeffectslot *Slot = SendSlots[i]; + ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs, + WetGain[i], voice->Chan[c].Send[i].Gains.Target); + } + } + } + + voice->IsHrtf = AL_FALSE; + } + else if(Device->Render_Mode == HrtfRender) + { + /* Full HRTF rendering. Skip the virtual channels and render each + * input channel to the real outputs. + */ + voice->DirectOut.Buffer = Device->RealOut.Buffer; + voice->DirectOut.Channels = Device->RealOut.NumChannels; + for(c = 0;c < num_channels;c++) + { + if(chans[c].channel == LFE) + { + /* Skip LFE */ + voice->Chan[c].Direct.Hrtf.Target.Delay[0] = 0; + voice->Chan[c].Direct.Hrtf.Target.Delay[1] = 0; + for(i = 0;i < HRIR_LENGTH;i++) + { + voice->Chan[c].Direct.Hrtf.Target.Coeffs[i][0] = 0.0f; + voice->Chan[c].Direct.Hrtf.Target.Coeffs[i][1] = 0.0f; + } + + for(i = 0;i < NumSends;i++) + { + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + voice->Chan[c].Send[i].Gains.Target[j] = 0.0f; + } + + continue; + } + + /* Get the static HRIR coefficients and delays for this channel. */ + GetHrtfCoeffs(Device->Hrtf.Handle, + chans[c].elevation, chans[c].angle, 0.0f, DryGain, + voice->Chan[c].Direct.Hrtf.Target.Coeffs, + voice->Chan[c].Direct.Hrtf.Target.Delay + ); + + /* Normal panning for auxiliary sends. */ + CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs); + + for(i = 0;i < NumSends;i++) + { + if(!SendSlots[i]) + { + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + voice->Chan[c].Send[i].Gains.Target[j] = 0.0f; + } + else + { + const ALeffectslot *Slot = SendSlots[i]; + ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs, + WetGain[i], voice->Chan[c].Send[i].Gains.Target); + } + } + } + + voice->IsHrtf = AL_TRUE; + } + else + { + /* Non-HRTF rendering. Use normal panning to the output. */ + for(c = 0;c < num_channels;c++) + { + /* Special-case LFE */ + if(chans[c].channel == LFE) + { + for(j = 0;j < MAX_OUTPUT_CHANNELS;j++) + voice->Chan[c].Direct.Gains.Target[j] = 0.0f; + if(Device->Dry.Buffer == Device->RealOut.Buffer) + { + int idx; + if((idx=GetChannelIdxByName(Device->RealOut, chans[c].channel)) != -1) + voice->Chan[c].Direct.Gains.Target[idx] = DryGain; + } + + for(i = 0;i < NumSends;i++) + { + ALuint j; + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + voice->Chan[c].Send[i].Gains.Target[j] = 0.0f; + } + continue; + } + + if(Device->Render_Mode == StereoPair) + { + /* Clamp X so it remains within 30 degrees of 0 or 180 degree azimuth. */ + ALfloat x = sinf(chans[c].angle) * cosf(chans[c].elevation); + coeffs[0] = clampf(-x, -0.5f, 0.5f) + 0.5f; + voice->Chan[c].Direct.Gains.Target[0] = coeffs[0] * DryGain; + voice->Chan[c].Direct.Gains.Target[1] = (1.0f-coeffs[0]) * DryGain; + for(j = 2;j < MAX_OUTPUT_CHANNELS;j++) + voice->Chan[c].Direct.Gains.Target[j] = 0.0f; + + CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs); + } + else + { + CalcAngleCoeffs(chans[c].angle, chans[c].elevation, 0.0f, coeffs); + ComputePanningGains(Device->Dry, coeffs, DryGain, + voice->Chan[c].Direct.Gains.Target); + } + + for(i = 0;i < NumSends;i++) + { + if(!SendSlots[i]) + { + ALuint j; + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + voice->Chan[c].Send[i].Gains.Target[j] = 0.0f; + } + else + { + const ALeffectslot *Slot = SendSlots[i]; + ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs, + WetGain[i], voice->Chan[c].Send[i].Gains.Target); + } + } + } + + voice->IsHrtf = AL_FALSE; + } + } + + { + ALfloat hfscale = ATOMIC_LOAD(&props->Direct.HFReference, almemory_order_relaxed) / + Frequency; + ALfloat lfscale = ATOMIC_LOAD(&props->Direct.LFReference, almemory_order_relaxed) / + Frequency; + DryGainHF = maxf(DryGainHF, 0.0001f); + DryGainLF = maxf(DryGainLF, 0.0001f); + for(c = 0;c < num_channels;c++) + { + voice->Chan[c].Direct.FilterType = AF_None; + if(DryGainHF != 1.0f) voice->Chan[c].Direct.FilterType |= AF_LowPass; + if(DryGainLF != 1.0f) voice->Chan[c].Direct.FilterType |= AF_HighPass; + ALfilterState_setParams( + &voice->Chan[c].Direct.LowPass, ALfilterType_HighShelf, + DryGainHF, hfscale, calc_rcpQ_from_slope(DryGainHF, 0.75f) + ); + ALfilterState_setParams( + &voice->Chan[c].Direct.HighPass, ALfilterType_LowShelf, + DryGainLF, lfscale, calc_rcpQ_from_slope(DryGainLF, 0.75f) + ); + } + } + for(i = 0;i < NumSends;i++) + { + ALfloat hfscale = ATOMIC_LOAD(&props->Send[i].HFReference, almemory_order_relaxed) / + Frequency; + ALfloat lfscale = ATOMIC_LOAD(&props->Send[i].LFReference, almemory_order_relaxed) / + Frequency; + WetGainHF[i] = maxf(WetGainHF[i], 0.0001f); + WetGainLF[i] = maxf(WetGainLF[i], 0.0001f); + for(c = 0;c < num_channels;c++) + { + voice->Chan[c].Send[i].FilterType = AF_None; + if(WetGainHF[i] != 1.0f) voice->Chan[c].Send[i].FilterType |= AF_LowPass; + if(WetGainLF[i] != 1.0f) voice->Chan[c].Send[i].FilterType |= AF_HighPass; + ALfilterState_setParams( + &voice->Chan[c].Send[i].LowPass, ALfilterType_HighShelf, + WetGainHF[i], hfscale, calc_rcpQ_from_slope(WetGainHF[i], 0.75f) + ); + ALfilterState_setParams( + &voice->Chan[c].Send[i].HighPass, ALfilterType_LowShelf, + WetGainLF[i], lfscale, calc_rcpQ_from_slope(WetGainLF[i], 0.75f) + ); + } + } +} + +static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *props, const ALbuffer *ALBuffer, const ALCcontext *ALContext) +{ + const ALCdevice *Device = ALContext->Device; + const ALlistener *Listener = ALContext->Listener; + aluVector Position, Velocity, Direction, SourceToListener; + ALfloat InnerAngle,OuterAngle,Distance,ClampedDist; + ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff; + ALfloat SourceVolume,ListenerGain; + ALfloat DopplerFactor, SpeedOfSound; + ALfloat AirAbsorptionFactor; + ALfloat RoomAirAbsorption[MAX_SENDS]; + ALeffectslot *SendSlots[MAX_SENDS]; + 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; + + 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 = Listener->Params.DopplerFactor; + SpeedOfSound = Listener->Params.SpeedOfSound; + NumSends = Device->NumAuxSends; + Frequency = Device->Frequency; + + /* Get listener properties */ + ListenerGain = Listener->Params.Gain; + MetersPerUnit = Listener->Params.MetersPerUnit; + + /* Get source properties */ + SourceVolume = ATOMIC_LOAD(&props->Gain, almemory_order_relaxed); + MinVolume = ATOMIC_LOAD(&props->MinGain, almemory_order_relaxed); + MaxVolume = ATOMIC_LOAD(&props->MaxGain, almemory_order_relaxed); + Pitch = ATOMIC_LOAD(&props->Pitch, almemory_order_relaxed); + aluVectorSet(&Position, ATOMIC_LOAD(&props->Position[0], almemory_order_relaxed), + ATOMIC_LOAD(&props->Position[1], almemory_order_relaxed), + ATOMIC_LOAD(&props->Position[2], almemory_order_relaxed), + 1.0f); + aluVectorSet(&Direction, ATOMIC_LOAD(&props->Direction[0], almemory_order_relaxed), + ATOMIC_LOAD(&props->Direction[1], almemory_order_relaxed), + ATOMIC_LOAD(&props->Direction[2], almemory_order_relaxed), + 0.0f); + aluVectorSet(&Velocity, ATOMIC_LOAD(&props->Velocity[0], almemory_order_relaxed), + ATOMIC_LOAD(&props->Velocity[1], almemory_order_relaxed), + ATOMIC_LOAD(&props->Velocity[2], almemory_order_relaxed), + 0.0f); + MinDist = ATOMIC_LOAD(&props->RefDistance, almemory_order_relaxed); + MaxDist = ATOMIC_LOAD(&props->MaxDistance, almemory_order_relaxed); + Rolloff = ATOMIC_LOAD(&props->RollOffFactor, almemory_order_relaxed); + DopplerFactor *= ATOMIC_LOAD(&props->DopplerFactor, almemory_order_relaxed); + InnerAngle = ATOMIC_LOAD(&props->InnerAngle, almemory_order_relaxed); + OuterAngle = ATOMIC_LOAD(&props->OuterAngle, almemory_order_relaxed); + AirAbsorptionFactor = ATOMIC_LOAD(&props->AirAbsorptionFactor, almemory_order_relaxed); + DryGainHFAuto = ATOMIC_LOAD(&props->DryGainHFAuto, almemory_order_relaxed); + WetGainAuto = ATOMIC_LOAD(&props->WetGainAuto, almemory_order_relaxed); + WetGainHFAuto = ATOMIC_LOAD(&props->WetGainHFAuto, almemory_order_relaxed); + RoomRolloffBase = ATOMIC_LOAD(&props->RoomRolloffFactor, almemory_order_relaxed); + + voice->DirectOut.Buffer = Device->Dry.Buffer; + voice->DirectOut.Channels = Device->Dry.NumChannels; + for(i = 0;i < NumSends;i++) + { + SendSlots[i] = ATOMIC_LOAD(&props->Send[i].Slot, almemory_order_relaxed); + + if(!SendSlots[i] && i == 0) + SendSlots[i] = Device->DefaultSlot; + if(!SendSlots[i] || SendSlots[i]->Params.EffectType == AL_EFFECT_NULL) + { + SendSlots[i] = NULL; + RoomRolloff[i] = 0.0f; + DecayDistance[i] = 0.0f; + RoomAirAbsorption[i] = 1.0f; + } + else if(SendSlots[i]->Params.AuxSendAuto) + { + RoomRolloff[i] = SendSlots[i]->Params.RoomRolloff + RoomRolloffBase; + DecayDistance[i] = SendSlots[i]->Params.DecayTime * + SPEEDOFSOUNDMETRESPERSEC; + RoomAirAbsorption[i] = SendSlots[i]->Params.AirAbsorptionGainHF; + } + 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(!SendSlots[i]) + { + voice->SendOut[i].Buffer = NULL; + voice->SendOut[i].Channels = 0; + } + else + { + voice->SendOut[i].Buffer = SendSlots[i]->WetBuffer; + voice->SendOut[i].Channels = SendSlots[i]->NumChannels; + } + } + + /* Transform source to listener space (convert to head relative) */ + if(ATOMIC_LOAD(&props->HeadRelative, almemory_order_relaxed) == 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]; + } + + aluNormalize(Direction.v); + 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); + + /* Calculate distance attenuation */ + ClampedDist = Distance; + + Attenuation = 1.0f; + for(i = 0;i < NumSends;i++) + RoomAttenuation[i] = 1.0f; + switch(Listener->Params.SourceDistanceModel ? + ATOMIC_LOAD(&props->DistanceModel, almemory_order_relaxed) : + Listener->Params.DistanceModel) + { + case InverseDistanceClamped: + ClampedDist = clampf(ClampedDist, MinDist, MaxDist); + if(MaxDist < MinDist) + break; + /*fall-through*/ + case InverseDistance: + if(MinDist > 0.0f) + { + ALfloat dist = lerp(MinDist, ClampedDist, Rolloff); + if(dist > 0.0f) Attenuation = MinDist / dist; + for(i = 0;i < NumSends;i++) + { + dist = lerp(MinDist, ClampedDist, RoomRolloff[i]); + if(dist > 0.0f) RoomAttenuation[i] = MinDist / dist; + } + } + 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 = (ClampedDist-MinDist) * 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 */ + if(InnerAngle < 360.0f) + { + ALfloat ConeVolume; + ALfloat ConeHF; + ALfloat Angle; + ALfloat scale; + + Angle = RAD2DEG(acosf(aluDotproduct(&Direction, &SourceToListener)) * ConeScale) * 2.0f; + if(Angle > InnerAngle) + { + if(Angle < OuterAngle) + { + scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle); + ConeVolume = lerp( + 1.0f, ATOMIC_LOAD(&props->OuterGain, almemory_order_relaxed), scale + ); + ConeHF = lerp( + 1.0f, ATOMIC_LOAD(&props->OuterGainHF, almemory_order_relaxed), scale + ); + } + else + { + ConeVolume = ATOMIC_LOAD(&props->OuterGain, almemory_order_relaxed); + ConeHF = ATOMIC_LOAD(&props->OuterGainHF, almemory_order_relaxed); + } + DryGain *= ConeVolume; + if(DryGainHFAuto) + DryGainHF *= ConeHF; + } + + /* Wet path uses the total area of the cone emitter (the room will + * receive the same amount of sound regardless of its direction). + */ + scale = (asinf(maxf((OuterAngle-InnerAngle)/360.0f, 0.0f)) / F_PI) + + (InnerAngle/360.0f); + if(WetGainAuto) + { + ConeVolume = lerp( + 1.0f, ATOMIC_LOAD(&props->OuterGain, almemory_order_relaxed), scale + ); + for(i = 0;i < NumSends;i++) + WetGain[i] *= ConeVolume; + } + if(WetGainHFAuto) + { + ConeHF = lerp( + 1.0f, ATOMIC_LOAD(&props->OuterGainHF, almemory_order_relaxed), scale + ); + for(i = 0;i < NumSends;i++) + WetGainHF[i] *= ConeHF; + } + } + + /* Apply gain and frequency filters */ + DryGain = clampf(DryGain, MinVolume, MaxVolume); + DryGain *= ATOMIC_LOAD(&props->Direct.Gain, almemory_order_relaxed) * ListenerGain; + DryGain = minf(DryGain, GAIN_MIX_MAX); + DryGainHF *= ATOMIC_LOAD(&props->Direct.GainHF, almemory_order_relaxed); + DryGainLF *= ATOMIC_LOAD(&props->Direct.GainLF, almemory_order_relaxed); + for(i = 0;i < NumSends;i++) + { + WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume); + WetGain[i] *= ATOMIC_LOAD(&props->Send[i].Gain, almemory_order_relaxed) * ListenerGain; + WetGain[i] = minf(WetGain[i], GAIN_MIX_MAX); + WetGainHF[i] *= ATOMIC_LOAD(&props->Send[i].GainHF, almemory_order_relaxed); + WetGainLF[i] *= ATOMIC_LOAD(&props->Send[i].GainLF, almemory_order_relaxed); + } + + /* Calculate velocity-based doppler effect */ + if(DopplerFactor > 0.0f) + { + const aluVector *lvelocity = &Listener->Params.Velocity; + ALfloat VSS, VLS; + + if(SpeedOfSound < 1.0f) + { + DopplerFactor *= 1.0f/SpeedOfSound; + SpeedOfSound = 1.0f; + } + + VSS = aluDotproduct(&Velocity, &SourceToListener) * DopplerFactor; + VLS = aluDotproduct(lvelocity, &SourceToListener) * DopplerFactor; + + Pitch *= clampf(SpeedOfSound-VLS, 1.0f, SpeedOfSound*2.0f - 1.0f) / + clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f); + } + + /* Calculate fixed-point stepping value, based on the pitch, buffer + * frequency, and output frequency. + */ + Pitch *= (ALfloat)ALBuffer->Frequency / Frequency; + if(Pitch > (ALfloat)MAX_PITCH) + voice->Step = MAX_PITCH<Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1); + BsincPrepare(voice->Step, &voice->SincState); + + if(Device->Render_Mode == HrtfRender) + { + /* Full HRTF rendering. Skip the virtual channels and render to the + * real outputs. + */ + ALfloat dir[3] = { 0.0f, 0.0f, -1.0f }; + ALfloat ev = 0.0f, az = 0.0f; + ALfloat radius = ATOMIC_LOAD(&props->Radius, almemory_order_relaxed); + ALfloat coeffs[MAX_AMBI_COEFFS]; + ALfloat spread = 0.0f; + + voice->DirectOut.Buffer = Device->RealOut.Buffer; + voice->DirectOut.Channels = Device->RealOut.NumChannels; + + if(Distance > FLT_EPSILON) + { + dir[0] = -SourceToListener.v[0]; + dir[1] = -SourceToListener.v[1]; + dir[2] = -SourceToListener.v[2] * ZScale; + + /* 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(dir[1], -1.0f, 1.0f)); + az = atan2f(dir[0], -dir[2]); + } + if(radius > Distance) + spread = F_TAU - Distance/radius*F_PI; + else if(Distance > FLT_EPSILON) + spread = asinf(radius / Distance) * 2.0f; + + /* Get the HRIR coefficients and delays. */ + GetHrtfCoeffs(Device->Hrtf.Handle, ev, az, spread, DryGain, + voice->Chan[0].Direct.Hrtf.Target.Coeffs, + voice->Chan[0].Direct.Hrtf.Target.Delay); + + CalcDirectionCoeffs(dir, spread, coeffs); + + for(i = 0;i < NumSends;i++) + { + if(!SendSlots[i]) + { + ALuint j; + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + voice->Chan[0].Send[i].Gains.Target[j] = 0.0f; + } + else + { + const ALeffectslot *Slot = SendSlots[i]; + ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs, + WetGain[i], voice->Chan[0].Send[i].Gains.Target); + } + } + + voice->IsHrtf = AL_TRUE; + } + else + { + /* Non-HRTF rendering. */ + ALfloat dir[3] = { 0.0f, 0.0f, -1.0f }; + ALfloat radius = ATOMIC_LOAD(&props->Radius, almemory_order_relaxed); + ALfloat coeffs[MAX_AMBI_COEFFS]; + ALfloat spread = 0.0f; + + /* Get the localized direction, and compute panned gains. */ + if(Distance > FLT_EPSILON) + { + dir[0] = -SourceToListener.v[0]; + dir[1] = -SourceToListener.v[1]; + dir[2] = -SourceToListener.v[2] * ZScale; + } + if(radius > Distance) + spread = F_TAU - Distance/radius*F_PI; + else if(Distance > FLT_EPSILON) + spread = asinf(radius / Distance) * 2.0f; + + if(Device->Render_Mode == StereoPair) + { + /* Clamp X so it remains within 30 degrees of 0 or 180 degree azimuth. */ + ALfloat x = -dir[0] * (0.5f * (cosf(spread*0.5f) + 1.0f)); + x = clampf(x, -0.5f, 0.5f) + 0.5f; + voice->Chan[0].Direct.Gains.Target[0] = x * DryGain; + voice->Chan[0].Direct.Gains.Target[1] = (1.0f-x) * DryGain; + for(i = 2;i < MAX_OUTPUT_CHANNELS;i++) + voice->Chan[0].Direct.Gains.Target[i] = 0.0f; + + CalcDirectionCoeffs(dir, spread, coeffs); + } + else + { + CalcDirectionCoeffs(dir, spread, coeffs); + ComputePanningGains(Device->Dry, coeffs, DryGain, + voice->Chan[0].Direct.Gains.Target); + } + + for(i = 0;i < NumSends;i++) + { + if(!SendSlots[i]) + { + ALuint j; + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + voice->Chan[0].Send[i].Gains.Target[j] = 0.0f; + } + else + { + const ALeffectslot *Slot = SendSlots[i]; + ComputePanningGainsBF(Slot->ChanMap, Slot->NumChannels, coeffs, + WetGain[i], voice->Chan[0].Send[i].Gains.Target); + } + } + + voice->IsHrtf = AL_FALSE; + } + + { + ALfloat hfscale = ATOMIC_LOAD(&props->Direct.HFReference, almemory_order_relaxed) / + Frequency; + ALfloat lfscale = ATOMIC_LOAD(&props->Direct.LFReference, almemory_order_relaxed) / + Frequency; + DryGainHF = maxf(DryGainHF, 0.0001f); + DryGainLF = maxf(DryGainLF, 0.0001f); + voice->Chan[0].Direct.FilterType = AF_None; + if(DryGainHF != 1.0f) voice->Chan[0].Direct.FilterType |= AF_LowPass; + if(DryGainLF != 1.0f) voice->Chan[0].Direct.FilterType |= AF_HighPass; + ALfilterState_setParams( + &voice->Chan[0].Direct.LowPass, ALfilterType_HighShelf, + DryGainHF, hfscale, calc_rcpQ_from_slope(DryGainHF, 0.75f) + ); + ALfilterState_setParams( + &voice->Chan[0].Direct.HighPass, ALfilterType_LowShelf, + DryGainLF, lfscale, calc_rcpQ_from_slope(DryGainLF, 0.75f) + ); + } + for(i = 0;i < NumSends;i++) + { + ALfloat hfscale = ATOMIC_LOAD(&props->Send[i].HFReference, almemory_order_relaxed) / + Frequency; + ALfloat lfscale = ATOMIC_LOAD(&props->Send[i].LFReference, almemory_order_relaxed) / + Frequency; + WetGainHF[i] = maxf(WetGainHF[i], 0.0001f); + WetGainLF[i] = maxf(WetGainLF[i], 0.0001f); + voice->Chan[0].Send[i].FilterType = AF_None; + if(WetGainHF[i] != 1.0f) voice->Chan[0].Send[i].FilterType |= AF_LowPass; + if(WetGainLF[i] != 1.0f) voice->Chan[0].Send[i].FilterType |= AF_HighPass; + ALfilterState_setParams( + &voice->Chan[0].Send[i].LowPass, ALfilterType_HighShelf, + WetGainHF[i], hfscale, calc_rcpQ_from_slope(WetGainHF[i], 0.75f) + ); + ALfilterState_setParams( + &voice->Chan[0].Send[i].HighPass, ALfilterType_LowShelf, + WetGainLF[i], lfscale, calc_rcpQ_from_slope(WetGainLF[i], 0.75f) + ); + } +} + +static void CalcSourceParams(ALvoice *voice, ALCcontext *context, ALboolean force) +{ + ALsource *source = voice->Source; + const ALbufferlistitem *BufferListItem; + struct ALsourceProps *first; + struct ALsourceProps *props; + + props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, NULL, almemory_order_acq_rel); + if(!props && !force) return; + + if(props) + { + voice->Props = *props; + + /* WARNING: A livelock is theoretically possible if another thread + * keeps changing the freelist head without giving this a chance to + * actually swap in the old container (practically impossible with this + * little code, but...). + */ + first = ATOMIC_LOAD(&source->FreeList); + do { + ATOMIC_STORE(&props->next, first, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*, + &source->FreeList, &first, props) == 0); + } + + BufferListItem = ATOMIC_LOAD(&source->queue, almemory_order_relaxed); + while(BufferListItem != NULL) + { + const ALbuffer *buffer; + if((buffer=BufferListItem->buffer) != NULL) + { + if(buffer->FmtChannels == FmtMono) + CalcAttnSourceParams(voice, &voice->Props, buffer, context); + else + CalcNonAttnSourceParams(voice, &voice->Props, buffer, context); + break; + } + BufferListItem = BufferListItem->next; + } +} + + +static void UpdateContextSources(ALCcontext *ctx, ALeffectslot *slot) +{ + ALvoice *voice, *voice_end; + ALsource *source; + + IncrementRef(&ctx->UpdateCount); + if(!ATOMIC_LOAD(&ctx->HoldUpdates)) + { + ALboolean force = CalcListenerParams(ctx); + while(slot) + { + force |= CalcEffectSlotParams(slot, ctx->Device); + slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed); + } + + voice = ctx->Voices; + voice_end = voice + ctx->VoiceCount; + for(;voice != voice_end;++voice) + { + if(!(source=voice->Source)) continue; + if(source->state != AL_PLAYING && source->state != AL_PAUSED) + voice->Source = NULL; + else + CalcSourceParams(voice, ctx, force); + } + } + IncrementRef(&ctx->UpdateCount); +} + + +/* Specialized function to clamp to [-1, +1] with only one branch. This also + * converts NaN to 0. */ +static inline ALfloat aluClampf(ALfloat val) +{ + if(fabsf(val) <= 1.0f) return val; + return (ALfloat)((0.0f < val) - (val < 0.0f)); +} + +static inline ALfloat aluF2F(ALfloat val) +{ return val; } + +static inline ALint aluF2I(ALfloat val) +{ + /* Floats only have a 24-bit mantissa, so [-16777215, +16777215] is the max + * integer range normalized floats can be safely converted to. + */ + return fastf2i(aluClampf(val)*16777215.0f)<<7; +} +static inline ALuint aluF2UI(ALfloat val) +{ return aluF2I(val)+2147483648u; } + +static inline ALshort aluF2S(ALfloat val) +{ return fastf2i(aluClampf(val)*32767.0f); } +static inline ALushort aluF2US(ALfloat val) +{ return aluF2S(val)+32768; } + +static inline ALbyte aluF2B(ALfloat val) +{ return fastf2i(aluClampf(val)*127.0f); } +static inline ALubyte aluF2UB(ALfloat val) +{ return aluF2B(val)+128; } + +#define DECL_TEMPLATE(T, func) \ +static void Write_##T(ALfloatBUFFERSIZE *InBuffer, ALvoid *OutBuffer, \ + ALuint SamplesToDo, ALuint numchans) \ +{ \ + ALuint i, j; \ + for(j = 0;j < numchans;j++) \ + { \ + const ALfloat *in = InBuffer[j]; \ + T *restrict out = (T*)OutBuffer + j; \ + for(i = 0;i < SamplesToDo;i++) \ + out[i*numchans] = func(in[i]); \ + } \ +} + +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; + ALvoice *voice, *voice_end; + ALeffectslot *slot; + ALsource *source; + ALCcontext *ctx; + FPUCtl oldMode; + ALuint i, c; + + SetMixerFPUMode(&oldMode); + + while(size > 0) + { + SamplesToDo = minu(size, BUFFERSIZE); + for(c = 0;c < device->Dry.NumChannels;c++) + memset(device->Dry.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)); + if(device->Dry.Buffer != device->FOAOut.Buffer) + for(c = 0;c < device->FOAOut.NumChannels;c++) + memset(device->FOAOut.Buffer[c], 0, SamplesToDo*sizeof(ALfloat)); + + IncrementRef(&device->MixCount); + V0(device->Backend,lock)(); + + if((slot=device->DefaultSlot) != NULL) + { + CalcEffectSlotParams(device->DefaultSlot, device); + for(i = 0;i < slot->NumChannels;i++) + memset(slot->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat)); + } + + ctx = ATOMIC_LOAD(&device->ContextList); + while(ctx) + { + ALeffectslot *slotroot; + + slotroot = ATOMIC_LOAD(&ctx->ActiveAuxSlotList); + UpdateContextSources(ctx, slotroot); + + slot = slotroot; + while(slot) + { + for(i = 0;i < slot->NumChannels;i++) + memset(slot->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat)); + slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed); + } + + /* source processing */ + voice = ctx->Voices; + voice_end = voice + ctx->VoiceCount; + for(;voice != voice_end;++voice) + { + ALboolean IsVoiceInit = (voice->Step > 0); + source = voice->Source; + if(source && source->state == AL_PLAYING && IsVoiceInit) + MixSource(voice, source, device, SamplesToDo); + } + + /* effect slot processing */ + slot = slotroot; + while(slot) + { + ALeffectState *state = slot->Params.EffectState; + V(state,process)(SamplesToDo, SAFE_CONST(ALfloatBUFFERSIZE*,slot->WetBuffer), + state->OutBuffer, state->OutChannels); + slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed); + } + + ctx = ctx->next; + } + + if(device->DefaultSlot != NULL) + { + const ALeffectslot *slot = device->DefaultSlot; + ALeffectState *state = slot->Params.EffectState; + V(state,process)(SamplesToDo, slot->WetBuffer, state->OutBuffer, + state->OutChannels); + } + + /* 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; + V0(device->Backend,unlock)(); + IncrementRef(&device->MixCount); + + if(device->Hrtf.Handle) + { + int lidx = GetChannelIdxByName(device->RealOut, FrontLeft); + int ridx = GetChannelIdxByName(device->RealOut, FrontRight); + if(lidx != -1 && ridx != -1) + { + HrtfDirectMixerFunc HrtfMix = SelectHrtfMixer(); + ALuint irsize = device->Hrtf.IrSize; + for(c = 0;c < device->Dry.NumChannels;c++) + { + HrtfMix(device->RealOut.Buffer, lidx, ridx, + device->Dry.Buffer[c], device->Hrtf.Offset, irsize, + device->Hrtf.Coeffs[c], device->Hrtf.Values[c], + SamplesToDo + ); + } + device->Hrtf.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(buffer) + { + ALfloat (*OutBuffer)[BUFFERSIZE] = device->RealOut.Buffer; + ALuint OutChannels = device->RealOut.NumChannels; + +#define WRITE(T, a, b, c, d) do { \ + Write_##T((a), (b), (c), (d)); \ + buffer = (T*)buffer + (c)*(d); \ +} while(0) + switch(device->FmtType) + { + case DevFmtByte: + WRITE(ALbyte, OutBuffer, buffer, SamplesToDo, OutChannels); + break; + case DevFmtUByte: + WRITE(ALubyte, OutBuffer, buffer, SamplesToDo, OutChannels); + break; + case DevFmtShort: + WRITE(ALshort, OutBuffer, buffer, SamplesToDo, OutChannels); + break; + case DevFmtUShort: + WRITE(ALushort, OutBuffer, buffer, SamplesToDo, OutChannels); + break; + case DevFmtInt: + WRITE(ALint, OutBuffer, buffer, SamplesToDo, OutChannels); + break; + case DevFmtUInt: + WRITE(ALuint, OutBuffer, buffer, SamplesToDo, OutChannels); + break; + case DevFmtFloat: + WRITE(ALfloat, OutBuffer, buffer, SamplesToDo, OutChannels); + break; + } +#undef WRITE + } + + size -= SamplesToDo; + } + + RestoreFPUMode(&oldMode); +} + + +ALvoid aluHandleDisconnect(ALCdevice *device) +{ + ALCcontext *Context; + + device->Connected = ALC_FALSE; + + Context = ATOMIC_LOAD(&device->ContextList); + while(Context) + { + ALvoice *voice, *voice_end; + + voice = Context->Voices; + voice_end = voice + Context->VoiceCount; + while(voice != voice_end) + { + ALsource *source = voice->Source; + voice->Source = NULL; + + if(source && source->state == AL_PLAYING) + { + source->state = AL_STOPPED; + ATOMIC_STORE(&source->current_buffer, NULL); + ATOMIC_STORE(&source->position, 0); + ATOMIC_STORE(&source->position_fraction, 0); + } + + voice++; + } + Context->VoiceCount = 0; + + Context = Context->next; + } +} diff --git a/Engine/lib/openal-soft/Alc/alcConfig.c b/Engine/lib/openal-soft/Alc/alcConfig.c new file mode 100644 index 000000000..f83ffd941 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/alcConfig.c @@ -0,0 +1,598 @@ +/** + * 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 + */ + +#ifdef _WIN32 +#ifdef __MINGW32__ +#define _WIN32_IE 0x501 +#else +#define _WIN32_IE 0x400 +#endif +#endif + +#include "config.h" + +#include +#include +#include +#include +#ifdef _WIN32_IE +#include +#include +#endif + +#include "alMain.h" +#include "compat.h" +#include "bool.h" + + +typedef struct ConfigEntry { + char *key; + char *value; +} ConfigEntry; + +typedef struct ConfigBlock { + ConfigEntry *entries; + unsigned int entryCount; +} ConfigBlock; +static ConfigBlock cfgBlock; + + +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; +} + + +static char *expdup(const char *str) +{ + char *output = NULL; + size_t maxlen = 0; + size_t len = 0; + + while(*str != '\0') + { + const char *addstr; + size_t addstrlen; + size_t i; + + if(str[0] != '$') + { + const char *next = strchr(str, '$'); + addstr = str; + addstrlen = next ? (size_t)(next-str) : strlen(str); + + str += addstrlen; + } + else + { + str++; + if(*str == '$') + { + const char *next = strchr(str+1, '$'); + addstr = str; + addstrlen = next ? (size_t)(next-str) : strlen(str); + + str += addstrlen; + } + else + { + 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); + } + } + if(addstrlen == 0) + continue; + + if(addstrlen >= maxlen-len) + { + void *temp = NULL; + size_t newmax; + + newmax = len+addstrlen+1; + if(newmax > maxlen) + temp = realloc(output, newmax); + if(!temp) + { + ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, maxlen); + return output; + } + + output = temp; + maxlen = newmax; + } + + for(i = 0;i < addstrlen;i++) + output[len++] = addstr[i]; + output[len] = '\0'; + } + + return output ? output : calloc(1, 1); +} + + +static void LoadConfigFromFile(FILE *f) +{ + char curSection[128] = ""; + char *buffer = NULL; + size_t maxlen = 0; + ConfigEntry *ent; + + while(readline(f, &buffer, &maxlen)) + { + char *line, *comment; + char key[256] = ""; + char value[256] = ""; + + line = rstrip(lstrip(buffer)); + if(!line[0]) continue; + + if(line[0] == '[') + { + char *section = line+1; + char *endsection; + + endsection = strchr(section, ']'); + if(!endsection || section == endsection) + { + 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; + + if(strcasecmp(section, "general") == 0) + curSection[0] = 0; + else + { + strncpy(curSection, section, sizeof(curSection)-1); + 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) + { + /* sscanf doesn't handle '' or "" as empty values, so clip it + * manually. */ + if(strcmp(value, "\"\"") == 0 || strcmp(value, "''") == 0) + value[0] = 0; + } + else if(sscanf(line, "%255[^=] %255[=]", key, value) == 2) + { + /* Special case for 'key =' */ + value[0] = 0; + } + else + { + ERR("config parse error: malformed option line: \"%s\"\n\n", line); + continue; + } + rstrip(key); + + if(curSection[0] != 0) + { + size_t len = strlen(curSection); + memmove(&key[len+1], key, sizeof(key)-1-len); + key[len] = '/'; + memcpy(key, curSection, len); + } + + /* Check if we already have this option set */ + ent = cfgBlock.entries; + while((unsigned int)(ent-cfgBlock.entries) < cfgBlock.entryCount) + { + if(strcasecmp(ent->key, key) == 0) + break; + ent++; + } + + if((unsigned int)(ent-cfgBlock.entries) >= cfgBlock.entryCount) + { + /* Allocate a new option entry */ + ent = realloc(cfgBlock.entries, (cfgBlock.entryCount+1)*sizeof(ConfigEntry)); + if(!ent) + { + ERR("config parse error: error reallocating config entries\n"); + continue; + } + cfgBlock.entries = ent; + ent = cfgBlock.entries + cfgBlock.entryCount; + cfgBlock.entryCount++; + + ent->key = strdup(key); + ent->value = NULL; + } + + free(ent->value); + ent->value = expdup(value); + + TRACE("found '%s' = '%s'\n", ent->key, ent->value); + } + + free(buffer); +} + +#ifdef _WIN32 +void ReadALConfig(void) +{ + WCHAR buffer[PATH_MAX]; + const WCHAR *str; + al_string ppath; + FILE *f; + + if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE) + { + al_string filepath = AL_STRING_INIT_STATIC(); + al_string_copy_wcstr(&filepath, buffer); + al_string_append_cstr(&filepath, "\\alsoft.ini"); + + TRACE("Loading config %s...\n", al_string_get_cstr(filepath)); + f = al_fopen(al_string_get_cstr(filepath), "rt"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + al_string_deinit(&filepath); + } + + ppath = GetProcPath(); + if(!al_string_empty(ppath)) + { + al_string_append_cstr(&ppath, "\\alsoft.ini"); + TRACE("Loading config %s...\n", al_string_get_cstr(ppath)); + f = al_fopen(al_string_get_cstr(ppath), "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + if((str=_wgetenv(L"ALSOFT_CONF")) != NULL && *str) + { + al_string filepath = AL_STRING_INIT_STATIC(); + al_string_copy_wcstr(&filepath, str); + + TRACE("Loading config %s...\n", al_string_get_cstr(filepath)); + f = al_fopen(al_string_get_cstr(filepath), "rt"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + al_string_deinit(&filepath); + } + + al_string_deinit(&ppath); +} +#else +void ReadALConfig(void) +{ + char buffer[PATH_MAX]; + const char *str; + al_string ppath; + FILE *f; + + str = "/etc/openal/alsoft.conf"; + + TRACE("Loading config %s...\n", str); + f = al_fopen(str, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + + if(!(str=getenv("XDG_CONFIG_DIRS")) || str[0] == 0) + str = "/etc/xdg"; + strncpy(buffer, str, sizeof(buffer)-1); + buffer[sizeof(buffer)-1] = 0; + /* Go through the list in reverse, since "the order of base directories + * denotes their importance; the first directory listed is the most + * important". Ergo, we need to load the settings from the later dirs + * first so that the settings in the earlier dirs override them. + */ + while(1) + { + char *next = strrchr(buffer, ':'); + if(next) *(next++) = 0; + else next = buffer; + + if(next[0] != '/') + WARN("Ignoring XDG config dir: %s\n", next); + else + { + size_t len = strlen(next); + strncpy(next+len, "/alsoft.conf", buffer+sizeof(buffer)-next-len); + buffer[sizeof(buffer)-1] = 0; + + TRACE("Loading config %s...\n", next); + f = al_fopen(next, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + if(next == buffer) + break; + } + + if((str=getenv("HOME")) != NULL && *str) + { + snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str); + + TRACE("Loading config %s...\n", buffer); + f = al_fopen(buffer, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + if((str=getenv("XDG_CONFIG_HOME")) != NULL && str[0] != 0) + snprintf(buffer, sizeof(buffer), "%s/%s", str, "alsoft.conf"); + else + { + buffer[0] = 0; + if((str=getenv("HOME")) != NULL && str[0] != 0) + snprintf(buffer, sizeof(buffer), "%s/.config/%s", str, "alsoft.conf"); + } + if(buffer[0] != 0) + { + TRACE("Loading config %s...\n", buffer); + f = al_fopen(buffer, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + ppath = GetProcPath(); + if(!al_string_empty(ppath)) + { + al_string_append_cstr(&ppath, "/alsoft.conf"); + TRACE("Loading config %s...\n", al_string_get_cstr(ppath)); + f = al_fopen(al_string_get_cstr(ppath), "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + if((str=getenv("ALSOFT_CONF")) != NULL && *str) + { + TRACE("Loading config %s...\n", str); + f = al_fopen(str, "r"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } + + al_string_deinit(&ppath); +} +#endif + +void FreeALConfig(void) +{ + unsigned int i; + + for(i = 0;i < cfgBlock.entryCount;i++) + { + free(cfgBlock.entries[i].key); + free(cfgBlock.entries[i].value); + } + free(cfgBlock.entries); +} + +const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def) +{ + unsigned int i; + char key[256]; + + if(!keyName) + return def; + + if(blockName && strcasecmp(blockName, "general") != 0) + { + if(devName) + snprintf(key, sizeof(key), "%s/%s/%s", blockName, devName, keyName); + else + snprintf(key, sizeof(key), "%s/%s", blockName, keyName); + } + else + { + 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(strcmp(cfgBlock.entries[i].key, key) == 0) + { + TRACE("Found %s = \"%s\"\n", key, cfgBlock.entries[i].value); + if(cfgBlock.entries[i].value[0]) + return cfgBlock.entries[i].value; + return def; + } + } + + if(!devName) + { + TRACE("Key %s not found\n", key); + return def; + } + return GetConfigValue(NULL, blockName, keyName, def); +} + +int ConfigValueExists(const char *devName, const char *blockName, const char *keyName) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + return !!val[0]; +} + +int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + + *ret = val; + return 1; +} + +int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + + *ret = strtol(val, NULL, 0); + return 1; +} + +int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + + *ret = strtoul(val, NULL, 0); + return 1; +} + +int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret) +{ + const char *val = GetConfigValue(devName, blockName, keyName, ""); + if(!val[0]) return 0; + +#ifdef HAVE_STRTOF + *ret = strtof(val, NULL); +#else + *ret = (float)strtod(val, NULL); +#endif + return 1; +} + +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(devName, blockName, keyName, ""); + + if(!val[0]) return !!def; + return (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 || + strcasecmp(val, "on") == 0 || atoi(val) != 0); +} diff --git a/Engine/lib/openal-soft/Alc/alcRing.c b/Engine/lib/openal-soft/Alc/alcRing.c new file mode 100644 index 000000000..5994f1967 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/alcRing.c @@ -0,0 +1,301 @@ +/** + * 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 +#include + +#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 { + volatile size_t write_ptr; + volatile size_t read_ptr; + size_t size; + size_t size_mask; + size_t elem_size; + int mlocked; + + alignas(16) char buf[]; +}; + +/* Create a new ringbuffer to hold at least `sz' elements of `elem_sz' bytes. + * The number of elements is rounded up to the next power of two. */ +ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz) +{ + ll_ringbuffer_t *rb; + ALuint power_of_two; + + power_of_two = NextPowerOf2(sz); + if(power_of_two < sz) + return NULL; + + rb = al_malloc(16, sizeof(*rb) + power_of_two*elem_sz); + if(!rb) return NULL; + + rb->size = power_of_two; + rb->size_mask = rb->size - 1; + rb->elem_size = elem_sz; + rb->write_ptr = 0; + rb->read_ptr = 0; + rb->mlocked = 0; + return rb; +} + +/* Free all data associated with the ringbuffer `rb'. */ +void ll_ringbuffer_free(ll_ringbuffer_t *rb) +{ + if(rb) + { +#ifdef USE_MLOCK + if(rb->mlocked) + munlock(rb, sizeof(*rb) + rb->size*rb->elem_size); +#endif /* USE_MLOCK */ + al_free(rb); + } +} + +/* Lock the data block of `rb' using the system call 'mlock'. */ +int ll_ringbuffer_mlock(ll_ringbuffer_t *rb) +{ +#ifdef USE_MLOCK + if(!rb->locked && mlock(rb, sizeof(*rb) + rb->size*rb->elem_size)) + return -1; +#endif /* USE_MLOCK */ + rb->mlocked = 1; + return 0; +} + +/* Reset the read and write pointers to zero. This is not thread safe. */ +void ll_ringbuffer_reset(ll_ringbuffer_t *rb) +{ + rb->read_ptr = 0; + rb->write_ptr = 0; + memset(rb->buf, 0, rb->size*rb->elem_size); +} + +/* Return the number of elements available for reading. This is the number of + * elements in front of the read pointer and behind the write pointer. */ +size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb) +{ + size_t w = rb->write_ptr; + size_t r = rb->read_ptr; + return (rb->size+w-r) & rb->size_mask; +} +/* Return the number of elements available for writing. This is the number of + * elements in front of the write pointer and behind the read pointer. */ +size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb) +{ + size_t w = rb->write_ptr; + size_t r = rb->read_ptr; + return (rb->size+r-w-1) & rb->size_mask; +} + +/* The copying data reader. Copy at most `cnt' elements from `rb' to `dest'. + * Returns the actual number of elements copied. */ +size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + + free_cnt = ll_ringbuffer_read_space(rb); + if(free_cnt == 0) return 0; + + to_read = (cnt > free_cnt) ? free_cnt : cnt; + cnt2 = rb->read_ptr + to_read; + if(cnt2 > rb->size) + { + n1 = rb->size - rb->read_ptr; + n2 = cnt2 & rb->size_mask; + } + else + { + n1 = to_read; + n2 = 0; + } + + memcpy(dest, &(rb->buf[rb->read_ptr*rb->elem_size]), n1*rb->elem_size); + rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask; + if(n2) + { + memcpy(dest + n1*rb->elem_size, &(rb->buf[rb->read_ptr*rb->elem_size]), n2*rb->elem_size); + rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask; + } + return to_read; +} + +/* The copying data reader w/o read pointer advance. Copy at most `cnt' + * elements from `rb' to `dest'. Returns the actual number of elements copied. + */ +size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_read; + size_t n1, n2; + size_t tmp_read_ptr; + + tmp_read_ptr = rb->read_ptr; + free_cnt = ll_ringbuffer_read_space(rb); + if(free_cnt == 0) return 0; + + to_read = (cnt > free_cnt) ? free_cnt : cnt; + cnt2 = tmp_read_ptr + to_read; + if(cnt2 > rb->size) + { + n1 = rb->size - tmp_read_ptr; + n2 = cnt2 & rb->size_mask; + } + else + { + n1 = to_read; + n2 = 0; + } + + memcpy(dest, &(rb->buf[tmp_read_ptr*rb->elem_size]), n1*rb->elem_size); + tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask; + if(n2) + memcpy(dest + n1*rb->elem_size, &(rb->buf[tmp_read_ptr*rb->elem_size]), n2*rb->elem_size); + return to_read; +} + +/* The copying data writer. Copy at most `cnt' elements to `rb' from `src'. + * Returns the actual number of elements copied. */ +size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt) +{ + size_t free_cnt; + size_t cnt2; + size_t to_write; + size_t n1, n2; + + free_cnt = ll_ringbuffer_write_space(rb); + if(free_cnt == 0) return 0; + + to_write = (cnt > free_cnt) ? free_cnt : cnt; + cnt2 = rb->write_ptr + to_write; + if(cnt2 > rb->size) + { + n1 = rb->size - rb->write_ptr; + n2 = cnt2 & rb->size_mask; + } + else + { + n1 = to_write; + n2 = 0; + } + + memcpy(&(rb->buf[rb->write_ptr*rb->elem_size]), src, n1*rb->elem_size); + rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask; + if(n2) + { + memcpy(&(rb->buf[rb->write_ptr*rb->elem_size]), src + n1*rb->elem_size, n2*rb->elem_size); + rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask; + } + return to_write; +} + +/* Advance the read pointer `cnt' places. */ +void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt) +{ + size_t tmp = (rb->read_ptr + cnt) & rb->size_mask; + rb->read_ptr = tmp; +} + +/* Advance the write pointer `cnt' places. */ +void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt) +{ + size_t tmp = (rb->write_ptr + cnt) & rb->size_mask; + rb->write_ptr = tmp; +} + +/* The non-copying data reader. `vec' is an array of two places. Set the values + * at `vec' to hold the current readable data at `rb'. If the readable data is + * in one segment the second segment has zero length. */ +void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t * vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = rb->write_ptr; + r = rb->read_ptr; + free_cnt = (rb->size+w-r) & rb->size_mask; + + cnt2 = r + free_cnt; + if(cnt2 > rb->size) + { + /* Two part vector: the rest of the buffer after the current write ptr, + * plus some from the start of the buffer. */ + vec[0].buf = (char*)&(rb->buf[r*rb->elem_size]); + vec[0].len = rb->size - r; + vec[1].buf = (char*)rb->buf; + vec[1].len = cnt2 & rb->size_mask; + } + else + { + /* Single part vector: just the rest of the buffer */ + vec[0].buf = (char*)&(rb->buf[r*rb->elem_size]); + vec[0].len = free_cnt; + vec[1].buf = NULL; + vec[1].len = 0; + } +} + +/* The non-copying data writer. `vec' is an array of two places. Set the values + * at `vec' to hold the current writeable data at `rb'. If the writeable data + * is in one segment the second segment has zero length. */ +void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec) +{ + size_t free_cnt; + size_t cnt2; + size_t w, r; + + w = rb->write_ptr; + r = rb->read_ptr; + free_cnt = (rb->size+r-w-1) & rb->size_mask; + + cnt2 = w + free_cnt; + if(cnt2 > rb->size) + { + /* Two part vector: the rest of the buffer after the current write ptr, + * plus some from the start of the buffer. */ + vec[0].buf = (char*)&(rb->buf[w*rb->elem_size]); + vec[0].len = rb->size - w; + vec[1].buf = (char*)rb->buf; + vec[1].len = cnt2 & rb->size_mask; + } + else + { + vec[0].buf = (char*)&(rb->buf[w*rb->elem_size]); + vec[0].len = free_cnt; + vec[1].buf = NULL; + vec[1].len = 0; + } +} diff --git a/Engine/lib/openal-soft/Alc/alstring.h b/Engine/lib/openal-soft/Alc/alstring.h new file mode 100644 index 000000000..6167f5ce1 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/alstring.h @@ -0,0 +1,49 @@ +#ifndef ALSTRING_H +#define ALSTRING_H + +#include + +#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 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 size_t 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_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to); + +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 +/* Windows-only methods to deal with WideChar strings. */ +void al_string_copy_wcstr(al_string *str, const wchar_t *from); +void al_string_append_wcstr(al_string *str, const wchar_t *from); +void al_string_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to); +#endif + +#endif /* ALSTRING_H */ diff --git a/Engine/lib/openal-soft/Alc/ambdec.c b/Engine/lib/openal-soft/Alc/ambdec.c new file mode 100644 index 000000000..255011d5e --- /dev/null +++ b/Engine/lib/openal-soft/Alc/ambdec.c @@ -0,0 +1,557 @@ + +#include "config.h" + +#include "ambdec.h" + +#include +#include +#include + +#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_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) +{ + ALuint 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 al_string_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 al_string_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], ALuint maxrow, FILE *f, char **buffer, size_t *maxlen, char **saveptr) +{ + int gotgains = 0; + ALuint 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) +{ + ALuint 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) +{ + ALuint i; + + al_string_deinit(&conf->Description); + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + { + al_string_deinit(&conf->Speakers[i].Name); + al_string_deinit(&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); + al_string_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_uint(&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; +} diff --git a/Engine/lib/openal-soft/Alc/ambdec.h b/Engine/lib/openal-soft/Alc/ambdec.h new file mode 100644 index 000000000..8a3befc1a --- /dev/null +++ b/Engine/lib/openal-soft/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 */ + ALuint 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 */ diff --git a/Engine/lib/openal-soft/Alc/backends/alsa.c b/Engine/lib/openal-soft/Alc/backends/alsa.c new file mode 100644 index 000000000..7a9045bb0 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/alsa.c @@ -0,0 +1,1394 @@ +/** + * 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 +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" + +#include "backends/base.h" + +#include + + +static const ALCchar alsaDevice[] = "ALSA Default"; + + +#ifdef HAVE_DYNLOAD +#define ALSA_FUNCS(MAGIC) \ + MAGIC(snd_strerror); \ + MAGIC(snd_pcm_open); \ + MAGIC(snd_pcm_close); \ + MAGIC(snd_pcm_nonblock); \ + MAGIC(snd_pcm_frames_to_bytes); \ + MAGIC(snd_pcm_bytes_to_frames); \ + MAGIC(snd_pcm_hw_params_malloc); \ + MAGIC(snd_pcm_hw_params_free); \ + MAGIC(snd_pcm_hw_params_any); \ + MAGIC(snd_pcm_hw_params_current); \ + MAGIC(snd_pcm_hw_params_set_access); \ + MAGIC(snd_pcm_hw_params_set_format); \ + MAGIC(snd_pcm_hw_params_set_channels); \ + MAGIC(snd_pcm_hw_params_set_periods_near); \ + MAGIC(snd_pcm_hw_params_set_rate_near); \ + MAGIC(snd_pcm_hw_params_set_rate); \ + MAGIC(snd_pcm_hw_params_set_rate_resample); \ + MAGIC(snd_pcm_hw_params_set_buffer_time_near); \ + MAGIC(snd_pcm_hw_params_set_period_time_near); \ + MAGIC(snd_pcm_hw_params_set_buffer_size_near); \ + MAGIC(snd_pcm_hw_params_set_period_size_near); \ + MAGIC(snd_pcm_hw_params_set_buffer_size_min); \ + MAGIC(snd_pcm_hw_params_get_buffer_time_min); \ + MAGIC(snd_pcm_hw_params_get_buffer_time_max); \ + MAGIC(snd_pcm_hw_params_get_period_time_min); \ + MAGIC(snd_pcm_hw_params_get_period_time_max); \ + MAGIC(snd_pcm_hw_params_get_buffer_size); \ + MAGIC(snd_pcm_hw_params_get_period_size); \ + MAGIC(snd_pcm_hw_params_get_access); \ + MAGIC(snd_pcm_hw_params_get_periods); \ + MAGIC(snd_pcm_hw_params_test_format); \ + MAGIC(snd_pcm_hw_params_test_channels); \ + MAGIC(snd_pcm_hw_params); \ + MAGIC(snd_pcm_sw_params_malloc); \ + MAGIC(snd_pcm_sw_params_current); \ + MAGIC(snd_pcm_sw_params_set_avail_min); \ + MAGIC(snd_pcm_sw_params_set_stop_threshold); \ + MAGIC(snd_pcm_sw_params); \ + MAGIC(snd_pcm_sw_params_free); \ + MAGIC(snd_pcm_prepare); \ + MAGIC(snd_pcm_start); \ + MAGIC(snd_pcm_resume); \ + MAGIC(snd_pcm_reset); \ + MAGIC(snd_pcm_wait); \ + MAGIC(snd_pcm_delay); \ + MAGIC(snd_pcm_state); \ + MAGIC(snd_pcm_avail_update); \ + MAGIC(snd_pcm_areas_silence); \ + MAGIC(snd_pcm_mmap_begin); \ + MAGIC(snd_pcm_mmap_commit); \ + MAGIC(snd_pcm_readi); \ + MAGIC(snd_pcm_writei); \ + MAGIC(snd_pcm_drain); \ + MAGIC(snd_pcm_drop); \ + MAGIC(snd_pcm_recover); \ + MAGIC(snd_pcm_info_malloc); \ + MAGIC(snd_pcm_info_free); \ + MAGIC(snd_pcm_info_set_device); \ + MAGIC(snd_pcm_info_set_subdevice); \ + MAGIC(snd_pcm_info_set_stream); \ + MAGIC(snd_pcm_info_get_name); \ + MAGIC(snd_ctl_pcm_next_device); \ + MAGIC(snd_ctl_pcm_info); \ + MAGIC(snd_ctl_open); \ + MAGIC(snd_ctl_close); \ + MAGIC(snd_ctl_card_info_malloc); \ + MAGIC(snd_ctl_card_info_free); \ + MAGIC(snd_ctl_card_info); \ + MAGIC(snd_ctl_card_info_get_name); \ + MAGIC(snd_ctl_card_info_get_id); \ + MAGIC(snd_card_next); \ + MAGIC(snd_config_update_free_global) + +static void *alsa_handle; +#define MAKE_FUNC(f) static __typeof(f) * p##f +ALSA_FUNCS(MAKE_FUNC); +#undef MAKE_FUNC + +#define snd_strerror psnd_strerror +#define snd_pcm_open psnd_pcm_open +#define snd_pcm_close psnd_pcm_close +#define snd_pcm_nonblock psnd_pcm_nonblock +#define snd_pcm_frames_to_bytes psnd_pcm_frames_to_bytes +#define snd_pcm_bytes_to_frames psnd_pcm_bytes_to_frames +#define snd_pcm_hw_params_malloc psnd_pcm_hw_params_malloc +#define snd_pcm_hw_params_free psnd_pcm_hw_params_free +#define snd_pcm_hw_params_any psnd_pcm_hw_params_any +#define snd_pcm_hw_params_current psnd_pcm_hw_params_current +#define snd_pcm_hw_params_set_access psnd_pcm_hw_params_set_access +#define snd_pcm_hw_params_set_format psnd_pcm_hw_params_set_format +#define snd_pcm_hw_params_set_channels psnd_pcm_hw_params_set_channels +#define snd_pcm_hw_params_set_periods_near psnd_pcm_hw_params_set_periods_near +#define snd_pcm_hw_params_set_rate_near psnd_pcm_hw_params_set_rate_near +#define snd_pcm_hw_params_set_rate psnd_pcm_hw_params_set_rate +#define snd_pcm_hw_params_set_rate_resample psnd_pcm_hw_params_set_rate_resample +#define snd_pcm_hw_params_set_buffer_time_near psnd_pcm_hw_params_set_buffer_time_near +#define snd_pcm_hw_params_set_period_time_near psnd_pcm_hw_params_set_period_time_near +#define snd_pcm_hw_params_set_buffer_size_near psnd_pcm_hw_params_set_buffer_size_near +#define snd_pcm_hw_params_set_period_size_near psnd_pcm_hw_params_set_period_size_near +#define snd_pcm_hw_params_set_buffer_size_min psnd_pcm_hw_params_set_buffer_size_min +#define snd_pcm_hw_params_get_buffer_time_min psnd_pcm_hw_params_get_buffer_time_min +#define snd_pcm_hw_params_get_buffer_time_max psnd_pcm_hw_params_get_buffer_time_max +#define snd_pcm_hw_params_get_period_time_min psnd_pcm_hw_params_get_period_time_min +#define snd_pcm_hw_params_get_period_time_max psnd_pcm_hw_params_get_period_time_max +#define snd_pcm_hw_params_get_buffer_size psnd_pcm_hw_params_get_buffer_size +#define snd_pcm_hw_params_get_period_size psnd_pcm_hw_params_get_period_size +#define snd_pcm_hw_params_get_access psnd_pcm_hw_params_get_access +#define snd_pcm_hw_params_get_periods psnd_pcm_hw_params_get_periods +#define snd_pcm_hw_params_test_format psnd_pcm_hw_params_test_format +#define snd_pcm_hw_params_test_channels psnd_pcm_hw_params_test_channels +#define snd_pcm_hw_params psnd_pcm_hw_params +#define snd_pcm_sw_params_malloc psnd_pcm_sw_params_malloc +#define snd_pcm_sw_params_current psnd_pcm_sw_params_current +#define snd_pcm_sw_params_set_avail_min psnd_pcm_sw_params_set_avail_min +#define snd_pcm_sw_params_set_stop_threshold psnd_pcm_sw_params_set_stop_threshold +#define snd_pcm_sw_params psnd_pcm_sw_params +#define snd_pcm_sw_params_free psnd_pcm_sw_params_free +#define snd_pcm_prepare psnd_pcm_prepare +#define snd_pcm_start psnd_pcm_start +#define snd_pcm_resume psnd_pcm_resume +#define snd_pcm_reset psnd_pcm_reset +#define snd_pcm_wait psnd_pcm_wait +#define snd_pcm_delay psnd_pcm_delay +#define snd_pcm_state psnd_pcm_state +#define snd_pcm_avail_update psnd_pcm_avail_update +#define snd_pcm_areas_silence psnd_pcm_areas_silence +#define snd_pcm_mmap_begin psnd_pcm_mmap_begin +#define snd_pcm_mmap_commit psnd_pcm_mmap_commit +#define snd_pcm_readi psnd_pcm_readi +#define snd_pcm_writei psnd_pcm_writei +#define snd_pcm_drain psnd_pcm_drain +#define snd_pcm_drop psnd_pcm_drop +#define snd_pcm_recover psnd_pcm_recover +#define snd_pcm_info_malloc psnd_pcm_info_malloc +#define snd_pcm_info_free psnd_pcm_info_free +#define snd_pcm_info_set_device psnd_pcm_info_set_device +#define snd_pcm_info_set_subdevice psnd_pcm_info_set_subdevice +#define snd_pcm_info_set_stream psnd_pcm_info_set_stream +#define snd_pcm_info_get_name psnd_pcm_info_get_name +#define snd_ctl_pcm_next_device psnd_ctl_pcm_next_device +#define snd_ctl_pcm_info psnd_ctl_pcm_info +#define snd_ctl_open psnd_ctl_open +#define snd_ctl_close psnd_ctl_close +#define snd_ctl_card_info_malloc psnd_ctl_card_info_malloc +#define snd_ctl_card_info_free psnd_ctl_card_info_free +#define snd_ctl_card_info psnd_ctl_card_info +#define snd_ctl_card_info_get_name psnd_ctl_card_info_get_name +#define snd_ctl_card_info_get_id psnd_ctl_card_info_get_id +#define snd_card_next psnd_card_next +#define snd_config_update_free_global psnd_config_update_free_global +#endif + + +static ALCboolean alsa_load(void) +{ + ALCboolean error = ALC_FALSE; + +#ifdef HAVE_DYNLOAD + if(!alsa_handle) + { + alsa_handle = LoadLib("libasound.so.2"); + if(!alsa_handle) + return ALC_FALSE; + + error = ALC_FALSE; +#define LOAD_FUNC(f) do { \ + p##f = GetSymbol(alsa_handle, #f); \ + if(p##f == NULL) { \ + error = ALC_TRUE; \ + } \ +} while(0) + ALSA_FUNCS(LOAD_FUNC); +#undef LOAD_FUNC + + if(error) + { + CloseLib(alsa_handle); + alsa_handle = NULL; + return ALC_FALSE; + } + } +#endif + + return !error; +} + + +typedef struct { + al_string name; + al_string device_name; +} DevMap; +TYPEDEF_VECTOR(DevMap, vector_DevMap) + +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; + +static void clear_devlist(vector_DevMap *devlist) +{ +#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 +} + + +static const char *prefix_name(snd_pcm_stream_t stream) +{ + assert(stream == SND_PCM_STREAM_PLAYBACK || stream == SND_PCM_STREAM_CAPTURE); + return (stream==SND_PCM_STREAM_PLAYBACK) ? "device-prefix" : "capture-prefix"; +} + +static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList) +{ + const char *main_prefix = "plughw:"; + snd_ctl_t *handle; + snd_ctl_card_info_t *info; + snd_pcm_info_t *pcminfo; + int card, err, dev; + DevMap entry; + + clear_devlist(DeviceList); + + snd_ctl_card_info_malloc(&info); + snd_pcm_info_malloc(&pcminfo); + + 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(NULL, "alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? + "device" : "capture", "default")); + 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(NULL, "alsa", prefix_name(stream), &main_prefix); + while(card >= 0) + { + const char *card_prefix = main_prefix; + const char *cardname, *cardid; + char name[256]; + + snprintf(name, sizeof(name), "hw:%d", card); + if((err = snd_ctl_open(&handle, name, 0)) < 0) + { + ERR("control open (hw:%d): %s\n", card, snd_strerror(err)); + goto next_card; + } + if((err = snd_ctl_card_info(handle, info)) < 0) + { + ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err)); + snd_ctl_close(handle); + goto next_card; + } + + cardname = snd_ctl_card_info_get_name(info); + cardid = snd_ctl_card_info_get_id(info); + + snprintf(name, sizeof(name), "%s-%s", prefix_name(stream), cardid); + ConfigValueStr(NULL, "alsa", name, &card_prefix); + + dev = -1; + while(1) + { + const char *device_prefix = card_prefix; + const char *devname; + char device[128]; + + if(snd_ctl_pcm_next_device(handle, &dev) < 0) + ERR("snd_ctl_pcm_next_device failed\n"); + if(dev < 0) + break; + + 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 != -ENOENT) + ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err)); + continue; + } + + devname = snd_pcm_info_get_name(pcminfo); + + snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev); + ConfigValueStr(NULL, "alsa", name, &device_prefix); + + snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)", + cardname, devname, cardid, dev); + snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d", + device_prefix, cardid, dev); + + TRACE("Got device \"%s\", \"%s\"\n", name, device); + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.device_name); + al_string_copy_cstr(&entry.name, name); + al_string_copy_cstr(&entry.device_name, device); + VECTOR_PUSH_BACK(*DeviceList, entry); + } + snd_ctl_close(handle); + next_card: + if(snd_card_next(&card) < 0) { + ERR("snd_card_next failed\n"); + break; + } + } + + snd_pcm_info_free(pcminfo); + snd_ctl_card_info_free(info); +} + + +static int verify_state(snd_pcm_t *handle) +{ + snd_pcm_state_t state = snd_pcm_state(handle); + int err; + + switch(state) + { + case SND_PCM_STATE_OPEN: + case SND_PCM_STATE_SETUP: + case SND_PCM_STATE_PREPARED: + case SND_PCM_STATE_RUNNING: + case SND_PCM_STATE_DRAINING: + case SND_PCM_STATE_PAUSED: + /* All Okay */ + break; + + case SND_PCM_STATE_XRUN: + if((err=snd_pcm_recover(handle, -EPIPE, 1)) < 0) + return err; + break; + case SND_PCM_STATE_SUSPENDED: + if((err=snd_pcm_recover(handle, -ESTRPIPE, 1)) < 0) + return err; + break; + case SND_PCM_STATE_DISCONNECTED: + return -ENODEV; + } + + return state; +} + + +typedef struct ALCplaybackAlsa { + DERIVE_FROM_TYPE(ALCbackend); + + snd_pcm_t *pcmHandle; + + ALvoid *buffer; + ALsizei size; + + volatile int killNow; + althrd_t thread; +} ALCplaybackAlsa; + +static int ALCplaybackAlsa_mixerProc(void *ptr); +static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr); + +static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device); +static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, Destruct) +static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name); +static void ALCplaybackAlsa_close(ALCplaybackAlsa *self); +static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self); +static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self); +static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self); +static DECLARE_FORWARD2(ALCplaybackAlsa, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, ALCuint, availableSamples) +static ClockLatency ALCplaybackAlsa_getClockLatency(ALCplaybackAlsa *self); +static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCplaybackAlsa) + +DEFINE_ALCBACKEND_VTABLE(ALCplaybackAlsa); + + +static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCplaybackAlsa, ALCbackend, self); +} + + +static int ALCplaybackAlsa_mixerProc(void *ptr) +{ + ALCplaybackAlsa *self = (ALCplaybackAlsa*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + const snd_pcm_channel_area_t *areas = NULL; + snd_pcm_uframes_t update_size, num_updates; + snd_pcm_sframes_t avail, commitres; + snd_pcm_uframes_t offset, frames; + char *WritePtr; + int err; + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + update_size = device->UpdateSize; + num_updates = device->NumUpdates; + while(!self->killNow) + { + int state = verify_state(self->pcmHandle); + if(state < 0) + { + ERR("Invalid state detected: %s\n", snd_strerror(state)); + ALCplaybackAlsa_lock(self); + aluHandleDisconnect(device); + ALCplaybackAlsa_unlock(self); + break; + } + + avail = snd_pcm_avail_update(self->pcmHandle); + if(avail < 0) + { + ERR("available update failed: %s\n", snd_strerror(avail)); + continue; + } + + if((snd_pcm_uframes_t)avail > update_size*(num_updates+1)) + { + WARN("available samples exceeds the buffer size\n"); + snd_pcm_reset(self->pcmHandle); + continue; + } + + // make sure there's frames to process + if((snd_pcm_uframes_t)avail < update_size) + { + if(state != SND_PCM_STATE_RUNNING) + { + err = snd_pcm_start(self->pcmHandle); + if(err < 0) + { + ERR("start failed: %s\n", snd_strerror(err)); + continue; + } + } + if(snd_pcm_wait(self->pcmHandle, 1000) == 0) + ERR("Wait timeout... buffer size too low?\n"); + continue; + } + avail -= avail%update_size; + + // it is possible that contiguous areas are smaller, thus we use a loop + ALCplaybackAlsa_lock(self); + while(avail > 0) + { + frames = avail; + + err = snd_pcm_mmap_begin(self->pcmHandle, &areas, &offset, &frames); + if(err < 0) + { + ERR("mmap begin error: %s\n", snd_strerror(err)); + break; + } + + WritePtr = (char*)areas->addr + (offset * areas->step / 8); + aluMixData(device, WritePtr, frames); + + commitres = snd_pcm_mmap_commit(self->pcmHandle, offset, frames); + if(commitres < 0 || (commitres-frames) != 0) + { + ERR("mmap commit error: %s\n", + snd_strerror(commitres >= 0 ? -EPIPE : commitres)); + break; + } + + avail -= frames; + } + ALCplaybackAlsa_unlock(self); + } + + return 0; +} + +static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr) +{ + ALCplaybackAlsa *self = (ALCplaybackAlsa*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + snd_pcm_uframes_t update_size, num_updates; + snd_pcm_sframes_t avail; + char *WritePtr; + int err; + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + update_size = device->UpdateSize; + num_updates = device->NumUpdates; + while(!self->killNow) + { + int state = verify_state(self->pcmHandle); + if(state < 0) + { + ERR("Invalid state detected: %s\n", snd_strerror(state)); + ALCplaybackAlsa_lock(self); + aluHandleDisconnect(device); + ALCplaybackAlsa_unlock(self); + break; + } + + avail = snd_pcm_avail_update(self->pcmHandle); + if(avail < 0) + { + ERR("available update failed: %s\n", snd_strerror(avail)); + continue; + } + + if((snd_pcm_uframes_t)avail > update_size*num_updates) + { + WARN("available samples exceeds the buffer size\n"); + snd_pcm_reset(self->pcmHandle); + continue; + } + + if((snd_pcm_uframes_t)avail < update_size) + { + if(state != SND_PCM_STATE_RUNNING) + { + err = snd_pcm_start(self->pcmHandle); + if(err < 0) + { + ERR("start failed: %s\n", snd_strerror(err)); + continue; + } + } + if(snd_pcm_wait(self->pcmHandle, 1000) == 0) + ERR("Wait timeout... buffer size too low?\n"); + continue; + } + + ALCplaybackAlsa_lock(self); + WritePtr = self->buffer; + avail = snd_pcm_bytes_to_frames(self->pcmHandle, self->size); + aluMixData(device, WritePtr, avail); + + while(avail > 0) + { + int ret = snd_pcm_writei(self->pcmHandle, WritePtr, avail); + switch (ret) + { + case -EAGAIN: + continue; +#if ESTRPIPE != EPIPE + case -ESTRPIPE: +#endif + case -EPIPE: + case -EINTR: + ret = snd_pcm_recover(self->pcmHandle, ret, 1); + if(ret < 0) + avail = 0; + break; + default: + if (ret >= 0) + { + WritePtr += snd_pcm_frames_to_bytes(self->pcmHandle, ret); + avail -= ret; + } + break; + } + if (ret < 0) + { + ret = snd_pcm_prepare(self->pcmHandle); + if(ret < 0) + break; + } + } + ALCplaybackAlsa_unlock(self); + } + + return 0; +} + + +static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + const char *driver = NULL; + int err; + + if(name) + { + const DevMap *iter; + + if(VECTOR_SIZE(PlaybackDevices) == 0) + probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices); + +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, name) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(PlaybackDevices)) + return ALC_INVALID_VALUE; + driver = al_string_get_cstr(iter->device_name); + } + else + { + name = alsaDevice; + driver = GetConfigValue(NULL, "alsa", "device", "default"); + } + + TRACE("Opening device \"%s\"\n", driver); + err = snd_pcm_open(&self->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); + if(err < 0) + { + ERR("Could not open playback device '%s': %s\n", driver, snd_strerror(err)); + return ALC_OUT_OF_MEMORY; + } + + /* 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); + + return ALC_NO_ERROR; +} + +static void ALCplaybackAlsa_close(ALCplaybackAlsa *self) +{ + snd_pcm_close(self->pcmHandle); +} + +static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + snd_pcm_uframes_t periodSizeInFrames; + unsigned int periodLen, bufferLen; + snd_pcm_sw_params_t *sp = NULL; + snd_pcm_hw_params_t *hp = NULL; + snd_pcm_format_t format = -1; + snd_pcm_access_t access; + unsigned int periods; + unsigned int rate; + const char *funcerr; + int allowmmap; + int dir; + int err; + + switch(device->FmtType) + { + case DevFmtByte: + format = SND_PCM_FORMAT_S8; + break; + case DevFmtUByte: + format = SND_PCM_FORMAT_U8; + break; + case DevFmtShort: + format = SND_PCM_FORMAT_S16; + break; + case DevFmtUShort: + format = SND_PCM_FORMAT_U16; + break; + case DevFmtInt: + format = SND_PCM_FORMAT_S32; + break; + case DevFmtUInt: + format = SND_PCM_FORMAT_U32; + break; + case DevFmtFloat: + format = SND_PCM_FORMAT_FLOAT; + break; + } + + allowmmap = GetConfigValueBool(al_string_get_cstr(device->DeviceName), "alsa", "mmap", 1); + periods = device->NumUpdates; + periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency; + bufferLen = periodLen * periods; + rate = device->Frequency; + + snd_pcm_hw_params_malloc(&hp); +#define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error + CHECK(snd_pcm_hw_params_any(self->pcmHandle, hp)); + /* set interleaved access */ + if(!allowmmap || snd_pcm_hw_params_set_access(self->pcmHandle, hp, SND_PCM_ACCESS_MMAP_INTERLEAVED) < 0) + { + /* No mmap */ + CHECK(snd_pcm_hw_params_set_access(self->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED)); + } + /* test and set format (implicitly sets sample bits) */ + if(snd_pcm_hw_params_test_format(self->pcmHandle, hp, format) < 0) + { + static const struct { + snd_pcm_format_t format; + enum DevFmtType fmttype; + } formatlist[] = { + { SND_PCM_FORMAT_FLOAT, DevFmtFloat }, + { SND_PCM_FORMAT_S32, DevFmtInt }, + { SND_PCM_FORMAT_U32, DevFmtUInt }, + { SND_PCM_FORMAT_S16, DevFmtShort }, + { SND_PCM_FORMAT_U16, DevFmtUShort }, + { SND_PCM_FORMAT_S8, DevFmtByte }, + { SND_PCM_FORMAT_U8, DevFmtUByte }, + }; + size_t k; + + for(k = 0;k < COUNTOF(formatlist);k++) + { + format = formatlist[k].format; + if(snd_pcm_hw_params_test_format(self->pcmHandle, hp, format) >= 0) + { + device->FmtType = formatlist[k].fmttype; + break; + } + } + } + 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) + { + static const enum DevFmtChannels channellist[] = { + DevFmtStereo, + DevFmtQuad, + DevFmtX51, + DevFmtX71, + DevFmtMono, + }; + size_t k; + + for(k = 0;k < COUNTOF(channellist);k++) + { + if(snd_pcm_hw_params_test_channels(self->pcmHandle, hp, ChannelsFromDevFmt(channellist[k])) >= 0) + { + device->FmtChans = channellist[k]; + break; + } + } + } + CHECK(snd_pcm_hw_params_set_channels(self->pcmHandle, hp, ChannelsFromDevFmt(device->FmtChans))); + /* set rate (implicitly constrains period/buffer parameters) */ + if(!GetConfigValueBool(al_string_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) + ERR("snd_pcm_hw_params_set_buffer_time_near failed: %s\n", snd_strerror(err)); + /* set period time (implicitly sets buffer size/bytes/time and period size/bytes) */ + if((err=snd_pcm_hw_params_set_period_time_near(self->pcmHandle, hp, &periodLen, NULL)) < 0) + ERR("snd_pcm_hw_params_set_period_time_near failed: %s\n", snd_strerror(err)); + /* install and prepare hardware configuration */ + CHECK(snd_pcm_hw_params(self->pcmHandle, hp)); + /* 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, &dir)); + if(dir != 0) + WARN("Inexact period count: %u (%d)\n", periods, dir); + + snd_pcm_hw_params_free(hp); + hp = NULL; + snd_pcm_sw_params_malloc(&sp); + + CHECK(snd_pcm_sw_params_current(self->pcmHandle, sp)); + CHECK(snd_pcm_sw_params_set_avail_min(self->pcmHandle, sp, periodSizeInFrames)); + CHECK(snd_pcm_sw_params_set_stop_threshold(self->pcmHandle, sp, periodSizeInFrames*periods)); + CHECK(snd_pcm_sw_params(self->pcmHandle, sp)); +#undef CHECK + snd_pcm_sw_params_free(sp); + sp = NULL; + + device->NumUpdates = periods; + device->UpdateSize = periodSizeInFrames; + device->Frequency = rate; + + SetDefaultChannelOrder(device); + + return ALC_TRUE; + +error: + ERR("%s failed: %s\n", funcerr, snd_strerror(err)); + if(hp) snd_pcm_hw_params_free(hp); + if(sp) snd_pcm_sw_params_free(sp); + return ALC_FALSE; +} + +static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + int (*thread_func)(void*) = NULL; + snd_pcm_hw_params_t *hp = NULL; + snd_pcm_access_t access; + const char *funcerr; + int err; + + snd_pcm_hw_params_malloc(&hp); +#define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error + CHECK(snd_pcm_hw_params_current(self->pcmHandle, hp)); + /* retrieve configuration info */ + CHECK(snd_pcm_hw_params_get_access(hp, &access)); +#undef CHECK + snd_pcm_hw_params_free(hp); + hp = NULL; + + self->size = snd_pcm_frames_to_bytes(self->pcmHandle, device->UpdateSize); + if(access == SND_PCM_ACCESS_RW_INTERLEAVED) + { + self->buffer = al_malloc(16, self->size); + if(!self->buffer) + { + ERR("buffer malloc failed\n"); + return ALC_FALSE; + } + thread_func = ALCplaybackAlsa_mixerNoMMapProc; + } + else + { + err = snd_pcm_prepare(self->pcmHandle); + if(err < 0) + { + ERR("snd_pcm_prepare(data->pcmHandle) failed: %s\n", snd_strerror(err)); + return ALC_FALSE; + } + thread_func = ALCplaybackAlsa_mixerProc; + } + self->killNow = 0; + if(althrd_create(&self->thread, thread_func, self) != althrd_success) + { + ERR("Could not create playback thread\n"); + al_free(self->buffer); + self->buffer = NULL; + return ALC_FALSE; + } + + return ALC_TRUE; + +error: + ERR("%s failed: %s\n", funcerr, snd_strerror(err)); + if(hp) snd_pcm_hw_params_free(hp); + return ALC_FALSE; +} + +static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self) +{ + int res; + + if(self->killNow) + return; + + self->killNow = 1; + althrd_join(self->thread, &res); + + al_free(self->buffer); + self->buffer = NULL; +} + +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)); + delay = 0; + } + if(delay < 0) delay = 0; + ret.Latency = delay * DEVICE_CLOCK_RES / device->Frequency; + ALCplaybackAlsa_unlock(self); + + return ret; +} + + +typedef struct ALCcaptureAlsa { + DERIVE_FROM_TYPE(ALCbackend); + + snd_pcm_t *pcmHandle; + + ALvoid *buffer; + ALsizei size; + + ALboolean doCapture; + ll_ringbuffer_t *ring; + + snd_pcm_sframes_t last_avail; +} ALCcaptureAlsa; + +static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device); +static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, Destruct) +static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name); +static void ALCcaptureAlsa_close(ALCcaptureAlsa *self); +static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, ALCboolean, reset) +static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self); +static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self); +static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buffer, ALCuint samples); +static ALCuint ALCcaptureAlsa_availableSamples(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) + +DEFINE_ALCBACKEND_VTABLE(ALCcaptureAlsa); + + +static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCcaptureAlsa, ALCbackend, self); +} + + +static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + const char *driver = NULL; + snd_pcm_hw_params_t *hp; + snd_pcm_uframes_t bufferSizeInFrames; + snd_pcm_uframes_t periodSizeInFrames; + ALboolean needring = AL_FALSE; + snd_pcm_format_t format = -1; + const char *funcerr; + int err; + + if(name) + { + const DevMap *iter; + + if(VECTOR_SIZE(CaptureDevices) == 0) + probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices); + +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, name) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(CaptureDevices)) + return ALC_INVALID_VALUE; + driver = al_string_get_cstr(iter->device_name); + } + else + { + name = alsaDevice; + driver = GetConfigValue(NULL, "alsa", "capture", "default"); + } + + TRACE("Opening device \"%s\"\n", driver); + err = snd_pcm_open(&self->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); + if(err < 0) + { + ERR("Could not open capture device '%s': %s\n", driver, snd_strerror(err)); + return ALC_INVALID_VALUE; + } + + /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ + snd_config_update_free_global(); + + switch(device->FmtType) + { + case DevFmtByte: + format = SND_PCM_FORMAT_S8; + break; + case DevFmtUByte: + format = SND_PCM_FORMAT_U8; + break; + case DevFmtShort: + format = SND_PCM_FORMAT_S16; + break; + case DevFmtUShort: + format = SND_PCM_FORMAT_U16; + break; + case DevFmtInt: + format = SND_PCM_FORMAT_S32; + break; + case DevFmtUInt: + format = SND_PCM_FORMAT_U32; + break; + case DevFmtFloat: + format = SND_PCM_FORMAT_FLOAT; + break; + } + + funcerr = NULL; + bufferSizeInFrames = maxu(device->UpdateSize*device->NumUpdates, + 100*device->Frequency/1000); + periodSizeInFrames = minu(bufferSizeInFrames, 25*device->Frequency/1000); + + snd_pcm_hw_params_malloc(&hp); +#define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error + CHECK(snd_pcm_hw_params_any(self->pcmHandle, hp)); + /* set interleaved access */ + CHECK(snd_pcm_hw_params_set_access(self->pcmHandle, hp, SND_PCM_ACCESS_RW_INTERLEAVED)); + /* 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))); + /* 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) */ + if(snd_pcm_hw_params_set_buffer_size_min(self->pcmHandle, hp, &bufferSizeInFrames) < 0) + { + TRACE("Buffer too large, using intermediate ring buffer\n"); + needring = AL_TRUE; + CHECK(snd_pcm_hw_params_set_buffer_size_near(self->pcmHandle, hp, &bufferSizeInFrames)); + } + /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ + CHECK(snd_pcm_hw_params_set_period_size_near(self->pcmHandle, hp, &periodSizeInFrames, NULL)); + /* install and prepare hardware configuration */ + CHECK(snd_pcm_hw_params(self->pcmHandle, hp)); + /* retrieve configuration info */ + CHECK(snd_pcm_hw_params_get_period_size(hp, &periodSizeInFrames, NULL)); +#undef CHECK + snd_pcm_hw_params_free(hp); + hp = NULL; + + if(needring) + { + self->ring = ll_ringbuffer_create( + device->UpdateSize*device->NumUpdates + 1, + FrameSizeFromDevFmt(device->FmtChans, device->FmtType) + ); + if(!self->ring) + { + ERR("ring buffer create failed\n"); + goto error2; + } + } + + al_string_copy_cstr(&device->DeviceName, name); + + return ALC_NO_ERROR; + +error: + ERR("%s failed: %s\n", funcerr, snd_strerror(err)); + if(hp) snd_pcm_hw_params_free(hp); + +error2: + ll_ringbuffer_free(self->ring); + self->ring = NULL; + snd_pcm_close(self->pcmHandle); + + return ALC_INVALID_VALUE; +} + +static void ALCcaptureAlsa_close(ALCcaptureAlsa *self) +{ + snd_pcm_close(self->pcmHandle); + ll_ringbuffer_free(self->ring); + + al_free(self->buffer); + self->buffer = NULL; +} + +static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self) +{ + int err = snd_pcm_start(self->pcmHandle); + if(err < 0) + { + ERR("start failed: %s\n", snd_strerror(err)); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + return ALC_FALSE; + } + + self->doCapture = AL_TRUE; + return ALC_TRUE; +} + +static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self) +{ + ALCuint avail; + int err; + + /* OpenAL requires access to unread audio after stopping, but ALSA's + * snd_pcm_drain is unreliable and snd_pcm_drop drops it. Capture what's + * available now so it'll be available later after the drop. */ + avail = ALCcaptureAlsa_availableSamples(self); + if(!self->ring && avail > 0) + { + /* The ring buffer implicitly captures when checking availability. + * Direct access needs to explicitly capture it into temp storage. */ + ALsizei size; + void *ptr; + + size = snd_pcm_frames_to_bytes(self->pcmHandle, avail); + ptr = al_malloc(16, size); + if(ptr) + { + ALCcaptureAlsa_captureSamples(self, ptr, avail); + al_free(self->buffer); + self->buffer = ptr; + self->size = size; + } + } + err = snd_pcm_drop(self->pcmHandle); + if(err < 0) + ERR("drop failed: %s\n", snd_strerror(err)); + self->doCapture = AL_FALSE; +} + +static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buffer, ALCuint samples) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + + if(self->ring) + { + ll_ringbuffer_read(self->ring, buffer, samples); + return ALC_NO_ERROR; + } + + self->last_avail -= samples; + while(device->Connected && samples > 0) + { + snd_pcm_sframes_t amt = 0; + + if(self->size > 0) + { + /* First get any data stored from the last stop */ + amt = snd_pcm_bytes_to_frames(self->pcmHandle, self->size); + if((snd_pcm_uframes_t)amt > samples) amt = samples; + + amt = snd_pcm_frames_to_bytes(self->pcmHandle, amt); + memcpy(buffer, self->buffer, amt); + + if(self->size > amt) + { + memmove(self->buffer, self->buffer+amt, self->size - amt); + self->size -= amt; + } + else + { + al_free(self->buffer); + self->buffer = NULL; + self->size = 0; + } + amt = snd_pcm_bytes_to_frames(self->pcmHandle, amt); + } + else if(self->doCapture) + amt = snd_pcm_readi(self->pcmHandle, buffer, samples); + if(amt < 0) + { + ERR("read error: %s\n", snd_strerror(amt)); + + if(amt == -EAGAIN) + continue; + if((amt=snd_pcm_recover(self->pcmHandle, amt, 1)) >= 0) + { + amt = snd_pcm_start(self->pcmHandle); + if(amt >= 0) + amt = snd_pcm_avail_update(self->pcmHandle); + } + if(amt < 0) + { + ERR("restore error: %s\n", snd_strerror(amt)); + aluHandleDisconnect(device); + break; + } + /* If the amount available is less than what's asked, we lost it + * during recovery. So just give silence instead. */ + if((snd_pcm_uframes_t)amt < samples) + break; + continue; + } + + buffer = (ALbyte*)buffer + amt; + samples -= amt; + } + if(samples > 0) + memset(buffer, ((device->FmtType == DevFmtUByte) ? 0x80 : 0), + snd_pcm_frames_to_bytes(self->pcmHandle, samples)); + + return ALC_NO_ERROR; +} + +static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + snd_pcm_sframes_t avail = 0; + + if(device->Connected && self->doCapture) + avail = snd_pcm_avail_update(self->pcmHandle); + if(avail < 0) + { + ERR("avail update failed: %s\n", snd_strerror(avail)); + + if((avail=snd_pcm_recover(self->pcmHandle, avail, 1)) >= 0) + { + if(self->doCapture) + avail = snd_pcm_start(self->pcmHandle); + if(avail >= 0) + avail = snd_pcm_avail_update(self->pcmHandle); + } + if(avail < 0) + { + ERR("restore error: %s\n", snd_strerror(avail)); + aluHandleDisconnect(device); + } + } + + if(!self->ring) + { + if(avail < 0) avail = 0; + avail += snd_pcm_bytes_to_frames(self->pcmHandle, self->size); + if(avail > self->last_avail) self->last_avail = avail; + return self->last_avail; + } + + while(avail > 0) + { + ll_ringbuffer_data_t vec[2]; + snd_pcm_sframes_t amt; + + ll_ringbuffer_get_write_vector(self->ring, vec); + if(vec[0].len == 0) break; + + 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)); + + if(amt == -EAGAIN) + continue; + if((amt=snd_pcm_recover(self->pcmHandle, amt, 1)) >= 0) + { + if(self->doCapture) + amt = snd_pcm_start(self->pcmHandle); + if(amt >= 0) + amt = snd_pcm_avail_update(self->pcmHandle); + } + if(amt < 0) + { + ERR("restore error: %s\n", snd_strerror(amt)); + aluHandleDisconnect(device); + break; + } + avail = amt; + continue; + } + + ll_ringbuffer_write_advance(self->ring, amt); + avail -= amt; + } + + return ll_ringbuffer_read_space(self->ring); +} + +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)); + delay = 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)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } + +typedef struct ALCalsaBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCalsaBackendFactory; +#define ALCALSABACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCalsaBackendFactory, ALCbackendFactory) } } + +static ALCboolean ALCalsaBackendFactory_init(ALCalsaBackendFactory* UNUSED(self)) +{ + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + + if(!alsa_load()) + return ALC_FALSE; + return ALC_TRUE; +} + +static void ALCalsaBackendFactory_deinit(ALCalsaBackendFactory* UNUSED(self)) +{ + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); + + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); + +#ifdef HAVE_DYNLOAD + if(alsa_handle) + CloseLib(alsa_handle); + alsa_handle = NULL; +#endif +} + +static ALCboolean ALCalsaBackendFactory_querySupport(ALCalsaBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback || type == ALCbackend_Capture) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCalsaBackendFactory_probe(ALCalsaBackendFactory* UNUSED(self), enum DevProbe type) +{ + switch(type) + { + case ALL_DEVICE_PROBE: + probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); + break; + + case CAPTURE_DEVICE_PROBE: + probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); + break; + } +} + +static ALCbackend* ALCalsaBackendFactory_createBackend(ALCalsaBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCplaybackAlsa *backend; + NEW_OBJ(backend, ALCplaybackAlsa)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + if(type == ALCbackend_Capture) + { + ALCcaptureAlsa *backend; + NEW_OBJ(backend, ALCcaptureAlsa)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} + +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCalsaBackendFactory); + + +ALCbackendFactory *ALCalsaBackendFactory_getFactory(void) +{ + static ALCalsaBackendFactory factory = ALCALSABACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} diff --git a/Engine/lib/openal-soft/Alc/backends/base.c b/Engine/lib/openal-soft/Alc/backends/base.c new file mode 100644 index 000000000..ff808f535 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/base.c @@ -0,0 +1,225 @@ + +#include "config.h" + +#include + +#include "alMain.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; + ClockLatency ret; + + almtx_lock(&self->mMutex); + ret.ClockTime = GetDeviceClockTime(device); + // TODO: Perhaps should be NumUpdates-1 worth of UpdateSize? + ret.Latency = 0; + almtx_unlock(&self->mMutex); + + 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)) +{ +} + + +/* 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 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); + +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); +} + + +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 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 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); +} + + +ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + PlaybackWrapper *backend; + + NEW_OBJ(backend, PlaybackWrapper)(device, funcs); + if(!backend) return NULL; + + return STATIC_CAST(ALCbackend, backend); + } + + if(type == ALCbackend_Capture) + { + CaptureWrapper *backend; + + NEW_OBJ(backend, CaptureWrapper)(device, funcs); + if(!backend) return NULL; + + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} diff --git a/Engine/lib/openal-soft/Alc/backends/base.h b/Engine/lib/openal-soft/Alc/backends/base.h new file mode 100644 index 000000000..04795b368 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/base.h @@ -0,0 +1,153 @@ +#ifndef AL_BACKENDS_BASE_H +#define AL_BACKENDS_BASE_H + +#include "alMain.h" +#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 { + const struct ALCbackendVtable *vtbl; + + ALCdevice *mDevice; + + almtx_t mMutex; +} ALCbackend; + +void ALCbackend_Construct(ALCbackend *self, ALCdevice *device); +void ALCbackend_Destruct(ALCbackend *self); +ALCboolean ALCbackend_reset(ALCbackend *self); +ALCenum ALCbackend_captureSamples(ALCbackend *self, void *buffer, ALCuint samples); +ALCuint ALCbackend_availableSamples(ALCbackend *self); +ClockLatency ALCbackend_getClockLatency(ALCbackend *self); +void ALCbackend_lock(ALCbackend *self); +void ALCbackend_unlock(ALCbackend *self); + +struct ALCbackendVtable { + void (*const Destruct)(ALCbackend*); + + ALCenum (*const open)(ALCbackend*, const ALCchar*); + void (*const close)(ALCbackend*); + + ALCboolean (*const reset)(ALCbackend*); + ALCboolean (*const start)(ALCbackend*); + void (*const stop)(ALCbackend*); + + ALCenum (*const captureSamples)(ALCbackend*, void*, ALCuint); + ALCuint (*const availableSamples)(ALCbackend*); + + ClockLatency (*const getClockLatency)(ALCbackend*); + + void (*const lock)(ALCbackend*); + void (*const unlock)(ALCbackend*); + + void (*const Delete)(void*); +}; + +#define DEFINE_ALCBACKEND_VTABLE(T) \ +DECLARE_THUNK(T, ALCbackend, void, Destruct) \ +DECLARE_THUNK1(T, ALCbackend, ALCenum, open, const ALCchar*) \ +DECLARE_THUNK(T, ALCbackend, void, close) \ +DECLARE_THUNK(T, ALCbackend, ALCboolean, reset) \ +DECLARE_THUNK(T, ALCbackend, ALCboolean, start) \ +DECLARE_THUNK(T, ALCbackend, void, stop) \ +DECLARE_THUNK2(T, ALCbackend, ALCenum, captureSamples, void*, ALCuint) \ +DECLARE_THUNK(T, ALCbackend, ALCuint, availableSamples) \ +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) \ +{ T##_Delete(STATIC_UPCAST(T, ALCbackend, (ALCbackend*)ptr)); } \ + \ +static const struct ALCbackendVtable T##_ALCbackend_vtable = { \ + T##_ALCbackend_Destruct, \ + \ + T##_ALCbackend_open, \ + T##_ALCbackend_close, \ + T##_ALCbackend_reset, \ + T##_ALCbackend_start, \ + T##_ALCbackend_stop, \ + T##_ALCbackend_captureSamples, \ + T##_ALCbackend_availableSamples, \ + T##_ALCbackend_getClockLatency, \ + T##_ALCbackend_lock, \ + T##_ALCbackend_unlock, \ + \ + T##_ALCbackend_Delete, \ +} + + +typedef enum ALCbackend_Type { + ALCbackend_Playback, + ALCbackend_Capture, + ALCbackend_Loopback +} ALCbackend_Type; + + +struct ALCbackendFactoryVtable; + +typedef struct ALCbackendFactory { + const struct ALCbackendFactoryVtable *vtbl; +} ALCbackendFactory; + +void ALCbackendFactory_deinit(ALCbackendFactory *self); + +struct ALCbackendFactoryVtable { + ALCboolean (*const init)(ALCbackendFactory *self); + void (*const deinit)(ALCbackendFactory *self); + + ALCboolean (*const querySupport)(ALCbackendFactory *self, ALCbackend_Type type); + + void (*const probe)(ALCbackendFactory *self, enum DevProbe type); + + ALCbackend* (*const createBackend)(ALCbackendFactory *self, ALCdevice *device, ALCbackend_Type type); +}; + +#define DEFINE_ALCBACKENDFACTORY_VTABLE(T) \ +DECLARE_THUNK(T, ALCbackendFactory, ALCboolean, init) \ +DECLARE_THUNK(T, ALCbackendFactory, void, deinit) \ +DECLARE_THUNK1(T, ALCbackendFactory, ALCboolean, querySupport, ALCbackend_Type) \ +DECLARE_THUNK1(T, ALCbackendFactory, void, probe, enum DevProbe) \ +DECLARE_THUNK2(T, ALCbackendFactory, ALCbackend*, createBackend, ALCdevice*, ALCbackend_Type) \ + \ +static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = { \ + T##_ALCbackendFactory_init, \ + T##_ALCbackendFactory_deinit, \ + T##_ALCbackendFactory_querySupport, \ + T##_ALCbackendFactory_probe, \ + T##_ALCbackendFactory_createBackend, \ +} + + +ALCbackendFactory *ALCpulseBackendFactory_getFactory(void); +ALCbackendFactory *ALCalsaBackendFactory_getFactory(void); +ALCbackendFactory *ALCossBackendFactory_getFactory(void); +ALCbackendFactory *ALCjackBackendFactory_getFactory(void); +ALCbackendFactory *ALCsolarisBackendFactory_getFactory(void); +ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void); +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); +ALCbackendFactory *ALCwinmmBackendFactory_getFactory(void); +ALCbackendFactory *ALCportBackendFactory_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 */ diff --git a/Engine/lib/openal-soft/Alc/backends/coreaudio.c b/Engine/lib/openal-soft/Alc/backends/coreaudio.c new file mode 100644 index 000000000..24aeabd42 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/coreaudio.c @@ -0,0 +1,724 @@ +/** + * 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 +#include +#include +#include + +#include "alMain.h" +#include "alu.h" + +#include +#include +#include +#include + + +typedef struct { + AudioUnit audioUnit; + + ALuint frameSize; + ALdouble sampleRateRatio; // Ratio of hardware sample rate / requested sample rate + AudioStreamBasicDescription format; // This is the OpenAL format as a CoreAudio ASBD + + AudioConverterRef audioConverter; // Sample rate converter if needed + AudioBufferList *bufferList; // Buffer for data coming from the input device + ALCvoid *resampleBuffer; // Buffer for returned RingBuffer data when resampling + + ll_ringbuffer_t *ring; +} ca_data; + +static const ALCchar ca_device[] = "CoreAudio Default"; + + +static 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; + + list = calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer)); + if(list) + { + list->mNumberBuffers = 1; + + list->mBuffers[0].mNumberChannels = channelCount; + list->mBuffers[0].mDataByteSize = byteSize; + list->mBuffers[0].mData = malloc(byteSize); + if(list->mBuffers[0].mData == NULL) + { + free(list); + list = NULL; + } + } + return list; +} + +static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, + UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) +{ + 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; +} + +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 + ll_ringbuffer_read(data->ring, data->resampleBuffer, *ioNumberDataPackets); + + // 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; + + return noErr; +} + +static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, + const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, + UInt32 inNumberFrames, AudioBufferList *ioData) +{ + ALCdevice *device = (ALCdevice*)inRefCon; + ca_data *data = (ca_data*)device->ExtraData; + AudioUnitRenderActionFlags flags = 0; + OSStatus err; + + // 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; + } + + ll_ringbuffer_write(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames); + + return noErr; +} + +static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) +{ + AudioComponentDescription desc; + AudioComponent comp; + ca_data *data; + OSStatus err; + + if(!deviceName) + deviceName = ca_device; + else if(strcmp(deviceName, ca_device) != 0) + return ALC_INVALID_VALUE; + + /* open the default output unit */ + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_DefaultOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + comp = AudioComponentFindNext(NULL, &desc); + if(comp == NULL) + { + ERR("AudioComponentFindNext failed\n"); + return ALC_INVALID_VALUE; + } + + data = calloc(1, sizeof(*data)); + + err = AudioComponentInstanceNew(comp, &data->audioUnit); + if(err != noErr) + { + ERR("AudioComponentInstanceNew failed\n"); + free(data); + return ALC_INVALID_VALUE; + } + + /* init and start the default audio unit... */ + err = AudioUnitInitialize(data->audioUnit); + if(err != noErr) + { + ERR("AudioUnitInitialize failed\n"); + AudioComponentInstanceDispose(data->audioUnit); + free(data); + return ALC_INVALID_VALUE; + } + + al_string_copy_cstr(&device->DeviceName, deviceName); + device->ExtraData = data; + return ALC_NO_ERROR; +} + +static void ca_close_playback(ALCdevice *device) +{ + ca_data *data = (ca_data*)device->ExtraData; + + AudioUnitUninitialize(data->audioUnit); + AudioComponentInstanceDispose(data->audioUnit); + + free(data); + device->ExtraData = NULL; +} + +static ALCboolean ca_reset_playback(ALCdevice *device) +{ + ca_data *data = (ca_data*)device->ExtraData; + AudioStreamBasicDescription streamFormat; + AURenderCallbackStruct input; + OSStatus err; + UInt32 size; + + err = AudioUnitUninitialize(data->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); + if(err != noErr || size != sizeof(AudioStreamBasicDescription)) + { + ERR("AudioUnitGetProperty failed\n"); + return ALC_FALSE; + } + +#if 0 + TRACE("Output streamFormat of default output unit -\n"); + TRACE(" streamFormat.mFramesPerPacket = %d\n", streamFormat.mFramesPerPacket); + TRACE(" streamFormat.mChannelsPerFrame = %d\n", streamFormat.mChannelsPerFrame); + TRACE(" streamFormat.mBitsPerChannel = %d\n", streamFormat.mBitsPerChannel); + TRACE(" streamFormat.mBytesPerPacket = %d\n", streamFormat.mBytesPerPacket); + TRACE(" streamFormat.mBytesPerFrame = %d\n", streamFormat.mBytesPerFrame); + TRACE(" streamFormat.mSampleRate = %5.0f\n", streamFormat.mSampleRate); +#endif + + /* set default output unit's input side to match output side */ + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed\n"); + return ALC_FALSE; + } + + if(device->Frequency != streamFormat.mSampleRate) + { + device->NumUpdates = (ALuint)((ALuint64)device->NumUpdates * + streamFormat.mSampleRate / + device->Frequency); + device->Frequency = streamFormat.mSampleRate; + } + + /* FIXME: How to tell what channels are what in the output device, and how + * to specify what we're giving? eg, 6.0 vs 5.1 */ + switch(streamFormat.mChannelsPerFrame) + { + 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: + ERR("Unhandled channel count (%d), using Stereo\n", streamFormat.mChannelsPerFrame); + device->FmtChans = DevFmtStereo; + streamFormat.mChannelsPerFrame = 2; + break; + } + SetDefaultWFXChannelOrder(device); + + /* use channel count and sample rate from the default output unit's current + * parameters, but reset everything else */ + streamFormat.mFramesPerPacket = 1; + streamFormat.mFormatFlags = 0; + switch(device->FmtType) + { + case DevFmtUByte: + device->FmtType = DevFmtByte; + /* fall-through */ + case DevFmtByte: + streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; + streamFormat.mBitsPerChannel = 8; + break; + case DevFmtUShort: + device->FmtType = DevFmtShort; + /* fall-through */ + case DevFmtShort: + streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; + streamFormat.mBitsPerChannel = 16; + break; + case DevFmtUInt: + device->FmtType = DevFmtInt; + /* fall-through */ + case DevFmtInt: + streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; + streamFormat.mBitsPerChannel = 32; + break; + case DevFmtFloat: + streamFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat; + streamFormat.mBitsPerChannel = 32; + break; + } + streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame * + streamFormat.mBitsPerChannel / 8; + streamFormat.mBytesPerPacket = streamFormat.mBytesPerFrame; + streamFormat.mFormatID = kAudioFormatLinearPCM; + streamFormat.mFormatFlags |= kAudioFormatFlagsNativeEndian | + kLinearPCMFormatFlagIsPacked; + + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription)); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed\n"); + return ALC_FALSE; + } + + /* setup callback */ + data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + input.inputProc = ca_callback; + input.inputProcRefCon = device; + + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct)); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed\n"); + return ALC_FALSE; + } + + /* init the default audio unit... */ + err = AudioUnitInitialize(data->audioUnit); + if(err != noErr) + { + ERR("AudioUnitInitialize failed\n"); + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static ALCboolean ca_start_playback(ALCdevice *device) +{ + ca_data *data = (ca_data*)device->ExtraData; + OSStatus err; + + err = AudioOutputUnitStart(data->audioUnit); + if(err != noErr) + { + ERR("AudioOutputUnitStart failed\n"); + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static void ca_stop_playback(ALCdevice *device) +{ + ca_data *data = (ca_data*)device->ExtraData; + OSStatus err; + + err = AudioOutputUnitStop(data->audioUnit); + if(err != noErr) + ERR("AudioOutputUnitStop failed\n"); +} + +static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) +{ + AudioStreamBasicDescription requestedFormat; // The application requested format + AudioStreamBasicDescription hardwareFormat; // The hardware format + AudioStreamBasicDescription outputFormat; // The AudioUnit output format + AURenderCallbackStruct input; + AudioComponentDescription desc; + AudioDeviceID inputDevice; + UInt32 outputFrameCount; + UInt32 propertySize; + AudioObjectPropertyAddress propertyAddress; + UInt32 enableIO; + AudioComponent comp; + ca_data *data; + OSStatus err; + + if(!deviceName) + deviceName = ca_device; + else if(strcmp(deviceName, ca_device) != 0) + return ALC_INVALID_VALUE; + + desc.componentType = kAudioUnitType_Output; + desc.componentSubType = kAudioUnitSubType_HALOutput; + desc.componentManufacturer = kAudioUnitManufacturer_Apple; + desc.componentFlags = 0; + desc.componentFlagsMask = 0; + + // Search for component with given description + comp = AudioComponentFindNext(NULL, &desc); + if(comp == NULL) + { + ERR("AudioComponentFindNext failed\n"); + return ALC_INVALID_VALUE; + } + + data = calloc(1, sizeof(*data)); + device->ExtraData = data; + + // Open the component + err = AudioComponentInstanceNew(comp, &data->audioUnit); + if(err != noErr) + { + ERR("AudioComponentInstanceNew failed\n"); + goto error; + } + + // Turn off AudioUnit output + enableIO = 0; + err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint)); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed\n"); + goto error; + } + + // Turn on AudioUnit input + enableIO = 1; + err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint)); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed\n"); + goto error; + } + + // Get the default input device + + propertySize = sizeof(AudioDeviceID); + propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice; + propertyAddress.mScope = kAudioObjectPropertyScopeGlobal; + propertyAddress.mElement = kAudioObjectPropertyElementMaster; + + err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, NULL, &propertySize, &inputDevice); + if(err != noErr) + { + ERR("AudioObjectGetPropertyData failed\n"); + goto error; + } + + if(inputDevice == kAudioDeviceUnknown) + { + ERR("No input device found\n"); + goto error; + } + + // Track the input device + err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID)); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed\n"); + goto error; + } + + // set capture callback + input.inputProc = ca_capture_callback; + input.inputProcRefCon = device; + + err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct)); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed\n"); + goto error; + } + + // Initialize the device + err = AudioUnitInitialize(data->audioUnit); + if(err != noErr) + { + ERR("AudioUnitInitialize failed\n"); + goto error; + } + + // Get the hardware format + propertySize = sizeof(AudioStreamBasicDescription); + err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize); + if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription)) + { + ERR("AudioUnitGetProperty failed\n"); + goto error; + } + + // Set up the requested format description + switch(device->FmtType) + { + case DevFmtUByte: + requestedFormat.mBitsPerChannel = 8; + requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; + break; + case DevFmtShort: + requestedFormat.mBitsPerChannel = 16; + requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; + break; + case DevFmtInt: + requestedFormat.mBitsPerChannel = 32; + requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; + break; + case DevFmtFloat: + requestedFormat.mBitsPerChannel = 32; + requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; + break; + case DevFmtByte: + case DevFmtUShort: + case DevFmtUInt: + ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType)); + goto error; + } + + switch(device->FmtChans) + { + case DevFmtMono: + requestedFormat.mChannelsPerFrame = 1; + break; + case DevFmtStereo: + requestedFormat.mChannelsPerFrame = 2; + break; + + case DevFmtQuad: + case DevFmtX51: + case DevFmtX51Rear: + case DevFmtX61: + case DevFmtX71: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans)); + goto error; + } + + requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8; + requestedFormat.mBytesPerPacket = requestedFormat.mBytesPerFrame; + requestedFormat.mSampleRate = device->Frequency; + requestedFormat.mFormatID = kAudioFormatLinearPCM; + requestedFormat.mReserved = 0; + requestedFormat.mFramesPerPacket = 1; + + // save requested format description for later use + data->format = requestedFormat; + data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + + // Use intermediate format for sample rate conversion (outputFormat) + // Set sample rate to the same as hardware for resampling later + outputFormat = requestedFormat; + outputFormat.mSampleRate = hardwareFormat.mSampleRate; + + // Determine sample rate ratio for resampling + data->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)); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed\n"); + goto error; + } + + // Set the AudioUnit output format frame count + outputFrameCount = device->UpdateSize * data->sampleRateRatio; + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount)); + if(err != noErr) + { + ERR("AudioUnitSetProperty failed: %d\n", err); + goto error; + } + + // Set up sample converter + err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter); + if(err != noErr) + { + ERR("AudioConverterNew failed: %d\n", err); + goto error; + } + + // Create a buffer for use in the resample callback + data->resampleBuffer = malloc(device->UpdateSize * data->frameSize * data->sampleRateRatio); + + // Allocate buffer for the AudioUnit output + data->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * data->frameSize * data->sampleRateRatio); + if(data->bufferList == NULL) + goto error; + + data->ring = ll_ringbuffer_create( + device->UpdateSize*data->sampleRateRatio*device->NumUpdates + 1, + data->frameSize + ); + if(!data->ring) goto error; + + al_string_copy_cstr(&device->DeviceName, deviceName); + + return ALC_NO_ERROR; + +error: + ll_ringbuffer_free(data->ring); + data->ring = NULL; + free(data->resampleBuffer); + destroy_buffer_list(data->bufferList); + + if(data->audioConverter) + AudioConverterDispose(data->audioConverter); + if(data->audioUnit) + AudioComponentInstanceDispose(data->audioUnit); + + free(data); + device->ExtraData = NULL; + + return ALC_INVALID_VALUE; +} + +static void ca_close_capture(ALCdevice *device) +{ + ca_data *data = (ca_data*)device->ExtraData; + + ll_ringbuffer_free(data->ring); + data->ring = NULL; + free(data->resampleBuffer); + destroy_buffer_list(data->bufferList); + + AudioConverterDispose(data->audioConverter); + AudioComponentInstanceDispose(data->audioUnit); + + free(data); + device->ExtraData = NULL; +} + +static void ca_start_capture(ALCdevice *device) +{ + ca_data *data = (ca_data*)device->ExtraData; + OSStatus err = AudioOutputUnitStart(data->audioUnit); + if(err != noErr) + ERR("AudioOutputUnitStart failed\n"); +} + +static void ca_stop_capture(ALCdevice *device) +{ + ca_data *data = (ca_data*)device->ExtraData; + OSStatus err = AudioOutputUnitStop(data->audioUnit); + if(err != noErr) + ERR("AudioOutputUnitStop failed\n"); +} + +static ALCenum ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) +{ + ca_data *data = (ca_data*)device->ExtraData; + AudioBufferList *list; + UInt32 frameCount; + OSStatus err; + + // If no samples are requested, just return + if(samples == 0) + return ALC_NO_ERROR; + + // Allocate a temporary AudioBufferList to use as the return resamples data + list = alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer)); + + // 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].mData = buffer; + + // Resample into another AudioBufferList + frameCount = samples; + err = AudioConverterFillComplexBuffer(data->audioConverter, ca_capture_conversion_callback, + device, &frameCount, list, NULL); + if(err != noErr) + { + ERR("AudioConverterFillComplexBuffer error: %d\n", err); + return ALC_INVALID_VALUE; + } + return ALC_NO_ERROR; +} + +static ALCuint ca_available_samples(ALCdevice *device) +{ + ca_data *data = device->ExtraData; + return ll_ringbuffer_read_space(data->ring) / data->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 +}; + +ALCboolean alc_ca_init(BackendFuncs *func_list) +{ + *func_list = ca_funcs; + return ALC_TRUE; +} + +void alc_ca_deinit(void) +{ +} + +void alc_ca_probe(enum DevProbe type) +{ + switch(type) + { + case ALL_DEVICE_PROBE: + AppendAllDevicesList(ca_device); + break; + case CAPTURE_DEVICE_PROBE: + AppendCaptureDeviceList(ca_device); + break; + } +} diff --git a/Engine/lib/openal-soft/Alc/backends/dsound.c b/Engine/lib/openal-soft/Alc/backends/dsound.c new file mode 100644 index 000000000..bb38d516b --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/dsound.c @@ -0,0 +1,1064 @@ +/** + * 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 +#include +#include + +#include +#include +#include +#ifndef _WAVEFORMATEXTENSIBLE_ +#include +#include +#endif + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" +#include "alstring.h" + +#include "backends/base.h" + +#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 +#ifndef DSSPEAKER_7POINT1_SURROUND +# define DSSPEAKER_7POINT1_SURROUND 0x00000008 +#endif +#ifndef DSSPEAKER_5POINT1_SURROUND +# define DSSPEAKER_5POINT1_SURROUND 0x00000009 +#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 DEVNAME_HEAD "OpenAL Soft on " + + +#ifdef HAVE_DYNLOAD +static void *ds_handle; +static HRESULT (WINAPI *pDirectSoundCreate)(const GUID *pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter); +static HRESULT (WINAPI *pDirectSoundEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext); +static HRESULT (WINAPI *pDirectSoundCaptureCreate)(const GUID *pcGuidDevice, IDirectSoundCapture **ppDSC, IUnknown *pUnkOuter); +static HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext); + +#define DirectSoundCreate pDirectSoundCreate +#define DirectSoundEnumerateW pDirectSoundEnumerateW +#define DirectSoundCaptureCreate pDirectSoundCaptureCreate +#define DirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW +#endif + + +static ALCboolean DSoundLoad(void) +{ +#ifdef HAVE_DYNLOAD + if(!ds_handle) + { + ds_handle = LoadLib("dsound.dll"); + if(ds_handle == NULL) + { + ERR("Failed to load dsound.dll\n"); + return ALC_FALSE; + } + +#define LOAD_FUNC(f) do { \ + p##f = GetSymbol(ds_handle, #f); \ + if(p##f == NULL) { \ + CloseLib(ds_handle); \ + ds_handle = NULL; \ + return ALC_FALSE; \ + } \ +} while(0) + LOAD_FUNC(DirectSoundCreate); + LOAD_FUNC(DirectSoundEnumerateW); + LOAD_FUNC(DirectSoundCaptureCreate); + LOAD_FUNC(DirectSoundCaptureEnumerateW); +#undef LOAD_FUNC + } +#endif + return ALC_TRUE; +} + + +#define MAX_UPDATES 128 + +typedef struct { + al_string name; + GUID guid; +} DevMap; +TYPEDEF_VECTOR(DevMap, vector_DevMap) + +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; + +static void clear_devlist(vector_DevMap *list) +{ +#define DEINIT_STR(i) AL_STRING_DEINIT((i)->name) + VECTOR_FOR_EACH(DevMap, *list, DEINIT_STR); + VECTOR_RESIZE(*list, 0, 0); +#undef DEINIT_STR +} + +static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data) +{ + vector_DevMap *devices = data; + OLECHAR *guidstr = NULL; + DevMap entry; + HRESULT hr; + int count; + + if(!guid) + return TRUE; + + AL_STRING_INIT(entry.name); + + count = 0; + while(1) + { + const DevMap *iter; + + al_string_copy_cstr(&entry.name, DEVNAME_HEAD); + al_string_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); + } + +#define MATCH_ENTRY(i) (al_string_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); + CoTaskMemFree(guidstr); + } + + VECTOR_PUSH_BACK(*devices, entry); + + return TRUE; +} + + +typedef struct ALCdsoundPlayback { + DERIVE_FROM_TYPE(ALCbackend); + + IDirectSound *DS; + IDirectSoundBuffer *PrimaryBuffer; + IDirectSoundBuffer *Buffer; + IDirectSoundNotify *Notifies; + HANDLE NotifyEvent; + + volatile int killNow; + althrd_t thread; +} ALCdsoundPlayback; + +static int ALCdsoundPlayback_mixerProc(void *ptr); + +static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device); +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, Destruct) +static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *name); +static void ALCdsoundPlayback_close(ALCdsoundPlayback *self); +static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self); +static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self); +static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self); +static DECLARE_FORWARD2(ALCdsoundPlayback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ALCuint, availableSamples) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCdsoundPlayback, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCdsoundPlayback) + +DEFINE_ALCBACKEND_VTABLE(ALCdsoundPlayback); + + +static void ALCdsoundPlayback_Construct(ALCdsoundPlayback *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCdsoundPlayback, ALCbackend, self); +} + + +FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) +{ + ALCdsoundPlayback *self = ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + DSBCAPS DSBCaps; + DWORD LastCursor = 0; + DWORD PlayCursor; + void *WritePtr1, *WritePtr2; + DWORD WriteCnt1, WriteCnt2; + BOOL Playing = FALSE; + DWORD FrameSize; + DWORD FragSize; + DWORD avail; + HRESULT err; + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + memset(&DSBCaps, 0, sizeof(DSBCaps)); + DSBCaps.dwSize = sizeof(DSBCaps); + err = IDirectSoundBuffer_GetCaps(self->Buffer, &DSBCaps); + if(FAILED(err)) + { + ERR("Failed to get buffer caps: 0x%lx\n", err); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); + return 1; + } + + FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + FragSize = device->UpdateSize * FrameSize; + + IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL); + while(!self->killNow) + { + // Get current play cursor + IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &PlayCursor, NULL); + avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes; + + if(avail < FragSize) + { + if(!Playing) + { + err = IDirectSoundBuffer_Play(self->Buffer, 0, 0, DSBPLAY_LOOPING); + if(FAILED(err)) + { + ERR("Failed to play buffer: 0x%lx\n", err); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); + return 1; + } + Playing = TRUE; + } + + avail = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); + if(avail != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: 0x%lx\n", avail); + continue; + } + avail -= avail%FragSize; + + // Lock output buffer + WriteCnt1 = 0; + WriteCnt2 = 0; + err = IDirectSoundBuffer_Lock(self->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); + + // If the buffer is lost, restore it and lock + if(err == DSERR_BUFFERLOST) + { + WARN("Buffer lost, restoring...\n"); + err = IDirectSoundBuffer_Restore(self->Buffer); + if(SUCCEEDED(err)) + { + Playing = FALSE; + LastCursor = 0; + err = IDirectSoundBuffer_Lock(self->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); + } + } + + // Successfully locked the output buffer + if(SUCCEEDED(err)) + { + // If we have an active context, mix data directly into output buffer otherwise fill with silence + aluMixData(device, WritePtr1, WriteCnt1/FrameSize); + aluMixData(device, WritePtr2, WriteCnt2/FrameSize); + + // Unlock output buffer only when successfully locked + IDirectSoundBuffer_Unlock(self->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); + } + else + { + ERR("Buffer lock error: %#lx\n", err); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); + return 1; + } + + // Update old write cursor location + LastCursor += WriteCnt1+WriteCnt2; + LastCursor %= DSBCaps.dwBufferBytes; + } + + return 0; +} + +static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *deviceName) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + const GUID *guid = NULL; + HRESULT hr, hrcom; + + if(VECTOR_SIZE(PlaybackDevices) == 0) + { + /* Initialize COM to prevent name truncation */ + hrcom = CoInitialize(NULL); + hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); + if(FAILED(hr)) + ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); + if(SUCCEEDED(hrcom)) + CoUninitialize(); + } + + if(!deviceName && VECTOR_SIZE(PlaybackDevices) > 0) + { + deviceName = al_string_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) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(PlaybackDevices)) + return ALC_INVALID_VALUE; + guid = &iter->guid; + } + + hr = DS_OK; + self->NotifyEvent = CreateEventW(NULL, FALSE, FALSE, NULL); + if(self->NotifyEvent == NULL) + hr = E_FAIL; + + //DirectSound Init code + if(SUCCEEDED(hr)) + hr = DirectSoundCreate(guid, &self->DS, NULL); + if(SUCCEEDED(hr)) + hr = IDirectSound_SetCooperativeLevel(self->DS, GetForegroundWindow(), DSSCL_PRIORITY); + if(FAILED(hr)) + { + if(self->DS) + IDirectSound_Release(self->DS); + self->DS = NULL; + if(self->NotifyEvent) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + + ERR("Device init failed: 0x%08lx\n", hr); + return ALC_INVALID_VALUE; + } + + al_string_copy_cstr(&device->DeviceName, deviceName); + + return ALC_NO_ERROR; +} + +static void ALCdsoundPlayback_close(ALCdsoundPlayback *self) +{ + if(self->Notifies) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; + + IDirectSound_Release(self->DS); + self->DS = NULL; + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; +} + +static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + DSBUFFERDESC DSBDescription; + WAVEFORMATEXTENSIBLE OutputType; + DWORD speakers; + HRESULT hr; + + memset(&OutputType, 0, sizeof(OutputType)); + + if(self->Notifies) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; + + switch(device->FmtType) + { + case DevFmtByte: + device->FmtType = DevFmtUByte; + break; + case DevFmtFloat: + if((device->Flags&DEVICE_SAMPLE_TYPE_REQUEST)) + break; + /* fall-through */ + case DevFmtUShort: + device->FmtType = DevFmtShort; + break; + case DevFmtUInt: + device->FmtType = DevFmtInt; + break; + case DevFmtUByte: + case DevFmtShort: + case DevFmtInt: + break; + } + + hr = IDirectSound_GetSpeakerConfig(self->DS, &speakers); + if(SUCCEEDED(hr)) + { + speakers = DSSPEAKER_CONFIG(speakers); + if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) + { + 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_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 DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + device->FmtChans = DevFmtStereo; + /*fall-through*/ + case DevFmtStereo: + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT; + break; + case DevFmtQuad: + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT | + SPEAKER_BACK_LEFT | + SPEAKER_BACK_RIGHT; + break; + case DevFmtX51: + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT | + SPEAKER_FRONT_CENTER | + SPEAKER_LOW_FREQUENCY | + SPEAKER_SIDE_LEFT | + SPEAKER_SIDE_RIGHT; + break; + case DevFmtX51Rear: + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | + SPEAKER_FRONT_RIGHT | + SPEAKER_FRONT_CENTER | + SPEAKER_LOW_FREQUENCY | + SPEAKER_BACK_LEFT | + SPEAKER_BACK_RIGHT; + break; + case DevFmtX61: + OutputType.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: + OutputType.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; + } + +retry_open: + hr = S_OK; + OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; + OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); + OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; + OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; + OutputType.Format.nSamplesPerSec = device->Frequency; + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; + OutputType.Format.cbSize = 0; + } + + if(OutputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) + { + OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + if(device->FmtType == DevFmtFloat) + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + else + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + + if(self->PrimaryBuffer) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; + } + else + { + if(SUCCEEDED(hr) && !self->PrimaryBuffer) + { + memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); + DSBDescription.dwSize=sizeof(DSBUFFERDESC); + DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; + hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->PrimaryBuffer, NULL); + } + if(SUCCEEDED(hr)) + hr = IDirectSoundBuffer_SetFormat(self->PrimaryBuffer,&OutputType.Format); + } + + if(SUCCEEDED(hr)) + { + if(device->NumUpdates > MAX_UPDATES) + { + device->UpdateSize = (device->UpdateSize*device->NumUpdates + + MAX_UPDATES-1) / MAX_UPDATES; + device->NumUpdates = MAX_UPDATES; + } + + memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); + DSBDescription.dwSize=sizeof(DSBUFFERDESC); + DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS; + DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * + OutputType.Format.nBlockAlign; + DSBDescription.lpwfxFormat=&OutputType.Format; + hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->Buffer, NULL); + if(FAILED(hr) && device->FmtType == DevFmtFloat) + { + device->FmtType = DevFmtShort; + goto retry_open; + } + } + + if(SUCCEEDED(hr)) + { + hr = IDirectSoundBuffer_QueryInterface(self->Buffer, &IID_IDirectSoundNotify, (void**)&self->Notifies); + if(SUCCEEDED(hr)) + { + DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; + ALuint i; + + for(i = 0;i < device->NumUpdates;++i) + { + notifies[i].dwOffset = i * device->UpdateSize * + OutputType.Format.nBlockAlign; + notifies[i].hEventNotify = self->NotifyEvent; + } + if(IDirectSoundNotify_SetNotificationPositions(self->Notifies, device->NumUpdates, notifies) != DS_OK) + hr = E_FAIL; + } + } + + if(FAILED(hr)) + { + if(self->Notifies != NULL) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer != NULL) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; + return ALC_FALSE; + } + + ResetEvent(self->NotifyEvent); + SetDefaultWFXChannelOrder(device); + + return ALC_TRUE; +} + +static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self) +{ + self->killNow = 0; + if(althrd_create(&self->thread, ALCdsoundPlayback_mixerProc, self) != althrd_success) + return ALC_FALSE; + + return ALC_TRUE; +} + +static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self) +{ + int res; + + if(self->killNow) + return; + + self->killNow = 1; + althrd_join(self->thread, &res); + + IDirectSoundBuffer_Stop(self->Buffer); +} + + + +typedef struct ALCdsoundCapture { + DERIVE_FROM_TYPE(ALCbackend); + + IDirectSoundCapture *DSC; + IDirectSoundCaptureBuffer *DSCbuffer; + DWORD BufferBytes; + DWORD Cursor; + + ll_ringbuffer_t *Ring; +} ALCdsoundCapture; + +static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, Destruct) +static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *name); +static void ALCdsoundCapture_close(ALCdsoundCapture *self); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALCboolean, reset) +static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self); +static void ALCdsoundCapture_stop(ALCdsoundCapture *self); +static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples); +static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ClockLatency, getClockLatency) +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCdsoundCapture) + +DEFINE_ALCBACKEND_VTABLE(ALCdsoundCapture); + +static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCdsoundCapture, ALCbackend, self); +} + + +static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *deviceName) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + WAVEFORMATEXTENSIBLE InputType; + DSCBUFFERDESC DSCBDescription; + const GUID *guid = NULL; + HRESULT hr, hrcom; + ALuint samples; + + if(VECTOR_SIZE(CaptureDevices) == 0) + { + /* Initialize COM to prevent name truncation */ + hrcom = CoInitialize(NULL); + hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); + if(FAILED(hr)) + ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); + if(SUCCEEDED(hrcom)) + CoUninitialize(); + } + + if(!deviceName && VECTOR_SIZE(CaptureDevices) > 0) + { + deviceName = al_string_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) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(CaptureDevices)) + return ALC_INVALID_VALUE; + guid = &iter->guid; + } + + switch(device->FmtType) + { + case DevFmtByte: + case DevFmtUShort: + case DevFmtUInt: + WARN("%s capture samples not supported\n", DevFmtTypeString(device->FmtType)); + return ALC_INVALID_ENUM; + + case DevFmtUByte: + case DevFmtShort: + case DevFmtInt: + case DevFmtFloat: + break; + } + + //DirectSoundCapture Init code + hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL); + if(SUCCEEDED(hr)) + { + 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_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 DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + break; + } + + 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; + + 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; + } + + 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; + + hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL); + } + if(SUCCEEDED(hr)) + { + self->Ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, + InputType.Format.nBlockAlign); + if(self->Ring == NULL) + hr = DSERR_OUTOFMEMORY; + } + + if(FAILED(hr)) + { + ERR("Device init failed: 0x%08lx\n", hr); + + ll_ringbuffer_free(self->Ring); + self->Ring = NULL; + if(self->DSCbuffer != NULL) + IDirectSoundCaptureBuffer_Release(self->DSCbuffer); + self->DSCbuffer = NULL; + if(self->DSC) + IDirectSoundCapture_Release(self->DSC); + self->DSC = NULL; + + return ALC_INVALID_VALUE; + } + + self->BufferBytes = DSCBDescription.dwBufferBytes; + SetDefaultWFXChannelOrder(device); + + al_string_copy_cstr(&device->DeviceName, deviceName); + + return ALC_NO_ERROR; +} + +static void ALCdsoundCapture_close(ALCdsoundCapture *self) +{ + ll_ringbuffer_free(self->Ring); + self->Ring = NULL; + + if(self->DSCbuffer != NULL) + { + IDirectSoundCaptureBuffer_Stop(self->DSCbuffer); + IDirectSoundCaptureBuffer_Release(self->DSCbuffer); + self->DSCbuffer = NULL; + } + + IDirectSoundCapture_Release(self->DSC); + self->DSC = NULL; +} + +static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self) +{ + HRESULT hr; + + hr = IDirectSoundCaptureBuffer_Start(self->DSCbuffer, DSCBSTART_LOOPING); + if(FAILED(hr)) + { + ERR("start failed: 0x%08lx\n", hr); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static void ALCdsoundCapture_stop(ALCdsoundCapture *self) +{ + HRESULT hr; + + hr = IDirectSoundCaptureBuffer_Stop(self->DSCbuffer); + if(FAILED(hr)) + { + ERR("stop failed: 0x%08lx\n", hr); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + } +} + +static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples) +{ + ll_ringbuffer_read(self->Ring, buffer, samples); + return ALC_NO_ERROR; +} + +static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + DWORD ReadCursor, LastCursor, BufferBytes, NumBytes; + void *ReadPtr1, *ReadPtr2; + DWORD ReadCnt1, ReadCnt2; + DWORD FrameSize; + HRESULT hr; + + if(!device->Connected) + goto done; + + FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + BufferBytes = self->BufferBytes; + LastCursor = self->Cursor; + + hr = IDirectSoundCaptureBuffer_GetCurrentPosition(self->DSCbuffer, NULL, &ReadCursor); + if(SUCCEEDED(hr)) + { + NumBytes = (ReadCursor-LastCursor + BufferBytes) % BufferBytes; + if(NumBytes == 0) + goto done; + hr = IDirectSoundCaptureBuffer_Lock(self->DSCbuffer, LastCursor, NumBytes, + &ReadPtr1, &ReadCnt1, + &ReadPtr2, &ReadCnt2, 0); + } + if(SUCCEEDED(hr)) + { + ll_ringbuffer_write(self->Ring, ReadPtr1, ReadCnt1/FrameSize); + if(ReadPtr2 != NULL) + ll_ringbuffer_write(self->Ring, ReadPtr2, ReadCnt2/FrameSize); + hr = IDirectSoundCaptureBuffer_Unlock(self->DSCbuffer, + ReadPtr1, ReadCnt1, + ReadPtr2, ReadCnt2); + self->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes; + } + + if(FAILED(hr)) + { + ERR("update failed: 0x%08lx\n", hr); + aluHandleDisconnect(device); + } + +done: + return ll_ringbuffer_read_space(self->Ring); +} + + +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } + +typedef struct ALCdsoundBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCdsoundBackendFactory; +#define ALCDSOUNDBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCdsoundBackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); + +static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory *self); +static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory *self); +static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory *self, ALCbackend_Type type); +static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCdsoundBackendFactory); + + +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void) +{ + static ALCdsoundBackendFactory factory = ALCDSOUNDBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} + + +static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory* UNUSED(self)) +{ + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + + if(!DSoundLoad()) + return ALC_FALSE; + return ALC_TRUE; +} + +static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory* UNUSED(self)) +{ + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); + + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); + +#ifdef HAVE_DYNLOAD + if(ds_handle) + CloseLib(ds_handle); + ds_handle = NULL; +#endif +} + +static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback || type == ALCbackend_Capture) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory* UNUSED(self), enum DevProbe type) +{ + HRESULT hr, hrcom; + + /* Initialize COM to prevent name truncation */ + hrcom = CoInitialize(NULL); + switch(type) + { + case ALL_DEVICE_PROBE: + clear_devlist(&PlaybackDevices); + hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); + if(FAILED(hr)) + ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); + break; + + case CAPTURE_DEVICE_PROBE: + clear_devlist(&CaptureDevices); + hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); + if(FAILED(hr)) + ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); + break; + } + if(SUCCEEDED(hrcom)) + CoUninitialize(); +} + +static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCdsoundPlayback *backend; + NEW_OBJ(backend, ALCdsoundPlayback)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + if(type == ALCbackend_Capture) + { + ALCdsoundCapture *backend; + NEW_OBJ(backend, ALCdsoundCapture)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} diff --git a/Engine/lib/openal-soft/Alc/backends/jack.c b/Engine/lib/openal-soft/Alc/backends/jack.c new file mode 100644 index 000000000..283df297a --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/jack.c @@ -0,0 +1,627 @@ +/** + * 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 +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" + +#include "backends/base.h" + +#include +#include + + +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); +#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 +#endif + + +static jack_options_t ClientOptions = JackNullOption; + +static ALCboolean jack_load(void) +{ + ALCboolean error = ALC_FALSE; + +#ifdef HAVE_DYNLOAD + if(!jack_handle) + { +#ifdef _WIN32 +#define JACKLIB "libjack.dll" +#else +#define JACKLIB "libjack.so.0" +#endif + jack_handle = LoadLib(JACKLIB); + if(!jack_handle) + return ALC_FALSE; + + error = ALC_FALSE; +#define LOAD_FUNC(f) do { \ + p##f = GetSymbol(jack_handle, #f); \ + if(p##f == NULL) { \ + error = ALC_TRUE; \ + } \ +} while(0) + JACK_FUNCS(LOAD_FUNC); +#undef LOAD_FUNC + + if(error) + { + CloseLib(jack_handle); + jack_handle = NULL; + return ALC_FALSE; + } + } +#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 void ALCjackPlayback_lock(ALCjackPlayback *self); +static void ALCjackPlayback_unlock(ALCjackPlayback *self); +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; + TRACE("%u update size x%u\n", device->UpdateSize, device->NumUpdates); + + bufsize = device->UpdateSize; + if(ConfigValueUInt(al_string_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) + bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize); + bufsize += device->UpdateSize; + + ll_ringbuffer_free(self->Ring); + self->Ring = ll_ringbuffer_create(bufsize, FrameSizeFromDevFmt(device->FmtChans, device->FmtType)); + 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; + ALuint 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++) + { + for(i = 0;i < todo;i++) + out[c][i] = ((ALfloat*)data[0].buf)[i*numchans + c]; + out[c] += todo; + } + total += todo; + + todo = minu(numframes-total, data[1].len); + if(todo > 0) + { + for(c = 0;c < numchans;c++) + { + for(i = 0;i < todo;i++) + out[c][i] = ((ALfloat*)data[1].buf)[i*numchans + c]; + 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;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); + + al_string_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; + ALuint 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(al_string_get_cstr(device->DeviceName), "jack", "buffer-size", &bufsize)) + bufsize = maxu(NextPowerOf2(bufsize), device->UpdateSize); + bufsize += device->UpdateSize; + + /* Force 32-bit float output. */ + device->FmtType = DevFmtFloat; + + numchans = ChannelsFromDevFmt(device->FmtChans); + 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)); + 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; + ALuint 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 ALCjackPlayback_lock(ALCjackPlayback *self) +{ + almtx_lock(&STATIC_CAST(ALCbackend,self)->mMutex); +} + +static void ALCjackPlayback_unlock(ALCjackPlayback *self) +{ + almtx_unlock(&STATIC_CAST(ALCbackend,self)->mMutex); +} + + +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)) +{ + jack_client_t *client; + jack_status_t status; + + if(!jack_load()) + return ALC_FALSE; + + if(!GetConfigValueBool(NULL, "jack", "spawn-server", 0)) + ClientOptions |= JackNoStartServer; + + jack_set_error_function(jack_msg_handler); + client = jack_client_open("alsoft", ClientOptions, &status, NULL); + jack_set_error_function(NULL); + 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); +} diff --git a/Engine/lib/openal-soft/Alc/backends/loopback.c b/Engine/lib/openal-soft/Alc/backends/loopback.c new file mode 100644 index 000000000..0164bc5a7 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/loopback.c @@ -0,0 +1,133 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include + +#include "alMain.h" +#include "alu.h" + +#include "backends/base.h" + + +typedef struct ALCloopback { + DERIVE_FROM_TYPE(ALCbackend); +} ALCloopback; + +static void ALCloopback_Construct(ALCloopback *self, ALCdevice *device); +static DECLARE_FORWARD(ALCloopback, ALCbackend, void, Destruct) +static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name); +static void ALCloopback_close(ALCloopback *self); +static ALCboolean ALCloopback_reset(ALCloopback *self); +static ALCboolean ALCloopback_start(ALCloopback *self); +static void ALCloopback_stop(ALCloopback *self); +static DECLARE_FORWARD2(ALCloopback, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCloopback, ALCbackend, ALCuint, availableSamples) +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) +DEFINE_ALCBACKEND_VTABLE(ALCloopback); + + +static void ALCloopback_Construct(ALCloopback *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCloopback, ALCbackend, self); +} + + +static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + + al_string_copy_cstr(&device->DeviceName, name); + return ALC_NO_ERROR; +} + +static void ALCloopback_close(ALCloopback* UNUSED(self)) +{ +} + +static ALCboolean ALCloopback_reset(ALCloopback *self) +{ + SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice); + return ALC_TRUE; +} + +static ALCboolean ALCloopback_start(ALCloopback* UNUSED(self)) +{ + return ALC_TRUE; +} + +static void ALCloopback_stop(ALCloopback* UNUSED(self)) +{ +} + + +typedef struct ALCloopbackFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCloopbackFactory; +#define ALCNULLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCloopbackFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCloopbackFactory_getFactory(void); +static ALCboolean ALCloopbackFactory_init(ALCloopbackFactory *self); +static DECLARE_FORWARD(ALCloopbackFactory, ALCbackendFactory, void, deinit) +static ALCboolean ALCloopbackFactory_querySupport(ALCloopbackFactory *self, ALCbackend_Type type); +static void ALCloopbackFactory_probe(ALCloopbackFactory *self, enum DevProbe type); +static ALCbackend* ALCloopbackFactory_createBackend(ALCloopbackFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCloopbackFactory); + + +ALCbackendFactory *ALCloopbackFactory_getFactory(void) +{ + static ALCloopbackFactory factory = ALCNULLBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} + +static ALCboolean ALCloopbackFactory_init(ALCloopbackFactory* UNUSED(self)) +{ + return ALC_TRUE; +} + +static ALCboolean ALCloopbackFactory_querySupport(ALCloopbackFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Loopback) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCloopbackFactory_probe(ALCloopbackFactory* UNUSED(self), enum DevProbe UNUSED(type)) +{ +} + +static ALCbackend* ALCloopbackFactory_createBackend(ALCloopbackFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Loopback) + { + ALCloopback *backend; + NEW_OBJ(backend, ALCloopback)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} diff --git a/Engine/lib/openal-soft/Alc/backends/mmdevapi.c b/Engine/lib/openal-soft/Alc/backends/mmdevapi.c new file mode 100644 index 000000000..3882b08f0 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/mmdevapi.c @@ -0,0 +1,1911 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#define COBJMACROS +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifndef _WAVEFORMATEXTENSIBLE_ +#include +#include +#endif + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" +#include "alstring.h" + +#include "backends/base.h" + + +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_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_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 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) +{ +#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; +static vector_DevMap CaptureDevices; + + +static HANDLE ThreadHdl; +static DWORD ThreadID; + +typedef struct { + HANDLE FinishedEvt; + HRESULT result; +} ThreadRequest; + +#define WM_USER_First (WM_USER+0) +#define WM_USER_OpenDevice (WM_USER+0) +#define WM_USER_ResetDevice (WM_USER+1) +#define WM_USER_StartDevice (WM_USER+2) +#define WM_USER_StopDevice (WM_USER+3) +#define WM_USER_CloseDevice (WM_USER+4) +#define WM_USER_Enumerate (WM_USER+5) +#define WM_USER_Last (WM_USER+5) + +static inline void ReturnMsgResponse(ThreadRequest *req, HRESULT res) +{ + req->result = res; + SetEvent(req->FinishedEvt); +} + +static HRESULT WaitForResponse(ThreadRequest *req) +{ + if(WaitForSingleObject(req->FinishedEvt, INFINITE) == WAIT_OBJECT_0) + return req->result; + ERR("Message response error: %lu\n", GetLastError()); + return E_FAIL; +} + + +static void get_device_name_and_guid(IMMDevice *device, al_string *name, al_string *guid) +{ + IPropertyStore *ps; + PROPVARIANT pvname; + PROPVARIANT pvguid; + HRESULT hr; + + al_string_copy_cstr(name, DEVNAME_HEAD); + + hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); + if(FAILED(hr)) + { + WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + al_string_append_cstr(name, "Unknown Device Name"); + if(guid!=NULL)al_string_copy_cstr(guid, "Unknown Device GUID"); + return; + } + + PropVariantInit(&pvname); + + hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname); + if(FAILED(hr)) + { + WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); + al_string_append_cstr(name, "Unknown Device Name"); + } + else if(pvname.vt == VT_LPWSTR) + al_string_append_wcstr(name, pvname.pwszVal); + else + { + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvname.vt); + al_string_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); + al_string_copy_cstr(guid, "Unknown Device GUID"); + } + else if(pvguid.vt == VT_LPWSTR) + al_string_copy_wcstr(guid, pvguid.pwszVal); + else + { + WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvguid.vt); + al_string_copy_cstr(guid, "Unknown Device GUID"); + } + + PropVariantClear(&pvguid); + } + + IPropertyStore_Release(ps); +} + +static void get_device_formfactor(IMMDevice *device, EndpointFormFactor *formfactor) +{ + IPropertyStore *ps; + PROPVARIANT pvform; + HRESULT 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, LPCWSTR 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) + { + const DevMap *iter; + + al_string_copy(&entry.name, tmpname); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&entry.name, str); + } + +#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) + VECTOR_FIND_IF(iter, const DevMap, *list, MATCH_ENTRY); + if(iter == VECTOR_END(*list)) break; +#undef MATCH_ENTRY + count++; + } + + TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.endpoint_guid), entry.devid); + VECTOR_PUSH_BACK(*list, entry); + + AL_STRING_DEINIT(tmpname); +} + +static LPWSTR get_device_id(IMMDevice *device) +{ + LPWSTR devid; + HRESULT hr; + + 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; + LPWSTR defdevid = NULL; + HRESULT hr; + UINT count; + UINT i; + + hr = IMMDeviceEnumerator_EnumAudioEndpoints(devenum, flowdir, DEVICE_STATE_ACTIVE, &coll); + if(FAILED(hr)) + { + ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); + return hr; + } + + count = 0; + hr = IMMDeviceCollection_GetCount(coll, &count); + if(SUCCEEDED(hr) && count > 0) + { + clear_devlist(list); + VECTOR_RESIZE(*list, 0, count); + + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir, + eMultimedia, &defdev); + } + if(SUCCEEDED(hr) && defdev != NULL) + { + defdevid = get_device_id(defdev); + if(defdevid) + add_device(defdev, defdevid, list); + } + + for(i = 0;i < count;++i) + { + IMMDevice *device; + LPWSTR devid; + + 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; +} + + +/* Proxy interface used by the message handler. */ +struct ALCmmdevProxyVtable; + +typedef struct ALCmmdevProxy { + const struct ALCmmdevProxyVtable *vtbl; +} ALCmmdevProxy; + +struct ALCmmdevProxyVtable { + HRESULT (*const openProxy)(ALCmmdevProxy*); + void (*const closeProxy)(ALCmmdevProxy*); + + HRESULT (*const resetProxy)(ALCmmdevProxy*); + HRESULT (*const startProxy)(ALCmmdevProxy*); + void (*const stopProxy)(ALCmmdevProxy*); +}; + +#define DEFINE_ALCMMDEVPROXY_VTABLE(T) \ +DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, openProxy) \ +DECLARE_THUNK(T, ALCmmdevProxy, void, closeProxy) \ +DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, resetProxy) \ +DECLARE_THUNK(T, ALCmmdevProxy, HRESULT, startProxy) \ +DECLARE_THUNK(T, ALCmmdevProxy, void, stopProxy) \ + \ +static const struct ALCmmdevProxyVtable T##_ALCmmdevProxy_vtable = { \ + T##_ALCmmdevProxy_openProxy, \ + T##_ALCmmdevProxy_closeProxy, \ + T##_ALCmmdevProxy_resetProxy, \ + T##_ALCmmdevProxy_startProxy, \ + T##_ALCmmdevProxy_stopProxy, \ +} + +static void ALCmmdevProxy_Construct(ALCmmdevProxy* UNUSED(self)) { } +static void ALCmmdevProxy_Destruct(ALCmmdevProxy* UNUSED(self)) { } + +static DWORD CALLBACK ALCmmdevProxy_messageHandler(void *ptr) +{ + ThreadRequest *req = ptr; + IMMDeviceEnumerator *Enumerator; + ALuint deviceCount = 0; + ALCmmdevProxy *proxy; + HRESULT hr, cohr; + MSG msg; + + TRACE("Starting message thread\n"); + + cohr = CoInitialize(NULL); + if(FAILED(cohr)) + { + WARN("Failed to initialize COM: 0x%08lx\n", cohr); + ReturnMsgResponse(req, cohr); + return 0; + } + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(FAILED(hr)) + { + WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); + CoUninitialize(); + ReturnMsgResponse(req, hr); + return 0; + } + Enumerator = ptr; + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + + CoUninitialize(); + + /* HACK: Force Windows to create a message queue for this thread before + * returning success, otherwise PostThreadMessage may fail if it gets + * called before GetMessage. + */ + PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + TRACE("Message thread initialization complete\n"); + ReturnMsgResponse(req, S_OK); + + TRACE("Starting message loop\n"); + while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last)) + { + TRACE("Got message %u (lparam=%p, wparam=%p)\n", msg.message, (void*)msg.lParam, (void*)msg.wParam); + switch(msg.message) + { + case WM_USER_OpenDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + hr = cohr = S_OK; + if(++deviceCount == 1) + hr = cohr = CoInitialize(NULL); + if(SUCCEEDED(hr)) + hr = V0(proxy,openProxy)(); + if(FAILED(hr)) + { + if(--deviceCount == 0 && SUCCEEDED(cohr)) + CoUninitialize(); + } + + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_ResetDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + hr = V0(proxy,resetProxy)(); + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_StartDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + hr = V0(proxy,startProxy)(); + ReturnMsgResponse(req, hr); + continue; + + case WM_USER_StopDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + V0(proxy,stopProxy)(); + ReturnMsgResponse(req, S_OK); + continue; + + case WM_USER_CloseDevice: + req = (ThreadRequest*)msg.wParam; + proxy = (ALCmmdevProxy*)msg.lParam; + + V0(proxy,closeProxy)(); + if(--deviceCount == 0) + CoUninitialize(); + + ReturnMsgResponse(req, S_OK); + continue; + + case WM_USER_Enumerate: + req = (ThreadRequest*)msg.wParam; + + hr = cohr = S_OK; + if(++deviceCount == 1) + hr = cohr = CoInitialize(NULL); + if(SUCCEEDED(hr)) + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(SUCCEEDED(hr)) + { + Enumerator = ptr; + + if(msg.lParam == ALL_DEVICE_PROBE) + hr = probe_devices(Enumerator, eRender, &PlaybackDevices); + else if(msg.lParam == CAPTURE_DEVICE_PROBE) + hr = probe_devices(Enumerator, eCapture, &CaptureDevices); + + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + } + + if(--deviceCount == 0 && SUCCEEDED(cohr)) + CoUninitialize(); + + ReturnMsgResponse(req, hr); + continue; + + default: + ERR("Unexpected message: %u\n", msg.message); + continue; + } + } + TRACE("Message loop finished\n"); + + return 0; +} + + +typedef struct ALCmmdevPlayback { + DERIVE_FROM_TYPE(ALCbackend); + DERIVE_FROM_TYPE(ALCmmdevProxy); + + WCHAR *devid; + + IMMDevice *mmdev; + IAudioClient *client; + IAudioRenderClient *render; + HANDLE NotifyEvent; + + HANDLE MsgEvent; + + volatile UINT32 Padding; + + volatile int killNow; + althrd_t thread; +} ALCmmdevPlayback; + +static int ALCmmdevPlayback_mixerProc(void *arg); + +static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device); +static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self); +static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *name); +static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *self); +static void ALCmmdevPlayback_close(ALCmmdevPlayback *self); +static void ALCmmdevPlayback_closeProxy(ALCmmdevPlayback *self); +static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self); +static HRESULT ALCmmdevPlayback_resetProxy(ALCmmdevPlayback *self); +static ALCboolean ALCmmdevPlayback_start(ALCmmdevPlayback *self); +static HRESULT ALCmmdevPlayback_startProxy(ALCmmdevPlayback *self); +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 ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self); +static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCmmdevPlayback, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCmmdevPlayback) + +DEFINE_ALCMMDEVPROXY_VTABLE(ALCmmdevPlayback); +DEFINE_ALCBACKEND_VTABLE(ALCmmdevPlayback); + + +static void ALCmmdevPlayback_Construct(ALCmmdevPlayback *self, ALCdevice *device) +{ + SET_VTABLE2(ALCmmdevPlayback, ALCbackend, self); + SET_VTABLE2(ALCmmdevPlayback, ALCmmdevProxy, self); + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + ALCmmdevProxy_Construct(STATIC_CAST(ALCmmdevProxy, self)); + + self->devid = NULL; + + self->mmdev = NULL; + self->client = NULL; + self->render = NULL; + self->NotifyEvent = NULL; + + self->MsgEvent = NULL; + + self->Padding = 0; + + self->killNow = 0; +} + +static void ALCmmdevPlayback_Destruct(ALCmmdevPlayback *self) +{ + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + if(self->MsgEvent != NULL) + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + free(self->devid); + self->devid = NULL; + + ALCmmdevProxy_Destruct(STATIC_CAST(ALCmmdevProxy, self)); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +FORCE_ALIGN static int ALCmmdevPlayback_mixerProc(void *arg) +{ + ALCmmdevPlayback *self = arg; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + UINT32 buffer_len, written; + ALuint update_size, len; + BYTE *buffer; + HRESULT hr; + + hr = CoInitialize(NULL); + if(FAILED(hr)) + { + ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); + V0(device->Backend,lock)(); + aluHandleDisconnect(device); + V0(device->Backend,unlock)(); + return 1; + } + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + update_size = device->UpdateSize; + buffer_len = update_size * device->NumUpdates; + while(!self->killNow) + { + hr = IAudioClient_GetCurrentPadding(self->client, &written); + if(FAILED(hr)) + { + ERR("Failed to get padding: 0x%08lx\n", hr); + V0(device->Backend,lock)(); + aluHandleDisconnect(device); + V0(device->Backend,unlock)(); + break; + } + self->Padding = written; + + len = buffer_len - written; + if(len < update_size) + { + DWORD res; + res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); + if(res != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: 0x%lx\n", res); + continue; + } + len -= len%update_size; + + hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer); + if(SUCCEEDED(hr)) + { + V0(device->Backend,lock)(); + aluMixData(device, buffer, len); + self->Padding = written + len; + V0(device->Backend,unlock)(); + hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0); + } + if(FAILED(hr)) + { + ERR("Failed to buffer data: 0x%08lx\n", hr); + V0(device->Backend,lock)(); + aluHandleDisconnect(device); + V0(device->Backend,unlock)(); + break; + } + } + self->Padding = 0; + + CoUninitialize(); + return 0; +} + + +static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *in) +{ + memset(out, 0, sizeof(*out)); + if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + *out = *(const WAVEFORMATEXTENSIBLE*)in; + else if(in->wFormatTag == WAVE_FORMAT_PCM) + { + out->Format = *in; + out->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + out->Format.cbSize = sizeof(*out) - sizeof(*in); + if(out->Format.nChannels == 1) + out->dwChannelMask = MONO; + else if(out->Format.nChannels == 2) + out->dwChannelMask = STEREO; + else + ERR("Unhandled PCM channel count: %d\n", out->Format.nChannels); + out->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + } + else if(in->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) + { + out->Format = *in; + out->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + out->Format.cbSize = sizeof(*out) - sizeof(*in); + if(out->Format.nChannels == 1) + out->dwChannelMask = MONO; + else if(out->Format.nChannels == 2) + out->dwChannelMask = STEREO; + else + ERR("Unhandled IEEE float channel count: %d\n", out->Format.nChannels); + out->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + } + else + { + ERR("Unhandled format tag: 0x%04x\n", in->wFormatTag); + return ALC_FALSE; + } + return ALC_TRUE; +} + +static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *deviceName) +{ + 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) + { + ERR("Failed to create message events: %lu\n", GetLastError()); + hr = E_FAIL; + } + + if(SUCCEEDED(hr)) + { + if(deviceName) + { + const DevMap *iter; + + if(VECTOR_SIZE(PlaybackDevices) == 0) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE)) + (void)WaitForResponse(&req); + } + + hr = E_FAIL; +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0 || \ + al_string_cmp_cstr((i)->endpoint_guid, deviceName) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(PlaybackDevices)) + { + 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, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + free(wname); + } + } + 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); + al_string_copy(&device->DeviceName, iter->name); + hr = S_OK; + } + } + } + + 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; + } + + return ALC_NO_ERROR; +} + +static HRESULT ALCmmdevPlayback_openProxy(ALCmmdevPlayback *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, eRender, eMultimedia, &self->mmdev); + else + hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev); + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + } + if(SUCCEEDED(hr)) + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(SUCCEEDED(hr)) + { + self->client = ptr; + if(al_string_empty(device->DeviceName)) + get_device_name_and_guid(self->mmdev, &device->DeviceName, NULL); + } + + if(FAILED(hr)) + { + if(self->mmdev) + IMMDevice_Release(self->mmdev); + self->mmdev = NULL; + } + + return hr; +} + + +static void ALCmmdevPlayback_close(ALCmmdevPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + (void)WaitForResponse(&req); + + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + + free(self->devid); + self->devid = NULL; +} + +static void ALCmmdevPlayback_closeProxy(ALCmmdevPlayback *self) +{ + if(self->client) + IAudioClient_Release(self->client); + self->client = NULL; + + if(self->mmdev) + IMMDevice_Release(self->mmdev); + self->mmdev = NULL; +} + + +static ALCboolean ALCmmdevPlayback_reset(ALCmmdevPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + HRESULT hr = E_FAIL; + + if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + hr = WaitForResponse(&req); + + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; +} + +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; + UINT32 buffer_len, min_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; + + hr = IAudioClient_GetMixFormat(self->client, &wfx); + if(FAILED(hr)) + { + ERR("Failed to get mix format: 0x%08lx\n", hr); + return hr; + } + + if(!MakeExtensible(&OutputType, wfx)) + { + CoTaskMemFree(wfx); + return E_FAIL; + } + CoTaskMemFree(wfx); + wfx = NULL; + + buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 + + device->Frequency-1) / device->Frequency; + + if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) + device->Frequency = OutputType.Format.nSamplesPerSec; + if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) + { + if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) + device->FmtChans = DevFmtMono; + else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) + device->FmtChans = DevFmtStereo; + else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) + device->FmtChans = DevFmtQuad; + else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) + device->FmtChans = DevFmtX51; + 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 || OutputType.dwChannelMask == X7DOT1_WIDE)) + device->FmtChans = DevFmtX71; + else + ERR("Unhandled channel config: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask); + } + + switch(device->FmtChans) + { + case DevFmtMono: + OutputType.Format.nChannels = 1; + OutputType.dwChannelMask = MONO; + break; + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + device->FmtChans = DevFmtStereo; + /*fall-through*/ + 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; + } + switch(device->FmtType) + { + case DevFmtByte: + device->FmtType = DevFmtUByte; + /* fall-through */ + case DevFmtUByte: + OutputType.Format.wBitsPerSample = 8; + OutputType.Samples.wValidBitsPerSample = 8; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtUShort: + device->FmtType = DevFmtShort; + /* fall-through */ + case DevFmtShort: + OutputType.Format.wBitsPerSample = 16; + OutputType.Samples.wValidBitsPerSample = 16; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtUInt: + device->FmtType = DevFmtInt; + /* fall-through */ + case DevFmtInt: + OutputType.Format.wBitsPerSample = 32; + OutputType.Samples.wValidBitsPerSample = 32; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtFloat: + OutputType.Format.wBitsPerSample = 32; + OutputType.Samples.wValidBitsPerSample = 32; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + break; + } + OutputType.Format.nSamplesPerSec = device->Frequency; + + OutputType.Format.nBlockAlign = OutputType.Format.nChannels * + OutputType.Format.wBitsPerSample / 8; + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * + OutputType.Format.nBlockAlign; + + hr = IAudioClient_IsFormatSupported(self->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); + if(FAILED(hr)) + { + ERR("Failed to check format support: 0x%08lx\n", hr); + hr = IAudioClient_GetMixFormat(self->client, &wfx); + } + if(FAILED(hr)) + { + ERR("Failed to find a supported format: 0x%08lx\n", hr); + return hr; + } + + if(wfx != NULL) + { + if(!MakeExtensible(&OutputType, wfx)) + { + CoTaskMemFree(wfx); + return E_FAIL; + } + CoTaskMemFree(wfx); + wfx = NULL; + + device->Frequency = OutputType.Format.nSamplesPerSec; + if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) + device->FmtChans = DevFmtMono; + else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) + device->FmtChans = DevFmtStereo; + else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) + device->FmtChans = DevFmtQuad; + else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) + device->FmtChans = DevFmtX51; + 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 || OutputType.dwChannelMask == X7DOT1_WIDE)) + device->FmtChans = DevFmtX71; + else + { + ERR("Unhandled extensible channels: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask); + device->FmtChans = DevFmtStereo; + OutputType.Format.nChannels = 2; + OutputType.dwChannelMask = STEREO; + } + + if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) + { + if(OutputType.Format.wBitsPerSample == 8) + device->FmtType = DevFmtUByte; + else if(OutputType.Format.wBitsPerSample == 16) + device->FmtType = DevFmtShort; + else if(OutputType.Format.wBitsPerSample == 32) + device->FmtType = DevFmtInt; + else + { + device->FmtType = DevFmtShort; + OutputType.Format.wBitsPerSample = 16; + } + } + else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) + { + device->FmtType = DevFmtFloat; + OutputType.Format.wBitsPerSample = 32; + } + else + { + ERR("Unhandled format sub-type\n"); + device->FmtType = DevFmtShort; + OutputType.Format.wBitsPerSample = 16; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + } + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + } + get_device_formfactor(self->mmdev, &formfactor); + device->IsHeadphones = (device->FmtChans == DevFmtStereo && + (formfactor == Headphones || formfactor == Headset) + ); + + SetDefaultWFXChannelOrder(device); + + 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_GetDevicePeriod(self->client, &min_per, NULL); + if(SUCCEEDED(hr)) + { + min_len = (UINT32)((min_per*device->Frequency + 10000000-1) / 10000000); + /* 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; + hr = IAudioClient_GetBufferSize(self->client, &buffer_len); + } + if(FAILED(hr)) + { + ERR("Failed to get audio buffer info: 0x%08lx\n", hr); + return hr; + } + + device->UpdateSize = min_len; + device->NumUpdates = buffer_len / device->UpdateSize; + if(device->NumUpdates <= 1) + { + ERR("Audio client returned buffer_len < period*2; expect break up\n"); + device->NumUpdates = 2; + device->UpdateSize = buffer_len / device->NumUpdates; + } + + 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 ALCmmdevPlayback_start(ALCmmdevPlayback *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 ALCmmdevPlayback_startProxy(ALCmmdevPlayback *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); + + if(SUCCEEDED(hr)) + hr = IAudioClient_GetService(self->client, &IID_IAudioRenderClient, &ptr); + if(SUCCEEDED(hr)) + { + self->render = ptr; + self->killNow = 0; + if(althrd_create(&self->thread, ALCmmdevPlayback_mixerProc, self) != althrd_success) + { + if(self->render) + IAudioRenderClient_Release(self->render); + self->render = NULL; + IAudioClient_Stop(self->client); + ERR("Failed to start thread\n"); + hr = E_FAIL; + } + } + + return hr; +} + + +static void ALCmmdevPlayback_stop(ALCmmdevPlayback *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + (void)WaitForResponse(&req); +} + +static void ALCmmdevPlayback_stopProxy(ALCmmdevPlayback *self) +{ + int res; + + if(!self->render) + return; + + self->killNow = 1; + althrd_join(self->thread, &res); + + IAudioRenderClient_Release(self->render); + self->render = NULL; + IAudioClient_Stop(self->client); +} + + +static ClockLatency ALCmmdevPlayback_getClockLatency(ALCmmdevPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ClockLatency ret; + + ALCmmdevPlayback_lock(self); + ret.ClockTime = GetDeviceClockTime(device); + ret.Latency = self->Padding * DEVICE_CLOCK_RES / device->Frequency; + ALCmmdevPlayback_unlock(self); + + return ret; +} + + +typedef struct ALCmmdevCapture { + DERIVE_FROM_TYPE(ALCbackend); + DERIVE_FROM_TYPE(ALCmmdevProxy); + + WCHAR *devid; + + IMMDevice *mmdev; + IAudioClient *client; + IAudioCaptureClient *capture; + HANDLE NotifyEvent; + + HANDLE MsgEvent; + + ll_ringbuffer_t *Ring; + + volatile int killNow; + althrd_t thread; +} ALCmmdevCapture; + +static int ALCmmdevCapture_recordProc(void *arg); + +static void ALCmmdevCapture_Construct(ALCmmdevCapture *self, ALCdevice *device); +static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self); +static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *name); +static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self); +static void ALCmmdevCapture_close(ALCmmdevCapture *self); +static void ALCmmdevCapture_closeProxy(ALCmmdevCapture *self); +static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, ALCboolean, reset) +static HRESULT ALCmmdevCapture_resetProxy(ALCmmdevCapture *self); +static ALCboolean ALCmmdevCapture_start(ALCmmdevCapture *self); +static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self); +static void ALCmmdevCapture_stop(ALCmmdevCapture *self); +static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self); +static ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples); +static ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self); +static DECLARE_FORWARD(ALCmmdevCapture, ALCbackend, 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) +{ + SET_VTABLE2(ALCmmdevCapture, ALCbackend, self); + SET_VTABLE2(ALCmmdevCapture, ALCmmdevProxy, self); + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + ALCmmdevProxy_Construct(STATIC_CAST(ALCmmdevProxy, self)); + + self->devid = NULL; + + self->mmdev = NULL; + self->client = NULL; + self->capture = NULL; + self->NotifyEvent = NULL; + + self->MsgEvent = NULL; + + self->Ring = NULL; + + self->killNow = 0; +} + +static void ALCmmdevCapture_Destruct(ALCmmdevCapture *self) +{ + ll_ringbuffer_free(self->Ring); + self->Ring = NULL; + + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + if(self->MsgEvent != NULL) + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + free(self->devid); + self->devid = NULL; + + ALCmmdevProxy_Destruct(STATIC_CAST(ALCmmdevProxy, self)); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +FORCE_ALIGN int ALCmmdevCapture_recordProc(void *arg) +{ + ALCmmdevCapture *self = arg; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + HRESULT hr; + + hr = CoInitialize(NULL); + if(FAILED(hr)) + { + ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); + V0(device->Backend,lock)(); + aluHandleDisconnect(device); + V0(device->Backend,unlock)(); + return 1; + } + + althrd_setname(althrd_current(), RECORD_THREAD_NAME); + + while(!self->killNow) + { + UINT32 avail; + DWORD res; + + hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail); + if(FAILED(hr)) + ERR("Failed to get next packet size: 0x%08lx\n", hr); + else while(avail > 0 && SUCCEEDED(hr)) + { + UINT32 numsamples; + DWORD flags; + BYTE *data; + + hr = IAudioCaptureClient_GetBuffer(self->capture, + &data, &numsamples, &flags, NULL, NULL + ); + if(FAILED(hr)) + { + ERR("Failed to get capture buffer: 0x%08lx\n", hr); + break; + } + + ll_ringbuffer_write(self->Ring, (char*)data, numsamples); + + hr = IAudioCaptureClient_ReleaseBuffer(self->capture, numsamples); + if(FAILED(hr)) + { + ERR("Failed to release capture buffer: 0x%08lx\n", hr); + break; + } + + hr = IAudioCaptureClient_GetNextPacketSize(self->capture, &avail); + if(FAILED(hr)) + ERR("Failed to get next packet size: 0x%08lx\n", hr); + } + + if(FAILED(hr)) + { + V0(device->Backend,lock)(); + aluHandleDisconnect(device); + V0(device->Backend,unlock)(); + break; + } + + res = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); + if(res != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: 0x%lx\n", res); + } + + CoUninitialize(); + return 0; +} + + +static ALCenum ALCmmdevCapture_open(ALCmmdevCapture *self, const ALCchar *deviceName) +{ + HRESULT hr = S_OK; + + self->NotifyEvent = 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()); + hr = E_FAIL; + } + + if(SUCCEEDED(hr)) + { + if(deviceName) + { + const DevMap *iter; + + if(VECTOR_SIZE(CaptureDevices) == 0) + { + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, CAPTURE_DEVICE_PROBE)) + (void)WaitForResponse(&req); + } + + hr = E_FAIL; +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0 || \ + al_string_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); + al_string_copy(&device->DeviceName, iter->name); + hr = S_OK; + } + } + } + + if(SUCCEEDED(hr)) + { + ThreadRequest req = { self->MsgEvent, 0 }; + + hr = E_FAIL; + if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + hr = WaitForResponse(&req); + else + ERR("Failed to post thread message: %lu\n", GetLastError()); + } + + if(FAILED(hr)) + { + if(self->NotifyEvent != NULL) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + if(self->MsgEvent != NULL) + CloseHandle(self->MsgEvent); + self->MsgEvent = NULL; + + free(self->devid); + self->devid = NULL; + + ERR("Device init failed: 0x%08lx\n", hr); + return ALC_INVALID_VALUE; + } + else + { + ThreadRequest req = { self->MsgEvent, 0 }; + + hr = E_FAIL; + if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + hr = WaitForResponse(&req); + else + ERR("Failed to post thread message: %lu\n", GetLastError()); + + if(FAILED(hr)) + { + ALCmmdevCapture_close(self); + if(hr == E_OUTOFMEMORY) + return ALC_OUT_OF_MEMORY; + return ALC_INVALID_VALUE; + } + } + + return ALC_NO_ERROR; +} + +static HRESULT ALCmmdevCapture_openProxy(ALCmmdevCapture *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + void *ptr; + HRESULT hr; + + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); + if(SUCCEEDED(hr)) + { + IMMDeviceEnumerator *Enumerator = ptr; + if(!self->devid) + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eCapture, eMultimedia, &self->mmdev); + else + hr = IMMDeviceEnumerator_GetDevice(Enumerator, self->devid, &self->mmdev); + IMMDeviceEnumerator_Release(Enumerator); + Enumerator = NULL; + } + if(SUCCEEDED(hr)) + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(SUCCEEDED(hr)) + { + self->client = ptr; + if(al_string_empty(device->DeviceName)) + get_device_name_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; + REFERENCE_TIME buf_time; + UINT32 buffer_len; + void *ptr = NULL; + HRESULT hr; + + if(self->client) + IAudioClient_Release(self->client); + self->client = NULL; + + hr = IMMDevice_Activate(self->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); + if(FAILED(hr)) + { + ERR("Failed to reactivate audio client: 0x%08lx\n", hr); + return hr; + } + self->client = ptr; + + buf_time = ((REFERENCE_TIME)device->UpdateSize*device->NumUpdates*10000000 + + device->Frequency-1) / device->Frequency; + + OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + switch(device->FmtChans) + { + case DevFmtMono: + OutputType.Format.nChannels = 1; + OutputType.dwChannelMask = MONO; + break; + case DevFmtStereo: + OutputType.Format.nChannels = 2; + OutputType.dwChannelMask = STEREO; + break; + case DevFmtQuad: + OutputType.Format.nChannels = 4; + OutputType.dwChannelMask = QUAD; + break; + case DevFmtX51: + OutputType.Format.nChannels = 6; + OutputType.dwChannelMask = X5DOT1; + break; + case DevFmtX51Rear: + OutputType.Format.nChannels = 6; + OutputType.dwChannelMask = X5DOT1REAR; + break; + case DevFmtX61: + OutputType.Format.nChannels = 7; + OutputType.dwChannelMask = X6DOT1; + break; + case DevFmtX71: + OutputType.Format.nChannels = 8; + OutputType.dwChannelMask = X7DOT1; + break; + + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + return E_FAIL; + } + switch(device->FmtType) + { + case DevFmtUByte: + OutputType.Format.wBitsPerSample = 8; + OutputType.Samples.wValidBitsPerSample = 8; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtShort: + OutputType.Format.wBitsPerSample = 16; + OutputType.Samples.wValidBitsPerSample = 16; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtInt: + OutputType.Format.wBitsPerSample = 32; + OutputType.Samples.wValidBitsPerSample = 32; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtFloat: + OutputType.Format.wBitsPerSample = 32; + OutputType.Samples.wValidBitsPerSample = 32; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + break; + + case DevFmtByte: + case DevFmtUShort: + case DevFmtUInt: + WARN("%s capture samples not supported\n", DevFmtTypeString(device->FmtType)); + return E_FAIL; + } + OutputType.Format.nSamplesPerSec = device->Frequency; + + OutputType.Format.nBlockAlign = OutputType.Format.nChannels * + OutputType.Format.wBitsPerSample / 8; + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * + OutputType.Format.nBlockAlign; + OutputType.Format.cbSize = sizeof(OutputType) - sizeof(OutputType.Format); + + hr = IAudioClient_IsFormatSupported(self->client, + AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx + ); + if(FAILED(hr)) + { + ERR("Failed to check format support: 0x%08lx\n", hr); + return hr; + } + + /* FIXME: We should do conversion/resampling if we didn't get a matching format. */ + if(wfx->nSamplesPerSec != OutputType.Format.nSamplesPerSec || + wfx->wBitsPerSample != OutputType.Format.wBitsPerSample || + wfx->nChannels != OutputType.Format.nChannels || + wfx->nBlockAlign != OutputType.Format.nBlockAlign) + { + ERR("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; + + hr = IAudioClient_Initialize(self->client, + AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + buf_time, 0, &OutputType.Format, NULL + ); + if(FAILED(hr)) + { + ERR("Failed to initialize audio client: 0x%08lx\n", hr); + return hr; + } + + hr = IAudioClient_GetBufferSize(self->client, &buffer_len); + if(FAILED(hr)) + { + ERR("Failed to get buffer size: 0x%08lx\n", hr); + return hr; + } + + buffer_len = maxu(device->UpdateSize*device->NumUpdates + 1, buffer_len); + ll_ringbuffer_free(self->Ring); + self->Ring = ll_ringbuffer_create(buffer_len, OutputType.Format.nBlockAlign); + if(!self->Ring) + { + ERR("Failed to allocate capture ring buffer\n"); + return E_OUTOFMEMORY; + } + + hr = IAudioClient_SetEventHandle(self->client, self->NotifyEvent); + if(FAILED(hr)) + { + ERR("Failed to set event handle: 0x%08lx\n", hr); + return hr; + } + + return hr; +} + + +static ALCboolean ALCmmdevCapture_start(ALCmmdevCapture *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + HRESULT hr = E_FAIL; + + if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + hr = WaitForResponse(&req); + + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; +} + +static HRESULT ALCmmdevCapture_startProxy(ALCmmdevCapture *self) +{ + HRESULT hr; + void *ptr; + + ResetEvent(self->NotifyEvent); + hr = IAudioClient_Start(self->client); + if(FAILED(hr)) + { + ERR("Failed to start audio client: 0x%08lx\n", hr); + return hr; + } + + hr = IAudioClient_GetService(self->client, &IID_IAudioCaptureClient, &ptr); + if(SUCCEEDED(hr)) + { + self->capture = ptr; + self->killNow = 0; + if(althrd_create(&self->thread, ALCmmdevCapture_recordProc, self) != althrd_success) + { + ERR("Failed to start thread\n"); + IAudioCaptureClient_Release(self->capture); + self->capture = NULL; + hr = E_FAIL; + } + } + + if(FAILED(hr)) + { + IAudioClient_Stop(self->client); + IAudioClient_Reset(self->client); + } + + return hr; +} + + +static void ALCmmdevCapture_stop(ALCmmdevCapture *self) +{ + ThreadRequest req = { self->MsgEvent, 0 }; + if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + (void)WaitForResponse(&req); +} + +static void ALCmmdevCapture_stopProxy(ALCmmdevCapture *self) +{ + int res; + + if(!self->capture) + return; + + self->killNow = 1; + althrd_join(self->thread, &res); + + IAudioCaptureClient_Release(self->capture); + self->capture = NULL; + IAudioClient_Stop(self->client); + IAudioClient_Reset(self->client); +} + + +ALuint ALCmmdevCapture_availableSamples(ALCmmdevCapture *self) +{ + return (ALuint)ll_ringbuffer_read_space(self->Ring); +} + +ALCenum ALCmmdevCapture_captureSamples(ALCmmdevCapture *self, ALCvoid *buffer, ALCuint samples) +{ + if(ALCmmdevCapture_availableSamples(self) < samples) + return ALC_INVALID_VALUE; + ll_ringbuffer_read(self->Ring, buffer, samples); + return ALC_NO_ERROR; +} + + +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_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); + } + + return NULL; +} + + +ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void) +{ + static ALCmmdevBackendFactory factory = ALCMMDEVBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} diff --git a/Engine/lib/openal-soft/Alc/backends/null.c b/Engine/lib/openal-soft/Alc/backends/null.c new file mode 100644 index 000000000..5b153cd97 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/null.c @@ -0,0 +1,223 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2010 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#ifdef HAVE_WINDOWS_H +#include +#endif + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" + +#include "backends/base.h" + + +typedef struct ALCnullBackend { + DERIVE_FROM_TYPE(ALCbackend); + + volatile int killNow; + althrd_t thread; +} ALCnullBackend; + +static int ALCnullBackend_mixerProc(void *ptr); + +static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device); +static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, Destruct) +static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name); +static void ALCnullBackend_close(ALCnullBackend *self); +static ALCboolean ALCnullBackend_reset(ALCnullBackend *self); +static ALCboolean ALCnullBackend_start(ALCnullBackend *self); +static void ALCnullBackend_stop(ALCnullBackend *self); +static DECLARE_FORWARD2(ALCnullBackend, ALCbackend, ALCenum, captureSamples, void*, ALCuint) +static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALCuint, availableSamples) +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) + +DEFINE_ALCBACKEND_VTABLE(ALCnullBackend); + + +static const ALCchar nullDevice[] = "No Output"; + + +static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCnullBackend, ALCbackend, self); +} + + +static int ALCnullBackend_mixerProc(void *ptr) +{ + ALCnullBackend *self = (ALCnullBackend*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + struct timespec now, start; + ALuint64 avail, done; + const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / + device->Frequency / 2); + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + 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) + { + aluMixData(device, NULL, device->UpdateSize); + done += device->UpdateSize; + } + } + + return 0; +} + + +static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name) +{ + ALCdevice *device; + + if(!name) + name = nullDevice; + else if(strcmp(name, nullDevice) != 0) + return ALC_INVALID_VALUE; + + device = STATIC_CAST(ALCbackend, self)->mDevice; + al_string_copy_cstr(&device->DeviceName, name); + + return ALC_NO_ERROR; +} + +static void ALCnullBackend_close(ALCnullBackend* UNUSED(self)) +{ +} + +static ALCboolean ALCnullBackend_reset(ALCnullBackend *self) +{ + SetDefaultWFXChannelOrder(STATIC_CAST(ALCbackend, self)->mDevice); + return ALC_TRUE; +} + +static ALCboolean ALCnullBackend_start(ALCnullBackend *self) +{ + self->killNow = 0; + if(althrd_create(&self->thread, ALCnullBackend_mixerProc, self) != althrd_success) + return ALC_FALSE; + return ALC_TRUE; +} + +static void ALCnullBackend_stop(ALCnullBackend *self) +{ + int res; + + if(self->killNow) + return; + + self->killNow = 1; + althrd_join(self->thread, &res); +} + + +typedef struct ALCnullBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCnullBackendFactory; +#define ALCNULLBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCnullBackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCnullBackendFactory_getFactory(void); + +static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory *self); +static DECLARE_FORWARD(ALCnullBackendFactory, ALCbackendFactory, void, deinit) +static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory *self, ALCbackend_Type type); +static void ALCnullBackendFactory_probe(ALCnullBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCnullBackendFactory); + + +ALCbackendFactory *ALCnullBackendFactory_getFactory(void) +{ + static ALCnullBackendFactory factory = ALCNULLBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} + + +static ALCboolean ALCnullBackendFactory_init(ALCnullBackendFactory* UNUSED(self)) +{ + return ALC_TRUE; +} + +static ALCboolean ALCnullBackendFactory_querySupport(ALCnullBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enum DevProbe type) +{ + switch(type) + { + case ALL_DEVICE_PROBE: + AppendAllDevicesList(nullDevice); + break; + case CAPTURE_DEVICE_PROBE: + break; + } +} + +static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCnullBackend *backend; + NEW_OBJ(backend, ALCnullBackend)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} diff --git a/Engine/lib/openal-soft/Alc/backends/opensl.c b/Engine/lib/openal-soft/Alc/backends/opensl.c new file mode 100644 index 000000000..0796c49ab --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/opensl.c @@ -0,0 +1,436 @@ +/* + * 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 + +#include "alMain.h" +#include "alu.h" +#include "threads.h" + +#include +#include + +/* 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_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 DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + break; + } + 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"); + } + if(SL_RESULT_SUCCESS == result) + { + SLAndroidSimpleBufferQueueState state; + do { + althrd_yield(); + result = VCALL(bufferQueue,GetState)(&state); + } while(SL_RESULT_SUCCESS == result && state.count > 0); + PRINTERR(result, "bufferQueue->GetState"); + } + + free(data->buffer); + 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 +}; + + +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; + } +} diff --git a/Engine/lib/openal-soft/Alc/backends/oss.c b/Engine/lib/openal-soft/Alc/backends/oss.c new file mode 100644 index 000000000..432c75f21 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/oss.c @@ -0,0 +1,821 @@ +/** + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" + +#include "backends/base.h" + +#include + +/* + * The OSS documentation talks about SOUND_MIXER_READ, but the header + * only contains MIXER_READ. Play safe. Same for WRITE. + */ +#ifndef SOUND_MIXER_READ +#define SOUND_MIXER_READ MIXER_READ +#endif +#ifndef SOUND_MIXER_WRITE +#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 + +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 + +static void ALCossListPopulate(struct oss_device *UNUSED(playback), struct oss_device *UNUSED(capture)) +{ +} + +#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 *playback, struct oss_device *capture) +{ + struct oss_sysinfo si; + struct oss_audioinfo ai; + int fd, i; + + if((fd=open("/dev/mixer", O_RDONLY)) < 0) + { + ERR("Could not open /dev/mixer\n"); + return; + } + if(ioctl(fd, SNDCTL_SYSINFO, &si) == -1) + { + ERR("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&DSP_CAP_INPUT) && capture != NULL) + ALCossListAppend(capture, handle, len, ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))); + if((ai.caps&DSP_CAP_OUTPUT) && playback != NULL) + ALCossListAppend(playback, 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) +{ + int y = 0; + while (x > 1) + { + x >>= 1; + y++; + } + return y; +} + +typedef struct ALCplaybackOSS { + DERIVE_FROM_TYPE(ALCbackend); + + int fd; + + ALubyte *mix_data; + int data_size; + + volatile int killNow; + althrd_t thread; +} ALCplaybackOSS; + +static int ALCplaybackOSS_mixerProc(void *ptr); + +static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device); +static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, Destruct) +static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name); +static void ALCplaybackOSS_close(ALCplaybackOSS *self); +static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self); +static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self); +static void ALCplaybackOSS_stop(ALCplaybackOSS *self); +static DECLARE_FORWARD2(ALCplaybackOSS, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) +static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALCuint, availableSamples) +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) +DEFINE_ALCBACKEND_VTABLE(ALCplaybackOSS); + + +static int ALCplaybackOSS_mixerProc(void *ptr) +{ + ALCplaybackOSS *self = (ALCplaybackOSS*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + ALint frameSize; + ssize_t wrote; + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + + while(!self->killNow && device->Connected) + { + ALint len = self->data_size; + ALubyte *WritePtr = self->mix_data; + + aluMixData(device, WritePtr, len/frameSize); + while(len > 0 && !self->killNow) + { + wrote = write(self->fd, WritePtr, len); + 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(1000000); + continue; + } + + len -= wrote; + WritePtr += wrote; + } + } + + return 0; +} + + +static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCplaybackOSS, ALCbackend, self); +} + +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 = dev->handle; + else + { + while (dev != NULL) + { + if (strcmp(dev->handle, name) == 0) + break; + dev = dev->next; + } + if (dev == NULL) + return ALC_INVALID_VALUE; + } + + self->killNow = 0; + + self->fd = open(dev->path, O_WRONLY); + if(self->fd == -1) + { + ERR("Could not open %s: %s\n", dev->path, strerror(errno)); + return ALC_INVALID_VALUE; + } + + al_string_copy_cstr(&device->DeviceName, name); + + return ALC_NO_ERROR; +} + +static void ALCplaybackOSS_close(ALCplaybackOSS *self) +{ + close(self->fd); + self->fd = -1; +} + +static ALCboolean ALCplaybackOSS_reset(ALCplaybackOSS *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + int numFragmentsLogSize; + int log2FragmentSize; + unsigned int periods; + audio_buf_info info; + ALuint frameSize; + int numChannels; + int ossFormat; + int ossSpeed; + char *err; + + switch(device->FmtType) + { + case DevFmtByte: + ossFormat = AFMT_S8; + break; + case DevFmtUByte: + ossFormat = AFMT_U8; + break; + case DevFmtUShort: + case DevFmtInt: + case DevFmtUInt: + case DevFmtFloat: + device->FmtType = DevFmtShort; + /* fall-through */ + case DevFmtShort: + ossFormat = AFMT_S16_NE; + break; + } + + periods = device->NumUpdates; + numChannels = ChannelsFromDevFmt(device->FmtChans); + frameSize = numChannels * BytesFromDevFmt(device->FmtType); + + 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--; + numFragmentsLogSize = (periods << 16) | log2FragmentSize; + +#define CHECKERR(func) if((func) < 0) { \ + err = #func; \ + goto err; \ +} + /* Don't fail if SETFRAGMENT fails. We can handle just about anything + * that's reported back via GETOSPACE */ + ioctl(self->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize); + CHECKERR(ioctl(self->fd, SNDCTL_DSP_SETFMT, &ossFormat)); + CHECKERR(ioctl(self->fd, SNDCTL_DSP_CHANNELS, &numChannels)); + CHECKERR(ioctl(self->fd, SNDCTL_DSP_SPEED, &ossSpeed)); + CHECKERR(ioctl(self->fd, SNDCTL_DSP_GETOSPACE, &info)); + if(0) + { + err: + ERR("%s failed: %s\n", err, strerror(errno)); + return ALC_FALSE; + } +#undef CHECKERR + + if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) + { + ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); + return ALC_FALSE; + } + + if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) || + (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) || + (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort))) + { + ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat); + return ALC_FALSE; + } + + device->Frequency = ossSpeed; + device->UpdateSize = info.fragsize / frameSize; + device->NumUpdates = info.fragments + 1; + + SetDefaultChannelOrder(device); + + return ALC_TRUE; +} + +static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + + self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->mix_data = calloc(1, self->data_size); + + self->killNow = 0; + if(althrd_create(&self->thread, ALCplaybackOSS_mixerProc, self) != althrd_success) + { + free(self->mix_data); + self->mix_data = NULL; + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static void ALCplaybackOSS_stop(ALCplaybackOSS *self) +{ + int res; + + if(self->killNow) + return; + + self->killNow = 1; + althrd_join(self->thread, &res); + + if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0) + ERR("Error resetting device: %s\n", strerror(errno)); + + free(self->mix_data); + self->mix_data = NULL; +} + + +typedef struct ALCcaptureOSS { + DERIVE_FROM_TYPE(ALCbackend); + + int fd; + + ll_ringbuffer_t *ring; + int doCapture; + + volatile int killNow; + althrd_t thread; +} ALCcaptureOSS; + +static int ALCcaptureOSS_recordProc(void *ptr); + +static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device); +static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, Destruct) +static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name); +static void ALCcaptureOSS_close(ALCcaptureOSS *self); +static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALCboolean, reset) +static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self); +static void ALCcaptureOSS_stop(ALCcaptureOSS *self); +static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples); +static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self); +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) +DEFINE_ALCBACKEND_VTABLE(ALCcaptureOSS); + + +static int ALCcaptureOSS_recordProc(void *ptr) +{ + ALCcaptureOSS *self = (ALCcaptureOSS*)ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + int frameSize; + ssize_t amt; + + SetRTPriority(); + althrd_setname(althrd_current(), RECORD_THREAD_NAME); + + frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + + while(!self->killNow) + { + ll_ringbuffer_data_t vec[2]; + + amt = 0; + if(self->doCapture) + { + ll_ringbuffer_get_write_vector(self->ring, vec); + if(vec[0].len > 0) + { + amt = read(self->fd, vec[0].buf, vec[0].len*frameSize); + 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/frameSize); + } + } + if(amt == 0) + { + al_nssleep(1000000); + continue; + } + } + + return 0; +} + + +static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCcaptureOSS, ALCbackend, self); +} + +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; + audio_buf_info info; + ALuint frameSize; + int numChannels; + int ossFormat; + int ossSpeed; + char *err; + + if(!name) + name = dev->handle; + else + { + while (dev != NULL) + { + if (strcmp(dev->handle, name) == 0) + break; + dev = dev->next; + } + if (dev == NULL) + return ALC_INVALID_VALUE; + } + + self->fd = open(dev->path, O_RDONLY); + if(self->fd == -1) + { + ERR("Could not open %s: %s\n", dev->path, strerror(errno)); + return ALC_INVALID_VALUE; + } + + switch(device->FmtType) + { + case DevFmtByte: + ossFormat = AFMT_S8; + break; + case DevFmtUByte: + ossFormat = AFMT_U8; + break; + case DevFmtShort: + ossFormat = AFMT_S16_NE; + break; + case DevFmtUShort: + case DevFmtInt: + case DevFmtUInt: + case DevFmtFloat: + ERR("%s capture samples not supported\n", DevFmtTypeString(device->FmtType)); + return ALC_INVALID_VALUE; + } + + periods = 4; + numChannels = ChannelsFromDevFmt(device->FmtChans); + frameSize = numChannels * BytesFromDevFmt(device->FmtType); + ossSpeed = device->Frequency; + log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates * + frameSize / periods); + + /* according to the OSS spec, 16 bytes are the minimum */ + if (log2FragmentSize < 4) + log2FragmentSize = 4; + numFragmentsLogSize = (periods << 16) | log2FragmentSize; + +#define CHECKERR(func) if((func) < 0) { \ + err = #func; \ + goto err; \ +} + CHECKERR(ioctl(self->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize)); + CHECKERR(ioctl(self->fd, SNDCTL_DSP_SETFMT, &ossFormat)); + CHECKERR(ioctl(self->fd, SNDCTL_DSP_CHANNELS, &numChannels)); + CHECKERR(ioctl(self->fd, SNDCTL_DSP_SPEED, &ossSpeed)); + CHECKERR(ioctl(self->fd, SNDCTL_DSP_GETISPACE, &info)); + if(0) + { + err: + ERR("%s failed: %s\n", err, strerror(errno)); + close(self->fd); + self->fd = -1; + return ALC_INVALID_VALUE; + } +#undef CHECKERR + + if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) + { + ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); + close(self->fd); + self->fd = -1; + return ALC_INVALID_VALUE; + } + + if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) || + (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) || + (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort))) + { + ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat); + close(self->fd); + self->fd = -1; + return ALC_INVALID_VALUE; + } + + self->ring = ll_ringbuffer_create(device->UpdateSize*device->NumUpdates + 1, frameSize); + if(!self->ring) + { + ERR("Ring buffer create failed\n"); + close(self->fd); + self->fd = -1; + return ALC_OUT_OF_MEMORY; + } + + self->killNow = 0; + if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success) + { + ll_ringbuffer_free(self->ring); + self->ring = NULL; + close(self->fd); + self->fd = -1; + return ALC_OUT_OF_MEMORY; + } + + al_string_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; + + ll_ringbuffer_free(self->ring); + self->ring = NULL; +} + +static ALCboolean ALCcaptureOSS_start(ALCcaptureOSS *self) +{ + self->doCapture = 1; + return ALC_TRUE; +} + +static void ALCcaptureOSS_stop(ALCcaptureOSS *self) +{ + self->doCapture = 0; +} + +static ALCenum ALCcaptureOSS_captureSamples(ALCcaptureOSS *self, ALCvoid *buffer, ALCuint samples) +{ + ll_ringbuffer_read(self->ring, buffer, samples); + return ALC_NO_ERROR; +} + +static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self) +{ + return ll_ringbuffer_read_space(self->ring); +} + + +typedef struct ALCossBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCossBackendFactory; +#define ALCOSSBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCossBackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCossBackendFactory_getFactory(void); + +static ALCboolean ALCossBackendFactory_init(ALCossBackendFactory *self); +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); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCossBackendFactory); + + +ALCbackendFactory *ALCossBackendFactory_getFactory(void) +{ + static ALCossBackendFactory factory = ALCOSSBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} + + +ALCboolean ALCossBackendFactory_init(ALCossBackendFactory* UNUSED(self)) +{ + 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) + return ALC_TRUE; + return ALC_FALSE; +} + +void ALCossBackendFactory_probe(ALCossBackendFactory* UNUSED(self), enum DevProbe type) +{ + switch(type) + { + case ALL_DEVICE_PROBE: + { + struct oss_device *cur = &oss_playback; + ALCossListFree(cur); + ALCossListPopulate(cur, NULL); + while (cur != NULL) + { + AppendAllDevicesList(cur->handle); + cur = cur->next; + } + } + break; + + case CAPTURE_DEVICE_PROBE: + { + struct oss_device *cur = &oss_capture; + ALCossListFree(cur); + ALCossListPopulate(NULL, cur); + while (cur != NULL) + { + AppendCaptureDeviceList(cur->handle); + cur = cur->next; + } + } + break; + } +} + +ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCplaybackOSS *backend; + NEW_OBJ(backend, ALCplaybackOSS)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + if(type == ALCbackend_Capture) + { + ALCcaptureOSS *backend; + NEW_OBJ(backend, ALCcaptureOSS)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} diff --git a/Engine/lib/openal-soft/Alc/backends/portaudio.c b/Engine/lib/openal-soft/Alc/backends/portaudio.c new file mode 100644 index 000000000..1dbca9416 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/portaudio.c @@ -0,0 +1,573 @@ +/** + * 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 +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "compat.h" + +#include "backends/base.h" + +#include + + +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; + + aluMixData(STATIC_CAST(ALCbackend, self)->mDevice, outputBuffer, framesPerBuffer); + 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; + } + + al_string_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); + + 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); + + 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; + } + + al_string_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); +} diff --git a/Engine/lib/openal-soft/Alc/backends/pulseaudio.c b/Engine/lib/openal-soft/Alc/backends/pulseaudio.c new file mode 100644 index 000000000..f46386e4f --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/pulseaudio.c @@ -0,0 +1,1847 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2009 by Konstantinos Natsakis + * Copyright (C) 2010 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" + +#include "backends/base.h" + +#include + +#if PA_API_VERSION == 12 + +#ifdef HAVE_DYNLOAD +static void *pa_handle; +#define MAKE_FUNC(x) static __typeof(x) * p##x +MAKE_FUNC(pa_context_unref); +MAKE_FUNC(pa_sample_spec_valid); +MAKE_FUNC(pa_frame_size); +MAKE_FUNC(pa_stream_drop); +MAKE_FUNC(pa_strerror); +MAKE_FUNC(pa_context_get_state); +MAKE_FUNC(pa_stream_get_state); +MAKE_FUNC(pa_threaded_mainloop_signal); +MAKE_FUNC(pa_stream_peek); +MAKE_FUNC(pa_threaded_mainloop_wait); +MAKE_FUNC(pa_threaded_mainloop_unlock); +MAKE_FUNC(pa_threaded_mainloop_in_thread); +MAKE_FUNC(pa_context_new); +MAKE_FUNC(pa_threaded_mainloop_stop); +MAKE_FUNC(pa_context_disconnect); +MAKE_FUNC(pa_threaded_mainloop_start); +MAKE_FUNC(pa_threaded_mainloop_get_api); +MAKE_FUNC(pa_context_set_state_callback); +MAKE_FUNC(pa_stream_write); +MAKE_FUNC(pa_xfree); +MAKE_FUNC(pa_stream_connect_record); +MAKE_FUNC(pa_stream_connect_playback); +MAKE_FUNC(pa_stream_readable_size); +MAKE_FUNC(pa_stream_writable_size); +MAKE_FUNC(pa_stream_is_corked); +MAKE_FUNC(pa_stream_cork); +MAKE_FUNC(pa_stream_is_suspended); +MAKE_FUNC(pa_stream_get_device_name); +MAKE_FUNC(pa_stream_get_latency); +MAKE_FUNC(pa_path_get_filename); +MAKE_FUNC(pa_get_binary_name); +MAKE_FUNC(pa_threaded_mainloop_free); +MAKE_FUNC(pa_context_errno); +MAKE_FUNC(pa_xmalloc); +MAKE_FUNC(pa_stream_unref); +MAKE_FUNC(pa_threaded_mainloop_accept); +MAKE_FUNC(pa_stream_set_write_callback); +MAKE_FUNC(pa_threaded_mainloop_new); +MAKE_FUNC(pa_context_connect); +MAKE_FUNC(pa_stream_set_buffer_attr); +MAKE_FUNC(pa_stream_get_buffer_attr); +MAKE_FUNC(pa_stream_get_sample_spec); +MAKE_FUNC(pa_stream_get_time); +MAKE_FUNC(pa_stream_set_read_callback); +MAKE_FUNC(pa_stream_set_state_callback); +MAKE_FUNC(pa_stream_set_moved_callback); +MAKE_FUNC(pa_stream_set_underflow_callback); +MAKE_FUNC(pa_stream_new_with_proplist); +MAKE_FUNC(pa_stream_disconnect); +MAKE_FUNC(pa_threaded_mainloop_lock); +MAKE_FUNC(pa_channel_map_init_auto); +MAKE_FUNC(pa_channel_map_parse); +MAKE_FUNC(pa_channel_map_snprint); +MAKE_FUNC(pa_channel_map_equal); +MAKE_FUNC(pa_context_get_server_info); +MAKE_FUNC(pa_context_get_sink_info_by_name); +MAKE_FUNC(pa_context_get_sink_info_list); +MAKE_FUNC(pa_context_get_source_info_by_name); +MAKE_FUNC(pa_context_get_source_info_list); +MAKE_FUNC(pa_operation_get_state); +MAKE_FUNC(pa_operation_unref); +MAKE_FUNC(pa_proplist_new); +MAKE_FUNC(pa_proplist_free); +MAKE_FUNC(pa_proplist_set); +MAKE_FUNC(pa_channel_map_superset); +MAKE_FUNC(pa_stream_set_buffer_attr_callback); +MAKE_FUNC(pa_stream_begin_write); +#undef MAKE_FUNC + +#define pa_context_unref ppa_context_unref +#define pa_sample_spec_valid ppa_sample_spec_valid +#define pa_frame_size ppa_frame_size +#define pa_stream_drop ppa_stream_drop +#define pa_strerror ppa_strerror +#define pa_context_get_state ppa_context_get_state +#define pa_stream_get_state ppa_stream_get_state +#define pa_threaded_mainloop_signal ppa_threaded_mainloop_signal +#define pa_stream_peek ppa_stream_peek +#define pa_threaded_mainloop_wait ppa_threaded_mainloop_wait +#define pa_threaded_mainloop_unlock ppa_threaded_mainloop_unlock +#define pa_threaded_mainloop_in_thread ppa_threaded_mainloop_in_thread +#define pa_context_new ppa_context_new +#define pa_threaded_mainloop_stop ppa_threaded_mainloop_stop +#define pa_context_disconnect ppa_context_disconnect +#define pa_threaded_mainloop_start ppa_threaded_mainloop_start +#define pa_threaded_mainloop_get_api ppa_threaded_mainloop_get_api +#define pa_context_set_state_callback ppa_context_set_state_callback +#define pa_stream_write ppa_stream_write +#define pa_xfree ppa_xfree +#define pa_stream_connect_record ppa_stream_connect_record +#define pa_stream_connect_playback ppa_stream_connect_playback +#define pa_stream_readable_size ppa_stream_readable_size +#define pa_stream_writable_size ppa_stream_writable_size +#define pa_stream_is_corked ppa_stream_is_corked +#define pa_stream_cork ppa_stream_cork +#define pa_stream_is_suspended ppa_stream_is_suspended +#define pa_stream_get_device_name ppa_stream_get_device_name +#define pa_stream_get_latency ppa_stream_get_latency +#define pa_path_get_filename ppa_path_get_filename +#define pa_get_binary_name ppa_get_binary_name +#define pa_threaded_mainloop_free ppa_threaded_mainloop_free +#define pa_context_errno ppa_context_errno +#define pa_xmalloc ppa_xmalloc +#define pa_stream_unref ppa_stream_unref +#define pa_threaded_mainloop_accept ppa_threaded_mainloop_accept +#define pa_stream_set_write_callback ppa_stream_set_write_callback +#define pa_threaded_mainloop_new ppa_threaded_mainloop_new +#define pa_context_connect ppa_context_connect +#define pa_stream_set_buffer_attr ppa_stream_set_buffer_attr +#define pa_stream_get_buffer_attr ppa_stream_get_buffer_attr +#define pa_stream_get_sample_spec ppa_stream_get_sample_spec +#define pa_stream_get_time ppa_stream_get_time +#define pa_stream_set_read_callback ppa_stream_set_read_callback +#define pa_stream_set_state_callback ppa_stream_set_state_callback +#define pa_stream_set_moved_callback ppa_stream_set_moved_callback +#define pa_stream_set_underflow_callback ppa_stream_set_underflow_callback +#define pa_stream_new_with_proplist ppa_stream_new_with_proplist +#define pa_stream_disconnect ppa_stream_disconnect +#define pa_threaded_mainloop_lock ppa_threaded_mainloop_lock +#define pa_channel_map_init_auto ppa_channel_map_init_auto +#define pa_channel_map_parse ppa_channel_map_parse +#define pa_channel_map_snprint ppa_channel_map_snprint +#define pa_channel_map_equal ppa_channel_map_equal +#define pa_context_get_server_info ppa_context_get_server_info +#define pa_context_get_sink_info_by_name ppa_context_get_sink_info_by_name +#define pa_context_get_sink_info_list ppa_context_get_sink_info_list +#define pa_context_get_source_info_by_name ppa_context_get_source_info_by_name +#define pa_context_get_source_info_list ppa_context_get_source_info_list +#define pa_operation_get_state ppa_operation_get_state +#define pa_operation_unref ppa_operation_unref +#define pa_proplist_new ppa_proplist_new +#define pa_proplist_free ppa_proplist_free +#define pa_proplist_set ppa_proplist_set +#define pa_channel_map_superset ppa_channel_map_superset +#define pa_stream_set_buffer_attr_callback ppa_stream_set_buffer_attr_callback +#define pa_stream_begin_write ppa_stream_begin_write + +#endif + +static ALCboolean pulse_load(void) +{ + ALCboolean ret = ALC_TRUE; +#ifdef HAVE_DYNLOAD + if(!pa_handle) + { +#ifdef _WIN32 +#define PALIB "libpulse-0.dll" +#elif defined(__APPLE__) && defined(__MACH__) +#define PALIB "libpulse.0.dylib" +#else +#define PALIB "libpulse.so.0" +#endif + pa_handle = LoadLib(PALIB); + if(!pa_handle) + return ALC_FALSE; + +#define LOAD_FUNC(x) do { \ + p##x = GetSymbol(pa_handle, #x); \ + if(!(p##x)) { \ + ret = ALC_FALSE; \ + } \ +} while(0) + LOAD_FUNC(pa_context_unref); + LOAD_FUNC(pa_sample_spec_valid); + LOAD_FUNC(pa_stream_drop); + LOAD_FUNC(pa_frame_size); + LOAD_FUNC(pa_strerror); + LOAD_FUNC(pa_context_get_state); + LOAD_FUNC(pa_stream_get_state); + LOAD_FUNC(pa_threaded_mainloop_signal); + LOAD_FUNC(pa_stream_peek); + LOAD_FUNC(pa_threaded_mainloop_wait); + LOAD_FUNC(pa_threaded_mainloop_unlock); + LOAD_FUNC(pa_threaded_mainloop_in_thread); + LOAD_FUNC(pa_context_new); + LOAD_FUNC(pa_threaded_mainloop_stop); + LOAD_FUNC(pa_context_disconnect); + LOAD_FUNC(pa_threaded_mainloop_start); + LOAD_FUNC(pa_threaded_mainloop_get_api); + LOAD_FUNC(pa_context_set_state_callback); + LOAD_FUNC(pa_stream_write); + LOAD_FUNC(pa_xfree); + LOAD_FUNC(pa_stream_connect_record); + LOAD_FUNC(pa_stream_connect_playback); + LOAD_FUNC(pa_stream_readable_size); + LOAD_FUNC(pa_stream_writable_size); + LOAD_FUNC(pa_stream_is_corked); + LOAD_FUNC(pa_stream_cork); + LOAD_FUNC(pa_stream_is_suspended); + LOAD_FUNC(pa_stream_get_device_name); + LOAD_FUNC(pa_stream_get_latency); + LOAD_FUNC(pa_path_get_filename); + LOAD_FUNC(pa_get_binary_name); + LOAD_FUNC(pa_threaded_mainloop_free); + LOAD_FUNC(pa_context_errno); + LOAD_FUNC(pa_xmalloc); + LOAD_FUNC(pa_stream_unref); + LOAD_FUNC(pa_threaded_mainloop_accept); + LOAD_FUNC(pa_stream_set_write_callback); + LOAD_FUNC(pa_threaded_mainloop_new); + LOAD_FUNC(pa_context_connect); + LOAD_FUNC(pa_stream_set_buffer_attr); + LOAD_FUNC(pa_stream_get_buffer_attr); + LOAD_FUNC(pa_stream_get_sample_spec); + LOAD_FUNC(pa_stream_get_time); + LOAD_FUNC(pa_stream_set_read_callback); + LOAD_FUNC(pa_stream_set_state_callback); + LOAD_FUNC(pa_stream_set_moved_callback); + LOAD_FUNC(pa_stream_set_underflow_callback); + LOAD_FUNC(pa_stream_new_with_proplist); + LOAD_FUNC(pa_stream_disconnect); + LOAD_FUNC(pa_threaded_mainloop_lock); + LOAD_FUNC(pa_channel_map_init_auto); + LOAD_FUNC(pa_channel_map_parse); + LOAD_FUNC(pa_channel_map_snprint); + LOAD_FUNC(pa_channel_map_equal); + LOAD_FUNC(pa_context_get_server_info); + LOAD_FUNC(pa_context_get_sink_info_by_name); + LOAD_FUNC(pa_context_get_sink_info_list); + LOAD_FUNC(pa_context_get_source_info_by_name); + LOAD_FUNC(pa_context_get_source_info_list); + LOAD_FUNC(pa_operation_get_state); + LOAD_FUNC(pa_operation_unref); + LOAD_FUNC(pa_proplist_new); + LOAD_FUNC(pa_proplist_free); + LOAD_FUNC(pa_proplist_set); + LOAD_FUNC(pa_channel_map_superset); + LOAD_FUNC(pa_stream_set_buffer_attr_callback); + LOAD_FUNC(pa_stream_begin_write); +#undef LOAD_FUNC + + if(ret == ALC_FALSE) + { + CloseLib(pa_handle); + pa_handle = NULL; + } + } +#endif /* HAVE_DYNLOAD */ + return ret; +} + + +/* Global flags and properties */ +static pa_context_flags_t pulse_ctx_flags; +static pa_proplist *prop_filter; + + +/* PulseAudio Event Callbacks */ +static void context_state_callback(pa_context *context, void *pdata) +{ + pa_threaded_mainloop *loop = pdata; + pa_context_state_t state; + + state = pa_context_get_state(context); + if(state == PA_CONTEXT_READY || !PA_CONTEXT_IS_GOOD(state)) + pa_threaded_mainloop_signal(loop, 0); +} + +static void stream_state_callback(pa_stream *stream, void *pdata) +{ + pa_threaded_mainloop *loop = pdata; + pa_stream_state_t state; + + state = pa_stream_get_state(stream); + if(state == PA_STREAM_READY || !PA_STREAM_IS_GOOD(state)) + pa_threaded_mainloop_signal(loop, 0); +} + +static void stream_success_callback(pa_stream *UNUSED(stream), int UNUSED(success), void *pdata) +{ + pa_threaded_mainloop *loop = pdata; + pa_threaded_mainloop_signal(loop, 0); +} + +static void wait_for_operation(pa_operation *op, pa_threaded_mainloop *loop) +{ + if(op) + { + while(pa_operation_get_state(op) == PA_OPERATION_RUNNING) + pa_threaded_mainloop_wait(loop); + pa_operation_unref(op); + } +} + + +static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent) +{ + const char *name = "OpenAL Soft"; + char path_name[PATH_MAX]; + pa_context_state_t state; + pa_context *context; + int err; + + if(pa_get_binary_name(path_name, sizeof(path_name))) + name = pa_path_get_filename(path_name); + + context = pa_context_new(pa_threaded_mainloop_get_api(loop), name); + if(!context) + { + ERR("pa_context_new() failed\n"); + return NULL; + } + + pa_context_set_state_callback(context, context_state_callback, loop); + + if((err=pa_context_connect(context, NULL, pulse_ctx_flags, NULL)) >= 0) + { + while((state=pa_context_get_state(context)) != PA_CONTEXT_READY) + { + if(!PA_CONTEXT_IS_GOOD(state)) + { + err = pa_context_errno(context); + if(err > 0) err = -err; + break; + } + + pa_threaded_mainloop_wait(loop); + } + } + pa_context_set_state_callback(context, NULL, NULL); + + if(err < 0) + { + if(!silent) + ERR("Context did not connect: %s\n", pa_strerror(err)); + pa_context_unref(context); + return NULL; + } + + return context; +} + + +static ALCboolean pulse_open(pa_threaded_mainloop **loop, pa_context **context, + void(*state_cb)(pa_context*,void*), void *ptr) +{ + if(!(*loop = pa_threaded_mainloop_new())) + { + ERR("pa_threaded_mainloop_new() failed!\n"); + return ALC_FALSE; + } + if(pa_threaded_mainloop_start(*loop) < 0) + { + ERR("pa_threaded_mainloop_start() failed\n"); + goto error; + } + + pa_threaded_mainloop_lock(*loop); + + *context = connect_context(*loop, AL_FALSE); + if(!*context) + { + pa_threaded_mainloop_unlock(*loop); + pa_threaded_mainloop_stop(*loop); + goto error; + } + pa_context_set_state_callback(*context, state_cb, ptr); + + pa_threaded_mainloop_unlock(*loop); + return ALC_TRUE; + +error: + pa_threaded_mainloop_free(*loop); + *loop = NULL; + + return ALC_FALSE; +} + +static void pulse_close(pa_threaded_mainloop *loop, pa_context *context, pa_stream *stream) +{ + pa_threaded_mainloop_lock(loop); + + if(stream) + { + pa_stream_set_state_callback(stream, NULL, NULL); + pa_stream_set_moved_callback(stream, NULL, NULL); + pa_stream_set_write_callback(stream, NULL, NULL); + pa_stream_set_buffer_attr_callback(stream, NULL, NULL); + pa_stream_disconnect(stream); + pa_stream_unref(stream); + } + + pa_context_disconnect(context); + pa_context_unref(context); + + pa_threaded_mainloop_unlock(loop); + + pa_threaded_mainloop_stop(loop); + pa_threaded_mainloop_free(loop); +} + + +typedef struct { + al_string name; + al_string device_name; +} DevMap; +TYPEDEF_VECTOR(DevMap, vector_DevMap) + +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; + +static void clear_devlist(vector_DevMap *list) +{ +#define DEINIT_STRS(i) (AL_STRING_DEINIT((i)->name),AL_STRING_DEINIT((i)->device_name)) + VECTOR_FOR_EACH(DevMap, *list, DEINIT_STRS); +#undef DEINIT_STRS + VECTOR_RESIZE(*list, 0, 0); +} + + +typedef struct ALCpulsePlayback { + DERIVE_FROM_TYPE(ALCbackend); + + al_string device_name; + + pa_buffer_attr attr; + pa_sample_spec spec; + + pa_threaded_mainloop *loop; + + pa_stream *stream; + pa_context *context; + + volatile ALboolean killNow; + althrd_t thread; +} ALCpulsePlayback; + +static void ALCpulsePlayback_deviceCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata); +static void ALCpulsePlayback_probeDevices(void); + +static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata); +static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata); +static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata); +static void ALCpulsePlayback_streamWriteCallback(pa_stream *p, size_t nbytes, void *userdata); +static void ALCpulsePlayback_sinkInfoCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata); +static void ALCpulsePlayback_sinkNameCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata); +static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata); +static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, pa_threaded_mainloop *loop, + pa_context *context, pa_stream_flags_t flags, + pa_buffer_attr *attr, pa_sample_spec *spec, + pa_channel_map *chanmap); +static int ALCpulsePlayback_mixerProc(void *ptr); + +static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device); +static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self); +static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name); +static void ALCpulsePlayback_close(ALCpulsePlayback *self); +static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self); +static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self); +static void ALCpulsePlayback_stop(ALCpulsePlayback *self); +static DECLARE_FORWARD2(ALCpulsePlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) +static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, ALCuint, availableSamples) +static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self); +static void ALCpulsePlayback_lock(ALCpulsePlayback *self); +static void ALCpulsePlayback_unlock(ALCpulsePlayback *self); +DECLARE_DEFAULT_ALLOCATORS(ALCpulsePlayback) + +DEFINE_ALCBACKEND_VTABLE(ALCpulsePlayback); + + +static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCpulsePlayback, ALCbackend, self); + + AL_STRING_INIT(self->device_name); +} + +static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self) +{ + AL_STRING_DEINIT(self->device_name); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata) +{ + pa_threaded_mainloop *loop = pdata; + const DevMap *iter; + DevMap entry; + int count; + + if(eol) + { + pa_threaded_mainloop_signal(loop, 0); + return; + } + +#define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_INFO_NAME); + if(iter != VECTOR_END(PlaybackDevices)) return; +#undef MATCH_INFO_NAME + + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.device_name); + + al_string_copy_cstr(&entry.device_name, info->name); + + count = 0; + while(1) + { + al_string_copy_cstr(&entry.name, info->description); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&entry.name, str); + } + +#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_ENTRY); + if(iter == VECTOR_END(PlaybackDevices)) break; +#undef MATCH_ENTRY + count++; + } + + TRACE("Got device \"%s\", \"%s\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.device_name)); + + VECTOR_PUSH_BACK(PlaybackDevices, entry); +} + +static void ALCpulsePlayback_probeDevices(void) +{ + pa_threaded_mainloop *loop; + + clear_devlist(&PlaybackDevices); + + if((loop=pa_threaded_mainloop_new()) && + pa_threaded_mainloop_start(loop) >= 0) + { + pa_context *context; + + pa_threaded_mainloop_lock(loop); + context = connect_context(loop, AL_FALSE); + if(context) + { + pa_operation *o; + pa_stream_flags_t flags; + pa_sample_spec spec; + pa_stream *stream; + + flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE | + PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE; + + spec.format = PA_SAMPLE_S16NE; + spec.rate = 44100; + spec.channels = 2; + + stream = ALCpulsePlayback_connectStream(NULL, loop, context, flags, + NULL, &spec, NULL); + if(stream) + { + o = pa_context_get_sink_info_by_name(context, pa_stream_get_device_name(stream), + ALCpulsePlayback_deviceCallback, loop); + wait_for_operation(o, loop); + + pa_stream_disconnect(stream); + pa_stream_unref(stream); + stream = NULL; + } + + o = pa_context_get_sink_info_list(context, ALCpulsePlayback_deviceCallback, loop); + wait_for_operation(o, loop); + + pa_context_disconnect(context); + pa_context_unref(context); + } + pa_threaded_mainloop_unlock(loop); + pa_threaded_mainloop_stop(loop); + } + if(loop) + pa_threaded_mainloop_free(loop); +} + + +static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata) +{ + ALCpulsePlayback *self = pdata; + + self->attr = *pa_stream_get_buffer_attr(stream); + TRACE("minreq=%d, tlength=%d, prebuf=%d\n", self->attr.minreq, self->attr.tlength, self->attr.prebuf); +} + +static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata) +{ + ALCpulsePlayback *self = pdata; + if(pa_context_get_state(context) == PA_CONTEXT_FAILED) + { + ERR("Received context failure!\n"); + aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice); + } + pa_threaded_mainloop_signal(self->loop, 0); +} + +static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata) +{ + ALCpulsePlayback *self = pdata; + if(pa_stream_get_state(stream) == PA_STREAM_FAILED) + { + ERR("Received stream failure!\n"); + aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice); + } + pa_threaded_mainloop_signal(self->loop, 0); +} + +static void ALCpulsePlayback_streamWriteCallback(pa_stream* UNUSED(p), size_t UNUSED(nbytes), void *pdata) +{ + ALCpulsePlayback *self = pdata; + pa_threaded_mainloop_signal(self->loop, 0); +} + +static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata) +{ + static const struct { + enum DevFmtChannels chans; + pa_channel_map map; + } chanmaps[] = { + { DevFmtX71, { 8, { + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT + } } }, + { DevFmtX61, { 7, { + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_REAR_CENTER, + PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT + } } }, + { DevFmtX51, { 6, { + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT + } } }, + { DevFmtX51Rear, { 6, { + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT + } } }, + { DevFmtQuad, { 4, { + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT + } } }, + { DevFmtStereo, { 2, { + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT + } } }, + { DevFmtMono, { 1, {PA_CHANNEL_POSITION_MONO} } } + }; + ALCpulsePlayback *self = pdata; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + size_t i; + + if(eol) + { + pa_threaded_mainloop_signal(self->loop, 0); + return; + } + + for(i = 0;i < COUNTOF(chanmaps);i++) + { + if(pa_channel_map_superset(&info->channel_map, &chanmaps[i].map)) + { + if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) + device->FmtChans = chanmaps[i].chans; + break; + } + } + if(i == COUNTOF(chanmaps)) + { + char chanmap_str[PA_CHANNEL_MAP_SNPRINT_MAX] = ""; + pa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map); + WARN("Failed to find format for channel map:\n %s\n", chanmap_str); + } + + if(info->active_port) + TRACE("Active port: %s (%s)\n", info->active_port->name, info->active_port->description); + device->IsHeadphones = (info->active_port && + strcmp(info->active_port->name, "analog-output-headphones") == 0 && + device->FmtChans == DevFmtStereo); +} + +static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata) +{ + ALCpulsePlayback *self = pdata; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + + if(eol) + { + pa_threaded_mainloop_signal(self->loop, 0); + return; + } + + al_string_copy_cstr(&device->DeviceName, info->description); +} + + +static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata) +{ + ALCpulsePlayback *self = pdata; + + al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(stream)); + + TRACE("Stream moved to %s\n", al_string_get_cstr(self->device_name)); +} + + +static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, + pa_threaded_mainloop *loop, pa_context *context, + pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, + pa_channel_map *chanmap) +{ + pa_stream_state_t state; + pa_stream *stream; + + stream = pa_stream_new_with_proplist(context, "Playback Stream", spec, chanmap, prop_filter); + if(!stream) + { + ERR("pa_stream_new_with_proplist() failed: %s\n", pa_strerror(pa_context_errno(context))); + return NULL; + } + + pa_stream_set_state_callback(stream, stream_state_callback, loop); + + if(pa_stream_connect_playback(stream, device_name, attr, flags, NULL, NULL) < 0) + { + ERR("Stream did not connect: %s\n", pa_strerror(pa_context_errno(context))); + pa_stream_unref(stream); + return NULL; + } + + while((state=pa_stream_get_state(stream)) != PA_STREAM_READY) + { + if(!PA_STREAM_IS_GOOD(state)) + { + ERR("Stream did not get ready: %s\n", pa_strerror(pa_context_errno(context))); + pa_stream_unref(stream); + return NULL; + } + + pa_threaded_mainloop_wait(loop); + } + pa_stream_set_state_callback(stream, NULL, NULL); + + return stream; +} + + +static int ALCpulsePlayback_mixerProc(void *ptr) +{ + ALCpulsePlayback *self = ptr; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + ALuint buffer_size; + ALint update_size; + size_t frame_size; + ssize_t len; + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + pa_threaded_mainloop_lock(self->loop); + frame_size = pa_frame_size(&self->spec); + update_size = device->UpdateSize * frame_size; + + /* Sanitize buffer metrics, in case we actually have less than what we + * asked for. */ + buffer_size = minu(update_size*device->NumUpdates, self->attr.tlength); + update_size = minu(update_size, buffer_size/2); + do { + len = pa_stream_writable_size(self->stream) - self->attr.tlength + + buffer_size; + if(len < update_size) + { + if(pa_stream_is_corked(self->stream) == 1) + { + pa_operation *o; + o = pa_stream_cork(self->stream, 0, NULL, NULL); + if(o) pa_operation_unref(o); + } + pa_threaded_mainloop_wait(self->loop); + continue; + } + len -= len%update_size; + + while(len > 0) + { + size_t newlen = len; + void *buf; + pa_free_cb_t free_func = NULL; + + if(pa_stream_begin_write(self->stream, &buf, &newlen) < 0) + { + buf = pa_xmalloc(newlen); + free_func = pa_xfree; + } + + aluMixData(device, buf, newlen/frame_size); + + pa_stream_write(self->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE); + len -= newlen; + } + } while(!self->killNow && device->Connected); + pa_threaded_mainloop_unlock(self->loop); + + return 0; +} + + +static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name) +{ + const_al_string dev_name = AL_STRING_INIT_STATIC(); + const char *pulse_name = NULL; + pa_stream_flags_t flags; + pa_sample_spec spec; + + if(name) + { + const DevMap *iter; + + if(VECTOR_SIZE(PlaybackDevices) == 0) + ALCpulsePlayback_probeDevices(); + +#define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(PlaybackDevices)) + return ALC_INVALID_VALUE; + pulse_name = al_string_get_cstr(iter->device_name); + dev_name = iter->name; + } + + if(!pulse_open(&self->loop, &self->context, ALCpulsePlayback_contextStateCallback, self)) + return ALC_INVALID_VALUE; + + pa_threaded_mainloop_lock(self->loop); + + flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE | + PA_STREAM_FIX_CHANNELS; + if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0)) + flags |= PA_STREAM_DONT_MOVE; + + spec.format = PA_SAMPLE_S16NE; + spec.rate = 44100; + spec.channels = 2; + + TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); + self->stream = ALCpulsePlayback_connectStream(pulse_name, self->loop, self->context, + flags, NULL, &spec, NULL); + if(!self->stream) + { + pa_threaded_mainloop_unlock(self->loop); + pulse_close(self->loop, self->context, self->stream); + self->loop = NULL; + self->context = NULL; + return ALC_INVALID_VALUE; + } + pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self); + + al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream)); + if(al_string_empty(dev_name)) + { + pa_operation *o = pa_context_get_sink_info_by_name( + self->context, al_string_get_cstr(self->device_name), + ALCpulsePlayback_sinkNameCallback, self + ); + wait_for_operation(o, self->loop); + } + else + { + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + al_string_copy(&device->DeviceName, dev_name); + } + + pa_threaded_mainloop_unlock(self->loop); + + return ALC_NO_ERROR; +} + +static void ALCpulsePlayback_close(ALCpulsePlayback *self) +{ + pulse_close(self->loop, self->context, self->stream); + self->loop = NULL; + self->context = NULL; + self->stream = NULL; + + al_string_clear(&self->device_name); +} + +static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + pa_stream_flags_t flags = 0; + const char *mapname = NULL; + pa_channel_map chanmap; + pa_operation *o; + ALuint len; + + pa_threaded_mainloop_lock(self->loop); + + if(self->stream) + { + pa_stream_set_state_callback(self->stream, NULL, NULL); + pa_stream_set_moved_callback(self->stream, NULL, NULL); + pa_stream_set_write_callback(self->stream, NULL, NULL); + pa_stream_set_buffer_attr_callback(self->stream, NULL, NULL); + pa_stream_disconnect(self->stream); + pa_stream_unref(self->stream); + self->stream = NULL; + } + + o = pa_context_get_sink_info_by_name(self->context, al_string_get_cstr(self->device_name), + ALCpulsePlayback_sinkInfoCallback, self); + wait_for_operation(o, self->loop); + + if(GetConfigValueBool(al_string_get_cstr(device->DeviceName), "pulse", "fix-rate", 0) || + !(device->Flags&DEVICE_FREQUENCY_REQUEST)) + flags |= PA_STREAM_FIX_RATE; + flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE; + flags |= PA_STREAM_ADJUST_LATENCY; + flags |= PA_STREAM_START_CORKED; + if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0)) + flags |= PA_STREAM_DONT_MOVE; + + switch(device->FmtType) + { + case DevFmtByte: + device->FmtType = DevFmtUByte; + /* fall-through */ + case DevFmtUByte: + self->spec.format = PA_SAMPLE_U8; + break; + case DevFmtUShort: + device->FmtType = DevFmtShort; + /* fall-through */ + case DevFmtShort: + self->spec.format = PA_SAMPLE_S16NE; + break; + case DevFmtUInt: + device->FmtType = DevFmtInt; + /* fall-through */ + case DevFmtInt: + self->spec.format = PA_SAMPLE_S32NE; + break; + case DevFmtFloat: + self->spec.format = PA_SAMPLE_FLOAT32NE; + break; + } + self->spec.rate = device->Frequency; + self->spec.channels = ChannelsFromDevFmt(device->FmtChans); + + if(pa_sample_spec_valid(&self->spec) == 0) + { + ERR("Invalid sample format\n"); + pa_threaded_mainloop_unlock(self->loop); + return ALC_FALSE; + } + + switch(device->FmtChans) + { + case DevFmtMono: + mapname = "mono"; + break; + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + device->FmtChans = DevFmtStereo; + /*fall-through*/ + case DevFmtStereo: + mapname = "front-left,front-right"; + break; + case DevFmtQuad: + mapname = "front-left,front-right,rear-left,rear-right"; + break; + case DevFmtX51: + mapname = "front-left,front-right,front-center,lfe,side-left,side-right"; + break; + case DevFmtX51Rear: + mapname = "front-left,front-right,front-center,lfe,rear-left,rear-right"; + break; + case DevFmtX61: + mapname = "front-left,front-right,front-center,lfe,rear-center,side-left,side-right"; + break; + case DevFmtX71: + mapname = "front-left,front-right,front-center,lfe,rear-left,rear-right,side-left,side-right"; + break; + } + if(!pa_channel_map_parse(&chanmap, mapname)) + { + ERR("Failed to build channel map for %s\n", DevFmtChannelsString(device->FmtChans)); + pa_threaded_mainloop_unlock(self->loop); + return ALC_FALSE; + } + SetDefaultWFXChannelOrder(device); + + self->attr.fragsize = -1; + self->attr.prebuf = 0; + self->attr.minreq = device->UpdateSize * pa_frame_size(&self->spec); + self->attr.tlength = self->attr.minreq * maxu(device->NumUpdates, 2); + self->attr.maxlength = -1; + + self->stream = ALCpulsePlayback_connectStream(al_string_get_cstr(self->device_name), + self->loop, self->context, flags, + &self->attr, &self->spec, &chanmap); + if(!self->stream) + { + pa_threaded_mainloop_unlock(self->loop); + return ALC_FALSE; + } + pa_stream_set_state_callback(self->stream, ALCpulsePlayback_streamStateCallback, self); + pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self); + pa_stream_set_write_callback(self->stream, ALCpulsePlayback_streamWriteCallback, self); + + self->spec = *(pa_stream_get_sample_spec(self->stream)); + if(device->Frequency != self->spec.rate) + { + /* Server updated our playback rate, so modify the buffer attribs + * accordingly. */ + device->NumUpdates = (ALuint)clampd( + (ALdouble)device->NumUpdates/device->Frequency*self->spec.rate + 0.5, 2.0, 16.0 + ); + + self->attr.minreq = device->UpdateSize * pa_frame_size(&self->spec); + self->attr.tlength = self->attr.minreq * device->NumUpdates; + self->attr.maxlength = -1; + self->attr.prebuf = 0; + + o = pa_stream_set_buffer_attr(self->stream, &self->attr, + stream_success_callback, self->loop); + wait_for_operation(o, self->loop); + + device->Frequency = self->spec.rate; + } + + pa_stream_set_buffer_attr_callback(self->stream, ALCpulsePlayback_bufferAttrCallback, self); + ALCpulsePlayback_bufferAttrCallback(self->stream, self); + + len = self->attr.minreq / pa_frame_size(&self->spec); + device->NumUpdates = (ALuint)clampd( + (ALdouble)device->NumUpdates/len*device->UpdateSize + 0.5, 2.0, 16.0 + ); + device->UpdateSize = len; + + /* HACK: prebuf should be 0 as that's what we set it to. However on some + * systems it comes back as non-0, so we have to make sure the device will + * write enough audio to start playback. The lack of manual start control + * may have unintended consequences, but it's better than not starting at + * all. + */ + if(self->attr.prebuf != 0) + { + len = self->attr.prebuf / pa_frame_size(&self->spec); + if(len <= device->UpdateSize*device->NumUpdates) + ERR("Non-0 prebuf, %u samples (%u bytes), device has %u samples\n", + len, self->attr.prebuf, device->UpdateSize*device->NumUpdates); + else + { + ERR("Large prebuf, %u samples (%u bytes), increasing device from %u samples", + len, self->attr.prebuf, device->UpdateSize*device->NumUpdates); + device->NumUpdates = (len+device->UpdateSize-1) / device->UpdateSize; + } + } + + pa_threaded_mainloop_unlock(self->loop); + return ALC_TRUE; +} + +static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self) +{ + self->killNow = AL_FALSE; + if(althrd_create(&self->thread, ALCpulsePlayback_mixerProc, self) != althrd_success) + return ALC_FALSE; + return ALC_TRUE; +} + +static void ALCpulsePlayback_stop(ALCpulsePlayback *self) +{ + pa_operation *o; + int res; + + if(!self->stream || self->killNow) + return; + + self->killNow = AL_TRUE; + /* Signal the main loop in case PulseAudio isn't sending us audio requests + * (e.g. if the device is suspended). We need to lock the mainloop in case + * the mixer is between checking the killNow flag but before waiting for + * the signal. + */ + pa_threaded_mainloop_lock(self->loop); + pa_threaded_mainloop_unlock(self->loop); + pa_threaded_mainloop_signal(self->loop, 0); + althrd_join(self->thread, &res); + + pa_threaded_mainloop_lock(self->loop); + + o = pa_stream_cork(self->stream, 1, stream_success_callback, self->loop); + wait_for_operation(o, self->loop); + + pa_threaded_mainloop_unlock(self->loop); +} + + +static ClockLatency ALCpulsePlayback_getClockLatency(ALCpulsePlayback *self) +{ + pa_usec_t latency = 0; + ClockLatency ret; + int neg, err; + + pa_threaded_mainloop_lock(self->loop); + ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice); + if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0) + { + /* FIXME: if err = -PA_ERR_NODATA, it means we were called too soon + * after starting the stream and no timing info has been received from + * the server yet. Should we wait, possibly stalling the app, or give a + * dummy value? Either way, it shouldn't be 0. */ + if(err != -PA_ERR_NODATA) + ERR("Failed to get stream latency: 0x%x\n", err); + latency = 0; + neg = 0; + } + if(neg) latency = 0; + ret.Latency = minu64(latency, U64(0xffffffffffffffff)/1000) * 1000; + pa_threaded_mainloop_unlock(self->loop); + + return ret; +} + + +static void ALCpulsePlayback_lock(ALCpulsePlayback *self) +{ + pa_threaded_mainloop_lock(self->loop); +} + +static void ALCpulsePlayback_unlock(ALCpulsePlayback *self) +{ + pa_threaded_mainloop_unlock(self->loop); +} + + +typedef struct ALCpulseCapture { + DERIVE_FROM_TYPE(ALCbackend); + + al_string device_name; + + const void *cap_store; + size_t cap_len; + size_t cap_remain; + + ALCuint last_readable; + + pa_buffer_attr attr; + pa_sample_spec spec; + + pa_threaded_mainloop *loop; + + pa_stream *stream; + pa_context *context; +} ALCpulseCapture; + +static void ALCpulseCapture_deviceCallback(pa_context *context, const pa_source_info *info, int eol, void *pdata); +static void ALCpulseCapture_probeDevices(void); + +static void ALCpulseCapture_contextStateCallback(pa_context *context, void *pdata); +static void ALCpulseCapture_streamStateCallback(pa_stream *stream, void *pdata); +static void ALCpulseCapture_sourceNameCallback(pa_context *context, const pa_source_info *info, int eol, void *pdata); +static void ALCpulseCapture_streamMovedCallback(pa_stream *stream, void *pdata); +static pa_stream *ALCpulseCapture_connectStream(const char *device_name, + pa_threaded_mainloop *loop, pa_context *context, + pa_stream_flags_t flags, pa_buffer_attr *attr, + pa_sample_spec *spec, pa_channel_map *chanmap); + +static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device); +static void ALCpulseCapture_Destruct(ALCpulseCapture *self); +static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name); +static void ALCpulseCapture_close(ALCpulseCapture *self); +static DECLARE_FORWARD(ALCpulseCapture, ALCbackend, ALCboolean, reset) +static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self); +static void ALCpulseCapture_stop(ALCpulseCapture *self); +static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *buffer, ALCuint samples); +static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self); +static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self); +static void ALCpulseCapture_lock(ALCpulseCapture *self); +static void ALCpulseCapture_unlock(ALCpulseCapture *self); +DECLARE_DEFAULT_ALLOCATORS(ALCpulseCapture) + +DEFINE_ALCBACKEND_VTABLE(ALCpulseCapture); + + +static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device) +{ + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCpulseCapture, ALCbackend, self); + + AL_STRING_INIT(self->device_name); +} + +static void ALCpulseCapture_Destruct(ALCpulseCapture *self) +{ + AL_STRING_DEINIT(self->device_name); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa_source_info *info, int eol, void *pdata) +{ + pa_threaded_mainloop *loop = pdata; + const DevMap *iter; + DevMap entry; + int count; + + if(eol) + { + pa_threaded_mainloop_signal(loop, 0); + return; + } + +#define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_INFO_NAME); + if(iter != VECTOR_END(CaptureDevices)) return; +#undef MATCH_INFO_NAME + + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.device_name); + + al_string_copy_cstr(&entry.device_name, info->name); + + count = 0; + while(1) + { + al_string_copy_cstr(&entry.name, info->description); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&entry.name, str); + } + +#define MATCH_ENTRY(i) (al_string_cmp(entry.name, (i)->name) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_ENTRY); + if(iter == VECTOR_END(CaptureDevices)) break; +#undef MATCH_ENTRY + count++; + } + + TRACE("Got device \"%s\", \"%s\"\n", al_string_get_cstr(entry.name), al_string_get_cstr(entry.device_name)); + + VECTOR_PUSH_BACK(CaptureDevices, entry); +} + +static void ALCpulseCapture_probeDevices(void) +{ + pa_threaded_mainloop *loop; + + clear_devlist(&CaptureDevices); + + if((loop=pa_threaded_mainloop_new()) && + pa_threaded_mainloop_start(loop) >= 0) + { + pa_context *context; + + pa_threaded_mainloop_lock(loop); + context = connect_context(loop, AL_FALSE); + if(context) + { + pa_operation *o; + pa_stream_flags_t flags; + pa_sample_spec spec; + pa_stream *stream; + + flags = PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE | + PA_STREAM_FIX_CHANNELS | PA_STREAM_DONT_MOVE; + + spec.format = PA_SAMPLE_S16NE; + spec.rate = 44100; + spec.channels = 1; + + stream = ALCpulseCapture_connectStream(NULL, loop, context, flags, + NULL, &spec, NULL); + if(stream) + { + o = pa_context_get_source_info_by_name(context, pa_stream_get_device_name(stream), + ALCpulseCapture_deviceCallback, loop); + wait_for_operation(o, loop); + + pa_stream_disconnect(stream); + pa_stream_unref(stream); + stream = NULL; + } + + o = pa_context_get_source_info_list(context, ALCpulseCapture_deviceCallback, loop); + wait_for_operation(o, loop); + + pa_context_disconnect(context); + pa_context_unref(context); + } + pa_threaded_mainloop_unlock(loop); + pa_threaded_mainloop_stop(loop); + } + if(loop) + pa_threaded_mainloop_free(loop); +} + + +static void ALCpulseCapture_contextStateCallback(pa_context *context, void *pdata) +{ + ALCpulseCapture *self = pdata; + if(pa_context_get_state(context) == PA_CONTEXT_FAILED) + { + ERR("Received context failure!\n"); + aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice); + } + pa_threaded_mainloop_signal(self->loop, 0); +} + +static void ALCpulseCapture_streamStateCallback(pa_stream *stream, void *pdata) +{ + ALCpulseCapture *self = pdata; + if(pa_stream_get_state(stream) == PA_STREAM_FAILED) + { + ERR("Received stream failure!\n"); + aluHandleDisconnect(STATIC_CAST(ALCbackend,self)->mDevice); + } + pa_threaded_mainloop_signal(self->loop, 0); +} + + +static void ALCpulseCapture_sourceNameCallback(pa_context *UNUSED(context), const pa_source_info *info, int eol, void *pdata) +{ + ALCpulseCapture *self = pdata; + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + + if(eol) + { + pa_threaded_mainloop_signal(self->loop, 0); + return; + } + + al_string_copy_cstr(&device->DeviceName, info->description); +} + + +static void ALCpulseCapture_streamMovedCallback(pa_stream *stream, void *pdata) +{ + ALCpulseCapture *self = pdata; + + al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(stream)); + + TRACE("Stream moved to %s\n", al_string_get_cstr(self->device_name)); +} + + +static pa_stream *ALCpulseCapture_connectStream(const char *device_name, + pa_threaded_mainloop *loop, pa_context *context, + pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, + pa_channel_map *chanmap) +{ + pa_stream_state_t state; + pa_stream *stream; + + stream = pa_stream_new_with_proplist(context, "Capture Stream", spec, chanmap, prop_filter); + if(!stream) + { + ERR("pa_stream_new_with_proplist() failed: %s\n", pa_strerror(pa_context_errno(context))); + return NULL; + } + + pa_stream_set_state_callback(stream, stream_state_callback, loop); + + if(pa_stream_connect_record(stream, device_name, attr, flags) < 0) + { + ERR("Stream did not connect: %s\n", pa_strerror(pa_context_errno(context))); + pa_stream_unref(stream); + return NULL; + } + + while((state=pa_stream_get_state(stream)) != PA_STREAM_READY) + { + if(!PA_STREAM_IS_GOOD(state)) + { + ERR("Stream did not get ready: %s\n", pa_strerror(pa_context_errno(context))); + pa_stream_unref(stream); + return NULL; + } + + pa_threaded_mainloop_wait(loop); + } + pa_stream_set_state_callback(stream, NULL, NULL); + + return stream; +} + + +static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) +{ + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + const char *pulse_name = NULL; + pa_stream_flags_t flags = 0; + pa_channel_map chanmap; + ALuint samples; + + if(name) + { + const DevMap *iter; + + if(VECTOR_SIZE(CaptureDevices) == 0) + ALCpulseCapture_probeDevices(); + +#define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_END(CaptureDevices)) + return ALC_INVALID_VALUE; + pulse_name = al_string_get_cstr(iter->device_name); + al_string_copy(&device->DeviceName, iter->name); + } + + if(!pulse_open(&self->loop, &self->context, ALCpulseCapture_contextStateCallback, self)) + return ALC_INVALID_VALUE; + + pa_threaded_mainloop_lock(self->loop); + + self->spec.rate = device->Frequency; + self->spec.channels = ChannelsFromDevFmt(device->FmtChans); + + switch(device->FmtType) + { + case DevFmtUByte: + self->spec.format = PA_SAMPLE_U8; + break; + case DevFmtShort: + self->spec.format = PA_SAMPLE_S16NE; + break; + case DevFmtInt: + self->spec.format = PA_SAMPLE_S32NE; + break; + case DevFmtFloat: + self->spec.format = PA_SAMPLE_FLOAT32NE; + break; + case DevFmtByte: + case DevFmtUShort: + case DevFmtUInt: + ERR("%s capture samples not supported\n", DevFmtTypeString(device->FmtType)); + pa_threaded_mainloop_unlock(self->loop); + goto fail; + } + + if(pa_sample_spec_valid(&self->spec) == 0) + { + ERR("Invalid sample format\n"); + pa_threaded_mainloop_unlock(self->loop); + goto fail; + } + + if(!pa_channel_map_init_auto(&chanmap, self->spec.channels, PA_CHANNEL_MAP_WAVEEX)) + { + ERR("Couldn't build map for channel count (%d)!\n", self->spec.channels); + pa_threaded_mainloop_unlock(self->loop); + goto fail; + } + + samples = device->UpdateSize * device->NumUpdates; + samples = maxu(samples, 100 * device->Frequency / 1000); + + self->attr.minreq = -1; + self->attr.prebuf = -1; + self->attr.maxlength = samples * pa_frame_size(&self->spec); + self->attr.tlength = -1; + self->attr.fragsize = minu(samples, 50*device->Frequency/1000) * + pa_frame_size(&self->spec); + + flags |= PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY; + if(!GetConfigValueBool(NULL, "pulse", "allow-moves", 0)) + flags |= PA_STREAM_DONT_MOVE; + + TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); + self->stream = ALCpulseCapture_connectStream(pulse_name, self->loop, self->context, + flags, &self->attr, &self->spec, + &chanmap); + if(!self->stream) + { + pa_threaded_mainloop_unlock(self->loop); + goto fail; + } + pa_stream_set_moved_callback(self->stream, ALCpulseCapture_streamMovedCallback, self); + pa_stream_set_state_callback(self->stream, ALCpulseCapture_streamStateCallback, self); + + al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream)); + if(al_string_empty(device->DeviceName)) + { + pa_operation *o = pa_context_get_source_info_by_name( + self->context, al_string_get_cstr(self->device_name), + ALCpulseCapture_sourceNameCallback, self + ); + wait_for_operation(o, self->loop); + } + + pa_threaded_mainloop_unlock(self->loop); + return ALC_NO_ERROR; + +fail: + pulse_close(self->loop, self->context, self->stream); + self->loop = NULL; + self->context = NULL; + self->stream = NULL; + + return ALC_INVALID_VALUE; +} + +static void ALCpulseCapture_close(ALCpulseCapture *self) +{ + pulse_close(self->loop, self->context, self->stream); + self->loop = NULL; + self->context = NULL; + self->stream = NULL; + + al_string_clear(&self->device_name); +} + +static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self) +{ + pa_operation *o; + o = pa_stream_cork(self->stream, 0, stream_success_callback, self->loop); + wait_for_operation(o, self->loop); + + return ALC_TRUE; +} + +static void ALCpulseCapture_stop(ALCpulseCapture *self) +{ + pa_operation *o; + o = pa_stream_cork(self->stream, 1, stream_success_callback, self->loop); + wait_for_operation(o, self->loop); +} + +static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *buffer, ALCuint samples) +{ + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + ALCuint todo = samples * pa_frame_size(&self->spec); + + /* Capture is done in fragment-sized chunks, so we loop until we get all + * that's available */ + self->last_readable -= todo; + while(todo > 0) + { + size_t rem = todo; + + if(self->cap_len == 0) + { + pa_stream_state_t state; + + state = pa_stream_get_state(self->stream); + if(!PA_STREAM_IS_GOOD(state)) + { + aluHandleDisconnect(device); + break; + } + if(pa_stream_peek(self->stream, &self->cap_store, &self->cap_len) < 0) + { + ERR("pa_stream_peek() failed: %s\n", + pa_strerror(pa_context_errno(self->context))); + aluHandleDisconnect(device); + break; + } + self->cap_remain = self->cap_len; + } + if(rem > self->cap_remain) + rem = self->cap_remain; + + memcpy(buffer, self->cap_store, rem); + + buffer = (ALbyte*)buffer + rem; + todo -= rem; + + self->cap_store = (ALbyte*)self->cap_store + rem; + self->cap_remain -= rem; + if(self->cap_remain == 0) + { + pa_stream_drop(self->stream); + self->cap_len = 0; + } + } + if(todo > 0) + memset(buffer, ((device->FmtType==DevFmtUByte) ? 0x80 : 0), todo); + + return ALC_NO_ERROR; +} + +static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; + size_t readable = self->cap_remain; + + if(device->Connected) + { + ssize_t got = pa_stream_readable_size(self->stream); + if(got < 0) + { + ERR("pa_stream_readable_size() failed: %s\n", pa_strerror(got)); + aluHandleDisconnect(device); + } + else if((size_t)got > self->cap_len) + readable += got - self->cap_len; + } + + if(self->last_readable < readable) + self->last_readable = readable; + return self->last_readable / pa_frame_size(&self->spec); +} + + +static ClockLatency ALCpulseCapture_getClockLatency(ALCpulseCapture *self) +{ + pa_usec_t latency = 0; + ClockLatency ret; + int neg, err; + + pa_threaded_mainloop_lock(self->loop); + ret.ClockTime = GetDeviceClockTime(STATIC_CAST(ALCbackend,self)->mDevice); + if((err=pa_stream_get_latency(self->stream, &latency, &neg)) != 0) + { + ERR("Failed to get stream latency: 0x%x\n", err); + latency = 0; + neg = 0; + } + if(neg) latency = 0; + ret.Latency = minu64(latency, U64(0xffffffffffffffff)/1000) * 1000; + pa_threaded_mainloop_unlock(self->loop); + + return ret; +} + + +static void ALCpulseCapture_lock(ALCpulseCapture *self) +{ + pa_threaded_mainloop_lock(self->loop); +} + +static void ALCpulseCapture_unlock(ALCpulseCapture *self) +{ + pa_threaded_mainloop_unlock(self->loop); +} + + +typedef struct ALCpulseBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCpulseBackendFactory; +#define ALCPULSEBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCpulseBackendFactory, ALCbackendFactory) } } + +static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory *self); +static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory *self); +static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory *self, ALCbackend_Type type); +static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory *self, ALCdevice *device, ALCbackend_Type type); + +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory); + + +static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(self)) +{ + ALCboolean ret = ALC_FALSE; + + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + + if(pulse_load()) + { + pa_threaded_mainloop *loop; + + pulse_ctx_flags = 0; + if(!GetConfigValueBool(NULL, "pulse", "spawn-server", 1)) + pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN; + + if((loop=pa_threaded_mainloop_new()) && + pa_threaded_mainloop_start(loop) >= 0) + { + pa_context *context; + + pa_threaded_mainloop_lock(loop); + context = connect_context(loop, AL_TRUE); + if(context) + { + ret = ALC_TRUE; + + /* Some libraries (Phonon, Qt) set some pulseaudio properties + * through environment variables, which causes all streams in + * the process to inherit them. This attempts to filter those + * properties out by setting them to 0-length data. */ + prop_filter = pa_proplist_new(); + pa_proplist_set(prop_filter, PA_PROP_MEDIA_ROLE, NULL, 0); + pa_proplist_set(prop_filter, "phonon.streamid", NULL, 0); + + pa_context_disconnect(context); + pa_context_unref(context); + } + pa_threaded_mainloop_unlock(loop); + pa_threaded_mainloop_stop(loop); + } + if(loop) + pa_threaded_mainloop_free(loop); + } + + return ret; +} + +static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory* UNUSED(self)) +{ + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); + + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); + + if(prop_filter) + pa_proplist_free(prop_filter); + prop_filter = NULL; + + /* PulseAudio doesn't like being CloseLib'd sometimes */ +} + +static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback || type == ALCbackend_Capture) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe type) +{ + switch(type) + { + case ALL_DEVICE_PROBE: + ALCpulsePlayback_probeDevices(); +#define APPEND_ALL_DEVICES_LIST(e) AppendAllDevicesList(al_string_get_cstr((e)->name)) + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, APPEND_ALL_DEVICES_LIST); +#undef APPEND_ALL_DEVICES_LIST + break; + + case CAPTURE_DEVICE_PROBE: + ALCpulseCapture_probeDevices(); +#define APPEND_CAPTURE_DEVICE_LIST(e) AppendCaptureDeviceList(al_string_get_cstr((e)->name)) + VECTOR_FOR_EACH(const DevMap, CaptureDevices, APPEND_CAPTURE_DEVICE_LIST); +#undef APPEND_CAPTURE_DEVICE_LIST + break; + } +} + +static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCpulsePlayback *backend; + NEW_OBJ(backend, ALCpulsePlayback)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + if(type == ALCbackend_Capture) + { + ALCpulseCapture *backend; + NEW_OBJ(backend, ALCpulseCapture)(device); + if(!backend) return NULL; + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} + + +#else /* PA_API_VERSION == 12 */ + +#warning "Unsupported API version, backend will be unavailable!" + +typedef struct ALCpulseBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCpulseBackendFactory; +#define ALCPULSEBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCpulseBackendFactory, ALCbackendFactory) } } + +static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(self)) +{ + return ALC_FALSE; +} + +static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory* UNUSED(self)) +{ +} + +static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UNUSED(self), ALCbackend_Type UNUSED(type)) +{ + return ALC_FALSE; +} + +static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe UNUSED(type)) +{ +} + +static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory* UNUSED(self), ALCdevice* UNUSED(device), ALCbackend_Type UNUSED(type)) +{ + return NULL; +} + +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory); + +#endif /* PA_API_VERSION == 12 */ + +ALCbackendFactory *ALCpulseBackendFactory_getFactory(void) +{ + static ALCpulseBackendFactory factory = ALCPULSEBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} diff --git a/Engine/lib/openal-soft/Alc/backends/qsa.c b/Engine/lib/openal-soft/Alc/backends/qsa.c new file mode 100644 index 000000000..b7923517a --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/qsa.c @@ -0,0 +1,916 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2011-2013 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 +#include +#include +#include +#include +#include +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "threads.h" + + +typedef struct { + snd_pcm_t* pcmHandle; + int audio_fd; + + snd_pcm_channel_setup_t csetup; + snd_pcm_channel_params_t cparams; + + ALvoid* buffer; + ALsizei size; + + volatile int killNow; + althrd_t thread; +} qsa_data; + +typedef struct { + ALCchar* name; + 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 const struct { + int32_t format; +} formatlist[] = { + {SND_PCM_SFMT_FLOAT_LE}, + {SND_PCM_SFMT_S32_LE}, + {SND_PCM_SFMT_U32_LE}, + {SND_PCM_SFMT_S16_LE}, + {SND_PCM_SFMT_U16_LE}, + {SND_PCM_SFMT_S8}, + {SND_PCM_SFMT_U8}, + {0}, +}; + +static const struct { + int32_t rate; +} ratelist[] = { + {192000}, + {176400}, + {96000}, + {88200}, + {48000}, + {44100}, + {32000}, + {24000}, + {22050}, + {16000}, + {12000}, + {11025}, + {8000}, + {0}, +}; + +static const struct { + int32_t channels; +} channellist[] = { + {8}, + {7}, + {6}, + {4}, + {2}, + {1}, + {0}, +}; + +static void deviceList(int type, vector_DevMap *devmap) +{ + snd_ctl_t* handle; + snd_pcm_info_t pcminfo; + int max_cards, card, err, dev; + DevMap entry; + char name[1024]; + struct snd_ctl_hw_info info; + + max_cards = snd_cards(); + if(max_cards < 0) + return; + + VECTOR_RESIZE(*devmap, 0, max_cards+1); + + entry.name = strdup(qsaDevice); + entry.card = 0; + entry.dev = 0; + VECTOR_PUSH_BACK(*devmap, entry); + + for(card = 0;card < max_cards;card++) + { + if((err=snd_ctl_open(&handle, card)) < 0) + continue; + + if((err=snd_ctl_hw_info(handle, &info)) < 0) + { + snd_ctl_close(handle); + continue; + } + + for(dev = 0;dev < (int)info.pcmdevs;dev++) + { + 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))) + { + 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); + } +} + + +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; + snd_pcm_channel_status_t status; + struct sched_param param; + fd_set wfds; + int selectret; + struct timeval timeout; + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + /* Increase default 10 priority to 11 to avoid jerky sound */ + SchedGet(0, 0, ¶m); + param.sched_priority=param.sched_curpriority+1; + SchedSet(0, 0, SCHED_NOCHANGE, ¶m); + + ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + + while (!data->killNow) + { + ALint len=data->size; + write_ptr=data->buffer; + + avail=len/frame_size; + aluMixData(device, write_ptr, avail); + + while (len>0 && !data->killNow) + { + 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); + + if (wrote<=0) + { + if ((errno==EAGAIN) || (errno==EWOULDBLOCK)) + { + continue; + } + + 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 ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0) + { + aluHandleDisconnect(device); + break; + } + } + } + else + { + write_ptr+=wrote; + len-=wrote; + } + } + } + + return 0; +} + +/************/ +/* Playback */ +/************/ + +static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName) +{ + qsa_data *data; + int card, dev; + int status; + + data = (qsa_data*)calloc(1, sizeof(qsa_data)); + if(data == NULL) + return ALC_OUT_OF_MEMORY; + + if(!deviceName) + deviceName = qsaDevice; + + if(strcmp(deviceName, qsaDevice) == 0) + status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_PLAYBACK); + else + { + const DevMap *iter; + + if(VECTOR_SIZE(DeviceNameMap) == 0) + deviceList(SND_PCM_CHANNEL_PLAYBACK, &DeviceNameMap); + +#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, iter->card, iter->dev, SND_PCM_OPEN_PLAYBACK); + } + + 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) + { + snd_pcm_close(data->pcmHandle); + free(data); + return ALC_INVALID_DEVICE; + } + + al_string_copy_cstr(&device->DeviceName, deviceName); + device->ExtraData = data; + + return ALC_NO_ERROR; +} + +static void qsa_close_playback(ALCdevice* device) +{ + qsa_data* data=(qsa_data*)device->ExtraData; + + if (data->buffer!=NULL) + { + free(data->buffer); + data->buffer=NULL; + } + + snd_pcm_close(data->pcmHandle); + free(data); + + device->ExtraData=NULL; +} + +static ALCboolean qsa_reset_playback(ALCdevice* device) +{ + qsa_data* data=(qsa_data*)device->ExtraData; + int32_t format=-1; + + switch(device->FmtType) + { + case DevFmtByte: + format=SND_PCM_SFMT_S8; + break; + case DevFmtUByte: + format=SND_PCM_SFMT_U8; + break; + case DevFmtShort: + format=SND_PCM_SFMT_S16_LE; + break; + case DevFmtUShort: + format=SND_PCM_SFMT_U16_LE; + break; + case DevFmtInt: + format=SND_PCM_SFMT_S32_LE; + break; + case DevFmtUInt: + format=SND_PCM_SFMT_U32_LE; + break; + case DevFmtFloat: + format=SND_PCM_SFMT_FLOAT_LE; + break; + } + + /* we actually don't want to block on writes */ + snd_pcm_nonblock_mode(data->pcmHandle, 1); + /* Disable mmap to control data transfer to the audio device */ + snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP); + snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_BUFFER_PARTIAL_BLOCKS); + + // configure a sound channel + memset(&data->cparams, 0, sizeof(data->cparams)); + data->cparams.channel=SND_PCM_CHANNEL_PLAYBACK; + data->cparams.mode=SND_PCM_MODE_BLOCK; + 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.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.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_FALSE; + } + } + + if ((snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_PLAYBACK))<0) + { + return ALC_FALSE; + } + + memset(&data->csetup, 0, sizeof(data->csetup)); + data->csetup.channel=SND_PCM_CHANNEL_PLAYBACK; + if (snd_pcm_plugin_setup(data->pcmHandle, &data->csetup)<0) + { + return ALC_FALSE; + } + + /* now fill back to the our AL device */ + device->Frequency=data->cparams.format.rate; + + switch (data->cparams.format.voices) + { + 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; + } + + 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; + } + + SetDefaultChannelOrder(device); + + device->UpdateSize=data->csetup.buf.block.frag_size/ + (ChannelsFromDevFmt(device->FmtChans)*BytesFromDevFmt(device->FmtType)); + device->NumUpdates=data->csetup.buf.block.frags; + + data->size=data->csetup.buf.block.frag_size; + data->buffer=malloc(data->size); + if (!data->buffer) + { + return ALC_FALSE; + } + + return ALC_TRUE; +} + +static ALCboolean qsa_start_playback(ALCdevice* device) +{ + qsa_data *data = (qsa_data*)device->ExtraData; + + data->killNow = 0; + if(althrd_create(&data->thread, qsa_proc_playback, device) != althrd_success) + return ALC_FALSE; + + return ALC_TRUE; +} + +static void qsa_stop_playback(ALCdevice* device) +{ + qsa_data *data = (qsa_data*)device->ExtraData; + int res; + + if(data->killNow) + return; + + data->killNow = 1; + althrd_join(data->thread, &res); +} + +/***********/ +/* Capture */ +/***********/ + +static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) +{ + qsa_data *data; + int card, dev; + int format=-1; + int status; + + data=(qsa_data*)calloc(1, sizeof(qsa_data)); + if (data==NULL) + { + return ALC_OUT_OF_MEMORY; + } + + if(!deviceName) + deviceName = qsaDevice; + + if(strcmp(deviceName, qsaDevice) == 0) + status = snd_pcm_open_preferred(&data->pcmHandle, &card, &dev, SND_PCM_OPEN_CAPTURE); + else + { + const DevMap *iter; + + if(VECTOR_SIZE(CaptureNameMap) == 0) + deviceList(SND_PCM_CHANNEL_CAPTURE, &CaptureNameMap); + +#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, iter->card, iter->dev, SND_PCM_OPEN_CAPTURE); + } + + 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) + { + snd_pcm_close(data->pcmHandle); + free(data); + return ALC_INVALID_DEVICE; + } + + al_string_copy_cstr(&device->DeviceName, deviceName); + device->ExtraData = data; + + switch (device->FmtType) + { + case DevFmtByte: + format=SND_PCM_SFMT_S8; + break; + case DevFmtUByte: + format=SND_PCM_SFMT_U8; + break; + case DevFmtShort: + format=SND_PCM_SFMT_S16_LE; + break; + case DevFmtUShort: + format=SND_PCM_SFMT_U16_LE; + break; + case DevFmtInt: + format=SND_PCM_SFMT_S32_LE; + break; + case DevFmtUInt: + format=SND_PCM_SFMT_U32_LE; + break; + case DevFmtFloat: + format=SND_PCM_SFMT_FLOAT_LE; + break; + } + + /* we actually don't want to block on reads */ + snd_pcm_nonblock_mode(data->pcmHandle, 1); + /* Disable mmap to control data transfer to the audio device */ + snd_pcm_plugin_set_disable(data->pcmHandle, PLUGIN_DISABLE_MMAP); + + /* configure a sound channel */ + memset(&data->cparams, 0, sizeof(data->cparams)); + data->cparams.mode=SND_PCM_MODE_BLOCK; + data->cparams.channel=SND_PCM_CHANNEL_CAPTURE; + data->cparams.start_mode=SND_PCM_START_GO; + 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.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.format=format; + + if(snd_pcm_plugin_params(data->pcmHandle, &data->cparams) < 0) + { + snd_pcm_close(data->pcmHandle); + free(data); + device->ExtraData=NULL; + + return ALC_INVALID_VALUE; + } + + return ALC_NO_ERROR; +} + +static void qsa_close_capture(ALCdevice* device) +{ + qsa_data* data=(qsa_data*)device->ExtraData; + + if (data->pcmHandle!=NULL) + snd_pcm_close(data->pcmHandle); + + free(data); + device->ExtraData=NULL; +} + +static void qsa_start_capture(ALCdevice* device) +{ + qsa_data* data=(qsa_data*)device->ExtraData; + int rstatus; + + if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) + { + ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); + return; + } + + memset(&data->csetup, 0, sizeof(data->csetup)); + data->csetup.channel=SND_PCM_CHANNEL_CAPTURE; + if ((rstatus=snd_pcm_plugin_setup(data->pcmHandle, &data->csetup))<0) + { + ERR("capture setup failed: %s\n", snd_strerror(rstatus)); + return; + } + + snd_pcm_capture_go(data->pcmHandle); +} + +static void qsa_stop_capture(ALCdevice* device) +{ + qsa_data* data=(qsa_data*)device->ExtraData; + + snd_pcm_capture_flush(data->pcmHandle); +} + +static ALCuint qsa_available_samples(ALCdevice* device) +{ + qsa_data* data=(qsa_data*)device->ExtraData; + snd_pcm_channel_status_t status; + ALint frame_size=FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + ALint free_size; + int rstatus; + + memset(&status, 0, sizeof (status)); + status.channel=SND_PCM_CHANNEL_CAPTURE; + snd_pcm_plugin_status(data->pcmHandle, &status); + if ((status.status==SND_PCM_STATUS_OVERRUN) || + (status.status==SND_PCM_STATUS_READY)) + { + if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) + { + ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); + aluHandleDisconnect(device); + return 0; + } + + snd_pcm_capture_go(data->pcmHandle); + return 0; + } + + free_size=data->csetup.buf.block.frag_size*data->csetup.buf.block.frags; + free_size-=status.free; + + return free_size/frame_size; +} + +static ALCenum qsa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) +{ + qsa_data* data=(qsa_data*)device->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 len=samples*frame_size; + int rstatus; + + read_ptr=buffer; + + while (len>0) + { + FD_ZERO(&rfds); + FD_SET(data->audio_fd, &rfds); + timeout.tv_sec=2; + timeout.tv_usec=0; + + /* Select also works like time slice to OS */ + bytes_read=0; + selectret=select(data->audio_fd+1, &rfds, NULL, NULL, &timeout); + switch (selectret) + { + case -1: + aluHandleDisconnect(device); + return ALC_INVALID_DEVICE; + case 0: + break; + default: + if (FD_ISSET(data->audio_fd, &rfds)) + { + bytes_read=snd_pcm_plugin_read(data->pcmHandle, read_ptr, len); + break; + } + break; + } + + if (bytes_read<=0) + { + if ((errno==EAGAIN) || (errno==EWOULDBLOCK)) + { + continue; + } + + memset(&status, 0, sizeof (status)); + status.channel=SND_PCM_CHANNEL_CAPTURE; + snd_pcm_plugin_status(data->pcmHandle, &status); + + /* we need to reinitialize the sound channel if we've overrun the buffer */ + if ((status.status==SND_PCM_STATUS_OVERRUN) || + (status.status==SND_PCM_STATUS_READY)) + { + if ((rstatus=snd_pcm_plugin_prepare(data->pcmHandle, SND_PCM_CHANNEL_CAPTURE))<0) + { + ERR("capture prepare failed: %s\n", snd_strerror(rstatus)); + aluHandleDisconnect(device); + return ALC_INVALID_DEVICE; + } + snd_pcm_capture_go(data->pcmHandle); + } + } + else + { + read_ptr+=bytes_read; + len-=bytes_read; + } + } + + return ALC_NO_ERROR; +} + +static const BackendFuncs qsa_funcs= { + 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 +}; + +ALCboolean alc_qsa_init(BackendFuncs* func_list) +{ + *func_list = qsa_funcs; + return ALC_TRUE; +} + +void alc_qsa_deinit(void) +{ +#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 +} + +void alc_qsa_probe(enum DevProbe type) +{ + switch (type) + { + case ALL_DEVICE_PROBE: +#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: +#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; + } +} diff --git a/Engine/lib/openal-soft/Alc/backends/sndio.c b/Engine/lib/openal-soft/Alc/backends/sndio.c new file mode 100644 index 000000000..52bff13a5 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/sndio.c @@ -0,0 +1,294 @@ +/** + * 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 +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "threads.h" + +#include + + +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 +}; + +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; + } +} diff --git a/Engine/lib/openal-soft/Alc/backends/solaris.c b/Engine/lib/openal-soft/Alc/backends/solaris.c new file mode 100644 index 000000000..01472e6a1 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/solaris.c @@ -0,0 +1,339 @@ +/** + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "threads.h" +#include "compat.h" + +#include "backends/base.h" + +#include + + +typedef struct ALCsolarisBackend { + DERIVE_FROM_TYPE(ALCbackend); + + int fd; + + ALubyte *mix_data; + int data_size; + + volatile int 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; +} + +static void ALCsolarisBackend_Destruct(ALCsolarisBackend *self) +{ + if(self->fd != -1) + close(self->fd); + self->fd = -1; + + free(self->mix_data); + self->mix_data = NULL; + self->data_size = 0; + + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); +} + + +static int ALCsolarisBackend_mixerProc(void *ptr) +{ + ALCsolarisBackend *self = ptr; + ALCdevice *Device = STATIC_CAST(ALCbackend,self)->mDevice; + ALint frameSize; + int wrote; + + SetRTPriority(); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); + + frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); + + while(!self->killNow && Device->Connected) + { + ALint len = self->data_size; + ALubyte *WritePtr = self->mix_data; + + aluMixData(Device, WritePtr, len/frameSize); + while(len > 0 && !self->killNow) + { + wrote = write(self->fd, WritePtr, len); + if(wrote < 0) + { + if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + { + ERR("write failed: %s\n", strerror(errno)); + ALCsolarisBackend_lock(self); + aluHandleDisconnect(Device); + ALCsolarisBackend_unlock(self); + break; + } + + al_nssleep(1000000); + continue; + } + + len -= wrote; + WritePtr += wrote; + } + } + + 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; + al_string_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; + 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(self->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); + + free(self->mix_data); + self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + self->mix_data = calloc(1, self->data_size); + + return ALC_TRUE; +} + +static ALCboolean ALCsolarisBackend_start(ALCsolarisBackend *self) +{ + self->killNow = 0; + 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(self->killNow) + return; + + self->killNow = 1; + 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; +} diff --git a/Engine/lib/openal-soft/Alc/backends/wave.c b/Engine/lib/openal-soft/Alc/backends/wave.c new file mode 100644 index 000000000..9bf5a7274 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/backends/wave.c @@ -0,0 +1,446 @@ +/** + * 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 +#include +#include +#include + +#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); + + 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) + { + aluMixData(device, self->mBuffer, device->UpdateSize); + 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; + al_string_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 = DevFmtAmbi1; + + 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 DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + /* .amb output requires FuMa */ + device->AmbiFmt = AmbiFormat_FuMa; + isbformat = 1; + chanmask = 0; + break; + } + bits = BytesFromDevFmt(device->FmtType) * 8; + channels = ChannelsFromDevFmt(device->FmtChans); + + fprintf(self->mFile, "RIFF"); + fwrite32le(0xFFFFFFFF, self->mFile); // 'RIFF' header len; filled in at close + + fprintf(self->mFile, "WAVE"); + + fprintf(self->mFile, "fmt "); + 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(((bits==32) ? (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) : + (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM)), 1, 16, self->mFile); + (void)val; + + fprintf(self->mFile, "data"); + 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); + 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; +} diff --git a/Engine/lib/openal-soft/Alc/backends/winmm.c b/Engine/lib/openal-soft/Alc/backends/winmm.c new file mode 100644 index 000000000..9d8f8e9d8 --- /dev/null +++ b/Engine/lib/openal-soft/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 +#include +#include + +#include +#include + +#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, al_string_deinit); + 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) + { + al_string_copy_cstr(&dname, DEVNAME_HEAD); + al_string_append_wcstr(&dname, WaveCaps.szPname); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&dname, str); + } + count++; + +#define MATCH_ENTRY(i) (al_string_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", al_string_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) + { + al_string_copy_cstr(&dname, DEVNAME_HEAD); + al_string_append_wcstr(&dname, WaveCaps.szPname); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&dname, str); + } + count++; + +#define MATCH_ENTRY(i) (al_string_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", al_string_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); + aluMixData(device, WaveHdr->lpData, WaveHdr->dwBufferLength / + self->Format.nBlockAlign); + + // 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) (!al_string_empty(*(iter)) && \ + (!deviceName || al_string_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; + } + + al_string_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); + + 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) (!al_string_empty(*(iter)) && (!name || al_string_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 DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + 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); + 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; + + al_string_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(!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)); +} + +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); +} diff --git a/Engine/lib/openal-soft/Alc/bformatdec.c b/Engine/lib/openal-soft/Alc/bformatdec.c new file mode 100644 index 000000000..2aab4ed8f --- /dev/null +++ b/Engine/lib/openal-soft/Alc/bformatdec.c @@ -0,0 +1,670 @@ + +#include "config.h" + +#include "bformatdec.h" +#include "ambdec.h" +#include "mixer_defs.h" +#include "alu.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, ALuint count) +{ + ALfloat coeff, d, x; + ALfloat z1, z2; + ALuint 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; +} + + +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 Ambi2DPoints[4][3] = { + { -0.707106781f, 0.0f, -0.707106781f }, + { 0.707106781f, 0.0f, -0.707106781f }, + { -0.707106781f, 0.0f, 0.707106781f }, + { 0.707106781f, 0.0f, 0.707106781f }, +}; +static const ALfloat Ambi2DDecoder[4][FB_Max][MAX_AMBI_COEFFS] = { + { { 0.353553f, 0.204094f, 0.0f, 0.204094f }, { 0.25f, 0.204094f, 0.0f, 0.204094f } }, + { { 0.353553f, -0.204094f, 0.0f, 0.204094f }, { 0.25f, -0.204094f, 0.0f, 0.204094f } }, + { { 0.353553f, 0.204094f, 0.0f, -0.204094f }, { 0.25f, 0.204094f, 0.0f, -0.204094f } }, + { { 0.353553f, -0.204094f, 0.0f, -0.204094f }, { 0.25f, -0.204094f, 0.0f, -0.204094f } }, +}; +static ALfloat Ambi2DEncoder[4][MAX_AMBI_COEFFS]; + +/* 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 ALfloat Ambi3DEncoder[8][MAX_AMBI_COEFFS]; + + +static RowMixerFunc MixMatrixRow = MixRow_C; + + +static alonce_flag bformatdec_inited = AL_ONCE_FLAG_INIT; + +static void init_bformatdec(void) +{ + ALuint i, j; + + MixMatrixRow = SelectRowMixer(); + + for(i = 0;i < COUNTOF(Ambi3DPoints);i++) + CalcDirectionCoeffs(Ambi3DPoints[i], 0.0f, Ambi3DEncoder[i]); + + for(i = 0;i < COUNTOF(Ambi2DPoints);i++) + { + CalcDirectionCoeffs(Ambi2DPoints[i], 0.0f, Ambi2DEncoder[i]); + + /* Remove the skipped height-related coefficients for 2D rendering. */ + Ambi2DEncoder[i][2] = Ambi2DEncoder[i][3]; + Ambi2DEncoder[i][3] = Ambi2DEncoder[i][4]; + Ambi2DEncoder[i][4] = Ambi2DEncoder[i][8]; + Ambi2DEncoder[i][5] = Ambi2DEncoder[i][9]; + Ambi2DEncoder[i][6] = Ambi2DEncoder[i][15]; + for(j = 7;j < MAX_AMBI_COEFFS;j++) + Ambi2DEncoder[i][j] = 0.0f; + } +} + + +#define MAX_DELAY_LENGTH 128 + +/* 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 { + alignas(16) ALfloat Buffer[MAX_DELAY_LENGTH]; + ALuint Length; /* Valid range is [0...MAX_DELAY_LENGTH). */ + } Delay[MAX_OUTPUT_CHANNELS]; + + struct { + BandSplitter XOver[4]; + + ALfloat Gains[4][MAX_OUTPUT_CHANNELS][FB_Max]; + } UpSampler; + + ALuint NumChannels; + ALboolean DualBand; + ALboolean Periphonic; +} 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); + } +} + +int bformatdec_getOrder(const struct BFormatDec *dec) +{ + if(dec->Periphonic) + { + if(dec->NumChannels > 9) return 3; + if(dec->NumChannels > 4) return 2; + if(dec->NumChannels > 1) return 1; + } + else + { + if(dec->NumChannels > 5) return 3; + if(dec->NumChannels > 3) return 2; + if(dec->NumChannels > 1) return 1; + } + return 0; +} + +void bformatdec_reset(BFormatDec *dec, const AmbDecConf *conf, ALuint chancount, ALuint srate, const ALuint chanmap[MAX_OUTPUT_CHANNELS], int flags) +{ + static const ALuint map2DTo3D[MAX_AMBI2D_COEFFS] = { + 0, 1, 3, 4, 8, 9, 15 + }; + const ALfloat *coeff_scale = UnitScale; + ALfloat distgain[MAX_OUTPUT_CHANNELS]; + ALfloat maxdist, ratio; + ALuint i, j, k; + + 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; + + ratio = 400.0f / (ALfloat)srate; + for(i = 0;i < 4;i++) + bandsplit_init(&dec->UpSampler.XOver[i], ratio); + memset(dec->UpSampler.Gains, 0, sizeof(dec->UpSampler.Gains)); + if((conf->ChanMask&AMBI_PERIPHONIC_MASK)) + { + /* Combine the matrices that do the in->virt and virt->out conversions + * so we get a single in->out conversion. + */ + for(i = 0;i < 4;i++) + { + for(j = 0;j < dec->NumChannels;j++) + { + ALfloat *gains = dec->UpSampler.Gains[i][j]; + for(k = 0;k < COUNTOF(Ambi3DDecoder);k++) + { + gains[FB_HighFreq] += Ambi3DDecoder[k][FB_HighFreq][i]*Ambi3DEncoder[k][j]; + gains[FB_LowFreq] += Ambi3DDecoder[k][FB_LowFreq][i]*Ambi3DEncoder[k][j]; + } + } + } + + dec->Periphonic = AL_TRUE; + } + else + { + for(i = 0;i < 4;i++) + { + for(j = 0;j < dec->NumChannels;j++) + { + ALfloat *gains = dec->UpSampler.Gains[i][j]; + for(k = 0;k < COUNTOF(Ambi2DDecoder);k++) + { + gains[FB_HighFreq] += Ambi2DDecoder[k][FB_HighFreq][i]*Ambi2DEncoder[k][j]; + gains[FB_LowFreq] += Ambi2DDecoder[k][FB_LowFreq][i]*Ambi2DEncoder[k][j]; + } + } + } + + dec->Periphonic = AL_FALSE; + } + + maxdist = 0.0f; + for(i = 0;i < conf->NumSpeakers;i++) + { + maxdist = maxf(maxdist, conf->Speakers[i].Distance); + distgain[i] = 1.0f; + } + + memset(dec->Delay, 0, sizeof(dec->Delay)); + if((flags&BFDF_DistanceComp) && maxdist > 0.0f) + { + for(i = 0;i < conf->NumSpeakers;i++) + { + ALuint chan = chanmap[i]; + ALfloat delay; + + /* Distance compensation only delays in steps of the sample rate. + * This is a bit less accurate since the delay time falls to the + * nearest sample time, but it's far simpler as it doesn't have to + * deal with phase offsets. This means at 48khz, for instance, the + * distance delay will be in steps of about 7 millimeters. + */ + delay = floorf((maxdist-conf->Speakers[i].Distance) / SPEEDOFSOUNDMETRESPERSEC * + (ALfloat)srate + 0.5f); + if(delay >= (ALfloat)MAX_DELAY_LENGTH) + ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n", + al_string_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH); + + dec->Delay[chan].Length = (ALuint)clampf(delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1)); + distgain[i] = conf->Speakers[i].Distance / maxdist; + TRACE("Channel %u \"%s\" distance compensation: %u samples, %f gain\n", chan, + al_string_get_cstr(conf->Speakers[i].Name), dec->Delay[chan].Length, distgain[i] + ); + } + } + + memset(&dec->Matrix, 0, sizeof(dec->Matrix)); + if(conf->FreqBands == 1) + { + dec->DualBand = AL_FALSE; + for(i = 0;i < conf->NumSpeakers;i++) + { + ALuint chan = chanmap[i]; + ALfloat gain; + ALuint j, k; + + if(!dec->Periphonic) + { + for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++) + { + ALuint 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<Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[l] * + gain * distgain[i]; + } + } + 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<Matrix.Single[chan][j] = conf->HFMatrix[i][k++] / coeff_scale[j] * + gain * distgain[i]; + } + } + } + } + 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++) + { + ALuint chan = chanmap[i]; + ALfloat gain; + ALuint j, k; + + if(!dec->Periphonic) + { + for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++) + { + ALuint 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<Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] / + coeff_scale[l] * gain * + distgain[i]; + } + for(j = 0,k = 0;j < MAX_AMBI2D_COEFFS;j++) + { + ALuint 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<Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] / + coeff_scale[l] * gain * + distgain[i]; + } + } + 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<Matrix.Dual[chan][FB_HighFreq][j] = conf->HFMatrix[i][k++] / + coeff_scale[j] * gain * + distgain[i]; + } + 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<Matrix.Dual[chan][FB_LowFreq][j] = conf->LFMatrix[i][k++] / + coeff_scale[j] * gain * + distgain[i]; + } + } + } + } +} + + +void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo) +{ + ALuint chan, i; + + 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 + ); + + if(dec->Delay[chan].Length > 0) + { + const ALuint base = dec->Delay[chan].Length; + if(SamplesToDo >= base) + { + for(i = 0;i < base;i++) + OutBuffer[chan][i] += dec->Delay[chan].Buffer[i]; + for(;i < SamplesToDo;i++) + OutBuffer[chan][i] += dec->ChannelMix[i-base]; + memcpy(dec->Delay[chan].Buffer, &dec->ChannelMix[SamplesToDo-base], + base*sizeof(ALfloat)); + } + else + { + for(i = 0;i < SamplesToDo;i++) + OutBuffer[chan][i] += dec->Delay[chan].Buffer[i]; + memmove(dec->Delay[chan].Buffer, dec->Delay[chan].Buffer+SamplesToDo, + base - SamplesToDo); + memcpy(dec->Delay[chan].Buffer+base-SamplesToDo, dec->ChannelMix, + SamplesToDo*sizeof(ALfloat)); + } + } + else 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); + + if(dec->Delay[chan].Length > 0) + { + const ALuint base = dec->Delay[chan].Length; + if(SamplesToDo >= base) + { + for(i = 0;i < base;i++) + OutBuffer[chan][i] += dec->Delay[chan].Buffer[i]; + for(;i < SamplesToDo;i++) + OutBuffer[chan][i] += dec->ChannelMix[i-base]; + memcpy(dec->Delay[chan].Buffer, &dec->ChannelMix[SamplesToDo-base], + base*sizeof(ALfloat)); + } + else + { + for(i = 0;i < SamplesToDo;i++) + OutBuffer[chan][i] += dec->Delay[chan].Buffer[i]; + memmove(dec->Delay[chan].Buffer, dec->Delay[chan].Buffer+SamplesToDo, + base - SamplesToDo); + memcpy(dec->Delay[chan].Buffer+base-SamplesToDo, dec->ChannelMix, + SamplesToDo*sizeof(ALfloat)); + } + } + else 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], ALuint InChannels, ALuint SamplesToDo) +{ + ALuint i, j; + + /* This up-sampler is very simplistic. It essentially decodes the first- + * order content to a square channel array (or cube if height is desired), + * then encodes those points onto the higher order soundfield. The decoder + * and encoder matrices have been combined to directly convert each input + * channel to the output, without the need for storing the virtual channel + * array. + */ + for(i = 0;i < InChannels;i++) + { + /* First, split the first-order components into low and high frequency + * bands. + */ + bandsplit_process(&dec->UpSampler.XOver[i], + dec->Samples[FB_HighFreq], dec->Samples[FB_LowFreq], + InSamples[i], SamplesToDo + ); + + /* Now write each band to the output. */ + for(j = 0;j < dec->NumChannels;j++) + MixMatrixRow(OutBuffer[j], dec->UpSampler.Gains[i][j], + SAFE_CONST(ALfloatBUFFERSIZE*,dec->Samples), FB_Max, 0, + SamplesToDo + ); + } +} + + +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 gains[8][MAX_OUTPUT_CHANNELS]; + ALfloat ratio; + ALuint i, j, k; + + ratio = 400.0f / (ALfloat)device->Frequency; + for(i = 0;i < 4;i++) + bandsplit_init(&ambiup->XOver[i], ratio); + + for(i = 0;i < COUNTOF(Ambi3DEncoder);i++) + ComputePanningGains(device->Dry, Ambi3DEncoder[i], 1.0f, gains[i]); + + memset(ambiup->Gains, 0, sizeof(ambiup->Gains)); + for(i = 0;i < 4;i++) + { + for(j = 0;j < device->Dry.NumChannels;j++) + { + for(k = 0;k < COUNTOF(Ambi3DDecoder);k++) + { + ambiup->Gains[i][j][FB_HighFreq] += Ambi3DDecoder[k][FB_HighFreq][i]*gains[k][j]; + ambiup->Gains[i][j][FB_LowFreq] += Ambi3DDecoder[k][FB_LowFreq][i]*gains[k][j]; + } + } + } +} + +void ambiup_process(struct AmbiUpsampler *ambiup, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo) +{ + ALuint 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 + ); + } +} diff --git a/Engine/lib/openal-soft/Alc/bformatdec.h b/Engine/lib/openal-soft/Alc/bformatdec.h new file mode 100644 index 000000000..e78d89a7b --- /dev/null +++ b/Engine/lib/openal-soft/Alc/bformatdec.h @@ -0,0 +1,49 @@ +#ifndef BFORMATDEC_H +#define BFORMATDEC_H + +#include "alMain.h" + +struct AmbDecConf; +struct BFormatDec; +struct AmbiUpsampler; + +enum BFormatDecFlags { + BFDF_DistanceComp = 1<<0 +}; + +struct BFormatDec *bformatdec_alloc(); +void bformatdec_free(struct BFormatDec *dec); +int bformatdec_getOrder(const struct BFormatDec *dec); +void bformatdec_reset(struct BFormatDec *dec, const struct AmbDecConf *conf, ALuint chancount, ALuint srate, const ALuint chanmap[MAX_OUTPUT_CHANNELS], int flags); + +/* Decodes the ambisonic input to the given output channels. */ +void bformatdec_process(struct BFormatDec *dec, ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint 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], ALuint InChannels, ALuint 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], ALuint OutChannels, const ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint 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, ALuint count); + +#endif /* BFORMATDEC_H */ diff --git a/Engine/lib/openal-soft/Alc/bs2b.c b/Engine/lib/openal-soft/Alc/bs2b.c new file mode 100644 index 000000000..ddc2e2f24 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/bs2b.c @@ -0,0 +1,187 @@ +/*- + * Copyright (c) 2005 Boris Mikhaylov + * + * 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. + */ + +#include "config.h" + +#include +#include + +#include "bs2b.h" +#include "alu.h" + + +/* Set up all data. */ +static void init(struct bs2b *bs2b) +{ + float Fc_lo, Fc_hi; + float G_lo, G_hi; + float x, g; + + switch(bs2b->level) + { + case BS2B_LOW_CLEVEL: /* Low crossfeed level */ + Fc_lo = 360.0f; + Fc_hi = 501.0f; + G_lo = 0.398107170553497f; + G_hi = 0.205671765275719f; + break; + + case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */ + Fc_lo = 500.0f; + Fc_hi = 711.0f; + G_lo = 0.459726988530872f; + G_hi = 0.228208484414988f; + break; + + case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */ + Fc_lo = 700.0f; + Fc_hi = 1021.0f; + G_lo = 0.530884444230988f; + G_hi = 0.250105790667544f; + break; + + case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */ + Fc_lo = 360.0f; + Fc_hi = 494.0f; + G_lo = 0.316227766016838f; + G_hi = 0.168236228897329f; + break; + + case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */ + Fc_lo = 500.0f; + Fc_hi = 689.0f; + G_lo = 0.354813389233575f; + G_hi = 0.187169483835901f; + break; + + default: /* High easy crossfeed level */ + bs2b->level = BS2B_HIGH_ECLEVEL; + + Fc_lo = 700.0f; + Fc_hi = 975.0f; + G_lo = 0.398107170553497f; + G_hi = 0.205671765275719f; + break; + } /* switch */ + + g = 1.0f / (1.0f - G_hi + G_lo); + + /* $fc = $Fc / $s; + * $d = 1 / 2 / pi / $fc; + * $x = exp(-1 / $d); + */ + x = expf(-2.0f * F_PI * Fc_lo / bs2b->srate); + bs2b->b1_lo = x; + bs2b->a0_lo = G_lo * (1.0f - x) * g; + + x = expf(-2.0f * F_PI * Fc_hi / bs2b->srate); + bs2b->b1_hi = x; + bs2b->a0_hi = (1.0f - G_hi * (1.0f - x)) * g; + bs2b->a1_hi = -x * g; +} /* init */ + + +/* Exported functions. + * See descriptions in "bs2b.h" + */ + +void bs2b_set_params(struct bs2b *bs2b, int level, int srate) +{ + if(srate <= 0) srate = 1; + + bs2b->level = level; + bs2b->srate = srate; + init(bs2b); +} /* bs2b_set_params */ + +int bs2b_get_level(struct bs2b *bs2b) +{ + return bs2b->level; +} /* bs2b_get_level */ + +int bs2b_get_srate(struct bs2b *bs2b) +{ + return bs2b->srate; +} /* bs2b_get_srate */ + +void bs2b_clear(struct bs2b *bs2b) +{ + memset(&bs2b->last_sample, 0, sizeof(bs2b->last_sample)); +} /* bs2b_clear */ + +void bs2b_cross_feed(struct bs2b *bs2b, float *restrict Left, float *restrict Right, unsigned int SamplesToDo) +{ + float lsamples[128][2]; + float rsamples[128][2]; + unsigned int base; + + for(base = 0;base < SamplesToDo;) + { + unsigned int todo = minu(128, SamplesToDo-base); + unsigned 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 */ diff --git a/Engine/lib/openal-soft/Alc/bsinc.c b/Engine/lib/openal-soft/Alc/bsinc.c new file mode 100644 index 000000000..f795120f7 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/bsinc.c @@ -0,0 +1,981 @@ + +#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 +}; diff --git a/Engine/lib/openal-soft/Alc/compat.h b/Engine/lib/openal-soft/Alc/compat.h new file mode 100644 index 000000000..114fc655d --- /dev/null +++ b/Engine/lib/openal-soft/Alc/compat.h @@ -0,0 +1,49 @@ +#ifndef AL_COMPAT_H +#define AL_COMPAT_H + +#include "alstring.h" + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include + +WCHAR *strdupW(const WCHAR *str); + +/* Opens a file with standard I/O. The filename is expected to be UTF-8. */ +FILE *al_fopen(const char *fname, const char *mode); + +#define HAVE_DYNLOAD 1 + +#else + +#define al_fopen fopen + +#if defined(HAVE_DLFCN_H) && !defined(IN_IDE_PARSER) +#define HAVE_DYNLOAD 1 +#endif + +#endif + +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 + +#endif /* AL_COMPAT_H */ diff --git a/Engine/lib/openal-soft/Alc/effects/chorus.c b/Engine/lib/openal-soft/Alc/effects/chorus.c new file mode 100644 index 000000000..63d0ca018 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/chorus.c @@ -0,0 +1,412 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2013 by Mike Gorchak + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "alMain.h" +#include "alFilter.h" +#include "alAuxEffectSlot.h" +#include "alError.h" +#include "alu.h" + + +enum ChorusWaveForm { + CWF_Triangle = AL_CHORUS_WAVEFORM_TRIANGLE, + CWF_Sinusoid = AL_CHORUS_WAVEFORM_SINUSOID +}; + +typedef struct ALchorusState { + DERIVE_FROM_TYPE(ALeffectState); + + ALfloat *SampleBuffer[2]; + ALuint BufferLength; + ALuint offset; + ALuint lfo_range; + ALfloat lfo_scale; + ALint lfo_disp; + + /* Gains for left and right sides */ + ALfloat Gain[2][MAX_OUTPUT_CHANNELS]; + + /* effect parameters */ + enum ChorusWaveForm waveform; + ALint delay; + ALfloat depth; + 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, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint 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) +{ + 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; + + maxlen = fastf2u(AL_CHORUS_MAX_DELAY * 3.0f * Device->Frequency) + 1; + maxlen = NextPowerOf2(maxlen); + + if(maxlen != state->BufferLength) + { + void *temp = al_calloc(16, maxlen * sizeof(ALfloat) * 2); + if(!temp) return AL_FALSE; + + al_free(state->SampleBuffer[0]); + state->SampleBuffer[0] = temp; + state->SampleBuffer[1] = state->SampleBuffer[0] + maxlen; + + state->BufferLength = maxlen; + } + + for(it = 0;it < state->BufferLength;it++) + { + state->SampleBuffer[0][it] = 0.0f; + state->SampleBuffer[1][it] = 0.0f; + } + + return AL_TRUE; +} + +static ALvoid 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(props->Chorus.Waveform) + { + case AL_CHORUS_WAVEFORM_TRIANGLE: + state->waveform = CWF_Triangle; + break; + case AL_CHORUS_WAVEFORM_SINUSOID: + state->waveform = CWF_Sinusoid; + break; + } + state->depth = props->Chorus.Depth; + state->feedback = props->Chorus.Feedback; + state->delay = fastf2i(props->Chorus.Delay * frequency); + + /* Gains for left and right sides */ + CalcXYZCoeffs(-1.0f, 0.0f, 0.0f, 0.0f, coeffs); + ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[0]); + CalcXYZCoeffs( 1.0f, 0.0f, 0.0f, 0.0f, coeffs); + ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[1]); + + phase = props->Chorus.Phase; + rate = props->Chorus.Rate; + if(!(rate > 0.0f)) + { + state->lfo_scale = 0.0f; + state->lfo_range = 1; + state->lfo_disp = 0; + } + else + { + /* Calculate LFO coefficient */ + state->lfo_range = fastf2u(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_TAU / state->lfo_range; + break; + } + + /* Calculate lfo phase displacement */ + state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f)); + } +} + +static inline void Triangle(ALint *delay_left, ALint *delay_right, ALuint offset, const ALchorusState *state) +{ + 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; +} + +static inline void Sinusoid(ALint *delay_left, ALint *delay_right, ALuint offset, const ALchorusState *state) +{ + 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; \ +} + +DECL_TEMPLATE(Triangle) +DECL_TEMPLATE(Sinusoid) + +#undef DECL_TEMPLATE + +static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + ALuint it, kt; + ALuint base; + + for(base = 0;base < SamplesToDo;) + { + ALfloat temps[128][2]; + ALuint td = minu(128, SamplesToDo-base); + + switch(state->waveform) + { + case CWF_Triangle: + ProcessTriangle(state, td, SamplesIn[0]+base, temps); + break; + case CWF_Sinusoid: + ProcessSinusoid(state, td, SamplesIn[0]+base, temps); + break; + } + + for(kt = 0;kt < NumChannels;kt++) + { + ALfloat gain = state->Gain[0][kt]; + if(fabsf(gain) > GAIN_SILENCE_THRESHOLD) + { + for(it = 0;it < td;it++) + SamplesOut[kt][it+base] += temps[it][0] * gain; + } + + gain = state->Gain[1][kt]; + if(fabsf(gain) > GAIN_SILENCE_THRESHOLD) + { + for(it = 0;it < td;it++) + SamplesOut[kt][it+base] += temps[it][1] * gain; + } + } + + base += td; + } +} + + +typedef struct ALchorusStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALchorusStateFactory; + +static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(factory)) +{ + ALchorusState *state; + + NEW_OBJ0(state, ALchorusState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALchorusStateFactory); + + +ALeffectStateFactory *ALchorusStateFactory_getFactory(void) +{ + static ALchorusStateFactory ChorusFactory = { { GET_VTABLE2(ALchorusStateFactory, ALeffectStateFactory) } }; + + return STATIC_CAST(ALeffectStateFactory, &ChorusFactory); +} + + +void ALchorus_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_CHORUS_WAVEFORM: + if(!(val >= AL_CHORUS_MIN_WAVEFORM && val <= AL_CHORUS_MAX_WAVEFORM)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Chorus.Waveform = val; + break; + + case AL_CHORUS_PHASE: + if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Chorus.Phase = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALchorus_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals) +{ + ALchorus_setParami(effect, context, param, vals[0]); +} +void ALchorus_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_CHORUS_RATE: + if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Chorus.Rate = val; + break; + + case AL_CHORUS_DEPTH: + if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Chorus.Depth = val; + break; + + case AL_CHORUS_FEEDBACK: + if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Chorus.Feedback = val; + break; + + case AL_CHORUS_DELAY: + if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Chorus.Delay = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALchorus_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + ALchorus_setParamf(effect, context, param, vals[0]); +} + +void ALchorus_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_CHORUS_WAVEFORM: + *val = props->Chorus.Waveform; + break; + + case AL_CHORUS_PHASE: + *val = props->Chorus.Phase; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALchorus_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals) +{ + ALchorus_getParami(effect, context, param, vals); +} +void ALchorus_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_CHORUS_RATE: + *val = props->Chorus.Rate; + break; + + case AL_CHORUS_DEPTH: + *val = props->Chorus.Depth; + break; + + case AL_CHORUS_FEEDBACK: + *val = props->Chorus.Feedback; + break; + + case AL_CHORUS_DELAY: + *val = props->Chorus.Delay; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALchorus_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals) +{ + ALchorus_getParamf(effect, context, param, vals); +} + +DEFINE_ALEFFECT_VTABLE(ALchorus); diff --git a/Engine/lib/openal-soft/Alc/effects/compressor.c b/Engine/lib/openal-soft/Alc/effects/compressor.c new file mode 100644 index 000000000..ab0a42167 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/compressor.c @@ -0,0 +1,254 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2013 by Anis A. Hireche + * 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 + +#include "config.h" +#include "alError.h" +#include "alMain.h" +#include "alAuxEffectSlot.h" +#include "alu.h" + + +typedef struct ALcompressorState { + DERIVE_FROM_TYPE(ALeffectState); + + /* Effect gains for each channel */ + ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS]; + + /* Effect parameters */ + ALboolean Enabled; + ALfloat AttackRate; + ALfloat ReleaseRate; + ALfloat GainCtrl; +} ALcompressorState; + +static ALvoid ALcompressorState_Destruct(ALcompressorState *state); +static ALboolean ALcompressorState_deviceUpdate(ALcompressorState *state, ALCdevice *device); +static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props); +static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint 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) +{ + const ALfloat attackTime = device->Frequency * 0.2f; /* 200ms Attack */ + const ALfloat releaseTime = device->Frequency * 0.4f; /* 400ms Release */ + + state->AttackRate = 1.0f / attackTime; + state->ReleaseRate = 1.0f / releaseTime; + + return AL_TRUE; +} + +static ALvoid ALcompressorState_update(ALcompressorState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props) +{ + ALuint i; + + state->Enabled = props->Compressor.OnOff; + + 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 (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + ALuint i, j, k; + ALuint base; + + for(base = 0;base < SamplesToDo;) + { + ALfloat temps[64][4]; + ALuint td = minu(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 gain = state->GainCtrl; + ALfloat output, amplitude; + + for(i = 0;i < td;i++) + { + /* 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); + + /* 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 gain = state->GainCtrl; + ALfloat output, amplitude; + + for(i = 0;i < td;i++) + { + /* 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); + for(j = 0;j < 4;j++) + temps[i][j] *= output; + } + + state->GainCtrl = gain; + } + + /* Now mix to the output. */ + for(j = 0;j < 4;j++) + { + for(k = 0;k < NumChannels;k++) + { + ALfloat gain = state->Gain[j][k]; + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; + + for(i = 0;i < td;i++) + SamplesOut[k][base+i] += gain * temps[i][j]; + } + } + + base += td; + } +} + + +typedef struct ALcompressorStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALcompressorStateFactory; + +static ALeffectState *ALcompressorStateFactory_create(ALcompressorStateFactory *UNUSED(factory)) +{ + ALcompressorState *state; + + NEW_OBJ0(state, ALcompressorState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALcompressorStateFactory); + +ALeffectStateFactory *ALcompressorStateFactory_getFactory(void) +{ + static ALcompressorStateFactory CompressorFactory = { { GET_VTABLE2(ALcompressorStateFactory, ALeffectStateFactory) } }; + + return STATIC_CAST(ALeffectStateFactory, &CompressorFactory); +} + + +void ALcompressor_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_COMPRESSOR_ONOFF: + if(!(val >= AL_COMPRESSOR_MIN_ONOFF && val <= AL_COMPRESSOR_MAX_ONOFF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Compressor.OnOff = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALcompressor_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals) +{ + ALcompressor_setParami(effect, context, param, vals[0]); +} +void ALcompressor_setParamf(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALfloat UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALcompressor_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + ALcompressor_setParamf(effect, context, param, vals[0]); +} + +void ALcompressor_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_COMPRESSOR_ONOFF: + *val = props->Compressor.OnOff; + break; + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALcompressor_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals) +{ + ALcompressor_getParami(effect, context, param, vals); +} +void ALcompressor_getParamf(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALcompressor_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals) +{ + ALcompressor_getParamf(effect, context, param, vals); +} + +DEFINE_ALEFFECT_VTABLE(ALcompressor); diff --git a/Engine/lib/openal-soft/Alc/effects/dedicated.c b/Engine/lib/openal-soft/Alc/effects/dedicated.c new file mode 100644 index 000000000..818cbb6bb --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/dedicated.c @@ -0,0 +1,201 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include + +#include "alMain.h" +#include "alFilter.h" +#include "alAuxEffectSlot.h" +#include "alError.h" +#include "alu.h" + + +typedef struct ALdedicatedState { + DERIVE_FROM_TYPE(ALeffectState); + + 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, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint 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 *state) +{ + ALeffectState_Destruct(STATIC_CAST(ALeffectState,state)); +} + +static ALboolean ALdedicatedState_deviceUpdate(ALdedicatedState *UNUSED(state), ALCdevice *UNUSED(device)) +{ + return AL_TRUE; +} + +static ALvoid ALdedicatedState_update(ALdedicatedState *state, const ALCdevice *device, const ALeffectslot *Slot, const ALeffectProps *props) +{ + ALfloat Gain; + ALuint i; + + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + state->gains[i] = 0.0f; + + 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) + { + 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]; + CalcXYZCoeffs(0.0f, 0.0f, -1.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)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + const ALfloat *gains = state->gains; + ALuint i, c; + + for(c = 0;c < NumChannels;c++) + { + if(!(fabsf(gains[c]) > GAIN_SILENCE_THRESHOLD)) + continue; + + for(i = 0;i < SamplesToDo;i++) + SamplesOut[c][i] += SamplesIn[0][i] * gains[c]; + } +} + + +typedef struct ALdedicatedStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALdedicatedStateFactory; + +ALeffectState *ALdedicatedStateFactory_create(ALdedicatedStateFactory *UNUSED(factory)) +{ + ALdedicatedState *state; + + NEW_OBJ0(state, ALdedicatedState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALdedicatedStateFactory); + + +ALeffectStateFactory *ALdedicatedStateFactory_getFactory(void) +{ + static ALdedicatedStateFactory DedicatedFactory = { { GET_VTABLE2(ALdedicatedStateFactory, ALeffectStateFactory) } }; + + return STATIC_CAST(ALeffectStateFactory, &DedicatedFactory); +} + + +void ALdedicated_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALdedicated_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals) +{ + ALdedicated_setParami(effect, context, param, vals[0]); +} +void ALdedicated_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_DEDICATED_GAIN: + if(!(val >= 0.0f && isfinite(val))) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Dedicated.Gain = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALdedicated_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + ALdedicated_setParamf(effect, context, param, vals[0]); +} + +void ALdedicated_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALdedicated_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals) +{ + ALdedicated_getParami(effect, context, param, vals); +} +void ALdedicated_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_DEDICATED_GAIN: + *val = props->Dedicated.Gain; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALdedicated_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals) +{ + ALdedicated_getParamf(effect, context, param, vals); +} + +DEFINE_ALEFFECT_VTABLE(ALdedicated); diff --git a/Engine/lib/openal-soft/Alc/effects/distortion.c b/Engine/lib/openal-soft/Alc/effects/distortion.c new file mode 100644 index 000000000..bc1e7d84f --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/distortion.c @@ -0,0 +1,298 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2013 by Mike Gorchak + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "alMain.h" +#include "alFilter.h" +#include "alAuxEffectSlot.h" +#include "alError.h" +#include "alu.h" + + +typedef struct ALdistortionState { + DERIVE_FROM_TYPE(ALeffectState); + + /* Effect gains for each channel */ + ALfloat Gain[MAX_OUTPUT_CHANNELS]; + + /* Effect parameters */ + ALfilterState lowpass; + ALfilterState bandpass; + ALfloat attenuation; + ALfloat edge_coeff; +} ALdistortionState; + +static ALvoid ALdistortionState_Destruct(ALdistortionState *state); +static ALboolean ALdistortionState_deviceUpdate(ALdistortionState *state, ALCdevice *device); +static ALvoid ALdistortionState_update(ALdistortionState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props); +static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint 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)) +{ + return AL_TRUE; +} + +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; + + /* Store distorted signal attenuation settings */ + state->attenuation = props->Distortion.Gain; + + /* Store waveshaper edge settings */ + edge = sinf(props->Distortion.Edge * (F_PI_2)); + edge = minf(edge, 0.99f); + state->edge_coeff = 2.0f * edge / (1.0f-edge); + + /* Lowpass filter */ + cutoff = props->Distortion.LowpassCutoff; + /* Bandwidth value is constant in octaves */ + bandwidth = (cutoff / 2.0f) / (cutoff * 0.67f); + ALfilterState_setParams(&state->lowpass, ALfilterType_LowPass, 1.0f, + cutoff / (frequency*4.0f), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth) + ); + + /* Bandpass filter */ + 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), calc_rcpQ_from_bandwidth(cutoff / (frequency*4.0f), bandwidth) + ); + + ComputeAmbientGains(Device->Dry, Slot->Params.Gain, state->Gain); +} + +static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + const ALfloat fc = state->edge_coeff; + ALuint base; + ALuint it; + ALuint ot; + ALuint kt; + + for(base = 0;base < SamplesToDo;) + { + float buffer[2][64 * 4]; + ALuint td = minu(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. */ + + /* Fill oversample buffer using zero stuffing */ + for(it = 0;it < td;it++) + { + buffer[0][it*4 + 0] = SamplesIn[0][it+base]; + 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. */ + 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;it++) + { + for(ot = 0;ot < 4;ot++) + { + /* Restore signal power by multiplying sample by amount of oversampling */ + ALfloat smp = buffer[1][it*4 + ot] * 4.0f; + + 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[1][it*4 + ot] = smp; + } + } + + /* Third step, do bandpass filtering of distorted signal */ + ALfilterState_process(&state->bandpass, buffer[0], buffer[1], td*4); + + for(kt = 0;kt < NumChannels;kt++) + { + /* 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 * buffer[0][it*4]; + } + + base += td; + } +} + + +typedef struct ALdistortionStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALdistortionStateFactory; + +static ALeffectState *ALdistortionStateFactory_create(ALdistortionStateFactory *UNUSED(factory)) +{ + ALdistortionState *state; + + NEW_OBJ0(state, ALdistortionState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALdistortionStateFactory); + + +ALeffectStateFactory *ALdistortionStateFactory_getFactory(void) +{ + static ALdistortionStateFactory DistortionFactory = { { GET_VTABLE2(ALdistortionStateFactory, ALeffectStateFactory) } }; + + return STATIC_CAST(ALeffectStateFactory, &DistortionFactory); +} + + +void ALdistortion_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALdistortion_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals) +{ + ALdistortion_setParami(effect, context, param, vals[0]); +} +void ALdistortion_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_DISTORTION_EDGE: + if(!(val >= AL_DISTORTION_MIN_EDGE && val <= AL_DISTORTION_MAX_EDGE)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Distortion.Edge = val; + break; + + case AL_DISTORTION_GAIN: + if(!(val >= AL_DISTORTION_MIN_GAIN && val <= AL_DISTORTION_MAX_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Distortion.Gain = val; + break; + + case AL_DISTORTION_LOWPASS_CUTOFF: + if(!(val >= AL_DISTORTION_MIN_LOWPASS_CUTOFF && val <= AL_DISTORTION_MAX_LOWPASS_CUTOFF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Distortion.LowpassCutoff = val; + break; + + case AL_DISTORTION_EQCENTER: + if(!(val >= AL_DISTORTION_MIN_EQCENTER && val <= AL_DISTORTION_MAX_EQCENTER)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Distortion.EQCenter = val; + break; + + case AL_DISTORTION_EQBANDWIDTH: + if(!(val >= AL_DISTORTION_MIN_EQBANDWIDTH && val <= AL_DISTORTION_MAX_EQBANDWIDTH)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Distortion.EQBandwidth = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALdistortion_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + ALdistortion_setParamf(effect, context, param, vals[0]); +} + +void ALdistortion_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALdistortion_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals) +{ + ALdistortion_getParami(effect, context, param, vals); +} +void ALdistortion_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_DISTORTION_EDGE: + *val = props->Distortion.Edge; + break; + + case AL_DISTORTION_GAIN: + *val = props->Distortion.Gain; + break; + + case AL_DISTORTION_LOWPASS_CUTOFF: + *val = props->Distortion.LowpassCutoff; + break; + + case AL_DISTORTION_EQCENTER: + *val = props->Distortion.EQCenter; + break; + + case AL_DISTORTION_EQBANDWIDTH: + *val = props->Distortion.EQBandwidth; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALdistortion_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals) +{ + ALdistortion_getParamf(effect, context, param, vals); +} + +DEFINE_ALEFFECT_VTABLE(ALdistortion); diff --git a/Engine/lib/openal-soft/Alc/effects/echo.c b/Engine/lib/openal-soft/Alc/effects/echo.c new file mode 100644 index 000000000..3ad1e9752 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/echo.c @@ -0,0 +1,326 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2009 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "alMain.h" +#include "alFilter.h" +#include "alAuxEffectSlot.h" +#include "alError.h" +#include "alu.h" + + +typedef struct ALechoState { + DERIVE_FROM_TYPE(ALeffectState); + + ALfloat *SampleBuffer; + ALuint BufferLength; + + // The echo is two tap. The delay is the number of samples from before the + // current offset + struct { + ALuint delay; + } Tap[2]; + ALuint Offset; + /* The panning gains for the two taps */ + 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, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint 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) +{ + al_free(state->SampleBuffer); + state->SampleBuffer = NULL; + ALeffectState_Destruct(STATIC_CAST(ALeffectState,state)); +} + +static ALboolean ALechoState_deviceUpdate(ALechoState *state, ALCdevice *Device) +{ + ALuint 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 = NextPowerOf2(maxlen); + + if(maxlen != state->BufferLength) + { + void *temp = al_calloc(16, maxlen * sizeof(ALfloat)); + if(!temp) return AL_FALSE; + + al_free(state->SampleBuffer); + state->SampleBuffer = temp; + state->BufferLength = maxlen; + } + for(i = 0;i < state->BufferLength;i++) + state->SampleBuffer[i] = 0.0f; + + return AL_TRUE; +} + +static ALvoid ALechoState_update(ALechoState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props) +{ + ALuint frequency = Device->Frequency; + ALfloat coeffs[MAX_AMBI_COEFFS]; + ALfloat gain, lrpan, spread; + + state->Tap[0].delay = fastf2u(props->Echo.Delay * frequency) + 1; + state->Tap[1].delay = fastf2u(props->Echo.LRDelay * frequency); + state->Tap[1].delay += state->Tap[0].delay; + + 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 = props->Echo.Feedback; + + gain = minf(1.0f - props->Echo.Damping, 0.01f); + ALfilterState_setParams(&state->Filter, ALfilterType_HighShelf, + gain, LOWPASSFREQREF/frequency, + calc_rcpQ_from_slope(gain, 0.75f)); + + gain = Slot->Params.Gain; + + /* First tap panning */ + CalcXYZCoeffs(-lrpan, 0.0f, 0.0f, spread, coeffs); + ComputePanningGains(Device->Dry, coeffs, gain, state->Gain[0]); + + /* Second tap panning */ + CalcXYZCoeffs( lrpan, 0.0f, 0.0f, spread, coeffs); + ComputePanningGains(Device->Dry, coeffs, gain, state->Gain[1]); +} + +static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint 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 x[2], y[2], in, out; + ALuint base; + ALuint i, k; + + 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[128][2]; + ALuint td = minu(128, SamplesToDo-base); + + for(i = 0;i < td;i++) + { + /* First tap */ + temps[i][0] = state->SampleBuffer[(offset-tap1) & mask]; + /* Second tap */ + temps[i][1] = state->SampleBuffer[(offset-tap2) & mask]; + + // Apply damping and feedback gain to the second tap, and mix in the + // new sample + in = temps[i][1] + SamplesIn[0][i+base]; + 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 < NumChannels;k++) + { + ALfloat gain = state->Gain[0][k]; + if(fabsf(gain) > GAIN_SILENCE_THRESHOLD) + { + for(i = 0;i < td;i++) + SamplesOut[k][i+base] += temps[i][0] * gain; + } + + gain = state->Gain[1][k]; + if(fabsf(gain) > GAIN_SILENCE_THRESHOLD) + { + for(i = 0;i < td;i++) + SamplesOut[k][i+base] += temps[i][1] * gain; + } + } + + 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; +} + + +typedef struct ALechoStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALechoStateFactory; + +ALeffectState *ALechoStateFactory_create(ALechoStateFactory *UNUSED(factory)) +{ + ALechoState *state; + + NEW_OBJ0(state, ALechoState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALechoStateFactory); + +ALeffectStateFactory *ALechoStateFactory_getFactory(void) +{ + static ALechoStateFactory EchoFactory = { { GET_VTABLE2(ALechoStateFactory, ALeffectStateFactory) } }; + + return STATIC_CAST(ALeffectStateFactory, &EchoFactory); +} + + +void ALecho_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALecho_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals) +{ + ALecho_setParami(effect, context, param, vals[0]); +} +void ALecho_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_ECHO_DELAY: + if(!(val >= AL_ECHO_MIN_DELAY && val <= AL_ECHO_MAX_DELAY)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Echo.Delay = val; + break; + + case AL_ECHO_LRDELAY: + if(!(val >= AL_ECHO_MIN_LRDELAY && val <= AL_ECHO_MAX_LRDELAY)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Echo.LRDelay = val; + break; + + case AL_ECHO_DAMPING: + if(!(val >= AL_ECHO_MIN_DAMPING && val <= AL_ECHO_MAX_DAMPING)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Echo.Damping = val; + break; + + case AL_ECHO_FEEDBACK: + if(!(val >= AL_ECHO_MIN_FEEDBACK && val <= AL_ECHO_MAX_FEEDBACK)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Echo.Feedback = val; + break; + + case AL_ECHO_SPREAD: + if(!(val >= AL_ECHO_MIN_SPREAD && val <= AL_ECHO_MAX_SPREAD)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Echo.Spread = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALecho_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + ALecho_setParamf(effect, context, param, vals[0]); +} + +void ALecho_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALecho_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals) +{ + ALecho_getParami(effect, context, param, vals); +} +void ALecho_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_ECHO_DELAY: + *val = props->Echo.Delay; + break; + + case AL_ECHO_LRDELAY: + *val = props->Echo.LRDelay; + break; + + case AL_ECHO_DAMPING: + *val = props->Echo.Damping; + break; + + case AL_ECHO_FEEDBACK: + *val = props->Echo.Feedback; + break; + + case AL_ECHO_SPREAD: + *val = props->Echo.Spread; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALecho_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals) +{ + ALecho_getParamf(effect, context, param, vals); +} + +DEFINE_ALEFFECT_VTABLE(ALecho); diff --git a/Engine/lib/openal-soft/Alc/effects/equalizer.c b/Engine/lib/openal-soft/Alc/effects/equalizer.c new file mode 100644 index 000000000..1a63b4181 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/equalizer.c @@ -0,0 +1,404 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2013 by Mike Gorchak + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "alMain.h" +#include "alFilter.h" +#include "alAuxEffectSlot.h" +#include "alError.h" +#include "alu.h" + + +/* The document "Effects Extension Guide.pdf" says that low and high * + * frequencies are cutoff frequencies. This is not fully correct, they * + * are corner frequencies for low and high shelf filters. If they were * + * just cutoff frequencies, there would be no need in cutoff frequency * + * gains, which are present. Documentation for "Creative Proteus X2" * + * software describes 4-band equalizer functionality in a much better * + * way. This equalizer seems to be a predecessor of OpenAL 4-band * + * equalizer. With low and high shelf filters we are able to cutoff * + * frequencies below and/or above corner frequencies using attenuation * + * gains (below 1.0) and amplify all low and/or high frequencies using * + * gains above 1.0. * + * * + * Low-shelf Low Mid Band High Mid Band High-shelf * + * corner center center corner * + * frequency frequency frequency frequency * + * 50Hz..800Hz 200Hz..3000Hz 1000Hz..8000Hz 4000Hz..16000Hz * + * * + * | | | | * + * | | | | * + * B -----+ /--+--\ /--+--\ +----- * + * O |\ | | | | | | /| * + * O | \ - | - - | - / | * + * S + | \ | | | | | | / | * + * T | | | | | | | | | | * + * ---------+---------------+------------------+---------------+-------- * + * C | | | | | | | | | | * + * U - | / | | | | | | \ | * + * T | / - | - - | - \ | * + * O |/ | | | | | | \| * + * F -----+ \--+--/ \--+--/ +----- * + * F | | | | * + * | | | | * + * * + * Gains vary from 0.126 up to 7.943, which means from -18dB attenuation * + * up to +18dB amplification. Band width varies from 0.01 up to 1.0 in * + * octaves for two mid bands. * + * * + * 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 */ + + +/* The maximum number of sample frames per update. */ +#define MAX_UPDATE_SAMPLES 256 + +typedef struct ALequalizerState { + DERIVE_FROM_TYPE(ALeffectState); + + /* Effect gains for each channel */ + ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS]; + + /* Effect parameters */ + ALfilterState filter[4][MAX_EFFECT_CHANNELS]; + + ALfloat SampleBuffer[4][MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES]; +} ALequalizerState; + +static ALvoid ALequalizerState_Destruct(ALequalizerState *state); +static ALboolean ALequalizerState_deviceUpdate(ALequalizerState *state, ALCdevice *device); +static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props); +static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint 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)) +{ + return AL_TRUE; +} + +static ALvoid ALequalizerState_update(ALequalizerState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props) +{ + ALfloat frequency = (ALfloat)device->Frequency; + 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 = sqrtf(props->Equalizer.LowGain); + 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++) + { + state->filter[0][i].a1 = state->filter[0][0].a1; + state->filter[0][i].a2 = state->filter[0][0].a2; + state->filter[0][i].b0 = state->filter[0][0].b0; + state->filter[0][i].b1 = state->filter[0][0].b1; + state->filter[0][i].b2 = state->filter[0][0].b2; + } + + gain = props->Equalizer.Mid1Gain; + 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++) + { + state->filter[1][i].a1 = state->filter[1][0].a1; + state->filter[1][i].a2 = state->filter[1][0].a2; + state->filter[1][i].b0 = state->filter[1][0].b0; + state->filter[1][i].b1 = state->filter[1][0].b1; + state->filter[1][i].b2 = state->filter[1][0].b2; + } + + gain = props->Equalizer.Mid2Gain; + 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++) + { + state->filter[2][i].a1 = state->filter[2][0].a1; + state->filter[2][i].a2 = state->filter[2][0].a2; + state->filter[2][i].b0 = state->filter[2][0].b0; + state->filter[2][i].b1 = state->filter[2][0].b1; + state->filter[2][i].b2 = state->filter[2][0].b2; + } + + gain = sqrtf(props->Equalizer.HighGain); + 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++) + { + state->filter[3][i].a1 = state->filter[3][0].a1; + state->filter[3][i].a2 = state->filter[3][0].a2; + state->filter[3][i].b0 = state->filter[3][0].b0; + state->filter[3][i].b1 = state->filter[3][0].b1; + state->filter[3][i].b2 = state->filter[3][0].b2; + } +} + +static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + ALfloat (*Samples)[MAX_EFFECT_CHANNELS][MAX_UPDATE_SAMPLES] = state->SampleBuffer; + ALuint it, kt, ft; + ALuint base; + + for(base = 0;base < SamplesToDo;) + { + ALuint td = minu(MAX_UPDATE_SAMPLES, SamplesToDo-base); + + for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++) + ALfilterState_process(&state->filter[0][ft], Samples[0][ft], &SamplesIn[ft][base], td); + for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++) + ALfilterState_process(&state->filter[1][ft], Samples[1][ft], Samples[0][ft], td); + for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++) + ALfilterState_process(&state->filter[2][ft], Samples[2][ft], Samples[1][ft], td); + for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++) + ALfilterState_process(&state->filter[3][ft], Samples[3][ft], Samples[2][ft], td); + + for(ft = 0;ft < MAX_EFFECT_CHANNELS;ft++) + { + for(kt = 0;kt < NumChannels;kt++) + { + ALfloat gain = state->Gain[ft][kt]; + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; + + for(it = 0;it < td;it++) + SamplesOut[kt][base+it] += gain * Samples[3][ft][it]; + } + } + + base += td; + } +} + + +typedef struct ALequalizerStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALequalizerStateFactory; + +ALeffectState *ALequalizerStateFactory_create(ALequalizerStateFactory *UNUSED(factory)) +{ + ALequalizerState *state; + + NEW_OBJ0(state, ALequalizerState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALequalizerStateFactory); + +ALeffectStateFactory *ALequalizerStateFactory_getFactory(void) +{ + static ALequalizerStateFactory EqualizerFactory = { { GET_VTABLE2(ALequalizerStateFactory, ALeffectStateFactory) } }; + + return STATIC_CAST(ALeffectStateFactory, &EqualizerFactory); +} + + +void ALequalizer_setParami(ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALequalizer_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals) +{ + ALequalizer_setParami(effect, context, param, vals[0]); +} +void ALequalizer_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_EQUALIZER_LOW_GAIN: + if(!(val >= AL_EQUALIZER_MIN_LOW_GAIN && val <= AL_EQUALIZER_MAX_LOW_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.LowGain = val; + break; + + case AL_EQUALIZER_LOW_CUTOFF: + if(!(val >= AL_EQUALIZER_MIN_LOW_CUTOFF && val <= AL_EQUALIZER_MAX_LOW_CUTOFF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.LowCutoff = val; + break; + + case AL_EQUALIZER_MID1_GAIN: + if(!(val >= AL_EQUALIZER_MIN_MID1_GAIN && val <= AL_EQUALIZER_MAX_MID1_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.Mid1Gain = val; + break; + + case AL_EQUALIZER_MID1_CENTER: + if(!(val >= AL_EQUALIZER_MIN_MID1_CENTER && val <= AL_EQUALIZER_MAX_MID1_CENTER)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.Mid1Center = val; + break; + + case AL_EQUALIZER_MID1_WIDTH: + if(!(val >= AL_EQUALIZER_MIN_MID1_WIDTH && val <= AL_EQUALIZER_MAX_MID1_WIDTH)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.Mid1Width = val; + break; + + case AL_EQUALIZER_MID2_GAIN: + if(!(val >= AL_EQUALIZER_MIN_MID2_GAIN && val <= AL_EQUALIZER_MAX_MID2_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.Mid2Gain = val; + break; + + case AL_EQUALIZER_MID2_CENTER: + if(!(val >= AL_EQUALIZER_MIN_MID2_CENTER && val <= AL_EQUALIZER_MAX_MID2_CENTER)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.Mid2Center = val; + break; + + case AL_EQUALIZER_MID2_WIDTH: + if(!(val >= AL_EQUALIZER_MIN_MID2_WIDTH && val <= AL_EQUALIZER_MAX_MID2_WIDTH)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.Mid2Width = val; + break; + + case AL_EQUALIZER_HIGH_GAIN: + if(!(val >= AL_EQUALIZER_MIN_HIGH_GAIN && val <= AL_EQUALIZER_MAX_HIGH_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.HighGain = val; + break; + + case AL_EQUALIZER_HIGH_CUTOFF: + if(!(val >= AL_EQUALIZER_MIN_HIGH_CUTOFF && val <= AL_EQUALIZER_MAX_HIGH_CUTOFF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Equalizer.HighCutoff = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALequalizer_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + ALequalizer_setParamf(effect, context, param, vals[0]); +} + +void ALequalizer_getParami(const ALeffect *UNUSED(effect), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +void ALequalizer_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals) +{ + ALequalizer_getParami(effect, context, param, vals); +} +void ALequalizer_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_EQUALIZER_LOW_GAIN: + *val = props->Equalizer.LowGain; + break; + + case AL_EQUALIZER_LOW_CUTOFF: + *val = props->Equalizer.LowCutoff; + break; + + case AL_EQUALIZER_MID1_GAIN: + *val = props->Equalizer.Mid1Gain; + break; + + case AL_EQUALIZER_MID1_CENTER: + *val = props->Equalizer.Mid1Center; + break; + + case AL_EQUALIZER_MID1_WIDTH: + *val = props->Equalizer.Mid1Width; + break; + + case AL_EQUALIZER_MID2_GAIN: + *val = props->Equalizer.Mid2Gain; + break; + + case AL_EQUALIZER_MID2_CENTER: + *val = props->Equalizer.Mid2Center; + break; + + case AL_EQUALIZER_MID2_WIDTH: + *val = props->Equalizer.Mid2Width; + break; + + case AL_EQUALIZER_HIGH_GAIN: + *val = props->Equalizer.HighGain; + break; + + case AL_EQUALIZER_HIGH_CUTOFF: + *val = props->Equalizer.HighCutoff; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALequalizer_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals) +{ + ALequalizer_getParamf(effect, context, param, vals); +} + +DEFINE_ALEFFECT_VTABLE(ALequalizer); diff --git a/Engine/lib/openal-soft/Alc/effects/flanger.c b/Engine/lib/openal-soft/Alc/effects/flanger.c new file mode 100644 index 000000000..1575212bc --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/flanger.c @@ -0,0 +1,411 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2013 by Mike Gorchak + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "alMain.h" +#include "alFilter.h" +#include "alAuxEffectSlot.h" +#include "alError.h" +#include "alu.h" + + +enum FlangerWaveForm { + FWF_Triangle = AL_FLANGER_WAVEFORM_TRIANGLE, + FWF_Sinusoid = AL_FLANGER_WAVEFORM_SINUSOID +}; + +typedef struct ALflangerState { + DERIVE_FROM_TYPE(ALeffectState); + + ALfloat *SampleBuffer[2]; + ALuint BufferLength; + ALuint offset; + ALuint lfo_range; + ALfloat lfo_scale; + ALint lfo_disp; + + /* Gains for left and right sides */ + ALfloat Gain[2][MAX_OUTPUT_CHANNELS]; + + /* effect parameters */ + enum FlangerWaveForm waveform; + ALint delay; + ALfloat depth; + ALfloat feedback; +} ALflangerState; + +static ALvoid ALflangerState_Destruct(ALflangerState *state); +static ALboolean ALflangerState_deviceUpdate(ALflangerState *state, ALCdevice *Device); +static ALvoid ALflangerState_update(ALflangerState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props); +static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels); +DECLARE_DEFAULT_ALLOCATORS(ALflangerState) + +DEFINE_ALEFFECTSTATE_VTABLE(ALflangerState); + + +static void ALflangerState_Construct(ALflangerState *state) +{ + ALeffectState_Construct(STATIC_CAST(ALeffectState, state)); + SET_VTABLE2(ALflangerState, ALeffectState, state); + + state->BufferLength = 0; + state->SampleBuffer[0] = NULL; + state->SampleBuffer[1] = NULL; + state->offset = 0; + state->lfo_range = 1; + state->waveform = FWF_Triangle; +} + +static ALvoid ALflangerState_Destruct(ALflangerState *state) +{ + al_free(state->SampleBuffer[0]); + state->SampleBuffer[0] = NULL; + state->SampleBuffer[1] = NULL; + + ALeffectState_Destruct(STATIC_CAST(ALeffectState,state)); +} + +static ALboolean ALflangerState_deviceUpdate(ALflangerState *state, ALCdevice *Device) +{ + ALuint maxlen; + ALuint it; + + maxlen = fastf2u(AL_FLANGER_MAX_DELAY * 3.0f * Device->Frequency) + 1; + maxlen = NextPowerOf2(maxlen); + + if(maxlen != state->BufferLength) + { + void *temp = al_calloc(16, maxlen * sizeof(ALfloat) * 2); + if(!temp) return AL_FALSE; + + al_free(state->SampleBuffer[0]); + state->SampleBuffer[0] = temp; + state->SampleBuffer[1] = state->SampleBuffer[0] + maxlen; + + state->BufferLength = maxlen; + } + + for(it = 0;it < state->BufferLength;it++) + { + state->SampleBuffer[0][it] = 0.0f; + state->SampleBuffer[1][it] = 0.0f; + } + + return AL_TRUE; +} + +static ALvoid ALflangerState_update(ALflangerState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props) +{ + ALfloat frequency = (ALfloat)Device->Frequency; + ALfloat coeffs[MAX_AMBI_COEFFS]; + ALfloat rate; + ALint phase; + + switch(props->Flanger.Waveform) + { + case AL_FLANGER_WAVEFORM_TRIANGLE: + state->waveform = FWF_Triangle; + break; + case AL_FLANGER_WAVEFORM_SINUSOID: + state->waveform = FWF_Sinusoid; + break; + } + state->depth = props->Flanger.Depth; + state->feedback = props->Flanger.Feedback; + state->delay = fastf2i(props->Flanger.Delay * frequency); + + /* Gains for left and right sides */ + CalcXYZCoeffs(-1.0f, 0.0f, 0.0f, 0.0f, coeffs); + ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[0]); + CalcXYZCoeffs( 1.0f, 0.0f, 0.0f, 0.0f, coeffs); + ComputePanningGains(Device->Dry, coeffs, Slot->Params.Gain, state->Gain[1]); + + phase = props->Flanger.Phase; + rate = props->Flanger.Rate; + if(!(rate > 0.0f)) + { + state->lfo_scale = 0.0f; + state->lfo_range = 1; + state->lfo_disp = 0; + } + else + { + /* Calculate LFO coefficient */ + state->lfo_range = fastf2u(frequency/rate + 0.5f); + switch(state->waveform) + { + case FWF_Triangle: + state->lfo_scale = 4.0f / state->lfo_range; + break; + case FWF_Sinusoid: + state->lfo_scale = F_TAU / state->lfo_range; + break; + } + + /* Calculate lfo phase displacement */ + state->lfo_disp = fastf2i(state->lfo_range * (phase/360.0f)); + } +} + +static inline void Triangle(ALint *delay_left, ALint *delay_right, ALuint offset, const ALflangerState *state) +{ + 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; +} + +static inline void Sinusoid(ALint *delay_left, ALint *delay_right, ALuint offset, const ALflangerState *state) +{ + 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(ALflangerState *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; \ +} + +DECL_TEMPLATE(Triangle) +DECL_TEMPLATE(Sinusoid) + +#undef DECL_TEMPLATE + +static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + ALuint it, kt; + ALuint base; + + for(base = 0;base < SamplesToDo;) + { + ALfloat temps[128][2]; + ALuint td = minu(128, SamplesToDo-base); + + switch(state->waveform) + { + case FWF_Triangle: + ProcessTriangle(state, td, SamplesIn[0]+base, temps); + break; + case FWF_Sinusoid: + ProcessSinusoid(state, td, SamplesIn[0]+base, temps); + break; + } + + for(kt = 0;kt < NumChannels;kt++) + { + ALfloat gain = state->Gain[0][kt]; + if(fabsf(gain) > GAIN_SILENCE_THRESHOLD) + { + for(it = 0;it < td;it++) + SamplesOut[kt][it+base] += temps[it][0] * gain; + } + + gain = state->Gain[1][kt]; + if(fabsf(gain) > GAIN_SILENCE_THRESHOLD) + { + for(it = 0;it < td;it++) + SamplesOut[kt][it+base] += temps[it][1] * gain; + } + } + + base += td; + } +} + + +typedef struct ALflangerStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALflangerStateFactory; + +ALeffectState *ALflangerStateFactory_create(ALflangerStateFactory *UNUSED(factory)) +{ + ALflangerState *state; + + NEW_OBJ0(state, ALflangerState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALflangerStateFactory); + +ALeffectStateFactory *ALflangerStateFactory_getFactory(void) +{ + static ALflangerStateFactory FlangerFactory = { { GET_VTABLE2(ALflangerStateFactory, ALeffectStateFactory) } }; + + return STATIC_CAST(ALeffectStateFactory, &FlangerFactory); +} + + +void ALflanger_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_FLANGER_WAVEFORM: + if(!(val >= AL_FLANGER_MIN_WAVEFORM && val <= AL_FLANGER_MAX_WAVEFORM)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Flanger.Waveform = val; + break; + + case AL_FLANGER_PHASE: + if(!(val >= AL_FLANGER_MIN_PHASE && val <= AL_FLANGER_MAX_PHASE)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Flanger.Phase = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALflanger_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals) +{ + ALflanger_setParami(effect, context, param, vals[0]); +} +void ALflanger_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_FLANGER_RATE: + if(!(val >= AL_FLANGER_MIN_RATE && val <= AL_FLANGER_MAX_RATE)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Flanger.Rate = val; + break; + + case AL_FLANGER_DEPTH: + if(!(val >= AL_FLANGER_MIN_DEPTH && val <= AL_FLANGER_MAX_DEPTH)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Flanger.Depth = val; + break; + + case AL_FLANGER_FEEDBACK: + if(!(val >= AL_FLANGER_MIN_FEEDBACK && val <= AL_FLANGER_MAX_FEEDBACK)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Flanger.Feedback = val; + break; + + case AL_FLANGER_DELAY: + if(!(val >= AL_FLANGER_MIN_DELAY && val <= AL_FLANGER_MAX_DELAY)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Flanger.Delay = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALflanger_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + ALflanger_setParamf(effect, context, param, vals[0]); +} + +void ALflanger_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_FLANGER_WAVEFORM: + *val = props->Flanger.Waveform; + break; + + case AL_FLANGER_PHASE: + *val = props->Flanger.Phase; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALflanger_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals) +{ + ALflanger_getParami(effect, context, param, vals); +} +void ALflanger_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_FLANGER_RATE: + *val = props->Flanger.Rate; + break; + + case AL_FLANGER_DEPTH: + *val = props->Flanger.Depth; + break; + + case AL_FLANGER_FEEDBACK: + *val = props->Flanger.Feedback; + break; + + case AL_FLANGER_DELAY: + *val = props->Flanger.Delay; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALflanger_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals) +{ + ALflanger_getParamf(effect, context, param, vals); +} + +DEFINE_ALEFFECT_VTABLE(ALflanger); diff --git a/Engine/lib/openal-soft/Alc/effects/modulator.c b/Engine/lib/openal-soft/Alc/effects/modulator.c new file mode 100644 index 000000000..247cdf61a --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/modulator.c @@ -0,0 +1,311 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2009 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "alMain.h" +#include "alFilter.h" +#include "alAuxEffectSlot.h" +#include "alError.h" +#include "alu.h" + + +typedef struct ALmodulatorState { + DERIVE_FROM_TYPE(ALeffectState); + + void (*Process)(ALfloat*, const ALfloat*, ALuint, const ALuint, ALuint); + + ALuint index; + ALuint step; + + ALfloat Gain[MAX_EFFECT_CHANNELS][MAX_OUTPUT_CHANNELS]; + + ALfilterState Filter[MAX_EFFECT_CHANNELS]; +} ALmodulatorState; + +static ALvoid ALmodulatorState_Destruct(ALmodulatorState *state); +static ALboolean ALmodulatorState_deviceUpdate(ALmodulatorState *state, ALCdevice *device); +static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props); +static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels); +DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState) + +DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState); + + +#define WAVEFORM_FRACBITS 24 +#define WAVEFORM_FRACONE (1<> (WAVEFORM_FRACBITS - 1)) & 1); +} + +#define DECL_TEMPLATE(func) \ +static void Modulate##func(ALfloat *restrict dst, const ALfloat *restrict src,\ + ALuint index, const ALuint step, ALuint todo) \ +{ \ + ALuint i; \ + for(i = 0;i < todo;i++) \ + { \ + index += step; \ + index &= WAVEFORM_FRACMASK; \ + dst[i] = src[i] * func(index); \ + } \ +} + +DECL_TEMPLATE(Sin) +DECL_TEMPLATE(Saw) +DECL_TEMPLATE(Square) + +#undef DECL_TEMPLATE + + +static void ALmodulatorState_Construct(ALmodulatorState *state) +{ + ALuint i; + + ALeffectState_Construct(STATIC_CAST(ALeffectState, state)); + SET_VTABLE2(ALmodulatorState, ALeffectState, state); + + state->index = 0; + state->step = 1; + + for(i = 0;i < MAX_EFFECT_CHANNELS;i++) + ALfilterState_clear(&state->Filter[i]); +} + +static ALvoid ALmodulatorState_Destruct(ALmodulatorState *state) +{ + ALeffectState_Destruct(STATIC_CAST(ALeffectState,state)); +} + +static ALboolean ALmodulatorState_deviceUpdate(ALmodulatorState *UNUSED(state), ALCdevice *UNUSED(device)) +{ + return AL_TRUE; +} + +static ALvoid ALmodulatorState_update(ALmodulatorState *state, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props) +{ + ALfloat cw, a; + ALuint i; + + if(props->Modulator.Waveform == AL_RING_MODULATOR_SINUSOID) + state->Process = ModulateSin; + else if(props->Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH) + state->Process = ModulateSaw; + else /*if(Slot->Params.EffectProps.Modulator.Waveform == AL_RING_MODULATOR_SQUARE)*/ + state->Process = ModulateSquare; + + state->step = fastf2u(props->Modulator.Frequency*WAVEFORM_FRACONE / + Device->Frequency); + if(state->step == 0) state->step = 1; + + /* Custom filter coeffs, which match the old version instead of a low-shelf. */ + cw = cosf(F_TAU * props->Modulator.HighPassCutoff / Device->Frequency); + a = (2.0f-cw) - sqrtf(powf(2.0f-cw, 2.0f) - 1.0f); + + for(i = 0;i < MAX_EFFECT_CHANNELS;i++) + { + state->Filter[i].a1 = -a; + state->Filter[i].a2 = 0.0f; + state->Filter[i].b0 = a; + state->Filter[i].b1 = -a; + state->Filter[i].b2 = 0.0f; + } + + 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]); +} + +static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + const ALuint step = state->step; + ALuint index = state->index; + ALuint base; + + for(base = 0;base < SamplesToDo;) + { + ALfloat temps[2][128]; + ALuint td = minu(128, SamplesToDo-base); + ALuint i, j, k; + + for(j = 0;j < MAX_EFFECT_CHANNELS;j++) + { + ALfilterState_process(&state->Filter[j], temps[0], &SamplesIn[j][base], td); + state->Process(temps[1], temps[0], index, step, td); + + for(k = 0;k < NumChannels;k++) + { + ALfloat gain = state->Gain[j][k]; + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; + + for(i = 0;i < td;i++) + SamplesOut[k][base+i] += gain * temps[1][i]; + } + } + + for(i = 0;i < td;i++) + { + index += step; + index &= WAVEFORM_FRACMASK; + } + base += td; + } + state->index = index; +} + + +typedef struct ALmodulatorStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALmodulatorStateFactory; + +static ALeffectState *ALmodulatorStateFactory_create(ALmodulatorStateFactory *UNUSED(factory)) +{ + ALmodulatorState *state; + + NEW_OBJ0(state, ALmodulatorState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALmodulatorStateFactory); + +ALeffectStateFactory *ALmodulatorStateFactory_getFactory(void) +{ + static ALmodulatorStateFactory ModulatorFactory = { { GET_VTABLE2(ALmodulatorStateFactory, ALeffectStateFactory) } }; + + return STATIC_CAST(ALeffectStateFactory, &ModulatorFactory); +} + + +void ALmodulator_setParamf(ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_RING_MODULATOR_FREQUENCY: + if(!(val >= AL_RING_MODULATOR_MIN_FREQUENCY && val <= AL_RING_MODULATOR_MAX_FREQUENCY)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Modulator.Frequency = val; + break; + + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: + if(!(val >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && val <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Modulator.HighPassCutoff = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALmodulator_setParamfv(ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + ALmodulator_setParamf(effect, context, param, vals[0]); +} +void ALmodulator_setParami(ALeffect *effect, ALCcontext *context, ALenum param, ALint val) +{ + ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_RING_MODULATOR_FREQUENCY: + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: + ALmodulator_setParamf(effect, context, param, (ALfloat)val); + break; + + case AL_RING_MODULATOR_WAVEFORM: + if(!(val >= AL_RING_MODULATOR_MIN_WAVEFORM && val <= AL_RING_MODULATOR_MAX_WAVEFORM)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + props->Modulator.Waveform = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALmodulator_setParamiv(ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals) +{ + ALmodulator_setParami(effect, context, param, vals[0]); +} + +void ALmodulator_getParami(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_RING_MODULATOR_FREQUENCY: + *val = (ALint)props->Modulator.Frequency; + break; + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: + *val = (ALint)props->Modulator.HighPassCutoff; + break; + case AL_RING_MODULATOR_WAVEFORM: + *val = props->Modulator.Waveform; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALmodulator_getParamiv(const ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals) +{ + ALmodulator_getParami(effect, context, param, vals); +} +void ALmodulator_getParamf(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val) +{ + const ALeffectProps *props = &effect->Props; + switch(param) + { + case AL_RING_MODULATOR_FREQUENCY: + *val = props->Modulator.Frequency; + break; + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: + *val = props->Modulator.HighPassCutoff; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALmodulator_getParamfv(const ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals) +{ + ALmodulator_getParamf(effect, context, param, vals); +} + +DEFINE_ALEFFECT_VTABLE(ALmodulator); diff --git a/Engine/lib/openal-soft/Alc/effects/null.c b/Engine/lib/openal-soft/Alc/effects/null.c new file mode 100644 index 000000000..bff00b567 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/null.c @@ -0,0 +1,179 @@ +#include "config.h" + +#include + +#include "AL/al.h" +#include "AL/alc.h" +#include "alMain.h" +#include "alAuxEffectSlot.h" +#include "alError.h" + + +typedef struct ALnullState { + DERIVE_FROM_TYPE(ALeffectState); +} ALnullState; + +/* Forward-declare "virtual" functions to define the vtable with. */ +static ALvoid ALnullState_Destruct(ALnullState *state); +static ALboolean ALnullState_deviceUpdate(ALnullState *state, ALCdevice *device); +static ALvoid ALnullState_update(ALnullState *state, const ALCdevice *device, const ALeffectslot *slot, const ALeffectProps *props); +static ALvoid ALnullState_process(ALnullState *state, ALuint samplesToDo, const ALfloatBUFFERSIZE*restrict samplesIn, ALfloatBUFFERSIZE*restrict samplesOut, ALuint NumChannels); +static void *ALnullState_New(size_t size); +static void ALnullState_Delete(void *ptr); + +/* Define the ALeffectState vtable for this type. */ +DEFINE_ALEFFECTSTATE_VTABLE(ALnullState); + + +/* This constructs the effect state. It's called when the object is first + * created. Make sure to call the parent Construct function first, and set the + * vtable! + */ +static void ALnullState_Construct(ALnullState *state) +{ + ALeffectState_Construct(STATIC_CAST(ALeffectState, state)); + SET_VTABLE2(ALnullState, ALeffectState, state); +} + +/* This destructs (not free!) the effect state. It's called only when the + * effect slot is no longer used. Make sure to call the parent Destruct + * function before returning! + */ +static ALvoid ALnullState_Destruct(ALnullState *state) +{ + ALeffectState_Destruct(STATIC_CAST(ALeffectState,state)); +} + +/* This updates the device-dependant effect state. This is called on + * initialization and any time the device parameters (eg. playback frequency, + * format) have been changed. + */ +static ALboolean ALnullState_deviceUpdate(ALnullState* UNUSED(state), ALCdevice* UNUSED(device)) +{ + return AL_TRUE; +} + +/* This updates the effect state. This is called any time the effect is + * (re)loaded into a slot. + */ +static ALvoid ALnullState_update(ALnullState* UNUSED(state), const ALCdevice* UNUSED(device), const ALeffectslot* UNUSED(slot), const ALeffectProps* UNUSED(props)) +{ +} + +/* This processes the effect state, for the given number of samples from the + * input to the output buffer. The result should be added to the output buffer, + * not replace it. + */ +static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALuint UNUSED(samplesToDo), const ALfloatBUFFERSIZE*restrict UNUSED(samplesIn), ALfloatBUFFERSIZE*restrict UNUSED(samplesOut), ALuint UNUSED(NumChannels)) +{ +} + +/* This allocates memory to store the object, before it gets constructed. + * DECLARE_DEFAULT_ALLOCATORS can be used to declare a default method. + */ +static void *ALnullState_New(size_t size) +{ + return al_malloc(16, size); +} + +/* This frees the memory used by the object, after it has been destructed. + * DECLARE_DEFAULT_ALLOCATORS can be used to declare a default method. + */ +static void ALnullState_Delete(void *ptr) +{ + al_free(ptr); +} + + +typedef struct ALnullStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALnullStateFactory; + +/* Creates ALeffectState objects of the appropriate type. */ +ALeffectState *ALnullStateFactory_create(ALnullStateFactory *UNUSED(factory)) +{ + ALnullState *state; + + NEW_OBJ0(state, ALnullState)(); + if(!state) return NULL; + + return STATIC_CAST(ALeffectState, state); +} + +/* Define the ALeffectStateFactory vtable for this type. */ +DEFINE_ALEFFECTSTATEFACTORY_VTABLE(ALnullStateFactory); + +ALeffectStateFactory *ALnullStateFactory_getFactory(void) +{ + static ALnullStateFactory NullFactory = { { GET_VTABLE2(ALnullStateFactory, ALeffectStateFactory) } }; + return STATIC_CAST(ALeffectStateFactory, &NullFactory); +} + + +void ALnull_setParami(ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALint UNUSED(val)) +{ + switch(param) + { + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALnull_setParamiv(ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, const ALint* UNUSED(vals)) +{ + switch(param) + { + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALnull_setParamf(ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALfloat UNUSED(val)) +{ + switch(param) + { + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALnull_setParamfv(ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, const ALfloat* UNUSED(vals)) +{ + switch(param) + { + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} + +void ALnull_getParami(const ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALint* UNUSED(val)) +{ + switch(param) + { + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALnull_getParamiv(const ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALint* UNUSED(vals)) +{ + switch(param) + { + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALnull_getParamf(const ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALfloat* UNUSED(val)) +{ + switch(param) + { + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +void ALnull_getParamfv(const ALeffect* UNUSED(effect), ALCcontext *context, ALenum param, ALfloat* UNUSED(vals)) +{ + switch(param) + { + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} + +DEFINE_ALEFFECT_VTABLE(ALnull); diff --git a/Engine/lib/openal-soft/Alc/effects/reverb.c b/Engine/lib/openal-soft/Alc/effects/reverb.c new file mode 100644 index 000000000..f2d5b7189 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/effects/reverb.c @@ -0,0 +1,1994 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include +#include + +#include "alMain.h" +#include "alu.h" +#include "alAuxEffectSlot.h" +#include "alEffect.h" +#include "alFilter.h" +#include "alError.h" +#include "mixer_defs.h" + + +/* This is the maximum number of samples processed for each inner loop + * iteration. */ +#define MAX_UPDATE_SAMPLES 256 + + +static MixerFunc MixSamples = Mix_C; +static RowMixerFunc MixRowSamples = MixRow_C; + +static alonce_flag mixfunc_inited = AL_ONCE_FLAG_INIT; +static void init_mixfunc(void) +{ + MixSamples = SelectMixer(); + MixRowSamples = SelectRowMixer(); +} + + +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 + struct { + ALfilterState Lp; + ALfilterState Hp; // EAX only + } Filter[4]; + + struct { + // Modulator delay line. + DelayLine Delay[4]; + + // 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; // EAX only + + /* Core delay line (early reflections and late reverb tap from this). */ + DelayLine Delay; + /* The tap points for the initial delay. First set go to early + * reflections, second to late reverb. + */ + ALuint EarlyDelayTap[4]; + ALuint LateDelayTap[4]; + + struct { + // 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. + ALfloat CurrentGain[4][MAX_OUTPUT_CHANNELS]; + ALfloat PanGain[4][MAX_OUTPUT_CHANNELS]; + } Early; + + 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. + struct { + ALfloat Coeff; + DelayLine Delay; + ALuint Offset; + } Ap[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. + struct { + ALfloat Sample; + ALfloat Coeff; + } Lp[4]; + + // The gain for each output channel based on 3D panning. + ALfloat CurrentGain[4][MAX_OUTPUT_CHANNELS]; + ALfloat PanGain[4][MAX_OUTPUT_CHANNELS]; + } Late; + + struct { + // Attenuation to compensate for the modal density and decay rate of + // the echo line. + ALfloat DensityGain; + + // Echo delay and all-pass lines. + struct { + DelayLine Feedback; + DelayLine Ap; + } Delay[4]; + + ALfloat Coeff; + ALfloat ApFeedCoeff; + ALfloat ApCoeff; + + ALuint Offset; + ALuint ApOffset; + + // The echo line is 1-pole low-pass filtered. + ALfloat LpCoeff; + ALfloat LpSample[4]; + + // Echo mixing coefficient. + ALfloat MixCoeff; + } Echo; // EAX only + + // The current read offset for all delay lines. + ALuint Offset; + + /* Temporary storage used when processing. */ + alignas(16) ALfloat AFormatSamples[4][MAX_UPDATE_SAMPLES]; + alignas(16) ALfloat ReverbSamples[4][MAX_UPDATE_SAMPLES]; + alignas(16) ALfloat EarlySamples[4][MAX_UPDATE_SAMPLES]; +} ALreverbState; + +static ALvoid ALreverbState_Destruct(ALreverbState *State); +static ALboolean ALreverbState_deviceUpdate(ALreverbState *State, ALCdevice *Device); +static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props); +static ALvoid ALreverbState_process(ALreverbState *State, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels); +DECLARE_DEFAULT_ALLOCATORS(ALreverbState) + +DEFINE_ALEFFECTSTATE_VTABLE(ALreverbState); + + +static void ALreverbState_Construct(ALreverbState *state) +{ + ALuint index, l; + + ALeffectState_Construct(STATIC_CAST(ALeffectState, state)); + SET_VTABLE2(ALreverbState, ALeffectState, state); + + state->IsEax = AL_FALSE; + + state->TotalSamples = 0; + state->SampleBuffer = NULL; + + for(index = 0;index < 4;index++) + { + ALfilterState_clear(&state->Filter[index].Lp); + ALfilterState_clear(&state->Filter[index].Hp); + + state->Mod.Delay[index].Mask = 0; + state->Mod.Delay[index].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; + for(index = 0;index < 4;index++) + state->EarlyDelayTap[index] = 0; + for(index = 0;index < 4;index++) + state->LateDelayTap[index] = 0; + + 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->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.Ap[index].Coeff = 0.0f; + state->Late.Ap[index].Delay.Mask = 0; + state->Late.Ap[index].Delay.Line = NULL; + state->Late.Ap[index].Offset = 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.Lp[index].Sample = 0.0f; + state->Late.Lp[index].Coeff = 0.0f; + } + + for(l = 0;l < 4;l++) + { + for(index = 0;index < MAX_OUTPUT_CHANNELS;index++) + { + state->Early.CurrentGain[l][index] = 0.0f; + state->Early.PanGain[l][index] = 0.0f; + state->Late.CurrentGain[l][index] = 0.0f; + state->Late.PanGain[l][index] = 0.0f; + } + } + + state->Echo.DensityGain = 0.0f; + for(l = 0;l < 4;l++) + { + state->Echo.Delay[l].Feedback.Mask = 0; + state->Echo.Delay[l].Feedback.Line = NULL; + state->Echo.Delay[l].Ap.Mask = 0; + state->Echo.Delay[l].Ap.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; + for(l = 0;l < 4;l++) + state->Echo.LpSample[l] = 0.0f; + state->Echo.MixCoeff = 0.0f; + + state->Offset = 0; +} + +static ALvoid ALreverbState_Destruct(ALreverbState *State) +{ + al_free(State->SampleBuffer); + State->SampleBuffer = NULL; + + ALeffectState_Destruct(STATIC_CAST(ALeffectState,State)); +} + +/* 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 (no + * high-pass, modulation, or echo). + */ +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 early reflections and late reverb are decorrelated between + * four channels. Their timings are dependent on a fraction and multiplier. See + * the UpdateDelayLine() 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 cyclical delay lines. +static const ALfloat LATE_LINE_LENGTH[4] = +{ + 0.0211f, 0.0311f, 0.0461f, 0.0680f +}; + +// 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 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; + + +#if defined(_WIN32) && !defined (_M_X64) && !defined(_M_ARM) +/* HACK: Workaround for a modff bug in 32-bit Windows, which attempts to write + * a 64-bit double to the 32-bit float parameter. + */ +static inline float hack_modff(float x, float *y) +{ + double di; + double df = modf((double)x, &di); + *y = (float)di; + return (float)df; +} +#define modff hack_modff +#endif + + +/************************************** + * Device Update * + **************************************/ + +// Given the allocated sample buffer, this function updates each delay line +// offset. +static inline ALvoid RealizeLineOffset(ALfloat *sampleBuffer, DelayLine *Delay) +{ + Delay->Line = &sampleBuffer[(ptrdiff_t)Delay->Line]; +} + +// Calculate the length of a delay line and store its mask and offset. +static ALuint CalcLineLength(ALfloat length, ptrdiff_t offset, ALuint frequency, ALuint extra, 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 = fastf2u(length*frequency) + extra; + samples = NextPowerOf2(samples + 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; + + // 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); + for(index = 0;index < 4;index++) + totalSamples += CalcLineLength(length, totalSamples, frequency, 1, + &State->Mod.Delay[index]); + + /* The initial delay is the sum of the reflections and late reverb delays. + * The decorrelator length is calculated from the lowest reverb density (a + * parameter value of 1). This must include space for storing a loop + * update. + */ + length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY + + AL_EAXREVERB_MAX_LATE_REVERB_DELAY; + length += (DECO_FRACTION * DECO_MULTIPLIER * DECO_MULTIPLIER) * + LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER); + /* Multiply length by 4, since we're storing 4 interleaved channels in the + * main delay line. + */ + totalSamples += CalcLineLength(length*4, totalSamples, frequency, + MAX_UPDATE_SAMPLES*4, &State->Delay); + + // The early reflection lines. + for(index = 0;index < 4;index++) + totalSamples += CalcLineLength(EARLY_LINE_LENGTH[index], totalSamples, + frequency, 0, &State->Early.Delay[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, 0, + &State->Late.Delay[index]); + } + + // The late all-pass lines. + for(index = 0;index < 4;index++) + totalSamples += CalcLineLength(ALLPASS_LINE_LENGTH[index], totalSamples, + frequency, 0, &State->Late.Ap[index].Delay); + + // The echo all-pass and delay lines. + for(index = 0;index < 4;index++) + { + totalSamples += CalcLineLength(ECHO_ALLPASS_LENGTH, totalSamples, + frequency, 0, &State->Echo.Delay[index].Ap); + totalSamples += CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME, totalSamples, + frequency, 0, &State->Echo.Delay[index].Feedback); + } + + if(totalSamples != State->TotalSamples) + { + ALfloat *newBuffer; + + TRACE("New reverb buffer length: %u samples\n", totalSamples); + newBuffer = al_calloc(16, sizeof(ALfloat) * totalSamples); + if(!newBuffer) return AL_FALSE; + + al_free(State->SampleBuffer); + State->SampleBuffer = newBuffer; + State->TotalSamples = totalSamples; + } + + // Update all delays to reflect the new sample buffer. + RealizeLineOffset(State->SampleBuffer, &State->Delay); + for(index = 0;index < 4;index++) + { + RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay[index]); + + RealizeLineOffset(State->SampleBuffer, &State->Early.Delay[index]); + + RealizeLineOffset(State->SampleBuffer, &State->Late.Ap[index].Delay); + RealizeLineOffset(State->SampleBuffer, &State->Late.Delay[index]); + + RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay[index].Ap); + RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay[index].Feedback); + } + + // 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.Ap[index].Offset = 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; +} + +/************************************** + * Effect Update * + **************************************/ + +// 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 main effect delay line. +static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALfloat density, ALuint frequency, ALreverbState *State) +{ + ALfloat length; + ALuint i; + + /* The early reflections and late reverb inputs are decorrelated to provide + * time-varying reflections, smooth out the reverb tail, and reduce harsh + * echoes. 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-1))) smallest_delay + * + * for index = 1...max_lines + */ + State->EarlyDelayTap[0] = fastf2u(earlyDelay * frequency); + for(i = 1;i < 4;i++) + { + length = (DECO_FRACTION * powf(DECO_MULTIPLIER, (ALfloat)i-1.0f)) * + EARLY_LINE_LENGTH[0]; + State->EarlyDelayTap[i] = fastf2u(length * frequency) + State->EarlyDelayTap[0]; + } + + State->LateDelayTap[0] = fastf2u((earlyDelay + lateDelay) * frequency); + for(i = 1;i < 4;i++) + { + length = (DECO_FRACTION * powf(DECO_MULTIPLIER, (ALfloat)i-1.0f)) * + LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER)); + State->LateDelayTap[i] = fastf2u(length * frequency) + State->LateDelayTap[0]; + } +} + +// Update the early reflections mix and line coefficients. +static ALvoid UpdateEarlyLines(ALfloat lateDelay, ALreverbState *State) +{ + ALuint index; + + // 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 late reverb mix, line lengths, and line coefficients. +static ALvoid UpdateLateLines(ALfloat xMix, ALfloat density, ALfloat decayTime, ALfloat diffusion, ALfloat echoDepth, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALreverbState *State) +{ + ALfloat length; + ALuint index; + + /* Calculate the late reverb gain. 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. Also 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->Late.Gain = xMix * (1.0f - (echoDepth*0.5f*(1.0f - diffusion))); + + /* 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); + /* To account for each channel being a discrete input, also multiply by + * sqrt(num_channels). + */ + State->Late.DensityGain = 2.0f * 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.Ap[index].Coeff = 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.Lp[index].Coeff = 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 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 coefficient. This is applied to the output mix + * only, not the feedback. + */ + State->Echo.MixCoeff = echoDepth; +} + +/* Creates a transform matrix given a reverb vector. This works by creating a + * Z-focus transform, then a rotate transform around X, then Y, to place the + * focal point in the direction of the vector, using the vector length as a + * focus strength. + * + * This isn't technically correct since the vector is supposed to define the + * aperture and not rotate the perceived soundfield, but in practice it's + * probably good enough. + */ +static aluMatrixf GetTransformFromVector(const ALfloat *vec) +{ + aluMatrixf zfocus, xrot, yrot; + aluMatrixf tmp1, tmp2; + ALfloat length; + ALfloat sa, a; + + length = sqrtf(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); + + /* Define a Z-focus (X in Ambisonics) transform, given the panning vector + * length. + */ + sa = sinf(minf(length, 1.0f) * (F_PI/4.0f)); + aluMatrixfSet(&zfocus, + 1.0f/(1.0f+sa), 0.0f, 0.0f, (sa/(1.0f+sa))/1.732050808f, + 0.0f, sqrtf((1.0f-sa)/(1.0f+sa)), 0.0f, 0.0f, + 0.0f, 0.0f, sqrtf((1.0f-sa)/(1.0f+sa)), 0.0f, + (sa/(1.0f+sa))*1.732050808f, 0.0f, 0.0f, 1.0f/(1.0f+sa) + ); + + /* Define rotation around X (Y in Ambisonics) */ + a = atan2f(vec[1], sqrtf(vec[0]*vec[0] + vec[2]*vec[2])); + aluMatrixfSet(&xrot, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, cosf(a), sinf(a), + 0.0f, 0.0f, -sinf(a), cosf(a) + ); + + /* Define rotation around Y (Z in Ambisonics). NOTE: EFX's reverb vectors + * use a right-handled coordinate system, compared to the rest of OpenAL + * which uses left-handed. This is fixed by negating Z, however it would + * need to also be negated to get a proper Ambisonics angle, thus + * cancelling it out. + */ + a = atan2f(-vec[0], vec[2]); + aluMatrixfSet(&yrot, + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, cosf(a), 0.0f, sinf(a), + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, -sinf(a), 0.0f, cosf(a) + ); + +#define MATRIX_MULT(_res, _m1, _m2) do { \ + int row, col; \ + for(col = 0;col < 4;col++) \ + { \ + for(row = 0;row < 4;row++) \ + _res.m[row][col] = _m1.m[row][0]*_m2.m[0][col] + _m1.m[row][1]*_m2.m[1][col] + \ + _m1.m[row][2]*_m2.m[2][col] + _m1.m[row][3]*_m2.m[3][col]; \ + } \ +} while(0) + /* Define a matrix that first focuses on Z, then rotates around X then Y to + * focus the output in the direction of the vector. + */ + MATRIX_MULT(tmp1, xrot, zfocus); + MATRIX_MULT(tmp2, yrot, tmp1); +#undef MATRIX_MULT + + return tmp2; +} + +// Update the early and late 3D panning gains. +static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALfloat EarlyGain, ALfloat LateGain, ALreverbState *State) +{ + /* Converts early reflections A-Format to B-Format (transposed). */ + static const aluMatrixf EarlyA2B = {{ + { 0.8660254038f, 0.8660254038f, 0.8660254038f, 0.8660254038f }, + { 0.8660254038f, 0.8660254038f, -0.8660254038f, -0.8660254038f }, + { 0.8660254038f, -0.8660254038f, 0.8660254038f, -0.8660254038f }, + { 0.8660254038f, -0.8660254038f, -0.8660254038f, 0.8660254038f } + }}; + /* Converts late reverb A-Format to B-Format (transposed). */ + static const aluMatrixf LateA2B = {{ + { 0.8660254038f, -0.8660254038f, 0.8660254038f, 0.8660254038f }, + { 0.8660254038f, -0.8660254038f, -0.8660254038f, -0.8660254038f }, + { 0.8660254038f, 0.8660254038f, 0.8660254038f, -0.8660254038f }, + { 0.8660254038f, 0.8660254038f, -0.8660254038f, 0.8660254038f } +/* { 0.8660254038f, 1.2247448714f, 0.0f, 0.8660254038f }, + { 0.8660254038f, 0.0f, -1.2247448714f, -0.8660254038f }, + { 0.8660254038f, 0.0f, 1.2247448714f, -0.8660254038f }, + { 0.8660254038f, -1.2247448714f, 0.0f, 0.8660254038f }*/ + }}; + aluMatrixf transform, rot; + ALuint i; + + STATIC_CAST(ALeffectState,State)->OutBuffer = Device->FOAOut.Buffer; + STATIC_CAST(ALeffectState,State)->OutChannels = Device->FOAOut.NumChannels; + + /* Note: Both _m2 and _res are transposed. */ +#define MATRIX_MULT(_res, _m1, _m2) do { \ + int row, col; \ + for(col = 0;col < 4;col++) \ + { \ + for(row = 0;row < 4;row++) \ + _res.m[col][row] = _m1.m[row][0]*_m2.m[col][0] + _m1.m[row][1]*_m2.m[col][1] + \ + _m1.m[row][2]*_m2.m[col][2] + _m1.m[row][3]*_m2.m[col][3]; \ + } \ +} while(0) + /* Create a matrix that first converts A-Format to B-Format, then rotates + * the B-Format soundfield according to the panning vector. + */ + rot = GetTransformFromVector(ReflectionsPan); + MATRIX_MULT(transform, rot, EarlyA2B); + memset(&State->Early.PanGain, 0, sizeof(State->Early.PanGain)); + for(i = 0;i < MAX_EFFECT_CHANNELS;i++) + ComputeFirstOrderGains(Device->FOAOut, transform.m[i], Gain*EarlyGain, State->Early.PanGain[i]); + + rot = GetTransformFromVector(LateReverbPan); + MATRIX_MULT(transform, rot, LateA2B); + memset(&State->Late.PanGain, 0, sizeof(State->Late.PanGain)); + for(i = 0;i < MAX_EFFECT_CHANNELS;i++) + ComputeFirstOrderGains(Device->FOAOut, transform.m[i], Gain*LateGain, State->Late.PanGain[i]); +#undef MATRIX_MULT +} + +static ALvoid ALreverbState_update(ALreverbState *State, const ALCdevice *Device, const ALeffectslot *Slot, const ALeffectProps *props) +{ + ALuint frequency = Device->Frequency; + ALfloat lfscale, hfscale, hfRatio; + ALfloat gain, gainlf, gainhf; + ALfloat cw, x, y; + ALuint i; + + if(Slot->Params.EffectType == AL_EFFECT_EAXREVERB && !EmulateEAXReverb) + State->IsEax = AL_TRUE; + else if(Slot->Params.EffectType == AL_EFFECT_REVERB || EmulateEAXReverb) + State->IsEax = AL_FALSE; + + // Calculate the master filters + hfscale = props->Reverb.HFReference / frequency; + gainhf = maxf(props->Reverb.GainHF, 0.0001f); + ALfilterState_setParams(&State->Filter[0].Lp, ALfilterType_HighShelf, + gainhf, hfscale, calc_rcpQ_from_slope(gainhf, 0.75f)); + lfscale = props->Reverb.LFReference / frequency; + gainlf = maxf(props->Reverb.GainLF, 0.0001f); + ALfilterState_setParams(&State->Filter[0].Hp, ALfilterType_LowShelf, + gainlf, lfscale, calc_rcpQ_from_slope(gainlf, 0.75f)); + for(i = 1;i < 4;i++) + { + State->Filter[i].Lp.a1 = State->Filter[0].Lp.a1; + State->Filter[i].Lp.a2 = State->Filter[0].Lp.a2; + State->Filter[i].Lp.b0 = State->Filter[0].Lp.b0; + State->Filter[i].Lp.b1 = State->Filter[0].Lp.b1; + State->Filter[i].Lp.b2 = State->Filter[0].Lp.b2; + + State->Filter[i].Hp.a1 = State->Filter[0].Hp.a1; + State->Filter[i].Hp.a2 = State->Filter[0].Hp.a2; + State->Filter[i].Hp.b0 = State->Filter[0].Hp.b0; + State->Filter[i].Hp.b1 = State->Filter[0].Hp.b1; + State->Filter[i].Hp.b2 = State->Filter[0].Hp.b2; + } + + // Update the modulator line. + UpdateModulator(props->Reverb.ModulationTime, props->Reverb.ModulationDepth, + frequency, State); + + // Update the main effect delay. + UpdateDelayLine(props->Reverb.ReflectionsDelay, props->Reverb.LateReverbDelay, + props->Reverb.Density, frequency, State); + + // Update the early lines. + UpdateEarlyLines(props->Reverb.LateReverbDelay, State); + + // Get the mixing matrix coefficients (x and y). + CalcMatrixCoeffs(props->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 = props->Reverb.DecayHFRatio; + if(props->Reverb.DecayHFLimit && props->Reverb.AirAbsorptionGainHF < 1.0f) + hfRatio = CalcLimitedHfRatio(hfRatio, props->Reverb.AirAbsorptionGainHF, + props->Reverb.DecayTime); + + cw = cosf(F_TAU * hfscale); + // Update the late lines. + UpdateLateLines(x, props->Reverb.Density, props->Reverb.DecayTime, + props->Reverb.Diffusion, props->Reverb.EchoDepth, + hfRatio, cw, frequency, State); + + // Update the echo line. + UpdateEchoLine(props->Reverb.EchoTime, props->Reverb.DecayTime, + props->Reverb.Diffusion, props->Reverb.EchoDepth, + hfRatio, cw, frequency, State); + + gain = props->Reverb.Gain * Slot->Params.Gain * ReverbBoost; + // Update early and late 3D panning. + Update3DPanning(Device, props->Reverb.ReflectionsPan, + props->Reverb.LateReverbPan, gain, + props->Reverb.ReflectionsGain, + props->Reverb.LateReverbGain, State); +} + + +/************************************** + * Effect Processing * + **************************************/ + +// 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; +} + +static inline ALfloat DelayLineInOut(DelayLine *Delay, ALuint offset, ALuint outoffset, ALfloat in) +{ + Delay->Line[offset&Delay->Mask] = in; + return Delay->Line[(offset-outoffset)&Delay->Mask]; +} + +static void CalcModulationDelays(ALreverbState *State, ALfloat *restrict delays, ALuint todo) +{ + ALfloat sinus, range; + ALuint index, i; + + index = State->Mod.Index; + range = State->Mod.Filter; + for(i = 0;i < todo;i++) + { + /* 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_TAU * index / State->Mod.Range); + + /* Step the modulation index forward, keeping it bound to its range. */ + index = (index+1) % 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. + */ + range = lerp(range, State->Mod.Depth, State->Mod.Coeff); + + /* Calculate the read offset with fraction. */ + delays[i] = range*sinus; + } + State->Mod.Index = index; + State->Mod.Filter = range; +} + +// Given some input samples, this function produces modulation for the late +// reverb. +static void EAXModulation(DelayLine *ModDelay, ALuint offset, const ALfloat *restrict delays, ALfloat*restrict dst, const ALfloat*restrict src, ALuint todo) +{ + ALfloat frac, fdelay; + ALfloat out0, out1; + ALuint delay, i; + + for(i = 0;i < todo;i++) + { + /* Separate the integer offset and fraction between it and the next + * sample. + */ + frac = modff(delays[i], &fdelay); + delay = fastf2u(fdelay); + + /* Add the incoming sample to the delay line, and get the two samples + * crossed by the offset delay. + */ + out0 = DelayLineInOut(ModDelay, offset, delay, src[i]); + out1 = DelayLineOut(ModDelay, offset - delay - 1); + offset++; + + /* The output is obtained by linearly interpolating the two samples + * that were acquired above. + */ + dst[i] = lerp(out0, out1, frac); + } +} + +/* Given some input samples from the main delay line, this function produces + * four-channel outputs for the early reflections. + */ +static ALvoid EarlyReflection(ALreverbState *State, ALuint todo, ALfloat (*restrict out)[MAX_UPDATE_SAMPLES]) +{ + ALfloat d[4], v, f[4]; + ALuint i; + + for(i = 0;i < todo;i++) + { + ALuint offset = State->Offset+i; + + /* Obtain the first reflection samples from the main delay line. */ + f[0] = DelayLineOut(&State->Delay, (offset-State->EarlyDelayTap[0])*4 + 0); + f[1] = DelayLineOut(&State->Delay, (offset-State->EarlyDelayTap[1])*4 + 1); + f[2] = DelayLineOut(&State->Delay, (offset-State->EarlyDelayTap[2])*4 + 2); + f[3] = DelayLineOut(&State->Delay, (offset-State->EarlyDelayTap[3])*4 + 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 = (f[0] + f[1] + f[2] + f[3]) * 0.5f; + + /* Calculate the feed values for the early delay lines. */ + d[0] = v - f[0]; + d[1] = v - f[1]; + d[2] = v - f[2]; + d[3] = v - f[3]; + + /* Feed the early delay lines, and load the delayed results. */ + d[0] = DelayLineInOut(&State->Early.Delay[0], offset, State->Early.Offset[0], d[0]); + d[1] = DelayLineInOut(&State->Early.Delay[1], offset, State->Early.Offset[1], d[1]); + d[2] = DelayLineInOut(&State->Early.Delay[2], offset, State->Early.Offset[2], d[2]); + d[3] = DelayLineInOut(&State->Early.Delay[3], offset, State->Early.Offset[3], d[3]); + + /* Output the initial reflection taps and the results of the delayed + * and decayed junction for all four channels. + */ + out[0][i] = f[0] + d[0]*State->Early.Coeff[0]; + out[1][i] = f[1] + d[1]*State->Early.Coeff[1]; + out[2][i] = f[2] + d[2]*State->Early.Coeff[2]; + out[3][i] = f[3] + d[3]*State->Early.Coeff[3]; + } +} + +// 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; +} + +// All-pass input/output routine for late reverb. +static inline ALfloat LateAllPassInOut(ALreverbState *State, ALuint offset, ALuint index, ALfloat in) +{ + return AllpassInOut(&State->Late.Ap[index].Delay, + offset - State->Late.Ap[index].Offset, + offset, in, State->Late.ApFeedCoeff, + State->Late.Ap[index].Coeff); +} + +// Low-pass filter input/output routine for late reverb. +static inline ALfloat LateLowPassInOut(ALreverbState *State, ALuint index, ALfloat in) +{ + in = lerp(in, State->Late.Lp[index].Sample, State->Late.Lp[index].Coeff); + State->Late.Lp[index].Sample = in; + return in; +} + +// Given four decorrelated input samples, this function produces four-channel +// output for the late reverb. +static ALvoid LateReverb(ALreverbState *State, ALuint todo, ALfloat (*restrict out)[MAX_UPDATE_SAMPLES]) +{ + ALfloat d[4], f[4]; + ALuint offset; + ALuint base, i; + + offset = State->Offset; + for(base = 0;base < todo;) + { + ALfloat tmp[MAX_UPDATE_SAMPLES/4][4]; + ALuint tmp_todo = minu(todo, MAX_UPDATE_SAMPLES/4); + + for(i = 0;i < tmp_todo;i++) + { + /* Obtain four decorrelated input samples. */ + f[0] = DelayLineOut(&State->Delay, (offset-State->LateDelayTap[0])*4 + 0) * State->Late.DensityGain; + f[1] = DelayLineOut(&State->Delay, (offset-State->LateDelayTap[1])*4 + 1) * State->Late.DensityGain; + f[2] = DelayLineOut(&State->Delay, (offset-State->LateDelayTap[2])*4 + 2) * State->Late.DensityGain; + f[3] = DelayLineOut(&State->Delay, (offset-State->LateDelayTap[3])*4 + 3) * State->Late.DensityGain; + + /* Add the decayed results of the cyclical delay lines, then pass + * the results through the low-pass filters. + */ + f[0] += DelayLineOut(&State->Late.Delay[0], offset-State->Late.Offset[0]) * State->Late.Coeff[0]; + f[1] += DelayLineOut(&State->Late.Delay[1], offset-State->Late.Offset[1]) * State->Late.Coeff[1]; + f[2] += DelayLineOut(&State->Late.Delay[2], offset-State->Late.Offset[2]) * State->Late.Coeff[2]; + f[3] += DelayLineOut(&State->Late.Delay[3], offset-State->Late.Offset[3]) * State->Late.Coeff[3]; + + /* This is where the feed-back cycles from line 0 to 3 to 1 to 2 + * and back to 0. + */ + d[0] = LateLowPassInOut(State, 2, f[2]); + d[1] = LateLowPassInOut(State, 3, f[3]); + d[2] = LateLowPassInOut(State, 1, f[1]); + d[3] = LateLowPassInOut(State, 0, f[0]); + + /* 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, offset, 0, d[0]); + d[1] = LateAllPassInOut(State, offset, 1, d[1]); + d[2] = LateAllPassInOut(State, offset, 2, d[2]); + d[3] = LateAllPassInOut(State, offset, 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] )); + + /* Re-feed the cyclical delay lines. */ + DelayLineIn(&State->Late.Delay[0], offset, f[0]); + DelayLineIn(&State->Late.Delay[1], offset, f[1]); + DelayLineIn(&State->Late.Delay[2], offset, f[2]); + DelayLineIn(&State->Late.Delay[3], offset, f[3]); + offset++; + + /* Output the results of the matrix for all four channels, + * attenuated by the late reverb gain (which is attenuated by the + * 'x' mix coefficient). + */ + tmp[i][0] = State->Late.Gain * f[0]; + tmp[i][1] = State->Late.Gain * f[1]; + tmp[i][2] = State->Late.Gain * f[2]; + tmp[i][3] = State->Late.Gain * f[3]; + } + + /* Deinterlace to output */ + for(i = 0;i < tmp_todo;i++) out[0][base+i] = tmp[i][0]; + for(i = 0;i < tmp_todo;i++) out[1][base+i] = tmp[i][1]; + for(i = 0;i < tmp_todo;i++) out[2][base+i] = tmp[i][2]; + for(i = 0;i < tmp_todo;i++) out[3][base+i] = tmp[i][3]; + + base += tmp_todo; + } +} + +// Given an input sample, this function mixes echo into the four-channel late +// reverb. +static ALvoid EAXEcho(ALreverbState *State, ALuint todo, ALfloat (*restrict late)[MAX_UPDATE_SAMPLES]) +{ + ALfloat feed; + ALuint offset; + ALuint c, i; + + for(c = 0;c < 4;c++) + { + offset = State->Offset; + for(i = 0;i < todo;i++) + { + // Get the latest attenuated echo sample for output. + feed = DelayLineOut(&State->Echo.Delay[c].Feedback, offset-State->Echo.Offset) * + State->Echo.Coeff; + + // Write the output. + late[c][i] += State->Echo.MixCoeff * feed; + + // Mix the energy-attenuated input with the output and pass it through + // the echo low-pass filter. + feed += DelayLineOut(&State->Delay, (offset-State->LateDelayTap[0])*4 + c) * + State->Echo.DensityGain; + feed = lerp(feed, State->Echo.LpSample[c], State->Echo.LpCoeff); + State->Echo.LpSample[c] = feed; + + // Then the echo all-pass filter. + feed = AllpassInOut(&State->Echo.Delay[c].Ap, offset-State->Echo.ApOffset, + offset, feed, State->Echo.ApFeedCoeff, + State->Echo.ApCoeff); + + // Feed the delay with the mixed and filtered sample. + DelayLineIn(&State->Echo.Delay[c].Feedback, offset, feed); + offset++; + } + } +} + +// Perform the non-EAX reverb pass on a given input sample, resulting in +// four-channel output. +static ALvoid VerbPass(ALreverbState *State, ALuint todo, ALfloat (*restrict input)[MAX_UPDATE_SAMPLES], ALfloat (*restrict early)[MAX_UPDATE_SAMPLES], ALfloat (*restrict late)[MAX_UPDATE_SAMPLES]) +{ + ALuint i, c; + + for(c = 0;c < 4;c++) + { + /* Low-pass filter the incoming samples (use the early buffer as temp + * storage). + */ + ALfilterState_process(&State->Filter[c].Lp, &early[0][0], input[c], todo); + for(i = 0;i < todo;i++) + DelayLineIn(&State->Delay, (State->Offset+i)*4 + c, early[0][i]); + } + + // Calculate the early reflection from the first delay tap. + EarlyReflection(State, todo, early); + + // Calculate the late reverb from the decorrelator taps. + LateReverb(State, todo, late); + + // Step all delays forward one sample. + State->Offset += todo; +} + +// Perform the EAX reverb pass on a given input sample, resulting in four- +// channel output. +static ALvoid EAXVerbPass(ALreverbState *State, ALuint todo, ALfloat (*restrict input)[MAX_UPDATE_SAMPLES], ALfloat (*restrict early)[MAX_UPDATE_SAMPLES], ALfloat (*restrict late)[MAX_UPDATE_SAMPLES]) +{ + ALuint i, c; + + /* Perform any modulation on the input (use the early and late buffers as + * temp storage). + */ + CalcModulationDelays(State, &late[0][0], todo); + for(c = 0;c < 4;c++) + { + EAXModulation(&State->Mod.Delay[c], State->Offset, &late[0][0], + &early[0][0], input[c], todo); + + /* Band-pass the incoming samples */ + ALfilterState_process(&State->Filter[c].Lp, &early[1][0], &early[0][0], todo); + ALfilterState_process(&State->Filter[c].Hp, &early[2][0], &early[1][0], todo); + + /* Feed the initial delay line. */ + for(i = 0;i < todo;i++) + DelayLineIn(&State->Delay, (State->Offset+i)*4 + c, early[2][i]); + } + + // Calculate the early reflection from the first delay tap. + EarlyReflection(State, todo, early); + + // Calculate the late reverb from the decorrelator taps. + LateReverb(State, todo, late); + + // Calculate and mix in any echo. + EAXEcho(State, todo, late); + + // Step all delays forward. + State->Offset += todo; +} + + +static ALvoid ALreverbState_processStandard(ALreverbState *State, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + static const aluMatrixf B2A = {{ + { 0.288675134595f, 0.288675134595f, 0.288675134595f, 0.288675134595f }, + { 0.288675134595f, 0.288675134595f, -0.288675134595f, -0.288675134595f }, + { 0.288675134595f, -0.288675134595f, 0.288675134595f, -0.288675134595f }, + { 0.288675134595f, -0.288675134595f, -0.288675134595f, 0.288675134595f } + }}; + ALfloat (*restrict afmt)[MAX_UPDATE_SAMPLES] = State->AFormatSamples; + ALfloat (*restrict early)[MAX_UPDATE_SAMPLES] = State->EarlySamples; + ALfloat (*restrict late)[MAX_UPDATE_SAMPLES] = State->ReverbSamples; + ALuint base, c; + + /* Process reverb for these samples. */ + for(base = 0;base < SamplesToDo;) + { + ALuint todo = minu(SamplesToDo-base, MAX_UPDATE_SAMPLES); + + /* Convert B-Foramt to A-Format for processing. */ + memset(afmt, 0, sizeof(*afmt)*4); + for(c = 0;c < 4;c++) + MixRowSamples(afmt[c], B2A.m[c], + SamplesIn, MAX_EFFECT_CHANNELS, base, todo + ); + + VerbPass(State, todo, afmt, early, late); + + /* Mix the A-Format results to output, implicitly converting back to + * B-Format. + */ + for(c = 0;c < 4;c++) + MixSamples(early[c], NumChannels, SamplesOut, + State->Early.CurrentGain[c], State->Early.PanGain[c], + SamplesToDo-base, base, todo + ); + for(c = 0;c < 4;c++) + MixSamples(late[c], NumChannels, SamplesOut, + State->Late.CurrentGain[c], State->Late.PanGain[c], + SamplesToDo-base, base, todo + ); + + base += todo; + } +} + +static ALvoid ALreverbState_processEax(ALreverbState *State, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + static const aluMatrixf B2A = {{ + { 0.288675134595f, 0.288675134595f, 0.288675134595f, 0.288675134595f }, + { 0.288675134595f, 0.288675134595f, -0.288675134595f, -0.288675134595f }, + { 0.288675134595f, -0.288675134595f, 0.288675134595f, -0.288675134595f }, + { 0.288675134595f, -0.288675134595f, -0.288675134595f, 0.288675134595f } + }}; + ALfloat (*restrict afmt)[MAX_UPDATE_SAMPLES] = State->AFormatSamples; + ALfloat (*restrict early)[MAX_UPDATE_SAMPLES] = State->EarlySamples; + ALfloat (*restrict late)[MAX_UPDATE_SAMPLES] = State->ReverbSamples; + ALuint base, c; + + /* Process reverb for these samples. */ + for(base = 0;base < SamplesToDo;) + { + ALuint todo = minu(SamplesToDo-base, MAX_UPDATE_SAMPLES); + + memset(afmt, 0, 4*MAX_UPDATE_SAMPLES*sizeof(float)); + for(c = 0;c < 4;c++) + MixRowSamples(afmt[c], B2A.m[c], + SamplesIn, MAX_EFFECT_CHANNELS, base, todo + ); + + EAXVerbPass(State, todo, afmt, early, late); + + for(c = 0;c < 4;c++) + MixSamples(early[c], NumChannels, SamplesOut, + State->Early.CurrentGain[c], State->Early.PanGain[c], + SamplesToDo-base, base, todo + ); + for(c = 0;c < 4;c++) + MixSamples(late[c], NumChannels, SamplesOut, + State->Late.CurrentGain[c], State->Late.PanGain[c], + SamplesToDo-base, base, todo + ); + + base += todo; + } +} + +static ALvoid ALreverbState_process(ALreverbState *State, ALuint SamplesToDo, const ALfloat (*restrict SamplesIn)[BUFFERSIZE], ALfloat (*restrict SamplesOut)[BUFFERSIZE], ALuint NumChannels) +{ + if(State->IsEax) + ALreverbState_processEax(State, SamplesToDo, SamplesIn, SamplesOut, NumChannels); + else + ALreverbState_processStandard(State, SamplesToDo, SamplesIn, SamplesOut, NumChannels); +} + + +typedef struct ALreverbStateFactory { + DERIVE_FROM_TYPE(ALeffectStateFactory); +} ALreverbStateFactory; + +static ALeffectState *ALreverbStateFactory_create(ALreverbStateFactory* UNUSED(factory)) +{ + ALreverbState *state; + + alcall_once(&mixfunc_inited, init_mixfunc); + + NEW_OBJ0(state, ALreverbState)(); + if(!state) return NULL; + + 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); + props->Reverb.ReflectionsPan[0] = vals[0]; + props->Reverb.ReflectionsPan[1] = vals[1]; + props->Reverb.ReflectionsPan[2] = vals[2]; + 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); + props->Reverb.LateReverbPan[0] = vals[0]; + props->Reverb.LateReverbPan[1] = vals[1]; + props->Reverb.LateReverbPan[2] = vals[2]; + 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: + vals[0] = props->Reverb.ReflectionsPan[0]; + vals[1] = props->Reverb.ReflectionsPan[1]; + vals[2] = props->Reverb.ReflectionsPan[2]; + break; + case AL_EAXREVERB_LATE_REVERB_PAN: + vals[0] = props->Reverb.LateReverbPan[0]; + vals[1] = props->Reverb.LateReverbPan[1]; + vals[2] = props->Reverb.LateReverbPan[2]; + 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); diff --git a/Engine/lib/openal-soft/Alc/helpers.c b/Engine/lib/openal-soft/Alc/helpers.c new file mode 100644 index 000000000..0a6982e90 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/helpers.c @@ -0,0 +1,1127 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 +#include +#include +#include +#include +#ifdef HAVE_MALLOC_H +#include +#endif +#ifdef HAVE_DIRENT_H +#include +#endif + +#ifndef AL_NO_UID_DEFS +#if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H) +#define INITGUID +#include +#ifdef HAVE_GUIDDEF_H +#include +#else +#include +#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); +DEFINE_GUID(IID_IAudioCaptureClient, 0xc8adbd64, 0xe71e, 0x48a0, 0xa4,0xde, 0x18,0x5c,0x39,0x5c,0xd3,0x17); + +#ifdef HAVE_MMDEVAPI +#include +#include +#include +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 ); +#endif +#endif +#endif /* AL_NO_UID_DEFS */ + +#ifdef HAVE_DLFCN_H +#include +#endif +#ifdef HAVE_INTRIN_H +#include +#endif +#ifdef HAVE_CPUID_H +#include +#endif +#ifdef HAVE_SYS_SYSCONF_H +#include +#endif +#ifdef HAVE_FLOAT_H +#include +#endif +#ifdef HAVE_IEEEFP_H +#include +#endif + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#elif defined(_WIN32_IE) +#include +#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<<0))) + { + caps |= CPU_CAP_SSE3; + 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<<0))) + { + caps |= CPU_CAP_SSE3; + 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!" + caps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1; +#elif defined(HAVE_SSE3) +#warning "Assuming SSE 3 run-time support!" + caps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3; +#elif defined(HAVE_SSE2) +#warning "Assuming SSE 2 run-time support!" + caps |= CPU_CAP_SSE | CPU_CAP_SSE2; +#elif defined(HAVE_SSE) +#warning "Assuming SSE run-time support!" + caps |= CPU_CAP_SSE; +#endif +#endif +#ifdef HAVE_NEON + FILE *file = fopen("/proc/cpuinfo", "rt"); + if(!file) + ERR("Failed to open /proc/cpuinfo, cannot check for NEON support\n"); + else + { + char buf[256]; + while(fgets(buf, sizeof(buf), file) != NULL) + { + char *str; + + if(strncmp(buf, "Features\t:", 10) != 0) + continue; + + TRACE("Got features string:%s\n", buf+10); + + str = buf; + while((str=strstr(str, "neon")) != NULL) + { + if(isspace(*(str-1)) && (str[4] == 0 || isspace(str[4]))) + { + caps |= CPU_CAP_NEON; + break; + } + str++; + } + break; + } + + fclose(file); + file = NULL; + } +#endif + + TRACE("Extensions:%s%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_SSE3) ? ((caps&CPU_CAP_SSE3) ? " +SSE3" : " -SSE3") : ""), + ((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 SetMixerFPUMode(FPUCtl *ctl) +{ +#ifdef HAVE_FENV_H + fegetenv(STATIC_CAST(fenv_t, ctl)); +#if defined(__GNUC__) && defined(HAVE_SSE) + /* FIXME: Some fegetenv implementations can get the SSE environment too? + * How to tell when it does? */ + if((CPUCapFlags&CPU_CAP_SSE)) + __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 +} + + +static int StringSortCompare(const void *str1, const void *str2) +{ + return al_string_cmp(*(const_al_string*)str1, *(const_al_string*)str2); +} + +#ifdef _WIN32 + +static WCHAR *strrchrW(WCHAR *str, WCHAR ch) +{ + WCHAR *ret = NULL; + while(*str) + { + if(*str == ch) + ret = str; + ++str; + } + return ret; +} + +al_string GetProcPath(void) +{ + al_string ret = AL_STRING_INIT_STATIC(); + WCHAR *pathname, *sep; + DWORD pathlen; + DWORD len; + + pathlen = 256; + pathname = malloc(pathlen * sizeof(pathname[0])); + while(pathlen > 0 && (len=GetModuleFileNameW(NULL, pathname, pathlen)) == pathlen) + { + free(pathname); + pathlen <<= 1; + pathname = malloc(pathlen * sizeof(pathname[0])); + } + if(len == 0) + { + free(pathname); + ERR("Failed to get process name: error %lu\n", GetLastError()); + return ret; + } + + pathname[len] = 0; + if((sep = strrchrW(pathname, '\\'))) + { + WCHAR *sep2 = strrchrW(pathname, '/'); + if(sep2) *sep2 = 0; + else *sep = 0; + } + else if((sep = strrchrW(pathname, '/'))) + *sep = 0; + al_string_copy_wcstr(&ret, pathname); + free(pathname); + + TRACE("Got: %s\n", al_string_get_cstr(ret)); + return ret; +} + + +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; +} + + +void al_print(const char *type, const char *func, const char *fmt, ...) +{ + char str[1024]; + WCHAR *wstr; + va_list ap; + + va_start(ap, fmt); + vsnprintf(str, sizeof(str), fmt, ap); + va_end(ap); + + str[sizeof(str)-1] = 0; + wstr = FromUTF8(str); + if(!wstr) + fprintf(LogFile, "AL lib: %s %s: %s", type, func, str); + else + { + fprintf(LogFile, "AL lib: %s %s: %ls", type, func, wstr); + free(wstr); + wstr = NULL; + } + fflush(LogFile); +} + + +static inline int is_slash(int c) +{ return (c == '\\' || c == '/'); } + +static void DirectorySearch(const char *path, const char *ext, vector_al_string *results) +{ + al_string pathstr = AL_STRING_INIT_STATIC(); + WIN32_FIND_DATAW fdata; + WCHAR *wpath; + HANDLE hdl; + + al_string_copy_cstr(&pathstr, path); + al_string_append_cstr(&pathstr, "\\*"); + al_string_append_cstr(&pathstr, ext); + + TRACE("Searching %s\n", al_string_get_cstr(pathstr)); + + wpath = FromUTF8(al_string_get_cstr(pathstr)); + + hdl = FindFirstFileW(wpath, &fdata); + if(hdl != INVALID_HANDLE_VALUE) + { + size_t base = VECTOR_SIZE(*results); + do { + al_string str = AL_STRING_INIT_STATIC(); + al_string_copy_cstr(&str, path); + al_string_append_char(&str, '\\'); + al_string_append_wcstr(&str, fdata.cFileName); + TRACE("Got result %s\n", al_string_get_cstr(str)); + VECTOR_PUSH_BACK(*results, str); + } while(FindNextFileW(hdl, &fdata)); + FindClose(hdl); + + if(VECTOR_SIZE(*results) > base) + qsort(VECTOR_BEGIN(*results)+base, VECTOR_SIZE(*results)-base, + sizeof(VECTOR_FRONT(*results)), StringSortCompare); + } + + free(wpath); + al_string_deinit(&pathstr); +} + +vector_al_string SearchDataFiles(const char *ext, const char *subdir) +{ + static const int ids[2] = { CSIDL_APPDATA, CSIDL_COMMON_APPDATA }; + static RefCount search_lock; + vector_al_string results = VECTOR_INIT_STATIC(); + size_t i; + + while(ATOMIC_EXCHANGE(uint, &search_lock, 1) == 1) + althrd_yield(); + + /* If the path is absolute, use it directly. */ + if(isalpha(subdir[0]) && subdir[1] == ':' && is_slash(subdir[2])) + { + al_string path = AL_STRING_INIT_STATIC(); + al_string_copy_cstr(&path, subdir); +#define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0) + VECTOR_FOR_EACH(char, path, FIX_SLASH); +#undef FIX_SLASH + + DirectorySearch(al_string_get_cstr(path), ext, &results); + + al_string_deinit(&path); + } + else if(subdir[0] == '\\' && subdir[1] == '\\' && subdir[2] == '?' && subdir[3] == '\\') + DirectorySearch(subdir, ext, &results); + else + { + al_string path = AL_STRING_INIT_STATIC(); + WCHAR *cwdbuf; + + /* Search the app-local directory. */ + if((cwdbuf=_wgetenv(L"ALSOFT_LOCAL_PATH")) && *cwdbuf != '\0') + { + al_string_copy_wcstr(&path, cwdbuf); + if(is_slash(VECTOR_BACK(path))) + { + VECTOR_POP_BACK(path); + *VECTOR_END(path) = 0; + } + } + else if(!(cwdbuf=_wgetcwd(NULL, 0))) + al_string_copy_cstr(&path, "."); + else + { + al_string_copy_wcstr(&path, cwdbuf); + if(is_slash(VECTOR_BACK(path))) + { + VECTOR_POP_BACK(path); + *VECTOR_END(path) = 0; + } + free(cwdbuf); + } +#define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0) + VECTOR_FOR_EACH(char, path, FIX_SLASH); +#undef FIX_SLASH + DirectorySearch(al_string_get_cstr(path), ext, &results); + + /* Search the local and global data dirs. */ + for(i = 0;i < COUNTOF(ids);i++) + { + WCHAR buffer[PATH_MAX]; + if(SHGetSpecialFolderPathW(NULL, buffer, ids[i], FALSE) != FALSE) + { + al_string_copy_wcstr(&path, buffer); + if(!is_slash(VECTOR_BACK(path))) + al_string_append_char(&path, '\\'); + al_string_append_cstr(&path, subdir); +#define FIX_SLASH(i) do { if(*(i) == '/') *(i) = '\\'; } while(0) + VECTOR_FOR_EACH(char, path, FIX_SLASH); +#undef FIX_SLASH + + DirectorySearch(al_string_get_cstr(path), ext, &results); + } + } + + al_string_deinit(&path); + } + + ATOMIC_STORE(&search_lock, 0); + + return results; +} + + +struct FileMapping MapFileToMem(const char *fname) +{ + struct FileMapping ret = { NULL, NULL, NULL, 0 }; + MEMORY_BASIC_INFORMATION meminfo; + HANDLE file, fmap; + WCHAR *wname; + void *ptr; + + wname = FromUTF8(fname); + + file = CreateFileW(wname, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if(file == INVALID_HANDLE_VALUE) + { + ERR("Failed to open %s: %lu\n", fname, GetLastError()); + free(wname); + return ret; + } + free(wname); + wname = NULL; + + fmap = CreateFileMappingW(file, NULL, PAGE_READONLY, 0, 0, NULL); + if(!fmap) + { + ERR("Failed to create map for %s: %lu\n", fname, GetLastError()); + CloseHandle(file); + return ret; + } + + ptr = MapViewOfFile(fmap, FILE_MAP_READ, 0, 0, 0); + if(!ptr) + { + ERR("Failed to map %s: %lu\n", fname, GetLastError()); + CloseHandle(fmap); + CloseHandle(file); + return ret; + } + + if(VirtualQuery(ptr, &meminfo, sizeof(meminfo)) != sizeof(meminfo)) + { + ERR("Failed to get map size for %s: %lu\n", fname, GetLastError()); + UnmapViewOfFile(ptr); + CloseHandle(fmap); + CloseHandle(file); + return ret; + } + + ret.file = file; + ret.fmap = fmap; + ret.ptr = ptr; + ret.len = meminfo.RegionSize; + return ret; +} + +void UnmapFileMem(const struct FileMapping *mapping) +{ + UnmapViewOfFile(mapping->ptr); + CloseHandle(mapping->fmap); + CloseHandle(mapping->file); +} + +#else + +al_string GetProcPath(void) +{ + al_string ret = AL_STRING_INIT_STATIC(); + const char *fname; + char *pathname, *sep; + size_t pathlen; + ssize_t len; + + pathlen = 256; + pathname = malloc(pathlen); + + fname = "/proc/self/exe"; + len = readlink(fname, pathname, pathlen); + if(len == -1 && errno == ENOENT) + { + fname = "/proc/self/file"; + len = readlink(fname, pathname, pathlen); + } + + while(len > 0 && (size_t)len == pathlen) + { + free(pathname); + pathlen <<= 1; + pathname = malloc(pathlen); + len = readlink(fname, pathname, pathlen); + } + if(len <= 0) + { + free(pathname); + WARN("Failed to readlink %s: %s\n", fname, strerror(errno)); + return ret; + } + + pathname[len] = 0; + sep = strrchr(pathname, '/'); + if(sep) + al_string_copy_range(&ret, pathname, sep); + else + al_string_copy_cstr(&ret, pathname); + free(pathname); + + TRACE("Got: %s\n", al_string_get_cstr(ret)); + return ret; +} + + +#ifdef HAVE_DLFCN_H + +void *LoadLib(const char *name) +{ + const char *err; + void *handle; + + dlerror(); + handle = dlopen(name, RTLD_NOW); + if((err=dlerror()) != NULL) + handle = NULL; + return handle; +} +void CloseLib(void *handle) +{ dlclose(handle); } +void *GetSymbol(void *handle, const char *name) +{ + const char *err; + void *sym; + + dlerror(); + sym = dlsym(handle, name); + if((err=dlerror()) != NULL) + { + WARN("Failed to load %s: %s\n", name, err); + sym = NULL; + } + return sym; +} + +#endif /* HAVE_DLFCN_H */ + +void al_print(const char *type, const char *func, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(LogFile, "AL lib: %s %s: ", type, func); + vfprintf(LogFile, fmt, ap); + va_end(ap); + + fflush(LogFile); +} + + +static void DirectorySearch(const char *path, const char *ext, vector_al_string *results) +{ + size_t extlen = strlen(ext); + DIR *dir; + + TRACE("Searching %s for *%s\n", path, ext); + dir = opendir(path); + if(dir != NULL) + { + size_t base = VECTOR_SIZE(*results); + struct dirent *dirent; + while((dirent=readdir(dir)) != NULL) + { + al_string str; + size_t len; + if(strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) + continue; + + len = strlen(dirent->d_name); + if(!(len > extlen)) + continue; + if(strcasecmp(dirent->d_name+len-extlen, ext) != 0) + continue; + + AL_STRING_INIT(str); + al_string_copy_cstr(&str, path); + if(VECTOR_BACK(str) != '/') + al_string_append_char(&str, '/'); + al_string_append_cstr(&str, dirent->d_name); + TRACE("Got result %s\n", al_string_get_cstr(str)); + VECTOR_PUSH_BACK(*results, str); + } + closedir(dir); + + if(VECTOR_SIZE(*results) > base) + qsort(VECTOR_BEGIN(*results)+base, VECTOR_SIZE(*results)-base, + sizeof(VECTOR_FRONT(*results)), StringSortCompare); + } +} + +vector_al_string SearchDataFiles(const char *ext, const char *subdir) +{ + static RefCount search_lock; + vector_al_string results = VECTOR_INIT_STATIC(); + + while(ATOMIC_EXCHANGE(uint, &search_lock, 1) == 1) + althrd_yield(); + + if(subdir[0] == '/') + DirectorySearch(subdir, ext, &results); + else + { + al_string path = AL_STRING_INIT_STATIC(); + const char *str, *next; + char cwdbuf[PATH_MAX]; + + /* Search the app-local directory. */ + if((str=getenv("ALSOFT_LOCAL_PATH")) && *str != '\0') + DirectorySearch(str, ext, &results); + else if(getcwd(cwdbuf, sizeof(cwdbuf))) + DirectorySearch(cwdbuf, ext, &results); + else + DirectorySearch(".", ext, &results); + + // Search local data dir + if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0') + { + al_string_copy_cstr(&path, str); + if(VECTOR_BACK(path) != '/') + al_string_append_char(&path, '/'); + al_string_append_cstr(&path, subdir); + DirectorySearch(al_string_get_cstr(path), ext, &results); + } + else if((str=getenv("HOME")) != NULL && str[0] != '\0') + { + al_string_copy_cstr(&path, str); + if(VECTOR_BACK(path) == '/') + { + VECTOR_POP_BACK(path); + *VECTOR_END(path) = 0; + } + al_string_append_cstr(&path, "/.local/share/"); + al_string_append_cstr(&path, subdir); + DirectorySearch(al_string_get_cstr(path), ext, &results); + } + + // Search global data dirs + if((str=getenv("XDG_DATA_DIRS")) == NULL || str[0] == '\0') + str = "/usr/local/share/:/usr/share/"; + + next = str; + while((str=next) != NULL && str[0] != '\0') + { + next = strchr(str, ':'); + if(!next) + al_string_copy_cstr(&path, str); + else + { + al_string_copy_range(&path, str, next); + ++next; + } + if(!al_string_empty(path)) + { + if(VECTOR_BACK(path) != '/') + al_string_append_char(&path, '/'); + al_string_append_cstr(&path, subdir); + + DirectorySearch(al_string_get_cstr(path), ext, &results); + } + } + + al_string_deinit(&path); + } + + ATOMIC_STORE(&search_lock, 0); + + return results; +} + + +struct FileMapping MapFileToMem(const char *fname) +{ + struct FileMapping ret = { -1, NULL, 0 }; + struct stat sbuf; + void *ptr; + int fd; + + fd = open(fname, O_RDONLY, 0); + if(fd == -1) + { + ERR("Failed to open %s: (%d) %s\n", fname, errno, strerror(errno)); + return ret; + } + if(fstat(fd, &sbuf) == -1) + { + ERR("Failed to stat %s: (%d) %s\n", fname, errno, strerror(errno)); + close(fd); + return ret; + } + + ptr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if(ptr == MAP_FAILED) + { + ERR("Failed to map %s: (%d) %s\n", fname, errno, strerror(errno)); + close(fd); + return ret; + } + + ret.fd = fd; + ret.ptr = ptr; + ret.len = sbuf.st_size; + return ret; +} + +void UnmapFileMem(const struct FileMapping *mapping) +{ + munmap(mapping->ptr, mapping->len); + close(mapping->fd); +} + +#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, ¶m); + } +#else + /* Real-time priority not available */ + failed = (RTPrioLevel>0); +#endif + if(failed) + ERR("Failed to set priority level for thread\n"); +} + + +extern inline void al_string_deinit(al_string *str); +extern inline size_t al_string_length(const_al_string str); +extern inline ALboolean al_string_empty(const_al_string str); +extern inline const al_string_char_type *al_string_get_cstr(const_al_string str); + +void al_string_clear(al_string *str) +{ + if(!al_string_empty(*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_RESIZE(*str, 0, 1); + VECTOR_ELEM(*str, 0) = 0; + } +} + +static inline int al_string_compare(const al_string_char_type *str1, size_t str1len, + const al_string_char_type *str2, size_t str2len) +{ + size_t complen = (str1len < str2len) ? 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, strlen(str2)); +} + +void al_string_copy(al_string *str, const_al_string from) +{ + size_t len = al_string_length(from); + size_t i; + + VECTOR_RESIZE(*str, len, len+1); + for(i = 0;i < len;i++) + VECTOR_ELEM(*str, i) = VECTOR_ELEM(from, i); + VECTOR_ELEM(*str, i) = 0; +} + +void al_string_copy_cstr(al_string *str, const al_string_char_type *from) +{ + size_t len = strlen(from); + size_t i; + + VECTOR_RESIZE(*str, len, len+1); + for(i = 0;i < len;i++) + VECTOR_ELEM(*str, i) = from[i]; + VECTOR_ELEM(*str, i) = 0; +} + +void al_string_copy_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) +{ + size_t len = to - from; + size_t i; + + VECTOR_RESIZE(*str, len, len+1); + for(i = 0;i < len;i++) + VECTOR_ELEM(*str, i) = from[i]; + VECTOR_ELEM(*str, i) = 0; +} + +void al_string_append_char(al_string *str, const al_string_char_type c) +{ + size_t len = al_string_length(*str); + VECTOR_RESIZE(*str, len, len+2); + VECTOR_PUSH_BACK(*str, c); + VECTOR_ELEM(*str, len+1) = 0; +} + +void al_string_append_cstr(al_string *str, const al_string_char_type *from) +{ + size_t len = strlen(from); + if(len != 0) + { + size_t base = al_string_length(*str); + size_t i; + + VECTOR_RESIZE(*str, base+len, base+len+1); + for(i = 0;i < len;i++) + VECTOR_ELEM(*str, base+i) = from[i]; + VECTOR_ELEM(*str, base+i) = 0; + } +} + +void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) +{ + size_t len = to - from; + if(len != 0) + { + size_t base = al_string_length(*str); + size_t i; + + VECTOR_RESIZE(*str, base+len, base+len+1); + for(i = 0;i < len;i++) + VECTOR_ELEM(*str, base+i) = from[i]; + VECTOR_ELEM(*str, base+i) = 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_RESIZE(*str, len-1, len); + WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str), len, NULL, NULL); + VECTOR_ELEM(*str, len-1) = 0; + } +} + +void al_string_append_wcstr(al_string *str, const wchar_t *from) +{ + int len; + if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) + { + size_t base = al_string_length(*str); + VECTOR_RESIZE(*str, base+len-1, base+len); + WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_ELEM(*str, base), len, NULL, NULL); + VECTOR_ELEM(*str, base+len-1) = 0; + } +} + +void al_string_append_wrange(al_string *str, const wchar_t *from, const wchar_t *to) +{ + int len; + if((len=WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), NULL, 0, NULL, NULL)) > 0) + { + size_t base = al_string_length(*str); + VECTOR_RESIZE(*str, base+len, base+len+1); + WideCharToMultiByte(CP_UTF8, 0, from, (int)(to-from), &VECTOR_ELEM(*str, base), len+1, NULL, NULL); + VECTOR_ELEM(*str, base+len) = 0; + } +} +#endif diff --git a/Engine/lib/openal-soft/Alc/hrtf.c b/Engine/lib/openal-soft/Alc/hrtf.c new file mode 100644 index 000000000..02889736c --- /dev/null +++ b/Engine/lib/openal-soft/Alc/hrtf.c @@ -0,0 +1,1054 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "AL/al.h" +#include "AL/alc.h" +#include "alMain.h" +#include "alSource.h" +#include "alu.h" +#include "bformatdec.h" +#include "hrtf.h" + +#include "compat.h" +#include "almalloc.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) + +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 index given the polar elevation in radians. This + * will return an index between 0 and (evcount - 1). Assumes the FPU is in + * round-to-zero mode. + */ +static ALuint CalcEvIndex(ALuint evcount, ALfloat ev) +{ + ev = (F_PI_2 + ev) * (evcount-1) / F_PI; + return minu(fastf2u(ev + 0.5f), evcount-1); +} + +/* Calculate the azimuth index given the polar azimuth in radians. This will + * return an index between 0 and (azcount - 1). Assumes the FPU is in round-to- + * zero mode. + */ +static ALuint CalcAzIndex(ALuint azcount, ALfloat az) +{ + az = (F_TAU + az) * azcount / F_TAU; + return fastf2u(az + 0.5f) % azcount; +} + +/* Calculates static HRIR coefficients and delays for the given polar elevation + * and azimuth in radians. The coefficients are normalized and attenuated by + * the specified gain. + */ +void GetHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays) +{ + ALuint evidx, azidx, lidx, ridx; + ALuint azcount, evoffset; + ALfloat dirfact; + ALuint i; + + dirfact = 1.0f - (spread / F_TAU); + + /* Claculate elevation index. */ + evidx = CalcEvIndex(Hrtf->evCount, elevation); + azcount = Hrtf->azCount[evidx]; + evoffset = Hrtf->evOffset[evidx]; + + /* Calculate azimuth index. */ + azidx = CalcAzIndex(Hrtf->azCount[evidx], azimuth); + + /* Calculate the HRIR indices for left and right channels. */ + lidx = evoffset + azidx; + ridx = evoffset + ((azcount-azidx) % azcount); + + /* Calculate the HRIR delays. */ + delays[0] = fastf2u(Hrtf->delays[lidx]*dirfact + 0.5f) << HRTFDELAY_BITS; + delays[1] = fastf2u(Hrtf->delays[ridx]*dirfact + 0.5f) << HRTFDELAY_BITS; + + /* Calculate the sample offsets for the HRIR indices. */ + lidx *= Hrtf->irSize; + ridx *= Hrtf->irSize; + + /* Calculate the normalized and attenuated HRIR coefficients. Zero the + * coefficients if gain is too low. + */ + if(gain > 0.0001f) + { + gain /= 32767.0f; + + i = 0; + coeffs[i][0] = lerp(PassthruCoeff, Hrtf->coeffs[lidx+i], dirfact)*gain; + coeffs[i][1] = lerp(PassthruCoeff, Hrtf->coeffs[ridx+i], dirfact)*gain; + for(i = 1;i < Hrtf->irSize;i++) + { + coeffs[i][0] = Hrtf->coeffs[lidx+i]*gain * dirfact; + coeffs[i][1] = Hrtf->coeffs[ridx+i]*gain * dirfact; + } + } + else + { + for(i = 0;i < Hrtf->irSize;i++) + { + coeffs[i][0] = 0.0f; + coeffs[i][1] = 0.0f; + } + } +} + + +ALuint BuildBFormatHrtf(const struct Hrtf *Hrtf, ALfloat (*coeffs)[HRIR_LENGTH][2], ALuint NumChannels) +{ + static const struct { + ALfloat elevation; + ALfloat azimuth; + } Ambi3DPoints[14] = { + { DEG2RAD( 90.0f), DEG2RAD( 0.0f) }, + { DEG2RAD( 35.0f), DEG2RAD( -45.0f) }, + { DEG2RAD( 35.0f), DEG2RAD( 45.0f) }, + { DEG2RAD( 35.0f), DEG2RAD( 135.0f) }, + { DEG2RAD( 35.0f), DEG2RAD(-135.0f) }, + { DEG2RAD( 0.0f), DEG2RAD( 0.0f) }, + { DEG2RAD( 0.0f), DEG2RAD( 90.0f) }, + { DEG2RAD( 0.0f), DEG2RAD( 180.0f) }, + { DEG2RAD( 0.0f), DEG2RAD( -90.0f) }, + { DEG2RAD(-35.0f), DEG2RAD( -45.0f) }, + { DEG2RAD(-35.0f), DEG2RAD( 45.0f) }, + { DEG2RAD(-35.0f), DEG2RAD( 135.0f) }, + { DEG2RAD(-35.0f), DEG2RAD(-135.0f) }, + { DEG2RAD(-90.0f), DEG2RAD( 0.0f) }, + }; + static const ALfloat Ambi3DMatrix[14][2][MAX_AMBI_COEFFS] = { + { { 0.078851598f, 0.000000000f, 0.070561967f, 0.000000000f }, { 0.0269973975f, 0.0000000000f, 0.0467610443f, 0.0000000000f } }, + { { 0.124051278f, 0.059847972f, 0.059847972f, 0.059847972f }, { 0.0269973975f, 0.0269973975f, 0.0269973975f, 0.0269973975f } }, + { { 0.124051278f, -0.059847972f, 0.059847972f, 0.059847972f }, { 0.0269973975f, -0.0269973975f, 0.0269973975f, 0.0269973975f } }, + { { 0.124051278f, -0.059847972f, 0.059847972f, -0.059847972f }, { 0.0269973975f, -0.0269973975f, 0.0269973975f, -0.0269973975f } }, + { { 0.124051278f, 0.059847972f, 0.059847972f, -0.059847972f }, { 0.0269973975f, 0.0269973975f, 0.0269973975f, -0.0269973975f } }, + { { 0.078851598f, 0.000000000f, 0.000000000f, 0.070561967f }, { 0.0269973975f, 0.0000000000f, 0.0000000000f, 0.0467610443f } }, + { { 0.078851598f, -0.070561967f, 0.000000000f, 0.000000000f }, { 0.0269973975f, -0.0467610443f, 0.0000000000f, 0.0000000000f } }, + { { 0.078851598f, 0.000000000f, 0.000000000f, -0.070561967f }, { 0.0269973975f, 0.0000000000f, 0.0000000000f, -0.0467610443f } }, + { { 0.078851598f, 0.070561967f, 0.000000000f, 0.000000000f }, { 0.0269973975f, 0.0467610443f, 0.0000000000f, 0.0000000000f } }, + { { 0.124051278f, 0.059847972f, -0.059847972f, 0.059847972f }, { 0.0269973975f, 0.0269973975f, -0.0269973975f, 0.0269973975f } }, + { { 0.124051278f, -0.059847972f, -0.059847972f, 0.059847972f }, { 0.0269973975f, -0.0269973975f, -0.0269973975f, 0.0269973975f } }, + { { 0.124051278f, -0.059847972f, -0.059847972f, -0.059847972f }, { 0.0269973975f, -0.0269973975f, -0.0269973975f, -0.0269973975f } }, + { { 0.124051278f, 0.059847972f, -0.059847972f, -0.059847972f }, { 0.0269973975f, 0.0269973975f, -0.0269973975f, -0.0269973975f } }, + { { 0.078851598f, 0.000000000f, -0.070561967f, 0.000000000f }, { 0.0269973975f, 0.0000000000f, -0.0467610443f, 0.0000000000f } }, + }; +/* Change this to 2 for dual-band HRTF processing. May require a higher quality + * band-splitter, or better calculation of the new IR length to deal with the + * tail generated by the filter. + */ +#define NUM_BANDS 2 + BandSplitter splitter; + ALfloat temps[3][HRIR_LENGTH]; + ALuint lidx[14], ridx[14]; + ALuint min_delay = HRTF_HISTORY_LENGTH; + ALuint max_length = 0; + ALuint i, j, c, b; + + assert(NumChannels == 4); + + for(c = 0;c < COUNTOF(Ambi3DPoints);c++) + { + ALuint evidx, azidx; + ALuint evoffset; + ALuint azcount; + + /* Calculate elevation index. */ + evidx = (ALuint)floorf((F_PI_2 + Ambi3DPoints[c].elevation) * + (Hrtf->evCount-1)/F_PI + 0.5f); + evidx = minu(evidx, Hrtf->evCount-1); + + azcount = Hrtf->azCount[evidx]; + evoffset = Hrtf->evOffset[evidx]; + + /* Calculate azimuth index for this elevation. */ + azidx = (ALuint)floorf((F_TAU+Ambi3DPoints[c].azimuth) * + azcount/F_TAU + 0.5f) % azcount; + + /* Calculate indices for left and right channels. */ + lidx[c] = evoffset + azidx; + ridx[c] = evoffset + ((azcount-azidx) % azcount); + + min_delay = minu(min_delay, minu(Hrtf->delays[lidx[c]], Hrtf->delays[ridx[c]])); + } + + memset(temps, 0, sizeof(temps)); + bandsplit_init(&splitter, 400.0f / (ALfloat)Hrtf->sampleRate); + for(c = 0;c < COUNTOF(Ambi3DMatrix);c++) + { + const ALshort *fir; + ALuint delay; + + /* Convert the left FIR from shorts to float */ + fir = &Hrtf->coeffs[lidx[c] * Hrtf->irSize]; + if(NUM_BANDS == 1) + { + for(i = 0;i < Hrtf->irSize;i++) + temps[0][i] = fir[i] / 32767.0f; + } + else + { + /* Band-split left HRIR into low and high frequency responses. */ + bandsplit_clear(&splitter); + for(i = 0;i < Hrtf->irSize;i++) + temps[2][i] = fir[i] / 32767.0f; + bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH); + } + + /* Add to the left output coefficients with the specified delay. */ + delay = Hrtf->delays[lidx[c]] - min_delay; + for(i = 0;i < NumChannels;++i) + { + for(b = 0;b < NUM_BANDS;b++) + { + ALuint k = 0; + for(j = delay;j < HRIR_LENGTH;++j) + coeffs[i][j][0] += temps[b][k++] * Ambi3DMatrix[c][b][i]; + } + } + max_length = maxu(max_length, minu(delay + Hrtf->irSize, HRIR_LENGTH)); + + /* Convert the right FIR from shorts to float */ + fir = &Hrtf->coeffs[ridx[c] * Hrtf->irSize]; + if(NUM_BANDS == 1) + { + for(i = 0;i < Hrtf->irSize;i++) + temps[0][i] = fir[i] / 32767.0f; + } + else + { + /* Band-split right HRIR into low and high frequency responses. */ + bandsplit_clear(&splitter); + for(i = 0;i < Hrtf->irSize;i++) + temps[2][i] = fir[i] / 32767.0f; + bandsplit_process(&splitter, temps[0], temps[1], temps[2], HRIR_LENGTH); + } + + /* Add to the right output coefficients with the specified delay. */ + delay = Hrtf->delays[ridx[c]] - min_delay; + for(i = 0;i < NumChannels;++i) + { + for(b = 0;b < NUM_BANDS;b++) + { + ALuint k = 0; + for(j = delay;j < HRIR_LENGTH;++j) + coeffs[i][j][1] += temps[b][k++] * Ambi3DMatrix[c][b][i]; + } + } + max_length = maxu(max_length, minu(delay + Hrtf->irSize, HRIR_LENGTH)); + } + TRACE("Skipped min delay: %u, new combined length: %u\n", min_delay, max_length); +#undef NUM_BANDS + + return max_length; +} + + +static struct Hrtf *LoadHrtf00(const ALubyte *data, size_t datalen, const_al_string filename) +{ + const ALubyte maxDelay = HRTF_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; + const ALubyte *delays = NULL; + ALuint i, j; + + if(datalen < 9) + { + ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n", + al_string_get_cstr(filename), 9, datalen); + return NULL; + } + + rate = *(data++); + rate |= *(data++)<<8; + rate |= *(data++)<<16; + rate |= *(data++)<<24; + datalen -= 4; + + irCount = *(data++); + irCount |= *(data++)<<8; + datalen -= 2; + + irSize = *(data++); + irSize |= *(data++)<<8; + datalen -= 2; + + evCount = *(data++); + datalen -= 1; + + 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; + + if(datalen < evCount*2) + { + ERR("Unexpected end of %s data (req %d, rem "SZFMT")\n", + al_string_get_cstr(filename), evCount*2, datalen); + 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] = *(data++); + evOffset[0] |= *(data++)<<8; + datalen -= 2; + for(i = 1;i < evCount;i++) + { + evOffset[i] = *(data++); + evOffset[i] |= *(data++)<<8; + datalen -= 2; + 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); + if(coeffs == NULL) + { + ERR("Out of memory.\n"); + failed = AL_TRUE; + } + } + + if(!failed) + { + size_t reqsize = 2*irSize*irCount + irCount; + if(datalen < reqsize) + { + ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT")\n", + al_string_get_cstr(filename), reqsize, datalen); + failed = AL_TRUE; + } + } + + if(!failed) + { + for(i = 0;i < irCount*irSize;i+=irSize) + { + for(j = 0;j < irSize;j++) + { + coeffs[i+j] = *(data++); + coeffs[i+j] |= *(data++)<<8; + datalen -= 2; + } + } + + delays = data; + data += irCount; + datalen -= irCount; + for(i = 0;i < irCount;i++) + { + if(delays[i] > maxDelay) + { + ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay); + failed = AL_TRUE; + } + } + } + + if(!failed) + { + size_t total = sizeof(struct Hrtf); + total += sizeof(azCount[0])*evCount; + total = (total+1)&~1; /* Align for (u)short fields */ + total += sizeof(evOffset[0])*evCount; + total += sizeof(coeffs[0])*irSize*irCount; + total += sizeof(delays[0])*irCount; + total += al_string_length(filename)+1; + + Hrtf = al_calloc(16, total); + if(Hrtf == NULL) + { + ERR("Out of memory.\n"); + failed = AL_TRUE; + } + } + + if(!failed) + { + char *base = (char*)Hrtf; + uintptr_t offset = sizeof(*Hrtf); + + Hrtf->sampleRate = rate; + Hrtf->irSize = irSize; + Hrtf->evCount = evCount; + Hrtf->azCount = ((ALubyte*)(base + offset)); offset += evCount*sizeof(Hrtf->azCount[0]); + offset = (offset+1)&~1; /* Align for (u)short fields */ + Hrtf->evOffset = ((ALushort*)(base + offset)); offset += evCount*sizeof(Hrtf->evOffset[0]); + Hrtf->coeffs = ((ALshort*)(base + offset)); offset += irSize*irCount*sizeof(Hrtf->coeffs[0]); + Hrtf->delays = ((ALubyte*)(base + offset)); offset += irCount*sizeof(Hrtf->delays[0]); + Hrtf->filename = ((char*)(base + offset)); + Hrtf->next = NULL; + + memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount); + memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount); + memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount); + memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount); + memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1); + } + + free(azCount); + free(evOffset); + free(coeffs); + return Hrtf; +} + +static struct Hrtf *LoadHrtf01(const ALubyte *data, size_t datalen, const_al_string filename) +{ + const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1; + struct Hrtf *Hrtf = NULL; + ALboolean failed = AL_FALSE; + ALuint rate = 0, irCount = 0; + ALubyte irSize = 0, evCount = 0; + const ALubyte *azCount = NULL; + ALushort *evOffset = NULL; + ALshort *coeffs = NULL; + const ALubyte *delays = NULL; + ALuint i, j; + + if(datalen < 6) + { + ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", + al_string_get_cstr(filename), 6, datalen); + return NULL; + } + + rate = *(data++); + rate |= *(data++)<<8; + rate |= *(data++)<<16; + rate |= *(data++)<<24; + datalen -= 4; + + irSize = *(data++); + datalen -= 1; + + evCount = *(data++); + datalen -= 1; + + 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; + + if(datalen < evCount) + { + ERR("Unexpected end of %s data (req %d, rem "SZFMT"\n", + al_string_get_cstr(filename), evCount, datalen); + return NULL; + } + + azCount = data; + data += evCount; + datalen -= 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++) + { + 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); + if(coeffs == NULL) + { + ERR("Out of memory.\n"); + failed = AL_TRUE; + } + } + + if(!failed) + { + size_t reqsize = 2*irSize*irCount + irCount; + if(datalen < reqsize) + { + ERR("Unexpected end of %s data (req "SZFMT", rem "SZFMT"\n", + al_string_get_cstr(filename), reqsize, datalen); + failed = AL_TRUE; + } + } + + if(!failed) + { + for(i = 0;i < irCount*irSize;i+=irSize) + { + for(j = 0;j < irSize;j++) + { + ALshort coeff; + coeff = *(data++); + coeff |= *(data++)<<8; + datalen -= 2; + coeffs[i+j] = coeff; + } + } + + delays = data; + data += irCount; + datalen -= irCount; + for(i = 0;i < irCount;i++) + { + if(delays[i] > maxDelay) + { + ERR("Invalid delays[%d]: %d (%d)\n", i, delays[i], maxDelay); + failed = AL_TRUE; + } + } + } + + if(!failed) + { + size_t total = sizeof(struct Hrtf); + total += sizeof(azCount[0])*evCount; + total = (total+1)&~1; /* Align for (u)short fields */ + total += sizeof(evOffset[0])*evCount; + total += sizeof(coeffs[0])*irSize*irCount; + total += sizeof(delays[0])*irCount; + total += al_string_length(filename)+1; + + Hrtf = al_calloc(16, total); + if(Hrtf == NULL) + { + ERR("Out of memory.\n"); + failed = AL_TRUE; + } + } + + if(!failed) + { + char *base = (char*)Hrtf; + uintptr_t offset = sizeof(*Hrtf); + + Hrtf->sampleRate = rate; + Hrtf->irSize = irSize; + Hrtf->evCount = evCount; + Hrtf->azCount = ((ALubyte*)(base + offset)); offset += evCount*sizeof(Hrtf->azCount[0]); + offset = (offset+1)&~1; /* Align for (u)short fields */ + Hrtf->evOffset = ((ALushort*)(base + offset)); offset += evCount*sizeof(Hrtf->evOffset[0]); + Hrtf->coeffs = ((ALshort*)(base + offset)); offset += irSize*irCount*sizeof(Hrtf->coeffs[0]); + Hrtf->delays = ((ALubyte*)(base + offset)); offset += irCount*sizeof(Hrtf->delays[0]); + Hrtf->filename = ((char*)(base + offset)); + Hrtf->next = NULL; + + memcpy((void*)Hrtf->azCount, azCount, sizeof(azCount[0])*evCount); + memcpy((void*)Hrtf->evOffset, evOffset, sizeof(evOffset[0])*evCount); + memcpy((void*)Hrtf->coeffs, coeffs, sizeof(coeffs[0])*irSize*irCount); + memcpy((void*)Hrtf->delays, delays, sizeof(delays[0])*irCount); + memcpy((void*)Hrtf->filename, al_string_get_cstr(filename), al_string_length(filename)+1); + } + + free(evOffset); + free(coeffs); + return Hrtf; +} + +static void AddFileEntry(vector_HrtfEntry *list, al_string *filename) +{ + HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL }; + struct Hrtf *hrtf = NULL; + const HrtfEntry *iter; + struct FileMapping fmap; + const char *name; + const char *ext; + int i; + +#define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0) + VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME); + if(iter != VECTOR_END(*list)) + { + TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename)); + goto done; + } +#undef MATCH_FNAME + + entry.hrtf = LoadedHrtfs; + while(entry.hrtf) + { + if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0) + { + TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename)); + goto skip_load; + } + entry.hrtf = entry.hrtf->next; + } + + TRACE("Loading %s...\n", al_string_get_cstr(*filename)); + fmap = MapFileToMem(al_string_get_cstr(*filename)); + if(fmap.ptr == NULL) + { + ERR("Could not open %s\n", al_string_get_cstr(*filename)); + goto done; + } + + if(fmap.len < sizeof(magicMarker01)) + ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), fmap.len); + else if(memcmp(fmap.ptr, magicMarker01, sizeof(magicMarker01)) == 0) + { + TRACE("Detected data set format v1\n"); + hrtf = LoadHrtf01((const ALubyte*)fmap.ptr+sizeof(magicMarker01), + fmap.len-sizeof(magicMarker01), *filename + ); + } + else if(memcmp(fmap.ptr, magicMarker00, sizeof(magicMarker00)) == 0) + { + TRACE("Detected data set format v0\n"); + hrtf = LoadHrtf00((const ALubyte*)fmap.ptr+sizeof(magicMarker00), + fmap.len-sizeof(magicMarker00), *filename + ); + } + else + ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), (const char*)fmap.ptr); + UnmapFileMem(&fmap); + + if(!hrtf) + { + ERR("Failed to load %s\n", al_string_get_cstr(*filename)); + goto done; + } + + hrtf->next = LoadedHrtfs; + LoadedHrtfs = hrtf; + TRACE("Loaded HRTF support for format: %s %uhz\n", + DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate); + entry.hrtf = hrtf; + +skip_load: + /* TODO: Get a human-readable name from the HRTF data (possibly coming in a + * format update). */ + name = strrchr(al_string_get_cstr(*filename), '/'); + if(!name) name = strrchr(al_string_get_cstr(*filename), '\\'); + if(!name) name = al_string_get_cstr(*filename); + else ++name; + + ext = strrchr(name, '.'); + + i = 0; + do { + if(!ext) + al_string_copy_cstr(&entry.name, name); + else + al_string_copy_range(&entry.name, name, ext); + if(i != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", i+1); + al_string_append_cstr(&entry.name, str); + } + ++i; + +#define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0) + VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME); +#undef MATCH_NAME + } while(iter != VECTOR_END(*list)); + + TRACE("Adding entry \"%s\" from file \"%s\"\n", al_string_get_cstr(entry.name), + al_string_get_cstr(*filename)); + VECTOR_PUSH_BACK(*list, entry); + +done: + al_string_deinit(filename); +} + +/* Unfortunate that we have to duplicate AddFileEntry to take a memory buffer + * for input instead of opening the given filename. + */ +static void AddBuiltInEntry(vector_HrtfEntry *list, const ALubyte *data, size_t datalen, al_string *filename) +{ + HrtfEntry entry = { AL_STRING_INIT_STATIC(), NULL }; + struct Hrtf *hrtf = NULL; + const HrtfEntry *iter; + int i; + +#define MATCH_FNAME(i) (al_string_cmp_cstr(*filename, (i)->hrtf->filename) == 0) + VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_FNAME); + if(iter != VECTOR_END(*list)) + { + TRACE("Skipping duplicate file entry %s\n", al_string_get_cstr(*filename)); + goto done; + } +#undef MATCH_FNAME + + entry.hrtf = LoadedHrtfs; + while(entry.hrtf) + { + if(al_string_cmp_cstr(*filename, entry.hrtf->filename) == 0) + { + TRACE("Skipping load of already-loaded file %s\n", al_string_get_cstr(*filename)); + goto skip_load; + } + entry.hrtf = entry.hrtf->next; + } + + TRACE("Loading %s...\n", al_string_get_cstr(*filename)); + if(datalen < sizeof(magicMarker01)) + { + ERR("%s data is too short ("SZFMT" bytes)\n", al_string_get_cstr(*filename), datalen); + goto done; + } + + if(memcmp(data, magicMarker01, sizeof(magicMarker01)) == 0) + { + TRACE("Detected data set format v1\n"); + hrtf = LoadHrtf01(data+sizeof(magicMarker01), + datalen-sizeof(magicMarker01), *filename + ); + } + else if(memcmp(data, magicMarker00, sizeof(magicMarker00)) == 0) + { + TRACE("Detected data set format v0\n"); + hrtf = LoadHrtf00(data+sizeof(magicMarker00), + datalen-sizeof(magicMarker00), *filename + ); + } + else + ERR("Invalid header in %s: \"%.8s\"\n", al_string_get_cstr(*filename), data); + + if(!hrtf) + { + ERR("Failed to load %s\n", al_string_get_cstr(*filename)); + goto done; + } + + hrtf->next = LoadedHrtfs; + LoadedHrtfs = hrtf; + TRACE("Loaded HRTF support for format: %s %uhz\n", + DevFmtChannelsString(DevFmtStereo), hrtf->sampleRate); + entry.hrtf = hrtf; + +skip_load: + i = 0; + do { + al_string_copy(&entry.name, *filename); + if(i != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", i+1); + al_string_append_cstr(&entry.name, str); + } + ++i; + +#define MATCH_NAME(i) (al_string_cmp(entry.name, (i)->name) == 0) + VECTOR_FIND_IF(iter, const HrtfEntry, *list, MATCH_NAME); +#undef MATCH_NAME + } while(iter != VECTOR_END(*list)); + + TRACE("Adding built-in entry \"%s\"\n", al_string_get_cstr(entry.name)); + VECTOR_PUSH_BACK(*list, entry); + +done: + al_string_deinit(filename); +} + + +#ifndef ALSOFT_EMBED_HRTF_DATA +#define IDR_DEFAULT_44100_MHR 0 +#define IDR_DEFAULT_48000_MHR 1 + +static const ALubyte *GetResource(int UNUSED(name), size_t *size) +{ + *size = 0; + return NULL; +} + +#else +#include "hrtf_res.h" + +#ifdef _WIN32 +static const ALubyte *GetResource(int name, size_t *size) +{ + HMODULE handle; + HGLOBAL res; + HRSRC rc; + + GetModuleHandleExW( + GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCWSTR)GetResource, &handle + ); + rc = FindResourceW(handle, MAKEINTRESOURCEW(name), MAKEINTRESOURCEW(MHRTYPE)); + res = LoadResource(handle, rc); + + *size = SizeofResource(handle, rc); + return LockResource(res); +} + +#else + +extern const ALubyte _binary_default_44100_mhr_start[] HIDDEN_DECL; +extern const ALubyte _binary_default_44100_mhr_end[] HIDDEN_DECL; +extern const ALubyte _binary_default_44100_mhr_size[] HIDDEN_DECL; + +extern const ALubyte _binary_default_48000_mhr_start[] HIDDEN_DECL; +extern const ALubyte _binary_default_48000_mhr_end[] HIDDEN_DECL; +extern const ALubyte _binary_default_48000_mhr_size[] HIDDEN_DECL; + +static const ALubyte *GetResource(int name, size_t *size) +{ + if(name == IDR_DEFAULT_44100_MHR) + { + /* Make sure all symbols are referenced, to ensure the compiler won't + * ignore the declarations and lose the visibility attribute used to + * hide them (would be nice if ld or objcopy could automatically mark + * them as hidden when generating them, but apparently they can't). + */ + const void *volatile ptr =_binary_default_44100_mhr_size; + (void)ptr; + *size = _binary_default_44100_mhr_end - _binary_default_44100_mhr_start; + return _binary_default_44100_mhr_start; + } + if(name == IDR_DEFAULT_48000_MHR) + { + const void *volatile ptr =_binary_default_48000_mhr_size; + (void)ptr; + *size = _binary_default_48000_mhr_end - _binary_default_48000_mhr_start; + return _binary_default_48000_mhr_start; + } + *size = 0; + return NULL; +} +#endif +#endif + +vector_HrtfEntry EnumerateHrtf(const_al_string devname) +{ + vector_HrtfEntry list = VECTOR_INIT_STATIC(); + const char *defaulthrtf = ""; + const char *pathlist = ""; + bool usedefaults = true; + + if(ConfigValueStr(al_string_get_cstr(devname), NULL, "hrtf-paths", &pathlist)) + { + while(pathlist && *pathlist) + { + const char *next, *end; + + while(isspace(*pathlist) || *pathlist == ',') + pathlist++; + if(*pathlist == '\0') + continue; + + next = strchr(pathlist, ','); + if(next) + end = next++; + else + { + end = pathlist + strlen(pathlist); + usedefaults = false; + } + + while(end != pathlist && isspace(*(end-1))) + --end; + if(end != pathlist) + { + al_string pname = AL_STRING_INIT_STATIC(); + vector_al_string flist; + + al_string_append_range(&pname, pathlist, end); + + flist = SearchDataFiles(".mhr", al_string_get_cstr(pname)); + VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list); + VECTOR_DEINIT(flist); + + al_string_deinit(&pname); + } + + pathlist = next; + } + } + else if(ConfigValueExists(al_string_get_cstr(devname), NULL, "hrtf_tables")) + ERR("The hrtf_tables option is deprecated, please use hrtf-paths instead.\n"); + + if(usedefaults) + { + vector_al_string flist; + const ALubyte *rdata; + size_t rsize; + + flist = SearchDataFiles(".mhr", "openal/hrtf"); + VECTOR_FOR_EACH_PARAMS(al_string, flist, AddFileEntry, &list); + VECTOR_DEINIT(flist); + + rdata = GetResource(IDR_DEFAULT_44100_MHR, &rsize); + if(rdata != NULL && rsize > 0) + { + al_string ename = AL_STRING_INIT_STATIC(); + al_string_copy_cstr(&ename, "Built-In 44100hz"); + AddBuiltInEntry(&list, rdata, rsize, &ename); + } + + rdata = GetResource(IDR_DEFAULT_48000_MHR, &rsize); + if(rdata != NULL && rsize > 0) + { + al_string ename = AL_STRING_INIT_STATIC(); + al_string_copy_cstr(&ename, "Built-In 48000hz"); + AddBuiltInEntry(&list, rdata, rsize, &ename); + } + } + + if(VECTOR_SIZE(list) > 1 && ConfigValueStr(al_string_get_cstr(devname), NULL, "default-hrtf", &defaulthrtf)) + { + const HrtfEntry *iter; + /* Find the preferred HRTF and move it to the front of the list. */ +#define FIND_ENTRY(i) (al_string_cmp_cstr((i)->name, defaulthrtf) == 0) + VECTOR_FIND_IF(iter, const HrtfEntry, list, FIND_ENTRY); +#undef FIND_ENTRY + if(iter == VECTOR_END(list)) + WARN("Failed to find default HRTF \"%s\"\n", defaulthrtf); + else if(iter != VECTOR_BEGIN(list)) + { + HrtfEntry entry = *iter; + memmove(&VECTOR_ELEM(list,1), &VECTOR_ELEM(list,0), + (iter-VECTOR_BEGIN(list))*sizeof(HrtfEntry)); + VECTOR_ELEM(list,0) = entry; + } + } + + return list; +} + +void FreeHrtfList(vector_HrtfEntry *list) +{ +#define CLEAR_ENTRY(i) do { \ + al_string_deinit(&(i)->name); \ +} while(0) + VECTOR_FOR_EACH(HrtfEntry, *list, CLEAR_ENTRY); + VECTOR_DEINIT(*list); +#undef CLEAR_ENTRY +} + + +void FreeHrtfs(void) +{ + struct Hrtf *Hrtf = LoadedHrtfs; + LoadedHrtfs = NULL; + + while(Hrtf != NULL) + { + struct Hrtf *next = Hrtf->next; + al_free(Hrtf); + Hrtf = next; + } +} diff --git a/Engine/lib/openal-soft/Alc/hrtf.h b/Engine/lib/openal-soft/Alc/hrtf.h new file mode 100644 index 000000000..ebba0d50c --- /dev/null +++ b/Engine/lib/openal-soft/Alc/hrtf.h @@ -0,0 +1,52 @@ +#ifndef ALC_HRTF_H +#define ALC_HRTF_H + +#include "AL/al.h" +#include "AL/alc.h" + +#include "alstring.h" + + +struct Hrtf { + ALuint sampleRate; + ALuint irSize; + ALubyte evCount; + + const ALubyte *azCount; + const ALushort *evOffset; + const ALshort *coeffs; + const ALubyte *delays; + + const char *filename; + struct Hrtf *next; +}; + +typedef struct HrtfEntry { + al_string name; + + const struct Hrtf *hrtf; +} HrtfEntry; +TYPEDEF_VECTOR(HrtfEntry, vector_HrtfEntry) + +#define HRIR_BITS (7) +#define HRIR_LENGTH (1< +#include +#include +#include +#include + +#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" + + +static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE, + "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!"); + +extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *restrict frac_arr, ALuint *restrict pos_arr, ALuint size); + +alignas(16) union ResamplerCoeffs ResampleCoeffs; + + +enum Resampler { + PointResampler, + LinearResampler, + FIR4Resampler, + FIR8Resampler, + BSincResampler, + + ResamplerDefault = LinearResampler +}; + +/* FIR8 requires 3 extra samples before the current position, and 4 after. */ +static_assert(MAX_PRE_SAMPLES >= 3, "MAX_PRE_SAMPLES must be at least 3!"); +static_assert(MAX_POST_SAMPLES >= 4, "MAX_POST_SAMPLES must be at least 4!"); + + +static MixerFunc MixSamples = Mix_C; +static HrtfMixerFunc MixHrtfSamples = MixHrtf_C; +static ResamplerFunc ResampleSamples = Resample_point32_C; + +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; +} + +RowMixerFunc SelectRowMixer(void) +{ +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return MixRow_SSE; +#endif +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return MixRow_Neon; +#endif + return MixRow_C; +} + +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 ResamplerFunc SelectResampler(enum Resampler resampler) +{ + 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 FIR4Resampler: +#ifdef HAVE_SSE4_1 + if((CPUCapFlags&CPU_CAP_SSE4_1)) + return Resample_fir4_32_SSE41; +#endif +#ifdef HAVE_SSE3 + if((CPUCapFlags&CPU_CAP_SSE3)) + return Resample_fir4_32_SSE3; +#endif + return Resample_fir4_32_C; + case FIR8Resampler: +#ifdef HAVE_SSE4_1 + if((CPUCapFlags&CPU_CAP_SSE4_1)) + return Resample_fir8_32_SSE41; +#endif +#ifdef HAVE_SSE3 + if((CPUCapFlags&CPU_CAP_SSE3)) + return Resample_fir8_32_SSE3; +#endif + return Resample_fir8_32_C; + case BSincResampler: +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return Resample_bsinc32_SSE; +#endif + return Resample_bsinc32_C; + } + + return Resample_point32_C; +} + + +/* The sinc resampler makes use of a Kaiser window to limit the needed sample + * points to 4 and 8, respectively. + */ + +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif +static inline double Sinc(double x) +{ + if(x == 0.0) return 1.0; + return sin(x*M_PI) / (x*M_PI); +} + +/* The zero-order modified Bessel function of the first kind, used for the + * Kaiser window. + * + * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k) + * = sum_{k=0}^inf ((x / 2)^k / k!)^2 + */ +static double BesselI_0(double x) +{ + double term, sum, x2, y, last_sum; + int k; + + /* Start at k=1 since k=0 is trivial. */ + term = 1.0; + sum = 1.0; + x2 = x / 2.0; + k = 1; + + /* Let the integration converge until the term of the sum is no longer + * significant. + */ + do { + y = x2 / k; + k ++; + last_sum = sum; + term *= y * y; + sum += term; + } while(sum != last_sum); + return sum; +} + +/* Calculate a Kaiser window from the given beta value and a normalized k + * [-1, 1]. + * + * w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B), -1 <= k <= 1 + * { 0, elsewhere. + * + * Where k can be calculated as: + * + * k = i / l, where -l <= i <= l. + * + * or: + * + * k = 2 i / M - 1, where 0 <= i <= M. + */ +static inline double Kaiser(double b, double k) +{ + if(k <= -1.0 || k >= 1.0) return 0.0; + return BesselI_0(b * sqrt(1.0 - (k*k))) / BesselI_0(b); +} + +static inline double CalcKaiserBeta(double rejection) +{ + if(rejection > 50.0) + return 0.1102 * (rejection - 8.7); + if(rejection >= 21.0) + return (0.5842 * pow(rejection - 21.0, 0.4)) + + (0.07886 * (rejection - 21.0)); + return 0.0; +} + +static float SincKaiser(double r, double x) +{ + /* Limit rippling to -60dB. */ + return (float)(Kaiser(CalcKaiserBeta(60.0), x / r) * Sinc(x)); +} + + +void aluInitMixer(void) +{ + enum Resampler resampler = ResamplerDefault; + const char *str; + ALuint i; + + if(ConfigValueStr(NULL, NULL, "resampler", &str)) + { + if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0) + resampler = PointResampler; + else if(strcasecmp(str, "linear") == 0) + resampler = LinearResampler; + else if(strcasecmp(str, "sinc4") == 0) + resampler = FIR4Resampler; + else if(strcasecmp(str, "sinc8") == 0) + resampler = FIR8Resampler; + else if(strcasecmp(str, "bsinc") == 0) + resampler = BSincResampler; + else if(strcasecmp(str, "cubic") == 0) + { + WARN("Resampler option \"cubic\" is deprecated, using sinc4\n"); + resampler = FIR4Resampler; + } + else + { + char *end; + long n = strtol(str, &end, 0); + if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == FIR4Resampler)) + resampler = n; + else + WARN("Invalid resampler: %s\n", str); + } + } + + if(resampler == FIR8Resampler) + for(i = 0;i < FRACTIONONE;i++) + { + ALdouble mu = (ALdouble)i / FRACTIONONE; + ResampleCoeffs.FIR8[i][0] = SincKaiser(4.0, mu - -3.0); + ResampleCoeffs.FIR8[i][1] = SincKaiser(4.0, mu - -2.0); + ResampleCoeffs.FIR8[i][2] = SincKaiser(4.0, mu - -1.0); + ResampleCoeffs.FIR8[i][3] = SincKaiser(4.0, mu - 0.0); + ResampleCoeffs.FIR8[i][4] = SincKaiser(4.0, mu - 1.0); + ResampleCoeffs.FIR8[i][5] = SincKaiser(4.0, mu - 2.0); + ResampleCoeffs.FIR8[i][6] = SincKaiser(4.0, mu - 3.0); + ResampleCoeffs.FIR8[i][7] = SincKaiser(4.0, mu - 4.0); + } + else if(resampler == FIR4Resampler) + for(i = 0;i < FRACTIONONE;i++) + { + ALdouble mu = (ALdouble)i / FRACTIONONE; + ResampleCoeffs.FIR4[i][0] = SincKaiser(2.0, mu - -1.0); + ResampleCoeffs.FIR4[i][1] = SincKaiser(2.0, mu - 0.0); + ResampleCoeffs.FIR4[i][2] = SincKaiser(2.0, mu - 1.0); + ResampleCoeffs.FIR4[i][3] = SincKaiser(2.0, mu - 2.0); + } + + MixHrtfSamples = SelectHrtfMixer(); + MixSamples = SelectMixer(); + ResampleSamples = SelectResampler(resampler); +} + + +static inline ALfloat Sample_ALbyte(ALbyte val) +{ 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 inline 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 inline 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: + ALfilterState_processPassthru(lpfilter, src, numsamples); + ALfilterState_processPassthru(hpfilter, src, numsamples); + break; + + case AF_LowPass: + ALfilterState_process(lpfilter, dst, src, numsamples); + ALfilterState_processPassthru(hpfilter, dst, numsamples); + return dst; + case AF_HighPass: + ALfilterState_processPassthru(lpfilter, src, numsamples); + ALfilterState_process(hpfilter, dst, src, numsamples); + return dst; + + case AF_BandPass: + for(i = 0;i < numsamples;) + { + ALfloat temp[256]; + ALuint todo = minu(256, numsamples-i); + + ALfilterState_process(lpfilter, temp, src+i, todo); + ALfilterState_process(hpfilter, dst+i, temp, todo); + i += todo; + } + return dst; + } + return src; +} + + +ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) +{ + ResamplerFunc Resample; + ALbufferlistitem *BufferListItem; + ALuint DataPosInt, DataPosFrac; + ALboolean Looping; + ALuint increment; + ALenum State; + ALuint OutPos; + ALuint NumChannels; + ALuint SampleSize; + ALint64 DataSize64; + ALuint Counter; + ALuint IrSize; + ALuint chan, send, j; + + /* Get source info */ + State = AL_PLAYING; /* Only called while playing. */ + BufferListItem = ATOMIC_LOAD(&Source->current_buffer); + DataPosInt = ATOMIC_LOAD(&Source->position, almemory_order_relaxed); + DataPosFrac = ATOMIC_LOAD(&Source->position_fraction, almemory_order_relaxed); + Looping = ATOMIC_LOAD(&Source->looping, almemory_order_relaxed); + NumChannels = Source->NumChannels; + SampleSize = Source->SampleSize; + increment = voice->Step; + + IrSize = (Device->Hrtf.Handle ? Device->Hrtf.Handle->irSize : 0); + + Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ? + Resample_copy32_C : ResampleSamples); + + Counter = voice->Moving ? SamplesToDo : 0; + OutPos = 0; + do { + ALuint SrcBufferSize, DstBufferSize; + + /* Figure out how many buffer samples will be needed */ + DataSize64 = SamplesToDo-OutPos; + DataSize64 *= increment; + DataSize64 += DataPosFrac+FRACTIONMASK; + DataSize64 >>= FRACTIONBITS; + DataSize64 += MAX_POST_SAMPLES+MAX_PRE_SAMPLES; + + SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE); + + /* Figure out how many samples we can actually mix from this. */ + DataSize64 = SrcBufferSize; + DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES; + 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; + + /* Load the previous samples into the source data first. */ + memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat)); + SrcDataSize = MAX_PRE_SAMPLES; + + if(Source->SourceType == AL_STATIC) + { + const ALbuffer *ALBuffer = BufferListItem->buffer; + const ALubyte *Data = ALBuffer->data; + ALuint DataSize; + ALuint pos; + + /* Offset buffer data to current channel */ + Data += chan*SampleSize; + + /* If current pos is beyond the loop range, do not loop */ + if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd) + { + Looping = AL_FALSE; + + /* Load what's left to play from the source buffer, and + * clear the rest of the temp buffer */ + pos = DataPosInt; + DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos); + + LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); + SrcDataSize += DataSize; + + SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize); + SrcDataSize += SrcBufferSize - SrcDataSize; + } + else + { + ALuint LoopStart = ALBuffer->LoopStart; + ALuint LoopEnd = ALBuffer->LoopEnd; + + /* Load what's left of this loop iteration, then load + * repeats of the loop section */ + pos = DataPosInt; + DataSize = LoopEnd - pos; + DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); + + LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); + SrcDataSize += DataSize; + + DataSize = LoopEnd-LoopStart; + while(SrcBufferSize > SrcDataSize) + { + DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); + + LoadSamples(&SrcData[SrcDataSize], &Data[LoopStart * NumChannels*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); + SrcDataSize += DataSize; + } + } + } + else + { + /* Crawl the buffer queue to fill in the temp buffer */ + ALbufferlistitem *tmpiter = BufferListItem; + ALuint pos = DataPosInt; + + 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; + } + } + } + + /* Store the last source samples used for next time. */ + memcpy(voice->PrevSamples[chan], + &SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS], + MAX_PRE_SAMPLES*sizeof(ALfloat) + ); + + /* Now resample, then filter and mix to the appropriate outputs. */ + ResampledData = Resample(&voice->SincState, + &SrcData[MAX_PRE_SAMPLES], DataPosFrac, increment, + Device->ResampledData, DstBufferSize + ); + { + DirectParams *parms = &voice->Chan[chan].Direct; + const ALfloat *samples; + + samples = DoFilters( + &parms->LowPass, &parms->HighPass, Device->FilteredData, + ResampledData, DstBufferSize, parms->FilterType + ); + if(!voice->IsHrtf) + { + if(!Counter) + memcpy(parms->Gains.Current, parms->Gains.Target, + sizeof(parms->Gains.Current)); + MixSamples(samples, voice->DirectOut.Channels, voice->DirectOut.Buffer, + parms->Gains.Current, parms->Gains.Target, Counter, OutPos, DstBufferSize + ); + } + else + { + MixHrtfParams hrtfparams; + int lidx, ridx; + + if(!Counter) + { + parms->Hrtf.Current = parms->Hrtf.Target; + for(j = 0;j < HRIR_LENGTH;j++) + { + hrtfparams.Steps.Coeffs[j][0] = 0.0f; + hrtfparams.Steps.Coeffs[j][1] = 0.0f; + } + hrtfparams.Steps.Delay[0] = 0; + hrtfparams.Steps.Delay[1] = 0; + } + else + { + ALfloat delta = 1.0f / (ALfloat)Counter; + ALfloat coeffdiff; + ALint delaydiff; + for(j = 0;j < IrSize;j++) + { + coeffdiff = parms->Hrtf.Target.Coeffs[j][0] - parms->Hrtf.Current.Coeffs[j][0]; + hrtfparams.Steps.Coeffs[j][0] = coeffdiff * delta; + coeffdiff = parms->Hrtf.Target.Coeffs[j][1] - parms->Hrtf.Current.Coeffs[j][1]; + hrtfparams.Steps.Coeffs[j][1] = coeffdiff * delta; + } + delaydiff = (ALint)(parms->Hrtf.Target.Delay[0] - parms->Hrtf.Current.Delay[0]); + hrtfparams.Steps.Delay[0] = fastf2i((ALfloat)delaydiff * delta); + delaydiff = (ALint)(parms->Hrtf.Target.Delay[1] - parms->Hrtf.Current.Delay[1]); + hrtfparams.Steps.Delay[1] = fastf2i((ALfloat)delaydiff * delta); + } + hrtfparams.Target = &parms->Hrtf.Target; + hrtfparams.Current = &parms->Hrtf.Current; + + lidx = GetChannelIdxByName(Device->RealOut, FrontLeft); + ridx = GetChannelIdxByName(Device->RealOut, FrontRight); + assert(lidx != -1 && ridx != -1); + + MixHrtfSamples(voice->DirectOut.Buffer, lidx, ridx, samples, Counter, + voice->Offset, OutPos, IrSize, &hrtfparams, + &parms->Hrtf.State, DstBufferSize); + } + } + + for(send = 0;send < Device->NumAuxSends;send++) + { + SendParams *parms = &voice->Chan[chan].Send[send]; + const ALfloat *samples; + + if(!voice->SendOut[send].Buffer) + continue; + + samples = DoFilters( + &parms->LowPass, &parms->HighPass, Device->FilteredData, + ResampledData, DstBufferSize, parms->FilterType + ); + + if(!Counter) + memcpy(parms->Gains.Current, parms->Gains.Target, + sizeof(parms->Gains.Current)); + MixSamples(samples, voice->SendOut[send].Channels, voice->SendOut[send].Buffer, + parms->Gains.Current, parms->Gains.Target, Counter, OutPos, DstBufferSize + ); + } + } + /* Update positions */ + DataPosFrac += increment*DstBufferSize; + DataPosInt += DataPosFrac>>FRACTIONBITS; + DataPosFrac &= FRACTIONMASK; + + OutPos += DstBufferSize; + voice->Offset += DstBufferSize; + Counter = maxu(DstBufferSize, Counter) - 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); + + voice->Moving = AL_TRUE; + + /* Update source info */ + Source->state = State; + ATOMIC_STORE(&Source->current_buffer, BufferListItem, almemory_order_relaxed); + ATOMIC_STORE(&Source->position, DataPosInt, almemory_order_relaxed); + ATOMIC_STORE(&Source->position_fraction, DataPosFrac); +} diff --git a/Engine/lib/openal-soft/Alc/mixer_c.c b/Engine/lib/openal-soft/Alc/mixer_c.c new file mode 100644 index 000000000..6ef818c78 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/mixer_c.c @@ -0,0 +1,228 @@ +#include "config.h" + +#include + +#include "alMain.h" +#include "alu.h" +#include "alSource.h" +#include "alAuxEffectSlot.h" + + +static inline ALfloat point32(const ALfloat *restrict vals, ALuint UNUSED(frac)) +{ return vals[0]; } +static inline ALfloat lerp32(const ALfloat *restrict vals, ALuint frac) +{ return lerp(vals[0], vals[1], frac * (1.0f/FRACTIONONE)); } +static inline ALfloat fir4_32(const ALfloat *restrict vals, ALuint frac) +{ return resample_fir4(vals[-1], vals[0], vals[1], vals[2], frac); } +static inline ALfloat fir8_32(const ALfloat *restrict vals, ALuint frac) +{ return resample_fir8(vals[-3], vals[-2], vals[-1], vals[0], vals[1], vals[2], vals[3], vals[4], frac); } + + +const ALfloat *Resample_copy32_C(const BsincState* UNUSED(state), const ALfloat *restrict src, ALuint UNUSED(frac), + ALuint UNUSED(increment), ALfloat *restrict dst, ALuint numsamples) +{ +#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 BsincState* UNUSED(state), \ + const ALfloat *restrict 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(fir4_32) +DECL_TEMPLATE(fir8_32) + +#undef DECL_TEMPLATE + +const ALfloat *Resample_bsinc32_C(const BsincState *state, const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint dstlen) +{ + const ALfloat *fil, *scd, *phd, *spd; + const ALfloat sf = state->sf; + const ALuint m = state->m; + const ALint l = state->l; + ALuint j_f, pi, i; + ALfloat pf, r; + ALint j_s; + + for(i = 0;i < dstlen;i++) + { + // Calculate the phase index and factor. +#define FRAC_PHASE_BITDIFF (FRACTIONBITS-BSINC_PHASE_BITS) + pi = frac >> FRAC_PHASE_BITDIFF; + pf = (frac & ((1<coeffs[pi].filter; + scd = state->coeffs[pi].scDelta; + phd = state->coeffs[pi].phDelta; + spd = state->coeffs[pi].spDelta; + + // Apply the scale and phase interpolated filter. + r = 0.0f; + for(j_f = 0,j_s = l;j_f < m;j_f++,j_s++) + r += (fil[j_f] + sf*scd[j_f] + pf*(phd[j_f] + sf*spd[j_f])) * + src[j_s]; + dst[i] = r; + + frac += increment; + src += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} + + +void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALuint numsamples) +{ + ALuint i; + if(numsamples > 1) + { + dst[0] = filter->b0 * src[0] + + filter->b1 * filter->x[0] + + filter->b2 * filter->x[1] - + filter->a1 * filter->y[0] - + filter->a2 * filter->y[1]; + dst[1] = filter->b0 * src[1] + + filter->b1 * src[0] + + filter->b2 * filter->x[0] - + filter->a1 * dst[0] - + filter->a2 * filter->y[0]; + for(i = 2;i < numsamples;i++) + dst[i] = filter->b0 * src[i] + + filter->b1 * src[i-1] + + filter->b2 * src[i-2] - + filter->a1 * dst[i-1] - + filter->a2 * dst[i-2]; + filter->x[0] = src[i-1]; + filter->x[1] = src[i-2]; + filter->y[0] = dst[i-1]; + filter->y[1] = dst[i-2]; + } + else if(numsamples == 1) + { + dst[0] = filter->b0 * src[0] + + filter->b1 * filter->x[0] + + filter->b2 * filter->x[1] - + filter->a1 * filter->y[0] - + filter->a2 * filter->y[1]; + filter->x[1] = filter->x[0]; + filter->x[0] = src[0]; + filter->y[1] = filter->y[0]; + filter->y[0] = dst[0]; + } +} + + +static inline void 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 MixHrtf MixHrtf_C +#define MixDirectHrtf MixDirectHrtf_C +#include "mixer_inc.c" +#undef MixHrtf + + +void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + ALfloat *CurrentGains, const ALfloat *TargetGains, ALuint Counter, ALuint OutPos, + ALuint BufferSize) +{ + ALfloat gain, delta, step; + ALuint c; + + delta = (Counter > 0) ? 1.0f/(ALfloat)Counter : 0.0f; + + for(c = 0;c < OutChans;c++) + { + ALuint pos = 0; + gain = CurrentGains[c]; + step = (TargetGains[c] - gain) * delta; + if(fabsf(step) > FLT_EPSILON) + { + ALuint minsize = minu(BufferSize, Counter); + for(;pos < minsize;pos++) + { + OutBuffer[c][OutPos+pos] += data[pos]*gain; + gain += step; + } + if(pos == Counter) + gain = TargetGains[c]; + CurrentGains[c] = gain; + } + + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; + for(;pos < BufferSize;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; + } +} + +/* Basically the inverse of the above. Rather than one input going to multiple + * outputs (each with its own gain), it's multiple inputs (each with its own + * gain) going to one output. This applies one row (vs one column) of a matrix + * transform. And as the matrices are more or less static once set up, no + * stepping is necessary. + */ +void MixRow_C(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans, ALuint InPos, ALuint BufferSize) +{ + ALuint c, i; + + for(c = 0;c < InChans;c++) + { + ALfloat gain = Gains[c]; + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; + + for(i = 0;i < BufferSize;i++) + OutBuffer[i] += data[c][InPos+i] * gain; + } +} diff --git a/Engine/lib/openal-soft/Alc/mixer_defs.h b/Engine/lib/openal-soft/Alc/mixer_defs.h new file mode 100644 index 000000000..249160025 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/mixer_defs.h @@ -0,0 +1,110 @@ +#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 MixHrtfParams; +struct HrtfState; + +/* C resamplers */ +const ALfloat *Resample_copy32_C(const BsincState *state, const ALfloat *restrict src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); +const ALfloat *Resample_point32_C(const BsincState *state, const ALfloat *restrict src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); +const ALfloat *Resample_lerp32_C(const BsincState *state, const ALfloat *restrict src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); +const ALfloat *Resample_fir4_32_C(const BsincState *state, const ALfloat *restrict src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); +const ALfloat *Resample_fir8_32_C(const BsincState *state, const ALfloat *restrict src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); +const ALfloat *Resample_bsinc32_C(const BsincState *state, const ALfloat *restrict src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); + + +/* C mixers */ +void MixHrtf_C(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos, + const ALuint IrSize, const struct MixHrtfParams *hrtfparams, + struct HrtfState *hrtfstate, ALuint BufferSize); +void MixDirectHrtf_C(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Offset, const ALuint IrSize, + ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2], + ALuint BufferSize); +void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + ALfloat *CurrentGains, const ALfloat *TargetGains, ALuint Counter, ALuint OutPos, + ALuint BufferSize); +void MixRow_C(ALfloat *OutBuffer, const ALfloat *Gains, + const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans, + ALuint InPos, ALuint BufferSize); + +/* SSE mixers */ +void MixHrtf_SSE(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos, + const ALuint IrSize, const struct MixHrtfParams *hrtfparams, + struct HrtfState *hrtfstate, ALuint BufferSize); +void MixDirectHrtf_SSE(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Offset, const ALuint IrSize, + ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2], + ALuint BufferSize); +void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + ALfloat *CurrentGains, const ALfloat *TargetGains, ALuint Counter, ALuint OutPos, + ALuint BufferSize); +void MixRow_SSE(ALfloat *OutBuffer, const ALfloat *Gains, + const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans, + ALuint InPos, ALuint BufferSize); + +/* SSE resamplers */ +inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *restrict frac_arr, ALuint *restrict 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_bsinc32_SSE(const BsincState *state, const ALfloat *restrict src, ALuint frac, + ALuint increment, ALfloat *restrict dst, ALuint dstlen); + +const ALfloat *Resample_lerp32_SSE2(const BsincState *state, const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples); +const ALfloat *Resample_lerp32_SSE41(const BsincState *state, const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples); + +const ALfloat *Resample_fir4_32_SSE3(const BsincState *state, const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples); +const ALfloat *Resample_fir4_32_SSE41(const BsincState *state, const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples); + +const ALfloat *Resample_fir8_32_SSE3(const BsincState *state, const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples); +const ALfloat *Resample_fir8_32_SSE41(const BsincState *state, const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples); + +/* Neon mixers */ +void MixHrtf_Neon(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos, + const ALuint IrSize, const struct MixHrtfParams *hrtfparams, + struct HrtfState *hrtfstate, ALuint BufferSize); +void MixDirectHrtf_Neon(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Offset, const ALuint IrSize, + ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2], + ALuint BufferSize); +void Mix_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + ALfloat *CurrentGains, const ALfloat *TargetGains, ALuint Counter, ALuint OutPos, + ALuint BufferSize); +void MixRow_Neon(ALfloat *OutBuffer, const ALfloat *Gains, + const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans, + ALuint InPos, ALuint BufferSize); + +#endif /* MIXER_DEFS_H */ diff --git a/Engine/lib/openal-soft/Alc/mixer_inc.c b/Engine/lib/openal-soft/Alc/mixer_inc.c new file mode 100644 index 000000000..25dc2b588 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/mixer_inc.c @@ -0,0 +1,149 @@ +#include "config.h" + +#include "alMain.h" +#include "alSource.h" + +#include "hrtf.h" +#include "mixer_defs.h" +#include "align.h" +#include "alu.h" + + +#define MAX_UPDATE_SAMPLES 128 + + +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], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos, + const ALuint IrSize, const MixHrtfParams *hrtfparams, HrtfState *hrtfstate, + ALuint BufferSize) +{ + ALfloat (*Coeffs)[2] = hrtfparams->Current->Coeffs; + ALuint Delay[2] = { hrtfparams->Current->Delay[0], hrtfparams->Current->Delay[1] }; + ALfloat out[MAX_UPDATE_SAMPLES][2]; + ALfloat left, right; + ALuint minsize; + ALuint pos, i; + + pos = 0; + if(Counter == 0) + goto skip_stepping; + + minsize = minu(BufferSize, Counter); + while(pos < minsize) + { + ALuint todo = minu(minsize-pos, MAX_UPDATE_SAMPLES); + + for(i = 0;i < todo;i++) + { + hrtfstate->History[Offset&HRTF_HISTORY_MASK] = data[pos++]; + left = lerp(hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&HRTF_HISTORY_MASK], + hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&HRTF_HISTORY_MASK], + (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE)); + right = lerp(hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&HRTF_HISTORY_MASK], + hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&HRTF_HISTORY_MASK], + (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE)); + + Delay[0] += hrtfparams->Steps.Delay[0]; + Delay[1] += hrtfparams->Steps.Delay[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->Steps.Coeffs, left, right); + out[i][0] = hrtfstate->Values[Offset&HRIR_MASK][0]; + out[i][1] = hrtfstate->Values[Offset&HRIR_MASK][1]; + } + + for(i = 0;i < todo;i++) + OutBuffer[lidx][OutPos+i] += out[i][0]; + for(i = 0;i < todo;i++) + OutBuffer[ridx][OutPos+i] += out[i][1]; + OutPos += todo; + } + + if(pos == Counter) + { + *hrtfparams->Current = *hrtfparams->Target; + Delay[0] = hrtfparams->Target->Delay[0]; + Delay[1] = hrtfparams->Target->Delay[1]; + } + else + { + hrtfparams->Current->Delay[0] = Delay[0]; + hrtfparams->Current->Delay[1] = Delay[1]; + } + +skip_stepping: + Delay[0] >>= HRTFDELAY_BITS; + Delay[1] >>= HRTFDELAY_BITS; + while(pos < BufferSize) + { + ALuint todo = minu(BufferSize-pos, MAX_UPDATE_SAMPLES); + + for(i = 0;i < todo;i++) + { + hrtfstate->History[Offset&HRTF_HISTORY_MASK] = data[pos++]; + left = hrtfstate->History[(Offset-Delay[0])&HRTF_HISTORY_MASK]; + right = hrtfstate->History[(Offset-Delay[1])&HRTF_HISTORY_MASK]; + + hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f; + hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f; + Offset++; + + ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right); + out[i][0] = hrtfstate->Values[Offset&HRIR_MASK][0]; + out[i][1] = hrtfstate->Values[Offset&HRIR_MASK][1]; + } + + for(i = 0;i < todo;i++) + OutBuffer[lidx][OutPos+i] += out[i][0]; + for(i = 0;i < todo;i++) + OutBuffer[ridx][OutPos+i] += out[i][1]; + OutPos += todo; + } +} + +void MixDirectHrtf(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Offset, const ALuint IrSize, + ALfloat (*restrict Coeffs)[2], ALfloat (*restrict Values)[2], + ALuint BufferSize) +{ + ALfloat out[MAX_UPDATE_SAMPLES][2]; + ALfloat insample; + ALuint pos, i; + + for(pos = 0;pos < BufferSize;) + { + ALuint todo = minu(BufferSize-pos, MAX_UPDATE_SAMPLES); + + for(i = 0;i < todo;i++) + { + Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f; + Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f; + Offset++; + + insample = *(data++); + ApplyCoeffs(Offset, Values, IrSize, Coeffs, insample, insample); + out[i][0] = Values[Offset&HRIR_MASK][0]; + out[i][1] = Values[Offset&HRIR_MASK][1]; + } + + for(i = 0;i < todo;i++) + OutBuffer[lidx][pos+i] += out[i][0]; + for(i = 0;i < todo;i++) + OutBuffer[ridx][pos+i] += out[i][1]; + pos += todo; + } +} diff --git a/Engine/lib/openal-soft/Alc/mixer_neon.c b/Engine/lib/openal-soft/Alc/mixer_neon.c new file mode 100644 index 000000000..6b506357b --- /dev/null +++ b/Engine/lib/openal-soft/Alc/mixer_neon.c @@ -0,0 +1,173 @@ +#include "config.h" + +#include + +#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 MixHrtf MixHrtf_Neon +#define MixDirectHrtf MixDirectHrtf_Neon +#include "mixer_inc.c" +#undef MixHrtf + + +void Mix_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + ALfloat *CurrentGains, const ALfloat *TargetGains, ALuint Counter, ALuint OutPos, + ALuint BufferSize) +{ + ALfloat gain, delta, step; + float32x4_t gain4; + ALuint c; + + delta = (Counter > 0) ? 1.0f/(ALfloat)Counter : 0.0f; + + for(c = 0;c < OutChans;c++) + { + ALuint pos = 0; + gain = CurrentGains[c]; + step = (TargetGains[c] - gain) * delta; + if(fabsf(step) > FLT_EPSILON) + { + ALuint minsize = minu(BufferSize, Counter); + /* Mix with applying gain steps in aligned multiples of 4. */ + if(minsize-pos > 3) + { + float32x4_t step4; + gain4 = vsetq_lane_f32(gain, gain4, 0); + gain4 = vsetq_lane_f32(gain + step, gain4, 1); + gain4 = vsetq_lane_f32(gain + step + step, gain4, 2); + gain4 = vsetq_lane_f32(gain + step + step + step, gain4, 3); + step4 = vdupq_n_f32(step + step + step + step); + do { + const float32x4_t val4 = vld1q_f32(&data[pos]); + float32x4_t dry4 = vld1q_f32(&OutBuffer[c][OutPos+pos]); + dry4 = vmlaq_f32(dry4, val4, gain4); + gain4 = vaddq_f32(gain4, step4); + vst1q_f32(&OutBuffer[c][OutPos+pos], dry4); + pos += 4; + } while(minsize-pos > 3); + /* NOTE: gain4 now represents the next four gains after the + * last four mixed samples, so the lowest element represents + * the next gain to apply. + */ + gain = vgetq_lane_f32(gain4, 0); + } + /* Mix with applying left over gain steps that aren't aligned multiples of 4. */ + for(;pos < minsize;pos++) + { + OutBuffer[c][OutPos+pos] += data[pos]*gain; + gain += step; + } + if(pos == Counter) + gain = TargetGains[c]; + CurrentGains[c] = gain; + + /* Mix until pos is aligned with 4 or the mix is done. */ + minsize = minu(BufferSize, (pos+3)&~3); + for(;pos < minsize;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; + } + + if(!(fabsf(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 = vmlaq_f32(dry4, val4, gain4); + vst1q_f32(&OutBuffer[c][OutPos+pos], dry4); + } + for(;pos < BufferSize;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; + } +} + +void MixRow_Neon(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans, ALuint InPos, ALuint BufferSize) +{ + float32x4_t gain4; + ALuint c; + + for(c = 0;c < InChans;c++) + { + ALuint pos = 0; + ALfloat gain = Gains[c]; + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; + + gain4 = vdupq_n_f32(gain); + for(;BufferSize-pos > 3;pos += 4) + { + const float32x4_t val4 = vld1q_f32(&data[c][InPos+pos]); + float32x4_t dry4 = vld1q_f32(&OutBuffer[pos]); + dry4 = vmlaq_f32(dry4, val4, gain4); + vst1q_f32(&OutBuffer[pos], dry4); + } + for(;pos < BufferSize;pos++) + OutBuffer[pos] += data[c][InPos+pos]*gain; + } +} diff --git a/Engine/lib/openal-soft/Alc/mixer_sse.c b/Engine/lib/openal-soft/Alc/mixer_sse.c new file mode 100644 index 000000000..f5e21e23d --- /dev/null +++ b/Engine/lib/openal-soft/Alc/mixer_sse.c @@ -0,0 +1,292 @@ +#include "config.h" + +#include + +#include "AL/al.h" +#include "AL/alc.h" +#include "alMain.h" +#include "alu.h" + +#include "alSource.h" +#include "alAuxEffectSlot.h" +#include "mixer_defs.h" + + +const ALfloat *Resample_bsinc32_SSE(const BsincState *state, const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint dstlen) +{ + const __m128 sf4 = _mm_set1_ps(state->sf); + const ALuint m = state->m; + const ALint l = state->l; + const ALfloat *fil, *scd, *phd, *spd; + ALuint pi, j_f, i; + ALfloat pf; + ALint j_s; + __m128 r4; + + for(i = 0;i < dstlen;i++) + { + // Calculate the phase index and factor. +#define FRAC_PHASE_BITDIFF (FRACTIONBITS-BSINC_PHASE_BITS) + pi = frac >> FRAC_PHASE_BITDIFF; + pf = (frac & ((1<coeffs[pi].filter; + scd = state->coeffs[pi].scDelta; + phd = state->coeffs[pi].phDelta; + spd = state->coeffs[pi].spDelta; + + // Apply the scale and phase interpolated filter. + r4 = _mm_setzero_ps(); + { + const __m128 pf4 = _mm_set1_ps(pf); + for(j_f = 0,j_s = l;j_f < m;j_f+=4,j_s+=4) + { + const __m128 f4 = _mm_add_ps( + _mm_add_ps( + _mm_load_ps(&fil[j_f]), + _mm_mul_ps(sf4, _mm_load_ps(&scd[j_f])) + ), + _mm_mul_ps( + pf4, + _mm_add_ps( + _mm_load_ps(&phd[j_f]), + _mm_mul_ps(sf4, _mm_load_ps(&spd[j_f])) + ) + ) + ); + r4 = _mm_add_ps(r4, _mm_mul_ps(f4, _mm_loadu_ps(&src[j_s]))); + } + } + r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); + r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); + dst[i] = _mm_cvtss_f32(r4); + + frac += increment; + src += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} + + +static inline void 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 MixHrtf MixHrtf_SSE +#define MixDirectHrtf MixDirectHrtf_SSE +#include "mixer_inc.c" +#undef MixHrtf + + +void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + ALfloat *CurrentGains, const ALfloat *TargetGains, ALuint Counter, ALuint OutPos, + ALuint BufferSize) +{ + ALfloat gain, delta, step; + __m128 gain4; + ALuint c; + + delta = (Counter > 0) ? 1.0f/(ALfloat)Counter : 0.0f; + + for(c = 0;c < OutChans;c++) + { + ALuint pos = 0; + gain = CurrentGains[c]; + step = (TargetGains[c] - gain) * delta; + if(fabsf(step) > FLT_EPSILON) + { + ALuint minsize = minu(BufferSize, Counter); + /* Mix with applying gain steps in aligned multiples of 4. */ + if(minsize-pos > 3) + { + __m128 step4; + 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_add_ps(gain4, step4); + _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4); + pos += 4; + } while(minsize-pos > 3); + /* NOTE: gain4 now represents the next four gains after the + * last four mixed samples, so the lowest element represents + * the next gain to apply. + */ + gain = _mm_cvtss_f32(gain4); + } + /* Mix with applying left over gain steps that aren't aligned multiples of 4. */ + for(;pos < minsize;pos++) + { + OutBuffer[c][OutPos+pos] += data[pos]*gain; + gain += step; + } + if(pos == Counter) + gain = TargetGains[c]; + CurrentGains[c] = gain; + + /* Mix until pos is aligned with 4 or the mix is done. */ + minsize = minu(BufferSize, (pos+3)&~3); + for(;pos < minsize;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; + } + + if(!(fabsf(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; + } +} + +void MixRow_SSE(ALfloat *OutBuffer, const ALfloat *Gains, const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans, ALuint InPos, ALuint BufferSize) +{ + __m128 gain4; + ALuint c; + + for(c = 0;c < InChans;c++) + { + ALuint pos = 0; + ALfloat gain = Gains[c]; + if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD)) + continue; + + gain4 = _mm_set1_ps(gain); + for(;BufferSize-pos > 3;pos += 4) + { + const __m128 val4 = _mm_load_ps(&data[c][InPos+pos]); + __m128 dry4 = _mm_load_ps(&OutBuffer[pos]); + dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4)); + _mm_store_ps(&OutBuffer[pos], dry4); + } + for(;pos < BufferSize;pos++) + OutBuffer[pos] += data[c][InPos+pos]*gain; + } +} diff --git a/Engine/lib/openal-soft/Alc/mixer_sse2.c b/Engine/lib/openal-soft/Alc/mixer_sse2.c new file mode 100644 index 000000000..22a18ef3d --- /dev/null +++ b/Engine/lib/openal-soft/Alc/mixer_sse2.c @@ -0,0 +1,82 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2014 by Timothy Arceri . + * 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 +#include + +#include "alu.h" +#include "mixer_defs.h" + + +const ALfloat *Resample_lerp32_SSE2(const BsincState* UNUSED(state), const ALfloat *restrict 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); + union { alignas(16) ALuint i[4]; float f[4]; } pos_; + union { alignas(16) ALuint i[4]; float f[4]; } frac_; + __m128i frac4, pos4; + ALuint pos; + ALuint i; + + InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4); + + frac4 = _mm_castps_si128(_mm_load_ps(frac_.f)); + pos4 = _mm_castps_si128(_mm_load_ps(pos_.f)); + + for(i = 0;numsamples-i > 3;i += 4) + { + const __m128 val1 = _mm_setr_ps(src[pos_.i[0]], src[pos_.i[1]], src[pos_.i[2]], src[pos_.i[3]]); + const __m128 val2 = _mm_setr_ps(src[pos_.i[0]+1], src[pos_.i[1]+1], src[pos_.i[2]+1], src[pos_.i[3]+1]); + + /* val1 + (val2-val1)*mu */ + const __m128 r0 = _mm_sub_ps(val2, val1); + const __m128 mu = _mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4); + const __m128 out = _mm_add_ps(val1, _mm_mul_ps(mu, r0)); + + _mm_store_ps(&dst[i], out); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS)); + frac4 = _mm_and_si128(frac4, fracMask4); + + _mm_store_ps(pos_.f, _mm_castsi128_ps(pos4)); + } + + /* NOTE: These four elements represent the position *after* the last four + * samples, so the lowest element is the next position to resample. + */ + pos = pos_.i[0]; + frac = _mm_cvtsi128_si32(frac4); + + for(;i < numsamples;i++) + { + dst[i] = lerp(src[pos], src[pos+1], frac * (1.0f/FRACTIONONE)); + + frac += increment; + pos += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} diff --git a/Engine/lib/openal-soft/Alc/mixer_sse3.c b/Engine/lib/openal-soft/Alc/mixer_sse3.c new file mode 100644 index 000000000..66005e534 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/mixer_sse3.c @@ -0,0 +1,164 @@ +/** + * OpenAL cross platform audio library, SSE3 mixer functions + * + * Copyright (C) 2014 by Timothy Arceri . + * Copyright (C) 2015 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include +#include + +#include "alu.h" +#include "mixer_defs.h" + + +const ALfloat *Resample_fir4_32_SSE3(const BsincState* UNUSED(state), const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples) +{ + const __m128i increment4 = _mm_set1_epi32(increment*4); + const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK); + union { alignas(16) ALuint i[4]; float f[4]; } pos_; + union { alignas(16) ALuint i[4]; float f[4]; } frac_; + __m128i frac4, pos4; + ALuint pos; + ALuint i; + + InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4); + + frac4 = _mm_castps_si128(_mm_load_ps(frac_.f)); + pos4 = _mm_castps_si128(_mm_load_ps(pos_.f)); + + --src; + for(i = 0;numsamples-i > 3;i += 4) + { + const __m128 val0 = _mm_loadu_ps(&src[pos_.i[0]]); + const __m128 val1 = _mm_loadu_ps(&src[pos_.i[1]]); + const __m128 val2 = _mm_loadu_ps(&src[pos_.i[2]]); + const __m128 val3 = _mm_loadu_ps(&src[pos_.i[3]]); + __m128 k0 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[0]]); + __m128 k1 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[1]]); + __m128 k2 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[2]]); + __m128 k3 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[3]]); + __m128 out; + + k0 = _mm_mul_ps(k0, val0); + k1 = _mm_mul_ps(k1, val1); + k2 = _mm_mul_ps(k2, val2); + k3 = _mm_mul_ps(k3, val3); + k0 = _mm_hadd_ps(k0, k1); + k2 = _mm_hadd_ps(k2, k3); + out = _mm_hadd_ps(k0, k2); + + _mm_store_ps(&dst[i], out); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS)); + frac4 = _mm_and_si128(frac4, fracMask4); + + _mm_store_ps(pos_.f, _mm_castsi128_ps(pos4)); + _mm_store_ps(frac_.f, _mm_castsi128_ps(frac4)); + } + + /* NOTE: These four elements represent the position *after* the last four + * samples, so the lowest element is the next position to resample. + */ + pos = pos_.i[0]; + frac = frac_.i[0]; + + for(;i < numsamples;i++) + { + dst[i] = resample_fir4(src[pos], src[pos+1], src[pos+2], src[pos+3], frac); + + frac += increment; + pos += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} + +const ALfloat *Resample_fir8_32_SSE3(const BsincState* UNUSED(state), const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples) +{ + const __m128i increment4 = _mm_set1_epi32(increment*4); + const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK); + union { alignas(16) ALuint i[4]; float f[4]; } pos_; + union { alignas(16) ALuint i[4]; float f[4]; } frac_; + __m128i frac4, pos4; + ALuint pos; + ALuint i, j; + + InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4); + + frac4 = _mm_castps_si128(_mm_load_ps(frac_.f)); + pos4 = _mm_castps_si128(_mm_load_ps(pos_.f)); + + src -= 3; + for(i = 0;numsamples-i > 3;i += 4) + { + __m128 out[2]; + for(j = 0;j < 8;j+=4) + { + const __m128 val0 = _mm_loadu_ps(&src[pos_.i[0]+j]); + const __m128 val1 = _mm_loadu_ps(&src[pos_.i[1]+j]); + const __m128 val2 = _mm_loadu_ps(&src[pos_.i[2]+j]); + const __m128 val3 = _mm_loadu_ps(&src[pos_.i[3]+j]); + __m128 k0 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[0]][j]); + __m128 k1 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[1]][j]); + __m128 k2 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[2]][j]); + __m128 k3 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[3]][j]); + + k0 = _mm_mul_ps(k0, val0); + k1 = _mm_mul_ps(k1, val1); + k2 = _mm_mul_ps(k2, val2); + k3 = _mm_mul_ps(k3, val3); + k0 = _mm_hadd_ps(k0, k1); + k2 = _mm_hadd_ps(k2, k3); + out[j>>2] = _mm_hadd_ps(k0, k2); + } + + out[0] = _mm_add_ps(out[0], out[1]); + _mm_store_ps(&dst[i], out[0]); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS)); + frac4 = _mm_and_si128(frac4, fracMask4); + + _mm_store_ps(pos_.f, _mm_castsi128_ps(pos4)); + _mm_store_ps(frac_.f, _mm_castsi128_ps(frac4)); + } + + pos = pos_.i[0]; + frac = frac_.i[0]; + + for(;i < numsamples;i++) + { + dst[i] = resample_fir8(src[pos ], src[pos+1], src[pos+2], src[pos+3], + src[pos+4], src[pos+5], src[pos+6], src[pos+7], frac); + + frac += increment; + pos += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} diff --git a/Engine/lib/openal-soft/Alc/mixer_sse41.c b/Engine/lib/openal-soft/Alc/mixer_sse41.c new file mode 100644 index 000000000..7a4db6cf7 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/mixer_sse41.c @@ -0,0 +1,227 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2014 by Timothy Arceri . + * 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 +#include +#include + +#include "alu.h" +#include "mixer_defs.h" + + +const ALfloat *Resample_lerp32_SSE41(const BsincState* UNUSED(state), const ALfloat *restrict 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); + union { alignas(16) ALuint i[4]; float f[4]; } pos_; + union { alignas(16) 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); + } + + /* NOTE: These four elements represent the position *after* the last four + * samples, so the lowest element is the next position to resample. + */ + pos = pos_.i[0]; + frac = _mm_cvtsi128_si32(frac4); + + for(;i < numsamples;i++) + { + dst[i] = lerp(src[pos], src[pos+1], frac * (1.0f/FRACTIONONE)); + + frac += increment; + pos += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} + +const ALfloat *Resample_fir4_32_SSE41(const BsincState* UNUSED(state), const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples) +{ + const __m128i increment4 = _mm_set1_epi32(increment*4); + const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK); + union { alignas(16) ALuint i[4]; float f[4]; } pos_; + union { alignas(16) ALuint i[4]; float f[4]; } frac_; + __m128i frac4, pos4; + ALuint pos; + ALuint i; + + InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4); + + frac4 = _mm_castps_si128(_mm_load_ps(frac_.f)); + pos4 = _mm_castps_si128(_mm_load_ps(pos_.f)); + + --src; + for(i = 0;numsamples-i > 3;i += 4) + { + const __m128 val0 = _mm_loadu_ps(&src[pos_.i[0]]); + const __m128 val1 = _mm_loadu_ps(&src[pos_.i[1]]); + const __m128 val2 = _mm_loadu_ps(&src[pos_.i[2]]); + const __m128 val3 = _mm_loadu_ps(&src[pos_.i[3]]); + __m128 k0 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[0]]); + __m128 k1 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[1]]); + __m128 k2 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[2]]); + __m128 k3 = _mm_load_ps(ResampleCoeffs.FIR4[frac_.i[3]]); + __m128 out; + + k0 = _mm_mul_ps(k0, val0); + k1 = _mm_mul_ps(k1, val1); + k2 = _mm_mul_ps(k2, val2); + k3 = _mm_mul_ps(k3, val3); + k0 = _mm_hadd_ps(k0, k1); + k2 = _mm_hadd_ps(k2, k3); + out = _mm_hadd_ps(k0, k2); + + _mm_store_ps(&dst[i], out); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS)); + frac4 = _mm_and_si128(frac4, fracMask4); + + pos_.i[0] = _mm_extract_epi32(pos4, 0); + pos_.i[1] = _mm_extract_epi32(pos4, 1); + pos_.i[2] = _mm_extract_epi32(pos4, 2); + pos_.i[3] = _mm_extract_epi32(pos4, 3); + frac_.i[0] = _mm_extract_epi32(frac4, 0); + frac_.i[1] = _mm_extract_epi32(frac4, 1); + frac_.i[2] = _mm_extract_epi32(frac4, 2); + frac_.i[3] = _mm_extract_epi32(frac4, 3); + } + + pos = pos_.i[0]; + frac = frac_.i[0]; + + for(;i < numsamples;i++) + { + dst[i] = resample_fir4(src[pos], src[pos+1], src[pos+2], src[pos+3], frac); + + frac += increment; + pos += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} + +const ALfloat *Resample_fir8_32_SSE41(const BsincState* UNUSED(state), const ALfloat *restrict src, + ALuint frac, ALuint increment, ALfloat *restrict dst, + ALuint numsamples) +{ + const __m128i increment4 = _mm_set1_epi32(increment*4); + const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK); + union { alignas(16) ALuint i[4]; float f[4]; } pos_; + union { alignas(16) ALuint i[4]; float f[4]; } frac_; + __m128i frac4, pos4; + ALuint pos; + ALuint i, j; + + InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4); + + frac4 = _mm_castps_si128(_mm_load_ps(frac_.f)); + pos4 = _mm_castps_si128(_mm_load_ps(pos_.f)); + + src -= 3; + for(i = 0;numsamples-i > 3;i += 4) + { + __m128 out[2]; + for(j = 0;j < 8;j+=4) + { + const __m128 val0 = _mm_loadu_ps(&src[pos_.i[0]+j]); + const __m128 val1 = _mm_loadu_ps(&src[pos_.i[1]+j]); + const __m128 val2 = _mm_loadu_ps(&src[pos_.i[2]+j]); + const __m128 val3 = _mm_loadu_ps(&src[pos_.i[3]+j]); + __m128 k0 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[0]][j]); + __m128 k1 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[1]][j]); + __m128 k2 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[2]][j]); + __m128 k3 = _mm_load_ps(&ResampleCoeffs.FIR8[frac_.i[3]][j]); + + k0 = _mm_mul_ps(k0, val0); + k1 = _mm_mul_ps(k1, val1); + k2 = _mm_mul_ps(k2, val2); + k3 = _mm_mul_ps(k3, val3); + k0 = _mm_hadd_ps(k0, k1); + k2 = _mm_hadd_ps(k2, k3); + out[j>>2] = _mm_hadd_ps(k0, k2); + } + + out[0] = _mm_add_ps(out[0], out[1]); + _mm_store_ps(&dst[i], out[0]); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS)); + frac4 = _mm_and_si128(frac4, fracMask4); + + pos_.i[0] = _mm_extract_epi32(pos4, 0); + pos_.i[1] = _mm_extract_epi32(pos4, 1); + pos_.i[2] = _mm_extract_epi32(pos4, 2); + pos_.i[3] = _mm_extract_epi32(pos4, 3); + frac_.i[0] = _mm_extract_epi32(frac4, 0); + frac_.i[1] = _mm_extract_epi32(frac4, 1); + frac_.i[2] = _mm_extract_epi32(frac4, 2); + frac_.i[3] = _mm_extract_epi32(frac4, 3); + } + + pos = pos_.i[0]; + frac = frac_.i[0]; + + for(;i < numsamples;i++) + { + dst[i] = resample_fir8(src[pos ], src[pos+1], src[pos+2], src[pos+3], + src[pos+4], src[pos+5], src[pos+6], src[pos+7], frac); + + frac += increment; + pos += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} diff --git a/Engine/lib/openal-soft/Alc/panning.c b/Engine/lib/openal-soft/Alc/panning.c new file mode 100644 index 000000000..1162bbbcf --- /dev/null +++ b/Engine/lib/openal-soft/Alc/panning.c @@ -0,0 +1,1037 @@ +/** + * 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., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "alMain.h" +#include "alAuxEffectSlot.h" +#include "alu.h" +#include "bool.h" +#include "ambdec.h" +#include "bformatdec.h" +#include "uhjfilter.h" +#include "bs2b.h" + + +extern inline void CalcXYZCoeffs(ALfloat x, ALfloat y, ALfloat z, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]); + + +#define ZERO_ORDER_SCALE 0.0f +#define FIRST_ORDER_SCALE 1.0f +#define SECOND_ORDER_SCALE (1.0f / 1.22474f) +#define THIRD_ORDER_SCALE (1.0f / 1.30657f) + + +static const ALuint FuMa2ACN[MAX_AMBI_COEFFS] = { + 0, /* W */ + 3, /* X */ + 1, /* Y */ + 2, /* Z */ + 6, /* R */ + 7, /* S */ + 5, /* T */ + 8, /* U */ + 4, /* V */ + 12, /* K */ + 13, /* L */ + 11, /* M */ + 14, /* N */ + 10, /* O */ + 15, /* P */ + 9, /* Q */ +}; +static const ALuint ACN2ACN[MAX_AMBI_COEFFS] = { + 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15 +}; + +/* NOTE: These are scale factors as applied to Ambisonics content. Decoder + * coefficients should be divided by these values to get proper N3D scalings. + */ +static const ALfloat UnitScale[MAX_AMBI_COEFFS] = { + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f +}; +static const ALfloat SN3D2N3DScale[MAX_AMBI_COEFFS] = { + 1.000000000f, /* ACN 0 (W), sqrt(1) */ + 1.732050808f, /* ACN 1 (Y), sqrt(3) */ + 1.732050808f, /* ACN 2 (Z), sqrt(3) */ + 1.732050808f, /* ACN 3 (X), sqrt(3) */ + 2.236067978f, /* ACN 4 (V), sqrt(5) */ + 2.236067978f, /* ACN 5 (T), sqrt(5) */ + 2.236067978f, /* ACN 6 (R), sqrt(5) */ + 2.236067978f, /* ACN 7 (S), sqrt(5) */ + 2.236067978f, /* ACN 8 (U), sqrt(5) */ + 2.645751311f, /* ACN 9 (Q), sqrt(7) */ + 2.645751311f, /* ACN 10 (O), sqrt(7) */ + 2.645751311f, /* ACN 11 (M), sqrt(7) */ + 2.645751311f, /* ACN 12 (K), sqrt(7) */ + 2.645751311f, /* ACN 13 (L), sqrt(7) */ + 2.645751311f, /* ACN 14 (N), sqrt(7) */ + 2.645751311f, /* ACN 15 (P), sqrt(7) */ +}; +static const ALfloat FuMa2N3DScale[MAX_AMBI_COEFFS] = { + 1.414213562f, /* ACN 0 (W), sqrt(2) */ + 1.732050808f, /* ACN 1 (Y), sqrt(3) */ + 1.732050808f, /* ACN 2 (Z), sqrt(3) */ + 1.732050808f, /* ACN 3 (X), sqrt(3) */ + 1.936491673f, /* ACN 4 (V), sqrt(15)/2 */ + 1.936491673f, /* ACN 5 (T), sqrt(15)/2 */ + 2.236067978f, /* ACN 6 (R), sqrt(5) */ + 1.936491673f, /* ACN 7 (S), sqrt(15)/2 */ + 1.936491673f, /* ACN 8 (U), sqrt(15)/2 */ + 2.091650066f, /* ACN 9 (Q), sqrt(35/8) */ + 1.972026594f, /* ACN 10 (O), sqrt(35)/3 */ + 2.231093404f, /* ACN 11 (M), sqrt(224/45) */ + 2.645751311f, /* ACN 12 (K), sqrt(7) */ + 2.231093404f, /* ACN 13 (L), sqrt(224/45) */ + 1.972026594f, /* ACN 14 (N), sqrt(35)/3 */ + 2.091650066f, /* ACN 15 (P), sqrt(35/8) */ +}; + + +void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]) +{ + /* Convert from OpenAL coords to Ambisonics. */ + ALfloat x = -dir[2]; + ALfloat y = -dir[0]; + ALfloat z = dir[1]; + + /* Zeroth-order */ + coeffs[0] = 1.0f; /* ACN 0 = 1 */ + /* First-order */ + coeffs[1] = 1.732050808f * y; /* ACN 1 = sqrt(3) * Y */ + coeffs[2] = 1.732050808f * z; /* ACN 2 = sqrt(3) * Z */ + coeffs[3] = 1.732050808f * x; /* ACN 3 = sqrt(3) * X */ + /* Second-order */ + coeffs[4] = 3.872983346f * x * y; /* ACN 4 = sqrt(15) * X * Y */ + coeffs[5] = 3.872983346f * y * z; /* ACN 5 = sqrt(15) * Y * Z */ + coeffs[6] = 1.118033989f * (3.0f*z*z - 1.0f); /* ACN 6 = sqrt(5)/2 * (3*Z*Z - 1) */ + coeffs[7] = 3.872983346f * x * z; /* ACN 7 = sqrt(15) * X * Z */ + coeffs[8] = 1.936491673f * (x*x - y*y); /* ACN 8 = sqrt(15)/2 * (X*X - Y*Y) */ + /* Third-order */ + coeffs[9] = 2.091650066f * y * (3.0f*x*x - y*y); /* ACN 9 = sqrt(35/8) * Y * (3*X*X - Y*Y) */ + coeffs[10] = 10.246950766f * z * x * y; /* ACN 10 = sqrt(105) * Z * X * Y */ + coeffs[11] = 1.620185175f * y * (5.0f*z*z - 1.0f); /* ACN 11 = sqrt(21/8) * Y * (5*Z*Z - 1) */ + coeffs[12] = 1.322875656f * z * (5.0f*z*z - 3.0f); /* ACN 12 = sqrt(7)/2 * Z * (5*Z*Z - 3) */ + coeffs[13] = 1.620185175f * x * (5.0f*z*z - 1.0f); /* ACN 13 = sqrt(21/8) * X * (5*Z*Z - 1) */ + coeffs[14] = 5.123475383f * z * (x*x - y*y); /* ACN 14 = sqrt(105)/2 * Z * (X*X - Y*Y) */ + coeffs[15] = 2.091650066f * x * (x*x - 3.0f*y*y); /* ACN 15 = sqrt(35/8) * X * (X*X - 3*Y*Y) */ + + if(spread > 0.0f) + { + /* Implement the spread by using a spherical source that subtends the + * angle spread. See: + * http://www.ppsloan.org/publications/StupidSH36.pdf - Appendix A3 + * + * When adjusted for N3D normalization instead of SN3D, these + * calculations are: + * + * ZH0 = -sqrt(pi) * (-1+ca); + * ZH1 = 0.5*sqrt(pi) * sa*sa; + * ZH2 = -0.5*sqrt(pi) * ca*(-1+ca)*(ca+1); + * ZH3 = -0.125*sqrt(pi) * (-1+ca)*(ca+1)*(5*ca*ca - 1); + * ZH4 = -0.125*sqrt(pi) * ca*(-1+ca)*(ca+1)*(7*ca*ca - 3); + * ZH5 = -0.0625*sqrt(pi) * (-1+ca)*(ca+1)*(21*ca*ca*ca*ca - 14*ca*ca + 1); + * + * The gain of the source is compensated for size, so that the + * loundness doesn't depend on the spread. That is, the factors are + * scaled so that ZH0 remains 1 regardless of the spread. Thus: + * + * ZH0 = 1.0f; + * ZH1 = 0.5f * (ca+1.0f); + * ZH2 = 0.5f * (ca+1.0f)*ca; + * ZH3 = 0.125f * (ca+1.0f)*(5.0f*ca*ca - 1.0f); + * ZH4 = 0.125f * (ca+1.0f)*(7.0f*ca*ca - 3.0f)*ca; + * ZH5 = 0.0625f * (ca+1.0f)*(21.0f*ca*ca*ca*ca - 14.0f*ca*ca + 1.0f); + */ + ALfloat ca = cosf(spread * 0.5f); + + ALfloat ZH0_norm = 1.0f; + ALfloat ZH1_norm = 0.5f * (ca+1.f); + ALfloat ZH2_norm = 0.5f * (ca+1.f)*ca; + ALfloat ZH3_norm = 0.125f * (ca+1.f)*(5.f*ca*ca-1.f); + + /* Zeroth-order */ + coeffs[0] *= ZH0_norm; + /* First-order */ + coeffs[1] *= ZH1_norm; + coeffs[2] *= ZH1_norm; + coeffs[3] *= ZH1_norm; + /* Second-order */ + coeffs[4] *= ZH2_norm; + coeffs[5] *= ZH2_norm; + coeffs[6] *= ZH2_norm; + coeffs[7] *= ZH2_norm; + coeffs[8] *= ZH2_norm; + /* Third-order */ + coeffs[9] *= ZH3_norm; + coeffs[10] *= ZH3_norm; + coeffs[11] *= ZH3_norm; + coeffs[12] *= ZH3_norm; + coeffs[13] *= ZH3_norm; + coeffs[14] *= ZH3_norm; + coeffs[15] *= ZH3_norm; + } +} + +void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]) +{ + ALfloat dir[3] = { + sinf(azimuth) * cosf(elevation), + sinf(elevation), + -cosf(azimuth) * cosf(elevation) + }; + CalcDirectionCoeffs(dir, spread, coeffs); +} + + +void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +{ + ALuint i; + + for(i = 0;i < numchans;i++) + { + // The W coefficients are based on a mathematical average of the + // output. The square root of the base average provides for a more + // perceptual average volume, better suited to non-directional gains. + gains[i] = sqrtf(chancoeffs[i][0]) * ingain; + } + for(;i < MAX_OUTPUT_CHANNELS;i++) + gains[i] = 0.0f; +} + +void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +{ + ALfloat gain = 0.0f; + ALuint i; + + for(i = 0;i < numchans;i++) + { + if(chanmap[i].Index == 0) + gain += chanmap[i].Scale; + } + gains[0] = gain * 1.414213562f * ingain; + for(i = 1;i < MAX_OUTPUT_CHANNELS;i++) + gains[i] = 0.0f; +} + +void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALuint numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +{ + ALuint i, j; + + for(i = 0;i < numchans;i++) + { + float gain = 0.0f; + for(j = 0;j < numcoeffs;j++) + gain += chancoeffs[i][j]*coeffs[j]; + gains[i] = gain * ingain; + } + for(;i < MAX_OUTPUT_CHANNELS;i++) + gains[i] = 0.0f; +} + +void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +{ + ALuint i; + + for(i = 0;i < numchans;i++) + gains[i] = chanmap[i].Scale * coeffs[chanmap[i].Index] * ingain; + for(;i < MAX_OUTPUT_CHANNELS;i++) + gains[i] = 0.0f; +} + +void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +{ + ALuint i, j; + + for(i = 0;i < numchans;i++) + { + float gain = 0.0f; + for(j = 0;j < 4;j++) + gain += chancoeffs[i][j] * mtx[j]; + gains[i] = gain * ingain; + } + for(;i < MAX_OUTPUT_CHANNELS;i++) + gains[i] = 0.0f; +} + +void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]) +{ + ALuint i; + + for(i = 0;i < numchans;i++) + gains[i] = chanmap[i].Scale * mtx[chanmap[i].Index] * ingain; + for(;i < MAX_OUTPUT_CHANNELS;i++) + gains[i] = 0.0f; +} + + +static inline const char *GetLabelFromChannel(enum Channel channel) +{ + switch(channel) + { + case FrontLeft: return "front-left"; + case FrontRight: return "front-right"; + case FrontCenter: return "front-center"; + case LFE: return "lfe"; + case BackLeft: return "back-left"; + case BackRight: return "back-right"; + case BackCenter: return "back-center"; + case SideLeft: return "side-left"; + case SideRight: return "side-right"; + + case UpperFrontLeft: return "upper-front-left"; + case UpperFrontRight: return "upper-front-right"; + case UpperBackLeft: return "upper-back-left"; + case UpperBackRight: return "upper-back-right"; + case LowerFrontLeft: return "lower-front-left"; + case LowerFrontRight: return "lower-front-right"; + case LowerBackLeft: return "lower-back-left"; + case LowerBackRight: return "lower-back-right"; + + case Aux0: return "aux-0"; + case Aux1: return "aux-1"; + case Aux2: return "aux-2"; + case Aux3: return "aux-3"; + case Aux4: return "aux-4"; + case Aux5: return "aux-5"; + case Aux6: return "aux-6"; + case Aux7: return "aux-7"; + case Aux8: return "aux-8"; + case Aux9: return "aux-9"; + case Aux10: return "aux-10"; + case Aux11: return "aux-11"; + case Aux12: return "aux-12"; + case Aux13: return "aux-13"; + case Aux14: return "aux-14"; + case Aux15: return "aux-15"; + + case InvalidChannel: break; + } + return "(unknown)"; +} + + +typedef struct ChannelMap { + enum Channel ChanName; + ChannelConfig Config; +} ChannelMap; + +static void SetChannelMap(const enum Channel *devchans, ChannelConfig *ambicoeffs, + const ChannelMap *chanmap, size_t count, ALuint *outcount, + ALboolean isfuma) +{ + const ALuint *acnmap = isfuma ? FuMa2ACN : ACN2ACN; + const ALfloat *n3dscale = isfuma ? FuMa2N3DScale : UnitScale; + size_t j, k; + ALuint i; + + for(i = 0;i < MAX_OUTPUT_CHANNELS && devchans[i] != InvalidChannel;i++) + { + if(devchans[i] == LFE) + { + for(j = 0;j < MAX_AMBI_COEFFS;j++) + ambicoeffs[i][j] = 0.0f; + continue; + } + + for(j = 0;j < count;j++) + { + if(devchans[i] != chanmap[j].ChanName) + continue; + + for(k = 0;k < MAX_AMBI_COEFFS;++k) + { + ALuint acn = acnmap[k]; + ambicoeffs[i][acn] = chanmap[j].Config[k] / n3dscale[acn]; + } + break; + } + if(j == count) + ERR("Failed to match %s channel (%u) in channel map\n", GetLabelFromChannel(devchans[i]), i); + } + *outcount = i; +} + +static bool MakeSpeakerMap(ALCdevice *device, const AmbDecConf *conf, ALuint speakermap[MAX_OUTPUT_CHANNELS]) +{ + ALuint i; + + for(i = 0;i < conf->NumSpeakers;i++) + { + int c = -1; + + /* NOTE: AmbDec does not define any standard speaker names, however + * for this to work we have to by able to find the output channel + * the speaker definition corresponds to. Therefore, OpenAL Soft + * requires these channel labels to be recognized: + * + * LF = Front left + * RF = Front right + * LS = Side left + * RS = Side right + * LB = Back left + * RB = Back right + * CE = Front center + * CB = Back center + * + * Additionally, surround51 will acknowledge back speakers for side + * channels, and surround51rear will acknowledge side speakers for + * back channels, to avoid issues with an ambdec expecting 5.1 to + * use the side channels when the device is configured for back, + * and vice-versa. + */ + if(al_string_cmp_cstr(conf->Speakers[i].Name, "LF") == 0) + c = GetChannelIdxByName(device->RealOut, FrontLeft); + else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RF") == 0) + c = GetChannelIdxByName(device->RealOut, FrontRight); + else if(al_string_cmp_cstr(conf->Speakers[i].Name, "CE") == 0) + c = GetChannelIdxByName(device->RealOut, FrontCenter); + else if(al_string_cmp_cstr(conf->Speakers[i].Name, "LS") == 0) + { + if(device->FmtChans == DevFmtX51Rear) + c = GetChannelIdxByName(device->RealOut, BackLeft); + else + c = GetChannelIdxByName(device->RealOut, SideLeft); + } + else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RS") == 0) + { + if(device->FmtChans == DevFmtX51Rear) + c = GetChannelIdxByName(device->RealOut, BackRight); + else + c = GetChannelIdxByName(device->RealOut, SideRight); + } + else if(al_string_cmp_cstr(conf->Speakers[i].Name, "LB") == 0) + { + if(device->FmtChans == DevFmtX51) + c = GetChannelIdxByName(device->RealOut, SideLeft); + else + c = GetChannelIdxByName(device->RealOut, BackLeft); + } + else if(al_string_cmp_cstr(conf->Speakers[i].Name, "RB") == 0) + { + if(device->FmtChans == DevFmtX51) + c = GetChannelIdxByName(device->RealOut, SideRight); + else + c = GetChannelIdxByName(device->RealOut, BackRight); + } + else if(al_string_cmp_cstr(conf->Speakers[i].Name, "CB") == 0) + c = GetChannelIdxByName(device->RealOut, BackCenter); + else + { + const char *name = al_string_get_cstr(conf->Speakers[i].Name); + unsigned int n; + char ch; + + if(sscanf(name, "AUX%u%c", &n, &ch) == 1 && n < 16) + c = GetChannelIdxByName(device->RealOut, Aux0+n); + else + { + ERR("AmbDec speaker label \"%s\" not recognized\n", name); + return false; + } + } + if(c == -1) + { + ERR("Failed to lookup AmbDec speaker label %s\n", + al_string_get_cstr(conf->Speakers[i].Name)); + return false; + } + speakermap[i] = c; + } + + return true; +} + + +/* NOTE: These decoder coefficients are using FuMa channel ordering and + * normalization, since that's what was produced by the Ambisonic Decoder + * Toolbox. SetChannelMap will convert them to N3D. + */ +static const ChannelMap MonoCfg[1] = { + { FrontCenter, { 1.414213562f } }, +}, StereoCfg[2] = { + { FrontLeft, { 0.707106781f, 0.0f, 0.5f, 0.0f } }, + { FrontRight, { 0.707106781f, 0.0f, -0.5f, 0.0f } }, +}, QuadCfg[4] = { + { FrontLeft, { 0.353553f, 0.306186f, 0.306186f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.125000f } }, + { FrontRight, { 0.353553f, 0.306186f, -0.306186f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.125000f } }, + { BackLeft, { 0.353553f, -0.306186f, 0.306186f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.125000f } }, + { BackRight, { 0.353553f, -0.306186f, -0.306186f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.125000f } }, +}, X51SideCfg[5] = { + { FrontLeft, { 0.208954f, 0.199518f, 0.223424f, 0.0f, 0.0f, 0.0f, 0.0f, -0.012543f, 0.144260f } }, + { FrontRight, { 0.208950f, 0.199514f, -0.223425f, 0.0f, 0.0f, 0.0f, 0.0f, -0.012544f, -0.144258f } }, + { FrontCenter, { 0.109403f, 0.168250f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.100431f, -0.000001f } }, + { SideLeft, { 0.470934f, -0.346484f, 0.327504f, 0.0f, 0.0f, 0.0f, 0.0f, -0.022188f, -0.041113f } }, + { SideRight, { 0.470936f, -0.346480f, -0.327507f, 0.0f, 0.0f, 0.0f, 0.0f, -0.022186f, 0.041114f } }, +}, X51RearCfg[5] = { + { FrontLeft, { 0.208954f, 0.199518f, 0.223424f, 0.0f, 0.0f, 0.0f, 0.0f, -0.012543f, 0.144260f } }, + { FrontRight, { 0.208950f, 0.199514f, -0.223425f, 0.0f, 0.0f, 0.0f, 0.0f, -0.012544f, -0.144258f } }, + { FrontCenter, { 0.109403f, 0.168250f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.100431f, -0.000001f } }, + { BackLeft, { 0.470934f, -0.346484f, 0.327504f, 0.0f, 0.0f, 0.0f, 0.0f, -0.022188f, -0.041113f } }, + { BackRight, { 0.470936f, -0.346480f, -0.327507f, 0.0f, 0.0f, 0.0f, 0.0f, -0.022186f, 0.041114f } }, +}, X61Cfg[6] = { + { FrontLeft, { 0.167065f, 0.200583f, 0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, 0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, 0.068910f } }, + { FrontRight, { 0.167065f, 0.200583f, -0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, -0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, -0.068910f } }, + { FrontCenter, { 0.109403f, 0.179490f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, 0.000000f } }, + { BackCenter, { 0.353556f, -0.461940f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.165723f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.000000f } }, + { SideLeft, { 0.289151f, -0.081301f, 0.401292f, 0.0f, 0.0f, 0.0f, 0.0f, -0.188208f, -0.071420f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.010099f, -0.032897f } }, + { SideRight, { 0.289151f, -0.081301f, -0.401292f, 0.0f, 0.0f, 0.0f, 0.0f, -0.188208f, 0.071420f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.010099f, 0.032897f } }, +}, X71Cfg[7] = { + { FrontLeft, { 0.167065f, 0.200583f, 0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, 0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, 0.068910f } }, + { FrontRight, { 0.167065f, 0.200583f, -0.172695f, 0.0f, 0.0f, 0.0f, 0.0f, 0.029855f, -0.186407f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -0.039241f, -0.068910f } }, + { FrontCenter, { 0.109403f, 0.179490f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.142031f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.072024f, 0.000000f } }, + { BackLeft, { 0.224752f, -0.295009f, 0.170325f, 0.0f, 0.0f, 0.0f, 0.0f, 0.105349f, -0.182473f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.065799f } }, + { BackRight, { 0.224752f, -0.295009f, -0.170325f, 0.0f, 0.0f, 0.0f, 0.0f, 0.105349f, 0.182473f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.065799f } }, + { SideLeft, { 0.224739f, 0.000000f, 0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.065795f } }, + { SideRight, { 0.224739f, 0.000000f, -0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.065795f } }, +}; + +static void InitPanning(ALCdevice *device) +{ + const ChannelMap *chanmap = NULL; + ALuint coeffcount = 0; + ALfloat ambiscale; + size_t count = 0; + ALuint i, j; + + ambiscale = 1.0f; + switch(device->FmtChans) + { + case DevFmtMono: + count = COUNTOF(MonoCfg); + chanmap = MonoCfg; + ambiscale = ZERO_ORDER_SCALE; + coeffcount = 1; + break; + + case DevFmtStereo: + count = COUNTOF(StereoCfg); + chanmap = StereoCfg; + ambiscale = FIRST_ORDER_SCALE; + coeffcount = 4; + break; + + case DevFmtQuad: + count = COUNTOF(QuadCfg); + chanmap = QuadCfg; + ambiscale = SECOND_ORDER_SCALE; + coeffcount = 9; + break; + + case DevFmtX51: + count = COUNTOF(X51SideCfg); + chanmap = X51SideCfg; + ambiscale = SECOND_ORDER_SCALE; + coeffcount = 9; + break; + + case DevFmtX51Rear: + count = COUNTOF(X51RearCfg); + chanmap = X51RearCfg; + ambiscale = SECOND_ORDER_SCALE; + coeffcount = 9; + break; + + case DevFmtX61: + count = COUNTOF(X61Cfg); + chanmap = X61Cfg; + ambiscale = THIRD_ORDER_SCALE; + coeffcount = 16; + break; + + case DevFmtX71: + count = COUNTOF(X71Cfg); + chanmap = X71Cfg; + ambiscale = THIRD_ORDER_SCALE; + coeffcount = 16; + break; + + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + break; + } + + if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + { + const ALuint *acnmap = (device->AmbiFmt == AmbiFormat_FuMa) ? FuMa2ACN : ACN2ACN; + const ALfloat *n3dscale = (device->AmbiFmt == AmbiFormat_FuMa) ? FuMa2N3DScale : + (device->AmbiFmt == AmbiFormat_ACN_SN3D) ? SN3D2N3DScale : + /*(device->AmbiFmt == AmbiFormat_ACN_N3D) ?*/ UnitScale; + + count = (device->FmtChans == DevFmtAmbi3) ? 16 : + (device->FmtChans == DevFmtAmbi2) ? 9 : + (device->FmtChans == DevFmtAmbi1) ? 4 : 1; + for(i = 0;i < count;i++) + { + ALuint acn = acnmap[i]; + device->Dry.Ambi.Map[i].Scale = 1.0f/n3dscale[acn]; + device->Dry.Ambi.Map[i].Index = acn; + } + device->Dry.CoeffCount = 0; + device->Dry.NumChannels = count; + + if(device->FmtChans == DevFmtAmbi1) + { + device->FOAOut.Ambi = device->Dry.Ambi; + device->FOAOut.CoeffCount = device->Dry.CoeffCount; + } + else + { + /* FOA output is always ACN+N3D for higher-order ambisonic output. + * The upsampler expects this and will convert it for output. + */ + memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi)); + for(i = 0;i < 4;i++) + { + device->FOAOut.Ambi.Map[i].Scale = 1.0f; + device->FOAOut.Ambi.Map[i].Index = i; + } + device->FOAOut.CoeffCount = 0; + + ambiup_reset(device->AmbiUp, device); + } + } + else + { + SetChannelMap(device->RealOut.ChannelName, device->Dry.Ambi.Coeffs, + chanmap, count, &device->Dry.NumChannels, AL_TRUE); + device->Dry.CoeffCount = coeffcount; + + memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi)); + for(i = 0;i < device->Dry.NumChannels;i++) + { + device->FOAOut.Ambi.Coeffs[i][0] = device->Dry.Ambi.Coeffs[i][0]; + for(j = 1;j < 4;j++) + device->FOAOut.Ambi.Coeffs[i][j] = device->Dry.Ambi.Coeffs[i][j] * ambiscale; + } + device->FOAOut.CoeffCount = 4; + } +} + +static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const ALuint speakermap[MAX_OUTPUT_CHANNELS]) +{ + ChannelMap chanmap[MAX_OUTPUT_CHANNELS]; + const ALfloat *coeff_scale = UnitScale; + ALfloat ambiscale = 1.0f; + ALuint i, j; + + if(conf->FreqBands != 1) + ERR("Basic renderer uses the high-frequency matrix as single-band (xover_freq = %.0fhz)\n", + conf->XOverFreq); + + if(conf->ChanMask > 0x1ff) + ambiscale = THIRD_ORDER_SCALE; + else if(conf->ChanMask > 0xf) + ambiscale = SECOND_ORDER_SCALE; + else if(conf->ChanMask > 0x1) + ambiscale = FIRST_ORDER_SCALE; + else + ambiscale = 0.0f; + + if(conf->CoeffScale == ADS_SN3D) + coeff_scale = SN3D2N3DScale; + else if(conf->CoeffScale == ADS_FuMa) + coeff_scale = FuMa2N3DScale; + + for(i = 0;i < conf->NumSpeakers;i++) + { + ALuint chan = speakermap[i]; + ALfloat gain; + ALuint k = 0; + + for(j = 0;j < MAX_AMBI_COEFFS;j++) + chanmap[i].Config[j] = 0.0f; + + chanmap[i].ChanName = device->RealOut.ChannelName[chan]; + for(j = 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<HFMatrix[i][k++] / coeff_scale[j] * gain; + } + } + + SetChannelMap(device->RealOut.ChannelName, device->Dry.Ambi.Coeffs, chanmap, + conf->NumSpeakers, &device->Dry.NumChannels, AL_FALSE); + device->Dry.CoeffCount = (conf->ChanMask > 0x1ff) ? 16 : + (conf->ChanMask > 0xf) ? 9 : 4; + + memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi)); + for(i = 0;i < device->Dry.NumChannels;i++) + { + device->FOAOut.Ambi.Coeffs[i][0] = device->Dry.Ambi.Coeffs[i][0]; + for(j = 1;j < 4;j++) + device->FOAOut.Ambi.Coeffs[i][j] = device->Dry.Ambi.Coeffs[i][j] * ambiscale; + } + device->FOAOut.CoeffCount = 4; +} + +static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALuint speakermap[MAX_OUTPUT_CHANNELS]) +{ + const char *devname; + int decflags = 0; + size_t count; + ALuint i; + + devname = al_string_get_cstr(device->DeviceName); + if(GetConfigValueBool(devname, "decoder", "distance-comp", 1)) + decflags |= BFDF_DistanceComp; + + if((conf->ChanMask&AMBI_PERIPHONIC_MASK)) + { + count = (conf->ChanMask > 0x1ff) ? 16 : + (conf->ChanMask > 0xf) ? 9 : 4; + for(i = 0;i < count;i++) + { + device->Dry.Ambi.Map[i].Scale = 1.0f; + device->Dry.Ambi.Map[i].Index = i; + } + } + else + { + static const int map[MAX_AMBI2D_COEFFS] = { 0, 1, 3, 4, 8, 9, 15 }; + + count = (conf->ChanMask > 0x1ff) ? 7 : + (conf->ChanMask > 0xf) ? 5 : 3; + for(i = 0;i < count;i++) + { + device->Dry.Ambi.Map[i].Scale = 1.0f; + device->Dry.Ambi.Map[i].Index = map[i]; + } + } + device->Dry.CoeffCount = 0; + device->Dry.NumChannels = count; + + TRACE("Enabling %s-band %s-order%s ambisonic decoder\n", + (conf->FreqBands == 1) ? "single" : "dual", + (conf->ChanMask > 0xf) ? (conf->ChanMask > 0x1ff) ? "third" : "second" : "first", + (conf->ChanMask&AMBI_PERIPHONIC_MASK) ? " periphonic" : "" + ); + bformatdec_reset(device->AmbiDecoder, conf, count, device->Frequency, + speakermap, decflags); + + if(bformatdec_getOrder(device->AmbiDecoder) < 2) + { + device->FOAOut.Ambi = device->Dry.Ambi; + device->FOAOut.CoeffCount = device->Dry.CoeffCount; + } + else + { + memset(&device->FOAOut.Ambi, 0, sizeof(device->FOAOut.Ambi)); + for(i = 0;i < 4;i++) + { + device->FOAOut.Ambi.Map[i].Scale = 1.0f; + device->FOAOut.Ambi.Map[i].Index = i; + } + device->FOAOut.CoeffCount = 0; + } +} + +static void InitHrtfPanning(ALCdevice *device) +{ + size_t count = 4; + ALuint i; + + for(i = 0;i < count;i++) + { + device->Dry.Ambi.Map[i].Scale = 1.0f; + device->Dry.Ambi.Map[i].Index = i; + } + device->Dry.CoeffCount = 0; + device->Dry.NumChannels = count; + + device->FOAOut.Ambi = device->Dry.Ambi; + device->FOAOut.CoeffCount = device->Dry.CoeffCount; + + memset(device->Hrtf.Coeffs, 0, sizeof(device->Hrtf.Coeffs)); + device->Hrtf.IrSize = BuildBFormatHrtf(device->Hrtf.Handle, + device->Hrtf.Coeffs, device->Dry.NumChannels + ); + + /* Round up to the nearest multiple of 8 */ + device->Hrtf.IrSize = (device->Hrtf.IrSize+7)&~7; +} + +static void InitUhjPanning(ALCdevice *device) +{ + size_t count = 3; + ALuint i; + + for(i = 0;i < count;i++) + { + ALuint acn = FuMa2ACN[i]; + device->Dry.Ambi.Map[i].Scale = 1.0f/FuMa2N3DScale[acn]; + device->Dry.Ambi.Map[i].Index = acn; + } + device->Dry.CoeffCount = 0; + device->Dry.NumChannels = count; + + device->FOAOut.Ambi = device->Dry.Ambi; + device->FOAOut.CoeffCount = device->Dry.CoeffCount; +} + +void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq) +{ + const char *mode; + bool headphones; + int bs2blevel; + size_t i; + + device->Hrtf.Handle = NULL; + al_string_clear(&device->Hrtf.Name); + device->Render_Mode = NormalRender; + + memset(&device->Dry.Ambi, 0, sizeof(device->Dry.Ambi)); + device->Dry.CoeffCount = 0; + device->Dry.NumChannels = 0; + + if(device->FmtChans != DevFmtStereo) + { + ALuint speakermap[MAX_OUTPUT_CHANNELS]; + const char *devname, *layout = NULL; + AmbDecConf conf, *pconf = NULL; + + if(hrtf_appreq == Hrtf_Enable) + device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT; + + ambdec_init(&conf); + + devname = al_string_get_cstr(device->DeviceName); + switch(device->FmtChans) + { + case DevFmtQuad: layout = "quad"; break; + case DevFmtX51: layout = "surround51"; break; + case DevFmtX51Rear: layout = "surround51rear"; break; + case DevFmtX61: layout = "surround61"; break; + case DevFmtX71: layout = "surround71"; break; + /* Mono, Stereo, and Ambisonics output don't use custom decoders. */ + case DevFmtMono: + case DevFmtStereo: + case DevFmtAmbi1: + case DevFmtAmbi2: + case DevFmtAmbi3: + break; + } + if(layout) + { + const char *fname; + if(ConfigValueStr(devname, "decoder", layout, &fname)) + { + if(!ambdec_load(&conf, fname)) + ERR("Failed to load layout file %s\n", fname); + else + { + if(conf.ChanMask > 0xffff) + ERR("Unsupported channel mask 0x%04x (max 0xffff)\n", conf.ChanMask); + else + { + if(MakeSpeakerMap(device, &conf, speakermap)) + pconf = &conf; + } + } + } + } + + if(pconf && GetConfigValueBool(devname, "decoder", "hq-mode", 0)) + { + ambiup_free(device->AmbiUp); + device->AmbiUp = NULL; + if(!device->AmbiDecoder) + device->AmbiDecoder = bformatdec_alloc(); + } + else + { + bformatdec_free(device->AmbiDecoder); + device->AmbiDecoder = NULL; + if(device->FmtChans > DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3) + { + if(!device->AmbiUp) + device->AmbiUp = ambiup_alloc(); + } + else + { + ambiup_free(device->AmbiUp); + device->AmbiUp = NULL; + } + } + + if(!pconf) + InitPanning(device); + else if(device->AmbiDecoder) + InitHQPanning(device, pconf, speakermap); + else + InitCustomPanning(device, pconf, speakermap); + + ambdec_deinit(&conf); + return; + } + + ambiup_free(device->AmbiUp); + device->AmbiUp = NULL; + bformatdec_free(device->AmbiDecoder); + device->AmbiDecoder = NULL; + + headphones = device->IsHeadphones; + if(device->Type != Loopback) + { + const char *mode; + if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "stereo-mode", &mode)) + { + if(strcasecmp(mode, "headphones") == 0) + headphones = true; + else if(strcasecmp(mode, "speakers") == 0) + headphones = false; + else if(strcasecmp(mode, "auto") != 0) + ERR("Unexpected stereo-mode: %s\n", mode); + } + } + + if(hrtf_userreq == Hrtf_Default) + { + bool usehrtf = (headphones && hrtf_appreq != Hrtf_Disable) || + (hrtf_appreq == Hrtf_Enable); + if(!usehrtf) goto no_hrtf; + + device->Hrtf.Status = ALC_HRTF_ENABLED_SOFT; + if(headphones && hrtf_appreq != Hrtf_Disable) + device->Hrtf.Status = ALC_HRTF_HEADPHONES_DETECTED_SOFT; + } + else + { + if(hrtf_userreq != Hrtf_Enable) + { + if(hrtf_appreq == Hrtf_Enable) + device->Hrtf.Status = ALC_HRTF_DENIED_SOFT; + goto no_hrtf; + } + device->Hrtf.Status = ALC_HRTF_REQUIRED_SOFT; + } + + if(VECTOR_SIZE(device->Hrtf.List) == 0) + { + VECTOR_DEINIT(device->Hrtf.List); + device->Hrtf.List = EnumerateHrtf(device->DeviceName); + } + + if(hrtf_id >= 0 && (size_t)hrtf_id < VECTOR_SIZE(device->Hrtf.List)) + { + const HrtfEntry *entry = &VECTOR_ELEM(device->Hrtf.List, hrtf_id); + if(entry->hrtf->sampleRate == device->Frequency) + { + device->Hrtf.Handle = entry->hrtf; + al_string_copy(&device->Hrtf.Name, entry->name); + } + } + + for(i = 0;!device->Hrtf.Handle && i < VECTOR_SIZE(device->Hrtf.List);i++) + { + const HrtfEntry *entry = &VECTOR_ELEM(device->Hrtf.List, i); + if(entry->hrtf->sampleRate == device->Frequency) + { + device->Hrtf.Handle = entry->hrtf; + al_string_copy(&device->Hrtf.Name, entry->name); + } + } + + if(device->Hrtf.Handle) + { + device->Render_Mode = HrtfRender; + if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "hrtf-mode", &mode)) + { + if(strcasecmp(mode, "full") == 0) + device->Render_Mode = HrtfRender; + else if(strcasecmp(mode, "basic") == 0) + device->Render_Mode = NormalRender; + else + ERR("Unexpected hrtf-mode: %s\n", mode); + } + + TRACE("HRTF enabled, \"%s\"\n", al_string_get_cstr(device->Hrtf.Name)); + InitHrtfPanning(device); + return; + } + device->Hrtf.Status = ALC_HRTF_UNSUPPORTED_FORMAT_SOFT; + +no_hrtf: + TRACE("HRTF disabled\n"); + + bs2blevel = ((headphones && hrtf_appreq != Hrtf_Disable) || + (hrtf_appreq == Hrtf_Enable)) ? 5 : 0; + if(device->Type != Loopback) + ConfigValueInt(al_string_get_cstr(device->DeviceName), NULL, "cf_level", &bs2blevel); + if(bs2blevel > 0 && bs2blevel <= 6) + { + device->Bs2b = al_calloc(16, sizeof(*device->Bs2b)); + bs2b_set_params(device->Bs2b, bs2blevel, device->Frequency); + device->Render_Mode = StereoPair; + TRACE("BS2B enabled\n"); + InitPanning(device); + return; + } + + TRACE("BS2B disabled\n"); + + device->Render_Mode = NormalRender; + if(ConfigValueStr(al_string_get_cstr(device->DeviceName), NULL, "stereo-panning", &mode)) + { + if(strcasecmp(mode, "paired") == 0) + device->Render_Mode = StereoPair; + else if(strcasecmp(mode, "uhj") != 0) + ERR("Unexpected stereo-panning: %s\n", mode); + } + if(device->Render_Mode == NormalRender) + { + device->Uhj_Encoder = al_calloc(16, sizeof(Uhj2Encoder)); + TRACE("UHJ enabled\n"); + InitUhjPanning(device); + return; + } + + TRACE("UHJ disabled\n"); + InitPanning(device); +} + + +void aluInitEffectPanning(ALeffectslot *slot) +{ + ALuint i; + + memset(slot->ChanMap, 0, sizeof(slot->ChanMap)); + slot->NumChannels = 0; + + for(i = 0;i < MAX_EFFECT_CHANNELS;i++) + { + slot->ChanMap[i].Scale = 1.0f; + slot->ChanMap[i].Index = i; + } + slot->NumChannels = i; +} diff --git a/Engine/lib/openal-soft/Alc/uhjfilter.c b/Engine/lib/openal-soft/Alc/uhjfilter.c new file mode 100644 index 000000000..0a702873c --- /dev/null +++ b/Engine/lib/openal-soft/Alc/uhjfilter.c @@ -0,0 +1,134 @@ + +#include "config.h" + +#include "alu.h" +#include "uhjfilter.h" + +/* This is the maximum number of samples processed for each inner loop + * iteration. */ +#define MAX_UPDATE_SAMPLES 128 + + +static const ALfloat Filter1Coeff[4] = { + 0.6923878f, 0.9360654322959f, 0.9882295226860f, 0.9987488452737f +}; +static const ALfloat Filter2Coeff[4] = { + 0.4021921162426f, 0.8561710882420f, 0.9722909545651f, 0.9952884791278f +}; + +static void allpass_process(AllPassState *state, ALfloat *restrict dst, const ALfloat *restrict src, const ALfloat aa, ALuint todo) +{ + ALuint i; + + if(todo > 1) + { + dst[0] = aa*(src[0] + state->y[1]) - state->x[1]; + dst[1] = aa*(src[1] + state->y[0]) - state->x[0]; + for(i = 2;i < todo;i++) + dst[i] = aa*(src[i] + dst[i-2]) - src[i-2]; + state->x[1] = src[i-2]; + state->x[0] = src[i-1]; + state->y[1] = dst[i-2]; + state->y[0] = dst[i-1]; + } + else if(todo == 1) + { + dst[0] = aa*(src[0] + state->y[1]) - state->x[1]; + state->x[1] = state->x[0]; + state->x[0] = src[0]; + state->y[1] = state->y[0]; + state->y[0] = dst[0]; + } +} + + +/* NOTE: There seems to be a bit of an inconsistency in how this encoding is + * supposed to work. Some references, such as + * + * http://members.tripod.com/martin_leese/Ambisonic/UHJ_file_format.html + * + * specify a pre-scaling of sqrt(2) on the W channel input, while other + * references, such as + * + * https://en.wikipedia.org/wiki/Ambisonic_UHJ_format#Encoding.5B1.5D + * and + * https://wiki.xiph.org/Ambisonics#UHJ_format + * + * do not. The sqrt(2) scaling is in line with B-Format decoder coefficients + * which include such a scaling for the W channel input, however the original + * source for this equation is a 1985 paper by Michael Gerzon, which does not + * apparently include the scaling. Applying the extra scaling creates a louder + * result with a narrower stereo image compared to not scaling, and I don't + * know which is the intended result. + */ + +void EncodeUhj2(Uhj2Encoder *enc, ALfloat *restrict LeftOut, ALfloat *restrict RightOut, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo) +{ + ALfloat D[MAX_UPDATE_SAMPLES], S[MAX_UPDATE_SAMPLES]; + ALfloat temp[2][MAX_UPDATE_SAMPLES]; + ALuint base, i; + + for(base = 0;base < SamplesToDo;) + { + ALuint todo = minu(SamplesToDo - base, MAX_UPDATE_SAMPLES); + + /* D = 0.6554516*Y */ + for(i = 0;i < todo;i++) + temp[0][i] = 0.6554516f*InSamples[2][base+i]; + allpass_process(&enc->Filter1_Y[0], temp[1], temp[0], + Filter1Coeff[0]*Filter1Coeff[0], todo); + allpass_process(&enc->Filter1_Y[1], temp[0], temp[1], + Filter1Coeff[1]*Filter1Coeff[1], todo); + allpass_process(&enc->Filter1_Y[2], temp[1], temp[0], + Filter1Coeff[2]*Filter1Coeff[2], todo); + /* NOTE: Filter1 requires a 1 sample delay for the final output, so + * take the last processed sample from the previous run as the first + * output sample. + */ + D[0] = enc->Filter1_Y[3].y[0]; + allpass_process(&enc->Filter1_Y[3], temp[0], temp[1], + Filter1Coeff[3]*Filter1Coeff[3], todo); + for(i = 1;i < todo;i++) + D[i] = temp[0][i-1]; + + /* D += j(-0.3420201*W + 0.5098604*X) */ + for(i = 0;i < todo;i++) + temp[0][i] = -0.3420201f*InSamples[0][base+i] + + 0.5098604f*InSamples[1][base+i]; + allpass_process(&enc->Filter2_WX[0], temp[1], temp[0], + Filter2Coeff[0]*Filter2Coeff[0], todo); + allpass_process(&enc->Filter2_WX[1], temp[0], temp[1], + Filter2Coeff[1]*Filter2Coeff[1], todo); + allpass_process(&enc->Filter2_WX[2], temp[1], temp[0], + Filter2Coeff[2]*Filter2Coeff[2], todo); + allpass_process(&enc->Filter2_WX[3], temp[0], temp[1], + Filter2Coeff[3]*Filter2Coeff[3], todo); + for(i = 0;i < todo;i++) + D[i] += temp[0][i]; + + /* S = 0.9396926*W + 0.1855740*X */ + for(i = 0;i < todo;i++) + temp[0][i] = 0.9396926f*InSamples[0][base+i] + + 0.1855740f*InSamples[1][base+i]; + allpass_process(&enc->Filter1_WX[0], temp[1], temp[0], + Filter1Coeff[0]*Filter1Coeff[0], todo); + allpass_process(&enc->Filter1_WX[1], temp[0], temp[1], + Filter1Coeff[1]*Filter1Coeff[1], todo); + allpass_process(&enc->Filter1_WX[2], temp[1], temp[0], + Filter1Coeff[2]*Filter1Coeff[2], todo); + S[0] = enc->Filter1_WX[3].y[0]; + allpass_process(&enc->Filter1_WX[3], temp[0], temp[1], + Filter1Coeff[3]*Filter1Coeff[3], todo); + for(i = 1;i < todo;i++) + S[i] = temp[0][i-1]; + + /* Left = (S + D)/2.0 */ + for(i = 0;i < todo;i++) + *(LeftOut++) += (S[i] + D[i]) * 0.5f; + /* Right = (S - D)/2.0 */ + for(i = 0;i < todo;i++) + *(RightOut++) += (S[i] - D[i]) * 0.5f; + + base += todo; + } +} diff --git a/Engine/lib/openal-soft/Alc/uhjfilter.h b/Engine/lib/openal-soft/Alc/uhjfilter.h new file mode 100644 index 000000000..14572bc31 --- /dev/null +++ b/Engine/lib/openal-soft/Alc/uhjfilter.h @@ -0,0 +1,48 @@ +#ifndef UHJFILTER_H +#define UHJFILTER_H + +#include "AL/al.h" + +#include "alMain.h" + +typedef struct AllPassState { + ALfloat x[2]; /* Last two input samples */ + ALfloat y[2]; /* Last two output samples */ +} AllPassState; + +/* Encoding 2-channel UHJ from B-Format is done as: + * + * S = 0.9396926*W + 0.1855740*X + * D = j(-0.3420201*W + 0.5098604*X) + 0.6554516*Y + * + * Left = (S + D)/2.0 + * Right = (S - D)/2.0 + * + * where j is a wide-band +90 degree phase shift. + * + * The phase shift is done using a Hilbert transform, described here: + * https://web.archive.org/web/20060708031958/http://www.biochem.oulu.fi/~oniemita/dsp/hilbert/ + * It works using 2 sets of 4 chained filters. The first filter chain produces + * a phase shift of varying magnitude over a wide range of frequencies, while + * the second filter chain produces a phase shift 90 degrees ahead of the + * first over the same range. + * + * Combining these two stages requires the use of three filter chains. S- + * channel output uses a Filter1 chain on the W and X channel mix, while the D- + * channel output uses a Filter1 chain on the Y channel plus a Filter2 chain on + * the W and X channel mix. This results in the W and X input mix on the D- + * channel output having the required +90 degree phase shift relative to the + * other inputs. + */ + +typedef struct Uhj2Encoder { + AllPassState Filter1_WX[4]; + AllPassState Filter1_Y[4]; + AllPassState Filter2_WX[4]; +} Uhj2Encoder; + +/* Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input + * signal. */ +void EncodeUhj2(Uhj2Encoder *enc, ALfloat *restrict LeftOut, ALfloat *restrict RightOut, ALfloat (*restrict InSamples)[BUFFERSIZE], ALuint SamplesToDo); + +#endif /* UHJFILTER_H */ diff --git a/Engine/lib/openal-soft/Alc/vector.h b/Engine/lib/openal-soft/Alc/vector.h new file mode 100644 index 000000000..4bb92458f --- /dev/null +++ b/Engine/lib/openal-soft/Alc/vector.h @@ -0,0 +1,110 @@ +#ifndef AL_VECTOR_H +#define AL_VECTOR_H + +#include + +#include + +#include "almalloc.h" + + +#define TYPEDEF_VECTOR(T, N) typedef struct { \ + size_t Capacity; \ + size_t Size; \ + T Data[]; \ +} _##N; \ +typedef _##N* N; \ +typedef const _##N* const_##N; + +#define VECTOR(T) struct { \ + size_t Capacity; \ + size_t Size; \ + T Data[]; \ +}* + +#define VECTOR_INIT(_x) do { (_x) = NULL; } while(0) +#define VECTOR_INIT_STATIC() NULL +#define VECTOR_DEINIT(_x) do { al_free((_x)); (_x) = NULL; } while(0) + +#define VECTOR_RESIZE(_x, _s, _c) do { \ + size_t _size = (_s); \ + size_t _cap = (_c); \ + if(_size > _cap) \ + _cap = _size; \ + \ + if(!(_x) && _cap == 0) \ + break; \ + \ + if(((_x) ? (_x)->Capacity : 0) < _cap) \ + { \ + size_t old_size = ((_x) ? (_x)->Size : 0); \ + void *temp; \ + \ + temp = al_calloc(16, sizeof(*(_x)) + sizeof((_x)->Data[0])*_cap); \ + assert(temp != NULL); \ + if((_x)) \ + memcpy(((ALubyte*)temp)+sizeof(*(_x)), (_x)->Data, \ + sizeof((_x)->Data[0])*old_size); \ + \ + al_free((_x)); \ + (_x) = temp; \ + (_x)->Capacity = _cap; \ + } \ + (_x)->Size = _size; \ +} while(0) \ + +#define VECTOR_CAPACITY(_x) ((_x) ? (_x)->Capacity : 0) +#define VECTOR_SIZE(_x) ((_x) ? (_x)->Size : 0) + +#define VECTOR_BEGIN(_x) ((_x) ? (_x)->Data + 0 : NULL) +#define VECTOR_END(_x) ((_x) ? (_x)->Data + (_x)->Size : NULL) + +#define VECTOR_PUSH_BACK(_x, _obj) do { \ + size_t _pbsize = VECTOR_SIZE(_x)+1; \ + VECTOR_RESIZE(_x, _pbsize, _pbsize); \ + (_x)->Data[(_x)->Size-1] = (_obj); \ +} while(0) +#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_BEGIN((_x)); \ + _t *_end = VECTOR_END((_x)); \ + for(;_iter != _end;++_iter) \ + _f(_iter); \ +} while(0) + +#define VECTOR_FOR_EACH_PARAMS(_t, _x, _f, ...) do { \ + _t *_iter = VECTOR_BEGIN((_x)); \ + _t *_end = VECTOR_END((_x)); \ + for(;_iter != _end;++_iter) \ + _f(__VA_ARGS__, _iter); \ +} while(0) + +#define VECTOR_FIND_IF(_i, _t, _x, _f) do { \ + _t *_iter = VECTOR_BEGIN((_x)); \ + _t *_end = VECTOR_END((_x)); \ + for(;_iter != _end;++_iter) \ + { \ + if(_f(_iter)) \ + break; \ + } \ + (_i) = _iter; \ +} while(0) + +#define VECTOR_FIND_IF_PARMS(_i, _t, _x, _f, ...) do { \ + _t *_iter = VECTOR_BEGIN((_x)); \ + _t *_end = VECTOR_END((_x)); \ + for(;_iter != _end;++_iter) \ + { \ + if(_f(__VA_ARGS__, _iter)) \ + break; \ + } \ + (_i) = _iter; \ +} while(0) + +#endif /* AL_VECTOR_H */ diff --git a/Engine/lib/openal-soft/CMakeLists.txt b/Engine/lib/openal-soft/CMakeLists.txt new file mode 100644 index 000000000..cf6d7ca6f --- /dev/null +++ b/Engine/lib/openal-soft/CMakeLists.txt @@ -0,0 +1,1468 @@ +# CMake build file list for OpenAL + +CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5) + +PROJECT(OpenAL) + +IF(COMMAND CMAKE_POLICY) + CMAKE_POLICY(SET CMP0003 NEW) + CMAKE_POLICY(SET CMP0005 NEW) + IF(POLICY CMP0042) + CMAKE_POLICY(SET CMP0042 NEW) + ENDIF(POLICY CMP0042) +ENDIF(COMMAND CMAKE_POLICY) + +SET(CMAKE_MODULE_PATH "${OpenAL_SOURCE_DIR}/cmake") + +INCLUDE(CheckFunctionExists) +INCLUDE(CheckLibraryExists) +INCLUDE(CheckSharedFunctionExists) +INCLUDE(CheckIncludeFile) +INCLUDE(CheckIncludeFiles) +INCLUDE(CheckSymbolExists) +INCLUDE(CheckCCompilerFlag) +INCLUDE(CheckCSourceCompiles) +INCLUDE(CheckTypeSize) +include(CheckStructHasMember) +include(CheckFileOffsetBits) +include(GNUInstallDirs) + + +SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) + + +OPTION(ALSOFT_DLOPEN "Check for the dlopen API for loading optional libs" ON) + +OPTION(ALSOFT_WERROR "Treat compile warnings as errors" OFF) + +OPTION(ALSOFT_UTILS "Build and install utility programs" ON) +OPTION(ALSOFT_NO_CONFIG_UTIL "Disable building the alsoft-config utility" OFF) + +OPTION(ALSOFT_EXAMPLES "Build and install example programs" ON) +OPTION(ALSOFT_TESTS "Build and install test programs" ON) + +OPTION(ALSOFT_CONFIG "Install alsoft.conf sample configuration file" ON) +OPTION(ALSOFT_HRTF_DEFS "Install HRTF definition files" ON) +OPTION(ALSOFT_AMBDEC_PRESETS "Install AmbDec preset files" ON) +OPTION(ALSOFT_INSTALL "Install headers and libraries" ON) + +if(DEFINED SHARE_INSTALL_DIR) + message(WARNING "SHARE_INSTALL_DIR is deprecated. Use the variables provided by the GNUInstallDirs module instead") + set(CMAKE_INSTALL_DATADIR "${SHARE_INSTALL_DIR}") +endif() + +if(DEFINED LIB_SUFFIX) + message(WARNING "LIB_SUFFIX is deprecated. Use the variables provided by the GNUInstallDirs module instead") +endif() + + +IF(NOT WIN32) + SET(LIBNAME openal) +ELSE() + SET(LIBNAME OpenAL32) + ADD_DEFINITIONS("-D_WIN32 -D_WIN32_WINNT=0x0502") + + # This option is mainly for static linking OpenAL Soft into another project + # that already defines the IDs. It is up to that project to ensure all + # required IDs are defined. + OPTION(ALSOFT_NO_UID_DEFS "Do not define GUIDs, IIDs, CLSIDs, or PropertyKeys" OFF) + + IF(MINGW) + OPTION(ALSOFT_BUILD_IMPORT_LIB "Build an import .lib using dlltool (requires sed)" ON) + IF(NOT DLLTOOL) + IF(HOST) + SET(DLLTOOL "${HOST}-dlltool") + ELSE() + SET(DLLTOOL "dlltool") + ENDIF() + ENDIF() + ENDIF() +ENDIF() + + +# QNX's gcc do not uses /usr/include and /usr/lib pathes by default +IF ("${CMAKE_C_PLATFORM_ID}" STREQUAL "QNX") + ADD_DEFINITIONS("-I/usr/include") + SET(EXTRA_LIBS ${EXTRA_LIBS} -L/usr/lib) +ENDIF() + +IF(NOT LIBTYPE) + SET(LIBTYPE SHARED) +ENDIF() + +SET(LIB_MAJOR_VERSION "1") +SET(LIB_MINOR_VERSION "17") +SET(LIB_REVISION "2") +SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}") + +SET(EXPORT_DECL "") +SET(ALIGN_DECL "") + + +CHECK_TYPE_SIZE("long" SIZEOF_LONG) +CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG) + + +CHECK_C_COMPILER_FLAG(-std=c11 HAVE_STD_C11) +IF(HAVE_STD_C11) + SET(CMAKE_C_FLAGS "-std=c11 ${CMAKE_C_FLAGS}") +ELSE() + CHECK_C_COMPILER_FLAG(-std=c99 HAVE_STD_C99) + IF(HAVE_STD_C99) + SET(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}") + ENDIF() +ENDIF() + +if(NOT WIN32) + # Check if _POSIX_C_SOURCE and _XOPEN_SOURCE needs to be set for POSIX functions + CHECK_SYMBOL_EXISTS(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN_DEFAULT) + IF(NOT HAVE_POSIX_MEMALIGN_DEFAULT) + SET(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=500") + CHECK_SYMBOL_EXISTS(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN_POSIX) + IF(NOT HAVE_POSIX_MEMALIGN_POSIX) + SET(CMAKE_REQUIRED_FLAGS ${OLD_REQUIRED_FLAGS}) + ELSE() + ADD_DEFINITIONS(-D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=500) + ENDIF() + ENDIF() + UNSET(OLD_REQUIRED_FLAGS) +ENDIF() + +# Set defines for large file support +CHECK_FILE_OFFSET_BITS() +IF(_FILE_OFFSET_BITS) + ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}) + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_FILE_OFFSET_BITS=${_FILE_OFFSET_BITS}") +ENDIF() +ADD_DEFINITIONS(-D_LARGEFILE_SOURCE -D_LARGE_FILES) +SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_LARGEFILE_SOURCE -D_LARGE_FILES") + +# MSVC may need workarounds for C99 restrict and inline +IF(MSVC) + # TODO: Once we truly require C99, these restrict and inline checks should go + # away. + CHECK_C_SOURCE_COMPILES("int *restrict foo; + int main() {return 0;}" HAVE_RESTRICT) + IF(NOT HAVE_RESTRICT) + ADD_DEFINITIONS("-Drestrict=") + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Drestrict=") + ENDIF() + + CHECK_C_SOURCE_COMPILES("inline void foo(void) { } + int main() {return 0;}" HAVE_INLINE) + IF(NOT HAVE_INLINE) + CHECK_C_SOURCE_COMPILES("__inline void foo(void) { } + int main() {return 0;}" HAVE___INLINE) + IF(NOT HAVE___INLINE) + MESSAGE(FATAL_ERROR "No inline keyword found, please report!") + ENDIF() + + ADD_DEFINITIONS(-Dinline=__inline) + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Dinline=__inline") + ENDIF() +ENDIF() + +# Make sure we have C99-style inline semantics with GCC (4.3 or newer). +IF(CMAKE_COMPILER_IS_GNUCC) + SET(OLD_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + # Force no inlining for the next test. + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS} -fno-inline") + + CHECK_C_SOURCE_COMPILES("extern inline int foo() { return 0; } + int main() {return foo();}" INLINE_IS_C99) + IF(NOT INLINE_IS_C99) + MESSAGE(FATAL_ERROR "Your compiler does not seem to have C99 inline semantics! + Please update your compiler for better C99 compliance.") + ENDIF() + + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}") +ENDIF() + +# Check if we have a proper timespec declaration +CHECK_STRUCT_HAS_MEMBER("struct timespec" tv_sec time.h HAVE_STRUCT_TIMESPEC) +IF(HAVE_STRUCT_TIMESPEC) + # Define it here so we don't have to include config.h for it + ADD_DEFINITIONS("-DHAVE_STRUCT_TIMESPEC") +ENDIF() + +# Some systems may need libatomic for C11 atomic functions to work +SET(OLD_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) +SET(CMAKE_REQUIRED_LIBRARIES ${OLD_REQUIRED_LIBRARIES} atomic) +CHECK_C_SOURCE_COMPILES("#include +int _Atomic foo = ATOMIC_VAR_INIT(0); +int main() +{ + return atomic_fetch_add(&foo, 2); +}" +HAVE_LIBATOMIC) +IF(NOT HAVE_LIBATOMIC) + SET(CMAKE_REQUIRED_LIBRARIES "${OLD_REQUIRED_LIBRARIES}") +ELSE() + SET(EXTRA_LIBS atomic ${EXTRA_LIBS}) +ENDIF() +UNSET(OLD_REQUIRED_LIBRARIES) + +# Check if we have C99 variable length arrays +CHECK_C_SOURCE_COMPILES( +"int main(int argc, char *argv[]) + { + volatile int tmp[argc]; + tmp[0] = argv[0][0]; + return tmp[0]; + }" +HAVE_C99_VLA) + +# Check if we have C99 bool +CHECK_C_SOURCE_COMPILES( +"int main(int argc, char *argv[]) + { + volatile _Bool ret; + ret = (argc > 1) ? 1 : 0; + return ret ? -1 : 0; + }" +HAVE_C99_BOOL) + +# Check if we have C11 static_assert +CHECK_C_SOURCE_COMPILES( +"int main() + { + _Static_assert(sizeof(int) == sizeof(int), \"What\"); + return 0; + }" +HAVE_C11_STATIC_ASSERT) + +# Check if we have C11 alignas +CHECK_C_SOURCE_COMPILES( +"_Alignas(16) int foo; + int main() + { + return 0; + }" +HAVE_C11_ALIGNAS) + +# Check if we have C11 _Atomic +CHECK_C_SOURCE_COMPILES( +"#include + const int _Atomic foo = ATOMIC_VAR_INIT(~0); + int _Atomic bar = ATOMIC_VAR_INIT(0); + int main() + { + atomic_fetch_add(&bar, 2); + return atomic_load(&foo); + }" +HAVE_C11_ATOMIC) + +# Add definitions, compiler switches, etc. +INCLUDE_DIRECTORIES("${OpenAL_SOURCE_DIR}/include" "${OpenAL_BINARY_DIR}") +IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES("${OpenAL_SOURCE_DIR}/OpenAL32/Include" "${OpenAL_SOURCE_DIR}/Alc") + IF(WIN32 AND ALSOFT_NO_UID_DEFS) + ADD_DEFINITIONS("-DAL_NO_UID_DEFS") + ENDIF() +ENDIF() + +IF(NOT CMAKE_BUILD_TYPE) + SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING + "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." + FORCE) +ENDIF() +IF(NOT CMAKE_DEBUG_POSTFIX) + SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING + "Library postfix for debug builds. Normally left blank." + FORCE) +ENDIF() + +SET(EXTRA_CFLAGS "") +IF(MSVC) + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) + ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} /wd4098") + + IF(NOT DXSDK_DIR) + STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}") + ELSE() + STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "${DXSDK_DIR}") + ENDIF() + IF(DXSDK_DIR) + MESSAGE(STATUS "Using DirectX SDK directory: ${DXSDK_DIR}") + ENDIF() + + OPTION(FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF) + IF(FORCE_STATIC_VCRT) + FOREACH(flag_var + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO) + IF(${flag_var} MATCHES "/MD") + STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + ENDIF() + ENDFOREACH(flag_var) + ENDIF() +ELSE() + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Winline -Wall") + CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA) + IF(HAVE_W_EXTRA) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wextra") + ENDIF() + + IF(ALSOFT_WERROR) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Werror") + ENDIF() + + # Force enable -fPIC for CMake versions before 2.8.9 (later versions have + # the POSITION_INDEPENDENT_CODE target property). The static common library + # will be linked into the dynamic openal library, which requires all its + # code to be position-independent. + IF(CMAKE_VERSION VERSION_LESS "2.8.9" AND NOT WIN32) + CHECK_C_COMPILER_FLAG(-fPIC HAVE_FPIC_SWITCH) + IF(HAVE_FPIC_SWITCH) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIC") + ENDIF() + ENDIF() + + # We want RelWithDebInfo to actually include debug stuff (define _DEBUG + # instead of NDEBUG) + FOREACH(flag_var CMAKE_C_FLAGS_RELWITHDEBINFO CMAKE_CXX_FLAGS_RELWITHDEBINFO) + IF(${flag_var} MATCHES "-DNDEBUG") + STRING(REGEX REPLACE "-DNDEBUG" "-D_DEBUG" ${flag_var} "${${flag_var}}") + ENDIF() + ENDFOREACH() + + CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor)); + int main() {return 0;}" HAVE_GCC_DESTRUCTOR) + + option(ALSOFT_STATIC_LIBGCC "Force -static-libgcc for static GCC runtimes" OFF) + if(ALSOFT_STATIC_LIBGCC) + set(OLD_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} -static-libgcc) + check_c_source_compiles( +"#include +int main() +{ + return 0; +}" + HAVE_STATIC_LIBGCC_SWITCH + ) + if(HAVE_STATIC_LIBGCC_SWITCH) + set(EXTRA_LIBS ${EXTRA_LIBS} -static-libgcc) + endif() + set(CMAKE_REQUIRED_LIBRARIES ${OLD_REQUIRED_LIBRARIES}) + unset(OLD_REQUIRED_LIBRARIES) + endif() +ENDIF() + +# Set visibility/export options if available +SET(HIDDEN_DECL "") +IF(WIN32) + SET(EXPORT_DECL "__declspec(dllexport)") + IF(NOT MINGW) + SET(ALIGN_DECL "__declspec(align(x))") + ELSE() + SET(ALIGN_DECL "__declspec(aligned(x))") + ENDIF() +ELSE() + SET(OLD_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + # Yes GCC, really don't accept visibility modes you don't support + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS} -Wattributes -Werror") + + CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"protected\"))); + int main() {return 0;}" HAVE_GCC_PROTECTED_VISIBILITY) + IF(HAVE_GCC_PROTECTED_VISIBILITY) + SET(EXPORT_DECL "__attribute__((visibility(\"protected\")))") + ELSE() + CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"default\"))); + int main() {return 0;}" HAVE_GCC_DEFAULT_VISIBILITY) + IF(HAVE_GCC_DEFAULT_VISIBILITY) + SET(EXPORT_DECL "__attribute__((visibility(\"default\")))") + ENDIF() + ENDIF() + + IF(HAVE_GCC_PROTECTED_VISIBILITY OR HAVE_GCC_DEFAULT_VISIBILITY) + CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN_SWITCH) + IF(HAVE_VISIBILITY_HIDDEN_SWITCH) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") + SET(HIDDEN_DECL "__attribute__((visibility(\"hidden\")))") + ENDIF() + ENDIF() + + CHECK_C_SOURCE_COMPILES("int foo __attribute__((aligned(16))); + int main() {return 0;}" HAVE_ATTRIBUTE_ALIGNED) + IF(HAVE_ATTRIBUTE_ALIGNED) + SET(ALIGN_DECL "__attribute__((aligned(x)))") + ENDIF() + + SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}") +ENDIF() + +SET(SSE_SWITCH "") +SET(SSE2_SWITCH "") +SET(SSE3_SWITCH "") +SET(SSE4_1_SWITCH "") +SET(FPU_NEON_SWITCH "") +IF(NOT MSVC) + CHECK_C_COMPILER_FLAG(-msse HAVE_MSSE_SWITCH) + IF(HAVE_MSSE_SWITCH) + SET(SSE_SWITCH "-msse") + ENDIF() + CHECK_C_COMPILER_FLAG(-msse2 HAVE_MSSE2_SWITCH) + IF(HAVE_MSSE2_SWITCH) + SET(SSE2_SWITCH "-msse2") + ENDIF() + CHECK_C_COMPILER_FLAG(-msse3 HAVE_MSSE3_SWITCH) + IF(HAVE_MSSE3_SWITCH) + SET(SSE3_SWITCH "-msse3") + ENDIF() + CHECK_C_COMPILER_FLAG(-msse4.1 HAVE_MSSE4_1_SWITCH) + IF(HAVE_MSSE4_1_SWITCH) + SET(SSE4_1_SWITCH "-msse4.1") + ENDIF() + CHECK_C_COMPILER_FLAG(-mfpu=neon HAVE_MFPU_NEON_SWITCH) + IF(HAVE_MFPU_NEON_SWITCH) + SET(FPU_NEON_SWITCH "-mfpu=neon") + ENDIF() +ENDIF() + +CHECK_C_SOURCE_COMPILES("int foo(const char *str, ...) __attribute__((format(printf, 1, 2))); + int main() {return 0;}" HAVE_GCC_FORMAT) + +CHECK_INCLUDE_FILE(stdbool.h HAVE_STDBOOL_H) +CHECK_INCLUDE_FILE(stdalign.h HAVE_STDALIGN_H) +CHECK_INCLUDE_FILE(malloc.h HAVE_MALLOC_H) +CHECK_INCLUDE_FILE(dirent.h HAVE_DIRENT_H) +CHECK_INCLUDE_FILE(strings.h HAVE_STRINGS_H) +CHECK_INCLUDE_FILE(cpuid.h HAVE_CPUID_H) +CHECK_INCLUDE_FILE(intrin.h HAVE_INTRIN_H) +CHECK_INCLUDE_FILE(sys/sysconf.h HAVE_SYS_SYSCONF_H) +CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H) +CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H) +CHECK_INCLUDE_FILE(ieeefp.h HAVE_IEEEFP_H) +CHECK_INCLUDE_FILE(guiddef.h HAVE_GUIDDEF_H) +IF(NOT HAVE_GUIDDEF_H) + CHECK_INCLUDE_FILE(initguid.h HAVE_INITGUID_H) +ENDIF() + +# Some systems need libm for some of the following math functions to work +CHECK_LIBRARY_EXISTS(m pow "" HAVE_LIBM) +IF(HAVE_LIBM) + SET(EXTRA_LIBS m ${EXTRA_LIBS}) + SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} m) +ENDIF() + +# Check for the dlopen API (for dynamicly loading backend libs) +IF(ALSOFT_DLOPEN) + CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_LIBDL) + IF(HAVE_LIBDL) + SET(EXTRA_LIBS dl ${EXTRA_LIBS}) + SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} dl) + ENDIF() + + CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H) +ENDIF() + +# Check for a cpuid intrinsic +IF(HAVE_CPUID_H) + CHECK_C_SOURCE_COMPILES("#include + int main() + { + unsigned int eax, ebx, ecx, edx; + return __get_cpuid(0, &eax, &ebx, &ecx, &edx); + }" HAVE_GCC_GET_CPUID) +ENDIF() +IF(HAVE_INTRIN_H) + CHECK_C_SOURCE_COMPILES("#include + int main() + { + int regs[4]; + __cpuid(regs, 0); + return regs[0]; + }" HAVE_CPUID_INTRINSIC) +ENDIF() + +CHECK_SYMBOL_EXISTS(aligned_alloc stdlib.h HAVE_ALIGNED_ALLOC) +CHECK_SYMBOL_EXISTS(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) +CHECK_SYMBOL_EXISTS(_aligned_malloc malloc.h HAVE__ALIGNED_MALLOC) +CHECK_SYMBOL_EXISTS(lrintf math.h HAVE_LRINTF) +CHECK_SYMBOL_EXISTS(modff math.h HAVE_MODFF) +IF(NOT HAVE_C99_VLA) + CHECK_SYMBOL_EXISTS(alloca malloc.h HAVE_ALLOCA) + IF(NOT HAVE_ALLOCA) + MESSAGE(FATAL_ERROR "No alloca function found, please report!") + ENDIF() +ENDIF() + +IF(HAVE_FLOAT_H) + CHECK_SYMBOL_EXISTS(_controlfp float.h HAVE__CONTROLFP) + CHECK_SYMBOL_EXISTS(__control87_2 float.h HAVE___CONTROL87_2) +ENDIF() + +CHECK_FUNCTION_EXISTS(stat HAVE_STAT) +CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF) +CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP) +IF(NOT HAVE_STRCASECMP) + CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP) + IF(NOT HAVE__STRICMP) + MESSAGE(FATAL_ERROR "No case-insensitive compare function found, please report!") + ENDIF() + + ADD_DEFINITIONS(-Dstrcasecmp=_stricmp) +ENDIF() + +CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP) +IF(NOT HAVE_STRNCASECMP) + CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP) + IF(NOT HAVE__STRNICMP) + MESSAGE(FATAL_ERROR "No case-insensitive size-limitted compare function found, please report!") + ENDIF() + + ADD_DEFINITIONS(-Dstrncasecmp=_strnicmp) +ENDIF() + +CHECK_SYMBOL_EXISTS(strnlen string.h HAVE_STRNLEN) +CHECK_SYMBOL_EXISTS(snprintf stdio.h HAVE_SNPRINTF) +IF(NOT HAVE_SNPRINTF) + CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF) + IF(NOT HAVE__SNPRINTF) + MESSAGE(FATAL_ERROR "No snprintf function found, please report!") + ENDIF() + + ADD_DEFINITIONS(-Dsnprintf=_snprintf) +ENDIF() + +CHECK_SYMBOL_EXISTS(isfinite math.h HAVE_ISFINITE) +IF(NOT HAVE_ISFINITE) + CHECK_FUNCTION_EXISTS(finite HAVE_FINITE) + IF(NOT HAVE_FINITE) + CHECK_FUNCTION_EXISTS(_finite HAVE__FINITE) + IF(NOT HAVE__FINITE) + MESSAGE(FATAL_ERROR "No isfinite function found, please report!") + ENDIF() + ADD_DEFINITIONS(-Disfinite=_finite) + ELSE() + ADD_DEFINITIONS(-Disfinite=finite) + ENDIF() +ENDIF() + +CHECK_SYMBOL_EXISTS(isnan math.h HAVE_ISNAN) +IF(NOT HAVE_ISNAN) + CHECK_FUNCTION_EXISTS(_isnan HAVE__ISNAN) + IF(NOT HAVE__ISNAN) + MESSAGE(FATAL_ERROR "No isnan function found, please report!") + ENDIF() + + ADD_DEFINITIONS(-Disnan=_isnan) +ENDIF() + + +# Check if we have Windows headers +CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0502) +IF(NOT HAVE_WINDOWS_H) + CHECK_SYMBOL_EXISTS(gettimeofday sys/time.h HAVE_GETTIMEOFDAY) + IF(NOT HAVE_GETTIMEOFDAY) + MESSAGE(FATAL_ERROR "No timing function found!") + ENDIF() + + CHECK_SYMBOL_EXISTS(nanosleep time.h HAVE_NANOSLEEP) + IF(NOT HAVE_NANOSLEEP) + MESSAGE(FATAL_ERROR "No sleep function found!") + ENDIF() + + # We need pthreads outside of Windows + CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H) + IF(NOT HAVE_PTHREAD_H) + MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!") + ENDIF() + # Some systems need pthread_np.h to get recursive mutexes + CHECK_INCLUDE_FILES("pthread.h;pthread_np.h" HAVE_PTHREAD_NP_H) + + CHECK_C_COMPILER_FLAG(-pthread HAVE_PTHREAD) + IF(HAVE_PTHREAD) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -pthread") + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -pthread") + SET(EXTRA_LIBS ${EXTRA_LIBS} -pthread) + ENDIF() + + CHECK_LIBRARY_EXISTS(pthread pthread_create "" HAVE_LIBPTHREAD) + IF(HAVE_LIBPTHREAD) + SET(EXTRA_LIBS pthread ${EXTRA_LIBS}) + ENDIF() + + CHECK_SYMBOL_EXISTS(pthread_setschedparam pthread.h HAVE_PTHREAD_SETSCHEDPARAM) + + IF(HAVE_PTHREAD_NP_H) + CHECK_SYMBOL_EXISTS(pthread_setname_np "pthread.h;pthread_np.h" HAVE_PTHREAD_SETNAME_NP) + IF(NOT HAVE_PTHREAD_SETNAME_NP) + CHECK_SYMBOL_EXISTS(pthread_set_name_np "pthread.h;pthread_np.h" HAVE_PTHREAD_SET_NAME_NP) + ELSE() + CHECK_C_SOURCE_COMPILES(" +#include +#include +int main() +{ + pthread_setname_np(\"testname\"); + return 0; +}" + PTHREAD_SETNAME_NP_ONE_PARAM + ) + ENDIF() + CHECK_SYMBOL_EXISTS(pthread_mutexattr_setkind_np "pthread.h;pthread_np.h" HAVE_PTHREAD_MUTEXATTR_SETKIND_NP) + ELSE() + CHECK_SYMBOL_EXISTS(pthread_setname_np pthread.h HAVE_PTHREAD_SETNAME_NP) + IF(NOT HAVE_PTHREAD_SETNAME_NP) + CHECK_SYMBOL_EXISTS(pthread_set_name_np pthread.h HAVE_PTHREAD_SET_NAME_NP) + ELSE() + CHECK_C_SOURCE_COMPILES(" +#include +int main() +{ + pthread_setname_np(\"testname\"); + return 0; +}" + PTHREAD_SETNAME_NP_ONE_PARAM + ) + ENDIF() + CHECK_SYMBOL_EXISTS(pthread_mutexattr_setkind_np pthread.h HAVE_PTHREAD_MUTEXATTR_SETKIND_NP) + ENDIF() + + CHECK_SYMBOL_EXISTS(pthread_mutex_timedlock pthread.h HAVE_PTHREAD_MUTEX_TIMEDLOCK) + + CHECK_LIBRARY_EXISTS(rt clock_gettime "" HAVE_LIBRT) + IF(HAVE_LIBRT) + SET(EXTRA_LIBS rt ${EXTRA_LIBS}) + ENDIF() +ENDIF() + +# Check for a 64-bit type +CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H) +IF(NOT HAVE_STDINT_H) + IF(HAVE_WINDOWS_H) + CHECK_C_SOURCE_COMPILES("#define _WIN32_WINNT 0x0502 + #include + __int64 foo; + int main() {return 0;}" HAVE___INT64) + ENDIF() + IF(NOT HAVE___INT64) + IF(NOT SIZEOF_LONG MATCHES "8") + IF(NOT SIZEOF_LONG_LONG MATCHES "8") + MESSAGE(FATAL_ERROR "No 64-bit types found, please report!") + ENDIF() + ENDIF() + ENDIF() +ENDIF() + + +SET(COMMON_OBJS common/almalloc.c + common/atomic.c + common/rwlock.c + common/threads.c + common/uintmap.c +) +SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c + OpenAL32/alBuffer.c + OpenAL32/alEffect.c + OpenAL32/alError.c + OpenAL32/alExtension.c + OpenAL32/alFilter.c + OpenAL32/alListener.c + OpenAL32/alSource.c + OpenAL32/alState.c + OpenAL32/alThunk.c + OpenAL32/sample_cvt.c +) +SET(ALC_OBJS Alc/ALc.c + Alc/ALu.c + Alc/alcConfig.c + Alc/alcRing.c + Alc/bs2b.c + Alc/effects/chorus.c + Alc/effects/compressor.c + Alc/effects/dedicated.c + Alc/effects/distortion.c + Alc/effects/echo.c + Alc/effects/equalizer.c + Alc/effects/flanger.c + Alc/effects/modulator.c + Alc/effects/null.c + Alc/effects/reverb.c + Alc/helpers.c + Alc/bsinc.c + Alc/hrtf.c + Alc/uhjfilter.c + Alc/ambdec.c + Alc/bformatdec.c + Alc/panning.c + Alc/mixer.c + Alc/mixer_c.c +) + + +SET(CPU_EXTS "Default") +SET(HAVE_SSE 0) +SET(HAVE_SSE2 0) +SET(HAVE_SSE3 0) +SET(HAVE_SSE4_1 0) +SET(HAVE_NEON 0) + +SET(HAVE_ALSA 0) +SET(HAVE_OSS 0) +SET(HAVE_SOLARIS 0) +SET(HAVE_SNDIO 0) +SET(HAVE_QSA 0) +SET(HAVE_DSOUND 0) +SET(HAVE_MMDEVAPI 0) +SET(HAVE_WINMM 0) +SET(HAVE_PORTAUDIO 0) +SET(HAVE_PULSEAUDIO 0) +SET(HAVE_COREAUDIO 0) +SET(HAVE_OPENSL 0) +SET(HAVE_WAVE 0) + +# Check for SSE support +OPTION(ALSOFT_REQUIRE_SSE "Require SSE support" OFF) +CHECK_INCLUDE_FILE(xmmintrin.h HAVE_XMMINTRIN_H "${SSE_SWITCH}") +IF(HAVE_XMMINTRIN_H) + OPTION(ALSOFT_CPUEXT_SSE "Enable SSE support" ON) + IF(ALSOFT_CPUEXT_SSE) + IF(ALIGN_DECL OR HAVE_C11_ALIGNAS) + SET(HAVE_SSE 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/mixer_sse.c) + IF(SSE_SWITCH) + SET_SOURCE_FILES_PROPERTIES(Alc/mixer_sse.c PROPERTIES + COMPILE_FLAGS "${SSE_SWITCH}") + ENDIF() + SET(CPU_EXTS "${CPU_EXTS}, SSE") + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_SSE AND NOT HAVE_SSE) + MESSAGE(FATAL_ERROR "Failed to enabled required SSE CPU extensions") +ENDIF() + +OPTION(ALSOFT_REQUIRE_SSE2 "Require SSE2 support" OFF) +CHECK_INCLUDE_FILE(emmintrin.h HAVE_EMMINTRIN_H "${SSE2_SWITCH}") +IF(HAVE_EMMINTRIN_H) + OPTION(ALSOFT_CPUEXT_SSE2 "Enable SSE2 support" ON) + IF(HAVE_SSE AND ALSOFT_CPUEXT_SSE2) + IF(ALIGN_DECL OR HAVE_C11_ALIGNAS) + SET(HAVE_SSE2 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/mixer_sse2.c) + IF(SSE2_SWITCH) + SET_SOURCE_FILES_PROPERTIES(Alc/mixer_sse2.c PROPERTIES + COMPILE_FLAGS "${SSE2_SWITCH}") + ENDIF() + SET(CPU_EXTS "${CPU_EXTS}, SSE2") + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_SSE2 AND NOT HAVE_SSE2) + MESSAGE(FATAL_ERROR "Failed to enable required SSE2 CPU extensions") +ENDIF() + +OPTION(ALSOFT_REQUIRE_SSE2 "Require SSE3 support" OFF) +CHECK_INCLUDE_FILE(pmmintrin.h HAVE_PMMINTRIN_H "${SSE3_SWITCH}") +IF(HAVE_EMMINTRIN_H) + OPTION(ALSOFT_CPUEXT_SSE3 "Enable SSE3 support" ON) + IF(HAVE_SSE2 AND ALSOFT_CPUEXT_SSE3) + IF(ALIGN_DECL OR HAVE_C11_ALIGNAS) + SET(HAVE_SSE3 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/mixer_sse3.c) + IF(SSE2_SWITCH) + SET_SOURCE_FILES_PROPERTIES(Alc/mixer_sse3.c PROPERTIES + COMPILE_FLAGS "${SSE3_SWITCH}") + ENDIF() + SET(CPU_EXTS "${CPU_EXTS}, SSE3") + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_SSE3 AND NOT HAVE_SSE3) + MESSAGE(FATAL_ERROR "Failed to enable required SSE3 CPU extensions") +ENDIF() + +OPTION(ALSOFT_REQUIRE_SSE4_1 "Require SSE4.1 support" OFF) +CHECK_INCLUDE_FILE(smmintrin.h HAVE_SMMINTRIN_H "${SSE4_1_SWITCH}") +IF(HAVE_SMMINTRIN_H) + OPTION(ALSOFT_CPUEXT_SSE4_1 "Enable SSE4.1 support" ON) + IF(HAVE_SSE2 AND ALSOFT_CPUEXT_SSE4_1) + IF(ALIGN_DECL OR HAVE_C11_ALIGNAS) + SET(HAVE_SSE4_1 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/mixer_sse41.c) + IF(SSE4_1_SWITCH) + SET_SOURCE_FILES_PROPERTIES(Alc/mixer_sse41.c PROPERTIES + COMPILE_FLAGS "${SSE4_1_SWITCH}") + ENDIF() + SET(CPU_EXTS "${CPU_EXTS}, SSE4.1") + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_SSE4_1 AND NOT HAVE_SSE4_1) + MESSAGE(FATAL_ERROR "Failed to enable required SSE4.1 CPU extensions") +ENDIF() + +# Check for ARM Neon support +OPTION(ALSOFT_REQUIRE_NEON "Require ARM Neon support" OFF) +CHECK_INCLUDE_FILE(arm_neon.h HAVE_ARM_NEON_H) +IF(HAVE_ARM_NEON_H) + OPTION(ALSOFT_CPUEXT_NEON "Enable ARM Neon support" ON) + IF(ALSOFT_CPUEXT_NEON) + SET(HAVE_NEON 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/mixer_neon.c) + IF(FPU_NEON_SWITCH) + SET_SOURCE_FILES_PROPERTIES(Alc/mixer_neon.c PROPERTIES + COMPILE_FLAGS "${FPU_NEON_SWITCH}") + ENDIF() + SET(CPU_EXTS "${CPU_EXTS}, Neon") + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_NEON AND NOT HAVE_NEON) + MESSAGE(FATAL_ERROR "Failed to enabled required ARM Neon CPU extensions") +ENDIF() + + +IF(WIN32 OR HAVE_DLFCN_H) + SET(IS_LINKED "") + MACRO(ADD_BACKEND_LIBS _LIBS) + ENDMACRO() +ELSE() + SET(IS_LINKED " (linked)") + MACRO(ADD_BACKEND_LIBS _LIBS) + SET(EXTRA_LIBS ${_LIBS} ${EXTRA_LIBS}) + ENDMACRO() +ENDIF() + +SET(BACKENDS "") +SET(ALC_OBJS ${ALC_OBJS} + Alc/backends/base.c + # Default backends, always available + Alc/backends/loopback.c + Alc/backends/null.c +) + +# Check ALSA backend +OPTION(ALSOFT_REQUIRE_ALSA "Require ALSA backend" OFF) +FIND_PACKAGE(ALSA) +IF(ALSA_FOUND) + OPTION(ALSOFT_BACKEND_ALSA "Enable ALSA backend" ON) + IF(ALSOFT_BACKEND_ALSA) + SET(HAVE_ALSA 1) + SET(BACKENDS "${BACKENDS} ALSA${IS_LINKED},") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/alsa.c) + ADD_BACKEND_LIBS(${ALSA_LIBRARIES}) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${ALSA_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_ALSA AND NOT HAVE_ALSA) + MESSAGE(FATAL_ERROR "Failed to enabled required ALSA backend") +ENDIF() + +# Check OSS backend +OPTION(ALSOFT_REQUIRE_OSS "Require OSS backend" OFF) +FIND_PACKAGE(OSS) +IF(OSS_FOUND) + OPTION(ALSOFT_BACKEND_OSS "Enable OSS backend" ON) + IF(ALSOFT_BACKEND_OSS) + SET(HAVE_OSS 1) + SET(BACKENDS "${BACKENDS} OSS,") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/oss.c) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${OSS_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_OSS AND NOT HAVE_OSS) + MESSAGE(FATAL_ERROR "Failed to enabled required OSS backend") +ENDIF() + +# Check Solaris backend +OPTION(ALSOFT_REQUIRE_SOLARIS "Require Solaris backend" OFF) +FIND_PACKAGE(AudioIO) +IF(AUDIOIO_FOUND) + OPTION(ALSOFT_BACKEND_SOLARIS "Enable Solaris backend" ON) + IF(ALSOFT_BACKEND_SOLARIS) + SET(HAVE_SOLARIS 1) + SET(BACKENDS "${BACKENDS} Solaris,") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/solaris.c) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${AUDIOIO_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_SOLARIS AND NOT HAVE_SOLARIS) + MESSAGE(FATAL_ERROR "Failed to enabled required Solaris backend") +ENDIF() + +# Check SndIO backend +OPTION(ALSOFT_REQUIRE_SNDIO "Require SndIO backend" OFF) +FIND_PACKAGE(SoundIO) +IF(SOUNDIO_FOUND) + OPTION(ALSOFT_BACKEND_SNDIO "Enable SndIO backend" ON) + IF(ALSOFT_BACKEND_SNDIO) + SET(HAVE_SNDIO 1) + SET(BACKENDS "${BACKENDS} SndIO (linked),") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/sndio.c) + SET(EXTRA_LIBS ${SOUNDIO_LIBRARIES} ${EXTRA_LIBS}) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${SOUNDIO_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_SNDIO AND NOT HAVE_SNDIO) + MESSAGE(FATAL_ERROR "Failed to enabled required SndIO backend") +ENDIF() + +# Check QSA backend +OPTION(ALSOFT_REQUIRE_QSA "Require QSA backend" OFF) +FIND_PACKAGE(QSA) +IF(QSA_FOUND) + OPTION(ALSOFT_BACKEND_QSA "Enable QSA backend" ON) + IF(ALSOFT_BACKEND_QSA) + SET(HAVE_QSA 1) + SET(BACKENDS "${BACKENDS} QSA (linked),") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/qsa.c) + SET(EXTRA_LIBS ${QSA_LIBRARIES} ${EXTRA_LIBS}) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${QSA_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_QSA AND NOT HAVE_QSA) + MESSAGE(FATAL_ERROR "Failed to enabled required QSA backend") +ENDIF() + +# Check Windows-only backends +OPTION(ALSOFT_REQUIRE_WINMM "Require Windows Multimedia backend" OFF) +OPTION(ALSOFT_REQUIRE_DSOUND "Require DirectSound backend" OFF) +OPTION(ALSOFT_REQUIRE_MMDEVAPI "Require MMDevApi backend" OFF) +IF(HAVE_WINDOWS_H) + # Check MMSystem backend + CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0502) + IF(HAVE_MMSYSTEM_H) + CHECK_SHARED_FUNCTION_EXISTS(waveOutOpen "windows.h;mmsystem.h" winmm "" HAVE_LIBWINMM) + IF(HAVE_LIBWINMM) + OPTION(ALSOFT_BACKEND_WINMM "Enable Windows Multimedia backend" ON) + IF(ALSOFT_BACKEND_WINMM) + SET(HAVE_WINMM 1) + SET(BACKENDS "${BACKENDS} WinMM,") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/winmm.c) + SET(EXTRA_LIBS winmm ${EXTRA_LIBS}) + ENDIF() + ENDIF() + ENDIF() + + # Check DSound backend + FIND_PACKAGE(DSound) + IF(DSOUND_FOUND) + OPTION(ALSOFT_BACKEND_DSOUND "Enable DirectSound backend" ON) + IF(ALSOFT_BACKEND_DSOUND) + SET(HAVE_DSOUND 1) + SET(BACKENDS "${BACKENDS} DirectSound${IS_LINKED},") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/dsound.c) + ADD_BACKEND_LIBS(${DSOUND_LIBRARIES}) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${DSOUND_INCLUDE_DIRS}) + ENDIF() + ENDIF() + ENDIF() + + # Check for MMDevApi backend + CHECK_INCLUDE_FILE(mmdeviceapi.h HAVE_MMDEVICEAPI_H) + IF(HAVE_MMDEVICEAPI_H) + OPTION(ALSOFT_BACKEND_MMDEVAPI "Enable MMDevApi backend" ON) + IF(ALSOFT_BACKEND_MMDEVAPI) + SET(HAVE_MMDEVAPI 1) + SET(BACKENDS "${BACKENDS} MMDevApi,") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/mmdevapi.c) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_WINMM AND NOT HAVE_WINMM) + MESSAGE(FATAL_ERROR "Failed to enabled required WinMM backend") +ENDIF() +IF(ALSOFT_REQUIRE_DSOUND AND NOT HAVE_DSOUND) + MESSAGE(FATAL_ERROR "Failed to enabled required DSound backend") +ENDIF() +IF(ALSOFT_REQUIRE_MMDEVAPI AND NOT HAVE_MMDEVAPI) + MESSAGE(FATAL_ERROR "Failed to enabled required MMDevApi backend") +ENDIF() + +# Check PortAudio backend +OPTION(ALSOFT_REQUIRE_PORTAUDIO "Require PortAudio backend" OFF) +FIND_PACKAGE(PortAudio) +IF(PORTAUDIO_FOUND) + OPTION(ALSOFT_BACKEND_PORTAUDIO "Enable PortAudio backend" ON) + IF(ALSOFT_BACKEND_PORTAUDIO) + SET(HAVE_PORTAUDIO 1) + SET(BACKENDS "${BACKENDS} PortAudio${IS_LINKED},") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/portaudio.c) + ADD_BACKEND_LIBS(${PORTAUDIO_LIBRARIES}) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${PORTAUDIO_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_PORTAUDIO AND NOT HAVE_PORTAUDIO) + MESSAGE(FATAL_ERROR "Failed to enabled required PortAudio backend") +ENDIF() + +# Check PulseAudio backend +OPTION(ALSOFT_REQUIRE_PULSEAUDIO "Require PulseAudio backend" OFF) +FIND_PACKAGE(PulseAudio) +IF(PULSEAUDIO_FOUND) + OPTION(ALSOFT_BACKEND_PULSEAUDIO "Enable PulseAudio backend" ON) + IF(ALSOFT_BACKEND_PULSEAUDIO) + SET(HAVE_PULSEAUDIO 1) + SET(BACKENDS "${BACKENDS} PulseAudio${IS_LINKED},") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/pulseaudio.c) + ADD_BACKEND_LIBS(${PULSEAUDIO_LIBRARIES}) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${PULSEAUDIO_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO) + MESSAGE(FATAL_ERROR "Failed to enabled required PulseAudio backend") +ENDIF() + +# Check JACK backend +OPTION(ALSOFT_REQUIRE_JACK "Require JACK backend" OFF) +FIND_PACKAGE(JACK) +IF(JACK_FOUND) + OPTION(ALSOFT_BACKEND_JACK "Enable JACK backend" ON) + IF(ALSOFT_BACKEND_JACK) + SET(HAVE_JACK 1) + SET(BACKENDS "${BACKENDS} JACK${IS_LINKED},") + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/jack.c) + ADD_BACKEND_LIBS(${JACK_LIBRARIES}) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${JACK_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_JACK AND NOT HAVE_JACK) + MESSAGE(FATAL_ERROR "Failed to enabled required JACK backend") +ENDIF() + +# Check CoreAudio backend +OPTION(ALSOFT_REQUIRE_COREAUDIO "Require CoreAudio backend" OFF) +FIND_LIBRARY(COREAUDIO_FRAMEWORK + NAMES CoreAudio + PATHS /System/Library/Frameworks +) +IF(COREAUDIO_FRAMEWORK) + OPTION(ALSOFT_BACKEND_COREAUDIO "Enable CoreAudio backend" ON) + IF(ALSOFT_BACKEND_COREAUDIO) + SET(HAVE_COREAUDIO 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/coreaudio.c) + SET(BACKENDS "${BACKENDS} CoreAudio,") + SET(EXTRA_LIBS ${COREAUDIO_FRAMEWORK} ${EXTRA_LIBS}) + SET(EXTRA_LIBS /System/Library/Frameworks/AudioUnit.framework ${EXTRA_LIBS}) + SET(EXTRA_LIBS /System/Library/Frameworks/ApplicationServices.framework ${EXTRA_LIBS}) + + # Some versions of OSX may need the AudioToolbox framework. Add it if + # it's found. + FIND_LIBRARY(AUDIOTOOLBOX_LIBRARY + NAMES AudioToolbox + PATHS ~/Library/Frameworks + /Library/Frameworks + /System/Library/Frameworks + ) + IF(AUDIOTOOLBOX_LIBRARY) + SET(EXTRA_LIBS ${AUDIOTOOLBOX_LIBRARY} ${EXTRA_LIBS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_COREAUDIO AND NOT HAVE_COREAUDIO) + MESSAGE(FATAL_ERROR "Failed to enabled required CoreAudio backend") +ENDIF() + +# Check for OpenSL (Android) backend +OPTION(ALSOFT_REQUIRE_OPENSL "Require OpenSL backend" OFF) +CHECK_INCLUDE_FILES("SLES/OpenSLES.h;SLES/OpenSLES_Android.h" HAVE_SLES_OPENSLES_ANDROID_H) +IF(HAVE_SLES_OPENSLES_ANDROID_H) + CHECK_SHARED_FUNCTION_EXISTS(slCreateEngine "SLES/OpenSLES.h" OpenSLES "" HAVE_LIBOPENSLES) + IF(HAVE_LIBOPENSLES) + OPTION(ALSOFT_BACKEND_OPENSL "Enable OpenSL backend" ON) + IF(ALSOFT_BACKEND_OPENSL) + SET(HAVE_OPENSL 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/opensl.c) + SET(BACKENDS "${BACKENDS} OpenSL,") + SET(EXTRA_LIBS OpenSLES ${EXTRA_LIBS}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_OPENSL AND NOT HAVE_OPENSL) + MESSAGE(FATAL_ERROR "Failed to enabled required OpenSL backend") +ENDIF() + +# Optionally enable the Wave Writer backend +OPTION(ALSOFT_BACKEND_WAVE "Enable Wave Writer backend" ON) +IF(ALSOFT_BACKEND_WAVE) + SET(HAVE_WAVE 1) + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/wave.c) + SET(BACKENDS "${BACKENDS} WaveFile,") +ENDIF() + +# This is always available +SET(BACKENDS "${BACKENDS} Null") + +option(ALSOFT_EMBED_HRTF_DATA "Embed the HRTF data files (increases library footprint)" OFF) +if(ALSOFT_EMBED_HRTF_DATA) + if(WIN32) + set(ALC_OBJS ${ALC_OBJS} Alc/hrtf_res.rc) + else() + set(FILENAMES default-44100.mhr default-48000.mhr) + foreach(FILENAME ${FILENAMES}) + set(outfile ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${FILENAME}${CMAKE_C_OUTPUT_EXTENSION}) + add_custom_command(OUTPUT ${outfile} + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/hrtf/${FILENAME}" + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/hrtf" + COMMAND "${CMAKE_LINKER}" -r -b binary -o "${outfile}" ${FILENAME} + COMMAND "${CMAKE_OBJCOPY}" --rename-section .data=.rodata,alloc,load,readonly,data,contents "${outfile}" "${outfile}" + COMMENT "Generating ${FILENAME}${CMAKE_C_OUTPUT_EXTENSION}" + VERBATIM + ) + set(ALC_OBJS ${ALC_OBJS} ${outfile}) + endforeach() + unset(outfile) + unset(FILENAMES) + endif() +endif() + + +IF(ALSOFT_UTILS AND NOT ALSOFT_NO_CONFIG_UTIL) + add_subdirectory(utils/alsoft-config) +ENDIF() +IF(ALSOFT_EXAMPLES) + FIND_PACKAGE(SDL2) + IF(SDL2_FOUND) + FIND_PACKAGE(SDL_sound) + IF(SDL_SOUND_FOUND AND CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR}) + ENDIF() + FIND_PACKAGE(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE) + IF(FFMPEG_FOUND AND CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${FFMPEG_INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDIF() + +IF(LIBTYPE STREQUAL "STATIC") + ADD_DEFINITIONS(-DAL_LIBTYPE_STATIC) + SET(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC ${PKG_CONFIG_CFLAGS}) +ENDIF() + +# Needed for openal.pc.in +SET(prefix ${CMAKE_INSTALL_PREFIX}) +SET(exec_prefix "\${prefix}") +SET(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}") +SET(bindir "\${exec_prefix}/${CMAKE_INSTALL_BINDIR}") +SET(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}") +SET(PACKAGE_VERSION "${LIB_VERSION}") + +# End configuration +CONFIGURE_FILE( + "${OpenAL_SOURCE_DIR}/config.h.in" + "${OpenAL_BINARY_DIR}/config.h") +CONFIGURE_FILE( + "${OpenAL_SOURCE_DIR}/openal.pc.in" + "${OpenAL_BINARY_DIR}/openal.pc" + @ONLY) + +# Build a common library with reusable helpers +ADD_LIBRARY(common STATIC ${COMMON_OBJS}) +SET_PROPERTY(TARGET common APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) +IF(NOT LIBTYPE STREQUAL "STATIC") + SET_PROPERTY(TARGET common PROPERTY POSITION_INDEPENDENT_CODE TRUE) +ENDIF() + +# Build main library +IF(LIBTYPE STREQUAL "STATIC") + ADD_LIBRARY(${LIBNAME} STATIC ${COMMON_OBJS} ${OPENAL_OBJS} ${ALC_OBJS}) +ELSE() + ADD_LIBRARY(${LIBNAME} SHARED ${OPENAL_OBJS} ${ALC_OBJS}) +ENDIF() +SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) +SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY COMPILE_DEFINITIONS AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES) +IF(WIN32 AND ALSOFT_NO_UID_DEFS) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY COMPILE_DEFINITIONS AL_NO_UID_DEFS) +ENDIF() +SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES "${OpenAL_SOURCE_DIR}/OpenAL32/Include" "${OpenAL_SOURCE_DIR}/Alc") +IF(HAVE_ALSA) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${ALSA_INCLUDE_DIRS}) +ENDIF() +IF(HAVE_OSS) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${OSS_INCLUDE_DIRS}) +ENDIF() +IF(HAVE_SOLARIS) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${AUDIOIO_INCLUDE_DIRS}) +ENDIF() +IF(HAVE_SNDIO) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${SOUNDIO_INCLUDE_DIRS}) +ENDIF() +IF(HAVE_QSA) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${QSA_INCLUDE_DIRS}) +ENDIF() +IF(HAVE_DSOUND) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${DSOUND_INCLUDE_DIRS}) +ENDIF() +IF(HAVE_PORTAUDIO) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${PORTAUDIO_INCLUDE_DIRS}) +ENDIF() +IF(HAVE_PULSEAUDIO) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${PULSEAUDIO_INCLUDE_DIRS}) +ENDIF() +IF(HAVE_JACK) + SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${JACK_INCLUDE_DIRS}) +ENDIF() +SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES VERSION ${LIB_VERSION} + SOVERSION ${LIB_MAJOR_VERSION}) +IF(WIN32 AND NOT LIBTYPE STREQUAL "STATIC") + SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "") + + IF(MINGW AND ALSOFT_BUILD_IMPORT_LIB) + FIND_PROGRAM(SED_EXECUTABLE NAMES sed DOC "sed executable") + FIND_PROGRAM(DLLTOOL_EXECUTABLE NAMES "${DLLTOOL}" DOC "dlltool executable") + IF(NOT SED_EXECUTABLE OR NOT DLLTOOL_EXECUTABLE) + MESSAGE(STATUS "") + IF(NOT SED_EXECUTABLE) + MESSAGE(STATUS "WARNING: Cannot find sed, disabling .def/.lib generation") + ENDIF() + IF(NOT DLLTOOL_EXECUTABLE) + MESSAGE(STATUS "WARNING: Cannot find dlltool, disabling .def/.lib generation") + ENDIF() + ELSE() + SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES LINK_FLAGS "-Wl,--output-def,${LIBNAME}.def") + ADD_CUSTOM_COMMAND(TARGET ${LIBNAME} POST_BUILD + COMMAND "${SED_EXECUTABLE}" -i -e "s/ @[^ ]*//" ${LIBNAME}.def + COMMAND "${DLLTOOL_EXECUTABLE}" -d ${LIBNAME}.def -l ${LIBNAME}.lib -D ${LIBNAME}.dll + COMMENT "Stripping ordinals from ${LIBNAME}.def and generating ${LIBNAME}.lib..." + VERBATIM + ) + ENDIF() + ENDIF() +ENDIF() + +TARGET_LINK_LIBRARIES(${LIBNAME} common ${EXTRA_LIBS}) + +IF(ALSOFT_INSTALL) + # Add an install target here + INSTALL(TARGETS ${LIBNAME} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + INSTALL(FILES include/AL/al.h + include/AL/alc.h + include/AL/alext.h + include/AL/efx.h + include/AL/efx-creative.h + include/AL/efx-presets.h + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/AL + ) + INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") +ENDIF() + + +MESSAGE(STATUS "") +MESSAGE(STATUS "Building OpenAL with support for the following backends:") +MESSAGE(STATUS " ${BACKENDS}") +MESSAGE(STATUS "") +MESSAGE(STATUS "Building with support for CPU extensions:") +MESSAGE(STATUS " ${CPU_EXTS}") +MESSAGE(STATUS "") + +IF(WIN32) + IF(NOT HAVE_DSOUND) + MESSAGE(STATUS "WARNING: Building the Windows version without DirectSound output") + MESSAGE(STATUS " This is probably NOT what you want!") + MESSAGE(STATUS "") + ENDIF() +ENDIF() + +if(ALSOFT_EMBED_HRTF_DATA) + message(STATUS "Embedding HRTF datasets") + message(STATUS "") +endif() + +# Install alsoft.conf configuration file +IF(ALSOFT_CONFIG) + INSTALL(FILES alsoftrc.sample + DESTINATION ${CMAKE_INSTALL_DATADIR}/openal + ) + MESSAGE(STATUS "Installing sample configuration") + MESSAGE(STATUS "") +ENDIF() + +# Install HRTF definitions +IF(ALSOFT_HRTF_DEFS) + INSTALL(FILES hrtf/default-44100.mhr + hrtf/default-48000.mhr + DESTINATION ${CMAKE_INSTALL_DATADIR}/openal/hrtf + ) + MESSAGE(STATUS "Installing HRTF definitions") + MESSAGE(STATUS "") +ENDIF() + +# Install AmbDec presets +IF(ALSOFT_AMBDEC_PRESETS) + INSTALL(FILES presets/3D7.1.ambdec + presets/hexagon.ambdec + presets/itu5.1.ambdec + presets/rectangle.ambdec + presets/square.ambdec + presets/presets.txt + DESTINATION ${CMAKE_INSTALL_DATADIR}/openal/presets + ) + MESSAGE(STATUS "Installing AmbDec presets") + MESSAGE(STATUS "") +ENDIF() + +IF(ALSOFT_UTILS) + ADD_EXECUTABLE(openal-info utils/openal-info.c) + SET_PROPERTY(TARGET openal-info APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + TARGET_LINK_LIBRARIES(openal-info ${LIBNAME}) + + ADD_EXECUTABLE(makehrtf utils/makehrtf.c) + SET_PROPERTY(TARGET makehrtf APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + IF(HAVE_LIBM) + TARGET_LINK_LIBRARIES(makehrtf m) + ENDIF() + + ADD_EXECUTABLE(bsincgen utils/bsincgen.c) + SET_PROPERTY(TARGET bsincgen APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + IF(HAVE_LIBM) + TARGET_LINK_LIBRARIES(bsincgen m) + ENDIF() + + IF(ALSOFT_INSTALL) + INSTALL(TARGETS openal-info makehrtf bsincgen + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + ENDIF() + + MESSAGE(STATUS "Building utility programs") + IF(TARGET alsoft-config) + MESSAGE(STATUS "Building configuration program") + ENDIF() + MESSAGE(STATUS "") +ENDIF() + +IF(ALSOFT_TESTS) + ADD_LIBRARY(test-common STATIC examples/common/alhelpers.c) + SET_PROPERTY(TARGET test-common APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + + ADD_EXECUTABLE(altonegen examples/altonegen.c) + TARGET_LINK_LIBRARIES(altonegen test-common ${LIBNAME}) + SET_PROPERTY(TARGET altonegen APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + + IF(ALSOFT_INSTALL) + INSTALL(TARGETS altonegen + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + ENDIF() + + MESSAGE(STATUS "Building test programs") + MESSAGE(STATUS "") +ENDIF() + +IF(ALSOFT_EXAMPLES) + IF(SDL2_FOUND AND SDL_SOUND_FOUND) + ADD_LIBRARY(ex-common STATIC examples/common/alhelpers.c + examples/common/sdl_sound.c) + SET_PROPERTY(TARGET ex-common APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + SET_PROPERTY(TARGET ex-common APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} + ${SDL_SOUND_INCLUDE_DIR}) + + ADD_EXECUTABLE(alstream examples/alstream.c) + TARGET_LINK_LIBRARIES(alstream ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} + common ${LIBNAME}) + SET_PROPERTY(TARGET alstream APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + SET_PROPERTY(TARGET alstream APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} + ${SDL_SOUND_INCLUDE_DIR}) + + ADD_EXECUTABLE(alreverb examples/alreverb.c) + TARGET_LINK_LIBRARIES(alreverb ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} + common ${LIBNAME}) + SET_PROPERTY(TARGET alreverb APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + SET_PROPERTY(TARGET alreverb APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} + ${SDL_SOUND_INCLUDE_DIR}) + + ADD_EXECUTABLE(allatency examples/allatency.c) + TARGET_LINK_LIBRARIES(allatency ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} + common ${LIBNAME}) + SET_PROPERTY(TARGET allatency APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + SET_PROPERTY(TARGET allatency APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} + ${SDL_SOUND_INCLUDE_DIR}) + + ADD_EXECUTABLE(alloopback examples/alloopback.c) + TARGET_LINK_LIBRARIES(alloopback ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} + common ${LIBNAME}) + SET_PROPERTY(TARGET alloopback APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + SET_PROPERTY(TARGET alloopback APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} + ${SDL_SOUND_INCLUDE_DIR}) + + ADD_EXECUTABLE(alhrtf examples/alhrtf.c) + TARGET_LINK_LIBRARIES(alhrtf ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} + common ${LIBNAME}) + SET_PROPERTY(TARGET alhrtf APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + SET_PROPERTY(TARGET alhrtf APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} + ${SDL_SOUND_INCLUDE_DIR}) + + IF(ALSOFT_INSTALL) + INSTALL(TARGETS alstream alreverb allatency alloopback alhrtf + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + ENDIF() + + SET(FFVER_OK FALSE) + IF(FFMPEG_FOUND) + SET(FFVER_OK TRUE) + IF(AVFORMAT_VERSION VERSION_LESS "55.33.100") + MESSAGE(STATUS "libavformat is too old! (${AVFORMAT_VERSION}, wanted 55.33.100)") + SET(FFVER_OK FALSE) + ENDIF() + IF(AVCODEC_VERSION VERSION_LESS "55.52.102") + MESSAGE(STATUS "libavcodec is too old! (${AVCODEC_VERSION}, wanted 55.52.102)") + SET(FFVER_OK FALSE) + ENDIF() + IF(AVUTIL_VERSION VERSION_LESS "52.66.100") + MESSAGE(STATUS "libavutil is too old! (${AVUTIL_VERSION}, wanted 52.66.100)") + SET(FFVER_OK FALSE) + ENDIF() + IF(SWSCALE_VERSION VERSION_LESS "2.5.102") + MESSAGE(STATUS "libswscale is too old! (${SWSCALE_VERSION}, wanted 2.5.102)") + SET(FFVER_OK FALSE) + ENDIF() + IF(SWRESAMPLE_VERSION VERSION_LESS "0.18.100") + MESSAGE(STATUS "libswresample is too old! (${SWRESAMPLE_VERSION}, wanted 0.18.100)") + SET(FFVER_OK FALSE) + ENDIF() + ENDIF() + IF(FFVER_OK AND NOT MSVC) + ADD_EXECUTABLE(alffplay examples/alffplay.c) + TARGET_LINK_LIBRARIES(alffplay common ex-common ${SDL2_LIBRARY} ${LIBNAME} ${FFMPEG_LIBRARIES}) + SET_PROPERTY(TARGET alffplay APPEND PROPERTY COMPILE_FLAGS ${EXTRA_CFLAGS}) + SET_PROPERTY(TARGET alffplay APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} + ${FFMPEG_INCLUDE_DIRS}) + + IF(ALSOFT_INSTALL) + INSTALL(TARGETS alffplay + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + ENDIF() + MESSAGE(STATUS "Building SDL and FFmpeg example programs") + ELSE() + MESSAGE(STATUS "Building SDL example programs") + ENDIF() + MESSAGE(STATUS "") + ENDIF() +ENDIF() diff --git a/Engine/lib/openal-soft/COPYING b/Engine/lib/openal-soft/COPYING new file mode 100644 index 000000000..5bc8fb2c8 --- /dev/null +++ b/Engine/lib/openal-soft/COPYING @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if +you distribute copies of the library, or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link a program with the library, you must provide +complete object files to the recipients so that they can relink them +with the library, after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +General Public License (also called "this License"). Each licensee is +addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also compile or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + c) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + d) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the source code distributed need not include anything that is normally +distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Library General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/Engine/lib/openal-soft/ChangeLog b/Engine/lib/openal-soft/ChangeLog new file mode 100644 index 000000000..189872cf7 --- /dev/null +++ b/Engine/lib/openal-soft/ChangeLog @@ -0,0 +1,188 @@ +openal-soft-1.17.2: + + Implemented device enumeration for OSSv4. + + Fixed building on OSX. + + Fixed building on non-Windows systems without POSIX-2008. + + Fixed Dedicated Dialog and Dedicated LFE effect output. + + Added a build option to override the share install dir. + + Added a build option to static-link libgcc for MinGW. + +openal-soft-1.17.1: + + Fixed building with JACK and without PulseAudio. + + Fixed building on FreeBSD. + + Fixed the ALSA backend's allow-resampler option. + + Fixed handling of inexact ALSA period counts. + + Altered device naming scheme on Windows backends to better match other + drivers. + + Updated the CoreAudio backend to use the AudioComponent API. This clears up + deprecation warnings for OSX 10.11, although requires OSX 10.6 or newer. + +openal-soft-1.17.0: + + Implemented a JACK playback backend. + + Implemented the AL_EXT_BFORMAT and AL_EXT_MULAW_BFORMAT extensions. + + Implemented the ALC_SOFT_HRTF extension. + + Implemented C, SSE3, and SSE4.1 based 4- and 8-point Sinc resamplers. + + Implemented a C and SSE based band-limited Sinc resampler. This does 12- to + 24-point Sinc resampling, and performs anti-aliasing. + + Implemented B-Format output support for the wave file writer. This creates + FuMa-style first-order Ambisonics wave files (AMB format). + + Implemented a stereo-mode config option for treating stereo modes as either + speakers or headphones. + + Implemented per-device configuration options. + + Fixed handling of PulseAudio and MMDevAPI devices that have identical + descriptions. + + Fixed a potential lockup when stopping playback of suspended PulseAudio devices. + + Fixed logging of Unicode characters on Windows. + + Fixed 5.1 surround sound channels. By default it will now use the side + channels for the surround output. A configuration using rear channels is + still available. + + Fixed the QSA backend potentially altering the capture format. + + Fixed detecting MMDevAPI's default device. + + Fixed returning the default capture device name. + + Fixed mixing property calculations when deferring context updates. + + Altered the behavior of alcSuspendContext and alcProcessContext to better + match certain Windows drivers. + + Altered the panning algorithm, utilizing Ambisonics for better side and + back positioning cues with surround sound output. + + Improved support for certain older Windows apps. + + Improved the alffplay example to support surround sound streams. + + Improved support for building as a sub-project. + + Added an HRTF playback example. + + Added a tone generator output test. + + Added a toolchain to help with cross-compiling to Android. + +openal-soft-1.16.0: + + Implemented EFX Chorus, Flanger, Distortion, Equalizer, and Compressor + effects. + + Implemented high-pass and band-pass EFX filters. + + Implemented the high-pass filter for the EAXReverb effect. + + Implemented SSE2 and SSE4.1 linear resamplers. + + Implemented Neon-enhanced non-HRTF mixers. + + Implemented a QSA backend, for QNX. + + Implemented the ALC_SOFT_pause_device, AL_SOFT_deferred_updates, + AL_SOFT_block_alignment, AL_SOFT_MSADPCM, and AL_SOFT_source_length + extensions. + + Fixed resetting mmdevapi backend devices. + + Fixed clamping when converting 32-bit float samples to integer. + + Fixed modulation range in the Modulator effect. + + Several fixes for the OpenSL playback backend. + + Fixed device specifier names that have Unicode characters on Windows. + + Added support for filenames and paths with Unicode (UTF-8) characters on + Windows. + + Added support for alsoft.conf config files found in XDG Base Directory + Specification locations (XDG_CONFIG_DIRS and XDG_CONFIG_HOME, or their + defaults) on non-Windows systems. + + Added a GUI configuration utility (requires Qt 4.8). + + Added support for environment variable expansion in config options (not + keys or section names). + + Added an example that uses SDL2 and ffmpeg. + + Modified examples to use SDL_sound. + + Modified CMake config option names for better sorting. + + HRTF data sets specified in the hrtf_tables config option may now be + relative or absolute filenames. + + Made the default HRTF data set an external file, and added a data set for + 48khz playback in addition to 44.1khz. + + Added support for C11 atomic methods. + + Improved support for some non-GNU build systems. + +openal-soft-1.15.1: + + Fixed a regression with retrieving the source's AL_GAIN property. + +openal-soft-1.15: + + Fixed device enumeration with the OSS backend. + + Reorganized internal mixing logic, so unneeded steps can potentially be + skipped for better performance. + + Removed the lookup table for calculating the mixing pans. The panning is + now calculated directly for better precision. + + Improved the panning of stereo source channels when using stereo output. + + Improved source filter quality on send paths. + + Added a config option to allow PulseAudio to move streams between devices. + + The PulseAudio backend will now attempt to spawn a server by default. + + Added a workaround for a DirectSound bug relating to float32 output. + + Added SSE-based mixers, for HRTF and non-HRTF mixing. + + Added support for the new AL_SOFT_source_latency extension. + + Improved ALSA capture by avoiding an extra buffer when using sizes + supported by the underlying device. + + Improved the makehrtf utility to support new options and input formats. + + Modified the CFLAGS declared in the pkg-config file so the "AL/" portion of + the header includes can optionally be omitted. + + Added a couple example code programs to show how to apply reverb, and + retrieve latency. + + The configuration sample is now installed into the share/openal/ directory + instead of /etc/openal. + + The configuration sample now gets installed by default. diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alAuxEffectSlot.h b/Engine/lib/openal-soft/OpenAL32/Include/alAuxEffectSlot.h new file mode 100644 index 000000000..70fcac5c3 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alAuxEffectSlot.h @@ -0,0 +1,183 @@ +#ifndef _AL_AUXEFFECTSLOT_H_ +#define _AL_AUXEFFECTSLOT_H_ + +#include "alMain.h" +#include "alEffect.h" + +#include "align.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ALeffectStateVtable; +struct ALeffectslot; + +typedef struct ALeffectState { + RefCount Ref; + const struct ALeffectStateVtable *vtbl; + + ALfloat (*OutBuffer)[BUFFERSIZE]; + ALuint OutChannels; +} ALeffectState; + +void ALeffectState_Construct(ALeffectState *state); +void ALeffectState_Destruct(ALeffectState *state); + +struct ALeffectStateVtable { + void (*const Destruct)(ALeffectState *state); + + ALboolean (*const deviceUpdate)(ALeffectState *state, ALCdevice *device); + void (*const update)(ALeffectState *state, const ALCdevice *device, const struct ALeffectslot *slot, const union ALeffectProps *props); + void (*const process)(ALeffectState *state, ALuint samplesToDo, const ALfloat (*restrict samplesIn)[BUFFERSIZE], ALfloat (*restrict samplesOut)[BUFFERSIZE], ALuint numChannels); + + void (*const Delete)(void *ptr); +}; + +#define DEFINE_ALEFFECTSTATE_VTABLE(T) \ +DECLARE_THUNK(T, ALeffectState, void, Destruct) \ +DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*) \ +DECLARE_THUNK3(T, ALeffectState, void, update, const ALCdevice*, const ALeffectslot*, const ALeffectProps*) \ +DECLARE_THUNK4(T, ALeffectState, void, process, ALuint, const ALfloatBUFFERSIZE*restrict, ALfloatBUFFERSIZE*restrict, ALuint) \ +static void T##_ALeffectState_Delete(void *ptr) \ +{ return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); } \ + \ +static const struct ALeffectStateVtable T##_ALeffectState_vtable = { \ + T##_ALeffectState_Destruct, \ + \ + T##_ALeffectState_deviceUpdate, \ + T##_ALeffectState_update, \ + T##_ALeffectState_process, \ + \ + T##_ALeffectState_Delete, \ +} + + +struct ALeffectStateFactoryVtable; + +typedef struct ALeffectStateFactory { + const struct ALeffectStateFactoryVtable *vtbl; +} ALeffectStateFactory; + +struct ALeffectStateFactoryVtable { + ALeffectState *(*const create)(ALeffectStateFactory *factory); +}; + +#define DEFINE_ALEFFECTSTATEFACTORY_VTABLE(T) \ +DECLARE_THUNK(T, ALeffectStateFactory, ALeffectState*, create) \ + \ +static const struct ALeffectStateFactoryVtable T##_ALeffectStateFactory_vtable = { \ + T##_ALeffectStateFactory_create, \ +} + + +#define MAX_EFFECT_CHANNELS (4) + + +struct ALeffectslotProps { + ATOMIC(ALfloat) Gain; + ATOMIC(ALboolean) AuxSendAuto; + + ATOMIC(ALenum) Type; + ALeffectProps Props; + + ATOMIC(ALeffectState*) State; + + ATOMIC(struct ALeffectslotProps*) next; +}; + + +typedef struct ALeffectslot { + ALboolean NeedsUpdate; + + ALfloat Gain; + ALboolean AuxSendAuto; + + struct { + ALenum Type; + ALeffectProps Props; + + ALeffectState *State; + } Effect; + + RefCount ref; + + ATOMIC(struct ALeffectslotProps*) Update; + ATOMIC(struct ALeffectslotProps*) FreeList; + + struct { + ALfloat Gain; + ALboolean AuxSendAuto; + + ALenum EffectType; + ALeffectState *EffectState; + + ALfloat RoomRolloff; /* Added to the source's room rolloff, not multiplied. */ + ALfloat DecayTime; + ALfloat AirAbsorptionGainHF; + } Params; + + /* Self ID */ + ALuint id; + + ALuint NumChannels; + BFChannelConfig ChanMap[MAX_EFFECT_CHANNELS]; + /* Wet buffer configuration is ACN channel order with N3D scaling: + * * Channel 0 is the unattenuated mono signal. + * * Channel 1 is OpenAL -X + * * Channel 2 is OpenAL Y + * * Channel 3 is OpenAL -Z + * Consequently, effects that only want to work with mono input can use + * channel 0 by itself. Effects that want multichannel can process the + * ambisonics signal and make a B-Format pan (ComputeFirstOrderGains) for + * first-order device output (FOAOut). + */ + alignas(16) ALfloat WetBuffer[MAX_EFFECT_CHANNELS][BUFFERSIZE]; + + ATOMIC(struct ALeffectslot*) next; +} ALeffectslot; + +inline void LockEffectSlotsRead(ALCcontext *context) +{ LockUIntMapRead(&context->EffectSlotMap); } +inline void UnlockEffectSlotsRead(ALCcontext *context) +{ UnlockUIntMapRead(&context->EffectSlotMap); } +inline void LockEffectSlotsWrite(ALCcontext *context) +{ LockUIntMapWrite(&context->EffectSlotMap); } +inline void UnlockEffectSlotsWrite(ALCcontext *context) +{ UnlockUIntMapWrite(&context->EffectSlotMap); } + +inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id) +{ return (struct ALeffectslot*)LookupUIntMapKeyNoLock(&context->EffectSlotMap, id); } +inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id) +{ return (struct ALeffectslot*)RemoveUIntMapKeyNoLock(&context->EffectSlotMap, id); } + +ALenum InitEffectSlot(ALeffectslot *slot); +void DeinitEffectSlot(ALeffectslot *slot); +void UpdateEffectSlotProps(ALeffectslot *slot); +void UpdateAllEffectSlotProps(ALCcontext *context); +ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context); + + +ALeffectStateFactory *ALnullStateFactory_getFactory(void); +ALeffectStateFactory *ALreverbStateFactory_getFactory(void); +ALeffectStateFactory *ALchorusStateFactory_getFactory(void); +ALeffectStateFactory *ALcompressorStateFactory_getFactory(void); +ALeffectStateFactory *ALdistortionStateFactory_getFactory(void); +ALeffectStateFactory *ALechoStateFactory_getFactory(void); +ALeffectStateFactory *ALequalizerStateFactory_getFactory(void); +ALeffectStateFactory *ALflangerStateFactory_getFactory(void); +ALeffectStateFactory *ALmodulatorStateFactory_getFactory(void); + +ALeffectStateFactory *ALdedicatedStateFactory_getFactory(void); + + +ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect); + +void InitEffectFactoryMap(void); +void DeinitEffectFactoryMap(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alBuffer.h b/Engine/lib/openal-soft/OpenAL32/Include/alBuffer.h new file mode 100644 index 000000000..e99af050a --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alBuffer.h @@ -0,0 +1,130 @@ +#ifndef _AL_BUFFER_H_ +#define _AL_BUFFER_H_ + +#include "alMain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* User formats */ +enum UserFmtType { + UserFmtByte = AL_BYTE_SOFT, + UserFmtUByte = AL_UNSIGNED_BYTE_SOFT, + UserFmtShort = AL_SHORT_SOFT, + UserFmtUShort = AL_UNSIGNED_SHORT_SOFT, + UserFmtInt = AL_INT_SOFT, + UserFmtUInt = AL_UNSIGNED_INT_SOFT, + UserFmtFloat = AL_FLOAT_SOFT, + UserFmtDouble = AL_DOUBLE_SOFT, + UserFmtByte3 = AL_BYTE3_SOFT, + UserFmtUByte3 = AL_UNSIGNED_BYTE3_SOFT, + UserFmtMulaw = AL_MULAW_SOFT, + UserFmtAlaw = 0x10000000, + UserFmtIMA4, + UserFmtMSADPCM, +}; +enum UserFmtChannels { + UserFmtMono = AL_MONO_SOFT, + UserFmtStereo = AL_STEREO_SOFT, + UserFmtRear = AL_REAR_SOFT, + UserFmtQuad = AL_QUAD_SOFT, + UserFmtX51 = AL_5POINT1_SOFT, /* (WFX order) */ + UserFmtX61 = AL_6POINT1_SOFT, /* (WFX order) */ + UserFmtX71 = AL_7POINT1_SOFT, /* (WFX order) */ + UserFmtBFormat2D = AL_BFORMAT2D_SOFT, /* WXY */ + UserFmtBFormat3D = AL_BFORMAT3D_SOFT, /* WXYZ */ +}; + +ALuint BytesFromUserFmt(enum UserFmtType type); +ALuint ChannelsFromUserFmt(enum UserFmtChannels chans); +inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type) +{ + return ChannelsFromUserFmt(chans) * BytesFromUserFmt(type); +} + + +/* Storable formats */ +enum FmtType { + FmtByte = UserFmtByte, + FmtShort = UserFmtShort, + FmtFloat = UserFmtFloat, +}; +enum FmtChannels { + FmtMono = UserFmtMono, + FmtStereo = UserFmtStereo, + FmtRear = UserFmtRear, + FmtQuad = UserFmtQuad, + FmtX51 = UserFmtX51, + FmtX61 = UserFmtX61, + FmtX71 = UserFmtX71, + FmtBFormat2D = UserFmtBFormat2D, + FmtBFormat3D = UserFmtBFormat3D, +}; +#define MAX_INPUT_CHANNELS (8) + +ALuint BytesFromFmt(enum FmtType type); +ALuint ChannelsFromFmt(enum FmtChannels chans); +inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type) +{ + return ChannelsFromFmt(chans) * BytesFromFmt(type); +} + + +typedef struct ALbuffer { + ALvoid *data; + + ALsizei Frequency; + ALenum Format; + ALsizei SampleLen; + + enum FmtChannels FmtChannels; + enum FmtType FmtType; + ALuint BytesAlloc; + + enum UserFmtChannels OriginalChannels; + enum UserFmtType OriginalType; + ALsizei OriginalSize; + ALsizei OriginalAlign; + + ALsizei LoopStart; + ALsizei LoopEnd; + + ATOMIC(ALsizei) UnpackAlign; + ATOMIC(ALsizei) PackAlign; + + /* Number of times buffer was attached to a source (deletion can only occur when 0) */ + RefCount ref; + + RWLock lock; + + /* Self ID */ + ALuint id; +} ALbuffer; + +ALbuffer *NewBuffer(ALCcontext *context); +void DeleteBuffer(ALCdevice *device, ALbuffer *buffer); + +ALenum LoadData(ALbuffer *buffer, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc); + +inline void LockBuffersRead(ALCdevice *device) +{ LockUIntMapRead(&device->BufferMap); } +inline void UnlockBuffersRead(ALCdevice *device) +{ UnlockUIntMapRead(&device->BufferMap); } +inline void LockBuffersWrite(ALCdevice *device) +{ LockUIntMapWrite(&device->BufferMap); } +inline void UnlockBuffersWrite(ALCdevice *device) +{ UnlockUIntMapWrite(&device->BufferMap); } + +inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) +{ return (struct ALbuffer*)LookupUIntMapKeyNoLock(&device->BufferMap, id); } +inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id) +{ return (struct ALbuffer*)RemoveUIntMapKeyNoLock(&device->BufferMap, id); } + +ALvoid ReleaseALBuffers(ALCdevice *device); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alEffect.h b/Engine/lib/openal-soft/OpenAL32/Include/alEffect.h new file mode 100644 index 000000000..b97b01479 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alEffect.h @@ -0,0 +1,196 @@ +#ifndef _AL_EFFECT_H_ +#define _AL_EFFECT_H_ + +#include "alMain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ALeffect; + +enum { + EAXREVERB = 0, + REVERB, + CHORUS, + COMPRESSOR, + DISTORTION, + ECHO, + EQUALIZER, + FLANGER, + MODULATOR, + DEDICATED, + + MAX_EFFECTS +}; +extern ALboolean DisabledEffects[MAX_EFFECTS]; + +extern ALfloat ReverbBoost; +extern ALboolean EmulateEAXReverb; + +struct ALeffectVtable { + void (*const setParami)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALint val); + void (*const setParamiv)(struct ALeffect *effect, ALCcontext *context, ALenum param, const ALint *vals); + void (*const setParamf)(struct ALeffect *effect, ALCcontext *context, ALenum param, ALfloat val); + void (*const setParamfv)(struct ALeffect *effect, ALCcontext *context, ALenum param, const ALfloat *vals); + + void (*const getParami)(const struct ALeffect *effect, ALCcontext *context, ALenum param, ALint *val); + void (*const getParamiv)(const struct ALeffect *effect, ALCcontext *context, ALenum param, ALint *vals); + void (*const getParamf)(const struct ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *val); + void (*const getParamfv)(const struct ALeffect *effect, ALCcontext *context, ALenum param, ALfloat *vals); +}; + +#define DEFINE_ALEFFECT_VTABLE(T) \ +const struct ALeffectVtable T##_vtable = { \ + T##_setParami, T##_setParamiv, \ + T##_setParamf, T##_setParamfv, \ + T##_getParami, T##_getParamiv, \ + T##_getParamf, T##_getParamfv, \ +} + +extern const struct ALeffectVtable ALeaxreverb_vtable; +extern const struct ALeffectVtable ALreverb_vtable; +extern const struct ALeffectVtable ALchorus_vtable; +extern const struct ALeffectVtable ALcompressor_vtable; +extern const struct ALeffectVtable ALdistortion_vtable; +extern const struct ALeffectVtable ALecho_vtable; +extern const struct ALeffectVtable ALequalizer_vtable; +extern const struct ALeffectVtable ALflanger_vtable; +extern const struct ALeffectVtable ALmodulator_vtable; +extern const struct ALeffectVtable ALnull_vtable; +extern const struct ALeffectVtable ALdedicated_vtable; + + +typedef union ALeffectProps { + struct { + // Shared Reverb Properties + ALfloat Density; + ALfloat Diffusion; + ALfloat Gain; + ALfloat GainHF; + ALfloat DecayTime; + ALfloat DecayHFRatio; + ALfloat ReflectionsGain; + ALfloat ReflectionsDelay; + ALfloat LateReverbGain; + ALfloat LateReverbDelay; + ALfloat AirAbsorptionGainHF; + ALfloat RoomRolloffFactor; + ALboolean DecayHFLimit; + + // Additional EAX Reverb Properties + ALfloat GainLF; + ALfloat DecayLFRatio; + ALfloat ReflectionsPan[3]; + ALfloat LateReverbPan[3]; + ALfloat EchoTime; + ALfloat EchoDepth; + ALfloat ModulationTime; + ALfloat ModulationDepth; + ALfloat HFReference; + ALfloat LFReference; + } Reverb; + + struct { + ALint Waveform; + ALint Phase; + ALfloat Rate; + ALfloat Depth; + ALfloat Feedback; + ALfloat Delay; + } Chorus; + + struct { + ALboolean OnOff; + } Compressor; + + struct { + ALfloat Edge; + ALfloat Gain; + ALfloat LowpassCutoff; + ALfloat EQCenter; + ALfloat EQBandwidth; + } Distortion; + + struct { + ALfloat Delay; + ALfloat LRDelay; + + ALfloat Damping; + ALfloat Feedback; + + ALfloat Spread; + } Echo; + + struct { + ALfloat LowCutoff; + ALfloat LowGain; + ALfloat Mid1Center; + ALfloat Mid1Gain; + ALfloat Mid1Width; + ALfloat Mid2Center; + ALfloat Mid2Gain; + ALfloat Mid2Width; + ALfloat HighCutoff; + ALfloat HighGain; + } Equalizer; + + struct { + ALint Waveform; + ALint Phase; + ALfloat Rate; + ALfloat Depth; + ALfloat Feedback; + ALfloat Delay; + } Flanger; + + struct { + ALfloat Frequency; + ALfloat HighPassCutoff; + ALint Waveform; + } Modulator; + + struct { + ALfloat Gain; + } Dedicated; +} ALeffectProps; + +typedef struct ALeffect { + // Effect type (AL_EFFECT_NULL, ...) + ALenum type; + + ALeffectProps Props; + + const struct ALeffectVtable *vtbl; + + /* Self ID */ + ALuint id; +} ALeffect; + +inline void LockEffectsRead(ALCdevice *device) +{ LockUIntMapRead(&device->EffectMap); } +inline void UnlockEffectsRead(ALCdevice *device) +{ UnlockUIntMapRead(&device->EffectMap); } +inline void LockEffectsWrite(ALCdevice *device) +{ LockUIntMapWrite(&device->EffectMap); } +inline void UnlockEffectsWrite(ALCdevice *device) +{ UnlockUIntMapWrite(&device->EffectMap); } + +inline struct ALeffect *LookupEffect(ALCdevice *device, ALuint id) +{ return (struct ALeffect*)LookupUIntMapKeyNoLock(&device->EffectMap, id); } +inline struct ALeffect *RemoveEffect(ALCdevice *device, ALuint id) +{ return (struct ALeffect*)RemoveUIntMapKeyNoLock(&device->EffectMap, id); } + +inline ALboolean IsReverbEffect(ALenum type) +{ return type == AL_EFFECT_REVERB || type == AL_EFFECT_EAXREVERB; } + +ALenum InitEffect(ALeffect *effect); +ALvoid ReleaseALEffects(ALCdevice *device); + +ALvoid LoadReverbPreset(const char *name, ALeffect *effect); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alError.h b/Engine/lib/openal-soft/OpenAL32/Include/alError.h new file mode 100644 index 000000000..ab91d27b2 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alError.h @@ -0,0 +1,33 @@ +#ifndef _AL_ERROR_H_ +#define _AL_ERROR_H_ + +#include "alMain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern ALboolean TrapALError; + +ALvoid alSetError(ALCcontext *Context, ALenum errorCode); + +#define SET_ERROR_AND_RETURN(ctx, err) do { \ + alSetError((ctx), (err)); \ + return; \ +} while(0) + +#define SET_ERROR_AND_RETURN_VALUE(ctx, err, val) do { \ + alSetError((ctx), (err)); \ + return (val); \ +} while(0) + +#define SET_ERROR_AND_GOTO(ctx, err, lbl) do { \ + alSetError((ctx), (err)); \ + goto lbl; \ +} while(0) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alFilter.h b/Engine/lib/openal-soft/OpenAL32/Include/alFilter.h new file mode 100644 index 000000000..1f7095bc6 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alFilter.h @@ -0,0 +1,155 @@ +#ifndef _AL_FILTER_H_ +#define _AL_FILTER_H_ + +#include "alMain.h" + +#include "math_defs.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 + */ +/* Implementation note: For the shelf filters, the specified gain is for the + * reference frequency, which is the centerpoint of the transition band. This + * better matches EFX filter design. To set the gain for the shelf itself, use + * the square root of the desired linear gain (or halve the dB gain). + */ + +typedef enum ALfilterType { + /** EFX-style low-pass filter, specifying a gain and reference frequency. */ + ALfilterType_HighShelf, + /** EFX-style high-pass filter, specifying a gain and reference frequency. */ + ALfilterType_LowShelf, + /** Peaking filter, specifying a gain and reference frequency. */ + ALfilterType_Peaking, + + /** Low-pass cut-off filter, specifying a cut-off frequency. */ + ALfilterType_LowPass, + /** High-pass cut-off filter, specifying a cut-off frequency. */ + ALfilterType_HighPass, + /** Band-pass filter, specifying a center frequency. */ + ALfilterType_BandPass, +} ALfilterType; + +typedef struct ALfilterState { + ALfloat x[2]; /* History of two last input samples */ + ALfloat y[2]; /* History of two last output samples */ + ALfloat a1, a2; /* Transfer function coefficients "a" (a0 is pre-applied) */ + ALfloat b0, b1, b2; /* Transfer function coefficients "b" */ +} ALfilterState; +/* Currently only a C-based filter process method is implemented. */ +#define ALfilterState_process ALfilterState_processC + +/* Calculates the rcpQ (i.e. 1/Q) coefficient for shelving filters, using the + * reference gain and shelf slope parameter. + * 0 < gain + * 0 < slope <= 1 + */ +inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope) +{ + return sqrtf((gain + 1.0f/gain)*(1.0f/slope - 1.0f) + 2.0f); +} +/* Calculates the rcpQ (i.e. 1/Q) coefficient for filters, using the frequency + * multiple (i.e. ref_freq / sampling_freq) and bandwidth. + * 0 < freq_mult < 0.5. + */ +inline ALfloat calc_rcpQ_from_bandwidth(ALfloat freq_mult, ALfloat bandwidth) +{ + ALfloat w0 = F_TAU * freq_mult; + return 2.0f*sinhf(logf(2.0f)/2.0f*bandwidth*w0/sinf(w0)); +} + +inline void ALfilterState_clear(ALfilterState *filter) +{ + filter->x[0] = 0.0f; + filter->x[1] = 0.0f; + filter->y[0] = 0.0f; + filter->y[1] = 0.0f; +} + +void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat rcpQ); + +void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *restrict src, ALuint numsamples); + +inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *restrict src, ALuint numsamples) +{ + if(numsamples >= 2) + { + filter->x[1] = src[numsamples-2]; + filter->x[0] = src[numsamples-1]; + filter->y[1] = src[numsamples-2]; + filter->y[0] = src[numsamples-1]; + } + else if(numsamples == 1) + { + filter->x[1] = filter->x[0]; + filter->x[0] = src[0]; + filter->y[1] = filter->y[0]; + filter->y[0] = src[0]; + } +} + + +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 void LockFiltersRead(ALCdevice *device) +{ LockUIntMapRead(&device->FilterMap); } +inline void UnlockFiltersRead(ALCdevice *device) +{ UnlockUIntMapRead(&device->FilterMap); } +inline void LockFiltersWrite(ALCdevice *device) +{ LockUIntMapWrite(&device->FilterMap); } +inline void UnlockFiltersWrite(ALCdevice *device) +{ UnlockUIntMapWrite(&device->FilterMap); } + +inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id) +{ return (struct ALfilter*)LookupUIntMapKeyNoLock(&device->FilterMap, id); } +inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id) +{ return (struct ALfilter*)RemoveUIntMapKeyNoLock(&device->FilterMap, id); } + +ALvoid ReleaseALFilters(ALCdevice *device); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alListener.h b/Engine/lib/openal-soft/OpenAL32/Include/alListener.h new file mode 100644 index 000000000..b89a00e7a --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alListener.h @@ -0,0 +1,66 @@ +#ifndef _AL_LISTENER_H_ +#define _AL_LISTENER_H_ + +#include "alMain.h" +#include "alu.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ALlistenerProps { + ATOMIC(ALfloat) Position[3]; + ATOMIC(ALfloat) Velocity[3]; + ATOMIC(ALfloat) Forward[3]; + ATOMIC(ALfloat) Up[3]; + ATOMIC(ALfloat) Gain; + ATOMIC(ALfloat) MetersPerUnit; + + ATOMIC(ALfloat) DopplerFactor; + ATOMIC(ALfloat) DopplerVelocity; + ATOMIC(ALfloat) SpeedOfSound; + ATOMIC(ALboolean) SourceDistanceModel; + ATOMIC(enum DistanceModel) DistanceModel; + + ATOMIC(struct ALlistenerProps*) next; +}; + +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; + + /* Pointer to the most recent property values that are awaiting an update. + */ + ATOMIC(struct ALlistenerProps*) Update; + + /* A linked list of unused property containers, free to use for future + * updates. + */ + ATOMIC(struct ALlistenerProps*) FreeList; + + struct { + aluMatrixf Matrix; + aluVector Velocity; + + ALfloat Gain; + ALfloat MetersPerUnit; + + ALfloat DopplerFactor; + ALfloat SpeedOfSound; + + ALboolean SourceDistanceModel; + enum DistanceModel DistanceModel; + } Params; +} ALlistener; + +void UpdateListenerProps(ALCcontext *context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alMain.h b/Engine/lib/openal-soft/OpenAL32/Include/alMain.h new file mode 100644 index 000000000..837e1082b --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alMain.h @@ -0,0 +1,967 @@ +#ifndef AL_MAIN_H +#define AL_MAIN_H + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_STRINGS_H +#include +#endif + +#ifdef HAVE_FENV_H +#include +#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" +#include "almalloc.h" +#include "threads.h" + +#include "hrtf.h" + +#ifndef ALC_SOFT_device_clock +#define ALC_SOFT_device_clock 1 +typedef int64_t ALCint64SOFT; +typedef uint64_t ALCuint64SOFT; +#define ALC_DEVICE_CLOCK_SOFT 0x1600 +#define ALC_DEVICE_LATENCY_SOFT 0x1601 +#define ALC_DEVICE_CLOCK_LATENCY_SOFT 0x1602 +typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); +#ifdef AL_ALEXT_PROTOTYPES +ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); +#endif +#endif + +#ifndef AL_SOFT_buffer_samples2 +#define AL_SOFT_buffer_samples2 1 +/* Channel configurations */ +#define AL_MONO_SOFT 0x1500 +#define AL_STEREO_SOFT 0x1501 +#define AL_REAR_SOFT 0x1502 +#define AL_QUAD_SOFT 0x1503 +#define AL_5POINT1_SOFT 0x1504 +#define AL_6POINT1_SOFT 0x1505 +#define AL_7POINT1_SOFT 0x1506 +#define AL_BFORMAT2D_SOFT 0x1507 +#define AL_BFORMAT3D_SOFT 0x1508 + +/* Sample types */ +#define AL_BYTE_SOFT 0x1400 +#define AL_UNSIGNED_BYTE_SOFT 0x1401 +#define AL_SHORT_SOFT 0x1402 +#define AL_UNSIGNED_SHORT_SOFT 0x1403 +#define AL_INT_SOFT 0x1404 +#define AL_UNSIGNED_INT_SOFT 0x1405 +#define AL_FLOAT_SOFT 0x1406 +#define AL_DOUBLE_SOFT 0x1407 +#define AL_BYTE3_SOFT 0x1408 +#define AL_UNSIGNED_BYTE3_SOFT 0x1409 +#define AL_MULAW_SOFT 0x140A + +/* Storage formats */ +#define AL_MONO8_SOFT 0x1100 +#define AL_MONO16_SOFT 0x1101 +#define AL_MONO32F_SOFT 0x10010 +#define AL_STEREO8_SOFT 0x1102 +#define AL_STEREO16_SOFT 0x1103 +#define AL_STEREO32F_SOFT 0x10011 +#define AL_QUAD8_SOFT 0x1204 +#define AL_QUAD16_SOFT 0x1205 +#define AL_QUAD32F_SOFT 0x1206 +#define AL_REAR8_SOFT 0x1207 +#define AL_REAR16_SOFT 0x1208 +#define AL_REAR32F_SOFT 0x1209 +#define AL_5POINT1_8_SOFT 0x120A +#define AL_5POINT1_16_SOFT 0x120B +#define AL_5POINT1_32F_SOFT 0x120C +#define AL_6POINT1_8_SOFT 0x120D +#define AL_6POINT1_16_SOFT 0x120E +#define AL_6POINT1_32F_SOFT 0x120F +#define AL_7POINT1_8_SOFT 0x1210 +#define AL_7POINT1_16_SOFT 0x1211 +#define AL_7POINT1_32F_SOFT 0x1212 +#define AL_BFORMAT2D_8_SOFT 0x20021 +#define AL_BFORMAT2D_16_SOFT 0x20022 +#define AL_BFORMAT2D_32F_SOFT 0x20023 +#define AL_BFORMAT3D_8_SOFT 0x20031 +#define AL_BFORMAT3D_16_SOFT 0x20032 +#define AL_BFORMAT3D_32F_SOFT 0x20033 + +/* Buffer attributes */ +#define AL_INTERNAL_FORMAT_SOFT 0x2008 +#define AL_BYTE_LENGTH_SOFT 0x2009 +#define AL_SAMPLE_LENGTH_SOFT 0x200A +#define AL_SEC_LENGTH_SOFT 0x200B + +#if 0 +typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*); +typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*); +typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum); +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data); +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); +#endif +#endif +#endif + + +#ifdef __GNUC__ +/* Because of a long-standing deficiency in C, you're not allowed to implicitly + * cast a pointer-to-type-array to a pointer-to-const-type-array. For example, + * + * int (*ptr)[10]; + * const int (*cptr)[10] = ptr; + * + * is not allowed and most compilers will generate noisy warnings about + * incompatible types, even though it just makes the array elements const. + * Clang will allow it if you make the array type a typedef, like this: + * + * typedef int int10[10]; + * int10 *ptr; + * const int10 *cptr = ptr; + * + * however GCC does not and still issues the incompatible type warning. The + * "proper" way to fix it is to add an explicit cast for the constified type, + * but that removes the vast majority of otherwise useful type-checking you'd + * get, and runs the risk of improper casts if types are later changed. Leaving + * it non-const can also be an issue if you use it as a function parameter, and + * happen to have a const type as input (and also reduce the capabilities of + * the compiler to better optimize the function). + * + * So to work around the problem, we use a macro. The macro first assigns the + * incoming variable to the specified non-const type to ensure it's the correct + * type, then casts the variable as the desired constified type. Very ugly, but + * I'd rather not have hundreds of lines of warnings because I want to tell the + * compiler that some array(s) can't be changed by the code, or have lots of + * error-prone casts. + */ +#define SAFE_CONST(T, var) __extension__({ \ + T _tmp = (var); \ + (const T)_tmp; \ +}) +#else +/* Non-GNU-compatible compilers have to use a straight cast with no extra + * checks, due to the lack of multi-statement expressions. + */ +#define SAFE_CONST(T, var) ((const T)(var)) +#endif + + +typedef ALint64SOFT ALint64; +typedef ALuint64SOFT ALuint64; + +#ifndef U64 +#if defined(_MSC_VER) +#define U64(x) ((ALuint64)(x##ui64)) +#elif SIZEOF_LONG == 8 +#define U64(x) ((ALuint64)(x##ul)) +#elif SIZEOF_LONG_LONG == 8 +#define U64(x) ((ALuint64)(x##ull)) +#endif +#endif + +#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_FORMAT(x, y, z) __attribute__((format(x, (y), (z)))) +#else +#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_THUNK4(T1, T2, rettype, func, argtype1, argtype2, argtype3, argtype4) \ +static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c, argtype4 d) \ +{ return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c, d); } + +#define DECLARE_DEFAULT_ALLOCATORS(T) \ +static void* T##_New(size_t size) { return al_malloc(16, size); } \ +static void T##_Delete(void *ptr) { al_free(ptr); } + +/* 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) + + +#define EXTRACT_NEW_ARGS(...) __VA_ARGS__); \ + } \ +} while(0) + +#define NEW_OBJ(_res, T) do { \ + _res = T##_New(sizeof(T)); \ + if(_res) \ + { \ + memset(_res, 0, sizeof(T)); \ + T##_Construct(_res, EXTRACT_NEW_ARGS +#define NEW_OBJ0(_res, T) do { \ + _res = T##_New(sizeof(T)); \ + if(_res) \ + { \ + memset(_res, 0, sizeof(T)); \ + T##_Construct(_res EXTRACT_NEW_ARGS + + +#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*); +} BackendFuncs; + +ALCboolean alc_sndio_init(BackendFuncs *func_list); +void alc_sndio_deinit(void); +void alc_sndio_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 Channel { + FrontLeft = 0, + FrontRight, + FrontCenter, + LFE, + BackLeft, + BackRight, + BackCenter, + SideLeft, + SideRight, + + UpperFrontLeft, + UpperFrontRight, + UpperBackLeft, + UpperBackRight, + LowerFrontLeft, + LowerFrontRight, + LowerBackLeft, + LowerBackRight, + + Aux0, + Aux1, + Aux2, + Aux3, + Aux4, + Aux5, + Aux6, + Aux7, + Aux8, + Aux9, + Aux10, + Aux11, + Aux12, + Aux13, + Aux14, + Aux15, + + InvalidChannel +}; + + +/* 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 rear channels instead of sides */ + DevFmtX51Rear = 0x80000000, + + /* Ambisonic formats should be kept together */ + DevFmtAmbi1, + DevFmtAmbi2, + DevFmtAmbi3, + + DevFmtChannelsDefault = DevFmtStereo +}; +#define MAX_OUTPUT_CHANNELS (16) + +ALuint BytesFromDevFmt(enum DevFmtType type); +ALuint ChannelsFromDevFmt(enum DevFmtChannels chans); +inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type) +{ + return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type); +} + +enum AmbiFormat { + AmbiFormat_FuMa, /* FuMa channel order and normalization */ + AmbiFormat_ACN_SN3D, /* ACN channel order and SN3D normalization */ + AmbiFormat_ACN_N3D, /* ACN channel order and N3D normalization */ + + AmbiFormat_Default = AmbiFormat_ACN_SN3D +}; + + +extern const struct EffectList { + const char *name; + int type; + const char *ename; + ALenum val; +} EffectList[]; + + +enum DeviceType { + Playback, + Capture, + Loopback +}; + + +enum RenderMode { + NormalRender, + StereoPair, + HrtfRender +}; + + +/* The maximum number of Ambisonics coefficients. For a given order (o), the + * size needed will be (o+1)**2, thus zero-order has 1, first-order has 4, + * second-order has 9, third-order has 16, and fourth-order has 25. + */ +#define MAX_AMBI_ORDER 3 +#define MAX_AMBI_COEFFS ((MAX_AMBI_ORDER+1) * (MAX_AMBI_ORDER+1)) + +/* A bitmask of ambisonic channels with height information. If none of these + * channels are used/needed, there's no height (e.g. with most surround sound + * speaker setups). This only specifies up to 4th order, which is the highest + * order a 32-bit mask value can specify (a 64-bit mask could handle up to 7th + * order). This is ACN ordering, with bit 0 being ACN 0, etc. + */ +#define AMBI_PERIPHONIC_MASK (0xfe7ce4) + +/* The maximum number of Ambisonic coefficients for 2D (non-periphonic) + * representation. This is 2 per each order above zero-order, plus 1 for zero- + * order. Or simply, o*2 + 1. + */ +#define MAX_AMBI2D_COEFFS (MAX_AMBI_ORDER*2 + 1) + + +typedef ALfloat ChannelConfig[MAX_AMBI_COEFFS]; +typedef struct BFChannelConfig { + ALfloat Scale; + ALuint Index; +} BFChannelConfig; + +typedef union AmbiConfig { + /* Ambisonic coefficients for mixing to the dry buffer. */ + ChannelConfig Coeffs[MAX_OUTPUT_CHANNELS]; + /* Coefficient channel mapping for mixing to the dry buffer. */ + BFChannelConfig Map[MAX_OUTPUT_CHANNELS]; +} AmbiConfig; + + +#define HRTF_HISTORY_BITS (6) +#define HRTF_HISTORY_LENGTH (1<Device); } + +inline void UnlockContext(ALCcontext *context) +{ ALCdevice_Unlock(context->Device); } + +enum { + DeferOff = AL_FALSE, + DeferAll, + DeferAllowPlay +}; + + +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 ll_ringbuffer ll_ringbuffer_t; +typedef struct ll_ringbuffer_data { + char *buf; + size_t len; +} ll_ringbuffer_data_t; +ll_ringbuffer_t *ll_ringbuffer_create(size_t sz, size_t elem_sz); +void ll_ringbuffer_free(ll_ringbuffer_t *rb); +void ll_ringbuffer_get_read_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec); +void ll_ringbuffer_get_write_vector(const ll_ringbuffer_t *rb, ll_ringbuffer_data_t *vec); +size_t ll_ringbuffer_read(ll_ringbuffer_t *rb, char *dest, size_t cnt); +size_t ll_ringbuffer_peek(ll_ringbuffer_t *rb, char *dest, size_t cnt); +void ll_ringbuffer_read_advance(ll_ringbuffer_t *rb, size_t cnt); +size_t ll_ringbuffer_read_space(const ll_ringbuffer_t *rb); +int ll_ringbuffer_mlock(ll_ringbuffer_t *rb); +void ll_ringbuffer_reset(ll_ringbuffer_t *rb); +size_t ll_ringbuffer_write(ll_ringbuffer_t *rb, const char *src, size_t cnt); +void ll_ringbuffer_write_advance(ll_ringbuffer_t *rb, size_t cnt); +size_t ll_ringbuffer_write_space(const ll_ringbuffer_t *rb); + +void ReadALConfig(void); +void FreeALConfig(void); +int ConfigValueExists(const char *devName, const char *blockName, const char *keyName); +const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName, const char *def); +int GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, int def); +int ConfigValueStr(const char *devName, const char *blockName, const char *keyName, const char **ret); +int ConfigValueInt(const char *devName, const char *blockName, const char *keyName, int *ret); +int ConfigValueUInt(const char *devName, const char *blockName, const char *keyName, unsigned int *ret); +int ConfigValueFloat(const char *devName, const char *blockName, const char *keyName, float *ret); +int ConfigValueBool(const char *devName, const char *blockName, const char *keyName, int *ret); + +void SetRTPriority(void); + +void SetDefaultChannelOrder(ALCdevice *device); +void SetDefaultWFXChannelOrder(ALCdevice *device); + +const ALCchar *DevFmtTypeString(enum DevFmtType type); +const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans); + +/** + * GetChannelIdxByName + * + * Returns the index for the given channel name (e.g. FrontCenter), or -1 if it + * doesn't exist. + */ +inline ALint GetChannelIndex(const enum Channel names[MAX_OUTPUT_CHANNELS], enum Channel chan) +{ + ALint i; + for(i = 0;i < MAX_OUTPUT_CHANNELS;i++) + { + if(names[i] == chan) + return i; + } + return -1; +} +#define GetChannelIdxByName(x, c) GetChannelIndex((x).ChannelName, (c)) + +extern FILE *LogFile; + +#if defined(__GNUC__) && !defined(_WIN32) && !defined(IN_IDE_PARSER) +#define AL_PRINT(T, MSG, ...) fprintf(LogFile, "AL lib: %s %s: "MSG, T, __FUNCTION__ , ## __VA_ARGS__) +#else +void al_print(const char *type, const char *func, const char *fmt, ...) DECL_FORMAT(printf, 3,4); +#define AL_PRINT(T, ...) al_print((T), __FUNCTION__, __VA_ARGS__) +#endif + +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_SSE3 = 1<<2, + CPU_CAP_SSE4_1 = 1<<3, + CPU_CAP_NEON = 1<<4, +}; + +void FillCPUCaps(ALuint capfilter); + +vector_al_string SearchDataFiles(const char *match, 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 diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alSource.h b/Engine/lib/openal-soft/OpenAL32/Include/alSource.h new file mode 100644 index 000000000..b288937a3 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alSource.h @@ -0,0 +1,231 @@ +#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 + +struct ALbuffer; +struct ALsource; +struct ALsourceProps; + + +typedef struct ALbufferlistitem { + struct ALbuffer *buffer; + struct ALbufferlistitem *volatile next; +} ALbufferlistitem; + + +struct ALsourceProps { + ATOMIC(ALfloat) Pitch; + ATOMIC(ALfloat) Gain; + ATOMIC(ALfloat) OuterGain; + ATOMIC(ALfloat) MinGain; + ATOMIC(ALfloat) MaxGain; + ATOMIC(ALfloat) InnerAngle; + ATOMIC(ALfloat) OuterAngle; + ATOMIC(ALfloat) RefDistance; + ATOMIC(ALfloat) MaxDistance; + ATOMIC(ALfloat) RollOffFactor; + ATOMIC(ALfloat) Position[3]; + ATOMIC(ALfloat) Velocity[3]; + ATOMIC(ALfloat) Direction[3]; + ATOMIC(ALfloat) Orientation[2][3]; + ATOMIC(ALboolean) HeadRelative; + ATOMIC(enum DistanceModel) DistanceModel; + ATOMIC(ALboolean) DirectChannels; + + ATOMIC(ALboolean) DryGainHFAuto; + ATOMIC(ALboolean) WetGainAuto; + ATOMIC(ALboolean) WetGainHFAuto; + ATOMIC(ALfloat) OuterGainHF; + + ATOMIC(ALfloat) AirAbsorptionFactor; + ATOMIC(ALfloat) RoomRolloffFactor; + ATOMIC(ALfloat) DopplerFactor; + + ATOMIC(ALfloat) StereoPan[2]; + + ATOMIC(ALfloat) Radius; + + /** Direct filter and auxiliary send info. */ + struct { + ATOMIC(ALfloat) Gain; + ATOMIC(ALfloat) GainHF; + ATOMIC(ALfloat) HFReference; + ATOMIC(ALfloat) GainLF; + ATOMIC(ALfloat) LFReference; + } Direct; + struct { + ATOMIC(struct ALeffectslot*) Slot; + ATOMIC(ALfloat) Gain; + ATOMIC(ALfloat) GainHF; + ATOMIC(ALfloat) HFReference; + ATOMIC(ALfloat) GainLF; + ATOMIC(ALfloat) LFReference; + } Send[MAX_SENDS]; + + ATOMIC(struct ALsourceProps*) next; +}; + + +typedef struct ALvoice { + struct ALsourceProps Props; + + struct ALsource *volatile Source; + + /** Current target parameters used for mixing. */ + ALint Step; + + /* If not 'moving', gain/coefficients are set directly without fading. */ + ALboolean Moving; + + ALboolean IsHrtf; + + ALuint Offset; /* Number of output samples mixed since starting. */ + + alignas(16) ALfloat PrevSamples[MAX_INPUT_CHANNELS][MAX_PRE_SAMPLES]; + + BsincState SincState; + + struct { + ALfloat (*Buffer)[BUFFERSIZE]; + ALuint Channels; + } DirectOut; + + struct { + ALfloat (*Buffer)[BUFFERSIZE]; + ALuint Channels; + } SendOut[MAX_SENDS]; + + struct { + DirectParams Direct; + SendParams Send[MAX_SENDS]; + } Chan[MAX_INPUT_CHANNELS]; +} ALvoice; + + +typedef struct ALsource { + /** Source properties. */ + ALfloat Pitch; + ALfloat Gain; + ALfloat OuterGain; + ALfloat MinGain; + ALfloat MaxGain; + ALfloat InnerAngle; + ALfloat OuterAngle; + ALfloat RefDistance; + ALfloat MaxDistance; + ALfloat RollOffFactor; + ALfloat Position[3]; + ALfloat Velocity[3]; + ALfloat Direction[3]; + ALfloat Orientation[2][3]; + ALboolean HeadRelative; + enum DistanceModel DistanceModel; + ALboolean DirectChannels; + + ALboolean DryGainHFAuto; + ALboolean WetGainAuto; + ALboolean WetGainHFAuto; + ALfloat OuterGainHF; + + ALfloat AirAbsorptionFactor; + ALfloat RoomRolloffFactor; + ALfloat DopplerFactor; + + /* NOTE: Stereo pan angles are specified in radians, counter-clockwise + * rather than clockwise. + */ + ALfloat StereoPan[2]; + + ALfloat Radius; + + /** 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]; + + /** + * Last user-specified offset, and the offset type (bytes, samples, or + * seconds). + */ + ALdouble Offset; + ALenum OffsetType; + + /** Source type (static, streaming, or undetermined) */ + ALint SourceType; + + /** Source state (initial, playing, paused, or stopped) */ + ALenum state; + ALenum new_state; + + /** Source Buffer Queue info. */ + RWLock queue_lock; + ATOMIC(ALbufferlistitem*) queue; + ATOMIC(ALbufferlistitem*) current_buffer; + + /** + * Source offset in samples, relative to the currently playing buffer, NOT + * the whole queue, and the fractional (fixed-point) offset to the next + * sample. + */ + ATOMIC(ALuint) position; + ATOMIC(ALuint) position_fraction; + + ATOMIC(ALboolean) looping; + + /** Current buffer sample info. */ + ALuint NumChannels; + ALuint SampleSize; + + ATOMIC(struct ALsourceProps*) Update; + ATOMIC(struct ALsourceProps*) FreeList; + + /** Self ID */ + ALuint id; +} ALsource; + +inline void LockSourcesRead(ALCcontext *context) +{ LockUIntMapRead(&context->SourceMap); } +inline void UnlockSourcesRead(ALCcontext *context) +{ UnlockUIntMapRead(&context->SourceMap); } +inline void LockSourcesWrite(ALCcontext *context) +{ LockUIntMapWrite(&context->SourceMap); } +inline void UnlockSourcesWrite(ALCcontext *context) +{ UnlockUIntMapWrite(&context->SourceMap); } + +inline struct ALsource *LookupSource(ALCcontext *context, ALuint id) +{ return (struct ALsource*)LookupUIntMapKeyNoLock(&context->SourceMap, id); } +inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id) +{ return (struct ALsource*)RemoveUIntMapKeyNoLock(&context->SourceMap, id); } + +void UpdateAllSourceProps(ALCcontext *context); +ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state); +ALboolean ApplyOffset(ALsource *Source); + +ALvoid ReleaseALSources(ALCcontext *Context); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alThunk.h b/Engine/lib/openal-soft/OpenAL32/Include/alThunk.h new file mode 100644 index 000000000..adc77dec9 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alThunk.h @@ -0,0 +1,20 @@ +#ifndef ALTHUNK_H +#define ALTHUNK_H + +#include "alMain.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void ThunkInit(void); +void ThunkExit(void); +ALenum NewThunkEntry(ALuint *index); +void FreeThunkEntry(ALuint index); + +#ifdef __cplusplus +} +#endif + +#endif //ALTHUNK_H + diff --git a/Engine/lib/openal-soft/OpenAL32/Include/alu.h b/Engine/lib/openal-soft/OpenAL32/Include/alu.h new file mode 100644 index 000000000..ae8645fa7 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/alu.h @@ -0,0 +1,363 @@ +#ifndef _ALU_H_ +#define _ALU_H_ + +#include +#include +#ifdef HAVE_FLOAT_H +#include +#endif +#ifdef HAVE_IEEEFP_H +#include +#endif + +#include "alMain.h" +#include "alBuffer.h" +#include "alFilter.h" +#include "alAuxEffectSlot.h" + +#include "hrtf.h" +#include "align.h" +#include "math_defs.h" + + +#define MAX_PITCH (255) + +/* Maximum number of buffer samples before the current pos needed for resampling. */ +#define MAX_PRE_SAMPLES 12 + +/* Maximum number of buffer samples after the current pos needed for resampling. */ +#define MAX_POST_SAMPLES 12 + + +#ifdef __cplusplus +extern "C" { +#endif + +struct ALsource; +struct ALsourceProps; +struct ALvoice; +struct ALeffectslot; +struct ALbuffer; + + +/* The number of distinct scale and phase intervals within the filter table. */ +#define BSINC_SCALE_BITS 4 +#define BSINC_SCALE_COUNT (1<v[0] = x; + vector->v[1] = y; + vector->v[2] = z; + vector->v[3] = w; +} + + +typedef union aluMatrixf { + alignas(16) ALfloat m[4][4]; +} aluMatrixf; +extern const aluMatrixf IdentityMatrixf; + +inline void aluMatrixfSetRow(aluMatrixf *matrix, ALuint row, + ALfloat m0, ALfloat m1, ALfloat m2, ALfloat m3) +{ + matrix->m[row][0] = m0; + matrix->m[row][1] = m1; + matrix->m[row][2] = m2; + matrix->m[row][3] = m3; +} + +inline void aluMatrixfSet(aluMatrixf *matrix, ALfloat m00, ALfloat m01, ALfloat m02, ALfloat m03, + ALfloat m10, ALfloat m11, ALfloat m12, ALfloat m13, + ALfloat m20, ALfloat m21, ALfloat m22, ALfloat m23, + ALfloat m30, ALfloat m31, ALfloat m32, ALfloat m33) +{ + aluMatrixfSetRow(matrix, 0, m00, m01, m02, m03); + aluMatrixfSetRow(matrix, 1, m10, m11, m12, m13); + aluMatrixfSetRow(matrix, 2, m20, m21, m22, m23); + aluMatrixfSetRow(matrix, 3, m30, m31, m32, m33); +} + + +enum ActiveFilters { + AF_None = 0, + AF_LowPass = 1, + AF_HighPass = 2, + AF_BandPass = AF_LowPass | AF_HighPass +}; + + +typedef struct MixHrtfParams { + const HrtfParams *Target; + HrtfParams *Current; + struct { + alignas(16) ALfloat Coeffs[HRIR_LENGTH][2]; + ALint Delay[2]; + } Steps; +} MixHrtfParams; + +typedef struct DirectParams { + enum ActiveFilters FilterType; + ALfilterState LowPass; + ALfilterState HighPass; + + struct { + HrtfParams Current; + HrtfParams Target; + HrtfState State; + } Hrtf; + + struct { + ALfloat Current[MAX_OUTPUT_CHANNELS]; + ALfloat Target[MAX_OUTPUT_CHANNELS]; + } Gains; +} DirectParams; + +typedef struct SendParams { + enum ActiveFilters FilterType; + ALfilterState LowPass; + ALfilterState HighPass; + + struct { + ALfloat Current[MAX_OUTPUT_CHANNELS]; + ALfloat Target[MAX_OUTPUT_CHANNELS]; + } Gains; +} SendParams; + + +typedef const ALfloat* (*ResamplerFunc)(const BsincState *state, + const ALfloat *restrict src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen +); + +typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans, + ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALfloat *CurrentGains, + const ALfloat *TargetGains, ALuint Counter, ALuint OutPos, + ALuint BufferSize); +typedef void (*RowMixerFunc)(ALfloat *OutBuffer, const ALfloat *gains, + const ALfloat (*restrict data)[BUFFERSIZE], ALuint InChans, + ALuint InPos, ALuint BufferSize); +typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], ALuint lidx, ALuint ridx, + const ALfloat *data, ALuint Counter, ALuint Offset, ALuint OutPos, + const ALuint IrSize, const MixHrtfParams *hrtfparams, + HrtfState *hrtfstate, ALuint BufferSize); +typedef void (*HrtfDirectMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], + ALuint lidx, ALuint ridx, const ALfloat *data, ALuint Offset, + const ALuint IrSize, ALfloat (*restrict Coeffs)[2], + ALfloat (*restrict Values)[2], ALuint BufferSize); + + +#define GAIN_MIX_MAX (16.0f) /* +24dB */ + +#define GAIN_SILENCE_THRESHOLD (0.00001f) /* -100dB */ + +#define SPEEDOFSOUNDMETRESPERSEC (343.3f) +#define AIRABSORBGAINHF (0.99426f) /* -0.05dB */ + +#define FRACTIONBITS (12) +#define FRACTIONONE (1< 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)); } + + +union ResamplerCoeffs { + ALfloat FIR4[FRACTIONONE][4]; + ALfloat FIR8[FRACTIONONE][8]; +}; +extern alignas(16) union ResamplerCoeffs ResampleCoeffs; + +extern alignas(16) const ALfloat bsincTab[18840]; + + +inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu) +{ + return val1 + (val2-val1)*mu; +} +inline ALfloat resample_fir4(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALuint frac) +{ + const ALfloat *k = ResampleCoeffs.FIR4[frac]; + return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3; +} +inline ALfloat resample_fir8(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat val4, ALfloat val5, ALfloat val6, ALfloat val7, ALuint frac) +{ + const ALfloat *k = ResampleCoeffs.FIR8[frac]; + return k[0]*val0 + k[1]*val1 + k[2]*val2 + k[3]*val3 + + k[4]*val4 + k[5]*val5 + k[6]*val6 + k[7]*val7; +} + + +enum HrtfRequestMode { + Hrtf_Default = 0, + Hrtf_Enable = 1, + Hrtf_Disable = 2, +}; + + +void aluInitMixer(void); + +MixerFunc SelectMixer(void); +RowMixerFunc SelectRowMixer(void); + +/* aluInitRenderer + * + * Set up the appropriate panning method and mixing method given the device + * properties. + */ +void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf_appreq, enum HrtfRequestMode hrtf_userreq); + +void aluInitEffectPanning(struct ALeffectslot *slot); + +/** + * CalcDirectionCoeffs + * + * Calculates ambisonic coefficients based on a direction vector. The vector + * must be normalized (unit length), and the spread is the angular width of the + * sound (0...tau). + */ +void CalcDirectionCoeffs(const ALfloat dir[3], ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]); + +/** + * CalcXYZCoeffs + * + * Same as CalcDirectionCoeffs except the direction is specified as separate x, + * y, and z parameters instead of an array. + */ +inline void CalcXYZCoeffs(ALfloat x, ALfloat y, ALfloat z, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]) +{ + ALfloat dir[3] = { x, y, z }; + CalcDirectionCoeffs(dir, spread, coeffs); +} + +/** + * CalcAngleCoeffs + * + * Calculates ambisonic coefficients based on azimuth and elevation. The + * azimuth and elevation parameters are in radians, going right and up + * respectively. + */ +void CalcAngleCoeffs(ALfloat azimuth, ALfloat elevation, ALfloat spread, ALfloat coeffs[MAX_AMBI_COEFFS]); + +/** + * ComputeAmbientGains + * + * Computes channel gains for ambient, omni-directional sounds. + */ +#define ComputeAmbientGains(b, g, o) do { \ + if((b).CoeffCount > 0) \ + ComputeAmbientGainsMC((b).Ambi.Coeffs, (b).NumChannels, g, o); \ + else \ + ComputeAmbientGainsBF((b).Ambi.Map, (b).NumChannels, g, o); \ +} while (0) +void ComputeAmbientGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputeAmbientGainsBF(const BFChannelConfig *chanmap, ALuint numchans, ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); + +/** + * ComputePanningGains + * + * Computes panning gains using the given channel decoder coefficients and the + * pre-calculated direction or angle coefficients. + */ +#define ComputePanningGains(b, c, g, o) do { \ + if((b).CoeffCount > 0) \ + ComputePanningGainsMC((b).Ambi.Coeffs, (b).NumChannels, (b).CoeffCount, c, g, o);\ + else \ + ComputePanningGainsBF((b).Ambi.Map, (b).NumChannels, c, g, o); \ +} while (0) +void ComputePanningGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, ALuint numcoeffs, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputePanningGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat coeffs[MAX_AMBI_COEFFS], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); + +/** + * ComputeFirstOrderGains + * + * Sets channel gains for a first-order ambisonics input channel. The matrix is + * a 1x4 'slice' of a transform matrix for the input channel, used to scale and + * orient the sound samples. + */ +#define ComputeFirstOrderGains(b, m, g, o) do { \ + if((b).CoeffCount > 0) \ + ComputeFirstOrderGainsMC((b).Ambi.Coeffs, (b).NumChannels, m, g, o); \ + else \ + ComputeFirstOrderGainsBF((b).Ambi.Map, (b).NumChannels, m, g, o); \ +} while (0) +void ComputeFirstOrderGainsMC(const ChannelConfig *chancoeffs, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); +void ComputeFirstOrderGainsBF(const BFChannelConfig *chanmap, ALuint numchans, const ALfloat mtx[4], ALfloat ingain, ALfloat gains[MAX_OUTPUT_CHANNELS]); + + +ALvoid MixSource(struct ALvoice *voice, struct ALsource *source, 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 diff --git a/Engine/lib/openal-soft/OpenAL32/Include/bs2b.h b/Engine/lib/openal-soft/OpenAL32/Include/bs2b.h new file mode 100644 index 000000000..bfe5c274c --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/bs2b.h @@ -0,0 +1,94 @@ +/*- + * Copyright (c) 2005 Boris Mikhaylov + * + * 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. + */ + +#ifndef BS2B_H +#define BS2B_H + +/* Number of crossfeed levels */ +#define BS2B_CLEVELS 3 + +/* Normal crossfeed levels */ +#define BS2B_HIGH_CLEVEL 3 +#define BS2B_MIDDLE_CLEVEL 2 +#define BS2B_LOW_CLEVEL 1 + +/* Easy crossfeed levels */ +#define BS2B_HIGH_ECLEVEL BS2B_HIGH_CLEVEL + BS2B_CLEVELS +#define BS2B_MIDDLE_ECLEVEL BS2B_MIDDLE_CLEVEL + BS2B_CLEVELS +#define BS2B_LOW_ECLEVEL BS2B_LOW_CLEVEL + BS2B_CLEVELS + +/* Default crossfeed levels */ +#define BS2B_DEFAULT_CLEVEL BS2B_HIGH_ECLEVEL +/* Default sample rate (Hz) */ +#define BS2B_DEFAULT_SRATE 44100 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +struct bs2b { + int level; /* Crossfeed level */ + int srate; /* Sample rate (Hz) */ + + /* Lowpass IIR filter coefficients */ + float a0_lo; + float b1_lo; + + /* Highboost IIR filter coefficients */ + float a0_hi; + float a1_hi; + float b1_hi; + + /* Buffer of last filtered sample. + * [0] - first channel, [1] - second channel + */ + struct t_last_sample { + float asis; + float lo; + float hi; + } last_sample[2]; +}; + +/* Clear buffers and set new coefficients with new crossfeed level and sample + * rate values. + * level - crossfeed level of *LEVEL values. + * srate - sample rate by Hz. + */ +void bs2b_set_params(struct bs2b *bs2b, int level, int srate); + +/* Return current crossfeed level value */ +int bs2b_get_level(struct bs2b *bs2b); + +/* Return current sample rate value */ +int bs2b_get_srate(struct bs2b *bs2b); + +/* Clear buffer */ +void bs2b_clear(struct bs2b *bs2b); + +void bs2b_cross_feed(struct bs2b *bs2b, float *restrict Left, float *restrict Right, unsigned int SamplesToDo); + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* BS2B_H */ diff --git a/Engine/lib/openal-soft/OpenAL32/Include/sample_cvt.h b/Engine/lib/openal-soft/OpenAL32/Include/sample_cvt.h new file mode 100644 index 000000000..12bb1fa6c --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/Include/sample_cvt.h @@ -0,0 +1,9 @@ +#ifndef SAMPLE_CVT_H +#define SAMPLE_CVT_H + +#include "AL/al.h" +#include "alBuffer.h" + +void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align); + +#endif /* SAMPLE_CVT_H */ diff --git a/Engine/lib/openal-soft/OpenAL32/alAuxEffectSlot.c b/Engine/lib/openal-soft/OpenAL32/alAuxEffectSlot.c new file mode 100644 index 000000000..b860b2b0e --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alAuxEffectSlot.c @@ -0,0 +1,715 @@ +/** + * 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 +#include + +#include "AL/al.h" +#include "AL/alc.h" +#include "alMain.h" +#include "alAuxEffectSlot.h" +#include "alThunk.h" +#include "alError.h" +#include "alListener.h" +#include "alSource.h" + +#include "almalloc.h" + + +extern inline void LockEffectSlotsRead(ALCcontext *context); +extern inline void UnlockEffectSlotsRead(ALCcontext *context); +extern inline void LockEffectSlotsWrite(ALCcontext *context); +extern inline void UnlockEffectSlotsWrite(ALCcontext *context); +extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id); +extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id); + +static void RemoveEffectSlotList(ALCcontext *Context, ALeffectslot *slot); + +static UIntMap EffectStateFactoryMap; +static inline ALeffectStateFactory *getFactoryByType(ALenum type) +{ + ALeffectStateFactory* (*getFactory)(void) = LookupUIntMapKey(&EffectStateFactoryMap, type); + if(getFactory != NULL) + return getFactory(); + return NULL; +} + +static void ALeffectState_IncRef(ALeffectState *state); +static void ALeffectState_DecRef(ALeffectState *state); + +#define DO_UPDATEPROPS() do { \ + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \ + UpdateEffectSlotProps(slot); \ + else \ + slot->NeedsUpdate = AL_TRUE; \ +} while(0) + + +AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) +{ + ALCcontext *context; + ALeffectslot *first, *last; + ALsizei cur; + ALenum err; + + context = GetContextRef(); + if(!context) return; + + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + first = last = NULL; + for(cur = 0;cur < n;cur++) + { + ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot)); + err = AL_OUT_OF_MEMORY; + if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR) + { + al_free(slot); + alDeleteAuxiliaryEffectSlots(cur, effectslots); + SET_ERROR_AND_GOTO(context, err, done); + } + + err = NewThunkEntry(&slot->id); + if(err == AL_NO_ERROR) + err = InsertUIntMapEntry(&context->EffectSlotMap, slot->id, slot); + if(err != AL_NO_ERROR) + { + FreeThunkEntry(slot->id); + ALeffectState_DecRef(slot->Effect.State); + if(slot->Params.EffectState) + ALeffectState_DecRef(slot->Params.EffectState); + al_free(slot); + + alDeleteAuxiliaryEffectSlots(cur, effectslots); + SET_ERROR_AND_GOTO(context, err, done); + } + + aluInitEffectPanning(slot); + + if(!first) first = slot; + if(last) ATOMIC_STORE(&last->next, slot, almemory_order_relaxed); + last = slot; + + effectslots[cur] = slot->id; + } + if(last != NULL) + { + ALeffectslot *root = ATOMIC_LOAD(&context->ActiveAuxSlotList); + do { + ATOMIC_STORE(&last->next, root, almemory_order_relaxed); + } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALeffectslot*, &context->ActiveAuxSlotList, + &root, first)); + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots) +{ + ALCcontext *context; + ALeffectslot *slot; + ALsizei i; + + context = GetContextRef(); + if(!context) return; + + LockEffectSlotsWrite(context); + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + for(i = 0;i < n;i++) + { + if((slot=LookupEffectSlot(context, effectslots[i])) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(ReadRef(&slot->ref) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + } + + // All effectslots are valid + for(i = 0;i < n;i++) + { + if((slot=RemoveEffectSlot(context, effectslots[i])) == NULL) + continue; + FreeThunkEntry(slot->id); + + RemoveEffectSlotList(context, slot); + DeinitEffectSlot(slot); + + memset(slot, 0, sizeof(*slot)); + al_free(slot); + } + +done: + UnlockEffectSlotsWrite(context); + ALCcontext_DecRef(context); +} + +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) +{ + ALCcontext *context; + ALboolean ret; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + LockEffectSlotsRead(context); + ret = (LookupEffectSlot(context, effectslot) ? AL_TRUE : AL_FALSE); + UnlockEffectSlotsRead(context); + + ALCcontext_DecRef(context); + + return ret; +} + +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value) +{ + ALCdevice *device; + ALCcontext *context; + ALeffectslot *slot; + ALeffect *effect = NULL; + ALenum err; + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + LockEffectSlotsRead(context); + if((slot=LookupEffectSlot(context, effectslot)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + switch(param) + { + case AL_EFFECTSLOT_EFFECT: + device = context->Device; + + LockEffectsRead(device); + effect = (value ? LookupEffect(device, value) : NULL); + if(!(value == 0 || effect != NULL)) + { + UnlockEffectsRead(device); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + err = InitializeEffect(device, slot, effect); + UnlockEffectsRead(device); + + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: + if(!(value == AL_TRUE || value == AL_FALSE)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + slot->AuxSendAuto = value; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + DO_UPDATEPROPS(); + +done: + UnlockEffectSlotsRead(context); + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values) +{ + ALCcontext *context; + + switch(param) + { + case AL_EFFECTSLOT_EFFECT: + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: + alAuxiliaryEffectSloti(effectslot, param, values[0]); + return; + } + + context = GetContextRef(); + if(!context) return; + + LockEffectSlotsRead(context); + if(LookupEffectSlot(context, effectslot) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockEffectSlotsRead(context); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value) +{ + ALCcontext *context; + ALeffectslot *slot; + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + LockEffectSlotsRead(context); + if((slot=LookupEffectSlot(context, effectslot)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + switch(param) + { + case AL_EFFECTSLOT_GAIN: + if(!(value >= 0.0f && value <= 1.0f)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + slot->Gain = value; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + DO_UPDATEPROPS(); + +done: + UnlockEffectSlotsRead(context); + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values) +{ + ALCcontext *context; + + switch(param) + { + case AL_EFFECTSLOT_GAIN: + alAuxiliaryEffectSlotf(effectslot, param, values[0]); + return; + } + + context = GetContextRef(); + if(!context) return; + + LockEffectSlotsRead(context); + if(LookupEffectSlot(context, effectslot) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockEffectSlotsRead(context); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value) +{ + ALCcontext *context; + ALeffectslot *slot; + + context = GetContextRef(); + if(!context) return; + + LockEffectSlotsRead(context); + if((slot=LookupEffectSlot(context, effectslot)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + switch(param) + { + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: + *value = slot->AuxSendAuto; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockEffectSlotsRead(context); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values) +{ + ALCcontext *context; + + switch(param) + { + case AL_EFFECTSLOT_EFFECT: + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: + alGetAuxiliaryEffectSloti(effectslot, param, values); + return; + } + + context = GetContextRef(); + if(!context) return; + + LockEffectSlotsRead(context); + if(LookupEffectSlot(context, effectslot) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockEffectSlotsRead(context); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value) +{ + ALCcontext *context; + ALeffectslot *slot; + + context = GetContextRef(); + if(!context) return; + + LockEffectSlotsRead(context); + if((slot=LookupEffectSlot(context, effectslot)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + switch(param) + { + case AL_EFFECTSLOT_GAIN: + *value = slot->Gain; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockEffectSlotsRead(context); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values) +{ + ALCcontext *context; + + switch(param) + { + case AL_EFFECTSLOT_GAIN: + alGetAuxiliaryEffectSlotf(effectslot, param, values); + return; + } + + context = GetContextRef(); + if(!context) return; + + LockEffectSlotsRead(context); + if(LookupEffectSlot(context, effectslot) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockEffectSlotsRead(context); + ALCcontext_DecRef(context); +} + + +static void RemoveEffectSlotList(ALCcontext *context, ALeffectslot *slot) +{ + ALCdevice *device = context->Device; + ALeffectslot *root, *next; + + root = slot; + next = ATOMIC_LOAD(&slot->next); + if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALeffectslot*, &context->ActiveAuxSlotList, &root, next)) + { + ALeffectslot *cur; + do { + cur = root; + root = slot; + } while(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALeffectslot*, &cur->next, &root, next)); + } + /* Wait for any mix that may be using these effect slots to finish. */ + while((ReadRef(&device->MixCount)&1) != 0) + althrd_yield(); +} + + +void InitEffectFactoryMap(void) +{ + InitUIntMap(&EffectStateFactoryMap, ~0); + + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_NULL, ALnullStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EAXREVERB, ALreverbStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_REVERB, ALreverbStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_CHORUS, ALchorusStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_COMPRESSOR, ALcompressorStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DISTORTION, ALdistortionStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_ECHO, ALechoStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EQUALIZER, ALequalizerStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_FLANGER, ALflangerStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_RING_MODULATOR, ALmodulatorStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_DIALOGUE, ALdedicatedStateFactory_getFactory); + InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, ALdedicatedStateFactory_getFactory); +} + +void DeinitEffectFactoryMap(void) +{ + ResetUIntMap(&EffectStateFactoryMap); +} + + +ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect) +{ + ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL); + struct ALeffectslotProps *props; + ALeffectState *State; + + if(newtype != EffectSlot->Effect.Type) + { + ALeffectStateFactory *factory; + FPUCtl oldMode; + + factory = getFactoryByType(newtype); + if(!factory) + { + ERR("Failed to find factory for effect type 0x%04x\n", newtype); + return AL_INVALID_ENUM; + } + State = V0(factory,create)(); + if(!State) return AL_OUT_OF_MEMORY; + + SetMixerFPUMode(&oldMode); + almtx_lock(&Device->BackendLock); + State->OutBuffer = Device->Dry.Buffer; + State->OutChannels = Device->Dry.NumChannels; + if(V(State,deviceUpdate)(Device) == AL_FALSE) + { + almtx_unlock(&Device->BackendLock); + RestoreFPUMode(&oldMode); + ALeffectState_DecRef(State); + return AL_OUT_OF_MEMORY; + } + almtx_unlock(&Device->BackendLock); + RestoreFPUMode(&oldMode); + + if(!effect) + { + EffectSlot->Effect.Type = AL_EFFECT_NULL; + memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props)); + } + else + { + EffectSlot->Effect.Type = effect->type; + EffectSlot->Effect.Props = effect->Props; + } + + ALeffectState_DecRef(EffectSlot->Effect.State); + EffectSlot->Effect.State = State; + } + else if(effect) + EffectSlot->Effect.Props = effect->Props; + + /* Remove state references from old effect slot property updates. */ + props = ATOMIC_LOAD(&EffectSlot->FreeList); + while(props) + { + State = ATOMIC_EXCHANGE(ALeffectState*, &props->State, NULL, almemory_order_relaxed); + if(State) ALeffectState_DecRef(State); + props = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + } + + return AL_NO_ERROR; +} + + +static void ALeffectState_IncRef(ALeffectState *state) +{ + uint ref; + ref = IncrementRef(&state->Ref); + TRACEREF("%p increasing refcount to %u\n", state, ref); +} + +static void ALeffectState_DecRef(ALeffectState *state) +{ + uint ref; + ref = DecrementRef(&state->Ref); + TRACEREF("%p decreasing refcount to %u\n", state, ref); + if(ref == 0) DELETE_OBJ(state); +} + + +void ALeffectState_Construct(ALeffectState *state) +{ + InitRef(&state->Ref, 1); + + state->OutBuffer = NULL; + state->OutChannels = 0; +} + +void ALeffectState_Destruct(ALeffectState *UNUSED(state)) +{ +} + + +ALenum InitEffectSlot(ALeffectslot *slot) +{ + ALeffectStateFactory *factory; + + slot->Effect.Type = AL_EFFECT_NULL; + + factory = getFactoryByType(AL_EFFECT_NULL); + if(!(slot->Effect.State=V0(factory,create)())) + return AL_OUT_OF_MEMORY; + + slot->NeedsUpdate = AL_FALSE; + slot->Gain = 1.0; + slot->AuxSendAuto = AL_TRUE; + InitRef(&slot->ref, 0); + + ATOMIC_INIT(&slot->Update, NULL); + ATOMIC_INIT(&slot->FreeList, NULL); + + slot->Params.Gain = 1.0f; + slot->Params.AuxSendAuto = AL_TRUE; + ALeffectState_IncRef(slot->Effect.State); + slot->Params.EffectState = slot->Effect.State; + slot->Params.RoomRolloff = 0.0f; + slot->Params.DecayTime = 0.0f; + slot->Params.AirAbsorptionGainHF = 1.0f; + + ATOMIC_INIT(&slot->next, NULL); + + return AL_NO_ERROR; +} + +void DeinitEffectSlot(ALeffectslot *slot) +{ + struct ALeffectslotProps *props; + ALeffectState *state; + size_t count = 0; + + props = ATOMIC_LOAD(&slot->Update); + if(props) + { + state = ATOMIC_LOAD(&props->State, almemory_order_relaxed); + if(state) ALeffectState_DecRef(state); + TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props); + al_free(props); + } + props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed); + while(props) + { + struct ALeffectslotProps *next; + state = ATOMIC_LOAD(&props->State, almemory_order_relaxed); + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + if(state) ALeffectState_DecRef(state); + al_free(props); + props = next; + ++count; + } + TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s"); + + ALeffectState_DecRef(slot->Effect.State); + if(slot->Params.EffectState) + ALeffectState_DecRef(slot->Params.EffectState); +} + +void UpdateEffectSlotProps(ALeffectslot *slot) +{ + struct ALeffectslotProps *props; + ALeffectState *oldstate; + + /* Get an unused property container, or allocate a new one as needed. */ + props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed); + if(!props) + props = al_calloc(16, sizeof(*props)); + else + { + struct ALeffectslotProps *next; + do { + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, + &slot->FreeList, &props, next, almemory_order_seq_cst, + almemory_order_consume) == 0); + } + + /* Copy in current property values. */ + ATOMIC_STORE(&props->Gain, slot->Gain, almemory_order_relaxed); + ATOMIC_STORE(&props->AuxSendAuto, slot->AuxSendAuto, almemory_order_relaxed); + + ATOMIC_STORE(&props->Type, slot->Effect.Type, almemory_order_relaxed); + props->Props = slot->Effect.Props; + /* Swap out any stale effect state object there may be in the container, to + * delete it. + */ + ALeffectState_IncRef(slot->Effect.State); + oldstate = ATOMIC_EXCHANGE(ALeffectState*, &props->State, slot->Effect.State, + almemory_order_relaxed); + + /* Set the new container for updating internal parameters. */ + props = ATOMIC_EXCHANGE(struct ALeffectslotProps*, &slot->Update, props, + almemory_order_acq_rel); + if(props) + { + /* If there was an unused update container, put it back in the + * freelist. + */ + struct ALeffectslotProps *first = ATOMIC_LOAD(&slot->FreeList); + do { + ATOMIC_STORE(&props->next, first, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALeffectslotProps*, + &slot->FreeList, &first, props) == 0); + } + + if(oldstate) + ALeffectState_DecRef(oldstate); +} + +void UpdateAllEffectSlotProps(ALCcontext *context) +{ + ALeffectslot *slot; + + LockEffectSlotsRead(context); + slot = ATOMIC_LOAD(&context->ActiveAuxSlotList); + while(slot) + { + if(slot->NeedsUpdate) + UpdateEffectSlotProps(slot); + slot->NeedsUpdate = AL_FALSE; + slot = ATOMIC_LOAD(&slot->next, almemory_order_relaxed); + } + UnlockEffectSlotsRead(context); +} + +ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context) +{ + ALsizei pos; + for(pos = 0;pos < Context->EffectSlotMap.size;pos++) + { + ALeffectslot *temp = Context->EffectSlotMap.values[pos]; + Context->EffectSlotMap.values[pos] = NULL; + + DeinitEffectSlot(temp); + + FreeThunkEntry(temp->id); + memset(temp, 0, sizeof(ALeffectslot)); + al_free(temp); + } +} diff --git a/Engine/lib/openal-soft/OpenAL32/alBuffer.c b/Engine/lib/openal-soft/OpenAL32/alBuffer.c new file mode 100644 index 000000000..193cfeaa9 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alBuffer.c @@ -0,0 +1,1415 @@ +/** + * 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 +#include +#include +#include +#ifdef HAVE_MALLOC_H +#include +#endif + +#include "alMain.h" +#include "alu.h" +#include "alError.h" +#include "alBuffer.h" +#include "alThunk.h" +#include "sample_cvt.h" + + +extern inline void LockBuffersRead(ALCdevice *device); +extern inline void UnlockBuffersRead(ALCdevice *device); +extern inline void LockBuffersWrite(ALCdevice *device); +extern inline void UnlockBuffersWrite(ALCdevice *device); +extern inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id); +extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id); +extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type); +extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type); + +static ALboolean IsValidType(ALenum type); +static ALboolean IsValidChannels(ALenum channels); +static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type); +static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type); +static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align); + + +AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) +{ + ALCcontext *context; + ALsizei cur = 0; + + context = GetContextRef(); + if(!context) return; + + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + for(cur = 0;cur < n;cur++) + { + ALbuffer *buffer = NewBuffer(context); + if(!buffer) + { + alDeleteBuffers(cur, buffers); + break; + } + + buffers[cur] = buffer->id; + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *ALBuf; + ALsizei i; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + + LockBuffersWrite(device); + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + for(i = 0;i < n;i++) + { + if(!buffers[i]) + continue; + + /* Check for valid Buffer ID */ + if((ALBuf=LookupBuffer(device, buffers[i])) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(ReadRef(&ALBuf->ref) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + } + + for(i = 0;i < n;i++) + { + if((ALBuf=LookupBuffer(device, buffers[i])) != NULL) + DeleteBuffer(device, ALBuf); + } + +done: + UnlockBuffersWrite(device); + ALCcontext_DecRef(context); +} + +AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer) +{ + ALCcontext *context; + ALboolean ret; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + LockBuffersRead(context->Device); + ret = ((!buffer || LookupBuffer(context->Device, buffer)) ? + AL_TRUE : AL_FALSE); + UnlockBuffersRead(context->Device); + + ALCcontext_DecRef(context); + + return ret; +} + + +AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) +{ + enum UserFmtChannels srcchannels = UserFmtMono; + enum UserFmtType srctype = UserFmtByte; + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALenum newformat = AL_NONE; + ALuint framesize; + ALsizei align; + ALenum err; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(size >= 0 && freq > 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + align = ATOMIC_LOAD(&albuf->UnpackAlign); + if(SanitizeAlignment(srctype, &align) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(srctype) + { + case UserFmtByte: + case UserFmtUByte: + case UserFmtShort: + case UserFmtUShort: + case UserFmtFloat: + framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + err = LoadData(albuf, freq, format, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case UserFmtInt: + case UserFmtUInt: + case UserFmtByte3: + case UserFmtUByte3: + case UserFmtDouble: + framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + switch(srcchannels) + { + case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break; + case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break; + case UserFmtRear: newformat = AL_FORMAT_REAR32; break; + case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break; + case UserFmtX51: newformat = AL_FORMAT_51CHN32; break; + case UserFmtX61: newformat = AL_FORMAT_61CHN32; break; + case UserFmtX71: newformat = AL_FORMAT_71CHN32; break; + case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_FLOAT32; break; + case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_FLOAT32; break; + } + err = LoadData(albuf, freq, newformat, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case UserFmtMulaw: + case UserFmtAlaw: + framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + switch(srcchannels) + { + case UserFmtMono: newformat = AL_FORMAT_MONO16; break; + case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; + case UserFmtRear: newformat = AL_FORMAT_REAR16; break; + case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; + case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; + case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; + case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; + case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break; + case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break; + } + err = LoadData(albuf, freq, newformat, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case UserFmtIMA4: + framesize = (align-1)/2 + 4; + framesize *= ChannelsFromUserFmt(srcchannels); + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + switch(srcchannels) + { + case UserFmtMono: newformat = AL_FORMAT_MONO16; break; + case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; + case UserFmtRear: newformat = AL_FORMAT_REAR16; break; + case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; + case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; + case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; + case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; + case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break; + case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break; + } + err = LoadData(albuf, freq, newformat, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case UserFmtMSADPCM: + framesize = (align-2)/2 + 7; + framesize *= ChannelsFromUserFmt(srcchannels); + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + switch(srcchannels) + { + case UserFmtMono: newformat = AL_FORMAT_MONO16; break; + case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; + case UserFmtRear: newformat = AL_FORMAT_REAR16; break; + case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; + case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; + case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; + case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; + case UserFmtBFormat2D: newformat = AL_FORMAT_BFORMAT2D_16; break; + case UserFmtBFormat3D: newformat = AL_FORMAT_BFORMAT3D_16; break; + } + err = LoadData(albuf, freq, newformat, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) +{ + enum UserFmtChannels srcchannels = UserFmtMono; + enum UserFmtType srctype = UserFmtByte; + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALuint byte_align; + ALuint channels; + ALuint bytes; + ALsizei align; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(length >= 0 && offset >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + WriteLock(&albuf->lock); + align = ATOMIC_LOAD(&albuf->UnpackAlign); + if(SanitizeAlignment(srctype, &align) == AL_FALSE) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(align != albuf->OriginalAlign) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + + if(albuf->OriginalType == UserFmtIMA4) + { + byte_align = (albuf->OriginalAlign-1)/2 + 4; + byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels); + } + else if(albuf->OriginalType == UserFmtMSADPCM) + { + byte_align = (albuf->OriginalAlign-2)/2 + 7; + byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels); + } + else + { + byte_align = albuf->OriginalAlign; + byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels, + albuf->OriginalType); + } + + if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset || + (offset%byte_align) != 0 || (length%byte_align) != 0) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + channels = ChannelsFromFmt(albuf->FmtChannels); + bytes = BytesFromFmt(albuf->FmtType); + /* offset -> byte offset, length -> sample count */ + offset = offset/byte_align * channels*bytes; + length = length/byte_align * albuf->OriginalAlign; + + ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, + data, srctype, channels, length, align); + WriteUnlock(&albuf->lock); + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, + ALuint samplerate, ALenum internalformat, ALsizei samples, + ALenum channels, ALenum type, const ALvoid *data) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALsizei align; + ALenum err; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(samples >= 0 && samplerate != 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + align = ATOMIC_LOAD(&albuf->UnpackAlign); + if(SanitizeAlignment(type, &align) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if((samples%align) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + err = LoadData(albuf, samplerate, internalformat, samples, + channels, type, data, align, AL_FALSE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, + ALsizei offset, ALsizei samples, + ALenum channels, ALenum type, const ALvoid *data) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALsizei align; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(samples >= 0 && offset >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(IsValidType(type) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + WriteLock(&albuf->lock); + align = ATOMIC_LOAD(&albuf->UnpackAlign); + if(SanitizeAlignment(type, &align) == AL_FALSE) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if(channels != (ALenum)albuf->FmtChannels) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if((samples%align) != 0) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + /* offset -> byte offset */ + offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType); + ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, + data, type, ChannelsFromFmt(albuf->FmtChannels), samples, align); + WriteUnlock(&albuf->lock); + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, + ALsizei offset, ALsizei samples, + ALenum channels, ALenum type, ALvoid *data) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALsizei align; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(samples >= 0 && offset >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(IsValidType(type) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + ReadLock(&albuf->lock); + align = ATOMIC_LOAD(&albuf->PackAlign); + if(SanitizeAlignment(type, &align) == AL_FALSE) + { + ReadUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if(channels != (ALenum)albuf->FmtChannels) + { + ReadUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset) + { + ReadUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if((samples%align) != 0) + { + ReadUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + /* offset -> byte offset */ + offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType); + ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, + ChannelsFromFmt(albuf->FmtChannels), samples, align); + ReadUnlock(&albuf->lock); + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format) +{ + enum FmtChannels dstchannels; + enum FmtType dsttype; + ALCcontext *context; + ALboolean ret; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + ret = DecomposeFormat(format, &dstchannels, &dsttype); + + ALCcontext_DecRef(context); + + return ret; +} + + +AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value)) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3)) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + switch(param) + { + case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: + if(!(value >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + ATOMIC_STORE(&albuf->UnpackAlign, value); + break; + + case AL_PACK_BLOCK_ALIGNMENT_SOFT: + if(!(value >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + ATOMIC_STORE(&albuf->PackAlign, value); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3)) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + if(values) + { + switch(param) + { + case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: + case AL_PACK_BLOCK_ALIGNMENT_SOFT: + alBufferi(buffer, param, values[0]); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_LOOP_POINTS_SOFT: + WriteLock(&albuf->lock); + if(ReadRef(&albuf->ref) != 0) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + } + if(values[0] >= values[1] || values[0] < 0 || + values[1] > albuf->SampleLen) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + albuf->LoopStart = values[0]; + albuf->LoopEnd = values[1]; + WriteUnlock(&albuf->lock); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(value)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_SEC_LENGTH_SOFT: + ReadLock(&albuf->lock); + if(albuf->SampleLen != 0) + *value = albuf->SampleLen / (ALfloat)albuf->Frequency; + else + *value = 0.0f; + ReadUnlock(&albuf->lock); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(value1 && value2 && value3)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values) +{ + ALCdevice *device; + ALCcontext *context; + + switch(param) + { + case AL_SEC_LENGTH_SOFT: + alGetBufferf(buffer, param, values); + return; + } + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(value)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_FREQUENCY: + *value = albuf->Frequency; + break; + + case AL_BITS: + *value = BytesFromFmt(albuf->FmtType) * 8; + break; + + case AL_CHANNELS: + *value = ChannelsFromFmt(albuf->FmtChannels); + break; + + case AL_SIZE: + ReadLock(&albuf->lock); + *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels, + albuf->FmtType); + ReadUnlock(&albuf->lock); + break; + + case AL_INTERNAL_FORMAT_SOFT: + *value = albuf->Format; + break; + + case AL_BYTE_LENGTH_SOFT: + *value = albuf->OriginalSize; + break; + + case AL_SAMPLE_LENGTH_SOFT: + *value = albuf->SampleLen; + break; + + case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: + *value = ATOMIC_LOAD(&albuf->UnpackAlign); + break; + + case AL_PACK_BLOCK_ALIGNMENT_SOFT: + *value = ATOMIC_LOAD(&albuf->PackAlign); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(value1 && value2 && value3)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + switch(param) + { + case AL_FREQUENCY: + case AL_BITS: + case AL_CHANNELS: + case AL_SIZE: + case AL_INTERNAL_FORMAT_SOFT: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: + case AL_PACK_BLOCK_ALIGNMENT_SOFT: + alGetBufferi(buffer, param, values); + return; + } + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockBuffersRead(device); + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_LOOP_POINTS_SOFT: + ReadLock(&albuf->lock); + values[0] = albuf->LoopStart; + values[1] = albuf->LoopEnd; + ReadUnlock(&albuf->lock); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + UnlockBuffersRead(device); + ALCcontext_DecRef(context); +} + + +/* + * LoadData + * + * Loads the specified data into the buffer, using the specified formats. + * Currently, the new format must have the same channel configuration as the + * original format. + */ +ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc) +{ + enum FmtChannels DstChannels = FmtMono; + enum FmtType DstType = FmtByte; + ALuint NewChannels, NewBytes; + ALuint64 newsize; + + if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE) + return AL_INVALID_ENUM; + if((long)SrcChannels != (long)DstChannels) + return AL_INVALID_ENUM; + + NewChannels = ChannelsFromFmt(DstChannels); + NewBytes = BytesFromFmt(DstType); + + newsize = frames; + newsize *= NewBytes; + newsize *= NewChannels; + if(newsize > INT_MAX) + return AL_OUT_OF_MEMORY; + + WriteLock(&ALBuf->lock); + if(ReadRef(&ALBuf->ref) != 0) + { + WriteUnlock(&ALBuf->lock); + return AL_INVALID_OPERATION; + } + + /* Round up to the next 16-byte multiple. This could reallocate only when + * increasing or the new size is less than half the current, but then the + * buffer's AL_SIZE would not be very reliable for accounting buffer memory + * usage, and reporting the real size could cause problems for apps that + * use AL_SIZE to try to get the buffer's play length. + */ + newsize = (newsize+15) & ~0xf; + if(newsize != ALBuf->BytesAlloc) + { + void *temp = al_calloc(16, (size_t)newsize); + if(!temp && newsize) + { + WriteUnlock(&ALBuf->lock); + return AL_OUT_OF_MEMORY; + } + al_free(ALBuf->data); + ALBuf->data = temp; + ALBuf->BytesAlloc = (ALuint)newsize; + } + + if(data != NULL) + ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align); + + if(storesrc) + { + ALBuf->OriginalChannels = SrcChannels; + ALBuf->OriginalType = SrcType; + if(SrcType == UserFmtIMA4) + { + ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels); + ALBuf->OriginalSize = frames / align * byte_align; + ALBuf->OriginalAlign = align; + } + else if(SrcType == UserFmtMSADPCM) + { + ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels); + ALBuf->OriginalSize = frames / align * byte_align; + ALBuf->OriginalAlign = align; + } + else + { + ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType); + ALBuf->OriginalAlign = 1; + } + } + else + { + ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels; + ALBuf->OriginalType = (enum UserFmtType)DstType; + ALBuf->OriginalSize = frames * NewBytes * NewChannels; + ALBuf->OriginalAlign = 1; + } + + ALBuf->Frequency = freq; + ALBuf->FmtChannels = DstChannels; + ALBuf->FmtType = DstType; + ALBuf->Format = NewFormat; + + ALBuf->SampleLen = frames; + ALBuf->LoopStart = 0; + ALBuf->LoopEnd = ALBuf->SampleLen; + + WriteUnlock(&ALBuf->lock); + return AL_NO_ERROR; +} + + +ALuint BytesFromUserFmt(enum UserFmtType type) +{ + switch(type) + { + case UserFmtByte: return sizeof(ALbyte); + case UserFmtUByte: return sizeof(ALubyte); + case UserFmtShort: return sizeof(ALshort); + case UserFmtUShort: return sizeof(ALushort); + case UserFmtInt: return sizeof(ALint); + case UserFmtUInt: return sizeof(ALuint); + case UserFmtFloat: return sizeof(ALfloat); + case UserFmtDouble: return sizeof(ALdouble); + case UserFmtByte3: return sizeof(ALbyte[3]); + case UserFmtUByte3: return sizeof(ALubyte[3]); + case UserFmtMulaw: return sizeof(ALubyte); + case UserFmtAlaw: return sizeof(ALubyte); + case UserFmtIMA4: break; /* not handled here */ + case UserFmtMSADPCM: break; /* not handled here */ + } + return 0; +} +ALuint ChannelsFromUserFmt(enum UserFmtChannels chans) +{ + switch(chans) + { + case UserFmtMono: return 1; + case UserFmtStereo: return 2; + case UserFmtRear: return 2; + case UserFmtQuad: return 4; + case UserFmtX51: return 6; + case UserFmtX61: return 7; + case UserFmtX71: return 8; + case UserFmtBFormat2D: return 3; + case UserFmtBFormat3D: return 4; + } + return 0; +} +static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, + enum UserFmtType *type) +{ + static const struct { + ALenum format; + enum UserFmtChannels channels; + enum UserFmtType type; + } list[] = { + { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte }, + { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort }, + { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat }, + { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble }, + { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 }, + { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM }, + { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw }, + { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw }, + + { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte }, + { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort }, + { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat }, + { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble }, + { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 }, + { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM }, + { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw }, + { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw }, + + { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte }, + { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort }, + { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat }, + { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw }, + + { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte }, + { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort }, + + { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte }, + { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort }, + { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat }, + { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw }, + + { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte }, + { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort }, + { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat }, + { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw }, + + { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte }, + { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort }, + { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat }, + { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw }, + + { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte }, + { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort }, + { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat }, + { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw }, + + { AL_FORMAT_BFORMAT2D_8, UserFmtBFormat2D, UserFmtUByte }, + { AL_FORMAT_BFORMAT2D_16, UserFmtBFormat2D, UserFmtShort }, + { AL_FORMAT_BFORMAT2D_FLOAT32, UserFmtBFormat2D, UserFmtFloat }, + { AL_FORMAT_BFORMAT2D_MULAW, UserFmtBFormat2D, UserFmtMulaw }, + + { AL_FORMAT_BFORMAT3D_8, UserFmtBFormat3D, UserFmtUByte }, + { AL_FORMAT_BFORMAT3D_16, UserFmtBFormat3D, UserFmtShort }, + { AL_FORMAT_BFORMAT3D_FLOAT32, UserFmtBFormat3D, UserFmtFloat }, + { AL_FORMAT_BFORMAT3D_MULAW, UserFmtBFormat3D, UserFmtMulaw }, + }; + ALuint i; + + for(i = 0;i < COUNTOF(list);i++) + { + if(list[i].format == format) + { + *chans = list[i].channels; + *type = list[i].type; + return AL_TRUE; + } + } + + return AL_FALSE; +} + +ALuint BytesFromFmt(enum FmtType type) +{ + switch(type) + { + case FmtByte: return sizeof(ALbyte); + case FmtShort: return sizeof(ALshort); + case FmtFloat: return sizeof(ALfloat); + } + return 0; +} +ALuint ChannelsFromFmt(enum FmtChannels chans) +{ + switch(chans) + { + case FmtMono: return 1; + case FmtStereo: return 2; + case FmtRear: return 2; + case FmtQuad: return 4; + case FmtX51: return 6; + case FmtX61: return 7; + case FmtX71: return 8; + case FmtBFormat2D: return 3; + case FmtBFormat3D: return 4; + } + return 0; +} +static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) +{ + static const struct { + ALenum format; + enum FmtChannels channels; + enum FmtType type; + } list[] = { + { AL_MONO8_SOFT, FmtMono, FmtByte }, + { AL_MONO16_SOFT, FmtMono, FmtShort }, + { AL_MONO32F_SOFT, FmtMono, FmtFloat }, + + { AL_STEREO8_SOFT, FmtStereo, FmtByte }, + { AL_STEREO16_SOFT, FmtStereo, FmtShort }, + { AL_STEREO32F_SOFT, FmtStereo, FmtFloat }, + + { AL_REAR8_SOFT, FmtRear, FmtByte }, + { AL_REAR16_SOFT, FmtRear, FmtShort }, + { AL_REAR32F_SOFT, FmtRear, FmtFloat }, + + { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte }, + { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort }, + + { AL_QUAD8_SOFT, FmtQuad, FmtByte }, + { AL_QUAD16_SOFT, FmtQuad, FmtShort }, + { AL_QUAD32F_SOFT, FmtQuad, FmtFloat }, + + { AL_5POINT1_8_SOFT, FmtX51, FmtByte }, + { AL_5POINT1_16_SOFT, FmtX51, FmtShort }, + { AL_5POINT1_32F_SOFT, FmtX51, FmtFloat }, + + { AL_6POINT1_8_SOFT, FmtX61, FmtByte }, + { AL_6POINT1_16_SOFT, FmtX61, FmtShort }, + { AL_6POINT1_32F_SOFT, FmtX61, FmtFloat }, + + { AL_7POINT1_8_SOFT, FmtX71, FmtByte }, + { AL_7POINT1_16_SOFT, FmtX71, FmtShort }, + { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat }, + + { AL_BFORMAT2D_8_SOFT, FmtBFormat2D, FmtByte }, + { AL_BFORMAT2D_16_SOFT, FmtBFormat2D, FmtShort }, + { AL_BFORMAT2D_32F_SOFT, FmtBFormat2D, FmtFloat }, + + { AL_BFORMAT3D_8_SOFT, FmtBFormat3D, FmtByte }, + { AL_BFORMAT3D_16_SOFT, FmtBFormat3D, FmtShort }, + { AL_BFORMAT3D_32F_SOFT, FmtBFormat3D, FmtFloat }, + }; + ALuint i; + + for(i = 0;i < COUNTOF(list);i++) + { + if(list[i].format == format) + { + *chans = list[i].channels; + *type = list[i].type; + return AL_TRUE; + } + } + + return AL_FALSE; +} + +static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align) +{ + if(*align < 0) + return AL_FALSE; + + if(*align == 0) + { + if(type == UserFmtIMA4) + { + /* Here is where things vary: + * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel + * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel + */ + *align = 65; + } + else if(type == UserFmtMSADPCM) + *align = 64; + else + *align = 1; + return AL_TRUE; + } + + if(type == UserFmtIMA4) + { + /* IMA4 block alignment must be a multiple of 8, plus 1. */ + return ((*align)&7) == 1; + } + if(type == UserFmtMSADPCM) + { + /* MSADPCM block alignment must be a multiple of 2. */ + /* FIXME: Too strict? Might only require align*channels to be a + * multiple of 2. */ + return ((*align)&1) == 0; + } + + return AL_TRUE; +} + + +static ALboolean IsValidType(ALenum type) +{ + switch(type) + { + case AL_BYTE_SOFT: + case AL_UNSIGNED_BYTE_SOFT: + case AL_SHORT_SOFT: + case AL_UNSIGNED_SHORT_SOFT: + case AL_INT_SOFT: + case AL_UNSIGNED_INT_SOFT: + case AL_FLOAT_SOFT: + case AL_DOUBLE_SOFT: + case AL_BYTE3_SOFT: + case AL_UNSIGNED_BYTE3_SOFT: + case AL_MULAW_SOFT: + return AL_TRUE; + } + return AL_FALSE; +} + +static ALboolean IsValidChannels(ALenum channels) +{ + switch(channels) + { + case AL_MONO_SOFT: + case AL_STEREO_SOFT: + case AL_REAR_SOFT: + case AL_QUAD_SOFT: + case AL_5POINT1_SOFT: + case AL_6POINT1_SOFT: + case AL_7POINT1_SOFT: + case AL_BFORMAT2D_SOFT: + case AL_BFORMAT3D_SOFT: + return AL_TRUE; + } + return AL_FALSE; +} + + +ALbuffer *NewBuffer(ALCcontext *context) +{ + ALCdevice *device = context->Device; + ALbuffer *buffer; + ALenum err; + + buffer = al_calloc(16, sizeof(ALbuffer)); + if(!buffer) + SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL); + RWLockInit(&buffer->lock); + + err = NewThunkEntry(&buffer->id); + if(err == AL_NO_ERROR) + err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer); + if(err != AL_NO_ERROR) + { + FreeThunkEntry(buffer->id); + memset(buffer, 0, sizeof(ALbuffer)); + al_free(buffer); + + SET_ERROR_AND_RETURN_VALUE(context, err, NULL); + } + + return buffer; +} + +void DeleteBuffer(ALCdevice *device, ALbuffer *buffer) +{ + RemoveBuffer(device, buffer->id); + FreeThunkEntry(buffer->id); + + al_free(buffer->data); + + memset(buffer, 0, sizeof(*buffer)); + al_free(buffer); +} + + +/* + * ReleaseALBuffers() + * + * INTERNAL: Called to destroy any buffers that still exist on the device + */ +ALvoid ReleaseALBuffers(ALCdevice *device) +{ + ALsizei i; + for(i = 0;i < device->BufferMap.size;i++) + { + ALbuffer *temp = device->BufferMap.values[i]; + device->BufferMap.values[i] = NULL; + + al_free(temp->data); + + FreeThunkEntry(temp->id); + memset(temp, 0, sizeof(ALbuffer)); + al_free(temp); + } +} diff --git a/Engine/lib/openal-soft/OpenAL32/alEffect.c b/Engine/lib/openal-soft/OpenAL32/alEffect.c new file mode 100644 index 000000000..65a4dcb68 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alEffect.c @@ -0,0 +1,716 @@ +/** + * 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 +#include +#include + +#include "AL/al.h" +#include "AL/alc.h" +#include "alMain.h" +#include "alEffect.h" +#include "alThunk.h" +#include "alError.h" + + +ALboolean DisabledEffects[MAX_EFFECTS]; + +extern inline void LockEffectsRead(ALCdevice *device); +extern inline void UnlockEffectsRead(ALCdevice *device); +extern inline void LockEffectsWrite(ALCdevice *device); +extern inline void UnlockEffectsWrite(ALCdevice *device); +extern inline struct ALeffect *LookupEffect(ALCdevice *device, ALuint id); +extern inline struct ALeffect *RemoveEffect(ALCdevice *device, ALuint id); +extern inline ALboolean IsReverbEffect(ALenum type); + +static void InitEffectParams(ALeffect *effect, ALenum type); + + +AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects) +{ + ALCdevice *device; + ALCcontext *context; + ALsizei cur; + + 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++) + { + ALeffect *effect = al_calloc(16, sizeof(ALeffect)); + ALenum err = AL_OUT_OF_MEMORY; + if(!effect || (err=InitEffect(effect)) != AL_NO_ERROR) + { + al_free(effect); + alDeleteEffects(cur, effects); + SET_ERROR_AND_GOTO(context, err, done); + } + + err = NewThunkEntry(&effect->id); + if(err == AL_NO_ERROR) + err = InsertUIntMapEntry(&device->EffectMap, effect->id, effect); + if(err != AL_NO_ERROR) + { + FreeThunkEntry(effect->id); + memset(effect, 0, sizeof(ALeffect)); + al_free(effect); + + alDeleteEffects(cur, effects); + SET_ERROR_AND_GOTO(context, err, done); + } + + effects[cur] = effect->id; + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects) +{ + ALCdevice *device; + ALCcontext *context; + ALeffect *effect; + ALsizei i; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockEffectsWrite(device); + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + for(i = 0;i < n;i++) + { + if(effects[i] && LookupEffect(device, effects[i]) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + } + for(i = 0;i < n;i++) + { + if((effect=RemoveEffect(device, effects[i])) == NULL) + continue; + FreeThunkEntry(effect->id); + + memset(effect, 0, sizeof(*effect)); + al_free(effect); + } + +done: + UnlockEffectsWrite(device); + ALCcontext_DecRef(context); +} + +AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect) +{ + ALCcontext *Context; + ALboolean result; + + Context = GetContextRef(); + if(!Context) return AL_FALSE; + + LockEffectsRead(Context->Device); + result = ((!effect || LookupEffect(Context->Device, effect)) ? + AL_TRUE : AL_FALSE); + UnlockEffectsRead(Context->Device); + + ALCcontext_DecRef(Context); + + return result; +} + +AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint value) +{ + ALCcontext *Context; + ALCdevice *Device; + ALeffect *ALEffect; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockEffectsWrite(Device); + if((ALEffect=LookupEffect(Device, effect)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + if(param == AL_EFFECT_TYPE) + { + ALboolean isOk = (value == AL_EFFECT_NULL); + ALint i; + for(i = 0;!isOk && EffectList[i].val;i++) + { + if(value == EffectList[i].val && + !DisabledEffects[EffectList[i].type]) + isOk = AL_TRUE; + } + + if(isOk) + InitEffectParams(ALEffect, value); + else + alSetError(Context, AL_INVALID_VALUE); + } + else + { + /* Call the appropriate handler */ + V(ALEffect,setParami)(Context, param, value); + } + } + UnlockEffectsWrite(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *values) +{ + ALCcontext *Context; + ALCdevice *Device; + ALeffect *ALEffect; + + switch(param) + { + case AL_EFFECT_TYPE: + alEffecti(effect, param, values[0]); + return; + } + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockEffectsWrite(Device); + if((ALEffect=LookupEffect(Device, effect)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + V(ALEffect,setParamiv)(Context, param, values); + } + UnlockEffectsWrite(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat value) +{ + ALCcontext *Context; + ALCdevice *Device; + ALeffect *ALEffect; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockEffectsWrite(Device); + if((ALEffect=LookupEffect(Device, effect)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + V(ALEffect,setParamf)(Context, param, value); + } + UnlockEffectsWrite(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *values) +{ + ALCcontext *Context; + ALCdevice *Device; + ALeffect *ALEffect; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockEffectsWrite(Device); + if((ALEffect=LookupEffect(Device, effect)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + V(ALEffect,setParamfv)(Context, param, values); + } + UnlockEffectsWrite(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *value) +{ + ALCcontext *Context; + ALCdevice *Device; + ALeffect *ALEffect; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockEffectsRead(Device); + if((ALEffect=LookupEffect(Device, effect)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + if(param == AL_EFFECT_TYPE) + *value = ALEffect->type; + else + { + /* Call the appropriate handler */ + V(ALEffect,getParami)(Context, param, value); + } + } + UnlockEffectsRead(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *values) +{ + ALCcontext *Context; + ALCdevice *Device; + ALeffect *ALEffect; + + switch(param) + { + case AL_EFFECT_TYPE: + alGetEffecti(effect, param, values); + return; + } + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockEffectsRead(Device); + if((ALEffect=LookupEffect(Device, effect)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + V(ALEffect,getParamiv)(Context, param, values); + } + UnlockEffectsRead(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *value) +{ + ALCcontext *Context; + ALCdevice *Device; + ALeffect *ALEffect; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockEffectsRead(Device); + if((ALEffect=LookupEffect(Device, effect)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + V(ALEffect,getParamf)(Context, param, value); + } + UnlockEffectsRead(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *values) +{ + ALCcontext *Context; + ALCdevice *Device; + ALeffect *ALEffect; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockEffectsRead(Device); + if((ALEffect=LookupEffect(Device, effect)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + V(ALEffect,getParamfv)(Context, param, values); + } + UnlockEffectsRead(Device); + + ALCcontext_DecRef(Context); +} + + +ALenum InitEffect(ALeffect *effect) +{ + InitEffectParams(effect, AL_EFFECT_NULL); + return AL_NO_ERROR; +} + +ALvoid ReleaseALEffects(ALCdevice *device) +{ + ALsizei i; + for(i = 0;i < device->EffectMap.size;i++) + { + ALeffect *temp = device->EffectMap.values[i]; + device->EffectMap.values[i] = NULL; + + // Release effect structure + FreeThunkEntry(temp->id); + memset(temp, 0, sizeof(ALeffect)); + al_free(temp); + } +} + + +static void InitEffectParams(ALeffect *effect, ALenum type) +{ + switch(type) + { + case AL_EFFECT_EAXREVERB: + effect->Props.Reverb.Density = AL_EAXREVERB_DEFAULT_DENSITY; + effect->Props.Reverb.Diffusion = AL_EAXREVERB_DEFAULT_DIFFUSION; + effect->Props.Reverb.Gain = AL_EAXREVERB_DEFAULT_GAIN; + effect->Props.Reverb.GainHF = AL_EAXREVERB_DEFAULT_GAINHF; + effect->Props.Reverb.GainLF = AL_EAXREVERB_DEFAULT_GAINLF; + effect->Props.Reverb.DecayTime = AL_EAXREVERB_DEFAULT_DECAY_TIME; + effect->Props.Reverb.DecayHFRatio = AL_EAXREVERB_DEFAULT_DECAY_HFRATIO; + effect->Props.Reverb.DecayLFRatio = AL_EAXREVERB_DEFAULT_DECAY_LFRATIO; + effect->Props.Reverb.ReflectionsGain = AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN; + effect->Props.Reverb.ReflectionsDelay = AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY; + effect->Props.Reverb.ReflectionsPan[0] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; + effect->Props.Reverb.ReflectionsPan[1] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; + effect->Props.Reverb.ReflectionsPan[2] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; + effect->Props.Reverb.LateReverbGain = AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN; + effect->Props.Reverb.LateReverbDelay = AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY; + effect->Props.Reverb.LateReverbPan[0] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; + effect->Props.Reverb.LateReverbPan[1] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; + effect->Props.Reverb.LateReverbPan[2] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; + effect->Props.Reverb.EchoTime = AL_EAXREVERB_DEFAULT_ECHO_TIME; + effect->Props.Reverb.EchoDepth = AL_EAXREVERB_DEFAULT_ECHO_DEPTH; + effect->Props.Reverb.ModulationTime = AL_EAXREVERB_DEFAULT_MODULATION_TIME; + effect->Props.Reverb.ModulationDepth = AL_EAXREVERB_DEFAULT_MODULATION_DEPTH; + effect->Props.Reverb.AirAbsorptionGainHF = AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF; + effect->Props.Reverb.HFReference = AL_EAXREVERB_DEFAULT_HFREFERENCE; + effect->Props.Reverb.LFReference = AL_EAXREVERB_DEFAULT_LFREFERENCE; + effect->Props.Reverb.RoomRolloffFactor = AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR; + effect->Props.Reverb.DecayHFLimit = AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT; + SET_VTABLE1(ALeaxreverb, effect); + break; + case AL_EFFECT_REVERB: + effect->Props.Reverb.Density = AL_REVERB_DEFAULT_DENSITY; + effect->Props.Reverb.Diffusion = AL_REVERB_DEFAULT_DIFFUSION; + effect->Props.Reverb.Gain = AL_REVERB_DEFAULT_GAIN; + effect->Props.Reverb.GainHF = AL_REVERB_DEFAULT_GAINHF; + effect->Props.Reverb.GainLF = 1.0f; + effect->Props.Reverb.DecayTime = AL_REVERB_DEFAULT_DECAY_TIME; + effect->Props.Reverb.DecayHFRatio = AL_REVERB_DEFAULT_DECAY_HFRATIO; + effect->Props.Reverb.DecayLFRatio = 1.0f; + effect->Props.Reverb.ReflectionsGain = AL_REVERB_DEFAULT_REFLECTIONS_GAIN; + effect->Props.Reverb.ReflectionsDelay = AL_REVERB_DEFAULT_REFLECTIONS_DELAY; + effect->Props.Reverb.ReflectionsPan[0] = 0.0f; + effect->Props.Reverb.ReflectionsPan[1] = 0.0f; + effect->Props.Reverb.ReflectionsPan[2] = 0.0f; + effect->Props.Reverb.LateReverbGain = AL_REVERB_DEFAULT_LATE_REVERB_GAIN; + effect->Props.Reverb.LateReverbDelay = AL_REVERB_DEFAULT_LATE_REVERB_DELAY; + effect->Props.Reverb.LateReverbPan[0] = 0.0f; + effect->Props.Reverb.LateReverbPan[1] = 0.0f; + effect->Props.Reverb.LateReverbPan[2] = 0.0f; + effect->Props.Reverb.EchoTime = 0.25f; + effect->Props.Reverb.EchoDepth = 0.0f; + effect->Props.Reverb.ModulationTime = 0.25f; + effect->Props.Reverb.ModulationDepth = 0.0f; + effect->Props.Reverb.AirAbsorptionGainHF = AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF; + effect->Props.Reverb.HFReference = 5000.0f; + effect->Props.Reverb.LFReference = 250.0f; + effect->Props.Reverb.RoomRolloffFactor = AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR; + effect->Props.Reverb.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT; + SET_VTABLE1(ALreverb, effect); + break; + case AL_EFFECT_CHORUS: + effect->Props.Chorus.Waveform = AL_CHORUS_DEFAULT_WAVEFORM; + effect->Props.Chorus.Phase = AL_CHORUS_DEFAULT_PHASE; + effect->Props.Chorus.Rate = AL_CHORUS_DEFAULT_RATE; + effect->Props.Chorus.Depth = AL_CHORUS_DEFAULT_DEPTH; + effect->Props.Chorus.Feedback = AL_CHORUS_DEFAULT_FEEDBACK; + effect->Props.Chorus.Delay = AL_CHORUS_DEFAULT_DELAY; + SET_VTABLE1(ALchorus, effect); + break; + case AL_EFFECT_COMPRESSOR: + effect->Props.Compressor.OnOff = AL_COMPRESSOR_DEFAULT_ONOFF; + SET_VTABLE1(ALcompressor, effect); + break; + case AL_EFFECT_DISTORTION: + effect->Props.Distortion.Edge = AL_DISTORTION_DEFAULT_EDGE; + effect->Props.Distortion.Gain = AL_DISTORTION_DEFAULT_GAIN; + effect->Props.Distortion.LowpassCutoff = AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF; + effect->Props.Distortion.EQCenter = AL_DISTORTION_DEFAULT_EQCENTER; + effect->Props.Distortion.EQBandwidth = AL_DISTORTION_DEFAULT_EQBANDWIDTH; + SET_VTABLE1(ALdistortion, effect); + break; + case AL_EFFECT_ECHO: + effect->Props.Echo.Delay = AL_ECHO_DEFAULT_DELAY; + effect->Props.Echo.LRDelay = AL_ECHO_DEFAULT_LRDELAY; + effect->Props.Echo.Damping = AL_ECHO_DEFAULT_DAMPING; + effect->Props.Echo.Feedback = AL_ECHO_DEFAULT_FEEDBACK; + effect->Props.Echo.Spread = AL_ECHO_DEFAULT_SPREAD; + SET_VTABLE1(ALecho, effect); + break; + case AL_EFFECT_EQUALIZER: + effect->Props.Equalizer.LowCutoff = AL_EQUALIZER_DEFAULT_LOW_CUTOFF; + effect->Props.Equalizer.LowGain = AL_EQUALIZER_DEFAULT_LOW_GAIN; + effect->Props.Equalizer.Mid1Center = AL_EQUALIZER_DEFAULT_MID1_CENTER; + effect->Props.Equalizer.Mid1Gain = AL_EQUALIZER_DEFAULT_MID1_GAIN; + effect->Props.Equalizer.Mid1Width = AL_EQUALIZER_DEFAULT_MID1_WIDTH; + effect->Props.Equalizer.Mid2Center = AL_EQUALIZER_DEFAULT_MID2_CENTER; + effect->Props.Equalizer.Mid2Gain = AL_EQUALIZER_DEFAULT_MID2_GAIN; + effect->Props.Equalizer.Mid2Width = AL_EQUALIZER_DEFAULT_MID2_WIDTH; + effect->Props.Equalizer.HighCutoff = AL_EQUALIZER_DEFAULT_HIGH_CUTOFF; + effect->Props.Equalizer.HighGain = AL_EQUALIZER_DEFAULT_HIGH_GAIN; + SET_VTABLE1(ALequalizer, effect); + break; + case AL_EFFECT_FLANGER: + effect->Props.Flanger.Waveform = AL_FLANGER_DEFAULT_WAVEFORM; + effect->Props.Flanger.Phase = AL_FLANGER_DEFAULT_PHASE; + effect->Props.Flanger.Rate = AL_FLANGER_DEFAULT_RATE; + effect->Props.Flanger.Depth = AL_FLANGER_DEFAULT_DEPTH; + effect->Props.Flanger.Feedback = AL_FLANGER_DEFAULT_FEEDBACK; + effect->Props.Flanger.Delay = AL_FLANGER_DEFAULT_DELAY; + SET_VTABLE1(ALflanger, effect); + break; + case AL_EFFECT_RING_MODULATOR: + effect->Props.Modulator.Frequency = AL_RING_MODULATOR_DEFAULT_FREQUENCY; + effect->Props.Modulator.HighPassCutoff = AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF; + effect->Props.Modulator.Waveform = AL_RING_MODULATOR_DEFAULT_WAVEFORM; + SET_VTABLE1(ALmodulator, effect); + break; + case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: + case AL_EFFECT_DEDICATED_DIALOGUE: + effect->Props.Dedicated.Gain = 1.0f; + SET_VTABLE1(ALdedicated, effect); + break; + default: + SET_VTABLE1(ALnull, effect); + break; + } + effect->type = type; +} + + +#include "AL/efx-presets.h" + +#define DECL(x) { #x, EFX_REVERB_PRESET_##x } +static const struct { + const char name[32]; + EFXEAXREVERBPROPERTIES props; +} reverblist[] = { + DECL(GENERIC), + DECL(PADDEDCELL), + DECL(ROOM), + DECL(BATHROOM), + DECL(LIVINGROOM), + DECL(STONEROOM), + DECL(AUDITORIUM), + DECL(CONCERTHALL), + DECL(CAVE), + DECL(ARENA), + DECL(HANGAR), + DECL(CARPETEDHALLWAY), + DECL(HALLWAY), + DECL(STONECORRIDOR), + DECL(ALLEY), + DECL(FOREST), + DECL(CITY), + DECL(MOUNTAINS), + DECL(QUARRY), + DECL(PLAIN), + DECL(PARKINGLOT), + DECL(SEWERPIPE), + DECL(UNDERWATER), + DECL(DRUGGED), + DECL(DIZZY), + DECL(PSYCHOTIC), + + DECL(CASTLE_SMALLROOM), + DECL(CASTLE_SHORTPASSAGE), + DECL(CASTLE_MEDIUMROOM), + DECL(CASTLE_LARGEROOM), + DECL(CASTLE_LONGPASSAGE), + DECL(CASTLE_HALL), + DECL(CASTLE_CUPBOARD), + DECL(CASTLE_COURTYARD), + DECL(CASTLE_ALCOVE), + + DECL(FACTORY_SMALLROOM), + DECL(FACTORY_SHORTPASSAGE), + DECL(FACTORY_MEDIUMROOM), + DECL(FACTORY_LARGEROOM), + DECL(FACTORY_LONGPASSAGE), + DECL(FACTORY_HALL), + DECL(FACTORY_CUPBOARD), + DECL(FACTORY_COURTYARD), + DECL(FACTORY_ALCOVE), + + DECL(ICEPALACE_SMALLROOM), + DECL(ICEPALACE_SHORTPASSAGE), + DECL(ICEPALACE_MEDIUMROOM), + DECL(ICEPALACE_LARGEROOM), + DECL(ICEPALACE_LONGPASSAGE), + DECL(ICEPALACE_HALL), + DECL(ICEPALACE_CUPBOARD), + DECL(ICEPALACE_COURTYARD), + DECL(ICEPALACE_ALCOVE), + + DECL(SPACESTATION_SMALLROOM), + DECL(SPACESTATION_SHORTPASSAGE), + DECL(SPACESTATION_MEDIUMROOM), + DECL(SPACESTATION_LARGEROOM), + DECL(SPACESTATION_LONGPASSAGE), + DECL(SPACESTATION_HALL), + DECL(SPACESTATION_CUPBOARD), + DECL(SPACESTATION_ALCOVE), + + DECL(WOODEN_SMALLROOM), + DECL(WOODEN_SHORTPASSAGE), + DECL(WOODEN_MEDIUMROOM), + DECL(WOODEN_LARGEROOM), + DECL(WOODEN_LONGPASSAGE), + DECL(WOODEN_HALL), + DECL(WOODEN_CUPBOARD), + DECL(WOODEN_COURTYARD), + DECL(WOODEN_ALCOVE), + + DECL(SPORT_EMPTYSTADIUM), + DECL(SPORT_SQUASHCOURT), + DECL(SPORT_SMALLSWIMMINGPOOL), + DECL(SPORT_LARGESWIMMINGPOOL), + DECL(SPORT_GYMNASIUM), + DECL(SPORT_FULLSTADIUM), + DECL(SPORT_STADIUMTANNOY), + + DECL(PREFAB_WORKSHOP), + DECL(PREFAB_SCHOOLROOM), + DECL(PREFAB_PRACTISEROOM), + DECL(PREFAB_OUTHOUSE), + DECL(PREFAB_CARAVAN), + + DECL(DOME_TOMB), + DECL(PIPE_SMALL), + DECL(DOME_SAINTPAULS), + DECL(PIPE_LONGTHIN), + DECL(PIPE_LARGE), + DECL(PIPE_RESONANT), + + DECL(OUTDOORS_BACKYARD), + DECL(OUTDOORS_ROLLINGPLAINS), + DECL(OUTDOORS_DEEPCANYON), + DECL(OUTDOORS_CREEK), + DECL(OUTDOORS_VALLEY), + + DECL(MOOD_HEAVEN), + DECL(MOOD_HELL), + DECL(MOOD_MEMORY), + + DECL(DRIVING_COMMENTATOR), + DECL(DRIVING_PITGARAGE), + DECL(DRIVING_INCAR_RACER), + DECL(DRIVING_INCAR_SPORTS), + DECL(DRIVING_INCAR_LUXURY), + DECL(DRIVING_FULLGRANDSTAND), + DECL(DRIVING_EMPTYGRANDSTAND), + DECL(DRIVING_TUNNEL), + + DECL(CITY_STREETS), + DECL(CITY_SUBWAY), + DECL(CITY_MUSEUM), + DECL(CITY_LIBRARY), + DECL(CITY_UNDERPASS), + DECL(CITY_ABANDONED), + + DECL(DUSTYROOM), + DECL(CHAPEL), + DECL(SMALLWATERROOM), +}; +#undef DECL + +ALvoid LoadReverbPreset(const char *name, ALeffect *effect) +{ + size_t i; + + if(strcasecmp(name, "NONE") == 0) + { + InitEffectParams(effect, AL_EFFECT_NULL); + TRACE("Loading reverb '%s'\n", "NONE"); + return; + } + + if(!DisabledEffects[EAXREVERB]) + InitEffectParams(effect, AL_EFFECT_EAXREVERB); + else if(!DisabledEffects[REVERB]) + InitEffectParams(effect, AL_EFFECT_REVERB); + else + InitEffectParams(effect, AL_EFFECT_NULL); + for(i = 0;i < COUNTOF(reverblist);i++) + { + const EFXEAXREVERBPROPERTIES *props; + + if(strcasecmp(name, reverblist[i].name) != 0) + continue; + + TRACE("Loading reverb '%s'\n", reverblist[i].name); + props = &reverblist[i].props; + effect->Props.Reverb.Density = props->flDensity; + effect->Props.Reverb.Diffusion = props->flDiffusion; + effect->Props.Reverb.Gain = props->flGain; + effect->Props.Reverb.GainHF = props->flGainHF; + effect->Props.Reverb.GainLF = props->flGainLF; + effect->Props.Reverb.DecayTime = props->flDecayTime; + effect->Props.Reverb.DecayHFRatio = props->flDecayHFRatio; + effect->Props.Reverb.DecayLFRatio = props->flDecayLFRatio; + effect->Props.Reverb.ReflectionsGain = props->flReflectionsGain; + effect->Props.Reverb.ReflectionsDelay = props->flReflectionsDelay; + effect->Props.Reverb.ReflectionsPan[0] = props->flReflectionsPan[0]; + effect->Props.Reverb.ReflectionsPan[1] = props->flReflectionsPan[1]; + effect->Props.Reverb.ReflectionsPan[2] = props->flReflectionsPan[2]; + effect->Props.Reverb.LateReverbGain = props->flLateReverbGain; + effect->Props.Reverb.LateReverbDelay = props->flLateReverbDelay; + effect->Props.Reverb.LateReverbPan[0] = props->flLateReverbPan[0]; + effect->Props.Reverb.LateReverbPan[1] = props->flLateReverbPan[1]; + effect->Props.Reverb.LateReverbPan[2] = props->flLateReverbPan[2]; + effect->Props.Reverb.EchoTime = props->flEchoTime; + effect->Props.Reverb.EchoDepth = props->flEchoDepth; + effect->Props.Reverb.ModulationTime = props->flModulationTime; + effect->Props.Reverb.ModulationDepth = props->flModulationDepth; + effect->Props.Reverb.AirAbsorptionGainHF = props->flAirAbsorptionGainHF; + effect->Props.Reverb.HFReference = props->flHFReference; + effect->Props.Reverb.LFReference = props->flLFReference; + effect->Props.Reverb.RoomRolloffFactor = props->flRoomRolloffFactor; + effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit; + return; + } + + WARN("Reverb preset '%s' not found\n", name); +} diff --git a/Engine/lib/openal-soft/OpenAL32/alError.c b/Engine/lib/openal-soft/OpenAL32/alError.c new file mode 100644 index 000000000..b38d8dfed --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alError.c @@ -0,0 +1,77 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2000 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 + +#ifdef HAVE_WINDOWS_H +#define WIN32_LEAN_AND_MEAN +#include +#endif + +#include "alMain.h" +#include "AL/alc.h" +#include "alError.h" + +ALboolean TrapALError = AL_FALSE; + +ALvoid alSetError(ALCcontext *Context, ALenum errorCode) +{ + ALenum curerr = AL_NO_ERROR; + if(TrapALError) + { +#ifdef _WIN32 + /* DebugBreak will cause an exception if there is no debugger */ + if(IsDebuggerPresent()) + DebugBreak(); +#elif defined(SIGTRAP) + raise(SIGTRAP); +#endif + } + ATOMIC_COMPARE_EXCHANGE_STRONG(ALenum, &Context->LastError, &curerr, errorCode); +} + +AL_API ALenum AL_APIENTRY alGetError(void) +{ + ALCcontext *Context; + ALenum errorCode; + + Context = GetContextRef(); + if(!Context) + { + if(TrapALError) + { +#ifdef _WIN32 + if(IsDebuggerPresent()) + DebugBreak(); +#elif defined(SIGTRAP) + raise(SIGTRAP); +#endif + } + return AL_INVALID_OPERATION; + } + + errorCode = ATOMIC_EXCHANGE(ALenum, &Context->LastError, AL_NO_ERROR); + + ALCcontext_DecRef(Context); + + return errorCode; +} diff --git a/Engine/lib/openal-soft/OpenAL32/alExtension.c b/Engine/lib/openal-soft/OpenAL32/alExtension.c new file mode 100644 index 000000000..1a559d9cb --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alExtension.c @@ -0,0 +1,103 @@ +/** + * 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 +#include +#include + +#include "alError.h" +#include "alMain.h" +#include "alFilter.h" +#include "alEffect.h" +#include "alAuxEffectSlot.h" +#include "alSource.h" +#include "alBuffer.h" +#include "AL/al.h" +#include "AL/alc.h" + + +const struct EffectList EffectList[] = { + { "eaxreverb", EAXREVERB, "AL_EFFECT_EAXREVERB", AL_EFFECT_EAXREVERB }, + { "reverb", REVERB, "AL_EFFECT_REVERB", AL_EFFECT_REVERB }, + { "chorus", CHORUS, "AL_EFFECT_CHORUS", AL_EFFECT_CHORUS }, + { "compressor", COMPRESSOR, "AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR }, + { "distortion", DISTORTION, "AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION }, + { "echo", ECHO, "AL_EFFECT_ECHO", AL_EFFECT_ECHO }, + { "equalizer", EQUALIZER, "AL_EFFECT_EQUALIZER", AL_EFFECT_EQUALIZER }, + { "flanger", FLANGER, "AL_EFFECT_FLANGER", AL_EFFECT_FLANGER }, + { "modulator", MODULATOR, "AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR }, + { "dedicated", DEDICATED, "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT }, + { "dedicated", DEDICATED, "AL_EFFECT_DEDICATED_DIALOGUE", AL_EFFECT_DEDICATED_DIALOGUE }, + { NULL, 0, NULL, (ALenum)0 } +}; + + +AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName) +{ + ALboolean ret = AL_FALSE; + ALCcontext *context; + const char *ptr; + size_t len; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + if(!(extName)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + len = strlen(extName); + ptr = context->ExtensionList; + while(ptr && *ptr) + { + if(strncasecmp(ptr, extName, len) == 0 && + (ptr[len] == '\0' || isspace(ptr[len]))) + { + ret = AL_TRUE; + break; + } + if((ptr=strchr(ptr, ' ')) != NULL) + { + do { + ++ptr; + } while(isspace(*ptr)); + } + } + +done: + ALCcontext_DecRef(context); + return ret; +} + + +AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName) +{ + if(!funcName) + return NULL; + return alcGetProcAddress(NULL, funcName); +} + +AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) +{ + if(!enumName) + return (ALenum)0; + return alcGetEnumValue(NULL, enumName); +} diff --git a/Engine/lib/openal-soft/OpenAL32/alFilter.c b/Engine/lib/openal-soft/OpenAL32/alFilter.c new file mode 100644 index 000000000..c675d3448 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alFilter.c @@ -0,0 +1,718 @@ +/** + * 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 + +#include "alMain.h" +#include "alu.h" +#include "alFilter.h" +#include "alThunk.h" +#include "alError.h" + + +extern inline void LockFiltersRead(ALCdevice *device); +extern inline void UnlockFiltersRead(ALCdevice *device); +extern inline void LockFiltersWrite(ALCdevice *device); +extern inline void UnlockFiltersWrite(ALCdevice *device); +extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id); +extern inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id); +extern inline void ALfilterState_clear(ALfilterState *filter); +extern inline void ALfilterState_processPassthru(ALfilterState *filter, const ALfloat *restrict src, ALuint numsamples); +extern inline ALfloat calc_rcpQ_from_slope(ALfloat gain, ALfloat slope); +extern inline ALfloat calc_rcpQ_from_bandwidth(ALfloat freq_mult, ALfloat bandwidth); + +static void InitFilterParams(ALfilter *filter, ALenum type); + + +AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters) +{ + ALCdevice *device; + ALCcontext *context; + ALsizei cur = 0; + ALenum err; + + context = GetContextRef(); + if(!context) return; + + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + device = context->Device; + for(cur = 0;cur < n;cur++) + { + ALfilter *filter = al_calloc(16, sizeof(ALfilter)); + if(!filter) + { + alDeleteFilters(cur, filters); + SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); + } + InitFilterParams(filter, AL_FILTER_NULL); + + err = NewThunkEntry(&filter->id); + if(err == AL_NO_ERROR) + err = InsertUIntMapEntry(&device->FilterMap, filter->id, filter); + if(err != AL_NO_ERROR) + { + FreeThunkEntry(filter->id); + memset(filter, 0, sizeof(ALfilter)); + al_free(filter); + + alDeleteFilters(cur, filters); + SET_ERROR_AND_GOTO(context, err, done); + } + + filters[cur] = filter->id; + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters) +{ + ALCdevice *device; + ALCcontext *context; + ALfilter *filter; + ALsizei i; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + LockFiltersWrite(device); + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + for(i = 0;i < n;i++) + { + if(filters[i] && LookupFilter(device, filters[i]) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + } + for(i = 0;i < n;i++) + { + if((filter=RemoveFilter(device, filters[i])) == NULL) + continue; + FreeThunkEntry(filter->id); + + memset(filter, 0, sizeof(*filter)); + al_free(filter); + } + +done: + UnlockFiltersWrite(device); + ALCcontext_DecRef(context); +} + +AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter) +{ + ALCcontext *Context; + ALboolean result; + + Context = GetContextRef(); + if(!Context) return AL_FALSE; + + LockFiltersRead(Context->Device); + result = ((!filter || LookupFilter(Context->Device, filter)) ? + AL_TRUE : AL_FALSE); + UnlockFiltersRead(Context->Device); + + ALCcontext_DecRef(Context); + + return result; +} + +AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value) +{ + ALCcontext *Context; + ALCdevice *Device; + ALfilter *ALFilter; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockFiltersWrite(Device); + if((ALFilter=LookupFilter(Device, filter)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + if(param == AL_FILTER_TYPE) + { + if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS || + value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS) + InitFilterParams(ALFilter, value); + else + alSetError(Context, AL_INVALID_VALUE); + } + else + { + /* Call the appropriate handler */ + ALfilter_SetParami(ALFilter, Context, param, value); + } + } + UnlockFiltersWrite(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *values) +{ + ALCcontext *Context; + ALCdevice *Device; + ALfilter *ALFilter; + + switch(param) + { + case AL_FILTER_TYPE: + alFilteri(filter, param, values[0]); + return; + } + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockFiltersWrite(Device); + if((ALFilter=LookupFilter(Device, filter)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + ALfilter_SetParamiv(ALFilter, Context, param, values); + } + UnlockFiltersWrite(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat value) +{ + ALCcontext *Context; + ALCdevice *Device; + ALfilter *ALFilter; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockFiltersWrite(Device); + if((ALFilter=LookupFilter(Device, filter)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + ALfilter_SetParamf(ALFilter, Context, param, value); + } + UnlockFiltersWrite(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *values) +{ + ALCcontext *Context; + ALCdevice *Device; + ALfilter *ALFilter; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockFiltersWrite(Device); + if((ALFilter=LookupFilter(Device, filter)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + ALfilter_SetParamfv(ALFilter, Context, param, values); + } + UnlockFiltersWrite(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *value) +{ + ALCcontext *Context; + ALCdevice *Device; + ALfilter *ALFilter; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockFiltersRead(Device); + if((ALFilter=LookupFilter(Device, filter)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + if(param == AL_FILTER_TYPE) + *value = ALFilter->type; + else + { + /* Call the appropriate handler */ + ALfilter_GetParami(ALFilter, Context, param, value); + } + } + UnlockFiltersRead(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *values) +{ + ALCcontext *Context; + ALCdevice *Device; + ALfilter *ALFilter; + + switch(param) + { + case AL_FILTER_TYPE: + alGetFilteri(filter, param, values); + return; + } + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockFiltersRead(Device); + if((ALFilter=LookupFilter(Device, filter)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + ALfilter_GetParamiv(ALFilter, Context, param, values); + } + UnlockFiltersRead(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *value) +{ + ALCcontext *Context; + ALCdevice *Device; + ALfilter *ALFilter; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockFiltersRead(Device); + if((ALFilter=LookupFilter(Device, filter)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + ALfilter_GetParamf(ALFilter, Context, param, value); + } + UnlockFiltersRead(Device); + + ALCcontext_DecRef(Context); +} + +AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *values) +{ + ALCcontext *Context; + ALCdevice *Device; + ALfilter *ALFilter; + + Context = GetContextRef(); + if(!Context) return; + + Device = Context->Device; + LockFiltersRead(Device); + if((ALFilter=LookupFilter(Device, filter)) == NULL) + alSetError(Context, AL_INVALID_NAME); + else + { + /* Call the appropriate handler */ + ALfilter_GetParamfv(ALFilter, Context, param, values); + } + UnlockFiltersRead(Device); + + ALCcontext_DecRef(Context); +} + + +void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat rcpQ) +{ + ALfloat alpha, sqrtgain_alpha_2; + ALfloat w0, sin_w0, cos_w0; + ALfloat a[3] = { 1.0f, 0.0f, 0.0f }; + ALfloat b[3] = { 1.0f, 0.0f, 0.0f }; + + // Limit gain to -100dB + gain = maxf(gain, 0.00001f); + + w0 = F_TAU * freq_mult; + sin_w0 = sinf(w0); + cos_w0 = cosf(w0); + alpha = sin_w0/2.0f * rcpQ; + + /* Calculate filter coefficients depending on filter type */ + switch(type) + { + case ALfilterType_HighShelf: + sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha; + b[0] = gain*((gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2); + b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cos_w0 ); + b[2] = gain*((gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2); + a[0] = (gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2; + a[1] = 2.0f* ((gain-1.0f) - (gain+1.0f)*cos_w0 ); + a[2] = (gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2; + break; + case ALfilterType_LowShelf: + sqrtgain_alpha_2 = 2.0f * sqrtf(gain) * alpha; + b[0] = gain*((gain+1.0f) - (gain-1.0f)*cos_w0 + sqrtgain_alpha_2); + b[1] = 2.0f*gain*((gain-1.0f) - (gain+1.0f)*cos_w0 ); + b[2] = gain*((gain+1.0f) - (gain-1.0f)*cos_w0 - sqrtgain_alpha_2); + a[0] = (gain+1.0f) + (gain-1.0f)*cos_w0 + sqrtgain_alpha_2; + a[1] = -2.0f* ((gain-1.0f) + (gain+1.0f)*cos_w0 ); + a[2] = (gain+1.0f) + (gain-1.0f)*cos_w0 - sqrtgain_alpha_2; + break; + case ALfilterType_Peaking: + gain = sqrtf(gain); + b[0] = 1.0f + alpha * gain; + b[1] = -2.0f * cos_w0; + b[2] = 1.0f - alpha * gain; + a[0] = 1.0f + alpha / gain; + a[1] = -2.0f * cos_w0; + a[2] = 1.0f - alpha / gain; + break; + + case ALfilterType_LowPass: + b[0] = (1.0f - cos_w0) / 2.0f; + b[1] = 1.0f - cos_w0; + b[2] = (1.0f - cos_w0) / 2.0f; + a[0] = 1.0f + alpha; + a[1] = -2.0f * cos_w0; + a[2] = 1.0f - alpha; + break; + case ALfilterType_HighPass: + b[0] = (1.0f + cos_w0) / 2.0f; + b[1] = -(1.0f + cos_w0); + b[2] = (1.0f + cos_w0) / 2.0f; + a[0] = 1.0f + alpha; + a[1] = -2.0f * cos_w0; + a[2] = 1.0f - alpha; + break; + case ALfilterType_BandPass: + b[0] = alpha; + b[1] = 0; + b[2] = -alpha; + a[0] = 1.0f + alpha; + a[1] = -2.0f * cos_w0; + a[2] = 1.0f - alpha; + break; + } + + filter->a1 = a[1] / a[0]; + filter->a2 = a[2] / a[0]; + filter->b0 = b[0] / a[0]; + filter->b1 = b[1] / a[0]; + filter->b2 = b[2] / a[0]; +} + + +static void lp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void lp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void lp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) +{ + switch(param) + { + case AL_LOWPASS_GAIN: + if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->Gain = val; + break; + + case AL_LOWPASS_GAINHF: + if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->GainHF = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void lp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + lp_SetParamf(filter, context, param, vals[0]); +} + +static void lp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void lp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void lp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) +{ + switch(param) + { + case AL_LOWPASS_GAIN: + *val = filter->Gain; + break; + + case AL_LOWPASS_GAINHF: + *val = filter->GainHF; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +{ + lp_GetParamf(filter, context, param, vals); +} + + +static void hp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void hp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void hp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) +{ + switch(param) + { + case AL_HIGHPASS_GAIN: + if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->Gain = val; + break; + + case AL_HIGHPASS_GAINLF: + if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->GainLF = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void hp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + hp_SetParamf(filter, context, param, vals[0]); +} + +static void hp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void hp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void hp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) +{ + switch(param) + { + case AL_HIGHPASS_GAIN: + *val = filter->Gain; + break; + + case AL_HIGHPASS_GAINLF: + *val = filter->GainLF; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void hp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +{ + hp_GetParamf(filter, context, param, vals); +} + + +static void bp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void bp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void bp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) +{ + switch(param) + { + case AL_BANDPASS_GAIN: + if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->Gain = val; + break; + + case AL_BANDPASS_GAINHF: + if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->GainHF = val; + break; + + case AL_BANDPASS_GAINLF: + if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->GainLF = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void bp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + bp_SetParamf(filter, context, param, vals[0]); +} + +static void bp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void bp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void bp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) +{ + switch(param) + { + case AL_BANDPASS_GAIN: + *val = filter->Gain; + break; + + case AL_BANDPASS_GAINHF: + *val = filter->GainHF; + break; + + case AL_BANDPASS_GAINLF: + *val = filter->GainLF; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void bp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +{ + bp_GetParamf(filter, context, param, vals); +} + + +static void null_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void null_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void null_SetParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void null_SetParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALfloat *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } + +static void null_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void null_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void null_GetParamf(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void null_GetParamfv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALfloat *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } + + +ALvoid ReleaseALFilters(ALCdevice *device) +{ + ALsizei i; + for(i = 0;i < device->FilterMap.size;i++) + { + ALfilter *temp = device->FilterMap.values[i]; + device->FilterMap.values[i] = NULL; + + // Release filter structure + FreeThunkEntry(temp->id); + memset(temp, 0, sizeof(ALfilter)); + al_free(temp); + } +} + + +static void InitFilterParams(ALfilter *filter, ALenum type) +{ + if(type == AL_FILTER_LOWPASS) + { + filter->Gain = AL_LOWPASS_DEFAULT_GAIN; + filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF; + filter->HFReference = LOWPASSFREQREF; + filter->GainLF = 1.0f; + filter->LFReference = HIGHPASSFREQREF; + + filter->SetParami = lp_SetParami; + filter->SetParamiv = lp_SetParamiv; + filter->SetParamf = lp_SetParamf; + filter->SetParamfv = lp_SetParamfv; + filter->GetParami = lp_GetParami; + filter->GetParamiv = lp_GetParamiv; + filter->GetParamf = lp_GetParamf; + filter->GetParamfv = lp_GetParamfv; + } + else if(type == AL_FILTER_HIGHPASS) + { + filter->Gain = AL_HIGHPASS_DEFAULT_GAIN; + filter->GainHF = 1.0f; + filter->HFReference = LOWPASSFREQREF; + filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF; + filter->LFReference = HIGHPASSFREQREF; + + filter->SetParami = hp_SetParami; + filter->SetParamiv = hp_SetParamiv; + filter->SetParamf = hp_SetParamf; + filter->SetParamfv = hp_SetParamfv; + filter->GetParami = hp_GetParami; + filter->GetParamiv = hp_GetParamiv; + filter->GetParamf = hp_GetParamf; + filter->GetParamfv = hp_GetParamfv; + } + else if(type == AL_FILTER_BANDPASS) + { + filter->Gain = AL_BANDPASS_DEFAULT_GAIN; + filter->GainHF = AL_BANDPASS_DEFAULT_GAINHF; + filter->HFReference = LOWPASSFREQREF; + filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF; + filter->LFReference = HIGHPASSFREQREF; + + filter->SetParami = bp_SetParami; + filter->SetParamiv = bp_SetParamiv; + filter->SetParamf = bp_SetParamf; + filter->SetParamfv = bp_SetParamfv; + filter->GetParami = bp_GetParami; + filter->GetParamiv = bp_GetParamiv; + filter->GetParamf = bp_GetParamf; + filter->GetParamfv = bp_GetParamfv; + } + else + { + filter->Gain = 1.0f; + filter->GainHF = 1.0f; + filter->HFReference = LOWPASSFREQREF; + filter->GainLF = 1.0f; + filter->LFReference = HIGHPASSFREQREF; + + filter->SetParami = null_SetParami; + filter->SetParamiv = null_SetParamiv; + filter->SetParamf = null_SetParamf; + filter->SetParamfv = null_SetParamfv; + filter->GetParami = null_GetParami; + filter->GetParamiv = null_GetParamiv; + filter->GetParamf = null_GetParamf; + filter->GetParamfv = null_GetParamfv; + } + filter->type = type; +} diff --git a/Engine/lib/openal-soft/OpenAL32/alListener.c b/Engine/lib/openal-soft/OpenAL32/alListener.c new file mode 100644 index 000000000..08ece19db --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alListener.c @@ -0,0 +1,515 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2000 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 "alMain.h" +#include "AL/alc.h" +#include "alError.h" +#include "alListener.h" +#include "alSource.h" + +AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + switch(param) + { + case AL_GAIN: + if(!(value >= 0.0f && isfinite(value))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + context->Listener->Gain = value; + break; + + case AL_METERS_PER_UNIT: + if(!(value >= 0.0f && isfinite(value))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + context->Listener->MetersPerUnit = value; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + +done: + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + switch(param) + { + case AL_POSITION: + if(!(isfinite(value1) && isfinite(value2) && isfinite(value3))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + context->Listener->Position[0] = value1; + context->Listener->Position[1] = value2; + context->Listener->Position[2] = value3; + break; + + case AL_VELOCITY: + if(!(isfinite(value1) && isfinite(value2) && isfinite(value3))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + context->Listener->Velocity[0] = value1; + context->Listener->Velocity[1] = value2; + context->Listener->Velocity[2] = value3; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + +done: + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values) +{ + ALCcontext *context; + + if(values) + { + switch(param) + { + case AL_GAIN: + case AL_METERS_PER_UNIT: + alListenerf(param, values[0]); + return; + + case AL_POSITION: + case AL_VELOCITY: + alListener3f(param, values[0], values[1], values[2]); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_ORIENTATION: + if(!(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) && + isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5]))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + /* AT then UP */ + context->Listener->Forward[0] = values[0]; + context->Listener->Forward[1] = values[1]; + context->Listener->Forward[2] = values[2]; + context->Listener->Up[0] = values[3]; + context->Listener->Up[1] = values[4]; + context->Listener->Up[2] = values[5]; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + +done: + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alListeneri(ALenum param, ALint UNUSED(value)) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + +done: + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3) +{ + ALCcontext *context; + + switch(param) + { + case AL_POSITION: + case AL_VELOCITY: + alListener3f(param, (ALfloat)value1, (ALfloat)value2, (ALfloat)value3); + return; + } + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + +done: + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values) +{ + ALCcontext *context; + + if(values) + { + ALfloat fvals[6]; + switch(param) + { + case AL_POSITION: + case AL_VELOCITY: + alListener3f(param, (ALfloat)values[0], (ALfloat)values[1], (ALfloat)values[2]); + return; + + case AL_ORIENTATION: + fvals[0] = (ALfloat)values[0]; + fvals[1] = (ALfloat)values[1]; + fvals[2] = (ALfloat)values[2]; + fvals[3] = (ALfloat)values[3]; + fvals[4] = (ALfloat)values[4]; + fvals[5] = (ALfloat)values[5]; + alListenerfv(param, fvals); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + +done: + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + ReadLock(&context->PropLock); + if(!(value)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_GAIN: + *value = context->Listener->Gain; + break; + + case AL_METERS_PER_UNIT: + *value = context->Listener->MetersPerUnit; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ReadUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + ReadLock(&context->PropLock); + if(!(value1 && value2 && value3)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_POSITION: + *value1 = context->Listener->Position[0]; + *value2 = context->Listener->Position[1]; + *value3 = context->Listener->Position[2]; + break; + + case AL_VELOCITY: + *value1 = context->Listener->Velocity[0]; + *value2 = context->Listener->Velocity[1]; + *value3 = context->Listener->Velocity[2]; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ReadUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values) +{ + ALCcontext *context; + + switch(param) + { + case AL_GAIN: + case AL_METERS_PER_UNIT: + alGetListenerf(param, values); + return; + + case AL_POSITION: + case AL_VELOCITY: + alGetListener3f(param, values+0, values+1, values+2); + return; + } + + context = GetContextRef(); + if(!context) return; + + ReadLock(&context->PropLock); + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_ORIENTATION: + // AT then UP + values[0] = context->Listener->Forward[0]; + values[1] = context->Listener->Forward[1]; + values[2] = context->Listener->Forward[2]; + values[3] = context->Listener->Up[0]; + values[4] = context->Listener->Up[1]; + values[5] = context->Listener->Up[2]; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ReadUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum param, ALint *value) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + ReadLock(&context->PropLock); + if(!(value)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ReadUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + ReadLock(&context->PropLock); + if(!(value1 && value2 && value3)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch (param) + { + case AL_POSITION: + *value1 = (ALint)context->Listener->Position[0]; + *value2 = (ALint)context->Listener->Position[1]; + *value3 = (ALint)context->Listener->Position[2]; + break; + + case AL_VELOCITY: + *value1 = (ALint)context->Listener->Velocity[0]; + *value2 = (ALint)context->Listener->Velocity[1]; + *value3 = (ALint)context->Listener->Velocity[2]; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ReadUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint* values) +{ + ALCcontext *context; + + switch(param) + { + case AL_POSITION: + case AL_VELOCITY: + alGetListener3i(param, values+0, values+1, values+2); + return; + } + + context = GetContextRef(); + if(!context) return; + + ReadLock(&context->PropLock); + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_ORIENTATION: + // AT then UP + values[0] = (ALint)context->Listener->Forward[0]; + values[1] = (ALint)context->Listener->Forward[1]; + values[2] = (ALint)context->Listener->Forward[2]; + values[3] = (ALint)context->Listener->Up[0]; + values[4] = (ALint)context->Listener->Up[1]; + values[5] = (ALint)context->Listener->Up[2]; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ReadUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + + +void UpdateListenerProps(ALCcontext *context) +{ + ALlistener *listener = context->Listener; + struct ALlistenerProps *props; + + /* Get an unused proprty container, or allocate a new one as needed. */ + props = ATOMIC_LOAD(&listener->FreeList, almemory_order_acquire); + if(!props) + props = al_calloc(16, sizeof(*props)); + else + { + struct ALlistenerProps *next; + do { + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*, + &listener->FreeList, &props, next, almemory_order_seq_cst, + almemory_order_consume) == 0); + } + + /* Copy in current property values. */ + ATOMIC_STORE(&props->Position[0], listener->Position[0], almemory_order_relaxed); + ATOMIC_STORE(&props->Position[1], listener->Position[1], almemory_order_relaxed); + ATOMIC_STORE(&props->Position[2], listener->Position[2], almemory_order_relaxed); + + ATOMIC_STORE(&props->Velocity[0], listener->Velocity[0], almemory_order_relaxed); + ATOMIC_STORE(&props->Velocity[1], listener->Velocity[1], almemory_order_relaxed); + ATOMIC_STORE(&props->Velocity[2], listener->Velocity[2], almemory_order_relaxed); + + ATOMIC_STORE(&props->Forward[0], listener->Forward[0], almemory_order_relaxed); + ATOMIC_STORE(&props->Forward[1], listener->Forward[1], almemory_order_relaxed); + ATOMIC_STORE(&props->Forward[2], listener->Forward[2], almemory_order_relaxed); + ATOMIC_STORE(&props->Up[0], listener->Up[0], almemory_order_relaxed); + ATOMIC_STORE(&props->Up[1], listener->Up[1], almemory_order_relaxed); + ATOMIC_STORE(&props->Up[2], listener->Up[2], almemory_order_relaxed); + + ATOMIC_STORE(&props->Gain, listener->Gain, almemory_order_relaxed); + ATOMIC_STORE(&props->MetersPerUnit, listener->MetersPerUnit, almemory_order_relaxed); + + ATOMIC_STORE(&props->DopplerFactor, context->DopplerFactor, almemory_order_relaxed); + ATOMIC_STORE(&props->DopplerVelocity, context->DopplerVelocity, almemory_order_relaxed); + ATOMIC_STORE(&props->SpeedOfSound, context->SpeedOfSound, almemory_order_relaxed); + + ATOMIC_STORE(&props->SourceDistanceModel, context->SourceDistanceModel, almemory_order_relaxed); + ATOMIC_STORE(&props->DistanceModel, context->DistanceModel, almemory_order_relaxed); + + /* Set the new container for updating internal parameters. */ + props = ATOMIC_EXCHANGE(struct ALlistenerProps*, &listener->Update, props, almemory_order_acq_rel); + if(props) + { + /* If there was an unused update container, put it back in the + * freelist. + */ + struct ALlistenerProps *first = ATOMIC_LOAD(&listener->FreeList); + do { + ATOMIC_STORE(&props->next, first, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALlistenerProps*, + &listener->FreeList, &first, props) == 0); + } +} diff --git a/Engine/lib/openal-soft/OpenAL32/alSource.c b/Engine/lib/openal-soft/OpenAL32/alSource.c new file mode 100644 index 000000000..f20498f48 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alSource.c @@ -0,0 +1,3401 @@ +/** + * 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 +#include +#include +#include + +#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 "backends/base.h" + +#include "threads.h" +#include "almalloc.h" + + +extern inline void LockSourcesRead(ALCcontext *context); +extern inline void UnlockSourcesRead(ALCcontext *context); +extern inline void LockSourcesWrite(ALCcontext *context); +extern inline void UnlockSourcesWrite(ALCcontext *context); +extern inline struct ALsource *LookupSource(ALCcontext *context, ALuint id); +extern inline struct ALsource *RemoveSource(ALCcontext *context, ALuint id); + +static void InitSourceParams(ALsource *Source); +static void DeinitSource(ALsource *source); +static void UpdateSourceProps(ALsource *source, ALuint num_sends); +static ALint64 GetSourceSampleOffset(ALsource *Source, ALCdevice *device, ALuint64 *clocktime); +static ALdouble GetSourceSecOffset(ALsource *Source, ALCdevice *device, ALuint64 *clocktime); +static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCdevice *device); +static ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALuint *frac); + +typedef enum SourceProp { + srcPitch = AL_PITCH, + srcGain = AL_GAIN, + srcMinGain = AL_MIN_GAIN, + srcMaxGain = AL_MAX_GAIN, + srcMaxDistance = AL_MAX_DISTANCE, + srcRolloffFactor = AL_ROLLOFF_FACTOR, + srcDopplerFactor = AL_DOPPLER_FACTOR, + srcConeOuterGain = AL_CONE_OUTER_GAIN, + srcSecOffset = AL_SEC_OFFSET, + srcSampleOffset = AL_SAMPLE_OFFSET, + srcByteOffset = AL_BYTE_OFFSET, + srcConeInnerAngle = AL_CONE_INNER_ANGLE, + srcConeOuterAngle = AL_CONE_OUTER_ANGLE, + srcRefDistance = AL_REFERENCE_DISTANCE, + + srcPosition = AL_POSITION, + srcVelocity = AL_VELOCITY, + srcDirection = AL_DIRECTION, + + srcSourceRelative = AL_SOURCE_RELATIVE, + srcLooping = AL_LOOPING, + srcBuffer = AL_BUFFER, + srcSourceState = AL_SOURCE_STATE, + srcBuffersQueued = AL_BUFFERS_QUEUED, + srcBuffersProcessed = AL_BUFFERS_PROCESSED, + srcSourceType = AL_SOURCE_TYPE, + + /* ALC_EXT_EFX */ + srcConeOuterGainHF = AL_CONE_OUTER_GAINHF, + srcAirAbsorptionFactor = AL_AIR_ABSORPTION_FACTOR, + srcRoomRolloffFactor = AL_ROOM_ROLLOFF_FACTOR, + srcDirectFilterGainHFAuto = AL_DIRECT_FILTER_GAINHF_AUTO, + srcAuxSendFilterGainAuto = AL_AUXILIARY_SEND_FILTER_GAIN_AUTO, + srcAuxSendFilterGainHFAuto = AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO, + srcDirectFilter = AL_DIRECT_FILTER, + srcAuxSendFilter = AL_AUXILIARY_SEND_FILTER, + + /* AL_SOFT_direct_channels */ + srcDirectChannelsSOFT = AL_DIRECT_CHANNELS_SOFT, + + /* AL_EXT_source_distance_model */ + srcDistanceModel = AL_DISTANCE_MODEL, + + srcByteLengthSOFT = AL_BYTE_LENGTH_SOFT, + srcSampleLengthSOFT = AL_SAMPLE_LENGTH_SOFT, + srcSecLengthSOFT = AL_SEC_LENGTH_SOFT, + + /* AL_SOFT_source_latency */ + srcSampleOffsetLatencySOFT = AL_SAMPLE_OFFSET_LATENCY_SOFT, + srcSecOffsetLatencySOFT = AL_SEC_OFFSET_LATENCY_SOFT, + + /* AL_EXT_STEREO_ANGLES */ + srcAngles = AL_STEREO_ANGLES, + + /* AL_EXT_SOURCE_RADIUS */ + srcRadius = AL_SOURCE_RADIUS, + + /* AL_EXT_BFORMAT */ + srcOrientation = AL_ORIENTATION, +} SourceProp; + +static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALfloat *values); +static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint *values); +static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALint64SOFT *values); + +static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALdouble *values); +static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint *values); +static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SourceProp prop, ALint64 *values); + +static inline bool SourceShouldUpdate(const ALsource *source, const ALCcontext *context) +{ + return (source->state == AL_PLAYING || source->state == AL_PAUSED) && + !ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire); +} + +static ALint FloatValsByProp(ALenum prop) +{ + if(prop != (ALenum)((SourceProp)prop)) + return 0; + switch((SourceProp)prop) + { + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + 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: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + case AL_SOURCE_RADIUS: + return 1; + + case AL_STEREO_ANGLES: + return 2; + + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + return 3; + + case AL_ORIENTATION: + return 6; + + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + break; /* i/i64 only */ + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; /* i64 only */ + } + return 0; +} +static ALint DoubleValsByProp(ALenum prop) +{ + if(prop != (ALenum)((SourceProp)prop)) + return 0; + switch((SourceProp)prop) + { + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + 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: + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_TYPE: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + case AL_SOURCE_RADIUS: + return 1; + + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_STEREO_ANGLES: + return 2; + + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + return 3; + + case AL_ORIENTATION: + return 6; + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + break; /* i/i64 only */ + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; /* i64 only */ + } + return 0; +} + +static ALint IntValsByProp(ALenum prop) +{ + if(prop != (ALenum)((SourceProp)prop)) + return 0; + switch((SourceProp)prop) + { + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + 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: + 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: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + case AL_SOURCE_RADIUS: + return 1; + + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + case AL_AUXILIARY_SEND_FILTER: + return 3; + + case AL_ORIENTATION: + return 6; + + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; /* i64 only */ + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ + case AL_STEREO_ANGLES: + break; /* Float/double only */ + } + return 0; +} +static ALint Int64ValsByProp(ALenum prop) +{ + if(prop != (ALenum)((SourceProp)prop)) + return 0; + switch((SourceProp)prop) + { + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_MAX_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_REFERENCE_DISTANCE: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + 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: + 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: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + case AL_SOURCE_RADIUS: + return 1; + + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + return 2; + + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + case AL_AUXILIARY_SEND_FILTER: + return 3; + + case AL_ORIENTATION: + return 6; + + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ + case AL_STEREO_ANGLES: + break; /* Float/double only */ + } + return 0; +} + + +#define CHECKVAL(x) do { \ + if(!(x)) \ + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); \ +} while(0) + +#define DO_UPDATEPROPS() do { \ + if(SourceShouldUpdate(Source, Context)) \ + UpdateSourceProps(Source, device->NumAuxSends); \ +} while(0) + +static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SourceProp prop, const ALfloat *values) +{ + ALCdevice *device = Context->Device; + ALint ival; + + switch(prop) + { + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + case AL_SEC_OFFSET_LATENCY_SOFT: + /* Query only */ + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); + + case AL_PITCH: + CHECKVAL(*values >= 0.0f); + + Source->Pitch = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_CONE_INNER_ANGLE: + CHECKVAL(*values >= 0.0f && *values <= 360.0f); + + Source->InnerAngle = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_CONE_OUTER_ANGLE: + CHECKVAL(*values >= 0.0f && *values <= 360.0f); + + Source->OuterAngle = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_GAIN: + CHECKVAL(*values >= 0.0f); + + Source->Gain = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_MAX_DISTANCE: + CHECKVAL(*values >= 0.0f); + + Source->MaxDistance = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_ROLLOFF_FACTOR: + CHECKVAL(*values >= 0.0f); + + Source->RollOffFactor = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_REFERENCE_DISTANCE: + CHECKVAL(*values >= 0.0f); + + Source->RefDistance = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_MIN_GAIN: + CHECKVAL(*values >= 0.0f); + + Source->MinGain = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_MAX_GAIN: + CHECKVAL(*values >= 0.0f); + + Source->MaxGain = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_CONE_OUTER_GAIN: + CHECKVAL(*values >= 0.0f && *values <= 1.0f); + + Source->OuterGain = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_CONE_OUTER_GAINHF: + CHECKVAL(*values >= 0.0f && *values <= 1.0f); + + Source->OuterGainHF = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_AIR_ABSORPTION_FACTOR: + CHECKVAL(*values >= 0.0f && *values <= 10.0f); + + Source->AirAbsorptionFactor = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_ROOM_ROLLOFF_FACTOR: + CHECKVAL(*values >= 0.0f && *values <= 10.0f); + + Source->RoomRolloffFactor = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_DOPPLER_FACTOR: + CHECKVAL(*values >= 0.0f && *values <= 1.0f); + + Source->DopplerFactor = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + CHECKVAL(*values >= 0.0f); + + Source->OffsetType = prop; + Source->Offset = *values; + + if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && + !ATOMIC_LOAD(&Context->DeferUpdates, almemory_order_acquire)) + { + LockContext(Context); + WriteLock(&Source->queue_lock); + if(ApplyOffset(Source) == AL_FALSE) + { + WriteUnlock(&Source->queue_lock); + UnlockContext(Context); + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); + } + WriteUnlock(&Source->queue_lock); + UnlockContext(Context); + } + return AL_TRUE; + + case AL_SOURCE_RADIUS: + CHECKVAL(*values >= 0.0f && isfinite(*values)); + + Source->Radius = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_STEREO_ANGLES: + CHECKVAL(isfinite(values[0]) && isfinite(values[1])); + + Source->StereoPan[0] = values[0]; + Source->StereoPan[1] = values[1]; + DO_UPDATEPROPS(); + return AL_TRUE; + + + case AL_POSITION: + CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); + + Source->Position[0] = values[0]; + Source->Position[1] = values[1]; + Source->Position[2] = values[2]; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_VELOCITY: + CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); + + Source->Velocity[0] = values[0]; + Source->Velocity[1] = values[1]; + Source->Velocity[2] = values[2]; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_DIRECTION: + CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2])); + + Source->Direction[0] = values[0]; + Source->Direction[1] = values[1]; + Source->Direction[2] = values[2]; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_ORIENTATION: + CHECKVAL(isfinite(values[0]) && isfinite(values[1]) && isfinite(values[2]) && + isfinite(values[3]) && isfinite(values[4]) && isfinite(values[5])); + + Source->Orientation[0][0] = values[0]; + Source->Orientation[0][1] = values[1]; + Source->Orientation[0][2] = values[2]; + Source->Orientation[1][0] = values[3]; + Source->Orientation[1][1] = values[4]; + Source->Orientation[1][2] = values[5]; + DO_UPDATEPROPS(); + return AL_TRUE; + + + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_SOURCE_TYPE: + case AL_DISTANCE_MODEL: + 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: + ival = (ALint)values[0]; + return SetSourceiv(Source, Context, prop, &ival); + + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + ival = (ALint)((ALuint)values[0]); + return SetSourceiv(Source, Context, prop, &ival); + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; + } + + 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, SourceProp prop, const ALint *values) +{ + ALCdevice *device = Context->Device; + ALbuffer *buffer = NULL; + ALfilter *filter = NULL; + ALeffectslot *slot = NULL; + ALbufferlistitem *oldlist; + ALbufferlistitem *newlist; + ALfloat fvals[6]; + + switch(prop) + { + case AL_SOURCE_STATE: + case AL_SOURCE_TYPE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + /* Query only */ + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); + + case AL_SOURCE_RELATIVE: + CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); + + Source->HeadRelative = (ALboolean)*values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_LOOPING: + CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); + + WriteLock(&Source->queue_lock); + ATOMIC_STORE(&Source->looping, *values); + WriteUnlock(&Source->queue_lock); + return AL_TRUE; + + case AL_BUFFER: + LockBuffersRead(device); + if(!(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL)) + { + UnlockBuffersRead(device); + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); + } + + WriteLock(&Source->queue_lock); + if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL)) + { + WriteUnlock(&Source->queue_lock); + UnlockBuffersRead(device); + 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; + 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); + UnlockBuffersRead(device); + + /* 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 AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + CHECKVAL(*values >= 0); + + Source->OffsetType = prop; + Source->Offset = *values; + + if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && + !ATOMIC_LOAD(&Context->DeferUpdates, almemory_order_acquire)) + { + LockContext(Context); + WriteLock(&Source->queue_lock); + if(ApplyOffset(Source) == AL_FALSE) + { + WriteUnlock(&Source->queue_lock); + UnlockContext(Context); + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); + } + WriteUnlock(&Source->queue_lock); + UnlockContext(Context); + } + return AL_TRUE; + + case AL_DIRECT_FILTER: + LockFiltersRead(device); + if(!(*values == 0 || (filter=LookupFilter(device, *values)) != NULL)) + { + UnlockFiltersRead(device); + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); + } + + 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; + } + UnlockFiltersRead(device); + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_DIRECT_FILTER_GAINHF_AUTO: + CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); + + Source->DryGainHFAuto = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: + CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); + + Source->WetGainAuto = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: + CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); + + Source->WetGainHFAuto = *values; + DO_UPDATEPROPS(); + return AL_TRUE; + + case AL_DIRECT_CHANNELS_SOFT: + CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); + + Source->DirectChannels = *values; + DO_UPDATEPROPS(); + 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) + DO_UPDATEPROPS(); + return AL_TRUE; + + + case AL_AUXILIARY_SEND_FILTER: + LockEffectSlotsRead(Context); + LockFiltersRead(device); + if(!((ALuint)values[1] < device->NumAuxSends && + (values[0] == 0 || (slot=LookupEffectSlot(Context, values[0])) != NULL) && + (values[2] == 0 || (filter=LookupFilter(device, values[2])) != NULL))) + { + UnlockFiltersRead(device); + UnlockEffectSlotsRead(Context); + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_VALUE, AL_FALSE); + } + + 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; + } + UnlockFiltersRead(device); + + if(slot != Source->Send[values[1]].Slot && + (Source->state == AL_PLAYING || Source->state == AL_PAUSED)) + { + /* Add refcount on the new slot, and release the previous slot */ + if(slot) IncrementRef(&slot->ref); + if(Source->Send[values[1]].Slot) + DecrementRef(&Source->Send[values[1]].Slot->ref); + Source->Send[values[1]].Slot = slot; + + /* We must force an update if the auxiliary slot changed on a + * playing source, in case the slot is about to be deleted. + */ + UpdateSourceProps(Source, device->NumAuxSends); + } + else + { + if(slot) IncrementRef(&slot->ref); + if(Source->Send[values[1]].Slot) + DecrementRef(&Source->Send[values[1]].Slot->ref); + Source->Send[values[1]].Slot = slot; + DO_UPDATEPROPS(); + } + UnlockEffectSlotsRead(Context); + + return AL_TRUE; + + + /* 1x float */ + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_SOURCE_RADIUS: + 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); + + /* 6x float */ + case AL_ORIENTATION: + fvals[0] = (ALfloat)values[0]; + fvals[1] = (ALfloat)values[1]; + fvals[2] = (ALfloat)values[2]; + fvals[3] = (ALfloat)values[3]; + fvals[4] = (ALfloat)values[4]; + fvals[5] = (ALfloat)values[5]; + return SetSourcefv(Source, Context, (int)prop, fvals); + + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_STEREO_ANGLES: + 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, SourceProp prop, const ALint64SOFT *values) +{ + ALfloat fvals[6]; + ALint ivals[3]; + + switch(prop) + { + case AL_SOURCE_TYPE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_SOURCE_STATE: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_SEC_LENGTH_SOFT: + /* Query only */ + SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); + + + /* 1x int */ + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + 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_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_DOPPLER_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_SOURCE_RADIUS: + 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); + + /* 6x float */ + case AL_ORIENTATION: + fvals[0] = (ALfloat)values[0]; + fvals[1] = (ALfloat)values[1]; + fvals[2] = (ALfloat)values[2]; + fvals[3] = (ALfloat)values[3]; + fvals[4] = (ALfloat)values[4]; + fvals[5] = (ALfloat)values[5]; + return SetSourcefv(Source, Context, (int)prop, fvals); + + case AL_SEC_OFFSET_LATENCY_SOFT: + case AL_STEREO_ANGLES: + break; + } + + 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, SourceProp prop, ALdouble *values) +{ + ALCdevice *device = Context->Device; + ALbufferlistitem *BufferList; + ClockLatency clocktime; + ALuint64 srcclock; + 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: + *values = GetSourceOffset(Source, prop, device); + 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 AL_SEC_LENGTH_SOFT: + 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_SOURCE_RADIUS: + *values = Source->Radius; + return AL_TRUE; + + case AL_STEREO_ANGLES: + values[0] = Source->StereoPan[0]; + values[1] = Source->StereoPan[1]; + return AL_TRUE; + + case AL_SEC_OFFSET_LATENCY_SOFT: + /* Get the source offset with the clock time first. Then get the + * clock time with the device latency. Order is important. + */ + values[0] = GetSourceSecOffset(Source, device, &srcclock); + clocktime = V0(device->Backend,getClockLatency)(); + if(srcclock == (ALuint64)clocktime.ClockTime) + values[1] = (ALdouble)clocktime.Latency / 1000000000.0; + else + { + /* If the clock time incremented, reduce the latency by that + * much since it's that much closer to the source offset it got + * earlier. + */ + ALuint64 diff = clocktime.ClockTime - srcclock; + values[1] = (ALdouble)(clocktime.Latency - minu64(clocktime.Latency, diff)) / + 1000000000.0; + } + return AL_TRUE; + + case AL_POSITION: + values[0] = Source->Position[0]; + values[1] = Source->Position[1]; + values[2] = Source->Position[2]; + return AL_TRUE; + + case AL_VELOCITY: + values[0] = Source->Velocity[0]; + values[1] = Source->Velocity[1]; + values[2] = Source->Velocity[2]; + return AL_TRUE; + + case AL_DIRECTION: + values[0] = Source->Direction[0]; + values[1] = Source->Direction[1]; + values[2] = Source->Direction[2]; + return AL_TRUE; + + case AL_ORIENTATION: + values[0] = Source->Orientation[0][0]; + values[1] = Source->Orientation[0][1]; + values[2] = Source->Orientation[0][2]; + values[3] = Source->Orientation[1][0]; + values[4] = Source->Orientation[1][1]; + values[5] = Source->Orientation[1][2]; + return AL_TRUE; + + /* 1x int */ + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + 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_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_DISTANCE_MODEL: + if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE) + *values = (ALdouble)ivals[0]; + return err; + + case AL_BUFFER: + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; + } + + 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, SourceProp prop, ALint *values) +{ + ALbufferlistitem *BufferList; + ALdouble dvals[6]; + ALboolean err; + + switch(prop) + { + case AL_SOURCE_RELATIVE: + *values = Source->HeadRelative; + return AL_TRUE; + + case AL_LOOPING: + *values = ATOMIC_LOAD(&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 AL_BYTE_LENGTH_SOFT: + 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 AL_SAMPLE_LENGTH_SOFT: + 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(ATOMIC_LOAD(&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; + + /* 1x float/double */ + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_DOPPLER_FACTOR: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_SEC_LENGTH_SOFT: + case AL_SOURCE_RADIUS: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) + *values = (ALint)dvals[0]; + return err; + + /* 3x float/double */ + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) + { + values[0] = (ALint)dvals[0]; + values[1] = (ALint)dvals[1]; + values[2] = (ALint)dvals[2]; + } + return err; + + /* 6x float/double */ + case AL_ORIENTATION: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) + { + values[0] = (ALint)dvals[0]; + values[1] = (ALint)dvals[1]; + values[2] = (ALint)dvals[2]; + values[3] = (ALint)dvals[3]; + values[4] = (ALint)dvals[4]; + values[5] = (ALint)dvals[5]; + } + return err; + + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + break; /* i64 only */ + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ + case AL_STEREO_ANGLES: + break; /* Float/double only */ + + case AL_DIRECT_FILTER: + case AL_AUXILIARY_SEND_FILTER: + 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, SourceProp prop, ALint64 *values) +{ + ALCdevice *device = Context->Device; + ClockLatency clocktime; + ALuint64 srcclock; + ALdouble dvals[6]; + ALint ivals[3]; + ALboolean err; + + switch(prop) + { + case AL_SAMPLE_OFFSET_LATENCY_SOFT: + /* Get the source offset with the clock time first. Then get the + * clock time with the device latency. Order is important. + */ + values[0] = GetSourceSampleOffset(Source, device, &srcclock); + clocktime = V0(device->Backend,getClockLatency)(); + if(srcclock == (ALuint64)clocktime.ClockTime) + values[1] = clocktime.Latency; + else + { + /* If the clock time incremented, reduce the latency by that + * much since it's that much closer to the source offset it got + * earlier. + */ + ALuint64 diff = clocktime.ClockTime - srcclock; + values[1] = clocktime.Latency - minu64(clocktime.Latency, diff); + } + return AL_TRUE; + + /* 1x float/double */ + case AL_CONE_INNER_ANGLE: + case AL_CONE_OUTER_ANGLE: + case AL_PITCH: + case AL_GAIN: + case AL_MIN_GAIN: + case AL_MAX_GAIN: + case AL_REFERENCE_DISTANCE: + case AL_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAIN: + case AL_MAX_DISTANCE: + case AL_SEC_OFFSET: + case AL_SAMPLE_OFFSET: + case AL_BYTE_OFFSET: + case AL_DOPPLER_FACTOR: + case AL_AIR_ABSORPTION_FACTOR: + case AL_ROOM_ROLLOFF_FACTOR: + case AL_CONE_OUTER_GAINHF: + case AL_SEC_LENGTH_SOFT: + case AL_SOURCE_RADIUS: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) + *values = (ALint64)dvals[0]; + return err; + + /* 3x float/double */ + case AL_POSITION: + case AL_VELOCITY: + case AL_DIRECTION: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) + { + values[0] = (ALint64)dvals[0]; + values[1] = (ALint64)dvals[1]; + values[2] = (ALint64)dvals[2]; + } + return err; + + /* 6x float/double */ + case AL_ORIENTATION: + if((err=GetSourcedv(Source, Context, prop, dvals)) != AL_FALSE) + { + values[0] = (ALint64)dvals[0]; + values[1] = (ALint64)dvals[1]; + values[2] = (ALint64)dvals[2]; + values[3] = (ALint64)dvals[3]; + values[4] = (ALint64)dvals[4]; + values[5] = (ALint64)dvals[5]; + } + return err; + + /* 1x int */ + case AL_SOURCE_RELATIVE: + case AL_LOOPING: + case AL_SOURCE_STATE: + case AL_BUFFERS_QUEUED: + case AL_BUFFERS_PROCESSED: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + 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, prop, ivals)) != AL_FALSE) + *values = ivals[0]; + return err; + + /* 1x uint */ + case AL_BUFFER: + case AL_DIRECT_FILTER: + if((err=GetSourceiv(Source, Context, prop, ivals)) != AL_FALSE) + *values = (ALuint)ivals[0]; + return err; + + /* 3x uint */ + case AL_AUXILIARY_SEND_FILTER: + if((err=GetSourceiv(Source, Context, prop, ivals)) != AL_FALSE) + { + values[0] = (ALuint)ivals[0]; + values[1] = (ALuint)ivals[1]; + values[2] = (ALuint)ivals[2]; + } + return err; + + case AL_SEC_OFFSET_LATENCY_SOFT: + break; /* Double only */ + case AL_STEREO_ANGLES: + break; /* Float/double only */ + } + + 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; + ALsource *Source; + ALsizei i; + + context = GetContextRef(); + if(!context) return; + + LockSourcesWrite(context); + 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++) + { + ALvoice *voice, *voice_end; + + if((Source=RemoveSource(context, sources[i])) == NULL) + continue; + FreeThunkEntry(Source->id); + + LockContext(context); + voice = context->Voices; + voice_end = voice + context->VoiceCount; + while(voice != voice_end) + { + ALsource *old = Source; + if(COMPARE_EXCHANGE(&voice->Source, &old, NULL)) + break; + voice++; + } + UnlockContext(context); + + DeinitSource(Source); + + memset(Source, 0, sizeof(*Source)); + al_free(Source); + } + +done: + UnlockSourcesWrite(context); + ALCcontext_DecRef(context); +} + + +AL_API ALboolean AL_APIENTRY alIsSource(ALuint source) +{ + ALCcontext *context; + ALboolean ret; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + LockSourcesRead(context); + ret = (LookupSource(context, source) ? AL_TRUE : AL_FALSE); + UnlockSourcesRead(context); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + } + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + + +AL_API ALvoid AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + } + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + } + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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 <= 6)) + alSetError(Context, AL_INVALID_ENUM); + else + { + ALfloat fvals[6]; + ALint i; + + for(i = 0;i < count;i++) + fvals[i] = (ALfloat)values[i]; + SetSourcefv(Source, Context, param, fvals); + } + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + + +AL_API ALvoid AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + } + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + + +AL_API ALvoid AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + } + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + 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; + + WriteLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + WriteUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + + +AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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; + } + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + 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; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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]; + } + } + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + 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; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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 <= 6)) + alSetError(Context, AL_INVALID_ENUM); + else + { + ALdouble dvals[6]; + if(GetSourcedv(Source, Context, param, dvals)) + { + ALint i; + for(i = 0;i < count;i++) + values[i] = (ALfloat)dvals[i]; + } + } + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + + +AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + 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; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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]; + } + } + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + +AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + + +AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + 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; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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]; + } + } + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + + +AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + + +AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + 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; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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]; + } + } + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + ALCcontext_DecRef(Context); +} + +AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values) +{ + ALCcontext *Context; + ALsource *Source; + + Context = GetContextRef(); + if(!Context) return; + + ReadLock(&Context->PropLock); + LockSourcesRead(Context); + 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); + UnlockSourcesRead(Context); + ReadUnlock(&Context->PropLock); + + 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; + + LockSourcesRead(context); + 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->MaxVoices-context->VoiceCount) + { + ALvoice *temp = NULL; + ALsizei newcount; + + newcount = context->MaxVoices << 1; + if(newcount > 0) + temp = al_malloc(16, newcount * sizeof(context->Voices[0])); + if(!temp) + { + UnlockContext(context); + SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); + } + memcpy(temp, context->Voices, context->MaxVoices * sizeof(temp[0])); + memset(&temp[context->MaxVoices], 0, (newcount-context->MaxVoices) * sizeof(temp[0])); + + al_free(context->Voices); + context->Voices = temp; + context->MaxVoices = newcount; + } + + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) == DeferAll) + { + for(i = 0;i < n;i++) + { + source = LookupSource(context, sources[i]); + source->new_state = AL_PLAYING; + } + } + else + { + for(i = 0;i < n;i++) + { + source = LookupSource(context, sources[i]); + SetSourceState(source, context, AL_PLAYING); + } + } + UnlockContext(context); + +done: + UnlockSourcesRead(context); + 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; + + LockSourcesRead(context); + 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); + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + { + for(i = 0;i < n;i++) + { + source = LookupSource(context, sources[i]); + source->new_state = AL_PAUSED; + } + } + else + { + for(i = 0;i < n;i++) + { + source = LookupSource(context, sources[i]); + SetSourceState(source, context, AL_PAUSED); + } + } + UnlockContext(context); + +done: + UnlockSourcesRead(context); + 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; + + LockSourcesRead(context); + 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: + UnlockSourcesRead(context); + 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; + + LockSourcesRead(context); + 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: + UnlockSourcesRead(context); + 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; + + LockSourcesRead(context); + 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; + } + + LockBuffersRead(device); + 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)); + BufferList = BufferListStart; + } + else + { + BufferList->next = malloc(sizeof(ALbufferlistitem)); + BufferList = BufferList->next; + } + BufferList->buffer = buffer; + BufferList->next = NULL; + 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(BufferListStart) + { + ALbufferlistitem *next = BufferListStart->next; + if((buffer=BufferListStart->buffer) != NULL) + { + DecrementRef(&buffer->ref); + ReadUnlock(&buffer->lock); + } + free(BufferListStart); + BufferListStart = next; + } + UnlockBuffersRead(device); + goto done; + } + } + /* All buffers good, unlock them now. */ + BufferList = BufferListStart; + while(BufferList != NULL) + { + ALbuffer *buffer = BufferList->buffer; + if(buffer) ReadUnlock(&buffer->lock); + BufferList = BufferList->next; + } + UnlockBuffersRead(device); + + /* 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; + BufferList->next = BufferListStart; + } + /* If the current buffer was at the end (NULL), put it at the start of the newly queued + * buffers. + */ + BufferList = NULL; + ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->current_buffer, &BufferList, BufferListStart); + WriteUnlock(&source->queue_lock); + +done: + UnlockSourcesRead(context); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint *buffers) +{ + ALCcontext *context; + ALsource *source; + ALbufferlistitem *OldHead; + ALbufferlistitem *OldTail; + ALbufferlistitem *Current; + ALsizei i = 0; + + if(nb == 0) + return; + + context = GetContextRef(); + if(!context) return; + + LockSourcesRead(context); + 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(ATOMIC_LOAD(&source->looping) || source->SourceType != AL_STREAMING) + { + WriteUnlock(&source->queue_lock); + /* Trying to unqueue buffers on a looping or non-streaming source. */ + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + /* Find the new buffer queue head */ + OldTail = ATOMIC_LOAD(&source->queue); + Current = ATOMIC_LOAD(&source->current_buffer); + if(OldTail != Current) + { + for(i = 1;i < nb;i++) + { + ALbufferlistitem *next = OldTail->next; + if(!next || next == Current) break; + OldTail = next; + } + } + if(i != nb) + { + WriteUnlock(&source->queue_lock); + /* Trying to unqueue pending buffers. */ + 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, OldTail->next); + if(OldTail->next) + { + ALCdevice *device = context->Device; + uint count; + + /* Once the active mix (if any) is done, it's safe to cut the old tail + * from the new head. + */ + 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: + UnlockSourcesRead(context); + ALCcontext_DecRef(context); +} + + +static void 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->Velocity[0] = 0.0f; + Source->Velocity[1] = 0.0f; + Source->Velocity[2] = 0.0f; + Source->Direction[0] = 0.0f; + Source->Direction[1] = 0.0f; + Source->Direction[2] = 0.0f; + Source->Orientation[0][0] = 0.0f; + Source->Orientation[0][1] = 0.0f; + Source->Orientation[0][2] = -1.0f; + Source->Orientation[1][0] = 0.0f; + Source->Orientation[1][1] = 1.0f; + Source->Orientation[1][2] = 0.0f; + Source->RefDistance = 1.0f; + Source->MaxDistance = FLT_MAX; + Source->RollOffFactor = 1.0f; + 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->StereoPan[0] = DEG2RAD( 30.0f); + Source->StereoPan[1] = DEG2RAD(-30.0f); + + Source->Radius = 0.0f; + + Source->DistanceModel = DefaultDistanceModel; + + 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; + } + + Source->Offset = 0.0; + Source->OffsetType = AL_NONE; + Source->SourceType = AL_UNDETERMINED; + Source->state = AL_INITIAL; + Source->new_state = AL_NONE; + + ATOMIC_INIT(&Source->queue, NULL); + ATOMIC_INIT(&Source->current_buffer, NULL); + + ATOMIC_INIT(&Source->position, 0); + ATOMIC_INIT(&Source->position_fraction, 0); + + ATOMIC_INIT(&Source->looping, AL_FALSE); + + ATOMIC_INIT(&Source->Update, NULL); + ATOMIC_INIT(&Source->FreeList, NULL); +} + +static void DeinitSource(ALsource *source) +{ + ALbufferlistitem *BufferList; + struct ALsourceProps *props; + size_t count = 0; + size_t i; + + props = ATOMIC_LOAD(&source->Update); + if(props) al_free(props); + + props = ATOMIC_LOAD(&source->FreeList, almemory_order_relaxed); + while(props) + { + struct ALsourceProps *next; + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + al_free(props); + props = next; + ++count; + } + /* This is excessively spammy if it traces every source destruction, so + * just warn if it was unexpectedly large. + */ + if(count > 3) + WARN("Freed "SZFMT" Source property objects\n", count); + + 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(i = 0;i < MAX_SENDS;++i) + { + if(source->Send[i].Slot) + DecrementRef(&source->Send[i].Slot->ref); + source->Send[i].Slot = NULL; + } +} + +static void UpdateSourceProps(ALsource *source, ALuint num_sends) +{ + struct ALsourceProps *props; + size_t i; + + /* Get an unused property container, or allocate a new one as needed. */ + props = ATOMIC_LOAD(&source->FreeList, almemory_order_acquire); + if(!props) + props = al_calloc(16, sizeof(*props)); + else + { + struct ALsourceProps *next; + do { + next = ATOMIC_LOAD(&props->next, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*, + &source->FreeList, &props, next, almemory_order_seq_cst, + almemory_order_consume) == 0); + } + + /* Copy in current property values. */ + ATOMIC_STORE(&props->Pitch, source->Pitch, almemory_order_relaxed); + ATOMIC_STORE(&props->Gain, source->Gain, almemory_order_relaxed); + ATOMIC_STORE(&props->OuterGain, source->OuterGain, almemory_order_relaxed); + ATOMIC_STORE(&props->MinGain, source->MinGain, almemory_order_relaxed); + ATOMIC_STORE(&props->MaxGain, source->MaxGain, almemory_order_relaxed); + ATOMIC_STORE(&props->InnerAngle, source->InnerAngle, almemory_order_relaxed); + ATOMIC_STORE(&props->OuterAngle, source->OuterAngle, almemory_order_relaxed); + ATOMIC_STORE(&props->RefDistance, source->RefDistance, almemory_order_relaxed); + ATOMIC_STORE(&props->MaxDistance, source->MaxDistance, almemory_order_relaxed); + ATOMIC_STORE(&props->RollOffFactor, source->RollOffFactor, almemory_order_relaxed); + for(i = 0;i < 3;i++) + ATOMIC_STORE(&props->Position[i], source->Position[i], almemory_order_relaxed); + for(i = 0;i < 3;i++) + ATOMIC_STORE(&props->Velocity[i], source->Velocity[i], almemory_order_relaxed); + for(i = 0;i < 3;i++) + ATOMIC_STORE(&props->Direction[i], source->Direction[i], almemory_order_relaxed); + for(i = 0;i < 2;i++) + { + size_t j; + for(j = 0;j < 3;j++) + ATOMIC_STORE(&props->Orientation[i][j], source->Orientation[i][j], + almemory_order_relaxed); + } + ATOMIC_STORE(&props->HeadRelative, source->HeadRelative, almemory_order_relaxed); + ATOMIC_STORE(&props->DistanceModel, source->DistanceModel, almemory_order_relaxed); + ATOMIC_STORE(&props->DirectChannels, source->DirectChannels, almemory_order_relaxed); + + ATOMIC_STORE(&props->DryGainHFAuto, source->DryGainHFAuto, almemory_order_relaxed); + ATOMIC_STORE(&props->WetGainAuto, source->WetGainAuto, almemory_order_relaxed); + ATOMIC_STORE(&props->WetGainHFAuto, source->WetGainHFAuto, almemory_order_relaxed); + ATOMIC_STORE(&props->OuterGainHF, source->OuterGainHF, almemory_order_relaxed); + + ATOMIC_STORE(&props->AirAbsorptionFactor, source->AirAbsorptionFactor, almemory_order_relaxed); + ATOMIC_STORE(&props->RoomRolloffFactor, source->RoomRolloffFactor, almemory_order_relaxed); + ATOMIC_STORE(&props->DopplerFactor, source->DopplerFactor, almemory_order_relaxed); + + ATOMIC_STORE(&props->StereoPan[0], source->StereoPan[0], almemory_order_relaxed); + ATOMIC_STORE(&props->StereoPan[1], source->StereoPan[1], almemory_order_relaxed); + + ATOMIC_STORE(&props->Radius, source->Radius, almemory_order_relaxed); + + ATOMIC_STORE(&props->Direct.Gain, source->Direct.Gain, almemory_order_relaxed); + ATOMIC_STORE(&props->Direct.GainHF, source->Direct.GainHF, almemory_order_relaxed); + ATOMIC_STORE(&props->Direct.HFReference, source->Direct.HFReference, almemory_order_relaxed); + ATOMIC_STORE(&props->Direct.GainLF, source->Direct.GainLF, almemory_order_relaxed); + ATOMIC_STORE(&props->Direct.LFReference, source->Direct.LFReference, almemory_order_relaxed); + + for(i = 0;i < num_sends;i++) + { + ATOMIC_STORE(&props->Send[i].Slot, source->Send[i].Slot, almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].Gain, source->Send[i].Gain, almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].GainHF, source->Send[i].GainHF, almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].HFReference, source->Send[i].HFReference, + almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].GainLF, source->Send[i].GainLF, almemory_order_relaxed); + ATOMIC_STORE(&props->Send[i].LFReference, source->Send[i].LFReference, + almemory_order_relaxed); + } + + /* Set the new container for updating internal parameters. */ + props = ATOMIC_EXCHANGE(struct ALsourceProps*, &source->Update, props, almemory_order_acq_rel); + if(props) + { + /* If there was an unused update container, put it back in the + * freelist. + */ + struct ALsourceProps *first = ATOMIC_LOAD(&source->FreeList); + do { + ATOMIC_STORE(&props->next, first, almemory_order_relaxed); + } while(ATOMIC_COMPARE_EXCHANGE_WEAK(struct ALsourceProps*, + &source->FreeList, &first, props) == 0); + } +} + +void UpdateAllSourceProps(ALCcontext *context) +{ + ALuint num_sends = context->Device->NumAuxSends; + ALsizei pos; + + for(pos = 0;pos < context->VoiceCount;pos++) + { + ALvoice *voice = &context->Voices[pos]; + ALsource *source = voice->Source; + if(source != NULL && (source->state == AL_PLAYING || + source->state == AL_PAUSED)) + UpdateSourceProps(source, num_sends); + } +} + + +/* SetSourceState + * + * Sets the source's new play state given its current state. + */ +ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) +{ + WriteLock(&Source->queue_lock); + if(state == AL_PLAYING) + { + ALCdevice *device = Context->Device; + ALbufferlistitem *BufferList; + ALboolean discontinuity; + ALvoice *voice = NULL; + ALsizei i; + + /* 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; + ATOMIC_STORE(&Source->current_buffer, BufferList, almemory_order_relaxed); + ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed); + ATOMIC_STORE(&Source->position_fraction, 0); + discontinuity = AL_TRUE; + } + else + { + Source->state = AL_PLAYING; + discontinuity = AL_FALSE; + } + + // Check if an Offset has been set + if(Source->OffsetType != AL_NONE) + { + ApplyOffset(Source); + /* discontinuity = AL_TRUE;??? */ + } + + /* If there's nothing to play, or device is disconnected, go right to + * stopped */ + if(!BufferList || !device->Connected) + goto do_stop; + + /* Make sure this source isn't already active, while looking for an + * unused active source slot to put it in. */ + for(i = 0;i < Context->VoiceCount;i++) + { + ALsource *old = Source; + if(COMPARE_EXCHANGE(&Context->Voices[i].Source, &old, NULL)) + { + if(voice == NULL) + { + voice = &Context->Voices[i]; + voice->Source = Source; + } + break; + } + old = NULL; + if(voice == NULL && COMPARE_EXCHANGE(&Context->Voices[i].Source, &old, Source)) + voice = &Context->Voices[i]; + } + if(voice == NULL) + { + voice = &Context->Voices[Context->VoiceCount++]; + voice->Source = Source; + } + + if(discontinuity) + { + /* Clear previous samples if playback is discontinuous. */ + memset(voice->PrevSamples, 0, sizeof(voice->PrevSamples)); + + /* Clear the stepping value so the mixer knows not to mix this + * until the update gets applied. + */ + voice->Step = 0; + } + + voice->Moving = AL_FALSE; + for(i = 0;i < MAX_INPUT_CHANNELS;i++) + { + ALsizei j; + for(j = 0;j < HRTF_HISTORY_LENGTH;j++) + voice->Chan[i].Direct.Hrtf.State.History[j] = 0.0f; + for(j = 0;j < HRIR_LENGTH;j++) + { + voice->Chan[i].Direct.Hrtf.State.Values[j][0] = 0.0f; + voice->Chan[i].Direct.Hrtf.State.Values[j][1] = 0.0f; + } + } + + UpdateSourceProps(Source, device->NumAuxSends); + } + 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->OffsetType = AL_NONE; + Source->Offset = 0.0; + } + else if(state == AL_INITIAL) + { + if(Source->state != AL_INITIAL) + { + Source->state = AL_INITIAL; + ATOMIC_STORE(&Source->current_buffer, ATOMIC_LOAD(&Source->queue), + almemory_order_relaxed); + ATOMIC_STORE(&Source->position, 0, almemory_order_relaxed); + ATOMIC_STORE(&Source->position_fraction, 0); + } + Source->OffsetType = AL_NONE; + Source->Offset = 0.0; + } + WriteUnlock(&Source->queue_lock); +} + +/* GetSourceSampleOffset + * + * 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 GetSourceSampleOffset(ALsource *Source, ALCdevice *device, ALuint64 *clocktime) +{ + const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; + ALuint64 readPos; + ALuint refcount; + + ReadLock(&Source->queue_lock); + if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) + { + ReadUnlock(&Source->queue_lock); + do { + while(((refcount=ReadRef(&device->MixCount))&1)) + althrd_yield(); + *clocktime = GetDeviceClockTime(device); + } while(refcount != ReadRef(&device->MixCount)); + return 0; + } + + do { + while(((refcount=ReadRef(&device->MixCount))&1)) + althrd_yield(); + *clocktime = GetDeviceClockTime(device); + + BufferList = ATOMIC_LOAD(&Source->queue, almemory_order_relaxed); + Current = ATOMIC_LOAD(&Source->current_buffer, almemory_order_relaxed); + + readPos = (ALuint64)ATOMIC_LOAD(&Source->position, almemory_order_relaxed) << 32; + readPos |= (ALuint64)ATOMIC_LOAD(&Source->position_fraction, almemory_order_relaxed) << + (32-FRACTIONBITS); + } while(refcount != ReadRef(&device->MixCount)); + while(BufferList && BufferList != Current) + { + if(BufferList->buffer) + readPos += (ALuint64)BufferList->buffer->SampleLen << 32; + BufferList = BufferList->next; + } + + ReadUnlock(&Source->queue_lock); + 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(ALsource *Source, ALCdevice *device, ALuint64 *clocktime) +{ + const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; + const ALbuffer *Buffer = NULL; + ALuint64 readPos; + ALuint refcount; + + ReadLock(&Source->queue_lock); + if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) + { + ReadUnlock(&Source->queue_lock); + do { + while(((refcount=ReadRef(&device->MixCount))&1)) + althrd_yield(); + *clocktime = GetDeviceClockTime(device); + } while(refcount != ReadRef(&device->MixCount)); + return 0.0; + } + + do { + while(((refcount=ReadRef(&device->MixCount))&1)) + althrd_yield(); + *clocktime = GetDeviceClockTime(device); + + BufferList = ATOMIC_LOAD(&Source->queue, almemory_order_relaxed); + Current = ATOMIC_LOAD(&Source->current_buffer, almemory_order_relaxed); + + readPos = (ALuint64)ATOMIC_LOAD(&Source->position, almemory_order_relaxed)<position_fraction, almemory_order_relaxed); + } while(refcount != ReadRef(&device->MixCount)); + 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); + + ReadUnlock(&Source->queue_lock); + return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency; +} + +/* GetSourceOffset + * + * Gets the current read offset for the given Source, in the appropriate format + * (Bytes, Samples or Seconds). The offset is relative to the start of the + * queue (not the start of the current buffer). + */ +static ALdouble GetSourceOffset(ALsource *Source, ALenum name, ALCdevice *device) +{ + const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; + const ALbuffer *Buffer = NULL; + ALboolean readFin = AL_FALSE; + ALuint readPos, readPosFrac; + ALuint totalBufferLen; + ALdouble offset = 0.0; + ALboolean looping; + ALuint refcount; + + ReadLock(&Source->queue_lock); + if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) + { + ReadUnlock(&Source->queue_lock); + return 0.0; + } + + totalBufferLen = 0; + do { + while(((refcount=ReadRef(&device->MixCount))&1)) + althrd_yield(); + BufferList = ATOMIC_LOAD(&Source->queue, almemory_order_relaxed); + Current = ATOMIC_LOAD(&Source->current_buffer, almemory_order_relaxed); + + readPos = ATOMIC_LOAD(&Source->position, almemory_order_relaxed); + readPosFrac = ATOMIC_LOAD(&Source->position_fraction, almemory_order_relaxed); + + looping = ATOMIC_LOAD(&Source->looping, almemory_order_relaxed); + } while(refcount != ReadRef(&device->MixCount)); + + 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(looping) + readPos %= totalBufferLen; + else + { + /* Wrap back to 0 */ + if(readPos >= totalBufferLen) + readPos = readPosFrac = 0; + } + + switch(name) + { + case AL_SEC_OFFSET: + offset = (readPos + (ALdouble)readPosFrac/FRACTIONONE)/Buffer->Frequency; + break; + + case AL_SAMPLE_OFFSET: + offset = readPos + (ALdouble)readPosFrac/FRACTIONONE; + break; + + case AL_BYTE_OFFSET: + 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 = (ALdouble)(readPos / 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 = (ALdouble)(readPos / FrameBlockSize * BlockSize); + } + else + { + ALuint FrameSize = FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType); + offset = (ALdouble)(readPos * FrameSize); + } + break; + } + + ReadUnlock(&Source->queue_lock); + return offset; +} + + +/* 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; + ALuint bufferLen, totalBufferLen; + ALuint offset=0, frac=0; + + /* Get sample frame offset */ + if(!GetSampleOffset(Source, &offset, &frac)) + 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, almemory_order_relaxed); + + ATOMIC_STORE(&Source->position, offset - totalBufferLen, almemory_order_relaxed); + ATOMIC_STORE(&Source->position_fraction, frac); + return AL_TRUE; + } + + totalBufferLen += bufferLen; + + BufferList = BufferList->next; + } + + /* Offset is out of range of the queue */ + return AL_FALSE; +} + + +/* GetSampleOffset + * + * Retrieves 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 ALboolean GetSampleOffset(ALsource *Source, ALuint *offset, ALuint *frac) +{ + const ALbuffer *Buffer = NULL; + const ALbufferlistitem *BufferList; + ALdouble dbloff, dblfrac; + + /* 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->OffsetType = AL_NONE; + Source->Offset = 0.0; + return AL_FALSE; + } + + switch(Source->OffsetType) + { + case AL_BYTE_OFFSET: + /* Determine the ByteOffset (and ensure it is block aligned) */ + *offset = (ALuint)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); + *frac = 0; + break; + + case AL_SAMPLE_OFFSET: + dblfrac = modf(Source->Offset, &dbloff); + *offset = (ALuint)mind(dbloff, UINT_MAX); + *frac = (ALuint)mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0); + break; + + case AL_SEC_OFFSET: + dblfrac = modf(Source->Offset*Buffer->Frequency, &dbloff); + *offset = (ALuint)mind(dbloff, UINT_MAX); + *frac = (ALuint)mind(dblfrac*FRACTIONONE, FRACTIONONE-1.0); + break; + } + Source->OffsetType = AL_NONE; + Source->Offset = 0.0; + + return AL_TRUE; +} + + +/* ReleaseALSources + * + * Destroys all sources in the source map. + */ +ALvoid ReleaseALSources(ALCcontext *Context) +{ + ALsizei pos; + for(pos = 0;pos < Context->SourceMap.size;pos++) + { + ALsource *temp = Context->SourceMap.values[pos]; + Context->SourceMap.values[pos] = NULL; + + DeinitSource(temp); + + FreeThunkEntry(temp->id); + memset(temp, 0, sizeof(*temp)); + al_free(temp); + } +} diff --git a/Engine/lib/openal-soft/OpenAL32/alState.c b/Engine/lib/openal-soft/OpenAL32/alState.c new file mode 100644 index 000000000..3d8e6c404 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alState.c @@ -0,0 +1,687 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2000 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 +#include "alMain.h" +#include "AL/alc.h" +#include "AL/al.h" +#include "AL/alext.h" +#include "alError.h" +#include "alListener.h" +#include "alSource.h" +#include "alAuxEffectSlot.h" + +#include "backends/base.h" + + +static const ALchar alVendor[] = "OpenAL Community"; +static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION; +static const ALchar alRenderer[] = "OpenAL Soft"; + +// Error Messages +static const ALchar alNoError[] = "No Error"; +static const ALchar alErrInvalidName[] = "Invalid Name"; +static const ALchar alErrInvalidEnum[] = "Invalid Enum"; +static const ALchar alErrInvalidValue[] = "Invalid Value"; +static const ALchar alErrInvalidOp[] = "Invalid Operation"; +static const ALchar alErrOutOfMemory[] = "Out of Memory"; + +AL_API ALvoid AL_APIENTRY alEnable(ALenum capability) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + switch(capability) + { + case AL_SOURCE_DISTANCE_MODEL: + context->SourceDistanceModel = AL_TRUE; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + +done: + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alDisable(ALenum capability) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + WriteLock(&context->PropLock); + switch(capability) + { + case AL_SOURCE_DISTANCE_MODEL: + context->SourceDistanceModel = AL_FALSE; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + +done: + WriteUnlock(&context->PropLock); + ALCcontext_DecRef(context); +} + +AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability) +{ + ALCcontext *context; + ALboolean value=AL_FALSE; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + switch(capability) + { + case AL_SOURCE_DISTANCE_MODEL: + value = context->SourceDistanceModel; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); + + return value; +} + +AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname) +{ + ALCcontext *context; + ALboolean value=AL_FALSE; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + switch(pname) + { + case AL_DOPPLER_FACTOR: + if(context->DopplerFactor != 0.0f) + value = AL_TRUE; + break; + + case AL_DOPPLER_VELOCITY: + if(context->DopplerVelocity != 0.0f) + value = AL_TRUE; + break; + + case AL_DISTANCE_MODEL: + if(context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED) + value = AL_TRUE; + break; + + case AL_SPEED_OF_SOUND: + if(context->SpeedOfSound != 0.0f) + value = AL_TRUE; + break; + + case AL_DEFERRED_UPDATES_SOFT: + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) == DeferAll) + value = AL_TRUE; + break; + + case AL_GAIN_LIMIT_SOFT: + if(GAIN_MIX_MAX/context->GainBoost != 0.0f) + value = AL_TRUE; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); + + return value; +} + +AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname) +{ + ALCcontext *context; + ALdouble value = 0.0; + + context = GetContextRef(); + if(!context) return 0.0; + + switch(pname) + { + case AL_DOPPLER_FACTOR: + value = (ALdouble)context->DopplerFactor; + break; + + case AL_DOPPLER_VELOCITY: + value = (ALdouble)context->DopplerVelocity; + break; + + case AL_DISTANCE_MODEL: + value = (ALdouble)context->DistanceModel; + break; + + case AL_SPEED_OF_SOUND: + value = (ALdouble)context->SpeedOfSound; + break; + + case AL_DEFERRED_UPDATES_SOFT: + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) == DeferAll) + value = (ALdouble)AL_TRUE; + break; + + case AL_GAIN_LIMIT_SOFT: + value = (ALdouble)GAIN_MIX_MAX/context->GainBoost; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); + + return value; +} + +AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname) +{ + ALCcontext *context; + ALfloat value = 0.0f; + + context = GetContextRef(); + if(!context) return 0.0f; + + switch(pname) + { + case AL_DOPPLER_FACTOR: + value = context->DopplerFactor; + break; + + case AL_DOPPLER_VELOCITY: + value = context->DopplerVelocity; + break; + + case AL_DISTANCE_MODEL: + value = (ALfloat)context->DistanceModel; + break; + + case AL_SPEED_OF_SOUND: + value = context->SpeedOfSound; + break; + + case AL_DEFERRED_UPDATES_SOFT: + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) == DeferAll) + value = (ALfloat)AL_TRUE; + break; + + case AL_GAIN_LIMIT_SOFT: + value = GAIN_MIX_MAX/context->GainBoost; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); + + return value; +} + +AL_API ALint AL_APIENTRY alGetInteger(ALenum pname) +{ + ALCcontext *context; + ALint value = 0; + + context = GetContextRef(); + if(!context) return 0; + + switch(pname) + { + case AL_DOPPLER_FACTOR: + value = (ALint)context->DopplerFactor; + break; + + case AL_DOPPLER_VELOCITY: + value = (ALint)context->DopplerVelocity; + break; + + case AL_DISTANCE_MODEL: + value = (ALint)context->DistanceModel; + break; + + case AL_SPEED_OF_SOUND: + value = (ALint)context->SpeedOfSound; + break; + + case AL_DEFERRED_UPDATES_SOFT: + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) == DeferAll) + value = (ALint)AL_TRUE; + break; + + case AL_GAIN_LIMIT_SOFT: + value = (ALint)(GAIN_MIX_MAX/context->GainBoost); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); + + return value; +} + +AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname) +{ + ALCcontext *context; + ALint64SOFT value = 0; + + context = GetContextRef(); + if(!context) return 0; + + switch(pname) + { + case AL_DOPPLER_FACTOR: + value = (ALint64SOFT)context->DopplerFactor; + break; + + case AL_DOPPLER_VELOCITY: + value = (ALint64SOFT)context->DopplerVelocity; + break; + + case AL_DISTANCE_MODEL: + value = (ALint64SOFT)context->DistanceModel; + break; + + case AL_SPEED_OF_SOUND: + value = (ALint64SOFT)context->SpeedOfSound; + break; + + case AL_DEFERRED_UPDATES_SOFT: + if(ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire) == DeferAll) + value = (ALint64SOFT)AL_TRUE; + break; + + case AL_GAIN_LIMIT_SOFT: + value = (ALint64SOFT)(GAIN_MIX_MAX/context->GainBoost); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); + + return value; +} + +AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values) +{ + ALCcontext *context; + + if(values) + { + switch(pname) + { + case AL_DOPPLER_FACTOR: + case AL_DOPPLER_VELOCITY: + case AL_DISTANCE_MODEL: + case AL_SPEED_OF_SOUND: + case AL_DEFERRED_UPDATES_SOFT: + case AL_GAIN_LIMIT_SOFT: + values[0] = alGetBoolean(pname); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(pname) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values) +{ + ALCcontext *context; + + if(values) + { + switch(pname) + { + case AL_DOPPLER_FACTOR: + case AL_DOPPLER_VELOCITY: + case AL_DISTANCE_MODEL: + case AL_SPEED_OF_SOUND: + case AL_DEFERRED_UPDATES_SOFT: + case AL_GAIN_LIMIT_SOFT: + values[0] = alGetDouble(pname); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(pname) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values) +{ + ALCcontext *context; + + if(values) + { + switch(pname) + { + case AL_DOPPLER_FACTOR: + case AL_DOPPLER_VELOCITY: + case AL_DISTANCE_MODEL: + case AL_SPEED_OF_SOUND: + case AL_DEFERRED_UPDATES_SOFT: + case AL_GAIN_LIMIT_SOFT: + values[0] = alGetFloat(pname); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(pname) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values) +{ + ALCcontext *context; + + if(values) + { + switch(pname) + { + case AL_DOPPLER_FACTOR: + case AL_DOPPLER_VELOCITY: + case AL_DISTANCE_MODEL: + case AL_SPEED_OF_SOUND: + case AL_DEFERRED_UPDATES_SOFT: + case AL_GAIN_LIMIT_SOFT: + values[0] = alGetInteger(pname); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + switch(pname) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + +AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values) +{ + ALCcontext *context; + + if(values) + { + switch(pname) + { + case AL_DOPPLER_FACTOR: + case AL_DOPPLER_VELOCITY: + case AL_DISTANCE_MODEL: + case AL_SPEED_OF_SOUND: + case AL_DEFERRED_UPDATES_SOFT: + case AL_GAIN_LIMIT_SOFT: + values[0] = alGetInteger64SOFT(pname); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + switch(pname) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + +AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname) +{ + const ALchar *value = NULL; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return NULL; + + switch(pname) + { + case AL_VENDOR: + value = alVendor; + break; + + case AL_VERSION: + value = alVersion; + break; + + case AL_RENDERER: + value = alRenderer; + break; + + case AL_EXTENSIONS: + value = context->ExtensionList; + break; + + case AL_NO_ERROR: + value = alNoError; + break; + + case AL_INVALID_NAME: + value = alErrInvalidName; + break; + + case AL_INVALID_ENUM: + value = alErrInvalidEnum; + break; + + case AL_INVALID_VALUE: + value = alErrInvalidValue; + break; + + case AL_INVALID_OPERATION: + value = alErrInvalidOp; + break; + + case AL_OUT_OF_MEMORY: + value = alErrOutOfMemory; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); + + return value; +} + +AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + if(!(value >= 0.0f && isfinite(value))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + WriteLock(&context->PropLock); + context->DopplerFactor = value; + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + WriteUnlock(&context->PropLock); + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + if(!(value >= 0.0f && isfinite(value))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + WriteLock(&context->PropLock); + context->DopplerVelocity = value; + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + WriteUnlock(&context->PropLock); + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + if(!(value > 0.0f && isfinite(value))) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + WriteLock(&context->PropLock); + context->SpeedOfSound = value; + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + WriteUnlock(&context->PropLock); + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED || + value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED || + value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED || + value == AL_NONE)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + WriteLock(&context->PropLock); + context->DistanceModel = value; + if(!context->SourceDistanceModel) + { + if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) + UpdateListenerProps(context); + } + WriteUnlock(&context->PropLock); + +done: + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + ALCcontext_DeferUpdates(context, DeferAll); + + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void) +{ + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + ALCcontext_ProcessUpdates(context); + + ALCcontext_DecRef(context); +} diff --git a/Engine/lib/openal-soft/OpenAL32/alThunk.c b/Engine/lib/openal-soft/OpenAL32/alThunk.c new file mode 100644 index 000000000..72fc0dcbe --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/alThunk.c @@ -0,0 +1,105 @@ +/** + * 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 + +#include "alMain.h" +#include "alThunk.h" + +#include "almalloc.h" + + +static ATOMIC(ALenum) *ThunkArray; +static ALuint ThunkArraySize; +static RWLock ThunkLock; + +void ThunkInit(void) +{ + RWLockInit(&ThunkLock); + ThunkArraySize = 1024; + ThunkArray = al_calloc(16, ThunkArraySize * sizeof(*ThunkArray)); +} + +void ThunkExit(void) +{ + al_free(ThunkArray); + ThunkArray = NULL; + ThunkArraySize = 0; +} + +ALenum NewThunkEntry(ALuint *index) +{ + void *NewList; + ALuint i; + + ReadLock(&ThunkLock); + for(i = 0;i < ThunkArraySize;i++) + { + if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE) == AL_FALSE) + { + ReadUnlock(&ThunkLock); + *index = i+1; + return AL_NO_ERROR; + } + } + ReadUnlock(&ThunkLock); + + WriteLock(&ThunkLock); + /* Double-check that there's still no free entries, in case another + * invocation just came through and increased the size of the array. + */ + for(;i < ThunkArraySize;i++) + { + if(ATOMIC_EXCHANGE(ALenum, &ThunkArray[i], AL_TRUE) == AL_FALSE) + { + WriteUnlock(&ThunkLock); + *index = i+1; + return AL_NO_ERROR; + } + } + + NewList = al_calloc(16, ThunkArraySize*2 * sizeof(*ThunkArray)); + if(!NewList) + { + WriteUnlock(&ThunkLock); + ERR("Realloc failed to increase to %u entries!\n", ThunkArraySize*2); + return AL_OUT_OF_MEMORY; + } + memcpy(NewList, ThunkArray, ThunkArraySize*sizeof(*ThunkArray)); + al_free(ThunkArray); + ThunkArray = NewList; + ThunkArraySize *= 2; + + ATOMIC_STORE(&ThunkArray[i], AL_TRUE); + WriteUnlock(&ThunkLock); + + *index = i+1; + return AL_NO_ERROR; +} + +void FreeThunkEntry(ALuint index) +{ + ReadLock(&ThunkLock); + if(index > 0 && index <= ThunkArraySize) + ATOMIC_STORE(&ThunkArray[index-1], AL_FALSE); + ReadUnlock(&ThunkLock); +} diff --git a/Engine/lib/openal-soft/OpenAL32/sample_cvt.c b/Engine/lib/openal-soft/OpenAL32/sample_cvt.c new file mode 100644 index 000000000..aff3de834 --- /dev/null +++ b/Engine/lib/openal-soft/OpenAL32/sample_cvt.c @@ -0,0 +1,1112 @@ + +#include "config.h" + +#include "sample_cvt.h" + +#ifdef HAVE_ALLOCA_H +#include +#endif +#ifdef HAVE_MALLOC_H +#include +#endif + +#include "AL/al.h" +#include "alu.h" +#include "alBuffer.h" + + +/* IMA ADPCM Stepsize table */ +static const int IMAStep_size[89] = { + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, + 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, + 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, + 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, + 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, + 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, + 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442, + 11487,12635,13899,15289,16818,18500,20350,22358,24633,27086,29794, + 32767 +}; + +/* IMA4 ADPCM Codeword decode table */ +static const int IMA4Codeword[16] = { + 1, 3, 5, 7, 9, 11, 13, 15, + -1,-3,-5,-7,-9,-11,-13,-15, +}; + +/* IMA4 ADPCM Step index adjust decode table */ +static const int IMA4Index_adjust[16] = { + -1,-1,-1,-1, 2, 4, 6, 8, + -1,-1,-1,-1, 2, 4, 6, 8 +}; + + +/* MSADPCM Adaption table */ +static const int MSADPCMAdaption[16] = { + 230, 230, 230, 230, 307, 409, 512, 614, + 768, 614, 512, 409, 307, 230, 230, 230 +}; + +/* MSADPCM Adaption Coefficient tables */ +static const int MSADPCMAdaptionCoeff[7][2] = { + { 256, 0 }, + { 512, -256 }, + { 0, 0 }, + { 192, 64 }, + { 240, 0 }, + { 460, -208 }, + { 392, -232 } +}; + + +/* A quick'n'dirty lookup table to decode a muLaw-encoded byte sample into a + * signed 16-bit sample */ +static const ALshort muLawDecompressionTable[256] = { + -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956, + -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764, + -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412, + -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316, + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, + -876, -844, -812, -780, -748, -716, -684, -652, + -620, -588, -556, -524, -492, -460, -428, -396, + -372, -356, -340, -324, -308, -292, -276, -260, + -244, -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, -64, + -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, + 876, 844, 812, 780, 748, 716, 684, 652, + 620, 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, 260, + 244, 228, 212, 196, 180, 164, 148, 132, + 120, 112, 104, 96, 88, 80, 72, 64, + 56, 48, 40, 32, 24, 16, 8, 0 +}; + +/* Values used when encoding a muLaw sample */ +static const int muLawBias = 0x84; +static const int muLawClip = 32635; +static const char muLawCompressTable[256] = { + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + + +/* A quick'n'dirty lookup table to decode an aLaw-encoded byte sample into a + * signed 16-bit sample */ +static const ALshort aLawDecompressionTable[256] = { + -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944, + -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136, + -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472, + -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848, + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848 +}; + +/* Values used when encoding an aLaw sample */ +static const int aLawClip = 32635; +static const char aLawCompressTable[128] = { + 1,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + + +typedef ALubyte ALmulaw; +typedef ALubyte ALalaw; +typedef ALubyte ALima4; +typedef ALubyte ALmsadpcm; +typedef struct { + ALbyte b[3]; +} ALbyte3; +static_assert(sizeof(ALbyte3)==sizeof(ALbyte[3]), "ALbyte3 size is not 3"); +typedef struct { + ALubyte b[3]; +} ALubyte3; +static_assert(sizeof(ALubyte3)==sizeof(ALubyte[3]), "ALubyte3 size is not 3"); + +static inline ALshort DecodeMuLaw(ALmulaw val) +{ return muLawDecompressionTable[val]; } + +static ALmulaw EncodeMuLaw(ALshort val) +{ + ALint mant, exp, sign; + + sign = (val>>8) & 0x80; + if(sign) + { + /* -32768 doesn't properly negate on a short; it results in itself. + * So clamp to -32767 */ + val = maxi(val, -32767); + val = -val; + } + + val = mini(val, muLawClip); + val += muLawBias; + + exp = muLawCompressTable[(val>>7) & 0xff]; + mant = (val >> (exp+3)) & 0x0f; + + return ~(sign | (exp<<4) | mant); +} + +static inline ALshort DecodeALaw(ALalaw val) +{ return aLawDecompressionTable[val]; } + +static ALalaw EncodeALaw(ALshort val) +{ + ALint mant, exp, sign; + + sign = ((~val) >> 8) & 0x80; + if(!sign) + { + val = maxi(val, -32767); + val = -val; + } + val = mini(val, aLawClip); + + if(val >= 256) + { + exp = aLawCompressTable[(val>>8) & 0x7f]; + mant = (val >> (exp+3)) & 0x0f; + } + else + { + exp = 0; + mant = val >> 4; + } + + return ((exp<<4) | mant) ^ (sign^0x55); +} + +static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans, ALsizei align) +{ + ALint sample[MAX_INPUT_CHANNELS], index[MAX_INPUT_CHANNELS]; + ALuint code[MAX_INPUT_CHANNELS]; + ALsizei j,k,c; + + for(c = 0;c < numchans;c++) + { + sample[c] = *(src++); + sample[c] |= *(src++) << 8; + sample[c] = (sample[c]^0x8000) - 32768; + index[c] = *(src++); + index[c] |= *(src++) << 8; + index[c] = (index[c]^0x8000) - 32768; + + index[c] = clampi(index[c], 0, 88); + + dst[c] = sample[c]; + } + + for(j = 1;j < align;j += 8) + { + for(c = 0;c < numchans;c++) + { + code[c] = *(src++); + code[c] |= *(src++) << 8; + code[c] |= *(src++) << 16; + code[c] |= *(src++) << 24; + } + + for(k = 0;k < 8;k++) + { + for(c = 0;c < numchans;c++) + { + int nibble = code[c]&0xf; + code[c] >>= 4; + + sample[c] += IMA4Codeword[nibble] * IMAStep_size[index[c]] / 8; + sample[c] = clampi(sample[c], -32768, 32767); + + index[c] += IMA4Index_adjust[nibble]; + index[c] = clampi(index[c], 0, 88); + + dst[(j+k)*numchans + c] = sample[c]; + } + } + } +} + +static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALint *index, ALint numchans, ALsizei align) +{ + ALsizei j,k,c; + + for(c = 0;c < numchans;c++) + { + int diff = src[c] - sample[c]; + int step = IMAStep_size[index[c]]; + int nibble; + + nibble = 0; + if(diff < 0) + { + nibble = 0x8; + diff = -diff; + } + + diff = mini(step*2, diff); + nibble |= (diff*8/step - 1) / 2; + + sample[c] += IMA4Codeword[nibble] * step / 8; + sample[c] = clampi(sample[c], -32768, 32767); + + index[c] += IMA4Index_adjust[nibble]; + index[c] = clampi(index[c], 0, 88); + + *(dst++) = sample[c] & 0xff; + *(dst++) = (sample[c]>>8) & 0xff; + *(dst++) = index[c] & 0xff; + *(dst++) = (index[c]>>8) & 0xff; + } + + for(j = 1;j < align;j += 8) + { + for(c = 0;c < numchans;c++) + { + for(k = 0;k < 8;k++) + { + int diff = src[(j+k)*numchans + c] - sample[c]; + int step = IMAStep_size[index[c]]; + int nibble; + + nibble = 0; + if(diff < 0) + { + nibble = 0x8; + diff = -diff; + } + + diff = mini(step*2, diff); + nibble |= (diff*8/step - 1) / 2; + + sample[c] += IMA4Codeword[nibble] * step / 8; + sample[c] = clampi(sample[c], -32768, 32767); + + index[c] += IMA4Index_adjust[nibble]; + index[c] = clampi(index[c], 0, 88); + + if(!(k&1)) *dst = nibble; + else *(dst++) |= nibble<<4; + } + } + } +} + + +static void DecodeMSADPCMBlock(ALshort *dst, const ALmsadpcm *src, ALint numchans, ALsizei align) +{ + ALubyte blockpred[MAX_INPUT_CHANNELS]; + ALint delta[MAX_INPUT_CHANNELS]; + ALshort samples[MAX_INPUT_CHANNELS][2]; + ALint i, j; + + for(i = 0;i < numchans;i++) + { + blockpred[i] = *(src++); + blockpred[i] = minu(blockpred[i], 6); + } + for(i = 0;i < numchans;i++) + { + delta[i] = *(src++); + delta[i] |= *(src++) << 8; + delta[i] = (delta[i]^0x8000) - 0x8000; + } + for(i = 0;i < numchans;i++) + { + samples[i][0] = *(src++); + samples[i][0] |= *(src++) << 8; + samples[i][0] = (samples[i][0]^0x8000) - 0x8000; + } + for(i = 0;i < numchans;i++) + { + samples[i][1] = *(src++); + samples[i][1] |= *(src++) << 8; + samples[i][1] = (samples[i][1]^0x8000) - 0x8000; + } + + /* Second sample is written first. */ + for(i = 0;i < numchans;i++) + *(dst++) = samples[i][1]; + for(i = 0;i < numchans;i++) + *(dst++) = samples[i][0]; + + for(j = 2;j < align;j++) + { + for(i = 0;i < numchans;i++) + { + const ALint num = (j*numchans) + i; + ALint nibble, pred; + + /* Read the nibble (first is in the upper bits). */ + if(!(num&1)) + nibble = (*src>>4)&0x0f; + else + nibble = (*(src++))&0x0f; + + pred = (samples[i][0]*MSADPCMAdaptionCoeff[blockpred[i]][0] + + samples[i][1]*MSADPCMAdaptionCoeff[blockpred[i]][1]) / 256; + pred += ((nibble^0x08) - 0x08) * delta[i]; + pred = clampi(pred, -32768, 32767); + + samples[i][1] = samples[i][0]; + samples[i][0] = pred; + + delta[i] = (MSADPCMAdaption[nibble] * delta[i]) / 256; + delta[i] = maxi(16, delta[i]); + + *(dst++) = pred; + } + } +} + +/* NOTE: This encoder is pretty dumb/simplistic. Some kind of pre-processing + * that tries to find the optimal block predictors would be nice, at least. A + * multi-pass method that can generate better deltas would be good, too. */ +static void EncodeMSADPCMBlock(ALmsadpcm *dst, const ALshort *src, ALint *sample, ALint numchans, ALsizei align) +{ + ALubyte blockpred[MAX_INPUT_CHANNELS]; + ALint delta[MAX_INPUT_CHANNELS]; + ALshort samples[MAX_INPUT_CHANNELS][2]; + ALint i, j; + + /* Block predictor */ + for(i = 0;i < numchans;i++) + { + /* FIXME: Calculate something better. */ + blockpred[i] = 0; + *(dst++) = blockpred[i]; + } + /* Initial delta */ + for(i = 0;i < numchans;i++) + { + delta[i] = 16; + *(dst++) = (delta[i] ) & 0xff; + *(dst++) = (delta[i]>>8) & 0xff; + } + /* Initial sample 1 */ + for(i = 0;i < numchans;i++) + { + samples[i][0] = src[1*numchans + i]; + *(dst++) = (samples[i][0] ) & 0xff; + *(dst++) = (samples[i][0]>>8) & 0xff; + } + /* Initial sample 2 */ + for(i = 0;i < numchans;i++) + { + samples[i][1] = src[i]; + *(dst++) = (samples[i][1] ) & 0xff; + *(dst++) = (samples[i][1]>>8) & 0xff; + } + + for(j = 2;j < align;j++) + { + for(i = 0;i < numchans;i++) + { + const ALint num = (j*numchans) + i; + ALint nibble = 0; + ALint bias; + + sample[i] = (samples[i][0]*MSADPCMAdaptionCoeff[blockpred[i]][0] + + samples[i][1]*MSADPCMAdaptionCoeff[blockpred[i]][1]) / 256; + + nibble = src[num] - sample[i]; + if(nibble >= 0) + bias = delta[i] / 2; + else + bias = -delta[i] / 2; + + nibble = (nibble + bias) / delta[i]; + nibble = clampi(nibble, -8, 7)&0x0f; + + sample[i] += ((nibble^0x08)-0x08) * delta[i]; + sample[i] = clampi(sample[i], -32768, 32767); + + samples[i][1] = samples[i][0]; + samples[i][0] = sample[i]; + + delta[i] = (MSADPCMAdaption[nibble] * delta[i]) / 256; + delta[i] = maxi(16, delta[i]); + + if(!(num&1)) + *dst = nibble << 4; + else + { + *dst |= nibble; + dst++; + } + } + } +} + + +static inline ALint DecodeByte3(ALbyte3 val) +{ + if(IS_LITTLE_ENDIAN) + return (val.b[2]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[0]); + return (val.b[0]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[2]); +} + +static inline ALbyte3 EncodeByte3(ALint val) +{ + if(IS_LITTLE_ENDIAN) + { + ALbyte3 ret = {{ val, val>>8, val>>16 }}; + return ret; + } + else + { + ALbyte3 ret = {{ val>>16, val>>8, val }}; + return ret; + } +} + +static inline ALint DecodeUByte3(ALubyte3 val) +{ + if(IS_LITTLE_ENDIAN) + return (val.b[2]<<16) | (val.b[1]<<8) | (val.b[0]); + return (val.b[0]<<16) | (val.b[1]<<8) | val.b[2]; +} + +static inline ALubyte3 EncodeUByte3(ALint val) +{ + if(IS_LITTLE_ENDIAN) + { + ALubyte3 ret = {{ val, val>>8, val>>16 }}; + return ret; + } + else + { + ALubyte3 ret = {{ val>>16, val>>8, val }}; + return ret; + } +} + + +/* Define same-type pass-through sample conversion functions (excludes ADPCM, + * which are block-based). */ +#define DECL_TEMPLATE(T) \ +static inline T Conv_##T##_##T(T val) { return val; } + +DECL_TEMPLATE(ALbyte); +DECL_TEMPLATE(ALubyte); +DECL_TEMPLATE(ALshort); +DECL_TEMPLATE(ALushort); +DECL_TEMPLATE(ALint); +DECL_TEMPLATE(ALuint); +DECL_TEMPLATE(ALbyte3); +DECL_TEMPLATE(ALubyte3); +DECL_TEMPLATE(ALalaw); +DECL_TEMPLATE(ALmulaw); + +/* Slightly special handling for floats and doubles (converts NaN to 0, and + * allows float<->double pass-through). + */ +static inline ALfloat Conv_ALfloat_ALfloat(ALfloat val) +{ return (val==val) ? val : 0.0f; } +static inline ALfloat Conv_ALfloat_ALdouble(ALdouble val) +{ return (val==val) ? (ALfloat)val : 0.0f; } +static inline ALdouble Conv_ALdouble_ALfloat(ALfloat val) +{ return (val==val) ? (ALdouble)val : 0.0; } +static inline ALdouble Conv_ALdouble_ALdouble(ALdouble val) +{ return (val==val) ? val : 0.0; } + +#undef DECL_TEMPLATE + +/* Define alternate-sign functions. */ +#define DECL_TEMPLATE(T1, T2, O) \ +static inline T1 Conv_##T1##_##T2(T2 val) { return (T1)val - O; } \ +static inline T2 Conv_##T2##_##T1(T1 val) { return (T2)val + O; } + +DECL_TEMPLATE(ALbyte, ALubyte, 128); +DECL_TEMPLATE(ALshort, ALushort, 32768); +DECL_TEMPLATE(ALint, ALuint, 2147483648u); + +#undef DECL_TEMPLATE + +/* Define int-type to int-type functions */ +#define DECL_TEMPLATE(T, ST, UT, SH) \ +static inline T Conv_##T##_##ST(ST val){ return val >> SH; } \ +static inline T Conv_##T##_##UT(UT val){ return Conv_##ST##_##UT(val) >> SH; }\ +static inline ST Conv_##ST##_##T(T val){ return val << SH; } \ +static inline UT Conv_##UT##_##T(T val){ return Conv_##UT##_##ST(val << SH); } + +#define DECL_TEMPLATE2(T1, T2, SH) \ +DECL_TEMPLATE(AL##T1, AL##T2, ALu##T2, SH) \ +DECL_TEMPLATE(ALu##T1, ALu##T2, AL##T2, SH) + +DECL_TEMPLATE2(byte, short, 8) +DECL_TEMPLATE2(short, int, 16) +DECL_TEMPLATE2(byte, int, 24) + +#undef DECL_TEMPLATE2 +#undef DECL_TEMPLATE + +/* Define int-type to fp functions */ +#define DECL_TEMPLATE(T, ST, UT, OP) \ +static inline T Conv_##T##_##ST(ST val) { return (T)val * OP; } \ +static inline T Conv_##T##_##UT(UT val) { return (T)Conv_##ST##_##UT(val) * OP; } + +#define DECL_TEMPLATE2(T1, T2, OP) \ +DECL_TEMPLATE(T1, AL##T2, ALu##T2, OP) + +DECL_TEMPLATE2(ALfloat, byte, (1.0f/127.0f)) +DECL_TEMPLATE2(ALdouble, byte, (1.0/127.0)) +DECL_TEMPLATE2(ALfloat, short, (1.0f/32767.0f)) +DECL_TEMPLATE2(ALdouble, short, (1.0/32767.0)) +DECL_TEMPLATE2(ALdouble, int, (1.0/2147483647.0)) + +/* Special handling for int32 to float32, since it would overflow. */ +static inline ALfloat Conv_ALfloat_ALint(ALint val) +{ return (ALfloat)(val>>7) * (1.0f/16777215.0f); } +static inline ALfloat Conv_ALfloat_ALuint(ALuint val) +{ return (ALfloat)(Conv_ALint_ALuint(val)>>7) * (1.0f/16777215.0f); } + +#undef DECL_TEMPLATE2 +#undef DECL_TEMPLATE + +/* Define fp to int-type functions */ +#define DECL_TEMPLATE(FT, T, smin, smax) \ +static inline AL##T Conv_AL##T##_##FT(FT val) \ +{ \ + if(val > 1.0f) return smax; \ + if(val < -1.0f) return smin; \ + return (AL##T)(val * (FT)smax); \ +} \ +static inline ALu##T Conv_ALu##T##_##FT(FT val) \ +{ return Conv_ALu##T##_AL##T(Conv_AL##T##_##FT(val)); } + +DECL_TEMPLATE(ALfloat, byte, -128, 127) +DECL_TEMPLATE(ALdouble, byte, -128, 127) +DECL_TEMPLATE(ALfloat, short, -32768, 32767) +DECL_TEMPLATE(ALdouble, short, -32768, 32767) +DECL_TEMPLATE(ALdouble, int, -2147483647-1, 2147483647) + +/* Special handling for float32 to int32, since it would overflow. */ +static inline ALint Conv_ALint_ALfloat(ALfloat val) +{ + if(val > 1.0f) return 2147483647; + if(val < -1.0f) return -2147483647-1; + return (ALint)(val * 16777215.0f) << 7; +} +static inline ALuint Conv_ALuint_ALfloat(ALfloat val) +{ return Conv_ALuint_ALint(Conv_ALint_ALfloat(val)); } + +#undef DECL_TEMPLATE + +/* Define byte3 and ubyte3 functions (goes through int and uint functions). */ +#define DECL_TEMPLATE(T) \ +static inline ALbyte3 Conv_ALbyte3_##T(T val) \ +{ return EncodeByte3(Conv_ALint_##T(val)>>8); } \ +static inline T Conv_##T##_ALbyte3(ALbyte3 val) \ +{ return Conv_##T##_ALint(DecodeByte3(val)<<8); } \ + \ +static inline ALubyte3 Conv_ALubyte3_##T(T val) \ +{ return EncodeUByte3(Conv_ALuint_##T(val)>>8); } \ +static inline T Conv_##T##_ALubyte3(ALubyte3 val) \ +{ return Conv_##T##_ALuint(DecodeUByte3(val)<<8); } + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +DECL_TEMPLATE(ALshort) +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) + +#undef DECL_TEMPLATE + +/* Define byte3 <-> ubyte3 functions. */ +static inline ALbyte3 Conv_ALbyte3_ALubyte3(ALubyte3 val) +{ return EncodeByte3(DecodeUByte3(val)-8388608); } +static inline ALubyte3 Conv_ALubyte3_ALbyte3(ALbyte3 val) +{ return EncodeUByte3(DecodeByte3(val)+8388608); } + +/* Define muLaw and aLaw functions (goes through short functions). */ +#define DECL_TEMPLATE(T) \ +static inline ALmulaw Conv_ALmulaw_##T(T val) \ +{ return EncodeMuLaw(Conv_ALshort_##T(val)); } \ +static inline T Conv_##T##_ALmulaw(ALmulaw val) \ +{ return Conv_##T##_ALshort(DecodeMuLaw(val)); } \ + \ +static inline ALalaw Conv_ALalaw_##T(T val) \ +{ return EncodeALaw(Conv_ALshort_##T(val)); } \ +static inline T Conv_##T##_ALalaw(ALalaw val) \ +{ return Conv_##T##_ALshort(DecodeALaw(val)); } + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +DECL_TEMPLATE(ALshort) +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +/* Define muLaw <-> aLaw functions. */ +static inline ALalaw Conv_ALalaw_ALmulaw(ALmulaw val) +{ return EncodeALaw(DecodeMuLaw(val)); } +static inline ALmulaw Conv_ALmulaw_ALalaw(ALalaw val) +{ return EncodeMuLaw(DecodeALaw(val)); } + + +#define DECL_TEMPLATE(T1, T2) \ +static void Convert_##T1##_##T2(T1 *dst, const T2 *src, ALuint numchans, \ + ALuint len, ALsizei UNUSED(align)) \ +{ \ + ALuint i, j; \ + for(i = 0;i < len;i++) \ + { \ + for(j = 0;j < numchans;j++) \ + *(dst++) = Conv_##T1##_##T2(*(src++)); \ + } \ +} + +#define DECL_TEMPLATE2(T) \ +DECL_TEMPLATE(T, ALbyte) \ +DECL_TEMPLATE(T, ALubyte) \ +DECL_TEMPLATE(T, ALshort) \ +DECL_TEMPLATE(T, ALushort) \ +DECL_TEMPLATE(T, ALint) \ +DECL_TEMPLATE(T, ALuint) \ +DECL_TEMPLATE(T, ALfloat) \ +DECL_TEMPLATE(T, ALdouble) \ +DECL_TEMPLATE(T, ALmulaw) \ +DECL_TEMPLATE(T, ALalaw) \ +DECL_TEMPLATE(T, ALbyte3) \ +DECL_TEMPLATE(T, ALubyte3) + +DECL_TEMPLATE2(ALbyte) +DECL_TEMPLATE2(ALubyte) +DECL_TEMPLATE2(ALshort) +DECL_TEMPLATE2(ALushort) +DECL_TEMPLATE2(ALint) +DECL_TEMPLATE2(ALuint) +DECL_TEMPLATE2(ALfloat) +DECL_TEMPLATE2(ALdouble) +DECL_TEMPLATE2(ALmulaw) +DECL_TEMPLATE2(ALalaw) +DECL_TEMPLATE2(ALbyte3) +DECL_TEMPLATE2(ALubyte3) + +#undef DECL_TEMPLATE2 +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \ + ALuint len, ALuint align) \ +{ \ + ALsizei byte_align = ((align-1)/2 + 4) * numchans; \ + DECL_VLA(ALshort, tmp, align*numchans); \ + ALuint i, j, k; \ + \ + assert(align > 0 && (len%align) == 0); \ + for(i = 0;i < len;i += align) \ + { \ + DecodeIMA4Block(tmp, src, numchans, align); \ + src += byte_align; \ + \ + for(j = 0;j < align;j++) \ + { \ + for(k = 0;k < numchans;k++) \ + *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]); \ + } \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +static void Convert_ALshort_ALima4(ALshort *dst, const ALima4 *src, ALuint numchans, + ALuint len, ALuint align) +{ + ALsizei byte_align = ((align-1)/2 + 4) * numchans; + ALuint i; + + assert(align > 0 && (len%align) == 0); + for(i = 0;i < len;i += align) + { + DecodeIMA4Block(dst, src, numchans, align); + src += byte_align; + dst += align*numchans; + } +} +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \ + ALuint len, ALuint align) \ +{ \ + ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; \ + ALint index[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; \ + ALsizei byte_align = ((align-1)/2 + 4) * numchans; \ + DECL_VLA(ALshort, tmp, align*numchans); \ + ALuint i, j, k; \ + \ + assert(align > 0 && (len%align) == 0); \ + for(i = 0;i < len;i += align) \ + { \ + for(j = 0;j < align;j++) \ + { \ + for(k = 0;k < numchans;k++) \ + tmp[j*numchans + k] = Conv_ALshort_##T(*(src++)); \ + } \ + EncodeIMA4Block(dst, tmp, sample, index, numchans, align); \ + dst += byte_align; \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +static void Convert_ALima4_ALshort(ALima4 *dst, const ALshort *src, + ALuint numchans, ALuint len, ALuint align) +{ + ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; + ALint index[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; + ALsizei byte_align = ((align-1)/2 + 4) * numchans; + ALuint i; + + assert(align > 0 && (len%align) == 0); + for(i = 0;i < len;i += align) + { + EncodeIMA4Block(dst, src, sample, index, numchans, align); + src += align*numchans; + dst += byte_align; + } +} +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + + +#define DECL_TEMPLATE(T) \ +static void Convert_##T##_ALmsadpcm(T *dst, const ALmsadpcm *src, \ + ALuint numchans, ALuint len, \ + ALuint align) \ +{ \ + ALsizei byte_align = ((align-2)/2 + 7) * numchans; \ + DECL_VLA(ALshort, tmp, align*numchans); \ + ALuint i, j, k; \ + \ + assert(align > 1 && (len%align) == 0); \ + for(i = 0;i < len;i += align) \ + { \ + DecodeMSADPCMBlock(tmp, src, numchans, align); \ + src += byte_align; \ + \ + for(j = 0;j < align;j++) \ + { \ + for(k = 0;k < numchans;k++) \ + *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]); \ + } \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +static void Convert_ALshort_ALmsadpcm(ALshort *dst, const ALmsadpcm *src, + ALuint numchans, ALuint len, + ALuint align) +{ + ALsizei byte_align = ((align-2)/2 + 7) * numchans; + ALuint i; + + assert(align > 1 && (len%align) == 0); + for(i = 0;i < len;i += align) + { + DecodeMSADPCMBlock(dst, src, numchans, align); + src += byte_align; + dst += align*numchans; + } +} +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static void Convert_ALmsadpcm_##T(ALmsadpcm *dst, const T *src, \ + ALuint numchans, ALuint len, ALuint align) \ +{ \ + ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; \ + ALsizei byte_align = ((align-2)/2 + 7) * numchans; \ + DECL_VLA(ALshort, tmp, align*numchans); \ + ALuint i, j, k; \ + \ + assert(align > 1 && (len%align) == 0); \ + for(i = 0;i < len;i += align) \ + { \ + for(j = 0;j < align;j++) \ + { \ + for(k = 0;k < numchans;k++) \ + tmp[j*numchans + k] = Conv_ALshort_##T(*(src++)); \ + } \ + EncodeMSADPCMBlock(dst, tmp, sample, numchans, align); \ + dst += byte_align; \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +static void Convert_ALmsadpcm_ALshort(ALmsadpcm *dst, const ALshort *src, + ALuint numchans, ALuint len, ALuint align) +{ + ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; + ALsizei byte_align = ((align-2)/2 + 7) * numchans; + ALuint i; + + assert(align > 1 && (len%align) == 0); + for(i = 0;i < len;i += align) + { + EncodeMSADPCMBlock(dst, src, sample, numchans, align); + src += align*numchans; + dst += byte_align; + } +} +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +/* NOTE: We don't store compressed samples internally, so these conversions + * should never happen. */ +static void Convert_ALima4_ALima4(ALima4* UNUSED(dst), const ALima4* UNUSED(src), + ALuint UNUSED(numchans), ALuint UNUSED(len), + ALuint UNUSED(align)) +{ + ERR("Unexpected IMA4-to-IMA4 conversion!\n"); +} + +static void Convert_ALmsadpcm_ALmsadpcm(ALmsadpcm* UNUSED(dst), const ALmsadpcm* UNUSED(src), + ALuint UNUSED(numchans), ALuint UNUSED(len), + ALuint UNUSED(align)) +{ + ERR("Unexpected MSADPCM-to-MSADPCM conversion!\n"); +} + +static void Convert_ALmsadpcm_ALima4(ALmsadpcm* UNUSED(dst), const ALima4* UNUSED(src), + ALuint UNUSED(numchans), ALuint UNUSED(len), + ALuint UNUSED(align)) +{ + ERR("Unexpected IMA4-to-MSADPCM conversion!\n"); +} + +static void Convert_ALima4_ALmsadpcm(ALima4* UNUSED(dst), const ALmsadpcm* UNUSED(src), + ALuint UNUSED(numchans), ALuint UNUSED(len), + ALuint UNUSED(align)) +{ + ERR("Unexpected MSADPCM-to-IMA4 conversion!\n"); +} + + +#define DECL_TEMPLATE(T) \ +static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType, \ + ALsizei numchans, ALsizei len, ALsizei align) \ +{ \ + switch(srcType) \ + { \ + case UserFmtByte: \ + Convert_##T##_ALbyte(dst, src, numchans, len, align); \ + break; \ + case UserFmtUByte: \ + Convert_##T##_ALubyte(dst, src, numchans, len, align); \ + break; \ + case UserFmtShort: \ + Convert_##T##_ALshort(dst, src, numchans, len, align); \ + break; \ + case UserFmtUShort: \ + Convert_##T##_ALushort(dst, src, numchans, len, align); \ + break; \ + case UserFmtInt: \ + Convert_##T##_ALint(dst, src, numchans, len, align); \ + break; \ + case UserFmtUInt: \ + Convert_##T##_ALuint(dst, src, numchans, len, align); \ + break; \ + case UserFmtFloat: \ + Convert_##T##_ALfloat(dst, src, numchans, len, align); \ + break; \ + case UserFmtDouble: \ + Convert_##T##_ALdouble(dst, src, numchans, len, align); \ + break; \ + case UserFmtMulaw: \ + Convert_##T##_ALmulaw(dst, src, numchans, len, align); \ + break; \ + case UserFmtAlaw: \ + Convert_##T##_ALalaw(dst, src, numchans, len, align); \ + break; \ + case UserFmtIMA4: \ + Convert_##T##_ALima4(dst, src, numchans, len, align); \ + break; \ + case UserFmtMSADPCM: \ + Convert_##T##_ALmsadpcm(dst, src, numchans, len, align); \ + break; \ + case UserFmtByte3: \ + Convert_##T##_ALbyte3(dst, src, numchans, len, align); \ + break; \ + case UserFmtUByte3: \ + Convert_##T##_ALubyte3(dst, src, numchans, len, align); \ + break; \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +DECL_TEMPLATE(ALshort) +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALima4) +DECL_TEMPLATE(ALmsadpcm) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + + +void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align) +{ + switch(dstType) + { + case UserFmtByte: + Convert_ALbyte(dst, src, srcType, numchans, len, align); + break; + case UserFmtUByte: + Convert_ALubyte(dst, src, srcType, numchans, len, align); + break; + case UserFmtShort: + Convert_ALshort(dst, src, srcType, numchans, len, align); + break; + case UserFmtUShort: + Convert_ALushort(dst, src, srcType, numchans, len, align); + break; + case UserFmtInt: + Convert_ALint(dst, src, srcType, numchans, len, align); + break; + case UserFmtUInt: + Convert_ALuint(dst, src, srcType, numchans, len, align); + break; + case UserFmtFloat: + Convert_ALfloat(dst, src, srcType, numchans, len, align); + break; + case UserFmtDouble: + Convert_ALdouble(dst, src, srcType, numchans, len, align); + break; + case UserFmtMulaw: + Convert_ALmulaw(dst, src, srcType, numchans, len, align); + break; + case UserFmtAlaw: + Convert_ALalaw(dst, src, srcType, numchans, len, align); + break; + case UserFmtIMA4: + Convert_ALima4(dst, src, srcType, numchans, len, align); + break; + case UserFmtMSADPCM: + Convert_ALmsadpcm(dst, src, srcType, numchans, len, align); + break; + case UserFmtByte3: + Convert_ALbyte3(dst, src, srcType, numchans, len, align); + break; + case UserFmtUByte3: + Convert_ALubyte3(dst, src, srcType, numchans, len, align); + break; + } +} diff --git a/Engine/lib/openal-soft/README b/Engine/lib/openal-soft/README new file mode 100644 index 000000000..a0178ae5e --- /dev/null +++ b/Engine/lib/openal-soft/README @@ -0,0 +1,55 @@ +Source Install +============== + +To install OpenAL Soft, use your favorite shell to go into the build/ +directory, and run: + +cmake .. + +Assuming configuration went well, you can then build it, typically using GNU +Make (KDevelop, MSVC, and others are possible depending on your system setup +and CMake configuration). + +Please Note: Double check that the appropriate backends were detected. Often, +complaints of no sound, crashing, and missing devices can be solved by making +sure the correct backends are being used. CMake's output will identify which +backends were enabled. + +For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio +were detected (if your target system uses them). For Windows, make sure +DirectSound was detected. + + +Utilities +========= + +The source package comes with an informational utility, openal-info, and is +built by default. It prints out information provided by the ALC and AL sub- +systems, including discovered devices, version information, and extensions. + + +Configuration +============= + +OpenAL Soft can be configured on a per-user and per-system basis. This allows +users and sysadmins to control information provided to applications, as well +as application-agnostic behavior of the library. See alsoftrc.sample for +available settings. + + +Acknowledgements +================ + +Special thanks go to: + +Creative Labs for the original source code this is based off of. + +Christopher Fitzgerald for the current reverb effect implementation, and +helping with the low-pass and HRTF filters. + +Christian Borss for the 3D panning code previous versions used as a base. + +Ben Davis for the idea behind a previous version of the click-removal code. + +Richard Furse for helping with my understanding of Ambisonics that is used by +the various parts of the library. diff --git a/Engine/lib/openal-soft/XCompile-Android.txt b/Engine/lib/openal-soft/XCompile-Android.txt new file mode 100644 index 000000000..3dd88e803 --- /dev/null +++ b/Engine/lib/openal-soft/XCompile-Android.txt @@ -0,0 +1,39 @@ +# Cross-compiling requires CMake 2.6 or newer. Example: +# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile-Android.txt -DHOST=arm-linux-androideabi +# Where 'arm-linux-androideabi' is the host prefix for the cross-compiler. If +# you already have a toolchain file setup, you may use that instead of this +# file. Make sure to set CMAKE_FIND_ROOT_PATH to where the NDK toolchain was +# installed (e.g. "$ENV{HOME}/toolchains/arm-linux-androideabi-r10c-21"). + +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Linux) + +# which compilers to use for C and C++ +SET(CMAKE_C_COMPILER "${HOST}-gcc") +SET(CMAKE_CXX_COMPILER "${HOST}-g++") +SET(CMAKE_RC_COMPILER "${HOST}-windres") + +# here is the target environment located +SET(CMAKE_FIND_ROOT_PATH "SET THIS TO THE NDK TOOLCHAIN'S INSTALL PATH") + +# here is where stuff gets installed to +SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}" CACHE STRING "Install path prefix, prepended onto install directories." FORCE) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# set env vars so that pkg-config will look in the appropriate directory for +# .pc files (as there seems to be no way to force using ${HOST}-pkg-config) +set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig") +set(ENV{PKG_CONFIG_PATH} "") + +# Qt4 tools +SET(QT_QMAKE_EXECUTABLE ${HOST}-qmake) +SET(QT_MOC_EXECUTABLE ${HOST}-moc) +SET(QT_RCC_EXECUTABLE ${HOST}-rcc) +SET(QT_UIC_EXECUTABLE ${HOST}-uic) +SET(QT_LRELEASE_EXECUTABLE ${HOST}-lrelease) diff --git a/Engine/lib/openal-soft/XCompile.txt b/Engine/lib/openal-soft/XCompile.txt new file mode 100644 index 000000000..32706bc18 --- /dev/null +++ b/Engine/lib/openal-soft/XCompile.txt @@ -0,0 +1,37 @@ +# Cross-compiling requires CMake 2.6 or newer. Example: +# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt -DHOST=i686-w64-mingw32 +# Where 'i686-w64-mingw32' is the host prefix for your cross-compiler. If you +# already have a toolchain file setup, you may use that instead of this file. + +# the name of the target operating system +SET(CMAKE_SYSTEM_NAME Windows) + +# which compilers to use for C and C++ +SET(CMAKE_C_COMPILER "${HOST}-gcc") +SET(CMAKE_CXX_COMPILER "${HOST}-g++") +SET(CMAKE_RC_COMPILER "${HOST}-windres") + +# here is the target environment located +SET(CMAKE_FIND_ROOT_PATH "/usr/${HOST}") + +# here is where stuff gets installed to +SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}" CACHE STRING "Install path prefix, prepended onto install directories." FORCE) + +# adjust the default behaviour of the FIND_XXX() commands: +# search headers and libraries in the target environment, search +# programs in the host environment +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) + +# set env vars so that pkg-config will look in the appropriate directory for +# .pc files (as there seems to be no way to force using ${HOST}-pkg-config) +set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig") +set(ENV{PKG_CONFIG_PATH} "") + +# Qt4 tools +SET(QT_QMAKE_EXECUTABLE ${HOST}-qmake) +SET(QT_MOC_EXECUTABLE ${HOST}-moc) +SET(QT_RCC_EXECUTABLE ${HOST}-rcc) +SET(QT_UIC_EXECUTABLE ${HOST}-uic) +SET(QT_LRELEASE_EXECUTABLE ${HOST}-lrelease) diff --git a/Engine/lib/openal-soft/alsoftrc.sample b/Engine/lib/openal-soft/alsoftrc.sample new file mode 100644 index 000000000..d5913ff0e --- /dev/null +++ b/Engine/lib/openal-soft/alsoftrc.sample @@ -0,0 +1,456 @@ +# OpenAL config file. +# +# Option blocks may appear multiple times, and duplicated options will take the +# last value specified. Environment variables may be specified within option +# values, and are automatically substituted when the config file is loaded. +# Environment variable names may only contain alpha-numeric characters (a-z, +# A-Z, 0-9) and underscores (_), and are prefixed with $. For example, +# specifying "$HOME/file.ext" would typically result in something like +# "/home/user/file.ext". To specify an actual "$" character, use "$$". +# +# Device-specific values may be specified by including the device name in the +# block name, with "general" replaced by the device name. That is, general +# options for the device "Name of Device" would be in the [Name of Device] +# block, while ALSA options would be in the [alsa/Name of Device] block. +# Options marked as "(global)" are not influenced by the device. +# +# The system-wide settings can be put in /etc/openal/alsoft.conf and user- +# specific override settings in $HOME/.alsoftrc. +# For Windows, these settings should go into $AppData\alsoft.ini +# +# Option and block names are case-senstive. The supplied values are only hints +# and may not be honored (though generally it'll try to get as close as +# possible). Note: options that are left unset may default to app- or system- +# specified values. These are the current available settings: + +## +## General stuff +## +[general] + +## disable-cpu-exts: (global) +# Disables use of specialized methods that use specific CPU intrinsics. +# Certain methods may utilize CPU extensions for improved performance, and +# this option is useful for preventing some or all of those methods from being +# used. The available extensions are: sse, sse2, sse3, sse4.1, and neon. +# Specifying 'all' disables use of all such specialized methods. +#disable-cpu-exts = + +## drivers: (global) +# Sets the backend driver list order, comma-seperated. Unknown backends and +# duplicated names are ignored. Unlisted backends won't be considered for use +# unless the list is ended with a comma (e.g. 'oss,' will try OSS first before +# other backends, while 'oss' will try OSS only). Backends prepended with - +# won't be considered for use (e.g. '-oss,' will try all available backends +# except OSS). An empty list means to try all backends. +#drivers = + +## channels: +# Sets the output channel configuration. If left unspecified, one will try to +# be detected from the system, and defaulting to stereo. The available values +# are: mono, stereo, quad, surround51, surround51rear, surround61, surround71, +# ambi1, ambi2, ambi3. Note that the ambi* configurations provide ambisonic +# channels of the given order (using ACN ordering and SN3D normalization by +# default), which need to be decoded to play correctly on speakers. +#channels = + +## sample-type: +# Sets the output sample type. Currently, all mixing is done with 32-bit float +# and converted to the output sample type as needed. Available values are: +# int8 - signed 8-bit int +# uint8 - unsigned 8-bit int +# int16 - signed 16-bit int +# uint16 - unsigned 16-bit int +# int32 - signed 32-bit int +# uint32 - unsigned 32-bit int +# float32 - 32-bit float +#sample-type = float32 + +## frequency: +# Sets the output frequency. If left unspecified it will try to detect a +# default from the system, otherwise it will default to 44100. +#frequency = + +## period_size: +# Sets the update period size, in frames. This is the number of frames needed +# for each mixing update. Acceptable values range between 64 and 8192. +#period_size = 1024 + +## periods: +# Sets the number of update periods. Higher values create a larger mix ahead, +# which helps protect against skips when the CPU is under load, but increases +# the delay between a sound getting mixed and being heard. Acceptable values +# range between 2 and 16. +#periods = 4 + +## stereo-mode: +# Specifies if stereo output is treated as being headphones or speakers. With +# headphones, HRTF or crossfeed filters may be used for better audio quality. +# Valid settings are auto, speakers, and headphones. +#stereo-mode = auto + +## stereo-panning: +# Specifies the panning method for non-HRTF stereo output. uhj (default) +# creates stereo-compatible two-channel UHJ output, which encodes some +# surround sound information, while paired uses standard pair-wise panning +# between -30 and +30 degrees. If crossfeed filters are used, uhj panning is +# disabled. +#stereo-panning = uhj + +## ambi-format: +# Specifies the channel order and normalization for the "ambi*" set of channel +# configurations. Valid settings are: fuma, acn+sn3d, acn+n3d +#ambi-format = acn+sn3d + +## hrtf: +# Controls HRTF processing. These filters provide better spatialization of +# sounds while using headphones, but do require a bit more CPU power. The +# default filters will only work with 44100hz or 48000hz stereo output. While +# HRTF is used, the cf_level option is ignored. Setting this to auto (default) +# will allow HRTF to be used when headphones are detected or the app requests +# it, while setting true or false will forcefully enable or disable HRTF +# respectively. +#hrtf = auto + +## default-hrtf: +# Specifies the default HRTF to use. When multiple HRTFs are available, this +# determines the preferred one to use if none are specifically requested. Note +# that this is the enumerated HRTF name, not necessarily the filename. +#default-hrtf = + +## hrtf-paths: +# Specifies a comma-separated list of paths containing HRTF data sets. The +# format of the files are described in docs/hrtf.txt. The files within the +# directories must have the .mhr file extension to be recognized. By default, +# OS-dependent data paths will be used. They will also be used if the list +# ends with a comma. On Windows this is: +# $AppData\openal\hrtf +# And on other systems, it's (in order): +# $XDG_DATA_HOME/openal/hrtf (defaults to $HOME/.local/share/openal/hrtf) +# $XDG_DATA_DIRS/openal/hrtf (defaults to /usr/local/share/openal/hrtf and +# /usr/share/openal/hrtf) +#hrtf-paths = + +## cf_level: +# Sets the crossfeed level for stereo output. Valid values are: +# 0 - No crossfeed +# 1 - Low crossfeed +# 2 - Middle crossfeed +# 3 - High crossfeed (virtual speakers are closer to itself) +# 4 - Low easy crossfeed +# 5 - Middle easy crossfeed +# 6 - High easy crossfeed +# Users of headphones may want to try various settings. Has no effect on non- +# stereo modes. +#cf_level = 0 + +## resampler: (global) +# Selects the resampler used when mixing sources. Valid values are: +# point - nearest sample, no interpolation +# linear - extrapolates samples using a linear slope between samples +# sinc4 - extrapolates samples using a 4-point Sinc filter +# sinc8 - extrapolates samples using an 8-point Sinc filter +# bsinc - extrapolates samples using a band-limited Sinc filter (varying +# between 12 and 24 points, with anti-aliasing) +# Specifying other values will result in using the default (linear). +#resampler = linear + +## rt-prio: (global) +# Sets real-time priority for the mixing thread. Not all drivers may use this +# (eg. PortAudio) as they already control the priority of the mixing thread. +# 0 and negative values will disable it. Note that this may constitute a +# security risk since a real-time priority thread can indefinitely block +# normal-priority threads if it fails to wait. As such, the default is +# disabled. +#rt-prio = 0 + +## sources: +# Sets the maximum number of allocatable sources. Lower values may help for +# systems with apps that try to play more sounds than the CPU can handle. +#sources = 256 + +## slots: +# Sets the maximum number of Auxiliary Effect Slots an app can create. A slot +# can use a non-negligible amount of CPU time if an effect is set on it even +# if no sources are feeding it, so this may help when apps use more than the +# system can handle. +#slots = 4 + +## sends: +# Sets the number of auxiliary sends per source. When not specified (default), +# it allows the app to request how many it wants. The maximum value currently +# possible is 4. +#sends = + +## volume-adjust: +# A global volume adjustment for source output, expressed in decibels. The +# value is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will +# be a scale of 4x, etc. Similarly, -6 will be x1/2, and -12 is about x1/4. A +# value of 0 means no change. +#volume-adjust = 0 + +## excludefx: (global) +# Sets which effects to exclude, preventing apps from using them. This can +# help for apps that try to use effects which are too CPU intensive for the +# system to handle. Available effects are: eaxreverb,reverb,chorus,compressor, +# distortion,echo,equalizer,flanger,modulator,dedicated +#excludefx = + +## default-reverb: (global) +# A reverb preset that applies by default to all sources on send 0 +# (applications that set their own slots on send 0 will override this). +# Available presets are: None, Generic, PaddedCell, Room, Bathroom, +# Livingroom, Stoneroom, Auditorium, ConcertHall, Cave, Arena, Hangar, +# CarpetedHallway, Hallway, StoneCorridor, Alley, Forest, City, Moutains, +# Quarry, Plain, ParkingLot, SewerPipe, Underwater, Drugged, Dizzy, Psychotic. +#default-reverb = + +## trap-alc-error: (global) +# Generates a SIGTRAP signal when an ALC device error is generated, on systems +# that support it. This helps when debugging, while trying to find the cause +# of a device error. On Windows, a breakpoint exception is generated. +#trap-alc-error = false + +## trap-al-error: (global) +# Generates a SIGTRAP signal when an AL context error is generated, on systems +# that support it. This helps when debugging, while trying to find the cause +# of a context error. On Windows, a breakpoint exception is generated. +#trap-al-error = false + +## +## Ambisonic decoder stuff +## +[decoder] + +## hq-mode: +# Enables a high-quality ambisonic decoder. This mode is capable of frequency- +# dependent processing, creating a better reproduction of 3D sound rendering +# over surround sound speakers. Enabling this also requires specifying decoder +# configuration files for the appropriate speaker configuration you intend to +# use (see the quad, surround51, etc options below). Currently, up to third- +# order decoding is supported. +hq-mode = false + +## distance-comp: +# Enables compensation for the speakers' relative distances to the listener. +# This applies the necessary delays and attenuation to make the speakers +# behave as though they are all equidistant, which is important for proper +# playback of 3D sound rendering. Requires the high-quality ambisonic decoder, +# as well as the proper distances to be specified in the decoder configuration +# file. +distance-comp = true + +## quad: +# Decoder configuration file for Quadrophonic channel output. See +# docs/ambdec.txt for a description of the file format. +quad = + +## surround51: +# Decoder configuration file for 5.1 Surround (Side) channel output. See +# docs/ambdec.txt for a description of the file format. +surround51 = + +## surround51rear: +# Decoder configuration file for 5.1 Surround (Rear) channel output. See +# docs/ambdec.txt for a description of the file format. +surround51rear = + +## surround61: +# Decoder configuration file for 6.1 Surround channel output. See +# docs/ambdec.txt for a description of the file format. +surround61 = + +## surround71: +# Decoder configuration file for 7.1 Surround channel output. See +# docs/ambdec.txt for a description of the file format. Note: This can be used +# to enable 3D7.1 with the appropriate configuration and speaker placement, +# see docs/3D7.1.txt. +surround71 = + +## +## Reverb effect stuff (includes EAX reverb) +## +[reverb] + +## boost: (global) +# A global amplification for reverb output, expressed in decibels. The value +# is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will be a +# scale of 4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A +# value of 0 means no change. +#boost = 0 + +## emulate-eax: (global) +# Allows the standard reverb effect to be used in place of EAX reverb. EAX +# reverb processing is a bit more CPU intensive than standard, so this option +# allows a simpler effect to be used at the loss of some quality. +#emulate-eax = false + +## +## PulseAudio backend stuff +## +[pulse] + +## spawn-server: (global) +# Attempts to autospawn a PulseAudio server whenever needed (initializing the +# backend, enumerating devices, etc). Setting autospawn to false in Pulse's +# client.conf will still prevent autospawning even if this is set to true. +#spawn-server = true + +## allow-moves: (global) +# Allows PulseAudio to move active streams to different devices. Note that the +# device specifier (seen by applications) will not be updated when this +# occurs, and neither will the AL device configuration (sample rate, format, +# etc). +#allow-moves = false + +## fix-rate: +# Specifies whether to match the playback stream's sample rate to the device's +# sample rate. Enabling this forces OpenAL Soft to mix sources and effects +# directly to the actual output rate, avoiding a second resample pass by the +# PulseAudio server. +#fix-rate = false + +## +## ALSA backend stuff +## +[alsa] + +## device: (global) +# Sets the device name for the default playback device. +#device = default + +## device-prefix: (global) +# Sets the prefix used by the discovered (non-default) playback devices. This +# will be appended with "CARD=c,DEV=d", where c is the card id and d is the +# device index for the requested device name. +#device-prefix = plughw: + +## device-prefix-*: (global) +# Card- and device-specific prefixes may be used to override the device-prefix +# option. The option may specify the card id (eg, device-prefix-NVidia), or +# the card id and device index (eg, device-prefix-NVidia-0). The card id is +# case-sensitive. +#device-prefix- = + +## capture: (global) +# Sets the device name for the default capture device. +#capture = default + +## capture-prefix: (global) +# Sets the prefix used by the discovered (non-default) capture devices. This +# will be appended with "CARD=c,DEV=d", where c is the card id and d is the +# device number for the requested device name. +#capture-prefix = plughw: + +## capture-prefix-*: (global) +# Card- and device-specific prefixes may be used to override the +# capture-prefix option. The option may specify the card id (eg, +# capture-prefix-NVidia), or the card id and device index (eg, +# capture-prefix-NVidia-0). The card id is case-sensitive. +#capture-prefix- = + +## mmap: +# Sets whether to try using mmap mode (helps reduce latencies and CPU +# consumption). If mmap isn't available, it will automatically fall back to +# non-mmap mode. True, yes, on, and non-0 values will attempt to use mmap. 0 +# and anything else will force mmap off. +#mmap = true + +## allow-resampler: +# Specifies whether to allow ALSA's built-in resampler. Enabling this will +# allow the playback device to be set to a different sample rate than the +# actual output, causing ALSA to apply its own resampling pass after OpenAL +# Soft resamples and mixes the sources and effects for output. +#allow-resampler = false + +## +## OSS backend stuff +## +[oss] + +## device: (global) +# Sets the device name for OSS output. +#device = /dev/dsp + +## capture: (global) +# Sets the device name for OSS capture. +#capture = /dev/dsp + +## +## Solaris backend stuff +## +[solaris] + +## device: (global) +# Sets the device name for Solaris output. +#device = /dev/audio + +## +## QSA backend stuff +## +[qsa] + +## +## JACK backend stuff +## +[jack] + +## spawn-server: (global) +# Attempts to autospawn a JACK server whenever needed (initializing the +# backend, opening devices, etc). +#spawn-server = false + +## buffer-size: +# Sets the update buffer size, in samples, that the backend will keep buffered +# to handle the server's real-time processing requests. This value must be a +# power of 2, or else it will be rounded up to the next power of 2. If it is +# less than JACK's buffer update size, it will be clamped. This option may +# be useful in case the server's update size is too small and doesn't give the +# mixer time to keep enough audio available for the processing requests. +#buffer-size = 0 + +## +## MMDevApi backend stuff +## +[mmdevapi] + +## +## DirectSound backend stuff +## +[dsound] + +## +## Windows Multimedia backend stuff +## +[winmm] + +## +## PortAudio backend stuff +## +[port] + +## device: (global) +# Sets the device index for output. Negative values will use the default as +# given by PortAudio itself. +#device = -1 + +## capture: (global) +# Sets the device index for capture. Negative values will use the default as +# given by PortAudio itself. +#capture = -1 + +## +## Wave File Writer stuff +## +[wave] + +## file: (global) +# Sets the filename of the wave file to write to. An empty name prevents the +# backend from opening, even when explicitly requested. +# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION! +#file = + +## bformat: (global) +# Creates AMB format files using first-order ambisonics instead of a standard +# single- or multi-channel .wav file. +#bformat = false diff --git a/Engine/lib/openal-soft/appveyor.yml b/Engine/lib/openal-soft/appveyor.yml new file mode 100644 index 000000000..4010f2ead --- /dev/null +++ b/Engine/lib/openal-soft/appveyor.yml @@ -0,0 +1,14 @@ +version: 1.17.2.{build} + +environment: + matrix: + - GEN: "Visual Studio 14 2015" + CFG: Release + - GEN: "Visual Studio 14 2015 Win64" + CFG: Release + +build_script: + - cd build + - cmake .. -G"%GEN%" + - cmake --build . --config %CFG% --clean-first + diff --git a/Engine/lib/openal-soft/cmake/CheckFileOffsetBits.c b/Engine/lib/openal-soft/cmake/CheckFileOffsetBits.c new file mode 100644 index 000000000..de98296ea --- /dev/null +++ b/Engine/lib/openal-soft/cmake/CheckFileOffsetBits.c @@ -0,0 +1,9 @@ +#include + +#define KB ((off_t)(1024)) +#define MB ((off_t)(KB*1024)) +#define GB ((off_t)(MB*1024)) +int tb[((GB+GB+GB) > GB) ? 1 : -1]; + +int main() +{ return 0; } diff --git a/Engine/lib/openal-soft/cmake/CheckFileOffsetBits.cmake b/Engine/lib/openal-soft/cmake/CheckFileOffsetBits.cmake new file mode 100644 index 000000000..1dc154e48 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/CheckFileOffsetBits.cmake @@ -0,0 +1,39 @@ +# - Check if the _FILE_OFFSET_BITS macro is needed for large files +# CHECK_FILE_OFFSET_BITS() +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# Copyright (c) 2009, Chris Robinson +# +# Redistribution and use is allowed according to the terms of the LGPL license. + + +MACRO(CHECK_FILE_OFFSET_BITS) + + IF(NOT DEFINED _FILE_OFFSET_BITS) + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files") + TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64 + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckFileOffsetBits.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}) + IF(NOT __WITHOUT_FILE_OFFSET_BITS_64) + TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64 + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckFileOffsetBits.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64) + ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64) + + IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files") + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - 64") + ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files") + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - not needed") + ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + ENDIF(NOT DEFINED _FILE_OFFSET_BITS) + +ENDMACRO(CHECK_FILE_OFFSET_BITS) \ No newline at end of file diff --git a/Engine/lib/openal-soft/cmake/CheckSharedFunctionExists.cmake b/Engine/lib/openal-soft/cmake/CheckSharedFunctionExists.cmake new file mode 100644 index 000000000..7975f2334 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/CheckSharedFunctionExists.cmake @@ -0,0 +1,92 @@ +# - Check if a symbol exists as a function, variable, or macro +# CHECK_SYMBOL_EXISTS( ) +# +# Check that the is available after including given header +# and store the result in a . Specify the list +# of files in one argument as a semicolon-separated list. +# +# If the header files define the symbol as a macro it is considered +# available and assumed to work. If the header files declare the +# symbol as a function or variable then the symbol must also be +# available for linking. If the symbol is a type or enum value +# it will not be recognized (consider using CheckTypeSize or +# CheckCSourceCompiles). +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link + +#============================================================================= +# Copyright 2003-2011 Kitware, Inc. +# +# 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.) + +MACRO(CHECK_SHARED_FUNCTION_EXISTS SYMBOL FILES LIBRARY LOCATION VARIABLE) + IF("${VARIABLE}" MATCHES "^${VARIABLE}$") + SET(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n") + SET(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) + IF(CMAKE_REQUIRED_LIBRARIES) + SET(CHECK_SYMBOL_EXISTS_LIBS + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES};${LIBRARY}") + ELSE(CMAKE_REQUIRED_LIBRARIES) + SET(CHECK_SYMBOL_EXISTS_LIBS + "-DLINK_LIBRARIES:STRING=${LIBRARY}") + ENDIF(CMAKE_REQUIRED_LIBRARIES) + IF(CMAKE_REQUIRED_INCLUDES) + SET(CMAKE_SYMBOL_EXISTS_INCLUDES + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") + ELSE(CMAKE_REQUIRED_INCLUDES) + SET(CMAKE_SYMBOL_EXISTS_INCLUDES) + ENDIF(CMAKE_REQUIRED_INCLUDES) + FOREACH(FILE ${FILES}) + SET(CMAKE_CONFIGURABLE_FILE_CONTENT + "${CMAKE_CONFIGURABLE_FILE_CONTENT}#include <${FILE}>\n") + ENDFOREACH(FILE) + SET(CMAKE_CONFIGURABLE_FILE_CONTENT + "${CMAKE_CONFIGURABLE_FILE_CONTENT}\nvoid cmakeRequireSymbol(int dummy,...){(void)dummy;}\nint main()\n{\n cmakeRequireSymbol(0,&${SYMBOL});\n return 0;\n}\n") + + CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" + "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" @ONLY) + + MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY}") + TRY_COMPILE(${VARIABLE} + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + CMAKE_FLAGS + -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS} + -DLINK_DIRECTORIES:STRING=${LOCATION} + "${CHECK_SYMBOL_EXISTS_LIBS}" + "${CMAKE_SYMBOL_EXISTS_INCLUDES}" + OUTPUT_VARIABLE OUTPUT) + IF(${VARIABLE}) + MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - found") + SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}") + FILE(APPEND ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if the ${SYMBOL} " + "exist in ${LIBRARY} passed with the following output:\n" + "${OUTPUT}\nFile ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n" + "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") + ELSE(${VARIABLE}) + MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - not found.") + SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}") + FILE(APPEND ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if the ${SYMBOL} " + "exist in ${LIBRARY} failed with the following output:\n" + "${OUTPUT}\nFile ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n" + "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") + ENDIF(${VARIABLE}) + ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$") +ENDMACRO(CHECK_SHARED_FUNCTION_EXISTS) diff --git a/Engine/lib/openal-soft/cmake/FindALSA.cmake b/Engine/lib/openal-soft/cmake/FindALSA.cmake new file mode 100644 index 000000000..519304d63 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindALSA.cmake @@ -0,0 +1,73 @@ +# - Find alsa +# Find the alsa libraries (asound) +# +# This module defines the following variables: +# ALSA_FOUND - True if ALSA_INCLUDE_DIR & ALSA_LIBRARY are found +# ALSA_LIBRARIES - Set when ALSA_LIBRARY is found +# ALSA_INCLUDE_DIRS - Set when ALSA_INCLUDE_DIR is found +# +# ALSA_INCLUDE_DIR - where to find asoundlib.h, etc. +# ALSA_LIBRARY - the asound library +# ALSA_VERSION_STRING - the version of alsa found (since CMake 2.8.8) +# + +#============================================================================= +# Copyright 2009-2011 Kitware, Inc. +# Copyright 2009-2011 Philip Lowman +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * The names of Kitware, Inc., the Insight Consortium, or the names of +# any consortium members, or of any contributors, may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +find_path(ALSA_INCLUDE_DIR NAMES alsa/asoundlib.h + DOC "The ALSA (asound) include directory" +) + +find_library(ALSA_LIBRARY NAMES asound + DOC "The ALSA (asound) library" +) + +if(ALSA_INCLUDE_DIR AND EXISTS "${ALSA_INCLUDE_DIR}/alsa/version.h") + file(STRINGS "${ALSA_INCLUDE_DIR}/alsa/version.h" alsa_version_str REGEX "^#define[\t ]+SND_LIB_VERSION_STR[\t ]+\".*\"") + + string(REGEX REPLACE "^.*SND_LIB_VERSION_STR[\t ]+\"([^\"]*)\".*$" "\\1" ALSA_VERSION_STRING "${alsa_version_str}") + unset(alsa_version_str) +endif() + +# handle the QUIETLY and REQUIRED arguments and set ALSA_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(ALSA + REQUIRED_VARS ALSA_LIBRARY ALSA_INCLUDE_DIR + VERSION_VAR ALSA_VERSION_STRING) + +if(ALSA_FOUND) + set( ALSA_LIBRARIES ${ALSA_LIBRARY} ) + set( ALSA_INCLUDE_DIRS ${ALSA_INCLUDE_DIR} ) +endif() + +mark_as_advanced(ALSA_INCLUDE_DIR ALSA_LIBRARY) diff --git a/Engine/lib/openal-soft/cmake/FindAudioIO.cmake b/Engine/lib/openal-soft/cmake/FindAudioIO.cmake new file mode 100644 index 000000000..f0f8b2a59 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindAudioIO.cmake @@ -0,0 +1,21 @@ +# - Find AudioIO includes and libraries +# +# AUDIOIO_FOUND - True if AUDIOIO_INCLUDE_DIR is found +# AUDIOIO_INCLUDE_DIRS - Set when AUDIOIO_INCLUDE_DIR is found +# +# AUDIOIO_INCLUDE_DIR - where to find sys/audioio.h, etc. +# + +find_path(AUDIOIO_INCLUDE_DIR + NAMES sys/audioio.h + DOC "The AudioIO include directory" +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(AudioIO REQUIRED_VARS AUDIOIO_INCLUDE_DIR) + +if(AUDIOIO_FOUND) + set(AUDIOIO_INCLUDE_DIRS ${AUDIOIO_INCLUDE_DIR}) +endif() + +mark_as_advanced(AUDIOIO_INCLUDE_DIR) diff --git a/Engine/lib/openal-soft/cmake/FindDSound.cmake b/Engine/lib/openal-soft/cmake/FindDSound.cmake new file mode 100644 index 000000000..0ddf98aad --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindDSound.cmake @@ -0,0 +1,35 @@ +# - 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 + NAMES dsound.h + PATHS "${DXSDK_DIR}" + PATH_SUFFIXES include + DOC "The DirectSound include directory" +) + +find_library(DSOUND_LIBRARY + NAMES dsound + PATHS "${DXSDK_DIR}" + PATH_SUFFIXES lib lib/x86 lib/x64 + 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) diff --git a/Engine/lib/openal-soft/cmake/FindFFmpeg.cmake b/Engine/lib/openal-soft/cmake/FindFFmpeg.cmake new file mode 100644 index 000000000..96cbb6ed0 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindFFmpeg.cmake @@ -0,0 +1,173 @@ +# vim: ts=2 sw=2 +# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) +# +# Once done this will define +# FFMPEG_FOUND - System has the all required components. +# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. +# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. +# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. +# +# For each of the components it will additionaly set. +# - AVCODEC +# - AVDEVICE +# - AVFORMAT +# - AVUTIL +# - POSTPROC +# - SWSCALE +# - SWRESAMPLE +# the following variables will be defined +# _FOUND - System has +# _INCLUDE_DIRS - Include directory necessary for using the headers +# _LIBRARIES - Link these to use +# _DEFINITIONS - Compiler switches required for using +# _VERSION - The components version +# +# Copyright (c) 2006, Matthias Kretz, +# Copyright (c) 2008, Alexander Neundorf, +# Copyright (c) 2011, Michael Jansen, +# +# Redistribution and use is allowed according to the terms of the BSD license. + +include(FindPackageHandleStandardArgs) + +if(NOT FFmpeg_FIND_COMPONENTS) + set(FFmpeg_FIND_COMPONENTS AVFORMAT AVCODEC AVUTIL) +endif() + +# +### Macro: set_component_found +# +# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present. +# +macro(set_component_found _component) + if(${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS) + # message(STATUS " - ${_component} found.") + set(${_component}_FOUND TRUE) + else() + # message(STATUS " - ${_component} not found.") + endif() +endmacro() + +# +### Macro: find_component +# +# Checks for the given component by invoking pkgconfig and then looking up the libraries and +# include directories. +# +macro(find_component _component _pkgconfig _library _header) + if(NOT WIN32) + # use pkg-config to get the directories and then use these values + # in the FIND_PATH() and FIND_LIBRARY() calls + find_package(PkgConfig) + if(PKG_CONFIG_FOUND) + pkg_check_modules(PC_${_component} ${_pkgconfig}) + endif() + endif() + + find_path(${_component}_INCLUDE_DIRS ${_header} + HINTS + ${FFMPEGSDK_INC} + ${PC_LIB${_component}_INCLUDEDIR} + ${PC_LIB${_component}_INCLUDE_DIRS} + PATH_SUFFIXES + ffmpeg + ) + + find_library(${_component}_LIBRARIES NAMES ${_library} + HINTS + ${FFMPEGSDK_LIB} + ${PC_LIB${_component}_LIBDIR} + ${PC_LIB${_component}_LIBRARY_DIRS} + ) + + STRING(REGEX REPLACE "/.*" "/version.h" _ver_header ${_header}) + if(EXISTS "${${_component}_INCLUDE_DIRS}/${_ver_header}") + file(STRINGS "${${_component}_INCLUDE_DIRS}/${_ver_header}" version_str REGEX "^#define[\t ]+LIB${_component}_VERSION_M.*") + + foreach(_str "${version_str}") + if(NOT version_maj) + string(REGEX REPLACE "^.*LIB${_component}_VERSION_MAJOR[\t ]+([0-9]*).*$" "\\1" version_maj "${_str}") + endif() + if(NOT version_min) + string(REGEX REPLACE "^.*LIB${_component}_VERSION_MINOR[\t ]+([0-9]*).*$" "\\1" version_min "${_str}") + endif() + if(NOT version_mic) + string(REGEX REPLACE "^.*LIB${_component}_VERSION_MICRO[\t ]+([0-9]*).*$" "\\1" version_mic "${_str}") + endif() + endforeach() + unset(version_str) + + set(${_component}_VERSION "${version_maj}.${version_min}.${version_mic}" CACHE STRING "The ${_component} version number.") + unset(version_maj) + unset(version_min) + unset(version_mic) + endif(EXISTS "${${_component}_INCLUDE_DIRS}/${_ver_header}") + set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number.") + set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS.") + + set_component_found(${_component}) + + mark_as_advanced( + ${_component}_INCLUDE_DIRS + ${_component}_LIBRARIES + ${_component}_DEFINITIONS + ${_component}_VERSION) +endmacro() + + +set(FFMPEGSDK $ENV{FFMPEG_HOME}) +if(FFMPEGSDK) + set(FFMPEGSDK_INC "${FFMPEGSDK}/include") + set(FFMPEGSDK_LIB "${FFMPEGSDK}/lib") +endif() + +# Check for all possible components. +find_component(AVCODEC libavcodec avcodec libavcodec/avcodec.h) +find_component(AVFORMAT libavformat avformat libavformat/avformat.h) +find_component(AVDEVICE libavdevice avdevice libavdevice/avdevice.h) +find_component(AVUTIL libavutil avutil libavutil/avutil.h) +find_component(SWSCALE libswscale swscale libswscale/swscale.h) +find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h) +find_component(POSTPROC libpostproc postproc libpostproc/postprocess.h) + +# Check if the required components were found and add their stuff to the FFMPEG_* vars. +foreach(_component ${FFmpeg_FIND_COMPONENTS}) + if(${_component}_FOUND) + # message(STATUS "Required component ${_component} present.") + set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${${_component}_LIBRARIES}) + set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS}) + list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS}) + else() + # message(STATUS "Required component ${_component} missing.") + endif() +endforeach() + +# Build the include path and library list with duplicates removed. +if(FFMPEG_INCLUDE_DIRS) + list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS) +endif() + +if(FFMPEG_LIBRARIES) + list(REMOVE_DUPLICATES FFMPEG_LIBRARIES) +endif() + +# cache the vars. +set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING "The FFmpeg include directories." FORCE) +set(FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} CACHE STRING "The FFmpeg libraries." FORCE) +set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} CACHE STRING "The FFmpeg cflags." FORCE) + +mark_as_advanced(FFMPEG_INCLUDE_DIRS FFMPEG_LIBRARIES FFMPEG_DEFINITIONS) + +# Now set the noncached _FOUND vars for the components. +foreach(_component AVCODEC AVDEVICE AVFORMAT AVUTIL POSTPROCESS SWRESAMPLE SWSCALE) + set_component_found(${_component}) +endforeach () + +# Compile the list of required vars +set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS) +foreach(_component ${FFmpeg_FIND_COMPONENTS}) + list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS) +endforeach() + +# Give a nice error message if some of the required vars are missing. +find_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS}) diff --git a/Engine/lib/openal-soft/cmake/FindJACK.cmake b/Engine/lib/openal-soft/cmake/FindJACK.cmake new file mode 100644 index 000000000..b72fe3f9a --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindJACK.cmake @@ -0,0 +1,60 @@ +# - Find JACK +# Find the JACK libraries +# +# This module defines the following variables: +# JACK_FOUND - True if JACK_INCLUDE_DIR & JACK_LIBRARY are found +# JACK_INCLUDE_DIRS - where to find jack.h, etc. +# JACK_LIBRARIES - the jack library +# + +#============================================================================= +# Copyright 2009-2011 Kitware, Inc. +# Copyright 2009-2011 Philip Lowman +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# * The names of Kitware, Inc., the Insight Consortium, or the names of +# any consortium members, or of any contributors, may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +find_path(JACK_INCLUDE_DIR NAMES jack/jack.h + DOC "The JACK include directory" +) + +find_library(JACK_LIBRARY NAMES jack + DOC "The JACK library" +) + +# handle the QUIETLY and REQUIRED arguments and set JACK_FOUND to TRUE if +# all listed variables are TRUE +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(JACK REQUIRED_VARS JACK_LIBRARY JACK_INCLUDE_DIR) + +if(JACK_FOUND) + set(JACK_LIBRARIES ${JACK_LIBRARY}) + set(JACK_INCLUDE_DIRS ${JACK_INCLUDE_DIR}) +endif() + +mark_as_advanced(JACK_INCLUDE_DIR JACK_LIBRARY) diff --git a/Engine/lib/openal-soft/cmake/FindOSS.cmake b/Engine/lib/openal-soft/cmake/FindOSS.cmake new file mode 100644 index 000000000..88ee66ad2 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindOSS.cmake @@ -0,0 +1,21 @@ +# - Find OSS includes +# +# OSS_FOUND - True if OSS_INCLUDE_DIR is found +# OSS_INCLUDE_DIRS - Set when OSS_INCLUDE_DIR is found +# +# OSS_INCLUDE_DIR - where to find sys/soundcard.h, etc. +# + +find_path(OSS_INCLUDE_DIR + NAMES sys/soundcard.h + DOC "The OSS include directory" +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OSS REQUIRED_VARS OSS_INCLUDE_DIR) + +if(OSS_FOUND) + set(OSS_INCLUDE_DIRS ${OSS_INCLUDE_DIR}) +endif() + +mark_as_advanced(OSS_INCLUDE_DIR) diff --git a/Engine/lib/openal-soft/cmake/FindPortAudio.cmake b/Engine/lib/openal-soft/cmake/FindPortAudio.cmake new file mode 100644 index 000000000..fad2313df --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindPortAudio.cmake @@ -0,0 +1,32 @@ +# - Find PortAudio includes and libraries +# +# PORTAUDIO_FOUND - True if PORTAUDIO_INCLUDE_DIR & PORTAUDIO_LIBRARY +# are found +# PORTAUDIO_LIBRARIES - Set when PORTAUDIO_LIBRARY is found +# PORTAUDIO_INCLUDE_DIRS - Set when PORTAUDIO_INCLUDE_DIR is found +# +# PORTAUDIO_INCLUDE_DIR - where to find portaudio.h, etc. +# PORTAUDIO_LIBRARY - the portaudio library +# + +find_path(PORTAUDIO_INCLUDE_DIR + NAMES portaudio.h + DOC "The PortAudio include directory" +) + +find_library(PORTAUDIO_LIBRARY + NAMES portaudio + DOC "The PortAudio library" +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PortAudio + REQUIRED_VARS PORTAUDIO_LIBRARY PORTAUDIO_INCLUDE_DIR +) + +if(PORTAUDIO_FOUND) + set(PORTAUDIO_LIBRARIES ${PORTAUDIO_LIBRARY}) + set(PORTAUDIO_INCLUDE_DIRS ${PORTAUDIO_INCLUDE_DIR}) +endif() + +mark_as_advanced(PORTAUDIO_INCLUDE_DIR PORTAUDIO_LIBRARY) diff --git a/Engine/lib/openal-soft/cmake/FindPulseAudio.cmake b/Engine/lib/openal-soft/cmake/FindPulseAudio.cmake new file mode 100644 index 000000000..1f6f843a1 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindPulseAudio.cmake @@ -0,0 +1,43 @@ +# - Find PulseAudio includes and libraries +# +# PULSEAUDIO_FOUND - True if PULSEAUDIO_INCLUDE_DIR & +# PULSEAUDIO_LIBRARY are found +# PULSEAUDIO_LIBRARIES - Set when PULSEAUDIO_LIBRARY is found +# PULSEAUDIO_INCLUDE_DIRS - Set when PULSEAUDIO_INCLUDE_DIR is found +# +# PULSEAUDIO_INCLUDE_DIR - where to find pulse/pulseaudio.h, etc. +# PULSEAUDIO_LIBRARY - the pulse library +# PULSEAUDIO_VERSION_STRING - the version of PulseAudio found +# + +find_path(PULSEAUDIO_INCLUDE_DIR + NAMES pulse/pulseaudio.h + DOC "The PulseAudio include directory" +) + +find_library(PULSEAUDIO_LIBRARY + NAMES pulse + DOC "The PulseAudio library" +) + +if(PULSEAUDIO_INCLUDE_DIR AND EXISTS "${PULSEAUDIO_INCLUDE_DIR}/pulse/version.h") + file(STRINGS "${PULSEAUDIO_INCLUDE_DIR}/pulse/version.h" pulse_version_str + REGEX "^#define[\t ]+pa_get_headers_version\\(\\)[\t ]+\\(\".*\"\\)") + + string(REGEX REPLACE "^.*pa_get_headers_version\\(\\)[\t ]+\\(\"([^\"]*)\"\\).*$" "\\1" + PULSEAUDIO_VERSION_STRING "${pulse_version_str}") + unset(pulse_version_str) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PulseAudio + REQUIRED_VARS PULSEAUDIO_LIBRARY PULSEAUDIO_INCLUDE_DIR + VERSION_VAR PULSEAUDIO_VERSION_STRING +) + +if(PULSEAUDIO_FOUND) + set(PULSEAUDIO_LIBRARIES ${PULSEAUDIO_LIBRARY}) + set(PULSEAUDIO_INCLUDE_DIRS ${PULSEAUDIO_INCLUDE_DIR}) +endif() + +mark_as_advanced(PULSEAUDIO_INCLUDE_DIR PULSEAUDIO_LIBRARY) diff --git a/Engine/lib/openal-soft/cmake/FindQSA.cmake b/Engine/lib/openal-soft/cmake/FindQSA.cmake new file mode 100644 index 000000000..0ad1fd438 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindQSA.cmake @@ -0,0 +1,34 @@ +# - Find QSA includes and libraries +# +# QSA_FOUND - True if QSA_INCLUDE_DIR & QSA_LIBRARY are found +# QSA_LIBRARIES - Set when QSA_LIBRARY is found +# QSA_INCLUDE_DIRS - Set when QSA_INCLUDE_DIR is found +# +# QSA_INCLUDE_DIR - where to find sys/asoundlib.h, etc. +# QSA_LIBRARY - the asound library +# + +# Only check for QSA on QNX, because it conflicts with ALSA. +if("${CMAKE_C_PLATFORM_ID}" STREQUAL "QNX") + find_path(QSA_INCLUDE_DIR + NAMES sys/asoundlib.h + DOC "The QSA include directory" + ) + + find_library(QSA_LIBRARY + NAMES asound + DOC "The QSA library" + ) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(QSA + REQUIRED_VARS QSA_LIBRARY QSA_INCLUDE_DIR +) + +if(QSA_FOUND) + set(QSA_LIBRARIES ${QSA_LIBRARY}) + set(QSA_INCLUDE_DIRS ${QSA_INCLUDE_DIR}) +endif() + +mark_as_advanced(QSA_INCLUDE_DIR QSA_LIBRARY) diff --git a/Engine/lib/openal-soft/cmake/FindSDL2.cmake b/Engine/lib/openal-soft/cmake/FindSDL2.cmake new file mode 100644 index 000000000..70e607a89 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindSDL2.cmake @@ -0,0 +1,193 @@ +# Locate SDL2 library +# This module defines +# SDL2_LIBRARY, the name of the library to link against +# SDL2_FOUND, if false, do not try to link to SDL2 +# SDL2_INCLUDE_DIR, where to find SDL.h +# +# This module responds to the the flag: +# SDL2_BUILDING_LIBRARY +# If this is defined, then no SDL2_main will be linked in because +# only applications need main(). +# Otherwise, it is assumed you are building an application and this +# module will attempt to locate and set the the proper link flags +# as part of the returned SDL2_LIBRARY variable. +# +# Don't forget to include SDL2main.h and SDL2main.m your project for the +# OS X framework based version. (Other versions link to -lSDL2main which +# this module will try to find on your behalf.) Also for OS X, this +# module will automatically add the -framework Cocoa on your behalf. +# +# +# Additional Note: If you see an empty SDL2_LIBRARY_TEMP in your configuration +# and no SDL2_LIBRARY, it means CMake did not find your SDL2 library +# (SDL2.dll, libsdl2.so, SDL2.framework, etc). +# Set SDL2_LIBRARY_TEMP to point to your SDL2 library, and configure again. +# Similarly, if you see an empty SDL2MAIN_LIBRARY, you should set this value +# as appropriate. These values are used to generate the final SDL2_LIBRARY +# variable, but when these values are unset, SDL2_LIBRARY does not get created. +# +# +# $SDL2DIR is an environment variable that would +# correspond to the ./configure --prefix=$SDL2DIR +# used in building SDL2. +# l.e.galup 9-20-02 +# +# Modified by Eric Wing. +# Added code to assist with automated building by using environmental variables +# and providing a more controlled/consistent search behavior. +# Added new modifications to recognize OS X frameworks and +# additional Unix paths (FreeBSD, etc). +# Also corrected the header search path to follow "proper" SDL2 guidelines. +# Added a search for SDL2main which is needed by some platforms. +# Added a search for threads which is needed by some platforms. +# Added needed compile switches for MinGW. +# +# On OSX, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of +# SDL2_LIBRARY to override this selection or set the CMake environment +# CMAKE_INCLUDE_PATH to modify the search paths. +# +# Note that the header path has changed from SDL2/SDL.h to just SDL.h +# This needed to change because "proper" SDL2 convention +# is #include "SDL.h", not . This is done for portability +# reasons because not all systems place things in SDL2/ (see FreeBSD). +# +# Ported by Johnny Patterson. This is a literal port for SDL2 of the FindSDL.cmake +# module with the minor edit of changing "SDL" to "SDL2" where necessary. This +# was not created for redistribution, and exists temporarily pending official +# SDL2 CMake modules. + +#============================================================================= +# Copyright 2003-2009 Kitware, Inc. +# +# 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.) + + +FIND_PATH(SDL2_INCLUDE_DIR SDL.h + HINTS + $ENV{SDL2DIR} + PATH_SUFFIXES include/SDL2 include + PATHS + ~/Library/Frameworks + /Library/Frameworks + /usr/local/include/SDL2 + /usr/include/SDL2 + /sw # Fink + /opt/local # DarwinPorts + /opt/csw # Blastwave + /opt +) +#MESSAGE("SDL2_INCLUDE_DIR is ${SDL2_INCLUDE_DIR}") + +FIND_LIBRARY(SDL2_LIBRARY_TEMP + NAMES SDL2 + HINTS + $ENV{SDL2DIR} + PATH_SUFFIXES lib64 lib + PATHS + /sw + /opt/local + /opt/csw + /opt +) + +#MESSAGE("SDL2_LIBRARY_TEMP is ${SDL2_LIBRARY_TEMP}") + +IF(NOT SDL2_BUILDING_LIBRARY) + IF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") + # Non-OS X framework versions expect you to also dynamically link to + # SDL2main. This is mainly for Windows and OS X. Other (Unix) platforms + # seem to provide SDL2main for compatibility even though they don't + # necessarily need it. + FIND_LIBRARY(SDL2MAIN_LIBRARY + NAMES SDL2main + HINTS + $ENV{SDL2DIR} + PATH_SUFFIXES lib64 lib + PATHS + /sw + /opt/local + /opt/csw + /opt + ) + ENDIF(NOT ${SDL2_INCLUDE_DIR} MATCHES ".framework") +ENDIF(NOT SDL2_BUILDING_LIBRARY) + +# SDL2 may require threads on your system. +# The Apple build may not need an explicit flag because one of the +# frameworks may already provide it. +# But for non-OSX systems, I will use the CMake Threads package. +IF(NOT APPLE) + FIND_PACKAGE(Threads) +ENDIF(NOT APPLE) + +# MinGW needs an additional library, mwindows +# It's total link flags should look like -lmingw32 -lSDL2main -lSDL2 -lmwindows +# (Actually on second look, I think it only needs one of the m* libraries.) +IF(MINGW) + SET(MINGW32_LIBRARY mingw32 CACHE STRING "mwindows for MinGW") +ENDIF(MINGW) + +SET(SDL2_FOUND "NO") +IF(SDL2_LIBRARY_TEMP) + # For SDL2main + IF(NOT SDL2_BUILDING_LIBRARY) + IF(SDL2MAIN_LIBRARY) + SET(SDL2_LIBRARY_TEMP ${SDL2MAIN_LIBRARY} ${SDL2_LIBRARY_TEMP}) + ENDIF(SDL2MAIN_LIBRARY) + ENDIF(NOT SDL2_BUILDING_LIBRARY) + + # For OS X, SDL2 uses Cocoa as a backend so it must link to Cocoa. + # CMake doesn't display the -framework Cocoa string in the UI even + # though it actually is there if I modify a pre-used variable. + # I think it has something to do with the CACHE STRING. + # So I use a temporary variable until the end so I can set the + # "real" variable in one-shot. + IF(APPLE) + SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} "-framework Cocoa") + ENDIF(APPLE) + + # For threads, as mentioned Apple doesn't need this. + # In fact, there seems to be a problem if I used the Threads package + # and try using this line, so I'm just skipping it entirely for OS X. + IF(NOT APPLE) + SET(SDL2_LIBRARY_TEMP ${SDL2_LIBRARY_TEMP} ${CMAKE_THREAD_LIBS_INIT}) + ENDIF(NOT APPLE) + + # For MinGW library + IF(MINGW) + SET(SDL2_LIBRARY_TEMP ${MINGW32_LIBRARY} ${SDL2_LIBRARY_TEMP}) + ENDIF(MINGW) + + IF(WIN32) + SET(SDL2_LIBRARY_TEMP winmm imm32 version msimg32 ${SDL2_LIBRARY_TEMP}) + ENDIF(WIN32) + + # Set the final string here so the GUI reflects the final state. + SET(SDL2_LIBRARY ${SDL2_LIBRARY_TEMP} CACHE STRING "Where the SDL2 Library can be found") + # Set the temp variable to INTERNAL so it is not seen in the CMake GUI + SET(SDL2_LIBRARY_TEMP "${SDL2_LIBRARY_TEMP}" CACHE INTERNAL "") + + SET(SDL2_FOUND "YES") +ENDIF(SDL2_LIBRARY_TEMP) + +INCLUDE(FindPackageHandleStandardArgs) + +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL2 + REQUIRED_VARS SDL2_LIBRARY SDL2_INCLUDE_DIR) + +IF(SDL2_STATIC) + if (UNIX AND NOT APPLE) + EXECUTE_PROCESS(COMMAND sdl2-config --static-libs OUTPUT_VARIABLE SDL2_LINK_FLAGS) + STRING(REGEX REPLACE "(\r?\n)+$" "" SDL2_LINK_FLAGS "${SDL2_LINK_FLAGS}") + SET(SDL2_LIBRARY ${SDL2_LINK_FLAGS}) + ENDIF() +ENDIF(SDL2_STATIC) diff --git a/Engine/lib/openal-soft/cmake/FindSDL_sound.cmake b/Engine/lib/openal-soft/cmake/FindSDL_sound.cmake new file mode 100644 index 000000000..5557b55b1 --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindSDL_sound.cmake @@ -0,0 +1,429 @@ +# - 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_LIBS "") + if(SDL2_FOUND) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY}) + foreach(lib ${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY}) + set(TMP_LIBS "${TMP_LIBS} \"${lib}\"") + endforeach() + set(TMP_INCLUDE_DIRS ${SDL2_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR}) + else() + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY}) + foreach(lib ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY}) + set(TMP_LIBS "${TMP_LIBS} \"${lib}\"") + endforeach() + set(TMP_INCLUDE_DIRS ${SDL_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR}) + endif() + + # Keep trying to build a temp project until we find all missing libs. + set(TRY_AGAIN TRUE) + WHILE(TRY_AGAIN) + set(TRY_AGAIN FALSE) + # message("TMP_TRY_LIBS ${TMP_TRY_LIBS}") + + # Write the CMakeLists.txt and test project + # Weird, this is still sketchy. If I don't quote the variables + # in the TARGET_LINK_LIBRARIES, I seem to loose everything + # in the SDL2_LIBRARY string after the "-framework". + # But if I quote the stuff in INCLUDE_DIRECTORIES, it doesn't work. + file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/CMakeLists.txt + "cmake_minimum_required(VERSION 2.8) + project(DetermineSoundLibs C) + include_directories(${TMP_INCLUDE_DIRS}) + add_executable(DetermineSoundLibs DetermineSoundLibs.c) + target_link_libraries(DetermineSoundLibs ${TMP_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. + + # Find libmath + if("${MY_OUTPUT}" MATCHES "cos@@GLIBC") + find_library(MATH_LIBRARY NAMES m) + if(MATH_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MATH_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${MATH_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif(MATH_LIBRARY) + endif("${MY_OUTPUT}" MATCHES "cos@@GLIBC") + + # Find MikMod + if("${MY_OUTPUT}" MATCHES "MikMod_") + find_library(MIKMOD_LIBRARY + NAMES libmikmod-coreaudio mikmod + PATHS + ENV MIKMODDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(MIKMOD_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MIKMOD_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${MIKMOD_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif(MIKMOD_LIBRARY) + endif("${MY_OUTPUT}" MATCHES "MikMod_") + + # Find ModPlug + if("${MY_OUTPUT}" MATCHES "MODPLUG_") + find_library(MODPLUG_LIBRARY + NAMES modplug + PATHS + ENV MODPLUGDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(MODPLUG_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MODPLUG_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${MODPLUG_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif() + endif() + + # Find Ogg and Vorbis + if("${MY_OUTPUT}" MATCHES "ov_") + find_library(VORBISFILE_LIBRARY + NAMES vorbisfile VorbisFile VORBISFILE + PATHS + ENV VORBISDIR + ENV OGGDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(VORBISFILE_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBISFILE_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${VORBISFILE_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif() + + find_library(VORBIS_LIBRARY + NAMES vorbis Vorbis VORBIS + PATHS + ENV OGGDIR + ENV VORBISDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(VORBIS_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBIS_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${VORBIS_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif() + + find_library(OGG_LIBRARY + NAMES ogg Ogg OGG + PATHS + ENV OGGDIR + ENV VORBISDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(OGG_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${OGG_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif() + endif() + + # Find SMPEG + if("${MY_OUTPUT}" MATCHES "SMPEG_") + find_library(SMPEG_LIBRARY + NAMES smpeg SMPEG Smpeg SMpeg + PATHS + ENV SMPEGDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(SMPEG_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SMPEG_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${SMPEG_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif() + endif() + + + # Find FLAC + if("${MY_OUTPUT}" MATCHES "FLAC_") + find_library(FLAC_LIBRARY + NAMES flac FLAC + PATHS + ENV FLACDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(FLAC_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${FLAC_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${FLAC_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif() + endif() + + + # 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}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${SPEEX_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif() + + # Find OGG (needed for Speex) + # We might have already found Ogg for Vorbis, so skip it if so. + if(NOT OGG_LIBRARY) + find_library(OGG_LIBRARY + NAMES ogg Ogg OGG + PATHS + ENV OGGDIR + ENV VORBISDIR + ENV SPEEXDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(OGG_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY}) + set(TMP_LIBS "${SDL_SOUND_LIBRARIES_TMP} \"${OGG_LIBRARY}\"") + set(TRY_AGAIN TRUE) + endif() + endif() + endif() + endif() + ENDWHILE() + unset(TMP_INCLUDE_DIRS) + unset(TMP_LIBS) + + set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARIES_TMP} CACHE INTERNAL "SDL_sound and dependent libraries") + 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) diff --git a/Engine/lib/openal-soft/cmake/FindSoundIO.cmake b/Engine/lib/openal-soft/cmake/FindSoundIO.cmake new file mode 100644 index 000000000..10450254d --- /dev/null +++ b/Engine/lib/openal-soft/cmake/FindSoundIO.cmake @@ -0,0 +1,32 @@ +# - Find SoundIO (sndio) includes and libraries +# +# SOUNDIO_FOUND - True if SOUNDIO_INCLUDE_DIR & SOUNDIO_LIBRARY are +# found +# SOUNDIO_LIBRARIES - Set when SOUNDIO_LIBRARY is found +# SOUNDIO_INCLUDE_DIRS - Set when SOUNDIO_INCLUDE_DIR is found +# +# SOUNDIO_INCLUDE_DIR - where to find sndio.h, etc. +# SOUNDIO_LIBRARY - the sndio library +# + +find_path(SOUNDIO_INCLUDE_DIR + NAMES sndio.h + DOC "The SoundIO include directory" +) + +find_library(SOUNDIO_LIBRARY + NAMES sndio + DOC "The SoundIO library" +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SoundIO + REQUIRED_VARS SOUNDIO_LIBRARY SOUNDIO_INCLUDE_DIR +) + +if(SOUNDIO_FOUND) + set(SOUNDIO_LIBRARIES ${SOUNDIO_LIBRARY}) + set(SOUNDIO_INCLUDE_DIRS ${SOUNDIO_INCLUDE_DIR}) +endif() + +mark_as_advanced(SOUNDIO_INCLUDE_DIR SOUNDIO_LIBRARY) diff --git a/Engine/lib/openal-soft/common/almalloc.c b/Engine/lib/openal-soft/common/almalloc.c new file mode 100644 index 000000000..8c1c5794e --- /dev/null +++ b/Engine/lib/openal-soft/common/almalloc.c @@ -0,0 +1,62 @@ + +#include "config.h" + +#include "almalloc.h" + +#include +#include +#ifdef HAVE_MALLOC_H +#include +#endif +#ifdef HAVE_WINDOWS_H +#include +#endif + +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(((ptrdiff_t)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 +} diff --git a/Engine/lib/openal-soft/common/atomic.c b/Engine/lib/openal-soft/common/atomic.c new file mode 100644 index 000000000..7a8fe6d80 --- /dev/null +++ b/Engine/lib/openal-soft/common/atomic.c @@ -0,0 +1,10 @@ + +#include "config.h" + +#include "atomic.h" + + +extern inline void InitRef(RefCount *ptr, uint value); +extern inline uint ReadRef(RefCount *ptr); +extern inline uint IncrementRef(RefCount *ptr); +extern inline uint DecrementRef(RefCount *ptr); diff --git a/Engine/lib/openal-soft/common/rwlock.c b/Engine/lib/openal-soft/common/rwlock.c new file mode 100644 index 000000000..cfa3aee4e --- /dev/null +++ b/Engine/lib/openal-soft/common/rwlock.c @@ -0,0 +1,57 @@ + +#include "config.h" + +#include "rwlock.h" + +#include "bool.h" +#include "atomic.h" +#include "threads.h" + + +/* A simple spinlock. Yield the thread while the given integer is set by + * another. Could probably be improved... */ +#define LOCK(l) do { \ + while(ATOMIC_EXCHANGE(int, &(l), true) == true) \ + althrd_yield(); \ +} while(0) +#define UNLOCK(l) ATOMIC_STORE(&(l), false) + + +void RWLockInit(RWLock *lock) +{ + InitRef(&lock->read_count, 0); + InitRef(&lock->write_count, 0); + ATOMIC_INIT(&lock->read_lock, false); + ATOMIC_INIT(&lock->read_entry_lock, false); + ATOMIC_INIT(&lock->write_lock, false); +} + +void ReadLock(RWLock *lock) +{ + LOCK(lock->read_entry_lock); + LOCK(lock->read_lock); + if(IncrementRef(&lock->read_count) == 1) + LOCK(lock->write_lock); + UNLOCK(lock->read_lock); + UNLOCK(lock->read_entry_lock); +} + +void ReadUnlock(RWLock *lock) +{ + if(DecrementRef(&lock->read_count) == 0) + UNLOCK(lock->write_lock); +} + +void WriteLock(RWLock *lock) +{ + if(IncrementRef(&lock->write_count) == 1) + LOCK(lock->read_lock); + LOCK(lock->write_lock); +} + +void WriteUnlock(RWLock *lock) +{ + UNLOCK(lock->write_lock); + if(DecrementRef(&lock->write_count) == 0) + UNLOCK(lock->read_lock); +} diff --git a/Engine/lib/openal-soft/common/threads.c b/Engine/lib/openal-soft/common/threads.c new file mode 100644 index 000000000..0a019d036 --- /dev/null +++ b/Engine/lib/openal-soft/common/threads.c @@ -0,0 +1,747 @@ +/** + * 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 "threads.h" + +#include +#include +#include + +#include "uintmap.h" + + +extern inline althrd_t althrd_current(void); +extern inline int althrd_equal(althrd_t thr0, althrd_t thr1); +extern inline void althrd_exit(int res); +extern inline void althrd_yield(void); + +extern inline int almtx_lock(almtx_t *mtx); +extern inline int almtx_unlock(almtx_t *mtx); +extern inline int almtx_trylock(almtx_t *mtx); + +extern inline void *altss_get(altss_t tss_id); +extern inline int altss_set(altss_t tss_id, void *val); + + +#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 + + +#define THREAD_STACK_SIZE (2*1024*1024) /* 2MB */ + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include + + +void althrd_setname(althrd_t thr, const char *name) +{ +#if defined(_MSC_VER) +#define MS_VC_EXCEPTION 0x406D1388 +#pragma pack(push,8) + struct { + DWORD dwType; // Must be 0x1000. + LPCSTR szName; // Pointer to name (in user addr space). + DWORD dwThreadID; // Thread ID (-1=caller thread). + DWORD dwFlags; // Reserved for future use, must be zero. + } info; +#pragma pack(pop) + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = thr; + info.dwFlags = 0; + + __try { + RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); + } + __except(EXCEPTION_CONTINUE_EXECUTION) { + } +#undef MS_VC_EXCEPTION +#else + (void)thr; + (void)name; +#endif +} + + +static UIntMap ThrdIdHandle = UINTMAP_STATIC_INITIALIZE; + +static void NTAPI althrd_callback(void* UNUSED(handle), DWORD reason, void* UNUSED(reserved)) +{ + if(reason == DLL_PROCESS_DETACH) + ResetUIntMap(&ThrdIdHandle); +} +#ifdef _MSC_VER +#pragma section(".CRT$XLC",read) +__declspec(allocate(".CRT$XLC")) PIMAGE_TLS_CALLBACK althrd_callback_ = althrd_callback; +#elif defined(__GNUC__) +PIMAGE_TLS_CALLBACK althrd_callback_ __attribute__((section(".CRT$XLC"))) = althrd_callback; +#else +PIMAGE_TLS_CALLBACK althrd_callback_ = althrd_callback; +#endif + + +typedef struct thread_cntr { + althrd_start_t func; + void *arg; +} thread_cntr; + +static DWORD WINAPI althrd_starter(void *arg) +{ + thread_cntr cntr; + memcpy(&cntr, arg, sizeof(cntr)); + free(arg); + + return (DWORD)((*cntr.func)(cntr.arg)); +} + + +int althrd_create(althrd_t *thr, althrd_start_t func, void *arg) +{ + thread_cntr *cntr; + DWORD thrid; + HANDLE hdl; + + cntr = malloc(sizeof(*cntr)); + if(!cntr) return althrd_nomem; + + cntr->func = func; + cntr->arg = arg; + + hdl = CreateThread(NULL, THREAD_STACK_SIZE, althrd_starter, cntr, 0, &thrid); + if(!hdl) + { + free(cntr); + return althrd_error; + } + InsertUIntMapEntry(&ThrdIdHandle, thrid, hdl); + + *thr = thrid; + return althrd_success; +} + +int althrd_detach(althrd_t thr) +{ + HANDLE hdl = RemoveUIntMapKey(&ThrdIdHandle, thr); + if(!hdl) return althrd_error; + + CloseHandle(hdl); + return althrd_success; +} + +int althrd_join(althrd_t thr, int *res) +{ + DWORD code; + + HANDLE hdl = RemoveUIntMapKey(&ThrdIdHandle, thr); + if(!hdl) return althrd_error; + + WaitForSingleObject(hdl, INFINITE); + GetExitCodeThread(hdl, &code); + CloseHandle(hdl); + + if(res != NULL) + *res = (int)code; + return althrd_success; +} + +int althrd_sleep(const struct timespec *ts, struct timespec* UNUSED(rem)) +{ + DWORD msec; + + if(ts->tv_sec < 0 || ts->tv_sec >= (0x7fffffff / 1000) || + ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000) + return -2; + + msec = (DWORD)(ts->tv_sec * 1000); + msec += (DWORD)((ts->tv_nsec+999999) / 1000000); + Sleep(msec); + + return 0; +} + + +int almtx_init(almtx_t *mtx, int type) +{ + if(!mtx) return althrd_error; + + type &= ~almtx_recursive; + if(type != almtx_plain) + return althrd_error; + + InitializeCriticalSection(mtx); + return althrd_success; +} + +void almtx_destroy(almtx_t *mtx) +{ + DeleteCriticalSection(mtx); +} + +int almtx_timedlock(almtx_t* UNUSED(mtx), const struct timespec* UNUSED(ts)) +{ + /* Windows CRITICAL_SECTIONs don't seem to have a timedlock method. */ + return althrd_error; +} + +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 +int alcnd_init(alcnd_t *cond) +{ + InitializeConditionVariable(cond); + return althrd_success; +} + +int alcnd_signal(alcnd_t *cond) +{ + WakeConditionVariable(cond); + return althrd_success; +} + +int alcnd_broadcast(alcnd_t *cond) +{ + WakeAllConditionVariable(cond); + return althrd_success; +} + +int alcnd_wait(alcnd_t *cond, almtx_t *mtx) +{ + if(SleepConditionVariableCS(cond, mtx, INFINITE) != 0) + return althrd_success; + return althrd_error; +} + +int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_point) +{ + struct timespec curtime; + DWORD sleeptime; + + if(altimespec_get(&curtime, AL_TIME_UTC) != AL_TIME_UTC) + return althrd_error; + + if(curtime.tv_sec > time_point->tv_sec || (curtime.tv_sec == time_point->tv_sec && + curtime.tv_nsec >= time_point->tv_nsec)) + { + if(SleepConditionVariableCS(cond, mtx, 0) != 0) + return althrd_success; + } + else + { + sleeptime = (time_point->tv_nsec - curtime.tv_nsec + 999999)/1000000; + sleeptime += (time_point->tv_sec - curtime.tv_sec)*1000; + if(SleepConditionVariableCS(cond, mtx, sleeptime) != 0) + return althrd_success; + } + return (GetLastError()==ERROR_TIMEOUT) ? althrd_timedout : althrd_error; +} + +void alcnd_destroy(alcnd_t* UNUSED(cond)) +{ + /* Nothing to delete? */ +} + +#else + +/* WARNING: This is a rather poor implementation of condition variables, with + * known problems. However, it's simple, efficient, and good enough for now to + * not require Vista. Based on "Strategies for Implementing POSIX Condition + * Variables" by Douglas C. Schmidt and Irfan Pyarali: + * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html + */ +/* A better solution may be using Wine's implementation. It requires internals + * (NtCreateKeyedEvent, NtReleaseKeyedEvent, and NtWaitForKeyedEvent) from + * ntdll, and implemention of exchange and compare-exchange for RefCounts. + */ + +typedef struct { + RefCount wait_count; + + HANDLE events[2]; +} _int_alcnd_t; +enum { + SIGNAL = 0, + BROADCAST = 1 +}; + +int alcnd_init(alcnd_t *cond) +{ + _int_alcnd_t *icond = calloc(1, sizeof(*icond)); + if(!icond) return althrd_nomem; + + InitRef(&icond->wait_count, 0); + + icond->events[SIGNAL] = CreateEventW(NULL, FALSE, FALSE, NULL); + icond->events[BROADCAST] = CreateEventW(NULL, TRUE, FALSE, NULL); + if(!icond->events[SIGNAL] || !icond->events[BROADCAST]) + { + if(icond->events[SIGNAL]) + CloseHandle(icond->events[SIGNAL]); + if(icond->events[BROADCAST]) + CloseHandle(icond->events[BROADCAST]); + free(icond); + return althrd_error; + } + + cond->Ptr = icond; + return althrd_success; +} + +int alcnd_signal(alcnd_t *cond) +{ + _int_alcnd_t *icond = cond->Ptr; + if(ReadRef(&icond->wait_count) > 0) + SetEvent(icond->events[SIGNAL]); + return althrd_success; +} + +int alcnd_broadcast(alcnd_t *cond) +{ + _int_alcnd_t *icond = cond->Ptr; + if(ReadRef(&icond->wait_count) > 0) + SetEvent(icond->events[BROADCAST]); + return althrd_success; +} + +int alcnd_wait(alcnd_t *cond, almtx_t *mtx) +{ + _int_alcnd_t *icond = cond->Ptr; + int res; + + IncrementRef(&icond->wait_count); + LeaveCriticalSection(mtx); + + res = WaitForMultipleObjects(2, icond->events, FALSE, INFINITE); + + if(DecrementRef(&icond->wait_count) == 0 && res == WAIT_OBJECT_0+BROADCAST) + ResetEvent(icond->events[BROADCAST]); + EnterCriticalSection(mtx); + + return althrd_success; +} + +int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_point) +{ + _int_alcnd_t *icond = cond->Ptr; + struct timespec curtime; + DWORD sleeptime; + int res; + + if(altimespec_get(&curtime, AL_TIME_UTC) != AL_TIME_UTC) + return althrd_error; + + if(curtime.tv_sec > time_point->tv_sec || (curtime.tv_sec == time_point->tv_sec && + curtime.tv_nsec >= time_point->tv_nsec)) + sleeptime = 0; + else + { + sleeptime = (time_point->tv_nsec - curtime.tv_nsec + 999999)/1000000; + sleeptime += (time_point->tv_sec - curtime.tv_sec)*1000; + } + + IncrementRef(&icond->wait_count); + LeaveCriticalSection(mtx); + + res = WaitForMultipleObjects(2, icond->events, FALSE, sleeptime); + + if(DecrementRef(&icond->wait_count) == 0 && res == WAIT_OBJECT_0+BROADCAST) + ResetEvent(icond->events[BROADCAST]); + EnterCriticalSection(mtx); + + return (res == WAIT_TIMEOUT) ? althrd_timedout : althrd_success; +} + +void alcnd_destroy(alcnd_t *cond) +{ + _int_alcnd_t *icond = cond->Ptr; + CloseHandle(icond->events[SIGNAL]); + CloseHandle(icond->events[BROADCAST]); + free(icond); +} +#endif /* defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 */ + + +/* An associative map of uint:void* pairs. The key is the TLS index (given by + * TlsAlloc), and the value is the altss_dtor_t callback. When a thread exits, + * we iterate over the TLS indices for their thread-local value and call the + * destructor function with it if they're both not NULL. To avoid using + * DllMain, a PIMAGE_TLS_CALLBACK function pointer is placed in a ".CRT$XLx" + * section (where x is a character A to Z) which will be called by the CRT. + */ +static UIntMap TlsDestructors = UINTMAP_STATIC_INITIALIZE; + +static void NTAPI altss_callback(void* UNUSED(handle), DWORD reason, void* UNUSED(reserved)) +{ + ALsizei i; + + if(reason == DLL_PROCESS_DETACH) + { + ResetUIntMap(&TlsDestructors); + return; + } + if(reason != DLL_THREAD_DETACH) + return; + + LockUIntMapRead(&TlsDestructors); + for(i = 0;i < TlsDestructors.size;i++) + { + void *ptr = altss_get(TlsDestructors.keys[i]); + altss_dtor_t callback = (altss_dtor_t)TlsDestructors.values[i]; + if(ptr && callback) + callback(ptr); + } + UnlockUIntMapRead(&TlsDestructors); +} +#ifdef _MSC_VER +#pragma section(".CRT$XLB",read) +__declspec(allocate(".CRT$XLB")) PIMAGE_TLS_CALLBACK altss_callback_ = altss_callback; +#elif defined(__GNUC__) +PIMAGE_TLS_CALLBACK altss_callback_ __attribute__((section(".CRT$XLB"))) = altss_callback; +#else +#warning "No TLS callback support, thread-local contexts may leak references on poorly written applications." +PIMAGE_TLS_CALLBACK altss_callback_ = altss_callback; +#endif + +int altss_create(altss_t *tss_id, altss_dtor_t callback) +{ + DWORD key = TlsAlloc(); + if(key == TLS_OUT_OF_INDEXES) + return althrd_error; + + *tss_id = key; + if(callback != NULL) + InsertUIntMapEntry(&TlsDestructors, key, callback); + return althrd_success; +} + +void altss_delete(altss_t tss_id) +{ + RemoveUIntMapKey(&TlsDestructors, tss_id); + TlsFree(tss_id); +} + + +int altimespec_get(struct timespec *ts, int base) +{ + static_assert(sizeof(FILETIME) == sizeof(ULARGE_INTEGER), + "Size of FILETIME does not match ULARGE_INTEGER"); + if(base == AL_TIME_UTC) + { + union { + FILETIME ftime; + ULARGE_INTEGER ulint; + } systime; + GetSystemTimeAsFileTime(&systime.ftime); + /* FILETIME is in 100-nanosecond units, or 1/10th of a microsecond. */ + ts->tv_sec = systime.ulint.QuadPart/10000000; + ts->tv_nsec = (systime.ulint.QuadPart%10000000) * 100; + return base; + } + + return 0; +} + + +void alcall_once(alonce_flag *once, void (*callback)(void)) +{ + LONG ret; + while((ret=InterlockedExchange(once, 1)) == 1) + althrd_yield(); + if(ret == 0) + (*callback)(); + InterlockedExchange(once, 2); +} + +#else + +#include +#include +#include +#ifdef HAVE_PTHREAD_NP_H +#include +#endif + + +extern inline int althrd_sleep(const struct timespec *ts, struct timespec *rem); +extern inline void alcall_once(alonce_flag *once, void (*callback)(void)); + + +void althrd_setname(althrd_t thr, const char *name) +{ +#if defined(HAVE_PTHREAD_SETNAME_NP) +#if defined(PTHREAD_SETNAME_NP_ONE_PARAM) + if(althrd_equal(thr, althrd_current())) + pthread_setname_np(name); +#else + pthread_setname_np(thr, name); +#endif +#elif defined(HAVE_PTHREAD_SET_NAME_NP) + pthread_set_name_np(thr, name); +#else + (void)thr; + (void)name; +#endif +} + + +typedef struct thread_cntr { + althrd_start_t func; + void *arg; +} thread_cntr; + +static void *althrd_starter(void *arg) +{ + thread_cntr cntr; + memcpy(&cntr, arg, sizeof(cntr)); + free(arg); + + return (void*)(intptr_t)((*cntr.func)(cntr.arg)); +} + + +int althrd_create(althrd_t *thr, althrd_start_t func, void *arg) +{ + thread_cntr *cntr; + pthread_attr_t attr; + size_t stackmult = 1; + int err; + + cntr = malloc(sizeof(*cntr)); + if(!cntr) return althrd_nomem; + + if(pthread_attr_init(&attr) != 0) + { + free(cntr); + return althrd_error; + } +retry_stacksize: + if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE*stackmult) != 0) + { + pthread_attr_destroy(&attr); + free(cntr); + return althrd_error; + } + + cntr->func = func; + cntr->arg = arg; + if((err=pthread_create(thr, &attr, althrd_starter, cntr)) == 0) + { + pthread_attr_destroy(&attr); + return althrd_success; + } + + if(err == EINVAL) + { + /* If an invalid stack size, try increasing it (limit x4, 8MB). */ + if(stackmult < 4) + { + stackmult *= 2; + goto retry_stacksize; + } + /* If still nothing, try defaults and hope they're good enough. */ + if(pthread_create(thr, NULL, althrd_starter, cntr) == 0) + { + pthread_attr_destroy(&attr); + return althrd_success; + } + } + pthread_attr_destroy(&attr); + free(cntr); + return althrd_error; +} + +int althrd_detach(althrd_t thr) +{ + if(pthread_detach(thr) != 0) + return althrd_error; + return althrd_success; +} + +int althrd_join(althrd_t thr, int *res) +{ + void *code; + + if(pthread_join(thr, &code) != 0) + return althrd_error; + if(res != NULL) + *res = (int)(intptr_t)code; + return althrd_success; +} + + +int almtx_init(almtx_t *mtx, int type) +{ + int ret; + + if(!mtx) return althrd_error; +#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK + if((type&~(almtx_recursive|almtx_timed)) != 0) + return althrd_error; +#else + if((type&~almtx_recursive) != 0) + return althrd_error; +#endif + + type &= ~almtx_timed; + if(type == almtx_plain) + ret = pthread_mutex_init(mtx, NULL); + else + { + pthread_mutexattr_t attr; + + ret = pthread_mutexattr_init(&attr); + if(ret) return althrd_error; + + if(type == almtx_recursive) + { + ret = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); +#ifdef HAVE_PTHREAD_MUTEXATTR_SETKIND_NP + if(ret != 0) + ret = pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE); +#endif + } + else + ret = 1; + if(ret == 0) + ret = pthread_mutex_init(mtx, &attr); + pthread_mutexattr_destroy(&attr); + } + return ret ? althrd_error : althrd_success; +} + +void almtx_destroy(almtx_t *mtx) +{ + pthread_mutex_destroy(mtx); +} + +int almtx_timedlock(almtx_t *mtx, const struct timespec *ts) +{ +#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK + int ret = pthread_mutex_timedlock(mtx, ts); + switch(ret) + { + case 0: return althrd_success; + case ETIMEDOUT: return althrd_timedout; + case EBUSY: return althrd_busy; + } +#endif + return althrd_error; +} + +int alcnd_init(alcnd_t *cond) +{ + if(pthread_cond_init(cond, NULL) == 0) + return althrd_success; + return althrd_error; +} + +int alcnd_signal(alcnd_t *cond) +{ + if(pthread_cond_signal(cond) == 0) + return althrd_success; + return althrd_error; +} + +int alcnd_broadcast(alcnd_t *cond) +{ + if(pthread_cond_broadcast(cond) == 0) + return althrd_success; + return althrd_error; +} + +int alcnd_wait(alcnd_t *cond, almtx_t *mtx) +{ + if(pthread_cond_wait(cond, mtx) == 0) + return althrd_success; + return althrd_error; +} + +int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_point) +{ + if(pthread_cond_timedwait(cond, mtx, time_point) == 0) + return althrd_success; + return althrd_error; +} + +void alcnd_destroy(alcnd_t *cond) +{ + pthread_cond_destroy(cond); +} + + +int altss_create(altss_t *tss_id, altss_dtor_t callback) +{ + if(pthread_key_create(tss_id, callback) != 0) + return althrd_error; + return althrd_success; +} + +void altss_delete(altss_t tss_id) +{ + pthread_key_delete(tss_id); +} + + +int altimespec_get(struct timespec *ts, int base) +{ + if(base == AL_TIME_UTC) + { + int ret; +#if _POSIX_TIMERS > 0 + ret = clock_gettime(CLOCK_REALTIME, ts); + if(ret == 0) return base; +#else /* _POSIX_TIMERS > 0 */ + struct timeval tv; + ret = gettimeofday(&tv, NULL); + if(ret == 0) + { + ts->tv_sec = tv.tv_sec; + ts->tv_nsec = tv.tv_usec * 1000; + return base; + } +#endif + } + + return 0; +} + +#endif + + +void al_nssleep(unsigned long nsec) +{ + struct timespec ts, rem; + ts.tv_sec = nsec / 1000000000ul; + ts.tv_nsec = nsec % 1000000000ul; + + while(althrd_sleep(&ts, &rem) == -1) + ts = rem; +} diff --git a/Engine/lib/openal-soft/common/uintmap.c b/Engine/lib/openal-soft/common/uintmap.c new file mode 100644 index 000000000..d3b519236 --- /dev/null +++ b/Engine/lib/openal-soft/common/uintmap.c @@ -0,0 +1,228 @@ + +#include "config.h" + +#include "uintmap.h" + +#include +#include + +#include "almalloc.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->keys = NULL; + map->values = NULL; + map->size = 0; + map->capacity = 0; + map->limit = limit; + RWLockInit(&map->lock); +} + +void ResetUIntMap(UIntMap *map) +{ + WriteLock(&map->lock); + al_free(map->keys); + map->keys = NULL; + map->values = NULL; + map->size = 0; + map->capacity = 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->keys[mid] < key) + low = mid + 1; + else + high = mid; + } + if(map->keys[low] < key) + low++; + pos = low; + } + + if(pos == map->size || map->keys[pos] != key) + { + if(map->size == map->limit) + { + WriteUnlock(&map->lock); + return AL_OUT_OF_MEMORY; + } + + if(map->size == map->capacity) + { + ALuint *keys = NULL; + ALvoid **values; + ALsizei newcap, keylen; + + newcap = (map->capacity ? (map->capacity<<1) : 4); + if(map->limit > 0 && newcap > map->limit) + newcap = map->limit; + if(newcap > map->capacity) + { + /* Round the memory size for keys up to a multiple of the + * pointer size. + */ + keylen = newcap * sizeof(map->keys[0]); + keylen += sizeof(map->values[0]) - 1; + keylen -= keylen%sizeof(map->values[0]); + + keys = al_malloc(16, keylen + newcap*sizeof(map->values[0])); + } + if(!keys) + { + WriteUnlock(&map->lock); + return AL_OUT_OF_MEMORY; + } + values = (ALvoid**)((ALbyte*)keys + keylen); + + if(map->keys) + { + memcpy(keys, map->keys, map->size*sizeof(map->keys[0])); + memcpy(values, map->values, map->size*sizeof(map->values[0])); + } + al_free(map->keys); + map->keys = keys; + map->values = values; + map->capacity = newcap; + } + + if(pos < map->size) + { + memmove(&map->keys[pos+1], &map->keys[pos], + (map->size-pos)*sizeof(map->keys[0])); + memmove(&map->values[pos+1], &map->values[pos], + (map->size-pos)*sizeof(map->values[0])); + } + map->size++; + } + map->keys[pos] = key; + map->values[pos] = 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->keys[mid] < key) + low = mid + 1; + else + high = mid; + } + if(map->keys[low] == key) + { + ptr = map->values[low]; + if(low < map->size-1) + { + memmove(&map->keys[low], &map->keys[low+1], + (map->size-1-low)*sizeof(map->keys[0])); + memmove(&map->values[low], &map->values[low+1], + (map->size-1-low)*sizeof(map->values[0])); + } + map->size--; + } + } + WriteUnlock(&map->lock); + return ptr; +} + +ALvoid *RemoveUIntMapKeyNoLock(UIntMap *map, ALuint key) +{ + if(map->size > 0) + { + ALsizei low = 0; + ALsizei high = map->size - 1; + while(low < high) + { + ALsizei mid = low + (high-low)/2; + if(map->keys[mid] < key) + low = mid + 1; + else + high = mid; + } + if(map->keys[low] == key) + { + ALvoid *ptr = map->values[low]; + if(low < map->size-1) + { + memmove(&map->keys[low], &map->keys[low+1], + (map->size-1-low)*sizeof(map->keys[0])); + memmove(&map->values[low], &map->values[low+1], + (map->size-1-low)*sizeof(map->values[0])); + } + map->size--; + return ptr; + } + } + return NULL; +} + +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->keys[mid] < key) + low = mid + 1; + else + high = mid; + } + if(map->keys[low] == key) + ptr = map->values[low]; + } + ReadUnlock(&map->lock); + return ptr; +} + +ALvoid *LookupUIntMapKeyNoLock(UIntMap *map, ALuint key) +{ + if(map->size > 0) + { + ALsizei low = 0; + ALsizei high = map->size - 1; + while(low < high) + { + ALsizei mid = low + (high-low)/2; + if(map->keys[mid] < key) + low = mid + 1; + else + high = mid; + } + if(map->keys[low] == key) + return map->values[low]; + } + return NULL; +} diff --git a/Engine/lib/openal-soft/config.h.in b/Engine/lib/openal-soft/config.h.in new file mode 100644 index 000000000..a06c2039a --- /dev/null +++ b/Engine/lib/openal-soft/config.h.in @@ -0,0 +1,204 @@ +/* API declaration export attribute */ +#define AL_API ${EXPORT_DECL} +#define ALC_API ${EXPORT_DECL} + +/* Define to the library version */ +#define ALSOFT_VERSION "${LIB_VERSION}" + +/* Define any available alignment declaration */ +#define ALIGN(x) ${ALIGN_DECL} + +/* Explicit hidden visibility attribute */ +#define HIDDEN_DECL ${HIDDEN_DECL} + +/* Define if HRTF data is embedded in the library */ +#cmakedefine ALSOFT_EMBED_HRTF_DATA + +/* Define if we have the C11 aligned_alloc function */ +#cmakedefine HAVE_ALIGNED_ALLOC + +/* Define if we have the posix_memalign function */ +#cmakedefine HAVE_POSIX_MEMALIGN + +/* Define if we have the _aligned_malloc function */ +#cmakedefine HAVE__ALIGNED_MALLOC + +/* Define if we have SSE CPU extensions */ +#cmakedefine HAVE_SSE +#cmakedefine HAVE_SSE2 +#cmakedefine HAVE_SSE3 +#cmakedefine HAVE_SSE4_1 + +/* Define if we have ARM Neon CPU extensions */ +#cmakedefine HAVE_NEON + +/* Define if we have the ALSA backend */ +#cmakedefine HAVE_ALSA + +/* Define if we have the OSS backend */ +#cmakedefine HAVE_OSS + +/* Define if we have the Solaris backend */ +#cmakedefine HAVE_SOLARIS + +/* Define if we have the SndIO backend */ +#cmakedefine HAVE_SNDIO + +/* Define if we have the QSA backend */ +#cmakedefine HAVE_QSA + +/* Define if we have the MMDevApi backend */ +#cmakedefine HAVE_MMDEVAPI + +/* Define if we have the DSound backend */ +#cmakedefine HAVE_DSOUND + +/* Define if we have the Windows Multimedia backend */ +#cmakedefine HAVE_WINMM + +/* Define if we have the PortAudio backend */ +#cmakedefine HAVE_PORTAUDIO + +/* Define if we have the PulseAudio backend */ +#cmakedefine HAVE_PULSEAUDIO + +/* Define if we have the JACK backend */ +#cmakedefine HAVE_JACK + +/* Define if we have the CoreAudio backend */ +#cmakedefine HAVE_COREAUDIO + +/* Define if we have the OpenSL backend */ +#cmakedefine HAVE_OPENSL + +/* Define if we have the Wave Writer backend */ +#cmakedefine HAVE_WAVE + +/* Define if we have the stat function */ +#cmakedefine HAVE_STAT + +/* Define if we have the lrintf function */ +#cmakedefine HAVE_LRINTF + +/* Define if we have the modff function */ +#cmakedefine HAVE_MODFF + +/* Define if we have the strtof function */ +#cmakedefine HAVE_STRTOF + +/* Define if we have the strnlen function */ +#cmakedefine HAVE_STRNLEN + +/* Define if we have the __int64 type */ +#cmakedefine HAVE___INT64 + +/* Define to the size of a long int type */ +#cmakedefine SIZEOF_LONG ${SIZEOF_LONG} + +/* Define to the size of a long long int type */ +#cmakedefine SIZEOF_LONG_LONG ${SIZEOF_LONG_LONG} + +/* Define if we have C99 variable-length array support */ +#cmakedefine HAVE_C99_VLA + +/* Define if we have C99 _Bool support */ +#cmakedefine HAVE_C99_BOOL + +/* Define if we have C11 _Static_assert support */ +#cmakedefine HAVE_C11_STATIC_ASSERT + +/* Define if we have C11 _Alignas support */ +#cmakedefine HAVE_C11_ALIGNAS + +/* Define if we have C11 _Atomic support */ +#cmakedefine HAVE_C11_ATOMIC + +/* Define if we have GCC's destructor attribute */ +#cmakedefine HAVE_GCC_DESTRUCTOR + +/* Define if we have GCC's format attribute */ +#cmakedefine HAVE_GCC_FORMAT + +/* Define if we have stdint.h */ +#cmakedefine HAVE_STDINT_H + +/* Define if we have stdbool.h */ +#cmakedefine HAVE_STDBOOL_H + +/* Define if we have stdalign.h */ +#cmakedefine HAVE_STDALIGN_H + +/* Define if we have windows.h */ +#cmakedefine HAVE_WINDOWS_H + +/* Define if we have dlfcn.h */ +#cmakedefine HAVE_DLFCN_H + +/* Define if we have pthread_np.h */ +#cmakedefine HAVE_PTHREAD_NP_H + +/* Define if we have alloca.h */ +#cmakedefine HAVE_ALLOCA_H + +/* Define if we have malloc.h */ +#cmakedefine HAVE_MALLOC_H + +/* Define if we have dirent.h */ +#cmakedefine HAVE_DIRENT_H + +/* Define if we have strings.h */ +#cmakedefine HAVE_STRINGS_H + +/* Define if we have cpuid.h */ +#cmakedefine HAVE_CPUID_H + +/* Define if we have intrin.h */ +#cmakedefine HAVE_INTRIN_H + +/* Define if we have sys/sysconf.h */ +#cmakedefine HAVE_SYS_SYSCONF_H + +/* Define if we have guiddef.h */ +#cmakedefine HAVE_GUIDDEF_H + +/* Define if we have initguid.h */ +#cmakedefine HAVE_INITGUID_H + +/* Define if we have ieeefp.h */ +#cmakedefine HAVE_IEEEFP_H + +/* Define if we have float.h */ +#cmakedefine HAVE_FLOAT_H + +/* Define if we have fenv.h */ +#cmakedefine HAVE_FENV_H + +/* Define if we have GCC's __get_cpuid() */ +#cmakedefine HAVE_GCC_GET_CPUID + +/* Define if we have the __cpuid() intrinsic */ +#cmakedefine HAVE_CPUID_INTRINSIC + +/* Define if we have _controlfp() */ +#cmakedefine HAVE__CONTROLFP + +/* Define if we have __control87_2() */ +#cmakedefine HAVE___CONTROL87_2 + +/* Define if we have pthread_setschedparam() */ +#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM + +/* Define if we have pthread_setname_np() */ +#cmakedefine HAVE_PTHREAD_SETNAME_NP + +/* Define if pthread_setname_np() only accepts one parameter */ +#cmakedefine PTHREAD_SETNAME_NP_ONE_PARAM + +/* Define if we have pthread_set_name_np() */ +#cmakedefine HAVE_PTHREAD_SET_NAME_NP + +/* Define if we have pthread_mutexattr_setkind_np() */ +#cmakedefine HAVE_PTHREAD_MUTEXATTR_SETKIND_NP + +/* Define if we have pthread_mutex_timedlock() */ +#cmakedefine HAVE_PTHREAD_MUTEX_TIMEDLOCK diff --git a/Engine/lib/openal-soft/include/AL/al.h b/Engine/lib/openal-soft/include/AL/al.h new file mode 100644 index 000000000..413b38331 --- /dev/null +++ b/Engine/lib/openal-soft/include/AL/al.h @@ -0,0 +1,656 @@ +#ifndef AL_AL_H +#define AL_AL_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef AL_API + #if defined(AL_LIBTYPE_STATIC) + #define AL_API + #elif defined(_WIN32) + #define AL_API __declspec(dllimport) + #else + #define AL_API extern + #endif +#endif + +#if defined(_WIN32) + #define AL_APIENTRY __cdecl +#else + #define AL_APIENTRY +#endif + + +/** Deprecated macro. */ +#define OPENAL +#define ALAPI AL_API +#define ALAPIENTRY AL_APIENTRY +#define AL_INVALID (-1) +#define AL_ILLEGAL_ENUM AL_INVALID_ENUM +#define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION + +/** Supported AL version. */ +#define AL_VERSION_1_0 +#define AL_VERSION_1_1 + +/** 8-bit boolean */ +typedef char ALboolean; + +/** character */ +typedef char ALchar; + +/** signed 8-bit 2's complement integer */ +typedef signed char ALbyte; + +/** unsigned 8-bit integer */ +typedef unsigned char ALubyte; + +/** signed 16-bit 2's complement integer */ +typedef short ALshort; + +/** unsigned 16-bit integer */ +typedef unsigned short ALushort; + +/** signed 32-bit 2's complement integer */ +typedef int ALint; + +/** unsigned 32-bit integer */ +typedef unsigned int ALuint; + +/** non-negative 32-bit binary integer size */ +typedef int ALsizei; + +/** enumerated 32-bit value */ +typedef int ALenum; + +/** 32-bit IEEE754 floating-point */ +typedef float ALfloat; + +/** 64-bit IEEE754 floating-point */ +typedef double ALdouble; + +/** void type (for opaque pointers only) */ +typedef void ALvoid; + + +/* Enumerant values begin at column 50. No tabs. */ + +/** "no distance model" or "no buffer" */ +#define AL_NONE 0 + +/** Boolean False. */ +#define AL_FALSE 0 + +/** Boolean True. */ +#define AL_TRUE 1 + + +/** + * Relative source. + * Type: ALboolean + * Range: [AL_TRUE, AL_FALSE] + * Default: AL_FALSE + * + * Specifies if the Source has relative coordinates. + */ +#define AL_SOURCE_RELATIVE 0x202 + + +/** + * Inner cone angle, in degrees. + * Type: ALint, ALfloat + * Range: [0 - 360] + * Default: 360 + * + * The angle covered by the inner cone, where the source will not attenuate. + */ +#define AL_CONE_INNER_ANGLE 0x1001 + +/** + * Outer cone angle, in degrees. + * Range: [0 - 360] + * Default: 360 + * + * The angle covered by the outer cone, where the source will be fully + * attenuated. + */ +#define AL_CONE_OUTER_ANGLE 0x1002 + +/** + * Source pitch. + * Type: ALfloat + * Range: [0.5 - 2.0] + * Default: 1.0 + * + * A multiplier for the frequency (sample rate) of the source's buffer. + */ +#define AL_PITCH 0x1003 + +/** + * Source or listener position. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * The source or listener location in three dimensional space. + * + * OpenAL, like OpenGL, uses a right handed coordinate system, where in a + * frontal default view X (thumb) points right, Y points up (index finger), and + * Z points towards the viewer/camera (middle finger). + * + * To switch from a left handed coordinate system, flip the sign on the Z + * coordinate. + */ +#define AL_POSITION 0x1004 + +/** + * Source direction. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * Specifies the current direction in local space. + * A zero-length vector specifies an omni-directional source (cone is ignored). + */ +#define AL_DIRECTION 0x1005 + +/** + * Source or listener velocity. + * Type: ALfloat[3], ALint[3] + * Default: {0, 0, 0} + * + * Specifies the current velocity in local space. + */ +#define AL_VELOCITY 0x1006 + +/** + * Source looping. + * Type: ALboolean + * Range: [AL_TRUE, AL_FALSE] + * Default: AL_FALSE + * + * Specifies whether source is looping. + */ +#define AL_LOOPING 0x1007 + +/** + * Source buffer. + * Type: ALuint + * Range: any valid Buffer. + * + * Specifies the buffer to provide sound samples. + */ +#define AL_BUFFER 0x1009 + +/** + * Source or listener gain. + * Type: ALfloat + * Range: [0.0 - ] + * + * A value of 1.0 means unattenuated. Each division by 2 equals an attenuation + * of about -6dB. Each multiplicaton by 2 equals an amplification of about + * +6dB. + * + * A value of 0.0 is meaningless with respect to a logarithmic scale; it is + * silent. + */ +#define AL_GAIN 0x100A + +/** + * Minimum source gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * + * The minimum gain allowed for a source, after distance and cone attenation is + * applied (if applicable). + */ +#define AL_MIN_GAIN 0x100D + +/** + * Maximum source gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * + * The maximum gain allowed for a source, after distance and cone attenation is + * applied (if applicable). + */ +#define AL_MAX_GAIN 0x100E + +/** + * Listener orientation. + * Type: ALfloat[6] + * Default: {0.0, 0.0, -1.0, 0.0, 1.0, 0.0} + * + * Effectively two three dimensional vectors. The first vector is the front (or + * "at") and the second is the top (or "up"). + * + * Both vectors are in local space. + */ +#define AL_ORIENTATION 0x100F + +/** + * Source state (query only). + * Type: ALint + * Range: [AL_INITIAL, AL_PLAYING, AL_PAUSED, AL_STOPPED] + */ +#define AL_SOURCE_STATE 0x1010 + +/** Source state value. */ +#define AL_INITIAL 0x1011 +#define AL_PLAYING 0x1012 +#define AL_PAUSED 0x1013 +#define AL_STOPPED 0x1014 + +/** + * Source Buffer Queue size (query only). + * Type: ALint + * + * The number of buffers queued using alSourceQueueBuffers, minus the buffers + * removed with alSourceUnqueueBuffers. + */ +#define AL_BUFFERS_QUEUED 0x1015 + +/** + * Source Buffer Queue processed count (query only). + * Type: ALint + * + * The number of queued buffers that have been fully processed, and can be + * removed with alSourceUnqueueBuffers. + * + * Looping sources will never fully process buffers because they will be set to + * play again for when the source loops. + */ +#define AL_BUFFERS_PROCESSED 0x1016 + +/** + * Source reference distance. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * The distance in units that no attenuation occurs. + * + * At 0.0, no distance attenuation ever occurs on non-linear attenuation models. + */ +#define AL_REFERENCE_DISTANCE 0x1020 + +/** + * Source rolloff factor. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * Multiplier to exaggerate or diminish distance attenuation. + * + * At 0.0, no distance attenuation ever occurs. + */ +#define AL_ROLLOFF_FACTOR 0x1021 + +/** + * Outer cone gain. + * Type: ALfloat + * Range: [0.0 - 1.0] + * Default: 0.0 + * + * The gain attenuation applied when the listener is outside of the source's + * outer cone. + */ +#define AL_CONE_OUTER_GAIN 0x1022 + +/** + * Source maximum distance. + * Type: ALfloat + * Range: [0.0 - ] + * Default: +inf + * + * The distance above which the source is not attenuated any further with a + * clamped distance model, or where attenuation reaches 0.0 gain for linear + * distance models with a default rolloff factor. + */ +#define AL_MAX_DISTANCE 0x1023 + +/** Source buffer position, in seconds */ +#define AL_SEC_OFFSET 0x1024 +/** Source buffer position, in sample frames */ +#define AL_SAMPLE_OFFSET 0x1025 +/** Source buffer position, in bytes */ +#define AL_BYTE_OFFSET 0x1026 + +/** + * Source type (query only). + * Type: ALint + * Range: [AL_STATIC, AL_STREAMING, AL_UNDETERMINED] + * + * A Source is Static if a Buffer has been attached using AL_BUFFER. + * + * A Source is Streaming if one or more Buffers have been attached using + * alSourceQueueBuffers. + * + * A Source is Undetermined when it has the NULL buffer attached using + * AL_BUFFER. + */ +#define AL_SOURCE_TYPE 0x1027 + +/** Source type value. */ +#define AL_STATIC 0x1028 +#define AL_STREAMING 0x1029 +#define AL_UNDETERMINED 0x1030 + +/** Buffer format specifier. */ +#define AL_FORMAT_MONO8 0x1100 +#define AL_FORMAT_MONO16 0x1101 +#define AL_FORMAT_STEREO8 0x1102 +#define AL_FORMAT_STEREO16 0x1103 + +/** Buffer frequency (query only). */ +#define AL_FREQUENCY 0x2001 +/** Buffer bits per sample (query only). */ +#define AL_BITS 0x2002 +/** Buffer channel count (query only). */ +#define AL_CHANNELS 0x2003 +/** Buffer data size (query only). */ +#define AL_SIZE 0x2004 + +/** + * Buffer state. + * + * Not for public use. + */ +#define AL_UNUSED 0x2010 +#define AL_PENDING 0x2011 +#define AL_PROCESSED 0x2012 + + +/** No error. */ +#define AL_NO_ERROR 0 + +/** Invalid name paramater passed to AL call. */ +#define AL_INVALID_NAME 0xA001 + +/** Invalid enum parameter passed to AL call. */ +#define AL_INVALID_ENUM 0xA002 + +/** Invalid value parameter passed to AL call. */ +#define AL_INVALID_VALUE 0xA003 + +/** Illegal AL call. */ +#define AL_INVALID_OPERATION 0xA004 + +/** Not enough memory. */ +#define AL_OUT_OF_MEMORY 0xA005 + + +/** Context string: Vendor ID. */ +#define AL_VENDOR 0xB001 +/** Context string: Version. */ +#define AL_VERSION 0xB002 +/** Context string: Renderer ID. */ +#define AL_RENDERER 0xB003 +/** Context string: Space-separated extension list. */ +#define AL_EXTENSIONS 0xB004 + + +/** + * Doppler scale. + * Type: ALfloat + * Range: [0.0 - ] + * Default: 1.0 + * + * Scale for source and listener velocities. + */ +#define AL_DOPPLER_FACTOR 0xC000 +AL_API void AL_APIENTRY alDopplerFactor(ALfloat value); + +/** + * Doppler velocity (deprecated). + * + * A multiplier applied to the Speed of Sound. + */ +#define AL_DOPPLER_VELOCITY 0xC001 +AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value); + +/** + * Speed of Sound, in units per second. + * Type: ALfloat + * Range: [0.0001 - ] + * Default: 343.3 + * + * The speed at which sound waves are assumed to travel, when calculating the + * doppler effect. + */ +#define AL_SPEED_OF_SOUND 0xC003 +AL_API void AL_APIENTRY alSpeedOfSound(ALfloat value); + +/** + * Distance attenuation model. + * Type: ALint + * Range: [AL_NONE, AL_INVERSE_DISTANCE, AL_INVERSE_DISTANCE_CLAMPED, + * AL_LINEAR_DISTANCE, AL_LINEAR_DISTANCE_CLAMPED, + * AL_EXPONENT_DISTANCE, AL_EXPONENT_DISTANCE_CLAMPED] + * Default: AL_INVERSE_DISTANCE_CLAMPED + * + * The model by which sources attenuate with distance. + * + * None - No distance attenuation. + * Inverse - Doubling the distance halves the source gain. + * Linear - Linear gain scaling between the reference and max distances. + * Exponent - Exponential gain dropoff. + * + * Clamped variations work like the non-clamped counterparts, except the + * distance calculated is clamped between the reference and max distances. + */ +#define AL_DISTANCE_MODEL 0xD000 +AL_API void AL_APIENTRY alDistanceModel(ALenum distanceModel); + +/** Distance model value. */ +#define AL_INVERSE_DISTANCE 0xD001 +#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 +#define AL_LINEAR_DISTANCE 0xD003 +#define AL_LINEAR_DISTANCE_CLAMPED 0xD004 +#define AL_EXPONENT_DISTANCE 0xD005 +#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 + +/** Renderer State management. */ +AL_API void AL_APIENTRY alEnable(ALenum capability); +AL_API void AL_APIENTRY alDisable(ALenum capability); +AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability); + +/** State retrieval. */ +AL_API const ALchar* AL_APIENTRY alGetString(ALenum param); +AL_API void AL_APIENTRY alGetBooleanv(ALenum param, ALboolean *values); +AL_API void AL_APIENTRY alGetIntegerv(ALenum param, ALint *values); +AL_API void AL_APIENTRY alGetFloatv(ALenum param, ALfloat *values); +AL_API void AL_APIENTRY alGetDoublev(ALenum param, ALdouble *values); +AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum param); +AL_API ALint AL_APIENTRY alGetInteger(ALenum param); +AL_API ALfloat AL_APIENTRY alGetFloat(ALenum param); +AL_API ALdouble AL_APIENTRY alGetDouble(ALenum param); + +/** + * Error retrieval. + * + * Obtain the first error generated in the AL context since the last check. + */ +AL_API ALenum AL_APIENTRY alGetError(void); + +/** + * Extension support. + * + * Query for the presence of an extension, and obtain any appropriate function + * pointers and enum values. + */ +AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extname); +AL_API void* AL_APIENTRY alGetProcAddress(const ALchar *fname); +AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *ename); + + +/** Set Listener parameters */ +AL_API void AL_APIENTRY alListenerf(ALenum param, ALfloat value); +AL_API void AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +AL_API void AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values); +AL_API void AL_APIENTRY alListeneri(ALenum param, ALint value); +AL_API void AL_APIENTRY alListener3i(ALenum param, ALint value1, ALint value2, ALint value3); +AL_API void AL_APIENTRY alListeneriv(ALenum param, const ALint *values); + +/** Get Listener parameters */ +AL_API void AL_APIENTRY alGetListenerf(ALenum param, ALfloat *value); +AL_API void AL_APIENTRY alGetListener3f(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +AL_API void AL_APIENTRY alGetListenerfv(ALenum param, ALfloat *values); +AL_API void AL_APIENTRY alGetListeneri(ALenum param, ALint *value); +AL_API void AL_APIENTRY alGetListener3i(ALenum param, ALint *value1, ALint *value2, ALint *value3); +AL_API void AL_APIENTRY alGetListeneriv(ALenum param, ALint *values); + + +/** Create Source objects. */ +AL_API void AL_APIENTRY alGenSources(ALsizei n, ALuint *sources); +/** Delete Source objects. */ +AL_API void AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources); +/** Verify a handle is a valid Source. */ +AL_API ALboolean AL_APIENTRY alIsSource(ALuint source); + +/** Set Source parameters. */ +AL_API void AL_APIENTRY alSourcef(ALuint source, ALenum param, ALfloat value); +AL_API void AL_APIENTRY alSource3f(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +AL_API void AL_APIENTRY alSourcefv(ALuint source, ALenum param, const ALfloat *values); +AL_API void AL_APIENTRY alSourcei(ALuint source, ALenum param, ALint value); +AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); +AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum param, const ALint *values); + +/** Get Source parameters. */ +AL_API void AL_APIENTRY alGetSourcef(ALuint source, ALenum param, ALfloat *value); +AL_API void AL_APIENTRY alGetSource3f(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +AL_API void AL_APIENTRY alGetSourcefv(ALuint source, ALenum param, ALfloat *values); +AL_API void AL_APIENTRY alGetSourcei(ALuint source, ALenum param, ALint *value); +AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); +AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum param, ALint *values); + + +/** Play, replay, or resume (if paused) a list of Sources */ +AL_API void AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources); +/** Stop a list of Sources */ +AL_API void AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources); +/** Rewind a list of Sources */ +AL_API void AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources); +/** Pause a list of Sources */ +AL_API void AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources); + +/** Play, replay, or resume a Source */ +AL_API void AL_APIENTRY alSourcePlay(ALuint source); +/** Stop a Source */ +AL_API void AL_APIENTRY alSourceStop(ALuint source); +/** Rewind a Source (set playback postiton to beginning) */ +AL_API void AL_APIENTRY alSourceRewind(ALuint source); +/** Pause a Source */ +AL_API void AL_APIENTRY alSourcePause(ALuint source); + +/** Queue buffers onto a source */ +AL_API void AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei nb, const ALuint *buffers); +/** Unqueue processed buffers from a source */ +AL_API void AL_APIENTRY alSourceUnqueueBuffers(ALuint source, ALsizei nb, ALuint *buffers); + + +/** Create Buffer objects */ +AL_API void AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers); +/** Delete Buffer objects */ +AL_API void AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers); +/** Verify a handle is a valid Buffer */ +AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer); + +/** Specifies the data to be copied into a buffer */ +AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); + +/** Set Buffer parameters, */ +AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat value); +AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values); +AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value); +AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); +AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values); + +/** Get Buffer parameters. */ +AL_API void AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value); +AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values); +AL_API void AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value); +AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); +AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values); + +/** Pointer-to-function type, useful for dynamically getting AL entry points. */ +typedef void (AL_APIENTRY *LPALENABLE)(ALenum capability); +typedef void (AL_APIENTRY *LPALDISABLE)(ALenum capability); +typedef ALboolean (AL_APIENTRY *LPALISENABLED)(ALenum capability); +typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)(ALenum param); +typedef void (AL_APIENTRY *LPALGETBOOLEANV)(ALenum param, ALboolean *values); +typedef void (AL_APIENTRY *LPALGETINTEGERV)(ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGETFLOATV)(ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETDOUBLEV)(ALenum param, ALdouble *values); +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)(ALenum param); +typedef ALint (AL_APIENTRY *LPALGETINTEGER)(ALenum param); +typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)(ALenum param); +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)(ALenum param); +typedef ALenum (AL_APIENTRY *LPALGETERROR)(void); +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar *extname); +typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)(const ALchar *fname); +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)(const ALchar *ename); +typedef void (AL_APIENTRY *LPALLISTENERF)(ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALLISTENER3F)(ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALLISTENERFV)(ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALLISTENERI)(ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALLISTENER3I)(ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALLISTENERIV)(ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETLISTENERF)(ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETLISTENER3F)(ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETLISTENERFV)(ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETLISTENERI)(ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETLISTENER3I)(ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETLISTENERIV)(ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALGENSOURCES)(ALsizei n, ALuint *sources); +typedef void (AL_APIENTRY *LPALDELETESOURCES)(ALsizei n, const ALuint *sources); +typedef ALboolean (AL_APIENTRY *LPALISSOURCE)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEF)(ALuint source, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALSOURCE3F)(ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALSOURCEFV)(ALuint source, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALSOURCEI)(ALuint source, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALSOURCE3I)(ALuint source, ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALSOURCEIV)(ALuint source, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETSOURCEF)(ALuint source, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETSOURCE3F)(ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETSOURCEFV)(ALuint source, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETSOURCEI)(ALuint source, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETSOURCE3I)(ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETSOURCEIV)(ALuint source, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALSOURCEPLAYV)(ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCESTOPV)(ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEREWINDV)(ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)(ALsizei n, const ALuint *sources); +typedef void (AL_APIENTRY *LPALSOURCEPLAY)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCESTOP)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEREWIND)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEPAUSE)(ALuint source); +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint source, ALsizei nb, const ALuint *buffers); +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint source, ALsizei nb, ALuint *buffers); +typedef void (AL_APIENTRY *LPALGENBUFFERS)(ALsizei n, ALuint *buffers); +typedef void (AL_APIENTRY *LPALDELETEBUFFERS)(ALsizei n, const ALuint *buffers); +typedef ALboolean (AL_APIENTRY *LPALISBUFFER)(ALuint buffer); +typedef void (AL_APIENTRY *LPALBUFFERDATA)(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq); +typedef void (AL_APIENTRY *LPALBUFFERF)(ALuint buffer, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALBUFFER3F)(ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3); +typedef void (AL_APIENTRY *LPALBUFFERFV)(ALuint buffer, ALenum param, const ALfloat *values); +typedef void (AL_APIENTRY *LPALBUFFERI)(ALuint buffer, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALBUFFER3I)(ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3); +typedef void (AL_APIENTRY *LPALBUFFERIV)(ALuint buffer, ALenum param, const ALint *values); +typedef void (AL_APIENTRY *LPALGETBUFFERF)(ALuint buffer, ALenum param, ALfloat *value); +typedef void (AL_APIENTRY *LPALGETBUFFER3F)(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3); +typedef void (AL_APIENTRY *LPALGETBUFFERFV)(ALuint buffer, ALenum param, ALfloat *values); +typedef void (AL_APIENTRY *LPALGETBUFFERI)(ALuint buffer, ALenum param, ALint *value); +typedef void (AL_APIENTRY *LPALGETBUFFER3I)(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3); +typedef void (AL_APIENTRY *LPALGETBUFFERIV)(ALuint buffer, ALenum param, ALint *values); +typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)(ALfloat value); +typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)(ALfloat value); +typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)(ALfloat value); +typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel); + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /* AL_AL_H */ diff --git a/Engine/lib/openal-soft/include/AL/alc.h b/Engine/lib/openal-soft/include/AL/alc.h new file mode 100644 index 000000000..294e8b33c --- /dev/null +++ b/Engine/lib/openal-soft/include/AL/alc.h @@ -0,0 +1,237 @@ +#ifndef AL_ALC_H +#define AL_ALC_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef ALC_API + #if defined(AL_LIBTYPE_STATIC) + #define ALC_API + #elif defined(_WIN32) + #define ALC_API __declspec(dllimport) + #else + #define ALC_API extern + #endif +#endif + +#if defined(_WIN32) + #define ALC_APIENTRY __cdecl +#else + #define ALC_APIENTRY +#endif + + +/** Deprecated macro. */ +#define ALCAPI ALC_API +#define ALCAPIENTRY ALC_APIENTRY +#define ALC_INVALID 0 + +/** Supported ALC version? */ +#define ALC_VERSION_0_1 1 + +/** Opaque device handle */ +typedef struct ALCdevice_struct ALCdevice; +/** Opaque context handle */ +typedef struct ALCcontext_struct ALCcontext; + +/** 8-bit boolean */ +typedef char ALCboolean; + +/** character */ +typedef char ALCchar; + +/** signed 8-bit 2's complement integer */ +typedef signed char ALCbyte; + +/** unsigned 8-bit integer */ +typedef unsigned char ALCubyte; + +/** signed 16-bit 2's complement integer */ +typedef short ALCshort; + +/** unsigned 16-bit integer */ +typedef unsigned short ALCushort; + +/** signed 32-bit 2's complement integer */ +typedef int ALCint; + +/** unsigned 32-bit integer */ +typedef unsigned int ALCuint; + +/** non-negative 32-bit binary integer size */ +typedef int ALCsizei; + +/** enumerated 32-bit value */ +typedef int ALCenum; + +/** 32-bit IEEE754 floating-point */ +typedef float ALCfloat; + +/** 64-bit IEEE754 floating-point */ +typedef double ALCdouble; + +/** void type (for opaque pointers only) */ +typedef void ALCvoid; + + +/* Enumerant values begin at column 50. No tabs. */ + +/** Boolean False. */ +#define ALC_FALSE 0 + +/** Boolean True. */ +#define ALC_TRUE 1 + +/** Context attribute: Hz. */ +#define ALC_FREQUENCY 0x1007 + +/** Context attribute: Hz. */ +#define ALC_REFRESH 0x1008 + +/** Context attribute: AL_TRUE or AL_FALSE. */ +#define ALC_SYNC 0x1009 + +/** Context attribute: requested Mono (3D) Sources. */ +#define ALC_MONO_SOURCES 0x1010 + +/** Context attribute: requested Stereo Sources. */ +#define ALC_STEREO_SOURCES 0x1011 + +/** No error. */ +#define ALC_NO_ERROR 0 + +/** Invalid device handle. */ +#define ALC_INVALID_DEVICE 0xA001 + +/** Invalid context handle. */ +#define ALC_INVALID_CONTEXT 0xA002 + +/** Invalid enum parameter passed to an ALC call. */ +#define ALC_INVALID_ENUM 0xA003 + +/** Invalid value parameter passed to an ALC call. */ +#define ALC_INVALID_VALUE 0xA004 + +/** Out of memory. */ +#define ALC_OUT_OF_MEMORY 0xA005 + + +/** Runtime ALC version. */ +#define ALC_MAJOR_VERSION 0x1000 +#define ALC_MINOR_VERSION 0x1001 + +/** Context attribute list properties. */ +#define ALC_ATTRIBUTES_SIZE 0x1002 +#define ALC_ALL_ATTRIBUTES 0x1003 + +/** String for the default device specifier. */ +#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 +/** + * String for the given device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known device specifiers (list ends with an empty string). + */ +#define ALC_DEVICE_SPECIFIER 0x1005 +/** String for space-separated list of ALC extensions. */ +#define ALC_EXTENSIONS 0x1006 + + +/** Capture extension */ +#define ALC_EXT_CAPTURE 1 +/** + * String for the given capture device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known capture device specifiers (list ends with an empty string). + */ +#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310 +/** String for the default capture device specifier. */ +#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311 +/** Number of sample frames available for capture. */ +#define ALC_CAPTURE_SAMPLES 0x312 + + +/** Enumerate All extension */ +#define ALC_ENUMERATE_ALL_EXT 1 +/** String for the default extended device specifier. */ +#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 +/** + * String for the given extended device's specifier. + * + * If device handle is NULL, it is instead a null-char separated list of + * strings of known extended device specifiers (list ends with an empty string). + */ +#define ALC_ALL_DEVICES_SPECIFIER 0x1013 + + +/** Context management. */ +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint* attrlist); +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context); +ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context); +ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context); +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void); +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *context); + +/** Device management. */ +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *devicename); +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device); + + +/** + * Error support. + * + * Obtain the most recent Device error. + */ +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device); + +/** + * Extension support. + * + * Query for the presence of an extension, and obtain any appropriate + * function pointers and enum values. + */ +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extname); +ALC_API void* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcname); +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumname); + +/** Query function. */ +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *device, ALCenum param); +ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); + +/** Capture function. */ +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device); +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); + +/** Pointer-to-function type, useful for dynamically getting ALC entry points. */ +typedef ALCcontext* (ALC_APIENTRY *LPALCCREATECONTEXT)(ALCdevice *device, const ALCint *attrlist); +typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)(ALCcontext *context); +typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)(ALCcontext *context); +typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)(ALCcontext *context); +typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)(ALCcontext *context); +typedef ALCcontext* (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)(void); +typedef ALCdevice* (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)(ALCcontext *context); +typedef ALCdevice* (ALC_APIENTRY *LPALCOPENDEVICE)(const ALCchar *devicename); +typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)(ALCdevice *device); +typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)(ALCdevice *device); +typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)(ALCdevice *device, const ALCchar *extname); +typedef void* (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname); +typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname); +typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)(ALCdevice *device, ALCenum param); +typedef void (ALC_APIENTRY *LPALCGETINTEGERV)(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values); +typedef ALCdevice* (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)(const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize); +typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)(ALCdevice *device); +typedef void (ALC_APIENTRY *LPALCCAPTURESTART)(ALCdevice *device); +typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)(ALCdevice *device); +typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); + +#if defined(__cplusplus) +} +#endif + +#endif /* AL_ALC_H */ diff --git a/Engine/lib/openal-soft/include/AL/alext.h b/Engine/lib/openal-soft/include/AL/alext.h new file mode 100644 index 000000000..0090c8041 --- /dev/null +++ b/Engine/lib/openal-soft/include/AL/alext.h @@ -0,0 +1,443 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2008 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 + */ + +#ifndef AL_ALEXT_H +#define AL_ALEXT_H + +#include +/* Define int64_t and uint64_t types */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +#elif defined(_WIN32) && defined(__GNUC__) +#include +#elif defined(_WIN32) +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +#else +/* Fallback if nothing above works */ +#include +#endif + +#include "alc.h" +#include "al.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef AL_LOKI_IMA_ADPCM_format +#define AL_LOKI_IMA_ADPCM_format 1 +#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000 +#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001 +#endif + +#ifndef AL_LOKI_WAVE_format +#define AL_LOKI_WAVE_format 1 +#define AL_FORMAT_WAVE_EXT 0x10002 +#endif + +#ifndef AL_EXT_vorbis +#define AL_EXT_vorbis 1 +#define AL_FORMAT_VORBIS_EXT 0x10003 +#endif + +#ifndef AL_LOKI_quadriphonic +#define AL_LOKI_quadriphonic 1 +#define AL_FORMAT_QUAD8_LOKI 0x10004 +#define AL_FORMAT_QUAD16_LOKI 0x10005 +#endif + +#ifndef AL_EXT_float32 +#define AL_EXT_float32 1 +#define AL_FORMAT_MONO_FLOAT32 0x10010 +#define AL_FORMAT_STEREO_FLOAT32 0x10011 +#endif + +#ifndef AL_EXT_double +#define AL_EXT_double 1 +#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012 +#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013 +#endif + +#ifndef AL_EXT_MULAW +#define AL_EXT_MULAW 1 +#define AL_FORMAT_MONO_MULAW_EXT 0x10014 +#define AL_FORMAT_STEREO_MULAW_EXT 0x10015 +#endif + +#ifndef AL_EXT_ALAW +#define AL_EXT_ALAW 1 +#define AL_FORMAT_MONO_ALAW_EXT 0x10016 +#define AL_FORMAT_STEREO_ALAW_EXT 0x10017 +#endif + +#ifndef ALC_LOKI_audio_channel +#define ALC_LOKI_audio_channel 1 +#define ALC_CHAN_MAIN_LOKI 0x500001 +#define ALC_CHAN_PCM_LOKI 0x500002 +#define ALC_CHAN_CD_LOKI 0x500003 +#endif + +#ifndef AL_EXT_MCFORMATS +#define AL_EXT_MCFORMATS 1 +#define AL_FORMAT_QUAD8 0x1204 +#define AL_FORMAT_QUAD16 0x1205 +#define AL_FORMAT_QUAD32 0x1206 +#define AL_FORMAT_REAR8 0x1207 +#define AL_FORMAT_REAR16 0x1208 +#define AL_FORMAT_REAR32 0x1209 +#define AL_FORMAT_51CHN8 0x120A +#define AL_FORMAT_51CHN16 0x120B +#define AL_FORMAT_51CHN32 0x120C +#define AL_FORMAT_61CHN8 0x120D +#define AL_FORMAT_61CHN16 0x120E +#define AL_FORMAT_61CHN32 0x120F +#define AL_FORMAT_71CHN8 0x1210 +#define AL_FORMAT_71CHN16 0x1211 +#define AL_FORMAT_71CHN32 0x1212 +#endif + +#ifndef AL_EXT_MULAW_MCFORMATS +#define AL_EXT_MULAW_MCFORMATS 1 +#define AL_FORMAT_MONO_MULAW 0x10014 +#define AL_FORMAT_STEREO_MULAW 0x10015 +#define AL_FORMAT_QUAD_MULAW 0x10021 +#define AL_FORMAT_REAR_MULAW 0x10022 +#define AL_FORMAT_51CHN_MULAW 0x10023 +#define AL_FORMAT_61CHN_MULAW 0x10024 +#define AL_FORMAT_71CHN_MULAW 0x10025 +#endif + +#ifndef AL_EXT_IMA4 +#define AL_EXT_IMA4 1 +#define AL_FORMAT_MONO_IMA4 0x1300 +#define AL_FORMAT_STEREO_IMA4 0x1301 +#endif + +#ifndef AL_EXT_STATIC_BUFFER +#define AL_EXT_STATIC_BUFFER 1 +typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei); +#ifdef AL_ALEXT_PROTOTYPES +AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq); +#endif +#endif + +#ifndef ALC_EXT_EFX +#define ALC_EXT_EFX 1 +#include "efx.h" +#endif + +#ifndef ALC_EXT_disconnect +#define ALC_EXT_disconnect 1 +#define ALC_CONNECTED 0x313 +#endif + +#ifndef ALC_EXT_thread_local_context +#define ALC_EXT_thread_local_context 1 +typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context); +typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void); +#ifdef AL_ALEXT_PROTOTYPES +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context); +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); +#endif +#endif + +#ifndef AL_EXT_source_distance_model +#define AL_EXT_source_distance_model 1 +#define AL_SOURCE_DISTANCE_MODEL 0x200 +#endif + +#ifndef AL_SOFT_buffer_sub_data +#define AL_SOFT_buffer_sub_data 1 +#define AL_BYTE_RW_OFFSETS_SOFT 0x1031 +#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032 +typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); +#ifdef AL_ALEXT_PROTOTYPES +AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); +#endif +#endif + +#ifndef AL_SOFT_loop_points +#define AL_SOFT_loop_points 1 +#define AL_LOOP_POINTS_SOFT 0x2015 +#endif + +#ifndef AL_EXT_FOLDBACK +#define AL_EXT_FOLDBACK 1 +#define AL_EXT_FOLDBACK_NAME "AL_EXT_FOLDBACK" +#define AL_FOLDBACK_EVENT_BLOCK 0x4112 +#define AL_FOLDBACK_EVENT_START 0x4111 +#define AL_FOLDBACK_EVENT_STOP 0x4113 +#define AL_FOLDBACK_MODE_MONO 0x4101 +#define AL_FOLDBACK_MODE_STEREO 0x4102 +typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei); +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK); +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void); +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback); +AL_API void AL_APIENTRY alRequestFoldbackStop(void); +#endif +#endif + +#ifndef ALC_EXT_DEDICATED +#define ALC_EXT_DEDICATED 1 +#define AL_DEDICATED_GAIN 0x0001 +#define AL_EFFECT_DEDICATED_DIALOGUE 0x9001 +#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000 +#endif + +#ifndef AL_SOFT_buffer_samples +#define AL_SOFT_buffer_samples 1 +/* Channel configurations */ +#define AL_MONO_SOFT 0x1500 +#define AL_STEREO_SOFT 0x1501 +#define AL_REAR_SOFT 0x1502 +#define AL_QUAD_SOFT 0x1503 +#define AL_5POINT1_SOFT 0x1504 +#define AL_6POINT1_SOFT 0x1505 +#define AL_7POINT1_SOFT 0x1506 + +/* Sample types */ +#define AL_BYTE_SOFT 0x1400 +#define AL_UNSIGNED_BYTE_SOFT 0x1401 +#define AL_SHORT_SOFT 0x1402 +#define AL_UNSIGNED_SHORT_SOFT 0x1403 +#define AL_INT_SOFT 0x1404 +#define AL_UNSIGNED_INT_SOFT 0x1405 +#define AL_FLOAT_SOFT 0x1406 +#define AL_DOUBLE_SOFT 0x1407 +#define AL_BYTE3_SOFT 0x1408 +#define AL_UNSIGNED_BYTE3_SOFT 0x1409 + +/* Storage formats */ +#define AL_MONO8_SOFT 0x1100 +#define AL_MONO16_SOFT 0x1101 +#define AL_MONO32F_SOFT 0x10010 +#define AL_STEREO8_SOFT 0x1102 +#define AL_STEREO16_SOFT 0x1103 +#define AL_STEREO32F_SOFT 0x10011 +#define AL_QUAD8_SOFT 0x1204 +#define AL_QUAD16_SOFT 0x1205 +#define AL_QUAD32F_SOFT 0x1206 +#define AL_REAR8_SOFT 0x1207 +#define AL_REAR16_SOFT 0x1208 +#define AL_REAR32F_SOFT 0x1209 +#define AL_5POINT1_8_SOFT 0x120A +#define AL_5POINT1_16_SOFT 0x120B +#define AL_5POINT1_32F_SOFT 0x120C +#define AL_6POINT1_8_SOFT 0x120D +#define AL_6POINT1_16_SOFT 0x120E +#define AL_6POINT1_32F_SOFT 0x120F +#define AL_7POINT1_8_SOFT 0x1210 +#define AL_7POINT1_16_SOFT 0x1211 +#define AL_7POINT1_32F_SOFT 0x1212 + +/* Buffer attributes */ +#define AL_INTERNAL_FORMAT_SOFT 0x2008 +#define AL_BYTE_LENGTH_SOFT 0x2009 +#define AL_SAMPLE_LENGTH_SOFT 0x200A +#define AL_SEC_LENGTH_SOFT 0x200B + +typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*); +typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*); +typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*); +typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum); +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, ALuint samplerate, ALenum internalformat, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, const ALvoid *data); +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, ALsizei offset, ALsizei samples, ALenum channels, ALenum type, ALvoid *data); +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); +#endif +#endif + +#ifndef AL_SOFT_direct_channels +#define AL_SOFT_direct_channels 1 +#define AL_DIRECT_CHANNELS_SOFT 0x1033 +#endif + +#ifndef ALC_SOFT_loopback +#define ALC_SOFT_loopback 1 +#define ALC_FORMAT_CHANNELS_SOFT 0x1990 +#define ALC_FORMAT_TYPE_SOFT 0x1991 + +/* Sample types */ +#define ALC_BYTE_SOFT 0x1400 +#define ALC_UNSIGNED_BYTE_SOFT 0x1401 +#define ALC_SHORT_SOFT 0x1402 +#define ALC_UNSIGNED_SHORT_SOFT 0x1403 +#define ALC_INT_SOFT 0x1404 +#define ALC_UNSIGNED_INT_SOFT 0x1405 +#define ALC_FLOAT_SOFT 0x1406 + +/* Channel configurations */ +#define ALC_MONO_SOFT 0x1500 +#define ALC_STEREO_SOFT 0x1501 +#define ALC_QUAD_SOFT 0x1503 +#define ALC_5POINT1_SOFT 0x1504 +#define ALC_6POINT1_SOFT 0x1505 +#define ALC_7POINT1_SOFT 0x1506 + +typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(const ALCchar*); +typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice*,ALCsizei,ALCenum,ALCenum); +typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice*,ALCvoid*,ALCsizei); +#ifdef AL_ALEXT_PROTOTYPES +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceName); +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type); +ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); +#endif +#endif + +#ifndef AL_EXT_STEREO_ANGLES +#define AL_EXT_STEREO_ANGLES 1 +#define AL_STEREO_ANGLES 0x1030 +#endif + +#ifndef AL_EXT_SOURCE_RADIUS +#define AL_EXT_SOURCE_RADIUS 1 +#define AL_SOURCE_RADIUS 0x1031 +#endif + +#ifndef AL_SOFT_source_latency +#define AL_SOFT_source_latency 1 +#define AL_SAMPLE_OFFSET_LATENCY_SOFT 0x1200 +#define AL_SEC_OFFSET_LATENCY_SOFT 0x1201 +typedef int64_t ALint64SOFT; +typedef uint64_t ALuint64SOFT; +typedef void (AL_APIENTRY*LPALSOURCEDSOFT)(ALuint,ALenum,ALdouble); +typedef void (AL_APIENTRY*LPALSOURCE3DSOFT)(ALuint,ALenum,ALdouble,ALdouble,ALdouble); +typedef void (AL_APIENTRY*LPALSOURCEDVSOFT)(ALuint,ALenum,const ALdouble*); +typedef void (AL_APIENTRY*LPALGETSOURCEDSOFT)(ALuint,ALenum,ALdouble*); +typedef void (AL_APIENTRY*LPALGETSOURCE3DSOFT)(ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*); +typedef void (AL_APIENTRY*LPALGETSOURCEDVSOFT)(ALuint,ALenum,ALdouble*); +typedef void (AL_APIENTRY*LPALSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT); +typedef void (AL_APIENTRY*LPALSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT); +typedef void (AL_APIENTRY*LPALSOURCEI64VSOFT)(ALuint,ALenum,const ALint64SOFT*); +typedef void (AL_APIENTRY*LPALGETSOURCEI64SOFT)(ALuint,ALenum,ALint64SOFT*); +typedef void (AL_APIENTRY*LPALGETSOURCE3I64SOFT)(ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*); +typedef void (AL_APIENTRY*LPALGETSOURCEI64VSOFT)(ALuint,ALenum,ALint64SOFT*); +#ifdef AL_ALEXT_PROTOTYPES +AL_API void AL_APIENTRY alSourcedSOFT(ALuint source, ALenum param, ALdouble value); +AL_API void AL_APIENTRY alSource3dSOFT(ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3); +AL_API void AL_APIENTRY alSourcedvSOFT(ALuint source, ALenum param, const ALdouble *values); +AL_API void AL_APIENTRY alGetSourcedSOFT(ALuint source, ALenum param, ALdouble *value); +AL_API void AL_APIENTRY alGetSource3dSOFT(ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3); +AL_API void AL_APIENTRY alGetSourcedvSOFT(ALuint source, ALenum param, ALdouble *values); +AL_API void AL_APIENTRY alSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT value); +AL_API void AL_APIENTRY alSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3); +AL_API void AL_APIENTRY alSourcei64vSOFT(ALuint source, ALenum param, const ALint64SOFT *values); +AL_API void AL_APIENTRY alGetSourcei64SOFT(ALuint source, ALenum param, ALint64SOFT *value); +AL_API void AL_APIENTRY alGetSource3i64SOFT(ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3); +AL_API void AL_APIENTRY alGetSourcei64vSOFT(ALuint source, ALenum param, ALint64SOFT *values); +#endif +#endif + +#ifndef ALC_EXT_DEFAULT_FILTER_ORDER +#define ALC_EXT_DEFAULT_FILTER_ORDER 1 +#define ALC_DEFAULT_FILTER_ORDER 0x1100 +#endif + +#ifndef AL_SOFT_deferred_updates +#define AL_SOFT_deferred_updates 1 +#define AL_DEFERRED_UPDATES_SOFT 0xC002 +typedef ALvoid (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void); +typedef ALvoid (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void); +#ifdef AL_ALEXT_PROTOTYPES +AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void); +AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void); +#endif +#endif + +#ifndef AL_SOFT_block_alignment +#define AL_SOFT_block_alignment 1 +#define AL_UNPACK_BLOCK_ALIGNMENT_SOFT 0x200C +#define AL_PACK_BLOCK_ALIGNMENT_SOFT 0x200D +#endif + +#ifndef AL_SOFT_MSADPCM +#define AL_SOFT_MSADPCM 1 +#define AL_FORMAT_MONO_MSADPCM_SOFT 0x1302 +#define AL_FORMAT_STEREO_MSADPCM_SOFT 0x1303 +#endif + +#ifndef AL_SOFT_source_length +#define AL_SOFT_source_length 1 +/*#define AL_BYTE_LENGTH_SOFT 0x2009*/ +/*#define AL_SAMPLE_LENGTH_SOFT 0x200A*/ +/*#define AL_SEC_LENGTH_SOFT 0x200B*/ +#endif + +#ifndef ALC_SOFT_pause_device +#define ALC_SOFT_pause_device 1 +typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device); +typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device); +#ifdef AL_ALEXT_PROTOTYPES +ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device); +ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); +#endif +#endif + +#ifndef AL_EXT_BFORMAT +#define AL_EXT_BFORMAT 1 +#define AL_FORMAT_BFORMAT2D_8 0x20021 +#define AL_FORMAT_BFORMAT2D_16 0x20022 +#define AL_FORMAT_BFORMAT2D_FLOAT32 0x20023 +#define AL_FORMAT_BFORMAT3D_8 0x20031 +#define AL_FORMAT_BFORMAT3D_16 0x20032 +#define AL_FORMAT_BFORMAT3D_FLOAT32 0x20033 +#endif + +#ifndef AL_EXT_MULAW_BFORMAT +#define AL_EXT_MULAW_BFORMAT 1 +#define AL_FORMAT_BFORMAT2D_MULAW 0x10031 +#define AL_FORMAT_BFORMAT3D_MULAW 0x10032 +#endif + +#ifndef ALC_SOFT_HRTF +#define ALC_SOFT_HRTF 1 +#define ALC_HRTF_SOFT 0x1992 +#define ALC_DONT_CARE_SOFT 0x0002 +#define ALC_HRTF_STATUS_SOFT 0x1993 +#define ALC_HRTF_DISABLED_SOFT 0x0000 +#define ALC_HRTF_ENABLED_SOFT 0x0001 +#define ALC_HRTF_DENIED_SOFT 0x0002 +#define ALC_HRTF_REQUIRED_SOFT 0x0003 +#define ALC_HRTF_HEADPHONES_DETECTED_SOFT 0x0004 +#define ALC_HRTF_UNSUPPORTED_FORMAT_SOFT 0x0005 +#define ALC_NUM_HRTF_SPECIFIERS_SOFT 0x1994 +#define ALC_HRTF_SPECIFIER_SOFT 0x1995 +#define ALC_HRTF_ID_SOFT 0x1996 +typedef const ALCchar* (ALC_APIENTRY*LPALCGETSTRINGISOFT)(ALCdevice *device, ALCenum paramName, ALCsizei index); +typedef ALCboolean (ALC_APIENTRY*LPALCRESETDEVICESOFT)(ALCdevice *device, const ALCint *attribs); +#ifdef AL_ALEXT_PROTOTYPES +ALC_API const ALCchar* ALC_APIENTRY alcGetStringiSOFT(ALCdevice *device, ALCenum paramName, ALCsizei index); +ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCint *attribs); +#endif +#endif + +#ifndef AL_SOFT_gain_clamp_ex +#define AL_SOFT_gain_clamp_ex 1 +#define AL_GAIN_LIMIT_SOFT 0x200E +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Engine/lib/openal-soft/include/AL/efx-creative.h b/Engine/lib/openal-soft/include/AL/efx-creative.h new file mode 100644 index 000000000..0a04c982e --- /dev/null +++ b/Engine/lib/openal-soft/include/AL/efx-creative.h @@ -0,0 +1,3 @@ +/* The tokens that would be defined here are already defined in efx.h. This + * empty file is here to provide compatibility with Windows-based projects + * that would include it. */ diff --git a/Engine/lib/openal-soft/include/AL/efx-presets.h b/Engine/lib/openal-soft/include/AL/efx-presets.h new file mode 100644 index 000000000..8539fd517 --- /dev/null +++ b/Engine/lib/openal-soft/include/AL/efx-presets.h @@ -0,0 +1,402 @@ +/* Reverb presets for EFX */ + +#ifndef EFX_PRESETS_H +#define EFX_PRESETS_H + +#ifndef EFXEAXREVERBPROPERTIES_DEFINED +#define EFXEAXREVERBPROPERTIES_DEFINED +typedef struct { + float flDensity; + float flDiffusion; + float flGain; + float flGainHF; + float flGainLF; + float flDecayTime; + float flDecayHFRatio; + float flDecayLFRatio; + float flReflectionsGain; + float flReflectionsDelay; + float flReflectionsPan[3]; + float flLateReverbGain; + float flLateReverbDelay; + float flLateReverbPan[3]; + float flEchoTime; + float flEchoDepth; + float flModulationTime; + float flModulationDepth; + float flAirAbsorptionGainHF; + float flHFReference; + float flLFReference; + float flRoomRolloffFactor; + int iDecayHFLimit; +} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES; +#endif + +/* Default Presets */ + +#define EFX_REVERB_PRESET_GENERIC \ + { 1.0000f, 1.0000f, 0.3162f, 0.8913f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_PADDEDCELL \ + { 0.1715f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.1700f, 0.1000f, 1.0000f, 0.2500f, 0.0010f, { 0.0000f, 0.0000f, 0.0000f }, 1.2691f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ROOM \ + { 0.4287f, 1.0000f, 0.3162f, 0.5929f, 1.0000f, 0.4000f, 0.8300f, 1.0000f, 0.1503f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.0629f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_BATHROOM \ + { 0.1715f, 1.0000f, 0.3162f, 0.2512f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.6531f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 3.2734f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_LIVINGROOM \ + { 0.9766f, 1.0000f, 0.3162f, 0.0010f, 1.0000f, 0.5000f, 0.1000f, 1.0000f, 0.2051f, 0.0030f, { 0.0000f, 0.0000f, 0.0000f }, 0.2805f, 0.0040f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_STONEROOM \ + { 1.0000f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 2.3100f, 0.6400f, 1.0000f, 0.4411f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1003f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_AUDITORIUM \ + { 1.0000f, 1.0000f, 0.3162f, 0.5781f, 1.0000f, 4.3200f, 0.5900f, 1.0000f, 0.4032f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7170f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CONCERTHALL \ + { 1.0000f, 1.0000f, 0.3162f, 0.5623f, 1.0000f, 3.9200f, 0.7000f, 1.0000f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.9977f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CAVE \ + { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 2.9100f, 1.3000f, 1.0000f, 0.5000f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.7063f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_ARENA \ + { 1.0000f, 1.0000f, 0.3162f, 0.4477f, 1.0000f, 7.2400f, 0.3300f, 1.0000f, 0.2612f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.0186f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_HANGAR \ + { 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 10.0500f, 0.2300f, 1.0000f, 0.5000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2560f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CARPETEDHALLWAY \ + { 0.4287f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 0.3000f, 0.1000f, 1.0000f, 0.1215f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 0.1531f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_HALLWAY \ + { 0.3645f, 1.0000f, 0.3162f, 0.7079f, 1.0000f, 1.4900f, 0.5900f, 1.0000f, 0.2458f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.6615f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_STONECORRIDOR \ + { 1.0000f, 1.0000f, 0.3162f, 0.7612f, 1.0000f, 2.7000f, 0.7900f, 1.0000f, 0.2472f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 1.5758f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ALLEY \ + { 1.0000f, 0.3000f, 0.3162f, 0.7328f, 1.0000f, 1.4900f, 0.8600f, 1.0000f, 0.2500f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.9954f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.9500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FOREST \ + { 1.0000f, 0.3000f, 0.3162f, 0.0224f, 1.0000f, 1.4900f, 0.5400f, 1.0000f, 0.0525f, 0.1620f, { 0.0000f, 0.0000f, 0.0000f }, 0.7682f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CITY \ + { 1.0000f, 0.5000f, 0.3162f, 0.3981f, 1.0000f, 1.4900f, 0.6700f, 1.0000f, 0.0730f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1427f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_MOUNTAINS \ + { 1.0000f, 0.2700f, 0.3162f, 0.0562f, 1.0000f, 1.4900f, 0.2100f, 1.0000f, 0.0407f, 0.3000f, { 0.0000f, 0.0000f, 0.0000f }, 0.1919f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_QUARRY \ + { 1.0000f, 1.0000f, 0.3162f, 0.3162f, 1.0000f, 1.4900f, 0.8300f, 1.0000f, 0.0000f, 0.0610f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.7000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_PLAIN \ + { 1.0000f, 0.2100f, 0.3162f, 0.1000f, 1.0000f, 1.4900f, 0.5000f, 1.0000f, 0.0585f, 0.1790f, { 0.0000f, 0.0000f, 0.0000f }, 0.1089f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_PARKINGLOT \ + { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 1.0000f, 1.6500f, 1.5000f, 1.0000f, 0.2082f, 0.0080f, { 0.0000f, 0.0000f, 0.0000f }, 0.2652f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_SEWERPIPE \ + { 0.3071f, 0.8000f, 0.3162f, 0.3162f, 1.0000f, 2.8100f, 0.1400f, 1.0000f, 1.6387f, 0.0140f, { 0.0000f, 0.0000f, 0.0000f }, 3.2471f, 0.0210f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_UNDERWATER \ + { 0.3645f, 1.0000f, 0.3162f, 0.0100f, 1.0000f, 1.4900f, 0.1000f, 1.0000f, 0.5963f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 7.0795f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 1.1800f, 0.3480f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_DRUGGED \ + { 0.4287f, 0.5000f, 0.3162f, 1.0000f, 1.0000f, 8.3900f, 1.3900f, 1.0000f, 0.8760f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 3.1081f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_DIZZY \ + { 0.3645f, 0.6000f, 0.3162f, 0.6310f, 1.0000f, 17.2300f, 0.5600f, 1.0000f, 0.1392f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4937f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.8100f, 0.3100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_PSYCHOTIC \ + { 0.0625f, 0.5000f, 0.3162f, 0.8404f, 1.0000f, 7.5600f, 0.9100f, 1.0000f, 0.4864f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 2.4378f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 4.0000f, 1.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +/* Castle Presets */ + +#define EFX_REVERB_PRESET_CASTLE_SMALLROOM \ + { 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 1.2200f, 0.8300f, 0.3100f, 0.8913f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE \ + { 1.0000f, 0.8900f, 0.3162f, 0.3162f, 0.1000f, 2.3200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CASTLE_MEDIUMROOM \ + { 1.0000f, 0.9300f, 0.3162f, 0.2818f, 0.1000f, 2.0400f, 0.8300f, 0.4600f, 0.6310f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1550f, 0.0300f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CASTLE_LARGEROOM \ + { 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.1259f, 2.5300f, 0.8300f, 0.5000f, 0.4467f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1850f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CASTLE_LONGPASSAGE \ + { 1.0000f, 0.8900f, 0.3162f, 0.3981f, 0.1000f, 3.4200f, 0.8300f, 0.3100f, 0.8913f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CASTLE_HALL \ + { 1.0000f, 0.8100f, 0.3162f, 0.2818f, 0.1778f, 3.1400f, 0.7900f, 0.6200f, 0.1778f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CASTLE_CUPBOARD \ + { 1.0000f, 0.8900f, 0.3162f, 0.2818f, 0.1000f, 0.6700f, 0.8700f, 0.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 3.5481f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CASTLE_COURTYARD \ + { 1.0000f, 0.4200f, 0.3162f, 0.4467f, 0.1995f, 2.1300f, 0.6100f, 0.2300f, 0.2239f, 0.1600f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3700f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_CASTLE_ALCOVE \ + { 1.0000f, 0.8900f, 0.3162f, 0.5012f, 0.1000f, 1.6400f, 0.8700f, 0.3100f, 1.0000f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1380f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 5168.6001f, 139.5000f, 0.0000f, 0x1 } + +/* Factory Presets */ + +#define EFX_REVERB_PRESET_FACTORY_SMALLROOM \ + { 0.3645f, 0.8200f, 0.3162f, 0.7943f, 0.5012f, 1.7200f, 0.6500f, 1.3100f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.1190f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE \ + { 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 2.5300f, 0.6500f, 1.3100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FACTORY_MEDIUMROOM \ + { 0.4287f, 0.8200f, 0.2512f, 0.7943f, 0.5012f, 2.7600f, 0.6500f, 1.3100f, 0.2818f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1740f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FACTORY_LARGEROOM \ + { 0.4287f, 0.7500f, 0.2512f, 0.7079f, 0.6310f, 4.2400f, 0.5100f, 1.3100f, 0.1778f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2310f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FACTORY_LONGPASSAGE \ + { 0.3645f, 0.6400f, 0.2512f, 0.7943f, 0.5012f, 4.0600f, 0.6500f, 1.3100f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.1350f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FACTORY_HALL \ + { 0.4287f, 0.7500f, 0.3162f, 0.7079f, 0.6310f, 7.4300f, 0.5100f, 1.3100f, 0.0631f, 0.0730f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FACTORY_CUPBOARD \ + { 0.3071f, 0.6300f, 0.2512f, 0.7943f, 0.5012f, 0.4900f, 0.6500f, 1.3100f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.1070f, 0.0700f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FACTORY_COURTYARD \ + { 0.3071f, 0.5700f, 0.3162f, 0.3162f, 0.6310f, 2.3200f, 0.2900f, 0.5600f, 0.2239f, 0.1400f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2900f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_FACTORY_ALCOVE \ + { 0.3645f, 0.5900f, 0.2512f, 0.7943f, 0.5012f, 3.1400f, 0.6500f, 1.3100f, 1.4125f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.1140f, 0.1000f, 0.2500f, 0.0000f, 0.9943f, 3762.6001f, 362.5000f, 0.0000f, 0x1 } + +/* Ice Palace Presets */ + +#define EFX_REVERB_PRESET_ICEPALACE_SMALLROOM \ + { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 1.5100f, 1.5300f, 0.2700f, 0.8913f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1640f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ICEPALACE_SHORTPASSAGE \ + { 1.0000f, 0.7500f, 0.3162f, 0.5623f, 0.2818f, 1.7900f, 1.4600f, 0.2800f, 0.5012f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM \ + { 1.0000f, 0.8700f, 0.3162f, 0.5623f, 0.4467f, 2.2200f, 1.5300f, 0.3200f, 0.3981f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ICEPALACE_LARGEROOM \ + { 1.0000f, 0.8100f, 0.3162f, 0.5623f, 0.4467f, 3.1400f, 1.5300f, 0.3200f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0270f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ICEPALACE_LONGPASSAGE \ + { 1.0000f, 0.7700f, 0.3162f, 0.5623f, 0.3981f, 3.0100f, 1.4600f, 0.2800f, 0.7943f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0250f, { 0.0000f, 0.0000f, 0.0000f }, 0.1860f, 0.0400f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ICEPALACE_HALL \ + { 1.0000f, 0.7600f, 0.3162f, 0.4467f, 0.5623f, 5.4900f, 1.5300f, 0.3800f, 0.1122f, 0.0540f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0520f, { 0.0000f, 0.0000f, 0.0000f }, 0.2260f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ICEPALACE_CUPBOARD \ + { 1.0000f, 0.8300f, 0.3162f, 0.5012f, 0.2239f, 0.7600f, 1.5300f, 0.2600f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1430f, 0.0800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ICEPALACE_COURTYARD \ + { 1.0000f, 0.5900f, 0.3162f, 0.2818f, 0.3162f, 2.0400f, 1.2000f, 0.3800f, 0.3162f, 0.1730f, { 0.0000f, 0.0000f, 0.0000f }, 0.3162f, 0.0430f, { 0.0000f, 0.0000f, 0.0000f }, 0.2350f, 0.4800f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_ICEPALACE_ALCOVE \ + { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 0.2818f, 2.7600f, 1.4600f, 0.2800f, 1.1220f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1610f, 0.0900f, 0.2500f, 0.0000f, 0.9943f, 12428.5000f, 99.6000f, 0.0000f, 0x1 } + +/* Space Station Presets */ + +#define EFX_REVERB_PRESET_SPACESTATION_SMALLROOM \ + { 0.2109f, 0.7000f, 0.3162f, 0.7079f, 0.8913f, 1.7200f, 0.8200f, 0.5500f, 0.7943f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0130f, { 0.0000f, 0.0000f, 0.0000f }, 0.1880f, 0.2600f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE \ + { 0.2109f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 3.5700f, 0.5000f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.1720f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM \ + { 0.2109f, 0.7500f, 0.3162f, 0.6310f, 0.8913f, 3.0100f, 0.5000f, 0.5500f, 0.3981f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2090f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPACESTATION_LARGEROOM \ + { 0.3645f, 0.8100f, 0.3162f, 0.6310f, 0.8913f, 3.8900f, 0.3800f, 0.6100f, 0.3162f, 0.0560f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0350f, { 0.0000f, 0.0000f, 0.0000f }, 0.2330f, 0.2800f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE \ + { 0.4287f, 0.8200f, 0.3162f, 0.6310f, 0.8913f, 4.6200f, 0.6200f, 0.5500f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2300f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPACESTATION_HALL \ + { 0.4287f, 0.8700f, 0.3162f, 0.6310f, 0.8913f, 7.1100f, 0.3800f, 0.6100f, 0.1778f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2500f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPACESTATION_CUPBOARD \ + { 0.1715f, 0.5600f, 0.3162f, 0.7079f, 0.8913f, 0.7900f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.7783f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1810f, 0.3100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPACESTATION_ALCOVE \ + { 0.2109f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.1600f, 0.8100f, 0.5500f, 1.4125f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0180f, { 0.0000f, 0.0000f, 0.0000f }, 0.1920f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 3316.1001f, 458.2000f, 0.0000f, 0x1 } + +/* Wooden Galleon Presets */ + +#define EFX_REVERB_PRESET_WOODEN_SMALLROOM \ + { 1.0000f, 1.0000f, 0.3162f, 0.1122f, 0.3162f, 0.7900f, 0.3200f, 0.8700f, 1.0000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE \ + { 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.7500f, 0.5000f, 0.8700f, 0.8913f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.6310f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_WOODEN_MEDIUMROOM \ + { 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.2818f, 1.4700f, 0.4200f, 0.8200f, 0.8913f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_WOODEN_LARGEROOM \ + { 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.2818f, 2.6500f, 0.3300f, 0.8200f, 0.8913f, 0.0660f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_WOODEN_LONGPASSAGE \ + { 1.0000f, 1.0000f, 0.3162f, 0.1000f, 0.3162f, 1.9900f, 0.4000f, 0.7900f, 1.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.4467f, 0.0360f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_WOODEN_HALL \ + { 1.0000f, 1.0000f, 0.3162f, 0.0794f, 0.2818f, 3.4500f, 0.3000f, 0.8200f, 0.8913f, 0.0880f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_WOODEN_CUPBOARD \ + { 1.0000f, 1.0000f, 0.3162f, 0.1413f, 0.3162f, 0.5600f, 0.4600f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_WOODEN_COURTYARD \ + { 1.0000f, 0.6500f, 0.3162f, 0.0794f, 0.3162f, 1.7900f, 0.3500f, 0.7900f, 0.5623f, 0.1230f, { 0.0000f, 0.0000f, 0.0000f }, 0.1000f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_WOODEN_ALCOVE \ + { 1.0000f, 1.0000f, 0.3162f, 0.1259f, 0.3162f, 1.2200f, 0.6200f, 0.9100f, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 4705.0000f, 99.6000f, 0.0000f, 0x1 } + +/* Sports Presets */ + +#define EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM \ + { 1.0000f, 1.0000f, 0.3162f, 0.4467f, 0.7943f, 6.2600f, 0.5100f, 1.1000f, 0.0631f, 0.1830f, { 0.0000f, 0.0000f, 0.0000f }, 0.3981f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPORT_SQUASHCOURT \ + { 1.0000f, 0.7500f, 0.3162f, 0.3162f, 0.7943f, 2.2200f, 0.9100f, 1.1600f, 0.4467f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.1260f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL \ + { 1.0000f, 0.7000f, 0.3162f, 0.7943f, 0.8913f, 2.7600f, 1.2500f, 1.1400f, 0.6310f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_SPORT_LARGESWIMMINGPOOL \ + { 1.0000f, 0.8200f, 0.3162f, 0.7943f, 1.0000f, 5.4900f, 1.3100f, 1.1400f, 0.4467f, 0.0390f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2220f, 0.5500f, 1.1590f, 0.2100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_SPORT_GYMNASIUM \ + { 1.0000f, 0.8100f, 0.3162f, 0.4467f, 0.8913f, 3.1400f, 1.0600f, 1.3500f, 0.3981f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0450f, { 0.0000f, 0.0000f, 0.0000f }, 0.1460f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPORT_FULLSTADIUM \ + { 1.0000f, 1.0000f, 0.3162f, 0.0708f, 0.7943f, 5.2500f, 0.1700f, 0.8000f, 0.1000f, 0.1880f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0380f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SPORT_STADIUMTANNOY \ + { 1.0000f, 0.7800f, 0.3162f, 0.5623f, 0.5012f, 2.5300f, 0.8800f, 0.6800f, 0.2818f, 0.2300f, { 0.0000f, 0.0000f, 0.0000f }, 0.5012f, 0.0630f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +/* Prefab Presets */ + +#define EFX_REVERB_PRESET_PREFAB_WORKSHOP \ + { 0.4287f, 1.0000f, 0.3162f, 0.1413f, 0.3981f, 0.7600f, 1.0000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_PREFAB_SCHOOLROOM \ + { 0.4022f, 0.6900f, 0.3162f, 0.6310f, 0.5012f, 0.9800f, 0.4500f, 0.1800f, 1.4125f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_PREFAB_PRACTISEROOM \ + { 0.4022f, 0.8700f, 0.3162f, 0.3981f, 0.5012f, 1.1200f, 0.5600f, 0.1800f, 1.2589f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0110f, { 0.0000f, 0.0000f, 0.0000f }, 0.0950f, 0.1400f, 0.2500f, 0.0000f, 0.9943f, 7176.8999f, 211.2000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_PREFAB_OUTHOUSE \ + { 1.0000f, 0.8200f, 0.3162f, 0.1122f, 0.1585f, 1.3800f, 0.3800f, 0.3500f, 0.8913f, 0.0240f, { 0.0000f, 0.0000f, -0.0000f }, 0.6310f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.1210f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_PREFAB_CARAVAN \ + { 1.0000f, 1.0000f, 0.3162f, 0.0891f, 0.1259f, 0.4300f, 1.5000f, 1.0000f, 1.0000f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 1.9953f, 0.0120f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +/* Dome and Pipe Presets */ + +#define EFX_REVERB_PRESET_DOME_TOMB \ + { 1.0000f, 0.7900f, 0.3162f, 0.3548f, 0.2239f, 4.1800f, 0.2100f, 0.1000f, 0.3868f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 1.6788f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.1770f, 0.1900f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_PIPE_SMALL \ + { 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 5.0400f, 0.1000f, 0.1000f, 0.5012f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 2.5119f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_DOME_SAINTPAULS \ + { 1.0000f, 0.8700f, 0.3162f, 0.3548f, 0.2239f, 10.4800f, 0.1900f, 0.1000f, 0.1778f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0420f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1200f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_PIPE_LONGTHIN \ + { 0.2560f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 9.2100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_PIPE_LARGE \ + { 1.0000f, 1.0000f, 0.3162f, 0.3548f, 0.2239f, 8.4500f, 0.1000f, 0.1000f, 0.3981f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_PIPE_RESONANT \ + { 0.1373f, 0.9100f, 0.3162f, 0.4467f, 0.2818f, 6.8100f, 0.1800f, 0.1000f, 0.7079f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.0000f, 0.0220f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 20.0000f, 0.0000f, 0x0 } + +/* Outdoors Presets */ + +#define EFX_REVERB_PRESET_OUTDOORS_BACKYARD \ + { 1.0000f, 0.4500f, 0.3162f, 0.2512f, 0.5012f, 1.1200f, 0.3400f, 0.4600f, 0.4467f, 0.0690f, { 0.0000f, 0.0000f, -0.0000f }, 0.7079f, 0.0230f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS \ + { 1.0000f, 0.0000f, 0.3162f, 0.0112f, 0.6310f, 2.1300f, 0.2100f, 0.4600f, 0.1778f, 0.3000f, { 0.0000f, 0.0000f, -0.0000f }, 0.4467f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON \ + { 1.0000f, 0.7400f, 0.3162f, 0.1778f, 0.6310f, 3.8900f, 0.2100f, 0.4600f, 0.3162f, 0.2230f, { 0.0000f, 0.0000f, -0.0000f }, 0.3548f, 0.0190f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_OUTDOORS_CREEK \ + { 1.0000f, 0.3500f, 0.3162f, 0.1778f, 0.5012f, 2.1300f, 0.2100f, 0.4600f, 0.3981f, 0.1150f, { 0.0000f, 0.0000f, -0.0000f }, 0.1995f, 0.0310f, { 0.0000f, 0.0000f, 0.0000f }, 0.2180f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 4399.1001f, 242.9000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_OUTDOORS_VALLEY \ + { 1.0000f, 0.2800f, 0.3162f, 0.0282f, 0.1585f, 2.8800f, 0.2600f, 0.3500f, 0.1413f, 0.2630f, { 0.0000f, 0.0000f, -0.0000f }, 0.3981f, 0.1000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.3400f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 } + +/* Mood Presets */ + +#define EFX_REVERB_PRESET_MOOD_HEAVEN \ + { 1.0000f, 0.9400f, 0.3162f, 0.7943f, 0.4467f, 5.0400f, 1.1200f, 0.5600f, 0.2427f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0290f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0800f, 2.7420f, 0.0500f, 0.9977f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_MOOD_HELL \ + { 1.0000f, 0.5700f, 0.3162f, 0.3548f, 0.4467f, 3.5700f, 0.4900f, 2.0000f, 0.0000f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1100f, 0.0400f, 2.1090f, 0.5200f, 0.9943f, 5000.0000f, 139.5000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_MOOD_MEMORY \ + { 1.0000f, 0.8500f, 0.3162f, 0.6310f, 0.3548f, 4.0600f, 0.8200f, 0.5600f, 0.0398f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.1220f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.4740f, 0.4500f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +/* Driving Presets */ + +#define EFX_REVERB_PRESET_DRIVING_COMMENTATOR \ + { 1.0000f, 0.0000f, 0.3162f, 0.5623f, 0.5012f, 2.4200f, 0.8800f, 0.6800f, 0.1995f, 0.0930f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0170f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 1.0000f, 0.2500f, 0.0000f, 0.9886f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_DRIVING_PITGARAGE \ + { 0.4287f, 0.5900f, 0.3162f, 0.7079f, 0.5623f, 1.7200f, 0.9300f, 0.8700f, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0160f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_DRIVING_INCAR_RACER \ + { 0.0832f, 0.8000f, 0.3162f, 1.0000f, 0.7943f, 0.1700f, 2.0000f, 0.4100f, 1.7783f, 0.0070f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0150f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS \ + { 0.0832f, 0.8000f, 0.3162f, 0.6310f, 1.0000f, 0.1700f, 0.7500f, 0.4100f, 1.0000f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.5623f, 0.0000f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY \ + { 0.2560f, 1.0000f, 0.3162f, 0.1000f, 0.5012f, 0.1300f, 0.4100f, 0.4600f, 0.7943f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 1.5849f, 0.0100f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10268.2002f, 251.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND \ + { 1.0000f, 1.0000f, 0.3162f, 0.2818f, 0.6310f, 3.0100f, 1.3700f, 1.2800f, 0.3548f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.1778f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND \ + { 1.0000f, 1.0000f, 0.3162f, 1.0000f, 0.7943f, 4.6200f, 1.7500f, 1.4000f, 0.2082f, 0.0900f, { 0.0000f, 0.0000f, 0.0000f }, 0.2512f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.0000f, 0.9943f, 10420.2002f, 250.0000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_DRIVING_TUNNEL \ + { 1.0000f, 0.8100f, 0.3162f, 0.3981f, 0.8913f, 3.4200f, 0.9400f, 1.3100f, 0.7079f, 0.0510f, { 0.0000f, 0.0000f, 0.0000f }, 0.7079f, 0.0470f, { 0.0000f, 0.0000f, 0.0000f }, 0.2140f, 0.0500f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 155.3000f, 0.0000f, 0x1 } + +/* City Presets */ + +#define EFX_REVERB_PRESET_CITY_STREETS \ + { 1.0000f, 0.7800f, 0.3162f, 0.7079f, 0.8913f, 1.7900f, 1.1200f, 0.9100f, 0.2818f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 0.1995f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CITY_SUBWAY \ + { 1.0000f, 0.7400f, 0.3162f, 0.7079f, 0.8913f, 3.0100f, 1.2300f, 0.9100f, 0.7079f, 0.0460f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0280f, { 0.0000f, 0.0000f, 0.0000f }, 0.1250f, 0.2100f, 0.2500f, 0.0000f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CITY_MUSEUM \ + { 1.0000f, 0.8200f, 0.3162f, 0.1778f, 0.1778f, 3.2800f, 1.4000f, 0.5700f, 0.2512f, 0.0390f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0340f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_CITY_LIBRARY \ + { 1.0000f, 0.8200f, 0.3162f, 0.2818f, 0.0891f, 2.7600f, 0.8900f, 0.4100f, 0.3548f, 0.0290f, { 0.0000f, 0.0000f, -0.0000f }, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 0.1300f, 0.1700f, 0.2500f, 0.0000f, 0.9943f, 2854.3999f, 107.5000f, 0.0000f, 0x0 } + +#define EFX_REVERB_PRESET_CITY_UNDERPASS \ + { 1.0000f, 0.8200f, 0.3162f, 0.4467f, 0.8913f, 3.5700f, 1.1200f, 0.9100f, 0.3981f, 0.0590f, { 0.0000f, 0.0000f, 0.0000f }, 0.8913f, 0.0370f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.1400f, 0.2500f, 0.0000f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CITY_ABANDONED \ + { 1.0000f, 0.6900f, 0.3162f, 0.7943f, 0.8913f, 3.2800f, 1.1700f, 0.9100f, 0.4467f, 0.0440f, { 0.0000f, 0.0000f, 0.0000f }, 0.2818f, 0.0240f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.2000f, 0.2500f, 0.0000f, 0.9966f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +/* Misc. Presets */ + +#define EFX_REVERB_PRESET_DUSTYROOM \ + { 0.3645f, 0.5600f, 0.3162f, 0.7943f, 0.7079f, 1.7900f, 0.3800f, 0.2100f, 0.5012f, 0.0020f, { 0.0000f, 0.0000f, 0.0000f }, 1.2589f, 0.0060f, { 0.0000f, 0.0000f, 0.0000f }, 0.2020f, 0.0500f, 0.2500f, 0.0000f, 0.9886f, 13046.0000f, 163.3000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_CHAPEL \ + { 1.0000f, 0.8400f, 0.3162f, 0.5623f, 1.0000f, 4.6200f, 0.6400f, 1.2300f, 0.4467f, 0.0320f, { 0.0000f, 0.0000f, 0.0000f }, 0.7943f, 0.0490f, { 0.0000f, 0.0000f, 0.0000f }, 0.2500f, 0.0000f, 0.2500f, 0.1100f, 0.9943f, 5000.0000f, 250.0000f, 0.0000f, 0x1 } + +#define EFX_REVERB_PRESET_SMALLWATERROOM \ + { 1.0000f, 0.7000f, 0.3162f, 0.4477f, 1.0000f, 1.5100f, 1.2500f, 1.1400f, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } + +#endif /* EFX_PRESETS_H */ diff --git a/Engine/lib/openal-soft/include/AL/efx.h b/Engine/lib/openal-soft/include/AL/efx.h new file mode 100644 index 000000000..57766983f --- /dev/null +++ b/Engine/lib/openal-soft/include/AL/efx.h @@ -0,0 +1,761 @@ +#ifndef AL_EFX_H +#define AL_EFX_H + + +#include "alc.h" +#include "al.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ALC_EXT_EFX_NAME "ALC_EXT_EFX" + +#define ALC_EFX_MAJOR_VERSION 0x20001 +#define ALC_EFX_MINOR_VERSION 0x20002 +#define ALC_MAX_AUXILIARY_SENDS 0x20003 + + +/* Listener properties. */ +#define AL_METERS_PER_UNIT 0x20004 + +/* Source properties. */ +#define AL_DIRECT_FILTER 0x20005 +#define AL_AUXILIARY_SEND_FILTER 0x20006 +#define AL_AIR_ABSORPTION_FACTOR 0x20007 +#define AL_ROOM_ROLLOFF_FACTOR 0x20008 +#define AL_CONE_OUTER_GAINHF 0x20009 +#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A +#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B +#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C + + +/* Effect properties. */ + +/* Reverb effect parameters */ +#define AL_REVERB_DENSITY 0x0001 +#define AL_REVERB_DIFFUSION 0x0002 +#define AL_REVERB_GAIN 0x0003 +#define AL_REVERB_GAINHF 0x0004 +#define AL_REVERB_DECAY_TIME 0x0005 +#define AL_REVERB_DECAY_HFRATIO 0x0006 +#define AL_REVERB_REFLECTIONS_GAIN 0x0007 +#define AL_REVERB_REFLECTIONS_DELAY 0x0008 +#define AL_REVERB_LATE_REVERB_GAIN 0x0009 +#define AL_REVERB_LATE_REVERB_DELAY 0x000A +#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B +#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C +#define AL_REVERB_DECAY_HFLIMIT 0x000D + +/* EAX Reverb effect parameters */ +#define AL_EAXREVERB_DENSITY 0x0001 +#define AL_EAXREVERB_DIFFUSION 0x0002 +#define AL_EAXREVERB_GAIN 0x0003 +#define AL_EAXREVERB_GAINHF 0x0004 +#define AL_EAXREVERB_GAINLF 0x0005 +#define AL_EAXREVERB_DECAY_TIME 0x0006 +#define AL_EAXREVERB_DECAY_HFRATIO 0x0007 +#define AL_EAXREVERB_DECAY_LFRATIO 0x0008 +#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009 +#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A +#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B +#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C +#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D +#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E +#define AL_EAXREVERB_ECHO_TIME 0x000F +#define AL_EAXREVERB_ECHO_DEPTH 0x0010 +#define AL_EAXREVERB_MODULATION_TIME 0x0011 +#define AL_EAXREVERB_MODULATION_DEPTH 0x0012 +#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013 +#define AL_EAXREVERB_HFREFERENCE 0x0014 +#define AL_EAXREVERB_LFREFERENCE 0x0015 +#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016 +#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017 + +/* Chorus effect parameters */ +#define AL_CHORUS_WAVEFORM 0x0001 +#define AL_CHORUS_PHASE 0x0002 +#define AL_CHORUS_RATE 0x0003 +#define AL_CHORUS_DEPTH 0x0004 +#define AL_CHORUS_FEEDBACK 0x0005 +#define AL_CHORUS_DELAY 0x0006 + +/* Distortion effect parameters */ +#define AL_DISTORTION_EDGE 0x0001 +#define AL_DISTORTION_GAIN 0x0002 +#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003 +#define AL_DISTORTION_EQCENTER 0x0004 +#define AL_DISTORTION_EQBANDWIDTH 0x0005 + +/* Echo effect parameters */ +#define AL_ECHO_DELAY 0x0001 +#define AL_ECHO_LRDELAY 0x0002 +#define AL_ECHO_DAMPING 0x0003 +#define AL_ECHO_FEEDBACK 0x0004 +#define AL_ECHO_SPREAD 0x0005 + +/* Flanger effect parameters */ +#define AL_FLANGER_WAVEFORM 0x0001 +#define AL_FLANGER_PHASE 0x0002 +#define AL_FLANGER_RATE 0x0003 +#define AL_FLANGER_DEPTH 0x0004 +#define AL_FLANGER_FEEDBACK 0x0005 +#define AL_FLANGER_DELAY 0x0006 + +/* Frequency shifter effect parameters */ +#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001 +#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002 +#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003 + +/* Vocal morpher effect parameters */ +#define AL_VOCAL_MORPHER_PHONEMEA 0x0001 +#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002 +#define AL_VOCAL_MORPHER_PHONEMEB 0x0003 +#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004 +#define AL_VOCAL_MORPHER_WAVEFORM 0x0005 +#define AL_VOCAL_MORPHER_RATE 0x0006 + +/* Pitchshifter effect parameters */ +#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001 +#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002 + +/* Ringmodulator effect parameters */ +#define AL_RING_MODULATOR_FREQUENCY 0x0001 +#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002 +#define AL_RING_MODULATOR_WAVEFORM 0x0003 + +/* Autowah effect parameters */ +#define AL_AUTOWAH_ATTACK_TIME 0x0001 +#define AL_AUTOWAH_RELEASE_TIME 0x0002 +#define AL_AUTOWAH_RESONANCE 0x0003 +#define AL_AUTOWAH_PEAK_GAIN 0x0004 + +/* Compressor effect parameters */ +#define AL_COMPRESSOR_ONOFF 0x0001 + +/* Equalizer effect parameters */ +#define AL_EQUALIZER_LOW_GAIN 0x0001 +#define AL_EQUALIZER_LOW_CUTOFF 0x0002 +#define AL_EQUALIZER_MID1_GAIN 0x0003 +#define AL_EQUALIZER_MID1_CENTER 0x0004 +#define AL_EQUALIZER_MID1_WIDTH 0x0005 +#define AL_EQUALIZER_MID2_GAIN 0x0006 +#define AL_EQUALIZER_MID2_CENTER 0x0007 +#define AL_EQUALIZER_MID2_WIDTH 0x0008 +#define AL_EQUALIZER_HIGH_GAIN 0x0009 +#define AL_EQUALIZER_HIGH_CUTOFF 0x000A + +/* Effect type */ +#define AL_EFFECT_FIRST_PARAMETER 0x0000 +#define AL_EFFECT_LAST_PARAMETER 0x8000 +#define AL_EFFECT_TYPE 0x8001 + +/* Effect types, used with the AL_EFFECT_TYPE property */ +#define AL_EFFECT_NULL 0x0000 +#define AL_EFFECT_REVERB 0x0001 +#define AL_EFFECT_CHORUS 0x0002 +#define AL_EFFECT_DISTORTION 0x0003 +#define AL_EFFECT_ECHO 0x0004 +#define AL_EFFECT_FLANGER 0x0005 +#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 +#define AL_EFFECT_VOCAL_MORPHER 0x0007 +#define AL_EFFECT_PITCH_SHIFTER 0x0008 +#define AL_EFFECT_RING_MODULATOR 0x0009 +#define AL_EFFECT_AUTOWAH 0x000A +#define AL_EFFECT_COMPRESSOR 0x000B +#define AL_EFFECT_EQUALIZER 0x000C +#define AL_EFFECT_EAXREVERB 0x8000 + +/* Auxiliary Effect Slot properties. */ +#define AL_EFFECTSLOT_EFFECT 0x0001 +#define AL_EFFECTSLOT_GAIN 0x0002 +#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003 + +/* NULL Auxiliary Slot ID to disable a source send. */ +#define AL_EFFECTSLOT_NULL 0x0000 + + +/* Filter properties. */ + +/* Lowpass filter parameters */ +#define AL_LOWPASS_GAIN 0x0001 +#define AL_LOWPASS_GAINHF 0x0002 + +/* Highpass filter parameters */ +#define AL_HIGHPASS_GAIN 0x0001 +#define AL_HIGHPASS_GAINLF 0x0002 + +/* Bandpass filter parameters */ +#define AL_BANDPASS_GAIN 0x0001 +#define AL_BANDPASS_GAINLF 0x0002 +#define AL_BANDPASS_GAINHF 0x0003 + +/* Filter type */ +#define AL_FILTER_FIRST_PARAMETER 0x0000 +#define AL_FILTER_LAST_PARAMETER 0x8000 +#define AL_FILTER_TYPE 0x8001 + +/* Filter types, used with the AL_FILTER_TYPE property */ +#define AL_FILTER_NULL 0x0000 +#define AL_FILTER_LOWPASS 0x0001 +#define AL_FILTER_HIGHPASS 0x0002 +#define AL_FILTER_BANDPASS 0x0003 + + +/* Effect object function types. */ +typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, const ALuint*); +typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint); +typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); +typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, const ALint*); +typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat); +typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, const ALfloat*); +typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*); + +/* Filter object function types. */ +typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, const ALuint*); +typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint); +typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); +typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, const ALint*); +typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat); +typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, const ALfloat*); +typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*); + +/* Auxiliary Effect Slot object function types. */ +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, const ALuint*); +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, const ALint*); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat); +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, const ALfloat*); +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*); +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); + +#ifdef AL_ALEXT_PROTOTYPES +AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects); +AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, const ALuint *effects); +AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect); +AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue); +AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, const ALint *piValues); +AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue); +AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, const ALfloat *pflValues); +AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue); +AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues); +AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue); +AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); + +AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters); +AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, const ALuint *filters); +AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter); +AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue); +AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, const ALint *piValues); +AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue); +AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, const ALfloat *pflValues); +AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue); +AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues); +AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue); +AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); + +AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); +AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots); +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot); +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue); +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *piValues); +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue); +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *pflValues); +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue); +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue); +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); +#endif + +/* Filter ranges and defaults. */ + +/* Lowpass filter */ +#define AL_LOWPASS_MIN_GAIN (0.0f) +#define AL_LOWPASS_MAX_GAIN (1.0f) +#define AL_LOWPASS_DEFAULT_GAIN (1.0f) + +#define AL_LOWPASS_MIN_GAINHF (0.0f) +#define AL_LOWPASS_MAX_GAINHF (1.0f) +#define AL_LOWPASS_DEFAULT_GAINHF (1.0f) + +/* Highpass filter */ +#define AL_HIGHPASS_MIN_GAIN (0.0f) +#define AL_HIGHPASS_MAX_GAIN (1.0f) +#define AL_HIGHPASS_DEFAULT_GAIN (1.0f) + +#define AL_HIGHPASS_MIN_GAINLF (0.0f) +#define AL_HIGHPASS_MAX_GAINLF (1.0f) +#define AL_HIGHPASS_DEFAULT_GAINLF (1.0f) + +/* Bandpass filter */ +#define AL_BANDPASS_MIN_GAIN (0.0f) +#define AL_BANDPASS_MAX_GAIN (1.0f) +#define AL_BANDPASS_DEFAULT_GAIN (1.0f) + +#define AL_BANDPASS_MIN_GAINHF (0.0f) +#define AL_BANDPASS_MAX_GAINHF (1.0f) +#define AL_BANDPASS_DEFAULT_GAINHF (1.0f) + +#define AL_BANDPASS_MIN_GAINLF (0.0f) +#define AL_BANDPASS_MAX_GAINLF (1.0f) +#define AL_BANDPASS_DEFAULT_GAINLF (1.0f) + + +/* Effect parameter ranges and defaults. */ + +/* Standard reverb effect */ +#define AL_REVERB_MIN_DENSITY (0.0f) +#define AL_REVERB_MAX_DENSITY (1.0f) +#define AL_REVERB_DEFAULT_DENSITY (1.0f) + +#define AL_REVERB_MIN_DIFFUSION (0.0f) +#define AL_REVERB_MAX_DIFFUSION (1.0f) +#define AL_REVERB_DEFAULT_DIFFUSION (1.0f) + +#define AL_REVERB_MIN_GAIN (0.0f) +#define AL_REVERB_MAX_GAIN (1.0f) +#define AL_REVERB_DEFAULT_GAIN (0.32f) + +#define AL_REVERB_MIN_GAINHF (0.0f) +#define AL_REVERB_MAX_GAINHF (1.0f) +#define AL_REVERB_DEFAULT_GAINHF (0.89f) + +#define AL_REVERB_MIN_DECAY_TIME (0.1f) +#define AL_REVERB_MAX_DECAY_TIME (20.0f) +#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f) + +#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f) +#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f) +#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f) + +#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f) +#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f) +#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f) + +#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f) +#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f) +#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f) + +#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f) +#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f) +#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f) + +#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f) +#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f) +#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f) + +#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f) +#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f) +#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f) + +#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f) +#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f) +#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) + +#define AL_REVERB_MIN_DECAY_HFLIMIT AL_FALSE +#define AL_REVERB_MAX_DECAY_HFLIMIT AL_TRUE +#define AL_REVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE + +/* EAX reverb effect */ +#define AL_EAXREVERB_MIN_DENSITY (0.0f) +#define AL_EAXREVERB_MAX_DENSITY (1.0f) +#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f) + +#define AL_EAXREVERB_MIN_DIFFUSION (0.0f) +#define AL_EAXREVERB_MAX_DIFFUSION (1.0f) +#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f) + +#define AL_EAXREVERB_MIN_GAIN (0.0f) +#define AL_EAXREVERB_MAX_GAIN (1.0f) +#define AL_EAXREVERB_DEFAULT_GAIN (0.32f) + +#define AL_EAXREVERB_MIN_GAINHF (0.0f) +#define AL_EAXREVERB_MAX_GAINHF (1.0f) +#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f) + +#define AL_EAXREVERB_MIN_GAINLF (0.0f) +#define AL_EAXREVERB_MAX_GAINLF (1.0f) +#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f) + +#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f) +#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f) +#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f) + +#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f) +#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f) +#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f) + +#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f) +#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f) +#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f) + +#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f) +#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f) +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f) + +#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f) +#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f) +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f) + +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f) + +#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f) +#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f) +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f) + +#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f) +#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f) +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f) + +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f) + +#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f) +#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f) +#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f) + +#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f) +#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f) +#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f) + +#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f) +#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f) +#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f) + +#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f) +#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f) +#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f) + +#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f) +#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f) +#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f) + +#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f) +#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f) +#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f) + +#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f) +#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f) +#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f) + +#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f) +#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f) +#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) + +#define AL_EAXREVERB_MIN_DECAY_HFLIMIT AL_FALSE +#define AL_EAXREVERB_MAX_DECAY_HFLIMIT AL_TRUE +#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE + +/* Chorus effect */ +#define AL_CHORUS_WAVEFORM_SINUSOID (0) +#define AL_CHORUS_WAVEFORM_TRIANGLE (1) + +#define AL_CHORUS_MIN_WAVEFORM (0) +#define AL_CHORUS_MAX_WAVEFORM (1) +#define AL_CHORUS_DEFAULT_WAVEFORM (1) + +#define AL_CHORUS_MIN_PHASE (-180) +#define AL_CHORUS_MAX_PHASE (180) +#define AL_CHORUS_DEFAULT_PHASE (90) + +#define AL_CHORUS_MIN_RATE (0.0f) +#define AL_CHORUS_MAX_RATE (10.0f) +#define AL_CHORUS_DEFAULT_RATE (1.1f) + +#define AL_CHORUS_MIN_DEPTH (0.0f) +#define AL_CHORUS_MAX_DEPTH (1.0f) +#define AL_CHORUS_DEFAULT_DEPTH (0.1f) + +#define AL_CHORUS_MIN_FEEDBACK (-1.0f) +#define AL_CHORUS_MAX_FEEDBACK (1.0f) +#define AL_CHORUS_DEFAULT_FEEDBACK (0.25f) + +#define AL_CHORUS_MIN_DELAY (0.0f) +#define AL_CHORUS_MAX_DELAY (0.016f) +#define AL_CHORUS_DEFAULT_DELAY (0.016f) + +/* Distortion effect */ +#define AL_DISTORTION_MIN_EDGE (0.0f) +#define AL_DISTORTION_MAX_EDGE (1.0f) +#define AL_DISTORTION_DEFAULT_EDGE (0.2f) + +#define AL_DISTORTION_MIN_GAIN (0.01f) +#define AL_DISTORTION_MAX_GAIN (1.0f) +#define AL_DISTORTION_DEFAULT_GAIN (0.05f) + +#define AL_DISTORTION_MIN_LOWPASS_CUTOFF (80.0f) +#define AL_DISTORTION_MAX_LOWPASS_CUTOFF (24000.0f) +#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF (8000.0f) + +#define AL_DISTORTION_MIN_EQCENTER (80.0f) +#define AL_DISTORTION_MAX_EQCENTER (24000.0f) +#define AL_DISTORTION_DEFAULT_EQCENTER (3600.0f) + +#define AL_DISTORTION_MIN_EQBANDWIDTH (80.0f) +#define AL_DISTORTION_MAX_EQBANDWIDTH (24000.0f) +#define AL_DISTORTION_DEFAULT_EQBANDWIDTH (3600.0f) + +/* Echo effect */ +#define AL_ECHO_MIN_DELAY (0.0f) +#define AL_ECHO_MAX_DELAY (0.207f) +#define AL_ECHO_DEFAULT_DELAY (0.1f) + +#define AL_ECHO_MIN_LRDELAY (0.0f) +#define AL_ECHO_MAX_LRDELAY (0.404f) +#define AL_ECHO_DEFAULT_LRDELAY (0.1f) + +#define AL_ECHO_MIN_DAMPING (0.0f) +#define AL_ECHO_MAX_DAMPING (0.99f) +#define AL_ECHO_DEFAULT_DAMPING (0.5f) + +#define AL_ECHO_MIN_FEEDBACK (0.0f) +#define AL_ECHO_MAX_FEEDBACK (1.0f) +#define AL_ECHO_DEFAULT_FEEDBACK (0.5f) + +#define AL_ECHO_MIN_SPREAD (-1.0f) +#define AL_ECHO_MAX_SPREAD (1.0f) +#define AL_ECHO_DEFAULT_SPREAD (-1.0f) + +/* Flanger effect */ +#define AL_FLANGER_WAVEFORM_SINUSOID (0) +#define AL_FLANGER_WAVEFORM_TRIANGLE (1) + +#define AL_FLANGER_MIN_WAVEFORM (0) +#define AL_FLANGER_MAX_WAVEFORM (1) +#define AL_FLANGER_DEFAULT_WAVEFORM (1) + +#define AL_FLANGER_MIN_PHASE (-180) +#define AL_FLANGER_MAX_PHASE (180) +#define AL_FLANGER_DEFAULT_PHASE (0) + +#define AL_FLANGER_MIN_RATE (0.0f) +#define AL_FLANGER_MAX_RATE (10.0f) +#define AL_FLANGER_DEFAULT_RATE (0.27f) + +#define AL_FLANGER_MIN_DEPTH (0.0f) +#define AL_FLANGER_MAX_DEPTH (1.0f) +#define AL_FLANGER_DEFAULT_DEPTH (1.0f) + +#define AL_FLANGER_MIN_FEEDBACK (-1.0f) +#define AL_FLANGER_MAX_FEEDBACK (1.0f) +#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f) + +#define AL_FLANGER_MIN_DELAY (0.0f) +#define AL_FLANGER_MAX_DELAY (0.004f) +#define AL_FLANGER_DEFAULT_DELAY (0.002f) + +/* Frequency shifter effect */ +#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY (0.0f) +#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY (24000.0f) +#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY (0.0f) + +#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION (0) +#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION (2) +#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION (0) + +#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN (0) +#define AL_FREQUENCY_SHIFTER_DIRECTION_UP (1) +#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF (2) + +#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION (0) +#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION (2) +#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION (0) + +/* Vocal morpher effect */ +#define AL_VOCAL_MORPHER_MIN_PHONEMEA (0) +#define AL_VOCAL_MORPHER_MAX_PHONEMEA (29) +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA (0) + +#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24) +#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING (24) +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING (0) + +#define AL_VOCAL_MORPHER_MIN_PHONEMEB (0) +#define AL_VOCAL_MORPHER_MAX_PHONEMEB (29) +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB (10) + +#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24) +#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING (24) +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING (0) + +#define AL_VOCAL_MORPHER_PHONEME_A (0) +#define AL_VOCAL_MORPHER_PHONEME_E (1) +#define AL_VOCAL_MORPHER_PHONEME_I (2) +#define AL_VOCAL_MORPHER_PHONEME_O (3) +#define AL_VOCAL_MORPHER_PHONEME_U (4) +#define AL_VOCAL_MORPHER_PHONEME_AA (5) +#define AL_VOCAL_MORPHER_PHONEME_AE (6) +#define AL_VOCAL_MORPHER_PHONEME_AH (7) +#define AL_VOCAL_MORPHER_PHONEME_AO (8) +#define AL_VOCAL_MORPHER_PHONEME_EH (9) +#define AL_VOCAL_MORPHER_PHONEME_ER (10) +#define AL_VOCAL_MORPHER_PHONEME_IH (11) +#define AL_VOCAL_MORPHER_PHONEME_IY (12) +#define AL_VOCAL_MORPHER_PHONEME_UH (13) +#define AL_VOCAL_MORPHER_PHONEME_UW (14) +#define AL_VOCAL_MORPHER_PHONEME_B (15) +#define AL_VOCAL_MORPHER_PHONEME_D (16) +#define AL_VOCAL_MORPHER_PHONEME_F (17) +#define AL_VOCAL_MORPHER_PHONEME_G (18) +#define AL_VOCAL_MORPHER_PHONEME_J (19) +#define AL_VOCAL_MORPHER_PHONEME_K (20) +#define AL_VOCAL_MORPHER_PHONEME_L (21) +#define AL_VOCAL_MORPHER_PHONEME_M (22) +#define AL_VOCAL_MORPHER_PHONEME_N (23) +#define AL_VOCAL_MORPHER_PHONEME_P (24) +#define AL_VOCAL_MORPHER_PHONEME_R (25) +#define AL_VOCAL_MORPHER_PHONEME_S (26) +#define AL_VOCAL_MORPHER_PHONEME_T (27) +#define AL_VOCAL_MORPHER_PHONEME_V (28) +#define AL_VOCAL_MORPHER_PHONEME_Z (29) + +#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID (0) +#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE (1) +#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH (2) + +#define AL_VOCAL_MORPHER_MIN_WAVEFORM (0) +#define AL_VOCAL_MORPHER_MAX_WAVEFORM (2) +#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM (0) + +#define AL_VOCAL_MORPHER_MIN_RATE (0.0f) +#define AL_VOCAL_MORPHER_MAX_RATE (10.0f) +#define AL_VOCAL_MORPHER_DEFAULT_RATE (1.41f) + +/* Pitch shifter effect */ +#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12) +#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE (12) +#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE (12) + +#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50) +#define AL_PITCH_SHIFTER_MAX_FINE_TUNE (50) +#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE (0) + +/* Ring modulator effect */ +#define AL_RING_MODULATOR_MIN_FREQUENCY (0.0f) +#define AL_RING_MODULATOR_MAX_FREQUENCY (8000.0f) +#define AL_RING_MODULATOR_DEFAULT_FREQUENCY (440.0f) + +#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF (0.0f) +#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF (24000.0f) +#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF (800.0f) + +#define AL_RING_MODULATOR_SINUSOID (0) +#define AL_RING_MODULATOR_SAWTOOTH (1) +#define AL_RING_MODULATOR_SQUARE (2) + +#define AL_RING_MODULATOR_MIN_WAVEFORM (0) +#define AL_RING_MODULATOR_MAX_WAVEFORM (2) +#define AL_RING_MODULATOR_DEFAULT_WAVEFORM (0) + +/* Autowah effect */ +#define AL_AUTOWAH_MIN_ATTACK_TIME (0.0001f) +#define AL_AUTOWAH_MAX_ATTACK_TIME (1.0f) +#define AL_AUTOWAH_DEFAULT_ATTACK_TIME (0.06f) + +#define AL_AUTOWAH_MIN_RELEASE_TIME (0.0001f) +#define AL_AUTOWAH_MAX_RELEASE_TIME (1.0f) +#define AL_AUTOWAH_DEFAULT_RELEASE_TIME (0.06f) + +#define AL_AUTOWAH_MIN_RESONANCE (2.0f) +#define AL_AUTOWAH_MAX_RESONANCE (1000.0f) +#define AL_AUTOWAH_DEFAULT_RESONANCE (1000.0f) + +#define AL_AUTOWAH_MIN_PEAK_GAIN (0.00003f) +#define AL_AUTOWAH_MAX_PEAK_GAIN (31621.0f) +#define AL_AUTOWAH_DEFAULT_PEAK_GAIN (11.22f) + +/* Compressor effect */ +#define AL_COMPRESSOR_MIN_ONOFF (0) +#define AL_COMPRESSOR_MAX_ONOFF (1) +#define AL_COMPRESSOR_DEFAULT_ONOFF (1) + +/* Equalizer effect */ +#define AL_EQUALIZER_MIN_LOW_GAIN (0.126f) +#define AL_EQUALIZER_MAX_LOW_GAIN (7.943f) +#define AL_EQUALIZER_DEFAULT_LOW_GAIN (1.0f) + +#define AL_EQUALIZER_MIN_LOW_CUTOFF (50.0f) +#define AL_EQUALIZER_MAX_LOW_CUTOFF (800.0f) +#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF (200.0f) + +#define AL_EQUALIZER_MIN_MID1_GAIN (0.126f) +#define AL_EQUALIZER_MAX_MID1_GAIN (7.943f) +#define AL_EQUALIZER_DEFAULT_MID1_GAIN (1.0f) + +#define AL_EQUALIZER_MIN_MID1_CENTER (200.0f) +#define AL_EQUALIZER_MAX_MID1_CENTER (3000.0f) +#define AL_EQUALIZER_DEFAULT_MID1_CENTER (500.0f) + +#define AL_EQUALIZER_MIN_MID1_WIDTH (0.01f) +#define AL_EQUALIZER_MAX_MID1_WIDTH (1.0f) +#define AL_EQUALIZER_DEFAULT_MID1_WIDTH (1.0f) + +#define AL_EQUALIZER_MIN_MID2_GAIN (0.126f) +#define AL_EQUALIZER_MAX_MID2_GAIN (7.943f) +#define AL_EQUALIZER_DEFAULT_MID2_GAIN (1.0f) + +#define AL_EQUALIZER_MIN_MID2_CENTER (1000.0f) +#define AL_EQUALIZER_MAX_MID2_CENTER (8000.0f) +#define AL_EQUALIZER_DEFAULT_MID2_CENTER (3000.0f) + +#define AL_EQUALIZER_MIN_MID2_WIDTH (0.01f) +#define AL_EQUALIZER_MAX_MID2_WIDTH (1.0f) +#define AL_EQUALIZER_DEFAULT_MID2_WIDTH (1.0f) + +#define AL_EQUALIZER_MIN_HIGH_GAIN (0.126f) +#define AL_EQUALIZER_MAX_HIGH_GAIN (7.943f) +#define AL_EQUALIZER_DEFAULT_HIGH_GAIN (1.0f) + +#define AL_EQUALIZER_MIN_HIGH_CUTOFF (4000.0f) +#define AL_EQUALIZER_MAX_HIGH_CUTOFF (16000.0f) +#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF (6000.0f) + + +/* Source parameter value ranges and defaults. */ +#define AL_MIN_AIR_ABSORPTION_FACTOR (0.0f) +#define AL_MAX_AIR_ABSORPTION_FACTOR (10.0f) +#define AL_DEFAULT_AIR_ABSORPTION_FACTOR (0.0f) + +#define AL_MIN_ROOM_ROLLOFF_FACTOR (0.0f) +#define AL_MAX_ROOM_ROLLOFF_FACTOR (10.0f) +#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) + +#define AL_MIN_CONE_OUTER_GAINHF (0.0f) +#define AL_MAX_CONE_OUTER_GAINHF (1.0f) +#define AL_DEFAULT_CONE_OUTER_GAINHF (1.0f) + +#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE +#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE +#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE + +#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE +#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE +#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE + +#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE +#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE +#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE + + +/* Listener parameter value ranges and defaults. */ +#define AL_MIN_METERS_PER_UNIT FLT_MIN +#define AL_MAX_METERS_PER_UNIT FLT_MAX +#define AL_DEFAULT_METERS_PER_UNIT (1.0f) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* AL_EFX_H */ diff --git a/Engine/lib/openal-soft/include/align.h b/Engine/lib/openal-soft/include/align.h new file mode 100644 index 000000000..e2dc81dff --- /dev/null +++ b/Engine/lib/openal-soft/include/align.h @@ -0,0 +1,21 @@ +#ifndef AL_ALIGN_H +#define AL_ALIGN_H + +#if defined(HAVE_STDALIGN_H) && defined(HAVE_C11_ALIGNAS) +#include +#endif + +#ifndef alignas +#if defined(IN_IDE_PARSER) +/* KDevelop has problems with our align macro, so just use nothing for parsing. */ +#define alignas(x) +#elif defined(HAVE_C11_ALIGNAS) +#define alignas _Alignas +#else +/* NOTE: Our custom ALIGN macro can't take a type name like alignas can. For + * maximum compatibility, only provide constant integer values to alignas. */ +#define alignas(_x) ALIGN(_x) +#endif +#endif + +#endif /* AL_ALIGN_H */ diff --git a/Engine/lib/openal-soft/include/almalloc.h b/Engine/lib/openal-soft/include/almalloc.h new file mode 100644 index 000000000..355db7954 --- /dev/null +++ b/Engine/lib/openal-soft/include/almalloc.h @@ -0,0 +1,18 @@ +#ifndef AL_MALLOC_H +#define AL_MALLOC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *al_malloc(size_t alignment, size_t size); +void *al_calloc(size_t alignment, size_t size); +void al_free(void *ptr); + +#ifdef __cplusplus +} +#endif + +#endif /* AL_MALLOC_H */ diff --git a/Engine/lib/openal-soft/include/atomic.h b/Engine/lib/openal-soft/include/atomic.h new file mode 100644 index 000000000..2a996625a --- /dev/null +++ b/Engine/lib/openal-soft/include/atomic.h @@ -0,0 +1,317 @@ +#ifndef AL_ATOMIC_H +#define AL_ATOMIC_H + +#include "static_assert.h" +#include "bool.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Atomics using C11 */ +#ifdef HAVE_C11_ATOMIC + +#include + +#define almemory_order memory_order +#define almemory_order_relaxed memory_order_relaxed +#define almemory_order_consume memory_order_consume +#define almemory_order_acquire memory_order_acquire +#define almemory_order_release memory_order_release +#define almemory_order_acq_rel memory_order_acq_rel +#define almemory_order_seq_cst memory_order_seq_cst + +#define ATOMIC(T) T _Atomic + +#define ATOMIC_INIT(_val, _newval) atomic_init((_val), (_newval)) +#define ATOMIC_INIT_STATIC(_newval) ATOMIC_VAR_INIT(_newval) + +#define PARAM2(f, a, b, ...) (f((a), (b))) +#define PARAM3(f, a, b, c, ...) (f((a), (b), (c))) +#define PARAM5(f, a, b, c, d, e, ...) (f((a), (b), (c), (d), (e))) + +#define ATOMIC_LOAD(...) PARAM2(atomic_load_explicit, __VA_ARGS__, memory_order_seq_cst) +#define ATOMIC_STORE(...) PARAM3(atomic_store_explicit, __VA_ARGS__, memory_order_seq_cst) + +#define ATOMIC_ADD(T, ...) PARAM3(atomic_fetch_add_explicit, __VA_ARGS__, memory_order_seq_cst) +#define ATOMIC_SUB(T, ...) PARAM3(atomic_fetch_sub_explicit, __VA_ARGS__, memory_order_seq_cst) + +#define ATOMIC_EXCHANGE(T, ...) PARAM3(atomic_exchange_explicit, __VA_ARGS__, memory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, ...) \ + PARAM5(atomic_compare_exchange_strong_explicit, __VA_ARGS__, memory_order_seq_cst, memory_order_seq_cst) +#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, ...) \ + PARAM5(atomic_compare_exchange_weak_explicit, __VA_ARGS__, memory_order_seq_cst, memory_order_seq_cst) + +/* Atomics using GCC intrinsics */ +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__QNXNTO__) + +enum almemory_order { + almemory_order_relaxed, + almemory_order_consume, + almemory_order_acquire, + almemory_order_release, + almemory_order_acq_rel, + almemory_order_seq_cst +}; + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_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" \ +) + + +enum almemory_order { + almemory_order_relaxed, + almemory_order_consume, + almemory_order_acquire, + almemory_order_release, + almemory_order_acq_rel, + almemory_order_seq_cst +}; + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_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 + +/* 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)) + + +enum almemory_order { + almemory_order_relaxed, + almemory_order_consume, + almemory_order_acquire, + almemory_order_release, + almemory_order_acq_rel, + almemory_order_seq_cst +}; + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_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 ATOMIC_COMPARE_EXCHANGE_STRONG +#endif + + +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; } + + +/* This is *NOT* atomic, but is a handy utility macro to compare-and-swap non- + * atomic variables. */ +#define COMPARE_EXCHANGE(_val, _oldval, _newval) ((*(_val) == *(_oldval)) ? ((*(_val)=(_newval)),true) : ((*(_oldval)=*(_val)),false)) + + +#ifdef __cplusplus +} +#endif + +#endif /* AL_ATOMIC_H */ diff --git a/Engine/lib/openal-soft/include/bool.h b/Engine/lib/openal-soft/include/bool.h new file mode 100644 index 000000000..6f714d09e --- /dev/null +++ b/Engine/lib/openal-soft/include/bool.h @@ -0,0 +1,18 @@ +#ifndef AL_BOOL_H +#define AL_BOOL_H + +#ifdef HAVE_STDBOOL_H +#include +#endif + +#ifndef bool +#ifdef HAVE_C99_BOOL +#define bool _Bool +#else +#define bool int +#endif +#define false 0 +#define true 1 +#endif + +#endif /* AL_BOOL_H */ diff --git a/Engine/lib/openal-soft/include/math_defs.h b/Engine/lib/openal-soft/include/math_defs.h new file mode 100644 index 000000000..149cf80ba --- /dev/null +++ b/Engine/lib/openal-soft/include/math_defs.h @@ -0,0 +1,19 @@ +#ifndef AL_MATH_DEFS_H +#define AL_MATH_DEFS_H + +#ifdef HAVE_FLOAT_H +#include +#endif + +#define F_PI (3.14159265358979323846f) +#define F_PI_2 (1.57079632679489661923f) +#define F_TAU (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)) + +#endif /* AL_MATH_DEFS_H */ diff --git a/Engine/lib/openal-soft/include/rwlock.h b/Engine/lib/openal-soft/include/rwlock.h new file mode 100644 index 000000000..158a06708 --- /dev/null +++ b/Engine/lib/openal-soft/include/rwlock.h @@ -0,0 +1,32 @@ +#ifndef AL_RWLOCK_H +#define AL_RWLOCK_H + +#include "bool.h" +#include "atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + RefCount read_count; + RefCount write_count; + ATOMIC(int) read_lock; + ATOMIC(int) read_entry_lock; + ATOMIC(int) write_lock; +} RWLock; +#define RWLOCK_STATIC_INITIALIZE { ATOMIC_INIT_STATIC(0), ATOMIC_INIT_STATIC(0), \ + ATOMIC_INIT_STATIC(false), ATOMIC_INIT_STATIC(false), \ + ATOMIC_INIT_STATIC(false) } + +void RWLockInit(RWLock *lock); +void ReadLock(RWLock *lock); +void ReadUnlock(RWLock *lock); +void WriteLock(RWLock *lock); +void WriteUnlock(RWLock *lock); + +#ifdef __cplusplus +} +#endif + +#endif /* AL_RWLOCK_H */ diff --git a/Engine/lib/openal-soft/include/static_assert.h b/Engine/lib/openal-soft/include/static_assert.h new file mode 100644 index 000000000..bf0ce0657 --- /dev/null +++ b/Engine/lib/openal-soft/include/static_assert.h @@ -0,0 +1,21 @@ +#ifndef AL_STATIC_ASSERT_H +#define AL_STATIC_ASSERT_H + +#include + + +#ifndef static_assert +#ifdef HAVE_C11_STATIC_ASSERT +#define static_assert _Static_assert +#else +#define CTASTR2(_pre,_post) _pre##_post +#define CTASTR(_pre,_post) CTASTR2(_pre,_post) +#if defined(__COUNTER__) +#define static_assert(_cond, _msg) typedef struct { int CTASTR(static_assert_failed_at_line_,__LINE__) : !!(_cond); } CTASTR(static_assertion_,__COUNTER__) +#else +#define static_assert(_cond, _msg) struct { int CTASTR(static_assert_failed_at_line_,__LINE__) : !!(_cond); } +#endif +#endif +#endif + +#endif /* AL_STATIC_ASSERT_H */ diff --git a/Engine/lib/openal-soft/include/threads.h b/Engine/lib/openal-soft/include/threads.h new file mode 100644 index 000000000..c2848ee77 --- /dev/null +++ b/Engine/lib/openal-soft/include/threads.h @@ -0,0 +1,237 @@ +#ifndef AL_THREADS_H +#define AL_THREADS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + althrd_success = 0, + althrd_error, + althrd_nomem, + althrd_timedout, + althrd_busy +}; + +enum { + almtx_plain = 0, + almtx_recursive = 1, + almtx_timed = 2 +}; + +typedef int (*althrd_start_t)(void*); +typedef void (*altss_dtor_t)(void*); + + +#define AL_TIME_UTC 1 + + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + + +#ifndef HAVE_STRUCT_TIMESPEC +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif + +typedef DWORD althrd_t; +typedef CRITICAL_SECTION almtx_t; +#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x0600 +typedef CONDITION_VARIABLE alcnd_t; +#else +typedef struct { void *Ptr; } alcnd_t; +#endif +typedef DWORD altss_t; +typedef LONG alonce_flag; + +#define AL_ONCE_FLAG_INIT 0 + +int althrd_sleep(const struct timespec *ts, struct timespec *rem); +void alcall_once(alonce_flag *once, void (*callback)(void)); + + +inline althrd_t althrd_current(void) +{ + return GetCurrentThreadId(); +} + +inline int althrd_equal(althrd_t thr0, althrd_t thr1) +{ + return thr0 == thr1; +} + +inline void althrd_exit(int res) +{ + ExitThread(res); +} + +inline void althrd_yield(void) +{ + SwitchToThread(); +} + + +inline int almtx_lock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + EnterCriticalSection(mtx); + return althrd_success; +} + +inline int almtx_unlock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + LeaveCriticalSection(mtx); + return althrd_success; +} + +inline int almtx_trylock(almtx_t *mtx) +{ + if(!mtx) return althrd_error; + if(!TryEnterCriticalSection(mtx)) + return althrd_busy; + return althrd_success; +} + + +inline void *altss_get(altss_t tss_id) +{ + return TlsGetValue(tss_id); +} + +inline int altss_set(altss_t tss_id, void *val) +{ + if(TlsSetValue(tss_id, val) == 0) + return althrd_error; + return althrd_success; +} + +#else + +#include +#include +#include + + +typedef pthread_t althrd_t; +typedef pthread_mutex_t almtx_t; +typedef pthread_cond_t alcnd_t; +typedef pthread_key_t altss_t; +typedef pthread_once_t alonce_flag; + +#define AL_ONCE_FLAG_INIT PTHREAD_ONCE_INIT + + +inline althrd_t althrd_current(void) +{ + return pthread_self(); +} + +inline int althrd_equal(althrd_t thr0, althrd_t thr1) +{ + return pthread_equal(thr0, thr1); +} + +inline void althrd_exit(int res) +{ + pthread_exit((void*)(intptr_t)res); +} + +inline void althrd_yield(void) +{ + sched_yield(); +} + +inline int althrd_sleep(const struct timespec *ts, struct timespec *rem) +{ + int ret = nanosleep(ts, rem); + if(ret != 0) + { + ret = ((errno==EINTR) ? -1 : -2); + errno = 0; + } + return ret; +} + + +inline int almtx_lock(almtx_t *mtx) +{ + if(pthread_mutex_lock(mtx) != 0) + return althrd_error; + return althrd_success; +} + +inline int almtx_unlock(almtx_t *mtx) +{ + if(pthread_mutex_unlock(mtx) != 0) + return althrd_error; + return althrd_success; +} + +inline int almtx_trylock(almtx_t *mtx) +{ + int ret = pthread_mutex_trylock(mtx); + switch(ret) + { + case 0: return althrd_success; + case EBUSY: return althrd_busy; + } + return althrd_error; +} + + +inline void *altss_get(altss_t tss_id) +{ + return pthread_getspecific(tss_id); +} + +inline int altss_set(altss_t tss_id, void *val) +{ + if(pthread_setspecific(tss_id, val) != 0) + return althrd_error; + return althrd_success; +} + + +inline void alcall_once(alonce_flag *once, void (*callback)(void)) +{ + pthread_once(once, callback); +} + +#endif + + +int althrd_create(althrd_t *thr, althrd_start_t func, void *arg); +int althrd_detach(althrd_t thr); +int althrd_join(althrd_t thr, int *res); +void althrd_setname(althrd_t thr, const char *name); + +int almtx_init(almtx_t *mtx, int type); +void almtx_destroy(almtx_t *mtx); +int almtx_timedlock(almtx_t *mtx, const struct timespec *ts); + +int alcnd_init(alcnd_t *cond); +int alcnd_signal(alcnd_t *cond); +int alcnd_broadcast(alcnd_t *cond); +int alcnd_wait(alcnd_t *cond, almtx_t *mtx); +int alcnd_timedwait(alcnd_t *cond, almtx_t *mtx, const struct timespec *time_point); +void alcnd_destroy(alcnd_t *cond); + +int altss_create(altss_t *tss_id, altss_dtor_t callback); +void altss_delete(altss_t tss_id); + +int altimespec_get(struct timespec *ts, int base); + +void al_nssleep(unsigned long nsec); + +#ifdef __cplusplus +} +#endif + +#endif /* AL_THREADS_H */ diff --git a/Engine/lib/openal-soft/include/uintmap.h b/Engine/lib/openal-soft/include/uintmap.h new file mode 100644 index 000000000..acb2749af --- /dev/null +++ b/Engine/lib/openal-soft/include/uintmap.h @@ -0,0 +1,45 @@ +#ifndef AL_UINTMAP_H +#define AL_UINTMAP_H + +#include "AL/al.h" +#include "rwlock.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct UIntMap { + ALuint *keys; + /* Shares memory with keys. */ + ALvoid **values; + + ALsizei size; + ALsizei capacity; + ALsizei limit; + RWLock lock; +} UIntMap; +#define UINTMAP_STATIC_INITIALIZE_N(_n) { NULL, NULL, 0, 0, (_n), RWLOCK_STATIC_INITIALIZE } +#define UINTMAP_STATIC_INITIALIZE UINTMAP_STATIC_INITIALIZE_N(~0) + +void InitUIntMap(UIntMap *map, ALsizei limit); +void ResetUIntMap(UIntMap *map); +ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value); +ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key); +ALvoid *RemoveUIntMapKeyNoLock(UIntMap *map, ALuint key); +ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key); +ALvoid *LookupUIntMapKeyNoLock(UIntMap *map, ALuint key); + +inline void LockUIntMapRead(UIntMap *map) +{ ReadLock(&map->lock); } +inline void UnlockUIntMapRead(UIntMap *map) +{ ReadUnlock(&map->lock); } +inline void LockUIntMapWrite(UIntMap *map) +{ WriteLock(&map->lock); } +inline void UnlockUIntMapWrite(UIntMap *map) +{ WriteUnlock(&map->lock); } + +#ifdef __cplusplus +} +#endif + +#endif /* AL_UINTMAP_H */ diff --git a/Engine/lib/openal-soft/openal.pc.in b/Engine/lib/openal-soft/openal.pc.in new file mode 100644 index 000000000..8bdd4f3b1 --- /dev/null +++ b/Engine/lib/openal-soft/openal.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: OpenAL +Description: OpenAL is a cross-platform 3D audio API +Requires: @PKG_CONFIG_REQUIRES@ +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -l@LIBNAME@ @PKG_CONFIG_LIBS@ +Cflags: -I${includedir} -I${includedir}/AL @PKG_CONFIG_CFLAGS@ diff --git a/Engine/lib/openal/FreeBSD/al/al.h b/Engine/lib/openal/FreeBSD/al/al.h deleted file mode 100644 index a4132f0a0..000000000 --- a/Engine/lib/openal/FreeBSD/al/al.h +++ /dev/null @@ -1,491 +0,0 @@ -#ifndef _AL_H_ -#define _AL_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 "altypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - #ifdef _LIB - #define ALAPI __declspec(dllexport) - #else - #define ALAPI __declspec(dllimport) - #endif - #define ALAPIENTRY __cdecl - #define AL_CALLBACK -#else - #ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif - #endif - #define ALAPI - #define ALAPIENTRY __cdecl - #define AL_CALLBACK -#endif - -#define OPENAL - -#ifndef AL_NO_PROTOTYPES - -/** - * OpenAL Maintenance Functions - * Initialization and exiting. - * State Management and Query. - * Error Handling. - * Extension Support. - */ - -/** State management. */ -ALAPI ALvoid ALAPIENTRY alEnable( ALenum capability ); -ALAPI ALvoid ALAPIENTRY alDisable( ALenum capability ); -ALAPI ALboolean ALAPIENTRY alIsEnabled( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI ALvoid ALAPIENTRY alHint( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY alGetBoolean( ALenum param ); -ALAPI ALint ALAPIENTRY alGetInteger( ALenum param ); -ALAPI ALfloat ALAPIENTRY alGetFloat( ALenum param ); -ALAPI ALdouble ALAPIENTRY alGetDouble( ALenum param ); -ALAPI ALvoid ALAPIENTRY alGetBooleanv( ALenum param, ALboolean* data ); -ALAPI ALvoid ALAPIENTRY alGetIntegerv( ALenum param, ALint* data ); -ALAPI ALvoid ALAPIENTRY alGetFloatv( ALenum param, ALfloat* data ); -ALAPI ALvoid ALAPIENTRY alGetDoublev( ALenum param, ALdouble* data ); -ALAPI ALubyte* ALAPIENTRY alGetString( ALenum param ); - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY alGetError( ALvoid ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALvoid* ALAPIENTRY alGetProcAddress( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY alGetEnumValue( ALubyte* ename ); - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Environment: default 0. - */ -ALAPI ALvoid ALAPIENTRY alListeneri( ALenum param, ALint value ); - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI ALvoid ALAPIENTRY alListenerf( ALenum param, ALfloat value ); - - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI ALvoid ALAPIENTRY alListener3f( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); - - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI ALvoid ALAPIENTRY alListenerfv( ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY alGetListeneri( ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetListenerf( ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY alGetListener3f( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY alGetListenerfv( ALenum param, ALfloat* values ); - - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI ALvoid ALAPIENTRY alGenSources( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI ALvoid ALAPIENTRY alDeleteSources( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY alIsSource( ALuint id ); - -/** Set an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY alSourcei( ALuint source, ALenum param, ALint value ); -ALAPI ALvoid ALAPIENTRY alSourcef( ALuint source, ALenum param, ALfloat value ); -ALAPI ALvoid ALAPIENTRY alSource3f( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI ALvoid ALAPIENTRY alSourcefv( ALuint source, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY alGetSourcei( ALuint source, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetSourcef( ALuint source, ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY alGetSource3f( ALuint source, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY alGetSourcefv( ALuint source, ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY alSourcePlayv( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourcePausev( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourceStopv( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n,ALuint *sources); - -/** Activate a source, start replay. */ -ALAPI ALvoid ALAPIENTRY alSourcePlay( ALuint source ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI ALvoid ALAPIENTRY alSourcePause( ALuint source ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI ALvoid ALAPIENTRY alSourceStop( ALuint source ); - -/** - * Rewinds a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - */ -ALAPI ALvoid ALAPIENTRY alSourceRewind( ALuint source ); - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI ALvoid ALAPIENTRY alGenBuffers( ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY alDeleteBuffers( ALsizei n, ALuint* buffers ); -ALAPI ALboolean ALAPIENTRY alIsBuffer( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI ALvoid ALAPIENTRY alBufferData( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - - -ALAPI ALvoid ALAPIENTRY alGetBufferi( ALuint buffer, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetBufferf( ALuint buffer, ALenum param, ALfloat* value ); - - - - -/** - * Queue stuff - */ - -ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers ); - -/** - * Knobs and dials - */ -ALAPI ALvoid ALAPIENTRY alDistanceModel( ALenum value ); -ALAPI ALvoid ALAPIENTRY alDopplerFactor( ALfloat value ); -ALAPI ALvoid ALAPIENTRY alDopplerVelocity( ALfloat value ); - -#else /* AL_NO_PROTOTYPES */ - -/** - * OpenAL Maintenance Functions - * Initialization and exiting. - * State Management and Query. - * Error Handling. - * Extension Support. - */ - -/** State management. */ -ALAPI ALvoid ALAPIENTRY (*alEnable)( ALenum capability ); -ALAPI ALvoid ALAPIENTRY (*alDisable)( ALenum capability ); -ALAPI ALboolean ALAPIENTRY (*alIsEnabled)( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI ALvoid ALAPIENTRY (*alHint)( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY (*alGetBoolean)( ALenum param ); -ALAPI ALint ALAPIENTRY (*alGetInteger)( ALenum param ); -ALAPI ALfloat ALAPIENTRY (*alGetFloat)( ALenum param ); -ALAPI ALdouble ALAPIENTRY (*alGetDouble)( ALenum param ); -ALAPI ALvoid ALAPIENTRY (*alGetBooleanv)( ALenum param, ALboolean* data ); -ALAPI ALvoid ALAPIENTRY (*alGetIntegerv)( ALenum param, ALint* data ); -ALAPI ALvoid ALAPIENTRY (*alGetFloatv)( ALenum param, ALfloat* data ); -ALAPI ALvoid ALAPIENTRY (*alGetDoublev)( ALenum param, ALdouble* data ); -ALAPI ALubyte* ALAPIENTRY (*alGetString)( ALenum param ); - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY (*alGetError)( ALvoid ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY (*alIsExtensionPresent)( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALvoid* ALAPIENTRY (*alGetProcAddress)( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY (*alGetEnumValue)( ALubyte* ename ); - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Environment: default 0. - */ -ALAPI ALvoid ALAPIENTRY (*alListeneri)( ALenum param, ALint value ); - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI ALvoid ALAPIENTRY (*alListenerf)( ALenum param, ALfloat value ); - - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI ALvoid ALAPIENTRY (*alListener3f)( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); - - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI ALvoid ALAPIENTRY (*alListenerfv)( ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY (*alGetListeneri)( ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetListenerf)( ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY (*alGetListener3f)( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY (*alGetListenerfv)( ALenum param, ALfloat* values ); - - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI ALvoid ALAPIENTRY (*alGenSources)( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI ALvoid ALAPIENTRY (*alDeleteSources)( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY (*alIsSource)( ALuint id ); - -/** Set an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY (*alSourcei)( ALuint source, ALenum param, ALint value ); -ALAPI ALvoid ALAPIENTRY (*alSourcef)( ALuint source, ALenum param, ALfloat value ); -ALAPI ALvoid ALAPIENTRY (*alSource3f)( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI ALvoid ALAPIENTRY (*alSourcefv)( ALuint source, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY (*alGetSourcei)( ALuint source, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetSourcef)( ALuint source, ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY (*alGetSourcefv)( ALuint source, ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY (*alSourcePlayv)( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY (*alSourceStopv)( ALsizei n, ALuint *sources ); - -/** Activate a source, start replay. */ -ALAPI ALvoid ALAPIENTRY (*alSourcePlay)( ALuint source ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI ALvoid ALAPIENTRY (*alSourcePause)( ALuint source ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI ALvoid ALAPIENTRY (*alSourceStop)( ALuint source ); - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI ALvoid ALAPIENTRY (*alGenBuffers)( ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY (*alDeleteBuffers)( ALsizei n, ALuint* buffers ); -ALAPI ALboolean ALAPIENTRY (*alIsBuffer)( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI ALvoid ALAPIENTRY (*alBufferData)( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - -ALAPI ALvoid ALAPIENTRY (*alGetBufferi)( ALuint buffer, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetBufferf)( ALuint buffer, ALenum param, ALfloat* value ); - - - - -/** - * Queue stuff - */ -ALAPI ALvoid ALAPIENTRY (*alSourceQueueBuffers)( ALuint source, ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY (*alSourceUnqueueBuffers)( ALuint source, ALsizei n, ALuint* buffers ); - -/** - * Knobs and dials - */ -ALAPI ALvoid ALAPIENTRY (*alDistanceModel)( ALenum value ); -ALAPI ALvoid ALAPIENTRY (*alDopplerFactor)( ALfloat value ); -ALAPI ALvoid ALAPIENTRY (*alDopplerVelocity)( ALfloat value ); - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/FreeBSD/al/al_func.h b/Engine/lib/openal/FreeBSD/al/al_func.h deleted file mode 100644 index 9a280ad2a..000000000 --- a/Engine/lib/openal/FreeBSD/al/al_func.h +++ /dev/null @@ -1,69 +0,0 @@ - -AL_FUNCTION(ALvoid, alEnable, ( ALenum capability ), return; ) -AL_FUNCTION(ALvoid, alDisable, ( ALenum capability ), return; ) -AL_FUNCTION(ALboolean, alIsEnabled, ( ALenum capability ), return AL_FALSE; ) - -//AL_FUNCTION(ALvoid, alHint, ( ALenum target, ALenum mode ), return; ) - -AL_FUNCTION(ALboolean, alGetBoolean, ( ALenum param ), return AL_FALSE; ) -AL_FUNCTION(ALint, alGetInteger, ( ALenum param ), return 0; ) -AL_FUNCTION(ALfloat, alGetFloat, ( ALenum param ), return 0.0f; ) -AL_FUNCTION(ALdouble, alGetDouble, ( ALenum param ), return 0.0; ) -AL_FUNCTION(ALvoid, alGetBooleanv, ( ALenum param, ALboolean* data ), return; ) -AL_FUNCTION(ALvoid, alGetIntegerv, ( ALenum param, ALint* data ), return; ) -AL_FUNCTION(ALvoid, alGetFloatv, ( ALenum param, ALfloat* data ), return; ) -AL_FUNCTION(ALvoid, alGetDoublev, ( ALenum param, ALdouble* data ), return; ) -AL_FUNCTION(ALubyte*, alGetString, ( ALenum param ), return NULL; ) - -AL_FUNCTION(ALenum, alGetError, ( ALvoid ), return AL_INVALID_VALUE; ) -AL_FUNCTION(ALboolean, alIsExtensionPresent, ( ALubyte* fname ), return AL_FALSE; ) -AL_FUNCTION(ALvoid*, alGetProcAddress, ( ALubyte* fname ), return NULL; ) -AL_FUNCTION(ALenum, alGetEnumValue, ( ALubyte* ename ), return AL_INVALID_ENUM; ) - -AL_FUNCTION(ALvoid, alListeneri, ( ALenum param, ALint value ), return; ) -AL_FUNCTION(ALvoid, alListenerf, ( ALenum param, ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alListener3f, ( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ), return; ) -AL_FUNCTION(ALvoid, alListenerfv, ( ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alGetListeneri, ( ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetListenerf, ( ALenum param, ALfloat* value ), return; ) -AL_FUNCTION(ALvoid, alGetListener3f, ( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ), return; ) -AL_FUNCTION(ALvoid, alGetListenerfv, ( ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alGenSources, ( ALsizei n, ALuint* sources ), return; ) -AL_FUNCTION(ALvoid, alDeleteSources, ( ALsizei n, ALuint* sources ), return; ) -AL_FUNCTION(ALboolean, alIsSource, ( ALuint id ), return AL_FALSE; ) - -AL_FUNCTION(ALvoid, alSourcei, ( ALuint source, ALenum param, ALint value ), return; ) -AL_FUNCTION(ALvoid, alSourcef, ( ALuint source, ALenum param, ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alSource3f, ( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ), return; ) -AL_FUNCTION(ALvoid, alSourcefv, ( ALuint source, ALenum param, ALfloat* values ), return; ) -AL_FUNCTION(ALvoid, alGetSourcei, ( ALuint source, ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetSourcef, ( ALuint source, ALenum param, ALfloat* value ), return; ) -//AL_FUNCTION(ALvoid, alGetSource3f, ( ALuint source, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ), return; ) -AL_FUNCTION(ALvoid, alGetSourcefv, ( ALuint source, ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alSourcePlayv, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourcePausev, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourceStopv, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourceRewindv, (ALsizei n,ALuint *sources), return; ) -AL_FUNCTION(ALvoid, alSourcePlay, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourcePause, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourceStop, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourceRewind, ( ALuint source ), return; ) - -AL_FUNCTION(ALvoid, alGenBuffers, ( ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALvoid, alDeleteBuffers, ( ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALboolean, alIsBuffer, ( ALuint buffer ), return AL_FALSE; ) -AL_FUNCTION(ALvoid, alBufferData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq ), return; ) -AL_FUNCTION(ALvoid, alGetBufferi, ( ALuint buffer, ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetBufferf, ( ALuint buffer, ALenum param, ALfloat* value ), return; ) - -AL_FUNCTION(ALvoid, alSourceQueueBuffers, ( ALuint source, ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALvoid, alSourceUnqueueBuffers, ( ALuint source, ALsizei n, ALuint* buffers ), return; ) - -AL_FUNCTION(ALvoid, alDistanceModel, ( ALenum value ), return; ) -AL_FUNCTION(ALvoid, alDopplerFactor, ( ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alDopplerVelocity, ( ALfloat value ), return; ) - - diff --git a/Engine/lib/openal/FreeBSD/al/alc.h b/Engine/lib/openal/FreeBSD/al/alc.h deleted file mode 100644 index 7804227d4..000000000 --- a/Engine/lib/openal/FreeBSD/al/alc.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef _ALC_H_ -#define _ALC_H_ - -#include "altypes.h" -#include "alctypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - #ifdef _LIB - #define ALCAPI __declspec(dllexport) - #else - #define ALCAPI __declspec(dllimport) - typedef ALCvoid ALCdevice; - typedef ALCvoid ALCcontext; - #endif - #define ALCAPIENTRY __cdecl -#else - #ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif - #endif - #define ALCAPI - #define ALCAPIENTRY __cdecl -#endif - - - -#ifndef ALC_NO_PROTOTYPES - -ALCAPI ALCubyte* ALCAPIENTRY alcGetString(ALCdevice *device,ALCenum param); -ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALCsizei size,ALCint *data); - -ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(ALCubyte *deviceName); -ALCAPI ALCvoid ALCAPIENTRY alcCloseDevice(ALCdevice *device); - -ALCAPI ALCcontext*ALCAPIENTRY alcCreateContext(ALCdevice *device,ALCint *attrList); -ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *context); -ALCAPI ALCcontext*ALCAPIENTRY alcGetCurrentContext(ALCvoid); -ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context); - -ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device); - -ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device,ALCubyte *extName); -ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device,ALCubyte *funcName); -ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device,ALCubyte *enumName); - -#else /* AL_NO_PROTOTYPES */ - -ALCAPI ALCubyte* ALCAPIENTRY (*alcGetString)(ALCdevice *device,ALCenum param); -ALCAPI ALCvoid ALCAPIENTRY (*alcGetIntegerv)(ALCdevice * device,ALCenum param,ALCsizei size,ALCint *data); - -ALCAPI ALCdevice* ALCAPIENTRY (*alcOpenDevice)(ALubyte *deviceName); -ALCAPI ALCvoid ALCAPIENTRY (*alcCloseDevice)(ALCdevice *device); - -ALCAPI ALCcontext*ALCAPIENTRY (*alcCreateContext)(ALCdevice *device,ALCint *attrList); -ALCAPI ALCboolean ALCAPIENTRY (*alcMakeContextCurrent)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcProcessContext)(ALCcontext *context); -ALCAPI ALCcontext*ALCAPIENTRY (*alcGetCurrentContext)(ALCvoid); -ALCAPI ALCdevice* ALCAPIENTRY (*alcGetContextsDevice)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcSuspendContext)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcDestroyContext)(ALCcontext *context); - -ALCAPI ALCenum ALCAPIENTRY (*alcGetError)(ALCdevice *device); - -ALCAPI ALCboolean ALCAPIENTRY (*alcIsExtensionPresent)(ALCdevice *device,ALCubyte *extName); -ALCAPI ALCvoid * ALCAPIENTRY (*alcGetProcAddress)(ALCdevice *device,ALCubyte *funcName); -ALCAPI ALCenum ALCAPIENTRY (*alcGetEnumValue)(ALCdevice *device,ALCubyte *enumName); - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/FreeBSD/al/alc_func.h b/Engine/lib/openal/FreeBSD/al/alc_func.h deleted file mode 100644 index 22da893e0..000000000 --- a/Engine/lib/openal/FreeBSD/al/alc_func.h +++ /dev/null @@ -1,20 +0,0 @@ - -//AL_FUNCTION(ALCubyte*, alcGetString, (ALCdevice *device,ALCenum param), return NULL; ) -//AL_FUNCTION(ALCvoid, alcGetIntegerv, (ALCdevice * device,ALCenum param,ALCsizei size,ALCint *data), return; ) - -AL_FUNCTION(ALCdevice*, alcOpenDevice, (ALubyte *deviceName), return NULL; ) -AL_FUNCTION(ALCvoid, alcCloseDevice, (ALCdevice *device), return; ) - -AL_FUNCTION(ALCcontext*, alcCreateContext, (ALCdevice *device,ALCint *attrList), return NULL; ) -AL_FUNCTION(ALCboolean, alcMakeContextCurrent, (ALCcontext *context), return AL_FALSE; ) -AL_FUNCTION(ALCvoid, alcProcessContext, (ALCcontext *context), return; ) -AL_FUNCTION(ALCcontext*, alcGetCurrentContext, (ALCvoid), return NULL; ) -AL_FUNCTION(ALCdevice*, alcGetContextsDevice, (ALCcontext *context), return NULL; ) -AL_FUNCTION(ALCvoid, alcSuspendContext, (ALCcontext *context), return; ) -AL_FUNCTION(ALCvoid, alcDestroyContext, (ALCcontext *context), return; ) - -AL_FUNCTION(ALCenum, alcGetError, (ALCdevice *device), return ALC_INVALID_DEVICE; ) - -//AL_FUNCTION(ALCboolean, alcIsExtensionPresent, (ALCdevice *device,ALCubyte *extName), return AL_FALSE; ) -//AL_FUNCTION(ALCvoid*, alcGetProcAddress, (ALCdevice *device,ALCubyte *funcName), return NULL; ) -//AL_FUNCTION(ALCenum, alcGetEnumValue, (ALCdevice *device,ALCubyte *enumName), return ALC_INVALID_ENUM; ) diff --git a/Engine/lib/openal/FreeBSD/al/alctypes.h b/Engine/lib/openal/FreeBSD/al/alctypes.h deleted file mode 100644 index 72ff49689..000000000 --- a/Engine/lib/openal/FreeBSD/al/alctypes.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef _ALCTYPES_H_ -#define _ALCTYPES_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 __cplusplus -extern "C" { -#endif - -/** ALC boolean type. */ -typedef char ALCboolean; - -/** ALC 8bit signed byte. */ -typedef char ALCbyte; - -/** ALC 8bit unsigned byte. */ -typedef unsigned char ALCubyte; - -/** ALC 16bit signed short integer type. */ -typedef short ALCshort; - -/** ALC 16bit unsigned short integer type. */ -typedef unsigned short ALCushort; - -/** ALC 32bit unsigned integer type. */ -typedef unsigned ALCuint; - -/** ALC 32bit signed integer type. */ -typedef int ALCint; - -/** ALC 32bit floating point type. */ -typedef float ALCfloat; - -/** ALC 64bit double point type. */ -typedef double ALCdouble; - -/** ALC 32bit type. */ -typedef unsigned int ALCsizei; - -/** ALC void type */ -typedef void ALCvoid; - -/** ALC enumerations. */ -typedef int ALCenum; - - -typedef ALCvoid ALCdevice; -typedef ALCvoid ALCcontext; - - -/* Bad value. */ -#define ALC_INVALID (-1) - -/* Boolean False. */ -#define ALC_FALSE 0 - -/* Boolean True. */ -#define ALC_TRUE 1 - -/** Errors: No Error. */ -#define ALC_NO_ERROR ALC_FALSE - -#define ALC_MAJOR_VERSION 0x1000 -#define ALC_MINOR_VERSION 0x1001 -#define ALC_ATTRIBUTES_SIZE 0x1002 -#define ALC_ALL_ATTRIBUTES 0x1003 - -#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 -#define ALC_DEVICE_SPECIFIER 0x1005 -#define ALC_EXTENSIONS 0x1006 - -#define ALC_FREQUENCY 0x1007 -#define ALC_REFRESH 0x1008 -#define ALC_SYNC 0x1009 - -/** - * The device argument does not name a valid dvice. - */ -#define ALC_INVALID_DEVICE 0xA001 - -/** - * The context argument does not name a valid context. - */ -#define ALC_INVALID_CONTEXT 0xA002 - -/** - * A function was called at inappropriate time, - * or in an inappropriate way, causing an illegal state. - * This can be an incompatible ALenum, object ID, - * and/or function. - */ -#define ALC_INVALID_ENUM 0xA003 - -/** - * Illegal value passed as an argument to an AL call. - * Applies to parameter values, but not to enumerations. - */ -#define ALC_INVALID_VALUE 0xA004 - -/** - * A function could not be completed, - * because there is not enough memory available. - */ -#define ALC_OUT_OF_MEMORY 0xA005 - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Engine/lib/openal/FreeBSD/al/altypes.h b/Engine/lib/openal/FreeBSD/al/altypes.h deleted file mode 100644 index 8aa99c608..000000000 --- a/Engine/lib/openal/FreeBSD/al/altypes.h +++ /dev/null @@ -1,332 +0,0 @@ -#ifndef _ALTYPES_H_ -#define _ALTYPES_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 __cplusplus -extern "C" { -#endif - -/** OpenAL boolean type. */ -typedef char ALboolean; - -/** OpenAL 8bit signed byte. */ -typedef char ALbyte; - -/** OpenAL 8bit unsigned byte. */ -typedef unsigned char ALubyte; - -/** OpenAL 16bit signed short integer type. */ -typedef short ALshort; - -/** OpenAL 16bit unsigned short integer type. */ -typedef unsigned short ALushort; - -/** OpenAL 32bit unsigned integer type. */ -typedef unsigned ALuint; - -/** OpenAL 32bit signed integer type. */ -typedef int ALint; - -/** OpenAL 32bit floating point type. */ -typedef float ALfloat; - -/** OpenAL 64bit double point type. */ -typedef double ALdouble; - -/** OpenAL 32bit type. */ -typedef unsigned int ALsizei; - -/** OpenAL void type */ -typedef void ALvoid; - -/** OpenAL enumerations. */ -typedef int ALenum; - -/* Bad value. */ -#define AL_INVALID (-1) - -/* Disable value. */ -#define AL_NONE 0 - -/* Boolean False. */ -#define AL_FALSE 0 - -/* Boolean True. */ -#define AL_TRUE 1 - -/** - * Indicate the type of AL_SOURCE. - * Sources can be spatialized - */ -#define AL_SOURCE_TYPE 0x200 - -/** Indicate source has absolute coordinates. */ -#define AL_SOURCE_ABSOLUTE 0x201 - -/** Indicate Source has listener relative coordinates. */ -#define AL_SOURCE_RELATIVE 0x202 - -/** - * Directional source, inner cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_INNER_ANGLE 0x1001 - -/** - * Directional source, outer cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_OUTER_ANGLE 0x1002 - -/** - * Specify the pitch to be applied, either at source, - * or on mixer results, at listener. - * Range: [0.5-2.0] - * Default: 1.0 - */ -#define AL_PITCH 0x1003 - -/** - * Specify the current location in three dimensional space. - * OpenAL, like OpenGL, uses a right handed coordinate system, - * where in a frontal default view X (thumb) points right, - * Y points up (index finger), and Z points towards the - * viewer/camera (middle finger). - * To switch from a left handed coordinate system, flip the - * sign on the Z coordinate. - * Listener position is always in the world coordinate system. - */ -#define AL_POSITION 0x1004 - -/** Specify the current direction as forward vector. */ -#define AL_DIRECTION 0x1005 - -/** Specify the current velocity in three dimensional space. */ -#define AL_VELOCITY 0x1006 - -/** - * Indicate whether source has to loop infinite. - * Type: ALboolean - * Range: [AL_TRUE, AL_FALSE] - * Default: AL_FALSE - */ -#define AL_LOOPING 0x1007 - -/** - * Indicate the buffer to provide sound samples. - * Type: ALuint. - * Range: any valid Buffer id. - */ -#define AL_BUFFER 0x1009 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN 0x100A - -/** - * Indicate minimum source attenuation. - * Type: ALfloat - * Range: [0.0 - 1.0] - */ -#define AL_MIN_GAIN 0x100D - -/** - * Indicate maximum source attenuation. - * Type: ALfloat - * Range: [0.0 - 1.0] - */ -#define AL_MAX_GAIN 0x100E - -/** - * Specify the current orientation. - * Type: ALfv6 (at/up) - * Range: N/A - */ -#define AL_ORIENTATION 0x100F - -/* byte offset into source (in canon format). -1 if source - * is not playing. Don't set this, get this. - * - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - */ -#define AL_REFERENCE_DISTANCE 0x1020 - - /** - * Indicate the rolloff factor for the source. - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - */ -#define AL_ROLLOFF_FACTOR 0x1021 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_CONE_OUTER_GAIN 0x1022 - -/** - * Specify the maximum distance. - * Type: ALfloat - * Range: [0.0 - ] - */ -#define AL_MAX_DISTANCE 0x1023 - -/** - * Specify the channel mask. (Creative) - * Type: ALuint - * Range: [0 - 255] - */ -#define AL_CHANNEL_MASK 0x3000 - -/** - * Source state information - */ -#define AL_SOURCE_STATE 0x1010 -#define AL_INITIAL 0x1011 -#define AL_PLAYING 0x1012 -#define AL_PAUSED 0x1013 -#define AL_STOPPED 0x1014 - -/** - * Buffer Queue params - */ -#define AL_BUFFERS_QUEUED 0x1015 -#define AL_BUFFERS_PROCESSED 0x1016 - -/** Sound buffers: format specifier. */ -#define AL_FORMAT_MONO8 0x1100 -#define AL_FORMAT_MONO16 0x1101 -#define AL_FORMAT_STEREO8 0x1102 -#define AL_FORMAT_STEREO16 0x1103 - -/** - * Sound buffers: frequency, in units of Hertz [Hz]. - * This is the number of samples per second. Half of the - * sample frequency marks the maximum significant - * frequency component. - */ -#define AL_FREQUENCY 0x2001 -#define AL_BITS 0x2002 -#define AL_CHANNELS 0x2003 -#define AL_SIZE 0x2004 -#define AL_DATA 0x2005 - -/** - * Buffer state. - * - * Not supported for public use (yet). - */ -#define AL_UNUSED 0x2010 -#define AL_PENDING 0x2011 -#define AL_PROCESSED 0x2012 - -/** Errors: No Error. */ -#define AL_NO_ERROR AL_FALSE - -/** - * Illegal name passed as an argument to an AL call. - */ -#define AL_INVALID_NAME 0xA001 - -/** - * Illegal enum passed as an argument to an AL call. - */ -#define AL_INVALID_ENUM 0xA002 -/** - * Illegal value passed as an argument to an AL call. - * Applies to parameter values, but not to enumerations. - */ -#define AL_INVALID_VALUE 0xA003 - -/** - * A function was called at inappropriate time, - * or in an inappropriate way, causing an illegal state. - * This can be an incompatible ALenum, object ID, - * and/or function. - */ -#define AL_INVALID_OPERATION 0xA004 - -/** - * A function could not be completed, - * because there is not enough memory available. - */ -#define AL_OUT_OF_MEMORY 0xA005 - -/** Context strings: Vendor Name. */ -#define AL_VENDOR 0xB001 -#define AL_VERSION 0xB002 -#define AL_RENDERER 0xB003 -#define AL_EXTENSIONS 0xB004 - -/** Global tweakage. */ - -/** - * Doppler scale. Default 1.0 - */ -#define AL_DOPPLER_FACTOR 0xC000 - -/** - * Doppler velocity. Default 1.0 - */ -#define AL_DOPPLER_VELOCITY 0xC001 - -/** - * Distance model. Default AL_INVERSE_DISTANCE_CLAMPED - */ -#define AL_DISTANCE_MODEL 0xD000 - -/** Distance models. */ - -#define AL_INVERSE_DISTANCE 0xD001 -#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 - - /** - * enables - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/FreeBSD/al/alu.h b/Engine/lib/openal/FreeBSD/al/alu.h deleted file mode 100644 index c6adff62c..000000000 --- a/Engine/lib/openal/FreeBSD/al/alu.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _ALU_H_ -#define _ALU_H_ - -#define ALUAPI -#define ALUAPIENTRY __cdecl - -#define BUFFERSIZE 48000 -#define FRACTIONBITS 14 -#define FRACTIONMASK ((1L< - - /* - * EAX Wrapper Interface (using Direct X 7) {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5} - */ - DEFINE_GUID(CLSID_EAXDirectSound, - 0x4ff53b81, - 0x1ce0, - 0x11d3, - 0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5); - - /* - * EAX Wrapper Interface (using Direct X 8) {CA503B60-B176-11d4-A094-D0C0BF3A560C} - */ - DEFINE_GUID(CLSID_EAXDirectSound8, - 0xca503b60, - 0xb176, - 0x11d4, - 0xa0, 0x94, 0xd0, 0xc0, 0xbf, 0x3a, 0x56, 0xc); - - - -#ifdef DIRECTSOUND_VERSION -#if DIRECTSOUND_VERSION == 0x0800 - __declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate8(GUID*, LPDIRECTSOUND8*, IUnknown FAR *); - typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE8)(GUID*, LPDIRECTSOUND8*, IUnknown FAR*); -#endif -#endif - - __declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID*, LPDIRECTSOUND*, IUnknown FAR *); - typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID*, LPDIRECTSOUND*, IUnknown FAR*); - -#else // OPENAL - #include - - #ifndef GUID_DEFINED - #define GUID_DEFINED - typedef struct _GUID - { - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; - } GUID; - #endif // !GUID_DEFINED - - #ifndef DEFINE_GUID - #ifndef INITGUID - #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const GUID FAR name - #else - #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } - #endif // INITGUID - #endif // DEFINE_GUID - - - /* - * EAX OpenAL Extension - */ - typedef ALenum (*EAXSet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint); - typedef ALenum (*EAXGet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint); -#endif - -#pragma pack(push, 4) - -/* - * EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87} - */ -DEFINE_GUID(DSPROPSETID_EAX30_ListenerProperties, - 0xa8fa6882, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties - -typedef enum -{ - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMLF, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_DECAYLFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REFLECTIONSPAN, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_REVERBPAN, - DSPROPERTY_EAXLISTENER_ECHOTIME, - DSPROPERTY_EAXLISTENER_ECHODEPTH, - DSPROPERTY_EAXLISTENER_MODULATIONTIME, - DSPROPERTY_EAXLISTENER_MODULATIONDEPTH, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_HFREFERENCE, - DSPROPERTY_EAXLISTENER_LFREFERENCE, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_FLAGS -} DSPROPERTY_EAX_LISTENERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \ - DSPROPERTY_EAXLISTENER_IMMEDIATE) - -typedef struct _EAXVECTOR { - float x; - float y; - float z; -} EAXVECTOR; - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times and delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -typedef struct _EAXLISTENERPROPERTIES -{ - unsigned long ulEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - long lRoom; // room effect level (at mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lRoomLF; // relative room effect level at low frequencies - float flDecayTime; // reverberation decay time at mid frequencies - float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio - float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - EAXVECTOR vReflectionsPan; // early reflections panning vector - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - EAXVECTOR vReverbPan; // late reverberation panning vector - float flEchoTime; // echo time - float flEchoDepth; // echo depth - float flModulationTime; // modulation time - float flModulationDepth; // modulation depth - float flAirAbsorptionHF; // change in level per meter at high frequencies - float flHFReference; // reference high frequency - float flLFReference; // reference low frequency - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - unsigned long ulFlags; // modifies the behavior of properties -} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_UNDEFINED, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time -#define EAXLISTENERFLAGS_ECHOTIMESCALE 0x00000040 // echo time -#define EAXLISTENERFLAGS_MODULATIONTIMESCALE 0x00000080 // modulation time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFF00 // reserved future use - -// Property ranges and defaults: - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINROOM (-10000) -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM (-1000) - -#define EAXLISTENER_MINROOMHF (-10000) -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF (-100) - -#define EAXLISTENER_MINROOMLF (-10000) -#define EAXLISTENER_MAXROOMLF 0 -#define EAXLISTENER_DEFAULTROOMLF 0 - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINDECAYLFRATIO 0.1f -#define EAXLISTENER_MAXDECAYLFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYLFRATIO 1.00f - -#define EAXLISTENER_MINREFLECTIONS (-10000) -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS (-2602) - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB (-10000) -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINECHOTIME 0.075f -#define EAXLISTENER_MAXECHOTIME 0.25f -#define EAXLISTENER_DEFAULTECHOTIME 0.25f - -#define EAXLISTENER_MINECHODEPTH 0.0f -#define EAXLISTENER_MAXECHODEPTH 1.0f -#define EAXLISTENER_DEFAULTECHODEPTH 0.0f - -#define EAXLISTENER_MINMODULATIONTIME 0.04f -#define EAXLISTENER_MAXMODULATIONTIME 4.0f -#define EAXLISTENER_DEFAULTMODULATIONTIME 0.25f - -#define EAXLISTENER_MINMODULATIONDEPTH 0.0f -#define EAXLISTENER_MAXMODULATIONDEPTH 1.0f -#define EAXLISTENER_DEFAULTMODULATIONDEPTH 0.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f) -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f) - -#define EAXLISTENER_MINHFREFERENCE 1000.0f -#define EAXLISTENER_MAXHFREFERENCE 20000.0f -#define EAXLISTENER_DEFAULTHFREFERENCE 5000.0f - -#define EAXLISTENER_MINLFREFERENCE 20.0f -#define EAXLISTENER_MAXLFREFERENCE 1000.0f -#define EAXLISTENER_DEFAULTLFREFERENCE 250.0f - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \ - EAXLISTENERFLAGS_REFLECTIONSSCALE | \ - EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | \ - EAXLISTENERFLAGS_REVERBDELAYSCALE | \ - EAXLISTENERFLAGS_DECAYHFLIMIT) - - - -/* -* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87} -*/ -DEFINE_GUID(DSPROPSETID_EAX30_BufferProperties, - 0xa8fa6881, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties -#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties - -typedef enum -{ - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS, - DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, - DSPROPERTY_EAXBUFFER_EXCLUSION, - DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, - DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -} DSPROPERTY_EAX_BUFFERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \ - DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -typedef struct _EAXBUFFERPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // relative occlusion control for room effect - float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) - float flExclusionLFRatio; // exclusion low-frequency level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flDopplerFactor; // like DS3D flDopplerFactor but per source - float flRolloffFactor; // like DS3D flRolloffFactor but per source - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long ulFlags; // modifies the behavior of properties -} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION, -typedef struct _EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION -typedef struct _EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION -typedef struct _EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// Property ranges and defaults: - -#define EAXBUFFER_MINDIRECT (-10000) -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF (-10000) -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM (-10000) -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF (-10000) -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINOBSTRUCTION (-10000) -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION (-10000) -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 1.5f - -#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO 1.0f - -#define EAXBUFFER_MINEXCLUSION (-10000) -#define EAXBUFFER_MAXEXCLUSION 0 -#define EAXBUFFER_DEFAULTEXCLUSION 0 - -#define EAXBUFFER_MINEXCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXEXCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO 1.0f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000) -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINDOPPLERFACTOR 0.0f -#define EAXBUFFER_MAXDOPPLERFACTOR 10.f -#define EAXBUFFER_DEFAULTDOPPLERFACTOR 0.0f - -#define EAXBUFFER_MINROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \ - EAXBUFFERFLAGS_ROOMAUTO | \ - EAXBUFFERFLAGS_ROOMHFAUTO ) - -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/Engine/lib/openal/FreeBSD/al/eax_func.h b/Engine/lib/openal/FreeBSD/al/eax_func.h deleted file mode 100644 index 8c36c7471..000000000 --- a/Engine/lib/openal/FreeBSD/al/eax_func.h +++ /dev/null @@ -1,3 +0,0 @@ - -AL_FUNCTION(ALenum, EAXSet, (const ALGUID*, ALuint, ALuint, ALvoid*, ALuint), return 0; ) -AL_FUNCTION(ALenum, EAXGet, (const ALGUID*, ALuint, ALuint, ALvoid*, ALuint), return 0; ) diff --git a/Engine/lib/openal/FreeBSD/al/eaxtypes.h b/Engine/lib/openal/FreeBSD/al/eaxtypes.h deleted file mode 100644 index 15ba59afc..000000000 --- a/Engine/lib/openal/FreeBSD/al/eaxtypes.h +++ /dev/null @@ -1,462 +0,0 @@ - - -typedef struct _ALGUID -{ - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -}ALGUID; - -#ifndef INITGUID - #define DEFINE_ALGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const ALGUID name -#else - #define DEFINE_ALGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const ALGUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } -#endif // INITGUID - - - -/* - * EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87} - */ -DEFINE_ALGUID(DSPROPSETID_EAX30_ListenerProperties, - 0xa8fa6882, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties - -typedef enum -{ - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMLF, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_DECAYLFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REFLECTIONSPAN, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_REVERBPAN, - DSPROPERTY_EAXLISTENER_ECHOTIME, - DSPROPERTY_EAXLISTENER_ECHODEPTH, - DSPROPERTY_EAXLISTENER_MODULATIONTIME, - DSPROPERTY_EAXLISTENER_MODULATIONDEPTH, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_HFREFERENCE, - DSPROPERTY_EAXLISTENER_LFREFERENCE, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_FLAGS -} DSPROPERTY_EAX_LISTENERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \ - DSPROPERTY_EAXLISTENER_IMMEDIATE) - -typedef struct _EAXVECTOR { - float x; - float y; - float z; -} EAXVECTOR; - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times and delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -typedef struct _EAXLISTENERPROPERTIES -{ - unsigned long ulEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - long lRoom; // room effect level (at mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lRoomLF; // relative room effect level at low frequencies - float flDecayTime; // reverberation decay time at mid frequencies - float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio - float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - EAXVECTOR vReflectionsPan; // early reflections panning vector - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - EAXVECTOR vReverbPan; // late reverberation panning vector - float flEchoTime; // echo time - float flEchoDepth; // echo depth - float flModulationTime; // modulation time - float flModulationDepth; // modulation depth - float flAirAbsorptionHF; // change in level per meter at high frequencies - float flHFReference; // reference high frequency - float flLFReference; // reference low frequency - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - unsigned long ulFlags; // modifies the behavior of properties -} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_UNDEFINED, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time -#define EAXLISTENERFLAGS_ECHOTIMESCALE 0x00000040 // echo time -#define EAXLISTENERFLAGS_MODULATIONTIMESCALE 0x00000080 // modulation time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFF00 // reserved future use - -// Property ranges and defaults: - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINROOM (-10000) -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM (-1000) - -#define EAXLISTENER_MINROOMHF (-10000) -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF (-100) - -#define EAXLISTENER_MINROOMLF (-10000) -#define EAXLISTENER_MAXROOMLF 0 -#define EAXLISTENER_DEFAULTROOMLF 0 - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINDECAYLFRATIO 0.1f -#define EAXLISTENER_MAXDECAYLFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYLFRATIO 1.00f - -#define EAXLISTENER_MINREFLECTIONS (-10000) -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS (-2602) - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB (-10000) -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINECHOTIME 0.075f -#define EAXLISTENER_MAXECHOTIME 0.25f -#define EAXLISTENER_DEFAULTECHOTIME 0.25f - -#define EAXLISTENER_MINECHODEPTH 0.0f -#define EAXLISTENER_MAXECHODEPTH 1.0f -#define EAXLISTENER_DEFAULTECHODEPTH 0.0f - -#define EAXLISTENER_MINMODULATIONTIME 0.04f -#define EAXLISTENER_MAXMODULATIONTIME 4.0f -#define EAXLISTENER_DEFAULTMODULATIONTIME 0.25f - -#define EAXLISTENER_MINMODULATIONDEPTH 0.0f -#define EAXLISTENER_MAXMODULATIONDEPTH 1.0f -#define EAXLISTENER_DEFAULTMODULATIONDEPTH 0.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f) -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f) - -#define EAXLISTENER_MINHFREFERENCE 1000.0f -#define EAXLISTENER_MAXHFREFERENCE 20000.0f -#define EAXLISTENER_DEFAULTHFREFERENCE 5000.0f - -#define EAXLISTENER_MINLFREFERENCE 20.0f -#define EAXLISTENER_MAXLFREFERENCE 1000.0f -#define EAXLISTENER_DEFAULTLFREFERENCE 250.0f - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \ - EAXLISTENERFLAGS_REFLECTIONSSCALE | \ - EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | \ - EAXLISTENERFLAGS_REVERBDELAYSCALE | \ - EAXLISTENERFLAGS_DECAYHFLIMIT) - - - -/* -* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87} -*/ -DEFINE_ALGUID(DSPROPSETID_EAX30_BufferProperties, - 0xa8fa6881, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties -#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties - -typedef enum -{ - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS, - DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, - DSPROPERTY_EAXBUFFER_EXCLUSION, - DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, - DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -} DSPROPERTY_EAX_BUFFERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \ - DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -typedef struct _EAXBUFFERPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // relative occlusion control for room effect - float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) - float flExclusionLFRatio; // exclusion low-frequency level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flDopplerFactor; // like DS3D flDopplerFactor but per source - float flRolloffFactor; // like DS3D flRolloffFactor but per source - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long ulFlags; // modifies the behavior of properties -} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION, -typedef struct _EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION -typedef struct _EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION -typedef struct _EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// Property ranges and defaults: - -#define EAXBUFFER_MINDIRECT (-10000) -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF (-10000) -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM (-10000) -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF (-10000) -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINOBSTRUCTION (-10000) -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION (-10000) -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 1.5f - -#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO 1.0f - -#define EAXBUFFER_MINEXCLUSION (-10000) -#define EAXBUFFER_MAXEXCLUSION 0 -#define EAXBUFFER_DEFAULTEXCLUSION 0 - -#define EAXBUFFER_MINEXCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXEXCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO 1.0f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000) -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINDOPPLERFACTOR 0.0f -#define EAXBUFFER_MAXDOPPLERFACTOR 10.f -#define EAXBUFFER_DEFAULTDOPPLERFACTOR 0.0f - -#define EAXBUFFER_MINROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \ - EAXBUFFERFLAGS_ROOMAUTO | \ - EAXBUFFERFLAGS_ROOMHFAUTO ) diff --git a/Engine/lib/openal/FreeBSD/openALFn.h b/Engine/lib/openal/FreeBSD/openALFn.h deleted file mode 100644 index 0f0b00d48..000000000 --- a/Engine/lib/openal/FreeBSD/openALFn.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef AL_FUNCTION -#define AL_FUNCTION(fn_return, fn_name, fn_args); -#endif - -#ifndef AL_EXTENSION -#define AL_EXTENSION(ext_name) -#endif - -#ifndef AL_EXT_FUNCTION -#define AL_EXT_FUNCTION(ext_name, fn_return, fn_name, fn_args) -#endif - -// AL functions -AL_FUNCTION(ALvoid, alEnable, ( ALenum capability )) -AL_FUNCTION(ALvoid, alDisable, ( ALenum capability )) -AL_FUNCTION(ALboolean, alIsEnabled, ( ALenum capability )) -AL_FUNCTION(ALvoid, alHint, ( ALenum target, ALenum mode )) -AL_FUNCTION(ALboolean, alGetBoolean, ( ALenum param )) -AL_FUNCTION(ALint, alGetInteger, ( ALenum param )) -AL_FUNCTION(ALfloat, alGetFloat, ( ALenum param )) -AL_FUNCTION(ALdouble, alGetDouble, ( ALenum param )) -AL_FUNCTION(ALvoid, alGetBooleanv, ( ALenum param, ALboolean* data )) -AL_FUNCTION(ALvoid, alGetIntegerv, ( ALenum param, ALint* data )) -AL_FUNCTION(ALvoid, alGetFloatv, ( ALenum param, ALfloat* data )) -AL_FUNCTION(ALvoid, alGetDoublev, ( ALenum param, ALdouble* data )) -AL_FUNCTION(const ALubyte*, alGetString, ( ALenum param )) -AL_FUNCTION(ALenum, alGetError, ( ALvoid )) -AL_FUNCTION(ALboolean, alIsExtensionPresent, ( const ALubyte* fname )) -AL_FUNCTION(ALvoid*, alGetProcAddress, ( const ALubyte* fname )) -AL_FUNCTION(ALenum, alGetEnumValue, ( const ALubyte* ename )) -AL_FUNCTION(ALvoid, alListenerf, ( ALenum pname, ALfloat param )) -AL_FUNCTION(ALvoid, alListener3f, ( ALenum pname, ALfloat param1, ALfloat param2, ALfloat param3 )) -AL_FUNCTION(ALvoid, alListenerfv, ( ALenum pname, ALfloat* param )) -AL_FUNCTION(ALvoid, alGetListeneri, ( ALenum pname, ALint* value )) -AL_FUNCTION(ALvoid, alGetListenerf, ( ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alGetListenerfv, ( ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alGenSources, ( ALsizei n, ALuint* sources )) -AL_FUNCTION(ALvoid, alDeleteSources, ( ALsizei n, ALuint* sources )) -AL_FUNCTION(ALboolean, alIsSource, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourcei, ( ALuint sid, ALenum param, ALint value )) -AL_FUNCTION(ALvoid, alSourcef, ( ALuint sid, ALenum param, ALfloat value )) -AL_FUNCTION(ALvoid, alSource3f, ( ALuint sid, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 )) -AL_FUNCTION(ALvoid, alSourcefv, ( ALuint sid, ALenum param, ALfloat* values )) -AL_FUNCTION(ALvoid, alGetSourcei, ( ALuint sid, ALenum pname, ALint* value )) -AL_FUNCTION(ALvoid, alGetSourcef, ( ALuint sid, ALenum pname, ALfloat* value )) -AL_FUNCTION(ALvoid, alGetSourcefv, ( ALuint sid, ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alSourcePlayv, ( ALuint ns, ALuint* ids )) -AL_FUNCTION(ALvoid, alSourceStopv, ( ALuint ns, ALuint* ids )) -AL_FUNCTION(ALvoid, alSourcePlay, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourcePause, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourceStop, ( ALuint sid )) -AL_FUNCTION(ALvoid, alGenBuffers, ( ALsizei n, ALuint* samples )) -AL_FUNCTION(ALvoid, alDeleteBuffers, ( ALsizei n, ALuint* samples )) -AL_FUNCTION(ALboolean, alIsBuffer, ( ALuint buffer )) -AL_FUNCTION(ALvoid, alBufferData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_FUNCTION(ALsizei, alBufferAppendData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_FUNCTION(ALvoid, alGetBufferi, ( ALuint buffer, ALenum param, ALint* value )) -AL_FUNCTION(ALvoid, alGetBufferf, ( ALuint buffer, ALenum param, ALfloat* value )) - -// ALC functions -AL_FUNCTION(ALvoid*, alcCreateContext, ( ALint* attrlist )) -AL_FUNCTION(ALCenum, alcMakeContextCurrent, ( ALvoid* context )) -AL_FUNCTION(ALvoid*, alcUpdateContext, ( ALvoid* context )) -AL_FUNCTION(ALCenum, alcDestroyContext, ( ALvoid* context )) -AL_FUNCTION(ALCenum, alcGetError, ( ALvoid )) -AL_FUNCTION(const ALubyte *, alcGetErrorString, ( ALvoid )) -AL_FUNCTION(ALvoid*, alcGetCurrentContext, ( ALvoid )) - -// ALUT functions -AL_FUNCTION(void, alutInit, ( int* argc, char** argv )) -AL_FUNCTION(void, alutExit, ( ALvoid )) -AL_FUNCTION(ALboolean, alutLoadWAV, ( const char* fname, ALvoid** data, ALsizei* format, ALsizei* size, ALsizei* bits, ALsizei* freq )) - -// Extensions -AL_EXTENSION(AL_EXT_IASIG) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alGenEnvironmentIASIG, ( ALsizei n, ALuint* environs )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alDeleteEnvironmentIASIG, ( ALsizei n, ALuint* environs )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALboolean, alIsEnvironmentIASIG, ( ALuint environment )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alEnvironmentiIASIG, ( ALuint eid, ALenum param, ALint value )) - -AL_EXTENSION(AL_EXT_DYNAMIX) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferi_EXT, ( ALuint buffer, ALenum pname, ALint value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferSyncData_EXT, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferStreamFile_EXT, ( ALuint buffer, const ALubyte* filename )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alSourceCallback_EXT, ( ALuint source, ALvoid* callback )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alSourceResetEnvironment_EXT, ( ALuint source )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alContexti_EXT, ( ALenum pname, ALint value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alGetContexti_EXT, ( ALenum pname, ALint* value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alGetContextstr_EXT, ( ALenum pname, ALuint idx, ALubyte** value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureInit_EXT, ( ALenum format, ALuint rate, ALsizei bufferSize )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureDestroy_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureStart_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureStop_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALsizei, alCaptureGetData_EXT, ( ALvoid* data, ALsizei n, ALenum format, ALuint rate )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alEnvironmentfIASIG, ( ALuint eid, ALenum param, ALfloat value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alGetEnvironmentiIASIG_EXT, ( ALuint eid, ALenum param, ALint * value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alGetEnvironmentfIASIG_EXT, ( ALuint eid, ALenum param, ALfloat * value )) - -#undef AL_EXTENSION -#undef AL_FUNCTION -#undef AL_EXT_FUNCTION diff --git a/Engine/lib/openal/LINUX/al/al.h b/Engine/lib/openal/LINUX/al/al.h deleted file mode 100644 index a4132f0a0..000000000 --- a/Engine/lib/openal/LINUX/al/al.h +++ /dev/null @@ -1,491 +0,0 @@ -#ifndef _AL_H_ -#define _AL_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 "altypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - #ifdef _LIB - #define ALAPI __declspec(dllexport) - #else - #define ALAPI __declspec(dllimport) - #endif - #define ALAPIENTRY __cdecl - #define AL_CALLBACK -#else - #ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif - #endif - #define ALAPI - #define ALAPIENTRY __cdecl - #define AL_CALLBACK -#endif - -#define OPENAL - -#ifndef AL_NO_PROTOTYPES - -/** - * OpenAL Maintenance Functions - * Initialization and exiting. - * State Management and Query. - * Error Handling. - * Extension Support. - */ - -/** State management. */ -ALAPI ALvoid ALAPIENTRY alEnable( ALenum capability ); -ALAPI ALvoid ALAPIENTRY alDisable( ALenum capability ); -ALAPI ALboolean ALAPIENTRY alIsEnabled( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI ALvoid ALAPIENTRY alHint( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY alGetBoolean( ALenum param ); -ALAPI ALint ALAPIENTRY alGetInteger( ALenum param ); -ALAPI ALfloat ALAPIENTRY alGetFloat( ALenum param ); -ALAPI ALdouble ALAPIENTRY alGetDouble( ALenum param ); -ALAPI ALvoid ALAPIENTRY alGetBooleanv( ALenum param, ALboolean* data ); -ALAPI ALvoid ALAPIENTRY alGetIntegerv( ALenum param, ALint* data ); -ALAPI ALvoid ALAPIENTRY alGetFloatv( ALenum param, ALfloat* data ); -ALAPI ALvoid ALAPIENTRY alGetDoublev( ALenum param, ALdouble* data ); -ALAPI ALubyte* ALAPIENTRY alGetString( ALenum param ); - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY alGetError( ALvoid ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALvoid* ALAPIENTRY alGetProcAddress( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY alGetEnumValue( ALubyte* ename ); - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Environment: default 0. - */ -ALAPI ALvoid ALAPIENTRY alListeneri( ALenum param, ALint value ); - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI ALvoid ALAPIENTRY alListenerf( ALenum param, ALfloat value ); - - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI ALvoid ALAPIENTRY alListener3f( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); - - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI ALvoid ALAPIENTRY alListenerfv( ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY alGetListeneri( ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetListenerf( ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY alGetListener3f( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY alGetListenerfv( ALenum param, ALfloat* values ); - - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI ALvoid ALAPIENTRY alGenSources( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI ALvoid ALAPIENTRY alDeleteSources( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY alIsSource( ALuint id ); - -/** Set an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY alSourcei( ALuint source, ALenum param, ALint value ); -ALAPI ALvoid ALAPIENTRY alSourcef( ALuint source, ALenum param, ALfloat value ); -ALAPI ALvoid ALAPIENTRY alSource3f( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI ALvoid ALAPIENTRY alSourcefv( ALuint source, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY alGetSourcei( ALuint source, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetSourcef( ALuint source, ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY alGetSource3f( ALuint source, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY alGetSourcefv( ALuint source, ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY alSourcePlayv( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourcePausev( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourceStopv( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n,ALuint *sources); - -/** Activate a source, start replay. */ -ALAPI ALvoid ALAPIENTRY alSourcePlay( ALuint source ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI ALvoid ALAPIENTRY alSourcePause( ALuint source ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI ALvoid ALAPIENTRY alSourceStop( ALuint source ); - -/** - * Rewinds a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - */ -ALAPI ALvoid ALAPIENTRY alSourceRewind( ALuint source ); - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI ALvoid ALAPIENTRY alGenBuffers( ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY alDeleteBuffers( ALsizei n, ALuint* buffers ); -ALAPI ALboolean ALAPIENTRY alIsBuffer( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI ALvoid ALAPIENTRY alBufferData( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - - -ALAPI ALvoid ALAPIENTRY alGetBufferi( ALuint buffer, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetBufferf( ALuint buffer, ALenum param, ALfloat* value ); - - - - -/** - * Queue stuff - */ - -ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers ); - -/** - * Knobs and dials - */ -ALAPI ALvoid ALAPIENTRY alDistanceModel( ALenum value ); -ALAPI ALvoid ALAPIENTRY alDopplerFactor( ALfloat value ); -ALAPI ALvoid ALAPIENTRY alDopplerVelocity( ALfloat value ); - -#else /* AL_NO_PROTOTYPES */ - -/** - * OpenAL Maintenance Functions - * Initialization and exiting. - * State Management and Query. - * Error Handling. - * Extension Support. - */ - -/** State management. */ -ALAPI ALvoid ALAPIENTRY (*alEnable)( ALenum capability ); -ALAPI ALvoid ALAPIENTRY (*alDisable)( ALenum capability ); -ALAPI ALboolean ALAPIENTRY (*alIsEnabled)( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI ALvoid ALAPIENTRY (*alHint)( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY (*alGetBoolean)( ALenum param ); -ALAPI ALint ALAPIENTRY (*alGetInteger)( ALenum param ); -ALAPI ALfloat ALAPIENTRY (*alGetFloat)( ALenum param ); -ALAPI ALdouble ALAPIENTRY (*alGetDouble)( ALenum param ); -ALAPI ALvoid ALAPIENTRY (*alGetBooleanv)( ALenum param, ALboolean* data ); -ALAPI ALvoid ALAPIENTRY (*alGetIntegerv)( ALenum param, ALint* data ); -ALAPI ALvoid ALAPIENTRY (*alGetFloatv)( ALenum param, ALfloat* data ); -ALAPI ALvoid ALAPIENTRY (*alGetDoublev)( ALenum param, ALdouble* data ); -ALAPI ALubyte* ALAPIENTRY (*alGetString)( ALenum param ); - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY (*alGetError)( ALvoid ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY (*alIsExtensionPresent)( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALvoid* ALAPIENTRY (*alGetProcAddress)( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY (*alGetEnumValue)( ALubyte* ename ); - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Environment: default 0. - */ -ALAPI ALvoid ALAPIENTRY (*alListeneri)( ALenum param, ALint value ); - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI ALvoid ALAPIENTRY (*alListenerf)( ALenum param, ALfloat value ); - - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI ALvoid ALAPIENTRY (*alListener3f)( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); - - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI ALvoid ALAPIENTRY (*alListenerfv)( ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY (*alGetListeneri)( ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetListenerf)( ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY (*alGetListener3f)( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY (*alGetListenerfv)( ALenum param, ALfloat* values ); - - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI ALvoid ALAPIENTRY (*alGenSources)( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI ALvoid ALAPIENTRY (*alDeleteSources)( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY (*alIsSource)( ALuint id ); - -/** Set an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY (*alSourcei)( ALuint source, ALenum param, ALint value ); -ALAPI ALvoid ALAPIENTRY (*alSourcef)( ALuint source, ALenum param, ALfloat value ); -ALAPI ALvoid ALAPIENTRY (*alSource3f)( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI ALvoid ALAPIENTRY (*alSourcefv)( ALuint source, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY (*alGetSourcei)( ALuint source, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetSourcef)( ALuint source, ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY (*alGetSourcefv)( ALuint source, ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY (*alSourcePlayv)( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY (*alSourceStopv)( ALsizei n, ALuint *sources ); - -/** Activate a source, start replay. */ -ALAPI ALvoid ALAPIENTRY (*alSourcePlay)( ALuint source ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI ALvoid ALAPIENTRY (*alSourcePause)( ALuint source ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI ALvoid ALAPIENTRY (*alSourceStop)( ALuint source ); - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI ALvoid ALAPIENTRY (*alGenBuffers)( ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY (*alDeleteBuffers)( ALsizei n, ALuint* buffers ); -ALAPI ALboolean ALAPIENTRY (*alIsBuffer)( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI ALvoid ALAPIENTRY (*alBufferData)( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - -ALAPI ALvoid ALAPIENTRY (*alGetBufferi)( ALuint buffer, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetBufferf)( ALuint buffer, ALenum param, ALfloat* value ); - - - - -/** - * Queue stuff - */ -ALAPI ALvoid ALAPIENTRY (*alSourceQueueBuffers)( ALuint source, ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY (*alSourceUnqueueBuffers)( ALuint source, ALsizei n, ALuint* buffers ); - -/** - * Knobs and dials - */ -ALAPI ALvoid ALAPIENTRY (*alDistanceModel)( ALenum value ); -ALAPI ALvoid ALAPIENTRY (*alDopplerFactor)( ALfloat value ); -ALAPI ALvoid ALAPIENTRY (*alDopplerVelocity)( ALfloat value ); - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/LINUX/al/al_func.h b/Engine/lib/openal/LINUX/al/al_func.h deleted file mode 100644 index 9a280ad2a..000000000 --- a/Engine/lib/openal/LINUX/al/al_func.h +++ /dev/null @@ -1,69 +0,0 @@ - -AL_FUNCTION(ALvoid, alEnable, ( ALenum capability ), return; ) -AL_FUNCTION(ALvoid, alDisable, ( ALenum capability ), return; ) -AL_FUNCTION(ALboolean, alIsEnabled, ( ALenum capability ), return AL_FALSE; ) - -//AL_FUNCTION(ALvoid, alHint, ( ALenum target, ALenum mode ), return; ) - -AL_FUNCTION(ALboolean, alGetBoolean, ( ALenum param ), return AL_FALSE; ) -AL_FUNCTION(ALint, alGetInteger, ( ALenum param ), return 0; ) -AL_FUNCTION(ALfloat, alGetFloat, ( ALenum param ), return 0.0f; ) -AL_FUNCTION(ALdouble, alGetDouble, ( ALenum param ), return 0.0; ) -AL_FUNCTION(ALvoid, alGetBooleanv, ( ALenum param, ALboolean* data ), return; ) -AL_FUNCTION(ALvoid, alGetIntegerv, ( ALenum param, ALint* data ), return; ) -AL_FUNCTION(ALvoid, alGetFloatv, ( ALenum param, ALfloat* data ), return; ) -AL_FUNCTION(ALvoid, alGetDoublev, ( ALenum param, ALdouble* data ), return; ) -AL_FUNCTION(ALubyte*, alGetString, ( ALenum param ), return NULL; ) - -AL_FUNCTION(ALenum, alGetError, ( ALvoid ), return AL_INVALID_VALUE; ) -AL_FUNCTION(ALboolean, alIsExtensionPresent, ( ALubyte* fname ), return AL_FALSE; ) -AL_FUNCTION(ALvoid*, alGetProcAddress, ( ALubyte* fname ), return NULL; ) -AL_FUNCTION(ALenum, alGetEnumValue, ( ALubyte* ename ), return AL_INVALID_ENUM; ) - -AL_FUNCTION(ALvoid, alListeneri, ( ALenum param, ALint value ), return; ) -AL_FUNCTION(ALvoid, alListenerf, ( ALenum param, ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alListener3f, ( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ), return; ) -AL_FUNCTION(ALvoid, alListenerfv, ( ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alGetListeneri, ( ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetListenerf, ( ALenum param, ALfloat* value ), return; ) -AL_FUNCTION(ALvoid, alGetListener3f, ( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ), return; ) -AL_FUNCTION(ALvoid, alGetListenerfv, ( ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alGenSources, ( ALsizei n, ALuint* sources ), return; ) -AL_FUNCTION(ALvoid, alDeleteSources, ( ALsizei n, ALuint* sources ), return; ) -AL_FUNCTION(ALboolean, alIsSource, ( ALuint id ), return AL_FALSE; ) - -AL_FUNCTION(ALvoid, alSourcei, ( ALuint source, ALenum param, ALint value ), return; ) -AL_FUNCTION(ALvoid, alSourcef, ( ALuint source, ALenum param, ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alSource3f, ( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ), return; ) -AL_FUNCTION(ALvoid, alSourcefv, ( ALuint source, ALenum param, ALfloat* values ), return; ) -AL_FUNCTION(ALvoid, alGetSourcei, ( ALuint source, ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetSourcef, ( ALuint source, ALenum param, ALfloat* value ), return; ) -//AL_FUNCTION(ALvoid, alGetSource3f, ( ALuint source, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ), return; ) -AL_FUNCTION(ALvoid, alGetSourcefv, ( ALuint source, ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alSourcePlayv, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourcePausev, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourceStopv, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourceRewindv, (ALsizei n,ALuint *sources), return; ) -AL_FUNCTION(ALvoid, alSourcePlay, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourcePause, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourceStop, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourceRewind, ( ALuint source ), return; ) - -AL_FUNCTION(ALvoid, alGenBuffers, ( ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALvoid, alDeleteBuffers, ( ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALboolean, alIsBuffer, ( ALuint buffer ), return AL_FALSE; ) -AL_FUNCTION(ALvoid, alBufferData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq ), return; ) -AL_FUNCTION(ALvoid, alGetBufferi, ( ALuint buffer, ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetBufferf, ( ALuint buffer, ALenum param, ALfloat* value ), return; ) - -AL_FUNCTION(ALvoid, alSourceQueueBuffers, ( ALuint source, ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALvoid, alSourceUnqueueBuffers, ( ALuint source, ALsizei n, ALuint* buffers ), return; ) - -AL_FUNCTION(ALvoid, alDistanceModel, ( ALenum value ), return; ) -AL_FUNCTION(ALvoid, alDopplerFactor, ( ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alDopplerVelocity, ( ALfloat value ), return; ) - - diff --git a/Engine/lib/openal/LINUX/al/alc.h b/Engine/lib/openal/LINUX/al/alc.h deleted file mode 100644 index 7804227d4..000000000 --- a/Engine/lib/openal/LINUX/al/alc.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef _ALC_H_ -#define _ALC_H_ - -#include "altypes.h" -#include "alctypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - #ifdef _LIB - #define ALCAPI __declspec(dllexport) - #else - #define ALCAPI __declspec(dllimport) - typedef ALCvoid ALCdevice; - typedef ALCvoid ALCcontext; - #endif - #define ALCAPIENTRY __cdecl -#else - #ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif - #endif - #define ALCAPI - #define ALCAPIENTRY __cdecl -#endif - - - -#ifndef ALC_NO_PROTOTYPES - -ALCAPI ALCubyte* ALCAPIENTRY alcGetString(ALCdevice *device,ALCenum param); -ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALCsizei size,ALCint *data); - -ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(ALCubyte *deviceName); -ALCAPI ALCvoid ALCAPIENTRY alcCloseDevice(ALCdevice *device); - -ALCAPI ALCcontext*ALCAPIENTRY alcCreateContext(ALCdevice *device,ALCint *attrList); -ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *context); -ALCAPI ALCcontext*ALCAPIENTRY alcGetCurrentContext(ALCvoid); -ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context); - -ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device); - -ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device,ALCubyte *extName); -ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device,ALCubyte *funcName); -ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device,ALCubyte *enumName); - -#else /* AL_NO_PROTOTYPES */ - -ALCAPI ALCubyte* ALCAPIENTRY (*alcGetString)(ALCdevice *device,ALCenum param); -ALCAPI ALCvoid ALCAPIENTRY (*alcGetIntegerv)(ALCdevice * device,ALCenum param,ALCsizei size,ALCint *data); - -ALCAPI ALCdevice* ALCAPIENTRY (*alcOpenDevice)(ALubyte *deviceName); -ALCAPI ALCvoid ALCAPIENTRY (*alcCloseDevice)(ALCdevice *device); - -ALCAPI ALCcontext*ALCAPIENTRY (*alcCreateContext)(ALCdevice *device,ALCint *attrList); -ALCAPI ALCboolean ALCAPIENTRY (*alcMakeContextCurrent)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcProcessContext)(ALCcontext *context); -ALCAPI ALCcontext*ALCAPIENTRY (*alcGetCurrentContext)(ALCvoid); -ALCAPI ALCdevice* ALCAPIENTRY (*alcGetContextsDevice)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcSuspendContext)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcDestroyContext)(ALCcontext *context); - -ALCAPI ALCenum ALCAPIENTRY (*alcGetError)(ALCdevice *device); - -ALCAPI ALCboolean ALCAPIENTRY (*alcIsExtensionPresent)(ALCdevice *device,ALCubyte *extName); -ALCAPI ALCvoid * ALCAPIENTRY (*alcGetProcAddress)(ALCdevice *device,ALCubyte *funcName); -ALCAPI ALCenum ALCAPIENTRY (*alcGetEnumValue)(ALCdevice *device,ALCubyte *enumName); - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/LINUX/al/alc_func.h b/Engine/lib/openal/LINUX/al/alc_func.h deleted file mode 100644 index 22da893e0..000000000 --- a/Engine/lib/openal/LINUX/al/alc_func.h +++ /dev/null @@ -1,20 +0,0 @@ - -//AL_FUNCTION(ALCubyte*, alcGetString, (ALCdevice *device,ALCenum param), return NULL; ) -//AL_FUNCTION(ALCvoid, alcGetIntegerv, (ALCdevice * device,ALCenum param,ALCsizei size,ALCint *data), return; ) - -AL_FUNCTION(ALCdevice*, alcOpenDevice, (ALubyte *deviceName), return NULL; ) -AL_FUNCTION(ALCvoid, alcCloseDevice, (ALCdevice *device), return; ) - -AL_FUNCTION(ALCcontext*, alcCreateContext, (ALCdevice *device,ALCint *attrList), return NULL; ) -AL_FUNCTION(ALCboolean, alcMakeContextCurrent, (ALCcontext *context), return AL_FALSE; ) -AL_FUNCTION(ALCvoid, alcProcessContext, (ALCcontext *context), return; ) -AL_FUNCTION(ALCcontext*, alcGetCurrentContext, (ALCvoid), return NULL; ) -AL_FUNCTION(ALCdevice*, alcGetContextsDevice, (ALCcontext *context), return NULL; ) -AL_FUNCTION(ALCvoid, alcSuspendContext, (ALCcontext *context), return; ) -AL_FUNCTION(ALCvoid, alcDestroyContext, (ALCcontext *context), return; ) - -AL_FUNCTION(ALCenum, alcGetError, (ALCdevice *device), return ALC_INVALID_DEVICE; ) - -//AL_FUNCTION(ALCboolean, alcIsExtensionPresent, (ALCdevice *device,ALCubyte *extName), return AL_FALSE; ) -//AL_FUNCTION(ALCvoid*, alcGetProcAddress, (ALCdevice *device,ALCubyte *funcName), return NULL; ) -//AL_FUNCTION(ALCenum, alcGetEnumValue, (ALCdevice *device,ALCubyte *enumName), return ALC_INVALID_ENUM; ) diff --git a/Engine/lib/openal/LINUX/al/alctypes.h b/Engine/lib/openal/LINUX/al/alctypes.h deleted file mode 100644 index 72ff49689..000000000 --- a/Engine/lib/openal/LINUX/al/alctypes.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef _ALCTYPES_H_ -#define _ALCTYPES_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 __cplusplus -extern "C" { -#endif - -/** ALC boolean type. */ -typedef char ALCboolean; - -/** ALC 8bit signed byte. */ -typedef char ALCbyte; - -/** ALC 8bit unsigned byte. */ -typedef unsigned char ALCubyte; - -/** ALC 16bit signed short integer type. */ -typedef short ALCshort; - -/** ALC 16bit unsigned short integer type. */ -typedef unsigned short ALCushort; - -/** ALC 32bit unsigned integer type. */ -typedef unsigned ALCuint; - -/** ALC 32bit signed integer type. */ -typedef int ALCint; - -/** ALC 32bit floating point type. */ -typedef float ALCfloat; - -/** ALC 64bit double point type. */ -typedef double ALCdouble; - -/** ALC 32bit type. */ -typedef unsigned int ALCsizei; - -/** ALC void type */ -typedef void ALCvoid; - -/** ALC enumerations. */ -typedef int ALCenum; - - -typedef ALCvoid ALCdevice; -typedef ALCvoid ALCcontext; - - -/* Bad value. */ -#define ALC_INVALID (-1) - -/* Boolean False. */ -#define ALC_FALSE 0 - -/* Boolean True. */ -#define ALC_TRUE 1 - -/** Errors: No Error. */ -#define ALC_NO_ERROR ALC_FALSE - -#define ALC_MAJOR_VERSION 0x1000 -#define ALC_MINOR_VERSION 0x1001 -#define ALC_ATTRIBUTES_SIZE 0x1002 -#define ALC_ALL_ATTRIBUTES 0x1003 - -#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 -#define ALC_DEVICE_SPECIFIER 0x1005 -#define ALC_EXTENSIONS 0x1006 - -#define ALC_FREQUENCY 0x1007 -#define ALC_REFRESH 0x1008 -#define ALC_SYNC 0x1009 - -/** - * The device argument does not name a valid dvice. - */ -#define ALC_INVALID_DEVICE 0xA001 - -/** - * The context argument does not name a valid context. - */ -#define ALC_INVALID_CONTEXT 0xA002 - -/** - * A function was called at inappropriate time, - * or in an inappropriate way, causing an illegal state. - * This can be an incompatible ALenum, object ID, - * and/or function. - */ -#define ALC_INVALID_ENUM 0xA003 - -/** - * Illegal value passed as an argument to an AL call. - * Applies to parameter values, but not to enumerations. - */ -#define ALC_INVALID_VALUE 0xA004 - -/** - * A function could not be completed, - * because there is not enough memory available. - */ -#define ALC_OUT_OF_MEMORY 0xA005 - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Engine/lib/openal/LINUX/al/altypes.h b/Engine/lib/openal/LINUX/al/altypes.h deleted file mode 100644 index 8aa99c608..000000000 --- a/Engine/lib/openal/LINUX/al/altypes.h +++ /dev/null @@ -1,332 +0,0 @@ -#ifndef _ALTYPES_H_ -#define _ALTYPES_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 __cplusplus -extern "C" { -#endif - -/** OpenAL boolean type. */ -typedef char ALboolean; - -/** OpenAL 8bit signed byte. */ -typedef char ALbyte; - -/** OpenAL 8bit unsigned byte. */ -typedef unsigned char ALubyte; - -/** OpenAL 16bit signed short integer type. */ -typedef short ALshort; - -/** OpenAL 16bit unsigned short integer type. */ -typedef unsigned short ALushort; - -/** OpenAL 32bit unsigned integer type. */ -typedef unsigned ALuint; - -/** OpenAL 32bit signed integer type. */ -typedef int ALint; - -/** OpenAL 32bit floating point type. */ -typedef float ALfloat; - -/** OpenAL 64bit double point type. */ -typedef double ALdouble; - -/** OpenAL 32bit type. */ -typedef unsigned int ALsizei; - -/** OpenAL void type */ -typedef void ALvoid; - -/** OpenAL enumerations. */ -typedef int ALenum; - -/* Bad value. */ -#define AL_INVALID (-1) - -/* Disable value. */ -#define AL_NONE 0 - -/* Boolean False. */ -#define AL_FALSE 0 - -/* Boolean True. */ -#define AL_TRUE 1 - -/** - * Indicate the type of AL_SOURCE. - * Sources can be spatialized - */ -#define AL_SOURCE_TYPE 0x200 - -/** Indicate source has absolute coordinates. */ -#define AL_SOURCE_ABSOLUTE 0x201 - -/** Indicate Source has listener relative coordinates. */ -#define AL_SOURCE_RELATIVE 0x202 - -/** - * Directional source, inner cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_INNER_ANGLE 0x1001 - -/** - * Directional source, outer cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_OUTER_ANGLE 0x1002 - -/** - * Specify the pitch to be applied, either at source, - * or on mixer results, at listener. - * Range: [0.5-2.0] - * Default: 1.0 - */ -#define AL_PITCH 0x1003 - -/** - * Specify the current location in three dimensional space. - * OpenAL, like OpenGL, uses a right handed coordinate system, - * where in a frontal default view X (thumb) points right, - * Y points up (index finger), and Z points towards the - * viewer/camera (middle finger). - * To switch from a left handed coordinate system, flip the - * sign on the Z coordinate. - * Listener position is always in the world coordinate system. - */ -#define AL_POSITION 0x1004 - -/** Specify the current direction as forward vector. */ -#define AL_DIRECTION 0x1005 - -/** Specify the current velocity in three dimensional space. */ -#define AL_VELOCITY 0x1006 - -/** - * Indicate whether source has to loop infinite. - * Type: ALboolean - * Range: [AL_TRUE, AL_FALSE] - * Default: AL_FALSE - */ -#define AL_LOOPING 0x1007 - -/** - * Indicate the buffer to provide sound samples. - * Type: ALuint. - * Range: any valid Buffer id. - */ -#define AL_BUFFER 0x1009 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN 0x100A - -/** - * Indicate minimum source attenuation. - * Type: ALfloat - * Range: [0.0 - 1.0] - */ -#define AL_MIN_GAIN 0x100D - -/** - * Indicate maximum source attenuation. - * Type: ALfloat - * Range: [0.0 - 1.0] - */ -#define AL_MAX_GAIN 0x100E - -/** - * Specify the current orientation. - * Type: ALfv6 (at/up) - * Range: N/A - */ -#define AL_ORIENTATION 0x100F - -/* byte offset into source (in canon format). -1 if source - * is not playing. Don't set this, get this. - * - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - */ -#define AL_REFERENCE_DISTANCE 0x1020 - - /** - * Indicate the rolloff factor for the source. - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - */ -#define AL_ROLLOFF_FACTOR 0x1021 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_CONE_OUTER_GAIN 0x1022 - -/** - * Specify the maximum distance. - * Type: ALfloat - * Range: [0.0 - ] - */ -#define AL_MAX_DISTANCE 0x1023 - -/** - * Specify the channel mask. (Creative) - * Type: ALuint - * Range: [0 - 255] - */ -#define AL_CHANNEL_MASK 0x3000 - -/** - * Source state information - */ -#define AL_SOURCE_STATE 0x1010 -#define AL_INITIAL 0x1011 -#define AL_PLAYING 0x1012 -#define AL_PAUSED 0x1013 -#define AL_STOPPED 0x1014 - -/** - * Buffer Queue params - */ -#define AL_BUFFERS_QUEUED 0x1015 -#define AL_BUFFERS_PROCESSED 0x1016 - -/** Sound buffers: format specifier. */ -#define AL_FORMAT_MONO8 0x1100 -#define AL_FORMAT_MONO16 0x1101 -#define AL_FORMAT_STEREO8 0x1102 -#define AL_FORMAT_STEREO16 0x1103 - -/** - * Sound buffers: frequency, in units of Hertz [Hz]. - * This is the number of samples per second. Half of the - * sample frequency marks the maximum significant - * frequency component. - */ -#define AL_FREQUENCY 0x2001 -#define AL_BITS 0x2002 -#define AL_CHANNELS 0x2003 -#define AL_SIZE 0x2004 -#define AL_DATA 0x2005 - -/** - * Buffer state. - * - * Not supported for public use (yet). - */ -#define AL_UNUSED 0x2010 -#define AL_PENDING 0x2011 -#define AL_PROCESSED 0x2012 - -/** Errors: No Error. */ -#define AL_NO_ERROR AL_FALSE - -/** - * Illegal name passed as an argument to an AL call. - */ -#define AL_INVALID_NAME 0xA001 - -/** - * Illegal enum passed as an argument to an AL call. - */ -#define AL_INVALID_ENUM 0xA002 -/** - * Illegal value passed as an argument to an AL call. - * Applies to parameter values, but not to enumerations. - */ -#define AL_INVALID_VALUE 0xA003 - -/** - * A function was called at inappropriate time, - * or in an inappropriate way, causing an illegal state. - * This can be an incompatible ALenum, object ID, - * and/or function. - */ -#define AL_INVALID_OPERATION 0xA004 - -/** - * A function could not be completed, - * because there is not enough memory available. - */ -#define AL_OUT_OF_MEMORY 0xA005 - -/** Context strings: Vendor Name. */ -#define AL_VENDOR 0xB001 -#define AL_VERSION 0xB002 -#define AL_RENDERER 0xB003 -#define AL_EXTENSIONS 0xB004 - -/** Global tweakage. */ - -/** - * Doppler scale. Default 1.0 - */ -#define AL_DOPPLER_FACTOR 0xC000 - -/** - * Doppler velocity. Default 1.0 - */ -#define AL_DOPPLER_VELOCITY 0xC001 - -/** - * Distance model. Default AL_INVERSE_DISTANCE_CLAMPED - */ -#define AL_DISTANCE_MODEL 0xD000 - -/** Distance models. */ - -#define AL_INVERSE_DISTANCE 0xD001 -#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 - - /** - * enables - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/LINUX/al/alu.h b/Engine/lib/openal/LINUX/al/alu.h deleted file mode 100644 index c6adff62c..000000000 --- a/Engine/lib/openal/LINUX/al/alu.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _ALU_H_ -#define _ALU_H_ - -#define ALUAPI -#define ALUAPIENTRY __cdecl - -#define BUFFERSIZE 48000 -#define FRACTIONBITS 14 -#define FRACTIONMASK ((1L< - - /* - * EAX Wrapper Interface (using Direct X 7) {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5} - */ - DEFINE_GUID(CLSID_EAXDirectSound, - 0x4ff53b81, - 0x1ce0, - 0x11d3, - 0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5); - - /* - * EAX Wrapper Interface (using Direct X 8) {CA503B60-B176-11d4-A094-D0C0BF3A560C} - */ - DEFINE_GUID(CLSID_EAXDirectSound8, - 0xca503b60, - 0xb176, - 0x11d4, - 0xa0, 0x94, 0xd0, 0xc0, 0xbf, 0x3a, 0x56, 0xc); - - - -#ifdef DIRECTSOUND_VERSION -#if DIRECTSOUND_VERSION == 0x0800 - __declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate8(GUID*, LPDIRECTSOUND8*, IUnknown FAR *); - typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE8)(GUID*, LPDIRECTSOUND8*, IUnknown FAR*); -#endif -#endif - - __declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID*, LPDIRECTSOUND*, IUnknown FAR *); - typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID*, LPDIRECTSOUND*, IUnknown FAR*); - -#else // OPENAL - #include - - #ifndef GUID_DEFINED - #define GUID_DEFINED - typedef struct _GUID - { - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; - } GUID; - #endif // !GUID_DEFINED - - #ifndef DEFINE_GUID - #ifndef INITGUID - #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const GUID FAR name - #else - #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } - #endif // INITGUID - #endif // DEFINE_GUID - - - /* - * EAX OpenAL Extension - */ - typedef ALenum (*EAXSet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint); - typedef ALenum (*EAXGet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint); -#endif - -#pragma pack(push, 4) - -/* - * EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87} - */ -DEFINE_GUID(DSPROPSETID_EAX30_ListenerProperties, - 0xa8fa6882, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties - -typedef enum -{ - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMLF, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_DECAYLFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REFLECTIONSPAN, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_REVERBPAN, - DSPROPERTY_EAXLISTENER_ECHOTIME, - DSPROPERTY_EAXLISTENER_ECHODEPTH, - DSPROPERTY_EAXLISTENER_MODULATIONTIME, - DSPROPERTY_EAXLISTENER_MODULATIONDEPTH, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_HFREFERENCE, - DSPROPERTY_EAXLISTENER_LFREFERENCE, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_FLAGS -} DSPROPERTY_EAX_LISTENERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \ - DSPROPERTY_EAXLISTENER_IMMEDIATE) - -typedef struct _EAXVECTOR { - float x; - float y; - float z; -} EAXVECTOR; - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times and delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -typedef struct _EAXLISTENERPROPERTIES -{ - unsigned long ulEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - long lRoom; // room effect level (at mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lRoomLF; // relative room effect level at low frequencies - float flDecayTime; // reverberation decay time at mid frequencies - float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio - float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - EAXVECTOR vReflectionsPan; // early reflections panning vector - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - EAXVECTOR vReverbPan; // late reverberation panning vector - float flEchoTime; // echo time - float flEchoDepth; // echo depth - float flModulationTime; // modulation time - float flModulationDepth; // modulation depth - float flAirAbsorptionHF; // change in level per meter at high frequencies - float flHFReference; // reference high frequency - float flLFReference; // reference low frequency - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - unsigned long ulFlags; // modifies the behavior of properties -} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_UNDEFINED, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time -#define EAXLISTENERFLAGS_ECHOTIMESCALE 0x00000040 // echo time -#define EAXLISTENERFLAGS_MODULATIONTIMESCALE 0x00000080 // modulation time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFF00 // reserved future use - -// Property ranges and defaults: - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINROOM (-10000) -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM (-1000) - -#define EAXLISTENER_MINROOMHF (-10000) -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF (-100) - -#define EAXLISTENER_MINROOMLF (-10000) -#define EAXLISTENER_MAXROOMLF 0 -#define EAXLISTENER_DEFAULTROOMLF 0 - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINDECAYLFRATIO 0.1f -#define EAXLISTENER_MAXDECAYLFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYLFRATIO 1.00f - -#define EAXLISTENER_MINREFLECTIONS (-10000) -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS (-2602) - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB (-10000) -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINECHOTIME 0.075f -#define EAXLISTENER_MAXECHOTIME 0.25f -#define EAXLISTENER_DEFAULTECHOTIME 0.25f - -#define EAXLISTENER_MINECHODEPTH 0.0f -#define EAXLISTENER_MAXECHODEPTH 1.0f -#define EAXLISTENER_DEFAULTECHODEPTH 0.0f - -#define EAXLISTENER_MINMODULATIONTIME 0.04f -#define EAXLISTENER_MAXMODULATIONTIME 4.0f -#define EAXLISTENER_DEFAULTMODULATIONTIME 0.25f - -#define EAXLISTENER_MINMODULATIONDEPTH 0.0f -#define EAXLISTENER_MAXMODULATIONDEPTH 1.0f -#define EAXLISTENER_DEFAULTMODULATIONDEPTH 0.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f) -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f) - -#define EAXLISTENER_MINHFREFERENCE 1000.0f -#define EAXLISTENER_MAXHFREFERENCE 20000.0f -#define EAXLISTENER_DEFAULTHFREFERENCE 5000.0f - -#define EAXLISTENER_MINLFREFERENCE 20.0f -#define EAXLISTENER_MAXLFREFERENCE 1000.0f -#define EAXLISTENER_DEFAULTLFREFERENCE 250.0f - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \ - EAXLISTENERFLAGS_REFLECTIONSSCALE | \ - EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | \ - EAXLISTENERFLAGS_REVERBDELAYSCALE | \ - EAXLISTENERFLAGS_DECAYHFLIMIT) - - - -/* -* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87} -*/ -DEFINE_GUID(DSPROPSETID_EAX30_BufferProperties, - 0xa8fa6881, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties -#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties - -typedef enum -{ - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS, - DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, - DSPROPERTY_EAXBUFFER_EXCLUSION, - DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, - DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -} DSPROPERTY_EAX_BUFFERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \ - DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -typedef struct _EAXBUFFERPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // relative occlusion control for room effect - float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) - float flExclusionLFRatio; // exclusion low-frequency level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flDopplerFactor; // like DS3D flDopplerFactor but per source - float flRolloffFactor; // like DS3D flRolloffFactor but per source - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long ulFlags; // modifies the behavior of properties -} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION, -typedef struct _EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION -typedef struct _EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION -typedef struct _EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// Property ranges and defaults: - -#define EAXBUFFER_MINDIRECT (-10000) -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF (-10000) -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM (-10000) -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF (-10000) -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINOBSTRUCTION (-10000) -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION (-10000) -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 1.5f - -#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO 1.0f - -#define EAXBUFFER_MINEXCLUSION (-10000) -#define EAXBUFFER_MAXEXCLUSION 0 -#define EAXBUFFER_DEFAULTEXCLUSION 0 - -#define EAXBUFFER_MINEXCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXEXCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO 1.0f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000) -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINDOPPLERFACTOR 0.0f -#define EAXBUFFER_MAXDOPPLERFACTOR 10.f -#define EAXBUFFER_DEFAULTDOPPLERFACTOR 0.0f - -#define EAXBUFFER_MINROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \ - EAXBUFFERFLAGS_ROOMAUTO | \ - EAXBUFFERFLAGS_ROOMHFAUTO ) - -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/Engine/lib/openal/LINUX/al/eax_func.h b/Engine/lib/openal/LINUX/al/eax_func.h deleted file mode 100644 index 8c36c7471..000000000 --- a/Engine/lib/openal/LINUX/al/eax_func.h +++ /dev/null @@ -1,3 +0,0 @@ - -AL_FUNCTION(ALenum, EAXSet, (const ALGUID*, ALuint, ALuint, ALvoid*, ALuint), return 0; ) -AL_FUNCTION(ALenum, EAXGet, (const ALGUID*, ALuint, ALuint, ALvoid*, ALuint), return 0; ) diff --git a/Engine/lib/openal/LINUX/al/eaxtypes.h b/Engine/lib/openal/LINUX/al/eaxtypes.h deleted file mode 100644 index 15ba59afc..000000000 --- a/Engine/lib/openal/LINUX/al/eaxtypes.h +++ /dev/null @@ -1,462 +0,0 @@ - - -typedef struct _ALGUID -{ - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -}ALGUID; - -#ifndef INITGUID - #define DEFINE_ALGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const ALGUID name -#else - #define DEFINE_ALGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const ALGUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } -#endif // INITGUID - - - -/* - * EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87} - */ -DEFINE_ALGUID(DSPROPSETID_EAX30_ListenerProperties, - 0xa8fa6882, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties - -typedef enum -{ - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMLF, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_DECAYLFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REFLECTIONSPAN, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_REVERBPAN, - DSPROPERTY_EAXLISTENER_ECHOTIME, - DSPROPERTY_EAXLISTENER_ECHODEPTH, - DSPROPERTY_EAXLISTENER_MODULATIONTIME, - DSPROPERTY_EAXLISTENER_MODULATIONDEPTH, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_HFREFERENCE, - DSPROPERTY_EAXLISTENER_LFREFERENCE, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_FLAGS -} DSPROPERTY_EAX_LISTENERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \ - DSPROPERTY_EAXLISTENER_IMMEDIATE) - -typedef struct _EAXVECTOR { - float x; - float y; - float z; -} EAXVECTOR; - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times and delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -typedef struct _EAXLISTENERPROPERTIES -{ - unsigned long ulEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - long lRoom; // room effect level (at mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lRoomLF; // relative room effect level at low frequencies - float flDecayTime; // reverberation decay time at mid frequencies - float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio - float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - EAXVECTOR vReflectionsPan; // early reflections panning vector - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - EAXVECTOR vReverbPan; // late reverberation panning vector - float flEchoTime; // echo time - float flEchoDepth; // echo depth - float flModulationTime; // modulation time - float flModulationDepth; // modulation depth - float flAirAbsorptionHF; // change in level per meter at high frequencies - float flHFReference; // reference high frequency - float flLFReference; // reference low frequency - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - unsigned long ulFlags; // modifies the behavior of properties -} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_UNDEFINED, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time -#define EAXLISTENERFLAGS_ECHOTIMESCALE 0x00000040 // echo time -#define EAXLISTENERFLAGS_MODULATIONTIMESCALE 0x00000080 // modulation time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFF00 // reserved future use - -// Property ranges and defaults: - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINROOM (-10000) -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM (-1000) - -#define EAXLISTENER_MINROOMHF (-10000) -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF (-100) - -#define EAXLISTENER_MINROOMLF (-10000) -#define EAXLISTENER_MAXROOMLF 0 -#define EAXLISTENER_DEFAULTROOMLF 0 - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINDECAYLFRATIO 0.1f -#define EAXLISTENER_MAXDECAYLFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYLFRATIO 1.00f - -#define EAXLISTENER_MINREFLECTIONS (-10000) -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS (-2602) - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB (-10000) -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINECHOTIME 0.075f -#define EAXLISTENER_MAXECHOTIME 0.25f -#define EAXLISTENER_DEFAULTECHOTIME 0.25f - -#define EAXLISTENER_MINECHODEPTH 0.0f -#define EAXLISTENER_MAXECHODEPTH 1.0f -#define EAXLISTENER_DEFAULTECHODEPTH 0.0f - -#define EAXLISTENER_MINMODULATIONTIME 0.04f -#define EAXLISTENER_MAXMODULATIONTIME 4.0f -#define EAXLISTENER_DEFAULTMODULATIONTIME 0.25f - -#define EAXLISTENER_MINMODULATIONDEPTH 0.0f -#define EAXLISTENER_MAXMODULATIONDEPTH 1.0f -#define EAXLISTENER_DEFAULTMODULATIONDEPTH 0.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f) -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f) - -#define EAXLISTENER_MINHFREFERENCE 1000.0f -#define EAXLISTENER_MAXHFREFERENCE 20000.0f -#define EAXLISTENER_DEFAULTHFREFERENCE 5000.0f - -#define EAXLISTENER_MINLFREFERENCE 20.0f -#define EAXLISTENER_MAXLFREFERENCE 1000.0f -#define EAXLISTENER_DEFAULTLFREFERENCE 250.0f - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \ - EAXLISTENERFLAGS_REFLECTIONSSCALE | \ - EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | \ - EAXLISTENERFLAGS_REVERBDELAYSCALE | \ - EAXLISTENERFLAGS_DECAYHFLIMIT) - - - -/* -* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87} -*/ -DEFINE_ALGUID(DSPROPSETID_EAX30_BufferProperties, - 0xa8fa6881, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties -#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties - -typedef enum -{ - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS, - DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, - DSPROPERTY_EAXBUFFER_EXCLUSION, - DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, - DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -} DSPROPERTY_EAX_BUFFERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \ - DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -typedef struct _EAXBUFFERPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // relative occlusion control for room effect - float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) - float flExclusionLFRatio; // exclusion low-frequency level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flDopplerFactor; // like DS3D flDopplerFactor but per source - float flRolloffFactor; // like DS3D flRolloffFactor but per source - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long ulFlags; // modifies the behavior of properties -} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION, -typedef struct _EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION -typedef struct _EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION -typedef struct _EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// Property ranges and defaults: - -#define EAXBUFFER_MINDIRECT (-10000) -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF (-10000) -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM (-10000) -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF (-10000) -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINOBSTRUCTION (-10000) -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION (-10000) -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 1.5f - -#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO 1.0f - -#define EAXBUFFER_MINEXCLUSION (-10000) -#define EAXBUFFER_MAXEXCLUSION 0 -#define EAXBUFFER_DEFAULTEXCLUSION 0 - -#define EAXBUFFER_MINEXCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXEXCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO 1.0f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000) -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINDOPPLERFACTOR 0.0f -#define EAXBUFFER_MAXDOPPLERFACTOR 10.f -#define EAXBUFFER_DEFAULTDOPPLERFACTOR 0.0f - -#define EAXBUFFER_MINROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \ - EAXBUFFERFLAGS_ROOMAUTO | \ - EAXBUFFERFLAGS_ROOMHFAUTO ) diff --git a/Engine/lib/openal/LINUX/libopenal.so b/Engine/lib/openal/LINUX/libopenal.so deleted file mode 100644 index ed65305a0a9d8b5a5da3151cbaffe57f19ef5987..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 281812 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 OpIx16eBHXR<@-O^cKvDq diff --git a/Engine/lib/openal/LINUX/openALFn.h b/Engine/lib/openal/LINUX/openALFn.h deleted file mode 100644 index 0f0b00d48..000000000 --- a/Engine/lib/openal/LINUX/openALFn.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef AL_FUNCTION -#define AL_FUNCTION(fn_return, fn_name, fn_args); -#endif - -#ifndef AL_EXTENSION -#define AL_EXTENSION(ext_name) -#endif - -#ifndef AL_EXT_FUNCTION -#define AL_EXT_FUNCTION(ext_name, fn_return, fn_name, fn_args) -#endif - -// AL functions -AL_FUNCTION(ALvoid, alEnable, ( ALenum capability )) -AL_FUNCTION(ALvoid, alDisable, ( ALenum capability )) -AL_FUNCTION(ALboolean, alIsEnabled, ( ALenum capability )) -AL_FUNCTION(ALvoid, alHint, ( ALenum target, ALenum mode )) -AL_FUNCTION(ALboolean, alGetBoolean, ( ALenum param )) -AL_FUNCTION(ALint, alGetInteger, ( ALenum param )) -AL_FUNCTION(ALfloat, alGetFloat, ( ALenum param )) -AL_FUNCTION(ALdouble, alGetDouble, ( ALenum param )) -AL_FUNCTION(ALvoid, alGetBooleanv, ( ALenum param, ALboolean* data )) -AL_FUNCTION(ALvoid, alGetIntegerv, ( ALenum param, ALint* data )) -AL_FUNCTION(ALvoid, alGetFloatv, ( ALenum param, ALfloat* data )) -AL_FUNCTION(ALvoid, alGetDoublev, ( ALenum param, ALdouble* data )) -AL_FUNCTION(const ALubyte*, alGetString, ( ALenum param )) -AL_FUNCTION(ALenum, alGetError, ( ALvoid )) -AL_FUNCTION(ALboolean, alIsExtensionPresent, ( const ALubyte* fname )) -AL_FUNCTION(ALvoid*, alGetProcAddress, ( const ALubyte* fname )) -AL_FUNCTION(ALenum, alGetEnumValue, ( const ALubyte* ename )) -AL_FUNCTION(ALvoid, alListenerf, ( ALenum pname, ALfloat param )) -AL_FUNCTION(ALvoid, alListener3f, ( ALenum pname, ALfloat param1, ALfloat param2, ALfloat param3 )) -AL_FUNCTION(ALvoid, alListenerfv, ( ALenum pname, ALfloat* param )) -AL_FUNCTION(ALvoid, alGetListeneri, ( ALenum pname, ALint* value )) -AL_FUNCTION(ALvoid, alGetListenerf, ( ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alGetListenerfv, ( ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alGenSources, ( ALsizei n, ALuint* sources )) -AL_FUNCTION(ALvoid, alDeleteSources, ( ALsizei n, ALuint* sources )) -AL_FUNCTION(ALboolean, alIsSource, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourcei, ( ALuint sid, ALenum param, ALint value )) -AL_FUNCTION(ALvoid, alSourcef, ( ALuint sid, ALenum param, ALfloat value )) -AL_FUNCTION(ALvoid, alSource3f, ( ALuint sid, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 )) -AL_FUNCTION(ALvoid, alSourcefv, ( ALuint sid, ALenum param, ALfloat* values )) -AL_FUNCTION(ALvoid, alGetSourcei, ( ALuint sid, ALenum pname, ALint* value )) -AL_FUNCTION(ALvoid, alGetSourcef, ( ALuint sid, ALenum pname, ALfloat* value )) -AL_FUNCTION(ALvoid, alGetSourcefv, ( ALuint sid, ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alSourcePlayv, ( ALuint ns, ALuint* ids )) -AL_FUNCTION(ALvoid, alSourceStopv, ( ALuint ns, ALuint* ids )) -AL_FUNCTION(ALvoid, alSourcePlay, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourcePause, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourceStop, ( ALuint sid )) -AL_FUNCTION(ALvoid, alGenBuffers, ( ALsizei n, ALuint* samples )) -AL_FUNCTION(ALvoid, alDeleteBuffers, ( ALsizei n, ALuint* samples )) -AL_FUNCTION(ALboolean, alIsBuffer, ( ALuint buffer )) -AL_FUNCTION(ALvoid, alBufferData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_FUNCTION(ALsizei, alBufferAppendData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_FUNCTION(ALvoid, alGetBufferi, ( ALuint buffer, ALenum param, ALint* value )) -AL_FUNCTION(ALvoid, alGetBufferf, ( ALuint buffer, ALenum param, ALfloat* value )) - -// ALC functions -AL_FUNCTION(ALvoid*, alcCreateContext, ( ALint* attrlist )) -AL_FUNCTION(ALCenum, alcMakeContextCurrent, ( ALvoid* context )) -AL_FUNCTION(ALvoid*, alcUpdateContext, ( ALvoid* context )) -AL_FUNCTION(ALCenum, alcDestroyContext, ( ALvoid* context )) -AL_FUNCTION(ALCenum, alcGetError, ( ALvoid )) -AL_FUNCTION(const ALubyte *, alcGetErrorString, ( ALvoid )) -AL_FUNCTION(ALvoid*, alcGetCurrentContext, ( ALvoid )) - -// ALUT functions -AL_FUNCTION(void, alutInit, ( int* argc, char** argv )) -AL_FUNCTION(void, alutExit, ( ALvoid )) -AL_FUNCTION(ALboolean, alutLoadWAV, ( const char* fname, ALvoid** data, ALsizei* format, ALsizei* size, ALsizei* bits, ALsizei* freq )) - -// Extensions -AL_EXTENSION(AL_EXT_IASIG) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alGenEnvironmentIASIG, ( ALsizei n, ALuint* environs )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alDeleteEnvironmentIASIG, ( ALsizei n, ALuint* environs )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALboolean, alIsEnvironmentIASIG, ( ALuint environment )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alEnvironmentiIASIG, ( ALuint eid, ALenum param, ALint value )) - -AL_EXTENSION(AL_EXT_DYNAMIX) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferi_EXT, ( ALuint buffer, ALenum pname, ALint value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferSyncData_EXT, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferStreamFile_EXT, ( ALuint buffer, const ALubyte* filename )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alSourceCallback_EXT, ( ALuint source, ALvoid* callback )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alSourceResetEnvironment_EXT, ( ALuint source )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alContexti_EXT, ( ALenum pname, ALint value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alGetContexti_EXT, ( ALenum pname, ALint* value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alGetContextstr_EXT, ( ALenum pname, ALuint idx, ALubyte** value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureInit_EXT, ( ALenum format, ALuint rate, ALsizei bufferSize )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureDestroy_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureStart_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureStop_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALsizei, alCaptureGetData_EXT, ( ALvoid* data, ALsizei n, ALenum format, ALuint rate )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alEnvironmentfIASIG, ( ALuint eid, ALenum param, ALfloat value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alGetEnvironmentiIASIG_EXT, ( ALuint eid, ALenum param, ALint * value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alGetEnvironmentfIASIG_EXT, ( ALuint eid, ALenum param, ALfloat * value )) - -#undef AL_EXTENSION -#undef AL_FUNCTION -#undef AL_EXT_FUNCTION diff --git a/Engine/lib/openal/LINUX/readme.txt b/Engine/lib/openal/LINUX/readme.txt deleted file mode 100644 index eaba63059..000000000 --- a/Engine/lib/openal/LINUX/readme.txt +++ /dev/null @@ -1,10 +0,0 @@ -This is an i586 optimized openal library that is suitable for shipping -games. It is glibc 2.2.5+ compatible. Note that currently this library is -not used when building the engine source code (it is only used by the -install_build scripts). - -Built on RH 7.3 with gcc296. - -Configure command: - -./configure --target=i586-pc-linux-gnu --enable-optimization --enable-sdl=yes diff --git a/Engine/lib/openal/OpenBSD/AL/al.h b/Engine/lib/openal/OpenBSD/AL/al.h deleted file mode 100644 index 6bbc1bb9e..000000000 --- a/Engine/lib/openal/OpenBSD/AL/al.h +++ /dev/null @@ -1,523 +0,0 @@ -#ifndef __al_h_ -#define __al_h_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#define ALAPI __declspec(dllexport) -#define ALAPIENTRY __cdecl -#define AL_CALLBACK -#else /* _WIN32 */ -#define ALAPI -#define ALAPIENTRY -#define AL_CALLBACK -#endif /* _WIN32 */ - -#ifndef AL_NO_PROTOTYPES - -/** - * OpenAL Maintenance Functions - * State Management and Query. - * Error Handling. - * Extension Support. - */ - - -/** Renderer State management. */ -ALAPI void ALAPIENTRY alEnable( ALenum capability ); - -ALAPI void ALAPIENTRY alDisable( ALenum capability ); - -ALAPI ALboolean ALAPIENTRY alIsEnabled( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI void ALAPIENTRY alHint( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY alGetBoolean( ALenum param ); - -/** State retrieval. */ -ALAPI ALint ALAPIENTRY alGetInteger( ALenum param ); - -/** State retrieval. */ -ALAPI ALfloat ALAPIENTRY alGetFloat( ALenum param ); - -/** State retrieval. */ -ALAPI ALdouble ALAPIENTRY alGetDouble( ALenum param ); - -/** State retrieval. */ -ALAPI void ALAPIENTRY alGetBooleanv( ALenum param, ALboolean* data ); - -/** State retrieval. */ -ALAPI void ALAPIENTRY alGetIntegerv( ALenum param, ALint* data ); - -/** State retrieval. */ -ALAPI void ALAPIENTRY alGetFloatv( ALenum param, ALfloat* data ); - -/** State retrieval. */ -ALAPI void ALAPIENTRY alGetDoublev( ALenum param, ALdouble* data ); - -/** State retrieval. */ -ALAPI const ALubyte* ALAPIENTRY alGetString( ALenum param ); - - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY alGetError( ALvoid ); - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( const ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI void* ALAPIENTRY alGetProcAddress( const ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY alGetEnumValue( const ALubyte* ename ); - - - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI void ALAPIENTRY alListenerf( ALenum pname, ALfloat param ); - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI void ALAPIENTRY alListener3f( ALenum pname, ALfloat param1, - ALfloat param2, - ALfloat param3 ); - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI void ALAPIENTRY alListenerfv( ALenum pname, ALfloat* param ); - -/* - * Retrieve listener information. - */ -ALAPI void ALAPIENTRY alGetListeneri( ALenum pname, ALint* value ); -ALAPI void ALAPIENTRY alGetListenerf( ALenum pname, ALfloat* values ); -ALAPI void ALAPIENTRY alGetListenerfv( ALenum pname, ALfloat* values ); - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI void ALAPIENTRY alGenSources( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI void ALAPIENTRY alDeleteSources( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY alIsSource( ALuint sid ); - - -/** Set an integer parameter for a Source object. */ -ALAPI void ALAPIENTRY alSourcei( ALuint sid, ALenum param, ALint value ); -ALAPI void ALAPIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value ); -ALAPI void ALAPIENTRY alSource3f( ALuint sid, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI void ALAPIENTRY alSourcefv( ALuint sid, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI void ALAPIENTRY alGetSourcei( ALuint sid, ALenum pname, ALint* value ); -ALAPI void ALAPIENTRY alGetSourcef( ALuint sid, ALenum pname, ALfloat* value ); -ALAPI void ALAPIENTRY alGetSourcefv( ALuint sid, ALenum pname, ALfloat* values ); - -ALAPI void ALAPIENTRY alSourcePlayv( ALuint ns, ALuint *ids ); -ALAPI void ALAPIENTRY alSourceStopv( ALuint ns, ALuint *ids ); - -/** Activate a source, start replay. */ -ALAPI void ALAPIENTRY alSourcePlay( ALuint sid ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI void ALAPIENTRY alSourcePause( ALuint sid ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI void ALAPIENTRY alSourceStop( ALuint sid ); - - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI void ALAPIENTRY alGenBuffers( ALsizei n, ALuint* samples ); - -ALAPI void ALAPIENTRY alDeleteBuffers( ALsizei n, ALuint* samples ); - - -ALAPI ALboolean ALAPIENTRY alIsBuffer( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI void ALAPIENTRY alBufferData( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - - -/** - * Specify data to be filled into a looping buffer. - * This takes the current position at the time of the - * call, and returns the number of samples written. - */ -ALsizei ALAPIENTRY alBufferAppendData( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - - - - -ALAPI void ALAPIENTRY alGetBufferi( ALuint buffer, ALenum param, ALint* value ); -ALAPI void ALAPIENTRY alGetBufferf( ALuint buffer, ALenum param, ALfloat* value ); - - - - - -/** - * Frequency Domain Filters are band filters. - * Attenuation in Media (distance based) - * Reflection Material - * Occlusion Material (separating surface) - * - * Temporal Domain Filters: - * Early Reflections - * Late Reverb - * - */ - - - - -/** - * EXTENSION: IASIG Level 2 Environment. - * Environment object generation. - * This is an EXTension that describes the Environment/Reverb - * properties according to IASIG Level 2 specifications. - */ - - - - - -/** - * Allocate n environment ids and store them in the array environs. - * Returns the number of environments actually allocated. - */ -ALAPI ALsizei ALAPIENTRY alGenEnvironmentIASIG( ALsizei n, ALuint* environs ); - -ALAPI void ALAPIENTRY alDeleteEnvironmentIASIG( ALsizei n, ALuint* environs ); - -ALAPI ALboolean ALAPIENTRY alIsEnvironmentIASIG( ALuint environ ); - -ALAPI void ALAPIENTRY alEnvironmentiIASIG( ALuint eid, ALenum param, ALint value ); - -ALAPI void ALAPIENTRY alEnvironmentfIASIG( ALuint eid, ALenum param, ALfloat value ); - - - - -#else /* AL_NO_PROTOTYPES */ -// -// -///** OpenAL Maintenance Functions */ -// -// void (*alEnable)( ALenum capability ); -// void (*alDisable)( ALenum capability ); -// ALboolean (*alIsEnabled)( ALenum capability ); -// void (*alHint)( ALenum target, ALenum mode ); -// ALboolean (*alGetBoolean)( ALenum param ); -// ALint (*alGetInteger)( ALenum param ); -// ALfloat (*alGetFloat)( ALenum param ); -// ALdouble (*alGetDouble)( ALenum param ); -// void (*alGetBooleanv)( ALenum param, -// ALboolean* data ); -// void (*alGetIntegerv)( ALenum param, -// ALint* data ); -// void (*alGetFloatv)( ALenum param, -// ALfloat* data ); -// void (*alGetDoublev)( ALenum param, -// ALdouble* data ); -// const ALubyte* (*GetString)( ALenum param ); -// ALenum (*alGetError)( ALvoid ); -// -// /** -// * Extension support. -// * Query existance of extension -// */ -// ALboolean (*alIsExtensionPresent)(const ALubyte* fname ); -// -// /** -// * Extension support. -// * Obtain the address of a function (usually an extension) -// * with the name fname. All addresses are context-independent. -// */ -// void* (*alGetProcAddress)( const ALubyte* fname ); -// -// -// /** -// * Extension support. -// * Obtain the integer value of an enumeration (usually an extension) with the name ename. -// */ -// ALenum (*alGetEnumValue)( const ALubyte* ename ); -// -///** -// * LISTENER -// * Listener is the sample position for a given context. -// * The multi-channel (usually stereo) output stream generated -// * by the mixer is parametrized by this Listener object: -// * its position and velocity relative to Sources, within -// * occluder and reflector geometry. -// */ -// /** -// * -// * Listener Gain: default 1.0f. -// */ -// void (*alListenerf)( ALenum pname, ALfloat param ); -// -// /** -// * -// * Listener Position. -// * Listener Velocity. -// */ -// void (*alListener3f)( ALenum pname, -// ALfloat param1, ALfloat param2, ALfloat param3); -// -// /** -// * -// * Listener Position: ALfloat[3] -// * Listener Velocity: ALfloat[3] -// * Listener Orientation: ALfloat[6] (forward and up vector). -// */ -// void (*alListenerfv)( ALenum pname, ALfloat* param ); -// -///** -// * SOURCE -// * Source objects are by default localized. Sources -// * take the PCM data provided in the specified Buffer, -// * apply Source-specific modifications, and then -// * submit them to be mixed according to spatial -// * arrangement etc. -// */ -// -// /** Create Source objects. */ -// void (*alGenSources)( ALsizei n, ALuint* sources ); -// -// /** Delete Source objects. */ -// void (*alDeleteSources)( ALsizei n, ALuint* sources ); -// -// /** Verify a handle is a valid Source. */ -// ALboolean (*alIsSource)( ALuint sid ); -// -// /** Set an integer parameter for a Source object. */ -// void (*alSourcei)( ALuint sid, ALenum param, ALint value); -// -// /** Set a float parameter for a Source object. */ -// void (*alSourcef)( ALuint sid, ALenum param, ALfloat value); -// -// /** Set a 3-float parameter for a Source object. */ -// void (*alSource3f)( ALuint sid, ALenum param, -// ALfloat v1, ALfloat v2, ALfloat v3 ); -// -// /** Set a float vector parameter for a Source object. */ -// void (*alSourcefv)( ALuint sid, ALenum param, -// ALfloat* values ); -// -// /** Get an integer parameter for a Source object. */ -// void (*alGetSourcei)( ALuint sid, -// ALenum pname, ALint* value ); -// /** Get a float parameter for a Source object. */ -// void (*alGetSourcef)( ALuint sid, -// ALenum pname, ALfloat* value ); -// /** Get a float vector parameter for a Source object. */ -// void (*alGetSourcefv)( ALuint sid, -// ALenum pname, ALfloat* values ); -// -// /** Activate a source, start replay. */ -// void (*alSourcePlay)( ALuint sid ); -// -// /** -// * Pause a source, -// * temporarily remove it from the mixer list. -// */ -// void (*alSourcePause)( ALuint sid ); -// -// /** -// * Stop a source, -// * temporarily remove it from the mixer list, -// * and reset its internal state to pre-Play. -// * To remove a Source completely, it has to be -// * deleted following Stop, or before Play. -// */ -// void (*alSourceStop)( ALuint sid ); -// -///** -// * BUFFER -// * Buffer objects are storage space for sample data. -// * Buffers are referred to by Sources. There can be more than -// * one Source using the same Buffer data. If Buffers have -// * to be duplicated on a per-Source basis, the driver has to -// * take care of allocation, copying, and deallocation as well -// * as propagating buffer data changes. -// */ -// -// /** Buffer object generation. */ -// void (*alGenBuffers)( ALsizei n, ALuint* samples ); -// void (*alDeleteBuffers)( ALsizei n, ALuint* samples ); -// ALboolean (*alIsBuffer)( ALuint buffer ); -// -// /** -// * Specify the data to be filled into a buffer. -// */ -// void (*alBufferData)( ALuint buffer, -// ALenum format, -// ALvoid* data, -// ALsizei size, -// ALsizei freq ); -// -// /** -// * Specify data to be filled into a looping buffer. -// * This takes the current position at the time of the -// * call, and returns the number of samples written. -// */ -// ALsizei (*alBufferAppendData)( ALuint buffer, -// ALenum format, -// ALvoid* data, -// ALsizei size, -// ALsizei freq ); -// void (*alGetBufferi)( ALuint buffer, -// ALenum param, ALint* value ); -// void (*alGetBufferf)( ALuint buffer, -// ALenum param, ALfloat* value ); -// -///** -// * EXTENSION: IASIG Level 2 Environment. -// * Environment object generation. -// * This is an EXTension that describes the Environment/Reverb -// * properties according to IASIG Level 2 specifications. -// */ -// /** -// * Allocate n environment ids and store them in the array environs. -// * Returns the number of environments actually allocated. -// */ -// ALsizei (*alGenEnvironmentIASIG)( ALsizei n, ALuint* environs ); -// void (*alDeleteEnvironmentIASIG)(ALsizei n, -// ALuint* environs); -// ALboolean (*alIsEnvironmentIASIG)( ALuint environ ); -// void (*alEnvironmentiIASIG)( ALuint eid, -// ALenum param, ALint value ); -// void (*alEnvironmentfIASIG)( ALuint eid, -// ALenum param, ALuint value ); -// -///** -// * Frequency Domain Filters are band filters. -// * Attenuation in Media (distance based) -// * Reflection Material -// * Occlusion Material (separating surface) -// * -// * Temporal Domain Filters: -// * Early Reflections -// * Late Reverb -// * -// */ -// -#endif /* AL_NO_PROTOTYPES */ - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* __al_h_ */ diff --git a/Engine/lib/openal/OpenBSD/AL/alc.h b/Engine/lib/openal/OpenBSD/AL/alc.h deleted file mode 100644 index 21b6e1666..000000000 --- a/Engine/lib/openal/OpenBSD/AL/alc.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef ALC_CONTEXT_H_ -#define ALC_CONTEXT_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define ALC_VERSION_0_1 1 - -#ifdef _WIN32 -#define ALAPI __declspec(dllexport) -#define ALAPIENTRY __cdecl -#else /* _WIN32 */ -#define ALAPI -#define ALAPIENTRY -#define AL_CALLBACK -#endif /* _WIN32 */ - -#ifndef AL_NO_PROTOTYPES - -ALAPI void * ALAPIENTRY alcCreateContext( ALint* attrlist ); - -/** - * There is no current context, as we can mix - * several active contexts. But al* calls - * only affect the current context. - */ -ALAPI ALCenum ALAPIENTRY alcMakeContextCurrent( ALvoid *alcHandle ); - -/** ??? */ -ALAPI void * ALAPIENTRY alcUpdateContext( ALvoid *alcHandle ); - -ALAPI ALCenum ALAPIENTRY alcDestroyContext( ALvoid *alcHandle ); - -ALAPI ALCenum ALAPIENTRY alcGetError( ALvoid ); - -ALAPI const ALubyte * ALAPIENTRY alcGetErrorString(ALenum param); - -ALAPI void * ALAPIENTRY alcGetCurrentContext( ALvoid ); - -#else -// -// void * (*alcCreateContext)( ALint* attrlist ); -// -// /** -// * There is no current context, as we can mix -// * several active contexts. But al* calls -// * only affect the current context. -// */ -// ALCenum (*alcMakeContextCurrent)( ALvoid *alcHandle ); -// -// /** ??? */ -// void * (*alcUpdateContext)( ALvoid *alcHandle ); -// -// ALCenum (*alcDestroyContext)( ALvoid *alcHandle ); -// -// ALCenum (*alcGetError) ( ALvoid ); -// -// const ALubyte *(*alcGetErrorString)(ALenum param); -// -// void * (*alcGetCurrentContext)( ALvoid ); -// -#endif /* AL_NO_PROTOTYPES */ - -#ifdef __cplusplus -} -#endif - -#endif /* ALC_CONTEXT_H_ */ diff --git a/Engine/lib/openal/OpenBSD/AL/alctypes.h b/Engine/lib/openal/OpenBSD/AL/alctypes.h deleted file mode 100644 index 5cade199b..000000000 --- a/Engine/lib/openal/OpenBSD/AL/alctypes.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _ALCTYPES_H_ -#define _ALCTYPES_H_ - -typedef enum { - ALC_INVALID, - - ALC_FREQUENCY, /* followed by Hz */ - ALC_RESOLUTION, /* followed by bits */ - - ALC_BUFFERSIZE, /* followed by bytes */ - ALC_CHANNELS, /* followed by hardware channels */ - /* Angst: differentiate channels by categories */ - - ALC_REFRESH, /* followed by Hz */ - ALC_MIXAHEAD, /* followed by msec */ - - ALC_SOURCES, /* followed by ### of sources */ - ALC_BUFFERS, /* followed by ### of buffers */ - - ALC_CD, /* do we want to control the CD? */ - - ALC_SYNC, /* synchronous (need alcUpdateContext) */ - - /* errors */ - ALC_NO_ERROR, - ALC_INVALID_DEVICE, /* No device */ - ALC_INVALID_CONTEXT /* invalid context ID */ -} ALCenum; - -#endif /* _ALCTYPES_H */ diff --git a/Engine/lib/openal/OpenBSD/AL/altypes.h b/Engine/lib/openal/OpenBSD/AL/altypes.h deleted file mode 100644 index 45722994c..000000000 --- a/Engine/lib/openal/OpenBSD/AL/altypes.h +++ /dev/null @@ -1,344 +0,0 @@ -#ifndef _AL_TYPES_H_ -#define _AL_TYPES_H_ - -/** OpenAL bool type. */ -typedef char ALboolean; - -/** OpenAL 8bit signed byte. */ -typedef signed char ALbyte; - -/** OpenAL 8bit unsigned byte. */ -typedef unsigned char ALubyte; - -/** OpenAL 16bit signed short integer type. */ -typedef short ALshort; - -/** OpenAL 16bit unsigned short integer type. */ -typedef unsigned short ALushort; - -/** OpenAL 32bit unsigned integer type. */ -typedef unsigned int ALuint; - -/** OpenAL 32bit signed integer type. */ -typedef int ALint; - -/** OpenAL 32bit floating point type. */ -typedef float ALfloat; - -/** OpenAL 64bit double point type. */ -typedef double ALdouble; - -/** OpenAL 32bit type. */ -typedef signed int ALsizei; - -/** OpenAL void type (for params, not returns). */ -typedef void ALvoid; - -/** OpenAL enumerations. */ -typedef int ALenum; - -/* Enumerant values begin at column 50. No tabs. */ - -/* bad value */ -#define AL_INVALID -1 - -/* Boolean False. */ -#define AL_FALSE 0 - -/** Boolean True. */ -#define AL_TRUE 1 - -/** - * Indicate the type of AL_SOURCE. - * Sources can be spatialized - */ -#define AL_SOURCE_TYPE 0x0200 - -/** Indicate Source has relative coordinates. */ -#define AL_SOURCE_RELATIVE 0x0202 - -/** - * Directional source, inner cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_INNER_ANGLE 0x1001 - -/** - * Directional source, outer cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_OUTER_ANGLE 0x1002 - -/** - * Specify the pitch to be applied, either at source, - * or on mixer results, at listener. - * Range: [0.5-2.0] - * Default: 1.0 - */ -#define AL_PITCH 0x1003 - -/** - * Specify the current location in three dimensional space. - * OpenAL, like OpenGL, uses a right handed coordinate system, - * where in a frontal default view X (thumb) points right, - * Y points up (index finger), and Z points towards the - * viewer/camera (middle finger). - * To switch from a left handed coordinate system, flip the - * sign on the Z coordinate. - * Listener position is always in the world coordinate system. - */ -#define AL_POSITION 0x1004 - -/** Specify the current direction. */ -#define AL_DIRECTION 0x1005 - -/** Specify the current velocity in three dimensional space. */ -#define AL_VELOCITY 0x1006 - -/** - * Indicate whether source is looping. - * Type: ALboolean? - * Range: [AL_TRUE, AL_FALSE] - * Default: FALSE. - */ -#define AL_SOURCE_LOOPING 0x1007 - -/** - * Indicate whether source is meant to be streaming. - * Type: ALboolean? - * Range: [AL_TRUE, AL_FALSE] - * Default: FALSE. - */ -#define AL_STREAMING 0x1008 - -/** - * Indicate the buffer to provide sound samples. - * Type: ALuint. - * Range: any valid Buffer id. - */ -#define AL_BUFFER 0x1009 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN 0x100A - -/** - * Indicate the gain (volume amplification) applied, in a - * normalized linear scale. This affects the value retrieved - * by AL_GAIN. - * - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * A value of 0.0 is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN_LINEAR 0x100B - -/* byte offset into source (in canon format). -1 if source - * is not playing. Don't set this, get this. - * - * Type: ALint - * Range: -1 - +inf - */ -#define AL_BYTE_LOKI 0x100C - -/* - * Indicate minimum source attenuation - * Type: ALfloat - * Range: [0.0 - 1.0] - * - */ -#define AL_SOURCE_ATTENUATION_MIN 0x100D - -/* - * Indicate maximum source attenuation - * Type: ALfloat - * Range: [0.0 - 1.0] - * - */ -#define AL_SOURCE_ATTENUATION_MAX 0x100E - -/* - * Indicate listener orientation. - * - * at/up - */ -#define AL_ORIENTATION 0x100F - - -/* - * Source state information. - */ -#define AL_SOURCE_STATE 0x1010 -#define AL_INITIAL 0x1011 -#define AL_PLAYING 0x1012 -#define AL_PAUSED 0x1013 -#define AL_STOPPED 0x1014 - - -/** Sound samples: format specifier. */ -#define AL_FORMAT_MONO8 0x1100 -#define AL_FORMAT_MONO16 0x1101 -#define AL_FORMAT_STEREO8 0x1102 -#define AL_FORMAT_STEREO16 0x1103 - - -/** - * Sound samples: frequency, in units of Hertz [Hz]. - * This is the number of samples per second. Half of the - * sample frequency marks the maximum significant - * frequency component. - */ -#define AL_FREQUENCY 0x2001 -#define AL_BITS 0x2002 -#define AL_CHANNELS 0x2003 -#define AL_SIZE 0x2004 - - -/** Errors: No Error. */ -#define AL_NO_ERROR AL_FALSE - -/** - * Invalid Name paramater passed to AL call. - */ -#define AL_INVALID_NAME 0xA001 - -/** - * Invalid parameter passed to AL call. - */ -#define AL_ILLEGAL_ENUM 0xA002 - -/** - * Invalid enum parameter value. - */ -#define AL_INVALID_VALUE 0xA003 - -/** - * Illegal call. - */ -#define AL_ILLEGAL_COMMAND 0xA004 - -/** - * No mojo. - */ -#define AL_OUT_OF_MEMORY 0xA005 - - -/** Context strings: Vendor Name. */ -#define AL_VENDOR 0xB001 -#define AL_VERSION 0xB002 -#define AL_RENDERER 0xB003 -#define AL_EXTENSIONS 0xB004 - - -/** IASIG Level 2 Environment. */ - -/** - * Parameter: IASIG ROOM blah - * Type: intgeger - * Range: [-10000, 0] - * Default: -10000 - */ -#define AL_ENV_ROOM_IASIG 0x3001 - -/** - * Parameter: IASIG ROOM_HIGH_FREQUENCY - * Type: integer - * Range: [-10000, 0] - * Default: 0 - */ -#define AL_ENV_ROOM_HIGH_FREQUENCY_IASIG 0x3002 - -/** - * Parameter: IASIG ROOM_ROLLOFF_FACTOR - * Type: float - * Range: [0.0, 10.0] - * Default: 0.0 - */ -#define AL_ENV_ROOM_ROLLOFF_FACTOR_IASIG 0x3003 - -/** - * Parameter: IASIG DECAY_TIME - * Type: float - * Range: [0.1, 20.0] - * Default: 1.0 - */ -#define AL_ENV_DECAY_TIME_IASIG 0x3004 - -/** - * Parameter: IASIG DECAY_HIGH_FREQUENCY_RATIO - * Type: float - * Range: [0.1, 2.0] - * Default: 0.5 - */ -#define AL_ENV_DECAY_HIGH_FREQUENCY_RATIO_IASIG 0x3005 - -/** - * Parameter: IASIG REFLECTIONS - * Type: integer - * Range: [-10000, 1000] - * Default: -10000 - */ -#define AL_ENV_REFLECTIONS_IASIG 0x3006 - -/** - * Parameter: IASIG REFLECTIONS_DELAY - * Type: float - * Range: [0.0, 0.3] - * Default: 0.02 - */ -#define AL_ENV_REFLECTIONS_DELAY_IASIG 0x3006 - -/** - * Parameter: IASIG REVERB - * Type: integer - * Range: [-10000,2000] - * Default: -10000 - */ -#define AL_ENV_REVERB_IASIG 0x3007 - -/** - * Parameter: IASIG REVERB_DELAY - * Type: float - * Range: [0.0, 0.1] - * Default: 0.04 - */ -#define AL_ENV_REVERB_DELAY_IASIG 0x3008 - -/** - * Parameter: IASIG DIFFUSION - * Type: float - * Range: [0.0, 100.0] - * Default: 100.0 - */ -#define AL_ENV_DIFFUSION_IASIG 0x3009 - -/** - * Parameter: IASIG DENSITY - * Type: float - * Range: [0.0, 100.0] - * Default: 100.0 - */ -#define AL_ENV_DENSITY_IASIG 0x300A - - /** - * Parameter: IASIG HIGH_FREQUENCY_REFERENCE - * Type: float - * Range: [20.0, 20000.0] - * Default: 5000.0 - */ -#define AL_ENV_HIGH_FREQUENCY_REFERENCE_IASIG 0x300B - -#endif diff --git a/Engine/lib/openal/OpenBSD/AL/alu.h b/Engine/lib/openal/OpenBSD/AL/alu.h deleted file mode 100644 index 169d5fb03..000000000 --- a/Engine/lib/openal/OpenBSD/AL/alu.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __alu_h_ -#define __alu_h_ - -#ifdef _WIN32 -#define ALAPI __declspec(dllexport) -#define ALAPIENTRY __cdecl -#else /* _WIN32 */ -#define ALAPI -#define ALAPIENTRY -#define AL_CALLBACK -#endif /* _WIN32 */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef AL_NO_PROTOTYPES - - - -#else - - - - - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef __cplusplus -} -#endif - -#endif /* __alu_h_ */ - diff --git a/Engine/lib/openal/OpenBSD/AL/alut.h b/Engine/lib/openal/OpenBSD/AL/alut.h deleted file mode 100644 index b43789030..000000000 --- a/Engine/lib/openal/OpenBSD/AL/alut.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _ALUT_H_ -#define _ALUT_H_ - -#include -#include - -#ifdef _WIN32 -#define ALAPI __declspec(dllexport) -#define ALAPIENTRY __cdecl -#define AL_CALLBACK -#else /* _WIN32 */ -#define ALAPI -#define ALAPIENTRY -#define AL_CALLBACK -#endif /* _WIN32 */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef AL_NO_PROTOTYPES - -ALAPI void ALAPIENTRY alutInit(int *argc, char *argv[]); -ALAPI void ALAPIENTRY alutExit(ALvoid); - -ALAPI ALboolean ALAPIENTRY alutLoadWAV( const char *fname, - ALvoid **wave, - ALsizei *format, - ALsizei *size, - ALsizei *bits, - ALsizei *freq ); - -#else -// -// void (*alutInit)(int *argc, char *argv[]); -// void (*alutExit)(ALvoid); -// -// ALboolean (*alutLoadWAV)( const char *fname, -// ALvoid **wave, -// ALsizei *format, -// ALsizei *size, -// ALsizei *bits, -// ALsizei *freq ); -// -// -#endif /* AL_NO_PROTOTYPES */ - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/OpenBSD/AL/aluttypes.h b/Engine/lib/openal/OpenBSD/AL/aluttypes.h deleted file mode 100644 index 252f622f6..000000000 --- a/Engine/lib/openal/OpenBSD/AL/aluttypes.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ALUTTYPES_H_ -#define _ALUTTYPES_H_ - - -#endif /* _ALUTTYPES_H_ */ diff --git a/Engine/lib/openal/OpenBSD/AL/alutypes.h b/Engine/lib/openal/OpenBSD/AL/alutypes.h deleted file mode 100644 index 82356c671..000000000 --- a/Engine/lib/openal/OpenBSD/AL/alutypes.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ALUTYPES_H_ -#define _ALUTYPES_H_ - - -#endif /* _ALUTYPES_H_ */ diff --git a/Engine/lib/openal/OpenBSD/openALFn.h b/Engine/lib/openal/OpenBSD/openALFn.h deleted file mode 100644 index 0f0b00d48..000000000 --- a/Engine/lib/openal/OpenBSD/openALFn.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef AL_FUNCTION -#define AL_FUNCTION(fn_return, fn_name, fn_args); -#endif - -#ifndef AL_EXTENSION -#define AL_EXTENSION(ext_name) -#endif - -#ifndef AL_EXT_FUNCTION -#define AL_EXT_FUNCTION(ext_name, fn_return, fn_name, fn_args) -#endif - -// AL functions -AL_FUNCTION(ALvoid, alEnable, ( ALenum capability )) -AL_FUNCTION(ALvoid, alDisable, ( ALenum capability )) -AL_FUNCTION(ALboolean, alIsEnabled, ( ALenum capability )) -AL_FUNCTION(ALvoid, alHint, ( ALenum target, ALenum mode )) -AL_FUNCTION(ALboolean, alGetBoolean, ( ALenum param )) -AL_FUNCTION(ALint, alGetInteger, ( ALenum param )) -AL_FUNCTION(ALfloat, alGetFloat, ( ALenum param )) -AL_FUNCTION(ALdouble, alGetDouble, ( ALenum param )) -AL_FUNCTION(ALvoid, alGetBooleanv, ( ALenum param, ALboolean* data )) -AL_FUNCTION(ALvoid, alGetIntegerv, ( ALenum param, ALint* data )) -AL_FUNCTION(ALvoid, alGetFloatv, ( ALenum param, ALfloat* data )) -AL_FUNCTION(ALvoid, alGetDoublev, ( ALenum param, ALdouble* data )) -AL_FUNCTION(const ALubyte*, alGetString, ( ALenum param )) -AL_FUNCTION(ALenum, alGetError, ( ALvoid )) -AL_FUNCTION(ALboolean, alIsExtensionPresent, ( const ALubyte* fname )) -AL_FUNCTION(ALvoid*, alGetProcAddress, ( const ALubyte* fname )) -AL_FUNCTION(ALenum, alGetEnumValue, ( const ALubyte* ename )) -AL_FUNCTION(ALvoid, alListenerf, ( ALenum pname, ALfloat param )) -AL_FUNCTION(ALvoid, alListener3f, ( ALenum pname, ALfloat param1, ALfloat param2, ALfloat param3 )) -AL_FUNCTION(ALvoid, alListenerfv, ( ALenum pname, ALfloat* param )) -AL_FUNCTION(ALvoid, alGetListeneri, ( ALenum pname, ALint* value )) -AL_FUNCTION(ALvoid, alGetListenerf, ( ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alGetListenerfv, ( ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alGenSources, ( ALsizei n, ALuint* sources )) -AL_FUNCTION(ALvoid, alDeleteSources, ( ALsizei n, ALuint* sources )) -AL_FUNCTION(ALboolean, alIsSource, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourcei, ( ALuint sid, ALenum param, ALint value )) -AL_FUNCTION(ALvoid, alSourcef, ( ALuint sid, ALenum param, ALfloat value )) -AL_FUNCTION(ALvoid, alSource3f, ( ALuint sid, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 )) -AL_FUNCTION(ALvoid, alSourcefv, ( ALuint sid, ALenum param, ALfloat* values )) -AL_FUNCTION(ALvoid, alGetSourcei, ( ALuint sid, ALenum pname, ALint* value )) -AL_FUNCTION(ALvoid, alGetSourcef, ( ALuint sid, ALenum pname, ALfloat* value )) -AL_FUNCTION(ALvoid, alGetSourcefv, ( ALuint sid, ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alSourcePlayv, ( ALuint ns, ALuint* ids )) -AL_FUNCTION(ALvoid, alSourceStopv, ( ALuint ns, ALuint* ids )) -AL_FUNCTION(ALvoid, alSourcePlay, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourcePause, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourceStop, ( ALuint sid )) -AL_FUNCTION(ALvoid, alGenBuffers, ( ALsizei n, ALuint* samples )) -AL_FUNCTION(ALvoid, alDeleteBuffers, ( ALsizei n, ALuint* samples )) -AL_FUNCTION(ALboolean, alIsBuffer, ( ALuint buffer )) -AL_FUNCTION(ALvoid, alBufferData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_FUNCTION(ALsizei, alBufferAppendData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_FUNCTION(ALvoid, alGetBufferi, ( ALuint buffer, ALenum param, ALint* value )) -AL_FUNCTION(ALvoid, alGetBufferf, ( ALuint buffer, ALenum param, ALfloat* value )) - -// ALC functions -AL_FUNCTION(ALvoid*, alcCreateContext, ( ALint* attrlist )) -AL_FUNCTION(ALCenum, alcMakeContextCurrent, ( ALvoid* context )) -AL_FUNCTION(ALvoid*, alcUpdateContext, ( ALvoid* context )) -AL_FUNCTION(ALCenum, alcDestroyContext, ( ALvoid* context )) -AL_FUNCTION(ALCenum, alcGetError, ( ALvoid )) -AL_FUNCTION(const ALubyte *, alcGetErrorString, ( ALvoid )) -AL_FUNCTION(ALvoid*, alcGetCurrentContext, ( ALvoid )) - -// ALUT functions -AL_FUNCTION(void, alutInit, ( int* argc, char** argv )) -AL_FUNCTION(void, alutExit, ( ALvoid )) -AL_FUNCTION(ALboolean, alutLoadWAV, ( const char* fname, ALvoid** data, ALsizei* format, ALsizei* size, ALsizei* bits, ALsizei* freq )) - -// Extensions -AL_EXTENSION(AL_EXT_IASIG) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alGenEnvironmentIASIG, ( ALsizei n, ALuint* environs )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alDeleteEnvironmentIASIG, ( ALsizei n, ALuint* environs )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALboolean, alIsEnvironmentIASIG, ( ALuint environment )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alEnvironmentiIASIG, ( ALuint eid, ALenum param, ALint value )) - -AL_EXTENSION(AL_EXT_DYNAMIX) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferi_EXT, ( ALuint buffer, ALenum pname, ALint value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferSyncData_EXT, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferStreamFile_EXT, ( ALuint buffer, const ALubyte* filename )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alSourceCallback_EXT, ( ALuint source, ALvoid* callback )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alSourceResetEnvironment_EXT, ( ALuint source )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alContexti_EXT, ( ALenum pname, ALint value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alGetContexti_EXT, ( ALenum pname, ALint* value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alGetContextstr_EXT, ( ALenum pname, ALuint idx, ALubyte** value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureInit_EXT, ( ALenum format, ALuint rate, ALsizei bufferSize )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureDestroy_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureStart_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureStop_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALsizei, alCaptureGetData_EXT, ( ALvoid* data, ALsizei n, ALenum format, ALuint rate )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alEnvironmentfIASIG, ( ALuint eid, ALenum param, ALfloat value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alGetEnvironmentiIASIG_EXT, ( ALuint eid, ALenum param, ALint * value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alGetEnvironmentfIASIG_EXT, ( ALuint eid, ALenum param, ALfloat * value )) - -#undef AL_EXTENSION -#undef AL_FUNCTION -#undef AL_EXT_FUNCTION diff --git a/Engine/lib/openal/X86UNIX/al/al.h b/Engine/lib/openal/X86UNIX/al/al.h deleted file mode 100644 index 6bbc1bb9e..000000000 --- a/Engine/lib/openal/X86UNIX/al/al.h +++ /dev/null @@ -1,523 +0,0 @@ -#ifndef __al_h_ -#define __al_h_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#define ALAPI __declspec(dllexport) -#define ALAPIENTRY __cdecl -#define AL_CALLBACK -#else /* _WIN32 */ -#define ALAPI -#define ALAPIENTRY -#define AL_CALLBACK -#endif /* _WIN32 */ - -#ifndef AL_NO_PROTOTYPES - -/** - * OpenAL Maintenance Functions - * State Management and Query. - * Error Handling. - * Extension Support. - */ - - -/** Renderer State management. */ -ALAPI void ALAPIENTRY alEnable( ALenum capability ); - -ALAPI void ALAPIENTRY alDisable( ALenum capability ); - -ALAPI ALboolean ALAPIENTRY alIsEnabled( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI void ALAPIENTRY alHint( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY alGetBoolean( ALenum param ); - -/** State retrieval. */ -ALAPI ALint ALAPIENTRY alGetInteger( ALenum param ); - -/** State retrieval. */ -ALAPI ALfloat ALAPIENTRY alGetFloat( ALenum param ); - -/** State retrieval. */ -ALAPI ALdouble ALAPIENTRY alGetDouble( ALenum param ); - -/** State retrieval. */ -ALAPI void ALAPIENTRY alGetBooleanv( ALenum param, ALboolean* data ); - -/** State retrieval. */ -ALAPI void ALAPIENTRY alGetIntegerv( ALenum param, ALint* data ); - -/** State retrieval. */ -ALAPI void ALAPIENTRY alGetFloatv( ALenum param, ALfloat* data ); - -/** State retrieval. */ -ALAPI void ALAPIENTRY alGetDoublev( ALenum param, ALdouble* data ); - -/** State retrieval. */ -ALAPI const ALubyte* ALAPIENTRY alGetString( ALenum param ); - - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY alGetError( ALvoid ); - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( const ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI void* ALAPIENTRY alGetProcAddress( const ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY alGetEnumValue( const ALubyte* ename ); - - - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI void ALAPIENTRY alListenerf( ALenum pname, ALfloat param ); - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI void ALAPIENTRY alListener3f( ALenum pname, ALfloat param1, - ALfloat param2, - ALfloat param3 ); - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI void ALAPIENTRY alListenerfv( ALenum pname, ALfloat* param ); - -/* - * Retrieve listener information. - */ -ALAPI void ALAPIENTRY alGetListeneri( ALenum pname, ALint* value ); -ALAPI void ALAPIENTRY alGetListenerf( ALenum pname, ALfloat* values ); -ALAPI void ALAPIENTRY alGetListenerfv( ALenum pname, ALfloat* values ); - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI void ALAPIENTRY alGenSources( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI void ALAPIENTRY alDeleteSources( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY alIsSource( ALuint sid ); - - -/** Set an integer parameter for a Source object. */ -ALAPI void ALAPIENTRY alSourcei( ALuint sid, ALenum param, ALint value ); -ALAPI void ALAPIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value ); -ALAPI void ALAPIENTRY alSource3f( ALuint sid, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI void ALAPIENTRY alSourcefv( ALuint sid, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI void ALAPIENTRY alGetSourcei( ALuint sid, ALenum pname, ALint* value ); -ALAPI void ALAPIENTRY alGetSourcef( ALuint sid, ALenum pname, ALfloat* value ); -ALAPI void ALAPIENTRY alGetSourcefv( ALuint sid, ALenum pname, ALfloat* values ); - -ALAPI void ALAPIENTRY alSourcePlayv( ALuint ns, ALuint *ids ); -ALAPI void ALAPIENTRY alSourceStopv( ALuint ns, ALuint *ids ); - -/** Activate a source, start replay. */ -ALAPI void ALAPIENTRY alSourcePlay( ALuint sid ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI void ALAPIENTRY alSourcePause( ALuint sid ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI void ALAPIENTRY alSourceStop( ALuint sid ); - - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI void ALAPIENTRY alGenBuffers( ALsizei n, ALuint* samples ); - -ALAPI void ALAPIENTRY alDeleteBuffers( ALsizei n, ALuint* samples ); - - -ALAPI ALboolean ALAPIENTRY alIsBuffer( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI void ALAPIENTRY alBufferData( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - - -/** - * Specify data to be filled into a looping buffer. - * This takes the current position at the time of the - * call, and returns the number of samples written. - */ -ALsizei ALAPIENTRY alBufferAppendData( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - - - - -ALAPI void ALAPIENTRY alGetBufferi( ALuint buffer, ALenum param, ALint* value ); -ALAPI void ALAPIENTRY alGetBufferf( ALuint buffer, ALenum param, ALfloat* value ); - - - - - -/** - * Frequency Domain Filters are band filters. - * Attenuation in Media (distance based) - * Reflection Material - * Occlusion Material (separating surface) - * - * Temporal Domain Filters: - * Early Reflections - * Late Reverb - * - */ - - - - -/** - * EXTENSION: IASIG Level 2 Environment. - * Environment object generation. - * This is an EXTension that describes the Environment/Reverb - * properties according to IASIG Level 2 specifications. - */ - - - - - -/** - * Allocate n environment ids and store them in the array environs. - * Returns the number of environments actually allocated. - */ -ALAPI ALsizei ALAPIENTRY alGenEnvironmentIASIG( ALsizei n, ALuint* environs ); - -ALAPI void ALAPIENTRY alDeleteEnvironmentIASIG( ALsizei n, ALuint* environs ); - -ALAPI ALboolean ALAPIENTRY alIsEnvironmentIASIG( ALuint environ ); - -ALAPI void ALAPIENTRY alEnvironmentiIASIG( ALuint eid, ALenum param, ALint value ); - -ALAPI void ALAPIENTRY alEnvironmentfIASIG( ALuint eid, ALenum param, ALfloat value ); - - - - -#else /* AL_NO_PROTOTYPES */ -// -// -///** OpenAL Maintenance Functions */ -// -// void (*alEnable)( ALenum capability ); -// void (*alDisable)( ALenum capability ); -// ALboolean (*alIsEnabled)( ALenum capability ); -// void (*alHint)( ALenum target, ALenum mode ); -// ALboolean (*alGetBoolean)( ALenum param ); -// ALint (*alGetInteger)( ALenum param ); -// ALfloat (*alGetFloat)( ALenum param ); -// ALdouble (*alGetDouble)( ALenum param ); -// void (*alGetBooleanv)( ALenum param, -// ALboolean* data ); -// void (*alGetIntegerv)( ALenum param, -// ALint* data ); -// void (*alGetFloatv)( ALenum param, -// ALfloat* data ); -// void (*alGetDoublev)( ALenum param, -// ALdouble* data ); -// const ALubyte* (*GetString)( ALenum param ); -// ALenum (*alGetError)( ALvoid ); -// -// /** -// * Extension support. -// * Query existance of extension -// */ -// ALboolean (*alIsExtensionPresent)(const ALubyte* fname ); -// -// /** -// * Extension support. -// * Obtain the address of a function (usually an extension) -// * with the name fname. All addresses are context-independent. -// */ -// void* (*alGetProcAddress)( const ALubyte* fname ); -// -// -// /** -// * Extension support. -// * Obtain the integer value of an enumeration (usually an extension) with the name ename. -// */ -// ALenum (*alGetEnumValue)( const ALubyte* ename ); -// -///** -// * LISTENER -// * Listener is the sample position for a given context. -// * The multi-channel (usually stereo) output stream generated -// * by the mixer is parametrized by this Listener object: -// * its position and velocity relative to Sources, within -// * occluder and reflector geometry. -// */ -// /** -// * -// * Listener Gain: default 1.0f. -// */ -// void (*alListenerf)( ALenum pname, ALfloat param ); -// -// /** -// * -// * Listener Position. -// * Listener Velocity. -// */ -// void (*alListener3f)( ALenum pname, -// ALfloat param1, ALfloat param2, ALfloat param3); -// -// /** -// * -// * Listener Position: ALfloat[3] -// * Listener Velocity: ALfloat[3] -// * Listener Orientation: ALfloat[6] (forward and up vector). -// */ -// void (*alListenerfv)( ALenum pname, ALfloat* param ); -// -///** -// * SOURCE -// * Source objects are by default localized. Sources -// * take the PCM data provided in the specified Buffer, -// * apply Source-specific modifications, and then -// * submit them to be mixed according to spatial -// * arrangement etc. -// */ -// -// /** Create Source objects. */ -// void (*alGenSources)( ALsizei n, ALuint* sources ); -// -// /** Delete Source objects. */ -// void (*alDeleteSources)( ALsizei n, ALuint* sources ); -// -// /** Verify a handle is a valid Source. */ -// ALboolean (*alIsSource)( ALuint sid ); -// -// /** Set an integer parameter for a Source object. */ -// void (*alSourcei)( ALuint sid, ALenum param, ALint value); -// -// /** Set a float parameter for a Source object. */ -// void (*alSourcef)( ALuint sid, ALenum param, ALfloat value); -// -// /** Set a 3-float parameter for a Source object. */ -// void (*alSource3f)( ALuint sid, ALenum param, -// ALfloat v1, ALfloat v2, ALfloat v3 ); -// -// /** Set a float vector parameter for a Source object. */ -// void (*alSourcefv)( ALuint sid, ALenum param, -// ALfloat* values ); -// -// /** Get an integer parameter for a Source object. */ -// void (*alGetSourcei)( ALuint sid, -// ALenum pname, ALint* value ); -// /** Get a float parameter for a Source object. */ -// void (*alGetSourcef)( ALuint sid, -// ALenum pname, ALfloat* value ); -// /** Get a float vector parameter for a Source object. */ -// void (*alGetSourcefv)( ALuint sid, -// ALenum pname, ALfloat* values ); -// -// /** Activate a source, start replay. */ -// void (*alSourcePlay)( ALuint sid ); -// -// /** -// * Pause a source, -// * temporarily remove it from the mixer list. -// */ -// void (*alSourcePause)( ALuint sid ); -// -// /** -// * Stop a source, -// * temporarily remove it from the mixer list, -// * and reset its internal state to pre-Play. -// * To remove a Source completely, it has to be -// * deleted following Stop, or before Play. -// */ -// void (*alSourceStop)( ALuint sid ); -// -///** -// * BUFFER -// * Buffer objects are storage space for sample data. -// * Buffers are referred to by Sources. There can be more than -// * one Source using the same Buffer data. If Buffers have -// * to be duplicated on a per-Source basis, the driver has to -// * take care of allocation, copying, and deallocation as well -// * as propagating buffer data changes. -// */ -// -// /** Buffer object generation. */ -// void (*alGenBuffers)( ALsizei n, ALuint* samples ); -// void (*alDeleteBuffers)( ALsizei n, ALuint* samples ); -// ALboolean (*alIsBuffer)( ALuint buffer ); -// -// /** -// * Specify the data to be filled into a buffer. -// */ -// void (*alBufferData)( ALuint buffer, -// ALenum format, -// ALvoid* data, -// ALsizei size, -// ALsizei freq ); -// -// /** -// * Specify data to be filled into a looping buffer. -// * This takes the current position at the time of the -// * call, and returns the number of samples written. -// */ -// ALsizei (*alBufferAppendData)( ALuint buffer, -// ALenum format, -// ALvoid* data, -// ALsizei size, -// ALsizei freq ); -// void (*alGetBufferi)( ALuint buffer, -// ALenum param, ALint* value ); -// void (*alGetBufferf)( ALuint buffer, -// ALenum param, ALfloat* value ); -// -///** -// * EXTENSION: IASIG Level 2 Environment. -// * Environment object generation. -// * This is an EXTension that describes the Environment/Reverb -// * properties according to IASIG Level 2 specifications. -// */ -// /** -// * Allocate n environment ids and store them in the array environs. -// * Returns the number of environments actually allocated. -// */ -// ALsizei (*alGenEnvironmentIASIG)( ALsizei n, ALuint* environs ); -// void (*alDeleteEnvironmentIASIG)(ALsizei n, -// ALuint* environs); -// ALboolean (*alIsEnvironmentIASIG)( ALuint environ ); -// void (*alEnvironmentiIASIG)( ALuint eid, -// ALenum param, ALint value ); -// void (*alEnvironmentfIASIG)( ALuint eid, -// ALenum param, ALuint value ); -// -///** -// * Frequency Domain Filters are band filters. -// * Attenuation in Media (distance based) -// * Reflection Material -// * Occlusion Material (separating surface) -// * -// * Temporal Domain Filters: -// * Early Reflections -// * Late Reverb -// * -// */ -// -#endif /* AL_NO_PROTOTYPES */ - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* __al_h_ */ diff --git a/Engine/lib/openal/X86UNIX/al/alc.h b/Engine/lib/openal/X86UNIX/al/alc.h deleted file mode 100644 index 21b6e1666..000000000 --- a/Engine/lib/openal/X86UNIX/al/alc.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef ALC_CONTEXT_H_ -#define ALC_CONTEXT_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define ALC_VERSION_0_1 1 - -#ifdef _WIN32 -#define ALAPI __declspec(dllexport) -#define ALAPIENTRY __cdecl -#else /* _WIN32 */ -#define ALAPI -#define ALAPIENTRY -#define AL_CALLBACK -#endif /* _WIN32 */ - -#ifndef AL_NO_PROTOTYPES - -ALAPI void * ALAPIENTRY alcCreateContext( ALint* attrlist ); - -/** - * There is no current context, as we can mix - * several active contexts. But al* calls - * only affect the current context. - */ -ALAPI ALCenum ALAPIENTRY alcMakeContextCurrent( ALvoid *alcHandle ); - -/** ??? */ -ALAPI void * ALAPIENTRY alcUpdateContext( ALvoid *alcHandle ); - -ALAPI ALCenum ALAPIENTRY alcDestroyContext( ALvoid *alcHandle ); - -ALAPI ALCenum ALAPIENTRY alcGetError( ALvoid ); - -ALAPI const ALubyte * ALAPIENTRY alcGetErrorString(ALenum param); - -ALAPI void * ALAPIENTRY alcGetCurrentContext( ALvoid ); - -#else -// -// void * (*alcCreateContext)( ALint* attrlist ); -// -// /** -// * There is no current context, as we can mix -// * several active contexts. But al* calls -// * only affect the current context. -// */ -// ALCenum (*alcMakeContextCurrent)( ALvoid *alcHandle ); -// -// /** ??? */ -// void * (*alcUpdateContext)( ALvoid *alcHandle ); -// -// ALCenum (*alcDestroyContext)( ALvoid *alcHandle ); -// -// ALCenum (*alcGetError) ( ALvoid ); -// -// const ALubyte *(*alcGetErrorString)(ALenum param); -// -// void * (*alcGetCurrentContext)( ALvoid ); -// -#endif /* AL_NO_PROTOTYPES */ - -#ifdef __cplusplus -} -#endif - -#endif /* ALC_CONTEXT_H_ */ diff --git a/Engine/lib/openal/X86UNIX/al/alctypes.h b/Engine/lib/openal/X86UNIX/al/alctypes.h deleted file mode 100644 index 5cade199b..000000000 --- a/Engine/lib/openal/X86UNIX/al/alctypes.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _ALCTYPES_H_ -#define _ALCTYPES_H_ - -typedef enum { - ALC_INVALID, - - ALC_FREQUENCY, /* followed by Hz */ - ALC_RESOLUTION, /* followed by bits */ - - ALC_BUFFERSIZE, /* followed by bytes */ - ALC_CHANNELS, /* followed by hardware channels */ - /* Angst: differentiate channels by categories */ - - ALC_REFRESH, /* followed by Hz */ - ALC_MIXAHEAD, /* followed by msec */ - - ALC_SOURCES, /* followed by ### of sources */ - ALC_BUFFERS, /* followed by ### of buffers */ - - ALC_CD, /* do we want to control the CD? */ - - ALC_SYNC, /* synchronous (need alcUpdateContext) */ - - /* errors */ - ALC_NO_ERROR, - ALC_INVALID_DEVICE, /* No device */ - ALC_INVALID_CONTEXT /* invalid context ID */ -} ALCenum; - -#endif /* _ALCTYPES_H */ diff --git a/Engine/lib/openal/X86UNIX/al/altypes.h b/Engine/lib/openal/X86UNIX/al/altypes.h deleted file mode 100644 index 45722994c..000000000 --- a/Engine/lib/openal/X86UNIX/al/altypes.h +++ /dev/null @@ -1,344 +0,0 @@ -#ifndef _AL_TYPES_H_ -#define _AL_TYPES_H_ - -/** OpenAL bool type. */ -typedef char ALboolean; - -/** OpenAL 8bit signed byte. */ -typedef signed char ALbyte; - -/** OpenAL 8bit unsigned byte. */ -typedef unsigned char ALubyte; - -/** OpenAL 16bit signed short integer type. */ -typedef short ALshort; - -/** OpenAL 16bit unsigned short integer type. */ -typedef unsigned short ALushort; - -/** OpenAL 32bit unsigned integer type. */ -typedef unsigned int ALuint; - -/** OpenAL 32bit signed integer type. */ -typedef int ALint; - -/** OpenAL 32bit floating point type. */ -typedef float ALfloat; - -/** OpenAL 64bit double point type. */ -typedef double ALdouble; - -/** OpenAL 32bit type. */ -typedef signed int ALsizei; - -/** OpenAL void type (for params, not returns). */ -typedef void ALvoid; - -/** OpenAL enumerations. */ -typedef int ALenum; - -/* Enumerant values begin at column 50. No tabs. */ - -/* bad value */ -#define AL_INVALID -1 - -/* Boolean False. */ -#define AL_FALSE 0 - -/** Boolean True. */ -#define AL_TRUE 1 - -/** - * Indicate the type of AL_SOURCE. - * Sources can be spatialized - */ -#define AL_SOURCE_TYPE 0x0200 - -/** Indicate Source has relative coordinates. */ -#define AL_SOURCE_RELATIVE 0x0202 - -/** - * Directional source, inner cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_INNER_ANGLE 0x1001 - -/** - * Directional source, outer cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_OUTER_ANGLE 0x1002 - -/** - * Specify the pitch to be applied, either at source, - * or on mixer results, at listener. - * Range: [0.5-2.0] - * Default: 1.0 - */ -#define AL_PITCH 0x1003 - -/** - * Specify the current location in three dimensional space. - * OpenAL, like OpenGL, uses a right handed coordinate system, - * where in a frontal default view X (thumb) points right, - * Y points up (index finger), and Z points towards the - * viewer/camera (middle finger). - * To switch from a left handed coordinate system, flip the - * sign on the Z coordinate. - * Listener position is always in the world coordinate system. - */ -#define AL_POSITION 0x1004 - -/** Specify the current direction. */ -#define AL_DIRECTION 0x1005 - -/** Specify the current velocity in three dimensional space. */ -#define AL_VELOCITY 0x1006 - -/** - * Indicate whether source is looping. - * Type: ALboolean? - * Range: [AL_TRUE, AL_FALSE] - * Default: FALSE. - */ -#define AL_SOURCE_LOOPING 0x1007 - -/** - * Indicate whether source is meant to be streaming. - * Type: ALboolean? - * Range: [AL_TRUE, AL_FALSE] - * Default: FALSE. - */ -#define AL_STREAMING 0x1008 - -/** - * Indicate the buffer to provide sound samples. - * Type: ALuint. - * Range: any valid Buffer id. - */ -#define AL_BUFFER 0x1009 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN 0x100A - -/** - * Indicate the gain (volume amplification) applied, in a - * normalized linear scale. This affects the value retrieved - * by AL_GAIN. - * - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * A value of 0.0 is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN_LINEAR 0x100B - -/* byte offset into source (in canon format). -1 if source - * is not playing. Don't set this, get this. - * - * Type: ALint - * Range: -1 - +inf - */ -#define AL_BYTE_LOKI 0x100C - -/* - * Indicate minimum source attenuation - * Type: ALfloat - * Range: [0.0 - 1.0] - * - */ -#define AL_SOURCE_ATTENUATION_MIN 0x100D - -/* - * Indicate maximum source attenuation - * Type: ALfloat - * Range: [0.0 - 1.0] - * - */ -#define AL_SOURCE_ATTENUATION_MAX 0x100E - -/* - * Indicate listener orientation. - * - * at/up - */ -#define AL_ORIENTATION 0x100F - - -/* - * Source state information. - */ -#define AL_SOURCE_STATE 0x1010 -#define AL_INITIAL 0x1011 -#define AL_PLAYING 0x1012 -#define AL_PAUSED 0x1013 -#define AL_STOPPED 0x1014 - - -/** Sound samples: format specifier. */ -#define AL_FORMAT_MONO8 0x1100 -#define AL_FORMAT_MONO16 0x1101 -#define AL_FORMAT_STEREO8 0x1102 -#define AL_FORMAT_STEREO16 0x1103 - - -/** - * Sound samples: frequency, in units of Hertz [Hz]. - * This is the number of samples per second. Half of the - * sample frequency marks the maximum significant - * frequency component. - */ -#define AL_FREQUENCY 0x2001 -#define AL_BITS 0x2002 -#define AL_CHANNELS 0x2003 -#define AL_SIZE 0x2004 - - -/** Errors: No Error. */ -#define AL_NO_ERROR AL_FALSE - -/** - * Invalid Name paramater passed to AL call. - */ -#define AL_INVALID_NAME 0xA001 - -/** - * Invalid parameter passed to AL call. - */ -#define AL_ILLEGAL_ENUM 0xA002 - -/** - * Invalid enum parameter value. - */ -#define AL_INVALID_VALUE 0xA003 - -/** - * Illegal call. - */ -#define AL_ILLEGAL_COMMAND 0xA004 - -/** - * No mojo. - */ -#define AL_OUT_OF_MEMORY 0xA005 - - -/** Context strings: Vendor Name. */ -#define AL_VENDOR 0xB001 -#define AL_VERSION 0xB002 -#define AL_RENDERER 0xB003 -#define AL_EXTENSIONS 0xB004 - - -/** IASIG Level 2 Environment. */ - -/** - * Parameter: IASIG ROOM blah - * Type: intgeger - * Range: [-10000, 0] - * Default: -10000 - */ -#define AL_ENV_ROOM_IASIG 0x3001 - -/** - * Parameter: IASIG ROOM_HIGH_FREQUENCY - * Type: integer - * Range: [-10000, 0] - * Default: 0 - */ -#define AL_ENV_ROOM_HIGH_FREQUENCY_IASIG 0x3002 - -/** - * Parameter: IASIG ROOM_ROLLOFF_FACTOR - * Type: float - * Range: [0.0, 10.0] - * Default: 0.0 - */ -#define AL_ENV_ROOM_ROLLOFF_FACTOR_IASIG 0x3003 - -/** - * Parameter: IASIG DECAY_TIME - * Type: float - * Range: [0.1, 20.0] - * Default: 1.0 - */ -#define AL_ENV_DECAY_TIME_IASIG 0x3004 - -/** - * Parameter: IASIG DECAY_HIGH_FREQUENCY_RATIO - * Type: float - * Range: [0.1, 2.0] - * Default: 0.5 - */ -#define AL_ENV_DECAY_HIGH_FREQUENCY_RATIO_IASIG 0x3005 - -/** - * Parameter: IASIG REFLECTIONS - * Type: integer - * Range: [-10000, 1000] - * Default: -10000 - */ -#define AL_ENV_REFLECTIONS_IASIG 0x3006 - -/** - * Parameter: IASIG REFLECTIONS_DELAY - * Type: float - * Range: [0.0, 0.3] - * Default: 0.02 - */ -#define AL_ENV_REFLECTIONS_DELAY_IASIG 0x3006 - -/** - * Parameter: IASIG REVERB - * Type: integer - * Range: [-10000,2000] - * Default: -10000 - */ -#define AL_ENV_REVERB_IASIG 0x3007 - -/** - * Parameter: IASIG REVERB_DELAY - * Type: float - * Range: [0.0, 0.1] - * Default: 0.04 - */ -#define AL_ENV_REVERB_DELAY_IASIG 0x3008 - -/** - * Parameter: IASIG DIFFUSION - * Type: float - * Range: [0.0, 100.0] - * Default: 100.0 - */ -#define AL_ENV_DIFFUSION_IASIG 0x3009 - -/** - * Parameter: IASIG DENSITY - * Type: float - * Range: [0.0, 100.0] - * Default: 100.0 - */ -#define AL_ENV_DENSITY_IASIG 0x300A - - /** - * Parameter: IASIG HIGH_FREQUENCY_REFERENCE - * Type: float - * Range: [20.0, 20000.0] - * Default: 5000.0 - */ -#define AL_ENV_HIGH_FREQUENCY_REFERENCE_IASIG 0x300B - -#endif diff --git a/Engine/lib/openal/X86UNIX/al/alu.h b/Engine/lib/openal/X86UNIX/al/alu.h deleted file mode 100644 index 169d5fb03..000000000 --- a/Engine/lib/openal/X86UNIX/al/alu.h +++ /dev/null @@ -1,37 +0,0 @@ -#ifndef __alu_h_ -#define __alu_h_ - -#ifdef _WIN32 -#define ALAPI __declspec(dllexport) -#define ALAPIENTRY __cdecl -#else /* _WIN32 */ -#define ALAPI -#define ALAPIENTRY -#define AL_CALLBACK -#endif /* _WIN32 */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef AL_NO_PROTOTYPES - - - -#else - - - - - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef __cplusplus -} -#endif - -#endif /* __alu_h_ */ - diff --git a/Engine/lib/openal/X86UNIX/al/alut.h b/Engine/lib/openal/X86UNIX/al/alut.h deleted file mode 100644 index b43789030..000000000 --- a/Engine/lib/openal/X86UNIX/al/alut.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef _ALUT_H_ -#define _ALUT_H_ - -#include -#include - -#ifdef _WIN32 -#define ALAPI __declspec(dllexport) -#define ALAPIENTRY __cdecl -#define AL_CALLBACK -#else /* _WIN32 */ -#define ALAPI -#define ALAPIENTRY -#define AL_CALLBACK -#endif /* _WIN32 */ - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef AL_NO_PROTOTYPES - -ALAPI void ALAPIENTRY alutInit(int *argc, char *argv[]); -ALAPI void ALAPIENTRY alutExit(ALvoid); - -ALAPI ALboolean ALAPIENTRY alutLoadWAV( const char *fname, - ALvoid **wave, - ALsizei *format, - ALsizei *size, - ALsizei *bits, - ALsizei *freq ); - -#else -// -// void (*alutInit)(int *argc, char *argv[]); -// void (*alutExit)(ALvoid); -// -// ALboolean (*alutLoadWAV)( const char *fname, -// ALvoid **wave, -// ALsizei *format, -// ALsizei *size, -// ALsizei *bits, -// ALsizei *freq ); -// -// -#endif /* AL_NO_PROTOTYPES */ - - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/X86UNIX/al/aluttypes.h b/Engine/lib/openal/X86UNIX/al/aluttypes.h deleted file mode 100644 index 252f622f6..000000000 --- a/Engine/lib/openal/X86UNIX/al/aluttypes.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ALUTTYPES_H_ -#define _ALUTTYPES_H_ - - -#endif /* _ALUTTYPES_H_ */ diff --git a/Engine/lib/openal/X86UNIX/al/alutypes.h b/Engine/lib/openal/X86UNIX/al/alutypes.h deleted file mode 100644 index 82356c671..000000000 --- a/Engine/lib/openal/X86UNIX/al/alutypes.h +++ /dev/null @@ -1,5 +0,0 @@ -#ifndef _ALUTYPES_H_ -#define _ALUTYPES_H_ - - -#endif /* _ALUTYPES_H_ */ diff --git a/Engine/lib/openal/X86UNIX/openALFn.h b/Engine/lib/openal/X86UNIX/openALFn.h deleted file mode 100644 index 0f0b00d48..000000000 --- a/Engine/lib/openal/X86UNIX/openALFn.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef AL_FUNCTION -#define AL_FUNCTION(fn_return, fn_name, fn_args); -#endif - -#ifndef AL_EXTENSION -#define AL_EXTENSION(ext_name) -#endif - -#ifndef AL_EXT_FUNCTION -#define AL_EXT_FUNCTION(ext_name, fn_return, fn_name, fn_args) -#endif - -// AL functions -AL_FUNCTION(ALvoid, alEnable, ( ALenum capability )) -AL_FUNCTION(ALvoid, alDisable, ( ALenum capability )) -AL_FUNCTION(ALboolean, alIsEnabled, ( ALenum capability )) -AL_FUNCTION(ALvoid, alHint, ( ALenum target, ALenum mode )) -AL_FUNCTION(ALboolean, alGetBoolean, ( ALenum param )) -AL_FUNCTION(ALint, alGetInteger, ( ALenum param )) -AL_FUNCTION(ALfloat, alGetFloat, ( ALenum param )) -AL_FUNCTION(ALdouble, alGetDouble, ( ALenum param )) -AL_FUNCTION(ALvoid, alGetBooleanv, ( ALenum param, ALboolean* data )) -AL_FUNCTION(ALvoid, alGetIntegerv, ( ALenum param, ALint* data )) -AL_FUNCTION(ALvoid, alGetFloatv, ( ALenum param, ALfloat* data )) -AL_FUNCTION(ALvoid, alGetDoublev, ( ALenum param, ALdouble* data )) -AL_FUNCTION(const ALubyte*, alGetString, ( ALenum param )) -AL_FUNCTION(ALenum, alGetError, ( ALvoid )) -AL_FUNCTION(ALboolean, alIsExtensionPresent, ( const ALubyte* fname )) -AL_FUNCTION(ALvoid*, alGetProcAddress, ( const ALubyte* fname )) -AL_FUNCTION(ALenum, alGetEnumValue, ( const ALubyte* ename )) -AL_FUNCTION(ALvoid, alListenerf, ( ALenum pname, ALfloat param )) -AL_FUNCTION(ALvoid, alListener3f, ( ALenum pname, ALfloat param1, ALfloat param2, ALfloat param3 )) -AL_FUNCTION(ALvoid, alListenerfv, ( ALenum pname, ALfloat* param )) -AL_FUNCTION(ALvoid, alGetListeneri, ( ALenum pname, ALint* value )) -AL_FUNCTION(ALvoid, alGetListenerf, ( ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alGetListenerfv, ( ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alGenSources, ( ALsizei n, ALuint* sources )) -AL_FUNCTION(ALvoid, alDeleteSources, ( ALsizei n, ALuint* sources )) -AL_FUNCTION(ALboolean, alIsSource, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourcei, ( ALuint sid, ALenum param, ALint value )) -AL_FUNCTION(ALvoid, alSourcef, ( ALuint sid, ALenum param, ALfloat value )) -AL_FUNCTION(ALvoid, alSource3f, ( ALuint sid, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 )) -AL_FUNCTION(ALvoid, alSourcefv, ( ALuint sid, ALenum param, ALfloat* values )) -AL_FUNCTION(ALvoid, alGetSourcei, ( ALuint sid, ALenum pname, ALint* value )) -AL_FUNCTION(ALvoid, alGetSourcef, ( ALuint sid, ALenum pname, ALfloat* value )) -AL_FUNCTION(ALvoid, alGetSourcefv, ( ALuint sid, ALenum pname, ALfloat* values )) -AL_FUNCTION(ALvoid, alSourcePlayv, ( ALuint ns, ALuint* ids )) -AL_FUNCTION(ALvoid, alSourceStopv, ( ALuint ns, ALuint* ids )) -AL_FUNCTION(ALvoid, alSourcePlay, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourcePause, ( ALuint sid )) -AL_FUNCTION(ALvoid, alSourceStop, ( ALuint sid )) -AL_FUNCTION(ALvoid, alGenBuffers, ( ALsizei n, ALuint* samples )) -AL_FUNCTION(ALvoid, alDeleteBuffers, ( ALsizei n, ALuint* samples )) -AL_FUNCTION(ALboolean, alIsBuffer, ( ALuint buffer )) -AL_FUNCTION(ALvoid, alBufferData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_FUNCTION(ALsizei, alBufferAppendData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_FUNCTION(ALvoid, alGetBufferi, ( ALuint buffer, ALenum param, ALint* value )) -AL_FUNCTION(ALvoid, alGetBufferf, ( ALuint buffer, ALenum param, ALfloat* value )) - -// ALC functions -AL_FUNCTION(ALvoid*, alcCreateContext, ( ALint* attrlist )) -AL_FUNCTION(ALCenum, alcMakeContextCurrent, ( ALvoid* context )) -AL_FUNCTION(ALvoid*, alcUpdateContext, ( ALvoid* context )) -AL_FUNCTION(ALCenum, alcDestroyContext, ( ALvoid* context )) -AL_FUNCTION(ALCenum, alcGetError, ( ALvoid )) -AL_FUNCTION(const ALubyte *, alcGetErrorString, ( ALvoid )) -AL_FUNCTION(ALvoid*, alcGetCurrentContext, ( ALvoid )) - -// ALUT functions -AL_FUNCTION(void, alutInit, ( int* argc, char** argv )) -AL_FUNCTION(void, alutExit, ( ALvoid )) -AL_FUNCTION(ALboolean, alutLoadWAV, ( const char* fname, ALvoid** data, ALsizei* format, ALsizei* size, ALsizei* bits, ALsizei* freq )) - -// Extensions -AL_EXTENSION(AL_EXT_IASIG) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alGenEnvironmentIASIG, ( ALsizei n, ALuint* environs )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alDeleteEnvironmentIASIG, ( ALsizei n, ALuint* environs )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALboolean, alIsEnvironmentIASIG, ( ALuint environment )) -AL_EXT_FUNCTION(AL_EXT_IASIG, ALvoid, alEnvironmentiIASIG, ( ALuint eid, ALenum param, ALint value )) - -AL_EXTENSION(AL_EXT_DYNAMIX) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferi_EXT, ( ALuint buffer, ALenum pname, ALint value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferSyncData_EXT, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alBufferStreamFile_EXT, ( ALuint buffer, const ALubyte* filename )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alSourceCallback_EXT, ( ALuint source, ALvoid* callback )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alSourceResetEnvironment_EXT, ( ALuint source )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alContexti_EXT, ( ALenum pname, ALint value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alGetContexti_EXT, ( ALenum pname, ALint* value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alGetContextstr_EXT, ( ALenum pname, ALuint idx, ALubyte** value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureInit_EXT, ( ALenum format, ALuint rate, ALsizei bufferSize )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureDestroy_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureStart_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALboolean, alCaptureStop_EXT, ( ALvoid )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALsizei, alCaptureGetData_EXT, ( ALvoid* data, ALsizei n, ALenum format, ALuint rate )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alEnvironmentfIASIG, ( ALuint eid, ALenum param, ALfloat value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alGetEnvironmentiIASIG_EXT, ( ALuint eid, ALenum param, ALint * value )) -AL_EXT_FUNCTION(AL_EXT_DYNAMIX, ALvoid, alGetEnvironmentfIASIG_EXT, ( ALuint eid, ALenum param, ALfloat * value )) - -#undef AL_EXTENSION -#undef AL_FUNCTION -#undef AL_EXT_FUNCTION diff --git a/Engine/lib/openal/macCarb/al/al.h b/Engine/lib/openal/macCarb/al/al.h deleted file mode 100644 index a4132f0a0..000000000 --- a/Engine/lib/openal/macCarb/al/al.h +++ /dev/null @@ -1,491 +0,0 @@ -#ifndef _AL_H_ -#define _AL_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 "altypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - #ifdef _LIB - #define ALAPI __declspec(dllexport) - #else - #define ALAPI __declspec(dllimport) - #endif - #define ALAPIENTRY __cdecl - #define AL_CALLBACK -#else - #ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif - #endif - #define ALAPI - #define ALAPIENTRY __cdecl - #define AL_CALLBACK -#endif - -#define OPENAL - -#ifndef AL_NO_PROTOTYPES - -/** - * OpenAL Maintenance Functions - * Initialization and exiting. - * State Management and Query. - * Error Handling. - * Extension Support. - */ - -/** State management. */ -ALAPI ALvoid ALAPIENTRY alEnable( ALenum capability ); -ALAPI ALvoid ALAPIENTRY alDisable( ALenum capability ); -ALAPI ALboolean ALAPIENTRY alIsEnabled( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI ALvoid ALAPIENTRY alHint( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY alGetBoolean( ALenum param ); -ALAPI ALint ALAPIENTRY alGetInteger( ALenum param ); -ALAPI ALfloat ALAPIENTRY alGetFloat( ALenum param ); -ALAPI ALdouble ALAPIENTRY alGetDouble( ALenum param ); -ALAPI ALvoid ALAPIENTRY alGetBooleanv( ALenum param, ALboolean* data ); -ALAPI ALvoid ALAPIENTRY alGetIntegerv( ALenum param, ALint* data ); -ALAPI ALvoid ALAPIENTRY alGetFloatv( ALenum param, ALfloat* data ); -ALAPI ALvoid ALAPIENTRY alGetDoublev( ALenum param, ALdouble* data ); -ALAPI ALubyte* ALAPIENTRY alGetString( ALenum param ); - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY alGetError( ALvoid ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALvoid* ALAPIENTRY alGetProcAddress( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY alGetEnumValue( ALubyte* ename ); - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Environment: default 0. - */ -ALAPI ALvoid ALAPIENTRY alListeneri( ALenum param, ALint value ); - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI ALvoid ALAPIENTRY alListenerf( ALenum param, ALfloat value ); - - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI ALvoid ALAPIENTRY alListener3f( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); - - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI ALvoid ALAPIENTRY alListenerfv( ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY alGetListeneri( ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetListenerf( ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY alGetListener3f( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY alGetListenerfv( ALenum param, ALfloat* values ); - - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI ALvoid ALAPIENTRY alGenSources( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI ALvoid ALAPIENTRY alDeleteSources( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY alIsSource( ALuint id ); - -/** Set an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY alSourcei( ALuint source, ALenum param, ALint value ); -ALAPI ALvoid ALAPIENTRY alSourcef( ALuint source, ALenum param, ALfloat value ); -ALAPI ALvoid ALAPIENTRY alSource3f( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI ALvoid ALAPIENTRY alSourcefv( ALuint source, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY alGetSourcei( ALuint source, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetSourcef( ALuint source, ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY alGetSource3f( ALuint source, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY alGetSourcefv( ALuint source, ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY alSourcePlayv( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourcePausev( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourceStopv( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n,ALuint *sources); - -/** Activate a source, start replay. */ -ALAPI ALvoid ALAPIENTRY alSourcePlay( ALuint source ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI ALvoid ALAPIENTRY alSourcePause( ALuint source ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI ALvoid ALAPIENTRY alSourceStop( ALuint source ); - -/** - * Rewinds a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - */ -ALAPI ALvoid ALAPIENTRY alSourceRewind( ALuint source ); - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI ALvoid ALAPIENTRY alGenBuffers( ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY alDeleteBuffers( ALsizei n, ALuint* buffers ); -ALAPI ALboolean ALAPIENTRY alIsBuffer( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI ALvoid ALAPIENTRY alBufferData( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - - -ALAPI ALvoid ALAPIENTRY alGetBufferi( ALuint buffer, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetBufferf( ALuint buffer, ALenum param, ALfloat* value ); - - - - -/** - * Queue stuff - */ - -ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers ); - -/** - * Knobs and dials - */ -ALAPI ALvoid ALAPIENTRY alDistanceModel( ALenum value ); -ALAPI ALvoid ALAPIENTRY alDopplerFactor( ALfloat value ); -ALAPI ALvoid ALAPIENTRY alDopplerVelocity( ALfloat value ); - -#else /* AL_NO_PROTOTYPES */ - -/** - * OpenAL Maintenance Functions - * Initialization and exiting. - * State Management and Query. - * Error Handling. - * Extension Support. - */ - -/** State management. */ -ALAPI ALvoid ALAPIENTRY (*alEnable)( ALenum capability ); -ALAPI ALvoid ALAPIENTRY (*alDisable)( ALenum capability ); -ALAPI ALboolean ALAPIENTRY (*alIsEnabled)( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI ALvoid ALAPIENTRY (*alHint)( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY (*alGetBoolean)( ALenum param ); -ALAPI ALint ALAPIENTRY (*alGetInteger)( ALenum param ); -ALAPI ALfloat ALAPIENTRY (*alGetFloat)( ALenum param ); -ALAPI ALdouble ALAPIENTRY (*alGetDouble)( ALenum param ); -ALAPI ALvoid ALAPIENTRY (*alGetBooleanv)( ALenum param, ALboolean* data ); -ALAPI ALvoid ALAPIENTRY (*alGetIntegerv)( ALenum param, ALint* data ); -ALAPI ALvoid ALAPIENTRY (*alGetFloatv)( ALenum param, ALfloat* data ); -ALAPI ALvoid ALAPIENTRY (*alGetDoublev)( ALenum param, ALdouble* data ); -ALAPI ALubyte* ALAPIENTRY (*alGetString)( ALenum param ); - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY (*alGetError)( ALvoid ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY (*alIsExtensionPresent)( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALvoid* ALAPIENTRY (*alGetProcAddress)( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY (*alGetEnumValue)( ALubyte* ename ); - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Environment: default 0. - */ -ALAPI ALvoid ALAPIENTRY (*alListeneri)( ALenum param, ALint value ); - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI ALvoid ALAPIENTRY (*alListenerf)( ALenum param, ALfloat value ); - - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI ALvoid ALAPIENTRY (*alListener3f)( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); - - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI ALvoid ALAPIENTRY (*alListenerfv)( ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY (*alGetListeneri)( ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetListenerf)( ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY (*alGetListener3f)( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY (*alGetListenerfv)( ALenum param, ALfloat* values ); - - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI ALvoid ALAPIENTRY (*alGenSources)( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI ALvoid ALAPIENTRY (*alDeleteSources)( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY (*alIsSource)( ALuint id ); - -/** Set an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY (*alSourcei)( ALuint source, ALenum param, ALint value ); -ALAPI ALvoid ALAPIENTRY (*alSourcef)( ALuint source, ALenum param, ALfloat value ); -ALAPI ALvoid ALAPIENTRY (*alSource3f)( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI ALvoid ALAPIENTRY (*alSourcefv)( ALuint source, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY (*alGetSourcei)( ALuint source, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetSourcef)( ALuint source, ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY (*alGetSourcefv)( ALuint source, ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY (*alSourcePlayv)( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY (*alSourceStopv)( ALsizei n, ALuint *sources ); - -/** Activate a source, start replay. */ -ALAPI ALvoid ALAPIENTRY (*alSourcePlay)( ALuint source ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI ALvoid ALAPIENTRY (*alSourcePause)( ALuint source ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI ALvoid ALAPIENTRY (*alSourceStop)( ALuint source ); - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI ALvoid ALAPIENTRY (*alGenBuffers)( ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY (*alDeleteBuffers)( ALsizei n, ALuint* buffers ); -ALAPI ALboolean ALAPIENTRY (*alIsBuffer)( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI ALvoid ALAPIENTRY (*alBufferData)( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - -ALAPI ALvoid ALAPIENTRY (*alGetBufferi)( ALuint buffer, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetBufferf)( ALuint buffer, ALenum param, ALfloat* value ); - - - - -/** - * Queue stuff - */ -ALAPI ALvoid ALAPIENTRY (*alSourceQueueBuffers)( ALuint source, ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY (*alSourceUnqueueBuffers)( ALuint source, ALsizei n, ALuint* buffers ); - -/** - * Knobs and dials - */ -ALAPI ALvoid ALAPIENTRY (*alDistanceModel)( ALenum value ); -ALAPI ALvoid ALAPIENTRY (*alDopplerFactor)( ALfloat value ); -ALAPI ALvoid ALAPIENTRY (*alDopplerVelocity)( ALfloat value ); - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/macCarb/al/al_func.h b/Engine/lib/openal/macCarb/al/al_func.h deleted file mode 100644 index 9a280ad2a..000000000 --- a/Engine/lib/openal/macCarb/al/al_func.h +++ /dev/null @@ -1,69 +0,0 @@ - -AL_FUNCTION(ALvoid, alEnable, ( ALenum capability ), return; ) -AL_FUNCTION(ALvoid, alDisable, ( ALenum capability ), return; ) -AL_FUNCTION(ALboolean, alIsEnabled, ( ALenum capability ), return AL_FALSE; ) - -//AL_FUNCTION(ALvoid, alHint, ( ALenum target, ALenum mode ), return; ) - -AL_FUNCTION(ALboolean, alGetBoolean, ( ALenum param ), return AL_FALSE; ) -AL_FUNCTION(ALint, alGetInteger, ( ALenum param ), return 0; ) -AL_FUNCTION(ALfloat, alGetFloat, ( ALenum param ), return 0.0f; ) -AL_FUNCTION(ALdouble, alGetDouble, ( ALenum param ), return 0.0; ) -AL_FUNCTION(ALvoid, alGetBooleanv, ( ALenum param, ALboolean* data ), return; ) -AL_FUNCTION(ALvoid, alGetIntegerv, ( ALenum param, ALint* data ), return; ) -AL_FUNCTION(ALvoid, alGetFloatv, ( ALenum param, ALfloat* data ), return; ) -AL_FUNCTION(ALvoid, alGetDoublev, ( ALenum param, ALdouble* data ), return; ) -AL_FUNCTION(ALubyte*, alGetString, ( ALenum param ), return NULL; ) - -AL_FUNCTION(ALenum, alGetError, ( ALvoid ), return AL_INVALID_VALUE; ) -AL_FUNCTION(ALboolean, alIsExtensionPresent, ( ALubyte* fname ), return AL_FALSE; ) -AL_FUNCTION(ALvoid*, alGetProcAddress, ( ALubyte* fname ), return NULL; ) -AL_FUNCTION(ALenum, alGetEnumValue, ( ALubyte* ename ), return AL_INVALID_ENUM; ) - -AL_FUNCTION(ALvoid, alListeneri, ( ALenum param, ALint value ), return; ) -AL_FUNCTION(ALvoid, alListenerf, ( ALenum param, ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alListener3f, ( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ), return; ) -AL_FUNCTION(ALvoid, alListenerfv, ( ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alGetListeneri, ( ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetListenerf, ( ALenum param, ALfloat* value ), return; ) -AL_FUNCTION(ALvoid, alGetListener3f, ( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ), return; ) -AL_FUNCTION(ALvoid, alGetListenerfv, ( ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alGenSources, ( ALsizei n, ALuint* sources ), return; ) -AL_FUNCTION(ALvoid, alDeleteSources, ( ALsizei n, ALuint* sources ), return; ) -AL_FUNCTION(ALboolean, alIsSource, ( ALuint id ), return AL_FALSE; ) - -AL_FUNCTION(ALvoid, alSourcei, ( ALuint source, ALenum param, ALint value ), return; ) -AL_FUNCTION(ALvoid, alSourcef, ( ALuint source, ALenum param, ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alSource3f, ( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ), return; ) -AL_FUNCTION(ALvoid, alSourcefv, ( ALuint source, ALenum param, ALfloat* values ), return; ) -AL_FUNCTION(ALvoid, alGetSourcei, ( ALuint source, ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetSourcef, ( ALuint source, ALenum param, ALfloat* value ), return; ) -//AL_FUNCTION(ALvoid, alGetSource3f, ( ALuint source, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ), return; ) -AL_FUNCTION(ALvoid, alGetSourcefv, ( ALuint source, ALenum param, ALfloat* values ), return; ) - -AL_FUNCTION(ALvoid, alSourcePlayv, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourcePausev, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourceStopv, ( ALsizei n, ALuint *sources ), return; ) -AL_FUNCTION(ALvoid, alSourceRewindv, (ALsizei n,ALuint *sources), return; ) -AL_FUNCTION(ALvoid, alSourcePlay, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourcePause, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourceStop, ( ALuint source ), return; ) -AL_FUNCTION(ALvoid, alSourceRewind, ( ALuint source ), return; ) - -AL_FUNCTION(ALvoid, alGenBuffers, ( ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALvoid, alDeleteBuffers, ( ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALboolean, alIsBuffer, ( ALuint buffer ), return AL_FALSE; ) -AL_FUNCTION(ALvoid, alBufferData, ( ALuint buffer, ALenum format, ALvoid* data, ALsizei size, ALsizei freq ), return; ) -AL_FUNCTION(ALvoid, alGetBufferi, ( ALuint buffer, ALenum param, ALint* value ), return; ) -AL_FUNCTION(ALvoid, alGetBufferf, ( ALuint buffer, ALenum param, ALfloat* value ), return; ) - -AL_FUNCTION(ALvoid, alSourceQueueBuffers, ( ALuint source, ALsizei n, ALuint* buffers ), return; ) -AL_FUNCTION(ALvoid, alSourceUnqueueBuffers, ( ALuint source, ALsizei n, ALuint* buffers ), return; ) - -AL_FUNCTION(ALvoid, alDistanceModel, ( ALenum value ), return; ) -AL_FUNCTION(ALvoid, alDopplerFactor, ( ALfloat value ), return; ) -AL_FUNCTION(ALvoid, alDopplerVelocity, ( ALfloat value ), return; ) - - diff --git a/Engine/lib/openal/macCarb/al/alc.h b/Engine/lib/openal/macCarb/al/alc.h deleted file mode 100644 index 7804227d4..000000000 --- a/Engine/lib/openal/macCarb/al/alc.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef _ALC_H_ -#define _ALC_H_ - -#include "altypes.h" -#include "alctypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - #ifdef _LIB - #define ALCAPI __declspec(dllexport) - #else - #define ALCAPI __declspec(dllimport) - typedef ALCvoid ALCdevice; - typedef ALCvoid ALCcontext; - #endif - #define ALCAPIENTRY __cdecl -#else - #ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif - #endif - #define ALCAPI - #define ALCAPIENTRY __cdecl -#endif - - - -#ifndef ALC_NO_PROTOTYPES - -ALCAPI ALCubyte* ALCAPIENTRY alcGetString(ALCdevice *device,ALCenum param); -ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALCsizei size,ALCint *data); - -ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(ALCubyte *deviceName); -ALCAPI ALCvoid ALCAPIENTRY alcCloseDevice(ALCdevice *device); - -ALCAPI ALCcontext*ALCAPIENTRY alcCreateContext(ALCdevice *device,ALCint *attrList); -ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *context); -ALCAPI ALCcontext*ALCAPIENTRY alcGetCurrentContext(ALCvoid); -ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context); - -ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device); - -ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device,ALCubyte *extName); -ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device,ALCubyte *funcName); -ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device,ALCubyte *enumName); - -#else /* AL_NO_PROTOTYPES */ - -ALCAPI ALCubyte* ALCAPIENTRY (*alcGetString)(ALCdevice *device,ALCenum param); -ALCAPI ALCvoid ALCAPIENTRY (*alcGetIntegerv)(ALCdevice * device,ALCenum param,ALCsizei size,ALCint *data); - -ALCAPI ALCdevice* ALCAPIENTRY (*alcOpenDevice)(ALubyte *deviceName); -ALCAPI ALCvoid ALCAPIENTRY (*alcCloseDevice)(ALCdevice *device); - -ALCAPI ALCcontext*ALCAPIENTRY (*alcCreateContext)(ALCdevice *device,ALCint *attrList); -ALCAPI ALCboolean ALCAPIENTRY (*alcMakeContextCurrent)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcProcessContext)(ALCcontext *context); -ALCAPI ALCcontext*ALCAPIENTRY (*alcGetCurrentContext)(ALCvoid); -ALCAPI ALCdevice* ALCAPIENTRY (*alcGetContextsDevice)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcSuspendContext)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcDestroyContext)(ALCcontext *context); - -ALCAPI ALCenum ALCAPIENTRY (*alcGetError)(ALCdevice *device); - -ALCAPI ALCboolean ALCAPIENTRY (*alcIsExtensionPresent)(ALCdevice *device,ALCubyte *extName); -ALCAPI ALCvoid * ALCAPIENTRY (*alcGetProcAddress)(ALCdevice *device,ALCubyte *funcName); -ALCAPI ALCenum ALCAPIENTRY (*alcGetEnumValue)(ALCdevice *device,ALCubyte *enumName); - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/macCarb/al/alc_func.h b/Engine/lib/openal/macCarb/al/alc_func.h deleted file mode 100644 index 22da893e0..000000000 --- a/Engine/lib/openal/macCarb/al/alc_func.h +++ /dev/null @@ -1,20 +0,0 @@ - -//AL_FUNCTION(ALCubyte*, alcGetString, (ALCdevice *device,ALCenum param), return NULL; ) -//AL_FUNCTION(ALCvoid, alcGetIntegerv, (ALCdevice * device,ALCenum param,ALCsizei size,ALCint *data), return; ) - -AL_FUNCTION(ALCdevice*, alcOpenDevice, (ALubyte *deviceName), return NULL; ) -AL_FUNCTION(ALCvoid, alcCloseDevice, (ALCdevice *device), return; ) - -AL_FUNCTION(ALCcontext*, alcCreateContext, (ALCdevice *device,ALCint *attrList), return NULL; ) -AL_FUNCTION(ALCboolean, alcMakeContextCurrent, (ALCcontext *context), return AL_FALSE; ) -AL_FUNCTION(ALCvoid, alcProcessContext, (ALCcontext *context), return; ) -AL_FUNCTION(ALCcontext*, alcGetCurrentContext, (ALCvoid), return NULL; ) -AL_FUNCTION(ALCdevice*, alcGetContextsDevice, (ALCcontext *context), return NULL; ) -AL_FUNCTION(ALCvoid, alcSuspendContext, (ALCcontext *context), return; ) -AL_FUNCTION(ALCvoid, alcDestroyContext, (ALCcontext *context), return; ) - -AL_FUNCTION(ALCenum, alcGetError, (ALCdevice *device), return ALC_INVALID_DEVICE; ) - -//AL_FUNCTION(ALCboolean, alcIsExtensionPresent, (ALCdevice *device,ALCubyte *extName), return AL_FALSE; ) -//AL_FUNCTION(ALCvoid*, alcGetProcAddress, (ALCdevice *device,ALCubyte *funcName), return NULL; ) -//AL_FUNCTION(ALCenum, alcGetEnumValue, (ALCdevice *device,ALCubyte *enumName), return ALC_INVALID_ENUM; ) diff --git a/Engine/lib/openal/macCarb/al/alctypes.h b/Engine/lib/openal/macCarb/al/alctypes.h deleted file mode 100644 index 72ff49689..000000000 --- a/Engine/lib/openal/macCarb/al/alctypes.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef _ALCTYPES_H_ -#define _ALCTYPES_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 __cplusplus -extern "C" { -#endif - -/** ALC boolean type. */ -typedef char ALCboolean; - -/** ALC 8bit signed byte. */ -typedef char ALCbyte; - -/** ALC 8bit unsigned byte. */ -typedef unsigned char ALCubyte; - -/** ALC 16bit signed short integer type. */ -typedef short ALCshort; - -/** ALC 16bit unsigned short integer type. */ -typedef unsigned short ALCushort; - -/** ALC 32bit unsigned integer type. */ -typedef unsigned ALCuint; - -/** ALC 32bit signed integer type. */ -typedef int ALCint; - -/** ALC 32bit floating point type. */ -typedef float ALCfloat; - -/** ALC 64bit double point type. */ -typedef double ALCdouble; - -/** ALC 32bit type. */ -typedef unsigned int ALCsizei; - -/** ALC void type */ -typedef void ALCvoid; - -/** ALC enumerations. */ -typedef int ALCenum; - - -typedef ALCvoid ALCdevice; -typedef ALCvoid ALCcontext; - - -/* Bad value. */ -#define ALC_INVALID (-1) - -/* Boolean False. */ -#define ALC_FALSE 0 - -/* Boolean True. */ -#define ALC_TRUE 1 - -/** Errors: No Error. */ -#define ALC_NO_ERROR ALC_FALSE - -#define ALC_MAJOR_VERSION 0x1000 -#define ALC_MINOR_VERSION 0x1001 -#define ALC_ATTRIBUTES_SIZE 0x1002 -#define ALC_ALL_ATTRIBUTES 0x1003 - -#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 -#define ALC_DEVICE_SPECIFIER 0x1005 -#define ALC_EXTENSIONS 0x1006 - -#define ALC_FREQUENCY 0x1007 -#define ALC_REFRESH 0x1008 -#define ALC_SYNC 0x1009 - -/** - * The device argument does not name a valid dvice. - */ -#define ALC_INVALID_DEVICE 0xA001 - -/** - * The context argument does not name a valid context. - */ -#define ALC_INVALID_CONTEXT 0xA002 - -/** - * A function was called at inappropriate time, - * or in an inappropriate way, causing an illegal state. - * This can be an incompatible ALenum, object ID, - * and/or function. - */ -#define ALC_INVALID_ENUM 0xA003 - -/** - * Illegal value passed as an argument to an AL call. - * Applies to parameter values, but not to enumerations. - */ -#define ALC_INVALID_VALUE 0xA004 - -/** - * A function could not be completed, - * because there is not enough memory available. - */ -#define ALC_OUT_OF_MEMORY 0xA005 - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Engine/lib/openal/macCarb/al/altypes.h b/Engine/lib/openal/macCarb/al/altypes.h deleted file mode 100644 index eb7c17301..000000000 --- a/Engine/lib/openal/macCarb/al/altypes.h +++ /dev/null @@ -1,336 +0,0 @@ -#ifndef _ALTYPES_H_ -#define _ALTYPES_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 __cplusplus -extern "C" { -#endif - -/** OpenAL boolean type. */ -typedef char ALboolean; - -/** OpenAL 8bit signed byte. */ -typedef char ALbyte; - -/** OpenAL 8bit unsigned byte. */ -typedef unsigned char ALubyte; - -/** OpenAL 16bit signed short integer type. */ -typedef short ALshort; - -/** OpenAL 16bit unsigned short integer type. */ -typedef unsigned short ALushort; - -/** OpenAL 32bit unsigned integer type. */ -typedef unsigned ALuint; - -/** OpenAL 32bit signed integer type. */ -typedef int ALint; - -/** OpenAL 32bit floating point type. */ -typedef float ALfloat; - -/** OpenAL 64bit double point type. */ -typedef double ALdouble; - -/** OpenAL 32bit type. */ -typedef unsigned int ALsizei; - -/** OpenAL void type */ -typedef void ALvoid; - -/** OpenAL enumerations. */ -typedef int ALenum; - -/* Bad value. */ -#define AL_INVALID (-1) - -/* Disable value. */ -#define AL_NONE 0 - -/* Boolean False. */ -#define AL_FALSE 0 - -/* Boolean True. */ -#define AL_TRUE 1 - -/** - * Indicate the type of AL_SOURCE. - * Sources can be spatialized - */ -#define AL_SOURCE_TYPE 0x200 - -/** Indicate source has absolute coordinates. */ -#define AL_SOURCE_ABSOLUTE 0x201 - -/** Indicate Source has listener relative coordinates. */ -#define AL_SOURCE_RELATIVE 0x202 - -/** - * Directional source, inner cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_INNER_ANGLE 0x1001 - -/** - * Directional source, outer cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_OUTER_ANGLE 0x1002 - -/** - * Specify the pitch to be applied, either at source, - * or on mixer results, at listener. - * Range: [0.5-2.0] - * Default: 1.0 - */ -#define AL_PITCH 0x1003 - -/** - * Specify the current location in three dimensional space. - * OpenAL, like OpenGL, uses a right handed coordinate system, - * where in a frontal default view X (thumb) points right, - * Y points up (index finger), and Z points towards the - * viewer/camera (middle finger). - * To switch from a left handed coordinate system, flip the - * sign on the Z coordinate. - * Listener position is always in the world coordinate system. - */ -#define AL_POSITION 0x1004 - -/** Specify the current direction as forward vector. */ -#define AL_DIRECTION 0x1005 - -/** Specify the current velocity in three dimensional space. */ -#define AL_VELOCITY 0x1006 - -/** - * Indicate whether source has to loop infinite. - * Type: ALboolean - * Range: [AL_TRUE, AL_FALSE] - * Default: AL_FALSE - */ -#define AL_LOOPING 0x1007 - -/** - * Indicate the buffer to provide sound samples. - * Type: ALuint. - * Range: any valid Buffer id. - */ -#define AL_BUFFER 0x1009 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN 0x100A - -/** - * Indicate minimum source attenuation. - * Type: ALfloat - * Range: [0.0 - 1.0] - */ -#define AL_MIN_GAIN 0x100D - -/** - * Indicate maximum source attenuation. - * Type: ALfloat - * Range: [0.0 - 1.0] - */ -#define AL_MAX_GAIN 0x100E - -/** - * Specify the current orientation. - * Type: ALfv6 (at/up) - * Range: N/A - */ -#define AL_ORIENTATION 0x100F - -/* byte offset into source (in canon format). -1 if source - * is not playing. Don't set this, get this. - * - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - */ -#define AL_REFERENCE_DISTANCE 0x1020 - - /** - * Indicate the rolloff factor for the source. - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - */ -#define AL_ROLLOFF_FACTOR 0x1021 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_CONE_OUTER_GAIN 0x1022 - -/** - * Specify the maximum distance. - * Type: ALfloat - * Range: [0.0 - ] - */ -#define AL_MAX_DISTANCE 0x1023 - -/** - * Specify the channel mask. (Creative) - * Type: ALuint - * Range: [0 - 255] - */ -#define AL_CHANNEL_MASK 0x3000 - -/** - * Source state information - */ -#define AL_SOURCE_STATE 0x1010 -#define AL_INITIAL 0x1011 -#define AL_PLAYING 0x1012 -#define AL_PAUSED 0x1013 -#define AL_STOPPED 0x1014 - -/** - * Buffer Queue params - */ -#define AL_BUFFERS_QUEUED 0x1015 -#define AL_BUFFERS_PROCESSED 0x1016 - -/** Sound buffers: format specifier. */ -#define AL_FORMAT_MONO8 0x1100 -#define AL_FORMAT_MONO16 0x1101 -#define AL_FORMAT_STEREO8 0x1102 -#define AL_FORMAT_STEREO16 0x1103 - -/** - * Sound buffers: frequency, in units of Hertz [Hz]. - * This is the number of samples per second. Half of the - * sample frequency marks the maximum significant - * frequency component. - */ -#define AL_FREQUENCY 0x2001 -#define AL_BITS 0x2002 -#define AL_CHANNELS 0x2003 -#define AL_SIZE 0x2004 -#define AL_DATA 0x2005 - -/** - * Buffer state. - * - * Not supported for public use (yet). - */ -#define AL_UNUSED 0x2010 -#define AL_PENDING 0x2011 -#define AL_PROCESSED 0x2012 - -/** Errors: No Error. */ -#define AL_NO_ERROR AL_FALSE - -/** - * Illegal name passed as an argument to an AL call. - */ -#define AL_INVALID_NAME 0xA001 - -/** - * Illegal enum passed as an argument to an AL call. - */ -#define AL_INVALID_ENUM 0xA002 -/** - * Illegal value passed as an argument to an AL call. - * Applies to parameter values, but not to enumerations. - */ -#define AL_INVALID_VALUE 0xA003 - -/** - * A function was called at inappropriate time, - * or in an inappropriate way, causing an illegal state. - * This can be an incompatible ALenum, object ID, - * and/or function. - */ -#define AL_INVALID_OPERATION 0xA004 - -/** - * A function could not be completed, - * because there is not enough memory available. - */ -#define AL_OUT_OF_MEMORY 0xA005 - -/** Context strings: Vendor Name. */ -#define AL_VENDOR 0xB001 -#define AL_VERSION 0xB002 -#define AL_RENDERER 0xB003 -#define AL_EXTENSIONS 0xB004 - -/** Global tweakage. */ - -/** - * Doppler scale. Default 1.0 - */ -#define AL_DOPPLER_FACTOR 0xC000 - -/** - * Doppler velocity. Default 1.0 - */ -#define AL_DOPPLER_VELOCITY 0xC001 - -/** - * Distance model. Default AL_INVERSE_DISTANCE_CLAMPED - */ -#define AL_DISTANCE_MODEL 0xD000 - -/** Distance models. */ - -#define AL_INVERSE_DISTANCE 0xD001 -#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 -#define AL_LINEAR_DISTANCE 0xD003 -#define AL_LINEAR_DISTANCE_CLAMPED 0xD004 -#define AL_EXPONENT_DISTANCE 0xD005 -#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 - - /** - * enables - */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/macCarb/al/alu.h b/Engine/lib/openal/macCarb/al/alu.h deleted file mode 100644 index c6adff62c..000000000 --- a/Engine/lib/openal/macCarb/al/alu.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef _ALU_H_ -#define _ALU_H_ - -#define ALUAPI -#define ALUAPIENTRY __cdecl - -#define BUFFERSIZE 48000 -#define FRACTIONBITS 14 -#define FRACTIONMASK ((1L< - - /* - * EAX Wrapper Interface (using Direct X 7) {4FF53B81-1CE0-11d3-AAB8-00A0C95949D5} - */ - DEFINE_GUID(CLSID_EAXDirectSound, - 0x4ff53b81, - 0x1ce0, - 0x11d3, - 0xaa, 0xb8, 0x0, 0xa0, 0xc9, 0x59, 0x49, 0xd5); - - /* - * EAX Wrapper Interface (using Direct X 8) {CA503B60-B176-11d4-A094-D0C0BF3A560C} - */ - DEFINE_GUID(CLSID_EAXDirectSound8, - 0xca503b60, - 0xb176, - 0x11d4, - 0xa0, 0x94, 0xd0, 0xc0, 0xbf, 0x3a, 0x56, 0xc); - - - -#ifdef DIRECTSOUND_VERSION -#if DIRECTSOUND_VERSION == 0x0800 - __declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate8(GUID*, LPDIRECTSOUND8*, IUnknown FAR *); - typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE8)(GUID*, LPDIRECTSOUND8*, IUnknown FAR*); -#endif -#endif - - __declspec(dllimport) HRESULT WINAPI EAXDirectSoundCreate(GUID*, LPDIRECTSOUND*, IUnknown FAR *); - typedef HRESULT (FAR PASCAL *LPEAXDIRECTSOUNDCREATE)(GUID*, LPDIRECTSOUND*, IUnknown FAR*); - -#else // OPENAL - #include - - #ifndef GUID_DEFINED - #define GUID_DEFINED - typedef struct _GUID - { - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; - } GUID; - #endif // !GUID_DEFINED - - #ifndef DEFINE_GUID - #ifndef INITGUID - #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const GUID FAR name - #else - #define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } - #endif // INITGUID - #endif // DEFINE_GUID - - - /* - * EAX OpenAL Extension - */ - typedef ALenum (*EAXSet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint); - typedef ALenum (*EAXGet)(const GUID*, ALuint, ALuint, ALvoid*, ALuint); -#endif - -#pragma pack(push, 4) - -/* - * EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87} - */ -DEFINE_GUID(DSPROPSETID_EAX30_ListenerProperties, - 0xa8fa6882, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties - -typedef enum -{ - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMLF, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_DECAYLFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REFLECTIONSPAN, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_REVERBPAN, - DSPROPERTY_EAXLISTENER_ECHOTIME, - DSPROPERTY_EAXLISTENER_ECHODEPTH, - DSPROPERTY_EAXLISTENER_MODULATIONTIME, - DSPROPERTY_EAXLISTENER_MODULATIONDEPTH, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_HFREFERENCE, - DSPROPERTY_EAXLISTENER_LFREFERENCE, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_FLAGS -} DSPROPERTY_EAX_LISTENERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \ - DSPROPERTY_EAXLISTENER_IMMEDIATE) - -typedef struct _EAXVECTOR { - float x; - float y; - float z; -} EAXVECTOR; - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times and delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -typedef struct _EAXLISTENERPROPERTIES -{ - unsigned long ulEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - long lRoom; // room effect level (at mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lRoomLF; // relative room effect level at low frequencies - float flDecayTime; // reverberation decay time at mid frequencies - float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio - float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - EAXVECTOR vReflectionsPan; // early reflections panning vector - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - EAXVECTOR vReverbPan; // late reverberation panning vector - float flEchoTime; // echo time - float flEchoDepth; // echo depth - float flModulationTime; // modulation time - float flModulationDepth; // modulation depth - float flAirAbsorptionHF; // change in level per meter at high frequencies - float flHFReference; // reference high frequency - float flLFReference; // reference low frequency - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - unsigned long ulFlags; // modifies the behavior of properties -} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_UNDEFINED, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time -#define EAXLISTENERFLAGS_ECHOTIMESCALE 0x00000040 // echo time -#define EAXLISTENERFLAGS_MODULATIONTIMESCALE 0x00000080 // modulation time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFF00 // reserved future use - -// Property ranges and defaults: - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINROOM (-10000) -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM (-1000) - -#define EAXLISTENER_MINROOMHF (-10000) -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF (-100) - -#define EAXLISTENER_MINROOMLF (-10000) -#define EAXLISTENER_MAXROOMLF 0 -#define EAXLISTENER_DEFAULTROOMLF 0 - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINDECAYLFRATIO 0.1f -#define EAXLISTENER_MAXDECAYLFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYLFRATIO 1.00f - -#define EAXLISTENER_MINREFLECTIONS (-10000) -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS (-2602) - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB (-10000) -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINECHOTIME 0.075f -#define EAXLISTENER_MAXECHOTIME 0.25f -#define EAXLISTENER_DEFAULTECHOTIME 0.25f - -#define EAXLISTENER_MINECHODEPTH 0.0f -#define EAXLISTENER_MAXECHODEPTH 1.0f -#define EAXLISTENER_DEFAULTECHODEPTH 0.0f - -#define EAXLISTENER_MINMODULATIONTIME 0.04f -#define EAXLISTENER_MAXMODULATIONTIME 4.0f -#define EAXLISTENER_DEFAULTMODULATIONTIME 0.25f - -#define EAXLISTENER_MINMODULATIONDEPTH 0.0f -#define EAXLISTENER_MAXMODULATIONDEPTH 1.0f -#define EAXLISTENER_DEFAULTMODULATIONDEPTH 0.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f) -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f) - -#define EAXLISTENER_MINHFREFERENCE 1000.0f -#define EAXLISTENER_MAXHFREFERENCE 20000.0f -#define EAXLISTENER_DEFAULTHFREFERENCE 5000.0f - -#define EAXLISTENER_MINLFREFERENCE 20.0f -#define EAXLISTENER_MAXLFREFERENCE 1000.0f -#define EAXLISTENER_DEFAULTLFREFERENCE 250.0f - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \ - EAXLISTENERFLAGS_REFLECTIONSSCALE | \ - EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | \ - EAXLISTENERFLAGS_REVERBDELAYSCALE | \ - EAXLISTENERFLAGS_DECAYHFLIMIT) - - - -/* -* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87} -*/ -DEFINE_GUID(DSPROPSETID_EAX30_BufferProperties, - 0xa8fa6881, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties -#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties - -typedef enum -{ - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS, - DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, - DSPROPERTY_EAXBUFFER_EXCLUSION, - DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, - DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -} DSPROPERTY_EAX_BUFFERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \ - DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -typedef struct _EAXBUFFERPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // relative occlusion control for room effect - float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) - float flExclusionLFRatio; // exclusion low-frequency level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flDopplerFactor; // like DS3D flDopplerFactor but per source - float flRolloffFactor; // like DS3D flRolloffFactor but per source - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long ulFlags; // modifies the behavior of properties -} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION, -typedef struct _EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION -typedef struct _EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION -typedef struct _EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// Property ranges and defaults: - -#define EAXBUFFER_MINDIRECT (-10000) -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF (-10000) -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM (-10000) -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF (-10000) -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINOBSTRUCTION (-10000) -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION (-10000) -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 1.5f - -#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO 1.0f - -#define EAXBUFFER_MINEXCLUSION (-10000) -#define EAXBUFFER_MAXEXCLUSION 0 -#define EAXBUFFER_DEFAULTEXCLUSION 0 - -#define EAXBUFFER_MINEXCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXEXCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO 1.0f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000) -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINDOPPLERFACTOR 0.0f -#define EAXBUFFER_MAXDOPPLERFACTOR 10.f -#define EAXBUFFER_DEFAULTDOPPLERFACTOR 0.0f - -#define EAXBUFFER_MINROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \ - EAXBUFFERFLAGS_ROOMAUTO | \ - EAXBUFFERFLAGS_ROOMHFAUTO ) - -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif // __cplusplus - -#endif diff --git a/Engine/lib/openal/macCarb/al/eax_func.h b/Engine/lib/openal/macCarb/al/eax_func.h deleted file mode 100644 index 8c36c7471..000000000 --- a/Engine/lib/openal/macCarb/al/eax_func.h +++ /dev/null @@ -1,3 +0,0 @@ - -AL_FUNCTION(ALenum, EAXSet, (const ALGUID*, ALuint, ALuint, ALvoid*, ALuint), return 0; ) -AL_FUNCTION(ALenum, EAXGet, (const ALGUID*, ALuint, ALuint, ALvoid*, ALuint), return 0; ) diff --git a/Engine/lib/openal/macCarb/al/eaxtypes.h b/Engine/lib/openal/macCarb/al/eaxtypes.h deleted file mode 100644 index 15ba59afc..000000000 --- a/Engine/lib/openal/macCarb/al/eaxtypes.h +++ /dev/null @@ -1,462 +0,0 @@ - - -typedef struct _ALGUID -{ - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -}ALGUID; - -#ifndef INITGUID - #define DEFINE_ALGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const ALGUID name -#else - #define DEFINE_ALGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const ALGUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } -#endif // INITGUID - - - -/* - * EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87} - */ -DEFINE_ALGUID(DSPROPSETID_EAX30_ListenerProperties, - 0xa8fa6882, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties - -typedef enum -{ - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMLF, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_DECAYLFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REFLECTIONSPAN, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_REVERBPAN, - DSPROPERTY_EAXLISTENER_ECHOTIME, - DSPROPERTY_EAXLISTENER_ECHODEPTH, - DSPROPERTY_EAXLISTENER_MODULATIONTIME, - DSPROPERTY_EAXLISTENER_MODULATIONDEPTH, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_HFREFERENCE, - DSPROPERTY_EAXLISTENER_LFREFERENCE, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_FLAGS -} DSPROPERTY_EAX_LISTENERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \ - DSPROPERTY_EAXLISTENER_IMMEDIATE) - -typedef struct _EAXVECTOR { - float x; - float y; - float z; -} EAXVECTOR; - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times and delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -typedef struct _EAXLISTENERPROPERTIES -{ - unsigned long ulEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - long lRoom; // room effect level (at mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lRoomLF; // relative room effect level at low frequencies - float flDecayTime; // reverberation decay time at mid frequencies - float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio - float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - EAXVECTOR vReflectionsPan; // early reflections panning vector - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - EAXVECTOR vReverbPan; // late reverberation panning vector - float flEchoTime; // echo time - float flEchoDepth; // echo depth - float flModulationTime; // modulation time - float flModulationDepth; // modulation depth - float flAirAbsorptionHF; // change in level per meter at high frequencies - float flHFReference; // reference high frequency - float flLFReference; // reference low frequency - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - unsigned long ulFlags; // modifies the behavior of properties -} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_UNDEFINED, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time -#define EAXLISTENERFLAGS_ECHOTIMESCALE 0x00000040 // echo time -#define EAXLISTENERFLAGS_MODULATIONTIMESCALE 0x00000080 // modulation time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFF00 // reserved future use - -// Property ranges and defaults: - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINROOM (-10000) -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM (-1000) - -#define EAXLISTENER_MINROOMHF (-10000) -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF (-100) - -#define EAXLISTENER_MINROOMLF (-10000) -#define EAXLISTENER_MAXROOMLF 0 -#define EAXLISTENER_DEFAULTROOMLF 0 - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINDECAYLFRATIO 0.1f -#define EAXLISTENER_MAXDECAYLFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYLFRATIO 1.00f - -#define EAXLISTENER_MINREFLECTIONS (-10000) -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS (-2602) - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB (-10000) -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINECHOTIME 0.075f -#define EAXLISTENER_MAXECHOTIME 0.25f -#define EAXLISTENER_DEFAULTECHOTIME 0.25f - -#define EAXLISTENER_MINECHODEPTH 0.0f -#define EAXLISTENER_MAXECHODEPTH 1.0f -#define EAXLISTENER_DEFAULTECHODEPTH 0.0f - -#define EAXLISTENER_MINMODULATIONTIME 0.04f -#define EAXLISTENER_MAXMODULATIONTIME 4.0f -#define EAXLISTENER_DEFAULTMODULATIONTIME 0.25f - -#define EAXLISTENER_MINMODULATIONDEPTH 0.0f -#define EAXLISTENER_MAXMODULATIONDEPTH 1.0f -#define EAXLISTENER_DEFAULTMODULATIONDEPTH 0.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f) -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f) - -#define EAXLISTENER_MINHFREFERENCE 1000.0f -#define EAXLISTENER_MAXHFREFERENCE 20000.0f -#define EAXLISTENER_DEFAULTHFREFERENCE 5000.0f - -#define EAXLISTENER_MINLFREFERENCE 20.0f -#define EAXLISTENER_MAXLFREFERENCE 1000.0f -#define EAXLISTENER_DEFAULTLFREFERENCE 250.0f - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \ - EAXLISTENERFLAGS_REFLECTIONSSCALE | \ - EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | \ - EAXLISTENERFLAGS_REVERBDELAYSCALE | \ - EAXLISTENERFLAGS_DECAYHFLIMIT) - - - -/* -* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87} -*/ -DEFINE_ALGUID(DSPROPSETID_EAX30_BufferProperties, - 0xa8fa6881, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties -#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties - -typedef enum -{ - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS, - DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, - DSPROPERTY_EAXBUFFER_EXCLUSION, - DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, - DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -} DSPROPERTY_EAX_BUFFERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \ - DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -typedef struct _EAXBUFFERPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // relative occlusion control for room effect - float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) - float flExclusionLFRatio; // exclusion low-frequency level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flDopplerFactor; // like DS3D flDopplerFactor but per source - float flRolloffFactor; // like DS3D flRolloffFactor but per source - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long ulFlags; // modifies the behavior of properties -} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION, -typedef struct _EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION -typedef struct _EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION -typedef struct _EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// Property ranges and defaults: - -#define EAXBUFFER_MINDIRECT (-10000) -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF (-10000) -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM (-10000) -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF (-10000) -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINOBSTRUCTION (-10000) -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION (-10000) -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 1.5f - -#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO 1.0f - -#define EAXBUFFER_MINEXCLUSION (-10000) -#define EAXBUFFER_MAXEXCLUSION 0 -#define EAXBUFFER_DEFAULTEXCLUSION 0 - -#define EAXBUFFER_MINEXCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXEXCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO 1.0f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000) -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINDOPPLERFACTOR 0.0f -#define EAXBUFFER_MAXDOPPLERFACTOR 10.f -#define EAXBUFFER_DEFAULTDOPPLERFACTOR 0.0f - -#define EAXBUFFER_MINROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \ - EAXBUFFERFLAGS_ROOMAUTO | \ - EAXBUFFERFLAGS_ROOMHFAUTO ) diff --git a/Engine/lib/openal/macCarb/openALFn.h b/Engine/lib/openal/macCarb/openALFn.h deleted file mode 100644 index 0061ec502..000000000 --- a/Engine/lib/openal/macCarb/openALFn.h +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef AL_FUNCTION -#define AL_FUNCTION(fn_name) -#endif - -// AL Functions -AL_FUNCTION( alEnable ); -AL_FUNCTION( alDisable ); -AL_FUNCTION( alIsEnabled ); -AL_FUNCTION( alHint ); -AL_FUNCTION( alGetBoolean ); -AL_FUNCTION( alGetInteger ); -AL_FUNCTION( alGetFloat ); -AL_FUNCTION( alGetDouble ); -AL_FUNCTION( alGetBooleanv ); -AL_FUNCTION( alGetIntegerv ); -AL_FUNCTION( alGetFloatv ); -AL_FUNCTION( alGetDoublev ); -AL_FUNCTION( alGetString ); -AL_FUNCTION( alGetError ); -AL_FUNCTION( alIsExtensionPresent ); -AL_FUNCTION( alGetProcAddress ); -AL_FUNCTION( alGetEnumValue ); -AL_FUNCTION( alListeneri ); -AL_FUNCTION( alListenerf ); -AL_FUNCTION( alListener3f ); -AL_FUNCTION( alListenerfv ); -AL_FUNCTION( alGetListeneri ); -AL_FUNCTION( alGetListenerf ); -AL_FUNCTION( alGetListener3f ); -AL_FUNCTION( alGetListenerfv ); -AL_FUNCTION( alGenSources ); -AL_FUNCTION( alDeleteSources ); -AL_FUNCTION( alIsSource ); -AL_FUNCTION( alSourcei ); -AL_FUNCTION( alSourcef ); -AL_FUNCTION( alSource3f ); -AL_FUNCTION( alSourcefv ); -AL_FUNCTION( alGetSourcei ); -AL_FUNCTION( alGetSourcef ); -AL_FUNCTION( alGetSource3f ); -AL_FUNCTION( alGetSourcefv ); -AL_FUNCTION( alSourcePlayv ); -AL_FUNCTION( alSourcePausev ); -AL_FUNCTION( alSourceStopv ); -AL_FUNCTION( alSourceRewindv ); -AL_FUNCTION( alSourcePlay ); -AL_FUNCTION( alSourcePause ); -AL_FUNCTION( alSourceStop ); -AL_FUNCTION( alSourceRewind ); -AL_FUNCTION( alGenBuffers ); -AL_FUNCTION( alDeleteBuffers ); -AL_FUNCTION( alIsBuffer ); -AL_FUNCTION( alBufferData ); -AL_FUNCTION( alGetBufferi ); -AL_FUNCTION( alGetBufferf ); -AL_FUNCTION( alSourceQueueBuffers ); -AL_FUNCTION( alSourceUnqueueBuffers ); -AL_FUNCTION( alDistanceModel ); -AL_FUNCTION( alDopplerFactor ); -AL_FUNCTION( alDopplerVelocity ); - -// ALC Functions -AL_FUNCTION( alcGetString ); -AL_FUNCTION( alcGetIntegerv ); -AL_FUNCTION( alcOpenDevice ); -AL_FUNCTION( alcCloseDevice ); -AL_FUNCTION( alcCreateContext ); -AL_FUNCTION( alcMakeContextCurrent ); -AL_FUNCTION( alcProcessContext ); -AL_FUNCTION( alcGetCurrentContext ); -AL_FUNCTION( alcGetContextsDevice ); -AL_FUNCTION( alcSuspendContext ); -AL_FUNCTION( alcDestroyContext ); -AL_FUNCTION( alcGetError ); -AL_FUNCTION( alcIsExtensionPresent ); -AL_FUNCTION( alcGetProcAddress ); -AL_FUNCTION( alcGetEnumValue ); - - -#undef AL_FUNCTION diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Headers b/Engine/lib/openal/macosx/OpenAL.framework/Headers deleted file mode 100644 index e1e95c912..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Headers +++ /dev/null @@ -1 +0,0 @@ -link Versions/Current/Headers/ \ No newline at end of file diff --git a/Engine/lib/openal/macosx/OpenAL.framework/OpenAL b/Engine/lib/openal/macosx/OpenAL.framework/OpenAL deleted file mode 100644 index f960e8d7e..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/OpenAL +++ /dev/null @@ -1 +0,0 @@ -link Versions/Current/OpenAL \ No newline at end of file diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Resources b/Engine/lib/openal/macosx/OpenAL.framework/Resources deleted file mode 100644 index 73f3c1806..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Resources +++ /dev/null @@ -1 +0,0 @@ -link Versions/Current/Resources/ \ No newline at end of file diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/al.h b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/al.h deleted file mode 100644 index 1e7a8bd80..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/al.h +++ /dev/null @@ -1,498 +0,0 @@ -#ifndef _AL_H_ -#define _AL_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 "altypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - #ifdef _LIB - #define ALAPI __declspec(dllexport) - #else - #define ALAPI __declspec(dllimport) - #endif - #define ALAPIENTRY __cdecl - #define AL_CALLBACK -#else - #ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif - #endif - #define ALAPI - #define ALAPIENTRY - #define AL_CALLBACK -#endif - -#define OPENAL - -#ifndef AL_NO_PROTOTYPES - -/** - * OpenAL Maintenance Functions - * Initialization and exiting. - * State Management and Query. - * Error Handling. - * Extension Support. - */ - -/** State management. */ -ALAPI ALvoid ALAPIENTRY alEnable( ALenum capability ); -ALAPI ALvoid ALAPIENTRY alDisable( ALenum capability ); -ALAPI ALboolean ALAPIENTRY alIsEnabled( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI ALvoid ALAPIENTRY alHint( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY alGetBoolean( ALenum param ); -ALAPI ALint ALAPIENTRY alGetInteger( ALenum param ); -ALAPI ALfloat ALAPIENTRY alGetFloat( ALenum param ); -ALAPI ALdouble ALAPIENTRY alGetDouble( ALenum param ); -ALAPI ALvoid ALAPIENTRY alGetBooleanv( ALenum param, ALboolean* data ); -ALAPI ALvoid ALAPIENTRY alGetIntegerv( ALenum param, ALint* data ); -ALAPI ALvoid ALAPIENTRY alGetFloatv( ALenum param, ALfloat* data ); -ALAPI ALvoid ALAPIENTRY alGetDoublev( ALenum param, ALdouble* data ); -ALAPI ALubyte* ALAPIENTRY alGetString( ALenum param ); - -ALAPI ALvoid ALAPIENTRY alSetInteger( ALenum pname, ALint value ); -ALAPI ALvoid ALAPIENTRY alSetDouble( ALenum pname, ALdouble value ); - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY alGetError( void ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY alIsExtensionPresent( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALvoid* ALAPIENTRY alGetProcAddress( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY alGetEnumValue( ALubyte* ename ); - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Environment: default 0. - */ -ALAPI ALvoid ALAPIENTRY alListeneri( ALenum param, ALint value ); - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI ALvoid ALAPIENTRY alListenerf( ALenum param, ALfloat value ); - - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI ALvoid ALAPIENTRY alListener3f( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); - - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI ALvoid ALAPIENTRY alListenerfv( ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY alGetListeneri( ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetListenerf( ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY alGetListener3f( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY alGetListenerfv( ALenum param, ALfloat* values ); - - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI ALvoid ALAPIENTRY alGenSources( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI ALvoid ALAPIENTRY alDeleteSources( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY alIsSource( ALuint id ); - -/** Set an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY alSourcei( ALuint source, ALenum param, ALint value ); -ALAPI ALvoid ALAPIENTRY alSourcef( ALuint source, ALenum param, ALfloat value ); -ALAPI ALvoid ALAPIENTRY alSource3f( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI ALvoid ALAPIENTRY alSourcefv( ALuint source, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY alGetSourcei( ALuint source, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetSourcef( ALuint source, ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY alGetSource3f( ALuint source, ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY alGetSourcefv( ALuint source, ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY alSourcePlayv( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourcePausev( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourceStopv( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY alSourceRewindv(ALsizei n,ALuint *sources); - -/** Activate a source, start replay. */ -ALAPI ALvoid ALAPIENTRY alSourcePlay( ALuint source ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI ALvoid ALAPIENTRY alSourcePause( ALuint source ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI ALvoid ALAPIENTRY alSourceStop( ALuint source ); - -/** - * Rewinds a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - */ -ALAPI ALvoid ALAPIENTRY alSourceRewind( ALuint source ); - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI ALvoid ALAPIENTRY alGenBuffers( ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY alDeleteBuffers( ALsizei n, ALuint* buffers ); -ALAPI ALboolean ALAPIENTRY alIsBuffer( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI ALvoid ALAPIENTRY alBufferData( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - - -ALAPI ALvoid ALAPIENTRY alGetBufferi( ALuint buffer, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY alGetBufferf( ALuint buffer, ALenum param, ALfloat* value ); - - - - -/** - * Queue stuff - */ - -ALAPI ALvoid ALAPIENTRY alSourceQueueBuffers( ALuint source, ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers ); - -/** - * Knobs and dials - */ -ALAPI ALvoid ALAPIENTRY alDistanceModel( ALenum value ); -ALAPI ALvoid ALAPIENTRY alDopplerFactor( ALfloat value ); -ALAPI ALvoid ALAPIENTRY alDopplerVelocity( ALfloat value ); - -#else /* AL_NO_PROTOTYPES */ - -/** - * OpenAL Maintenance Functions - * Initialization and exiting. - * State Management and Query. - * Error Handling. - * Extension Support. - */ - -/** State management. */ -ALAPI ALvoid ALAPIENTRY (*alEnable)( ALenum capability ); -ALAPI ALvoid ALAPIENTRY (*alDisable)( ALenum capability ); -ALAPI ALboolean ALAPIENTRY (*alIsEnabled)( ALenum capability ); - -/** Application preferences for driver performance choices. */ -ALAPI ALvoid ALAPIENTRY (*alHint)( ALenum target, ALenum mode ); - -/** State retrieval. */ -ALAPI ALboolean ALAPIENTRY (*alGetBoolean)( ALenum param ); -ALAPI ALint ALAPIENTRY (*alGetInteger)( ALenum param ); -ALAPI ALfloat ALAPIENTRY (*alGetFloat)( ALenum param ); -ALAPI ALdouble ALAPIENTRY (*alGetDouble)( ALenum param ); -ALAPI ALvoid ALAPIENTRY (*alGetBooleanv)( ALenum param, ALboolean* data ); -ALAPI ALvoid ALAPIENTRY (*alGetIntegerv)( ALenum param, ALint* data ); -ALAPI ALvoid ALAPIENTRY (*alGetFloatv)( ALenum param, ALfloat* data ); -ALAPI ALvoid ALAPIENTRY (*alGetDoublev)( ALenum param, ALdouble* data ); -ALAPI ALubyte* ALAPIENTRY (*alGetString)( ALenum param ); - -ALAPI ALvoid ALAPIENTRY (*alSetInteger)( ALenum pname, ALint value ); -ALAPI ALvoid ALAPIENTRY (*alSetDouble)( ALenum pname, ALdouble value ); - -/** - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -ALAPI ALenum ALAPIENTRY (*alGetError)( ALvoid ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALboolean ALAPIENTRY (*alIsExtensionPresent)( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the address of a function (usually an extension) - * with the name fname. All addresses are context-independent. - */ -ALAPI ALvoid* ALAPIENTRY (*alGetProcAddress)( ALubyte* fname ); - - -/** - * Extension support. - * Obtain the integer value of an enumeration (usually an extension) with the name ename. - */ -ALAPI ALenum ALAPIENTRY (*alGetEnumValue)( ALubyte* ename ); - - - - -/** - * LISTENER - * Listener is the sample position for a given context. - * The multi-channel (usually stereo) output stream generated - * by the mixer is parametrized by this Listener object: - * its position and velocity relative to Sources, within - * occluder and reflector geometry. - */ - - - -/** - * - * Listener Environment: default 0. - */ -ALAPI ALvoid ALAPIENTRY (*alListeneri)( ALenum param, ALint value ); - - -/** - * - * Listener Gain: default 1.0f. - */ -ALAPI ALvoid ALAPIENTRY (*alListenerf)( ALenum param, ALfloat value ); - - -/** - * - * Listener Position. - * Listener Velocity. - */ -ALAPI ALvoid ALAPIENTRY (*alListener3f)( ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); - - -/** - * - * Listener Position: ALfloat[3] - * Listener Velocity: ALfloat[3] - * Listener Orientation: ALfloat[6] (forward and up vector). - */ -ALAPI ALvoid ALAPIENTRY (*alListenerfv)( ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY (*alGetListeneri)( ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetListenerf)( ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY (*alGetListener3f)( ALenum param, ALfloat* v1, ALfloat* v2, ALfloat* v3 ); -ALAPI ALvoid ALAPIENTRY (*alGetListenerfv)( ALenum param, ALfloat* values ); - - -/** - * SOURCE - * Source objects are by default localized. Sources - * take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial - * arrangement etc. - */ - - - -/** Create Source objects. */ -ALAPI ALvoid ALAPIENTRY (*alGenSources)( ALsizei n, ALuint* sources ); - -/** Delete Source objects. */ -ALAPI ALvoid ALAPIENTRY (*alDeleteSources)( ALsizei n, ALuint* sources ); - -/** Verify a handle is a valid Source. */ -ALAPI ALboolean ALAPIENTRY (*alIsSource)( ALuint id ); - -/** Set an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY (*alSourcei)( ALuint source, ALenum param, ALint value ); -ALAPI ALvoid ALAPIENTRY (*alSourcef)( ALuint source, ALenum param, ALfloat value ); -ALAPI ALvoid ALAPIENTRY (*alSource3f)( ALuint source, ALenum param, ALfloat v1, ALfloat v2, ALfloat v3 ); -ALAPI ALvoid ALAPIENTRY (*alSourcefv)( ALuint source, ALenum param, ALfloat* values ); - -/** Get an integer parameter for a Source object. */ -ALAPI ALvoid ALAPIENTRY (*alGetSourcei)( ALuint source, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetSourcef)( ALuint source, ALenum param, ALfloat* value ); -ALAPI ALvoid ALAPIENTRY (*alGetSourcefv)( ALuint source, ALenum param, ALfloat* values ); - -ALAPI ALvoid ALAPIENTRY (*alSourcePlayv)( ALsizei n, ALuint *sources ); -ALAPI ALvoid ALAPIENTRY (*alSourceStopv)( ALsizei n, ALuint *sources ); - -/** Activate a source, start replay. */ -ALAPI ALvoid ALAPIENTRY (*alSourcePlay)( ALuint source ); - -/** - * Pause a source, - * temporarily remove it from the mixer list. - */ -ALAPI ALvoid ALAPIENTRY (*alSourcePause)( ALuint source ); - -/** - * Stop a source, - * temporarily remove it from the mixer list, - * and reset its internal state to pre-Play. - * To remove a Source completely, it has to be - * deleted following Stop, or before Play. - */ -ALAPI ALvoid ALAPIENTRY (*alSourceStop)( ALuint source ); - - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. There can be more than - * one Source using the same Buffer data. If Buffers have - * to be duplicated on a per-Source basis, the driver has to - * take care of allocation, copying, and deallocation as well - * as propagating buffer data changes. - */ - - - - -/** Buffer object generation. */ -ALAPI ALvoid ALAPIENTRY (*alGenBuffers)( ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY (*alDeleteBuffers)( ALsizei n, ALuint* buffers ); -ALAPI ALboolean ALAPIENTRY (*alIsBuffer)( ALuint buffer ); - -/** - * Specify the data to be filled into a buffer. - */ -ALAPI ALvoid ALAPIENTRY (*alBufferData)( ALuint buffer, - ALenum format, - ALvoid* data, - ALsizei size, - ALsizei freq ); - -ALAPI ALvoid ALAPIENTRY (*alGetBufferi)( ALuint buffer, ALenum param, ALint* value ); -ALAPI ALvoid ALAPIENTRY (*alGetBufferf)( ALuint buffer, ALenum param, ALfloat* value ); - - - - -/** - * Queue stuff - */ -ALAPI ALvoid ALAPIENTRY (*alSourceQueueBuffers)( ALuint source, ALsizei n, ALuint* buffers ); -ALAPI ALvoid ALAPIENTRY (*alSourceUnqueueBuffers)( ALuint source, ALsizei n, ALuint* buffers ); - -/** - * Knobs and dials - */ -ALAPI ALvoid ALAPIENTRY (*alDistanceModel)( ALenum value ); -ALAPI ALvoid ALAPIENTRY (*alDopplerFactor)( ALfloat value ); -ALAPI ALvoid ALAPIENTRY (*alDopplerVelocity)( ALfloat value ); - - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alc.h b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alc.h deleted file mode 100644 index 62601d1d2..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alc.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef _ALC_H_ -#define _ALC_H_ - -#include "altypes.h" -#include "alctypes.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 - #ifdef _LIB - #define ALCAPI __declspec(dllexport) - #else - #define ALCAPI __declspec(dllimport) - typedef ALCvoid ALCdevice; - typedef ALCvoid ALCcontext; - #endif - #define ALCAPIENTRY __cdecl -#else - #ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif - #endif - #define ALCAPI - #define ALCAPIENTRY - typedef ALCvoid ALCdevice; - typedef ALCvoid ALCcontext; -#endif - -#ifndef ALC_NO_PROTOTYPES - -ALCAPI ALCubyte* ALCAPIENTRY alcGetString(ALCdevice *device,ALCenum param); -ALCAPI ALCvoid ALCAPIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALCsizei size,ALCint *data); - -ALCAPI ALCdevice* ALCAPIENTRY alcOpenDevice(ALCubyte *deviceName); -ALCAPI ALCvoid ALCAPIENTRY alcCloseDevice(ALCdevice *device); - -ALCAPI ALCcontext*ALCAPIENTRY alcCreateContext(ALCdevice *device,ALCint *attrList); -ALCAPI ALCboolean ALCAPIENTRY alcMakeContextCurrent(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcProcessContext(ALCcontext *context); -ALCAPI ALCcontext*ALCAPIENTRY alcGetCurrentContext(void); -ALCAPI ALCdevice* ALCAPIENTRY alcGetContextsDevice(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcSuspendContext(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY alcDestroyContext(ALCcontext *context); - -ALCAPI ALCenum ALCAPIENTRY alcGetError(ALCdevice *device); - -ALCAPI ALCboolean ALCAPIENTRY alcIsExtensionPresent(ALCdevice *device,ALCubyte *extName); -ALCAPI ALCvoid * ALCAPIENTRY alcGetProcAddress(ALCdevice *device,ALCubyte *funcName); -ALCAPI ALCenum ALCAPIENTRY alcGetEnumValue(ALCdevice *device,ALCubyte *enumName); - -#else /* AL_NO_PROTOTYPES */ - -ALCAPI ALCubyte* ALCAPIENTRY (*alcGetString)(ALCdevice *device,ALCenum param); -ALCAPI ALCvoid ALCAPIENTRY (*alcGetIntegerv)(ALCdevice * device,ALCenum param,ALCsizei size,ALCint *data); - -ALCAPI ALCdevice* ALCAPIENTRY (*alcOpenDevice)(ALubyte *deviceName); -ALCAPI ALCvoid ALCAPIENTRY (*alcCloseDevice)(ALCdevice *device); - -ALCAPI ALCcontext*ALCAPIENTRY (*alcCreateContext)(ALCdevice *device,ALCint *attrList); -ALCAPI ALCboolean ALCAPIENTRY (*alcMakeContextCurrent)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcProcessContext)(ALCcontext *context); -ALCAPI ALCcontext*ALCAPIENTRY (*alcGetCurrentContext)(ALCvoid); -ALCAPI ALCdevice* ALCAPIENTRY (*alcGetContextsDevice)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcSuspendContext)(ALCcontext *context); -ALCAPI ALCvoid ALCAPIENTRY (*alcDestroyContext)(ALCcontext *context); - -ALCAPI ALCenum ALCAPIENTRY (*alcGetError)(ALCdevice *device); - -ALCAPI ALCboolean ALCAPIENTRY (*alcIsExtensionPresent)(ALCdevice *device,ALCubyte *extName); -ALCAPI ALCvoid * ALCAPIENTRY (*alcGetProcAddress)(ALCdevice *device,ALCubyte *funcName); -ALCAPI ALCenum ALCAPIENTRY (*alcGetEnumValue)(ALCdevice *device,ALCubyte *enumName); - -#endif /* AL_NO_PROTOTYPES */ - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alctypes.h b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alctypes.h deleted file mode 100644 index 90364609d..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alctypes.h +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef _ALCTYPES_H_ -#define _ALCTYPES_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 by authors. - * Portions Copyright (C) 2004 by Apple Computer Inc. - * 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.1 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 __cplusplus -extern "C" { -#endif - -/** ALC boolean type. */ -typedef char ALCboolean; - -/** ALC 8bit signed byte. */ -typedef char ALCbyte; - -/** ALC 8bit unsigned byte. */ -typedef unsigned char ALCubyte; - -/** ALC 16bit signed short integer type. */ -typedef short ALCshort; - -/** ALC 16bit unsigned short integer type. */ -typedef unsigned short ALCushort; - -/** ALC 32bit unsigned integer type. */ -typedef unsigned ALCuint; - -/** ALC 32bit signed integer type. */ -typedef int ALCint; - -/** ALC 32bit floating point type. */ -typedef float ALCfloat; - -/** ALC 64bit double point type. */ -typedef double ALCdouble; - -/** ALC 32bit type. */ -typedef unsigned int ALCsizei; - -/** ALC void type */ -typedef void ALCvoid; - -/** ALC enumerations. */ -typedef int ALCenum; - -/* Bad value. */ -#define ALC_INVALID (-1) - -/* Boolean False. */ -#define ALC_FALSE 0 - -/* Boolean True. */ -#define ALC_TRUE 1 - -/** Errors: No Error. */ -#define ALC_NO_ERROR ALC_FALSE - -#define ALC_MAJOR_VERSION 0x1000 -#define ALC_MINOR_VERSION 0x1001 -#define ALC_ATTRIBUTES_SIZE 0x1002 -#define ALC_ALL_ATTRIBUTES 0x1003 - -#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 -#define ALC_DEVICE_SPECIFIER 0x1005 -#define ALC_EXTENSIONS 0x1006 - -#define ALC_FREQUENCY 0x1007 -#define ALC_REFRESH 0x1008 -#define ALC_SYNC 0x1009 - -/** - * The device argument does not name a valid dvice. - */ -#define ALC_INVALID_DEVICE 0xA001 - -/** - * The context argument does not name a valid context. - */ -#define ALC_INVALID_CONTEXT 0xA002 - -/** - * A function was called at inappropriate time, - * or in an inappropriate way, causing an illegal state. - * This can be an incompatible ALenum, object ID, - * and/or function. - */ -#define ALC_INVALID_ENUM 0xA003 - -/** - * Illegal value passed as an argument to an AL call. - * Applies to parameter values, but not to enumerations. - */ -#define ALC_INVALID_VALUE 0xA004 - -/** - * A function could not be completed, - * because there is not enough memory available. - */ -#define ALC_OUT_OF_MEMORY 0xA005 - - -//********************************************************************************* -// OSX Specific Properties -//********************************************************************************* - -/** - * Convert Data When Loading. Default false, currently applies only to monophonic sounds - */ -#define ALC_CONVERT_DATA_UPON_LOADING 0xF001 - -/** - * Render Quality. - */ -#define ALC_SPATIAL_RENDERING_QUALITY 0xF002 - #define ALC_SPATIAL_RENDERING_QUALITY_HIGH 'rqhi' - #define ALC_SPATIAL_RENDERING_QUALITY_LOW 'rdlo' - -/** - * Mixer Output Rate. - */ -#define ALC_MIXER_OUTPUT_RATE 0xF003 - -/** - * Maximum Mixer Busses. - * Set this before opening a new OAL device to indicate how many busses on the mixer - * are desired. Get returns either the current devices bus count value, or the value - * that will be used to open a device - */ -#define ALC_MIXER_MAXIMUM_BUSSES 0xF004 - -/** - * Render Channels. - * Allows a user to force OpenAL to render to stereo, regardless of the audio hardware being used - */ -#define ALC_RENDER_CHANNEL_COUNT 0xF005 - #define ALC_RENDER_CHANNEL_COUNT_STEREO 'rcst' - #define ALC_RENDER_CHANNEL_COUNT_MULTICHANNEL 'rcmc' - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/altypes.h b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/altypes.h deleted file mode 100644 index f15bcd351..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/altypes.h +++ /dev/null @@ -1,336 +0,0 @@ -#ifndef _ALTYPES_H_ -#define _ALTYPES_H_ - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 __cplusplus -extern "C" { -#endif - -/** OpenAL boolean type. */ -typedef char ALboolean; - -/** OpenAL 8bit signed byte. */ -typedef char ALbyte; - -/** OpenAL 8bit unsigned byte. */ -typedef unsigned char ALubyte; - -/** OpenAL 16bit signed short integer type. */ -typedef short ALshort; - -/** OpenAL 16bit unsigned short integer type. */ -typedef unsigned short ALushort; - -/** OpenAL 32bit unsigned integer type. */ -typedef unsigned ALuint; - -/** OpenAL 32bit signed integer type. */ -typedef int ALint; - -/** OpenAL 32bit floating point type. */ -typedef float ALfloat; - -/** OpenAL 64bit double point type. */ -typedef double ALdouble; - -/** OpenAL 32bit type. */ -typedef unsigned int ALsizei; - -/** OpenAL void type */ -typedef void ALvoid; - -/** OpenAL enumerations. */ -typedef int ALenum; - -/* Bad value. */ -#define AL_INVALID (-1) - -/* Disable value. */ -#define AL_NONE 0 - -/* Boolean False. */ -#define AL_FALSE 0 - -/* Boolean True. */ -#define AL_TRUE 1 - -/** - * Indicate the type of AL_SOURCE. - * Sources can be spatialized - */ -#define AL_SOURCE_TYPE 0x200 - -/** Indicate source has absolute coordinates. */ -#define AL_SOURCE_ABSOLUTE 0x201 - -/** Indicate Source has listener relative coordinates. */ -#define AL_SOURCE_RELATIVE 0x202 - -/** - * Directional source, inner cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_INNER_ANGLE 0x1001 - -/** - * Directional source, outer cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_OUTER_ANGLE 0x1002 - -/** - * Specify the pitch to be applied, either at source, - * or on mixer results, at listener. - * Range: [0.5-2.0] - * Default: 1.0 - */ -#define AL_PITCH 0x1003 - -/** - * Specify the current location in three dimensional space. - * OpenAL, like OpenGL, uses a right handed coordinate system, - * where in a frontal default view X (thumb) points right, - * Y points up (index finger), and Z points towards the - * viewer/camera (middle finger). - * To switch from a left handed coordinate system, flip the - * sign on the Z coordinate. - * Listener position is always in the world coordinate system. - */ -#define AL_POSITION 0x1004 - -/** Specify the current direction as forward vector. */ -#define AL_DIRECTION 0x1005 - -/** Specify the current velocity in three dimensional space. */ -#define AL_VELOCITY 0x1006 - -/** - * Indicate whether source has to loop infinite. - * Type: ALboolean - * Range: [AL_TRUE, AL_FALSE] - * Default: AL_FALSE - */ -#define AL_LOOPING 0x1007 - -/** - * Indicate the buffer to provide sound samples. - * Type: ALuint. - * Range: any valid Buffer id. - */ -#define AL_BUFFER 0x1009 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN 0x100A - -/** - * Indicate minimum source attenuation. - * Type: ALfloat - * Range: [0.0 - 1.0] - */ -#define AL_MIN_GAIN 0x100D - -/** - * Indicate maximum source attenuation. - * Type: ALfloat - * Range: [0.0 - 1.0] - */ -#define AL_MAX_GAIN 0x100E - -/** - * Specify the current orientation. - * Type: ALfv6 (at/up) - * Range: N/A - */ -#define AL_ORIENTATION 0x100F - -/* byte offset into source (in canon format). -1 if source - * is not playing. Don't set this, get this. - * - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - */ -#define AL_REFERENCE_DISTANCE 0x1020 - - /** - * Indicate the rolloff factor for the source. - * Type: ALfloat - * Range: [0.0 - ] - * Default: 1.0 - */ -#define AL_ROLLOFF_FACTOR 0x1021 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_CONE_OUTER_GAIN 0x1022 - -/** - * Specify the maximum distance. - * Type: ALfloat - * Range: [0.0 - ] - */ -#define AL_MAX_DISTANCE 0x1023 - -/** - * Source state information - */ -#define AL_SOURCE_STATE 0x1010 -#define AL_INITIAL 0x1011 -#define AL_PLAYING 0x1012 -#define AL_PAUSED 0x1013 -#define AL_STOPPED 0x1014 - -/** - * Buffer Queue params - */ -#define AL_BUFFERS_QUEUED 0x1015 -#define AL_BUFFERS_PROCESSED 0x1016 - -/** - * Source buffer position information - */ -#define AL_SEC_OFFSET 0x1024 -#define AL_SAMPLE_OFFSET 0x1025 -#define AL_BYTE_OFFSET 0x1026 - -/** Sound buffers: format specifier. */ -#define AL_FORMAT_MONO8 0x1100 -#define AL_FORMAT_MONO16 0x1101 -#define AL_FORMAT_STEREO8 0x1102 -#define AL_FORMAT_STEREO16 0x1103 - -/** - * Sound buffers: frequency, in units of Hertz [Hz]. - * This is the number of samples per second. Half of the - * sample frequency marks the maximum significant - * frequency component. - */ -#define AL_FREQUENCY 0x2001 -#define AL_BITS 0x2002 -#define AL_CHANNELS 0x2003 -#define AL_SIZE 0x2004 - -/** - * Buffer state. - * - * Not supported for public use (yet). - */ -#define AL_UNUSED 0x2010 -#define AL_PENDING 0x2011 -#define AL_PROCESSED 0x2012 - -/** Errors: No Error. */ -#define AL_NO_ERROR AL_FALSE - -/** - * Illegal name passed as an argument to an AL call. - */ -#define AL_INVALID_NAME 0xA001 - -/** - * Illegal enum passed as an argument to an AL call. - */ -#define AL_INVALID_ENUM 0xA002 -/** - * Illegal value passed as an argument to an AL call. - * Applies to parameter values, but not to enumerations. - */ -#define AL_INVALID_VALUE 0xA003 - -/** - * A function was called at inappropriate time, - * or in an inappropriate way, causing an illegal state. - * This can be an incompatible ALenum, object ID, - * and/or function. - */ -#define AL_INVALID_OPERATION 0xA004 - -/** - * A function could not be completed, - * because there is not enough memory available. - */ -#define AL_OUT_OF_MEMORY 0xA005 - -/** Context strings: Vendor Name. */ -#define AL_VENDOR 0xB001 -#define AL_VERSION 0xB002 -#define AL_RENDERER 0xB003 -#define AL_EXTENSIONS 0xB004 - -/** Global tweakage. */ - -/** - * Doppler scale. Default 1.0 - */ -#define AL_DOPPLER_FACTOR 0xC000 - -/** - * Doppler velocity. Default 1.0 - */ -#define AL_DOPPLER_VELOCITY 0xC001 - -/** - * Distance model. Default AL_INVERSE_DISTANCE_CLAMPED - */ -#define AL_DISTANCE_MODEL 0xD000 - -/** Distance models. */ - -#define AL_INVERSE_DISTANCE 0xD001 -#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 -#define AL_LINEAR_DISTANCE 0xD003 -#define AL_LINEAR_DISTANCE_CLAMPED 0xD004 -#define AL_EXPONENT_DISTANCE 0xD005 -#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 - - /** - * enables - */ - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alut.h b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alut.h deleted file mode 100644 index 0b1baea41..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/alut.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 - */ - -#ifndef _ALUT_H_ -#define _ALUT_H_ - -#define ALUTAPI -#define ALUTAPIENTRY - -#include "al.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export on - #endif -#endif - -ALUTAPI ALvoid ALUTAPIENTRY alutInit(ALint *argc,ALbyte **argv); -ALUTAPI ALvoid ALUTAPIENTRY alutExit(ALvoid); -ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVFile(ALbyte *file,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq); -ALUTAPI ALvoid ALUTAPIENTRY alutLoadWAVMemory(ALbyte *memory,ALenum *format,ALvoid **data,ALsizei *size,ALsizei *freq); -ALUTAPI ALvoid ALUTAPIENTRY alutUnloadWAV(ALenum format,ALvoid *data,ALsizei size,ALsizei freq); - -#ifdef TARGET_OS_MAC - #if TARGET_OS_MAC - #pragma export off - #endif -#endif - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/eaxtypes.h b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/eaxtypes.h deleted file mode 100644 index 15ba59afc..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Headers/eaxtypes.h +++ /dev/null @@ -1,462 +0,0 @@ - - -typedef struct _ALGUID -{ - unsigned long Data1; - unsigned short Data2; - unsigned short Data3; - unsigned char Data4[8]; -}ALGUID; - -#ifndef INITGUID - #define DEFINE_ALGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const ALGUID name -#else - #define DEFINE_ALGUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ - extern const ALGUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } -#endif // INITGUID - - - -/* - * EAX 3.0 listener property set {A8FA6880-B476-11d3-BDB9-00C0F02DDF87} - */ -DEFINE_ALGUID(DSPROPSETID_EAX30_ListenerProperties, - 0xa8fa6882, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x00, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_ListenerProperties DSPROPSETID_EAX30_ListenerProperties - -typedef enum -{ - DSPROPERTY_EAXLISTENER_NONE, - DSPROPERTY_EAXLISTENER_ALLPARAMETERS, - DSPROPERTY_EAXLISTENER_ENVIRONMENT, - DSPROPERTY_EAXLISTENER_ENVIRONMENTSIZE, - DSPROPERTY_EAXLISTENER_ENVIRONMENTDIFFUSION, - DSPROPERTY_EAXLISTENER_ROOM, - DSPROPERTY_EAXLISTENER_ROOMHF, - DSPROPERTY_EAXLISTENER_ROOMLF, - DSPROPERTY_EAXLISTENER_DECAYTIME, - DSPROPERTY_EAXLISTENER_DECAYHFRATIO, - DSPROPERTY_EAXLISTENER_DECAYLFRATIO, - DSPROPERTY_EAXLISTENER_REFLECTIONS, - DSPROPERTY_EAXLISTENER_REFLECTIONSDELAY, - DSPROPERTY_EAXLISTENER_REFLECTIONSPAN, - DSPROPERTY_EAXLISTENER_REVERB, - DSPROPERTY_EAXLISTENER_REVERBDELAY, - DSPROPERTY_EAXLISTENER_REVERBPAN, - DSPROPERTY_EAXLISTENER_ECHOTIME, - DSPROPERTY_EAXLISTENER_ECHODEPTH, - DSPROPERTY_EAXLISTENER_MODULATIONTIME, - DSPROPERTY_EAXLISTENER_MODULATIONDEPTH, - DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF, - DSPROPERTY_EAXLISTENER_HFREFERENCE, - DSPROPERTY_EAXLISTENER_LFREFERENCE, - DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXLISTENER_FLAGS -} DSPROPERTY_EAX_LISTENERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXLISTENER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXLISTENER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXLISTENER_NONE | \ - DSPROPERTY_EAXLISTENER_IMMEDIATE) - -typedef struct _EAXVECTOR { - float x; - float y; - float z; -} EAXVECTOR; - -// Use this structure for DSPROPERTY_EAXLISTENER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all times and delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myListener.lRoom = -1000; -// myListener.lRoomHF = -100; -// ... -// myListener.dwFlags = myFlags /* see EAXLISTENERFLAGS below */ ; -// instead of: -// myListener = { -1000, -100, ... , 0x00000009 }; -// If you want to save and load presets in binary form, you -// should define your own structure to insure future compatibility. -// -typedef struct _EAXLISTENERPROPERTIES -{ - unsigned long ulEnvironment; // sets all listener properties - float flEnvironmentSize; // environment size in meters - float flEnvironmentDiffusion; // environment diffusion - long lRoom; // room effect level (at mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lRoomLF; // relative room effect level at low frequencies - float flDecayTime; // reverberation decay time at mid frequencies - float flDecayHFRatio; // high-frequency to mid-frequency decay time ratio - float flDecayLFRatio; // low-frequency to mid-frequency decay time ratio - long lReflections; // early reflections level relative to room effect - float flReflectionsDelay; // initial reflection delay time - EAXVECTOR vReflectionsPan; // early reflections panning vector - long lReverb; // late reverberation level relative to room effect - float flReverbDelay; // late reverberation delay time relative to initial reflection - EAXVECTOR vReverbPan; // late reverberation panning vector - float flEchoTime; // echo time - float flEchoDepth; // echo depth - float flModulationTime; // modulation time - float flModulationDepth; // modulation depth - float flAirAbsorptionHF; // change in level per meter at high frequencies - float flHFReference; // reference high frequency - float flLFReference; // reference low frequency - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - unsigned long ulFlags; // modifies the behavior of properties -} EAXLISTENERPROPERTIES, *LPEAXLISTENERPROPERTIES; - -// used by DSPROPERTY_EAXLISTENER_ENVIRONMENT -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_UNDEFINED, - - EAX_ENVIRONMENT_COUNT -}; - -// Used by DSPROPERTY_EAXLISTENER_FLAGS -// -// Note: The number and order of flags may change in future EAX versions. -// It is recommended to use the flag defines as follows: -// myFlags = EAXLISTENERFLAGS_DECAYTIMESCALE | EAXLISTENERFLAGS_REVERBSCALE; -// instead of: -// myFlags = 0x00000009; -// -// These flags determine what properties are affected by environment size. -#define EAXLISTENERFLAGS_DECAYTIMESCALE 0x00000001 // reverberation decay time -#define EAXLISTENERFLAGS_REFLECTIONSSCALE 0x00000002 // reflection level -#define EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE 0x00000004 // initial reflection delay time -#define EAXLISTENERFLAGS_REVERBSCALE 0x00000008 // reflections level -#define EAXLISTENERFLAGS_REVERBDELAYSCALE 0x00000010 // late reverberation delay time -#define EAXLISTENERFLAGS_ECHOTIMESCALE 0x00000040 // echo time -#define EAXLISTENERFLAGS_MODULATIONTIMESCALE 0x00000080 // modulation time - -// This flag limits high-frequency decay time according to air absorption. -#define EAXLISTENERFLAGS_DECAYHFLIMIT 0x00000020 - -#define EAXLISTENERFLAGS_RESERVED 0xFFFFFF00 // reserved future use - -// Property ranges and defaults: - -#define EAXLISTENER_MINENVIRONMENT 0 -#define EAXLISTENER_MAXENVIRONMENT (EAX_ENVIRONMENT_COUNT-1) -#define EAXLISTENER_DEFAULTENVIRONMENT EAX_ENVIRONMENT_GENERIC - -#define EAXLISTENER_MINENVIRONMENTSIZE 1.0f -#define EAXLISTENER_MAXENVIRONMENTSIZE 100.0f -#define EAXLISTENER_DEFAULTENVIRONMENTSIZE 7.5f - -#define EAXLISTENER_MINENVIRONMENTDIFFUSION 0.0f -#define EAXLISTENER_MAXENVIRONMENTDIFFUSION 1.0f -#define EAXLISTENER_DEFAULTENVIRONMENTDIFFUSION 1.0f - -#define EAXLISTENER_MINROOM (-10000) -#define EAXLISTENER_MAXROOM 0 -#define EAXLISTENER_DEFAULTROOM (-1000) - -#define EAXLISTENER_MINROOMHF (-10000) -#define EAXLISTENER_MAXROOMHF 0 -#define EAXLISTENER_DEFAULTROOMHF (-100) - -#define EAXLISTENER_MINROOMLF (-10000) -#define EAXLISTENER_MAXROOMLF 0 -#define EAXLISTENER_DEFAULTROOMLF 0 - -#define EAXLISTENER_MINDECAYTIME 0.1f -#define EAXLISTENER_MAXDECAYTIME 20.0f -#define EAXLISTENER_DEFAULTDECAYTIME 1.49f - -#define EAXLISTENER_MINDECAYHFRATIO 0.1f -#define EAXLISTENER_MAXDECAYHFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYHFRATIO 0.83f - -#define EAXLISTENER_MINDECAYLFRATIO 0.1f -#define EAXLISTENER_MAXDECAYLFRATIO 2.0f -#define EAXLISTENER_DEFAULTDECAYLFRATIO 1.00f - -#define EAXLISTENER_MINREFLECTIONS (-10000) -#define EAXLISTENER_MAXREFLECTIONS 1000 -#define EAXLISTENER_DEFAULTREFLECTIONS (-2602) - -#define EAXLISTENER_MINREFLECTIONSDELAY 0.0f -#define EAXLISTENER_MAXREFLECTIONSDELAY 0.3f -#define EAXLISTENER_DEFAULTREFLECTIONSDELAY 0.007f - -#define EAXLISTENER_MINREVERB (-10000) -#define EAXLISTENER_MAXREVERB 2000 -#define EAXLISTENER_DEFAULTREVERB 200 - -#define EAXLISTENER_MINREVERBDELAY 0.0f -#define EAXLISTENER_MAXREVERBDELAY 0.1f -#define EAXLISTENER_DEFAULTREVERBDELAY 0.011f - -#define EAXLISTENER_MINECHOTIME 0.075f -#define EAXLISTENER_MAXECHOTIME 0.25f -#define EAXLISTENER_DEFAULTECHOTIME 0.25f - -#define EAXLISTENER_MINECHODEPTH 0.0f -#define EAXLISTENER_MAXECHODEPTH 1.0f -#define EAXLISTENER_DEFAULTECHODEPTH 0.0f - -#define EAXLISTENER_MINMODULATIONTIME 0.04f -#define EAXLISTENER_MAXMODULATIONTIME 4.0f -#define EAXLISTENER_DEFAULTMODULATIONTIME 0.25f - -#define EAXLISTENER_MINMODULATIONDEPTH 0.0f -#define EAXLISTENER_MAXMODULATIONDEPTH 1.0f -#define EAXLISTENER_DEFAULTMODULATIONDEPTH 0.0f - -#define EAXLISTENER_MINAIRABSORPTIONHF (-100.0f) -#define EAXLISTENER_MAXAIRABSORPTIONHF 0.0f -#define EAXLISTENER_DEFAULTAIRABSORPTIONHF (-5.0f) - -#define EAXLISTENER_MINHFREFERENCE 1000.0f -#define EAXLISTENER_MAXHFREFERENCE 20000.0f -#define EAXLISTENER_DEFAULTHFREFERENCE 5000.0f - -#define EAXLISTENER_MINLFREFERENCE 20.0f -#define EAXLISTENER_MAXLFREFERENCE 1000.0f -#define EAXLISTENER_DEFAULTLFREFERENCE 250.0f - -#define EAXLISTENER_MINROOMROLLOFFFACTOR 0.0f -#define EAXLISTENER_MAXROOMROLLOFFFACTOR 10.0f -#define EAXLISTENER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXLISTENER_DEFAULTFLAGS (EAXLISTENERFLAGS_DECAYTIMESCALE | \ - EAXLISTENERFLAGS_REFLECTIONSSCALE | \ - EAXLISTENERFLAGS_REFLECTIONSDELAYSCALE | \ - EAXLISTENERFLAGS_REVERBSCALE | \ - EAXLISTENERFLAGS_REVERBDELAYSCALE | \ - EAXLISTENERFLAGS_DECAYHFLIMIT) - - - -/* -* EAX 3.0 buffer property set {A8FA6881-B476-11d3-BDB9-00C0F02DDF87} -*/ -DEFINE_ALGUID(DSPROPSETID_EAX30_BufferProperties, - 0xa8fa6881, - 0xb476, - 0x11d3, - 0xbd, 0xb9, 0x0, 0xc0, 0xf0, 0x2d, 0xdf, 0x87); - -// For compatibility with future EAX versions: -#define DSPROPSETID_EAX_BufferProperties DSPROPSETID_EAX30_BufferProperties -#define DSPROPSETID_EAX_SourceProperties DSPROPSETID_EAX30_BufferProperties - -typedef enum -{ - DSPROPERTY_EAXBUFFER_NONE, - DSPROPERTY_EAXBUFFER_ALLPARAMETERS, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONPARAMETERS, - DSPROPERTY_EAXBUFFER_OCCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_EXCLUSIONPARAMETERS, - DSPROPERTY_EAXBUFFER_DIRECT, - DSPROPERTY_EAXBUFFER_DIRECTHF, - DSPROPERTY_EAXBUFFER_ROOM, - DSPROPERTY_EAXBUFFER_ROOMHF, - DSPROPERTY_EAXBUFFER_OBSTRUCTION, - DSPROPERTY_EAXBUFFER_OBSTRUCTIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSION, - DSPROPERTY_EAXBUFFER_OCCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONROOMRATIO, - DSPROPERTY_EAXBUFFER_OCCLUSIONDIRECTRATIO, - DSPROPERTY_EAXBUFFER_EXCLUSION, - DSPROPERTY_EAXBUFFER_EXCLUSIONLFRATIO, - DSPROPERTY_EAXBUFFER_OUTSIDEVOLUMEHF, - DSPROPERTY_EAXBUFFER_DOPPLERFACTOR, - DSPROPERTY_EAXBUFFER_ROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_ROOMROLLOFFFACTOR, - DSPROPERTY_EAXBUFFER_AIRABSORPTIONFACTOR, - DSPROPERTY_EAXBUFFER_FLAGS -} DSPROPERTY_EAX_BUFFERPROPERTY; - -// OR these flags with property id -#define DSPROPERTY_EAXBUFFER_IMMEDIATE 0x00000000 // changes take effect immediately -#define DSPROPERTY_EAXBUFFER_DEFERRED 0x80000000 // changes take effect later -#define DSPROPERTY_EAXBUFFER_COMMITDEFERREDSETTINGS (DSPROPERTY_EAXBUFFER_NONE | \ - DSPROPERTY_EAXBUFFER_IMMEDIATE) - -// Use this structure for DSPROPERTY_EAXBUFFER_ALLPARAMETERS -// - all levels are hundredths of decibels -// - all delays are in seconds -// -// NOTE: This structure may change in future EAX versions. -// It is recommended to initialize fields by name: -// myBuffer.lDirect = 0; -// myBuffer.lDirectHF = -200; -// ... -// myBuffer.dwFlags = myFlags /* see EAXBUFFERFLAGS below */ ; -// instead of: -// myBuffer = { 0, -200, ... , 0x00000003 }; -// -typedef struct _EAXBUFFERPROPERTIES -{ - long lDirect; // direct path level (at low and mid frequencies) - long lDirectHF; // relative direct path level at high frequencies - long lRoom; // room effect level (at low and mid frequencies) - long lRoomHF; // relative room effect level at high frequencies - long lObstruction; // main obstruction control (attenuation at high frequencies) - float flObstructionLFRatio; // obstruction low-frequency level re. main control - long lOcclusion; // main occlusion control (attenuation at high frequencies) - float flOcclusionLFRatio; // occlusion low-frequency level re. main control - float flOcclusionRoomRatio; // relative occlusion control for room effect - float flOcclusionDirectRatio; // relative occlusion control for direct path - long lExclusion; // main exlusion control (attenuation at high frequencies) - float flExclusionLFRatio; // exclusion low-frequency level re. main control - long lOutsideVolumeHF; // outside sound cone level at high frequencies - float flDopplerFactor; // like DS3D flDopplerFactor but per source - float flRolloffFactor; // like DS3D flRolloffFactor but per source - float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect - float flAirAbsorptionFactor; // multiplies DSPROPERTY_EAXLISTENER_AIRABSORPTIONHF - unsigned long ulFlags; // modifies the behavior of properties -} EAXBUFFERPROPERTIES, *LPEAXBUFFERPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OBSTRUCTION, -typedef struct _EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_OCCLUSION -typedef struct _EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; - -// Use this structure for DSPROPERTY_EAXBUFFER_EXCLUSION -typedef struct _EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; - -// Used by DSPROPERTY_EAXBUFFER_FLAGS -// TRUE: value is computed automatically - property is an offset -// FALSE: value is used directly -// -// Note: The number and order of flags may change in future EAX versions. -// To insure future compatibility, use flag defines as follows: -// myFlags = EAXBUFFERFLAGS_DIRECTHFAUTO | EAXBUFFERFLAGS_ROOMAUTO; -// instead of: -// myFlags = 0x00000003; -// -#define EAXBUFFERFLAGS_DIRECTHFAUTO 0x00000001 // affects DSPROPERTY_EAXBUFFER_DIRECTHF -#define EAXBUFFERFLAGS_ROOMAUTO 0x00000002 // affects DSPROPERTY_EAXBUFFER_ROOM -#define EAXBUFFERFLAGS_ROOMHFAUTO 0x00000004 // affects DSPROPERTY_EAXBUFFER_ROOMHF - -#define EAXBUFFERFLAGS_RESERVED 0xFFFFFFF8 // reserved future use - -// Property ranges and defaults: - -#define EAXBUFFER_MINDIRECT (-10000) -#define EAXBUFFER_MAXDIRECT 1000 -#define EAXBUFFER_DEFAULTDIRECT 0 - -#define EAXBUFFER_MINDIRECTHF (-10000) -#define EAXBUFFER_MAXDIRECTHF 0 -#define EAXBUFFER_DEFAULTDIRECTHF 0 - -#define EAXBUFFER_MINROOM (-10000) -#define EAXBUFFER_MAXROOM 1000 -#define EAXBUFFER_DEFAULTROOM 0 - -#define EAXBUFFER_MINROOMHF (-10000) -#define EAXBUFFER_MAXROOMHF 0 -#define EAXBUFFER_DEFAULTROOMHF 0 - -#define EAXBUFFER_MINOBSTRUCTION (-10000) -#define EAXBUFFER_MAXOBSTRUCTION 0 -#define EAXBUFFER_DEFAULTOBSTRUCTION 0 - -#define EAXBUFFER_MINOBSTRUCTIONLFRATIO 0.0f -#define EAXBUFFER_MAXOBSTRUCTIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOBSTRUCTIONLFRATIO 0.0f - -#define EAXBUFFER_MINOCCLUSION (-10000) -#define EAXBUFFER_MAXOCCLUSION 0 -#define EAXBUFFER_DEFAULTOCCLUSION 0 - -#define EAXBUFFER_MINOCCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTOCCLUSIONLFRATIO 0.25f - -#define EAXBUFFER_MINOCCLUSIONROOMRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONROOMRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONROOMRATIO 1.5f - -#define EAXBUFFER_MINOCCLUSIONDIRECTRATIO 0.0f -#define EAXBUFFER_MAXOCCLUSIONDIRECTRATIO 10.0f -#define EAXBUFFER_DEFAULTOCCLUSIONDIRECTRATIO 1.0f - -#define EAXBUFFER_MINEXCLUSION (-10000) -#define EAXBUFFER_MAXEXCLUSION 0 -#define EAXBUFFER_DEFAULTEXCLUSION 0 - -#define EAXBUFFER_MINEXCLUSIONLFRATIO 0.0f -#define EAXBUFFER_MAXEXCLUSIONLFRATIO 1.0f -#define EAXBUFFER_DEFAULTEXCLUSIONLFRATIO 1.0f - -#define EAXBUFFER_MINOUTSIDEVOLUMEHF (-10000) -#define EAXBUFFER_MAXOUTSIDEVOLUMEHF 0 -#define EAXBUFFER_DEFAULTOUTSIDEVOLUMEHF 0 - -#define EAXBUFFER_MINDOPPLERFACTOR 0.0f -#define EAXBUFFER_MAXDOPPLERFACTOR 10.f -#define EAXBUFFER_DEFAULTDOPPLERFACTOR 0.0f - -#define EAXBUFFER_MINROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINROOMROLLOFFFACTOR 0.0f -#define EAXBUFFER_MAXROOMROLLOFFFACTOR 10.f -#define EAXBUFFER_DEFAULTROOMROLLOFFFACTOR 0.0f - -#define EAXBUFFER_MINAIRABSORPTIONFACTOR 0.0f -#define EAXBUFFER_MAXAIRABSORPTIONFACTOR 10.0f -#define EAXBUFFER_DEFAULTAIRABSORPTIONFACTOR 1.0f - -#define EAXBUFFER_DEFAULTFLAGS (EAXBUFFERFLAGS_DIRECTHFAUTO | \ - EAXBUFFERFLAGS_ROOMAUTO | \ - EAXBUFFERFLAGS_ROOMHFAUTO ) diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/OpenAL b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/OpenAL deleted file mode 100644 index 40c63cbf6911e06e37ae317db64fd1df635fa5d8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 400924 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

lF;Ns+0O_fZTw z_j%O^U#>TSPPVB2J@rO}o+hH_sSU+rh@O9KlGy2Z#09x7=o=Hf+`Q7eFI1rFU3D(? z!BN5~=?G;mrLz+ql)2RDt^H|yYJ@GCxuCtG7SftPKn&DCXaKh{ez z3-}CCKel_77yvv0zn;fHLnXMIQZ4?{IxeaoR ze#u{w*yMyse}zwS9DTz#aiJdMT#r03*lxrzl{tc4VjnaSKBt8~ZzTVVd>q_&PDlpd zu7=G--Z@<(Jo^B@xR~jYZ+-#Kq$_KL9~@NH2#>sqwr1p5QF#jS)aTRj`&Exq$@d`r zPy^qFbi{5O^2i3JMJ3G{pbyRyExdb!L6ru1vG@(1isH9x1IMqd!EY__3q9|xWl0lY zAEPwu%28=X^Q3e|cicYTMeDvzVZXL(q)G#2P8Xp;=se*0-0XlodJZ&LjQG~9cdJQ9 zQ9ERhfb(JIpMnP0!~a_u>OmhG-=|yS|81``hsdet<8+32cKyj{Dm_;zfo3-d{ra5i#z*{6}%Q*tpL7qi9^@Upo0b z>e68@zbA>Gy1(Fhj^!T8ni2}t+&Icea}>as74>nuW<+JPYig7iKC?-zYXgk|{GiAt z#V%BSh`{Ly^$?tt_d)Y2?rXqyP|k*T|Ci@UX32&O4D*-AqcFc$PjrdEteHD%U{>Y$ zy_-~egMK)DOARk}pj2UhTuaZ=7ywxedKeY~sZehwz=wGL2E>&;Owv66ES_Iaeq`%lwEw)7*%q^m z=>6$*e=+II)(mP-Vm~T;w-$OqwOhy2!n&OFZtiSV?>>3)ti;|IqU}s=MLXg74Rl;@ zIeu$o{Dg-8PfX2mK*ozn7xsexPi%lM6ZW;0+_%2`ugMFdc)2>ytE9Xr@0));Pjj7t zdH=5(-aq#2mGl0wvBW3vlSm&{lOH0n9D0`!yw3_JG#cY=Yne}(+ZgFxpCmljl9_58 zg!?|6uMb$jXTp+IN**Xn$8W4fFImR@v2A#7%tAiwl0~ZTq~iMzud2Qm*Rezw8i!o> zCGdTso_w8v3x0YRW7K}2h;-|n0{W}yfBi?qD+T?p-?XtXcx5h`hpJR+OhmQ&|k#>*AL;k zqGw{BpFR`UHMBcNwAaw?=(#BEj&?_BcNVecKjeme4$Nsg!})qd!$`iK)ISf8)A4<7 zSM7?tonP$Q9+o%Z9SzN7IqrOgN;6p!I&b=WG(+ywa)mzs<5`71LNjEG;s%wVPx6FR zozAvea6zu<9S+1Ah0VC1fctGkzsyGCVE8keaec*vRO5}1!!n%LQI62OGMTT#U|#4T z8A9y1r0u&;TG}w53QjRV2O5(lHoXbY`{q3&vs~m`(LAT#i5xt7-o_kl?RXybgG;jT zyosJahvyv`*E7M^Boxkb$!xL%^`6I?mPe`AfcD!npR}|KsMjN*o``yPLKcM#KA%C` z5}OKo2)KR^a!QR!fFVhV=iie%AY|NowI4>hlobmZtE!LxW-pyyrRK854 zd@slvl#s^R_0xuPPqpDdK3H|C+5JZc>i;!8qdNQ_`HehwL;>-$@B4Dj^^98Hi5(2mwsrqgdDyoh)l4Y)rn9Q!oO;43fL zn;vRg;~N}_`2S`<$;Oef#hf2{Zo>I8Z>u`@Zo`@Z=zrN*3f`fL#8SvFX#3%qN=pz`F~toG;!@h~W!9H=KA#wGXN-|Ltkj4)vKY{TcJjBl}e!LgacZ z6+Q&!WWWpJqVOS>^1O$99v3M+R_*@IfokG0;1f2ORrJ69qefgW=zsmr&v9L2FFqu@ zqLIaScSdFL-B+Xb;zRhyhlfRMJ=W6u*?O%k_VdX;c3fT-KbE4h_*>!1aenC87@Tw6 zl{GUK=ZEGGEQ_BO0-n26oZByhbMP_VH-o<*?m!F>?{h0SpPq*69Or$muflbX^VsWm z4##y3&QJHzf4|k}zu)FYaef*y^xIVtoDbw*X>m^em7@O~id{Z?Hfon+e5pz~?rd29 zA;#bFHS}Lctp4M^)c7;8IRCH9=)X^(|9*QywbvJb^DLYTu-yd;{$bl|Sr6=>0X&cQ z-k1wEd@yYIKH%>>o*jv2J5^d4@hn|Gj%UA(XWLYJZ^yMZ=$*zO(p<@Yw~eh`fpb28 zBbf@ut|2(^PG@8dK}HTg>Px791V_?Wckp&#d)vN;c4V{@&W)9^7J>Km)jG++0NU|q zjqZehfNLccOlH38Nk)+a#r~}Z#|-GrVK{=X@}I^L`teTU1=5e8HT7p7?)xdPV^QZs z(2pm_;hsiDJ4Quiv}0Hf^r+KI_VOfjY)83QjU&0?$Mw^XmyM5nv}54;(nsr~viX}* zd6&jc(wdk~iO=$t>n{LBX;uO5mhz?K9{^9JhwRqd(-g-aFa%S zg_y9c_(IbsX2uz>1r5_PyvA!Mc;OcjMT^fxGX-;R1A#IGX+t69vpe) z_XpNN;MM+ce{WGN+z04AN6M?|!$*IDEdOS%#Ae%K>HW^pDBSNHjKcl?eu*6% z`;Wo>N7uk`|FI+r_ko+P9PYQb_J@0{@{VFee%^j|V7Nc30vrn^HfyTF?=wgaH2UL! z2L1yY_}>Hk?|e1}RZY{NW66L0j~h!|^3u1fnG zu`$*&Rb=m#T$Oj8HRIf!+C?$`eD~vgPY%A;iS^o%^j?n(_YlKB%W1E~@S$hlJ`tt; z+lQjGKhZ9+1LHvZXe^_ztbZl!r{#g^f4VG6|8_qAy)xL_w#LHV!{=KH><3nT1?=UQ zhrPW!3VZvJDD1}%0xuK)aoA5S9vJph;kiH7cG|{XIo;pd84LR#T~WHf-S`!-mtG$B zw$oAA+m1$IKL-D|{nmdR_LJeYuRimLlRS??Syy;#+?B)rW@{|$AIeeK+nc@ucIV|` zf9p&X_P0(%VgJJsiM8bn1Up{?Y#bB21_=KWYYJAHZ@aeLT#cANkM+oLAIO;ucDhzs z+w<=GV6nR9oJamB@ju1z~A{Jjrkr|6Fh=SE-;De^Ijyo=x< zs4)}JZ84AW3U7_`Jjd5!to0t`Aq;geahe)4u|lcVVw@Yp?EAe#kNcdywv$-7qR-?hDCJk2?Pt2%f5UaXJ5 zxk+~MTxKP1vj%aS9cnIwAMHKYFpeZA_h_K^_DA@i#(>{P zl=bXR@c)~)Vm-SJF_r+WXNU6>D7NAXu#C0Bi7wZ`JkeFc<8knrC1GFumGi{jRVuy7zsw_iN$f_xM_H6__AcbS zZt@Fw27cj`L&*EETGxlyGWIHKuvRr67vm;blb<>X`}yXrWIHLo z`|2*chv$saI%eN>U&1-9W!h@7|Fg_iSZYEcF>XRA0}EML<5^5=K;C`t>j%d3duO9~ z-qUymcvfQ;dnOVNDfYP(nx5iBi{f_23ni%xn@~HmV zJ2S@tJn*%i-_4NN-mM;wW}UOHkAIEz0fIZcHUQod0%IPd{YYqiQ>Jw}t3RwKT9<_5 zkLbUI)*8I~-%E_xruQ|vXwZrC&_fPIKes;J7az1w7Uq;ZpFh^uY)uRE9iOvIR(WPw zH~4U$5MBRDqxptrj(ZZhXr|BJmgzx zeKL%Tz@q-RIH4aH7st;=aS`xbIW7Vt2gb$wLBRC61{cI18eFvA7sW;E^e8S4-yyNq zO@9{`$iE|=AlSoe-^2?_zVxvR5g6UtwWDKQQ9o>V>KI)|^Ly$c^)3wOX7g*%|h|9E%0!~&H6q3{6U>qmd&I>f*n zQvGhM`Fr0wrl&X$y?;C~?0+~Lg?(4kmBYU4R-!M-k#mqA?|Yo!vajSQwT=Yrw9aW% z*Enh3EdmcIgoi)^Gj&|gkLkFc94KcQ9k5}6sVozFV$%Jrj_cGohY9+CZ*;u1WrtKuvPaN->=<24wA1?LqpcuQe=;HN*{u(r$bmO^nNR@pk1 ziHCse)&yobM0L(EYX^c=fp(VHahxRvHZiGV2Y7QC%kNmjW67ErWCzxpw7A~6Kgyds zw?=W@0lT+r(u=X{x7%-3 z=huDK-j6v5C*&VcyV14V)N=Gy(Es{q@;@}V|1a2oE$(+{;=emI@!$WtRbo3R{@V=S z%#U}NB73S3zxP|C{YswyUDv?6;dgCOoNrq~JRiZiW^Ude=i5eUa9*bJ_;QNPYIuB$ z%Hzuc?`FzRkc5&x`41(1@*hh2`udaqv1Pup_(3gSnq-?n8@tWN5*M0L{k`#_^1)@{tl<$_%| zG8XQ4c5=8QbBC>)qPk(LCjaA|XC<~Zn*Y%hIy<26@|ApfSQ?lw4`)T;{`I*l*Tui~ z#KQf1YZUHnPVRd?9N_Oa!FDARuNS`)K&;3?^Hi^P+* zJRQaj%{L{srH0;lnie{+2c>D?W;k3AurW25&C=i#R)_x)I_dhqV!xSv2e zPjq08vea-Gd0*lC3F1R{pOORzU%TP=R~uf(dTIFn5V7p;Ufge2+DH9b!wRgYgzp=~ z^1Fk$ze#N$drcauFwYL(PY@q2Kz@^h%QxD``yPe@yay1zKSF$@z=-?hO8d0-W5~{Z zK5{=vtSCsw{i#a(SSMO)NQ&UckG(|Z6o|M#mUOu2zEGfvRm;>%7 zDD4~Zj>+J|QT!DYD)^gyMr|MOo(z6ngTGiq77o zwvRlo!Brak4He4@5a*b^Ol==|DT50%_!}aY7c9s9a<%;gw4bfPp8@z=iThL4_J^ST zBn|!&fj>X)k5$_rW?MSwyas=Xz~5%vPf*+cmTmQ*!y5cu1N?1~gjr|Q_Th^RdR@ie zw}HPl1%I>J)%Hzje}x8rUBKV9sJ}^VKMn0yY4A4!_``n3vzDpt--z}LH25=$56wWn z+pKc6{V`}iTZ2ENST-XW_ou4u8_|A}27g1v@)>vsVAfc*{o%IS`12b44HX}rk&XKa zYWvsPmc}2};BScd$PB9_%sivEk2R$D*ERSXDpt(M$NhG-{Uo%%LW93+#W^zyaetHA z{z$Z6rQ&a-STdtR!QaefYWv?t`vp<_%~%Zlf&XWgEA3<7r`q^z4gQ9U56)PD`%{(n zu|L$(_#_Sft_A*@aeu7RKJ68yKd-^x2;grA?kA}2ga7r1HTW9_{B=k|(HW(E6WZ6m zuE8JpZ$=mHw=3=A-K^F66@Bp6gZrD5_Dxui)mQbwALw7SOl^NS+Aq-HZD*iG4IIaFm5+A%rMEeOU{(+x3 zt^OM!K6DT0`@k8sec&fftN&8PvU?o3->$X~{Sc?se?|}rRebWEB!y5b@SNQM#GZe3)J{)m==xAMwhQ}bI_nei4`}dQt zNBubV`k|+F%Qbv79C&~oxW9?)F7<_6{W$bhrh#>&_{hEB_4{kcXQIC7y$AG_r-5g< zIOkr-^Zobb$Vy*W(~d`9CY2|Ki6!@16qxS6RRa^vPZgU|dT%~p8i6)O#=;~V*T9q{ zK6EeWdf%t9FbP{?VY;^p&m4?}Nzn5DwScJ(&uof?NvPDo1RZhj8a%Tk7A7HIGv*eI zc?h0yiUc?C=kT_Gmj&9lF>EV`iVxlkS-vkf3ResG8SmBI5P2q1EW5W2&y1ou3#Zk| z7J9F;OC!_Y5+A5v3E zTu|sx$m8<7uPFh_$K?7S@LWsx#Rm%$(atjbR^VFK0Ul)bSXvaC@JwkGt`2%HG*bgt zida^djc07;fC5+X-VPnT??*n7CoTF7jGByS41jPM-siwk>({%zMi$;DmHaH*TET$1 zip1wI`~8C3i#&$4tOM7K1P@@@0$(sl^hexB=koG+;0~g-bE-eijW?MvPI{&@2Yor8 zYSFp9h15n7+Q<;`oFmU4Pw(QPt!Aa47QsdREamUW`<1p^&=%TWjs0$U+bwz*was%| znF}(clOJiP`I8J9>Ew!bAI{0nU@w~X6*w;gFX`mc_LVp<0?+8=2iw=+obarZA8PmG zJP-KP$z|>9aV~<-b#i%oGtM)?8#?*n_RTmqseQHJJc;Pxh@;%Rz^kHz&%p~Z2etEk zT%{G+=k{gG{2#-S=`uHabH^*#pw2)oY_o1KJbop0>oT)YvQo+ZM0{Y8i(B+ zPkU()Z^|~zd0HvIMA=ux({F9~*L~|$1$@!coyx$7pihO)3#DlJ8#n*S#_6lMC zbH!nw-X>-5S-jJjM7#lf>3n=ihIP-ci)OVKBIW=QSq+MA2fR-2!Sa@SwX?b zrhCvYO_D!f{_Bkw2yHxw7@&lhh>#1{un7O~6o z#haEWUo=m=a=zH)iRFuSDasd{)%jmL3DZJN3N%QJJVq{Di#4?FY>_9}+HN>+4Oug;wc9j3gO&+9mL^~SqW zdr2Qr%rb-4*`|dy+HlVE9H)ggEX27q88Y3_xIY``7McfR4h&rGpnDp*+N6npZ<@h% zB>Vt8hxqp<+OIhh{|?Jj1b-?o^^c$I4XSG(mx-V3?Ty9}Hk`Tg_{obou{eA)NPMKk z{a+fT;t+f!F{>I!nHG9Mi61$D-(rG)y8?fNmzp*3H_uRc4)AXW{LQZ-R>0%goR6BL zd=$Y!Umkj%uK~z}Z|}Z6ms$7Nqlx{m=kSw!aQ&)@srJ{e8~eb&|3Vc0O`{b3N<3sI z9Si;a}42aTP}W! zq>m-`;yCKpu?~HuCeynOM&dPZZv1<ch{hlR0C)-MUIM6#$;k6%(8Q&(@KT`Ek3NuGj zTmwGKTH_G-6=j4svb}*Z_Y{O~Fz|gdz@N$Fy9M&@DGc6#cNVcuh&mR+1>pg8k`)~D z_<17PBl!6O^nMv^z9VAedT2lMEq=U@5p%u9px}()Mq9Ktp(oklcFj6jCVv$B?;8|*tkxWw8}_&XfHT^4k?!Q6^hD%Zg_!(Tyt1N4U#-$Y}y zXA{#f;&LV9xLoeFI359VhuF;K$lfC%#)@kWXT72=wn-BhvfM zezOgGozi%O*FAXWoUct=OP+Hrh2k@KPEc+fjEgfr~BY9RXrU!@Q{pD3|k@8tVa0)P08v9zr60Wa8R zmhVp~@5K3jrpGrCXzz3b;f(J?yMyxv->*y^AM_sfL3Id=(PlZ(gK}=%ODLCP5a|Hz zvuXHk#~z~w;7!?Q7C2PqA-~)SIz{%G1>gGNJNO##?i1+dL#d=aXR+t0jPJxC-v#gE zBi>4MmDmdhCAOZv%Y^fF>VA_y8x9^>satpcrPyEDOrsNL#ED?9wEMs;2roTTSoW?-mQdpf`i(}J6t{m)|NEd>%ts} z{Lf#tLPOzdS)>guNv{!r}5lH!FLg@cq-|ix~eC z;H?)?_brMsZ#t;(T+0`rtzL}BUMTpUor1r?xytbk4`|Q^zT*3^hQC!o@NpQMxn4W3 z`n~jx0;7tT5`q)Dz^IPBfUiL{K_>H5*#x|<+GNt(b{Z$)k;@hv=>e_zKBBartt4zb zL4G2~JMjbN4%XG7!=NR%2ZZy>(J}zN6Vw?9cYHh@V}3zKo3VB=;Fl^4G^tk~4NZ8+Lx(@m%yP@8fb?q^?nr zEeecb*+HR<@FfLJWxhk}=-ZZe;e&bu>8F&yI_w!AkG=n469cdt!KKMG z->x7Y15HzCpWTir$W16_>F{$0rY-b3=QY(1D7-deWGpV%&)4G8RSViK4IRD`+F~3T zd^}U&8`F4-Sr+j4HO6x7ve>b#lBt38e$^fE2Xs<^d1UWf!|hqqc^x5^Yf*wTE(xZ;@1M0tQ}tDA*@3V0_^+O z!}ah@ec+3~Qd~o~bN^#E-cO@%)x@Qeq)R}kNuZ^IsW*aJZH z=JGveaK2JvkF26t7V%K7W3n8`n4X09ieJx>L!lg#0sg3Qc>P*-p<%6%1zy+J&l1G? z+k^t&XrZX%HleEiaY05qLEOha?}8pB6VGJ()(RFBEABf`N>IvBDo`p>s&UVSJTATb zBK#`Ex=<2*_%?VH|LvqpDQ-;>2|~is-Xufd0ar< ze^}8c8b7s8w~_L#2{*JJZ1&=NHoy_Sb<<^@0)F(sPTSz?;yTT5Jn*T)-}Hu_%2Rx) z%$dN^g-kuI6Jz}N9^|x8!!U}G0*@Emh3{4q?@Dam5$_3BV0Iv<`8MEn6X>x-Vy+jE z%iF}dAj>K89{3kOMO=9huJ5^pY*`oV=vlJ~`%iYmpBaVy&uHx#IY`tNMMBjktEInt&c*s_QN9lF;}D{RXZBF3glLhdHikbEW42d^>jt+Q)wM__iRUG0FHIGQKA_ zS3ZXLtPJ|T34ask&|Ui4zcKdAUs+=Pb9e@GNs<$F{E+XBq(|tRg9H!#enZi%FC*`j zWzw@=d?zI{8U4Kg9*0jVL*703HhGxG={fiZd58xP%$f9zw;0bn7xN6)Az}?f?EAr; zsFS3gBY#cRFP#4??xWudE-PsM!N*H-C9w+Cmwj@$`g@$$CS+i*QIj?=-nHRoo)1rR zbegNv{G8hp`0lVTmC!j>e6KMPvT21cn+Une)5N;&~0b~a$X17yMTGT5SS&DWj+xKeG+1?0Y?>H=x6Yto#e53 zEqlfTed(FT_pku(Zd~HY#czSjn!^o?DdMB1uI6#o&( zcatmV+jo;+MZe59n&o>h6SpGVxOPTyMK~f{fd>gszP@;B`1*Kq1U(l>rz8P4Jhw~9 zN1req{LS?){7fZ2FDZWZf5VtunlZUZ=9Dpw-}()XN!E->){N<<%Z(|_^K*IV9>jgXvy&QW%@cCf0l6`>t`#cehgc%5 zaYENwX#KbKaiJ=g*-UNid8WM>3uKYLIc{x@cndi%d#Bgx_d4F-L~HdRQUwVjy@({zwiXgNbqpeUotL9<<$l zIr;lt<2tv z?_!-x$jUf-_WP60ZWKYs4AAj^%#6_Sk=qN}pS-<_&tYX_a!?OCf>uPwP?yPm(Rv~I zknQWx@n41i2k2O#(lJ}5V}(k`^a1Dy8C2F!arT|DU!E<^Qe`l^DMGtx*5&O_S~qhUlp%u}+Fi7Qb|!oBp|r0< zyIb%0d$fby;jtaEfwVUV?4Q4{{rkFp0_HxM(BEa4Ur>zxe0c4`^+&VfpCBK9cWbCC zeuxR^(%iv{Z@WM{Z@TL{Z{;={gQp)aaYJJ#U@C8Nmu_p z+4b%eGB4Ywnjb*%NA7=MZHKSVsJ4AK)=tBALG^ij;r;je`95FM=fGUh&@q!S`1XnP zjt>08h|kesM%)j+Mr7}+|DN$AspH}A3}HMG|Kb}Ok4YU*x{9BOFVSy2(6j#pe`I}a z{`lwhdiG`e{J(2Y#BZoy%Rk!hKS9@`%l3IWx&Np52r-y&JhZQmaJl{@4d255gkCG8 zm?Xs(xnA3eZ&?emzGsd@iM?X2q(II?EOQQY1#-Duc=Ys6n{i z&euQeh>@T5q$0kA`Z6ZDi1Rbo6S#lIT#fls0b;Hxo~ej&7bC7e#K>x<-i_~Fu>x9K zK%70#ec(F&&CM{3o?`exPeuJ8%N25$`;) z#fWnkQjV25z+tmu&5gd{od-WFW}OJR8wJRB8W3hr0_tN;!c~W{CrqhEyu^<6Y(Dl0 zxQDd_9;^0D!MLA{j+LO&$l5il*W3u6HmZ4Yx6h=Hu4ilZc)#U zbxxl1M0rRm%vOBcXCjxqMh)cppMWGmHGU8NrTB}9Bm6G6j1vItOx38!_{$7HOIUq;P-d4fS_gGje1n7G?{JS=O zmeJ5EtjC(E9i;%J5Tyvkfl`7}hEjo2iBcsAH_e4^sF*O630CAtqpu=IH8V8`tf(yw z@2B`HD#ZZPJN(6SA(uBJt}TErCdl#*>Jx3eE`n$A{lN7Y|2sbH0}eXw^C8a+I;Eo% zdxGPc!}uMLg!FFsxAZM~6Zk}b8*<+zwrHXJv(@x|6>9)LLQ^<79Qaltt^pQy3Z)0- zEJ`oRd6Ww%LBPpS^eD)=OyA&51Kjw2*R;?go3}{dISd$Av(G6si%!AF=^!j$=&=b# zjJXT#XL{23y*zyPFsnXI01v0nr01}vm?gFfR@5`0jmid_09q_xgmu&+T+hOF@C%Mj zg0I0TWMd4LoS!2W(QN**HkGf(~-EA%`OYkPC7unEt>oYRHL?Y?^DWoxTN_rQ~_s*{I<7$E(Pfp?A5Q5Bv4>M z!&vrE6y2PrdQa$kPIOX|=hXdv|*sB29EA4xQnA09UhPXP} z5wa^}Lny9J@iF2t*p^=8FBs${EL*V&@hc@Z%!xc)yEy>-)}ZW#9v=i;*2cRUjx(Rx zfqej5DK`RZ>3EL#n#;}_=7Z14*SyAFR;n$0J zM$yMVK7_mkz5FMp_uPyZicYdguBq20xe|<4tIRTLrWygyHK78-y4z~-Z8dzSp5=@+ z5*+gFEOeggqMk$DGuBG>61vI?e(V7J{QYsrRtNa7@4HjJFw9DR%nhgIS5a3Cs8@CNJCE81=KO@JuX!4-62%T8?k=q5-Kjry}k+X zFKIs^;M8<>S5G?S7*c*&;BWIx%vYWoEqSVD?Z~VKR+{)|2;s^qm$O6Xp|!Oz0Hw z!#>a!??4RQ13U}hlfz;+z7H(0!?XrYa7x1U&yv4@e2*=GG~{^-z08VvPpgOJ1()|Q z(9yWJiAkZ<3&a;I-tA_RT!cPqSz=})`lw}DfgO0y`FSQxcGygT<3d$i$#)Iljl8o< zveHAR*q=jz3(4=ca-L3VO~D#$5NoRfazeYIALl4**EBvF4<8@kA@~7TdTWtT*=iB0 z0x3d;yoOx}n(SEXm+*ZYS}U&noa>Pofn%T83|A<1qROM%Xn!3i&9_D4S8pM|d4& z3(5|Z0Lnh-J%e0|abOIRaNQD-akW4JD%UZ*6auJZ0+ zE8TIx(>7)@??A31-ltIX#?%^G+koC7`n*o}lXAib%&wZ1Dc*d14d2!wTKR za+vX2d2sz=Jo7J{b}6t;LDmcVf&?SB0%PdKF^K%j^Yk7B;Q{NiS(1>vAGVdgkC_fV zV8A-3j^3e=pQ@MPJK}x{zaRFE;IGdlyMaC!y~iOhTTuoXy~6`IGM9tC8`&v!+!Fyu zC-%G~{|)+SeiQPrI+5$kzoiX6NEBU^ZzUy=ZdGKxQh=P7h1-_cf^%rYg1V)cBXp{H zYihk89#VAjyn~`O6r%TnDKAuBvZ93QqwcHZGf?ah^)Zb>UZnaPI)=uSt@r@*6KG6o zTONAvG2Fkrlwey>uJ|7Frz_8wO!PJh$?zGB;k8NHpNH0Z5Hmciotu!JC%q0{0e8Ng zLJ`Rq;kIEXJCFBTdXZn3MfjD3k#oaxMRcHd=!rIR-IE!Fd*~~EKPp#q<74IOX(RA` zF2`!TwtgmPgK==2Z;OoW5T}juekf@3s0}j6X~X3Z>tqUT@-}fCKTkNWXp+}FZ4C1_ z+J9Q1&7<)|8}1)PXqq=aN}Gyug*HzoMrkweF7jc}@2v{1oTDPN0WHG5G|`6gll#-= zQm-lt9neAa-cw&$=umh*uQW;KD89Z^{j&dZ=jW<0**P%HEhtw=X=oIg>w zoaiD6|HAj~hF_$}MXn+jBnS1mpdHCY8TL{DO(kK(D`?w*ab1`edQiv#Z^8$*PU>ck z`kCy4w~^U%9Pl$OD46TGu**VCE%(O{BOlE{J~YJv-J=l4xe@bG*iwquWRl#}3RbTR zI^nv#)nVV6XhQk2^`NsP)TF^?GQ?f1&=rVB!AEkbJ`(z*zRf1oS7TCCR}P{mF&?UK zgY66ZXoyRh6j_C@=p%m*Il8=VE52R59pC0Qqi@QeMqE?GeA_pK71b;*uJ*x>p~&!w zTHp)#>TP%rERC(fc_q%Pa87W!P*!?i+cAG>p}uK++Oc^p81sFw7dC>;wSizK{}DDH z@3(aVAD3Q7-Z+mx@m%mG7Vr$hoS+ADf)9E8$%;8a0Ck_87P?e7smqx3%tfKdE3ghV zzNG3$8|Ci$)P0sA6OW8TKONlW=m_s&nXo+@u65L@xT13O3DFt;k!}jH;v%OHx%M!r(!F%K?Wl4r8gtK8P-=# zF?+c2eP|IU%0u2F<{&~g#k8pXW-oh&{8Q)>4V{1T1^6@kE*}4Ow}_la*m5Now-zuj zWj!7pe9~r?uG+m$k}LQf4$!p(^YSwH6O_N4+}+y5%CPoS793{axH_~;D5LjP;OAj4 zvk`p%OSG3r{y%u2gmQdEnZqy8Gu-AN$56@f9dVGp-;KOsBjtm`Uo@iaO2mthF$^7v zqxS{)gsGe^8L;0%0J(o{8?I-8R{BOB^5%XZe4pO&>cD&jbqwgkq4K!ACyKw9s##<>!cNN=$zc@>GX;ne2w$h`iff*Dprig1%0RR^xCV^e*_P z5OwT4HYojX_TD%?s_I(w-)Ck*CJ^nYV>@WX2}BzpLTc%~6B1x1L>wTtu?`oiU?&7E zDBg>e{%+JWnKMbyAoTN@2=xXVXh8I0Yx~e*FCx&1VjI-^`QWc=0l^m(Ew-+h0)KlW$O?6c3_Yp=c5+H0-7_CAj9vB!R=@)7)f-2<^JOPIGh z@Vdl$M8%MkG0vXU+3VJn_28n8ICy2%04KC>-Hyz_7l;g#eS>fX@bmq6Z+i`P0`pwa z!tYx2=3=GoHSw{-U*UvnY9ls}GQAtt`?W!8oz@_zfxYBedXb$M(GyYI=5*Zy;TZnWw7U*h99b&N6WiK@v*?Kp8)DLSitE@Be!V@D10 zr@sp9MHX}>=ORq3a>t+ks`&pafhl=O58v1@;+2eP;(8TFex{M5f@80=EA$-dq8>hE zu@#;3AIOQu%aF&mo!E_>$SYTsFW9tQnL(cLuDm1fBJ0wrdC0Ianl9zt2r^#F7;t8v z9TB=k{z3Rly?c)Cu z{x9Xf>^qp0S>{H)2hkyLv^>ff@PFgWK?XKX(q+JygHOiN@*8Aex5&VMT#u}^;Y*1P z9k=%ls+lwP4VoVLnS5V5Gx%(a$V=!Z!@KR3H-c;M8nI4g1P}OyV)&9{?WU@0hBmC( zHjOp^jJaywq#j%kjos(a*mKa;G|nplM`aVg@fo+!HnKU+xhI7z56gPhGK}#I&!|-f zH1=@zWoy0KBlfxYti^X-hMkJ;QYbVNRaMtC<3|*oxT%M4060S^INwUgGo6 zda&*LJAKySKM?DM3^`ubj2?WSIzarb$$ox3dmeDD;e6pv!|LZZc5k7aF%^325301b zrQKil_NS=Fwcuu_OLd_+*d3YfZ-&V6Pj8 zu@9qqZ(tke*)#AdzSm0V6`8jbxv%wJ_@YbJ5A5eI%H>&%Byw>sDNb5IT1Z+)oHp+dtI)N!E+jJFIo}duE%68( z0+(Kw(8?J z-720wt*@%a)B0*?4RT|!?Kao3-3;r##DUYc+j;ulbmZc{!*(kuIIW}JG_NAae%&N> z{Ihmk=uzl@kR3N)?&Lm)9T!U2`c3?9(QR_{Xsxt%MO8yRZD5Pn?-SW^rX3g3_MdIX z#V6Uef|WUKD>PhT+i~*?>@_KNnyw|b$f0Yil|zA+l5bavj$rcJYyTd0K;*TSDVw;v zADsyqvYEYXkDTwIj?dbqR6L{a;4QQc(@w8?Kkb2zMnTidp=o|gy@Y2fd^Kb_?HAg= zFMcIu*lYa2`Tn*+HcRRZ{Y>`o(v=a$Fa2&{T^q%_=%!L8`%c{Z@wB~e8a42b_-FaX zN`QMki~wt&#oE_ZX|WdUwAY55o~&v72$OV3)`vTb2d{le*1iyTji5tmz0QKxwJs>* zehzv64m$Eqba#y0$HCZTOw=BD(q;|Vp1DvrL0HotaJ38 z5|}i6z$r8^==>M3EqP~<9~u1}Kk^3lt6cWl1ze(6ZcYu_KX%qG*2N{SX`FCARB#e$ zJ=NcQ2;3>;-U#&euYl8Sw4?F(jSpJZId%jvXt~e{EM>Vh{vS??9nn(k*b&3`s?c|A z{Xpb`IqxF*wmNrQ4!weS;11D~sq-vi>J{ z9k8eVq22ly`dZH#ydIb?D^;O+r{_axf&TcW5qmV%^z#7YxG&qK^=wNSGqWFEz&Yc7 zp<%tJu}wwM2Zg`gz@YV5WWGKhmzjKl7u^u~=oQ;M$U73xyjt4g+hn((m-_X&+?&Pz zF}$p~D(OA_-5tGey*~T0>?xS1DjRdL5;E3_z2MH!`wV-U{~4XGUWGU1s|Q6_u|8%D z9(UvEG5`HqYZf@54r>gyg-=!BCl14#B0t5B4dbh9Z)6;C4{M>9l<>(NCsOx76A^S|=*}EEM^!#x!zeta^-o7fT!n8_Xc~Pl zeWnfd_ZK5WwJwHyUZUe6L|0VkiY~o3;?a6$x9UPa^r361mY>3J>)<#1h+->C+ywo1 zwMW!O=wma#Eq=H1TlPLP=vGgV+DI!&o5Z#Urfhu;{C!^PjQelRe<$g6;?1Nxq)bhGk9 zC&sFEYIS7>*!Hp?wwKt9eL~0R2Y160&3lpE+&A?d+H~kzV!V=%ecQikD|+-yV10)6 zZ&ZQAH5a_zJ_kA*%bGEq=fjj&{29%Mj1YWUEBU(RxS+8a28apG|p30!62e0TH z=EHKn=Tt_=m$2t-v2L|^;G5wpJo_uhc7`qPA7VeNf_Q?E*oyO!(bdGyW0zHo*58ae zW)9yP4qNViVoO%rGS7W%VmJ0zmog^aq~N<3IDn z+EFKKPbKFsm|L&#R9TVc`@#pGRjc9kjt95f{(#ht;A%O0&8=#}?8)rcR{yRs(Uhq} zFDnEt1G~%HwDv>)gMxeDO+5?_3*vHyy%+n*(KWZYZydbsgJjTE}F3UUP)I zF;%0~>{l6Q#fN_D9%R?DM;grsF66wt>*-VxI!8ZuW_dUG*>~|;+=rA@LH2xHv8Ji3 zM8+L!x?vUkI9}iHj2Y~tRfFW5l@vY@UvC#O7~CNnMW-NM2D|fS9ge^enIy7 zL+pv;-`0LXWI-CZRzH}+7Z^eA6(e)js~Y}CNwt*Kk#|_NIXSoJDuGYnlJN;_&1)Ht zU#~~VnT73x<($6T37z7LJry-I{207m^|Y3A&m!k;LC)Qa zoI4x8H`71sv@K`9_hj=r;7X}5aMvY0T?*bB(6>xm&iSoNiSIz}AoJ*hd6oaj4`ftS z6P(f5S6a(pFYP2EKrOF!T!YJ6|HbptqEZ?CDz%eV({kRE}|^H>Lzrzc-|d#=P5 zRoV|1gx8|<7f4;o9SzKd@Lv0+*!(|6Ca-~pkx#_xthVF0`b%v7M=oE&8VGHeol5FN zHDAu-E)V#!d7hSmN_b^e0^XKb#P5IT=f00Z;w;!tRd>ky$s+D&?8v^V$IJhUIPDFi zJqtfMGD!HG^Djjq|6)D+mc)Nt&%Wi3f4`nRW_inG)`{WB zUhE0cQ*|uOeMYI+F01P0JL#tmp(n6!-HQxkuX3l}JKJU3a${bw<);cjBX#o3E+74P zns<>Q{SspVZw5~5!$;q%fG)ZJqaR&lwX;X;w{_fODfZg@>7Dpq*=sKw!n?8`i5!or z(Ff^ckR5x&b=D!Z3m>`Cv0ft2nq*IT^wZFpC#tT0QuJ!!Lx~x&*4@QDLa{ZpfgO9p z1@Pf6$N!vr&#`~6=leJ8DSwxB%Wd00R`XqTygQHYh62Y85n0!xYT6aV>}efb=vsXI ziKy)(?nYPc=FXwaRMGr=d#Pu4$6*3tf;H;|d?s*!s}(Ux2zFB#?S!a&My(LG>Tpu2FxjyXsqwB+0@E^T0La9CYSJ5BlgwPqE1qO4I zjT7CkhwmpHCf=on{Q&TA^j2U87r^nMjQi-7uBT+&;3dfT0!LGGwq-o3sPE9|iF&N- zqo4FGm_M7SPTW(UJ+dc)4#9ntd$=PBpM%#j^#8;1jYaOYDwmg ze9sP_a^^+8XVYxD08 zsV%=FR)*&>;yDcJgxRyH>n0wEHfoQy7~iLz8seV(ediI}u>jh;u72zL8;!=JQ|C0k z|CV}+ac%^MT}LNn?*V6G+bnv{4WO^@(3@NCN5Y6PA?q`JC`)yDT9 zfgY>#zkl@d{O|X@m;ZfvA3S$~o4|V)wY*#sZ8~`uJvX?JZ;b)Aw-4Tu7&9uMu{hzv?0`^vLVI6fH*#^zD z^%Yd#WAo?nr{#UkpNGhekl-UEv0uPxbuToe-B!lg)_1$WsXjcqfb>K4A#GZ()I+l= z)rt)C(Wk{bt-#sVZGa>22>hG+3SC$CjWIsy`&j|F=k5x1ym-=gxr1a1e(?v4&fUw6 zjlA31UvFGZU#of7dLCTzZrjl@?(b&|)zLpSUeb5uTfpoKa0kXj=;K(6z`cxku~roj z|M~MjGs=%9yrsaTpUJqG(_>lJvE1FmrT8HY!PE0E8x#7^JErd+4sTFCeJ8QU2r&-7 zyeG0c<1(tG?$PkVQpT#=w9squOByfjFj}8~fqOdF9Z}&&jmBg?d++#E#NU9)SJQI=xNAKb{Llw(mO{gacQ+bO0GHL*XI#zLdXKuvi`9~B!5oxj)yBAwP`9zK zKD4c`E4=OK;^7mIUO9Rq`w4|dN9R9v^!EIxEM#VX*9>1bK9l}D<~*f}`j-O>cU5th z3pf^iZz13bayp!a%gl+ z-;6n>eQ$+J`hy{%#bYhtBC0;t@e^VrP3f9qt)fi!Ja*q|%w;UcvTBa>QI?VNtTK*X zk^j_7zcse>7aUX2oo<6ZCrs&zSio2&?+dN<^cdTrmt#l&`B+K+56cyD(5~Am{Y+M? zp4B$AZwjyrKRo}b;ZNO+PiTzt%9$YS$#S8A?sdkJo|(qn{z9L|N%zgh()Y8_&d_*C z|4*og?V0UW>EC_A8jh?YmR{?T1F=`7PV5zOU9Wpy{P#vSW5=e%C$Zj@%U#4G*NNk; zlXY;@+s&V8i;6?fX*YVi!V>@43@oC?xVzprR%1=A9y~om=e~6#l**hjnyy(gLcDm0 z9Bjfu$468cRmb)@WdX;YlCl@1Y}EnYgI}WR&p!|wLE4dW{@=p?02h+a5!(RUPNnZ> zo}}#^*bf`9zlW7de`OUx&IC-q&@XW@*b0TKUc^?Vp7_3{o;fTmXQ6tgAD)Wfq7>Yj*djI2{d#E#Zx z4j6UtgN4j*&ESJV?zh47OG1=|(PKir^nY`;zx$Hx@mGqBn#?8H{yjxTl=lOP$yfWk zr&B)HsO=t|?SG}ps1sc?Ip(EC;&lRyw=lfTD4Q}x87Jet>7L=A_VpJ*x0YHdeqi8i z6&^SlR_RIcspY#XKi$&bHD^RSdO^jEZ1&`eBV+ciR|~CrwRrKZmLjIWh%NR_On0jV zvv>L?5=$CSt}Gj8t}7eYe@C>mucWtB?jCyol&>_Ki3g4*d+*7Ps8d20uPlHzTb1Wz z{8(CKkB;R_W%YN51QzM@&Iv4JypMk)`C||Fe5$}x&!?YmIT?a-Lkt_#j~e;W3sz@OHZof0ca%f{-!ylzuS&YUd(;&$jqp^ zX>J=j^Fo&zZ@Sc;nEOkozG*4@j&bzsoGl^eEe7`SH}dUh{FEXa%x#>7dpMhost;bV zWyJ@Nhd3`}s@`y9J!iJSW2oibLg(2XPQFZHro?~3dv}`;6T|PJeo6%`_yXACQcvXN zv%ny>1og@-@G8%AS&waB5O?FPQk)A5D;4)N++pSgMb~Y#o>zrScB9uetHmkqamLRm zJ{&*y?gvBR3yiY+m5=qYj&;d}ed|xTb-BCDOF6m~_N(}K{OI*kUqKgqPfZ1B$0hC1 zrj)y==cOI5^lwhRs8Mjo`5+aHv(FQ!tYNr+0H4@JdX6IYUgpf~j4N!PhK@_;yAs!> zoc{qUHOQ7~lkX^etJSI>RJPEGONz4gIWYlZ=grK1J0j~K`7E(@Y?&IXup;)mf>()y zk~5VvvojYbh;?A?y74#%Eq>- z(A#>>{Xsk6Y++?Ldmk2iQ+myKzuU>z2tAZ4m4zN8t`>SY>~o&YbMha^Ua=ih`u-ww z?Ir%wR_Z^>nGE(>oH}2V9NjG}Fh&w8Y;26G zqr084;kz`RfS!zW2lH@~;N-pQWDPeL5^sJlJ``ePEZzk-N^m1>$XXg=%u_f^nT{A6 z8@4tO?|pO@dU{7wQAUNIVy|kw+B`N7`|%moSy`+yyjv>1c-s&6r`^(Tg;M8B-_Xg+ zQFY`sISULnu^8(So1!+KW3vsv2Z4C0ok`r`)z zyYL)-O(pYgtv6Ud{`4K-2LFG2GV&CAVCV?+cZG~4s`?V(m9sXnNiFsEnLgGnPZHih zw)G~;Q$fvpEu-$fu2}`6>JJ0oS+az7BiY`z?(ExbM)s|?RQ6EY`fP8<^GbCS@CtnC6MjkG2=2pw zH!_VsD2@J-zLq&^cFW!Fo|Xo5oEG+?>@z2^O61q7dR5o9UTt4quYSF}SnXUMQ9C-; ztJ!PnacC8*S!*Kd@7j?Q$i-M_2s#A!v4p1t-sZDWf}vTnU2 zHA1QS=A}W-bbDE^GID;u?K0(VJE&Z331zgUREF{z;3tGn)pT^LYdY%Hw2qXzHvE{O zEZ%1?#$%mA7kiUEC~WQYA^4X&VY)Ki;N>Q`%0YD32%^+;R2dYW->>FQP+ zmK*A~Z4vbw{DTJVzd-xDz|Ft#-mif17vST+t-+@4h^R;D_c8kYXK?idZT%dXT?Bl; zSa=)fEQhK+vxa@?RA}Y}@Qexo$1fJHWWM@X|K6p1+66A?Xk!XI$egu9?C3G!N$~~s z_4Ak33(f==gT_>jY_3T+LeoO?3OXi6lJnM=L#q|=Q;pCBXK|#zqEL&v+;qEzjwe}^ z$unK&QC2ENAi;bzr+vK zwO;)~#=!Y9U-Hdw`&sAGv%<%d3`hJ2t*I)dW_i3-70gRw(a3S;dn5f%;=cgL&zRGT ze*s>%uDKsuhc;$SJKkh^%SBg*-&M3Ke%BrG+m5h%0222gye+&ZZIC>yZB=_mf#0dvC=vawA1~hq^5Mtzw~r!TVJhDRnreSnBoS0s zCKfv1)5doQ?RjNwYe#O#xgoKK;nzA@J45#$4B0;D_r3wGD`;MSKNJ6UVW{n3xFSs1 z2;Rp}U16~Qwv&Fk^><@hfx8ZRjA6G~%-zSlUJ{>=j#2>qY;et?en92|ekv56 zU9^CCxb3FKSaUwMoGQ9AuJI~5j91zQhCpJ-*oVs6AjV~?zYC{)m*4mN{@D0t=6fCW!%E_;d{t83e6UsO%X(bda&V>8m$6sg|NCRq z)xMU>nu8s>{MVFUbFgci7rJg|kMU*|2m!Yfhc{u8wRj01D!U_brK>UcF7x)=ulXGx zzVFWIj6ngfjA4W-GF|S67)vl#5D1yeOJ$9!0WOL8@=p@D(C(3vS3%;Zc>i8uW97;WSKMs6m4!&_N#{D4dwa(TN<3qrG%hip+w}J6{!~IU2 zqwmf|pM^0t0{BLh3Lh6P=~DT?S90g~v~K7VJcX`3_$vJe1oxrZgNONDD891L^xq$o z_Vm1b7n}FCgCFTdL%@R=l|wn)bn0^z+Uu zE$h`*^!v@o1&@wfmv3@xw%72So}bh4Yd5H%*72WH;acEMHK-!^QD|XUD2!eLzr+89 zv#`0~eLwObATmMZ2G3PR(AKv^W*{RJ^*#KS?}_0*f&`Hk%4nH;^6W%8F5PyM`r97;&Ze-vn=7Bvi;%Ev}#Bk7GAu#*o zd>8Xn$bFW+_7-sQ2;UJx7Rb9+jsCWopK%7t&==%g;v8ihfs~tX(|DbCOH>hKC=y#m zY*vkr1&qJJ`IZv!%C|)Iw=A$dWE{x2E|GiaLCB?s`gpwI>t+jkBEmDxt~9yWV}Yu! z`iA(%tG;eF2jNxMT;e1)RrMmr-fg%;e=lj9tHTN@rU)HZJg~0^T8N1Zs%YM~hu=}&6WSZ7C;qjH)_uJ^D-&D0V%feU{0`>Y5u3N- zzJ13j(=w~#{{4!+v<*i8LD~}=&S&%EexYG~_Bk|Te-ZV<)Y0-Sv~j=Cd!e)!dTf6w zFg}6(Cu`%}vS#x8RET~2fbhHZ66^N;`zIvwr#2ERg?)TcBf3|}Ecp6EawkJ! z)g@!o^~OS@@?P`)x6jW(5X_tHZ@EI z6ZbbXN*$4hp%wd0$}2V-b9<&+;0^*@Ky;P#0RYFw(UP4uuB`Mdix#0gZ|d< z^otr3=-;uS0s1<0K+@&O?XaC~5nxl5fx`^l<$h7sk54 zo}V|$mS3UHPu;?Ld5!XJN%ZbAZtswO(wZ^T~ z@>XT6L1%B{>?HcTtE~q8{%z&yn5x{CGX@Pmuxq^@p3(L%-+vLEUhHMz6_FdEIE1PB zgmdonDf%8XQ)SvTGePdDi9as<5tY63Lh9r5RRL2GHw*2Vai0&r07>nkJwtrswGV?Q zhp)`$a?z<`sS55S+aC2h+(M*Ai5oU$U3FRZ(o&SmWt zctxMmePn>`1=hjlQt4v?^2BTA`&4)Xaq}~^94d@WM;}86F_*Is%-Q~2AL8GTHmqUD z8GFoS$f%%0gF#d2ed9ny7&@HKIGr(yPfho|i9HB>ZM&Dfv$+39ichDN-}gc1#94`bXD&G1XKoI~HzM;0 z?Q1?sgJ3EYc#yjX&?&qQF9fX12Ijm_<{Uh3 z7vF&Ru$hMwTCaE*J9-4)sI&1Du;%gGrjNoTc!Dn4cf(gtAS?_8FGrXA-+w`-R#Z`fqdAJKopp9pzQ? zS?@-@wOC@5#K&RJ&*j=*D7+!-3p873HL%vXbiYAsBe-Hc0|vjgY3SeC3(|Zc^E5#B z^8LLHsx{W2nr4kwO=dhAT0(3Q@A_g5`4eW1&Y$3v$+}WV*;dN7Lbt(E^h?ogmc(^^ zFV8+$EYlunXw+5xjm}B_JQ_;Y5z&yKGBn+YSh!#A;<40=O&KW^CNu#lkDju zWsotJa_3+a_=N6deHXeHIHj)~-G?5Ve}KEjyb>#cjf$K;_zm6-oc7)1&9nV1qbh9Q zTi$hdb?LRdXn^HFXOz)QrpC=x zA21d}&e#G|8D%Q84nISajZf;!-8+KI5~qH*;4p_zYuSvn_1FyTnR3p*?7vLjI~V@U zjJi_jTJR(|5*S4$m^(S&*Ny%O?gSsACq>o1*N9gI);IL|NN6+%>otR5?JB(tI%ki! zY^|0VbyZ!J562&QQ8kSSgt1G)RlSuDqeCm1SF!2i@4m~ehf;rNgj2cAdO zcOIpz20Zx0#=$qF{W5wDGNGkT^vEjkf?pNbE?}PJ{6pEe5vmGbne%P$vh{MlOmqiX z@2wTn`>dZ%N1qzMOzK6|-V^vGyf!cYeaT1m`NS`(_b*@IZcEmt+#QCp z$I(*koImD#%}d}-;=z-p_%OiZz#7HAK#oTQkHV9-Oxb%<&*=cIk9keg`FEMeW!Em2 zd9^lNyO7w|X9oC>w$9+c&u=?*R@-+EYTM_ujV^W7yw7V}Y>L5f1GBz|5q`PCf+l5u z3f`-c^;L90Xj%4)4ViO(*NMCon#5N*SLR>zOMHnjkySl!AJE^W-fi%0&~8=Nv*18S zdc(9m{hLAq_Y$+uUfRBR+TQltre)HPPunFrTKdSep7guZUhc0cEfIaLf28_w@2F{8 z1=r93G-u0kfm>qbaxzkE!kml@JvQ$c^2Z}IqU9uOnhhM8$&*<~_kDn=jOCy?Ym@{kHH6?mId+Zu;J@yLD zSjhcer*#bEUT)1e7wr#*0~qS<_2KoqrGMmom8=EMIv{Y!U4nzwfv-Mu8jhMyJr|GF zbVSvdwYfD*$0fGeYtye~UlDmG;~kLywr;5HViSC?+9Op z9z0I0fF5(OHo=wn zh=JGM0~LG;oDR&QV+GNx%=iVT_Y_4Zum+)J1 z@fZ1}jNC^qcn}y)il5tphwd14kXQgi$o6L`vRdP2z^Ca?08p^wUPT70S)+Xufjf>}InGoUa(AB0i3h0FQqlxc-1%*h zZ#gT0ayB^ax|aC}`^700=6;rg&{&vLo z&s~CZ@;zEMf%i}YchP`z@ZBZjKBvi^dsOZD0ef%-=FOM*E1U6ohq2c!bqiw&ws8iB-wS1KEzaBV zJg@Sg8kWA)-6cAD=*R93_N3>LuO?q6=dguVEAe%7+~i)@ajCnr?Pl6*R`<|GseVV# z*~!uHsloG~h@58};gvU|drfuu&9FX4+X|gertezmyRC>e-_-Tjf!hG(-=;h;sC=!Q zC*fI`XZkLn@H$ny0vRZK!}3h@x|!MjJh`XET)_Uy8}77Sc5=A1EpRYi8M_Lv%eHb> zLe3g`1?Jq`p*Mj~TaF}Kf?>h!uN~eHJ|R}Y5*`t{6B&*!A9n6*Ho~3xo)s@^`ZFpf zXHUWxt0HTM93R9Nb)V%6SDR8p_S(t)k)6BdARggT7d+!aVoM#JR+CH0kY2^L9w#j! zZ6Z-m+HvnX-BzAQsk4*xAt_g$>oW&~&S@+6{Oo+lLi(=zFHU{*|6iEg0dV+Vm|V=C zo@?AQI(PmL=?RU<;`4SNZ!5Ivkl%f|-=@l6%KrmhJc}Z~HraKs@7+C?{oBLu?QONn zvwSgfvUZT1EIdp_GA)K2c%IV)p^33>kf57O^RgjCL;oHvAa)rR{g3 zJkR5KRNjjz-$e5!H7+$$!?ww(Q%ju-crVR+MW^38{;%}Ov*RBRem_yE#__+F`$m*m z?LtPoJ>#*JXLtD~Ms}zP{9pXHJGfJ|%N^r)oN=nqWqkL1C9T+o>6hVeOr^cnb4beef9!t5b-8>({f0KN8WT$$9 zcc0+*D9ScdXB2h({12L$^5c=6F6Pd)lK-p2>s+n5IY-usj#W-wAHNOSDWcv2ev4ie zB==Glq^z!uJwn#>?Ok@h#j^7!DEG8YgC3?q4=QthtlAo3R=f3@$+P?fdjhge0^Hw)A`#&#ce!|2I)oJ;Oe!%lu@Np_)8G9;5WZxBhjBP{D z04Isyh5ke}G_eR+*BYC(94!$2BCq4Ka#Y0>dH@NzsTPxvVMf|cs+IpMo!_hZ-AUR= zdcrAtmEXHa@R8O@4pUy32+s*I_fMEZZ+e}4qdBauj=WR;o9a6x{ePu7^gHsrH4(l^ z^aj%$dL!dfOL@PXd~qT?SMmjk@XeCXO@wchda>k+Iu)X$@LGKqGd%FWQ+#HsJQ4qP zV=zpEE<@TY$vuyBssR6e1OL&-X$Sv>;Ggz+?`uKyz3H4Mis-Uvj@J__U4H7-Qm@XY zLpA4dur>Q}n+`>HYOgnH1;5aS=*Xpsm3lnEv1`>7=%`fg%$9k~y<-+!KzwX(IMR8- zWAm5Dh8ODxXnVfq%QntxTA~kqW_=~zLUb29fv3g`hb*O05xN5WzB2kRzx2YSX%Q(f@7IZR}N zVe!n8XHu^96>Jdvs5Lw@d6wZ>P@Yu)N6f{(7SBZ2YbQ3J*!sX&i+IGfojike@Gd|J;Qs4g%sfIq_ z6L;5&XWeV%+W@xy^x>0(bgGqh*`HrPW^Bpf9C|A3Dnf_r1bA@Hf1l)*UFOmF9}4YV z>R!ovui|s95!}zr{@LI+>&J&D*aN9a-RoX0bDo;4!m(;%B*44yNSZy|#Ax9&SF1B; ztS=wFAnyq6%R9OHQkQy5a`pJFbv)^lciPEWdp=w)?=r`(!SBi(v+q&EvuI4w|4qg? z-Y*%yM)QI%If;ABD%`@qK6FO4+UQ?Wx!%5OU*d^FU2Zd~p3htLtkg03TF501S<3DG zo9EtJHHork#P@EztYQ4I+nSmE;Dn8b4?dv(Fm|EVSHYK=zRBH2-JCuyb^n$AcRAw& zcOUGKcVrw=pSnv2JzLLM!r;i2zSrH#^R{G*mb-O1{P2Fl>H7x`KC$s^+zT!RA1Rp+ z!N+uJ-$oqQ!m`7=Y_b5MAh5cYjed=7mZ`jc@ag416Y7zg7bF`D~f zXW0xJ{{Qh!zXZ*wH2|KaBw*9G*{SSR_QVu4wbEMyf<-|c5zvJf--^&ugq1b6T zJ6i9ti0#WB!0O^pg3@+n3YzaS_6kmAuA}PLALwr#2`!{t!By*B3c5_>?Cr4J;bY`& zVw|EcwbJJ|OIT(NVr8WN8i-Xs6JUMjmc-v*}PTlWZ(N&N=_!CpuB0_8JRYpeUVSwHoe}MSN zRu_MIOy&Szl#a8t&o~%+TktDH)sBSBx9|$zEzaPZI8S2h#a|Rv-H}!6jP1~wk*kw7 z+&$@tdpn7`r!HRAWI!LDK&aT`8>}}C`0Sts?Tf%iCwm=M>s7DHo{;Q^XnE3b)yv{r zimJ@hGS{*P!hHKf)4z4R&6V?m7%$6z;E>o8kI36KjGJVTTqHNiL&_r!A?1_2qyo}V z(lAmX={(Z;q%V=AjSEN@k}e|oNf(p8O!^8bKpIZEgmfvXh;$ig1nKe)mkN@KNmEE8 zNux+5q$@~QlD>#M>AR#jsh%{S)IeH5x`lr3AYV+nmGnK*Lee7A zZKT`LM~zDOGgSSp<8pT#zPvlkb$iE|O?$?TZ`E?Y$dUj4WGi>|!24}GgvYkc64@v` zlw7O%=VjKg?W{f9`To$WW;{>_PuPCQ27J0Af1$kre#r3@YwPObe%6vvT5q)1h!exD z%Z!Zl%bMha#&Bp|*jOBgw}u)17-vbL$pxvDd(U_@Pvn&B!x#;_&?C3=4tLk+c+^dQ zYRv6>(pJ8FA5mlozlCmHv=Lv63^JVa=Zv9Tr@6^1KFd&+u_{X*jM28~T@ewimP@5fHJ z{pmG~qr)=Xy`eBMYQ?nWz#w(f(}`gykiCqp%PoN$d5sLYg?93#J@hA$r4sMprk#(- z^T_*Te0JSWe=cpCw}~!Nun>G~F~h_#i2u`BbJ)l7i2kHy9&_A6j45jdd(=67;D27F z_sodJVedbWK3w4k)kgaD>i?D+%74*wF5#JR_WULnp^wyJb4=HJ20352%x#=_;yD8} z!XA#iPdh`;ZetK0^F=;0cG>6PK0!?*fzz;__?YoWMfT=oY^q*)a_dE6i4&8+_$%U{ z)DcJVBTXOBL5@Z=U98XBBXp6j&+E~&lFEBIl*;3r+=+dI=O?Ou^#N=8%T|PX%nf>V zA^-P~^Buap9_H#t70i*$R~Q}Z^t^n6&m=c5d0V6E?}}tj9GHwVX*O@O(CGjy(5+3g zC$2k_W`A{yz+nLcYqHR(Ut;fUI_Q^gtZ10*|0hps8q$2V?T1n(ura>GnQ+Z&mGebf z&tq^!%&?O31PB5T_uXD!3;E;f;; zy`DWY=!v`pzW0%rlFCTsqzNP)CrchC)l}R*y@)(WDj|JgU7kltwWK;yj5LQdmlP*0 zAT1;Bqevc-msCjdk^H0psfZLLm5@qFWu$V_1X74p zMGBK@NKsNPsg4vQ%^}St#XDvyMKVY(5}QKGL&_r!A?1_2qyo}V(lAmX={(Z;q%VihKe2IP!($ zxf4W8}Ay&mq5^d@lLo zR55fvojdCcqX*w*<{4yC&VCm;B|5g)5X7T;h!@7^^z;wKc8E1_#&1wO0_&8ly`PQA zp$)zFj{YRFPV_fv)2bd>COVY1Pgui3)vPa5rH!Ji2I3^?NBWTUD`z7{)g>!)wo9%| zWb6NW|HYfm-T$RO{|o)IrrB`)C;Kn?oc{m9_=o?M#vklDcmJ3Ch4BynD~&%`^f~?i zh4BaeO5?x0<6QltFI9Z;{0II@(AJKf^})zqcscPu(5V)n_0?PrcnDhR4Nw z&D^0j4_?Nv!`^_zaMdgf+t0-QpWTVCV;;UKbZ2-*+g7P&6_9vRkulm2b{{eG=-xS9 zDpxP3qso}Z-iHr0Cr2DTU1W*a{dznS$Ac`9@v#S5r2PcM&s(jR^#Hpe;{@&r#PSzP zpSeDW1yi8|*kEgkcL5$?^PK^U+}A@L%1?h&+Zo5g27&1;8_|Ky_L%@1Fd;X665osL z^vV7X-wV1^a5(_avbWEK=Z!Cb$LX6nQ-kp%HjMZO1xLil)QP+m8JotIaqzTRWN1|V z^aHu?L41edr<672C(Nl?l!>bUHhk8BxX23b9g3;rO=Bg- zf31@91k8Q5uVO}|T;zFb40u%FL(L(cYfAa7+lezGrYrfg3;pdp8+RGcbw9sor(bN> znIC8yg*7A8rLa4GR>7QTS&!qT~F4BdUJBH&=#ldh_Y>$9grN5t}Obu6#bbM__@6{uLhbTi_bMDf`5# zFj%eQdc3T220lN35`KfWJoxmptb4LgU5J0sjv01v0lk*$cuQaqJ{a7W)6Z3MUIZGG z?=|?xFV}sQd;^~>yjaVb4%(+ba$xZ}e%lG(7%ksiRV7k}@3vgZbK}eP$DUOn+$D4M z^91K2{bxVV!IRSuqN;Wu?RmO+9g(teO5=maOgtlv4T0Ws*4uLJWF3f?}D$& z9qhrjWH)n9(%AIRlqcRWR#`3_vb;n6IC${t|KV%DnHoL3KVCg+D!408-;T{S7TVy9 zrqHfEZ?w(42_57AUvK9pIioxM;=$vz=V|5+nIn-y%(LL#U-^hCH@Q-am}tM##yqEu zC;7JLE7To`?}WEx&qQK8|B7*?KYR4QGOl!Hc5jKy>EKvX%D98{?6Ti)L2jMU^N(yg zL+1>${}3cj6h6~&qW?FpbRnd&l=OcH9%e?6l)7iCL0;x-z{_r}^~c6-myQX#b7)Ty@#03R$n^ed5MF z5<975G>fohKxEro~%= z{ws*#*Ep7Wb$t6JvR{cGakuOR0+WTlet`{pwnzFuXW!^Y)Y0qDPVQ?H`r(^DLD7%Q zRoVs(o4-Og{{7d5wi*+Gsf`ow&+ef;cX*w;Q0`=t|u3V%8@ z>3P0UXsHb!&BQLgOAwawPwr0R%dy+|Q#a$Pt84*3?Bk=`^j9+Pl@Ya|vR*A*v0lv* z``4!DPa-)Qmwj)$?9*9NNBS64Z}>pHX}K7fPp|rHy%Qe{)MG!=X)g~tUkr>XO)myC zD7;YZ@+Uie0-vv?8~rOII;W2BUSPW98L)3h509vYj%*NHs-}q;IP%5frxkwXd7ZR1 zaf956r;23kGVVxcHgFqwjH&leMTuP#JV(}%{|LTQial+^`~CU)yo?h4W?;S^vgc>; ze9=!~CH)ECx2#s`DrA-1wZ*uW$Twf`{l3QUr7|vlb6*$dDA-?u4hk!~v@SOn-6drE ziTf*r2BC?<@GtZ^iWp}HtK|MI=9~BX@6a^5Q=hj8@l5XMYc%g0rT1Q>9(4}cbgTl5 zcd3JmK+{eavLL&-Il{f0N}o?HL9XfX0*ifz4C9c#g~k|94>*u`chTMJ$mKidUdFrm zEPRv=#s}{Uo*N&8h9886AKapf9`wT_etiaV2<7|@A-NHAv;RooCy_qA2hi7)M^w|4UX- z|Hwh$%?B3zQCt&@EwD}QrA6OM)Z6J4}1QTCx2+lRMExzv|)OIG!TORPsPT%7ZF zfy;=*H1OTfXJkCUb{T27&1dhP6#69TyVwW+7Cz>`oLP3|o{N0fYk-r>UAXce-6%iS zaO9N4)yV%`J0g<>e~Bo#1iw|cVGlNZ$rn}Yb)3%N_Rn4S{KHYzwcT!Cg>vhUw$oU% zwVn18TL-V)e*O_zubCHpf4tB)^i(DGSE%8kKKh)Mqkl7eq*Uw{GyL9F;SJf3fP?cC zQig5elo1F z2)u8Gk2!eyU=W_9Oz>ov5zp%2>AcJUo`8w7_IC{6X~*Z`={#ZxPaga%o?NrO7*FA~ zpT*P3ZW~XBN1w*i$)8JE4p)QmG`1C;z@bmU*VkF!_uERH!S@>Iu|S^-!GLrIyldzIz0B?;$VJ0`}e;`MpVV8 zWaExpkoE=Vzs~tHGLGHZtV*jC^%VL?E9)@0kG1$FvSwW@bHO-~QIj7B=F|RqIj`&3 z{vwxR8>RlKvfLO%50&ps3d}jVk?U9Z0$I^j5r(IaaE2^p>w%nG57XD3Df00Tu)bjr zhi+E+V&})IkKa=jBn|Z3Vs7cM1+COyhNl z=Sqz7)g_nD2}ic8Qqz5--#K#^;_eq^&Ya;lhepPwso#E2K`(G*lFNIg?gX>o?T4g| zG;N9wZn|#t^9`v1_+%gZ*+FrZQ z55`kLm&Vil=(zR<-lJ{PHGP~-w}zI(+)XYrFE+N5?|v_TTj;!8&S+P7d6%{{z6IB} zg~yFwA$7B5!~%Lb4`vaYrg19mrH2==Mi@ru#)957cn<+%Y9e?7--*#5`c3trzrCX1 zu;3s1*q-D29M3yG@-DekLhufMm5hZa$wgn$c7}XUIww1#>Y*~eFPJZM5u-be1Iwr5 zBf&$Jz{L7KFS+hWSl_?Q+Duzsu_w%BqZ&mQqm9ve-KUK8{BGgZTwl3|W zIQ|*<;K6^TuI7Ur{R>^gC+Cv+o6%Ffl^HueE~@J_!4_gSD%n}BF%D_IQDESXLHs` zoX?xYzy90PIe2rvKN;J;?(C9%hq8_PjjXl5INP>Al1=Zg&vxujWxMvT&u-e^o!z|u zPx107}q`enu??u{s zk@jAsy%%ZkMcR9j_FkgBmuT-L+IxxiUZOquW&tpIO`n&k7{(f+-{v-zOoH8B#;q;#FKRqL~j6I=gG1rcaV=zsKexk?VJd`;r<_M&dMBogZ&GCaUMV0fBfA2fARhw{TKdq z`gb2VcmH3!|A#y}=lJy;=k}l8)b}OZ`+dkv=?DGhgv>GXC3{a*=+F9Yb&=~iKM&)| z?a>iC`S!pb-Ltg&Mf-Du=}Y4FWbI~6mG3-7^<6-GgGqc>_**2^q(-skJj$L0-?+{B zpXj?rXemb6BYNr()}GToC3LhLY=h}Bc|YGjjjJKotwR>w+&i!jc(5mcC*Z(yy)#eZbLwDjB=(+oS1q$!W8pyP zsvl=hCNqEZqt_nCM)0#A=Zb7lb7L;sca!Wz;)jtl z6!?bp_^!3bm753pc87N;AF+r<@doYZ@K?T>JHuws~&MIomvWf7Bjx zjuyeY#y{uUWUp4f9iF)PhJi6d&-F51)}z8zH)~tBRBQsJYE=_@+6Z0G zlY;?x&fE)SJ>J=!-K*!`jxR|IUiCMf<<5Qfh!bA{hN_v3i5r1~dzbKI9d!Ds5?gQ8 zJ=_PqADB9slM#RPC#_!bw@A#YoEaz_zm|n#r&>yxk-kLi4$j|5O#V*jgL{mc4nHex zF4t}1m!Une;cKkB2k1-Nh8q9uM+?m)hdeLzRh0bgpBtNwJliNbm&{3W#_t-pF&?>J zf-&p&WXw`FnAU{mcNS-N$+(5a5;xr-c#oU^gwJ;<^ZrZl|Nk=nk1HFY7hmE6aPT)X z8_lKIQuxrZcfD!qC4aP8#!=LyeK99q$j!}z_v$g!Hnlv`*i^HM@tt_wc@`Uw|C8q) zzOQNH?BZ?UZ1b5o`zMXFLXERawXX{QguW}^cl)hKTTC4VARoisSj~mIuq#6=2eyYwIt~`v@FkRD@ zFh=kETlh^JvL5d&c;c3ox!>|D??UKL#usjOmEvz! zxi%u~F{Z#pav2^v>HAXUk+w{A5ohP5U*lDI{OVxu}z>2ugn!?&35Gej~cmFo2TqR+Yb{+EnP{MWI&HfR`YWsFJdNJ!RJX)Cg$|7Fcb zH`#nc8-|_}e5yQ`Sb~7&or>&n;h*rj{=MQ~wG6chpHx>$e5%L_ksmp^t=CNS)U>Rb zw*IhL?!&=9*)4o7Fwt%i{SH~RlYU1KTfjVsJm#6K37^q*b(^_$fHhaI1IT23-yN|q z=#M{?wxM~6&H4Pb7ym2#7C4t4B7IBwXJnzX2I%z`UZQWye2BjP1vzND z05}$3x=U~@JYs(fgew%`B=KzIHOYn0th7TJdTvp2 z_n!ykk;oUuqUAkf-3)BCa_7^mxUKtA)+zGFMJ`6`Ero44YSf4o&IUsz#RQq1m zsX1DvcH*1P`=cW(j|m-xayS#6MSfFOBKly?zae`U&{I(KjvP(tJI;Yg;L&he=;O$7 z*>46WjnBb;kaRu!FRARSQa8Px7@O|wVZJN7$HGS?bA4T>3SwszQKsuqewgyGl%s2k z{BSvTrTsk^bQ!&eu-@K75Svka2|cbA6ZrmTT4Yo@~`qN#Cq%aj8qam6Gq? zu%fKrP*-QIh3Z=e|J=;j{ryUf*lXx<)CkY>t)bGBU24R>^%~!`i;IPc)PfAB(-`3@_-|9ogTZ?>yQoW3NHY&Tt>*40q$~$B#D&T(ftfmp7nmwca4U z(t~n8W;W|Bbzq&4{R#Zgsbc-=c%3dAxuPs{44ls& z^CdUD#~zNVb=ohJ_D_%hxQzdFTbHZPZ|lu~Ke^)qzy1~>z5x2t`lrNCXdfi=BXT$A zj}duqE;_Zuylu!5nZK&=)N+0AH+Aj^TPhuqJ20|`CzUcs1z@{QRoBO+5>I9D!zo2!S8zZ@>AJeEh(QK$IkGBb8D{3|59P)MUk1!~Lv^t?J(DXe{NTG~J} zGJB3>9%Y{Rp3v)w$;gq%-#cr5_)e(M<&0{7Q*W~8M89(!5 zc1c@x&RjD;_B*;QJwIo)CGAN0?2I)++A|9(8xxDlzsx;7VYA?CuQO)&p^o*Pv0DM* zL2m`|rqCvKT6T;0?AlYrXV#Na*)0xVbEYr5<=5zO@b%_O)(&{P3*O%7@b(sKeRg9i zlI?=GRr0<%X}8sU9(~U}yu6W(% zYsMUhCQtKqk?^j=)7(3x>C`*G&yO<~!z!U0`+Y=L*=Kmtfrt6`C#HdGc+%m=&7&R> zehic+YWq&}O3y+Wa_cro)TCEj~M$Z}UBP(FHFmVD-X_&>M4Il<)#;nhyt&^*ANaB`WABXdZpFA=@oCvsi-p#7>`8@yX8^OJCa_Y8Bw9BH2H>MNf$ z0@(>&CCdK%kkHhuOFffio-~cgJWU5b_>#=!`(8KSir2+@nWuc_>HeVRN%Ifzk8jy~UYhX2F%Rcy}n!}=oM0Vs;9e|!=hSo=A&4lI6K*(1Ymf=#d` z_iXTf-`TKp{v=z)ex$%#rM|0S4OO4FN#M=FYT+l)aAG^11t(`SiOd4bee%CxT$d$9mH ziZRdgR(=O67GbATpL>HE*%LVIyi+vjojKH#J9!jqRT<}N3S~^v1~RBr+7La4^AyTj zB>wZe)r)jb~!emD7?wn^;ykeCR@m-7QLAHKn37Ca4_&mx{58o(Fx zDDMJ?>^a$ftU+ykzI+?FZ(Ghw-do9HNlKZ~P!I}K8W8C69!$!q#;t?M#zDJMt zsk1k5&+v1}w{y&Om)wDjyekm968y@2#A(_pY`aCb-D>am|Kp-iN@8X%@yodg_9FK2 zzlOaQL&}}97l?HnYThz%U+}jhJG0wqQ(!HT_Cm~G=u!MR-P{w`FrNZd}H>rPZkZ7@qHdC;~8WBR?@HzQlT-x?b)Rj3tIlwqxB+ z?hbL^m_Ba+e0CYJ#Q4$7hP`#ngS>OuS?~Nvk4^4&25#paxtHTV4ExR$`n33U+3SH1 z(&mr2*Cda#R=2Qc(E(q6`FXiR1`Si>K60*NM0fDuB47D+-9BoZJ%u%R8uganH#?hcZ+0Ru*hmNv1AE_PADMn%Pf z7F*nf7Taj?+pyv;T5NHP^S+U7r!lOvtS7Pt3+)u@=XS^~o%3F$Negbo z*su;els3D3*HP#|dgJozjdAUDB#VUnE!~DiTt$56O}E1d|lkrzG({lgav5Z7W_@dWb9kixC5(x zF&=HL#oeKE{zk??IoJCPcodUo%6#5_WJeX5)5g0WBN8NZF6IT3z-e4O^N^qb%(=bRMI>BPsm z0NCdY(C?yb@XRs9S~+Xn!=EzD-J*T?T7GlKwjGPPk0I43G6j^Im+PWvnDUk&7lkpUY@b>@)+cu z058woFSiwYWGtK1 zZ$nq54)3GCn=%J>S;p2I+t6ONC*|PX@ar50>ytz;cdtLLr9q#y=C7c>eD?_22uE+= z?|z<9dMVC{TFAY^pUh}}0rLmz*zQ4xrQQ4EX!1&I0CiSuz#q1@#t(^DKcPOuCztPygl0!QX@b40LqFeNdKqlX4w2(x%LnRLuB}Xh9xp^bz{mX7e#s~K1+=ebOiV?7 z42M6%`iMMm=9i!O?FCIe2Hiwi*Zr33LOyz``NwE`As6z!@xfl=+t z6l+b$lglt~0H5pj7tnqpjqnfikMt$5r|i8pew5rkZ3y`B!D{fM$l}LaoR1KGluX8V ziJa?+@I$L&o}jN4Fy8tkFKvsr`Dys*qpW^FPQaNgXGJ%r@Ee}2OX6{f?V%LLUe|N%L{+Ij(G_tf!W_yr9^W z3ADM5m^aUdE>fnnaahMz3>$~Ftg;qoXY;So7ZG{tJe$P<``7_p(-;Q39SD3)wK>3* zY2sj;4m^&D6SbYPk3RHI>@B`MYg&i;B7GIC+inLBlhEI}!szcLss0Z8OSxI_4Hjsb zuyLHL&uadq$`gEP15aFx2aR))uT$1>FF^Y;S99V$o%NP!QQuX2Y_vRfl>H}o2!v2%ro{Eo6xjqYi+S{L>81tD%A5YFGQIm14kP5tD0IO-R_H3&`(H*nw9rZM6A&A`F= zKgEZopEb)wSv6su1`QfnUzqkPX*=!dEQm@9S~vZ|B*_%!%H=wp=LkrW<>`iOI_ z8|uAMN2fHu2wtKrh8(?8N2mP)b>a_mTA*j#yO?p%!QS9kVW*KEx|kVk<~P!R7%ySy z@3TC!A4v+AdXvH-z+r6(>q=TFzPG@7w)FgMNm)GO0sfCm^(Pm}`e1&)fNxU07&|@B z@X6g+&j23@XZmcV&yTnQ;Bn#HFlP{W4BIjRb;C~g1dhSVKE6%-{^Ad>k#>`Au_rk1 z*B1XcZT%#`8g(=sb<#6Fj{1POUU*@Jp8#&|XHS@8!K26% zXE>lNT5u2S4EV@(dyscc(*)RnJt#veE}W^vGoFM;Xq$?(yOx@;XonufcaYBYN743O z3Ak0LV_S(++u8gb^gY~YL%f${G-^*~@Y~W!kDxCT1Ya|;p1}J;#^i~*J{e(+-A`tG zYc==TfxQ7QI5tdp%-fu2{p0sb(7$Zv8{C1iW6j{Y)6X`nI~D0m!H+-4yaV%pno&Ac zwYggsVm-(Xd~-J&<@j4wju7soxky_$T6m4Jv)sguI{qek-82bnJ+1%`AVa=aX+e#8 z0bNOhez##gMToln40M?K-B-7%&t~7js=La^C`UcHTFyE^{~5e=P={Feu&(SNWi#2U zY3twlHz(R6u4{F8A93u&em*>#R71bsnb%T=F^4kx{qVPHnvCxwCiH>9{Hz6Yhx+!x z;U~^=d`k(Q()N@~J=)>O8}}e^kHR{&AoSqHqzvzKSaYIm34EZ68|YKJ=Y!6qw=){Q zncOfI_7d`N$^P43jOS^e@7Zz!ItzQuJ_Orv_EEN=|A~wJtMb5QvQI$9mbYk2|FA*U zAU}XLF`(s!M$PfSC-6m<{MSCvm%0UOC4@#F>iT-oC;ECuyHpfumlpPKmymzvmivtM z?>X!dfWEM_KcGX}ANs)d_GcaR!t%-9-z@D9Y@}*y-cPmKALzacJC!PWs(9%joz44U zYqrzwgfS-MxVlKY^Hr327uTB6PEc2X#-7$aT-P+i7cViF# z2fJApvyE{BSs%%<1N#_6{yzQ4Wb}!*tcBc=7yKpH_a_9?U^3>qviy^qz|+i_0z0Z91~+3!M-?ovvwo)3f+YLmNvcFPJUv)94(+} zU&u|RXbo!I~NzHn)9N!SnhOIu1l5l->yXg$8S za|*9OKY8_Zr=E@WqBb~OcTWt4%LCf9$JX6f{yLuP)^*A~xbBeLL+jp?dq?ANx$kbg zO77i_KDi%hTq5_L#{1-crm>TEU28lf_w>g1%3pu=5WanS58plw$G1;c;oB!4zI|GP zZ=deNw@;n;_URD5eR>byJ`KmWPgmjFCm+6jT7qw%?!&iFoqF$~L)Zr^73*x?!}#`9 zlW=aOQ^rcE6I*aTD{PgMdct~xdbHc8|MLg5rLqs&)L(R{@5Fx54*kS;V!vop---SB zRa379!11^Zhu^?aV&Et;aBLtBes3mvT9YjKb9@i7Kwo9gyG2^%4TI%___egp%nLGc zg%-Y{1#w|4`3D2xM%)v9a3r=o?cJ6~j?|0ahq)K2H{cOvH9(#?b9~_% zTb_8YOzo2==L>9kKK8Cpf9{h$c`9Gi$dh>ir}fRDw8PL5mV-JHT=@Gb;CFUjko9Vz z+F$8%?6U#-P1=jJuX5}_&4&;lY);?u5HIyi_EBs3Sy5i)hjMlU`w`4%^8TOYv3zd& zoj42L#K-ST&3x=Qsf*D#Uq6#q`MTgFz9OysHTs$&501+vy?&DIIQ!pu8hlW^n|U+? zS6`aVIYiFE1*g8=V)~Ta`yg2PA=Z{xbg6w1KFqb#MSha5n|`DEt&@NKdWrDS^v7ZI z(KfiDV-rmu9sX&$+TY-Vvyh*kJej=zgY)oX!1Ibi$_Ms!0`v@i<=41B3;Sc4j8|(4 zE9Co6)(iB(_u~u*C(nVPjLb6H=UJ32;kyL2B;?1vA)rfadzJo~yk%V>|LTI|!D}5X z2kSNKH2S2->!mR!emf82;Wv3i+{^>Gr^NooO`jM2?c#x_&HU`;k+sfOa1Tng|AoCA z{cYZlK4HGf=Di+N_UiQ(Wv^ZjD0}t9n{jYFZNpJw;3zV16c{)*$HB4Mh9ld+;Wlt& z891iL!7)C9coENQ4@Xa8;YSrNdL$Rsprt) zV9RSKL@$e}d9VG@GMLzwXK2DI1ixnMR zIA4)-q{5H)FMy7T1|1aD+IlWAz2lF~*?dwg?@E+7%s#+CWD|VswmbGU&L@M#sd&>6rAe zqT``gZFI=D*uh5+p?r@YPmGQcA1gY3__&RZQx`zT#ReVu5juVvQ2h951L(LdK{{3# zbd0vq@p$5NOq4zGeEN>3BXqoaTG8=puTSq1|1ZA%NIRwI_`!A?9V;$?4)zzp{~hCP zbj&yCmtW5^H)Zxet0|Auc+};n{RgE<$9^h%$MbB!Z?yLf*KiJ3p z5Bkw(%9?&y6Us+Fj6Pa$>MIk_A3J+5#+}w)<@gczCZPWni*I&cpM1d@ibpAL;rrCL zk73+_^Q7oECqEXtL(}L}TmY_lHeB_8Caw`STDjL@NS-nD-==53E*eNTP^V;EC4~NyxmO&+urHj{k0910Vn1Smq3<2U zxz4ONSm%VXNBD`@laY2w!YaA8>N8<^CTx;^p8YV)nZeE_dl)Y59M=2W{8Kd_1$+57_d(24 zbd7tjlXiU5N?Q>~K_B-X&Sk?sT!!^9$OHIO?fAJT5ymyy_f_@_`0V}2z|I`MfgkiC5}pgUPsxHP_n8D>52~e@XU1 z3lw0z55F-e#2#2LVLde7r|IWax&U@ zjBTOqQ|-;TQC!o4{j<~ZF;0(fSkcGY8*c3tr@%>(jrzT75Hs?|L?PIHsH#;I|^q7aJ7r+djscK263SlF?uN8t29I zv&=7$`oWJNvyG^eLHk@S*8$sk%=%{fV$j>&w9(L8sZ-!fChcur2d-|}Cu=F!)Cdm1 zm^$&SZOy8^ouxjhF^&D*lqt%DaSqKxzT$Gy9@upQ?SdoVRk~s7jfu}3L!d85oycq1 zUnf2b*0NHsqS8K$K4uH&9`%PoqtqqR!Z8Jd4$CKEon^ZqdWQKH@<7hwWVy>ZUgEym zJY$vfEWkP4EH`n|4j4G|SU%PZ85hEO4f3r>8<&%3=zbK9M!gVQWz07ldR|98Z{CUg zE3o(OTU_IP{%MTu2wvC^cit$@<3*R5XM`euS!+OjRe6tnobsIfuvX6bXVtErUn+CV zoa=v->l(sr$J(GLAt?`NVR?M|10S1m5*p2QsLEHY3t&GR+A#8t_7v;r?r+9BePixj z!+mQI&-JhGGC%BNTflJv>Jfamt7WYX=@Q@alaHflFuv~q4XdMQxZK!VN6qPlM$SA@ze(JqE2{${9@{h z`u5t~k8d~IG~x@id?|xG#hzS!bmo(bf!DIbHk}bY6dl~5_CVyEpXeg?K%g#S49?hJ z^wtr99hYQ~A9+E1i-UZ`HYtAYkJi!iKNu`Ok*CpCF+ZvIC+~=0^!Ft0FsJnS`H(rzw9oP5W?c0~3>lJJtNNzayMoFA!yt_5nm6?4C|35guS~<07pvzaI}I+&6~wYy`<-t!(+YCQbbYL6o5p@=} znBNOvU+0ILn+&~07~X#%^ui8Gy8v6w{l$v3zgueRn%FQ+@r8oLG%D?8zS>UY`4+=(mn^Bk^aNrxPJeJ z>^TRW65pKt3g{SU65DL|>0|Xh1h;A16dyXs1Na2@1Bdhz;JcHOhn**1e@i#tb^e-<>ZViG{7!pe+p-IlmA7rc|WlTe7s0_k25B~J69mf;Qf5X`)GY8{QtT`_9HUK zEvV01?R=NDKIBn}qWM4G1&t+m_Z#nT8a%@}W9VyQKSlc2Cf^&scnEgd~41`1RJ?93LUG*XR=yN~63-R2e8|_a}{4UyW`dyGgq&{DN&Zob72Ynmb zU#xBPdiQCWfgp66K9u-DLsGDoy@czpv7Wzx@&et4|MeeZjCb+B^15|h$?rd!08>Pt zOyqYX<@f&M;zOD8TWHoD_;i*{y1obW%n4iqKdqnqj!E5#mLK6yZa3&R{YIPoP!EDO z`GFqLG1`)!dcUZj{8092`HiWuhkr&p6h!0VTXN)89S@>f5BdVR>%|5wLe{VDCMn2*% z1S;Rju=@;lesatYbzwL8%CSzV6W}NN7Q##P2^7DsgDl>8BO33A8TR!EcD#n1)Hl>9 zo76GXHK|XO(LQr5a{|^Ky|YI3umAnH^mQz{|2+yn_=mnf=Jd@n+xvvTU8GHpjQ`<# zBJnHXd$Ap5`B7i79(U06w^=-koqiMdK!=>*BPPjQmD#VMEf=2_I?)6^(l2X*Q^@i* zU8SE31ZQE-;3DcDbl{Wm5nFNUB|M9rXomfO@9~t_2f6D$ zVRLDR&<@BL#$)WuUwI0&OWPwpvE64i{ciZ%w0qpQkn~X|q35-o6LGdQ=`_cF(NFcW zjX=1cHl%3@%ENM8fpXl3{-!F2%pGIQr#e!W-jAcp(tAqEf^U9l4~_DS2qI5@(`(pB zvs~2!l6*ez9M_s{zkd`P94W|C#+MtG_dBR9yUq-@|y`D z2)@~;&&Iie#umH3JZ=x@s4&|u>2s*|%a{XV{E4TV_kj->tCG1T`e@taoY(ZgDEh|I z=dkq;-lhL2eFy3te2Vd^zX5*${fz+o8juz1rRr~7elO%xFJX{t9@=C2aquNa1heqG z|A;>jMBk?Sml**k<`GzLf+)jwj2EFSuptsA-{Fj=zlZsOo$&t&hdeO;^mbtXL4RP! zPcs7R{vGw~+BcY&sfz>kP3*jEeiU+g8a#&_MWz^smhUJ2gnr#U!cU|98oL<$`YgWV z(*jx1eGq*21ONFQe1i#HZnMjPX@2#VC4)<$&rvdv`0JXV=_7-7y9|2hS11|4=E3LK zFEYThlEH5uS2B1ZL+nip?$9fdf!H25{7lGzVa^wo3^0BN+1-opPauOHLk2HE29V!i zGQf8+{bg{?9fAGFAOpxyWN^)N=4HuXfPRc!24e46pEiKETQMg9J~jvFKiGMhi#qbl z%>(n2@yAbH7%$&h5zWhYDiklFi?rP>xJU8wvZpOxW*@Tg^5hNCyo5e}DqfENY&0*& zJEC|ATM*UPHf^`^V>-CUsr0SIm$~L8%hoJH|HSZPq+Nm>Y46aMbcl^H@tAD@+8)|s zIj;qFpLN5hzx{3SM&=nBzlAyuJFM)K^Kw(x62`eA;IsTo(|3S;rF{c!f*X4TtNE0k z_mQ4$jG9vk_K3|yesVq~+b{UE4xt5kV($A1j%{&nj%h;ZU$RU-z2{NlA-`k}8@g@M z^(<(J$v4yILfa%X$^1^w9YOfof(zp;_$JsvyDaSvXhVN_)ByR9mNaNfB>zio`GX%( z`I|g3^9OIt{MFvczd24CI7TBlA+Kl}{$s1129}?E@aezdJYZZN1YZVi|4aG^8I=EX z<~|gV31uX09bm+l4^M93o)OLWz%Ii7qpe&!Y8v)TgI%)Pyd3D#zkU=%n;N(b^7}s8 zXnt4B{t)&+1Wn5Kco}U<@{39r>A%6IKZCq6HoZyo(BzBq6*>YhLPt2p20l?&Fvs`- zaH;n5PMd!Yo=ZE6Hi)tYKGo+l+i+8_;bXCWSh|L`*&M^eSv^k)4%o(MpXWCtqQ-bR zt|ns-jxkobsPo9n(s?sqRWBnx7368=*Z3^YnSJX6sZ&OqsoGHV(SaYn&6>FQZRKkI z0_ucWhXOhN=6RIwTbl(xeJ1D-+ulG6R&Kt_OFZc{vuNEGo4<&5{@q@>KPYxpPlr^5m`k$zdG=3q^Pd!mO@~hVd){#@3 ztBfr}lYW!u<~#=Y+z0>Cf${f#6bnE5tmyk$-@eEksPdD=Kjr+YmuK2xOx^TQh3lxiPa3 zZTJ*2wj(|T@QJKI8~aimx98fVh~3KGh4X`NFvi`_21XhF8TM4=+NHpH_@=ZiFL5q! z%xY8T=_83e?d@FjdqaAB^>%nz{ZnZ|c^0eb(j4niO-*n$%NMXHu@oV4sJ53dYm+ z()KrF{EBnM`P;QAflt#Ct`wdxetU|Q|1Nt_)NAQ?(=}_wo zCU@w18_rh7xBgo2IhH4fW3%o+M~*+xG8E?#C&4ycU8BBf#=5BIGHG+>g3o^Hp`F(z z&CuiMu^iY3@pYhgID0$P44wqDkQdj*ZP!WzLoi02uZ1{&k1|R-iFYsbM8kWi`FX@~ zY=-@)0Oy#$aIx?eddIaxFFUy0T$n%n>-ae(61jmC?9ho>xKsAV-EP0)dW2V zVm!+Do~r=5i@l}6JJyv)uEPEva(+_oMhEtINCh8+c0zLIZ{CFTbn zHu;8c#oW|Eq{}etJNshz{`jz6C;2V4$wT|M)Pw8e7w09QkJ%WvtBWeHy_}|=(^jEe zv|H>4@jFGx+^_ah(2BU%bmI=;d%E#Wwu|NIU-mCOYAbsN@u>3~EPavsW0uwOT?W;c zFRVzQoLJBI$&mreY5I1Mp_G$88OmzOu^szxQI3XBq~ti}xLFq370xSBmXb!v@Q7W8 z7gnax+Y>00*Qx`<4SmD@P~4w0u%5b}^CRhdiLR$>CD1kQ+t|2)dkGAn>vq|jJOM9a z$Ue5r!Gr#M%6Y=Zr@xTQvpIGc&(=<`_!F@aQ~KJ7fouc$70Wi*?Lbu9&ar2<1ssP1 z@1$*)aX4w)4WBTp$EW|aLhJ$kLA2rQ)BE&e^n0Z|j2oyOXZt5>w;#qlDdujrJPiAc zHmVtI6wfx@@;vrpLH`D8{k%MD59=q*J)B&Db-ipeRQ#~=}SOXa{*ZQ)2Y%Ayw zH@^s9g>~W{w59E5yg{d|Gb@7MlBwoWvNC=8s~fl`Hn<&EKISzrCdIad^LT7qgf_G( z%`d>_V%#5NMMb2!al4GGk?sQ0&AA=SM?KB<4nCVJu=WgTkKLA-{(-qJk+ur$f}Qrw z4y~Qz1yTn1@*KlqIXG5|wlA&mTNo?dZkFTH`9A&Nex3ssY&XhrY3y=71l^5lU>ZhBw z5anch&UT!BNb^3W4@KJL735=MGtRo@Tu4Qqm%LBK3q*7H``?0Ro28`o#s z=SxM`?dvcB%k_rPkD!c~puDK3h7HO@zx1U!d84#Z*b8{XRl#%(x}Q<1rQGP&(ly@U zJ7(gn&>-tXsWxPt8`XgK#{EedOv83NuUve9^W3wg`N7R6gIQ{iDz7@X9^Z5PT^)3B zHElor!+^KPSSS9r?c92XVIO<13S*wAj~T(Q0bi1VkK^v}F@5?yPf(vZ)`@m@DD%Dj zg>&BseslAQ$?Ns=?AJ9<-P{8`%MS#OjAg!{CFAxNwLG8RywymXjy2+H-Ztxvu`CB* zurKuUZv!vJiea~b54MNj7iJpIZ!mwnr!!vBQaw-lf#1VAdf?-le(1nP_~XHTeRiY1 z8udryfjNFBapk3w|5D~m`Oa%Ht@`TBA8b_Vw#d=YjUj=azMvd^+T>*N$ff2ZKUo??y=NKOhn92BxZW0hl|1w}i?mDj zGd}bjXhj%klD7W<*EmHl9$Qpi((Wp7Jp-)RcllvOL=l1EZk=H^C z%SSz7-{8XWx;`6?_wXlw8N4aS`{3oc|6hRKAs6?-J3SWOC?8JgntaD1^DYN4F8Jk8-?MsrQ2^q9Yua;}|W*5wVV;3hP7WA)Qqp zSigMw&+b?HQeJ4*6C<4Z(*~OuV!X%=Hm6^oE-t;{H)7B`J(}KE=ESDg@q_;KzW$b? zx9r=|^uGSmUxwaKXm|VY_vP);^uGLPYxgAP8!zjR_`DsM!+6=Wd#_wBV;J@^c+C573?4q;M9|p)y{%(9`*@(# zvp=6s_#4l@8KLt)6Y?8?&X?B=Oy^6-2c^?!JIPP-Qq~H_;wSufX-A`YIkFx!s`Xs3 z0Y3f3w+5#1r8oQ0h<>e_&-j}+qiD4Gu)@nfi^dU0eEKu@NBH<6pKsOInx&rzZ$kn<`r;OjG9+ysU2iqA+NFdh+nm5XQy)wk<2e(tib#( z4t(A(e&vJ8FA9vZeSc)*-G$TDd^9n-e*e?}bS=GLx(vUUd=lS{yuw%#*XhCMHu%*% zWe~djh7WJ_ThcIw_b(|pbKNgKoA?F4Pl=)zbEmXD_*U(X0qM2*y-|Ejh~D*^5~p`~ zz^DIsPBgtA&WTO$XCA*0dVga2b*k+YzY=|{EZS)Lspua$(WZZdu?Fr7d>Z;KzKDIE zpscKFO>I?KWkqdm+0x}zt81&vYL?a1*HqNje4~2hsIo{Mc(WZT9j-^ZQw9Vkkz-FDWaY@s<3NVvMupmrS!>5I$q( zj6%lWoL@4#ka;lPd_j2WtT~LIrXCco*)!+NnpRjgtFR=$wD>DX1-NOz1H3Z|XO-p8 zxTQpJO4!UfrS>p?ap^QPdy>XKb9QlQ@yr=aUr;=&aGJcRxUUqJ%$!zSI*)NBGiUmX zXWSxbrp~$f=E7MD=9c_oNjtrGMw#`TKi7JmIjgvEMk#1S7Q{2F5J?MXfb@dm*`@h- zPZF36enDJ(qf7Z-tg|k&M!rnY{*7W?+vgtEt%*^ZaKK{!< zZ3~+Xh8F^=e;6T&YgQq$oH1>lk#2VJSB3sLGa_{Q3uhEq^heV&4UD*T=B%=>6waD0 ztOZVl70>7wmS0*rt9U9DV0M|2$F#Eil9IAWIO&;IR#13z{+yCh+`m!`>CE;QPAk5- zSj23^#||%?TUt1SG|X0b>;)rU2z*xIY^+7a^Xz#u(A$#o&zM;!lC;GPz@=!opmf{0o1Yt71dq` z%rJXhH1!{vSWpO6H+Te9u+=KX*Ql_vX(jp7srXTq2I-Z;m)(X(ZDxK+{_3il<^I}= zHPtI8O}b@u#Y%LEwQ;ycuNu9|&HFXARqo2gx$e#nLM{*|@W6?Y@wT+lbVw(9DIHT6;~{-}S$v_&hIFGZG&bFW&ydSzubp*0mgXNGUa z%-d%e5h!9kFxSUcFssH@F0NR%thyFV1C$iT08$}Q>Fhuf zF-$8F_PGlcH#O~MgGX|&S$3z}zZ}IwyH?C!+=UTtya`LSIY#&#gWZuB%(H-XOjEM_ z>)Q01hKhx?)!Lk8ON}R#VHE{1ZLymV{6D&C9DkT5IxcpY32cKEK=WM~!z`wPnUaA! zUkQ?LO8kg|^dtH8Pcv}bK*$EjU(26%^|j24cQ+gf_iTSb@y(icH^Th*@%!%9=vVmh zPzlrtC&UpBj}a%FWzeRUr^D1W3# zT19<*_0qa}cl~m=f_5uDxxZdhzu3KOb#1M?j`|duw z_Fg#`!976yu{iPj;>35viEoJ$zc@~ONt}33ocN5v<5!=H6MrI3e0QAqopItf#)+?u z6Yq}`KOs(h=HT)5=i|ip#ECx;Cw^C)_)T%*>*B1q)yX*V2jj$d z#fcBaiLZ|nKQ~VNlsNJ3IPuQG<5%{^i9Z}Ces`Ss);RGEapLF4iTB2d&yExC8a#f* z={WI6;>7QX6W6_~-Z=5?apHq<;;Z7s7sZLs zjT4_fc>MCSapI4~iQg9|z9UY2OPu({apFtj#CzhzXAB;{>|C7q6LI3Z5k*rt3H9`gwq9-gh?!dCwo)BKMmB&p+=3&^)-=ps4FT;a)>0Y2h zyo>mT^r@HssT}tkcfb6{j;G$g-)p45sT+a#^UAOKnY`_%TK;RVNuS~dGk@a_h)hB` zzTq#Kg-_7(hlX&f>`UqCX$}VG;BxEXiEcooJ2h?T?fB8s9&+qR+MdkEoRM{(&0mKH z?5~NdL=R8O(zK+xjMMm&j%Wqm?tCysQjhEw+}Vf?VB3rW+>00?@Gb%?Fu%e~8g>G% z3N#$G;Oux6csbxm!x24vV;W#j#)OTg0q_n@50h(-77Jcz*q$6AxWi!-5>j(`^l*L# z${2yS)AC@-wjo=Gwz(8d9a2&(twOrRdU#qn?gwJ!6G`MkR)lbkG!ipUl)s=C_tw~H z1-@@O@Xc{T58pf&cVTTGc`#AhNKk}7%FLyQZz2CCAY#e)7@I!Q5CQp`l!JILa7D_U z_LHQCl6N?_r?d|tcqS+|_>@f@(8EQo2<~Q_`X1)On&g3Tp(nk96 zi?Sr`0$dQ!8!b3PP6n8fwdMirQ9XRC3$TYR*tGpa9vZsCwLO&~*&~Cb^e0KrNqnq2 zQ1iT52S^+0z^z>h-^pPFO1_6+@=GVi%!v?SJ>Lk2bCZ$$N+}}<8 z&M?6>5=&>~k7+mQ;TcGqRKmReh4Icv1&ZiN8nRP~cdNuGw{}nu`%fU>gG~E3lKLF(_l?ZZj42w@nY<9zyVGrYW=1@F88v5Ks6c>;XMIw-(QW|C<)9vQrrm zXu_V+!?N5@V83g@_QMPQBxUL0uOh-xi=QR`EFfULS!BMafoM`8_9qE8@M~3o&m{aI ziMIpWD8Z+Pzz-WZe-GfPt4n@M`2I3$b5U2mJ-jt-%Lu_ZayJ%csr>fo;RRl#cQXCY zBzD03Sf0~*xGV$k^@NW_U&xdIY=NdFqx|KtAxTpR{|fQPrcZJn*(02Qypv1y@WT1X z=Lpk1E3qbB%1AOO1FCP-8^|SjqaLn2hhXZj;LPp7(bnVf@Rjt6k$%5@yPrfU) z-Da0a7s_AVi*z}$(=o5i2vwq6PSpQJs8?Dq(@1@`wShK?0>2aTzq1Yb(Bzr0HY@4+ zi8OCnRu+(n6E^U!D$ulxX~g#Su`f10c>%v$4=({dQqPw>gha4MV%^%spt$xcgZvzI zLW7x>Tf{umo;%O#;ict}Ya8?Ymck+Jx@psFbrJ9>*?M^SLBP`wSkfF5-jXHwkOKLy z*aaGC*OxT*fu|i~kgZ(I1M**a25Ce$zuqTJ4EVizxE{KY z2E5quCChE_3b(Whpo;cnNQNH%I`m%IlQ^(mJ=~C;AZ#sQSw_*1LGXefLty{b901<) zpf8Hvh>R?r6CU>e8zB>Z2@5r_9ufYW9{wiksKS3|T==0mdN=^yDEP|3;lbyja{+%A z@)6r4_ItoO+HKka=+4lP9$wdN>dtKDV@t=^99Ey38x7Mzc@2gA54udg`fO?Vm>IGE zDECm<{~+s+3vp&!ggQz{qkcvzHQ-&S|4n-UpGNpw2$n|AXFzzr9$rs5oF)7;1#i?X zzC@7Y1?6?2{x_Ebzv%HzQSh{tDvc#+vHLFAzZO5zNV{}>RGNNyOhFze_3(yGfZvGN zCD$r=%Of%@M#caZ13XAY{lDiZ(zi4H=T-Va%9M)wztM~GiSAyi;KdH|(crS(&@vCy z|9dGzX*)j`KM&OZ*1dqw0O*p>^vNR&+F_bL!@&ZtQ(^zV(~dMEdoe;H%k9!RiIE0$ z4TJo@TaPqeWO0`sm#$%ue_IRSsUdg$Nx{b{`>+;0yp=joz%;*CX$Imi^nDoQ|6n>; zxsRYUCN%WQALmQv$Z}OX2-^c!1G3jjELfvH@jb(G^R*038=eN(E(Eiz<{x-4JR9MZ zKkdKDuTMWIBhnWn9+c&VJ%FTsntu$hMXwby?uWkx;gCRCM)(5fcD+7;r^S{D}V9%jJ@O8{ts?X{Y1BK}Sa* z&jRFa(@_(ja^V$5s4HN112z}14U#t=@W*hJvtSdRL$+|hjp)&|LIg?uji%M?k1>Jj z4WnEmp;tEpU-B`*!=DH(Y4-Eb2tGMD{y$gALQXU ziSTyZ)2;M<_!ez5lYpxjGVg11l7OrD2*MMzIZ5+1?bc0zue0(s^_Kz4=48V!YXRI* zgbY@Pk#|xT;LZZB&BE8O9F}*|U$5t`?xWY+JAkttxT+o^LYr@AR;j1s5~bg&g;ah)y449oEbAQl(mOZe z-fF=+BQ2`Yk4le_CTZYH?(Ds=G>&W>bysu&X&?g!eCbD_v$pZW410TT>q#lygD>^{ zDS$s{m1S^v_)@!|3yysWz~=z2R}cTN9A#i%&EPE@4pqS!WR5LDen}aC1?}3-2rT=n zs+*dooKC|fOf%WbbR~MYGviaFgI((kUSK+uDGBoLJdJdL2%Ry@lnq#vzYF}0QGOC|cl&OK1uRz!-fIXHV>|#CqIMUc@9T0CTU>g9d+Dp=B_`He=%LC+V$O82o5n$*(6KH%x*m@0V8R{QqY&!9l&#<@IkUV+1D3wRg5N~LwmT!xD2J;-4FMf zyr$0{@e!~&8va1P3*~`st4pn_&?Zk5ufbnSU$yrj6jkNW8_z=qOm}{lYKrA(d0je!R zSyN&E4j%yAd<)LbBL&+XDQoIsJ^b1kz_UHP<3AZ6f#;hkE9hzJIX(QdDuhMok1zxB z8J3CoT`1o^CX8YCR8=s2xS+@f`pvPFpM&<~E-Rfi&e1;P!J*q+TT|PHeRueG(!MQI zBUvMNo18&s5a~mD_{}!xsi=!xUVZt>$(092GM7j_=@v4m@57Gi;a`@5{$qf+<0^th zcwtAyn6#0Ke#murx*q;@3-a$}M5NrtaQ%bBx20_z(I(kW7}=e~y0U)=AyM|>(EpRL z9VuQbt?QxG9mBQ{Z%=!0#I})JKhu`3vOB`MsnYIqF}3tZhi}4|$5A|&OL_@re{}dx zP4hx#TCOb|`Z|0c!jYfmmvH{r%gA@t3ny$ZV8IWguOe~EG^vVdjVd8O8B1vetSSc{ z@CTX7SPJq?w0|UHDeXvGEA$B(8Dpu(*a`I1W-Cp)BQ!HVq@4=d6YWQ(9R~bKz(?8- zJ6_d~0=~4f7~=qbTmA#ugb{AQmIF3YS7VRG0q=+sz-|I;iIkT=X8zG*B5XT3mLN+w zhJp1idBwVCt2ml1|-VyG3u0KO22X_ zJbu8Kyoju4DgMape^U0q@uvdZHzCQqe_^_4o+_y-zJV8i+GoQ4Sn@E7$`?z=iMK%y zpC|v=R@v&g@L5vIh?wX-*R!05Tpf`%BtnC#K3Uet(ga{Ts)s*;R2^)i6>fBz9!l9U zWc$!|*Mq6shHaHr!CKcqsBFNe>EUn}p8MPT2t|a0{}t|u1D64~`KV__fK#><5BM|r zZON?Y9!q9!#Dm|0dyh?K%-v=9xc$@L+&8_Be6@h2x8{Q_-h+M({RRCn?zIsZ4h%4x zD7ac($A(B)Lt>+aOPNexg8Jje)e5*e+*O{YY=};2hX+r40do*{Rjw$XNdRGxRf2K= z;V&E4XW zxC?B{v?^U6figJH_v3>a+f*(eBt&$s5trdt##7pL{j+D0Pm!dHk&kWMhIQhwu755K z_tOH;B`fyo;~LpBoS0QzJE!Xx`SIM+4_2+&a*YhR3|Nex=ojsRec7a7O{AtV%Ql$< z8XSII&t$^xet4yDBROfvzYt&pfNjS;OJFlwmNeJGOg%Ju#}~GLu|4O(G26bh^{Teq z?_T|#vELro>e({>fonEj8=CNs*Zsqn@4r5!c1p?;Z^~T-DK$kYi%U}O^rtK;O{t!n zQZ+xNvOHyBRZ7KTvxRg@?_Q%m+f}{(-l9;CRG{t z)NH_)PULw~x~^ZG4Vs)nlVLXdme^pU{kE|%h+n*Yzs0TRg5q$8l` zJf7SBPxExcUH9;FGS;Q2wsP9PTJ{EfhP~214_l`#7J9AubBZO?^zI2)1i0D+;OYQ( zAOW~GU3X_C0M`w;`UK#50e3h)oCErGImzN zz(neZ26NM8$Zeapsss*ao@-|;eT`;VX)~R5q`I>kN4tEpEVwQHXwQc ze;)TpAH(j$SaY)um#$yq2V8%-DhkRG2mWHsvwlrC?vZ|wWf$!Z1E)h}Py#g523$)T zx-6Pa8k8M~6qZdkWor4MH-xSFXW+Pg3K9%v z=LiS8etl~KaCLw?9S1H8@v!T8yKrw%auya*y%8kyM|*XBVmqGC#n1zDI?O)L>;)|R z$jL{c2&(?a@Cnp(n7z)BS5a%qAye%1s9|oAQG?)6DT5pqLj86u*7d0&+?5Y#w*#i1 zCZOVH_w{4Rk4#;^8MowPlCPyl2trScKYe^(H-eC+cqh_yN2j6gF-6RD*(%-4Gq@|8 z8=+Md$cfGpqufubm!f&-fb~rcUQFeb2_cKv&5h#{#ldj)J%!)q|+l(Oby}NY1 zbOQL^H!u4bk`kQ4OS%BBoz(TOW*}W%RNiKrY6@JXQ4$c_u&r0w8Edz| z1I#(<6;(E!jr1o>Go;23u^gYv1BK2!z{7r2&PDp17-j0)z}Pw1&!$ZLp=DFtzz)2N zytte7ko2hZO1B7uHhod~ATVYgk+ynbp=tZ5Ps{^l*4Qz))foKsD>G~A?xMwr&tt|m zIoRnS9_a3(2HdkEaF$b%jqr_#ug85bJgEO{ix#!uUJpFQTZk-T*ZF3y(;@5$z#cYX z|8ZbglLwaV&YNoSIUDK8gLAmgm+~2HE78%5Grm6}T#>HdiMB^8RdQCEMYulx6KwaL za}iu_!o|RaF@QTsdzT4ge)AN=AB@QE`g={;ksi=pgF34f5WnD2b%d`bp9lxKYdpBe zg9F_)sLOHT+5ktL7z`if(+#*5-06oDWsoY=>XLY^S zWx_r=C@k$xZIubTb70tP*eJ+#Y#Ly_1T%Gx&o+G{9O~#;+~dNv1CBC?hwlL3N)v!P z4Y=C)aLLg3u`LO}fwr-raZvi8cga&^cnxw@1pIa{VtTgQf&Jj1JC28Z3C}q z+wMA#dpYr>Q8>2#s^w8A+X0_K>P*BQ#m;ZxM|o(Swtz!oJ4djznH6NEhv*o}Z? z*$QS1S~f?Ht}ks(46maUuzM1O4FdLP0}13e~60LmKKY z(-?N8PZ~9JZuY}b21l)~uPOnw-%1m^41`4+ys81Pi!E4dOn@O)zm>2D01JC$cM}VWs!f&UW`Vz^3_`7snw2JjA7SAKlVmFdb0G@j3jR~)y*~X)c$u7W_;<+dR z*a?7b0qm3*unKEAVin$Uz_N_-V4;V}n{ccg`5g<^?B6N;b%LL1x^;aG?zXiXeR*hh z)0Cu`20q9)P*z7n4Em$(tdDFb0q|JP;VEz)<0z?wG3k9flF1}yHjv8f2G!b?a63;D03Ok?Sb9Tw$F zf&3dY0lSkC8h;{q`|3K%m4f=;xCv0l27otp*Ytsz2kL*2JZTvq4TEj) zFb&FoZ}tVyg*2%s|GoYTNQ1JZqWt#;kY(4lA3q|}rYT>Z@JDogTa^j_T3q}iG{9T< z4-O9R!J0acu0KfpBJvn*hFK?2wE-ozb3_%=uwEyc2IUyhrt9q`NVAh9#mt8hDi^|| z{cG<=NTTrPbbb2-z_(fWqsQOv`V0IcVgI(bUjY1EUEe{}l(V8g8b5>0HlO%60=^{? zc%F5DbF0?`ijp3~*@`#|QqBU~oxh%E=i+?d^;)Jn^I=$VE|wn2d9v&EGdOE7a^^u1 z_lDKnLF5?3=zA`v(~vHg=Pw3dz`1TI9(P%|bH zk)AZjIpa9fOK9PFpT9QFRpyzW1;9s~?|{yfJk9%vmJ>XH{4no?{JNS(Yw3-z{JxvOZFJ7n zLQVRS%@ul2{x&TmScr5xQI;erbK2%g#dDMQ|8r#Ly7<3GcF9l0klp?NPj-LFdN<^b z|0dbZi6OhI{~Bbs7W-|B&BNI}I7ipTv-^y5f;(vM0w*Uo1cs#3zGda6z}7s1y8L~^ zE^Wa1kS&^*XC4)4$*+ahB0bKmk@F8niOow#n3L})e_oJh{f=@IhbOd9>~M~eb~E78 z%(SrCX@Tt?&HI?<+Jfha<(jtTInBxQZ#J*f(r~$&fHUv!HD{5QGO=k2;%N6$HAe`m zHMjf<^u2AIh0ODSdX+sB`~JLs4mKNy6@!-VN6t-zJ$ABuC}(aE=ePu`VXI&>14$@j zP)iG@80|(1XiG`Pxy5=9>G9zMreKq5i}?O5@COY0`IqBu($k-ww@GV1J#UlW`k&8R z$D^N~w~m@m&)cM?zgFIw^(3!c%anSuL(W9o?bC;Td|joMjyjSN+<|%x|0Fa`OApyeQ#$<}_&$q$`pz3n|4`~Aeas?7 zQ`42G+r{vkl#l2E{Tl63u2a*d!{-dXhGx=EoU7T3bWZqwX^pAy z{hraXB<)nqNt{hdunVbP*bn`56YvNAK3&oghQ4J}CGh#s*+jnZ*WAHQ;M$-$1Mrhz z57UE(w6xHR3N|<#`37N&?$L4sNy#{C9%t-oc!wWlzQf4|9-Pr`;=c;`PQj+#2ihLf zvNm4{n#O=O#5bjCuEt@YZJU0Y;iMyMG?# za|W?mdhLzAhTLSKzjt!E=9ml|O*M$~A^p9u_m63%cupHf-flyga3`J67eDj`Hr-8_ zOv*&gzkQ46E;~0j{~9>f!G_~3!Y%7y>p?TZ-$a{HZs5u`ae;T4TS&{=uQhC02>pZq zD{afKL4#^D`r^NT0Q?u5?G$LuY`Ot7oHEKdlr-x(6Wy9)^A#wg!)QyutFvFVg~-B{$@z3SV-9kj>gD z;A;@?_dvc`kaw2m8VkO8AJES>pFrBIO!BiekX57wn<2~XzikM$qit-_oNTXn_94z; zcQ!uqUIWgFOJiG!vN<)?#$Ezq^#FCo)=GAV=fE!&`v)7XAO7jcLFy4JZ6 z_atCZ9}w=sJuL)0uu~fKXfxVeo+U{gLj2Kjm#KU~n~QlieFO2sd#KN8TacIFW_sWY zY(n^BiXOrJf|k}iTGQ5DEO~mHE1@@+qRiBr-)hd#yOKU9cp1w3!tWalJu>xQ>IeF6 zXG4W32bK`7OHz2qAI@V7p6>zAV-}vY7A^>kW&`4wM-w5EAgJzUR zXohY@)2!_WZV$`b_}qI9lu`43=-4Fa-eovP4Q*5Yli^ynP2iU!|DJF;WS0h8<=BES z`kT#7sy@TlcQ(RTlQUqCG`Yo2qnxnwF7gj{FpWHeuj&MS&JgWCbSnUUd74!95Li#Tly6Tn28J+4cap>jH46*>ID$6KA7X8Pw&fW$3Lwv>(l@E6xxWt%0AeDzHIoDt1s9GMPG7q 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

  • yAJLq=BC>m}Df`XM6;^`m8fvkWJ2w z%lo@8E8Z8u?siEq``iwOPQi(@_H^?Ru9EaF2_w zH8+RLh2QB$XhAtaF6=`hY%Uxm;Pi80gG5-XF8trlg*$4JXe&!$>Ov-hC(ecXHEK>j z7k=pxa&x#`*jE#Lf?RkNiBK+ZMpmpGmSK(om2+@8J?MyR4e3k+#MvK)Q7sHvV8J)9 z4C9b64p4vCdTbb#!jP$cb`~4P0bwi`hG?vyK20>#J}9?uI&t#7tSh{~TU%Axg=dbr zItSA@SX)|?L)}^09mxMwK2|i{1b!l%A2_c)f1kJd;A`yd*MKddfC>Uuv%^9I)>#2( zd-D%?tE+gi$RPri8n(;|i}B`HR`oO?hcskHDCAI8f(fbCkinsl>ZOn$mr-Dga>SEtJ``7-L_`i2r$p4ceYx{qwaKiaNH571+|65oA zVf`O#g@y6|;Zze3A;;G<{kYoLy6bh;Be_!nXwZ7|r(h|3 z|I#PYUPk>|BZorPZV@wt6Rt+K4Fw!iBQLZ9!q&*2yBcj_YGg$yFM;tIar3XA2?BlV<71k0!pDb|(pp(P_V)B5N^*`L zI?cEC@D&m6k8xzp&Ee{2N=@(y>St3VO#S@tTUL3>hU@XY!Uj#PUq7??QRpyKm-t5scOc=VSre-F#Yt!E0 zNS!*@k(xQOSN6cv%wBX?Q!~4VF5qYP$#zS4dTM5Wdihp(@B;pTez_9f-6Bl*$o_qD z`*nAZ?B~u*9nfnacOlmuJ?PDL_Zyj--IL)&kk==7fSs4qYe08KzviBtKK*+Q=*508 zWP9}L=k9JUtgwOZ%s$yNO2b&q8+bf&oq%uiOSWaf@kf6;usk!~#xL)}E2lUCwkqc-mE&WIK&2{Gn!-Kq> zeto*T`&+k(Yy9C!C#>Ag%gYj}9Rd+-2vw%E|$(qm7U=q1DZx%+1r z9sP%7GqN%1&+aqQ-LD@xjW4ubjLc5W(mXWvWTZPgH_ILlmx^HBAH1hej=P_hE~A&? zGO|zl$SikOpML7w?o=?1%-kEQdzx0u?w~>n-2l>L><#jaA;;VsG)B^RY^0=VAbA%o z$DvGuPucH5(J<+@yH3*CgJPLUMYY#~AkSVGgXN!+*h5a7Q6EthY_-brYc1Z$?wP4s zQt)e48t%6W{7Bx9(N?Brrsj{EG%aWH=(*!(bne_UfAoxT@Y{;qq+1f*Q^!pjO@o;} zdD`eacm_|JdP`!?v`JH8^zS8q!IN&8I(}RtSL1IPPYao={M@NCj|t&@#-v*&$~~FW zW;?Pb%^5vr@_0w?)G10i9L;AYHXoPRePW^z^1u1Gw(>{rsT~%c7ZkS18o}W8=&4i3 zPnIasCgo`ysgo@$5t%eqgUrl5630$#mDs#v8`p%y zjCrjRuWH`9Lz@mWuS#s;n$z6XY4YHf2quo1bW7{;R>mYwo|Kn2d3^BFF+uZ*%rO~} zXu02!n6DW@Jkv*yy^XxG5;|sX-gr`)KQ$bexF(WWt$BP(_Hu9Hxy_Fq{v|USqjm$!P0WN^=U=&g?GISRgHd@G&UNcd2$LYu)BYVQj>$|5~ z)wW%`?y2rMV{xZ+a$slW=Z&9p!u!qyobkXJ51jG984sNCz!?vm@xU1mobkXJ51jG9 z84sNCz!?wxKj48lzbl-TDK=)~o~5o9Kvy6K7zIoR<^u)5GGH|jVY}yqWL(8vF+jl4 zJgNz6$IasLOTZCV=!Lm6q$=QO7j;!Byqka@fQaAuQxAv|nREFg7v>kd>A$FM;&l)1<%Q%wkDtqdM2`RFNm_*bhgLI6J$}UtzgOQAqC?p+n zI(@zOA>^Hp30Z7cBnLT&SS8qT*dB6h6qc`oY9B;AifOTv`RdOEUjuw8vS%Hq8?O18 zJop2oyfAqIh!VG)Bo7J*{ydVrjYjr;{+vYi5mogvIO;RK0EH_DZ)&h?5{Q!1hfbvT zx~Qw3R@rC4Q6K9Ch~?dSqY1GWHj~aiNbCpBkK(@0{5eq^l*?JjNwD}P>T$gQg|q#2 zxJv<(!*WvEN%ZnI-|;XYW=ByUPAKb+>cAPeW^+h4#G>BeLiEZmhkCLFO)gA`EC#F{ zV@=^S>F$oCBjf> zBPXh){6zg#FF@gJ=nZ!$unCCzoIfYB0e{{}u)JycPGsez&yZ{{y|@kR$hU{s3lU)^ zEi4RoqySzZN_I1Z^wg3zvU0%0ebkq1DRcQJFLPPQ%Ep5SfT%4ew8H2W*;^6WEVBDg zE;|I-4-x5u9Z|FRa|(M`A=^M?+niihY&Zf87aNXmA_+0Ski9X;-7d1L`EwE*B#&g% zWL?rGHrxkDLmqY6$@NOU^#C3d*`543i4CVK%R6?5JolpBJGovdt0}+(K-3ogoWzFz z-(_iQrQV8(d&J&=-Ck*=TLwey1>fZN1VTmt^7xNB|K#~H44Gu$Ig#DVpOg6H7J{WM zdqrd``15~A_H^2umo(achz)Z3*GX)6LuI9h71iP7veKTs1KcdKi%u>p_ErE3MfOi8 zm%SZ1@!8WrR5^c6V(*h0{F=yqc@o(nQP~%3@EUML8@-T@N7NX-SObob$5<#vzg~!b z$6xIsq``V_1st^17Z4;>sTzoqPC+{e57;5w$6E(4O1KE=wiiMKLV7Mjs1*<;jjQPS z3)msYzla`l@fH`S)N>GN=}JX4=a1-l2<(`~AJJnjIp=pCL(S=BI*}=$fa<^QWG*?6`6Y;(F+2tC$Pl#517*NGtM$)^gI~f!imE+^UM`( zPl=(DUP-sPc#eycqaKE3E67jkfSD1x84 z2x;qLkD4O*KNlA#Ow$y~NG2D9Zmf^%InSr*W7tXUK~54t7vxQIx{uNV7WX*T*6Xjuj= zzgdRQci@qcMMOmsFvKO32b1eUX&;9C}GG;L7eNa|SXDil68WD?gCDl_W* zQrBVDM2Jj9N~!A^Uvq}$w{TIKe8T9WFpyb@s!Zf1&)bVmb$ix3>i2qv(&X) zEYvlIM_RVJlFsp|@*i=kzV zFX?r#cO(rYN49?0-0$kkVjH2;+mLpl#WAF7jq($l`dvGqF~R)4SAGYV-*quek#`~A zLumB0N9SbaA8J(Ux=;Bj=y_B5^W*TF@;|%G?`nn)(bEC>K0>2sJ$fEge&h2>U0*AI zAo+DMD@{Z`0X;Vfjl92^-!)(P(dgNr{PZjQuD>aN9Q-QfU*5{^iXeYQ&l>b62#uZ& zt^KYJ$}fj6%Xfr72mND|zn6IB`$WP|hwoGVdiakizf*$WwH=ydn%_wNN?a-EyhCX2 z%|_-CB^68>37L8YSBL({jVwiCDJa-m4v^7 zv`1^+B_#P>Ero`^8GaYmggK)N9Mj`VU5^UgpumycrPLL9zQylxVX14P(D2v5|EKcv z;E!iNknrbIN8S(`Jr$IPCakFx{-~~{t~-T>zZUu5l>bTRQrD~tEq*-w!$Kp!?D|qy zUn-=?@5G)LgoeK}xzrWk*y3-z0RIaOzX^K&t^5PRKT*{Bakt|B3o5dIq3>j?nOn&~tVIG`<@(#P4b>G`{L_G3|`em9?~?Dp3csBEovHlyO8l-O<-3qyt^Bvi_jS<0^uDHi7k+rh z#{W|JkIeSFz86~bC(yPeLW`gC{jNqr!(Rjca^(-4>vy$NzT?tTS9j%K{s*2N%6GvZ zqx^BiI}JK$&mGF&j-Qv>_$!tF?l9Uwp@}z-di0F)JE7-QoBZ3#|2dVm(Z>Ht`4cAj zUG*-r^b}DJjs0ru?J$c|LS7 zUCV?|{pvJ|XPnY0&`+rR)qVV~4MLNy0hHS^<$s&ycfG6pB>0~zfBtm8>!9*e@c+-s zU$&5Xak-^u1%AFn=m{y)kuy2I~^y27%v4EcDWv2%jQ@477~M${*9q?|Mb~tMJ3$lz%1Z{Y?2C zNbeElmyh+k8eD1VSq1-6q49q_K6fdd2%V~Q0(4)cqoGGB-57ed(y`D>l#YSESLrzD zyUw!w(73(dwHZ3-heOK$p`G9Ln~mS-Y)gJ0{41b?^74H;DW7Ag*V#7yEy|Cf{aIw= zuTg#i?ffe?{s+n*Lq2{dH2#dnZ?WfC`WvE0z6}?Qx2N(uFR^l4eKE`Er; z&+lrkbjCe?SBBD`LEolyHuQ3(2S7ik^ib#zl)m=?zw2kEJ3}Y7u=F2-&QLnzLBDH; z(%YaPQo0&FyOiF8Jyl9S0A0VOrRTF%e%F;sPrjeJ*%m%|^ebaV4|J5(Y&f2_(SNtm z|FO}RxU73qxHnDd^;eX-ZdH0d^xaDDgMLHlSjMCWmF^1Nm@Nrn!*ulAr1YW7OI^1? z2kr6M=x0R+pFe&t&oUeTd*P!eleo@mZ^=Be+V5&AH2ehk9fc+zJEfMo?lJrVM>+BS zsQe1}gRd3&0>?0H*eo>i?bAwK*Gs;`Uj{#xJtso1;ob>CBXby;J<8vVjGHYA!k>)J z%|avJ3jWO2(Ae*K*YENM=|}voHA-)N)bHA)bmH@V*KVbMf1PKv((9h1ztP6hbNNe* zVU?cu2IB&yyFTG}_QvR3KJUecv$9zKBd=OQ|fwN z>2m0gm7WgmxY5$H20ye=x*R%3=@jTWN>^jgdZo*tKTtXm8v;sCN4{l>rL!784-lF( z4tR_9Q2A>}<5SA-_l4h;kZQ@#ca^$UDeb_YTZQJ{R>;Js)%a}^wD9M>>32OUG=7_o z&b>+}pyzv~UFbQxyCt)ZypV6c$i0(4^1HeyzZ#ibrS~E;UFjA0Q@%wb`ZrJ>o)(&W zhyK&=+N1pS#1+}Yl5rv5EJ)*@u1b%B9-?#wdS*jMIjrA3$}h+MHjqgD|CYb$I5hc8h(KzlXNAdTl@ldscWv#(FKk} zv_Bs!|2_CQJuQ9$@^1@`o*6ypS7ccHWysGI8vb_lf2#aW*w(w3@{xaCX!LJJzKgcE z#V`0>gOy%Qz0Oy981zb|@1-vPS?OiZ(l=AOzSMoC7eSwOHTp^WHgvXCy4yzTyV4(W z?<}P=|Lk|&r}QRd-cWig{0gPx&?7s~MCapv`YK9)^&;b3r8AM4r1S{tV~Nsh*7Gb= zdMffCDD8*-N$K{`m$tI>zrBGuK&9i+bBofQ;4f2p#>@2om97uHU+F#g>TGQT*RJ!s z+AE#8%kLVl^m58}*7a6gccL>-=@IyLxzf{V8=qDBt8%|GmaZ3iTY6+KWmGQoIR%cGoKjaKq2qW)+|Kj8za=AkD*Fmex;9)( zdX+ExD;Fw1t^@NS%9s6@&nmwH`JKv_y_jDpKN0?K%9p*G7Y?xWSGO;9wO6_TnGB&x z?{eONi*>YHmoPT^#?=8^3I7d>BoaCdI0pZN)Lu!qI6&AaY|2wzE|{cuPnj5O=($@ znWnTX$?PWb_<0!qd{5$n-Ua=J(np}55gL1B59@u(&%2I(pwergCn|ju`T{MVvhTIC z@)O}-JPb$opPS+5=Fq`%{c#=sPUBzUaTp zqK(hbrVYVn!++E!^Sq7TVUvH~#{bfy`Rj08Ntr!$wbm zx%Vd)roa_I5;{@r920@_aZE3uH*gb>3FH8M0V&Y80+WF$z%)P#>QX=^T%W=L+s}4X4vlblA|0`t z6|Yb{PH`v2v5G5(Sn?Yc7b_m7*rhmH@h;A{6a8xx=PAxmoS?XRkR`WG@oL4B6{jeU zS6s=7KE`gvD-@4Y+(~h);tEaz5&6}MCo4`-9Iv=?fa+DeLUD%T1jW_;)n3J`6^~Nf zL2-=Yef=!?4T_5t4_17nuN7XTc(CGDimOLj;d4e$JSgEW zQyk42oNKw>H!8w$9e6L8GjU?~fH~A9wjA6PybHV-+yi;xAKTzkZ2e%3b+%P4|su9z#o8{0Xej0I`9Y}XBQ0ze86O2 zB`_4Y1sDOyX>?K@X)+wcfrp@ZtUBa8o@;KcHm*)k3cD~02m952i74&^WsL@F(B_;A!AVzz;kHtOFJSlnqA-a0Ad4Xb*G)BCtb#azdH>WX+2F zq7~OuTwn1y+#|oU6~C|iJ&He2{GsAs75}2Rfnqu4PktXM-mCay#h)ntS@BPbe^-1| zu^hD}KRKvLe&;BTRV+uU$*-Ye=_AW8PH`i}=P8cTbVVvYU-|KhFHn4;;)@hFR(!GI zCW=|wX8jbK)0N=-rs0<;PEdTQ;--p!RQ!YD|0q79xV7RN6t_{_O>tYrH!5~1PEp)W zajN3>iqjNdtGK)34vKpyzD}`QaYx1JimzAPQ*kH7a>|!^OeQL!9SCBM#!r4Gn1S+Ud)`E^n(bwz&HD?Uqcg5pMsFI0Si z;&{auDQ>LzV#Q4qU!pihajfD*#g{3*T=5l(lN2{se5K;66t_^^QgH{xS1Z0oaVy2G z70YR!^1D=VTg5KL?G*P_+*5Im;w;5-jHvwFinA5>P@Ji_yW%v(sfyDTrzpNj@j%6N z+02h=H1p$CiTUxW!~A$vVSdszlwXSZYjqQaOw()WD$1{ig&c0h>56+QmM*0Hq#G)~ zW)^ZJD!xqd<%+LREZtT4HMfxIx(a!fUbj%(Qt{P_uTk7eacjj4qs))4wE4Ldw^Q6+ z@wJLOD85c{N5$7G?xc8w)|Y=MeopZ|#m_7LRPhUnKU2I>@#l(PR9vC>CBf35hS;@1=(Qv8kL35qu>zD4mw#gi1juJ~5P zZz#S^@npqQ6i-z=P4RTaw=15Zc&6gND9%%yuXvW?GR3nMZ&5r)@m9ri6~C!?p5kqa z|DgD+y zI9G8m#RC*4YdaxBZuzZMJ%3XCq~fO(uT%WAV!z^2#p@M6qxf0He^%T~aiZeO6ko3R z3dKo^n=8Ij@l}djC~m3vYQ@(m&ajeW#tT9+&1QZwo{%4}C(KXA8}gIkyZmGvAwL<) z%TLA;^6O_IGgc9DfL_a3M1BJ;WX32$GSy>#GS-maPz#wciIBteTE;!{8(|?c{t&XC zrlY^&0g7`K4^-Sr@gT*66%SE7RPoJij|o~(F^;;D+KDW0zQcEvLk z&s3bJIA8HB#j_R9Q9M`iJjH)dJYVqw#S0bRp}0VCq2fh~J&KDIFIK!n@lwUbioJ^O zRP0l{OmT_g<%;i8yh8CG6|Yo$x8hZb?@@fOVwo4=H|F@gs^K zRlG*=V~QVF{Dk7QivOheNySeoUZ?nJ#eT)5iq|WCM)9+X|Ezd};^!1UulNPU8x_B( z_$9?JE8e8|6~(VAeogUa#jh)VL-Ah}mnq(&c&p+!6>n4gSH;^E?@+u`@mq@DR{S@` zyA;2p_+7<+S6r@mx8nB{zpr?Y;tv#msQ4qrdli4I_!GtdP`pp^r;0yQ{JG)^#a}4? zQt^Jp2NeHP@mGrfrMOaYmEx}zA5?ru@i&UURs5aeYQ^6xKCJlPijOG%kK!K`|ETz= z;(te2#9_tXE3Q`jt>W(#H;A<4>npCOI9l;fs`qEbzbO7y@o$QMR~%66Q2jfGm}zZC zaJ(yXN%BjukRx5O9T67U1?URg0CWRx1X6%hAPwja^Z?udIwE@lmjX?JWj{p&z104xO0ntD`pgzz5hyl(5&IZl_Vu5pkhJX`@0~!J6 z0p|npzy-jCz(qh~;9{T&a0!qATnaP==rcvqUy7u!6iGiRl0H%-{i8_wMv?T3BIy%F z(jSVXFBC~XD3U%k1oD7jl@LG5sydK^FZ-h6&o8c|+R(Kn{9o_-&gm=Na;XUwP zcptnUJ^&wt55b4wBk)o97+04UxY8gm*Fe$Rrnfw9linI zgm1yO;XCkM_#S*8egHp&AHk2|C-77F8T=f60l$P_!LQ*rz<5}5`0qA!;n%ot1IOVi zm;npwFbi`q4-2peORx;Lh1XQ2hxz$UbTbx4gh zNR9PJjkQOObw`agM~(GHjkQLNbw({D5AWgcd*OZXe)s@<5IzJShL6BU;bZV|_yl|s zJ_VnK&%kHlbMSfi0(=p^1Yd@)z*pgG@OAhGd=tI}J=lR=@ZdVQ0DTyM4*?9}dI%wc z7)G!M7hxX`;0E|-_!qbv+#T)#_k?@Fzrw%4z2V>CK5$?75BN{`FZgfxANXImAKV`v z01t!*!Gqx;@KCrB9tIDGN5CWDQSfNE2_6GC!(-ub@OXFvJQ1D*Pll(!Q{idwba)0l z6P^XnhUY+sc5=ao>j7JG4f}8n8*mM~Zw*^-4f}5GB;1Ygy94XL+5`D}6FdWciJo7; z&*5kAQ}``pYH%wM|NaKQU%^k{$M7TgA^ZTo58s3D!nff&z#OXf+rZqZ#=NPvOFAB0 z2N&QX+z8Kx-zWU{;CBJreeDkcn|%#?eeI6`JADlseGU734cmO}kKuRV4**+94LeDV zwQP-bY>hQ+jrr8A9tzKbTjTx{_*3{Z_;dIR_)GXJ_-ptZ_*?ip_`h>`8)Qm+aJ0ivV&bA?rr1abfwR=8_Q=`&aAn6UdOd& z+HO1=o(i4eZetJe@qx$P-Ew%H$m`y|8*VzW+vrXRHYk|ga-FanT=d6epd4;cF-IO6 z{+<^G{=oI)#-_DI>2f|zzZaBqcBDv##O9m67kf_MyTMgCZk_Iwb(>@isusxirt8xr z*NjjYA2bGKO$HHzqNPnYa^uxq$M@a-8RsAv#nqNH3K^6wpK{}sJ;&=i+kJOE@PiYh zsH)8@RaIA?X-4NMT=(#TjuSH|wDS3D$8P8vb66iIXHuCqL{f*V!H9lTZjHJ%M$Vv8 zJQr(T6gz&$U5R7YA33oX_>DogTYgCDhshdL%idL}&a*yk6uD7jvy$aQg$>FVWv4zF zgaapTg#iOdd~k+xxV{@UT6?Yf>}oI=20qVO(^tjYbUQ)V9SkaIUyd$A)|P1aH8=7? zH|b1;#ww3o^$FtD1ZHPe1Hb3(j6(HfQwfJZQj;T86IqsBXwMC|E8Qy}RE@Z5H5h3I zl@?C@4N>Z2qG2hod+R;Nk0x3!@{c2;#MnD9VQQ%q!X) z`981G)MvxJC?clrvqRTU9qrf&v-I0>FieBa4ZFM^agMrPpkBM=K|f#P{MBnq#<`kz z?s8rkC@3=!Tw(5{=cgOQ>!a8EMB87R$7Ck~Y-VK9`Iy`mk?C;x*c~RiY z7qY!KbBu^0sbh98bjeFUpgZs%i;$tzaIH0S((Ct|{!07A+Gc%jb)_ALt}{5{L|%sh zs}p)Me`8n|km{xhsm3H&gb)L$EIVcxV^do0SzVzBd*X^pLh*k;Ek(RSAd1BP- zx#7AqRAn)Sq|tOH<>arI7R1_O3c=EGVa(=9es}0b^9*!@N6=ysw2^Gn1EKYpj1#Z zF%NNcwzswGMQX^BFZlXl0*Mk@`I?bCa(mZ#vK{j7l8BddC@mt~iO5DfUa~j0Z5}4K zIcUdoL&po7rw3X4G}^H>W49@DC$^%v*`BrWn(Mn!)EqS0j`V0))@aBxZErKF>ozvq zmMyCD%4wf=_UoP>(MfIhdR7UI&C`@}ss%9Uzp_Q3)fRQb+8#4_Ck{f{R#&=k6H=aX zvFCcc#HQZiGObh2?vlN3(-x82Xi-nIX$$#cZY3VAY4*B_iA}k1%M?yMN3wM3z+#Ki z+1r%5eZro4_d9y36N=liW_T+lgK}lqn=21{cwFMJHP0sdvbu zCp@XpnVsQ^jEa}9e(D7<3|EKt#7i!MA%QDghzSGIl`P(bq^Di*Y`~gop)$48&hW%h zX{zOznA)_9cl3d1s^vU-vZ}xa8)yd`sMA+=3Sqw}x@0tM4p2gokWh>J#G@e84n|?e z%?TwQTF8sUevs6mer5r3lVhEEG{(8iz$87iP%s?!-SDK-VWlU9@*YK@^DfplHp6ma z+A9%k_&O`1R+ zD;Hk|W2MUlE0c=!SPMo;JCe9^WO0>SC!M&mU{SAWJrO;1=R|~^GD%z7EVH1K{lLLK zE^{G&mx6S%GAvi#CYGojv2875Cax@Q;-O<}XC|Oc;yTl=I2NR4+<1t(|27onaN8%WmSKGpn8D_&TF1Jl9b$V#}=$ zS?kJ?#J$?{Wjl($iB~gH&x9zD{+$M?r<83^W&9KmZ#N6n4_Au{!OWaUm3&iil}#n2 zekVb?qE&@uu2Qh9E*+|CD|O4t%3P(mvZ{2buBnYcc5{&R^@Ojd2HQE5_(a20e2kDLbSEC`(QuNRi-O2&)+ zg($MisPu}>(95NijsZ$gc9rC3qU=1IP-vylNp{@Xd**uLYS|!+WA5{Pc?= zb>uYYL0l`)?wm+&%+yjjubf~uj){~C16hZ?n9@KabydB!zIEqtf?x9)=-Sx-G`OoN^|4N!?1Jbjn@pBrk4Q$W*ekoCYQv$YpP~GsT?ST5Lw@ zI7*vsoFI(dt~zLvw}@KxO=fF*u6p8<;{^qQIZ_cXo+Qi3;f11z=pJ%dQOAFHy4fZw ziWHm1sHNB_CXsnYeEk|Z<#>LB5vH7yIQXTvYUNDYR46HwpGh}*+f`LdLY0!z6KSKI zIDewE)e0g`xp7{p*E3`;FPW({NXny4TIbo&V-Qitpipblyv)34Y#WLrXJZ371~ZU5 zx4Ki8DztF0MQO2SPvEhgougJP5LVR8J6wlzgD)j}N@&jO*{j`SX-Irl{m3 z&4FsHyk0_eqDfPhLz7gip<=^7ZMMx`n~l*KyOM&CN}FuF6!}PX(NI-22&8IE0(H_^ z^FlUeMK2ngkUILN#Y~FkP(+pJXQA3q;vi>UpqkkQRPfxpEbH9R+-5>#GwAov_IhfO zT1`hhY(*`Gl#nT^smd%SxoL86DO~Y)`ffEXEhBS$h>Yq~n{J<{YR{x6$#X6(Lx%DN zQ;C^{N~u-5@A3*8?S5Cid$s~O8B88aiM0} z6=#FQhH>VdZmEjqZpZa3By_i(zBm$V_kvJuHjjzA*_Qi!#9mG}qLXtF4u`o?McZTI zGxjAay8V`{75}1WUfYX&$LF0kNKSPP+(Bo^N{A`7I_6b+ag?VPa+Xz=smw0SQlgpi z6AZIdd5&S0Do-W9x$R*T^#75M|X`Pu23K9XDZ)Jn#jr;^hq)i1Bu9@^!ppLzid zTU_$hG_@KsByfcbF<~R?N)~TI($g+@w%Ik+LS<^Fo#BbQT2n2@#MGu;yrXYsO|_gy zPgWLK8YJ`?cPC^&h{b@+P&OZxQ^@3-kCv8+8s*iGm~P3F)|H8qd;#Q#-%8Pl zZQ2kY*@*ART5^e9_Dh<{nniRih=*a&9d+VXPfd&r-Z}!uxksyE5JkBtNhEVnKH|EA z*?<2$>$V_l^;#>lw#uA{X$VWAZdjI@FUpxTwUF3O%D!4WtMcL^d`!4r5-U?Mldn?z zb-ffH6F*&zo5GpvW()E$0y+b|?QsI>vfLnGtp#jusNI1|m$8bW=IHIs)g*e$nwLFU zRktv$l)9MEcbK>-0s3<~^-7oOV+7M_*P()9*^x6LnW{~EOqVJXD}O_Rb!sk%Sk;M- zB&$_d3N|UAXa+NcNm8u!_;$sMb`5J#t6mH?DWE)AQez4+eFn`NcnKG6(nKDCHUI*5EMZ%!QV1ybYmDp~V8vqOhH+2V!~kACGv*J{<5 zq!fF2d|uabIv02nvhVAZnI|_lsQ?;1GE9w5P}Vs z4d=3LbUyK}Mo5je)u7C7YY5{>NldrZz@@d|s8hJZL=B3?>`j@4&4Gz!*c_OwV+?^5 zMq7@nq1i}g8o$QakE?1b>m`GTFo+$pq>=`+e0Wtw-e8uk98z;x(Mv}kV+vYWSrwmU zR}5uS`10^FRZlhJ75mlU-yB|A)(y(9VCKhIr)aQ=pL<rkZtHTT|msFTc z=MV!b>XO(UX(~El#e)Z3W3>OifYBM{nedF?Rt3 zr!v&LOU@|RER*_#F-=W$ihtaUs=xPnvq_>w48W1sSm5_opecS zL7XOA*^Yuf)ssYNb>!akxG){na8@b_l1mB>u&6bx*z}%oTZI@(E;&+?*a8RZ_q|xw zq5ho(iEAEOUaKYV5+gWuCnC%3i_Y-GLF`5?Y23=Y^CEZU)}ctDvw-muz8H+54 z(|PJw>MfE}-r`s4eI{_acU?KpvmsB`jxY+Q9%Z5I(|}Y=d8LA)ugd5urPL_}WQP(7 z$-|$?(;zI>_jvM4<3<1ak1EIE)QW|PfBpCtL_nvSX?WNem->|+TyQr4Iz z%&76=ko;Y`#-n6Ym_R(SY8KzGFkd;e3R@jDh#r>9OI0{Ill8fDALESYbC+Lhb^S=y zI-$jHvEIp9UWgilA-C;K$N{ewajTj5=jf7?Q)j_)RJEC;R(tx8#n4PLvCs0B=MuX4HMCRJfW{9m#`c~PO9t;McEkRdKW`(3}KAZ9^xpDwYt*K zw?L(D|BA1!Lp>9jyQ|}At3b)GEV`g3KG}>!&TdlQviPFVOhYu7D&=NFnRhwDveLiO z@0XIu2UH@7RL*fRQ@@nXaxS18NzIokzVb%6LT2fvbe*!`+Ds{f!lNRTyD?5zY`WUc zdn6IJnuWF!+1P4oIq7Ow1=?zEqJBXbDDxkp?bX; zoxSM0yz7(m`&)8indCo}Ti|#+7bGcfS#2`9thV!FnB0GF!D{YCM|*cLI*;ZHLT+I*!<= z)N^C$-&NnMlzctvtK=1VJKV-r@)QYiBc2y?a8I3nwSB%yD5M~QGcS34lC1PflNP#% z?#)#xQPEhc{Z8`gs7NeC=OTCA>#+IGotS<%GWQE>8BM|9D7~$2WuiyuZ)}9~g>UST zu51@kOX6-D+1Rq|x_c$7E?rpdoh-b{-s#$_98eifavi)Zn;$!*SZVA~e#Nmv`QFd2_bqDzyu+ z$^+_NwHl2Cx0zqMYHWbl8TR?e2#$A-?Q}YIyTg_ZOOEbw{&$mCa{(f=P)pPq3kznF z>4k$0tKLx`gGqC8PBx2`{jx8JRSW&p8;HxljM5^F)QXV3HyhUc1^L*t+^{VlF=Om3 IE$+(xKl%O&MF0Q* diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Resources/English.lproj/InfoPlist.strings b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Resources/English.lproj/InfoPlist.strings deleted file mode 100644 index 201c6ba895e4537a99f585eae95e7039b85f3dc8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 474 zcmbu5O$&lh5Jm60Um-3dN^28DixT>PC`f2;r52TmT2Mc}I$0Ejt>W?C=)5~K=iSRy zHI-#(q`emMwAET?`C5`Y5)-9l_KJuGG2k5X7w}zGoa<9%WH+c!xvEUh63bCfT^&#_ z(fJzFe@8UbW}BK&?{nK>x~Wz{g{u{F68g_jzFAx{30#rF!fxN}hHPjpb`uu+$Fx2( zve)bWol$|zfj-8SJ8Q^W?mpGwu+(@mjOA*8M?1WUG=;!}(9=A3tf>CsUD3@)=Nq7z BPQ?HK diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Resources/Info.plist b/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Resources/Info.plist deleted file mode 100644 index a811c8bf9..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Versions/A/Resources/Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - OpenAL - CFBundleGetInfoString - OpenAL - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - OpenAL - CFBundlePackageType - FMWK - CFBundleShortVersionString - OpenAL - CFBundleSignature - ???? - CFBundleVersion - 1.0.1d1 - CSResourcesFileMapped - - - diff --git a/Engine/lib/openal/macosx/OpenAL.framework/Versions/Current b/Engine/lib/openal/macosx/OpenAL.framework/Versions/Current deleted file mode 100644 index dcf3361c8..000000000 --- a/Engine/lib/openal/macosx/OpenAL.framework/Versions/Current +++ /dev/null @@ -1 +0,0 @@ -link A/ \ No newline at end of file diff --git a/Engine/lib/openal/win32/al/EFX-Util.h b/Engine/lib/openal/win32/al/EFX-Util.h deleted file mode 100644 index b4a6b4e2d..000000000 --- a/Engine/lib/openal/win32/al/EFX-Util.h +++ /dev/null @@ -1,422 +0,0 @@ -/*******************************************************************\ -* * -* EFX-UTIL.H - EFX Utilities functions and Reverb Presets * -* * -* File revision 1.0 * -* * -\*******************************************************************/ - -#ifndef EAXVECTOR_DEFINED -#define EAXVECTOR_DEFINED -typedef struct _EAXVECTOR { - float x; - float y; - float z; -} EAXVECTOR; -#endif - -#ifndef EAXREVERBPROPERTIES_DEFINED -#define EAXREVERBPROPERTIES_DEFINED -typedef struct _EAXREVERBPROPERTIES -{ - unsigned long ulEnvironment; - float flEnvironmentSize; - float flEnvironmentDiffusion; - long lRoom; - long lRoomHF; - long lRoomLF; - float flDecayTime; - float flDecayHFRatio; - float flDecayLFRatio; - long lReflections; - float flReflectionsDelay; - EAXVECTOR vReflectionsPan; - long lReverb; - float flReverbDelay; - EAXVECTOR vReverbPan; - float flEchoTime; - float flEchoDepth; - float flModulationTime; - float flModulationDepth; - float flAirAbsorptionHF; - float flHFReference; - float flLFReference; - float flRoomRolloffFactor; - unsigned long ulFlags; -} EAXREVERBPROPERTIES, *LPEAXREVERBPROPERTIES; -#endif - -#ifndef EFXEAXREVERBPROPERTIES_DEFINED -#define EFXEAXREVERBPROPERTIES_DEFINED -typedef struct -{ - float flDensity; - float flDiffusion; - float flGain; - float flGainHF; - float flGainLF; - float flDecayTime; - float flDecayHFRatio; - float flDecayLFRatio; - float flReflectionsGain; - float flReflectionsDelay; - float flReflectionsPan[3]; - float flLateReverbGain; - float flLateReverbDelay; - float flLateReverbPan[3]; - float flEchoTime; - float flEchoDepth; - float flModulationTime; - float flModulationDepth; - float flAirAbsorptionGainHF; - float flHFReference; - float flLFReference; - float flRoomRolloffFactor; - int iDecayHFLimit; -} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES; -#endif - -#ifndef EAXOBSTRUCTIONPROPERTIES_DEFINED -#define EAXOBSTRUCTIONPROPERTIES_DEFINED -typedef struct _EAXOBSTRUCTIONPROPERTIES -{ - long lObstruction; - float flObstructionLFRatio; -} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; -#endif - -#ifndef EAXOCCLUSIONPROPERTIES_DEFINED -#define EAXOCCLUSIONPROPERTIES_DEFINED -typedef struct _EAXOCCLUSIONPROPERTIES -{ - long lOcclusion; - float flOcclusionLFRatio; - float flOcclusionRoomRatio; - float flOcclusionDirectRatio; -} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; -#endif - -#ifndef EAXEXCLUSIONPROPERTIES_DEFINED -#define EAXEXCLUSIONPROPERTIES_DEFINED -typedef struct _EAXEXCLUSIONPROPERTIES -{ - long lExclusion; - float flExclusionLFRatio; -} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; -#endif - -#ifndef EFXLOWPASSFILTER_DEFINED -#define EFXLOWPASSFILTER_DEFINED -typedef struct _EFXLOWPASSFILTER -{ - float flGain; - float flGainHF; -} EFXLOWPASSFILTER, *LPEFXLOWPASSFILTER; -#endif - -void ConvertReverbParameters(EAXREVERBPROPERTIES *pEAXProp, EFXEAXREVERBPROPERTIES *pEFXEAXReverb); -void ConvertObstructionParameters(EAXOBSTRUCTIONPROPERTIES *pObProp, EFXLOWPASSFILTER *pDirectLowPassFilter); -void ConvertExclusionParameters(EAXEXCLUSIONPROPERTIES *pExProp, EFXLOWPASSFILTER *pSendLowPassFilter); -void ConvertOcclusionParameters(EAXOCCLUSIONPROPERTIES *pOcProp, EFXLOWPASSFILTER *pDirectLowPassFilter, EFXLOWPASSFILTER *pSendLowPassFilter); - - -/***********************************************************************************************\ -* -* EAX Reverb Presets in legacy format - use ConvertReverbParameters() to convert to -* EFX EAX Reverb Presets for use with the OpenAL Effects Extension. -* -************************************************************************************************/ - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_GENERIC \ - {0, 7.5f, 1.000f, -1000, -100, 0, 1.49f, 0.83f, 1.00f, -2602, 0.007f, 0.00f,0.00f,0.00f, 200, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_PADDEDCELL \ - {1, 1.4f, 1.000f, -1000, -6000, 0, 0.17f, 0.10f, 1.00f, -1204, 0.001f, 0.00f,0.00f,0.00f, 207, 0.002f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_ROOM \ - {2, 1.9f, 1.000f, -1000, -454, 0, 0.40f, 0.83f, 1.00f, -1646, 0.002f, 0.00f,0.00f,0.00f, 53, 0.003f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_BATHROOM \ - {3, 1.4f, 1.000f, -1000, -1200, 0, 1.49f, 0.54f, 1.00f, -370, 0.007f, 0.00f,0.00f,0.00f, 1030, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_LIVINGROOM \ - {4, 2.5f, 1.000f, -1000, -6000, 0, 0.50f, 0.10f, 1.00f, -1376, 0.003f, 0.00f,0.00f,0.00f, -1104, 0.004f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_STONEROOM \ - {5, 11.6f, 1.000f, -1000, -300, 0, 2.31f, 0.64f, 1.00f, -711, 0.012f, 0.00f,0.00f,0.00f, 83, 0.017f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_AUDITORIUM \ - {6, 21.6f, 1.000f, -1000, -476, 0, 4.32f, 0.59f, 1.00f, -789, 0.020f, 0.00f,0.00f,0.00f, -289, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_CONCERTHALL \ - {7, 19.6f, 1.000f, -1000, -500, 0, 3.92f, 0.70f, 1.00f, -1230, 0.020f, 0.00f,0.00f,0.00f, -02, 0.029f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_CAVE \ - {8, 14.6f, 1.000f, -1000, 0, 0, 2.91f, 1.30f, 1.00f, -602, 0.015f, 0.00f,0.00f,0.00f, -302, 0.022f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } -#define REVERB_PRESET_ARENA \ - {9, 36.2f, 1.000f, -1000, -698, 0, 7.24f, 0.33f, 1.00f, -1166, 0.020f, 0.00f,0.00f,0.00f, 16, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_HANGAR \ - {10, 50.3f, 1.000f, -1000, -1000, 0, 10.05f, 0.23f, 1.00f, -602, 0.020f, 0.00f,0.00f,0.00f, 198, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_CARPETTEDHALLWAY \ - {11, 1.9f, 1.000f, -1000, -4000, 0, 0.30f, 0.10f, 1.00f, -1831, 0.002f, 0.00f,0.00f,0.00f, -1630, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_HALLWAY \ - {12, 1.8f, 1.000f, -1000, -300, 0, 1.49f, 0.59f, 1.00f, -1219, 0.007f, 0.00f,0.00f,0.00f, 441, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_STONECORRIDOR \ - {13, 13.5f, 1.000f, -1000, -237, 0, 2.70f, 0.79f, 1.00f, -1214, 0.013f, 0.00f,0.00f,0.00f, 395, 0.020f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_ALLEY \ - {14, 7.5f, 0.300f, -1000, -270, 0, 1.49f, 0.86f, 1.00f, -1204, 0.007f, 0.00f,0.00f,0.00f, -4, 0.011f, 0.00f,0.00f,0.00f, 0.125f, 0.950f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_FOREST \ - {15, 38.0f, 0.300f, -1000, -3300, 0, 1.49f, 0.54f, 1.00f, -2560, 0.162f, 0.00f,0.00f,0.00f, -229, 0.088f, 0.00f,0.00f,0.00f, 0.125f, 1.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_CITY \ - {16, 7.5f, 0.500f, -1000, -800, 0, 1.49f, 0.67f, 1.00f, -2273, 0.007f, 0.00f,0.00f,0.00f, -1691, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_MOUNTAINS \ - {17, 100.0f, 0.270f, -1000, -2500, 0, 1.49f, 0.21f, 1.00f, -2780, 0.300f, 0.00f,0.00f,0.00f, -1434, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } -#define REVERB_PRESET_QUARRY \ - {18, 17.5f, 1.000f, -1000, -1000, 0, 1.49f, 0.83f, 1.00f, -10000, 0.061f, 0.00f,0.00f,0.00f, 500, 0.025f, 0.00f,0.00f,0.00f, 0.125f, 0.700f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_PLAIN \ - {19, 42.5f, 0.210f, -1000, -2000, 0, 1.49f, 0.50f, 1.00f, -2466, 0.179f, 0.00f,0.00f,0.00f, -1926, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_PARKINGLOT \ - {20, 8.3f, 1.000f, -1000, 0, 0, 1.65f, 1.50f, 1.00f, -1363, 0.008f, 0.00f,0.00f,0.00f, -1153, 0.012f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } -#define REVERB_PRESET_SEWERPIPE \ - {21, 1.7f, 0.800f, -1000, -1000, 0, 2.81f, 0.14f, 1.00f, 429, 0.014f, 0.00f,0.00f,0.00f, 1023, 0.021f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_UNDERWATER \ - {22, 1.8f, 1.000f, -1000, -4000, 0, 1.49f, 0.10f, 1.00f, -449, 0.007f, 0.00f,0.00f,0.00f, 1700, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 1.180f, 0.348f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_DRUGGED \ - {23, 1.9f, 0.500f, -1000, 0, 0, 8.39f, 1.39f, 1.00f, -115, 0.002f, 0.00f,0.00f,0.00f, 985, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } -#define REVERB_PRESET_DIZZY \ - {24, 1.8f, 0.600f, -1000, -400, 0, 17.23f, 0.56f, 1.00f, -1713, 0.020f, 0.00f,0.00f,0.00f, -613, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.810f, 0.310f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } -#define REVERB_PRESET_PSYCHOTIC \ - {25, 1.0f, 0.500f, -1000, -151, 0, 7.56f, 0.91f, 1.00f, -626, 0.020f, 0.00f,0.00f,0.00f, 774, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 4.000f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } - - -// CASTLE PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_CASTLE_SMALLROOM \ - { 26, 8.3f, 0.890f, -1000, -800, -2000, 1.22f, 0.83f, 0.31f, -100, 0.022f, 0.00f,0.00f,0.00f, 600, 0.011f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } -#define REVERB_PRESET_CASTLE_SHORTPASSAGE \ - { 26, 8.3f, 0.890f, -1000, -1000, -2000, 2.32f, 0.83f, 0.31f, -100, 0.007f, 0.00f,0.00f,0.00f, 200, 0.023f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } -#define REVERB_PRESET_CASTLE_MEDIUMROOM \ - { 26, 8.3f, 0.930f, -1000, -1100, -2000, 2.04f, 0.83f, 0.46f, -400, 0.022f, 0.00f,0.00f,0.00f, 400, 0.011f, 0.00f,0.00f,0.00f, 0.155f, 0.030f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } -#define REVERB_PRESET_CASTLE_LONGPASSAGE \ - { 26, 8.3f, 0.890f, -1000, -800, -2000, 3.42f, 0.83f, 0.31f, -100, 0.007f, 0.00f,0.00f,0.00f, 300, 0.023f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } -#define REVERB_PRESET_CASTLE_LARGEROOM \ - { 26, 8.3f, 0.820f, -1000, -1100, -1800, 2.53f, 0.83f, 0.50f, -700, 0.034f, 0.00f,0.00f,0.00f, 200, 0.016f, 0.00f,0.00f,0.00f, 0.185f, 0.070f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } -#define REVERB_PRESET_CASTLE_HALL \ - { 26, 8.3f, 0.810f, -1000, -1100, -1500, 3.14f, 0.79f, 0.62f, -1500, 0.056f, 0.00f,0.00f,0.00f, 100, 0.024f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } -#define REVERB_PRESET_CASTLE_CUPBOARD \ - { 26, 8.3f, 0.890f, -1000, -1100, -2000, 0.67f, 0.87f, 0.31f, 300, 0.010f, 0.00f,0.00f,0.00f, 1100, 0.007f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } -#define REVERB_PRESET_CASTLE_COURTYARD \ - { 26, 8.3f, 0.420f, -1000, -700, -1400, 2.13f, 0.61f, 0.23f, -1300, 0.160f, 0.00f,0.00f,0.00f, -300, 0.036f, 0.00f,0.00f,0.00f, 0.250f, 0.370f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } -#define REVERB_PRESET_CASTLE_ALCOVE \ - { 26, 8.3f, 0.890f, -1000, -600, -2000, 1.64f, 0.87f, 0.31f, 00, 0.007f, 0.00f,0.00f,0.00f, 300, 0.034f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } - - -// FACTORY PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_FACTORY_ALCOVE \ - { 26, 1.8f, 0.590f, -1200, -200, -600, 3.14f, 0.65f, 1.31f, 300, 0.010f, 0.00f,0.00f,0.00f, 000, 0.038f, 0.00f,0.00f,0.00f, 0.114f, 0.100f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } -#define REVERB_PRESET_FACTORY_SHORTPASSAGE \ - { 26, 1.8f, 0.640f, -1200, -200, -600, 2.53f, 0.65f, 1.31f, 0, 0.010f, 0.00f,0.00f,0.00f, 200, 0.038f, 0.00f,0.00f,0.00f, 0.135f, 0.230f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } -#define REVERB_PRESET_FACTORY_MEDIUMROOM \ - { 26, 1.9f, 0.820f, -1200, -200, -600, 2.76f, 0.65f, 1.31f, -1100, 0.022f, 0.00f,0.00f,0.00f, 300, 0.023f, 0.00f,0.00f,0.00f, 0.174f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } -#define REVERB_PRESET_FACTORY_LONGPASSAGE \ - { 26, 1.8f, 0.640f, -1200, -200, -600, 4.06f, 0.65f, 1.31f, 0, 0.020f, 0.00f,0.00f,0.00f, 200, 0.037f, 0.00f,0.00f,0.00f, 0.135f, 0.230f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } -#define REVERB_PRESET_FACTORY_LARGEROOM \ - { 26, 1.9f, 0.750f, -1200, -300, -400, 4.24f, 0.51f, 1.31f, -1500, 0.039f, 0.00f,0.00f,0.00f, 100, 0.023f, 0.00f,0.00f,0.00f, 0.231f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } -#define REVERB_PRESET_FACTORY_HALL \ - { 26, 1.9f, 0.750f, -1000, -300, -400, 7.43f, 0.51f, 1.31f, -2400, 0.073f, 0.00f,0.00f,0.00f, -100, 0.027f, 0.00f,0.00f,0.00f, 0.250f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } -#define REVERB_PRESET_FACTORY_CUPBOARD \ - { 26, 1.7f, 0.630f, -1200, -200, -600, 0.49f, 0.65f, 1.31f, 200, 0.010f, 0.00f,0.00f,0.00f, 600, 0.032f, 0.00f,0.00f,0.00f, 0.107f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } -#define REVERB_PRESET_FACTORY_COURTYARD \ - { 26, 1.7f, 0.570f, -1000, -1000, -400, 2.32f, 0.29f, 0.56f, -1300, 0.140f, 0.00f,0.00f,0.00f, -800, 0.039f, 0.00f,0.00f,0.00f, 0.250f, 0.290f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } -#define REVERB_PRESET_FACTORY_SMALLROOM \ - { 26, 1.8f, 0.820f, -1000, -200, -600, 1.72f, 0.65f, 1.31f, -300, 0.010f, 0.00f,0.00f,0.00f, 500, 0.024f, 0.00f,0.00f,0.00f, 0.119f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } - - -// ICE PALACE PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_ICEPALACE_ALCOVE \ - { 26, 2.7f, 0.840f, -1000, -500, -1100, 2.76f, 1.46f, 0.28f, 100, 0.010f, 0.00f,0.00f,0.00f, -100, 0.030f, 0.00f,0.00f,0.00f, 0.161f, 0.090f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } -#define REVERB_PRESET_ICEPALACE_SHORTPASSAGE \ - { 26, 2.7f, 0.750f, -1000, -500, -1100, 1.79f, 1.46f, 0.28f, -600, 0.010f, 0.00f,0.00f,0.00f, 100, 0.019f, 0.00f,0.00f,0.00f, 0.177f, 0.090f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } -#define REVERB_PRESET_ICEPALACE_MEDIUMROOM \ - { 26, 2.7f, 0.870f, -1000, -500, -700, 2.22f, 1.53f, 0.32f, -800, 0.039f, 0.00f,0.00f,0.00f, 100, 0.027f, 0.00f,0.00f,0.00f, 0.186f, 0.120f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } -#define REVERB_PRESET_ICEPALACE_LONGPASSAGE \ - { 26, 2.7f, 0.770f, -1000, -500, -800, 3.01f, 1.46f, 0.28f, -200, 0.012f, 0.00f,0.00f,0.00f, 200, 0.025f, 0.00f,0.00f,0.00f, 0.186f, 0.040f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } -#define REVERB_PRESET_ICEPALACE_LARGEROOM \ - { 26, 2.9f, 0.810f, -1000, -500, -700, 3.14f, 1.53f, 0.32f, -1200, 0.039f, 0.00f,0.00f,0.00f, 000, 0.027f, 0.00f,0.00f,0.00f, 0.214f, 0.110f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } -#define REVERB_PRESET_ICEPALACE_HALL \ - { 26, 2.9f, 0.760f, -1000, -700, -500, 5.49f, 1.53f, 0.38f, -1900, 0.054f, 0.00f,0.00f,0.00f, -400, 0.052f, 0.00f,0.00f,0.00f, 0.226f, 0.110f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } -#define REVERB_PRESET_ICEPALACE_CUPBOARD \ - { 26, 2.7f, 0.830f, -1000, -600, -1300, 0.76f, 1.53f, 0.26f, 100, 0.012f, 0.00f,0.00f,0.00f, 600, 0.016f, 0.00f,0.00f,0.00f, 0.143f, 0.080f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } -#define REVERB_PRESET_ICEPALACE_COURTYARD \ - { 26, 2.9f, 0.590f, -1000, -1100, -1000, 2.04f, 1.20f, 0.38f, -1000, 0.173f, 0.00f,0.00f,0.00f, -1000, 0.043f, 0.00f,0.00f,0.00f, 0.235f, 0.480f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } -#define REVERB_PRESET_ICEPALACE_SMALLROOM \ - { 26, 2.7f, 0.840f, -1000, -500, -1100, 1.51f, 1.53f, 0.27f, -100, 0.010f, 0.00f,0.00f,0.00f, 300, 0.011f, 0.00f,0.00f,0.00f, 0.164f, 0.140f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } - - -// SPACE STATION PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_SPACESTATION_ALCOVE \ - { 26, 1.5f, 0.780f, -1000, -300, -100, 1.16f, 0.81f, 0.55f, 300, 0.007f, 0.00f,0.00f,0.00f, 000, 0.018f, 0.00f,0.00f,0.00f, 0.192f, 0.210f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPACESTATION_MEDIUMROOM \ - { 26, 1.5f, 0.750f, -1000, -400, -100, 3.01f, 0.50f, 0.55f, -800, 0.034f, 0.00f,0.00f,0.00f, 100, 0.035f, 0.00f,0.00f,0.00f, 0.209f, 0.310f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPACESTATION_SHORTPASSAGE \ - { 26, 1.5f, 0.870f, -1000, -400, -100, 3.57f, 0.50f, 0.55f, 0, 0.012f, 0.00f,0.00f,0.00f, 100, 0.016f, 0.00f,0.00f,0.00f, 0.172f, 0.200f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPACESTATION_LONGPASSAGE \ - { 26, 1.9f, 0.820f, -1000, -400, -100, 4.62f, 0.62f, 0.55f, 0, 0.012f, 0.00f,0.00f,0.00f, 200, 0.031f, 0.00f,0.00f,0.00f, 0.250f, 0.230f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPACESTATION_LARGEROOM \ - { 26, 1.8f, 0.810f, -1000, -400, -100, 3.89f, 0.38f, 0.61f, -1000, 0.056f, 0.00f,0.00f,0.00f, -100, 0.035f, 0.00f,0.00f,0.00f, 0.233f, 0.280f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPACESTATION_HALL \ - { 26, 1.9f, 0.870f, -1000, -400, -100, 7.11f, 0.38f, 0.61f, -1500, 0.100f, 0.00f,0.00f,0.00f, -400, 0.047f, 0.00f,0.00f,0.00f, 0.250f, 0.250f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPACESTATION_CUPBOARD \ - { 26, 1.4f, 0.560f, -1000, -300, -100, 0.79f, 0.81f, 0.55f, 300, 0.007f, 0.00f,0.00f,0.00f, 500, 0.018f, 0.00f,0.00f,0.00f, 0.181f, 0.310f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPACESTATION_SMALLROOM \ - { 26, 1.5f, 0.700f, -1000, -300, -100, 1.72f, 0.82f, 0.55f, -200, 0.007f, 0.00f,0.00f,0.00f, 300, 0.013f, 0.00f,0.00f,0.00f, 0.188f, 0.260f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } - - -// WOODEN GALLEON PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_WOODEN_ALCOVE \ - { 26, 7.5f, 1.000f, -1000, -1800, -1000, 1.22f, 0.62f, 0.91f, 100, 0.012f, 0.00f,0.00f,0.00f, -300, 0.024f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } -#define REVERB_PRESET_WOODEN_SHORTPASSAGE \ - { 26, 7.5f, 1.000f, -1000, -1800, -1000, 1.75f, 0.50f, 0.87f, -100, 0.012f, 0.00f,0.00f,0.00f, -400, 0.024f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } -#define REVERB_PRESET_WOODEN_MEDIUMROOM \ - { 26, 7.5f, 1.000f, -1000, -2000, -1100, 1.47f, 0.42f, 0.82f, -100, 0.049f, 0.00f,0.00f,0.00f, -100, 0.029f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } -#define REVERB_PRESET_WOODEN_LONGPASSAGE \ - { 26, 7.5f, 1.000f, -1000, -2000, -1000, 1.99f, 0.40f, 0.79f, 000, 0.020f, 0.00f,0.00f,0.00f, -700, 0.036f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } -#define REVERB_PRESET_WOODEN_LARGEROOM \ - { 26, 7.5f, 1.000f, -1000, -2100, -1100, 2.65f, 0.33f, 0.82f, -100, 0.066f, 0.00f,0.00f,0.00f, -200, 0.049f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } -#define REVERB_PRESET_WOODEN_HALL \ - { 26, 7.5f, 1.000f, -1000, -2200, -1100, 3.45f, 0.30f, 0.82f, -100, 0.088f, 0.00f,0.00f,0.00f, -200, 0.063f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } -#define REVERB_PRESET_WOODEN_CUPBOARD \ - { 26, 7.5f, 1.000f, -1000, -1700, -1000, 0.56f, 0.46f, 0.91f, 100, 0.012f, 0.00f,0.00f,0.00f, 100, 0.028f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } -#define REVERB_PRESET_WOODEN_SMALLROOM \ - { 26, 7.5f, 1.000f, -1000, -1900, -1000, 0.79f, 0.32f, 0.87f, 00, 0.032f, 0.00f,0.00f,0.00f, -100, 0.029f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } -#define REVERB_PRESET_WOODEN_COURTYARD \ - { 26, 7.5f, 0.650f, -1000, -2200, -1000, 1.79f, 0.35f, 0.79f, -500, 0.123f, 0.00f,0.00f,0.00f, -2000, 0.032f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } - - -// SPORTS PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_SPORT_EMPTYSTADIUM \ - { 26, 7.2f, 1.000f, -1000, -700, -200, 6.26f, 0.51f, 1.10f, -2400, 0.183f, 0.00f,0.00f,0.00f, -800, 0.038f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } -#define REVERB_PRESET_SPORT_SQUASHCOURT \ - { 26, 7.5f, 0.750f, -1000, -1000, -200, 2.22f, 0.91f, 1.16f, -700, 0.007f, 0.00f,0.00f,0.00f, -200, 0.011f, 0.00f,0.00f,0.00f, 0.126f, 0.190f, 0.250f, 0.000f, -5.0f, 7176.9f, 211.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL \ - { 26, 36.2f, 0.700f, -1000, -200, -100, 2.76f, 1.25f, 1.14f, -400, 0.020f, 0.00f,0.00f,0.00f, -200, 0.030f, 0.00f,0.00f,0.00f, 0.179f, 0.150f, 0.895f, 0.190f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x0 } -#define REVERB_PRESET_SPORT_LARGESWIMMINGPOOL\ - { 26, 36.2f, 0.820f, -1000, -200, 0, 5.49f, 1.31f, 1.14f, -700, 0.039f, 0.00f,0.00f,0.00f, -600, 0.049f, 0.00f,0.00f,0.00f, 0.222f, 0.550f, 1.159f, 0.210f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x0 } -#define REVERB_PRESET_SPORT_GYMNASIUM \ - { 26, 7.5f, 0.810f, -1000, -700, -100, 3.14f, 1.06f, 1.35f, -800, 0.029f, 0.00f,0.00f,0.00f, -500, 0.045f, 0.00f,0.00f,0.00f, 0.146f, 0.140f, 0.250f, 0.000f, -5.0f, 7176.9f, 211.2f, 0.00f, 0x20 } -#define REVERB_PRESET_SPORT_FULLSTADIUM \ - { 26, 7.2f, 1.000f, -1000, -2300, -200, 5.25f, 0.17f, 0.80f, -2000, 0.188f, 0.00f,0.00f,0.00f, -1100, 0.038f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } -#define REVERB_PRESET_SPORT_STADIUMTANNOY \ - { 26, 3.0f, 0.780f, -1000, -500, -600, 2.53f, 0.88f, 0.68f, -1100, 0.230f, 0.00f,0.00f,0.00f, -600, 0.063f, 0.00f,0.00f,0.00f, 0.250f, 0.200f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } - - -// PREFAB PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_PREFAB_WORKSHOP \ - { 26, 1.9f, 1.000f, -1000, -1700, -800, 0.76f, 1.00f, 1.00f, 0, 0.012f, 0.00f,0.00f,0.00f, 100, 0.012f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x0 } -#define REVERB_PRESET_PREFAB_SCHOOLROOM \ - { 26, 1.86f, 0.690f, -1000, -400, -600, 0.98f, 0.45f, 0.18f, 300, 0.017f, 0.00f,0.00f,0.00f, 300, 0.015f, 0.00f,0.00f,0.00f, 0.095f, 0.140f, 0.250f, 0.000f, -5.0f, 7176.9f, 211.2f, 0.00f, 0x20 } -#define REVERB_PRESET_PREFAB_PRACTISEROOM \ - { 26, 1.86f, 0.870f, -1000, -800, -600, 1.12f, 0.56f, 0.18f, 200, 0.010f, 0.00f,0.00f,0.00f, 300, 0.011f, 0.00f,0.00f,0.00f, 0.095f, 0.140f, 0.250f, 0.000f, -5.0f, 7176.9f, 211.2f, 0.00f, 0x20 } -#define REVERB_PRESET_PREFAB_OUTHOUSE \ - { 26, 80.3f, 0.820f, -1000, -1900, -1600, 1.38f, 0.38f, 0.35f, -100, 0.024f, 0.00f,0.00f,-0.00f, -400, 0.044f, 0.00f,0.00f,0.00f, 0.121f, 0.170f, 0.250f, 0.000f, -5.0f, 2854.4f, 107.5f, 0.00f, 0x0 } -#define REVERB_PRESET_PREFAB_CARAVAN \ - { 26, 8.3f, 1.000f, -1000, -2100, -1800, 0.43f, 1.50f, 1.00f, 0, 0.012f, 0.00f,0.00f,0.00f, 600, 0.012f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } - // for US developers, a caravan is the same as a trailer =o) - - -// DOME AND PIPE PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_DOME_TOMB \ - { 26, 51.8f, 0.790f, -1000, -900, -1300, 4.18f, 0.21f, 0.10f, -825, 0.030f, 0.00f,0.00f,0.00f, 450, 0.022f, 0.00f,0.00f,0.00f, 0.177f, 0.190f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x0 } -#define REVERB_PRESET_PIPE_SMALL \ - { 26, 50.3f, 1.000f, -1000, -900, -1300, 5.04f, 0.10f, 0.10f, -600, 0.032f, 0.00f,0.00f,0.00f, 800, 0.015f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x3f } -#define REVERB_PRESET_DOME_SAINTPAULS \ - { 26, 50.3f, 0.870f, -1000, -900, -1300, 10.48f, 0.19f, 0.10f, -1500, 0.090f, 0.00f,0.00f,0.00f, 200, 0.042f, 0.00f,0.00f,0.00f, 0.250f, 0.120f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x3f } -#define REVERB_PRESET_PIPE_LONGTHIN \ - { 26, 1.6f, 0.910f, -1000, -700, -1100, 9.21f, 0.18f, 0.10f, -300, 0.010f, 0.00f,0.00f,0.00f, -300, 0.022f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x0 } -#define REVERB_PRESET_PIPE_LARGE \ - { 26, 50.3f, 1.000f, -1000, -900, -1300, 8.45f, 0.10f, 0.10f, -800, 0.046f, 0.00f,0.00f,0.00f, 400, 0.032f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x3f } -#define REVERB_PRESET_PIPE_RESONANT \ - { 26, 1.3f, 0.910f, -1000, -700, -1100, 6.81f, 0.18f, 0.10f, -300, 0.010f, 0.00f,0.00f,0.00f, 00, 0.022f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x0 } - - -// OUTDOORS PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_OUTDOORS_BACKYARD \ - { 26, 80.3f, 0.450f, -1000, -1200, -600, 1.12f, 0.34f, 0.46f, -700, 0.069f, 0.00f,0.00f,-0.00f, -300, 0.023f, 0.00f,0.00f,0.00f, 0.218f, 0.340f, 0.250f, 0.000f, -5.0f, 4399.1f, 242.9f, 0.00f, 0x0 } -#define REVERB_PRESET_OUTDOORS_ROLLINGPLAINS \ - { 26, 80.3f, 0.000f, -1000, -3900, -400, 2.13f, 0.21f, 0.46f, -1500, 0.300f, 0.00f,0.00f,-0.00f, -700, 0.019f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -5.0f, 4399.1f, 242.9f, 0.00f, 0x0 } -#define REVERB_PRESET_OUTDOORS_DEEPCANYON \ - { 26, 80.3f, 0.740f, -1000, -1500, -400, 3.89f, 0.21f, 0.46f, -1000, 0.223f, 0.00f,0.00f,-0.00f, -900, 0.019f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -5.0f, 4399.1f, 242.9f, 0.00f, 0x0 } -#define REVERB_PRESET_OUTDOORS_CREEK \ - { 26, 80.3f, 0.350f, -1000, -1500, -600, 2.13f, 0.21f, 0.46f, -800, 0.115f, 0.00f,0.00f,-0.00f, -1400, 0.031f, 0.00f,0.00f,0.00f, 0.218f, 0.340f, 0.250f, 0.000f, -5.0f, 4399.1f, 242.9f, 0.00f, 0x0 } -#define REVERB_PRESET_OUTDOORS_VALLEY \ - { 26, 80.3f, 0.280f, -1000, -3100, -1600, 2.88f, 0.26f, 0.35f, -1700, 0.263f, 0.00f,0.00f,-0.00f, -800, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 0.340f, 0.250f, 0.000f, -5.0f, 2854.4f, 107.5f, 0.00f, 0x0 } - - -// MOOD PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_MOOD_HEAVEN \ - { 26, 19.6f, 0.940f, -1000, -200, -700, 5.04f, 1.12f, 0.56f, -1230, 0.020f, 0.00f,0.00f,0.00f, 200, 0.029f, 0.00f,0.00f,0.00f, 0.250f, 0.080f, 2.742f, 0.050f, -2.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_MOOD_HELL \ - { 26, 100.0f, 0.570f, -1000, -900, -700, 3.57f, 0.49f, 2.00f, -10000, 0.020f, 0.00f,0.00f,0.00f, 300, 0.030f, 0.00f,0.00f,0.00f, 0.110f, 0.040f, 2.109f, 0.520f, -5.0f, 5000.0f, 139.5f, 0.00f, 0x40 } -#define REVERB_PRESET_MOOD_MEMORY \ - { 26, 8.0f, 0.850f, -1000, -400, -900, 4.06f, 0.82f, 0.56f, -2800, 0.000f, 0.00f,0.00f,0.00f, 100, 0.000f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.474f, 0.450f, -10.0f, 5000.0f, 250.0f, 0.00f, 0x0 } - - -// DRIVING SIMULATION PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_DRIVING_COMMENTATOR \ - { 26, 3.0f, 0.000f, 1000, -500, -600, 2.42f, 0.88f, 0.68f, -1400, 0.093f, 0.00f,0.00f,0.00f, -1200, 0.017f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -10.0f, 5000.0f, 250.0f, 0.00f, 0x20 } -#define REVERB_PRESET_DRIVING_PITGARAGE \ - { 26, 1.9f, 0.590f, -1000, -300, -500, 1.72f, 0.93f, 0.87f, -500, 0.000f, 0.00f,0.00f,0.00f, 200, 0.016f, 0.00f,0.00f,0.00f, 0.250f, 0.110f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x0 } -#define REVERB_PRESET_DRIVING_INCAR_RACER \ - { 26, 1.1f, 0.800f, -1000, 0, -200, 0.17f, 2.00f, 0.41f, 500, 0.007f, 0.00f,0.00f,0.00f, -300, 0.015f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10268.2f, 251.0f, 0.00f, 0x20 } -#define REVERB_PRESET_DRIVING_INCAR_SPORTS \ - { 26, 1.1f, 0.800f, -1000, -400, 0, 0.17f, 0.75f, 0.41f, 0, 0.010f, 0.00f,0.00f,0.00f, -500, 0.000f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10268.2f, 251.0f, 0.00f, 0x20 } -#define REVERB_PRESET_DRIVING_INCAR_LUXURY \ - { 26, 1.6f, 1.000f, -1000, -2000, -600, 0.13f, 0.41f, 0.46f, -200, 0.010f, 0.00f,0.00f,0.00f, 400, 0.010f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10268.2f, 251.0f, 0.00f, 0x20 } -#define REVERB_PRESET_DRIVING_FULLGRANDSTAND \ - { 26, 8.3f, 1.000f, -1000, -1100, -400, 3.01f, 1.37f, 1.28f, -900, 0.090f, 0.00f,0.00f,0.00f, -1500, 0.049f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10420.2f, 250.0f, 0.00f, 0x1f } -#define REVERB_PRESET_DRIVING_EMPTYGRANDSTAND \ - { 26, 8.3f, 1.000f, -1000, 0, -200, 4.62f, 1.75f, 1.40f, -1363, 0.090f, 0.00f,0.00f,0.00f, -1200, 0.049f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10420.2f, 250.0f, 0.00f, 0x1f } -#define REVERB_PRESET_DRIVING_TUNNEL \ - { 26, 3.1f, 0.810f, -1000, -800, -100, 3.42f, 0.94f, 1.31f, -300, 0.051f, 0.00f,0.00f,0.00f, -300, 0.047f, 0.00f,0.00f,0.00f, 0.214f, 0.050f, 0.250f, 0.000f, -5.0f, 5000.0f, 155.3f, 0.00f, 0x20 } - - -// CITY PRESETS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_CITY_STREETS \ - { 26, 3.0f, 0.780f, -1000, -300, -100, 1.79f, 1.12f, 0.91f, -1100, 0.046f, 0.00f,0.00f,0.00f, -1400, 0.028f, 0.00f,0.00f,0.00f, 0.250f, 0.200f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } -#define REVERB_PRESET_CITY_SUBWAY \ - { 26, 3.0f, 0.740f, -1000, -300, -100, 3.01f, 1.23f, 0.91f, -300, 0.046f, 0.00f,0.00f,0.00f, 200, 0.028f, 0.00f,0.00f,0.00f, 0.125f, 0.210f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } -#define REVERB_PRESET_CITY_MUSEUM \ - { 26, 80.3f, 0.820f, -1000, -1500, -1500, 3.28f, 1.40f, 0.57f, -1200, 0.039f, 0.00f,0.00f,-0.00f, -100, 0.034f, 0.00f,0.00f,0.00f, 0.130f, 0.170f, 0.250f, 0.000f, -5.0f, 2854.4f, 107.5f, 0.00f, 0x0 } -#define REVERB_PRESET_CITY_LIBRARY \ - { 26, 80.3f, 0.820f, -1000, -1100, -2100, 2.76f, 0.89f, 0.41f, -900, 0.029f, 0.00f,0.00f,-0.00f, -100, 0.020f, 0.00f,0.00f,0.00f, 0.130f, 0.170f, 0.250f, 0.000f, -5.0f, 2854.4f, 107.5f, 0.00f, 0x0 } -#define REVERB_PRESET_CITY_UNDERPASS \ - { 26, 3.0f, 0.820f, -1000, -700, -100, 3.57f, 1.12f, 0.91f, -800, 0.059f, 0.00f,0.00f,0.00f, -100, 0.037f, 0.00f,0.00f,0.00f, 0.250f, 0.140f, 0.250f, 0.000f, -7.0f, 5000.0f, 250.0f, 0.00f, 0x20 } -#define REVERB_PRESET_CITY_ABANDONED \ - { 26, 3.0f, 0.690f, -1000, -200, -100, 3.28f, 1.17f, 0.91f, -700, 0.044f, 0.00f,0.00f,0.00f, -1100, 0.024f, 0.00f,0.00f,0.00f, 0.250f, 0.200f, 0.250f, 0.000f, -3.0f, 5000.0f, 250.0f, 0.00f, 0x20 } - - -// MISC ROOMS - -// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS -#define REVERB_PRESET_DUSTYROOM \ - { 26, 1.8f, 0.560f, -1000, -200, -300, 1.79f, 0.38f, 0.21f, -600, 0.002f, 0.00f,0.00f,0.00f, 200, 0.006f, 0.00f,0.00f,0.00f, 0.202f, 0.050f, 0.250f, 0.000f, -10.0f, 13046.0f, 163.3f, 0.00f, 0x20 } -#define REVERB_PRESET_CHAPEL \ - { 26, 19.6f, 0.840f, -1000, -500, 0, 4.62f, 0.64f, 1.23f, -700, 0.032f, 0.00f,0.00f,0.00f, -200, 0.049f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.110f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } -#define REVERB_PRESET_SMALLWATERROOM \ - { 26, 36.2f, 0.700f, -1000, -698, 0, 1.51f, 1.25f, 1.14f, -100, 0.020f, 0.00f,0.00f,0.00f, 300, 0.030f, 0.00f,0.00f,0.00f, 0.179f, 0.150f, 0.895f, 0.190f, -7.0f, 5000.0f, 250.0f, 0.00f, 0x0 } diff --git a/Engine/lib/openal/win32/al/al.h b/Engine/lib/openal/win32/al/al.h deleted file mode 100644 index 981b0890b..000000000 --- a/Engine/lib/openal/win32/al/al.h +++ /dev/null @@ -1,750 +0,0 @@ -#ifndef AL_AL_H -#define AL_AL_H - -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2000 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 - */ - -#if defined(__cplusplus) -extern "C" { -#endif - -#if defined(_WIN32) && !defined(_XBOX) - /* _OPENAL32LIB is deprecated */ - #if defined(AL_BUILD_LIBRARY) || defined (_OPENAL32LIB) - #define AL_API __declspec(dllexport) - #else - #define AL_API __declspec(dllimport) - #endif -#else - #define AL_API extern -#endif - -#if defined(_WIN32) - #define AL_APIENTRY __cdecl -#else - #define AL_APIENTRY -#endif - -#if TARGET_OS_MAC - #pragma export on -#endif - -/* The OPENAL, ALAPI, and ALAPIENTRY macros are deprecated, but are included for applications porting code - from AL 1.0 */ -#define OPENAL -#define ALAPI AL_API -#define ALAPIENTRY AL_APIENTRY - -#define AL_VERSION_1_0 -#define AL_VERSION_1_1 - - -/** 8-bit boolean */ -typedef char ALboolean; - -/** character */ -typedef char ALchar; - -/** signed 8-bit 2's complement integer */ -typedef char ALbyte; - -/** unsigned 8-bit integer */ -typedef unsigned char ALubyte; - -/** signed 16-bit 2's complement integer */ -typedef short ALshort; - -/** unsigned 16-bit integer */ -typedef unsigned short ALushort; - -/** signed 32-bit 2's complement integer */ -typedef int ALint; - -/** unsigned 32-bit integer */ -typedef unsigned int ALuint; - -/** non-negative 32-bit binary integer size */ -typedef int ALsizei; - -/** enumerated 32-bit value */ -typedef int ALenum; - -/** 32-bit IEEE754 floating-point */ -typedef float ALfloat; - -/** 64-bit IEEE754 floating-point */ -typedef double ALdouble; - -/** void type (for opaque pointers only) */ -typedef void ALvoid; - - -/* Enumerant values begin at column 50. No tabs. */ - -/* bad value */ -#define AL_INVALID -1 - -#define AL_NONE 0 - -/* Boolean False. */ -#define AL_FALSE 0 - -/** Boolean True. */ -#define AL_TRUE 1 - -/** Indicate Source has relative coordinates. */ -#define AL_SOURCE_RELATIVE 0x202 - - - -/** - * Directional source, inner cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_INNER_ANGLE 0x1001 - -/** - * Directional source, outer cone angle, in degrees. - * Range: [0-360] - * Default: 360 - */ -#define AL_CONE_OUTER_ANGLE 0x1002 - -/** - * Specify the pitch to be applied, either at source, - * or on mixer results, at listener. - * Range: [0.5-2.0] - * Default: 1.0 - */ -#define AL_PITCH 0x1003 - -/** - * Specify the current location in three dimensional space. - * OpenAL, like OpenGL, uses a right handed coordinate system, - * where in a frontal default view X (thumb) points right, - * Y points up (index finger), and Z points towards the - * viewer/camera (middle finger). - * To switch from a left handed coordinate system, flip the - * sign on the Z coordinate. - * Listener position is always in the world coordinate system. - */ -#define AL_POSITION 0x1004 - -/** Specify the current direction. */ -#define AL_DIRECTION 0x1005 - -/** Specify the current velocity in three dimensional space. */ -#define AL_VELOCITY 0x1006 - -/** - * Indicate whether source is looping. - * Type: ALboolean? - * Range: [AL_TRUE, AL_FALSE] - * Default: FALSE. - */ -#define AL_LOOPING 0x1007 - -/** - * Indicate the buffer to provide sound samples. - * Type: ALuint. - * Range: any valid Buffer id. - */ -#define AL_BUFFER 0x1009 - -/** - * Indicate the gain (volume amplification) applied. - * Type: ALfloat. - * Range: ]0.0- ] - * A value of 1.0 means un-attenuated/unchanged. - * Each division by 2 equals an attenuation of -6dB. - * Each multiplicaton with 2 equals an amplification of +6dB. - * A value of 0.0 is meaningless with respect to a logarithmic - * scale; it is interpreted as zero volume - the channel - * is effectively disabled. - */ -#define AL_GAIN 0x100A - -/* - * Indicate minimum source attenuation - * Type: ALfloat - * Range: [0.0 - 1.0] - * - * Logarthmic - */ -#define AL_MIN_GAIN 0x100D - -/** - * Indicate maximum source attenuation - * Type: ALfloat - * Range: [0.0 - 1.0] - * - * Logarthmic - */ -#define AL_MAX_GAIN 0x100E - -/** - * Indicate listener orientation. - * - * at/up - */ -#define AL_ORIENTATION 0x100F - -/** - * Specify the channel mask. (Creative) - * Type: ALuint - * Range: [0 - 255] - */ -#define AL_CHANNEL_MASK 0x3000 - - -/** - * Source state information. - */ -#define AL_SOURCE_STATE 0x1010 -#define AL_INITIAL 0x1011 -#define AL_PLAYING 0x1012 -#define AL_PAUSED 0x1013 -#define AL_STOPPED 0x1014 - -/** - * Buffer Queue params - */ -#define AL_BUFFERS_QUEUED 0x1015 -#define AL_BUFFERS_PROCESSED 0x1016 - -/** - * Source buffer position information - */ -#define AL_SEC_OFFSET 0x1024 -#define AL_SAMPLE_OFFSET 0x1025 -#define AL_BYTE_OFFSET 0x1026 - -/* - * Source type (Static, Streaming or undetermined) - * Source is Static if a Buffer has been attached using AL_BUFFER - * Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers - * Source is undetermined when it has the NULL buffer attached - */ -#define AL_SOURCE_TYPE 0x1027 -#define AL_STATIC 0x1028 -#define AL_STREAMING 0x1029 -#define AL_UNDETERMINED 0x1030 - -/** Sound samples: format specifier. */ -#define AL_FORMAT_MONO8 0x1100 -#define AL_FORMAT_MONO16 0x1101 -#define AL_FORMAT_STEREO8 0x1102 -#define AL_FORMAT_STEREO16 0x1103 - -/** - * source specific reference distance - * Type: ALfloat - * Range: 0.0 - +inf - * - * At 0.0, no distance attenuation occurs. Default is - * 1.0. - */ -#define AL_REFERENCE_DISTANCE 0x1020 - -/** - * source specific rolloff factor - * Type: ALfloat - * Range: 0.0 - +inf - * - */ -#define AL_ROLLOFF_FACTOR 0x1021 - -/** - * Directional source, outer cone gain. - * - * Default: 0.0 - * Range: [0.0 - 1.0] - * Logarithmic - */ -#define AL_CONE_OUTER_GAIN 0x1022 - -/** - * Indicate distance above which sources are not - * attenuated using the inverse clamped distance model. - * - * Default: +inf - * Type: ALfloat - * Range: 0.0 - +inf - */ -#define AL_MAX_DISTANCE 0x1023 - -/** - * Sound samples: frequency, in units of Hertz [Hz]. - * This is the number of samples per second. Half of the - * sample frequency marks the maximum significant - * frequency component. - */ -#define AL_FREQUENCY 0x2001 -#define AL_BITS 0x2002 -#define AL_CHANNELS 0x2003 -#define AL_SIZE 0x2004 - -/** - * Buffer state. - * - * Not supported for public use (yet). - */ -#define AL_UNUSED 0x2010 -#define AL_PENDING 0x2011 -#define AL_PROCESSED 0x2012 - - -/** Errors: No Error. */ -#define AL_NO_ERROR AL_FALSE - -/** - * Invalid Name paramater passed to AL call. - */ -#define AL_INVALID_NAME 0xA001 - -/** - * Invalid parameter passed to AL call. - */ -#define AL_ILLEGAL_ENUM 0xA002 -#define AL_INVALID_ENUM 0xA002 - -/** - * Invalid enum parameter value. - */ -#define AL_INVALID_VALUE 0xA003 - -/** - * Illegal call. - */ -#define AL_ILLEGAL_COMMAND 0xA004 -#define AL_INVALID_OPERATION 0xA004 - - -/** - * No mojo. - */ -#define AL_OUT_OF_MEMORY 0xA005 - - -/** Context strings: Vendor Name. */ -#define AL_VENDOR 0xB001 -#define AL_VERSION 0xB002 -#define AL_RENDERER 0xB003 -#define AL_EXTENSIONS 0xB004 - -/** Global tweakage. */ - -/** - * Doppler scale. Default 1.0 - */ -#define AL_DOPPLER_FACTOR 0xC000 - -/** - * Tweaks speed of propagation. - */ -#define AL_DOPPLER_VELOCITY 0xC001 - -/** - * Speed of Sound in units per second - */ -#define AL_SPEED_OF_SOUND 0xC003 - -/** - * Distance models - * - * used in conjunction with DistanceModel - * - * implicit: NONE, which disances distance attenuation. - */ -#define AL_DISTANCE_MODEL 0xD000 -#define AL_INVERSE_DISTANCE 0xD001 -#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 -#define AL_LINEAR_DISTANCE 0xD003 -#define AL_LINEAR_DISTANCE_CLAMPED 0xD004 -#define AL_EXPONENT_DISTANCE 0xD005 -#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 - - -#if !defined(AL_NO_PROTOTYPES) - -/* - * Renderer State management - */ -AL_API void AL_APIENTRY alEnable( ALenum capability ); - -AL_API void AL_APIENTRY alDisable( ALenum capability ); - -AL_API ALboolean AL_APIENTRY alIsEnabled( ALenum capability ); - - -/* - * State retrieval - */ -AL_API const ALchar* AL_APIENTRY alGetString( ALenum param ); - -AL_API void AL_APIENTRY alGetBooleanv( ALenum param, ALboolean* data ); - -AL_API void AL_APIENTRY alGetIntegerv( ALenum param, ALint* data ); - -AL_API void AL_APIENTRY alGetFloatv( ALenum param, ALfloat* data ); - -AL_API void AL_APIENTRY alGetDoublev( ALenum param, ALdouble* data ); - -AL_API ALboolean AL_APIENTRY alGetBoolean( ALenum param ); - -AL_API ALint AL_APIENTRY alGetInteger( ALenum param ); - -AL_API ALfloat AL_APIENTRY alGetFloat( ALenum param ); - -AL_API ALdouble AL_APIENTRY alGetDouble( ALenum param ); - - -/* - * Error support. - * Obtain the most recent error generated in the AL state machine. - */ -AL_API ALenum AL_APIENTRY alGetError( void ); - - -/* - * Extension support. - * Query for the presence of an extension, and obtain any appropriate - * function pointers and enum values. - */ -AL_API ALboolean AL_APIENTRY alIsExtensionPresent( const ALchar* extname ); - -AL_API void* AL_APIENTRY alGetProcAddress( const ALchar* fname ); - -AL_API ALenum AL_APIENTRY alGetEnumValue( const ALchar* ename ); - - -/* - * LISTENER - * Listener represents the location and orientation of the - * 'user' in 3D-space. - * - * Properties include: - - * - * Gain AL_GAIN ALfloat - * Position AL_POSITION ALfloat[3] - * Velocity AL_VELOCITY ALfloat[3] - * Orientation AL_ORIENTATION ALfloat[6] (Forward then Up vectors) -*/ - -/* - * Set Listener parameters - */ -AL_API void AL_APIENTRY alListenerf( ALenum param, ALfloat value ); - -AL_API void AL_APIENTRY alListener3f( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); - -AL_API void AL_APIENTRY alListenerfv( ALenum param, const ALfloat* values ); - -AL_API void AL_APIENTRY alListeneri( ALenum param, ALint value ); - -AL_API void AL_APIENTRY alListener3i( ALenum param, ALint value1, ALint value2, ALint value3 ); - -AL_API void AL_APIENTRY alListeneriv( ALenum param, const ALint* values ); - -/* - * Get Listener parameters - */ -AL_API void AL_APIENTRY alGetListenerf( ALenum param, ALfloat* value ); - -AL_API void AL_APIENTRY alGetListener3f( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ); - -AL_API void AL_APIENTRY alGetListenerfv( ALenum param, ALfloat* values ); - -AL_API void AL_APIENTRY alGetListeneri( ALenum param, ALint* value ); - -AL_API void AL_APIENTRY alGetListener3i( ALenum param, ALint *value1, ALint *value2, ALint *value3 ); - -AL_API void AL_APIENTRY alGetListeneriv( ALenum param, ALint* values ); - - -/** - * SOURCE - * Sources represent individual sound objects in 3D-space. - * Sources take the PCM data provided in the specified Buffer, - * apply Source-specific modifications, and then - * submit them to be mixed according to spatial arrangement etc. - * - * Properties include: - - * - * Gain AL_GAIN ALfloat - * Min Gain AL_MIN_GAIN ALfloat - * Max Gain AL_MAX_GAIN ALfloat - * Position AL_POSITION ALfloat[3] - * Velocity AL_VELOCITY ALfloat[3] - * Direction AL_DIRECTION ALfloat[3] - * Head Relative Mode AL_SOURCE_RELATIVE ALint (AL_TRUE or AL_FALSE) - * Reference Distance AL_REFERENCE_DISTANCE ALfloat - * Max Distance AL_MAX_DISTANCE ALfloat - * RollOff Factor AL_ROLLOFF_FACTOR ALfloat - * Inner Angle AL_CONE_INNER_ANGLE ALint or ALfloat - * Outer Angle AL_CONE_OUTER_ANGLE ALint or ALfloat - * Cone Outer Gain AL_CONE_OUTER_GAIN ALint or ALfloat - * Pitch AL_PITCH ALfloat - * Looping AL_LOOPING ALint (AL_TRUE or AL_FALSE) - * MS Offset AL_MSEC_OFFSET ALint or ALfloat - * Byte Offset AL_BYTE_OFFSET ALint or ALfloat - * Sample Offset AL_SAMPLE_OFFSET ALint or ALfloat - * Attached Buffer AL_BUFFER ALint - * State (Query only) AL_SOURCE_STATE ALint - * Buffers Queued (Query only) AL_BUFFERS_QUEUED ALint - * Buffers Processed (Query only) AL_BUFFERS_PROCESSED ALint - */ - -/* Create Source objects */ -AL_API void AL_APIENTRY alGenSources( ALsizei n, ALuint* sources ); - -/* Delete Source objects */ -AL_API void AL_APIENTRY alDeleteSources( ALsizei n, const ALuint* sources ); - -/* Verify a handle is a valid Source */ -AL_API ALboolean AL_APIENTRY alIsSource( ALuint sid ); - -/* - * Set Source parameters - */ -AL_API void AL_APIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value ); - -AL_API void AL_APIENTRY alSource3f( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); - -AL_API void AL_APIENTRY alSourcefv( ALuint sid, ALenum param, const ALfloat* values ); - -AL_API void AL_APIENTRY alSourcei( ALuint sid, ALenum param, ALint value ); - -AL_API void AL_APIENTRY alSource3i( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ); - -AL_API void AL_APIENTRY alSourceiv( ALuint sid, ALenum param, const ALint* values ); - -/* - * Get Source parameters - */ -AL_API void AL_APIENTRY alGetSourcef( ALuint sid, ALenum param, ALfloat* value ); - -AL_API void AL_APIENTRY alGetSource3f( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); - -AL_API void AL_APIENTRY alGetSourcefv( ALuint sid, ALenum param, ALfloat* values ); - -AL_API void AL_APIENTRY alGetSourcei( ALuint sid, ALenum param, ALint* value ); - -AL_API void AL_APIENTRY alGetSource3i( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3); - -AL_API void AL_APIENTRY alGetSourceiv( ALuint sid, ALenum param, ALint* values ); - - -/* - * Source vector based playback calls - */ - -/* Play, replay, or resume (if paused) a list of Sources */ -AL_API void AL_APIENTRY alSourcePlayv( ALsizei ns, const ALuint *sids ); - -/* Stop a list of Sources */ -AL_API void AL_APIENTRY alSourceStopv( ALsizei ns, const ALuint *sids ); - -/* Rewind a list of Sources */ -AL_API void AL_APIENTRY alSourceRewindv( ALsizei ns, const ALuint *sids ); - -/* Pause a list of Sources */ -AL_API void AL_APIENTRY alSourcePausev( ALsizei ns, const ALuint *sids ); - -/* - * Source based playback calls - */ - -/* Play, replay, or resume a Source */ -AL_API void AL_APIENTRY alSourcePlay( ALuint sid ); - -/* Stop a Source */ -AL_API void AL_APIENTRY alSourceStop( ALuint sid ); - -/* Rewind a Source (set playback postiton to beginning) */ -AL_API void AL_APIENTRY alSourceRewind( ALuint sid ); - -/* Pause a Source */ -AL_API void AL_APIENTRY alSourcePause( ALuint sid ); - -/* - * Source Queuing - */ -AL_API void AL_APIENTRY alSourceQueueBuffers( ALuint sid, ALsizei numEntries, const ALuint *bids ); - -AL_API void AL_APIENTRY alSourceUnqueueBuffers( ALuint sid, ALsizei numEntries, ALuint *bids ); - - -/** - * BUFFER - * Buffer objects are storage space for sample data. - * Buffers are referred to by Sources. One Buffer can be used - * by multiple Sources. - * - * Properties include: - - * - * Frequency (Query only) AL_FREQUENCY ALint - * Size (Query only) AL_SIZE ALint - * Bits (Query only) AL_BITS ALint - * Channels (Query only) AL_CHANNELS ALint - */ - -/* Create Buffer objects */ -AL_API void AL_APIENTRY alGenBuffers( ALsizei n, ALuint* buffers ); - -/* Delete Buffer objects */ -AL_API void AL_APIENTRY alDeleteBuffers( ALsizei n, const ALuint* buffers ); - -/* Verify a handle is a valid Buffer */ -AL_API ALboolean AL_APIENTRY alIsBuffer( ALuint bid ); - -/* Specify the data to be copied into a buffer */ -AL_API void AL_APIENTRY alBufferData( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ); - -/* - * Set Buffer parameters - */ -AL_API void AL_APIENTRY alBufferf( ALuint bid, ALenum param, ALfloat value ); - -AL_API void AL_APIENTRY alBuffer3f( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); - -AL_API void AL_APIENTRY alBufferfv( ALuint bid, ALenum param, const ALfloat* values ); - -AL_API void AL_APIENTRY alBufferi( ALuint bid, ALenum param, ALint value ); - -AL_API void AL_APIENTRY alBuffer3i( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ); - -AL_API void AL_APIENTRY alBufferiv( ALuint bid, ALenum param, const ALint* values ); - -/* - * Get Buffer parameters - */ -AL_API void AL_APIENTRY alGetBufferf( ALuint bid, ALenum param, ALfloat* value ); - -AL_API void AL_APIENTRY alGetBuffer3f( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); - -AL_API void AL_APIENTRY alGetBufferfv( ALuint bid, ALenum param, ALfloat* values ); - -AL_API void AL_APIENTRY alGetBufferi( ALuint bid, ALenum param, ALint* value ); - -AL_API void AL_APIENTRY alGetBuffer3i( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3); - -AL_API void AL_APIENTRY alGetBufferiv( ALuint bid, ALenum param, ALint* values ); - - -/* - * Global Parameters - */ -AL_API void AL_APIENTRY alDopplerFactor( ALfloat value ); - -AL_API void AL_APIENTRY alDopplerVelocity( ALfloat value ); - -AL_API void AL_APIENTRY alSpeedOfSound( ALfloat value ); - -AL_API void AL_APIENTRY alDistanceModel( ALenum distanceModel ); - -#else /* AL_NO_PROTOTYPES */ - -typedef void (AL_APIENTRY *LPALENABLE)( ALenum capability ); -typedef void (AL_APIENTRY *LPALDISABLE)( ALenum capability ); -typedef ALboolean (AL_APIENTRY *LPALISENABLED)( ALenum capability ); -typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)( ALenum param ); -typedef void (AL_APIENTRY *LPALGETBOOLEANV)( ALenum param, ALboolean* data ); -typedef void (AL_APIENTRY *LPALGETINTEGERV)( ALenum param, ALint* data ); -typedef void (AL_APIENTRY *LPALGETFLOATV)( ALenum param, ALfloat* data ); -typedef void (AL_APIENTRY *LPALGETDOUBLEV)( ALenum param, ALdouble* data ); -typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)( ALenum param ); -typedef ALint (AL_APIENTRY *LPALGETINTEGER)( ALenum param ); -typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)( ALenum param ); -typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)( ALenum param ); -typedef ALenum (AL_APIENTRY *LPALGETERROR)( void ); -typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar* extname ); -typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)( const ALchar* fname ); -typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)( const ALchar* ename ); -typedef void (AL_APIENTRY *LPALLISTENERF)( ALenum param, ALfloat value ); -typedef void (AL_APIENTRY *LPALLISTENER3F)( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); -typedef void (AL_APIENTRY *LPALLISTENERFV)( ALenum param, const ALfloat* values ); -typedef void (AL_APIENTRY *LPALLISTENERI)( ALenum param, ALint value ); -typedef void (AL_APIENTRY *LPALLISTENER3I)( ALenum param, ALint value1, ALint value2, ALint value3 ); -typedef void (AL_APIENTRY *LPALLISTENERIV)( ALenum param, const ALint* values ); -typedef void (AL_APIENTRY *LPALGETLISTENERF)( ALenum param, ALfloat* value ); -typedef void (AL_APIENTRY *LPALGETLISTENER3F)( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ); -typedef void (AL_APIENTRY *LPALGETLISTENERFV)( ALenum param, ALfloat* values ); -typedef void (AL_APIENTRY *LPALGETLISTENERI)( ALenum param, ALint* value ); -typedef void (AL_APIENTRY *LPALGETLISTENER3I)( ALenum param, ALint *value1, ALint *value2, ALint *value3 ); -typedef void (AL_APIENTRY *LPALGETLISTENERIV)( ALenum param, ALint* values ); -typedef void (AL_APIENTRY *LPALGENSOURCES)( ALsizei n, ALuint* sources ); -typedef void (AL_APIENTRY *LPALDELETESOURCES)( ALsizei n, const ALuint* sources ); -typedef ALboolean (AL_APIENTRY *LPALISSOURCE)( ALuint sid ); -typedef void (AL_APIENTRY *LPALSOURCEF)( ALuint sid, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALSOURCE3F)( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); -typedef void (AL_APIENTRY *LPALSOURCEFV)( ALuint sid, ALenum param, const ALfloat* values ); -typedef void (AL_APIENTRY *LPALSOURCEI)( ALuint sid, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALSOURCE3I)( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ); -typedef void (AL_APIENTRY *LPALSOURCEIV)( ALuint sid, ALenum param, const ALint* values ); -typedef void (AL_APIENTRY *LPALGETSOURCEF)( ALuint sid, ALenum param, ALfloat* value ); -typedef void (AL_APIENTRY *LPALGETSOURCE3F)( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); -typedef void (AL_APIENTRY *LPALGETSOURCEFV)( ALuint sid, ALenum param, ALfloat* values ); -typedef void (AL_APIENTRY *LPALGETSOURCEI)( ALuint sid, ALenum param, ALint* value ); -typedef void (AL_APIENTRY *LPALGETSOURCE3I)( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3); -typedef void (AL_APIENTRY *LPALGETSOURCEIV)( ALuint sid, ALenum param, ALint* values ); -typedef void (AL_APIENTRY *LPALSOURCEPLAYV)( ALsizei ns, const ALuint *sids ); -typedef void (AL_APIENTRY *LPALSOURCESTOPV)( ALsizei ns, const ALuint *sids ); -typedef void (AL_APIENTRY *LPALSOURCEREWINDV)( ALsizei ns, const ALuint *sids ); -typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)( ALsizei ns, const ALuint *sids ); -typedef void (AL_APIENTRY *LPALSOURCEPLAY)( ALuint sid ); -typedef void (AL_APIENTRY *LPALSOURCESTOP)( ALuint sid ); -typedef void (AL_APIENTRY *LPALSOURCEREWIND)( ALuint sid ); -typedef void (AL_APIENTRY *LPALSOURCEPAUSE)( ALuint sid ); -typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint sid, ALsizei numEntries, const ALuint *bids ); -typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint sid, ALsizei numEntries, ALuint *bids ); -typedef void (AL_APIENTRY *LPALGENBUFFERS)( ALsizei n, ALuint* buffers ); -typedef void (AL_APIENTRY *LPALDELETEBUFFERS)( ALsizei n, const ALuint* buffers ); -typedef ALboolean (AL_APIENTRY *LPALISBUFFER)( ALuint bid ); -typedef void (AL_APIENTRY *LPALBUFFERDATA)( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ); -typedef void (AL_APIENTRY *LPALBUFFERF)( ALuint bid, ALenum param, ALfloat value); -typedef void (AL_APIENTRY *LPALBUFFER3F)( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); -typedef void (AL_APIENTRY *LPALBUFFERFV)( ALuint bid, ALenum param, const ALfloat* values ); -typedef void (AL_APIENTRY *LPALBUFFERI)( ALuint bid, ALenum param, ALint value); -typedef void (AL_APIENTRY *LPALBUFFER3I)( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ); -typedef void (AL_APIENTRY *LPALBUFFERIV)( ALuint bid, ALenum param, const ALint* values ); -typedef void (AL_APIENTRY *LPALGETBUFFERF)( ALuint bid, ALenum param, ALfloat* value ); -typedef void (AL_APIENTRY *LPALGETBUFFER3F)( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); -typedef void (AL_APIENTRY *LPALGETBUFFERFV)( ALuint bid, ALenum param, ALfloat* values ); -typedef void (AL_APIENTRY *LPALGETBUFFERI)( ALuint bid, ALenum param, ALint* value ); -typedef void (AL_APIENTRY *LPALGETBUFFER3I)( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3); -typedef void (AL_APIENTRY *LPALGETBUFFERIV)( ALuint bid, ALenum param, ALint* values ); -typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)( ALfloat value ); -typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)( ALfloat value ); -typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)( ALfloat value ); -typedef void (AL_APIENTRY *LPALDISTANCEMODEL)( ALenum distanceModel ); - -#endif /* AL_NO_PROTOTYPES */ - -#if TARGET_OS_MAC - #pragma export off -#endif - -#if defined(__cplusplus) -} /* extern "C" */ -#endif - -#endif /* AL_AL_H */ diff --git a/Engine/lib/openal/win32/al/alc.h b/Engine/lib/openal/win32/al/alc.h deleted file mode 100644 index 07e287dac..000000000 --- a/Engine/lib/openal/win32/al/alc.h +++ /dev/null @@ -1,273 +0,0 @@ -#ifndef AL_ALC_H -#define AL_ALC_H - -#if defined(__cplusplus) -extern "C" { -#endif - -#if defined(_WIN32) && !defined(_XBOX) - /* _OPENAL32LIB is deprecated */ - #if defined(AL_BUILD_LIBRARY) || defined (_OPENAL32LIB) - #define ALC_API __declspec(dllexport) - #else - #define ALC_API __declspec(dllimport) - #endif -#else - #define ALC_API extern -#endif - -#if defined(_WIN32) - #define ALC_APIENTRY __cdecl -#else - #define ALC_APIENTRY -#endif - -#if TARGET_OS_MAC - #pragma export on -#endif - -/* The ALCAPI, and ALCAPIENTRY macros are deprecated, but are included for applications porting code - from AL 1.0 */ -#define ALCAPI ALC_API -#define ALCAPIENTRY ALC_APIENTRY - -#define ALC_VERSION_0_1 1 - -typedef struct ALCdevice_struct ALCdevice; -typedef struct ALCcontext_struct ALCcontext; - - -/** 8-bit boolean */ -typedef char ALCboolean; - -/** character */ -typedef char ALCchar; - -/** signed 8-bit 2's complement integer */ -typedef char ALCbyte; - -/** unsigned 8-bit integer */ -typedef unsigned char ALCubyte; - -/** signed 16-bit 2's complement integer */ -typedef short ALCshort; - -/** unsigned 16-bit integer */ -typedef unsigned short ALCushort; - -/** signed 32-bit 2's complement integer */ -typedef int ALCint; - -/** unsigned 32-bit integer */ -typedef unsigned int ALCuint; - -/** non-negative 32-bit binary integer size */ -typedef int ALCsizei; - -/** enumerated 32-bit value */ -typedef int ALCenum; - -/** 32-bit IEEE754 floating-point */ -typedef float ALCfloat; - -/** 64-bit IEEE754 floating-point */ -typedef double ALCdouble; - -/** void type (for opaque pointers only) */ -typedef void ALCvoid; - - -/* Enumerant values begin at column 50. No tabs. */ - -/* bad value */ -#define ALC_INVALID 0 - -/* Boolean False. */ -#define ALC_FALSE 0 - -/* Boolean True. */ -#define ALC_TRUE 1 - -/** - * followed by Hz - */ -#define ALC_FREQUENCY 0x1007 - -/** - * followed by Hz - */ -#define ALC_REFRESH 0x1008 - -/** - * followed by AL_TRUE, AL_FALSE - */ -#define ALC_SYNC 0x1009 - -/** - * followed by Num of requested Mono (3D) Sources - */ -#define ALC_MONO_SOURCES 0x1010 - -/** - * followed by Num of requested Stereo Sources - */ -#define ALC_STEREO_SOURCES 0x1011 - -/** - * errors - */ - -/** - * No error - */ -#define ALC_NO_ERROR ALC_FALSE - -/** - * No device - */ -#define ALC_INVALID_DEVICE 0xA001 - -/** - * invalid context ID - */ -#define ALC_INVALID_CONTEXT 0xA002 - -/** - * bad enum - */ -#define ALC_INVALID_ENUM 0xA003 - -/** - * bad value - */ -#define ALC_INVALID_VALUE 0xA004 - -/** - * Out of memory. - */ -#define ALC_OUT_OF_MEMORY 0xA005 - - -/** - * The Specifier string for default device - */ -#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 -#define ALC_DEVICE_SPECIFIER 0x1005 -#define ALC_EXTENSIONS 0x1006 - -#define ALC_MAJOR_VERSION 0x1000 -#define ALC_MINOR_VERSION 0x1001 - -#define ALC_ATTRIBUTES_SIZE 0x1002 -#define ALC_ALL_ATTRIBUTES 0x1003 - -/** - * Capture extension - */ -#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310 -#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311 -#define ALC_CAPTURE_SAMPLES 0x312 - - -#if !defined(ALC_NO_PROTOTYPES) - -/* - * Context Management - */ -ALC_API ALCcontext * ALC_APIENTRY alcCreateContext( ALCdevice *device, const ALCint* attrlist ); - -ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent( ALCcontext *context ); - -ALC_API void ALC_APIENTRY alcProcessContext( ALCcontext *context ); - -ALC_API void ALC_APIENTRY alcSuspendContext( ALCcontext *context ); - -ALC_API void ALC_APIENTRY alcDestroyContext( ALCcontext *context ); - -ALC_API ALCcontext * ALC_APIENTRY alcGetCurrentContext( ALCvoid ); - -ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice( ALCcontext *context ); - - -/* - * Device Management - */ -ALC_API ALCdevice * ALC_APIENTRY alcOpenDevice( const ALCchar *devicename ); - -ALC_API ALCboolean ALC_APIENTRY alcCloseDevice( ALCdevice *device ); - - -/* - * Error support. - * Obtain the most recent Context error - */ -ALC_API ALCenum ALC_APIENTRY alcGetError( ALCdevice *device ); - - -/* - * Extension support. - * Query for the presence of an extension, and obtain any appropriate - * function pointers and enum values. - */ -ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent( ALCdevice *device, const ALCchar *extname ); - -ALC_API void * ALC_APIENTRY alcGetProcAddress( ALCdevice *device, const ALCchar *funcname ); - -ALC_API ALCenum ALC_APIENTRY alcGetEnumValue( ALCdevice *device, const ALCchar *enumname ); - - -/* - * Query functions - */ -ALC_API const ALCchar * ALC_APIENTRY alcGetString( ALCdevice *device, ALCenum param ); - -ALC_API void ALC_APIENTRY alcGetIntegerv( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *data ); - - -/* - * Capture functions - */ -ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ); - -ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice( ALCdevice *device ); - -ALC_API void ALC_APIENTRY alcCaptureStart( ALCdevice *device ); - -ALC_API void ALC_APIENTRY alcCaptureStop( ALCdevice *device ); - -ALC_API void ALC_APIENTRY alcCaptureSamples( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ); - -#else /* ALC_NO_PROTOTYPES */ - -typedef ALCcontext * (ALC_APIENTRY *LPALCCREATECONTEXT) (ALCdevice *device, const ALCint *attrlist); -typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)( ALCcontext *context ); -typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)( ALCcontext *context ); -typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)( ALCcontext *context ); -typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)( ALCcontext *context ); -typedef ALCcontext * (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)( ALCvoid ); -typedef ALCdevice * (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)( ALCcontext *context ); -typedef ALCdevice * (ALC_APIENTRY *LPALCOPENDEVICE)( const ALCchar *devicename ); -typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)( ALCdevice *device ); -typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)( ALCdevice *device ); -typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)( ALCdevice *device, const ALCchar *extname ); -typedef void * (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname ); -typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname ); -typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)( ALCdevice *device, ALCenum param ); -typedef void (ALC_APIENTRY *LPALCGETINTEGERV)( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest ); -typedef ALCdevice * (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ); -typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)( ALCdevice *device ); -typedef void (ALC_APIENTRY *LPALCCAPTURESTART)( ALCdevice *device ); -typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)( ALCdevice *device ); -typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ); - -#endif /* ALC_NO_PROTOTYPES */ - -#if TARGET_OS_MAC - #pragma export off -#endif - -#if defined(__cplusplus) -} -#endif - -#endif /* AL_ALC_H */ diff --git a/Engine/lib/openal/win32/al/efx-creative.h b/Engine/lib/openal/win32/al/efx-creative.h deleted file mode 100644 index 4ea9da6b7..000000000 --- a/Engine/lib/openal/win32/al/efx-creative.h +++ /dev/null @@ -1,151 +0,0 @@ -#ifndef __efxcreative_h_ -#define __efxcreative_h_ - -/** - * efx-creative.h - Environmental Audio Extensions - * for OpenAL Effects Extension. - * - */ -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * Effect object definitions to be used with alEffect functions. - * - * Effect parameter value definitions, ranges, and defaults - * appear farther down in this file. - */ - -/* AL EAXReverb effect parameters. */ -#define AL_EAXREVERB_DENSITY 0x0001 -#define AL_EAXREVERB_DIFFUSION 0x0002 -#define AL_EAXREVERB_GAIN 0x0003 -#define AL_EAXREVERB_GAINHF 0x0004 -#define AL_EAXREVERB_GAINLF 0x0005 -#define AL_EAXREVERB_DECAY_TIME 0x0006 -#define AL_EAXREVERB_DECAY_HFRATIO 0x0007 -#define AL_EAXREVERB_DECAY_LFRATIO 0x0008 -#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009 -#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A -#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B -#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C -#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D -#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E -#define AL_EAXREVERB_ECHO_TIME 0x000F -#define AL_EAXREVERB_ECHO_DEPTH 0x0010 -#define AL_EAXREVERB_MODULATION_TIME 0x0011 -#define AL_EAXREVERB_MODULATION_DEPTH 0x0012 -#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013 -#define AL_EAXREVERB_HFREFERENCE 0x0014 -#define AL_EAXREVERB_LFREFERENCE 0x0015 -#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016 -#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017 - -/* Effect type definitions to be used with AL_EFFECT_TYPE. */ -#define AL_EFFECT_EAXREVERB 0x8000 - - - - /********************************************************** - * Effect parameter structures, value definitions, ranges and defaults. - */ - -/** - * AL reverb effect parameter ranges and defaults - */ -#define AL_EAXREVERB_MIN_DENSITY 0.0f -#define AL_EAXREVERB_MAX_DENSITY 1.0f -#define AL_EAXREVERB_DEFAULT_DENSITY 1.0f - -#define AL_EAXREVERB_MIN_DIFFUSION 0.0f -#define AL_EAXREVERB_MAX_DIFFUSION 1.0f -#define AL_EAXREVERB_DEFAULT_DIFFUSION 1.0f - -#define AL_EAXREVERB_MIN_GAIN 0.0f -#define AL_EAXREVERB_MAX_GAIN 1.0f -#define AL_EAXREVERB_DEFAULT_GAIN 0.32f - -#define AL_EAXREVERB_MIN_GAINHF 0.0f -#define AL_EAXREVERB_MAX_GAINHF 1.0f -#define AL_EAXREVERB_DEFAULT_GAINHF 0.89f - -#define AL_EAXREVERB_MIN_GAINLF 0.0f -#define AL_EAXREVERB_MAX_GAINLF 1.0f -#define AL_EAXREVERB_DEFAULT_GAINLF 1.0f - -#define AL_EAXREVERB_MIN_DECAY_TIME 0.1f -#define AL_EAXREVERB_MAX_DECAY_TIME 20.0f -#define AL_EAXREVERB_DEFAULT_DECAY_TIME 1.49f - -#define AL_EAXREVERB_MIN_DECAY_HFRATIO 0.1f -#define AL_EAXREVERB_MAX_DECAY_HFRATIO 2.0f -#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO 0.83f - -#define AL_EAXREVERB_MIN_DECAY_LFRATIO 0.1f -#define AL_EAXREVERB_MAX_DECAY_LFRATIO 2.0f -#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO 1.0f - -#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN 0.0f -#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN 3.16f -#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN 0.05f - -#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY 0.0f -#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY 0.3f -#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY 0.007f - -#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN {0.0f, 0.0f, 0.0f} - -#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN 0.0f -#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN 10.0f -#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN 1.26f - -#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY 0.0f -#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY 0.1f -#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY 0.011f - -#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN {0.0f, 0.0f, 0.0f} - -#define AL_EAXREVERB_MIN_ECHO_TIME 0.075f -#define AL_EAXREVERB_MAX_ECHO_TIME 0.25f -#define AL_EAXREVERB_DEFAULT_ECHO_TIME 0.25f - -#define AL_EAXREVERB_MIN_ECHO_DEPTH 0.0f -#define AL_EAXREVERB_MAX_ECHO_DEPTH 1.0f -#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH 0.0f - -#define AL_EAXREVERB_MIN_MODULATION_TIME 0.04f -#define AL_EAXREVERB_MAX_MODULATION_TIME 4.0f -#define AL_EAXREVERB_DEFAULT_MODULATION_TIME 0.25f - -#define AL_EAXREVERB_MIN_MODULATION_DEPTH 0.0f -#define AL_EAXREVERB_MAX_MODULATION_DEPTH 1.0f -#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH 0.0f - -#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF 0.892f -#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF 1.0f -#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF 0.994f - -#define AL_EAXREVERB_MIN_HFREFERENCE 1000.0f -#define AL_EAXREVERB_MAX_HFREFERENCE 20000.0f -#define AL_EAXREVERB_DEFAULT_HFREFERENCE 5000.0f - -#define AL_EAXREVERB_MIN_LFREFERENCE 20.0f -#define AL_EAXREVERB_MAX_LFREFERENCE 1000.0f -#define AL_EAXREVERB_DEFAULT_LFREFERENCE 250.0f - -#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR 0.0f -#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR 10.0f -#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR 0.0f - -#define AL_EAXREVERB_MIN_DECAY_HFLIMIT AL_FALSE -#define AL_EAXREVERB_MAX_DECAY_HFLIMIT AL_TRUE -#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* __efxcreative_h_ */ diff --git a/Engine/lib/openal/win32/al/efx.h b/Engine/lib/openal/win32/al/efx.h deleted file mode 100644 index 6b58a1796..000000000 --- a/Engine/lib/openal/win32/al/efx.h +++ /dev/null @@ -1,756 +0,0 @@ -#ifndef __efx_h_ -#define __efx_h_ - -/** - * OpenAL cross platform effects extension audio library - * Copyright (C) 2005-2006 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 __cplusplus -extern "C" { -#endif - -#define ALC_EXT_EFX_NAME "ALC_EXT_EFX" - -/** - * Context definitions to be used with alcCreateContext. - * These values must be unique and not conflict with other - * al context values. - */ -#define ALC_EFX_MAJOR_VERSION 0x20001 -#define ALC_EFX_MINOR_VERSION 0x20002 -#define ALC_MAX_AUXILIARY_SENDS 0x20003 - - - - -/** - * Listener definitions to be used with alListener functions. - * These values must be unique and not conflict with other - * al listener values. - */ -#define AL_METERS_PER_UNIT 0x20004 - - - - -/** - * Source definitions to be used with alSource functions. - * These values must be unique and not conflict with other - * al source values. - */ -#define AL_DIRECT_FILTER 0x20005 -#define AL_AUXILIARY_SEND_FILTER 0x20006 -#define AL_AIR_ABSORPTION_FACTOR 0x20007 -#define AL_ROOM_ROLLOFF_FACTOR 0x20008 -#define AL_CONE_OUTER_GAINHF 0x20009 -#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A -#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B -#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C - - - - -/** - * Effect object definitions to be used with alEffect functions. - * - * Effect parameter value definitions, ranges, and defaults - * appear farther down in this file. - */ - -/* Reverb Parameters */ -#define AL_REVERB_DENSITY 0x0001 -#define AL_REVERB_DIFFUSION 0x0002 -#define AL_REVERB_GAIN 0x0003 -#define AL_REVERB_GAINHF 0x0004 -#define AL_REVERB_DECAY_TIME 0x0005 -#define AL_REVERB_DECAY_HFRATIO 0x0006 -#define AL_REVERB_REFLECTIONS_GAIN 0x0007 -#define AL_REVERB_REFLECTIONS_DELAY 0x0008 -#define AL_REVERB_LATE_REVERB_GAIN 0x0009 -#define AL_REVERB_LATE_REVERB_DELAY 0x000A -#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B -#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C -#define AL_REVERB_DECAY_HFLIMIT 0x000D - -/* Chorus Parameters */ -#define AL_CHORUS_WAVEFORM 0x0001 -#define AL_CHORUS_PHASE 0x0002 -#define AL_CHORUS_RATE 0x0003 -#define AL_CHORUS_DEPTH 0x0004 -#define AL_CHORUS_FEEDBACK 0x0005 -#define AL_CHORUS_DELAY 0x0006 - -/* Distortion Parameters */ -#define AL_DISTORTION_EDGE 0x0001 -#define AL_DISTORTION_GAIN 0x0002 -#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003 -#define AL_DISTORTION_EQCENTER 0x0004 -#define AL_DISTORTION_EQBANDWIDTH 0x0005 - -/* Echo Parameters */ -#define AL_ECHO_DELAY 0x0001 -#define AL_ECHO_LRDELAY 0x0002 -#define AL_ECHO_DAMPING 0x0003 -#define AL_ECHO_FEEDBACK 0x0004 -#define AL_ECHO_SPREAD 0x0005 - -/* Flanger Parameters */ -#define AL_FLANGER_WAVEFORM 0x0001 -#define AL_FLANGER_PHASE 0x0002 -#define AL_FLANGER_RATE 0x0003 -#define AL_FLANGER_DEPTH 0x0004 -#define AL_FLANGER_FEEDBACK 0x0005 -#define AL_FLANGER_DELAY 0x0006 - -/* Frequencyshifter Parameters */ -#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001 -#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002 -#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003 - -/* Vocalmorpher Parameters */ -#define AL_VOCAL_MORPHER_PHONEMEA 0x0001 -#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002 -#define AL_VOCAL_MORPHER_PHONEMEB 0x0003 -#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004 -#define AL_VOCAL_MORPHER_WAVEFORM 0x0005 -#define AL_VOCAL_MORPHER_RATE 0x0006 - -/* Pitchshifter Parameters */ -#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001 -#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002 - -/* Ringmodulator Parameters */ -#define AL_RING_MODULATOR_FREQUENCY 0x0001 -#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002 -#define AL_RING_MODULATOR_WAVEFORM 0x0003 - -/* Autowah Parameters */ -#define AL_AUTOWAH_ATTACK_TIME 0x0001 -#define AL_AUTOWAH_RELEASE_TIME 0x0002 -#define AL_AUTOWAH_RESONANCE 0x0003 -#define AL_AUTOWAH_PEAK_GAIN 0x0004 - -/* Compressor Parameters */ -#define AL_COMPRESSOR_ONOFF 0x0001 - -/* Equalizer Parameters */ -#define AL_EQUALIZER_LOW_GAIN 0x0001 -#define AL_EQUALIZER_LOW_CUTOFF 0x0002 -#define AL_EQUALIZER_MID1_GAIN 0x0003 -#define AL_EQUALIZER_MID1_CENTER 0x0004 -#define AL_EQUALIZER_MID1_WIDTH 0x0005 -#define AL_EQUALIZER_MID2_GAIN 0x0006 -#define AL_EQUALIZER_MID2_CENTER 0x0007 -#define AL_EQUALIZER_MID2_WIDTH 0x0008 -#define AL_EQUALIZER_HIGH_GAIN 0x0009 -#define AL_EQUALIZER_HIGH_CUTOFF 0x000A - -/* Effect type */ -#define AL_EFFECT_FIRST_PARAMETER 0x0000 -#define AL_EFFECT_LAST_PARAMETER 0x8000 -#define AL_EFFECT_TYPE 0x8001 - -/* Effect type definitions to be used with AL_EFFECT_TYPE. */ -#define AL_EFFECT_NULL 0x0000 /* Can also be used as an Effect Object ID */ -#define AL_EFFECT_REVERB 0x0001 -#define AL_EFFECT_CHORUS 0x0002 -#define AL_EFFECT_DISTORTION 0x0003 -#define AL_EFFECT_ECHO 0x0004 -#define AL_EFFECT_FLANGER 0x0005 -#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 -#define AL_EFFECT_VOCAL_MORPHER 0x0007 -#define AL_EFFECT_PITCH_SHIFTER 0x0008 -#define AL_EFFECT_RING_MODULATOR 0x0009 -#define AL_EFFECT_AUTOWAH 0x000A -#define AL_EFFECT_COMPRESSOR 0x000B -#define AL_EFFECT_EQUALIZER 0x000C - -/** - * Auxiliary Slot object definitions to be used with alAuxiliaryEffectSlot functions. - */ -#define AL_EFFECTSLOT_EFFECT 0x0001 -#define AL_EFFECTSLOT_GAIN 0x0002 -#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003 - -/** - * Value to be used as an Auxiliary Slot ID to disable a source send.. - */ -#define AL_EFFECTSLOT_NULL 0x0000 - - - -/** - * Filter object definitions to be used with alFilter functions. - */ - -/* Lowpass parameters. */ -#define AL_LOWPASS_GAIN 0x0001 -#define AL_LOWPASS_GAINHF 0x0002 - -/* Highpass Parameters */ -#define AL_HIGHPASS_GAIN 0x0001 -#define AL_HIGHPASS_GAINLF 0x0002 - -/* Bandpass Parameters */ -#define AL_BANDPASS_GAIN 0x0001 -#define AL_BANDPASS_GAINLF 0x0002 -#define AL_BANDPASS_GAINHF 0x0003 - -/* Filter type */ -#define AL_FILTER_FIRST_PARAMETER 0x0000 -#define AL_FILTER_LAST_PARAMETER 0x8000 -#define AL_FILTER_TYPE 0x8001 - -/* Filter type definitions to be used with AL_FILTER_TYPE. */ -#define AL_FILTER_NULL 0x0000 /* Can also be used as a Filter Object ID */ -#define AL_FILTER_LOWPASS 0x0001 -#define AL_FILTER_HIGHPASS 0x0002 -#define AL_FILTER_BANDPASS 0x0003 - - -/** - * Effect object functions. - */ - -/* Create Effect objects. */ -typedef void (__cdecl *LPALGENEFFECTS)( ALsizei n, ALuint* effects ); - -/* Delete Effect objects. */ -typedef void (__cdecl *LPALDELETEEFFECTS)( ALsizei n, ALuint* effects ); - -/* Verify a handle is a valid Effect. */ -typedef ALboolean (__cdecl *LPALISEFFECT)( ALuint eid ); - -/* Set an integer parameter for an Effect object. */ -typedef void (__cdecl *LPALEFFECTI)( ALuint eid, ALenum param, ALint value); -typedef void (__cdecl *LPALEFFECTIV)( ALuint eid, ALenum param, ALint* values ); - -/* Set a floating point parameter for an Effect object. */ -typedef void (__cdecl *LPALEFFECTF)( ALuint eid, ALenum param, ALfloat value); -typedef void (__cdecl *LPALEFFECTFV)( ALuint eid, ALenum param, ALfloat* values ); - -/* Get an integer parameter for an Effect object. */ -typedef void (__cdecl *LPALGETEFFECTI)( ALuint eid, ALenum pname, ALint* value ); -typedef void (__cdecl *LPALGETEFFECTIV)( ALuint eid, ALenum pname, ALint* values ); - -/* Get a floating point parameter for an Effect object. */ -typedef void (__cdecl *LPALGETEFFECTF)( ALuint eid, ALenum pname, ALfloat* value ); -typedef void (__cdecl *LPALGETEFFECTFV)( ALuint eid, ALenum pname, ALfloat* values ); - - -/** - * Filter object functions - */ - -/* Create Filter objects. */ -typedef void (__cdecl *LPALGENFILTERS)( ALsizei n, ALuint* filters ); - -/* Delete Filter objects. */ -typedef void (__cdecl *LPALDELETEFILTERS)( ALsizei n, ALuint* filters ); - -/* Verify a handle is a valid Filter. */ -typedef ALboolean (__cdecl *LPALISFILTER)( ALuint fid ); - -/* Set an integer parameter for a Filter object. */ -typedef void (__cdecl *LPALFILTERI)( ALuint fid, ALenum param, ALint value ); -typedef void (__cdecl *LPALFILTERIV)( ALuint fid, ALenum param, ALint* values ); - -/* Set a floating point parameter for an Filter object. */ -typedef void (__cdecl *LPALFILTERF)( ALuint fid, ALenum param, ALfloat value); -typedef void (__cdecl *LPALFILTERFV)( ALuint fid, ALenum param, ALfloat* values ); - -/* Get an integer parameter for a Filter object. */ -typedef void (__cdecl *LPALGETFILTERI)( ALuint fid, ALenum pname, ALint* value ); -typedef void (__cdecl *LPALGETFILTERIV)( ALuint fid, ALenum pname, ALint* values ); - -/* Get a floating point parameter for a Filter object. */ -typedef void (__cdecl *LPALGETFILTERF)( ALuint fid, ALenum pname, ALfloat* value ); -typedef void (__cdecl *LPALGETFILTERFV)( ALuint fid, ALenum pname, ALfloat* values ); - - -/** - * Auxiliary Slot object functions - */ - -/* Create Auxiliary Slot objects. */ -typedef void (__cdecl *LPALGENAUXILIARYEFFECTSLOTS)( ALsizei n, ALuint* slots ); - -/* Delete Auxiliary Slot objects. */ -typedef void (__cdecl *LPALDELETEAUXILIARYEFFECTSLOTS)( ALsizei n, ALuint* slots ); - -/* Verify a handle is a valid Auxiliary Slot. */ -typedef ALboolean (__cdecl *LPALISAUXILIARYEFFECTSLOT)( ALuint slot ); - -/* Set an integer parameter for a Auxiliary Slot object. */ -typedef void (__cdecl *LPALAUXILIARYEFFECTSLOTI)( ALuint asid, ALenum param, ALint value ); -typedef void (__cdecl *LPALAUXILIARYEFFECTSLOTIV)( ALuint asid, ALenum param, ALint* values ); - -/* Set a floating point parameter for an Auxiliary Slot object. */ -typedef void (__cdecl *LPALAUXILIARYEFFECTSLOTF)( ALuint asid, ALenum param, ALfloat value ); -typedef void (__cdecl *LPALAUXILIARYEFFECTSLOTFV)( ALuint asid, ALenum param, ALfloat* values ); - -/* Get an integer parameter for a Auxiliary Slot object. */ -typedef void (__cdecl *LPALGETAUXILIARYEFFECTSLOTI)( ALuint asid, ALenum pname, ALint* value ); -typedef void (__cdecl *LPALGETAUXILIARYEFFECTSLOTIV)( ALuint asid, ALenum pname, ALint* values ); - -/* Get a floating point parameter for a Auxiliary Slot object. */ -typedef void (__cdecl *LPALGETAUXILIARYEFFECTSLOTF)( ALuint asid, ALenum pname, ALfloat* value ); -typedef void (__cdecl *LPALGETAUXILIARYEFFECTSLOTFV)( ALuint asid, ALenum pname, ALfloat* values ); - - - - -/********************************************************** - * Filter ranges and defaults. - */ - -/** - * Lowpass filter - */ - -#define LOWPASS_MIN_GAIN 0.0f -#define LOWPASS_MAX_GAIN 1.0f -#define LOWPASS_DEFAULT_GAIN 1.0f - -#define LOWPASS_MIN_GAINHF 0.0f -#define LOWPASS_MAX_GAINHF 1.0f -#define LOWPASS_DEFAULT_GAINHF 1.0f - -/** - * Highpass filter - */ - -#define HIGHPASS_MIN_GAIN 0.0f -#define HIGHPASS_MAX_GAIN 1.0f -#define HIGHPASS_DEFAULT_GAIN 1.0f - -#define HIGHPASS_MIN_GAINLF 0.0f -#define HIGHPASS_MAX_GAINLF 1.0f -#define HIGHPASS_DEFAULT_GAINLF 1.0f - -/** - * Bandpass filter - */ - -#define BANDPASS_MIN_GAIN 0.0f -#define BANDPASS_MAX_GAIN 1.0f -#define BANDPASS_DEFAULT_GAIN 1.0f - -#define BANDPASS_MIN_GAINHF 0.0f -#define BANDPASS_MAX_GAINHF 1.0f -#define BANDPASS_DEFAULT_GAINHF 1.0f - -#define BANDPASS_MIN_GAINLF 0.0f -#define BANDPASS_MAX_GAINLF 1.0f -#define BANDPASS_DEFAULT_GAINLF 1.0f - - - - - /********************************************************** - * Effect parameter structures, value definitions, ranges and defaults. - */ - -/** - * AL reverb effect parameter ranges and defaults - */ -#define AL_REVERB_MIN_DENSITY 0.0f -#define AL_REVERB_MAX_DENSITY 1.0f -#define AL_REVERB_DEFAULT_DENSITY 1.0f - -#define AL_REVERB_MIN_DIFFUSION 0.0f -#define AL_REVERB_MAX_DIFFUSION 1.0f -#define AL_REVERB_DEFAULT_DIFFUSION 1.0f - -#define AL_REVERB_MIN_GAIN 0.0f -#define AL_REVERB_MAX_GAIN 1.0f -#define AL_REVERB_DEFAULT_GAIN 0.32f - -#define AL_REVERB_MIN_GAINHF 0.0f -#define AL_REVERB_MAX_GAINHF 1.0f -#define AL_REVERB_DEFAULT_GAINHF 0.89f - -#define AL_REVERB_MIN_DECAY_TIME 0.1f -#define AL_REVERB_MAX_DECAY_TIME 20.0f -#define AL_REVERB_DEFAULT_DECAY_TIME 1.49f - -#define AL_REVERB_MIN_DECAY_HFRATIO 0.1f -#define AL_REVERB_MAX_DECAY_HFRATIO 2.0f -#define AL_REVERB_DEFAULT_DECAY_HFRATIO 0.83f - -#define AL_REVERB_MIN_REFLECTIONS_GAIN 0.0f -#define AL_REVERB_MAX_REFLECTIONS_GAIN 3.16f -#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN 0.05f - -#define AL_REVERB_MIN_REFLECTIONS_DELAY 0.0f -#define AL_REVERB_MAX_REFLECTIONS_DELAY 0.3f -#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY 0.007f - -#define AL_REVERB_MIN_LATE_REVERB_GAIN 0.0f -#define AL_REVERB_MAX_LATE_REVERB_GAIN 10.0f -#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN 1.26f - -#define AL_REVERB_MIN_LATE_REVERB_DELAY 0.0f -#define AL_REVERB_MAX_LATE_REVERB_DELAY 0.1f -#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY 0.011f - -#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF 0.892f -#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF 1.0f -#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF 0.994f - -#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR 0.0f -#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR 10.0f -#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR 0.0f - -#define AL_REVERB_MIN_DECAY_HFLIMIT AL_FALSE -#define AL_REVERB_MAX_DECAY_HFLIMIT AL_TRUE -#define AL_REVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE - -/** - * AL chorus effect parameter ranges and defaults - */ -#define AL_CHORUS_MIN_WAVEFORM 0 -#define AL_CHORUS_MAX_WAVEFORM 1 -#define AL_CHORUS_DEFAULT_WAVEFORM 1 - -#define AL_CHORUS_WAVEFORM_SINUSOID 0 -#define AL_CHORUS_WAVEFORM_TRIANGLE 1 - -#define AL_CHORUS_MIN_PHASE (-180) -#define AL_CHORUS_MAX_PHASE 180 -#define AL_CHORUS_DEFAULT_PHASE 90 - -#define AL_CHORUS_MIN_RATE 0.0f -#define AL_CHORUS_MAX_RATE 10.0f -#define AL_CHORUS_DEFAULT_RATE 1.1f - -#define AL_CHORUS_MIN_DEPTH 0.0f -#define AL_CHORUS_MAX_DEPTH 1.0f -#define AL_CHORUS_DEFAULT_DEPTH 0.1f - -#define AL_CHORUS_MIN_FEEDBACK (-1.0f) -#define AL_CHORUS_MAX_FEEDBACK 1.0f -#define AL_CHORUS_DEFAULT_FEEDBACK 0.25f - -#define AL_CHORUS_MIN_DELAY 0.0f -#define AL_CHORUS_MAX_DELAY 0.016f -#define AL_CHORUS_DEFAULT_DELAY 0.016f - -/** - * AL distortion effect parameter ranges and defaults - */ -#define AL_DISTORTION_MIN_EDGE 0.0f -#define AL_DISTORTION_MAX_EDGE 1.0f -#define AL_DISTORTION_DEFAULT_EDGE 0.2f - -#define AL_DISTORTION_MIN_GAIN 0.01f -#define AL_DISTORTION_MAX_GAIN 1.0f -#define AL_DISTORTION_DEFAULT_GAIN 0.05f - -#define AL_DISTORTION_MIN_LOWPASS_CUTOFF 80.0f -#define AL_DISTORTION_MAX_LOWPASS_CUTOFF 24000.0f -#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF 8000.0f - -#define AL_DISTORTION_MIN_EQCENTER 80.0f -#define AL_DISTORTION_MAX_EQCENTER 24000.0f -#define AL_DISTORTION_DEFAULT_EQCENTER 3600.0f - -#define AL_DISTORTION_MIN_EQBANDWIDTH 80.0f -#define AL_DISTORTION_MAX_EQBANDWIDTH 24000.0f -#define AL_DISTORTION_DEFAULT_EQBANDWIDTH 3600.0f - -/** - * AL echo effect parameter ranges and defaults - */ -#define AL_ECHO_MIN_DELAY 0.0f -#define AL_ECHO_MAX_DELAY 0.207f -#define AL_ECHO_DEFAULT_DELAY 0.1f - -#define AL_ECHO_MIN_LRDELAY 0.0f -#define AL_ECHO_MAX_LRDELAY 0.404f -#define AL_ECHO_DEFAULT_LRDELAY 0.1f - -#define AL_ECHO_MIN_DAMPING 0.0f -#define AL_ECHO_MAX_DAMPING 0.99f -#define AL_ECHO_DEFAULT_DAMPING 0.5f - -#define AL_ECHO_MIN_FEEDBACK 0.0f -#define AL_ECHO_MAX_FEEDBACK 1.0f -#define AL_ECHO_DEFAULT_FEEDBACK 0.5f - -#define AL_ECHO_MIN_SPREAD (-1.0f) -#define AL_ECHO_MAX_SPREAD 1.0f -#define AL_ECHO_DEFAULT_SPREAD (-1.0f) - -/** - * AL flanger effect parameter ranges and defaults - */ -#define AL_FLANGER_MIN_WAVEFORM 0 -#define AL_FLANGER_MAX_WAVEFORM 1 -#define AL_FLANGER_DEFAULT_WAVEFORM 1 - -#define AL_FLANGER_WAVEFORM_SINUSOID 0 -#define AL_FLANGER_WAVEFORM_TRIANGLE 1 - -#define AL_FLANGER_MIN_PHASE (-180) -#define AL_FLANGER_MAX_PHASE 180 -#define AL_FLANGER_DEFAULT_PHASE 0 - -#define AL_FLANGER_MIN_RATE 0.0f -#define AL_FLANGER_MAX_RATE 10.0f -#define AL_FLANGER_DEFAULT_RATE 0.27f - -#define AL_FLANGER_MIN_DEPTH 0.0f -#define AL_FLANGER_MAX_DEPTH 1.0f -#define AL_FLANGER_DEFAULT_DEPTH 1.0f - -#define AL_FLANGER_MIN_FEEDBACK (-1.0f) -#define AL_FLANGER_MAX_FEEDBACK 1.0f -#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f) - -#define AL_FLANGER_MIN_DELAY 0.0f -#define AL_FLANGER_MAX_DELAY 0.004f -#define AL_FLANGER_DEFAULT_DELAY 0.002f - -/** - * AL frequency shifter effect parameter ranges and defaults - */ -#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY 0.0f -#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY 24000.0f -#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY 0.0f - -#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION 0 -#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION 2 -#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION 0 - -#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION 0 -#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION 2 -#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION 0 - -#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN 0 -#define AL_FREQUENCY_SHIFTER_DIRECTION_UP 1 -#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF 2 - -/** - * AL vocal morpher effect parameter ranges and defaults - */ -#define AL_VOCAL_MORPHER_MIN_PHONEMEA 0 -#define AL_VOCAL_MORPHER_MAX_PHONEMEA 29 -#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA 0 - -#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24) -#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING 24 -#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING 0 - -#define AL_VOCAL_MORPHER_MIN_PHONEMEB 0 -#define AL_VOCAL_MORPHER_MAX_PHONEMEB 29 -#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB 10 - -#define AL_VOCAL_MORPHER_PHONEME_A 0 -#define AL_VOCAL_MORPHER_PHONEME_E 1 -#define AL_VOCAL_MORPHER_PHONEME_I 2 -#define AL_VOCAL_MORPHER_PHONEME_O 3 -#define AL_VOCAL_MORPHER_PHONEME_U 4 -#define AL_VOCAL_MORPHER_PHONEME_AA 5 -#define AL_VOCAL_MORPHER_PHONEME_AE 6 -#define AL_VOCAL_MORPHER_PHONEME_AH 7 -#define AL_VOCAL_MORPHER_PHONEME_AO 8 -#define AL_VOCAL_MORPHER_PHONEME_EH 9 -#define AL_VOCAL_MORPHER_PHONEME_ER 10 -#define AL_VOCAL_MORPHER_PHONEME_IH 11 -#define AL_VOCAL_MORPHER_PHONEME_IY 12 -#define AL_VOCAL_MORPHER_PHONEME_UH 13 -#define AL_VOCAL_MORPHER_PHONEME_UW 14 -#define AL_VOCAL_MORPHER_PHONEME_B 15 -#define AL_VOCAL_MORPHER_PHONEME_D 16 -#define AL_VOCAL_MORPHER_PHONEME_F 17 -#define AL_VOCAL_MORPHER_PHONEME_G 18 -#define AL_VOCAL_MORPHER_PHONEME_J 19 -#define AL_VOCAL_MORPHER_PHONEME_K 20 -#define AL_VOCAL_MORPHER_PHONEME_L 21 -#define AL_VOCAL_MORPHER_PHONEME_M 22 -#define AL_VOCAL_MORPHER_PHONEME_N 23 -#define AL_VOCAL_MORPHER_PHONEME_P 24 -#define AL_VOCAL_MORPHER_PHONEME_R 25 -#define AL_VOCAL_MORPHER_PHONEME_S 26 -#define AL_VOCAL_MORPHER_PHONEME_T 27 -#define AL_VOCAL_MORPHER_PHONEME_V 28 -#define AL_VOCAL_MORPHER_PHONEME_Z 29 - -#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24) -#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING 24 -#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING 0 - -#define AL_VOCAL_MORPHER_MIN_WAVEFORM 0 -#define AL_VOCAL_MORPHER_MAX_WAVEFORM 2 -#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM 0 - -#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID 0 -#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE 1 -#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH 2 - -#define AL_VOCAL_MORPHER_MIN_RATE 0.0f -#define AL_VOCAL_MORPHER_MAX_RATE 10.0f -#define AL_VOCAL_MORPHER_DEFAULT_RATE 1.41f - -/** - * AL pitch shifter effect parameter ranges and defaults - */ -#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12) -#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE 12 -#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE 12 - -#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50) -#define AL_PITCH_SHIFTER_MAX_FINE_TUNE 50 -#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE 0 - -/** - * AL ring modulator effect parameter ranges and defaults - */ -#define AL_RING_MODULATOR_MIN_FREQUENCY 0.0f -#define AL_RING_MODULATOR_MAX_FREQUENCY 8000.0f -#define AL_RING_MODULATOR_DEFAULT_FREQUENCY 440.0f - -#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF 0.0f -#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF 24000.0f -#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF 800.0f - -#define AL_RING_MODULATOR_MIN_WAVEFORM 0 -#define AL_RING_MODULATOR_MAX_WAVEFORM 2 -#define AL_RING_MODULATOR_DEFAULT_WAVEFORM 0 - -#define AL_RING_MODULATOR_SINUSOID 0 -#define AL_RING_MODULATOR_SAWTOOTH 1 -#define AL_RING_MODULATOR_SQUARE 2 - -/** - * AL autowah effect parameter ranges and defaults - */ -#define AL_AUTOWAH_MIN_ATTACK_TIME 0.0001f -#define AL_AUTOWAH_MAX_ATTACK_TIME 1.0f -#define AL_AUTOWAH_DEFAULT_ATTACK_TIME 0.06f - -#define AL_AUTOWAH_MIN_RELEASE_TIME 0.0001f -#define AL_AUTOWAH_MAX_RELEASE_TIME 1.0f -#define AL_AUTOWAH_DEFAULT_RELEASE_TIME 0.06f - -#define AL_AUTOWAH_MIN_RESONANCE 2.0f -#define AL_AUTOWAH_MAX_RESONANCE 1000.0f -#define AL_AUTOWAH_DEFAULT_RESONANCE 1000.0f - -#define AL_AUTOWAH_MIN_PEAK_GAIN 0.00003f -#define AL_AUTOWAH_MAX_PEAK_GAIN 31621.0f -#define AL_AUTOWAH_DEFAULT_PEAK_GAIN 11.22f - -/** - * AL compressor effect parameter ranges and defaults - */ -#define AL_COMPRESSOR_MIN_ONOFF 0 -#define AL_COMPRESSOR_MAX_ONOFF 1 -#define AL_COMPRESSOR_DEFAULT_ONOFF 1 - -/** - * AL equalizer effect parameter ranges and defaults - */ -#define AL_EQUALIZER_MIN_LOW_GAIN 0.126f -#define AL_EQUALIZER_MAX_LOW_GAIN 7.943f -#define AL_EQUALIZER_DEFAULT_LOW_GAIN 1.0f - -#define AL_EQUALIZER_MIN_LOW_CUTOFF 50.0f -#define AL_EQUALIZER_MAX_LOW_CUTOFF 800.0f -#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF 200.0f - -#define AL_EQUALIZER_MIN_MID1_GAIN 0.126f -#define AL_EQUALIZER_MAX_MID1_GAIN 7.943f -#define AL_EQUALIZER_DEFAULT_MID1_GAIN 1.0f - -#define AL_EQUALIZER_MIN_MID1_CENTER 200.0f -#define AL_EQUALIZER_MAX_MID1_CENTER 3000.0f -#define AL_EQUALIZER_DEFAULT_MID1_CENTER 500.0f - -#define AL_EQUALIZER_MIN_MID1_WIDTH 0.01f -#define AL_EQUALIZER_MAX_MID1_WIDTH 1.0f -#define AL_EQUALIZER_DEFAULT_MID1_WIDTH 1.0f - -#define AL_EQUALIZER_MIN_MID2_GAIN 0.126f -#define AL_EQUALIZER_MAX_MID2_GAIN 7.943f -#define AL_EQUALIZER_DEFAULT_MID2_GAIN 1.0f - -#define AL_EQUALIZER_MIN_MID2_CENTER 1000.0f -#define AL_EQUALIZER_MAX_MID2_CENTER 8000.0f -#define AL_EQUALIZER_DEFAULT_MID2_CENTER 3000.0f - -#define AL_EQUALIZER_MIN_MID2_WIDTH 0.01f -#define AL_EQUALIZER_MAX_MID2_WIDTH 1.0f -#define AL_EQUALIZER_DEFAULT_MID2_WIDTH 1.0f - -#define AL_EQUALIZER_MIN_HIGH_GAIN 0.126f -#define AL_EQUALIZER_MAX_HIGH_GAIN 7.943f -#define AL_EQUALIZER_DEFAULT_HIGH_GAIN 1.0f - -#define AL_EQUALIZER_MIN_HIGH_CUTOFF 4000.0f -#define AL_EQUALIZER_MAX_HIGH_CUTOFF 16000.0f -#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF 6000.0f - - - - -/********************************************************** - * Source parameter value definitions, ranges and defaults. - */ -#define AL_MIN_AIR_ABSORPTION_FACTOR 0.0f -#define AL_MAX_AIR_ABSORPTION_FACTOR 10.0f -#define AL_DEFAULT_AIR_ABSORPTION_FACTOR 0.0f - -#define AL_MIN_ROOM_ROLLOFF_FACTOR 0.0f -#define AL_MAX_ROOM_ROLLOFF_FACTOR 10.0f -#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR 0.0f - -#define AL_MIN_CONE_OUTER_GAINHF 0.0f -#define AL_MAX_CONE_OUTER_GAINHF 1.0f -#define AL_DEFAULT_CONE_OUTER_GAINHF 1.0f - -#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE -#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE -#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE - -#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE -#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE -#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE - -#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE -#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE -#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE - - - - -/********************************************************** - * Listener parameter value definitions, ranges and defaults. - */ -#define AL_MIN_METERS_PER_UNIT FLT_MIN -#define AL_MAX_METERS_PER_UNIT FLT_MAX -#define AL_DEFAULT_METERS_PER_UNIT 1.0f - - -#ifdef __cplusplus -} /* extern "C" */ -#endif - -#endif /* __efx_h_ */ diff --git a/Engine/lib/openal/win32/al/xram.h b/Engine/lib/openal/win32/al/xram.h deleted file mode 100644 index 5d8366242..000000000 --- a/Engine/lib/openal/win32/al/xram.h +++ /dev/null @@ -1,94 +0,0 @@ -#include - -// X-RAM Function pointer definitions -typedef ALboolean (__cdecl *EAXSetBufferMode)(ALsizei n, ALuint *buffers, ALint value); -typedef ALenum (__cdecl *EAXGetBufferMode)(ALuint buffer, ALint *value); - -////////////////////////////////////////////////////////////////////////////// -// Query for X-RAM extension -// -// if (alIsExtensionPresent("EAX-RAM") == AL_TRUE) -// X-RAM Extension found -// -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// X-RAM enum names -// -// "AL_EAX_RAM_SIZE" -// "AL_EAX_RAM_FREE" -// "AL_STORAGE_AUTOMATIC" -// "AL_STORAGE_HARDWARE" -// "AL_STORAGE_ACCESSIBLE" -// -// Query enum values using alGetEnumValue, for example -// -// long lRamSizeEnum = alGetEnumValue("AL_EAX_RAM_SIZE") -// -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// Query total amount of X-RAM -// -// long lTotalSize = alGetInteger(alGetEnumValue("AL_EAX_RAM_SIZE") -// -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// Query free X-RAM available -// -// long lFreeSize = alGetInteger(alGetEnumValue("AL_EAX_RAM_FREE") -// -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// Query X-RAM Function pointers -// -// Use typedefs defined above to get the X-RAM function pointers using -// alGetProcAddress -// -// EAXSetBufferMode eaxSetBufferMode; -// EAXGetBufferMode eaxGetBufferMode; -// -// eaxSetBufferMode = (EAXSetBufferMode)alGetProcAddress("EAXSetBufferMode"); -// eaxGetBufferMode = (EAXGetBufferMode)alGetProcAddress("EAXGetBufferMode"); -// -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// Force an Open AL Buffer into X-RAM (good for non-streaming buffers) -// -// ALuint uiBuffer; -// alGenBuffers(1, &uiBuffer); -// eaxSetBufferMode(1, &uiBuffer, alGetEnumValue("AL_STORAGE_HARDWARE")); -// alBufferData(...); -// -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// Force an Open AL Buffer into 'accessible' (currently host) RAM (good for streaming buffers) -// -// ALuint uiBuffer; -// alGenBuffers(1, &uiBuffer); -// eaxSetBufferMode(1, &uiBuffer, alGetEnumValue("AL_STORAGE_ACCESSIBLE")); -// alBufferData(...); -// -////////////////////////////////////////////////////////////////////////////// - - -////////////////////////////////////////////////////////////////////////////// -// Put an Open AL Buffer into X-RAM if memory is available, otherwise use -// host RAM. This is the default mode. -// -// ALuint uiBuffer; -// alGenBuffers(1, &uiBuffer); -// eaxSetBufferMode(1, &uiBuffer, alGetEnumValue("AL_STORAGE_AUTOMATIC")); -// alBufferData(...); -// -////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/Tools/CMake/torque3d.cmake b/Tools/CMake/torque3d.cmake index 7ef1abe51..276ab712f 100644 --- a/Tools/CMake/torque3d.cmake +++ b/Tools/CMake/torque3d.cmake @@ -65,6 +65,19 @@ else() set(TORQUE_SFX_DirectX OFF) endif() option(TORQUE_SFX_OPENAL "OpenAL Sound" ON) +#windows uses openal-soft +if(WIN32) +#disable a few things that are not required +set(ALSOFT_TESTS OFF CACHE BOOL "Build and install test programs" FORCE) +set(ALSOFT_UTILS OFF CACHE BOOL "Build and install utility programs" FORCE) +set(ALSOFT_EXAMPLES OFF CACHE BOOL "Build and install example programs" FORCE) +set(ALSOFT_CONFIG OFF CACHE BOOL "Install alsoft.conf sample configuration file" FORCE) +set(ALSOFT_INSTALL OFF CACHE BOOL "Install headers and libraries" FORCE) +set(ALSOFT_NO_CONFIG_UTIL OFF CACHE BOOL "Disable building the alsoft-config utility" FORCE) +set(ALSOFT_HRTF_DEFS OFF CACHE BOOL "Install HRTF definition files" FORCE) +set(ALSOFT_AMBDEC_PRESETS OFF CACHE BOOL "Install AmbDec presets" FORCE) +add_subdirectory( ${libDir}/openal-soft ${CMAKE_CURRENT_BINARY_DIR}/openal-soft) +endif() mark_as_advanced(TORQUE_SFX_OPENAL) option(TORQUE_HIFI "HIFI? support" OFF) mark_as_advanced(TORQUE_HIFI) @@ -332,7 +345,7 @@ if(TORQUE_SFX_OPENAL AND NOT TORQUE_DEDICATED) addPath("${srcDir}/sfx/openal") if(WIN32) addPath("${srcDir}/sfx/openal/win32") - addInclude("${libDir}/openal/win32") + addInclude("${libDir}/openal-soft/include") endif() if(UNIX AND NOT APPLE) addPath("${srcDir}/sfx/openal/linux")