From 70eef137ae9a50c0aa30c903a7f81c69b6f8785e Mon Sep 17 00:00:00 2001 From: fysx Date: Mon, 8 Sep 2014 21:17:12 +0200 Subject: [PATCH] updated OpenAL-Soft to version 1.16.0 --- jni/love/Android.mk | 7 +- .../Alc/ALc.c | 942 ++++--- .../Alc/ALu.c | 706 +++--- .../Alc/alcConfig.c | 217 +- .../Alc/alcRing.c | 19 +- jni/openal-soft-1.16.0/Alc/alstring.h | 45 + .../Alc/backends/alsa.c | 263 +- .../Alc/backends/base.c | 78 +- .../Alc/backends/base.h | 18 +- .../Alc/backends/coreaudio.c | 5 +- .../Alc/backends/dsound.c | 766 +++--- .../Alc/backends/loopback.c | 26 +- .../Alc/backends/mmdevapi.c | 1119 +++++---- .../Alc/backends/null.c | 92 +- .../Alc/backends/opensl.c | 95 +- .../Alc/backends/oss.c | 64 +- .../Alc/backends/portaudio.c | 9 +- .../Alc/backends/pulseaudio.c | 375 ++- .../Alc/backends/qsa.c | 60 +- .../Alc/backends/sndio.c | 18 +- .../Alc/backends/solaris.c | 20 +- .../Alc/backends/wave.c | 83 +- .../Alc/backends/winmm.c | 329 +-- .../Alc/bs2b.c | 116 +- jni/openal-soft-1.16.0/Alc/compat.h | 32 + .../Alc/effects/autowah.c | 27 +- .../Alc/effects/chorus.c | 42 +- .../Alc/effects/compressor.c | 11 +- .../Alc/effects/dedicated.c | 7 +- .../Alc/effects/distortion.c | 7 +- .../Alc/effects/echo.c | 9 +- .../Alc/effects/equalizer.c | 7 +- .../Alc/effects/flanger.c | 42 +- .../Alc/effects/modulator.c | 7 +- .../Alc/effects/null.c | 18 +- .../Alc/effects/reverb.c | 9 +- .../Alc/evtqueue.h | 0 jni/openal-soft-1.16.0/Alc/helpers.c | 814 ++++++ .../Alc/hrtf.c | 276 +- jni/openal-soft-1.16.0/Alc/hrtf.h | 28 + .../Alc/midi/base.c | 72 +- .../Alc/midi/base.h | 35 +- .../Alc/midi/dummy.c | 37 +- .../Alc/midi/fluidsynth.c | 249 +- .../Alc/midi/sf2load.c | 549 ++-- jni/openal-soft-1.16.0/Alc/midi/soft.c | 140 ++ .../Alc/mixer.c | 283 ++- .../Alc/mixer_c.c | 103 +- jni/openal-soft-1.16.0/Alc/mixer_defs.h | 65 + jni/openal-soft-1.16.0/Alc/mixer_inc.c | 93 + jni/openal-soft-1.16.0/Alc/mixer_neon.c | 118 + jni/openal-soft-1.16.0/Alc/mixer_sse.c | 202 ++ jni/openal-soft-1.16.0/Alc/mixer_sse2.c | 78 + jni/openal-soft-1.16.0/Alc/mixer_sse41.c | 82 + .../Alc/panning.c | 0 jni/openal-soft-1.16.0/Alc/vector.h | 87 + .../Android.mk | 5 +- .../CMakeLists.txt | 824 +++--- .../COPYING | 0 .../OpenAL32/Include/alAuxEffectSlot.h | 14 +- .../OpenAL32/Include/alBuffer.h | 18 +- .../OpenAL32/Include/alEffect.h | 0 .../OpenAL32/Include/alError.h | 0 .../OpenAL32/Include/alFilter.h | 26 +- .../OpenAL32/Include/alListener.h | 0 .../OpenAL32/Include/alMain.h | 268 +- .../OpenAL32/Include/alMidi.h | 38 +- .../OpenAL32/Include/alSource.h | 110 +- .../OpenAL32/Include/alThunk.h | 0 .../OpenAL32/Include/alu.h | 123 +- .../OpenAL32/Include/bs2b.h | 50 +- .../OpenAL32/Include/sample_cvt.h | 9 + .../OpenAL32/alAuxEffectSlot.c | 86 +- jni/openal-soft-1.16.0/OpenAL32/alBuffer.c | 1329 ++++++++++ .../OpenAL32/alEffect.c | 0 .../OpenAL32/alError.c | 5 +- .../OpenAL32/alExtension.c | 2 + .../OpenAL32/alFilter.c | 223 +- .../OpenAL32/alFontsound.c | 104 +- .../OpenAL32/alListener.c | 10 +- .../OpenAL32/alMidi.c | 18 +- .../OpenAL32/alPreset.c | 21 +- .../OpenAL32/alSoundfont.c | 233 +- .../OpenAL32/alSource.c | 722 ++++-- .../OpenAL32/alState.c | 40 +- .../OpenAL32/alThunk.c | 0 jni/openal-soft-1.16.0/OpenAL32/sample_cvt.c | 1269 ++++++++++ .../README | 0 .../XCompile.txt | 0 .../alsoftrc.sample | 77 +- jni/openal-soft-1.16.0/build/.empty | 0 .../cmake/CheckFileOffsetBits.c | 9 + .../cmake/CheckFileOffsetBits.cmake | 39 + .../cmake/CheckSharedFunctionExists.cmake | 0 jni/openal-soft-1.16.0/cmake/FindALSA.cmake | 73 + .../cmake/FindAudioIO.cmake | 21 + jni/openal-soft-1.16.0/cmake/FindDSound.cmake | 33 + jni/openal-soft-1.16.0/cmake/FindFFmpeg.cmake | 173 ++ .../cmake/FindFluidSynth.cmake | 8 +- jni/openal-soft-1.16.0/cmake/FindOSS.cmake | 21 + .../cmake/FindPortAudio.cmake | 32 + .../cmake/FindPulseAudio.cmake | 43 + jni/openal-soft-1.16.0/cmake/FindQSA.cmake | 34 + jni/openal-soft-1.16.0/cmake/FindSDL2.cmake | 193 ++ .../cmake/FindSDL_sound.cmake | 380 +++ .../cmake/FindSoundIO.cmake | 32 + jni/openal-soft-1.16.0/common/atomic.c | 13 + jni/openal-soft-1.16.0/common/rwlock.c | 57 + jni/openal-soft-1.16.0/common/threads.c | 744 ++++++ jni/openal-soft-1.16.0/common/uintmap.c | 144 ++ .../config.h | 63 +- .../config.h.in | 57 +- .../env-vars.txt | 0 jni/openal-soft-1.16.0/examples/alffplay.c | 1479 +++++++++++ .../examples/allatency.c | 0 .../examples/alloopback.c | 7 +- .../examples/alreverb.c | 0 .../examples/alstream.c | 0 .../examples/common/alhelpers.c | 0 .../examples/common/alhelpers.h | 0 .../examples/common/sdl_sound.c | 0 .../examples/common/sdl_sound.h | 0 .../hrtf.txt | 10 +- jni/openal-soft-1.16.0/hrtf/default-44100.mhr | Bin 0 -> 53853 bytes jni/openal-soft-1.16.0/hrtf/default-48000.mhr | Bin 0 -> 53853 bytes .../include/AL/al.h | 0 .../include/AL/alc.h | 0 .../include/AL/alext.h | 29 + .../include/AL/efx-creative.h | 0 .../include/AL/efx-presets.h | 0 .../include/AL/efx.h | 0 jni/openal-soft-1.16.0/include/align.h | 21 + jni/openal-soft-1.16.0/include/atomic.h | 313 +++ jni/openal-soft-1.16.0/include/bool.h | 18 + jni/openal-soft-1.16.0/include/rwlock.h | 32 + .../include/static_assert.h | 17 + jni/openal-soft-1.16.0/include/threads.h | 243 ++ .../include}/uintmap.h | 11 +- .../openal.pc.in | 0 .../utils/CIAIR.def | 0 .../utils/IRC_1005.def | 0 .../utils/MIT_KEMAR.def | 0 .../utils/alsoft-config/CMakeLists.txt | 0 .../utils/alsoft-config/main.cpp | 0 .../utils/alsoft-config/mainwindow.cpp | 126 +- .../utils/alsoft-config/mainwindow.h | 0 .../utils/alsoft-config/mainwindow.ui | 205 +- .../utils/makehrtf.c | 97 +- .../utils/openal-info.c | 0 jni/openal-soft-android/.gitignore | 6 - jni/openal-soft-android/Alc/atomic.h | 180 -- jni/openal-soft-android/Alc/compat.h | 65 - jni/openal-soft-android/Alc/helpers.c | 708 ------ jni/openal-soft-android/Alc/hrtf_tables.inc | 848 ------- jni/openal-soft-android/Alc/mixer_defs.h | 33 - jni/openal-soft-android/Alc/mixer_inc.c | 140 -- jni/openal-soft-android/Alc/mixer_neon.c | 130 - jni/openal-soft-android/Alc/mixer_sse.c | 164 -- jni/openal-soft-android/Alc/rwlock.h | 21 - jni/openal-soft-android/Alc/threads.c | 200 -- .../OpenAL32/Include/threads.h | 14 - jni/openal-soft-android/OpenAL32/alBuffer.c | 2212 ----------------- .../cmake/FindSDL_sound.cmake | 382 --- .../cmake/toolchain.android.cmake | 171 -- 164 files changed, 14660 insertions(+), 10016 deletions(-) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/ALc.c (81%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/ALu.c (65%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/alcConfig.c (68%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/alcRing.c (89%) create mode 100644 jni/openal-soft-1.16.0/Alc/alstring.h rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/alsa.c (90%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/base.c (77%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/base.h (91%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/coreaudio.c (99%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/dsound.c (54%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/loopback.c (90%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/mmdevapi.c (56%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/null.c (75%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/opensl.c (78%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/oss.c (93%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/portaudio.c (97%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/pulseaudio.c (87%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/qsa.c (97%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/sndio.c (95%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/solaris.c (95%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/wave.c (80%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/backends/winmm.c (68%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/bs2b.c (51%) create mode 100644 jni/openal-soft-1.16.0/Alc/compat.h rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/autowah.c (93%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/chorus.c (93%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/compressor.c (96%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/dedicated.c (97%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/distortion.c (98%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/echo.c (98%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/equalizer.c (99%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/flanger.c (93%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/modulator.c (98%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/null.c (91%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/effects/reverb.c (99%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/evtqueue.h (100%) create mode 100644 jni/openal-soft-1.16.0/Alc/helpers.c rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/hrtf.c (71%) create mode 100644 jni/openal-soft-1.16.0/Alc/hrtf.h rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/midi/base.c (77%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/midi/base.h (85%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/midi/dummy.c (64%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/midi/fluidsynth.c (76%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/midi/sf2load.c (73%) create mode 100644 jni/openal-soft-1.16.0/Alc/midi/soft.c rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/mixer.c (59%) rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/mixer_c.c (50%) create mode 100644 jni/openal-soft-1.16.0/Alc/mixer_defs.h create mode 100644 jni/openal-soft-1.16.0/Alc/mixer_inc.c create mode 100644 jni/openal-soft-1.16.0/Alc/mixer_neon.c create mode 100644 jni/openal-soft-1.16.0/Alc/mixer_sse.c create mode 100644 jni/openal-soft-1.16.0/Alc/mixer_sse2.c create mode 100644 jni/openal-soft-1.16.0/Alc/mixer_sse41.c rename jni/{openal-soft-android => openal-soft-1.16.0}/Alc/panning.c (100%) create mode 100644 jni/openal-soft-1.16.0/Alc/vector.h rename jni/{openal-soft-android => openal-soft-1.16.0}/Android.mk (76%) rename jni/{openal-soft-android => openal-soft-1.16.0}/CMakeLists.txt (58%) rename jni/{openal-soft-android => openal-soft-1.16.0}/COPYING (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alAuxEffectSlot.h (93%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alBuffer.h (79%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alEffect.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alError.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alFilter.h (77%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alListener.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alMain.h (87%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alMidi.h (81%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alSource.h (56%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alThunk.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/alu.h (54%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/Include/bs2b.h (69%) create mode 100644 jni/openal-soft-1.16.0/OpenAL32/Include/sample_cvt.h rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alAuxEffectSlot.c (87%) create mode 100644 jni/openal-soft-1.16.0/OpenAL32/alBuffer.c rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alEffect.c (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alError.c (90%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alExtension.c (99%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alFilter.c (67%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alFontsound.c (92%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alListener.c (97%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alMidi.c (93%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alPreset.c (94%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alSoundfont.c (64%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alSource.c (78%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alState.c (93%) rename jni/{openal-soft-android => openal-soft-1.16.0}/OpenAL32/alThunk.c (100%) create mode 100644 jni/openal-soft-1.16.0/OpenAL32/sample_cvt.c rename jni/{openal-soft-android => openal-soft-1.16.0}/README (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/XCompile.txt (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/alsoftrc.sample (81%) create mode 100644 jni/openal-soft-1.16.0/build/.empty create mode 100644 jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.c create mode 100644 jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.cmake rename jni/{openal-soft-android => openal-soft-1.16.0}/cmake/CheckSharedFunctionExists.cmake (100%) create mode 100644 jni/openal-soft-1.16.0/cmake/FindALSA.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindAudioIO.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindDSound.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindFFmpeg.cmake rename jni/{openal-soft-android => openal-soft-1.16.0}/cmake/FindFluidSynth.cmake (67%) create mode 100644 jni/openal-soft-1.16.0/cmake/FindOSS.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindPortAudio.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindPulseAudio.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindQSA.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindSDL2.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindSDL_sound.cmake create mode 100644 jni/openal-soft-1.16.0/cmake/FindSoundIO.cmake create mode 100644 jni/openal-soft-1.16.0/common/atomic.c create mode 100644 jni/openal-soft-1.16.0/common/rwlock.c create mode 100644 jni/openal-soft-1.16.0/common/threads.c create mode 100644 jni/openal-soft-1.16.0/common/uintmap.c rename jni/{openal-soft-android => openal-soft-1.16.0}/config.h (72%) rename jni/{openal-soft-android => openal-soft-1.16.0}/config.h.in (74%) rename jni/{openal-soft-android => openal-soft-1.16.0}/env-vars.txt (100%) create mode 100644 jni/openal-soft-1.16.0/examples/alffplay.c rename jni/{openal-soft-android => openal-soft-1.16.0}/examples/allatency.c (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/examples/alloopback.c (99%) rename jni/{openal-soft-android => openal-soft-1.16.0}/examples/alreverb.c (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/examples/alstream.c (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/examples/common/alhelpers.c (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/examples/common/alhelpers.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/examples/common/sdl_sound.c (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/examples/common/sdl_sound.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/hrtf.txt (91%) create mode 100644 jni/openal-soft-1.16.0/hrtf/default-44100.mhr create mode 100644 jni/openal-soft-1.16.0/hrtf/default-48000.mhr rename jni/{openal-soft-android => openal-soft-1.16.0}/include/AL/al.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/include/AL/alc.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/include/AL/alext.h (94%) rename jni/{openal-soft-android => openal-soft-1.16.0}/include/AL/efx-creative.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/include/AL/efx-presets.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/include/AL/efx.h (100%) create mode 100644 jni/openal-soft-1.16.0/include/align.h create mode 100644 jni/openal-soft-1.16.0/include/atomic.h create mode 100644 jni/openal-soft-1.16.0/include/bool.h create mode 100644 jni/openal-soft-1.16.0/include/rwlock.h create mode 100644 jni/openal-soft-1.16.0/include/static_assert.h create mode 100644 jni/openal-soft-1.16.0/include/threads.h rename jni/{openal-soft-android/Alc => openal-soft-1.16.0/include}/uintmap.h (78%) rename jni/{openal-soft-android => openal-soft-1.16.0}/openal.pc.in (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/CIAIR.def (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/IRC_1005.def (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/MIT_KEMAR.def (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/alsoft-config/CMakeLists.txt (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/alsoft-config/main.cpp (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/alsoft-config/mainwindow.cpp (84%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/alsoft-config/mainwindow.h (100%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/alsoft-config/mainwindow.ui (90%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/makehrtf.c (98%) rename jni/{openal-soft-android => openal-soft-1.16.0}/utils/openal-info.c (100%) delete mode 100644 jni/openal-soft-android/.gitignore delete mode 100644 jni/openal-soft-android/Alc/atomic.h delete mode 100644 jni/openal-soft-android/Alc/compat.h delete mode 100644 jni/openal-soft-android/Alc/helpers.c delete mode 100644 jni/openal-soft-android/Alc/hrtf_tables.inc delete mode 100644 jni/openal-soft-android/Alc/mixer_defs.h delete mode 100644 jni/openal-soft-android/Alc/mixer_inc.c delete mode 100644 jni/openal-soft-android/Alc/mixer_neon.c delete mode 100644 jni/openal-soft-android/Alc/mixer_sse.c delete mode 100644 jni/openal-soft-android/Alc/rwlock.h delete mode 100644 jni/openal-soft-android/Alc/threads.c delete mode 100644 jni/openal-soft-android/OpenAL32/Include/threads.h delete mode 100644 jni/openal-soft-android/OpenAL32/alBuffer.c delete mode 100644 jni/openal-soft-android/cmake/FindSDL_sound.cmake delete mode 100644 jni/openal-soft-android/cmake/toolchain.android.cmake diff --git a/jni/love/Android.mk b/jni/love/Android.mk index 9de44af2..97962239 100644 --- a/jni/love/Android.mk +++ b/jni/love/Android.mk @@ -6,7 +6,8 @@ include $(CLEAR_VARS) LOCAL_MODULE := liblove LOCAL_CFLAGS := -fexceptions -g -Dlinux -Dunix \ -DHAVE_GCC_DESTRUCTOR=1 -DOPT_GENERIC -DREAL_IS_FLOAT \ - -DGL_GLEXT_PROTOTYPES -DLOVE_TURBO_JPEG -DLOVE_NO_DEVIL + -DGL_GLEXT_PROTOTYPES -DLOVE_TURBO_JPEG -DLOVE_NO_DEVIL \ + -DAL_ALEXT_PROTOTYPES LOCAL_CPPFLAGS := ${LOCAL_CFLAGS} @@ -21,8 +22,8 @@ LOCAL_C_INCLUDES := \ ${LOCAL_PATH}/../libjpeg-turbo-1.3.1/ \ ${LOCAL_PATH}/../lcms2-2.5/include \ ${LOCAL_PATH}/../tiff-3.9.5/libtiff \ - ${LOCAL_PATH}/../openal-soft-android/include \ - ${LOCAL_PATH}/../openal-soft-android/OpenAL32/Include \ + ${LOCAL_PATH}/../openal-soft-1.16.0/include \ + ${LOCAL_PATH}/../openal-soft-1.16.0/OpenAL32/Include \ ${LOCAL_PATH}/../freetype2-android/include \ ${LOCAL_PATH}/../freetype2-android/src \ ${LOCAL_PATH}/../physfs-2.1.0/src \ diff --git a/jni/openal-soft-android/Alc/ALc.c b/jni/openal-soft-1.16.0/Alc/ALc.c similarity index 81% rename from jni/openal-soft-android/Alc/ALc.c rename to jni/openal-soft-1.16.0/Alc/ALc.c index 7d8f14cd..f7f7b63a 100644 --- a/jni/openal-soft-android/Alc/ALc.c +++ b/jni/openal-soft-1.16.0/Alc/ALc.c @@ -39,6 +39,10 @@ #include "bs2b.h" #include "alu.h" +#include "compat.h" +#include "threads.h" +#include "alstring.h" + #include "backends/base.h" #include "midi/base.h" @@ -79,10 +83,10 @@ static struct BackendInfo BackendList[] = { { "qsa", NULL, alc_qsa_init, alc_qsa_deinit, alc_qsa_probe, EmptyFuncs }, #endif #ifdef HAVE_MMDEVAPI - { "mmdevapi", NULL, alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs }, + { "mmdevapi", ALCmmdevBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif #ifdef HAVE_DSOUND - { "dsound", NULL, alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs }, + { "dsound", ALCdsoundBackendFactory_getFactory, NULL, NULL, NULL, EmptyFuncs }, #endif #ifdef HAVE_WINMM { "winmm", NULL, alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs }, @@ -153,6 +157,8 @@ static const ALCfunction alcFunctions[] = { DECL(alcDevicePauseSOFT), DECL(alcDeviceResumeSOFT), + DECL(alcGetInteger64vSOFT), + DECL(alEnable), DECL(alDisable), DECL(alIsEnabled), @@ -287,10 +293,6 @@ static const ALCfunction alcFunctions[] = { DECL(alGenSoundfontsSOFT), DECL(alDeleteSoundfontsSOFT), DECL(alIsSoundfontSOFT), - DECL(alSoundfontSamplesSOFT), - DECL(alGetSoundfontSamplesSOFT), - DECL(alSoundfontMapSamplesSOFT), - DECL(alSoundfontUnmapSamplesSOFT), DECL(alGetSoundfontivSOFT), DECL(alSoundfontPresetsSOFT), DECL(alGenPresetsSOFT), @@ -443,6 +445,8 @@ static const ALCenums enumeration[] = { 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), @@ -521,6 +525,8 @@ static const ALCenums enumeration[] = { 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_UNUSED), DECL(AL_PENDING), @@ -555,14 +561,19 @@ static const ALCenums enumeration[] = { DECL(AL_FILTER_TYPE), DECL(AL_FILTER_NULL), DECL(AL_FILTER_LOWPASS), -#if 0 DECL(AL_FILTER_HIGHPASS), DECL(AL_FILTER_BANDPASS), -#endif 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), @@ -577,7 +588,9 @@ static const ALCenums enumeration[] = { 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), @@ -651,10 +664,12 @@ static const ALCenums enumeration[] = { DECL(AL_RING_MODULATOR_HIGHPASS_CUTOFF), DECL(AL_RING_MODULATOR_WAVEFORM), +#if 0 DECL(AL_AUTOWAH_ATTACK_TIME), DECL(AL_AUTOWAH_PEAK_GAIN), DECL(AL_AUTOWAH_RELEASE_TIME), DECL(AL_AUTOWAH_RESONANCE), +#endif DECL(AL_COMPRESSOR_ONOFF), @@ -689,11 +704,9 @@ static const ALCchar alcErrOutOfMemory[] = "Out of Memory"; /* Enumerated device names */ static const ALCchar alcDefaultName[] = "OpenAL Soft\0"; -static ALCchar *alcAllDevicesList; -static ALCchar *alcCaptureDeviceList; -/* Sizes only include the first ending null character, not the second */ -static size_t alcAllDevicesListSize; -static size_t alcCaptureDeviceListSize; + +static al_string alcAllDevicesList; +static al_string alcCaptureDeviceList; /* Default is always the first in the list */ static ALCchar *alcDefaultAllDevicesSpecifier; @@ -704,16 +717,17 @@ static const ALchar alExtList[] = "AL_EXT_ALAW 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_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model " - "AL_LOKI_quadriphonic AL_SOFT_buffer_samples AL_SOFT_buffer_sub_data " - "AL_SOFT_deferred_updates AL_SOFT_direct_channels AL_SOFT_loop_points " - "AL_SOFT_source_latency"; + "AL_LOKI_quadriphonic AL_SOFT_block_alignment AL_SOFT_buffer_samples " + "AL_SOFT_buffer_sub_data AL_SOFT_deferred_updates AL_SOFT_direct_channels " + "AL_SOFT_loop_points AL_SOFT_MSADPCM AL_SOFT_source_latency " + "AL_SOFT_source_length"; -static volatile ALCenum LastNullDeviceError = ALC_NO_ERROR; +static ATOMIC(ALCenum) LastNullDeviceError = ATOMIC_INIT_STATIC(ALC_NO_ERROR); /* Thread-local current context */ -static althread_key_t LocalContext; +static altss_t LocalContext; /* Process-wide current context */ -static ALCcontext *volatile GlobalContext = NULL; +static ATOMIC(ALCcontext*) GlobalContext = ATOMIC_INIT_STATIC(NULL); /* Mixing thread piority level */ ALint RTPrioLevel; @@ -729,7 +743,7 @@ enum LogLevel LogLevel = LogError; static ALCboolean TrapALCError = ALC_FALSE; /* One-time configuration init control */ -static althread_once_t alc_config_once = ALTHREAD_ONCE_INIT; +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; @@ -744,8 +758,8 @@ static const ALCchar alcNoDeviceExtList[] = 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_HRTF ALC_SOFT_loopback " - "ALC_SOFTX_midi_interface ALC_SOFTX_pause_device"; + "ALC_EXT_thread_local_context ALC_SOFTX_device_clock ALC_SOFTX_HRTF " + "ALC_SOFT_loopback ALC_SOFTX_midi_interface ALC_SOFT_pause_device"; static const ALCint alcMajorVersion = 1; static const ALCint alcMinorVersion = 1; @@ -756,17 +770,18 @@ static const ALCint alcEFXMinorVersion = 0; /************************************************ * Device lists ************************************************/ -static ALCdevice *volatile DeviceList = NULL; +static ATOMIC(ALCdevice*) DeviceList = ATOMIC_INIT_STATIC(NULL); -static CRITICAL_SECTION ListLock; - -static void LockLists(void) +static almtx_t ListLock; +static inline void LockLists(void) { - EnterCriticalSection(&ListLock); + int lockret = almtx_lock(&ListLock); + assert(lockret == althrd_success); } -static void UnlockLists(void) +static inline void UnlockLists(void) { - LeaveCriticalSection(&ListLock); + int unlockret = almtx_unlock(&ListLock); + assert(unlockret == althrd_success); } /************************************************ @@ -777,34 +792,19 @@ static void alc_init(void); static void alc_deinit(void); static void alc_deinit_safe(void); -UIntMap TlsDestructor; - #ifndef AL_LIBTYPE_STATIC -BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) +BOOL APIENTRY DllMain(HINSTANCE hModule, DWORD reason, LPVOID lpReserved) { - ALsizei i; - - // Perform actions based on the reason for calling. - switch(ul_reason_for_call) + 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); - InitUIntMap(&TlsDestructor, ~0); alc_init(); break; case DLL_THREAD_DETACH: - LockUIntMapRead(&TlsDestructor); - for(i = 0;i < TlsDestructor.size;i++) - { - void *ptr = althread_getspecific(TlsDestructor.array[i].key); - void (*callback)(void*) = (void(*)(void*))TlsDestructor.array[i].value; - if(ptr && callback) - callback(ptr); - } - UnlockUIntMapRead(&TlsDestructor); break; case DLL_PROCESS_DETACH: @@ -812,7 +812,6 @@ BOOL APIENTRY DllMain(HINSTANCE hModule,DWORD ul_reason_for_call,LPVOID lpReserv alc_deinit(); else alc_deinit_safe(); - ResetUIntMap(&TlsDestructor); break; } return TRUE; @@ -853,9 +852,13 @@ 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; @@ -864,8 +867,12 @@ static void alc_init(void) if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) ZScale *= -1.0f; - althread_key_create(&LocalContext, ReleaseThreadCtx); - InitializeCriticalSection(&ListLock); + ret = altss_create(&LocalContext, ReleaseThreadCtx); + assert(ret == althrd_success); + + ret = almtx_init(&ListLock, almtx_recursive); + assert(ret == althrd_success); + ThunkInit(); } @@ -887,7 +894,7 @@ static void alc_initconfig(void) str = getenv("ALSOFT_LOGFILE"); if(str && str[0]) { - FILE *logfile = fopen(str, "wt"); + FILE *logfile = al_fopen(str, "wt"); if(logfile) LogFile = logfile; else ERR("Failed to open log file '%s'\n", str); } @@ -902,8 +909,12 @@ static void alc_initconfig(void) ReadALConfig(); capfilter = 0; -#ifdef HAVE_SSE +#if defined(HAVE_SSE4_1) + capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1; +#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; @@ -933,6 +944,8 @@ static void alc_initconfig(void) capfilter &= ~CPU_CAP_SSE; else if(len == 4 && strncasecmp(str, "sse2", len) == 0) capfilter &= ~CPU_CAP_SSE2; + 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 @@ -1138,7 +1151,7 @@ static void alc_initconfig(void) if((str && str[0]) || ConfigValueStr(NULL, "default-reverb", &str)) LoadReverbPreset(str, &DefaultEffect); } -#define DO_INITCONFIG() althread_once(&alc_config_once, alc_initconfig) +#define DO_INITCONFIG() alcall_once(&alc_config_once, alc_initconfig) /************************************************ @@ -1148,17 +1161,15 @@ static void alc_cleanup(void) { ALCdevice *dev; - free(alcAllDevicesList); alcAllDevicesList = NULL; - alcAllDevicesListSize = 0; - free(alcCaptureDeviceList); alcCaptureDeviceList = NULL; - alcCaptureDeviceListSize = 0; + AL_STRING_DEINIT(alcAllDevicesList); + AL_STRING_DEINIT(alcCaptureDeviceList); free(alcDefaultAllDevicesSpecifier); alcDefaultAllDevicesSpecifier = NULL; free(alcCaptureDefaultDeviceSpecifier); alcCaptureDefaultDeviceSpecifier = NULL; - if((dev=ExchangePtr((XchgPtr*)&DeviceList, NULL)) != NULL) + if((dev=ATOMIC_EXCHANGE(ALCdevice*, &DeviceList, NULL)) != NULL) { ALCuint num = 0; do { @@ -1178,8 +1189,8 @@ static void alc_deinit_safe(void) FreeALConfig(); ThunkExit(); - DeleteCriticalSection(&ListLock); - althread_key_delete(LocalContext); + almtx_destroy(&ListLock); + altss_delete(LocalContext); if(LogFile != stderr) fclose(LogFile); @@ -1217,14 +1228,12 @@ static void alc_deinit(void) /************************************************ * Device enumeration ************************************************/ -static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type) +static void ProbeDevices(al_string *list, enum DevProbe type) { DO_INITCONFIG(); LockLists(); - free(*list); - *list = NULL; - *listsize = 0; + al_string_clear(list); if(type == ALL_DEVICE_PROBE && (PlaybackBackend.Probe || PlaybackBackend.getFactory)) { @@ -1248,42 +1257,24 @@ static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type) } UnlockLists(); } - static void ProbeAllDevicesList(void) -{ ProbeList(&alcAllDevicesList, &alcAllDevicesListSize, ALL_DEVICE_PROBE); } +{ ProbeDevices(&alcAllDevicesList, ALL_DEVICE_PROBE); } static void ProbeCaptureDeviceList(void) -{ ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); } +{ ProbeDevices(&alcCaptureDeviceList, CAPTURE_DEVICE_PROBE); } - -static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize) +static void AppendDevice(const ALCchar *name, al_string *devnames) { size_t len = strlen(name); - void *temp; - - if(len == 0) - return; - - temp = realloc(*List, (*ListSize) + len + 2); - if(!temp) + if(len > 0) { - ERR("Realloc failed to add %s!\n", name); - return; + al_string_append_range(devnames, name, name+len); + al_string_append_char(devnames, '\0'); } - *List = temp; - - memcpy((*List)+(*ListSize), name, len+1); - *ListSize += len+1; - (*List)[*ListSize] = 0; } - -#define DECL_APPEND_LIST_FUNC(type) \ -void Append##type##List(const ALCchar *name) \ -{ AppendList(name, &alc##type##List, &alc##type##ListSize); } - -DECL_APPEND_LIST_FUNC(AllDevices) -DECL_APPEND_LIST_FUNC(CaptureDevice) - -#undef DECL_APPEND_LIST_FUNC +void AppendAllDevicesList(const ALCchar *name) +{ AppendDevice(name, &alcAllDevicesList); } +void AppendCaptureDeviceList(const ALCchar *name) +{ AppendDevice(name, &alcCaptureDeviceList); } /************************************************ @@ -1348,8 +1339,8 @@ ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) return 0; } -static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans, - enum DevFmtType *type) +DECL_CONST static ALboolean DecomposeDevFormat(ALenum format, + enum DevFmtChannels *chans, enum DevFmtType *type) { static const struct { ALenum format; @@ -1395,7 +1386,7 @@ static ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans, return AL_FALSE; } -static ALCboolean IsValidALCType(ALCenum type) +DECL_CONST static ALCboolean IsValidALCType(ALCenum type) { switch(type) { @@ -1411,7 +1402,7 @@ static ALCboolean IsValidALCType(ALCenum type) return ALC_FALSE; } -static ALCboolean IsValidALCChannels(ALCenum channels) +DECL_CONST static ALCboolean IsValidALCChannels(ALCenum channels) { switch(channels) { @@ -1571,12 +1562,24 @@ static void alcSetError(ALCdevice *device, ALCenum errorCode) } if(device) - device->LastError = errorCode; + ATOMIC_STORE(&device->LastError, errorCode); else - LastNullDeviceError = errorCode; + 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 @@ -1589,7 +1592,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) enum DevFmtType oldType; ALCuint oldFreq; FPUCtl oldMode; - ALuint i; // Check for attributes if(device->Type == Loopback) @@ -1600,7 +1602,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) GotType = 1<<2, GotAll = GotFreq|GotChans|GotType }; - ALCuint freq, numMono, numStereo, numSends; + ALCuint freq, numMono, numStereo, numSends, flags; enum DevFmtChannels schans; enum DevFmtType stype; ALCuint attrIdx = 0; @@ -1618,6 +1620,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) schans = device->FmtChans; stype = device->FmtType; freq = device->Frequency; + flags = device->Flags; while(attrList[attrIdx]) { @@ -1662,9 +1665,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if(attrList[attrIdx] == ALC_HRTF_SOFT) { if(attrList[attrIdx + 1] != ALC_FALSE) - device->Flags |= DEVICE_HRTF_REQUEST; + flags |= DEVICE_HRTF_REQUEST; else - device->Flags &= ~DEVICE_HRTF_REQUEST; + flags &= ~DEVICE_HRTF_REQUEST; } attrIdx += 2; @@ -1681,8 +1684,10 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if((device->Flags&DEVICE_RUNNING)) V0(device->Backend,stop)(); - device->Flags &= ~DEVICE_RUNNING; + device->Flags = (flags & ~DEVICE_RUNNING); + if(freq != device->Frequency) + UpdateClockBase(device); device->Frequency = freq; device->FmtChans = schans; device->FmtType = stype; @@ -1749,6 +1754,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if((CPUCapFlags&(CPU_CAP_SSE|CPU_CAP_NEON)) != 0) device->UpdateSize = (device->UpdateSize+3)&~3; + if(freq != device->Frequency) + UpdateClockBase(device); device->Frequency = freq; device->NumMonoSources = numMono; device->NumStereoSources = numStereo; @@ -1758,6 +1765,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) if((device->Flags&DEVICE_RUNNING)) return ALC_NO_ERROR; + UpdateClockBase(device); + oldFreq = device->Frequency; oldChans = device->FmtChans; oldType = device->FmtType; @@ -1771,16 +1780,34 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) device->Frequency, device->UpdateSize, device->NumUpdates); + if(device->Type != Loopback) + { + bool usehrtf = !!(device->Flags&DEVICE_HRTF_REQUEST); + if(GetConfigValueBool(NULL, "hrtf", usehrtf)) + device->Flags |= DEVICE_HRTF_REQUEST; + else + device->Flags &= ~DEVICE_HRTF_REQUEST; + } if((device->Flags&DEVICE_HRTF_REQUEST)) { - enum DevFmtChannels chans; - ALCuint freq; - - FindHrtfFormat(device, &chans, &freq); - device->Frequency = freq; - device->FmtChans = chans; - device->Flags |= DEVICE_CHANNELS_REQUEST | - DEVICE_FREQUENCY_REQUEST; + enum DevFmtChannels chans = device->FmtChans; + ALCuint freq = device->Frequency; + if(FindHrtfFormat(&chans, &freq)) + { + if(device->Type != Loopback) + { + device->Frequency = freq; + device->FmtChans = chans; + device->Flags |= DEVICE_CHANNELS_REQUEST | + DEVICE_FREQUENCY_REQUEST; + } + else if(device->Frequency != freq || device->FmtChans != chans) + { + ERR("Requested format not HRTF compatible: %s, %uhz\n", + DevFmtChannelsString(device->FmtChans), device->Frequency); + device->Flags &= ~DEVICE_HRTF_REQUEST; + } + } } if(V0(device->Backend,reset)() == ALC_FALSE) @@ -1811,25 +1838,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) aluInitPanning(device); - for(i = 0;i < MaxChannels;i++) - { - device->ClickRemoval[i] = 0.0f; - device->PendingClicks[i] = 0.0f; - } - V(device->Synth,update)(device); device->Hrtf = NULL; - if(device->Type != Loopback && ConfigValueExists(NULL, "hrtf")) - { - if(GetConfigValueBool(NULL, "hrtf", AL_FALSE)) - device->Flags |= DEVICE_HRTF_REQUEST; - else - device->Flags &= ~DEVICE_HRTF_REQUEST; - } if((device->Flags&DEVICE_HRTF_REQUEST)) { - device->Hrtf = GetHrtf(device); + device->Hrtf = GetHrtf(device->FmtChans, device->Frequency); if(!device->Hrtf) device->Flags &= ~DEVICE_HRTF_REQUEST; } @@ -1867,12 +1881,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) SetMixerFPUMode(&oldMode); ALCdevice_Lock(device); - context = device->ContextList; + context = ATOMIC_LOAD(&device->ContextList); while(context) { ALsizei pos; - context->UpdateSources = AL_FALSE; + ATOMIC_STORE(&context->UpdateSources, AL_FALSE); LockUIntMapRead(&context->EffectSlotMap); for(pos = 0;pos < context->EffectSlotMap.size;pos++) { @@ -1885,7 +1899,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) RestoreFPUMode(&oldMode); return ALC_INVALID_DEVICE; } - slot->NeedsUpdate = AL_FALSE; + ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE); V(slot->EffectState,update)(device, slot); } UnlockUIntMapRead(&context->EffectSlotMap); @@ -1904,11 +1918,26 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) source->Send[s].GainHF = 1.0f; s++; } - source->NeedsUpdate = AL_FALSE; - ALsource_Update(source, context); + ATOMIC_STORE(&source->NeedsUpdate, AL_TRUE); } UnlockUIntMapRead(&context->SourceMap); + for(pos = 0;pos < context->ActiveSourceCount;pos++) + { + ALactivesource *src = context->ActiveSources[pos]; + ALsource *source = src->Source; + ALuint s = device->NumAuxSends; + while(s < MAX_SENDS) + { + src->Send[s].Moving = AL_FALSE; + src->Send[s].Counter = 0; + s++; + } + + src->Update(src, context); + ATOMIC_STORE(&source->NeedsUpdate, AL_FALSE); + } + context = context->next; } if(device->DefaultSlot) @@ -1921,7 +1950,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) RestoreFPUMode(&oldMode); return ALC_INVALID_DEVICE; } - slot->NeedsUpdate = AL_FALSE; + ATOMIC_STORE(&slot->NeedsUpdate, AL_FALSE); V(slot->EffectState,update)(device, slot); } ALCdevice_Unlock(device); @@ -2009,8 +2038,7 @@ static ALCvoid FreeDevice(ALCdevice *device) free(device->Bs2b); device->Bs2b = NULL; - free(device->DeviceName); - device->DeviceName = NULL; + AL_STRING_DEINIT(device->DeviceName); al_free(device); } @@ -2018,14 +2046,14 @@ static ALCvoid FreeDevice(ALCdevice *device) void ALCdevice_IncRef(ALCdevice *device) { - RefCount ref; + uint ref; ref = IncrementRef(&device->ref); TRACEREF("%p increasing refcount to %u\n", device, ref); } void ALCdevice_DecRef(ALCdevice *device) { - RefCount ref; + uint ref; ref = DecrementRef(&device->ref); TRACEREF("%p decreasing refcount to %u\n", device, ref); if(ref == 0) FreeDevice(device); @@ -2043,7 +2071,7 @@ static ALCdevice *VerifyDevice(ALCdevice *device) return NULL; LockLists(); - tmpDevice = DeviceList; + tmpDevice = ATOMIC_LOAD(&DeviceList); while(tmpDevice && tmpDevice != device) tmpDevice = tmpDevice->next; @@ -2086,8 +2114,8 @@ static ALvoid InitContext(ALCcontext *Context) Context->Listener->Params.Velocity[i] = 0.0f; //Validate Context - Context->LastError = AL_NO_ERROR; - Context->UpdateSources = AL_FALSE; + ATOMIC_INIT(&Context->LastError, AL_NO_ERROR); + ATOMIC_INIT(&Context->UpdateSources, AL_FALSE); Context->ActiveSourceCount = 0; InitUIntMap(&Context->SourceMap, Context->Device->MaxNoOfSources); InitUIntMap(&Context->EffectSlotMap, Context->Device->AuxiliaryEffectSlotMax); @@ -2111,6 +2139,8 @@ static ALvoid InitContext(ALCcontext *Context) */ static ALCvoid FreeContext(ALCcontext *context) { + ALsizei i; + TRACE("%p\n", context); if(context->SourceMap.size > 0) @@ -2127,15 +2157,17 @@ static ALCvoid FreeContext(ALCcontext *context) } ResetUIntMap(&context->EffectSlotMap); - context->ActiveSourceCount = 0; + for(i = 0;i < context->MaxActiveSources;i++) + { + al_free(context->ActiveSources[i]); + context->ActiveSources[i] = NULL; + } free(context->ActiveSources); context->ActiveSources = NULL; + context->ActiveSourceCount = 0; context->MaxActiveSources = 0; - context->ActiveEffectSlotCount = 0; - free(context->ActiveEffectSlots); - context->ActiveEffectSlots = NULL; - context->MaxActiveEffectSlots = 0; + VECTOR_DEINIT(context->ActiveAuxSlots); ALCdevice_DecRef(context->Device); context->Device = NULL; @@ -2152,25 +2184,30 @@ static ALCvoid FreeContext(ALCcontext *context) */ static void ReleaseContext(ALCcontext *context, ALCdevice *device) { - ALCcontext *volatile*tmp_ctx; + ALCcontext *nextctx; + ALCcontext *origctx; - if(althread_getspecific(LocalContext) == context) + if(altss_get(LocalContext) == context) { WARN("%p released while current on thread\n", context); - althread_setspecific(LocalContext, NULL); + altss_set(LocalContext, NULL); ALCcontext_DecRef(context); } - if(CompExchangePtr((XchgPtr*)&GlobalContext, context, NULL)) + origctx = context; + if(ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &GlobalContext, &origctx, NULL)) ALCcontext_DecRef(context); ALCdevice_Lock(device); - tmp_ctx = &device->ContextList; - while(*tmp_ctx) + origctx = context; + nextctx = context->next; + if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALCcontext*, &device->ContextList, &origctx, nextctx)) { - if(CompExchangePtr((XchgPtr*)tmp_ctx, context, context->next)) - break; - tmp_ctx = &(*tmp_ctx)->next; + ALCcontext *list; + do { + list = origctx; + origctx = context; + } while(!COMPARE_EXCHANGE(&list->next, &origctx, nextctx)); } ALCdevice_Unlock(device); @@ -2179,14 +2216,14 @@ static void ReleaseContext(ALCcontext *context, ALCdevice *device) void ALCcontext_IncRef(ALCcontext *context) { - RefCount ref; + uint ref; ref = IncrementRef(&context->ref); TRACEREF("%p increasing refcount to %u\n", context, ref); } void ALCcontext_DecRef(ALCcontext *context) { - RefCount ref; + uint ref; ref = DecrementRef(&context->ref); TRACEREF("%p decreasing refcount to %u\n", context, ref); if(ref == 0) FreeContext(context); @@ -2207,19 +2244,19 @@ static ALCcontext *VerifyContext(ALCcontext *context) ALCdevice *dev; LockLists(); - dev = DeviceList; + dev = ATOMIC_LOAD(&DeviceList); while(dev) { - ALCcontext *tmp_ctx = dev->ContextList; - while(tmp_ctx) + ALCcontext *ctx = ATOMIC_LOAD(&dev->ContextList); + while(ctx) { - if(tmp_ctx == context) + if(ctx == context) { - ALCcontext_IncRef(tmp_ctx); + ALCcontext_IncRef(ctx); UnlockLists(); - return tmp_ctx; + return ctx; } - tmp_ctx = tmp_ctx->next; + ctx = ctx->next; } dev = dev->next; } @@ -2238,13 +2275,13 @@ ALCcontext *GetContextRef(void) { ALCcontext *context; - context = althread_getspecific(LocalContext); + context = altss_get(LocalContext); if(context) ALCcontext_IncRef(context); else { LockLists(); - context = GlobalContext; + context = ATOMIC_LOAD(&GlobalContext); if(context) ALCcontext_IncRef(context); UnlockLists(); @@ -2268,11 +2305,11 @@ ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) if(VerifyDevice(device)) { - errorCode = ExchangeInt(&device->LastError, ALC_NO_ERROR); + errorCode = ATOMIC_EXCHANGE(ALCenum, &device->LastError, ALC_NO_ERROR); ALCdevice_DecRef(device); } else - errorCode = ExchangeInt(&LastNullDeviceError, ALC_NO_ERROR); + errorCode = ATOMIC_EXCHANGE(ALCenum, &LastNullDeviceError, ALC_NO_ERROR); return errorCode; } @@ -2336,26 +2373,26 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para case ALC_ALL_DEVICES_SPECIFIER: if(VerifyDevice(Device)) { - value = Device->DeviceName; + value = al_string_get_cstr(Device->DeviceName); ALCdevice_DecRef(Device); } else { ProbeAllDevicesList(); - value = alcAllDevicesList; + value = al_string_get_cstr(alcAllDevicesList); } break; case ALC_CAPTURE_DEVICE_SPECIFIER: if(VerifyDevice(Device)) { - value = Device->DeviceName; + value = al_string_get_cstr(Device->DeviceName); ALCdevice_DecRef(Device); } else { ProbeCaptureDeviceList(); - value = alcCaptureDeviceList; + value = al_string_get_cstr(alcCaptureDeviceList); } break; @@ -2365,14 +2402,13 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para break; case ALC_DEFAULT_ALL_DEVICES_SPECIFIER: - if(!alcAllDevicesList) + if(al_string_empty(alcAllDevicesList)) ProbeAllDevicesList(); Device = VerifyDevice(Device); free(alcDefaultAllDevicesSpecifier); - alcDefaultAllDevicesSpecifier = strdup(alcAllDevicesList ? - alcAllDevicesList : ""); + alcDefaultAllDevicesSpecifier = strdup(al_string_get_cstr(alcAllDevicesList)); if(!alcDefaultAllDevicesSpecifier) alcSetError(Device, ALC_OUT_OF_MEMORY); @@ -2381,14 +2417,13 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para break; case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: - if(!alcCaptureDeviceList) + if(al_string_empty(alcCaptureDeviceList)) ProbeCaptureDeviceList(); Device = VerifyDevice(Device); free(alcCaptureDefaultDeviceSpecifier); - alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ? - alcCaptureDeviceList : ""); + alcCaptureDefaultDeviceSpecifier = strdup(al_string_get_cstr(alcAllDevicesList)); if(!alcCaptureDefaultDeviceSpecifier) alcSetError(Device, ALC_OUT_OF_MEMORY); @@ -2417,19 +2452,14 @@ ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum para } -/* alcGetIntegerv - * - * Returns information about the device and the version of OpenAL - */ -ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data) +static ALCsizei GetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) { - device = VerifyDevice(device); + ALCsizei i; - if(size == 0 || data == NULL) + if(size <= 0 || values == NULL) { alcSetError(device, ALC_INVALID_VALUE); - if(device) ALCdevice_DecRef(device); - return; + return 0; } if(!device) @@ -2437,11 +2467,11 @@ ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsi switch(param) { case ALC_MAJOR_VERSION: - *data = alcMajorVersion; - break; + values[0] = alcMajorVersion; + return 1; case ALC_MINOR_VERSION: - *data = alcMinorVersion; - break; + values[0] = alcMinorVersion; + return 1; case ALC_ATTRIBUTES_SIZE: case ALC_ALL_ATTRIBUTES: @@ -2454,153 +2484,269 @@ ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsi case ALC_FORMAT_CHANNELS_SOFT: case ALC_FORMAT_TYPE_SOFT: alcSetError(NULL, ALC_INVALID_DEVICE); - break; + return 0; default: alcSetError(NULL, ALC_INVALID_ENUM); - break; + return 0; } + return 0; } - else if(device->Type == Capture) + + if(device->Type == Capture) { switch(param) { case ALC_CAPTURE_SAMPLES: ALCdevice_Lock(device); - *data = V0(device->Backend,availableSamples)(); + values[0] = V0(device->Backend,availableSamples)(); ALCdevice_Unlock(device); - break; + return 1; case ALC_CONNECTED: - *data = device->Connected; - break; + values[0] = device->Connected; + return 1; default: alcSetError(device, ALC_INVALID_ENUM); - break; + 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] = 15; + return 1; + + case ALC_ALL_ATTRIBUTES: + if(size < 15) + { + alcSetError(device, ALC_INVALID_VALUE); + return 0; + } + + i = 0; + 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 ? ALC_TRUE : ALC_FALSE); + + 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; + } + values[0] = device->Frequency / device->UpdateSize; + 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 ? ALC_TRUE : ALC_FALSE); + 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) +{ + device = 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; + + device = 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 */ { - switch(param) + switch(pname) { - case ALC_MAJOR_VERSION: - *data = alcMajorVersion; - break; - - case ALC_MINOR_VERSION: - *data = alcMinorVersion; - break; - - case ALC_EFX_MAJOR_VERSION: - *data = alcEFXMajorVersion; - break; - - case ALC_EFX_MINOR_VERSION: - *data = alcEFXMinorVersion; - break; - case ALC_ATTRIBUTES_SIZE: - *data = 15; + *values = 17; break; case ALC_ALL_ATTRIBUTES: - if(size < 15) + if(size < 17) alcSetError(device, ALC_INVALID_VALUE); else { int i = 0; - data[i++] = ALC_FREQUENCY; - data[i++] = device->Frequency; + V0(device->Backend,lock)(); + values[i++] = ALC_FREQUENCY; + values[i++] = device->Frequency; if(device->Type != Loopback) { - data[i++] = ALC_REFRESH; - data[i++] = device->Frequency / device->UpdateSize; + values[i++] = ALC_REFRESH; + values[i++] = device->Frequency / device->UpdateSize; - data[i++] = ALC_SYNC; - data[i++] = ALC_FALSE; + values[i++] = ALC_SYNC; + values[i++] = ALC_FALSE; } else { - data[i++] = ALC_FORMAT_CHANNELS_SOFT; - data[i++] = device->FmtChans; + values[i++] = ALC_FORMAT_CHANNELS_SOFT; + values[i++] = device->FmtChans; - data[i++] = ALC_FORMAT_TYPE_SOFT; - data[i++] = device->FmtType; + values[i++] = ALC_FORMAT_TYPE_SOFT; + values[i++] = device->FmtType; } - data[i++] = ALC_MONO_SOURCES; - data[i++] = device->NumMonoSources; + values[i++] = ALC_MONO_SOURCES; + values[i++] = device->NumMonoSources; - data[i++] = ALC_STEREO_SOURCES; - data[i++] = device->NumStereoSources; + values[i++] = ALC_STEREO_SOURCES; + values[i++] = device->NumStereoSources; - data[i++] = ALC_MAX_AUXILIARY_SENDS; - data[i++] = device->NumAuxSends; + values[i++] = ALC_MAX_AUXILIARY_SENDS; + values[i++] = device->NumAuxSends; - data[i++] = ALC_HRTF_SOFT; - data[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE); + values[i++] = ALC_HRTF_SOFT; + values[i++] = (device->Hrtf ? ALC_TRUE : ALC_FALSE); - data[i++] = 0; + values[i++] = ALC_DEVICE_CLOCK_SOFT; + values[i++] = device->ClockBase + + (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency); + + values[i++] = 0; + V0(device->Backend,unlock)(); } break; - case ALC_FREQUENCY: - *data = device->Frequency; - break; - - case ALC_REFRESH: - if(device->Type == Loopback) - alcSetError(device, ALC_INVALID_DEVICE); - else - *data = device->Frequency / device->UpdateSize; - break; - - case ALC_SYNC: - if(device->Type == Loopback) - alcSetError(device, ALC_INVALID_DEVICE); - else - *data = ALC_FALSE; - break; - - case ALC_FORMAT_CHANNELS_SOFT: - if(device->Type != Loopback) - alcSetError(device, ALC_INVALID_DEVICE); - else - *data = device->FmtChans; - break; - - case ALC_FORMAT_TYPE_SOFT: - if(device->Type != Loopback) - alcSetError(device, ALC_INVALID_DEVICE); - else - *data = device->FmtType; - break; - - case ALC_MONO_SOURCES: - *data = device->NumMonoSources; - break; - - case ALC_STEREO_SOURCES: - *data = device->NumStereoSources; - break; - - case ALC_MAX_AUXILIARY_SENDS: - *data = device->NumAuxSends; - break; - - case ALC_CONNECTED: - *data = device->Connected; - break; - - case ALC_HRTF_SOFT: - *data = (device->Hrtf ? ALC_TRUE : ALC_FALSE); + case ALC_DEVICE_CLOCK_SOFT: + V0(device->Backend,lock)(); + *values = device->ClockBase + + (device->SamplesDone * DEVICE_CLOCK_RES / device->Frequency); + V0(device->Backend,unlock)(); break; default: - alcSetError(device, ALC_INVALID_ENUM); + ivals = malloc(size * sizeof(ALCint)); + size = GetIntegerv(device, pname, size, ivals); + for(i = 0;i < size;i++) + values[i] = ivals[i]; + free(ivals); break; } } @@ -2717,7 +2863,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin return NULL; } - device->LastError = ALC_NO_ERROR; + ATOMIC_STORE(&device->LastError, ALC_NO_ERROR); if((err=UpdateDeviceParams(device, attrList)) != ALC_NO_ERROR) { @@ -2733,27 +2879,37 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin return NULL; } - ALContext = calloc(1, sizeof(ALCcontext)+15+sizeof(ALlistener)); + ALContext = calloc(1, sizeof(ALCcontext)+sizeof(ALlistener)); if(ALContext) { - ALContext->ref = 1; - ALContext->Listener = (ALlistener*)(((ALintptrEXT)(ALContext+1)+15)&~15); + InitRef(&ALContext->ref, 1); + ALContext->Listener = (ALlistener*)ALContext->_listener_mem; + + VECTOR_INIT(ALContext->ActiveAuxSlots); ALContext->MaxActiveSources = 256; - ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) * - ALContext->MaxActiveSources); + ALContext->ActiveSources = calloc(ALContext->MaxActiveSources, + sizeof(ALContext->ActiveSources[0])); } if(!ALContext || !ALContext->ActiveSources) { - if(!device->ContextList) + if(!ATOMIC_LOAD(&device->ContextList)) { V0(device->Backend,stop)(); device->Flags &= ~DEVICE_RUNNING; } UnlockLists(); - free(ALContext); - ALContext = NULL; + if(ALContext) + { + free(ALContext->ActiveSources); + ALContext->ActiveSources = NULL; + + VECTOR_DEINIT(ALContext->ActiveAuxSlots); + + free(ALContext); + ALContext = NULL; + } alcSetError(device, ALC_OUT_OF_MEMORY); ALCdevice_DecRef(device); @@ -2764,9 +2920,12 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin ALCdevice_IncRef(device); InitContext(ALContext); - do { - ALContext->next = device->ContextList; - } while(!CompExchangePtr((XchgPtr*)&device->ContextList, ALContext->next, ALContext)); + { + ALCcontext *head = ATOMIC_LOAD(&device->ContextList); + do { + ALContext->next = head; + } while(!ATOMIC_COMPARE_EXCHANGE_WEAK(ALCcontext*, &device->ContextList, &head, ALContext)); + } UnlockLists(); ALCdevice_DecRef(device); @@ -2789,7 +2948,7 @@ ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context) if(Device) { ReleaseContext(context, Device); - if(!Device->ContextList) + if(!ATOMIC_LOAD(&Device->ContextList)) { V0(Device->Backend,stop)(); Device->Flags &= ~DEVICE_RUNNING; @@ -2805,11 +2964,8 @@ ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context) */ ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) { - ALCcontext *Context; - - Context = althread_getspecific(LocalContext); - if(!Context) Context = GlobalContext; - + ALCcontext *Context = altss_get(LocalContext); + if(!Context) Context = ATOMIC_LOAD(&GlobalContext); return Context; } @@ -2819,9 +2975,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) */ ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) { - ALCcontext *Context; - Context = althread_getspecific(LocalContext); - return Context; + return altss_get(LocalContext); } @@ -2839,12 +2993,12 @@ ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) return ALC_FALSE; } /* context's reference count is already incremented */ - context = ExchangePtr((XchgPtr*)&GlobalContext, context); + context = ATOMIC_EXCHANGE(ALCcontext*, &GlobalContext, context); if(context) ALCcontext_DecRef(context); - if((context=althread_getspecific(LocalContext)) != NULL) + if((context=altss_get(LocalContext)) != NULL) { - althread_setspecific(LocalContext, NULL); + altss_set(LocalContext, NULL); ALCcontext_DecRef(context); } @@ -2866,8 +3020,8 @@ ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) return ALC_FALSE; } /* context's reference count is already incremented */ - old = althread_getspecific(LocalContext); - althread_setspecific(LocalContext, context); + old = altss_get(LocalContext); + altss_set(LocalContext, context); if(old) ALCcontext_DecRef(old); return ALC_TRUE; @@ -2915,7 +3069,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) if(deviceName && (!deviceName[0] || strcasecmp(deviceName, alcDefaultName) == 0 || strcasecmp(deviceName, "openal-soft") == 0)) deviceName = NULL; - device = al_calloc(16, sizeof(ALCdevice)+15+sizeof(ALeffectslot)); + device = al_calloc(16, sizeof(ALCdevice)+sizeof(ALeffectslot)); if(!device) { alcSetError(NULL, ALC_OUT_OF_MEMORY); @@ -2923,17 +3077,20 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) } //Validate device - device->ref = 1; + InitRef(&device->ref, 1); device->Connected = ALC_TRUE; device->Type = Playback; - device->LastError = ALC_NO_ERROR; + ATOMIC_INIT(&device->LastError, ALC_NO_ERROR); device->Flags = 0; device->Bs2b = NULL; device->Bs2bLevel = 0; - device->DeviceName = NULL; + AL_STRING_INIT(device->DeviceName); - device->ContextList = NULL; + ATOMIC_INIT(&device->ContextList, NULL); + + device->ClockBase = 0; + device->SamplesDone = 0; device->MaxNoOfSources = 256; device->AuxiliaryEffectSlotMax = 4; @@ -2954,10 +3111,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) device->UpdateSize = 1024; if(!PlaybackBackend.getFactory) - { - device->Funcs = &PlaybackBackend.Funcs; - device->Backend = create_backend_wrapper(device, ALCbackend_Playback); - } + device->Backend = create_backend_wrapper(device, &PlaybackBackend.Funcs, + ALCbackend_Playback); else { ALCbackendFactory *factory = PlaybackBackend.getFactory(); @@ -3127,7 +3282,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) if(DefaultEffect.type != AL_EFFECT_NULL) { - device->DefaultSlot = (ALeffectslot*)(((ALintptrEXT)(device+1)+15)&~15); + device->DefaultSlot = (ALeffectslot*)device->_slot_mem; if(InitEffectSlot(device->DefaultSlot) != AL_NO_ERROR) { device->DefaultSlot = NULL; @@ -3142,11 +3297,14 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) } } - do { - device->next = DeviceList; - } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device)); + { + 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, device->DeviceName); + TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName)); return device; } @@ -3154,36 +3312,48 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) * * Closes the given device. */ -ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *Device) +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) { - ALCdevice *volatile*list; + ALCdevice *list, *origdev, *nextdev; ALCcontext *ctx; LockLists(); - list = &DeviceList; - while(*list && *list != Device) - list = &(*list)->next; - - if(!*list || (*list)->Type == Capture) + list = ATOMIC_LOAD(&DeviceList); + do { + if(list == device) + break; + } while((list=list->next) != NULL); + if(!list || list->Type == Capture) { - alcSetError(*list, ALC_INVALID_DEVICE); + alcSetError(list, ALC_INVALID_DEVICE); UnlockLists(); return ALC_FALSE; } - *list = (*list)->next; + 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(); - while((ctx=Device->ContextList) != NULL) + ctx = ATOMIC_LOAD(&device->ContextList); + while(ctx != NULL) { + ALCcontext *next = ctx->next; WARN("Releasing context %p\n", ctx); - ReleaseContext(ctx, Device); + ReleaseContext(ctx, device); + ctx = next; } - if((Device->Flags&DEVICE_RUNNING)) - V0(Device->Backend,stop)(); - Device->Flags &= ~DEVICE_RUNNING; + if((device->Flags&DEVICE_RUNNING)) + V0(device->Backend,stop)(); + device->Flags &= ~DEVICE_RUNNING; - ALCdevice_DecRef(Device); + ALCdevice_DecRef(device); return ALC_TRUE; } @@ -3222,10 +3392,12 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, } //Validate device - device->ref = 1; + InitRef(&device->ref, 1); device->Connected = ALC_TRUE; device->Type = Capture; + AL_STRING_INIT(device->DeviceName); + InitUIntMap(&device->BufferMap, ~0); InitUIntMap(&device->EffectMap, ~0); InitUIntMap(&device->FilterMap, ~0); @@ -3233,13 +3405,9 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, InitUIntMap(&device->PresetMap, ~0); InitUIntMap(&device->FontsoundMap, ~0); - device->DeviceName = NULL; - if(!CaptureBackend.getFactory) - { - device->Funcs = &CaptureBackend.Funcs; - device->Backend = create_backend_wrapper(device, ALCbackend_Capture); - } + device->Backend = create_backend_wrapper(device, &CaptureBackend.Funcs, + ALCbackend_Capture); else { ALCbackendFactory *factory = CaptureBackend.getFactory(); @@ -3273,34 +3441,46 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, return NULL; } - do { - device->next = DeviceList; - } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device)); + { + 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, device->DeviceName); + TRACE("Created device %p, \"%s\"\n", device, al_string_get_cstr(device->DeviceName)); return device; } -ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *Device) +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) { - ALCdevice *volatile*list; + ALCdevice *list, *next, *nextdev; LockLists(); - list = &DeviceList; - while(*list && *list != Device) - list = &(*list)->next; - - if(!*list || (*list)->Type != Capture) + list = ATOMIC_LOAD(&DeviceList); + do { + if(list == device) + break; + } while((list=list->next) != NULL); + if(!list || list->Type != Capture) { - alcSetError(*list, ALC_INVALID_DEVICE); + alcSetError(list, ALC_INVALID_DEVICE); UnlockLists(); return ALC_FALSE; } - *list = (*list)->next; + 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); + ALCdevice_DecRef(device); return ALC_TRUE; } @@ -3390,17 +3570,20 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN } //Validate device - device->ref = 1; + InitRef(&device->ref, 1); device->Connected = ALC_TRUE; device->Type = Loopback; - device->LastError = ALC_NO_ERROR; + ATOMIC_INIT(&device->LastError, ALC_NO_ERROR); device->Flags = 0; device->Bs2b = NULL; device->Bs2bLevel = 0; - device->DeviceName = NULL; + AL_STRING_INIT(device->DeviceName); - device->ContextList = NULL; + ATOMIC_INIT(&device->ContextList, NULL); + + device->ClockBase = 0; + device->SamplesDone = 0; device->MaxNoOfSources = 256; device->AuxiliaryEffectSlotMax = 4; @@ -3453,9 +3636,13 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN // Open the "backend" V(device->Backend,open)("Loopback"); - do { - device->next = DeviceList; - } while(!CompExchangePtr((XchgPtr*)&DeviceList, device->next, device)); + + { + 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; @@ -3539,17 +3726,18 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) LockLists(); if((device->Flags&DEVICE_PAUSED)) { - if(V0(device->Backend,start)() != ALC_FALSE) + device->Flags &= ~DEVICE_PAUSED; + if(ATOMIC_LOAD(&device->ContextList) != NULL) { - device->Flags |= DEVICE_RUNNING; - device->Flags &= ~DEVICE_PAUSED; - } - else - { - alcSetError(device, ALC_INVALID_DEVICE); - ALCdevice_Lock(device); - aluHandleDisconnect(device); - ALCdevice_Unlock(device); + if(V0(device->Backend,start)() != ALC_FALSE) + device->Flags |= DEVICE_RUNNING; + else + { + alcSetError(device, ALC_INVALID_DEVICE); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); + } } } UnlockLists(); diff --git a/jni/openal-soft-android/Alc/ALu.c b/jni/openal-soft-1.16.0/Alc/ALu.c similarity index 65% rename from jni/openal-soft-android/Alc/ALu.c rename to jni/openal-soft-1.16.0/Alc/ALu.c index bf09450f..a85e1aa0 100644 --- a/jni/openal-soft-android/Alc/ALu.c +++ b/jni/openal-soft-1.16.0/Alc/ALu.c @@ -33,12 +33,15 @@ #include "alAuxEffectSlot.h" #include "alu.h" #include "bs2b.h" - -#include "mixer_defs.h" +#include "hrtf.h" +#include "static_assert.h" #include "midi/base.h" +static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE, + "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!"); + struct ChanMap { enum Channel channel; ALfloat angle; @@ -77,69 +80,6 @@ extern inline ALuint64 clampu64(ALuint64 val, ALuint64 min, ALuint64 max); extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu); extern inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat mu); -static ResamplerFunc SelectResampler(enum Resampler Resampler, ALuint increment) -{ - if(increment == FRACTIONONE) - return Resample_copy32_C; - switch(Resampler) - { - case PointResampler: - return Resample_point32_C; - case LinearResampler: - return Resample_lerp32_C; - case CubicResampler: - return Resample_cubic32_C; - case ResamplerMax: - /* Shouldn't happen */ - break; - } - - return Resample_point32_C; -} - - -static DryMixerFunc SelectHrtfMixer(void) -{ -#ifdef HAVE_SSE - if((CPUCapFlags&CPU_CAP_SSE)) - return MixDirect_Hrtf_SSE; -#endif -#ifdef HAVE_NEON - if((CPUCapFlags&CPU_CAP_NEON)) - return MixDirect_Hrtf_Neon; -#endif - - return MixDirect_Hrtf_C; -} - -static DryMixerFunc SelectDirectMixer(void) -{ -#ifdef HAVE_SSE - if((CPUCapFlags&CPU_CAP_SSE)) - return MixDirect_SSE; -#endif -#ifdef HAVE_NEON - if((CPUCapFlags&CPU_CAP_NEON)) - return MixDirect_Neon; -#endif - - return MixDirect_C; -} - -static WetMixerFunc SelectSendMixer(void) -{ -#ifdef HAVE_SSE - if((CPUCapFlags&CPU_CAP_SSE)) - return MixSend_SSE; -#endif -#ifdef HAVE_NEON - if((CPUCapFlags&CPU_CAP_NEON)) - return MixSend_Neon; -#endif - - return MixSend_C; -} - static inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector) { @@ -226,7 +166,7 @@ static ALvoid CalcListenerParams(ALlistener *Listener) aluMatrixVector(Listener->Params.Velocity, 0.0f, Listener->Params.Matrix); } -ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) +ALvoid CalcNonAttnSourceParams(ALactivesource *src, const ALCcontext *ALContext) { static const struct ChanMap MonoMap[1] = { { FrontCenter, 0.0f } }; static const struct ChanMap StereoMap[2] = { @@ -276,21 +216,21 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) }; ALCdevice *Device = ALContext->Device; + const ALsource *ALSource = src->Source; ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume; ALbufferlistitem *BufferListItem; enum FmtChannels Channels; - ALfloat (*SrcMatrix)[MaxChannels]; - ALfloat DryGain, DryGainHF; + ALfloat DryGain, DryGainHF, DryGainLF; ALfloat WetGain[MAX_SENDS]; ALfloat WetGainHF[MAX_SENDS]; + ALfloat WetGainLF[MAX_SENDS]; ALint NumSends, Frequency; const struct ChanMap *chans = NULL; - enum Resampler Resampler; ALint num_channels = 0; ALboolean DirectChannels; ALfloat hwidth = 0.0f; ALfloat Pitch; - ALint i, c; + ALint i, j, c; /* Get device properties */ NumSends = Device->NumAuxSends; @@ -304,56 +244,57 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) MinVolume = ALSource->MinGain; MaxVolume = ALSource->MaxGain; Pitch = ALSource->Pitch; - Resampler = ALSource->Resampler; DirectChannels = ALSource->DirectChannels; + src->Direct.OutBuffer = Device->DryBuffer; + for(i = 0;i < NumSends;i++) + { + ALeffectslot *Slot = ALSource->Send[i].Slot; + if(!Slot && i == 0) + Slot = Device->DefaultSlot; + if(!Slot || Slot->EffectType == AL_EFFECT_NULL) + src->Send[i].OutBuffer = NULL; + else + src->Send[i].OutBuffer = Slot->WetBuffer; + } + /* Calculate the stepping value */ Channels = FmtMono; - BufferListItem = ALSource->queue; + BufferListItem = ATOMIC_LOAD(&ALSource->queue); while(BufferListItem != NULL) { ALbuffer *ALBuffer; if((ALBuffer=BufferListItem->buffer) != NULL) { Pitch = Pitch * ALBuffer->Frequency / Frequency; - if(Pitch > 10.0f) - ALSource->Params.Step = 10< (ALfloat)MAX_PITCH) + src->Step = MAX_PITCH<Params.Step = fastf2i(Pitch*FRACTIONONE); - if(ALSource->Params.Step == 0) - ALSource->Params.Step = 1; + src->Step = fastf2i(Pitch*FRACTIONONE); + if(src->Step == 0) + src->Step = 1; } - ALSource->Params.Resample = SelectResampler(Resampler, ALSource->Params.Step); Channels = ALBuffer->FmtChannels; break; } BufferListItem = BufferListItem->next; } - if(!DirectChannels && Device->Hrtf) - ALSource->Params.DryMix = SelectHrtfMixer(); - else - ALSource->Params.DryMix = SelectDirectMixer(); - ALSource->Params.WetMix = SelectSendMixer(); /* Calculate gains */ DryGain = clampf(SourceVolume, MinVolume, MaxVolume); - DryGain *= ALSource->DirectGain * ListenerGain; - DryGainHF = ALSource->DirectGainHF; + DryGain *= ALSource->Direct.Gain * ListenerGain; + DryGainHF = ALSource->Direct.GainHF; + DryGainLF = ALSource->Direct.GainLF; for(i = 0;i < NumSends;i++) { - WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume); - WetGain[i] *= ALSource->Send[i].Gain * ListenerGain; + WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume); + WetGain[i] *= ALSource->Send[i].Gain * ListenerGain; WetGainHF[i] = ALSource->Send[i].GainHF; + WetGainLF[i] = ALSource->Send[i].GainLF; } - SrcMatrix = ALSource->Params.Direct.Gains; - for(i = 0;i < MAX_INPUT_CHANNELS;i++) - { - for(c = 0;c < MaxChannels;c++) - SrcMatrix[i][c] = 0.0f; - } switch(Channels) { case FmtMono: @@ -410,16 +351,59 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) { for(c = 0;c < num_channels;c++) { + MixGains *gains = src->Direct.Mix.Gains[c]; + for(j = 0;j < MaxChannels;j++) + gains[j].Target = 0.0f; + } + + for(c = 0;c < num_channels;c++) + { + MixGains *gains = src->Direct.Mix.Gains[c]; for(i = 0;i < (ALint)Device->NumChan;i++) { enum Channel chan = Device->Speaker2Chan[i]; if(chan == chans[c].channel) { - SrcMatrix[c][chan] = DryGain; + gains[chan].Target = DryGain; break; } } } + + if(!src->Direct.Moving) + { + for(i = 0;i < num_channels;i++) + { + MixGains *gains = src->Direct.Mix.Gains[i]; + for(j = 0;j < MaxChannels;j++) + { + gains[j].Current = gains[j].Target; + gains[j].Step = 1.0f; + } + } + src->Direct.Counter = 0; + src->Direct.Moving = AL_TRUE; + } + else + { + for(i = 0;i < num_channels;i++) + { + MixGains *gains = src->Direct.Mix.Gains[i]; + for(j = 0;j < MaxChannels;j++) + { + ALfloat cur = maxf(gains[j].Current, FLT_EPSILON); + ALfloat trg = maxf(gains[j].Target, FLT_EPSILON); + if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD) + gains[j].Step = powf(trg/cur, 1.0f/64.0f); + else + gains[j].Step = 1.0f; + gains[j].Current = cur; + } + } + src->Direct.Counter = 64; + } + + src->IsHrtf = AL_FALSE; } else if(Device->Hrtf) { @@ -428,12 +412,12 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) if(chans[c].channel == LFE) { /* Skip LFE */ - ALSource->Params.Direct.Hrtf.Params.Delay[c][0] = 0; - ALSource->Params.Direct.Hrtf.Params.Delay[c][1] = 0; + src->Direct.Mix.Hrtf.Params[c].Delay[0] = 0; + src->Direct.Mix.Hrtf.Params[c].Delay[1] = 0; for(i = 0;i < HRIR_LENGTH;i++) { - ALSource->Params.Direct.Hrtf.Params.Coeffs[c][i][0] = 0.0f; - ALSource->Params.Direct.Hrtf.Params.Coeffs[c][i][1] = 0.0f; + src->Direct.Mix.Hrtf.Params[c].Coeffs[i][0] = 0.0f; + src->Direct.Mix.Hrtf.Params[c].Coeffs[i][1] = 0.0f; } } else @@ -441,75 +425,148 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) /* Get the static HRIR coefficients and delays for this * channel. */ GetLerpedHrtfCoeffs(Device->Hrtf, - 0.0f, chans[c].angle, DryGain, - ALSource->Params.Direct.Hrtf.Params.Coeffs[c], - ALSource->Params.Direct.Hrtf.Params.Delay[c]); + 0.0f, chans[c].angle, 1.0f, DryGain, + src->Direct.Mix.Hrtf.Params[c].Coeffs, + src->Direct.Mix.Hrtf.Params[c].Delay); } } - ALSource->Hrtf.Counter = 0; - ALSource->Params.Direct.Hrtf.Params.IrSize = GetHrtfIrSize(Device->Hrtf); + src->Direct.Counter = 0; + src->Direct.Moving = AL_TRUE; + src->Direct.Mix.Hrtf.IrSize = GetHrtfIrSize(Device->Hrtf); - ALSource->Params.Direct.Hrtf.State = &ALSource->Hrtf; + src->IsHrtf = AL_TRUE; } else { + for(i = 0;i < num_channels;i++) + { + MixGains *gains = src->Direct.Mix.Gains[i]; + for(j = 0;j < MaxChannels;j++) + gains[j].Target = 0.0f; + } + DryGain *= lerp(1.0f, 1.0f/sqrtf((float)Device->NumChan), hwidth/F_PI); for(c = 0;c < num_channels;c++) { + MixGains *gains = src->Direct.Mix.Gains[c]; + ALfloat Target[MaxChannels]; + /* Special-case LFE */ if(chans[c].channel == LFE) { - SrcMatrix[c][chans[c].channel] = DryGain; + gains[chans[c].channel].Target = DryGain; continue; } - ComputeAngleGains(Device, chans[c].angle, hwidth, DryGain, - SrcMatrix[c]); + ComputeAngleGains(Device, chans[c].angle, hwidth, DryGain, Target); + for(i = 0;i < MaxChannels;i++) + gains[i].Target = Target[i]; } - } - ALSource->Params.Direct.OutBuffer = Device->DryBuffer; - ALSource->Params.Direct.ClickRemoval = Device->ClickRemoval; - ALSource->Params.Direct.PendingClicks = Device->PendingClicks; - for(i = 0;i < NumSends;i++) - { - ALeffectslot *Slot = ALSource->Send[i].Slot; - if(!Slot && i == 0) - Slot = Device->DefaultSlot; - if(!Slot || Slot->EffectType == AL_EFFECT_NULL) + if(!src->Direct.Moving) { - ALSource->Params.Send[i].OutBuffer = NULL; - ALSource->Params.Send[i].ClickRemoval = NULL; - ALSource->Params.Send[i].PendingClicks = NULL; + for(i = 0;i < num_channels;i++) + { + MixGains *gains = src->Direct.Mix.Gains[i]; + for(j = 0;j < MaxChannels;j++) + { + gains[j].Current = gains[j].Target; + gains[j].Step = 1.0f; + } + } + src->Direct.Counter = 0; + src->Direct.Moving = AL_TRUE; } else { - ALSource->Params.Send[i].OutBuffer = Slot->WetBuffer; - ALSource->Params.Send[i].ClickRemoval = Slot->ClickRemoval; - ALSource->Params.Send[i].PendingClicks = Slot->PendingClicks; + for(i = 0;i < num_channels;i++) + { + MixGains *gains = src->Direct.Mix.Gains[i]; + for(j = 0;j < MaxChannels;j++) + { + ALfloat trg = maxf(gains[j].Target, FLT_EPSILON); + ALfloat cur = maxf(gains[j].Current, FLT_EPSILON); + if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD) + gains[j].Step = powf(trg/cur, 1.0f/64.0f); + else + gains[j].Step = 1.0f; + gains[j].Current = cur; + } + } + src->Direct.Counter = 64; } - ALSource->Params.Send[i].Gain = WetGain[i]; - } - { - ALfloat gain = maxf(0.01f, DryGainHF); - for(c = 0;c < num_channels;c++) - ALfilterState_setParams(&ALSource->Params.Direct.LpFilter[c], - ALfilterType_HighShelf, gain, - (ALfloat)LOWPASSFREQREF/Frequency, 0.0f); + src->IsHrtf = AL_FALSE; } for(i = 0;i < NumSends;i++) { - ALfloat gain = maxf(0.01f, WetGainHF[i]); + src->Send[i].Gain.Target = WetGain[i]; + if(!src->Send[i].Moving) + { + src->Send[i].Gain.Current = src->Send[i].Gain.Target; + src->Send[i].Gain.Step = 1.0f; + src->Send[i].Counter = 0; + src->Send[i].Moving = AL_TRUE; + } + else + { + ALfloat cur = maxf(src->Send[i].Gain.Current, FLT_EPSILON); + ALfloat trg = maxf(src->Send[i].Gain.Target, FLT_EPSILON); + if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD) + src->Send[i].Gain.Step = powf(trg/cur, 1.0f/64.0f); + else + src->Send[i].Gain.Step = 1.0f; + src->Send[i].Gain.Current = cur; + src->Send[i].Counter = 64; + } + } + + { + ALfloat gainhf = maxf(0.01f, DryGainHF); + ALfloat gainlf = maxf(0.01f, DryGainLF); + ALfloat hfscale = ALSource->Direct.HFReference / Frequency; + ALfloat lfscale = ALSource->Direct.LFReference / Frequency; for(c = 0;c < num_channels;c++) - ALfilterState_setParams(&ALSource->Params.Send[i].LpFilter[c], - ALfilterType_HighShelf, gain, - (ALfloat)LOWPASSFREQREF/Frequency, 0.0f); + { + src->Direct.Filters[c].ActiveType = AF_None; + if(gainhf != 1.0f) src->Direct.Filters[c].ActiveType |= AF_LowPass; + if(gainlf != 1.0f) src->Direct.Filters[c].ActiveType |= AF_HighPass; + ALfilterState_setParams( + &src->Direct.Filters[c].LowPass, ALfilterType_HighShelf, gainhf, + hfscale, 0.0f + ); + ALfilterState_setParams( + &src->Direct.Filters[c].HighPass, ALfilterType_LowShelf, gainlf, + lfscale, 0.0f + ); + } + } + for(i = 0;i < NumSends;i++) + { + ALfloat gainhf = maxf(0.01f, WetGainHF[i]); + ALfloat gainlf = maxf(0.01f, WetGainLF[i]); + ALfloat hfscale = ALSource->Send[i].HFReference / Frequency; + ALfloat lfscale = ALSource->Send[i].LFReference / Frequency; + for(c = 0;c < num_channels;c++) + { + src->Send[i].Filters[c].ActiveType = AF_None; + if(gainhf != 1.0f) src->Send[i].Filters[c].ActiveType |= AF_LowPass; + if(gainlf != 1.0f) src->Send[i].Filters[c].ActiveType |= AF_HighPass; + ALfilterState_setParams( + &src->Send[i].Filters[c].LowPass, ALfilterType_HighShelf, gainhf, + hfscale, 0.0f + ); + ALfilterState_setParams( + &src->Send[i].Filters[c].HighPass, ALfilterType_LowShelf, gainlf, + lfscale, 0.0f + ); + } } } -ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) +ALvoid CalcSourceParams(ALactivesource *src, const ALCcontext *ALContext) { ALCdevice *Device = ALContext->Device; + const ALsource *ALSource = src->Source; ALfloat Velocity[3],Direction[3],Position[3],SourceToListener[3]; ALfloat InnerAngle,OuterAngle,Angle,Distance,ClampedDist; ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff; @@ -526,20 +583,25 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) 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; - enum Resampler Resampler; ALfloat Pitch; ALuint Frequency; ALint NumSends; ALint i, j; DryGainHF = 1.0f; + DryGainLF = 1.0f; for(i = 0;i < MAX_SENDS;i++) + { WetGainHF[i] = 1.0f; + WetGainLF[i] = 1.0f; + } /* Get context/device properties */ DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor; @@ -556,7 +618,6 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) MinVolume = ALSource->MinGain; MaxVolume = ALSource->MaxGain; Pitch = ALSource->Pitch; - Resampler = ALSource->Resampler; Position[0] = ALSource->Position[0]; Position[1] = ALSource->Position[1]; Position[2] = ALSource->Position[2]; @@ -577,9 +638,7 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) WetGainHFAuto = ALSource->WetGainHFAuto; RoomRolloffBase = ALSource->RoomRolloffFactor; - ALSource->Params.Direct.OutBuffer = Device->DryBuffer; - ALSource->Params.Direct.ClickRemoval = Device->ClickRemoval; - ALSource->Params.Direct.PendingClicks = Device->PendingClicks; + src->Direct.OutBuffer = Device->DryBuffer; for(i = 0;i < NumSends;i++) { ALeffectslot *Slot = ALSource->Send[i].Slot; @@ -619,17 +678,9 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) } if(!Slot || Slot->EffectType == AL_EFFECT_NULL) - { - ALSource->Params.Send[i].OutBuffer = NULL; - ALSource->Params.Send[i].ClickRemoval = NULL; - ALSource->Params.Send[i].PendingClicks = NULL; - } + src->Send[i].OutBuffer = NULL; else - { - ALSource->Params.Send[i].OutBuffer = Slot->WetBuffer; - ALSource->Params.Send[i].ClickRemoval = Slot->ClickRemoval; - ALSource->Params.Send[i].PendingClicks = Slot->PendingClicks; - } + src->Send[i].OutBuffer = Slot->WetBuffer; } /* Transform source to listener space (convert to head relative) */ @@ -792,12 +843,14 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume); /* Apply gain and frequency filters */ - DryGain *= ALSource->DirectGain * ListenerGain; - DryGainHF *= ALSource->DirectGainHF; + DryGain *= ALSource->Direct.Gain * ListenerGain; + DryGainHF *= ALSource->Direct.GainHF; + DryGainLF *= ALSource->Direct.GainLF; for(i = 0;i < NumSends;i++) { WetGain[i] *= ALSource->Send[i].Gain * ListenerGain; WetGainHF[i] *= ALSource->Send[i].GainHF; + WetGainLF[i] *= ALSource->Send[i].GainLF; } /* Calculate velocity-based doppler effect */ @@ -819,7 +872,7 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) clampf(SpeedOfSound-VSS, 1.0f, SpeedOfSound*2.0f - 1.0f); } - BufferListItem = ALSource->queue; + BufferListItem = ATOMIC_LOAD(&ALSource->queue); while(BufferListItem != NULL) { ALbuffer *ALBuffer; @@ -828,30 +881,26 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) /* Calculate fixed-point stepping value, based on the pitch, buffer * frequency, and output frequency. */ Pitch = Pitch * ALBuffer->Frequency / Frequency; - if(Pitch > 10.0f) - ALSource->Params.Step = 10< (ALfloat)MAX_PITCH) + src->Step = MAX_PITCH<Params.Step = fastf2i(Pitch*FRACTIONONE); - if(ALSource->Params.Step == 0) - ALSource->Params.Step = 1; + src->Step = fastf2i(Pitch*FRACTIONONE); + if(src->Step == 0) + src->Step = 1; } - ALSource->Params.Resample = SelectResampler(Resampler, ALSource->Params.Step); break; } BufferListItem = BufferListItem->next; } - if(Device->Hrtf) - ALSource->Params.DryMix = SelectHrtfMixer(); - else - ALSource->Params.DryMix = SelectDirectMixer(); - ALSource->Params.WetMix = SelectSendMixer(); if(Device->Hrtf) { /* Use a binaural HRTF algorithm for stereo headphone playback */ ALfloat delta, ev = 0.0f, az = 0.0f; + ALfloat radius = ALSource->Radius; + ALfloat dirfact = 1.0f; if(Distance > FLT_EPSILON) { @@ -867,70 +916,72 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) ev = asinf(clampf(Position[1], -1.0f, 1.0f)); az = atan2f(Position[0], -Position[2]*ZScale); } + if(radius > Distance) + dirfact *= Distance / radius; /* Check to see if the HRIR is already moving. */ - if(ALSource->Hrtf.Moving) + if(src->Direct.Moving) { /* Calculate the normalized HRTF transition factor (delta). */ - delta = CalcHrtfDelta(ALSource->Params.Direct.Hrtf.Params.Gain, DryGain, - ALSource->Params.Direct.Hrtf.Params.Dir, Position); + delta = CalcHrtfDelta(src->Direct.Mix.Hrtf.Gain, DryGain, + src->Direct.Mix.Hrtf.Dir, Position); /* If the delta is large enough, get the moving HRIR target * coefficients, target delays, steppping values, and counter. */ if(delta > 0.001f) { - ALSource->Hrtf.Counter = GetMovingHrtfCoeffs(Device->Hrtf, - ev, az, DryGain, delta, - ALSource->Hrtf.Counter, - ALSource->Params.Direct.Hrtf.Params.Coeffs[0], - ALSource->Params.Direct.Hrtf.Params.Delay[0], - ALSource->Params.Direct.Hrtf.Params.CoeffStep, - ALSource->Params.Direct.Hrtf.Params.DelayStep); - ALSource->Params.Direct.Hrtf.Params.Gain = DryGain; - ALSource->Params.Direct.Hrtf.Params.Dir[0] = Position[0]; - ALSource->Params.Direct.Hrtf.Params.Dir[1] = Position[1]; - ALSource->Params.Direct.Hrtf.Params.Dir[2] = Position[2]; + ALuint counter = GetMovingHrtfCoeffs(Device->Hrtf, + ev, az, dirfact, DryGain, delta, src->Direct.Counter, + src->Direct.Mix.Hrtf.Params[0].Coeffs, src->Direct.Mix.Hrtf.Params[0].Delay, + src->Direct.Mix.Hrtf.Params[0].CoeffStep, src->Direct.Mix.Hrtf.Params[0].DelayStep + ); + src->Direct.Counter = counter; + src->Direct.Mix.Hrtf.Gain = DryGain; + src->Direct.Mix.Hrtf.Dir[0] = Position[0]; + src->Direct.Mix.Hrtf.Dir[1] = Position[1]; + src->Direct.Mix.Hrtf.Dir[2] = Position[2]; } } else { /* Get the initial (static) HRIR coefficients and delays. */ - GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, DryGain, - ALSource->Params.Direct.Hrtf.Params.Coeffs[0], - ALSource->Params.Direct.Hrtf.Params.Delay[0]); - ALSource->Hrtf.Counter = 0; - ALSource->Hrtf.Moving = AL_TRUE; - ALSource->Params.Direct.Hrtf.Params.Gain = DryGain; - ALSource->Params.Direct.Hrtf.Params.Dir[0] = Position[0]; - ALSource->Params.Direct.Hrtf.Params.Dir[1] = Position[1]; - ALSource->Params.Direct.Hrtf.Params.Dir[2] = Position[2]; + GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, dirfact, DryGain, + src->Direct.Mix.Hrtf.Params[0].Coeffs, + src->Direct.Mix.Hrtf.Params[0].Delay); + src->Direct.Counter = 0; + src->Direct.Moving = AL_TRUE; + src->Direct.Mix.Hrtf.Gain = DryGain; + src->Direct.Mix.Hrtf.Dir[0] = Position[0]; + src->Direct.Mix.Hrtf.Dir[1] = Position[1]; + src->Direct.Mix.Hrtf.Dir[2] = Position[2]; } - ALSource->Params.Direct.Hrtf.Params.IrSize = GetHrtfIrSize(Device->Hrtf); + src->Direct.Mix.Hrtf.IrSize = GetHrtfIrSize(Device->Hrtf); - ALSource->Params.Direct.Hrtf.State = &ALSource->Hrtf; + src->IsHrtf = AL_TRUE; } else { - ALfloat (*Matrix)[MaxChannels] = ALSource->Params.Direct.Gains; + MixGains *gains = src->Direct.Mix.Gains[0]; ALfloat DirGain = 0.0f; ALfloat AmbientGain; - for(i = 0;i < MAX_INPUT_CHANNELS;i++) - { - for(j = 0;j < MaxChannels;j++) - Matrix[i][j] = 0.0f; - } + for(j = 0;j < MaxChannels;j++) + gains[j].Target = 0.0f; /* Normalize the length, and compute panned gains. */ if(Distance > FLT_EPSILON) { - ALfloat invlen = 1.0f/Distance; + ALfloat radius = ALSource->Radius; + ALfloat Target[MaxChannels]; + ALfloat invlen = 1.0f/maxf(Distance, radius); Position[0] *= invlen; Position[1] *= invlen; Position[2] *= invlen; DirGain = sqrtf(Position[0]*Position[0] + Position[2]*Position[2]); ComputeAngleGains(Device, atan2f(Position[0], -Position[2]*ZScale), 0.0f, - DryGain*DirGain, Matrix[0]); + DryGain*DirGain, Target); + for(j = 0;j < MaxChannels;j++) + gains[j].Target = Target[j]; } /* Adjustment for vertical offsets. Not the greatest, but simple @@ -939,25 +990,93 @@ ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) for(i = 0;i < (ALint)Device->NumChan;i++) { enum Channel chan = Device->Speaker2Chan[i]; - Matrix[0][chan] = maxf(Matrix[0][chan], AmbientGain); + gains[chan].Target = maxf(gains[chan].Target, AmbientGain); + } + + if(!src->Direct.Moving) + { + for(j = 0;j < MaxChannels;j++) + { + gains[j].Current = gains[j].Target; + gains[j].Step = 1.0f; + } + src->Direct.Counter = 0; + src->Direct.Moving = AL_TRUE; + } + else + { + for(j = 0;j < MaxChannels;j++) + { + ALfloat cur = maxf(gains[j].Current, FLT_EPSILON); + ALfloat trg = maxf(gains[j].Target, FLT_EPSILON); + if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD) + gains[j].Step = powf(trg/cur, 1.0f/64.0f); + else + gains[j].Step = 1.0f; + gains[j].Current = cur; + } + src->Direct.Counter = 64; + } + + src->IsHrtf = AL_FALSE; + } + for(i = 0;i < NumSends;i++) + { + src->Send[i].Gain.Target = WetGain[i]; + if(!src->Send[i].Moving) + { + src->Send[i].Gain.Current = src->Send[i].Gain.Target; + src->Send[i].Gain.Step = 1.0f; + src->Send[i].Counter = 0; + src->Send[i].Moving = AL_TRUE; + } + else + { + ALfloat cur = maxf(src->Send[i].Gain.Current, FLT_EPSILON); + ALfloat trg = maxf(src->Send[i].Gain.Target, FLT_EPSILON); + if(fabs(trg - cur) >= GAIN_SILENCE_THRESHOLD) + src->Send[i].Gain.Step = powf(trg/cur, 1.0f/64.0f); + else + src->Send[i].Gain.Step = 1.0f; + src->Send[i].Gain.Current = cur; + src->Send[i].Counter = 64; } } - for(i = 0;i < NumSends;i++) - ALSource->Params.Send[i].Gain = WetGain[i]; - { - ALfloat gain = maxf(0.01f, DryGainHF); - ALfilterState_setParams(&ALSource->Params.Direct.LpFilter[0], - ALfilterType_HighShelf, gain, - (ALfloat)LOWPASSFREQREF/Frequency, 0.0f); + ALfloat gainhf = maxf(0.01f, DryGainHF); + ALfloat gainlf = maxf(0.01f, DryGainLF); + ALfloat hfscale = ALSource->Direct.HFReference / Frequency; + ALfloat lfscale = ALSource->Direct.LFReference / Frequency; + src->Direct.Filters[0].ActiveType = AF_None; + if(gainhf != 1.0f) src->Direct.Filters[0].ActiveType |= AF_LowPass; + if(gainlf != 1.0f) src->Direct.Filters[0].ActiveType |= AF_HighPass; + ALfilterState_setParams( + &src->Direct.Filters[0].LowPass, ALfilterType_HighShelf, gainhf, + hfscale, 0.0f + ); + ALfilterState_setParams( + &src->Direct.Filters[0].HighPass, ALfilterType_LowShelf, gainlf, + lfscale, 0.0f + ); } for(i = 0;i < NumSends;i++) { - ALfloat gain = maxf(0.01f, WetGainHF[i]); - ALfilterState_setParams(&ALSource->Params.Send[i].LpFilter[0], - ALfilterType_HighShelf, gain, - (ALfloat)LOWPASSFREQREF/Frequency, 0.0f); + ALfloat gainhf = maxf(0.01f, WetGainHF[i]); + ALfloat gainlf = maxf(0.01f, WetGainLF[i]); + ALfloat hfscale = ALSource->Send[i].HFReference / Frequency; + ALfloat lfscale = ALSource->Send[i].LFReference / Frequency; + src->Send[i].Filters[0].ActiveType = AF_None; + if(gainhf != 1.0f) src->Send[i].Filters[0].ActiveType |= AF_LowPass; + if(gainlf != 1.0f) src->Send[i].Filters[0].ActiveType |= AF_HighPass; + ALfilterState_setParams( + &src->Send[i].Filters[0].LowPass, ALfilterType_HighShelf, gainhf, + hfscale, 0.0f + ); + ALfilterState_setParams( + &src->Send[i].Filters[0].HighPass, ALfilterType_LowShelf, gainlf, + lfscale, 0.0f + ); } } @@ -987,11 +1106,10 @@ static inline ALubyte aluF2UB(ALfloat val) { return aluF2B(val)+128; } #define DECL_TEMPLATE(T, func) \ -static int Write_##T(ALCdevice *device, T *restrict buffer, \ - ALuint SamplesToDo) \ +static void Write_##T(ALCdevice *device, ALvoid **buffer, ALuint SamplesToDo) \ { \ ALfloat (*restrict DryBuffer)[BUFFERSIZE] = device->DryBuffer; \ - ALuint numchans = ChannelsFromDevFmt(device->FmtChans); \ + const ALuint numchans = ChannelsFromDevFmt(device->FmtChans); \ const ALuint *offsets = device->ChannelOffsets; \ ALuint i, j; \ \ @@ -1002,11 +1120,11 @@ static int Write_##T(ALCdevice *device, T *restrict buffer, \ if(offsets[j] == INVALID_OFFSET) \ continue; \ \ - out = buffer + offsets[j]; \ + out = (T*)(*buffer) + offsets[j]; \ for(i = 0;i < SamplesToDo;i++) \ out[i*numchans] = func(DryBuffer[j][i]); \ } \ - return SamplesToDo*numchans*sizeof(T); \ + *buffer = (char*)(*buffer) + SamplesToDo*numchans*sizeof(T); \ } DECL_TEMPLATE(ALfloat, aluF2F) @@ -1024,7 +1142,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) { ALuint SamplesToDo; ALeffectslot **slot, **slot_end; - ALsource **src, **src_end; + ALactivesource **src, **src_end; ALCcontext *ctx; FPUCtl oldMode; ALuint i, c; @@ -1033,6 +1151,8 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) while(size > 0) { + IncrementRef(&device->MixCount); + SamplesToDo = minu(size, BUFFERSIZE); for(c = 0;c < MaxChannels;c++) memset(device->DryBuffer[c], 0, SamplesToDo*sizeof(ALfloat)); @@ -1040,14 +1160,14 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) ALCdevice_Lock(device); V(device->Synth,process)(SamplesToDo, device->DryBuffer); - ctx = device->ContextList; + ctx = ATOMIC_LOAD(&device->ContextList); while(ctx) { ALenum DeferUpdates = ctx->DeferUpdates; ALenum UpdateSources = AL_FALSE; if(!DeferUpdates) - UpdateSources = ExchangeInt(&ctx->UpdateSources, AL_FALSE); + UpdateSources = ATOMIC_EXCHANGE(ALenum, &ctx->UpdateSources, AL_FALSE); if(UpdateSources) CalcListenerParams(ctx->Listener); @@ -1057,38 +1177,32 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) src_end = src + ctx->ActiveSourceCount; while(src != src_end) { - if((*src)->state != AL_PLAYING) + ALsource *source = (*src)->Source; + + if(source->state != AL_PLAYING && source->state != AL_PAUSED) { + ALactivesource *temp = *(--src_end); + *src_end = *src; + *src = temp; --(ctx->ActiveSourceCount); - *src = *(--src_end); continue; } - if(!DeferUpdates && (ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) || + if(!DeferUpdates && (ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources)) - ALsource_Update(*src, ctx); + (*src)->Update(*src, ctx); - MixSource(*src, device, SamplesToDo); + if(source->state != AL_PAUSED) + MixSource(*src, device, SamplesToDo); src++; } /* effect slot processing */ - slot = ctx->ActiveEffectSlots; - slot_end = slot + ctx->ActiveEffectSlotCount; + slot = VECTOR_ITER_BEGIN(ctx->ActiveAuxSlots); + slot_end = VECTOR_ITER_END(ctx->ActiveAuxSlots); while(slot != slot_end) { - ALfloat offset = (*slot)->ClickRemoval[0]; - if(offset < (1.0f/32768.0f)) - offset = 0.0f; - else for(i = 0;i < SamplesToDo;i++) - { - (*slot)->WetBuffer[0][i] += offset; - offset -= offset * (1.0f/256.0f); - } - (*slot)->ClickRemoval[0] = offset + (*slot)->PendingClicks[0]; - (*slot)->PendingClicks[0] = 0.0f; - - if(!DeferUpdates && ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE)) + if(!DeferUpdates && ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE)) V((*slot)->EffectState,update)(device, *slot); V((*slot)->EffectState,process)(SamplesToDo, (*slot)->WetBuffer[0], @@ -1106,18 +1220,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) slot = &device->DefaultSlot; if(*slot != NULL) { - ALfloat offset = (*slot)->ClickRemoval[0]; - if(offset < (1.0f/32768.0f)) - offset = 0.0f; - else for(i = 0;i < SamplesToDo;i++) - { - (*slot)->WetBuffer[0][i] += offset; - offset -= offset * (1.0f/256.0f); - } - (*slot)->ClickRemoval[0] = offset + (*slot)->PendingClicks[0]; - (*slot)->PendingClicks[0] = 0.0f; - - if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE)) + if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE)) V((*slot)->EffectState,update)(device, *slot); V((*slot)->EffectState,process)(SamplesToDo, (*slot)->WetBuffer[0], @@ -1126,102 +1229,60 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) for(i = 0;i < SamplesToDo;i++) (*slot)->WetBuffer[0][i] = 0.0f; } + + /* Increment the clock time. Every second's worth of samples is + * converted and added to clock base so that large sample counts don't + * overflow during conversion. This also guarantees an exact, stable + * conversion. */ + device->SamplesDone += SamplesToDo; + device->ClockBase += (device->SamplesDone/device->Frequency) * DEVICE_CLOCK_RES; + device->SamplesDone %= device->Frequency; ALCdevice_Unlock(device); - /* Click-removal. Could do better; this only really handles immediate - * changes between updates where a predictive sample could be - * generated. Delays caused by effects and HRTF aren't caught. */ - if(device->FmtChans == DevFmtMono) + if(device->Bs2b) { - ALfloat offset = device->ClickRemoval[FrontCenter]; - if(offset < (1.0f/32768.0f)) - offset = 0.0f; - else for(i = 0;i < SamplesToDo;i++) - { - device->DryBuffer[FrontCenter][i] += offset; - offset -= offset * (1.0f/256.0f); - } - device->ClickRemoval[FrontCenter] = offset + device->PendingClicks[FrontCenter]; - device->PendingClicks[FrontCenter] = 0.0f; - } - else if(device->FmtChans == DevFmtStereo) - { - /* Assumes the first two channels are FrontLeft and FrontRight */ - for(c = 0;c < 2;c++) - { - ALfloat offset = device->ClickRemoval[c]; - if(offset < (1.0f/32768.0f)) - offset = 0.0f; - else for(i = 0;i < SamplesToDo;i++) - { - device->DryBuffer[c][i] += offset; - offset -= offset * (1.0f/256.0f); - } - device->ClickRemoval[c] = offset + device->PendingClicks[c]; - device->PendingClicks[c] = 0.0f; - } - if(device->Bs2b) + /* Apply binaural/crossfeed filter */ + for(i = 0;i < SamplesToDo;i++) { float samples[2]; - for(i = 0;i < SamplesToDo;i++) - { - samples[0] = device->DryBuffer[FrontLeft][i]; - samples[1] = device->DryBuffer[FrontRight][i]; - bs2b_cross_feed(device->Bs2b, samples); - device->DryBuffer[FrontLeft][i] = samples[0]; - device->DryBuffer[FrontRight][i] = samples[1]; - } - } - } - else - { - for(c = 0;c < MaxChannels;c++) - { - ALfloat offset = device->ClickRemoval[c]; - if(offset < (1.0f/32768.0f)) - offset = 0.0f; - else for(i = 0;i < SamplesToDo;i++) - { - device->DryBuffer[c][i] += offset; - offset -= offset * (1.0f/256.0f); - } - device->ClickRemoval[c] = offset + device->PendingClicks[c]; - device->PendingClicks[c] = 0.0f; + samples[0] = device->DryBuffer[FrontLeft][i]; + samples[1] = device->DryBuffer[FrontRight][i]; + bs2b_cross_feed(device->Bs2b, samples); + device->DryBuffer[FrontLeft][i] = samples[0]; + device->DryBuffer[FrontRight][i] = samples[1]; } } if(buffer) { - int bytes = 0; switch(device->FmtType) { case DevFmtByte: - bytes = Write_ALbyte(device, buffer, SamplesToDo); + Write_ALbyte(device, &buffer, SamplesToDo); break; case DevFmtUByte: - bytes = Write_ALubyte(device, buffer, SamplesToDo); + Write_ALubyte(device, &buffer, SamplesToDo); break; case DevFmtShort: - bytes = Write_ALshort(device, buffer, SamplesToDo); + Write_ALshort(device, &buffer, SamplesToDo); break; case DevFmtUShort: - bytes = Write_ALushort(device, buffer, SamplesToDo); + Write_ALushort(device, &buffer, SamplesToDo); break; case DevFmtInt: - bytes = Write_ALint(device, buffer, SamplesToDo); + Write_ALint(device, &buffer, SamplesToDo); break; case DevFmtUInt: - bytes = Write_ALuint(device, buffer, SamplesToDo); + Write_ALuint(device, &buffer, SamplesToDo); break; case DevFmtFloat: - bytes = Write_ALfloat(device, buffer, SamplesToDo); + Write_ALfloat(device, &buffer, SamplesToDo); break; } - - buffer = (ALubyte*)buffer + bytes; } size -= SamplesToDo; + IncrementRef(&device->MixCount); } RestoreFPUMode(&oldMode); @@ -1234,21 +1295,22 @@ ALvoid aluHandleDisconnect(ALCdevice *device) device->Connected = ALC_FALSE; - Context = device->ContextList; + Context = ATOMIC_LOAD(&device->ContextList); while(Context) { - ALsource **src, **src_end; + ALactivesource **src, **src_end; src = Context->ActiveSources; src_end = src + Context->ActiveSourceCount; while(src != src_end) { - if((*src)->state == AL_PLAYING) + ALsource *source = (*src)->Source; + if(source->state == AL_PLAYING) { - (*src)->state = AL_STOPPED; - (*src)->BuffersPlayed = (*src)->BuffersInQueue; - (*src)->position = 0; - (*src)->position_fraction = 0; + source->state = AL_STOPPED; + ATOMIC_STORE(&source->current_buffer, NULL); + source->position = 0; + source->position_fraction = 0; } src++; } diff --git a/jni/openal-soft-android/Alc/alcConfig.c b/jni/openal-soft-1.16.0/Alc/alcConfig.c similarity index 68% rename from jni/openal-soft-android/Alc/alcConfig.c rename to jni/openal-soft-1.16.0/Alc/alcConfig.c index 98c0df32..2c9aef41 100644 --- a/jni/openal-soft-android/Alc/alcConfig.c +++ b/jni/openal-soft-1.16.0/Alc/alcConfig.c @@ -32,13 +32,14 @@ #include #include #include - -#include "alMain.h" - #ifdef _WIN32_IE #include #endif +#include "alMain.h" +#include "compat.h" + + typedef struct ConfigEntry { char *key; char *value; @@ -48,10 +49,8 @@ typedef struct ConfigBlock { ConfigEntry *entries; unsigned int entryCount; } ConfigBlock; - static ConfigBlock cfgBlock; -static char buffer[1024]; static char *lstrip(char *line) { @@ -69,23 +68,132 @@ static char *rstrip(char *line) return line; } +static int readline(FILE *f, char **output, size_t *maxlen) +{ + size_t len = 0; + int c; + + while((c=fgetc(f)) != EOF && (c == '\r' || c == '\n')) + ; + if(c == EOF) + return 0; + + do { + if(len+1 >= *maxlen) + { + void *temp = NULL; + size_t newmax; + + newmax = (*maxlen ? (*maxlen)<<1 : 32); + if(newmax > *maxlen) + temp = realloc(*output, newmax); + if(!temp) + { + ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, *maxlen); + return 0; + } + + *output = temp; + *maxlen = newmax; + } + (*output)[len++] = c; + (*output)[len] = '\0'; + } while((c=fgetc(f)) != EOF && c != '\r' && c != '\n'); + + return 1; +} + + +static char *expdup(const char *str) +{ + char *output = NULL; + size_t maxlen = 0; + size_t len = 0; + + while(*str != '\0') + { + const char *addstr; + size_t addstrlen; + size_t i; + + if(str[0] != '$') + { + const char *next = strchr(str, '$'); + addstr = str; + addstrlen = next ? (size_t)(next-str) : strlen(str); + + str += addstrlen; + } + else + { + str++; + if(*str == '$') + { + const char *next = strchr(str+1, '$'); + addstr = str; + addstrlen = next ? (size_t)(next-str) : strlen(str); + + str += addstrlen; + } + else + { + char envname[1024]; + size_t k = 0; + + while((isalnum(*str) || *str == '_') && k < sizeof(envname)-1) + envname[k++] = *(str++); + envname[k++] = '\0'; + + if((addstr=getenv(envname)) == NULL) + continue; + addstrlen = strlen(addstr); + } + } + if(addstrlen == 0) + continue; + + if(addstrlen >= maxlen-len) + { + void *temp = NULL; + size_t newmax; + + newmax = len+addstrlen+1; + if(newmax > maxlen) + temp = realloc(output, newmax); + if(!temp) + { + ERR("Failed to realloc "SZFMT" bytes from "SZFMT"!\n", newmax, maxlen); + return output; + } + + output = temp; + maxlen = newmax; + } + + for(i = 0;i < addstrlen;i++) + output[len++] = addstr[i]; + output[len] = '\0'; + } + + return output ? output : calloc(1, 1); +} + + static void LoadConfigFromFile(FILE *f) { char curSection[128] = ""; + char *buffer = NULL; + size_t maxlen = 0; ConfigEntry *ent; - while(fgets(buffer, sizeof(buffer), f)) + while(readline(f, &buffer, &maxlen)) { char *line, *comment; char key[256] = ""; char value[256] = ""; comment = strchr(buffer, '#'); - if(comment) - { - *(comment++) = 0; - comment = rstrip(lstrip(comment)); - } + if(comment) *(comment++) = 0; line = rstrip(lstrip(buffer)); if(!line[0]) @@ -123,26 +231,26 @@ static void LoadConfigFromFile(FILE *f) * manually. */ if(strcmp(value, "\"\"") == 0 || strcmp(value, "''") == 0) value[0] = 0; - } - else if(sscanf(line, "%255[^=] %255[=]", key, value) == 2) - { - /* Special case for 'key =' */ - value[0] = 0; - } - else - { - ERR("config parse error: malformed option line: \"%s\"\n\n", line); - continue; - } - rstrip(key); + } + 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); - } + if(curSection[0] != 0) + { + size_t len = strlen(curSection); + memmove(&key[len+1], key, sizeof(key)-1-len); + key[len] = '/'; + memcpy(key, curSection, len); + } /* Check if we already have this option set */ ent = cfgBlock.entries; @@ -171,36 +279,57 @@ static void LoadConfigFromFile(FILE *f) } free(ent->value); - ent->value = strdup(value); + ent->value = expdup(value); TRACE("found '%s' = '%s'\n", ent->key, ent->value); } + + free(buffer); } +#ifdef _WIN32 void ReadALConfig(void) { - const char *str; + WCHAR buffer[PATH_MAX]; + const WCHAR *str; FILE *f; -#ifdef _WIN32 - if(SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE) + if(SHGetSpecialFolderPathW(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE) { - size_t p = strlen(buffer); - snprintf(buffer+p, sizeof(buffer)-p, "\\alsoft.ini"); + size_t p = lstrlenW(buffer); + _snwprintf(buffer+p, PATH_MAX-p, L"\\alsoft.ini"); - TRACE("Loading config %s...\n", buffer); - f = fopen(buffer, "rt"); + TRACE("Loading config %ls...\n", buffer); + f = _wfopen(buffer, L"rt"); if(f) { LoadConfigFromFile(f); fclose(f); } } + + if((str=_wgetenv(L"ALSOFT_CONF")) != NULL && *str) + { + TRACE("Loading config %ls...\n", str); + f = _wfopen(str, L"rt"); + if(f) + { + LoadConfigFromFile(f); + fclose(f); + } + } +} #else +void ReadALConfig(void) +{ + char buffer[PATH_MAX]; + const char *str; + FILE *f; + str = "/etc/openal/alsoft.conf"; TRACE("Loading config %s...\n", str); - f = fopen(str, "r"); + f = al_fopen(str, "r"); if(f) { LoadConfigFromFile(f); @@ -231,7 +360,7 @@ void ReadALConfig(void) buffer[sizeof(buffer)-1] = 0; TRACE("Loading config %s...\n", next); - f = fopen(next, "r"); + f = al_fopen(next, "r"); if(f) { LoadConfigFromFile(f); @@ -247,7 +376,7 @@ void ReadALConfig(void) snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str); TRACE("Loading config %s...\n", buffer); - f = fopen(buffer, "r"); + f = al_fopen(buffer, "r"); if(f) { LoadConfigFromFile(f); @@ -266,19 +395,18 @@ void ReadALConfig(void) if(buffer[0] != 0) { TRACE("Loading config %s...\n", buffer); - f = fopen(buffer, "r"); + f = al_fopen(buffer, "r"); if(f) { LoadConfigFromFile(f); fclose(f); } } -#endif if((str=getenv("ALSOFT_CONF")) != NULL && *str) { TRACE("Loading config %s...\n", str); - f = fopen(str, "r"); + f = al_fopen(str, "r"); if(f) { LoadConfigFromFile(f); @@ -286,6 +414,7 @@ void ReadALConfig(void) } } } +#endif void FreeALConfig(void) { diff --git a/jni/openal-soft-android/Alc/alcRing.c b/jni/openal-soft-1.16.0/Alc/alcRing.c similarity index 89% rename from jni/openal-soft-android/Alc/alcRing.c rename to jni/openal-soft-1.16.0/Alc/alcRing.c index f831860f..9b5d8214 100644 --- a/jni/openal-soft-android/Alc/alcRing.c +++ b/jni/openal-soft-1.16.0/Alc/alcRing.c @@ -24,6 +24,7 @@ #include #include "alMain.h" +#include "threads.h" #include "compat.h" @@ -35,7 +36,7 @@ struct RingBuffer { ALint read_pos; ALint write_pos; - CRITICAL_SECTION cs; + almtx_t mtx; }; @@ -51,7 +52,7 @@ RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length) ring->read_pos = 0; ring->write_pos = 0; - InitializeCriticalSection(&ring->cs); + almtx_init(&ring->mtx, almtx_plain); } return ring; } @@ -60,7 +61,7 @@ void DestroyRingBuffer(RingBuffer *ring) { if(ring) { - DeleteCriticalSection(&ring->cs); + almtx_destroy(&ring->mtx); free(ring); } } @@ -69,9 +70,9 @@ ALsizei RingBufferSize(RingBuffer *ring) { ALsizei s; - EnterCriticalSection(&ring->cs); + almtx_lock(&ring->mtx); s = (ring->write_pos-ring->read_pos+ring->length) % ring->length; - LeaveCriticalSection(&ring->cs); + almtx_unlock(&ring->mtx); return s; } @@ -80,7 +81,7 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len) { int remain; - EnterCriticalSection(&ring->cs); + almtx_lock(&ring->mtx); remain = (ring->read_pos-ring->write_pos-1+ring->length) % ring->length; if(remain < len) len = remain; @@ -103,14 +104,14 @@ void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len) ring->write_pos %= ring->length; } - LeaveCriticalSection(&ring->cs); + almtx_unlock(&ring->mtx); } void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len) { int remain; - EnterCriticalSection(&ring->cs); + almtx_lock(&ring->mtx); remain = ring->length - ring->read_pos; if(remain < len) @@ -124,5 +125,5 @@ void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len) ring->read_pos += len; ring->read_pos %= ring->length; - LeaveCriticalSection(&ring->cs); + almtx_unlock(&ring->mtx); } diff --git a/jni/openal-soft-1.16.0/Alc/alstring.h b/jni/openal-soft-1.16.0/Alc/alstring.h new file mode 100644 index 00000000..32f4280a --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/alstring.h @@ -0,0 +1,45 @@ +#ifndef ALSTRING_H +#define ALSTRING_H + +#include + +#include "vector.h" + + +typedef char al_string_char_type; +TYPEDEF_VECTOR(al_string_char_type, al_string) + +inline void al_string_deinit(al_string *str) +{ VECTOR_DEINIT(*str); } +#define AL_STRING_INIT(_x) do { (_x) = (al_string)NULL; } while(0) +#define AL_STRING_INIT_STATIC() ((al_string)NULL) +#define AL_STRING_DEINIT(_x) al_string_deinit(&(_x)) + +inline ALsizei al_string_length(const_al_string str) +{ return VECTOR_SIZE(str); } + +inline ALboolean al_string_empty(const_al_string str) +{ return al_string_length(str) == 0; } + +inline const al_string_char_type *al_string_get_cstr(const_al_string str) +{ return str ? &VECTOR_FRONT(str) : ""; } + +void al_string_clear(al_string *str); + +int al_string_cmp(const_al_string str1, const_al_string str2); +int al_string_cmp_cstr(const_al_string str1, const al_string_char_type *str2); + +void al_string_copy(al_string *str, const_al_string from); +void al_string_copy_cstr(al_string *str, const al_string_char_type *from); + +void al_string_append_char(al_string *str, const al_string_char_type c); +void al_string_append_cstr(al_string *str, const al_string_char_type *from); +void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to); + +#ifdef _WIN32 +#include +/* Windows-only methods to deal with WideChar strings. */ +void al_string_copy_wcstr(al_string *str, const wchar_t *from); +#endif + +#endif /* ALSTRING_H */ diff --git a/jni/openal-soft-android/Alc/backends/alsa.c b/jni/openal-soft-1.16.0/Alc/backends/alsa.c similarity index 90% rename from jni/openal-soft-android/Alc/backends/alsa.c rename to jni/openal-soft-1.16.0/Alc/backends/alsa.c index 874b31c3..d5174da8 100644 --- a/jni/openal-soft-android/Alc/backends/alsa.c +++ b/jni/openal-soft-1.16.0/Alc/backends/alsa.c @@ -227,14 +227,27 @@ static ALCboolean alsa_load(void) typedef struct { - ALCchar *name; - char *device; + al_string name; + al_string device_name; } DevMap; +TYPEDEF_VECTOR(DevMap, vector_DevMap) -static DevMap *allDevNameMap; -static ALuint numDevNames; -static DevMap *allCaptureDevNameMap; -static ALuint numCaptureDevNames; +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; + +static void clear_devlist(vector_DevMap *devlist) +{ + DevMap *iter, *end; + + iter = VECTOR_ITER_BEGIN(*devlist); + end = VECTOR_ITER_END(*devlist); + for(;iter != end;iter++) + { + AL_STRING_DEINIT(iter->name); + AL_STRING_DEINIT(iter->device_name); + } + VECTOR_RESIZE(*devlist, 0); +} static const char *prefix_name(snd_pcm_stream_t stream) @@ -243,23 +256,26 @@ static const char *prefix_name(snd_pcm_stream_t stream) return (stream==SND_PCM_STREAM_PLAYBACK) ? "device-prefix" : "capture-prefix"; } -static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count) +static void probe_devices(snd_pcm_stream_t stream, vector_DevMap *DeviceList) { const char *main_prefix = "plughw:"; snd_ctl_t *handle; - int card, err, dev, idx; snd_ctl_card_info_t *info; snd_pcm_info_t *pcminfo; - DevMap *DevList; + int card, err, dev; + DevMap entry; + + clear_devlist(DeviceList); snd_ctl_card_info_malloc(&info); snd_pcm_info_malloc(&pcminfo); - DevList = malloc(sizeof(DevMap) * 1); - DevList[0].name = strdup(alsaDevice); - DevList[0].device = strdup(GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? - "device" : "capture", "default")); - idx = 1; + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.device_name); + al_string_copy_cstr(&entry.name, alsaDevice); + al_string_copy_cstr(&entry.device_name, GetConfigValue("alsa", (stream==SND_PCM_STREAM_PLAYBACK) ? + "device" : "capture", "default")); + VECTOR_PUSH_BACK(*DeviceList, entry); card = -1; if((err=snd_card_next(&card)) < 0) @@ -293,8 +309,9 @@ static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count) dev = -1; while(1) { + const char *device_prefix = card_prefix; const char *devname; - void *temp; + char device[128]; if(snd_ctl_pcm_next_device(handle, &dev) < 0) ERR("snd_ctl_pcm_next_device failed\n"); @@ -310,28 +327,22 @@ static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count) continue; } - temp = realloc(DevList, sizeof(DevMap) * (idx+1)); - if(temp) - { - const char *device_prefix = card_prefix; - char device[128]; + devname = snd_pcm_info_get_name(pcminfo); - DevList = temp; - devname = snd_pcm_info_get_name(pcminfo); + snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev); + ConfigValueStr("alsa", name, &device_prefix); - snprintf(name, sizeof(name), "%s-%s-%d", prefix_name(stream), cardid, dev); - ConfigValueStr("alsa", name, &device_prefix); + snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)", + cardname, devname, cardid, dev); + snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d", + device_prefix, cardid, dev); - snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)", - cardname, devname, cardid, dev); - snprintf(device, sizeof(device), "%sCARD=%s,DEV=%d", - device_prefix, cardid, dev); - - TRACE("Got device \"%s\", \"%s\"\n", name, device); - DevList[idx].name = strdup(name); - DevList[idx].device = strdup(device); - idx++; - } + TRACE("Got device \"%s\", \"%s\"\n", name, device); + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.device_name); + al_string_copy_cstr(&entry.name, name); + al_string_copy_cstr(&entry.device_name, device); + VECTOR_PUSH_BACK(*DeviceList, entry); } snd_ctl_close(handle); next_card: @@ -343,9 +354,6 @@ static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count) snd_pcm_info_free(pcminfo); snd_ctl_card_info_free(info); - - *count = idx; - return DevList; } @@ -390,12 +398,11 @@ typedef struct ALCplaybackAlsa { ALsizei size; volatile int killNow; - althread_t thread; + althrd_t thread; } ALCplaybackAlsa; -DECLARE_ALCBACKEND_VTABLE(ALCplaybackAlsa); -static ALuint ALCplaybackAlsa_mixerProc(ALvoid *ptr); -static ALuint ALCplaybackAlsa_mixerNoMMapProc(ALvoid *ptr); +static int ALCplaybackAlsa_mixerProc(void *ptr); +static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr); static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device); static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, Destruct) @@ -406,8 +413,12 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self); static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self); static DECLARE_FORWARD2(ALCplaybackAlsa, ALCbackend, ALCenum, captureSamples, void*, ALCuint) static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, ALCuint, availableSamples) +static ALint64 ALCplaybackAlsa_getLatency(ALCplaybackAlsa *self); static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, lock) static DECLARE_FORWARD(ALCplaybackAlsa, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCplaybackAlsa) + +DEFINE_ALCBACKEND_VTABLE(ALCplaybackAlsa); static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device) @@ -417,7 +428,7 @@ static void ALCplaybackAlsa_Construct(ALCplaybackAlsa *self, ALCdevice *device) } -static ALuint ALCplaybackAlsa_mixerProc(ALvoid *ptr) +static int ALCplaybackAlsa_mixerProc(void *ptr) { ALCplaybackAlsa *self = (ALCplaybackAlsa*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -429,7 +440,7 @@ static ALuint ALCplaybackAlsa_mixerProc(ALvoid *ptr) int err; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); update_size = device->UpdateSize; num_updates = device->NumUpdates; @@ -509,7 +520,7 @@ static ALuint ALCplaybackAlsa_mixerProc(ALvoid *ptr) return 0; } -static ALuint ALCplaybackAlsa_mixerNoMMapProc(ALvoid *ptr) +static int ALCplaybackAlsa_mixerNoMMapProc(void *ptr) { ALCplaybackAlsa *self = (ALCplaybackAlsa*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -519,7 +530,7 @@ static ALuint ALCplaybackAlsa_mixerNoMMapProc(ALvoid *ptr) int err; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); update_size = device->UpdateSize; num_updates = device->NumUpdates; @@ -614,21 +625,17 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) if(name) { - size_t idx; + const DevMap *iter; - if(!allDevNameMap) - allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames); + if(VECTOR_SIZE(PlaybackDevices) == 0) + probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices); - for(idx = 0;idx < numDevNames;idx++) - { - if(strcmp(name, allDevNameMap[idx].name) == 0) - { - driver = allDevNameMap[idx].device; - break; - } - } - if(idx == numDevNames) +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, name) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_ITER_END(PlaybackDevices)) return ALC_INVALID_VALUE; + driver = al_string_get_cstr(iter->device_name); } else { @@ -636,6 +643,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) driver = GetConfigValue("alsa", "device", "default"); } + TRACE("Opening device \"%s\"\n", driver); err = snd_pcm_open(&self->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if(err < 0) { @@ -646,7 +654,7 @@ static ALCenum ALCplaybackAlsa_open(ALCplaybackAlsa *self, const ALCchar *name) /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ snd_config_update_free_global(); - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -663,15 +671,14 @@ static ALCboolean ALCplaybackAlsa_reset(ALCplaybackAlsa *self) unsigned int periodLen, bufferLen; snd_pcm_sw_params_t *sp = NULL; snd_pcm_hw_params_t *hp = NULL; + snd_pcm_format_t format = -1; snd_pcm_access_t access; - snd_pcm_format_t format; unsigned int periods; unsigned int rate; const char *funcerr; int allowmmap; int err; - format = -1; switch(device->FmtType) { case DevFmtByte: @@ -809,7 +816,7 @@ error: static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALuint (*thread_func)(ALvoid*) = NULL; + int (*thread_func)(void*) = NULL; snd_pcm_hw_params_t *hp = NULL; snd_pcm_access_t access; const char *funcerr; @@ -845,7 +852,8 @@ static ALCboolean ALCplaybackAlsa_start(ALCplaybackAlsa *self) } thread_func = ALCplaybackAlsa_mixerProc; } - if(!StartThread(&self->thread, thread_func, self)) + self->killNow = 0; + if(althrd_create(&self->thread, thread_func, self) != althrd_success) { ERR("Could not create playback thread\n"); free(self->buffer); @@ -863,13 +871,14 @@ error: static void ALCplaybackAlsa_stop(ALCplaybackAlsa *self) { - if(self->thread) - { - self->killNow = 1; - StopThread(self->thread); - self->thread = NULL; - } - self->killNow = 0; + int res; + + if(self->killNow) + return; + + self->killNow = 1; + althrd_join(self->thread, &res); + free(self->buffer); self->buffer = NULL; } @@ -889,14 +898,6 @@ static ALint64 ALCplaybackAlsa_getLatency(ALCplaybackAlsa *self) } -static void ALCplaybackAlsa_Delete(ALCplaybackAlsa *self) -{ - free(self); -} - -DEFINE_ALCBACKEND_VTABLE(ALCplaybackAlsa); - - typedef struct ALCcaptureAlsa { DERIVE_FROM_TYPE(ALCbackend); @@ -910,7 +911,6 @@ typedef struct ALCcaptureAlsa { snd_pcm_sframes_t last_avail; } ALCcaptureAlsa; -DECLARE_ALCBACKEND_VTABLE(ALCcaptureAlsa); static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device); static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, Destruct) @@ -921,8 +921,12 @@ static ALCboolean ALCcaptureAlsa_start(ALCcaptureAlsa *self); static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self); static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCcaptureAlsa_availableSamples(ALCcaptureAlsa *self); +static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self); static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, lock) static DECLARE_FORWARD(ALCcaptureAlsa, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCcaptureAlsa) + +DEFINE_ALCBACKEND_VTABLE(ALCcaptureAlsa); static void ALCcaptureAlsa_Construct(ALCcaptureAlsa *self, ALCdevice *device) @@ -940,27 +944,23 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) snd_pcm_uframes_t bufferSizeInFrames; snd_pcm_uframes_t periodSizeInFrames; ALboolean needring = AL_FALSE; - snd_pcm_format_t format; + snd_pcm_format_t format = -1; const char *funcerr; int err; if(name) { - size_t idx; + const DevMap *iter; - if(!allCaptureDevNameMap) - allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames); + if(VECTOR_SIZE(CaptureDevices) == 0) + probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices); - for(idx = 0;idx < numCaptureDevNames;idx++) - { - if(strcmp(name, allCaptureDevNameMap[idx].name) == 0) - { - driver = allCaptureDevNameMap[idx].device; - break; - } - } - if(idx == numCaptureDevNames) +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, name) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_ITER_END(CaptureDevices)) return ALC_INVALID_VALUE; + driver = al_string_get_cstr(iter->device_name); } else { @@ -968,6 +968,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) driver = GetConfigValue("alsa", "capture", "default"); } + TRACE("Opening device \"%s\"\n", driver); err = snd_pcm_open(&self->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); if(err < 0) { @@ -978,7 +979,6 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ snd_config_update_free_global(); - format = -1; switch(device->FmtType) { case DevFmtByte: @@ -1056,7 +1056,7 @@ static ALCenum ALCcaptureAlsa_open(ALCcaptureAlsa *self, const ALCchar *name) } } - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; @@ -1114,11 +1114,12 @@ static void ALCcaptureAlsa_stop(ALCcaptureAlsa *self) void *ptr; size = snd_pcm_frames_to_bytes(self->pcmHandle, avail); - ptr = realloc(self->buffer, size); + ptr = malloc(size); if(ptr) { + ALCcaptureAlsa_captureSamples(self, ptr, avail); + free(self->buffer); self->buffer = ptr; - ALCcaptureAlsa_captureSamples(self, self->buffer, avail); self->size = size; } } @@ -1150,7 +1151,7 @@ static ALCenum ALCcaptureAlsa_captureSamples(ALCcaptureAlsa *self, ALCvoid *buff if((snd_pcm_uframes_t)amt > samples) amt = samples; amt = snd_pcm_frames_to_bytes(self->pcmHandle, amt); - memmove(buffer, self->buffer, amt); + memcpy(buffer, self->buffer, amt); if(self->size > amt) { @@ -1287,14 +1288,11 @@ static ALint64 ALCcaptureAlsa_getLatency(ALCcaptureAlsa *self) return maxi64((ALint64)delay*1000000000/device->Frequency, 0); } -static void ALCcaptureAlsa_Delete(ALCcaptureAlsa *self) -{ - free(self); -} - -DEFINE_ALCBACKEND_VTABLE(ALCcaptureAlsa); - +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } typedef struct ALCalsaBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); @@ -1303,6 +1301,9 @@ typedef struct ALCalsaBackendFactory { static ALCboolean ALCalsaBackendFactory_init(ALCalsaBackendFactory* UNUSED(self)) { + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + if(!alsa_load()) return ALC_FALSE; return ALC_TRUE; @@ -1310,25 +1311,11 @@ static ALCboolean ALCalsaBackendFactory_init(ALCalsaBackendFactory* UNUSED(self) static void ALCalsaBackendFactory_deinit(ALCalsaBackendFactory* UNUSED(self)) { - ALuint i; + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); - for(i = 0;i < numDevNames;++i) - { - free(allDevNameMap[i].name); - free(allDevNameMap[i].device); - } - free(allDevNameMap); - allDevNameMap = NULL; - numDevNames = 0; - - for(i = 0;i < numCaptureDevNames;++i) - { - free(allCaptureDevNameMap[i].name); - free(allCaptureDevNameMap[i].device); - } - free(allCaptureDevNameMap); - allCaptureDevNameMap = NULL; - numCaptureDevNames = 0; + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); #ifdef HAVE_DYNLOAD if(alsa_handle) @@ -1346,36 +1333,16 @@ static ALCboolean ALCalsaBackendFactory_querySupport(ALCalsaBackendFactory* UNUS static void ALCalsaBackendFactory_probe(ALCalsaBackendFactory* UNUSED(self), enum DevProbe type) { - ALuint i; - switch(type) { case ALL_DEVICE_PROBE: - for(i = 0;i < numDevNames;++i) - { - free(allDevNameMap[i].name); - free(allDevNameMap[i].device); - } - - free(allDevNameMap); - allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames); - - for(i = 0;i < numDevNames;++i) - AppendAllDevicesList(allDevNameMap[i].name); + probe_devices(SND_PCM_STREAM_PLAYBACK, &PlaybackDevices); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: - for(i = 0;i < numCaptureDevNames;++i) - { - free(allCaptureDevNameMap[i].name); - free(allCaptureDevNameMap[i].device); - } - - free(allCaptureDevNameMap); - allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames); - - for(i = 0;i < numCaptureDevNames;++i) - AppendCaptureDeviceList(allCaptureDevNameMap[i].name); + probe_devices(SND_PCM_STREAM_CAPTURE, &CaptureDevices); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); break; } } @@ -1386,8 +1353,9 @@ static ALCbackend* ALCalsaBackendFactory_createBackend(ALCalsaBackendFactory* UN { ALCplaybackAlsa *backend; - backend = calloc(1, sizeof(*backend)); + backend = ALCplaybackAlsa_New(sizeof(*backend)); if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); ALCplaybackAlsa_Construct(backend, device); @@ -1397,8 +1365,9 @@ static ALCbackend* ALCalsaBackendFactory_createBackend(ALCalsaBackendFactory* UN { ALCcaptureAlsa *backend; - backend = calloc(1, sizeof(*backend)); + backend = ALCcaptureAlsa_New(sizeof(*backend)); if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); ALCcaptureAlsa_Construct(backend, device); diff --git a/jni/openal-soft-android/Alc/backends/base.c b/jni/openal-soft-1.16.0/Alc/backends/base.c similarity index 77% rename from jni/openal-soft-android/Alc/backends/base.c rename to jni/openal-soft-1.16.0/Alc/backends/base.c index fe797562..37e4ccc9 100644 --- a/jni/openal-soft-android/Alc/backends/base.c +++ b/jni/openal-soft-1.16.0/Alc/backends/base.c @@ -11,13 +11,15 @@ /* Base ALCbackend method implementations. */ void ALCbackend_Construct(ALCbackend *self, ALCdevice *device) { + int ret; self->mDevice = device; - InitializeCriticalSection(&self->mMutex); + ret = almtx_init(&self->mMutex, almtx_recursive); + assert(ret == althrd_success); } void ALCbackend_Destruct(ALCbackend *self) { - DeleteCriticalSection(&self->mMutex); + almtx_destroy(&self->mMutex); } ALCboolean ALCbackend_reset(ALCbackend* UNUSED(self)) @@ -42,12 +44,14 @@ ALint64 ALCbackend_getLatency(ALCbackend* UNUSED(self)) void ALCbackend_lock(ALCbackend *self) { - EnterCriticalSection(&self->mMutex); + int ret = almtx_lock(&self->mMutex); + assert(ret == althrd_success); } void ALCbackend_unlock(ALCbackend *self) { - LeaveCriticalSection(&self->mMutex); + int ret = almtx_unlock(&self->mMutex); + assert(ret == althrd_success); } @@ -60,9 +64,11 @@ void ALCbackendFactory_deinit(ALCbackendFactory* UNUSED(self)) /* Wrappers to use an old-style backend with the new interface. */ typedef struct PlaybackWrapper { DERIVE_FROM_TYPE(ALCbackend); + + const BackendFuncs *Funcs; } PlaybackWrapper; -static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device); +static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs); static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, Destruct) static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name); static void PlaybackWrapper_close(PlaybackWrapper *self); @@ -74,62 +80,61 @@ static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, ALCuint, availableSamples) static ALint64 PlaybackWrapper_getLatency(PlaybackWrapper *self); static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, lock) static DECLARE_FORWARD(PlaybackWrapper, ALCbackend, void, unlock) -static void PlaybackWrapper_Delete(PlaybackWrapper *self); +DECLARE_DEFAULT_ALLOCATORS(PlaybackWrapper) DEFINE_ALCBACKEND_VTABLE(PlaybackWrapper); -static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device) +static void PlaybackWrapper_Construct(PlaybackWrapper *self, ALCdevice *device, const BackendFuncs *funcs) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(PlaybackWrapper, ALCbackend, self); + + self->Funcs = funcs; } static ALCenum PlaybackWrapper_open(PlaybackWrapper *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return device->Funcs->OpenPlayback(device, name); + return self->Funcs->OpenPlayback(device, name); } static void PlaybackWrapper_close(PlaybackWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - device->Funcs->ClosePlayback(device); + self->Funcs->ClosePlayback(device); } static ALCboolean PlaybackWrapper_reset(PlaybackWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return device->Funcs->ResetPlayback(device); + return self->Funcs->ResetPlayback(device); } static ALCboolean PlaybackWrapper_start(PlaybackWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return device->Funcs->StartPlayback(device); + return self->Funcs->StartPlayback(device); } static void PlaybackWrapper_stop(PlaybackWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - device->Funcs->StopPlayback(device); + self->Funcs->StopPlayback(device); } static ALint64 PlaybackWrapper_getLatency(PlaybackWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return device->Funcs->GetLatency(device); -} - -static void PlaybackWrapper_Delete(PlaybackWrapper *self) -{ - free(self); + return self->Funcs->GetLatency(device); } typedef struct CaptureWrapper { DERIVE_FROM_TYPE(ALCbackend); + + const BackendFuncs *Funcs; } CaptureWrapper; -static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device); +static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs); static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, Destruct) static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name); static void CaptureWrapper_close(CaptureWrapper *self); @@ -141,75 +146,72 @@ static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self); static ALint64 CaptureWrapper_getLatency(CaptureWrapper *self); static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, lock) static DECLARE_FORWARD(CaptureWrapper, ALCbackend, void, unlock) -static void CaptureWrapper_Delete(CaptureWrapper *self); +DECLARE_DEFAULT_ALLOCATORS(CaptureWrapper) DEFINE_ALCBACKEND_VTABLE(CaptureWrapper); -static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device) +static void CaptureWrapper_Construct(CaptureWrapper *self, ALCdevice *device, const BackendFuncs *funcs) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(CaptureWrapper, ALCbackend, self); + + self->Funcs = funcs; } static ALCenum CaptureWrapper_open(CaptureWrapper *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return device->Funcs->OpenCapture(device, name); + return self->Funcs->OpenCapture(device, name); } static void CaptureWrapper_close(CaptureWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - device->Funcs->CloseCapture(device); + self->Funcs->CloseCapture(device); } static ALCboolean CaptureWrapper_start(CaptureWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - device->Funcs->StartCapture(device); + self->Funcs->StartCapture(device); return ALC_TRUE; } static void CaptureWrapper_stop(CaptureWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - device->Funcs->StopCapture(device); + self->Funcs->StopCapture(device); } static ALCenum CaptureWrapper_captureSamples(CaptureWrapper *self, void *buffer, ALCuint samples) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return device->Funcs->CaptureSamples(device, buffer, samples); + return self->Funcs->CaptureSamples(device, buffer, samples); } static ALCuint CaptureWrapper_availableSamples(CaptureWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return device->Funcs->AvailableSamples(device); + return self->Funcs->AvailableSamples(device); } static ALint64 CaptureWrapper_getLatency(CaptureWrapper *self) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - return device->Funcs->GetLatency(device); -} - -static void CaptureWrapper_Delete(CaptureWrapper *self) -{ - free(self); + return self->Funcs->GetLatency(device); } -ALCbackend *create_backend_wrapper(ALCdevice *device, ALCbackend_Type type) +ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type) { if(type == ALCbackend_Playback) { PlaybackWrapper *backend; - backend = malloc(sizeof(*backend)); + backend = PlaybackWrapper_New(sizeof(*backend)); if(!backend) return NULL; - PlaybackWrapper_Construct(backend, device); + PlaybackWrapper_Construct(backend, device, funcs); return STATIC_CAST(ALCbackend, backend); } @@ -218,10 +220,10 @@ ALCbackend *create_backend_wrapper(ALCdevice *device, ALCbackend_Type type) { CaptureWrapper *backend; - backend = malloc(sizeof(*backend)); + backend = CaptureWrapper_New(sizeof(*backend)); if(!backend) return NULL; - CaptureWrapper_Construct(backend, device); + CaptureWrapper_Construct(backend, device, funcs); return STATIC_CAST(ALCbackend, backend); } diff --git a/jni/openal-soft-android/Alc/backends/base.h b/jni/openal-soft-1.16.0/Alc/backends/base.h similarity index 91% rename from jni/openal-soft-android/Alc/backends/base.h rename to jni/openal-soft-1.16.0/Alc/backends/base.h index 1bbc1fb0..5573c178 100644 --- a/jni/openal-soft-android/Alc/backends/base.h +++ b/jni/openal-soft-1.16.0/Alc/backends/base.h @@ -2,7 +2,7 @@ #define AL_BACKENDS_BASE_H #include "alMain.h" -#include "compat.h" +#include "threads.h" struct ALCbackendVtable; @@ -12,7 +12,7 @@ typedef struct ALCbackend { ALCdevice *mDevice; - CRITICAL_SECTION mMutex; + almtx_t mMutex; } ALCbackend; void ALCbackend_Construct(ALCbackend *self, ALCdevice *device); @@ -42,12 +42,9 @@ struct ALCbackendVtable { void (*const lock)(ALCbackend*); void (*const unlock)(ALCbackend*); - void (*const Delete)(ALCbackend*); + void (*const Delete)(void*); }; -#define DECLARE_ALCBACKEND_VTABLE(T) \ -static const struct ALCbackendVtable T##_ALCbackend_vtable - #define DEFINE_ALCBACKEND_VTABLE(T) \ DECLARE_THUNK(T, ALCbackend, void, Destruct) \ DECLARE_THUNK1(T, ALCbackend, ALCenum, open, const ALCchar*) \ @@ -60,9 +57,10 @@ DECLARE_THUNK(T, ALCbackend, ALCuint, availableSamples) \ DECLARE_THUNK(T, ALCbackend, ALint64, getLatency) \ DECLARE_THUNK(T, ALCbackend, void, lock) \ DECLARE_THUNK(T, ALCbackend, void, unlock) \ -DECLARE_THUNK(T, ALCbackend, void, Delete) \ +static void T##_ALCbackend_Delete(void *ptr) \ +{ T##_Delete(STATIC_UPCAST(T, ALCbackend, (ALCbackend*)ptr)); } \ \ -DECLARE_ALCBACKEND_VTABLE(T) = { \ +static const struct ALCbackendVtable T##_ALCbackend_vtable = { \ T##_ALCbackend_Destruct, \ \ T##_ALCbackend_open, \ @@ -125,9 +123,11 @@ static const struct ALCbackendFactoryVtable T##_ALCbackendFactory_vtable = { \ ALCbackendFactory *ALCpulseBackendFactory_getFactory(void); ALCbackendFactory *ALCalsaBackendFactory_getFactory(void); ALCbackendFactory *ALCossBackendFactory_getFactory(void); +ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void); +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); ALCbackendFactory *ALCnullBackendFactory_getFactory(void); ALCbackendFactory *ALCloopbackFactory_getFactory(void); -ALCbackend *create_backend_wrapper(ALCdevice *device, ALCbackend_Type type); +ALCbackend *create_backend_wrapper(ALCdevice *device, const BackendFuncs *funcs, ALCbackend_Type type); #endif /* AL_BACKENDS_BASE_H */ diff --git a/jni/openal-soft-android/Alc/backends/coreaudio.c b/jni/openal-soft-1.16.0/Alc/backends/coreaudio.c similarity index 99% rename from jni/openal-soft-android/Alc/backends/coreaudio.c rename to jni/openal-soft-1.16.0/Alc/backends/coreaudio.c index 5c9b69c8..b3583ffd 100644 --- a/jni/openal-soft-android/Alc/backends/coreaudio.c +++ b/jni/openal-soft-1.16.0/Alc/backends/coreaudio.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "alMain.h" #include "alu.h" @@ -180,7 +181,7 @@ static ALCenum ca_open_playback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; } @@ -577,6 +578,8 @@ static ALCenum ca_open_capture(ALCdevice *device, const ALCchar *deviceName) if(data->ring == NULL) goto error; + al_string_copy_cstr(&device->DeviceName, deviceName); + return ALC_NO_ERROR; error: diff --git a/jni/openal-soft-android/Alc/backends/dsound.c b/jni/openal-soft-1.16.0/Alc/backends/dsound.c similarity index 54% rename from jni/openal-soft-android/Alc/backends/dsound.c rename to jni/openal-soft-1.16.0/Alc/backends/dsound.c index 6b108fba..2229347e 100644 --- a/jni/openal-soft-android/Alc/backends/dsound.c +++ b/jni/openal-soft-1.16.0/Alc/backends/dsound.c @@ -36,6 +36,9 @@ #include "alu.h" #include "threads.h" #include "compat.h" +#include "alstring.h" + +#include "backends/base.h" #ifndef DSSPEAKER_5POINT1 # define DSSPEAKER_5POINT1 0x00000006 @@ -55,54 +58,23 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); +#ifdef HAVE_DYNLOAD static void *ds_handle; -static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter); -static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext); -static HRESULT (WINAPI *pDirectSoundCaptureCreate)(LPCGUID pcGuidDevice, IDirectSoundCapture **ppDSC, IUnknown *pUnkOuter); -static HRESULT (WINAPI *pDirectSoundCaptureEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext); +static HRESULT (WINAPI *pDirectSoundCreate)(const GUID *pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter); +static HRESULT (WINAPI *pDirectSoundEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext); +static HRESULT (WINAPI *pDirectSoundCaptureCreate)(const GUID *pcGuidDevice, IDirectSoundCapture **ppDSC, IUnknown *pUnkOuter); +static HRESULT (WINAPI *pDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext); #define DirectSoundCreate pDirectSoundCreate -#define DirectSoundEnumerateA pDirectSoundEnumerateA +#define DirectSoundEnumerateW pDirectSoundEnumerateW #define DirectSoundCaptureCreate pDirectSoundCaptureCreate -#define DirectSoundCaptureEnumerateA pDirectSoundCaptureEnumerateA +#define DirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW +#endif -typedef struct { - // DirectSound Playback Device - IDirectSound *DS; - IDirectSoundBuffer *PrimaryBuffer; - IDirectSoundBuffer *Buffer; - IDirectSoundNotify *Notifies; - HANDLE NotifyEvent; - - volatile int killNow; - althread_t thread; -} DSoundPlaybackData; - -typedef struct { - // DirectSound Capture Device - IDirectSoundCapture *DSC; - IDirectSoundCaptureBuffer *DSCbuffer; - DWORD BufferBytes; - DWORD Cursor; - RingBuffer *Ring; -} DSoundCaptureData; - - -typedef struct { - ALCchar *name; - GUID guid; -} DevMap; - -static DevMap *PlaybackDeviceList; -static ALuint NumPlaybackDevices; -static DevMap *CaptureDeviceList; -static ALuint NumCaptureDevices; - -#define MAX_UPDATES 128 - static ALCboolean DSoundLoad(void) { +#ifdef HAVE_DYNLOAD if(!ds_handle) { ds_handle = LoadLib("dsound.dll"); @@ -121,117 +93,130 @@ static ALCboolean DSoundLoad(void) } \ } while(0) LOAD_FUNC(DirectSoundCreate); - LOAD_FUNC(DirectSoundEnumerateA); + LOAD_FUNC(DirectSoundEnumerateW); LOAD_FUNC(DirectSoundCaptureCreate); - LOAD_FUNC(DirectSoundCaptureEnumerateA); + LOAD_FUNC(DirectSoundCaptureEnumerateW); #undef LOAD_FUNC } +#endif return ALC_TRUE; } -static BOOL CALLBACK DSoundEnumPlaybackDevices(LPGUID guid, LPCSTR desc, LPCSTR UNUSED(drvname), LPVOID UNUSED(data)) +#define MAX_UPDATES 128 + +typedef struct { + al_string name; + GUID guid; +} DevMap; +TYPEDEF_VECTOR(DevMap, vector_DevMap) + +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; + +static void clear_devlist(vector_DevMap *list) { - LPOLESTR guidstr = NULL; - char str[1024]; +#define DEINIT_STR(i) AL_STRING_DEINIT((i)->name) + VECTOR_FOR_EACH(DevMap, *list, DEINIT_STR); +#undef DEINIT_STR + VECTOR_RESIZE(*list, 0); +} + +static BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR* UNUSED(drvname), void *data) +{ + vector_DevMap *devices = data; + OLECHAR *guidstr = NULL; + DevMap *iter, *end; + DevMap entry; HRESULT hr; - void *temp; int count; - ALuint i; if(!guid) return TRUE; + AL_STRING_INIT(entry.name); + count = 0; do { - if(count == 0) - snprintf(str, sizeof(str), "%s", desc); - else - snprintf(str, sizeof(str), "%s #%d", desc, count+1); + al_string_copy_wcstr(&entry.name, desc); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&entry.name, str); + } count++; - for(i = 0;i < NumPlaybackDevices;i++) + iter = VECTOR_ITER_BEGIN(*devices); + end = VECTOR_ITER_END(*devices); + for(;iter != end;++iter) { - if(strcmp(str, PlaybackDeviceList[i].name) == 0) + if(al_string_cmp(entry.name, iter->name) == 0) break; } - } while(i != NumPlaybackDevices); + } while(iter != end); + entry.guid = *guid; hr = StringFromCLSID(guid, &guidstr); if(SUCCEEDED(hr)) { - TRACE("Got device \"%s\", GUID \"%ls\"\n", str, guidstr); + TRACE("Got device \"%s\", GUID \"%ls\"\n", al_string_get_cstr(entry.name), guidstr); CoTaskMemFree(guidstr); } - temp = realloc(PlaybackDeviceList, sizeof(DevMap) * (NumPlaybackDevices+1)); - if(temp) - { - PlaybackDeviceList = temp; - PlaybackDeviceList[NumPlaybackDevices].name = strdup(str); - PlaybackDeviceList[NumPlaybackDevices].guid = *guid; - NumPlaybackDevices++; - } + VECTOR_PUSH_BACK(*devices, entry); return TRUE; } -static BOOL CALLBACK DSoundEnumCaptureDevices(LPGUID guid, LPCSTR desc, LPCSTR UNUSED(drvname), LPVOID UNUSED(data)) +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, ALint64, getLatency) +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) { - LPOLESTR guidstr = NULL; - char str[1024]; - HRESULT hr; - void *temp; - int count; - ALuint i; - - if(!guid) - return TRUE; - - count = 0; - do { - if(count == 0) - snprintf(str, sizeof(str), "%s", desc); - else - snprintf(str, sizeof(str), "%s #%d", desc, count+1); - count++; - - for(i = 0;i < NumCaptureDevices;i++) - { - if(strcmp(str, CaptureDeviceList[i].name) == 0) - break; - } - } while(i != NumCaptureDevices); - - hr = StringFromCLSID(guid, &guidstr); - if(SUCCEEDED(hr)) - { - TRACE("Got device \"%s\", GUID \"%ls\"\n", str, guidstr); - CoTaskMemFree(guidstr); - } - - temp = realloc(CaptureDeviceList, sizeof(DevMap) * (NumCaptureDevices+1)); - if(temp) - { - CaptureDeviceList = temp; - CaptureDeviceList[NumCaptureDevices].name = strdup(str); - CaptureDeviceList[NumCaptureDevices].guid = *guid; - NumCaptureDevices++; - } - - return TRUE; + ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); + SET_VTABLE2(ALCdsoundPlayback, ALCbackend, self); } -FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr) +FORCE_ALIGN static int ALCdsoundPlayback_mixerProc(void *ptr) { - ALCdevice *Device = (ALCdevice*)ptr; - DSoundPlaybackData *data = (DSoundPlaybackData*)Device->ExtraData; + ALCdsoundPlayback *self = ptr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; DSBCAPS DSBCaps; DWORD LastCursor = 0; DWORD PlayCursor; - VOID *WritePtr1, *WritePtr2; + void *WritePtr1, *WritePtr2; DWORD WriteCnt1, WriteCnt2; BOOL Playing = FALSE; DWORD FrameSize; @@ -240,47 +225,47 @@ FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr) HRESULT err; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); memset(&DSBCaps, 0, sizeof(DSBCaps)); DSBCaps.dwSize = sizeof(DSBCaps); - err = IDirectSoundBuffer_GetCaps(data->Buffer, &DSBCaps); + err = IDirectSoundBuffer_GetCaps(self->Buffer, &DSBCaps); if(FAILED(err)) { ERR("Failed to get buffer caps: 0x%lx\n", err); - ALCdevice_Lock(Device); - aluHandleDisconnect(Device); - ALCdevice_Unlock(Device); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); return 1; } - FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - FragSize = Device->UpdateSize * FrameSize; + FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + FragSize = device->UpdateSize * FrameSize; - IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &LastCursor, NULL); - while(!data->killNow) + IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &LastCursor, NULL); + while(!self->killNow) { // Get current play cursor - IDirectSoundBuffer_GetCurrentPosition(data->Buffer, &PlayCursor, NULL); + IDirectSoundBuffer_GetCurrentPosition(self->Buffer, &PlayCursor, NULL); avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes; if(avail < FragSize) { if(!Playing) { - err = IDirectSoundBuffer_Play(data->Buffer, 0, 0, DSBPLAY_LOOPING); + err = IDirectSoundBuffer_Play(self->Buffer, 0, 0, DSBPLAY_LOOPING); if(FAILED(err)) { ERR("Failed to play buffer: 0x%lx\n", err); - ALCdevice_Lock(Device); - aluHandleDisconnect(Device); - ALCdevice_Unlock(Device); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); return 1; } Playing = TRUE; } - avail = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE); + avail = WaitForSingleObjectEx(self->NotifyEvent, 2000, FALSE); if(avail != WAIT_OBJECT_0) ERR("WaitForSingleObjectEx error: 0x%lx\n", avail); continue; @@ -290,18 +275,18 @@ FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr) // Lock output buffer WriteCnt1 = 0; WriteCnt2 = 0; - err = IDirectSoundBuffer_Lock(data->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); + err = IDirectSoundBuffer_Lock(self->Buffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); // If the buffer is lost, restore it and lock if(err == DSERR_BUFFERLOST) { WARN("Buffer lost, restoring...\n"); - err = IDirectSoundBuffer_Restore(data->Buffer); + err = IDirectSoundBuffer_Restore(self->Buffer); if(SUCCEEDED(err)) { Playing = FALSE; LastCursor = 0; - err = IDirectSoundBuffer_Lock(data->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); + err = IDirectSoundBuffer_Lock(self->Buffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); } } @@ -309,18 +294,18 @@ FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr) if(SUCCEEDED(err)) { // If we have an active context, mix data directly into output buffer otherwise fill with silence - aluMixData(Device, WritePtr1, WriteCnt1/FrameSize); - aluMixData(Device, WritePtr2, WriteCnt2/FrameSize); + aluMixData(device, WritePtr1, WriteCnt1/FrameSize); + aluMixData(device, WritePtr2, WriteCnt2/FrameSize); // Unlock output buffer only when successfully locked - IDirectSoundBuffer_Unlock(data->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); + IDirectSoundBuffer_Unlock(self->Buffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); } else { ERR("Buffer lock error: %#lx\n", err); - ALCdevice_Lock(Device); - aluHandleDisconnect(Device); - ALCdevice_Unlock(Device); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); return 1; } @@ -332,94 +317,89 @@ FORCE_ALIGN static ALuint DSoundPlaybackProc(ALvoid *ptr) return 0; } -static ALCenum DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) +static ALCenum ALCdsoundPlayback_open(ALCdsoundPlayback *self, const ALCchar *deviceName) { - DSoundPlaybackData *data = NULL; - LPGUID guid = NULL; - HRESULT hr; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + const GUID *guid = NULL; + HRESULT hr, hrcom; - if(!PlaybackDeviceList) + if(VECTOR_SIZE(PlaybackDevices) == 0) { - hr = DirectSoundEnumerateA(DSoundEnumPlaybackDevices, NULL); + /* Initialize COM to prevent name truncation */ + hrcom = CoInitialize(NULL); + hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); if(FAILED(hr)) - ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); + ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); + if(SUCCEEDED(hrcom)) + CoUninitialize(); } - if(!deviceName && NumPlaybackDevices > 0) + if(!deviceName && VECTOR_SIZE(PlaybackDevices) > 0) { - deviceName = PlaybackDeviceList[0].name; - guid = &PlaybackDeviceList[0].guid; + deviceName = al_string_get_cstr(VECTOR_FRONT(PlaybackDevices).name); + guid = &VECTOR_FRONT(PlaybackDevices).guid; } else { - ALuint i; + const DevMap *iter; - for(i = 0;i < NumPlaybackDevices;i++) - { - if(strcmp(deviceName, PlaybackDeviceList[i].name) == 0) - { - guid = &PlaybackDeviceList[i].guid; - break; - } - } - if(i == NumPlaybackDevices) +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_ITER_END(PlaybackDevices)) return ALC_INVALID_VALUE; + guid = &iter->guid; } - //Initialise requested device - data = calloc(1, sizeof(DSoundPlaybackData)); - if(!data) - return ALC_OUT_OF_MEMORY; - hr = DS_OK; - data->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->NotifyEvent == NULL) + self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if(self->NotifyEvent == NULL) hr = E_FAIL; //DirectSound Init code if(SUCCEEDED(hr)) - hr = DirectSoundCreate(guid, &data->DS, NULL); + hr = DirectSoundCreate(guid, &self->DS, NULL); if(SUCCEEDED(hr)) - hr = IDirectSound_SetCooperativeLevel(data->DS, GetForegroundWindow(), DSSCL_PRIORITY); + hr = IDirectSound_SetCooperativeLevel(self->DS, GetForegroundWindow(), DSSCL_PRIORITY); if(FAILED(hr)) { - if(data->DS) - IDirectSound_Release(data->DS); - if(data->NotifyEvent) - CloseHandle(data->NotifyEvent); - free(data); + if(self->DS) + IDirectSound_Release(self->DS); + self->DS = NULL; + if(self->NotifyEvent) + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; + ERR("Device init failed: 0x%08lx\n", hr); return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); - device->ExtraData = data; + al_string_copy_cstr(&device->DeviceName, deviceName); + return ALC_NO_ERROR; } -static void DSoundClosePlayback(ALCdevice *device) +static void ALCdsoundPlayback_close(ALCdsoundPlayback *self) { - DSoundPlaybackData *data = device->ExtraData; + if(self->Notifies) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; - if(data->Notifies) - IDirectSoundNotify_Release(data->Notifies); - data->Notifies = NULL; - if(data->Buffer) - IDirectSoundBuffer_Release(data->Buffer); - data->Buffer = NULL; - if(data->PrimaryBuffer != NULL) - IDirectSoundBuffer_Release(data->PrimaryBuffer); - data->PrimaryBuffer = NULL; - - IDirectSound_Release(data->DS); - CloseHandle(data->NotifyEvent); - free(data); - device->ExtraData = NULL; + IDirectSound_Release(self->DS); + self->DS = NULL; + CloseHandle(self->NotifyEvent); + self->NotifyEvent = NULL; } -static ALCboolean DSoundResetPlayback(ALCdevice *device) +static ALCboolean ALCdsoundPlayback_reset(ALCdsoundPlayback *self) { - DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; DSBUFFERDESC DSBDescription; WAVEFORMATEXTENSIBLE OutputType; DWORD speakers; @@ -427,15 +407,15 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device) memset(&OutputType, 0, sizeof(OutputType)); - if(data->Notifies) - IDirectSoundNotify_Release(data->Notifies); - data->Notifies = NULL; - if(data->Buffer) - IDirectSoundBuffer_Release(data->Buffer); - data->Buffer = NULL; - if(data->PrimaryBuffer != NULL) - IDirectSoundBuffer_Release(data->PrimaryBuffer); - data->PrimaryBuffer = NULL; + if(self->Notifies) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; switch(device->FmtType) { @@ -458,7 +438,7 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device) break; } - hr = IDirectSound_GetSpeakerConfig(data->DS, &speakers); + hr = IDirectSound_GetSpeakerConfig(self->DS, &speakers); if(SUCCEEDED(hr)) { if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) @@ -551,21 +531,21 @@ retry_open: else OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - if(data->PrimaryBuffer) - IDirectSoundBuffer_Release(data->PrimaryBuffer); - data->PrimaryBuffer = NULL; + if(self->PrimaryBuffer) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; } else { - if(SUCCEEDED(hr) && !data->PrimaryBuffer) + if(SUCCEEDED(hr) && !self->PrimaryBuffer) { memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; - hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->PrimaryBuffer, NULL); + hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->PrimaryBuffer, NULL); } if(SUCCEEDED(hr)) - hr = IDirectSoundBuffer_SetFormat(data->PrimaryBuffer,&OutputType.Format); + hr = IDirectSoundBuffer_SetFormat(self->PrimaryBuffer,&OutputType.Format); } if(SUCCEEDED(hr)) @@ -583,7 +563,7 @@ retry_open: DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat=&OutputType.Format; - hr = IDirectSound_CreateSoundBuffer(data->DS, &DSBDescription, &data->Buffer, NULL); + hr = IDirectSound_CreateSoundBuffer(self->DS, &DSBDescription, &self->Buffer, NULL); if(FAILED(hr) && device->FmtType == DevFmtFloat) { device->FmtType = DevFmtShort; @@ -593,7 +573,7 @@ retry_open: if(SUCCEEDED(hr)) { - hr = IDirectSoundBuffer_QueryInterface(data->Buffer, &IID_IDirectSoundNotify, (LPVOID *)&data->Notifies); + hr = IDirectSoundBuffer_QueryInterface(self->Buffer, &IID_IDirectSoundNotify, (void**)&self->Notifies); if(SUCCEEDED(hr)) { DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; @@ -603,98 +583,125 @@ retry_open: { notifies[i].dwOffset = i * device->UpdateSize * OutputType.Format.nBlockAlign; - notifies[i].hEventNotify = data->NotifyEvent; + notifies[i].hEventNotify = self->NotifyEvent; } - if(IDirectSoundNotify_SetNotificationPositions(data->Notifies, device->NumUpdates, notifies) != DS_OK) + if(IDirectSoundNotify_SetNotificationPositions(self->Notifies, device->NumUpdates, notifies) != DS_OK) hr = E_FAIL; } } if(FAILED(hr)) { - if(data->Notifies != NULL) - IDirectSoundNotify_Release(data->Notifies); - data->Notifies = NULL; - if(data->Buffer != NULL) - IDirectSoundBuffer_Release(data->Buffer); - data->Buffer = NULL; - if(data->PrimaryBuffer != NULL) - IDirectSoundBuffer_Release(data->PrimaryBuffer); - data->PrimaryBuffer = NULL; + if(self->Notifies != NULL) + IDirectSoundNotify_Release(self->Notifies); + self->Notifies = NULL; + if(self->Buffer != NULL) + IDirectSoundBuffer_Release(self->Buffer); + self->Buffer = NULL; + if(self->PrimaryBuffer != NULL) + IDirectSoundBuffer_Release(self->PrimaryBuffer); + self->PrimaryBuffer = NULL; return ALC_FALSE; } - ResetEvent(data->NotifyEvent); + ResetEvent(self->NotifyEvent); SetDefaultWFXChannelOrder(device); return ALC_TRUE; } -static ALCboolean DSoundStartPlayback(ALCdevice *device) +static ALCboolean ALCdsoundPlayback_start(ALCdsoundPlayback *self) { - DSoundPlaybackData *data = (DSoundPlaybackData*)device->ExtraData; - - if(!StartThread(&data->thread, DSoundPlaybackProc, device)) + self->killNow = 0; + if(althrd_create(&self->thread, ALCdsoundPlayback_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; } -static void DSoundStopPlayback(ALCdevice *device) +static void ALCdsoundPlayback_stop(ALCdsoundPlayback *self) { - DSoundPlaybackData *data = device->ExtraData; + int res; - if(!data->thread) + if(self->killNow) return; - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; + self->killNow = 1; + althrd_join(self->thread, &res); - data->killNow = 0; - IDirectSoundBuffer_Stop(data->Buffer); + IDirectSoundBuffer_Stop(self->Buffer); } -static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) + +typedef struct ALCdsoundCapture { + DERIVE_FROM_TYPE(ALCbackend); + + IDirectSoundCapture *DSC; + IDirectSoundCaptureBuffer *DSCbuffer; + DWORD BufferBytes; + DWORD Cursor; + RingBuffer *Ring; +} ALCdsoundCapture; + +static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, Destruct) +static ALCenum ALCdsoundCapture_open(ALCdsoundCapture *self, const ALCchar *name); +static void ALCdsoundCapture_close(ALCdsoundCapture *self); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALCboolean, reset) +static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self); +static void ALCdsoundCapture_stop(ALCdsoundCapture *self); +static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples); +static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self); +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, ALint64, getLatency) +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, lock) +static DECLARE_FORWARD(ALCdsoundCapture, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCdsoundCapture) + +DEFINE_ALCBACKEND_VTABLE(ALCdsoundCapture); + +static void ALCdsoundCapture_Construct(ALCdsoundCapture *self, ALCdevice *device) { - DSoundCaptureData *data = NULL; + 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; - LPGUID guid = NULL; + const GUID *guid = NULL; HRESULT hr, hrcom; ALuint samples; - if(!CaptureDeviceList) + if(VECTOR_SIZE(CaptureDevices) == 0) { /* Initialize COM to prevent name truncation */ hrcom = CoInitialize(NULL); - hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL); + hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); if(FAILED(hr)) - ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); + ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); if(SUCCEEDED(hrcom)) CoUninitialize(); } - if(!deviceName && NumCaptureDevices > 0) + if(!deviceName && VECTOR_SIZE(CaptureDevices) > 0) { - deviceName = CaptureDeviceList[0].name; - guid = &CaptureDeviceList[0].guid; + deviceName = al_string_get_cstr(VECTOR_FRONT(CaptureDevices).name); + guid = &VECTOR_FRONT(CaptureDevices).guid; } else { - ALuint i; + const DevMap *iter; - for(i = 0;i < NumCaptureDevices;i++) - { - if(strcmp(deviceName, CaptureDeviceList[i].name) == 0) - { - guid = &CaptureDeviceList[i].guid; - break; - } - } - if(i == NumCaptureDevices) +#define MATCH_NAME(i) (al_string_cmp_cstr((i)->name, deviceName) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_ITER_END(CaptureDevices)) return ALC_INVALID_VALUE; + guid = &iter->guid; } switch(device->FmtType) @@ -712,16 +719,8 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) break; } - //Initialise requested device - data = calloc(1, sizeof(DSoundCaptureData)); - if(!data) - return ALC_OUT_OF_MEMORY; - - hr = DS_OK; - //DirectSoundCapture Init code - if(SUCCEEDED(hr)) - hr = DirectSoundCaptureCreate(guid, &data->DSC, NULL); + hr = DirectSoundCaptureCreate(guid, &self->DSC, NULL); if(SUCCEEDED(hr)) { memset(&InputType, 0, sizeof(InputType)); @@ -806,12 +805,12 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) DSCBDescription.dwBufferBytes = samples * InputType.Format.nBlockAlign; DSCBDescription.lpwfxFormat = &InputType.Format; - hr = IDirectSoundCapture_CreateCaptureBuffer(data->DSC, &DSCBDescription, &data->DSCbuffer, NULL); + hr = IDirectSoundCapture_CreateCaptureBuffer(self->DSC, &DSCBDescription, &self->DSCbuffer, NULL); } if(SUCCEEDED(hr)) { - data->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates); - if(data->Ring == NULL) + self->Ring = CreateRingBuffer(InputType.Format.nBlockAlign, device->UpdateSize * device->NumUpdates); + if(self->Ring == NULL) hr = DSERR_OUTOFMEMORY; } @@ -819,218 +818,237 @@ static ALCenum DSoundOpenCapture(ALCdevice *device, const ALCchar *deviceName) { ERR("Device init failed: 0x%08lx\n", hr); - DestroyRingBuffer(data->Ring); - data->Ring = NULL; - if(data->DSCbuffer != NULL) - IDirectSoundCaptureBuffer_Release(data->DSCbuffer); - data->DSCbuffer = NULL; - if(data->DSC) - IDirectSoundCapture_Release(data->DSC); - data->DSC = NULL; + DestroyRingBuffer(self->Ring); + self->Ring = NULL; + if(self->DSCbuffer != NULL) + IDirectSoundCaptureBuffer_Release(self->DSCbuffer); + self->DSCbuffer = NULL; + if(self->DSC) + IDirectSoundCapture_Release(self->DSC); + self->DSC = NULL; - free(data); return ALC_INVALID_VALUE; } - data->BufferBytes = DSCBDescription.dwBufferBytes; + self->BufferBytes = DSCBDescription.dwBufferBytes; SetDefaultWFXChannelOrder(device); - device->DeviceName = strdup(deviceName); - device->ExtraData = data; + al_string_copy_cstr(&device->DeviceName, deviceName); return ALC_NO_ERROR; } -static void DSoundCloseCapture(ALCdevice *device) +static void ALCdsoundCapture_close(ALCdsoundCapture *self) { - DSoundCaptureData *data = device->ExtraData; + DestroyRingBuffer(self->Ring); + self->Ring = NULL; - DestroyRingBuffer(data->Ring); - data->Ring = NULL; - - if(data->DSCbuffer != NULL) + if(self->DSCbuffer != NULL) { - IDirectSoundCaptureBuffer_Stop(data->DSCbuffer); - IDirectSoundCaptureBuffer_Release(data->DSCbuffer); - data->DSCbuffer = NULL; + IDirectSoundCaptureBuffer_Stop(self->DSCbuffer); + IDirectSoundCaptureBuffer_Release(self->DSCbuffer); + self->DSCbuffer = NULL; } - IDirectSoundCapture_Release(data->DSC); - data->DSC = NULL; - - free(data); - device->ExtraData = NULL; + IDirectSoundCapture_Release(self->DSC); + self->DSC = NULL; } -static void DSoundStartCapture(ALCdevice *device) +static ALCboolean ALCdsoundCapture_start(ALCdsoundCapture *self) { - DSoundCaptureData *data = device->ExtraData; HRESULT hr; - hr = IDirectSoundCaptureBuffer_Start(data->DSCbuffer, DSCBSTART_LOOPING); + hr = IDirectSoundCaptureBuffer_Start(self->DSCbuffer, DSCBSTART_LOOPING); if(FAILED(hr)) { ERR("start failed: 0x%08lx\n", hr); - aluHandleDisconnect(device); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); + return ALC_FALSE; } + + return ALC_TRUE; } -static void DSoundStopCapture(ALCdevice *device) +static void ALCdsoundCapture_stop(ALCdsoundCapture *self) { - DSoundCaptureData *data = device->ExtraData; HRESULT hr; - hr = IDirectSoundCaptureBuffer_Stop(data->DSCbuffer); + hr = IDirectSoundCaptureBuffer_Stop(self->DSCbuffer); if(FAILED(hr)) { ERR("stop failed: 0x%08lx\n", hr); - aluHandleDisconnect(device); + aluHandleDisconnect(STATIC_CAST(ALCbackend, self)->mDevice); } } -static ALCenum DSoundCaptureSamples(ALCdevice *Device, ALCvoid *pBuffer, ALCuint lSamples) +static ALCenum ALCdsoundCapture_captureSamples(ALCdsoundCapture *self, ALCvoid *buffer, ALCuint samples) { - DSoundCaptureData *data = Device->ExtraData; - ReadRingBuffer(data->Ring, pBuffer, lSamples); + ReadRingBuffer(self->Ring, buffer, samples); return ALC_NO_ERROR; } -static ALCuint DSoundAvailableSamples(ALCdevice *Device) +static ALCuint ALCdsoundCapture_availableSamples(ALCdsoundCapture *self) { - DSoundCaptureData *data = Device->ExtraData; + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; DWORD ReadCursor, LastCursor, BufferBytes, NumBytes; - VOID *ReadPtr1, *ReadPtr2; + void *ReadPtr1, *ReadPtr2; DWORD ReadCnt1, ReadCnt2; DWORD FrameSize; HRESULT hr; - if(!Device->Connected) + if(!device->Connected) goto done; - FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - BufferBytes = data->BufferBytes; - LastCursor = data->Cursor; + FrameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); + BufferBytes = self->BufferBytes; + LastCursor = self->Cursor; - hr = IDirectSoundCaptureBuffer_GetCurrentPosition(data->DSCbuffer, NULL, &ReadCursor); + hr = IDirectSoundCaptureBuffer_GetCurrentPosition(self->DSCbuffer, NULL, &ReadCursor); if(SUCCEEDED(hr)) { NumBytes = (ReadCursor-LastCursor + BufferBytes) % BufferBytes; if(NumBytes == 0) goto done; - hr = IDirectSoundCaptureBuffer_Lock(data->DSCbuffer, LastCursor, NumBytes, + hr = IDirectSoundCaptureBuffer_Lock(self->DSCbuffer, LastCursor, NumBytes, &ReadPtr1, &ReadCnt1, &ReadPtr2, &ReadCnt2, 0); } if(SUCCEEDED(hr)) { - WriteRingBuffer(data->Ring, ReadPtr1, ReadCnt1/FrameSize); + WriteRingBuffer(self->Ring, ReadPtr1, ReadCnt1/FrameSize); if(ReadPtr2 != NULL) - WriteRingBuffer(data->Ring, ReadPtr2, ReadCnt2/FrameSize); - hr = IDirectSoundCaptureBuffer_Unlock(data->DSCbuffer, + WriteRingBuffer(self->Ring, ReadPtr2, ReadCnt2/FrameSize); + hr = IDirectSoundCaptureBuffer_Unlock(self->DSCbuffer, ReadPtr1, ReadCnt1, ReadPtr2, ReadCnt2); - data->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes; + self->Cursor = (LastCursor+ReadCnt1+ReadCnt2) % BufferBytes; } if(FAILED(hr)) { ERR("update failed: 0x%08lx\n", hr); - aluHandleDisconnect(Device); + aluHandleDisconnect(device); } done: - return RingBufferSize(data->Ring); + return RingBufferSize(self->Ring); } -static const BackendFuncs DSoundFuncs = { - DSoundOpenPlayback, - DSoundClosePlayback, - DSoundResetPlayback, - DSoundStartPlayback, - DSoundStopPlayback, - DSoundOpenCapture, - DSoundCloseCapture, - DSoundStartCapture, - DSoundStopCapture, - DSoundCaptureSamples, - DSoundAvailableSamples, - ALCdevice_GetLatencyDefault -}; +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } + +typedef struct ALCdsoundBackendFactory { + DERIVE_FROM_TYPE(ALCbackendFactory); +} ALCdsoundBackendFactory; +#define ALCDSOUNDBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCdsoundBackendFactory, ALCbackendFactory) } } + +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void); + +static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory *self); +static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory *self); +static ALCboolean ALCdsoundBackendFactory_querySupport(ALCdsoundBackendFactory *self, ALCbackend_Type type); +static void ALCdsoundBackendFactory_probe(ALCdsoundBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory *self, ALCdevice *device, ALCbackend_Type type); +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCdsoundBackendFactory); -ALCboolean alcDSoundInit(BackendFuncs *FuncList) +ALCbackendFactory *ALCdsoundBackendFactory_getFactory(void) { + static ALCdsoundBackendFactory factory = ALCDSOUNDBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); +} + + +static ALCboolean ALCdsoundBackendFactory_init(ALCdsoundBackendFactory* UNUSED(self)) +{ + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + if(!DSoundLoad()) return ALC_FALSE; - *FuncList = DSoundFuncs; return ALC_TRUE; } -void alcDSoundDeinit(void) +static void ALCdsoundBackendFactory_deinit(ALCdsoundBackendFactory* UNUSED(self)) { - ALuint i; + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); - for(i = 0;i < NumPlaybackDevices;++i) - free(PlaybackDeviceList[i].name); - free(PlaybackDeviceList); - PlaybackDeviceList = NULL; - NumPlaybackDevices = 0; - - for(i = 0;i < NumCaptureDevices;++i) - free(CaptureDeviceList[i].name); - free(CaptureDeviceList); - CaptureDeviceList = NULL; - NumCaptureDevices = 0; + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); +#ifdef HAVE_DYNLOAD if(ds_handle) CloseLib(ds_handle); ds_handle = NULL; +#endif } -void alcDSoundProbe(enum DevProbe type) +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; - ALuint i; + /* Initialize COM to prevent name truncation */ + hrcom = CoInitialize(NULL); switch(type) { case ALL_DEVICE_PROBE: - for(i = 0;i < NumPlaybackDevices;++i) - free(PlaybackDeviceList[i].name); - free(PlaybackDeviceList); - PlaybackDeviceList = NULL; - NumPlaybackDevices = 0; - - hr = DirectSoundEnumerateA(DSoundEnumPlaybackDevices, NULL); + clear_devlist(&PlaybackDevices); + hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); if(FAILED(hr)) - ERR("Error enumerating DirectSound playback devices (%#x)!\n", (unsigned int)hr); - else - { - for(i = 0;i < NumPlaybackDevices;i++) - AppendAllDevicesList(PlaybackDeviceList[i].name); - } + ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: - for(i = 0;i < NumCaptureDevices;++i) - free(CaptureDeviceList[i].name); - free(CaptureDeviceList); - CaptureDeviceList = NULL; - NumCaptureDevices = 0; - - /* Initialize COM to prevent name truncation */ - hrcom = CoInitialize(NULL); - hr = DirectSoundCaptureEnumerateA(DSoundEnumCaptureDevices, NULL); + clear_devlist(&CaptureDevices); + hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); if(FAILED(hr)) - ERR("Error enumerating DirectSound capture devices (%#x)!\n", (unsigned int)hr); - else - { - for(i = 0;i < NumCaptureDevices;i++) - AppendCaptureDeviceList(CaptureDeviceList[i].name); - } - if(SUCCEEDED(hrcom)) - CoUninitialize(); + ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); break; } + if(SUCCEEDED(hrcom)) + CoUninitialize(); +} + +static ALCbackend* ALCdsoundBackendFactory_createBackend(ALCdsoundBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCdsoundPlayback *backend; + + backend = ALCdsoundPlayback_New(sizeof(*backend)); + if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); + + ALCdsoundPlayback_Construct(backend, device); + + return STATIC_CAST(ALCbackend, backend); + } + + if(type == ALCbackend_Capture) + { + ALCdsoundCapture *backend; + + backend = ALCdsoundCapture_New(sizeof(*backend)); + if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); + + ALCdsoundCapture_Construct(backend, device); + + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; } diff --git a/jni/openal-soft-android/Alc/backends/loopback.c b/jni/openal-soft-1.16.0/Alc/backends/loopback.c similarity index 90% rename from jni/openal-soft-android/Alc/backends/loopback.c rename to jni/openal-soft-1.16.0/Alc/backends/loopback.c index cd5b1a1e..505dfacf 100644 --- a/jni/openal-soft-android/Alc/backends/loopback.c +++ b/jni/openal-soft-1.16.0/Alc/backends/loopback.c @@ -44,7 +44,7 @@ static DECLARE_FORWARD(ALCloopback, ALCbackend, ALCuint, availableSamples) static DECLARE_FORWARD(ALCloopback, ALCbackend, ALint64, getLatency) static DECLARE_FORWARD(ALCloopback, ALCbackend, void, lock) static DECLARE_FORWARD(ALCloopback, ALCbackend, void, unlock) -static void ALCloopback_Delete(ALCloopback *self); +DECLARE_DEFAULT_ALLOCATORS(ALCloopback) DEFINE_ALCBACKEND_VTABLE(ALCloopback); @@ -59,7 +59,7 @@ static ALCenum ALCloopback_open(ALCloopback *self, const ALCchar *name) { ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -83,12 +83,6 @@ static void ALCloopback_stop(ALCloopback* UNUSED(self)) } -static void ALCloopback_Delete(ALCloopback *self) -{ - free(self); -} - - typedef struct ALCloopbackFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCloopbackFactory; @@ -127,14 +121,18 @@ static void ALCloopbackFactory_probe(ALCloopbackFactory* UNUSED(self), enum DevP static ALCbackend* ALCloopbackFactory_createBackend(ALCloopbackFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) { - ALCloopback *backend; + if(type == ALCbackend_Loopback) + { + ALCloopback *backend; - assert(type == ALCbackend_Loopback); + backend = ALCloopback_New(sizeof(*backend)); + if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); - backend = calloc(1, sizeof(*backend)); - if(!backend) return NULL; + ALCloopback_Construct(backend, device); - ALCloopback_Construct(backend, device); + return STATIC_CAST(ALCbackend, backend); + } - return STATIC_CAST(ALCbackend, backend); + return NULL; } diff --git a/jni/openal-soft-android/Alc/backends/mmdevapi.c b/jni/openal-soft-1.16.0/Alc/backends/mmdevapi.c similarity index 56% rename from jni/openal-soft-android/Alc/backends/mmdevapi.c rename to jni/openal-soft-1.16.0/Alc/backends/mmdevapi.c index fa7c54f9..430e1cb8 100644 --- a/jni/openal-soft-android/Alc/backends/mmdevapi.c +++ b/jni/openal-soft-1.16.0/Alc/backends/mmdevapi.c @@ -42,6 +42,9 @@ #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); @@ -59,31 +62,27 @@ DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80, typedef struct { - WCHAR *devid; - - IMMDevice *mmdev; - IAudioClient *client; - IAudioRenderClient *render; - HANDLE NotifyEvent; - - HANDLE MsgEvent; - - volatile UINT32 Padding; - - volatile int killNow; - althread_t thread; -} MMDevApiData; - - -typedef struct { - ALCchar *name; + al_string name; WCHAR *devid; } DevMap; +TYPEDEF_VECTOR(DevMap, vector_DevMap) -static DevMap *PlaybackDeviceList; -static ALuint NumPlaybackDevices; -static DevMap *CaptureDeviceList; -static ALuint NumCaptureDevices; +static void clear_devlist(vector_DevMap *list) +{ + DevMap *iter, *end; + + iter = VECTOR_ITER_BEGIN(*list); + end = VECTOR_ITER_END(*list); + for(;iter != end;iter++) + { + AL_STRING_DEINIT(iter->name); + free(iter->devid); + } + VECTOR_RESIZE(*list, 0); +} + +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; static HANDLE ThreadHdl; @@ -103,6 +102,12 @@ typedef struct { #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) @@ -112,45 +117,32 @@ static HRESULT WaitForResponse(ThreadRequest *req) } -static ALCchar *get_device_name(IMMDevice *device) +static void get_device_name(IMMDevice *device, al_string *name) { - ALCchar *name = NULL; IPropertyStore *ps; PROPVARIANT pvname; HRESULT hr; - int len; hr = IMMDevice_OpenPropertyStore(device, STGM_READ, &ps); if(FAILED(hr)) { WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - return calloc(1, 1); + return; } PropVariantInit(&pvname); hr = IPropertyStore_GetValue(ps, (const PROPERTYKEY*)&DEVPKEY_Device_FriendlyName, &pvname); if(FAILED(hr)) - { WARN("GetValue failed: 0x%08lx\n", hr); - name = calloc(1, 1); - } else - { - if((len=WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, NULL, 0, NULL, NULL)) > 0) - { - name = calloc(1, len); - WideCharToMultiByte(CP_ACP, 0, pvname.pwszVal, -1, name, len, NULL, NULL); - } - } + al_string_copy_wcstr(name, pvname.pwszVal); PropVariantClear(&pvname); IPropertyStore_Release(ps); - - return name; } -static void add_device(IMMDevice *device, DevMap *devmap) +static void add_device(IMMDevice *device, vector_DevMap *list) { LPWSTR devid; HRESULT hr; @@ -158,48 +150,52 @@ static void add_device(IMMDevice *device, DevMap *devmap) hr = IMMDevice_GetId(device, &devid); if(SUCCEEDED(hr)) { - devmap->devid = strdupW(devid); - devmap->name = get_device_name(device); - TRACE("Got device \"%s\", \"%ls\"\n", devmap->name, devmap->devid); + DevMap entry; + AL_STRING_INIT(entry.name); + + entry.devid = strdupW(devid); + get_device_name(device, &entry.name); + CoTaskMemFree(devid); + + TRACE("Got device \"%s\", \"%ls\"\n", al_string_get_cstr(entry.name), entry.devid); + VECTOR_PUSH_BACK(*list, entry); } } -static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALuint *numdevs) +static HRESULT probe_devices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, vector_DevMap *list) { IMMDeviceCollection *coll; IMMDevice *defdev = NULL; - DevMap *devlist = NULL; HRESULT hr; UINT count; - UINT idx; 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 NULL; + return hr; } - idx = count = 0; + count = 0; hr = IMMDeviceCollection_GetCount(coll, &count); if(SUCCEEDED(hr) && count > 0) { - devlist = calloc(count, sizeof(*devlist)); - if(!devlist) + clear_devlist(list); + if(!VECTOR_RESERVE(*list, count+1)) { IMMDeviceCollection_Release(coll); - return NULL; + return E_OUTOFMEMORY; } hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, flowdir, eMultimedia, &defdev); } if(SUCCEEDED(hr) && defdev != NULL) - add_device(defdev, &devlist[idx++]); + add_device(defdev, list); - for(i = 0;i < count && idx < count;++i) + for(i = 0;i < count;++i) { IMMDevice *device; @@ -207,7 +203,7 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu continue; if(device != defdev) - add_device(device, &devlist[idx++]); + add_device(device, list); IMMDevice_Release(device); } @@ -215,15 +211,269 @@ static DevMap *ProbeDevices(IMMDeviceEnumerator *devenum, EDataFlow flowdir, ALu if(defdev) IMMDevice_Release(defdev); IMMDeviceCollection_Release(coll); - *numdevs = idx; - return devlist; + return S_OK; } -FORCE_ALIGN static ALuint MMDevApiProc(ALvoid *ptr) +/* 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) { - ALCdevice *device = ptr; - MMDevApiData *data = device->ExtraData; + 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\n", msg.message); + 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 ALint64 ALCmmdevPlayback_getLatency(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; @@ -236,17 +486,17 @@ FORCE_ALIGN static ALuint MMDevApiProc(ALvoid *ptr) ALCdevice_Lock(device); aluHandleDisconnect(device); ALCdevice_Unlock(device); - return 0; + return 1; } SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); update_size = device->UpdateSize; buffer_len = update_size * device->NumUpdates; - while(!data->killNow) + while(!self->killNow) { - hr = IAudioClient_GetCurrentPadding(data->client, &written); + hr = IAudioClient_GetCurrentPadding(self->client, &written); if(FAILED(hr)) { ERR("Failed to get padding: 0x%08lx\n", hr); @@ -255,27 +505,27 @@ FORCE_ALIGN static ALuint MMDevApiProc(ALvoid *ptr) ALCdevice_Unlock(device); break; } - data->Padding = written; + self->Padding = written; len = buffer_len - written; if(len < update_size) { DWORD res; - res = WaitForSingleObjectEx(data->NotifyEvent, 2000, FALSE); + 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(data->render, len, &buffer); + hr = IAudioRenderClient_GetBuffer(self->render, len, &buffer); if(SUCCEEDED(hr)) { ALCdevice_Lock(device); aluMixData(device, buffer, len); - data->Padding = written + len; + self->Padding = written + len; ALCdevice_Unlock(device); - hr = IAudioRenderClient_ReleaseBuffer(data->render, len, 0); + hr = IAudioRenderClient_ReleaseBuffer(self->render, len, 0); } if(FAILED(hr)) { @@ -286,7 +536,7 @@ FORCE_ALIGN static ALuint MMDevApiProc(ALvoid *ptr) break; } } - data->Padding = 0; + self->Padding = 0; CoUninitialize(); return 0; @@ -332,16 +582,178 @@ static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX * return ALC_TRUE; } -static HRESULT DoReset(ALCdevice *device) + +static ALCenum ALCmmdevPlayback_open(ALCmmdevPlayback *self, const ALCchar *deviceName) { - MMDevApiData *data = device->ExtraData; + HRESULT hr = S_OK; + + self->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + self->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if(self->NotifyEvent == NULL || self->MsgEvent == NULL) + { + ERR("Failed to create message events: %lu\n", GetLastError()); + hr = E_FAIL; + } + + if(SUCCEEDED(hr)) + { + if(deviceName) + { + const DevMap *iter, *end; + + 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; + iter = VECTOR_ITER_BEGIN(PlaybackDevices); + end = VECTOR_ITER_END(PlaybackDevices); + for(;iter != end;iter++) + { + if(al_string_cmp_cstr(iter->name, deviceName) == 0) + { + self->devid = strdupW(iter->devid); + hr = S_OK; + break; + } + } + if(FAILED(hr)) + WARN("Failed to find device name matching \"%s\"\n", deviceName); + } + } + + 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; + get_device_name(self->mmdev, &device->DeviceName); + } + + 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; WAVEFORMATEXTENSIBLE OutputType; WAVEFORMATEX *wfx = NULL; REFERENCE_TIME min_per, buf_time; UINT32 buffer_len, min_len; + void *ptr = NULL; HRESULT hr; - hr = IAudioClient_GetMixFormat(data->client, &wfx); + 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); @@ -451,11 +863,11 @@ static HRESULT DoReset(ALCdevice *device) OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * OutputType.Format.nBlockAlign; - hr = IAudioClient_IsFormatSupported(data->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); + 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(data->client, &wfx); + hr = IAudioClient_GetMixFormat(self->client, &wfx); } if(FAILED(hr)) { @@ -527,7 +939,7 @@ static HRESULT DoReset(ALCdevice *device) SetDefaultWFXChannelOrder(device); - hr = IAudioClient_Initialize(data->client, AUDCLNT_SHAREMODE_SHARED, + hr = IAudioClient_Initialize(self->client, AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buf_time, 0, &OutputType.Format, NULL); if(FAILED(hr)) @@ -536,14 +948,14 @@ static HRESULT DoReset(ALCdevice *device) return hr; } - hr = IAudioClient_GetDevicePeriod(data->client, &min_per, NULL); + 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(data->client, &buffer_len); + hr = IAudioClient_GetBufferSize(self->client, &buffer_len); } if(FAILED(hr)) { @@ -560,242 +972,108 @@ static HRESULT DoReset(ALCdevice *device) 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 DWORD CALLBACK MMDevApiMsgProc(void *ptr) +static ALCboolean ALCmmdevPlayback_start(ALCmmdevPlayback *self) { - ThreadRequest *req = ptr; - IMMDeviceEnumerator *Enumerator; - ALuint deviceCount = 0; - MMDevApiData *data; - ALCdevice *device; - HRESULT hr, cohr; - MSG msg; + ThreadRequest req = { self->MsgEvent, 0 }; + HRESULT hr = E_FAIL; - TRACE("Starting message thread\n"); + if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)STATIC_CAST(ALCmmdevProxy, self))) + hr = WaitForResponse(&req); - cohr = CoInitialize(NULL); - if(FAILED(cohr)) - { - WARN("Failed to initialize COM: 0x%08lx\n", cohr); - req->result = cohr; - SetEvent(req->FinishedEvt); - return 0; - } + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; +} - hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); +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)) { - WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); - CoUninitialize(); - req->result = hr; - SetEvent(req->FinishedEvt); - return 0; - } - Enumerator = ptr; - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - - CoUninitialize(); - - req->result = S_OK; - SetEvent(req->FinishedEvt); - - TRACE("Starting message loop\n"); - while(GetMessage(&msg, NULL, WM_USER_First, WM_USER_Last)) - { - TRACE("Got message %u\n", msg.message); - switch(msg.message) + self->render = ptr; + self->killNow = 0; + if(althrd_create(&self->thread, ALCmmdevPlayback_mixerProc, self) != althrd_success) { - case WM_USER_OpenDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - 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(!data->devid) - hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &data->mmdev); - else - hr = IMMDeviceEnumerator_GetDevice(Enumerator, data->devid, &data->mmdev); - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - } - if(SUCCEEDED(hr)) - hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); - if(SUCCEEDED(hr)) - { - data->client = ptr; - device->DeviceName = get_device_name(data->mmdev); - } - - if(FAILED(hr)) - { - if(data->mmdev) - IMMDevice_Release(data->mmdev); - data->mmdev = NULL; - if(--deviceCount == 0 && SUCCEEDED(cohr)) - CoUninitialize(); - } - - req->result = hr; - SetEvent(req->FinishedEvt); - continue; - - case WM_USER_ResetDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - - req->result = DoReset(device); - SetEvent(req->FinishedEvt); - continue; - - case WM_USER_StartDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - ResetEvent(data->NotifyEvent); - hr = IAudioClient_SetEventHandle(data->client, data->NotifyEvent); - if(FAILED(hr)) - ERR("Failed to set event handle: 0x%08lx\n", hr); - else - { - hr = IAudioClient_Start(data->client); - if(FAILED(hr)) - ERR("Failed to start audio client: 0x%08lx\n", hr); - } - - if(SUCCEEDED(hr)) - hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &ptr); - if(SUCCEEDED(hr)) - { - data->render = ptr; - if(!StartThread(&data->thread, MMDevApiProc, device)) - { - if(data->render) - IAudioRenderClient_Release(data->render); - data->render = NULL; - IAudioClient_Stop(data->client); - ERR("Failed to start thread\n"); - hr = E_FAIL; - } - } - - req->result = hr; - SetEvent(req->FinishedEvt); - continue; - - case WM_USER_StopDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - if(data->thread) - { - data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - - data->killNow = 0; - - IAudioRenderClient_Release(data->render); - data->render = NULL; - IAudioClient_Stop(data->client); - } - - req->result = S_OK; - SetEvent(req->FinishedEvt); - continue; - - case WM_USER_CloseDevice: - req = (ThreadRequest*)msg.wParam; - device = (ALCdevice*)msg.lParam; - data = device->ExtraData; - - IAudioClient_Release(data->client); - data->client = NULL; - - IMMDevice_Release(data->mmdev); - data->mmdev = NULL; - - if(--deviceCount == 0) - CoUninitialize(); - - req->result = S_OK; - SetEvent(req->FinishedEvt); - 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)) - { - EDataFlow flowdir; - DevMap **devlist; - ALuint *numdevs; - ALuint i; - - Enumerator = ptr; - if(msg.lParam == CAPTURE_DEVICE_PROBE) - { - flowdir = eCapture; - devlist = &CaptureDeviceList; - numdevs = &NumCaptureDevices; - } - else - { - flowdir = eRender; - devlist = &PlaybackDeviceList; - numdevs = &NumPlaybackDevices; - } - - for(i = 0;i < *numdevs;i++) - { - free((*devlist)[i].name); - free((*devlist)[i].devid); - } - free(*devlist); - *devlist = NULL; - *numdevs = 0; - - *devlist = ProbeDevices(Enumerator, flowdir, numdevs); - - IMMDeviceEnumerator_Release(Enumerator); - Enumerator = NULL; - } - - if(--deviceCount == 0 && SUCCEEDED(cohr)) - CoUninitialize(); - - req->result = S_OK; - SetEvent(req->FinishedEvt); - continue; - - default: - ERR("Unexpected message: %u\n", msg.message); - continue; + if(self->render) + IAudioRenderClient_Release(self->render); + self->render = NULL; + IAudioClient_Stop(self->client); + ERR("Failed to start thread\n"); + hr = E_FAIL; } } - TRACE("Message loop finished\n"); - return 0; + 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 ALint64 ALCmmdevPlayback_getLatency(ALCmmdevPlayback *self) +{ + ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; + return (ALint64)self->Padding * 1000000000 / device->Frequency; +} + + +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; @@ -809,7 +1087,7 @@ static BOOL MMDevApiLoad(void) ERR("Failed to create event: %lu\n", GetLastError()); else { - ThreadHdl = CreateThread(NULL, 0, MMDevApiMsgProc, &req, 0, &ThreadID); + ThreadHdl = CreateThread(NULL, 0, ALCmmdevProxy_messageHandler, &req, 0, &ThreadID); if(ThreadHdl != NULL) InitResult = WaitForResponse(&req); CloseHandle(req.FinishedEvt); @@ -818,189 +1096,23 @@ static BOOL MMDevApiLoad(void) return SUCCEEDED(InitResult); } - -static ALCenum MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName) +static ALCboolean ALCmmdevBackendFactory_init(ALCmmdevBackendFactory* UNUSED(self)) { - MMDevApiData *data = NULL; - HRESULT hr; + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); - //Initialise requested device - data = calloc(1, sizeof(MMDevApiData)); - if(!data) - return ALC_OUT_OF_MEMORY; - device->ExtraData = data; - - hr = S_OK; - data->NotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - data->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->NotifyEvent == NULL || data->MsgEvent == NULL) - hr = E_FAIL; - - if(SUCCEEDED(hr)) - { - if(deviceName) - { - ALuint i; - - if(!PlaybackDeviceList) - { - ThreadRequest req = { data->MsgEvent, 0 }; - if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, ALL_DEVICE_PROBE)) - (void)WaitForResponse(&req); - } - - hr = E_FAIL; - for(i = 0;i < NumPlaybackDevices;i++) - { - if(strcmp(deviceName, PlaybackDeviceList[i].name) == 0) - { - data->devid = strdupW(PlaybackDeviceList[i].devid); - hr = S_OK; - break; - } - } - } - } - - if(SUCCEEDED(hr)) - { - ThreadRequest req = { data->MsgEvent, 0 }; - - hr = E_FAIL; - if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)device)) - hr = WaitForResponse(&req); - } - - if(FAILED(hr)) - { - if(data->NotifyEvent != NULL) - CloseHandle(data->NotifyEvent); - data->NotifyEvent = NULL; - if(data->MsgEvent != NULL) - CloseHandle(data->MsgEvent); - data->MsgEvent = NULL; - - free(data->devid); - data->devid = NULL; - - free(data); - device->ExtraData = NULL; - - ERR("Device init failed: 0x%08lx\n", hr); - return ALC_INVALID_VALUE; - } - - return ALC_NO_ERROR; -} - -static void MMDevApiClosePlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - - if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)device)) - (void)WaitForResponse(&req); - - CloseHandle(data->MsgEvent); - data->MsgEvent = NULL; - - CloseHandle(data->NotifyEvent); - data->NotifyEvent = NULL; - - free(data->devid); - data->devid = NULL; - - free(data); - device->ExtraData = NULL; -} - -static ALCboolean MMDevApiResetPlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - HRESULT hr = E_FAIL; - - if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)device)) - hr = WaitForResponse(&req); - - return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; -} - -static ALCboolean MMDevApiStartPlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - HRESULT hr = E_FAIL; - - if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)device)) - hr = WaitForResponse(&req); - - return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; -} - -static void MMDevApiStopPlayback(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - ThreadRequest req = { data->MsgEvent, 0 }; - - if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)device)) - (void)WaitForResponse(&req); -} - - -static ALint64 MMDevApiGetLatency(ALCdevice *device) -{ - MMDevApiData *data = device->ExtraData; - - return (ALint64)data->Padding * 1000000000 / device->Frequency; -} - - -static const BackendFuncs MMDevApiFuncs = { - MMDevApiOpenPlayback, - MMDevApiClosePlayback, - MMDevApiResetPlayback, - MMDevApiStartPlayback, - MMDevApiStopPlayback, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - MMDevApiGetLatency -}; - - -ALCboolean alcMMDevApiInit(BackendFuncs *FuncList) -{ if(!MMDevApiLoad()) return ALC_FALSE; - *FuncList = MMDevApiFuncs; return ALC_TRUE; } -void alcMMDevApiDeinit(void) +static void ALCmmdevBackendFactory_deinit(ALCmmdevBackendFactory* UNUSED(self)) { - ALuint i; + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); - for(i = 0;i < NumPlaybackDevices;i++) - { - free(PlaybackDeviceList[i].name); - free(PlaybackDeviceList[i].devid); - } - free(PlaybackDeviceList); - PlaybackDeviceList = NULL; - NumPlaybackDevices = 0; - - for(i = 0;i < NumCaptureDevices;i++) - { - free(CaptureDeviceList[i].name); - free(CaptureDeviceList[i].devid); - } - free(CaptureDeviceList); - CaptureDeviceList = NULL; - NumCaptureDevices = 0; + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); if(ThreadHdl) { @@ -1011,34 +1123,61 @@ void alcMMDevApiDeinit(void) } } -void alcMMDevApiProbe(enum DevProbe type) +static ALCboolean ALCmmdevBackendFactory_querySupport(ALCmmdevBackendFactory* UNUSED(self), ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + return ALC_TRUE; + return ALC_FALSE; +} + +static void ALCmmdevBackendFactory_probe(ALCmmdevBackendFactory* UNUSED(self), enum DevProbe type) { ThreadRequest req = { NULL, 0 }; - HRESULT hr = E_FAIL; - switch(type) + req.FinishedEvt = CreateEvent(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: - req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL); - if(req.FinishedEvt == NULL) - ERR("Failed to create event: %lu\n", GetLastError()); - else if(PostThreadMessage(ThreadID, WM_USER_Enumerate, (WPARAM)&req, type)) - hr = WaitForResponse(&req); - if(SUCCEEDED(hr)) - { - ALuint i; - for(i = 0;i < NumPlaybackDevices;i++) - { - if(PlaybackDeviceList[i].name) - AppendAllDevicesList(PlaybackDeviceList[i].name); - } - } + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); break; - } - if(req.FinishedEvt != NULL) + } CloseHandle(req.FinishedEvt); - req.FinishedEvt = NULL; + req.FinishedEvt = NULL; + } +} + +static ALCbackend* ALCmmdevBackendFactory_createBackend(ALCmmdevBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) +{ + if(type == ALCbackend_Playback) + { + ALCmmdevPlayback *backend; + + backend = ALCmmdevPlayback_New(sizeof(*backend)); + if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); + + ALCmmdevPlayback_Construct(backend, device); + + return STATIC_CAST(ALCbackend, backend); + } + + return NULL; +} + + +ALCbackendFactory *ALCmmdevBackendFactory_getFactory(void) +{ + static ALCmmdevBackendFactory factory = ALCMMDEVBACKENDFACTORY_INITIALIZER; + return STATIC_CAST(ALCbackendFactory, &factory); } diff --git a/jni/openal-soft-android/Alc/backends/null.c b/jni/openal-soft-1.16.0/Alc/backends/null.c similarity index 75% rename from jni/openal-soft-android/Alc/backends/null.c rename to jni/openal-soft-1.16.0/Alc/backends/null.c index a7056369..3f09c5d6 100644 --- a/jni/openal-soft-android/Alc/backends/null.c +++ b/jni/openal-soft-1.16.0/Alc/backends/null.c @@ -37,11 +37,10 @@ typedef struct ALCnullBackend { DERIVE_FROM_TYPE(ALCbackend); volatile int killNow; - althread_t thread; + althrd_t thread; } ALCnullBackend; -DECLARE_ALCBACKEND_VTABLE(ALCnullBackend); -static ALuint ALCnullBackend_mixerProc(ALvoid *ptr); +static int ALCnullBackend_mixerProc(void *ptr); static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device); static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, Destruct) @@ -55,6 +54,10 @@ static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALCuint, availableSamples) static DECLARE_FORWARD(ALCnullBackend, ALCbackend, ALint64, getLatency) static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, lock) static DECLARE_FORWARD(ALCnullBackend, ALCbackend, void, unlock) +DECLARE_DEFAULT_ALLOCATORS(ALCnullBackend) + +DEFINE_ALCBACKEND_VTABLE(ALCnullBackend); + static const ALCchar nullDevice[] = "No Output"; @@ -66,42 +69,49 @@ static void ALCnullBackend_Construct(ALCnullBackend *self, ALCdevice *device) } -static ALuint ALCnullBackend_mixerProc(ALvoid *ptr) +static int ALCnullBackend_mixerProc(void *ptr) { ALCnullBackend *self = (ALCnullBackend*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; - ALuint now, start; + struct timespec now, start; ALuint64 avail, done; + const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / + device->Frequency / 2); SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); done = 0; - start = timeGetTime(); + if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) + { + ERR("Failed to get starting time\n"); + return 1; + } while(!self->killNow && device->Connected) { - now = timeGetTime(); + if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) + { + ERR("Failed to get current time\n"); + return 1; + } - avail = (ALuint64)(now-start) * device->Frequency / 1000; + avail = (now.tv_sec - start.tv_sec) * device->Frequency; + avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000; if(avail < done) { - /* Timer wrapped (50 days???). Add the remainder of the cycle to - * the available count and reset the number of samples done */ - avail += (U64(1)<<32)*device->Frequency/1000 - done; - done = 0; - } - if(avail-done < device->UpdateSize) - { - ALuint restTime = (ALuint)((device->UpdateSize - (avail-done)) * 1000 / - device->Frequency); - Sleep(restTime); - continue; + /* Oops, time skipped backwards. Reset the number of samples done + * with one update available since we (likely) just came back from + * sleeping. */ + done = avail - device->UpdateSize; } - do { + if(avail-done < device->UpdateSize) + al_nssleep(0, restTime); + else while(avail-done >= device->UpdateSize) + { aluMixData(device, NULL, device->UpdateSize); done += device->UpdateSize; - } while(avail-done >= device->UpdateSize); + } } return 0; @@ -118,7 +128,7 @@ static ALCenum ALCnullBackend_open(ALCnullBackend *self, const ALCchar *name) return ALC_INVALID_VALUE; device = STATIC_CAST(ALCbackend, self)->mDevice; - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -135,32 +145,24 @@ static ALCboolean ALCnullBackend_reset(ALCnullBackend *self) static ALCboolean ALCnullBackend_start(ALCnullBackend *self) { - if(!StartThread(&self->thread, ALCnullBackend_mixerProc, self)) + self->killNow = 0; + if(althrd_create(&self->thread, ALCnullBackend_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; } static void ALCnullBackend_stop(ALCnullBackend *self) { - if(!self->thread) + int res; + + if(self->killNow) return; self->killNow = 1; - StopThread(self->thread); - self->thread = NULL; - - self->killNow = 0; + althrd_join(self->thread, &res); } -static void ALCnullBackend_Delete(ALCnullBackend *self) -{ - free(self); -} - -DEFINE_ALCBACKEND_VTABLE(ALCnullBackend); - - typedef struct ALCnullBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCnullBackendFactory; @@ -209,14 +211,18 @@ static void ALCnullBackendFactory_probe(ALCnullBackendFactory* UNUSED(self), enu static ALCbackend* ALCnullBackendFactory_createBackend(ALCnullBackendFactory* UNUSED(self), ALCdevice *device, ALCbackend_Type type) { - ALCnullBackend *backend; + if(type == ALCbackend_Playback) + { + ALCnullBackend *backend; - assert(type == ALCbackend_Playback); + backend = ALCnullBackend_New(sizeof(*backend)); + if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); - backend = calloc(1, sizeof(*backend)); - if(!backend) return NULL; + ALCnullBackend_Construct(backend, device); - ALCnullBackend_Construct(backend, device); + return STATIC_CAST(ALCbackend, backend); + } - return STATIC_CAST(ALCbackend, backend); + return NULL; } diff --git a/jni/openal-soft-android/Alc/backends/opensl.c b/jni/openal-soft-1.16.0/Alc/backends/opensl.c similarity index 78% rename from jni/openal-soft-android/Alc/backends/opensl.c rename to jni/openal-soft-1.16.0/Alc/backends/opensl.c index 76cbaf1a..220e6e5c 100644 --- a/jni/openal-soft-android/Alc/backends/opensl.c +++ b/jni/openal-soft-1.16.0/Alc/backends/opensl.c @@ -28,62 +28,9 @@ #include -#if 1 #include -#else -extern SLAPIENTRY const SLInterfaceID SL_IID_ANDROIDSIMPLEBUFFERQUEUE; - -struct SLAndroidSimpleBufferQueueItf_; -typedef const struct SLAndroidSimpleBufferQueueItf_ * const * SLAndroidSimpleBufferQueueItf; - -typedef void (*slAndroidSimpleBufferQueueCallback)(SLAndroidSimpleBufferQueueItf caller, void *pContext); - -typedef struct SLAndroidSimpleBufferQueueState_ { - SLuint32 count; - SLuint32 index; -} SLAndroidSimpleBufferQueueState; - - -struct SLAndroidSimpleBufferQueueItf_ { - SLresult (*Enqueue) ( - SLAndroidSimpleBufferQueueItf self, - const void *pBuffer, - SLuint32 size - ); - SLresult (*Clear) ( - SLAndroidSimpleBufferQueueItf self - ); - SLresult (*GetState) ( - SLAndroidSimpleBufferQueueItf self, - SLAndroidSimpleBufferQueueState *pState - ); - SLresult (*RegisterCallback) ( - SLAndroidSimpleBufferQueueItf self, - slAndroidSimpleBufferQueueCallback callback, - void* pContext - ); -}; - -#define SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE ((SLuint32) 0x800007BD) - -typedef struct SLDataLocator_AndroidSimpleBufferQueue { - SLuint32 locatorType; - SLuint32 numBuffers; -} SLDataLocator_AndroidSimpleBufferQueue; - -#endif /* Helper macros */ -#define SLObjectItf_Realize(a,b) ((*(a))->Realize((a),(b))) -#define SLObjectItf_GetInterface(a,b,c) ((*(a))->GetInterface((a),(b),(c))) -#define SLObjectItf_Destroy(a) ((*(a))->Destroy((a))) - -#define SLEngineItf_CreateOutputMix(a,b,c,d,e) ((*(a))->CreateOutputMix((a),(b),(c),(d),(e))) -#define SLEngineItf_CreateAudioPlayer(a,b,c,d,e,f,g) ((*(a))->CreateAudioPlayer((a),(b),(c),(d),(e),(f),(g))) - -#define SLPlayItf_SetPlayState(a,b) ((*(a))->SetPlayState((a),(b))) - -/* Should start using these generic callers instead of the name-specific ones above. */ #define VCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS #define VCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS @@ -186,7 +133,7 @@ static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *context) buf = (ALbyte*)data->buffer + data->curBuffer*data->bufferSize; aluMixData(Device, buf, data->bufferSize/data->frameSize); - result = (*bq)->Enqueue(bq, buf, data->bufferSize); + result = VCALL(bq,Enqueue)(buf, data->bufferSize); PRINTERR(result, "bq->Enqueue"); data->curBuffer = (data->curBuffer+1) % Device->NumUpdates; @@ -212,33 +159,33 @@ static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName PRINTERR(result, "slCreateEngine"); if(SL_RESULT_SUCCESS == result) { - result = SLObjectItf_Realize(data->engineObject, SL_BOOLEAN_FALSE); + result = VCALL(data->engineObject,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "engine->Realize"); } if(SL_RESULT_SUCCESS == result) { - result = SLObjectItf_GetInterface(data->engineObject, SL_IID_ENGINE, &data->engine); + result = VCALL(data->engineObject,GetInterface)(SL_IID_ENGINE, &data->engine); PRINTERR(result, "engine->GetInterface"); } if(SL_RESULT_SUCCESS == result) { - result = SLEngineItf_CreateOutputMix(data->engine, &data->outputMix, 0, NULL, NULL); + result = VCALL(data->engine,CreateOutputMix)(&data->outputMix, 0, NULL, NULL); PRINTERR(result, "engine->CreateOutputMix"); } if(SL_RESULT_SUCCESS == result) { - result = SLObjectItf_Realize(data->outputMix, SL_BOOLEAN_FALSE); + result = VCALL(data->outputMix,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "outputMix->Realize"); } if(SL_RESULT_SUCCESS != result) { if(data->outputMix != NULL) - SLObjectItf_Destroy(data->outputMix); + VCALL0(data->outputMix,Destroy)(); data->outputMix = NULL; if(data->engineObject != NULL) - SLObjectItf_Destroy(data->engineObject); + VCALL0(data->engineObject,Destroy)(); data->engineObject = NULL; data->engine = NULL; @@ -246,7 +193,7 @@ static ALCenum opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName return ALC_INVALID_VALUE; } - Device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&Device->DeviceName, deviceName); Device->ExtraData = data; return ALC_NO_ERROR; @@ -258,13 +205,13 @@ static void opensl_close_playback(ALCdevice *Device) osl_data *data = Device->ExtraData; if(data->bufferQueueObject != NULL) - SLObjectItf_Destroy(data->bufferQueueObject); + VCALL0(data->bufferQueueObject,Destroy)(); data->bufferQueueObject = NULL; - SLObjectItf_Destroy(data->outputMix); + VCALL0(data->outputMix,Destroy)(); data->outputMix = NULL; - SLObjectItf_Destroy(data->engineObject); + VCALL0(data->engineObject,Destroy)(); data->engineObject = NULL; data->engine = NULL; @@ -321,21 +268,21 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device) if(data->bufferQueueObject != NULL) - SLObjectItf_Destroy(data->bufferQueueObject); + VCALL0(data->bufferQueueObject,Destroy)(); data->bufferQueueObject = NULL; - result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req); + result = VCALL(data->engine,CreateAudioPlayer)(&data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req); PRINTERR(result, "engine->CreateAudioPlayer"); if(SL_RESULT_SUCCESS == result) { - result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE); + result = VCALL(data->bufferQueueObject,Realize)(SL_BOOLEAN_FALSE); PRINTERR(result, "bufferQueue->Realize"); } if(SL_RESULT_SUCCESS != result) { if(data->bufferQueueObject != NULL) - SLObjectItf_Destroy(data->bufferQueueObject); + VCALL0(data->bufferQueueObject,Destroy)(); data->bufferQueueObject = NULL; return ALC_FALSE; @@ -352,11 +299,11 @@ static ALCboolean opensl_start_playback(ALCdevice *Device) SLresult result; ALuint i; - result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue); + result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { - result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device); + result = VCALL(bufferQueue,RegisterCallback)(opensl_callback, Device); PRINTERR(result, "bufferQueue->RegisterCallback"); } if(SL_RESULT_SUCCESS == result) @@ -376,26 +323,26 @@ static ALCboolean opensl_start_playback(ALCdevice *Device) if(SL_RESULT_SUCCESS == result) { ALvoid *buf = (ALbyte*)data->buffer + i*data->bufferSize; - result = (*bufferQueue)->Enqueue(bufferQueue, buf, data->bufferSize); + result = VCALL(bufferQueue,Enqueue)(buf, data->bufferSize); PRINTERR(result, "bufferQueue->Enqueue"); } } data->curBuffer = 0; if(SL_RESULT_SUCCESS == result) { - result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player); + result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_PLAY, &player); PRINTERR(result, "bufferQueue->GetInterface"); } if(SL_RESULT_SUCCESS == result) { - result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING); + result = VCALL(player,SetPlayState)(SL_PLAYSTATE_PLAYING); PRINTERR(result, "player->SetPlayState"); } if(SL_RESULT_SUCCESS != result) { if(data->bufferQueueObject != NULL) - SLObjectItf_Destroy(data->bufferQueueObject); + VCALL0(data->bufferQueueObject,Destroy)(); data->bufferQueueObject = NULL; free(data->buffer); diff --git a/jni/openal-soft-android/Alc/backends/oss.c b/jni/openal-soft-1.16.0/Alc/backends/oss.c similarity index 93% rename from jni/openal-soft-android/Alc/backends/oss.c rename to jni/openal-soft-1.16.0/Alc/backends/oss.c index c79793c2..93e026e9 100644 --- a/jni/openal-soft-android/Alc/backends/oss.c +++ b/jni/openal-soft-1.16.0/Alc/backends/oss.c @@ -78,10 +78,10 @@ typedef struct ALCplaybackOSS { int data_size; volatile int killNow; - althread_t thread; + althrd_t thread; } ALCplaybackOSS; -static ALuint ALCplaybackOSS_mixerProc(ALvoid *ptr); +static int ALCplaybackOSS_mixerProc(void *ptr); static void ALCplaybackOSS_Construct(ALCplaybackOSS *self, ALCdevice *device); static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, Destruct) @@ -95,11 +95,11 @@ static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALCuint, availableSamples) static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, ALint64, getLatency) static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, lock) static DECLARE_FORWARD(ALCplaybackOSS, ALCbackend, void, unlock) -static void ALCplaybackOSS_Delete(ALCplaybackOSS *self); +DECLARE_DEFAULT_ALLOCATORS(ALCplaybackOSS) DEFINE_ALCBACKEND_VTABLE(ALCplaybackOSS); -static ALuint ALCplaybackOSS_mixerProc(ALvoid *ptr) +static int ALCplaybackOSS_mixerProc(void *ptr) { ALCplaybackOSS *self = (ALCplaybackOSS*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -107,7 +107,7 @@ static ALuint ALCplaybackOSS_mixerProc(ALvoid *ptr) ssize_t wrote; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); @@ -131,7 +131,7 @@ static ALuint ALCplaybackOSS_mixerProc(ALvoid *ptr) break; } - Sleep(1); + al_nssleep(0, 1000000); continue; } @@ -168,7 +168,7 @@ static ALCenum ALCplaybackOSS_open(ALCplaybackOSS *self, const ALCchar *name) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } @@ -275,7 +275,8 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self) self->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); self->mix_data = calloc(1, self->data_size); - if(!StartThread(&self->thread, ALCplaybackOSS_mixerProc, self)) + self->killNow = 0; + if(althrd_create(&self->thread, ALCplaybackOSS_mixerProc, self) != althrd_success) { free(self->mix_data); self->mix_data = NULL; @@ -287,14 +288,14 @@ static ALCboolean ALCplaybackOSS_start(ALCplaybackOSS *self) static void ALCplaybackOSS_stop(ALCplaybackOSS *self) { - if(!self->thread) + int res; + + if(self->killNow) return; self->killNow = 1; - StopThread(self->thread); - self->thread = NULL; + althrd_join(self->thread, &res); - self->killNow = 0; if(ioctl(self->fd, SNDCTL_DSP_RESET) != 0) ERR("Error resetting device: %s\n", strerror(errno)); @@ -302,11 +303,6 @@ static void ALCplaybackOSS_stop(ALCplaybackOSS *self) self->mix_data = NULL; } -static void ALCplaybackOSS_Delete(ALCplaybackOSS *self) -{ - free(self); -} - typedef struct ALCcaptureOSS { DERIVE_FROM_TYPE(ALCbackend); @@ -320,10 +316,10 @@ typedef struct ALCcaptureOSS { int doCapture; volatile int killNow; - althread_t thread; + althrd_t thread; } ALCcaptureOSS; -static ALuint ALCcaptureOSS_recordProc(ALvoid *ptr); +static int ALCcaptureOSS_recordProc(void *ptr); static void ALCcaptureOSS_Construct(ALCcaptureOSS *self, ALCdevice *device); static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, Destruct) @@ -337,11 +333,11 @@ static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self); static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, ALint64, getLatency) static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, lock) static DECLARE_FORWARD(ALCcaptureOSS, ALCbackend, void, unlock) -static void ALCcaptureOSS_Delete(ALCcaptureOSS *self); +DECLARE_DEFAULT_ALLOCATORS(ALCcaptureOSS) DEFINE_ALCBACKEND_VTABLE(ALCcaptureOSS); -static ALuint ALCcaptureOSS_recordProc(ALvoid *ptr) +static int ALCcaptureOSS_recordProc(void *ptr) { ALCcaptureOSS *self = (ALCcaptureOSS*)ptr; ALCdevice *device = STATIC_CAST(ALCbackend, self)->mDevice; @@ -349,7 +345,7 @@ static ALuint ALCcaptureOSS_recordProc(ALvoid *ptr) int amt; SetRTPriority(); - SetThreadName("alsoft-record"); + althrd_setname(althrd_current(), "alsoft-record"); frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); @@ -366,7 +362,7 @@ static ALuint ALCcaptureOSS_recordProc(ALvoid *ptr) } if(amt == 0) { - Sleep(1); + al_nssleep(0, 1000000); continue; } if(self->doCapture) @@ -488,7 +484,8 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) self->data_size = info.fragsize; self->read_data = calloc(1, self->data_size); - if(!StartThread(&self->thread, ALCcaptureOSS_recordProc, self)) + self->killNow = 0; + if(althrd_create(&self->thread, ALCcaptureOSS_recordProc, self) != althrd_success) { device->ExtraData = NULL; close(self->fd); @@ -496,16 +493,17 @@ static ALCenum ALCcaptureOSS_open(ALCcaptureOSS *self, const ALCchar *name) return ALC_OUT_OF_MEMORY; } - device->DeviceName = strdup(name); + al_string_copy_cstr(&device->DeviceName, name); return ALC_NO_ERROR; } static void ALCcaptureOSS_close(ALCcaptureOSS *self) { + int res; + self->killNow = 1; - StopThread(self->thread); - self->killNow = 0; + althrd_join(self->thread, &res); close(self->fd); self->fd = -1; @@ -539,12 +537,6 @@ static ALCuint ALCcaptureOSS_availableSamples(ALCcaptureOSS *self) return RingBufferSize(self->ring); } -void ALCcaptureOSS_Delete(ALCcaptureOSS *self) -{ - free(self); -} - - typedef struct ALCossBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); @@ -615,8 +607,9 @@ ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory* UNUSED(self { ALCplaybackOSS *backend; - backend = calloc(1, sizeof(*backend)); + backend = ALCplaybackOSS_New(sizeof(*backend)); if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); ALCplaybackOSS_Construct(backend, device); @@ -626,8 +619,9 @@ ALCbackend* ALCossBackendFactory_createBackend(ALCossBackendFactory* UNUSED(self { ALCcaptureOSS *backend; - backend = calloc(1, sizeof(*backend)); + backend = ALCcaptureOSS_New(sizeof(*backend)); if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); ALCcaptureOSS_Construct(backend, device); diff --git a/jni/openal-soft-android/Alc/backends/portaudio.c b/jni/openal-soft-1.16.0/Alc/backends/portaudio.c similarity index 97% rename from jni/openal-soft-android/Alc/backends/portaudio.c rename to jni/openal-soft-1.16.0/Alc/backends/portaudio.c index 162788fc..5f11526d 100644 --- a/jni/openal-soft-android/Alc/backends/portaudio.c +++ b/jni/openal-soft-1.16.0/Alc/backends/portaudio.c @@ -45,6 +45,7 @@ MAKE_FUNC(Pa_StopStream); MAKE_FUNC(Pa_OpenStream); MAKE_FUNC(Pa_CloseStream); MAKE_FUNC(Pa_GetDefaultOutputDevice); +MAKE_FUNC(Pa_GetDefaultInputDevice); MAKE_FUNC(Pa_GetStreamInfo); #undef MAKE_FUNC @@ -56,6 +57,7 @@ MAKE_FUNC(Pa_GetStreamInfo); #define Pa_OpenStream pPa_OpenStream #define Pa_CloseStream pPa_CloseStream #define Pa_GetDefaultOutputDevice pPa_GetDefaultOutputDevice +#define Pa_GetDefaultInputDevice pPa_GetDefaultInputDevice #define Pa_GetStreamInfo pPa_GetStreamInfo #endif @@ -97,6 +99,7 @@ static ALCboolean pa_load(void) LOAD_FUNC(Pa_OpenStream); LOAD_FUNC(Pa_CloseStream); LOAD_FUNC(Pa_GetDefaultOutputDevice); + LOAD_FUNC(Pa_GetDefaultInputDevice); LOAD_FUNC(Pa_GetStreamInfo); #undef LOAD_FUNC @@ -212,7 +215,7 @@ retry_open: } device->ExtraData = data; - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); return ALC_NO_ERROR; } @@ -318,7 +321,7 @@ static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName) data->params.device = -1; if(!ConfigValueInt("port", "capture", &data->params.device) || data->params.device < 0) - data->params.device = Pa_GetDefaultOutputDevice(); + data->params.device = Pa_GetDefaultInputDevice(); data->params.suggestedLatency = 0.0f; data->params.hostApiSpecificStreamInfo = NULL; @@ -354,7 +357,7 @@ static ALCenum pa_open_capture(ALCdevice *device, const ALCchar *deviceName) goto error; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; diff --git a/jni/openal-soft-android/Alc/backends/pulseaudio.c b/jni/openal-soft-1.16.0/Alc/backends/pulseaudio.c similarity index 87% rename from jni/openal-soft-android/Alc/backends/pulseaudio.c rename to jni/openal-soft-1.16.0/Alc/backends/pulseaudio.c index e2ae52ae..8bd731ff 100644 --- a/jni/openal-soft-android/Alc/backends/pulseaudio.c +++ b/jni/openal-soft-1.16.0/Alc/backends/pulseaudio.c @@ -306,9 +306,6 @@ static ALCboolean pulse_load(void) static pa_context_flags_t pulse_ctx_flags; static pa_proplist *prop_filter; -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif /* PulseAudio Event Callbacks */ static void context_state_callback(pa_context *context, void *pdata) @@ -438,7 +435,9 @@ static void pulse_close(pa_threaded_mainloop *loop, pa_context *context, if(stream) { + pa_stream_set_state_callback(stream, NULL, NULL); pa_stream_set_moved_callback(stream, NULL, NULL); + pa_stream_set_write_callback(stream, NULL, NULL); #if PA_CHECK_VERSION(0,9,15) if(pa_stream_set_buffer_attr_callback) pa_stream_set_buffer_attr_callback(stream, NULL, NULL); @@ -458,20 +457,27 @@ static void pulse_close(pa_threaded_mainloop *loop, pa_context *context, typedef struct { - char *name; - char *device_name; + al_string name; + al_string device_name; } DevMap; +TYPEDEF_VECTOR(DevMap, vector_DevMap) -static DevMap *allDevNameMap; -static ALuint numDevNames; -static DevMap *allCaptureDevNameMap; -static ALuint numCaptureDevNames; +static vector_DevMap PlaybackDevices; +static vector_DevMap CaptureDevices; + +static void clear_devlist(vector_DevMap *list) +{ +#define DEINIT_STRS(i) (AL_STRING_DEINIT((i)->name),AL_STRING_DEINIT((i)->device_name)) + VECTOR_FOR_EACH(DevMap, *list, DEINIT_STRS); +#undef DEINIT_STRS + VECTOR_RESIZE(*list, 0); +} typedef struct ALCpulsePlayback { DERIVE_FROM_TYPE(ALCbackend); - char *device_name; + al_string device_name; pa_buffer_attr attr; pa_sample_spec spec; @@ -482,9 +488,8 @@ typedef struct ALCpulsePlayback { pa_context *context; volatile ALboolean killNow; - althread_t thread; + althrd_t thread; } ALCpulsePlayback; -DECLARE_ALCBACKEND_VTABLE(ALCpulsePlayback); static void ALCpulsePlayback_deviceCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata); static void ALCpulsePlayback_probeDevices(void); @@ -492,6 +497,7 @@ static void ALCpulsePlayback_probeDevices(void); static void ALCpulsePlayback_bufferAttrCallback(pa_stream *stream, void *pdata); static void ALCpulsePlayback_contextStateCallback(pa_context *context, void *pdata); static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata); +static void ALCpulsePlayback_streamWriteCallback(pa_stream *p, size_t nbytes, void *userdata); static void ALCpulsePlayback_sinkInfoCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata); static void ALCpulsePlayback_sinkNameCallback(pa_context *context, const pa_sink_info *info, int eol, void *pdata); static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata); @@ -499,10 +505,10 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, pa_thr pa_context *context, pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap); -static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr); +static int ALCpulsePlayback_mixerProc(void *ptr); static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device); -static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, void, Destruct) +static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self); static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name); static void ALCpulsePlayback_close(ALCpulsePlayback *self); static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self); @@ -510,22 +516,34 @@ static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self); static void ALCpulsePlayback_stop(ALCpulsePlayback *self); static DECLARE_FORWARD2(ALCpulsePlayback, ALCbackend, ALCenum, captureSamples, ALCvoid*, ALCuint) static DECLARE_FORWARD(ALCpulsePlayback, ALCbackend, ALCuint, availableSamples) +static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self); static void ALCpulsePlayback_lock(ALCpulsePlayback *self); static void ALCpulsePlayback_unlock(ALCpulsePlayback *self); +DECLARE_DEFAULT_ALLOCATORS(ALCpulsePlayback) + +DEFINE_ALCBACKEND_VTABLE(ALCpulsePlayback); static void ALCpulsePlayback_Construct(ALCpulsePlayback *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCpulsePlayback, ALCbackend, self); + + AL_STRING_INIT(self->device_name); +} + +static void ALCpulsePlayback_Destruct(ALCpulsePlayback *self) +{ + AL_STRING_DEINIT(self->device_name); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata) { pa_threaded_mainloop *loop = pdata; - void *temp; - ALuint i; + const DevMap *iter; + DevMap entry; if(eol) { @@ -533,29 +551,29 @@ static void ALCpulsePlayback_deviceCallback(pa_context *UNUSED(context), const p return; } - for(i = 0;i < numDevNames;i++) - { - if(strcmp(info->name, allDevNameMap[i].device_name) == 0) - return; - } +#define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_INFO_NAME); +#undef MATCH_INFO_NAME + if(iter != VECTOR_ITER_END(PlaybackDevices)) + return; TRACE("Got device \"%s\", \"%s\"\n", info->description, info->name); - temp = realloc(allDevNameMap, (numDevNames+1) * sizeof(*allDevNameMap)); - if(temp) - { - allDevNameMap = temp; - allDevNameMap[numDevNames].name = strdup(info->description); - allDevNameMap[numDevNames].device_name = strdup(info->name); - numDevNames++; - } + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.device_name); + + al_string_copy_cstr(&entry.name, info->description); + al_string_copy_cstr(&entry.device_name, info->name); + + VECTOR_PUSH_BACK(PlaybackDevices, entry); } static void ALCpulsePlayback_probeDevices(void) { pa_threaded_mainloop *loop; - allDevNameMap = malloc(sizeof(DevMap) * 1); + clear_devlist(&PlaybackDevices); + if((loop=pa_threaded_mainloop_new()) && pa_threaded_mainloop_start(loop) >= 0) { @@ -634,6 +652,12 @@ static void ALCpulsePlayback_streamStateCallback(pa_stream *stream, void *pdata) pa_threaded_mainloop_signal(self->loop, 0); } +static void ALCpulsePlayback_streamWriteCallback(pa_stream* UNUSED(p), size_t UNUSED(nbytes), void *pdata) +{ + ALCpulsePlayback *self = pdata; + pa_threaded_mainloop_signal(self->loop, 0); +} + static void ALCpulsePlayback_sinkInfoCallback(pa_context *UNUSED(context), const pa_sink_info *info, int eol, void *pdata) { ALCpulsePlayback *self = pdata; @@ -697,8 +721,7 @@ static void ALCpulsePlayback_sinkNameCallback(pa_context *UNUSED(context), const return; } - free(device->DeviceName); - device->DeviceName = strdup(info->description); + al_string_copy_cstr(&device->DeviceName, info->description); } @@ -706,10 +729,9 @@ static void ALCpulsePlayback_streamMovedCallback(pa_stream *stream, void *pdata) { ALCpulsePlayback *self = pdata; - free(self->device_name); - self->device_name = strdup(pa_stream_get_device_name(stream)); + al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(stream)); - TRACE("Stream moved to %s\n", self->device_name); + TRACE("Stream moved to %s\n", al_string_get_cstr(self->device_name)); } @@ -754,7 +776,7 @@ static pa_stream *ALCpulsePlayback_connectStream(const char *device_name, } -static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr) +static int ALCpulsePlayback_mixerProc(void *ptr) { ALCpulsePlayback *self = ptr; ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; @@ -764,7 +786,7 @@ static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr) ssize_t len; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); pa_threaded_mainloop_lock(self->loop); frame_size = pa_frame_size(&self->spec); @@ -785,9 +807,7 @@ static ALuint ALCpulsePlayback_mixerProc(ALvoid *ptr) o = pa_stream_cork(self->stream, 0, NULL, NULL); if(o) pa_operation_unref(o); } - pa_threaded_mainloop_unlock(self->loop); - Sleep(1); - pa_threaded_mainloop_lock(self->loop); + pa_threaded_mainloop_wait(self->loop); continue; } len -= len%update_size; @@ -828,21 +848,17 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name if(name) { - ALuint i; + const DevMap *iter; - if(!allDevNameMap) + if(VECTOR_SIZE(PlaybackDevices) == 0) ALCpulsePlayback_probeDevices(); - for(i = 0;i < numDevNames;i++) - { - if(strcmp(name, allDevNameMap[i].name) == 0) - { - pulse_name = allDevNameMap[i].device_name; - break; - } - } - if(i == numDevNames) +#define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0) + VECTOR_FIND_IF(iter, const DevMap, PlaybackDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_ITER_END(PlaybackDevices)) return ALC_INVALID_VALUE; + pulse_name = al_string_get_cstr(iter->device_name); } if(!pulse_open(&self->loop, &self->context, ALCpulsePlayback_contextStateCallback, self)) @@ -859,6 +875,7 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name spec.rate = 44100; spec.channels = 2; + TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); self->stream = ALCpulsePlayback_connectStream(pulse_name, self->loop, self->context, flags, NULL, &spec, NULL); if(!self->stream) @@ -871,8 +888,9 @@ static ALCenum ALCpulsePlayback_open(ALCpulsePlayback *self, const ALCchar *name } pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self); - self->device_name = strdup(pa_stream_get_device_name(self->stream)); - o = pa_context_get_sink_info_by_name(self->context, self->device_name, + al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream)); + o = pa_context_get_sink_info_by_name(self->context, + al_string_get_cstr(self->device_name), ALCpulsePlayback_sinkNameCallback, self); wait_for_operation(o, self->loop); @@ -888,16 +906,15 @@ static void ALCpulsePlayback_close(ALCpulsePlayback *self) self->context = NULL; self->stream = NULL; - free(self->device_name); - self->device_name = NULL; + al_string_clear(&self->device_name); } static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) { ALCdevice *device = STATIC_CAST(ALCbackend,self)->mDevice; pa_stream_flags_t flags = 0; + const char *mapname = NULL; pa_channel_map chanmap; - const char *mapname; ALuint len; pa_threaded_mainloop_lock(self->loop); @@ -917,7 +934,8 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) { pa_operation *o; - o = pa_context_get_sink_info_by_name(self->context, self->device_name, + o = pa_context_get_sink_info_by_name(self->context, + al_string_get_cstr(self->device_name), ALCpulsePlayback_sinkInfoCallback, self); wait_for_operation(o, self->loop); } @@ -964,7 +982,6 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) return ALC_FALSE; } - mapname = "(invalid)"; switch(device->FmtChans) { case DevFmtMono: @@ -1003,9 +1020,9 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) self->attr.tlength = self->attr.minreq * maxu(device->NumUpdates, 2); self->attr.maxlength = -1; - self->stream = ALCpulsePlayback_connectStream(self->device_name, self->loop, - self->context, flags, &self->attr, - &self->spec, &chanmap); + self->stream = ALCpulsePlayback_connectStream(al_string_get_cstr(self->device_name), + self->loop, self->context, flags, + &self->attr, &self->spec, &chanmap); if(!self->stream) { pa_threaded_mainloop_unlock(self->loop); @@ -1013,6 +1030,7 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) } pa_stream_set_state_callback(self->stream, ALCpulsePlayback_streamStateCallback, self); pa_stream_set_moved_callback(self->stream, ALCpulsePlayback_streamMovedCallback, self); + pa_stream_set_write_callback(self->stream, ALCpulsePlayback_streamWriteCallback, self); self->spec = *(pa_stream_get_sample_spec(self->stream)); if(device->Frequency != self->spec.rate) @@ -1054,7 +1072,8 @@ static ALCboolean ALCpulsePlayback_reset(ALCpulsePlayback *self) static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self) { - if(!StartThread(&self->thread, ALCpulsePlayback_mixerProc, self)) + self->killNow = AL_FALSE; + if(althrd_create(&self->thread, ALCpulsePlayback_mixerProc, self) != althrd_success) return ALC_FALSE; return ALC_TRUE; } @@ -1062,17 +1081,13 @@ static ALCboolean ALCpulsePlayback_start(ALCpulsePlayback *self) static void ALCpulsePlayback_stop(ALCpulsePlayback *self) { pa_operation *o; + int res; if(!self->stream) return; self->killNow = AL_TRUE; - if(self->thread) - { - StopThread(self->thread); - self->thread = NULL; - } - self->killNow = AL_FALSE; + althrd_join(self->thread, &res); pa_threaded_mainloop_lock(self->loop); @@ -1083,6 +1098,27 @@ static void ALCpulsePlayback_stop(ALCpulsePlayback *self) } +static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self) +{ + pa_usec_t latency = 0; + int neg, err; + + 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); + return 0; + } + + if(neg) latency = 0; + return (ALint64)minu64(latency, U64(0x7fffffffffffffff)/1000) * 1000; +} + + static void ALCpulsePlayback_lock(ALCpulsePlayback *self) { pa_threaded_mainloop_lock(self->loop); @@ -1094,34 +1130,10 @@ static void ALCpulsePlayback_unlock(ALCpulsePlayback *self) } -static ALint64 ALCpulsePlayback_getLatency(ALCpulsePlayback *self) -{ - pa_usec_t latency = 0; - int neg; - - if(pa_stream_get_latency(self->stream, &latency, &neg) != 0) - { - ERR("Failed to get stream latency!\n"); - return 0; - } - - if(neg) latency = 0; - return (ALint64)minu64(latency, U64(0x7fffffffffffffff)/1000) * 1000; -} - - -static void ALCpulsePlayback_Delete(ALCpulsePlayback *self) -{ - free(self); -} - -DEFINE_ALCBACKEND_VTABLE(ALCpulsePlayback); - - typedef struct ALCpulseCapture { DERIVE_FROM_TYPE(ALCbackend); - char *device_name; + al_string device_name; const void *cap_store; size_t cap_len; @@ -1137,7 +1149,6 @@ typedef struct ALCpulseCapture { pa_stream *stream; pa_context *context; } ALCpulseCapture; -DECLARE_ALCBACKEND_VTABLE(ALCpulseCapture); static void ALCpulseCapture_deviceCallback(pa_context *context, const pa_source_info *info, int eol, void *pdata); static void ALCpulseCapture_probeDevices(void); @@ -1152,7 +1163,7 @@ static pa_stream *ALCpulseCapture_connectStream(const char *device_name, pa_sample_spec *spec, pa_channel_map *chanmap); static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device); -static DECLARE_FORWARD(ALCpulseCapture, ALCbackend, void, Destruct) +static void ALCpulseCapture_Destruct(ALCpulseCapture *self); static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name); static void ALCpulseCapture_close(ALCpulseCapture *self); static DECLARE_FORWARD(ALCpulseCapture, ALCbackend, ALCboolean, reset) @@ -1160,22 +1171,34 @@ static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self); static void ALCpulseCapture_stop(ALCpulseCapture *self); static ALCenum ALCpulseCapture_captureSamples(ALCpulseCapture *self, ALCvoid *buffer, ALCuint samples); static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self); +static ALint64 ALCpulseCapture_getLatency(ALCpulseCapture *self); static void ALCpulseCapture_lock(ALCpulseCapture *self); static void ALCpulseCapture_unlock(ALCpulseCapture *self); +DECLARE_DEFAULT_ALLOCATORS(ALCpulseCapture) + +DEFINE_ALCBACKEND_VTABLE(ALCpulseCapture); static void ALCpulseCapture_Construct(ALCpulseCapture *self, ALCdevice *device) { ALCbackend_Construct(STATIC_CAST(ALCbackend, self), device); SET_VTABLE2(ALCpulseCapture, ALCbackend, self); + + AL_STRING_INIT(self->device_name); +} + +static void ALCpulseCapture_Destruct(ALCpulseCapture *self) +{ + AL_STRING_DEINIT(self->device_name); + ALCbackend_Destruct(STATIC_CAST(ALCbackend, self)); } static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa_source_info *info, int eol, void *pdata) { pa_threaded_mainloop *loop = pdata; - void *temp; - ALuint i; + const DevMap *iter; + DevMap entry; if(eol) { @@ -1183,29 +1206,29 @@ static void ALCpulseCapture_deviceCallback(pa_context *UNUSED(context), const pa return; } - for(i = 0;i < numCaptureDevNames;i++) - { - if(strcmp(info->name, allCaptureDevNameMap[i].device_name) == 0) - return; - } +#define MATCH_INFO_NAME(iter) (al_string_cmp_cstr((iter)->device_name, info->name) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_INFO_NAME); +#undef MATCH_INFO_NAME + if(iter != VECTOR_ITER_END(CaptureDevices)) + return; TRACE("Got device \"%s\", \"%s\"\n", info->description, info->name); - temp = realloc(allCaptureDevNameMap, (numCaptureDevNames+1) * sizeof(*allCaptureDevNameMap)); - if(temp) - { - allCaptureDevNameMap = temp; - allCaptureDevNameMap[numCaptureDevNames].name = strdup(info->description); - allCaptureDevNameMap[numCaptureDevNames].device_name = strdup(info->name); - numCaptureDevNames++; - } + AL_STRING_INIT(entry.name); + AL_STRING_INIT(entry.device_name); + + al_string_copy_cstr(&entry.name, info->description); + al_string_copy_cstr(&entry.device_name, info->name); + + VECTOR_PUSH_BACK(CaptureDevices, entry); } static void ALCpulseCapture_probeDevices(void) { pa_threaded_mainloop *loop; - allCaptureDevNameMap = malloc(sizeof(DevMap) * 1); + clear_devlist(&CaptureDevices); + if((loop=pa_threaded_mainloop_new()) && pa_threaded_mainloop_start(loop) >= 0) { @@ -1288,8 +1311,7 @@ static void ALCpulseCapture_sourceNameCallback(pa_context *UNUSED(context), cons return; } - free(device->DeviceName); - device->DeviceName = strdup(info->description); + al_string_copy_cstr(&device->DeviceName, info->description); } @@ -1297,10 +1319,9 @@ static void ALCpulseCapture_streamMovedCallback(pa_stream *stream, void *pdata) { ALCpulseCapture *self = pdata; - free(self->device_name); - self->device_name = strdup(pa_stream_get_device_name(stream)); + al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(stream)); - TRACE("Stream moved to %s\n", self->device_name); + TRACE("Stream moved to %s\n", al_string_get_cstr(self->device_name)); } @@ -1356,21 +1377,17 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) if(name) { - ALuint i; + const DevMap *iter; - if(!allCaptureDevNameMap) + if(VECTOR_SIZE(CaptureDevices) == 0) ALCpulseCapture_probeDevices(); - for(i = 0;i < numCaptureDevNames;i++) - { - if(strcmp(name, allCaptureDevNameMap[i].name) == 0) - { - pulse_name = allCaptureDevNameMap[i].device_name; - break; - } - } - if(i == numCaptureDevNames) +#define MATCH_NAME(iter) (al_string_cmp_cstr((iter)->name, name) == 0) + VECTOR_FIND_IF(iter, const DevMap, CaptureDevices, MATCH_NAME); +#undef MATCH_NAME + if(iter == VECTOR_ITER_END(CaptureDevices)) return ALC_INVALID_VALUE; + pulse_name = al_string_get_cstr(iter->device_name); } if(!pulse_open(&self->loop, &self->context, ALCpulseCapture_contextStateCallback, self)) @@ -1431,6 +1448,7 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) if(!GetConfigValueBool("pulse", "allow-moves", 0)) flags |= PA_STREAM_DONT_MOVE; + TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); self->stream = ALCpulseCapture_connectStream(pulse_name, self->loop, self->context, flags, &self->attr, &self->spec, &chanmap); @@ -1442,8 +1460,9 @@ static ALCenum ALCpulseCapture_open(ALCpulseCapture *self, const ALCchar *name) pa_stream_set_moved_callback(self->stream, ALCpulseCapture_streamMovedCallback, self); pa_stream_set_state_callback(self->stream, ALCpulseCapture_streamStateCallback, self); - self->device_name = strdup(pa_stream_get_device_name(self->stream)); - o = pa_context_get_source_info_by_name(self->context, self->device_name, + al_string_copy_cstr(&self->device_name, pa_stream_get_device_name(self->stream)); + o = pa_context_get_source_info_by_name(self->context, + al_string_get_cstr(self->device_name), ALCpulseCapture_sourceNameCallback, self); wait_for_operation(o, self->loop); @@ -1466,8 +1485,7 @@ static void ALCpulseCapture_close(ALCpulseCapture *self) self->context = NULL; self->stream = NULL; - free(self->device_name); - self->device_name = NULL; + al_string_clear(&self->device_name); } static ALCboolean ALCpulseCapture_start(ALCpulseCapture *self) @@ -1562,17 +1580,6 @@ static ALCuint ALCpulseCapture_availableSamples(ALCpulseCapture *self) } -static void ALCpulseCapture_lock(ALCpulseCapture *self) -{ - pa_threaded_mainloop_lock(self->loop); -} - -static void ALCpulseCapture_unlock(ALCpulseCapture *self) -{ - pa_threaded_mainloop_unlock(self->loop); -} - - static ALint64 ALCpulseCapture_getLatency(ALCpulseCapture *self) { pa_usec_t latency = 0; @@ -1589,23 +1596,43 @@ static ALint64 ALCpulseCapture_getLatency(ALCpulseCapture *self) } -static void ALCpulseCapture_Delete(ALCpulseCapture *self) +static void ALCpulseCapture_lock(ALCpulseCapture *self) { - free(self); + pa_threaded_mainloop_lock(self->loop); } -DEFINE_ALCBACKEND_VTABLE(ALCpulseCapture); +static void ALCpulseCapture_unlock(ALCpulseCapture *self) +{ + pa_threaded_mainloop_unlock(self->loop); +} +static inline void AppendAllDevicesList2(const DevMap *entry) +{ AppendAllDevicesList(al_string_get_cstr(entry->name)); } +static inline void AppendCaptureDeviceList2(const DevMap *entry) +{ AppendCaptureDeviceList(al_string_get_cstr(entry->name)); } + typedef struct ALCpulseBackendFactory { DERIVE_FROM_TYPE(ALCbackendFactory); } ALCpulseBackendFactory; #define ALCPULSEBACKENDFACTORY_INITIALIZER { { GET_VTABLE2(ALCpulseBackendFactory, ALCbackendFactory) } } +static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory *self); +static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory *self); +static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory *self, ALCbackend_Type type); +static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory *self, enum DevProbe type); +static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory *self, ALCdevice *device, ALCbackend_Type type); + +DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory); + + static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(self)) { ALCboolean ret = ALC_FALSE; + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + if(pulse_load()) { pa_threaded_mainloop *loop; @@ -1648,25 +1675,11 @@ static ALCboolean ALCpulseBackendFactory_init(ALCpulseBackendFactory* UNUSED(sel static void ALCpulseBackendFactory_deinit(ALCpulseBackendFactory* UNUSED(self)) { - ALuint i; + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); - for(i = 0;i < numDevNames;++i) - { - free(allDevNameMap[i].name); - free(allDevNameMap[i].device_name); - } - free(allDevNameMap); - allDevNameMap = NULL; - numDevNames = 0; - - for(i = 0;i < numCaptureDevNames;++i) - { - free(allCaptureDevNameMap[i].name); - free(allCaptureDevNameMap[i].device_name); - } - free(allCaptureDevNameMap); - allCaptureDevNameMap = NULL; - numCaptureDevNames = 0; + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); if(prop_filter) pa_proplist_free(prop_filter); @@ -1684,40 +1697,16 @@ static ALCboolean ALCpulseBackendFactory_querySupport(ALCpulseBackendFactory* UN static void ALCpulseBackendFactory_probe(ALCpulseBackendFactory* UNUSED(self), enum DevProbe type) { - ALuint i; - switch(type) { case ALL_DEVICE_PROBE: - for(i = 0;i < numDevNames;++i) - { - free(allDevNameMap[i].name); - free(allDevNameMap[i].device_name); - } - free(allDevNameMap); - allDevNameMap = NULL; - numDevNames = 0; - ALCpulsePlayback_probeDevices(); - - for(i = 0;i < numDevNames;i++) - AppendAllDevicesList(allDevNameMap[i].name); + VECTOR_FOR_EACH(const DevMap, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: - for(i = 0;i < numCaptureDevNames;++i) - { - free(allCaptureDevNameMap[i].name); - free(allCaptureDevNameMap[i].device_name); - } - free(allCaptureDevNameMap); - allCaptureDevNameMap = NULL; - numCaptureDevNames = 0; - ALCpulseCapture_probeDevices(); - - for(i = 0;i < numCaptureDevNames;i++) - AppendCaptureDeviceList(allCaptureDevNameMap[i].name); + VECTOR_FOR_EACH(const DevMap, CaptureDevices, AppendCaptureDeviceList2); break; } } @@ -1728,8 +1717,9 @@ static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory* { ALCpulsePlayback *backend; - backend = calloc(1, sizeof(*backend)); + backend = ALCpulsePlayback_New(sizeof(*backend)); if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); ALCpulsePlayback_Construct(backend, device); @@ -1739,8 +1729,9 @@ static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory* { ALCpulseCapture *backend; - backend = calloc(1, sizeof(*backend)); + backend = ALCpulseCapture_New(sizeof(*backend)); if(!backend) return NULL; + memset(backend, 0, sizeof(*backend)); ALCpulseCapture_Construct(backend, device); @@ -1750,8 +1741,6 @@ static ALCbackend* ALCpulseBackendFactory_createBackend(ALCpulseBackendFactory* return NULL; } -DEFINE_ALCBACKENDFACTORY_VTABLE(ALCpulseBackendFactory); - #else /* PA_API_VERSION == 12 */ diff --git a/jni/openal-soft-android/Alc/backends/qsa.c b/jni/openal-soft-1.16.0/Alc/backends/qsa.c similarity index 97% rename from jni/openal-soft-android/Alc/backends/qsa.c rename to jni/openal-soft-1.16.0/Alc/backends/qsa.c index c9762f85..9258e4e5 100644 --- a/jni/openal-soft-android/Alc/backends/qsa.c +++ b/jni/openal-soft-1.16.0/Alc/backends/qsa.c @@ -34,8 +34,7 @@ #include "threads.h" -typedef struct -{ +typedef struct { snd_pcm_t* pcmHandle; int audio_fd; @@ -46,27 +45,24 @@ typedef struct ALsizei size; volatile int killNow; - althread_t thread; + althrd_t thread; } qsa_data; -typedef struct -{ +typedef struct { ALCchar* name; int card; int dev; } DevMap; -static const ALCchar qsaDevice[]="QSA Default"; +static const ALCchar qsaDevice[] = "QSA Default"; static DevMap* allDevNameMap; static ALuint numDevNames; static DevMap* allCaptureDevNameMap; static ALuint numCaptureDevNames; -static const struct -{ +static const struct { int32_t format; -} formatlist[]= -{ +} formatlist[] = { {SND_PCM_SFMT_FLOAT_LE}, {SND_PCM_SFMT_S32_LE}, {SND_PCM_SFMT_U32_LE}, @@ -77,11 +73,9 @@ static const struct {0}, }; -static const struct -{ +static const struct { int32_t rate; -} ratelist[]= -{ +} ratelist[] = { {192000}, {176400}, {96000}, @@ -98,11 +92,9 @@ static const struct {0}, }; -static const struct -{ +static const struct { int32_t channels; -} channellist[]= -{ +} channellist[] = { {8}, {7}, {6}, @@ -112,7 +104,7 @@ static const struct {0}, }; -static DevMap* deviceList(int type, ALuint* count) +static DevMap *deviceList(int type, ALuint *count) { snd_ctl_t* handle; snd_pcm_info_t pcminfo; @@ -178,7 +170,7 @@ static DevMap* deviceList(int type, ALuint* count) } -FORCE_ALIGN static ALuint qsa_proc_playback(ALvoid* ptr) +FORCE_ALIGN static int qsa_proc_playback(void* ptr) { ALCdevice* device=(ALCdevice*)ptr; qsa_data* data=(qsa_data*)device->ExtraData; @@ -191,7 +183,7 @@ FORCE_ALIGN static ALuint qsa_proc_playback(ALvoid* ptr) struct timeval timeout; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); /* Increase default 10 priority to 11 to avoid jerky sound */ SchedGet(0, 0, ¶m); @@ -343,8 +335,8 @@ static ALCenum qsa_open_playback(ALCdevice* device, const ALCchar* deviceName) return ALC_INVALID_DEVICE; } - device->DeviceName=strdup(deviceName); - device->ExtraData=data; + al_string_copy_cstr(&device->DeviceName, deviceName); + device->ExtraData = data; return ALC_NO_ERROR; } @@ -616,7 +608,8 @@ static ALCboolean qsa_start_playback(ALCdevice* device) { qsa_data *data = (qsa_data*)device->ExtraData; - if(!StartThread(&data->thread, qsa_proc_playback, device)) + data->killNow = 0; + if(althrd_create(&data->thread, qsa_proc_playback, device) != althrd_success) return ALC_FALSE; return ALC_TRUE; @@ -624,15 +617,14 @@ static ALCboolean qsa_start_playback(ALCdevice* device) static void qsa_stop_playback(ALCdevice* device) { - qsa_data* data=(qsa_data*)device->ExtraData; + qsa_data *data = (qsa_data*)device->ExtraData; + int res; - if (data->thread) - { - data->killNow=1; - StopThread(data->thread); - data->thread=NULL; - } - data->killNow=0; + if(data->killNow) + return; + + data->killNow = 1; + althrd_join(data->thread, &res); } /***********/ @@ -711,8 +703,8 @@ static ALCenum qsa_open_capture(ALCdevice* device, const ALCchar* deviceName) return ALC_INVALID_DEVICE; } - device->DeviceName=strdup(deviceName); - device->ExtraData=data; + al_string_copy_cstr(&device->DeviceName, deviceName); + device->ExtraData = data; switch (device->FmtType) { diff --git a/jni/openal-soft-android/Alc/backends/sndio.c b/jni/openal-soft-1.16.0/Alc/backends/sndio.c similarity index 95% rename from jni/openal-soft-android/Alc/backends/sndio.c rename to jni/openal-soft-1.16.0/Alc/backends/sndio.c index 80aebfd1..7152b2d6 100644 --- a/jni/openal-soft-android/Alc/backends/sndio.c +++ b/jni/openal-soft-1.16.0/Alc/backends/sndio.c @@ -47,11 +47,11 @@ typedef struct { ALsizei data_size; volatile int killNow; - althread_t thread; + althrd_t thread; } sndio_data; -static ALuint sndio_proc(ALvoid *ptr) +static int sndio_proc(void *ptr) { ALCdevice *device = ptr; sndio_data *data = device->ExtraData; @@ -59,7 +59,7 @@ static ALuint sndio_proc(ALvoid *ptr) size_t wrote; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); @@ -111,7 +111,7 @@ static ALCenum sndio_open_playback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; @@ -224,7 +224,8 @@ static ALCboolean sndio_start_playback(ALCdevice *device) data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); data->mix_data = calloc(1, data->data_size); - if(!StartThread(&data->thread, sndio_proc, device)) + data->killNow = 0; + if(althrd_create(&data->thread, sndio_proc, device) != althrd_success) { sio_stop(data->sndHandle); free(data->mix_data); @@ -238,15 +239,14 @@ static ALCboolean sndio_start_playback(ALCdevice *device) static void sndio_stop_playback(ALCdevice *device) { sndio_data *data = device->ExtraData; + int res; - if(!data->thread) + if(data->killNow) return; data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; + althrd_join(data->thread, &res); - data->killNow = 0; if(!sio_stop(data->sndHandle)) ERR("Error stopping device\n"); diff --git a/jni/openal-soft-android/Alc/backends/solaris.c b/jni/openal-soft-1.16.0/Alc/backends/solaris.c similarity index 95% rename from jni/openal-soft-android/Alc/backends/solaris.c rename to jni/openal-soft-1.16.0/Alc/backends/solaris.c index 700131c8..20d861d2 100644 --- a/jni/openal-soft-android/Alc/backends/solaris.c +++ b/jni/openal-soft-1.16.0/Alc/backends/solaris.c @@ -50,11 +50,11 @@ typedef struct { int data_size; volatile int killNow; - althread_t thread; + althrd_t thread; } solaris_data; -static ALuint SolarisProc(ALvoid *ptr) +static int SolarisProc(void *ptr) { ALCdevice *Device = (ALCdevice*)ptr; solaris_data *data = (solaris_data*)Device->ExtraData; @@ -62,7 +62,7 @@ static ALuint SolarisProc(ALvoid *ptr) int wrote; SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); @@ -86,7 +86,7 @@ static ALuint SolarisProc(ALvoid *ptr) break; } - Sleep(1); + al_nssleep(0, 1000000); continue; } @@ -119,7 +119,7 @@ static ALCenum solaris_open_playback(ALCdevice *device, const ALCchar *deviceNam return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; } @@ -211,7 +211,8 @@ static ALCboolean solaris_start_playback(ALCdevice *device) data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType); data->mix_data = calloc(1, data->data_size); - if(!StartThread(&data->thread, SolarisProc, device)) + data->killNow = 0; + if(althrd_create(&data->thread, SolarisProc, device) != althrd_success) { free(data->mix_data); data->mix_data = NULL; @@ -224,15 +225,14 @@ static ALCboolean solaris_start_playback(ALCdevice *device) static void solaris_stop_playback(ALCdevice *device) { solaris_data *data = (solaris_data*)device->ExtraData; + int res; - if(!data->thread) + if(data->killNow) return; data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; + althrd_join(data->thread, &res); - data->killNow = 0; if(ioctl(data->fd, AUDIO_DRAIN) < 0) ERR("Error draining device: %s\n", strerror(errno)); diff --git a/jni/openal-soft-android/Alc/backends/wave.c b/jni/openal-soft-1.16.0/Alc/backends/wave.c similarity index 80% rename from jni/openal-soft-android/Alc/backends/wave.c rename to jni/openal-soft-1.16.0/Alc/backends/wave.c index 2fafc4b9..421ca5d7 100644 --- a/jni/openal-soft-android/Alc/backends/wave.c +++ b/jni/openal-soft-1.16.0/Alc/backends/wave.c @@ -42,7 +42,7 @@ typedef struct { ALuint size; volatile int killNow; - althread_t thread; + althrd_t thread; } wave_data; @@ -85,49 +85,55 @@ static void fwrite32le(ALuint val, FILE *f) } -static ALuint WaveProc(ALvoid *ptr) +static int WaveProc(void *ptr) { - ALCdevice *Device = (ALCdevice*)ptr; - wave_data *data = (wave_data*)Device->ExtraData; + ALCdevice *device = (ALCdevice*)ptr; + wave_data *data = (wave_data*)device->ExtraData; + struct timespec now, start; + ALint64 avail, done; ALuint frameSize; - ALuint now, start; - ALuint64 avail, done; size_t fs; - const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 / - Device->Frequency / 2; + const long restTime = (long)((ALuint64)device->UpdateSize * 1000000000 / + device->Frequency / 2); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); - frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); + frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); done = 0; - start = timeGetTime(); - while(!data->killNow && Device->Connected) + if(altimespec_get(&start, AL_TIME_UTC) != AL_TIME_UTC) { - now = timeGetTime(); + ERR("Failed to get starting time\n"); + return 1; + } + while(!data->killNow && device->Connected) + { + if(altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) + { + ERR("Failed to get current time\n"); + return 1; + } - avail = (ALuint64)(now-start) * Device->Frequency / 1000; + avail = (now.tv_sec - start.tv_sec) * device->Frequency; + avail += (ALint64)(now.tv_nsec - start.tv_nsec) * device->Frequency / 1000000000; if(avail < done) { - /* Timer wrapped (50 days???). Add the remainder of the cycle to - * the available count and reset the number of samples done */ - avail += ((ALuint64)1<<32)*Device->Frequency/1000 - done; - done = 0; - } - if(avail-done < Device->UpdateSize) - { - Sleep(restTime); - continue; + /* Oops, time skipped backwards. Reset the number of samples done + * with one update available since we (likely) just came back from + * sleeping. */ + done = avail - device->UpdateSize; } - while(avail-done >= Device->UpdateSize) + if(avail-done < device->UpdateSize) + al_nssleep(0, restTime); + else while(avail-done >= device->UpdateSize) { - aluMixData(Device, data->buffer, Device->UpdateSize); - done += Device->UpdateSize; + aluMixData(device, data->buffer, device->UpdateSize); + done += device->UpdateSize; if(!IS_LITTLE_ENDIAN) { - ALuint bytesize = BytesFromDevFmt(Device->FmtType); + ALuint bytesize = BytesFromDevFmt(device->FmtType); ALubyte *bytes = data->buffer; ALuint i; @@ -149,16 +155,16 @@ static ALuint WaveProc(ALvoid *ptr) } else { - fs = fwrite(data->buffer, frameSize, Device->UpdateSize, + fs = fwrite(data->buffer, frameSize, device->UpdateSize, data->f); (void)fs; } if(ferror(data->f)) { ERR("Error writing to file\n"); - ALCdevice_Lock(Device); - aluHandleDisconnect(Device); - ALCdevice_Unlock(Device); + ALCdevice_Lock(device); + aluHandleDisconnect(device); + ALCdevice_Unlock(device); break; } } @@ -183,7 +189,7 @@ static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName) data = (wave_data*)calloc(1, sizeof(wave_data)); - data->f = fopen(fname, "wb"); + data->f = al_fopen(fname, "wb"); if(!data->f) { free(data); @@ -191,7 +197,7 @@ static ALCenum wave_open_playback(ALCdevice *device, const ALCchar *deviceName) return ALC_INVALID_VALUE; } - device->DeviceName = strdup(deviceName); + al_string_copy_cstr(&device->DeviceName, deviceName); device->ExtraData = data; return ALC_NO_ERROR; } @@ -291,7 +297,8 @@ static ALCboolean wave_start_playback(ALCdevice *device) return ALC_FALSE; } - if(!StartThread(&data->thread, WaveProc, device)) + data->killNow = 0; + if(althrd_create(&data->thread, WaveProc, device) != althrd_success) { free(data->buffer); data->buffer = NULL; @@ -306,15 +313,13 @@ static void wave_stop_playback(ALCdevice *device) wave_data *data = (wave_data*)device->ExtraData; ALuint dataLen; long size; + int res; - if(!data->thread) + if(data->killNow) return; data->killNow = 1; - StopThread(data->thread); - data->thread = NULL; - - data->killNow = 0; + althrd_join(data->thread, &res); free(data->buffer); data->buffer = NULL; diff --git a/jni/openal-soft-android/Alc/backends/winmm.c b/jni/openal-soft-1.16.0/Alc/backends/winmm.c similarity index 68% rename from jni/openal-soft-android/Alc/backends/winmm.c rename to jni/openal-soft-1.16.0/Alc/backends/winmm.c index 7082a874..cad66470 100644 --- a/jni/openal-soft-android/Alc/backends/winmm.c +++ b/jni/openal-soft-1.16.0/Alc/backends/winmm.c @@ -39,10 +39,9 @@ typedef struct { // MMSYSTEM Device volatile ALboolean killNow; - HANDLE WaveThreadEvent; - HANDLE WaveThread; - DWORD WaveThreadID; - volatile LONG WaveBuffersCommitted; + althrd_t thread; + + RefCount WaveBuffersCommitted; WAVEHDR WaveBuffer[4]; union { @@ -56,87 +55,102 @@ typedef struct { } WinMMData; -static ALCchar **PlaybackDeviceList; -static ALuint NumPlaybackDevices; -static ALCchar **CaptureDeviceList; -static ALuint NumCaptureDevices; +TYPEDEF_VECTOR(al_string, vector_al_string) +static vector_al_string PlaybackDevices; +static vector_al_string CaptureDevices; + +static void clear_devlist(vector_al_string *list) +{ + VECTOR_FOR_EACH(al_string, *list, al_string_deinit); + VECTOR_RESIZE(*list, 0); +} static void ProbePlaybackDevices(void) { + al_string *iter, *end; + ALuint numdevs; ALuint i; - for(i = 0;i < NumPlaybackDevices;i++) - free(PlaybackDeviceList[i]); + clear_devlist(&PlaybackDevices); - NumPlaybackDevices = waveOutGetNumDevs(); - PlaybackDeviceList = realloc(PlaybackDeviceList, sizeof(ALCchar*) * NumPlaybackDevices); - for(i = 0;i < NumPlaybackDevices;i++) + numdevs = waveOutGetNumDevs(); + VECTOR_RESERVE(PlaybackDevices, numdevs); + for(i = 0;i < numdevs;i++) { - WAVEOUTCAPS WaveCaps; + WAVEOUTCAPSW WaveCaps; + al_string dname; - PlaybackDeviceList[i] = NULL; - if(waveOutGetDevCaps(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) + AL_STRING_INIT(dname); + if(waveOutGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) { - char name[1024]; - ALuint count, j; - - count = 0; + ALuint count = 0; do { - if(count == 0) - snprintf(name, sizeof(name), "%s", WaveCaps.szPname); - else - snprintf(name, sizeof(name), "%s #%d", WaveCaps.szPname, count+1); + al_string_copy_wcstr(&dname, WaveCaps.szPname); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&dname, str); + } count++; - for(j = 0;j < i;j++) + iter = VECTOR_ITER_BEGIN(PlaybackDevices); + end = VECTOR_ITER_END(PlaybackDevices); + for(;iter != end;iter++) { - if(strcmp(name, PlaybackDeviceList[j]) == 0) + if(al_string_cmp(*iter, dname) == 0) break; } - } while(j != i); + } while(iter != end); - PlaybackDeviceList[i] = strdup(name); + TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); } + VECTOR_PUSH_BACK(PlaybackDevices, dname); } } static void ProbeCaptureDevices(void) { + al_string *iter, *end; + ALuint numdevs; ALuint i; - for(i = 0;i < NumCaptureDevices;i++) - free(CaptureDeviceList[i]); + clear_devlist(&CaptureDevices); - NumCaptureDevices = waveInGetNumDevs(); - CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices); - for(i = 0;i < NumCaptureDevices;i++) + numdevs = waveInGetNumDevs(); + VECTOR_RESERVE(CaptureDevices, numdevs); + for(i = 0;i < numdevs;i++) { - WAVEINCAPS WaveInCaps; + WAVEINCAPSW WaveCaps; + al_string dname; - CaptureDeviceList[i] = NULL; - if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) + AL_STRING_INIT(dname); + if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) { - char name[1024]; - ALuint count, j; - - count = 0; + ALuint count = 0; do { - if(count == 0) - snprintf(name, sizeof(name), "%s", WaveInCaps.szPname); - else - snprintf(name, sizeof(name), "%s #%d", WaveInCaps.szPname, count+1); + al_string_copy_wcstr(&dname, WaveCaps.szPname); + if(count != 0) + { + char str[64]; + snprintf(str, sizeof(str), " #%d", count+1); + al_string_append_cstr(&dname, str); + } count++; - for(j = 0;j < i;j++) + iter = VECTOR_ITER_BEGIN(CaptureDevices); + end = VECTOR_ITER_END(CaptureDevices); + for(;iter != end;iter++) { - if(strcmp(name, CaptureDeviceList[j]) == 0) + if(al_string_cmp(*iter, dname) == 0) break; } - } while(j != i); + } while(iter != end); - CaptureDeviceList[i] = strdup(name); + TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); } + VECTOR_PUSH_BACK(CaptureDevices, dname); } } @@ -155,28 +169,19 @@ static void CALLBACK WaveOutProc(HWAVEOUT UNUSED(device), UINT msg, DWORD_PTR in if(msg != WOM_DONE) return; - InterlockedDecrement(&data->WaveBuffersCommitted); - PostThreadMessage(data->WaveThreadID, msg, 0, param1); + DecrementRef(&data->WaveBuffersCommitted); + PostThreadMessage(data->thread, msg, 0, param1); } -/* - PlaybackThreadProc - - Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its - audio data. -*/ -FORCE_ALIGN static DWORD WINAPI PlaybackThreadProc(LPVOID param) +FORCE_ALIGN static int PlaybackThreadProc(void *arg) { - ALCdevice *Device = (ALCdevice*)param; + ALCdevice *Device = (ALCdevice*)arg; WinMMData *data = Device->ExtraData; - LPWAVEHDR WaveHdr; - ALuint FrameSize; + WAVEHDR *WaveHdr; MSG msg; - FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - SetRTPriority(); - SetThreadName(MIXER_THREAD_NAME); + althrd_setname(althrd_current(), MIXER_THREAD_NAME); while(GetMessage(&msg, NULL, 0, 0)) { @@ -185,24 +190,20 @@ FORCE_ALIGN static DWORD WINAPI PlaybackThreadProc(LPVOID param) if(data->killNow) { - if(data->WaveBuffersCommitted == 0) + if(ReadRef(&data->WaveBuffersCommitted) == 0) break; continue; } - WaveHdr = ((LPWAVEHDR)msg.lParam); - aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength/FrameSize); + WaveHdr = ((WAVEHDR*)msg.lParam); + aluMixData(Device, WaveHdr->lpData, WaveHdr->dwBufferLength / + data->Format.nBlockAlign); // Send buffer back to play more data waveOutWrite(data->WaveHandle.Out, WaveHdr, sizeof(WAVEHDR)); - InterlockedIncrement(&data->WaveBuffersCommitted); + IncrementRef(&data->WaveBuffersCommitted); } - // Signal Wave Thread completed event - if(data->WaveThreadEvent) - SetEvent(data->WaveThreadEvent); - - ExitThread(0); return 0; } @@ -220,26 +221,18 @@ static void CALLBACK WaveInProc(HWAVEIN UNUSED(device), UINT msg, DWORD_PTR inst if(msg != WIM_DATA) return; - InterlockedDecrement(&data->WaveBuffersCommitted); - PostThreadMessage(data->WaveThreadID, msg, 0, param1); + DecrementRef(&data->WaveBuffersCommitted); + PostThreadMessage(data->thread, msg, 0, param1); } -/* - CaptureThreadProc - - Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new - audio data. -*/ -static DWORD WINAPI CaptureThreadProc(LPVOID param) +static int CaptureThreadProc(void *arg) { - ALCdevice *Device = (ALCdevice*)param; + ALCdevice *Device = (ALCdevice*)arg; WinMMData *data = Device->ExtraData; - LPWAVEHDR WaveHdr; - ALuint FrameSize; + WAVEHDR *WaveHdr; MSG msg; - FrameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); - SetThreadName("alsoft-record"); + althrd_setname(althrd_current(), "alsoft-record"); while(GetMessage(&msg, NULL, 0, 0)) { @@ -250,19 +243,15 @@ static DWORD WINAPI CaptureThreadProc(LPVOID param) if(data->killNow) break; - WaveHdr = ((LPWAVEHDR)msg.lParam); - WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData, WaveHdr->dwBytesRecorded/FrameSize); + WaveHdr = ((WAVEHDR*)msg.lParam); + WriteRingBuffer(data->Ring, (ALubyte*)WaveHdr->lpData, + WaveHdr->dwBytesRecorded/data->Format.nBlockAlign); // Send buffer back to capture more data waveInAddBuffer(data->WaveHandle.In, WaveHdr, sizeof(WAVEHDR)); - InterlockedIncrement(&data->WaveBuffersCommitted); + IncrementRef(&data->WaveBuffersCommitted); } - // Signal Wave Thread completed event - if(data->WaveThreadEvent) - SetEvent(data->WaveThreadEvent); - - ExitThread(0); return 0; } @@ -270,24 +259,26 @@ static DWORD WINAPI CaptureThreadProc(LPVOID param) static ALCenum WinMMOpenPlayback(ALCdevice *Device, const ALCchar *deviceName) { WinMMData *data = NULL; - UINT DeviceID = 0; + const al_string *iter, *end; + UINT DeviceID; MMRESULT res; - ALuint i = 0; - if(!PlaybackDeviceList) + if(VECTOR_SIZE(PlaybackDevices) == 0) ProbePlaybackDevices(); // Find the Device ID matching the deviceName if valid - for(i = 0;i < NumPlaybackDevices;i++) + iter = VECTOR_ITER_BEGIN(PlaybackDevices); + end = VECTOR_ITER_END(PlaybackDevices); + for(;iter != end;iter++) { - if(PlaybackDeviceList[i] && - (!deviceName || strcmp(deviceName, PlaybackDeviceList[i]) == 0)) + if(!al_string_empty(*iter) && + (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0)) { - DeviceID = i; + DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(PlaybackDevices)); break; } } - if(i == NumPlaybackDevices) + if(iter == end) return ALC_INVALID_VALUE; data = calloc(1, sizeof(*data)); @@ -329,20 +320,10 @@ retry_open: goto failure; } - data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->WaveThreadEvent == NULL) - { - ERR("CreateEvent failed: %lu\n", GetLastError()); - goto failure; - } - - Device->DeviceName = strdup(PlaybackDeviceList[DeviceID]); + al_string_copy(&Device->DeviceName, VECTOR_ELEM(PlaybackDevices, DeviceID)); return ALC_NO_ERROR; failure: - if(data->WaveThreadEvent) - CloseHandle(data->WaveThreadEvent); - if(data->WaveHandle.Out) waveOutClose(data->WaveHandle.Out); @@ -356,9 +337,6 @@ static void WinMMClosePlayback(ALCdevice *device) WinMMData *data = (WinMMData*)device->ExtraData; // Close the Wave device - CloseHandle(data->WaveThreadEvent); - data->WaveThreadEvent = 0; - waveOutClose(data->WaveHandle.Out); data->WaveHandle.Out = 0; @@ -426,11 +404,11 @@ static ALCboolean WinMMStartPlayback(ALCdevice *device) ALint BufferSize; ALuint i; - data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &data->WaveThreadID); - if(data->WaveThread == NULL) + data->killNow = AL_FALSE; + if(althrd_create(&data->thread, PlaybackThreadProc, device) != althrd_success) return ALC_FALSE; - data->WaveBuffersCommitted = 0; + InitRef(&data->WaveBuffersCommitted, 0); // Create 4 Buffers BufferSize = device->UpdateSize*device->NumUpdates / 4; @@ -441,12 +419,12 @@ static ALCboolean WinMMStartPlayback(ALCdevice *device) { memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR)); data->WaveBuffer[i].dwBufferLength = BufferSize; - data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData : + data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData : (data->WaveBuffer[i-1].lpData + data->WaveBuffer[i-1].dwBufferLength)); waveOutPrepareHeader(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR)); waveOutWrite(data->WaveHandle.Out, &data->WaveBuffer[i], sizeof(WAVEHDR)); - InterlockedIncrement(&data->WaveBuffersCommitted); + IncrementRef(&data->WaveBuffersCommitted); } return ALC_TRUE; @@ -458,19 +436,12 @@ static void WinMMStopPlayback(ALCdevice *device) void *buffer = NULL; int i; - if(data->WaveThread == NULL) + if(data->killNow) return; // Set flag to stop processing headers data->killNow = AL_TRUE; - - // Wait for signal that Wave Thread has been destroyed - WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE); - - CloseHandle(data->WaveThread); - data->WaveThread = 0; - - data->killNow = AL_FALSE; + althrd_join(data->thread, &i); // Release the wave buffers for(i = 0;i < 4;i++) @@ -485,28 +456,31 @@ static void WinMMStopPlayback(ALCdevice *device) static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) { + const al_string *iter, *end; ALbyte *BufferData = NULL; DWORD CapturedDataSize; WinMMData *data = NULL; - UINT DeviceID = 0; ALint BufferSize; + UINT DeviceID; MMRESULT res; ALuint i; - if(!CaptureDeviceList) + if(VECTOR_SIZE(CaptureDevices) == 0) ProbeCaptureDevices(); // Find the Device ID matching the deviceName if valid - for(i = 0;i < NumCaptureDevices;i++) + iter = VECTOR_ITER_BEGIN(CaptureDevices); + end = VECTOR_ITER_END(CaptureDevices); + for(;iter != end;iter++) { - if(CaptureDeviceList[i] && - (!deviceName || strcmp(deviceName, CaptureDeviceList[i]) == 0)) + if(!al_string_empty(*iter) && + (!deviceName || al_string_cmp_cstr(*iter, deviceName) == 0)) { - DeviceID = i; + DeviceID = (UINT)(iter - VECTOR_ITER_BEGIN(CaptureDevices)); break; } } - if(i == NumCaptureDevices) + if(iter == end) return ALC_INVALID_VALUE; switch(Device->FmtChans) @@ -560,13 +534,6 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) goto failure; } - data->WaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - if(data->WaveThreadEvent == NULL) - { - ERR("CreateEvent failed: %lu\n", GetLastError()); - goto failure; - } - // Allocate circular memory buffer for the captured audio CapturedDataSize = Device->UpdateSize*Device->NumUpdates; @@ -578,7 +545,7 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) if(!data->Ring) goto failure; - data->WaveBuffersCommitted = 0; + InitRef(&data->WaveBuffersCommitted, 0); // Create 4 Buffers of 50ms each BufferSize = data->Format.nAvgBytesPerSec / 20; @@ -592,27 +559,23 @@ static ALCenum WinMMOpenCapture(ALCdevice *Device, const ALCchar *deviceName) { memset(&data->WaveBuffer[i], 0, sizeof(WAVEHDR)); data->WaveBuffer[i].dwBufferLength = BufferSize; - data->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData : + data->WaveBuffer[i].lpData = ((i==0) ? (CHAR*)BufferData : (data->WaveBuffer[i-1].lpData + data->WaveBuffer[i-1].dwBufferLength)); data->WaveBuffer[i].dwFlags = 0; data->WaveBuffer[i].dwLoops = 0; waveInPrepareHeader(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR)); waveInAddBuffer(data->WaveHandle.In, &data->WaveBuffer[i], sizeof(WAVEHDR)); - InterlockedIncrement(&data->WaveBuffersCommitted); + IncrementRef(&data->WaveBuffersCommitted); } - data->WaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)Device, 0, &data->WaveThreadID); - if (data->WaveThread == NULL) + if(althrd_create(&data->thread, CaptureThreadProc, Device) != althrd_success) goto failure; - Device->DeviceName = strdup(CaptureDeviceList[DeviceID]); + al_string_copy(&Device->DeviceName, VECTOR_ELEM(CaptureDevices, DeviceID)); return ALC_NO_ERROR; failure: - if(data->WaveThread) - CloseHandle(data->WaveThread); - if(BufferData) { for(i = 0;i < 4;i++) @@ -623,9 +586,6 @@ failure: if(data->Ring) DestroyRingBuffer(data->Ring); - if(data->WaveThreadEvent) - CloseHandle(data->WaveThreadEvent); - if(data->WaveHandle.In) waveInClose(data->WaveHandle.In); @@ -642,16 +602,13 @@ static void WinMMCloseCapture(ALCdevice *Device) /* Tell the processing thread to quit and wait for it to do so. */ data->killNow = AL_TRUE; - PostThreadMessage(data->WaveThreadID, WM_QUIT, 0, 0); + PostThreadMessage(data->thread, WM_QUIT, 0, 0); - WaitForSingleObjectEx(data->WaveThreadEvent, 5000, FALSE); + althrd_join(data->thread, &i); /* Make sure capture is stopped and all pending buffers are flushed. */ waveInReset(data->WaveHandle.In); - CloseHandle(data->WaveThread); - data->WaveThread = 0; - // Release the wave buffers for(i = 0;i < 4;i++) { @@ -665,9 +622,6 @@ static void WinMMCloseCapture(ALCdevice *Device) data->Ring = NULL; // Close the Wave device - CloseHandle(data->WaveThreadEvent); - data->WaveThreadEvent = 0; - waveInClose(data->WaveHandle.In); data->WaveHandle.In = 0; @@ -701,6 +655,17 @@ static ALCuint WinMMAvailableSamples(ALCdevice *Device) } +static inline void AppendAllDevicesList2(const al_string *name) +{ + if(!al_string_empty(*name)) + AppendAllDevicesList(al_string_get_cstr(*name)); +} +static inline void AppendCaptureDeviceList2(const al_string *name) +{ + if(!al_string_empty(*name)) + AppendCaptureDeviceList(al_string_get_cstr(*name)); +} + static const BackendFuncs WinMMFuncs = { WinMMOpenPlayback, WinMMClosePlayback, @@ -718,52 +683,34 @@ static const BackendFuncs WinMMFuncs = { ALCboolean alcWinMMInit(BackendFuncs *FuncList) { + VECTOR_INIT(PlaybackDevices); + VECTOR_INIT(CaptureDevices); + *FuncList = WinMMFuncs; return ALC_TRUE; } void alcWinMMDeinit() { - ALuint i; + clear_devlist(&PlaybackDevices); + VECTOR_DEINIT(PlaybackDevices); - for(i = 0;i < NumPlaybackDevices;i++) - free(PlaybackDeviceList[i]); - free(PlaybackDeviceList); - PlaybackDeviceList = NULL; - - NumPlaybackDevices = 0; - - - for(i = 0;i < NumCaptureDevices;i++) - free(CaptureDeviceList[i]); - free(CaptureDeviceList); - CaptureDeviceList = NULL; - - NumCaptureDevices = 0; + clear_devlist(&CaptureDevices); + VECTOR_DEINIT(CaptureDevices); } void alcWinMMProbe(enum DevProbe type) { - ALuint i; - switch(type) { case ALL_DEVICE_PROBE: ProbePlaybackDevices(); - for(i = 0;i < NumPlaybackDevices;i++) - { - if(PlaybackDeviceList[i]) - AppendAllDevicesList(PlaybackDeviceList[i]); - } + VECTOR_FOR_EACH(const al_string, PlaybackDevices, AppendAllDevicesList2); break; case CAPTURE_DEVICE_PROBE: ProbeCaptureDevices(); - for(i = 0;i < NumCaptureDevices;i++) - { - if(CaptureDeviceList[i]) - AppendCaptureDeviceList(CaptureDeviceList[i]); - } + VECTOR_FOR_EACH(const al_string, CaptureDevices, AppendCaptureDeviceList2); break; } } diff --git a/jni/openal-soft-android/Alc/bs2b.c b/jni/openal-soft-1.16.0/Alc/bs2b.c similarity index 51% rename from jni/openal-soft-android/Alc/bs2b.c rename to jni/openal-soft-1.16.0/Alc/bs2b.c index 0319f948..d936f75a 100644 --- a/jni/openal-soft-android/Alc/bs2b.c +++ b/jni/openal-soft-1.16.0/Alc/bs2b.c @@ -27,93 +27,82 @@ #include #include "bs2b.h" +#include "alu.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif -/* Single pole IIR filter. - * O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1] - */ - -/* Lowpass filter */ -#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1)) - -/* Highboost filter */ -#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1)) - /* Set up all data. */ static void init(struct bs2b *bs2b) { - double Fc_lo, Fc_hi; - double G_lo, G_hi; - double x; + float Fc_lo, Fc_hi; + float G_lo, G_hi; + float x, g; - if ((bs2b->srate > 192000) || (bs2b->srate < 2000)) - bs2b->srate = BS2B_DEFAULT_SRATE; + bs2b->srate = clampi(bs2b->srate, 2000, 192000); switch(bs2b->level) { case BS2B_LOW_CLEVEL: /* Low crossfeed level */ - Fc_lo = 360.0; - Fc_hi = 501.0; - G_lo = 0.398107170553497; - G_hi = 0.205671765275719; + Fc_lo = 360.0f; + Fc_hi = 501.0f; + G_lo = 0.398107170553497f; + G_hi = 0.205671765275719f; break; case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */ - Fc_lo = 500.0; - Fc_hi = 711.0; - G_lo = 0.459726988530872; - G_hi = 0.228208484414988; + Fc_lo = 500.0f; + Fc_hi = 711.0f; + G_lo = 0.459726988530872f; + G_hi = 0.228208484414988f; break; case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */ - Fc_lo = 700.0; - Fc_hi = 1021.0; - G_lo = 0.530884444230988; - G_hi = 0.250105790667544; + Fc_lo = 700.0f; + Fc_hi = 1021.0f; + G_lo = 0.530884444230988f; + G_hi = 0.250105790667544f; break; case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */ - Fc_lo = 360.0; - Fc_hi = 494.0; - G_lo = 0.316227766016838; - G_hi = 0.168236228897329; + Fc_lo = 360.0f; + Fc_hi = 494.0f; + G_lo = 0.316227766016838f; + G_hi = 0.168236228897329f; break; case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */ - Fc_lo = 500.0; - Fc_hi = 689.0; - G_lo = 0.354813389233575; - G_hi = 0.187169483835901; + Fc_lo = 500.0f; + Fc_hi = 689.0f; + G_lo = 0.354813389233575f; + G_hi = 0.187169483835901f; break; default: /* High easy crossfeed level */ bs2b->level = BS2B_HIGH_ECLEVEL; - Fc_lo = 700.0; - Fc_hi = 975.0; - G_lo = 0.398107170553497; - G_hi = 0.205671765275719; + Fc_lo = 700.0f; + Fc_hi = 975.0f; + G_lo = 0.398107170553497f; + G_hi = 0.205671765275719f; break; } /* switch */ + g = 1.0f / (1.0f - G_hi + G_lo); + /* $fc = $Fc / $s; * $d = 1 / 2 / pi / $fc; * $x = exp(-1 / $d); */ - - x = exp(-2.0 * M_PI * Fc_lo / bs2b->srate); + x = expf(-2.0f * F_PI * Fc_lo / bs2b->srate); bs2b->b1_lo = x; - bs2b->a0_lo = G_lo * (1.0 - x); + bs2b->a0_lo = G_lo * (1.0f - x) * g; - x = exp(-2.0 * M_PI * Fc_hi / bs2b->srate); + x = expf(-2.0f * F_PI * Fc_hi / bs2b->srate); bs2b->b1_hi = x; - bs2b->a0_hi = 1.0 - G_hi * (1.0 - x); - bs2b->a1_hi = -x; - - bs2b->gain = 1.0f / (float)(1.0 - G_hi + G_lo); + bs2b->a0_hi = (1.0f - G_hi * (1.0f - x)) * g; + bs2b->a1_hi = -x * g; } /* init */ /* Exported functions. @@ -151,35 +140,4 @@ void bs2b_clear(struct bs2b *bs2b) memset(&bs2b->last_sample, 0, sizeof(bs2b->last_sample)); } /* bs2b_clear */ -void bs2b_cross_feed(struct bs2b *bs2b, float *sample) -{ - /* Lowpass filter */ - bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]); - bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]); - - /* Highboost filter */ - bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]); - bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]); - bs2b->last_sample.asis[0] = sample[0]; - bs2b->last_sample.asis[1] = sample[1]; - - /* Crossfeed */ - sample[0] = (float)(bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1]); - sample[1] = (float)(bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0]); - - /* Bass boost cause allpass attenuation */ - sample[0] *= bs2b->gain; - sample[1] *= bs2b->gain; - - /* Clipping of overloaded samples */ -#if 0 - if (sample[0] > 1.0) - sample[0] = 1.0; - if (sample[0] < -1.0) - sample[0] = -1.0; - if (sample[1] > 1.0) - sample[1] = 1.0; - if (sample[1] < -1.0) - sample[1] = -1.0; -#endif -} /* bs2b_cross_feed */ +extern inline void bs2b_cross_feed(struct bs2b *bs2b, float *restrict samples); diff --git a/jni/openal-soft-1.16.0/Alc/compat.h b/jni/openal-soft-1.16.0/Alc/compat.h new file mode 100644 index 00000000..f54ef9ce --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/compat.h @@ -0,0 +1,32 @@ +#ifndef AL_COMPAT_H +#define AL_COMPAT_H + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include + +WCHAR *strdupW(const WCHAR *str); + +/* Opens a file with standard I/O. The filename is expected to be UTF-8. */ +FILE *al_fopen(const char *fname, const char *mode); + +#define HAVE_DYNLOAD 1 + +#else + +#define al_fopen fopen + +#if defined(HAVE_DLFCN_H) && !defined(IN_IDE_PARSER) +#define HAVE_DYNLOAD 1 +#endif + +#endif + +#ifdef HAVE_DYNLOAD +void *LoadLib(const char *name); +void CloseLib(void *handle); +void *GetSymbol(void *handle, const char *name); +#endif + +#endif /* AL_COMPAT_H */ diff --git a/jni/openal-soft-android/Alc/effects/autowah.c b/jni/openal-soft-1.16.0/Alc/effects/autowah.c similarity index 93% rename from jni/openal-soft-android/Alc/effects/autowah.c rename to jni/openal-soft-1.16.0/Alc/effects/autowah.c index 9a45e233..c8317c8b 100644 --- a/jni/openal-soft-android/Alc/effects/autowah.c +++ b/jni/openal-soft-1.16.0/Alc/effects/autowah.c @@ -59,7 +59,7 @@ static ALvoid ALautowahState_Destruct(ALautowahState *UNUSED(state)) static ALboolean ALautowahState_deviceUpdate(ALautowahState *state, ALCdevice *device) { - state->Frequency = device->Frequency; + state->Frequency = (ALfloat)device->Frequency; return AL_TRUE; } @@ -71,8 +71,8 @@ static ALvoid ALautowahState_update(ALautowahState *state, ALCdevice *device, co attackTime = slot->EffectProps.Autowah.AttackTime * state->Frequency; releaseTime = slot->EffectProps.Autowah.ReleaseTime * state->Frequency; - state->AttackRate = 1.0f / attackTime; - state->ReleaseRate = 1.0f / releaseTime; + state->AttackRate = powf(1.0f/GAIN_SILENCE_THRESHOLD, 1.0f/attackTime); + state->ReleaseRate = powf(GAIN_SILENCE_THRESHOLD/1.0f, 1.0f/releaseTime); state->PeakGain = slot->EffectProps.Autowah.PeakGain; state->Resonance = slot->EffectProps.Autowah.Resonance; @@ -100,15 +100,15 @@ static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo, /* Similar to compressor, we get the current amplitude of the * incoming signal, and attack or release to reach it. */ - amplitude = fabs(smp); + amplitude = fabsf(smp); if(amplitude > gain) - gain = minf(gain+state->AttackRate, amplitude); + gain = minf(gain*state->AttackRate, amplitude); else if(amplitude < gain) - gain = maxf(gain-state->ReleaseRate, amplitude); + gain = maxf(gain*state->ReleaseRate, amplitude); gain = maxf(gain, GAIN_SILENCE_THRESHOLD); /* FIXME: What range does the filter cover? */ - cutoff = lerp(1000.0f, (ALfloat)LOWPASSFREQREF, minf(gain/state->PeakGain, 1.0f)); + cutoff = lerp(20.0f, 20000.0f, minf(gain/state->PeakGain, 1.0f)); /* The code below is like calling ALfilterState_setParams with * ALfilterType_LowPass. However, instead of passing a bandwidth, @@ -151,10 +151,7 @@ static ALvoid ALautowahState_process(ALautowahState *state, ALuint SamplesToDo, } } -static void ALautowahState_Delete(ALautowahState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALautowahState) DEFINE_ALEFFECTSTATE_VTABLE(ALautowahState); @@ -167,13 +164,13 @@ static ALeffectState *ALautowahStateFactory_create(ALautowahStateFactory *UNUSED { ALautowahState *state; - state = malloc(sizeof(*state)); + state = ALautowahState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALautowahState, ALeffectState, state); - state->AttackRate = 0.0f; - state->ReleaseRate = 0.0f; - state->Resonance = 0.0f; + state->AttackRate = 1.0f; + state->ReleaseRate = 1.0f; + state->Resonance = 2.0f; state->PeakGain = 1.0f; state->GainCtrl = 1.0f; diff --git a/jni/openal-soft-android/Alc/effects/chorus.c b/jni/openal-soft-1.16.0/Alc/effects/chorus.c similarity index 93% rename from jni/openal-soft-android/Alc/effects/chorus.c rename to jni/openal-soft-1.16.0/Alc/effects/chorus.c index 4945faf2..a6bb199e 100644 --- a/jni/openal-soft-android/Alc/effects/chorus.c +++ b/jni/openal-soft-1.16.0/Alc/effects/chorus.c @@ -30,6 +30,11 @@ #include "alu.h" +enum ChorusWaveForm { + CWF_Triangle = AL_CHORUS_WAVEFORM_TRIANGLE, + CWF_Sinusoid = AL_CHORUS_WAVEFORM_SINUSOID +}; + typedef struct ALchorusState { DERIVE_FROM_TYPE(ALeffectState); @@ -44,7 +49,7 @@ typedef struct ALchorusState { ALfloat Gain[2][MaxChannels]; /* effect parameters */ - ALint waveform; + enum ChorusWaveForm waveform; ALint delay; ALfloat depth; ALfloat feedback; @@ -92,7 +97,15 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons ALfloat rate; ALint phase; - state->waveform = Slot->EffectProps.Chorus.Waveform; + switch(Slot->EffectProps.Chorus.Waveform) + { + case AL_CHORUS_WAVEFORM_TRIANGLE: + state->waveform = CWF_Triangle; + break; + case AL_CHORUS_WAVEFORM_SINUSOID: + state->waveform = CWF_Sinusoid; + break; + } state->depth = Slot->EffectProps.Chorus.Depth; state->feedback = Slot->EffectProps.Chorus.Feedback; state->delay = fastf2i(Slot->EffectProps.Chorus.Delay * frequency); @@ -115,10 +128,10 @@ static ALvoid ALchorusState_update(ALchorusState *state, ALCdevice *Device, cons state->lfo_range = fastf2u(frequency/rate + 0.5f); switch(state->waveform) { - case AL_CHORUS_WAVEFORM_TRIANGLE: + case CWF_Triangle: state->lfo_scale = 4.0f / state->lfo_range; break; - case AL_CHORUS_WAVEFORM_SINUSOID: + case CWF_Sinusoid: state->lfo_scale = F_2PI / state->lfo_range; break; } @@ -198,10 +211,15 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, co ALfloat temps[64][2]; ALuint td = minu(SamplesToDo-base, 64); - if(state->waveform == AL_CHORUS_WAVEFORM_TRIANGLE) - ProcessTriangle(state, td, SamplesIn+base, temps); - else if(state->waveform == AL_CHORUS_WAVEFORM_SINUSOID) - ProcessSinusoid(state, td, SamplesIn+base, temps); + switch(state->waveform) + { + case CWF_Triangle: + ProcessTriangle(state, td, SamplesIn+base, temps); + break; + case CWF_Sinusoid: + ProcessSinusoid(state, td, SamplesIn+base, temps); + break; + } for(kt = 0;kt < MaxChannels;kt++) { @@ -224,10 +242,7 @@ static ALvoid ALchorusState_process(ALchorusState *state, ALuint SamplesToDo, co } } -static void ALchorusState_Delete(ALchorusState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALchorusState) DEFINE_ALEFFECTSTATE_VTABLE(ALchorusState); @@ -240,7 +255,7 @@ static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(f { ALchorusState *state; - state = malloc(sizeof(*state)); + state = ALchorusState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALchorusState, ALeffectState, state); @@ -249,6 +264,7 @@ static ALeffectState *ALchorusStateFactory_create(ALchorusStateFactory *UNUSED(f state->SampleBuffer[1] = NULL; state->offset = 0; state->lfo_range = 1; + state->waveform = CWF_Triangle; return STATIC_CAST(ALeffectState, state); } diff --git a/jni/openal-soft-android/Alc/effects/compressor.c b/jni/openal-soft-1.16.0/Alc/effects/compressor.c similarity index 96% rename from jni/openal-soft-android/Alc/effects/compressor.c rename to jni/openal-soft-1.16.0/Alc/effects/compressor.c index 14c0ed10..9728cabe 100644 --- a/jni/openal-soft-android/Alc/effects/compressor.c +++ b/jni/openal-soft-1.16.0/Alc/effects/compressor.c @@ -84,12 +84,12 @@ static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint Samples { smp = SamplesIn[it+base]; - amplitude = fabs(smp); + amplitude = fabsf(smp); if(amplitude > gain) gain = minf(gain+state->AttackRate, amplitude); else if(amplitude < gain) gain = maxf(gain-state->ReleaseRate, amplitude); - output = 1.0 / clampf(gain, 0.5f, 2.0f); + output = 1.0f / clampf(gain, 0.5f, 2.0f); temps[it] = smp * output; } @@ -133,10 +133,7 @@ static ALvoid ALcompressorState_process(ALcompressorState *state, ALuint Samples } } -static void ALcompressorState_Delete(ALcompressorState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALcompressorState) DEFINE_ALEFFECTSTATE_VTABLE(ALcompressorState); @@ -149,7 +146,7 @@ static ALeffectState *ALcompressorStateFactory_create(ALcompressorStateFactory * { ALcompressorState *state; - state = malloc(sizeof(*state)); + state = ALcompressorState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALcompressorState, ALeffectState, state); diff --git a/jni/openal-soft-android/Alc/effects/dedicated.c b/jni/openal-soft-1.16.0/Alc/effects/dedicated.c similarity index 97% rename from jni/openal-soft-android/Alc/effects/dedicated.c rename to jni/openal-soft-1.16.0/Alc/effects/dedicated.c index fe57c7d8..89af1c84 100644 --- a/jni/openal-soft-android/Alc/effects/dedicated.c +++ b/jni/openal-soft-1.16.0/Alc/effects/dedicated.c @@ -76,10 +76,7 @@ static ALvoid ALdedicatedState_process(ALdedicatedState *state, ALuint SamplesTo } } -static void ALdedicatedState_Delete(ALdedicatedState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALdedicatedState) DEFINE_ALEFFECTSTATE_VTABLE(ALdedicatedState); @@ -93,7 +90,7 @@ ALeffectState *ALdedicatedStateFactory_create(ALdedicatedStateFactory *UNUSED(fa ALdedicatedState *state; ALsizei s; - state = malloc(sizeof(*state)); + state = ALdedicatedState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALdedicatedState, ALeffectState, state); diff --git a/jni/openal-soft-android/Alc/effects/distortion.c b/jni/openal-soft-1.16.0/Alc/effects/distortion.c similarity index 98% rename from jni/openal-soft-android/Alc/effects/distortion.c rename to jni/openal-soft-1.16.0/Alc/effects/distortion.c index e39a8197..b535655b 100644 --- a/jni/openal-soft-android/Alc/effects/distortion.c +++ b/jni/openal-soft-1.16.0/Alc/effects/distortion.c @@ -170,10 +170,7 @@ static ALvoid ALdistortionState_process(ALdistortionState *state, ALuint Samples } } -static void ALdistortionState_Delete(ALdistortionState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALdistortionState) DEFINE_ALEFFECTSTATE_VTABLE(ALdistortionState); @@ -186,7 +183,7 @@ static ALeffectState *ALdistortionStateFactory_create(ALdistortionStateFactory * { ALdistortionState *state; - state = malloc(sizeof(*state)); + state = ALdistortionState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALdistortionState, ALeffectState, state); diff --git a/jni/openal-soft-android/Alc/effects/echo.c b/jni/openal-soft-1.16.0/Alc/effects/echo.c similarity index 98% rename from jni/openal-soft-android/Alc/effects/echo.c rename to jni/openal-soft-1.16.0/Alc/effects/echo.c index 7471c3dd..049ae9c7 100644 --- a/jni/openal-soft-android/Alc/effects/echo.c +++ b/jni/openal-soft-1.16.0/Alc/effects/echo.c @@ -97,7 +97,7 @@ static ALvoid ALechoState_update(ALechoState *state, ALCdevice *Device, const AL ALfilterState_setParams(&state->Filter, ALfilterType_HighShelf, 1.0f - Slot->EffectProps.Echo.Damping, - (ALfloat)LOWPASSFREQREF/frequency, 0.0f); + LOWPASSFREQREF/frequency, 0.0f); gain = Slot->Gain; dirGain = fabsf(lrpan); @@ -161,10 +161,7 @@ static ALvoid ALechoState_process(ALechoState *state, ALuint SamplesToDo, const state->Offset = offset; } -static void ALechoState_Delete(ALechoState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALechoState) DEFINE_ALEFFECTSTATE_VTABLE(ALechoState); @@ -177,7 +174,7 @@ ALeffectState *ALechoStateFactory_create(ALechoStateFactory *UNUSED(factory)) { ALechoState *state; - state = malloc(sizeof(*state)); + state = ALechoState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALechoState, ALeffectState, state); diff --git a/jni/openal-soft-android/Alc/effects/equalizer.c b/jni/openal-soft-1.16.0/Alc/effects/equalizer.c similarity index 99% rename from jni/openal-soft-android/Alc/effects/equalizer.c rename to jni/openal-soft-1.16.0/Alc/effects/equalizer.c index d5bd2caf..cfe7c46c 100644 --- a/jni/openal-soft-android/Alc/effects/equalizer.c +++ b/jni/openal-soft-1.16.0/Alc/effects/equalizer.c @@ -155,10 +155,7 @@ static ALvoid ALequalizerState_process(ALequalizerState *state, ALuint SamplesTo } } -static void ALequalizerState_Delete(ALequalizerState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALequalizerState) DEFINE_ALEFFECTSTATE_VTABLE(ALequalizerState); @@ -172,7 +169,7 @@ ALeffectState *ALequalizerStateFactory_create(ALequalizerStateFactory *UNUSED(fa ALequalizerState *state; int it; - state = malloc(sizeof(*state)); + state = ALequalizerState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALequalizerState, ALeffectState, state); diff --git a/jni/openal-soft-android/Alc/effects/flanger.c b/jni/openal-soft-1.16.0/Alc/effects/flanger.c similarity index 93% rename from jni/openal-soft-android/Alc/effects/flanger.c rename to jni/openal-soft-1.16.0/Alc/effects/flanger.c index a94cd365..117cd1f2 100644 --- a/jni/openal-soft-android/Alc/effects/flanger.c +++ b/jni/openal-soft-1.16.0/Alc/effects/flanger.c @@ -30,6 +30,11 @@ #include "alu.h" +enum FlangerWaveForm { + FWF_Triangle = AL_FLANGER_WAVEFORM_TRIANGLE, + FWF_Sinusoid = AL_FLANGER_WAVEFORM_SINUSOID +}; + typedef struct ALflangerState { DERIVE_FROM_TYPE(ALeffectState); @@ -44,7 +49,7 @@ typedef struct ALflangerState { ALfloat Gain[2][MaxChannels]; /* effect parameters */ - ALint waveform; + enum FlangerWaveForm waveform; ALint delay; ALfloat depth; ALfloat feedback; @@ -92,7 +97,15 @@ static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, co ALfloat rate; ALint phase; - state->waveform = Slot->EffectProps.Flanger.Waveform; + switch(Slot->EffectProps.Flanger.Waveform) + { + case AL_FLANGER_WAVEFORM_TRIANGLE: + state->waveform = FWF_Triangle; + break; + case AL_FLANGER_WAVEFORM_SINUSOID: + state->waveform = FWF_Sinusoid; + break; + } state->depth = Slot->EffectProps.Flanger.Depth; state->feedback = Slot->EffectProps.Flanger.Feedback; state->delay = fastf2i(Slot->EffectProps.Flanger.Delay * frequency); @@ -115,10 +128,10 @@ static ALvoid ALflangerState_update(ALflangerState *state, ALCdevice *Device, co state->lfo_range = fastf2u(frequency/rate + 0.5f); switch(state->waveform) { - case AL_FLANGER_WAVEFORM_TRIANGLE: + case FWF_Triangle: state->lfo_scale = 4.0f / state->lfo_range; break; - case AL_FLANGER_WAVEFORM_SINUSOID: + case FWF_Sinusoid: state->lfo_scale = F_2PI / state->lfo_range; break; } @@ -198,10 +211,15 @@ static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo, ALfloat temps[64][2]; ALuint td = minu(SamplesToDo-base, 64); - if(state->waveform == AL_FLANGER_WAVEFORM_TRIANGLE) - ProcessTriangle(state, td, SamplesIn+base, temps); - else if(state->waveform == AL_FLANGER_WAVEFORM_SINUSOID) - ProcessSinusoid(state, td, SamplesIn+base, temps); + switch(state->waveform) + { + case FWF_Triangle: + ProcessTriangle(state, td, SamplesIn+base, temps); + break; + case FWF_Sinusoid: + ProcessSinusoid(state, td, SamplesIn+base, temps); + break; + } for(kt = 0;kt < MaxChannels;kt++) { @@ -224,10 +242,7 @@ static ALvoid ALflangerState_process(ALflangerState *state, ALuint SamplesToDo, } } -static void ALflangerState_Delete(ALflangerState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALflangerState) DEFINE_ALEFFECTSTATE_VTABLE(ALflangerState); @@ -240,7 +255,7 @@ ALeffectState *ALflangerStateFactory_create(ALflangerStateFactory *UNUSED(factor { ALflangerState *state; - state = malloc(sizeof(*state)); + state = ALflangerState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALflangerState, ALeffectState, state); @@ -249,6 +264,7 @@ ALeffectState *ALflangerStateFactory_create(ALflangerStateFactory *UNUSED(factor state->SampleBuffer[1] = NULL; state->offset = 0; state->lfo_range = 1; + state->waveform = FWF_Triangle; return STATIC_CAST(ALeffectState, state); } diff --git a/jni/openal-soft-android/Alc/effects/modulator.c b/jni/openal-soft-1.16.0/Alc/effects/modulator.c similarity index 98% rename from jni/openal-soft-android/Alc/effects/modulator.c rename to jni/openal-soft-1.16.0/Alc/effects/modulator.c index 17ca7e17..a5475708 100644 --- a/jni/openal-soft-android/Alc/effects/modulator.c +++ b/jni/openal-soft-1.16.0/Alc/effects/modulator.c @@ -171,10 +171,7 @@ static ALvoid ALmodulatorState_process(ALmodulatorState *state, ALuint SamplesTo } } -static void ALmodulatorState_Delete(ALmodulatorState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALmodulatorState) DEFINE_ALEFFECTSTATE_VTABLE(ALmodulatorState); @@ -187,7 +184,7 @@ static ALeffectState *ALmodulatorStateFactory_create(ALmodulatorStateFactory *UN { ALmodulatorState *state; - state = malloc(sizeof(*state)); + state = ALmodulatorState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALmodulatorState, ALeffectState, state); diff --git a/jni/openal-soft-android/Alc/effects/null.c b/jni/openal-soft-1.16.0/Alc/effects/null.c similarity index 91% rename from jni/openal-soft-android/Alc/effects/null.c rename to jni/openal-soft-1.16.0/Alc/effects/null.c index 816a2525..6dacd021 100644 --- a/jni/openal-soft-android/Alc/effects/null.c +++ b/jni/openal-soft-1.16.0/Alc/effects/null.c @@ -48,10 +48,20 @@ static ALvoid ALnullState_process(ALnullState* UNUSED(state), ALuint UNUSED(samp (void)samplesOut; } -/* This frees the memory used by the object, after it has been destructed. */ -static void ALnullState_Delete(ALnullState *state) +/* This allocates memory to store the object, before it gets constructed. + * DECLARE_DEFAULT_ALLOCATORS can be used to declate a default method. + */ +static void *ALnullState_New(size_t size) { - free(state); + return malloc(size); +} + +/* This frees the memory used by the object, after it has been destructed. + * DECLARE_DEFAULT_ALLOCATORS can be used to declate a default method. + */ +static void ALnullState_Delete(void *ptr) +{ + free(ptr); } /* Define the forwards and the ALeffectState vtable for this type. */ @@ -67,7 +77,7 @@ ALeffectState *ALnullStateFactory_create(ALnullStateFactory *UNUSED(factory)) { ALnullState *state; - state = calloc(1, sizeof(*state)); + state = ALnullState_New(sizeof(*state)); if(!state) return NULL; /* Set vtables for inherited types. */ SET_VTABLE2(ALnullState, ALeffectState, state); diff --git a/jni/openal-soft-android/Alc/effects/reverb.c b/jni/openal-soft-1.16.0/Alc/effects/reverb.c similarity index 99% rename from jni/openal-soft-android/Alc/effects/reverb.c rename to jni/openal-soft-1.16.0/Alc/effects/reverb.c index 75ec76e3..245aed41 100644 --- a/jni/openal-soft-android/Alc/effects/reverb.c +++ b/jni/openal-soft-1.16.0/Alc/effects/reverb.c @@ -1096,7 +1096,7 @@ static ALvoid ALreverbState_update(ALreverbState *State, ALCdevice *Device, cons } else { - hfscale = (ALfloat)LOWPASSFREQREF / frequency; + hfscale = LOWPASSFREQREF / frequency; ALfilterState_setParams(&State->LpFilter, ALfilterType_HighShelf, Slot->EffectProps.Reverb.GainHF, hfscale, 0.0f); @@ -1170,10 +1170,7 @@ static ALvoid ALreverbState_Destruct(ALreverbState *State) State->SampleBuffer = NULL; } -static void ALreverbState_Delete(ALreverbState *state) -{ - free(state); -} +DECLARE_DEFAULT_ALLOCATORS(ALreverbState) DEFINE_ALEFFECTSTATE_VTABLE(ALreverbState); @@ -1187,7 +1184,7 @@ static ALeffectState *ALreverbStateFactory_create(ALreverbStateFactory* UNUSED(f ALreverbState *state; ALuint index; - state = malloc(sizeof(ALreverbState)); + state = ALreverbState_New(sizeof(*state)); if(!state) return NULL; SET_VTABLE2(ALreverbState, ALeffectState, state); diff --git a/jni/openal-soft-android/Alc/evtqueue.h b/jni/openal-soft-1.16.0/Alc/evtqueue.h similarity index 100% rename from jni/openal-soft-android/Alc/evtqueue.h rename to jni/openal-soft-1.16.0/Alc/evtqueue.h diff --git a/jni/openal-soft-1.16.0/Alc/helpers.c b/jni/openal-soft-1.16.0/Alc/helpers.c new file mode 100644 index 00000000..fc879d95 --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/helpers.c @@ -0,0 +1,814 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2011 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#ifdef _WIN32 +#ifdef __MINGW32__ +#define _WIN32_IE 0x501 +#else +#define _WIN32_IE 0x400 +#endif +#endif + +#include "config.h" + +#include +#include +#include +#include +#ifdef HAVE_MALLOC_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); + +#ifdef HAVE_MMDEVAPI +#include +DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); +#endif +#endif +#endif /* AL_NO_UID_DEFS */ + +#ifdef HAVE_DLFCN_H +#include +#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 + +#ifdef _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<<19))) + caps |= CPU_CAP_SSE4_1; + } + } + } + } +#elif defined(HAVE_CPUID_INTRINSIC) && (defined(__i386__) || defined(__x86_64__) || \ + defined(_M_IX86) || defined(_M_X64)) + union { + int regs[4]; + char str[sizeof(int[4])]; + } cpuinf[3]; + + (__cpuid)(cpuinf[0].regs, 0); + if(cpuinf[0].regs[0] == 0) + ERR("Failed to get CPUID\n"); + else + { + unsigned int maxfunc = cpuinf[0].regs[0]; + unsigned int maxextfunc; + + (__cpuid)(cpuinf[0].regs, 0x80000000); + maxextfunc = cpuinf[0].regs[0]; + + TRACE("Detected max CPUID function: 0x%x (ext. 0x%x)\n", maxfunc, maxextfunc); + + TRACE("Vendor ID: \"%.4s%.4s%.4s\"\n", cpuinf[0].str+4, cpuinf[0].str+12, cpuinf[0].str+8); + if(maxextfunc >= 0x80000004) + { + (__cpuid)(cpuinf[0].regs, 0x80000002); + (__cpuid)(cpuinf[1].regs, 0x80000003); + (__cpuid)(cpuinf[2].regs, 0x80000004); + TRACE("Name: \"%.16s%.16s%.16s\"\n", cpuinf[0].str, cpuinf[1].str, cpuinf[2].str); + } + + if(maxfunc >= 1) + { + (__cpuid)(cpuinf[0].regs, 1); + if((cpuinf[0].regs[3]&(1<<25))) + { + caps |= CPU_CAP_SSE; + if((cpuinf[0].regs[3]&(1<<26))) + { + caps |= CPU_CAP_SSE2; + if((cpuinf[0].regs[2]&(1<<19))) + caps |= CPU_CAP_SSE4_1; + } + } + } + } +#else + /* Assume support for whatever's supported if we can't check for it */ +#if defined(HAVE_SSE4_1) +#warning "Assuming SSE 4.1 run-time support!" + capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE4_1; +#elif defined(HAVE_SSE2) +#warning "Assuming SSE 2 run-time support!" + capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2; +#elif defined(HAVE_SSE) +#warning "Assuming SSE run-time support!" + capfilter |= CPU_CAP_SSE; +#endif +#endif +#ifdef HAVE_NEON + /* Assume Neon support if compiled with it */ + caps |= CPU_CAP_NEON; +#endif + + TRACE("Extensions:%s%s%s%s%s\n", + ((capfilter&CPU_CAP_SSE) ? ((caps&CPU_CAP_SSE) ? " +SSE" : " -SSE") : ""), + ((capfilter&CPU_CAP_SSE2) ? ((caps&CPU_CAP_SSE2) ? " +SSE2" : " -SSE2") : ""), + ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""), + ((capfilter&CPU_CAP_NEON) ? ((caps&CPU_CAP_NEON) ? " +Neon" : " -Neon") : ""), + ((!capfilter) ? " -none-" : "") + ); + CPUCapFlags = caps & capfilter; +} + + +void *al_malloc(size_t alignment, size_t size) +{ +#if defined(HAVE_ALIGNED_ALLOC) + size = (size+(alignment-1))&~(alignment-1); + return aligned_alloc(alignment, size); +#elif defined(HAVE_POSIX_MEMALIGN) + void *ret; + if(posix_memalign(&ret, alignment, size) == 0) + return ret; + return NULL; +#elif defined(HAVE__ALIGNED_MALLOC) + return _aligned_malloc(size, alignment); +#else + char *ret = malloc(size+alignment); + if(ret != NULL) + { + *(ret++) = 0x00; + while(((ALintptrEXT)ret&(alignment-1)) != 0) + *(ret++) = 0x55; + } + return ret; +#endif +} + +void *al_calloc(size_t alignment, size_t size) +{ + void *ret = al_malloc(alignment, size); + if(ret) memset(ret, 0, size); + return ret; +} + +void al_free(void *ptr) +{ +#if defined(HAVE_ALIGNED_ALLOC) || defined(HAVE_POSIX_MEMALIGN) + free(ptr); +#elif defined(HAVE__ALIGNED_MALLOC) + _aligned_free(ptr); +#else + if(ptr != NULL) + { + char *finder = ptr; + do { + --finder; + } while(*finder == 0x55); + free(finder); + } +#endif +} + + +void SetMixerFPUMode(FPUCtl *ctl) +{ +#ifdef HAVE_FENV_H + fegetenv(STATIC_CAST(fenv_t, ctl)); +#if defined(__GNUC__) && defined(HAVE_SSE) + if((CPUCapFlags&CPU_CAP_SSE)) + __asm__ __volatile__("stmxcsr %0" : "=m" (*&ctl->sse_state)); +#endif + +#ifdef FE_TOWARDZERO + fesetround(FE_TOWARDZERO); +#endif +#if defined(__GNUC__) && defined(HAVE_SSE) + if((CPUCapFlags&CPU_CAP_SSE)) + { + int sseState = ctl->sse_state; + sseState |= 0x6000; /* set round-to-zero */ + sseState |= 0x8000; /* set flush-to-zero */ + if((CPUCapFlags&CPU_CAP_SSE2)) + sseState |= 0x0040; /* set denormals-are-zero */ + __asm__ __volatile__("ldmxcsr %0" : : "m" (*&sseState)); + } +#endif + +#elif defined(HAVE___CONTROL87_2) + + int mode; + __control87_2(0, 0, &ctl->state, NULL); + __control87_2(_RC_CHOP, _MCW_RC, &mode, NULL); +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + { + __control87_2(0, 0, NULL, &ctl->sse_state); + __control87_2(_RC_CHOP|_DN_FLUSH, _MCW_RC|_MCW_DN, NULL, &mode); + } +#endif + +#elif defined(HAVE__CONTROLFP) + + ctl->state = _controlfp(0, 0); + (void)_controlfp(_RC_CHOP, _MCW_RC); +#endif +} + +void RestoreFPUMode(const FPUCtl *ctl) +{ +#ifdef HAVE_FENV_H + fesetenv(STATIC_CAST(fenv_t, ctl)); +#if defined(__GNUC__) && defined(HAVE_SSE) + if((CPUCapFlags&CPU_CAP_SSE)) + __asm__ __volatile__("ldmxcsr %0" : : "m" (*&ctl->sse_state)); +#endif + +#elif defined(HAVE___CONTROL87_2) + + int mode; + __control87_2(ctl->state, _MCW_RC, &mode, NULL); +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + __control87_2(ctl->sse_state, _MCW_RC|_MCW_DN, NULL, &mode); +#endif + +#elif defined(HAVE__CONTROLFP) + + _controlfp(ctl->state, _MCW_RC); +#endif +} + + +#ifdef _WIN32 + +static WCHAR *FromUTF8(const char *str) +{ + WCHAR *out = NULL; + int len; + + if((len=MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0)) > 0) + { + out = calloc(sizeof(WCHAR), len); + MultiByteToWideChar(CP_UTF8, 0, str, -1, out, len); + } + return out; +} + + +void *LoadLib(const char *name) +{ + HANDLE hdl = NULL; + WCHAR *wname; + + wname = FromUTF8(name); + if(!wname) + ERR("Failed to convert UTF-8 filename: \"%s\"\n", name); + else + { + hdl = LoadLibraryW(wname); + free(wname); + } + return hdl; +} +void CloseLib(void *handle) +{ FreeLibrary((HANDLE)handle); } +void *GetSymbol(void *handle, const char *name) +{ + void *ret; + + ret = (void*)GetProcAddress((HANDLE)handle, name); + if(ret == NULL) + ERR("Failed to load %s\n", name); + return ret; +} + +WCHAR *strdupW(const WCHAR *str) +{ + const WCHAR *n; + WCHAR *ret; + size_t len; + + n = str; + while(*n) n++; + len = n - str; + + ret = calloc(sizeof(WCHAR), len+1); + if(ret != NULL) + memcpy(ret, str, sizeof(WCHAR)*len); + return ret; +} + +FILE *al_fopen(const char *fname, const char *mode) +{ + WCHAR *wname=NULL, *wmode=NULL; + FILE *file = NULL; + + wname = FromUTF8(fname); + wmode = FromUTF8(mode); + if(!wname) + ERR("Failed to convert UTF-8 filename: \"%s\"\n", fname); + else if(!wmode) + ERR("Failed to convert UTF-8 mode: \"%s\"\n", mode); + else + file = _wfopen(wname, wmode); + + free(wname); + free(wmode); + + return file; +} + +#else + +#ifdef HAVE_DLFCN_H + +void *LoadLib(const char *name) +{ + const char *err; + void *handle; + + dlerror(); + handle = dlopen(name, RTLD_NOW); + if((err=dlerror()) != NULL) + handle = NULL; + return handle; +} +void CloseLib(void *handle) +{ dlclose(handle); } +void *GetSymbol(void *handle, const char *name) +{ + const char *err; + void *sym; + + dlerror(); + sym = dlsym(handle, name); + if((err=dlerror()) != NULL) + { + WARN("Failed to load %s: %s\n", name, err); + sym = NULL; + } + return sym; +} + +#endif +#endif + + +void al_print(const char *type, const char *func, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + fprintf(LogFile, "AL lib: %s %s: ", type, func); + vfprintf(LogFile, fmt, ap); + va_end(ap); + + fflush(LogFile); +} + +#ifdef _WIN32 +static inline int is_slash(int c) +{ return (c == '\\' || c == '/'); } + +FILE *OpenDataFile(const char *fname, const char *subdir) +{ + static const int ids[2] = { CSIDL_APPDATA, CSIDL_COMMON_APPDATA }; + WCHAR *wname=NULL, *wsubdir=NULL; + FILE *f; + int i; + + /* If the path is absolute, open it directly. */ + if(fname[0] != '\0' && fname[1] == ':' && is_slash(fname[2])) + { + if((f=al_fopen(fname, "rb")) != NULL) + { + TRACE("Opened %s\n", fname); + return f; + } + WARN("Could not open %s\n", fname); + return NULL; + } + + /* If it's relative, try the current directory first before the data directories. */ + if((f=al_fopen(fname, "rb")) != NULL) + { + TRACE("Opened %s\n", fname); + return f; + } + WARN("Could not open %s\n", fname); + + wname = FromUTF8(fname); + wsubdir = FromUTF8(subdir); + if(!wname) + ERR("Failed to convert UTF-8 filename: \"%s\"\n", fname); + else if(!wsubdir) + ERR("Failed to convert UTF-8 subdir: \"%s\"\n", subdir); + else for(i = 0;i < 2;i++) + { + WCHAR buffer[PATH_MAX]; + size_t len; + + if(SHGetSpecialFolderPathW(NULL, buffer, ids[i], FALSE) == FALSE) + continue; + + len = lstrlenW(buffer); + if(len > 0 && is_slash(buffer[len-1])) + buffer[--len] = '\0'; + _snwprintf(buffer+len, PATH_MAX-len, L"/%ls/%ls", wsubdir, wname); + len = lstrlenW(buffer); + while(len > 0) + { + --len; + if(buffer[len] == '/') + buffer[len] = '\\'; + } + + if((f=_wfopen(buffer, L"rb")) != NULL) + { + TRACE("Opened %ls\n", buffer); + return f; + } + WARN("Could not open %ls\n", buffer); + } + free(wname); + free(wsubdir); + + return NULL; +} +#else +FILE *OpenDataFile(const char *fname, const char *subdir) +{ + char buffer[PATH_MAX] = ""; + const char *str, *next; + FILE *f; + + if(fname[0] == '/') + { + if((f=al_fopen(fname, "rb")) != NULL) + { + TRACE("Opened %s\n", fname); + return f; + } + WARN("Could not open %s\n", fname); + return NULL; + } + + if((f=al_fopen(fname, "rb")) != NULL) + { + TRACE("Opened %s\n", fname); + return f; + } + WARN("Could not open %s\n", fname); + + if((str=getenv("XDG_DATA_HOME")) != NULL && str[0] != '\0') + snprintf(buffer, sizeof(buffer), "%s/%s/%s", str, subdir, fname); + else if((str=getenv("HOME")) != NULL && str[0] != '\0') + snprintf(buffer, sizeof(buffer), "%s/.local/share/%s/%s", str, subdir, fname); + if(buffer[0]) + { + if((f=al_fopen(buffer, "rb")) != NULL) + { + TRACE("Opened %s\n", buffer); + return f; + } + WARN("Could not open %s\n", buffer); + } + + if((str=getenv("XDG_DATA_DIRS")) == NULL || str[0] == '\0') + str = "/usr/local/share/:/usr/share/"; + + next = str; + while((str=next) != NULL && str[0] != '\0') + { + size_t len; + next = strchr(str, ':'); + + if(!next) + len = strlen(str); + else + { + len = next - str; + next++; + } + + if(len > sizeof(buffer)-1) + len = sizeof(buffer)-1; + strncpy(buffer, str, len); + buffer[len] = '\0'; + snprintf(buffer+len, sizeof(buffer)-len, "/%s/%s", subdir, fname); + + if((f=al_fopen(buffer, "rb")) != NULL) + { + TRACE("Opened %s\n", buffer); + return f; + } + WARN("Could not open %s\n", buffer); + } + + return NULL; +} +#endif + + +void SetRTPriority(void) +{ + ALboolean failed = AL_FALSE; + +#ifdef _WIN32 + if(RTPrioLevel > 0) + failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); +#elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__) + if(RTPrioLevel > 0) + { + struct sched_param param; + /* Use the minimum real-time priority possible for now (on Linux this + * should be 1 for SCHED_RR) */ + param.sched_priority = sched_get_priority_min(SCHED_RR); + failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, ¶m); + } +#else + /* Real-time priority not available */ + failed = (RTPrioLevel>0); +#endif + if(failed) + ERR("Failed to set priority level for thread\n"); +} + + +ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count, ALboolean exact) +{ + vector_ *vecptr = (vector_*)ptr; + if(obj_count < 0) + return AL_FALSE; + if((*vecptr ? (*vecptr)->Capacity : 0) < obj_count) + { + ALsizei old_size = (*vecptr ? (*vecptr)->Size : 0); + void *temp; + + /* Use the next power-of-2 size if we don't need to allocate the exact + * amount. This is preferred when regularly increasing the vector since + * it means fewer reallocations. Though it means it also wastes some + * memory. */ + if(exact == AL_FALSE) + { + obj_count = NextPowerOf2((ALuint)obj_count); + if(obj_count < 0) return AL_FALSE; + } + + /* Need to be explicit with the caller type's base size, because it + * could have extra padding before the start of the array (that is, + * sizeof(*vector_) may not equal base_size). */ + temp = realloc(*vecptr, base_size + obj_size*obj_count); + if(temp == NULL) return AL_FALSE; + + *vecptr = temp; + (*vecptr)->Capacity = obj_count; + (*vecptr)->Size = old_size; + } + return AL_TRUE; +} + +ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count) +{ + vector_ *vecptr = (vector_*)ptr; + if(obj_count < 0) + return AL_FALSE; + if(*vecptr || obj_count > 0) + { + if(!vector_reserve((char*)vecptr, base_size, obj_size, obj_count, AL_TRUE)) + return AL_FALSE; + (*vecptr)->Size = obj_count; + } + return AL_TRUE; +} + +ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_pos, const void *datstart, const void *datend) +{ + vector_ *vecptr = (vector_*)ptr; + if(datstart != datend) + { + ptrdiff_t ins_elem = (*vecptr ? ((char*)ins_pos - ((char*)(*vecptr) + base_size)) : + ((char*)ins_pos - (char*)NULL)) / + obj_size; + ptrdiff_t numins = ((const char*)datend - (const char*)datstart) / obj_size; + + assert(numins > 0); + if(INT_MAX-VECTOR_SIZE(*vecptr) <= numins || + !vector_reserve((char*)vecptr, base_size, obj_size, VECTOR_SIZE(*vecptr)+numins, AL_TRUE)) + return AL_FALSE; + + /* NOTE: ins_pos may have been invalidated if *vecptr moved. Use ins_elem instead. */ + if(ins_elem < (*vecptr)->Size) + { + memmove((char*)(*vecptr) + base_size + ((ins_elem+numins)*obj_size), + (char*)(*vecptr) + base_size + ((ins_elem )*obj_size), + ((*vecptr)->Size-ins_elem)*obj_size); + } + memcpy((char*)(*vecptr) + base_size + (ins_elem*obj_size), + datstart, numins*obj_size); + (*vecptr)->Size += (ALsizei)numins; + } + return AL_TRUE; +} + + +extern inline void al_string_deinit(al_string *str); +extern inline ALsizei al_string_length(const_al_string str); +extern inline ALboolean al_string_empty(const_al_string str); +extern inline const al_string_char_type *al_string_get_cstr(const_al_string str); + +void al_string_clear(al_string *str) +{ + /* Reserve one more character than the total size of the string. This is to + * ensure we have space to add a null terminator in the string data so it + * can be used as a C-style string. */ + VECTOR_RESERVE(*str, 1); + VECTOR_RESIZE(*str, 0); + *VECTOR_ITER_END(*str) = 0; +} + +static inline int al_string_compare(const al_string_char_type *str1, ALsizei str1len, + const al_string_char_type *str2, ALsizei str2len) +{ + ALsizei complen = mini(str1len, str2len); + int ret = memcmp(str1, str2, complen); + if(ret == 0) + { + if(str1len > str2len) return 1; + if(str1len < str2len) return -1; + } + return ret; +} +int al_string_cmp(const_al_string str1, const_al_string str2) +{ + return al_string_compare(&VECTOR_FRONT(str1), al_string_length(str1), + &VECTOR_FRONT(str2), al_string_length(str2)); +} +int al_string_cmp_cstr(const_al_string str1, const al_string_char_type *str2) +{ + return al_string_compare(&VECTOR_FRONT(str1), al_string_length(str1), + str2, (ALsizei)strlen(str2)); +} + +void al_string_copy(al_string *str, const_al_string from) +{ + ALsizei len = VECTOR_SIZE(from); + VECTOR_RESERVE(*str, len+1); + VECTOR_RESIZE(*str, 0); + VECTOR_INSERT(*str, VECTOR_ITER_END(*str), VECTOR_ITER_BEGIN(from), VECTOR_ITER_BEGIN(from)+len); + *VECTOR_ITER_END(*str) = 0; +} + +void al_string_copy_cstr(al_string *str, const al_string_char_type *from) +{ + size_t len = strlen(from); + VECTOR_RESERVE(*str, len+1); + VECTOR_RESIZE(*str, 0); + VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, from+len); + *VECTOR_ITER_END(*str) = 0; +} + +void al_string_append_char(al_string *str, const al_string_char_type c) +{ + VECTOR_RESERVE(*str, al_string_length(*str)+2); + VECTOR_PUSH_BACK(*str, c); + *VECTOR_ITER_END(*str) = 0; +} + +void al_string_append_cstr(al_string *str, const al_string_char_type *from) +{ + size_t len = strlen(from); + if(len != 0) + { + VECTOR_RESERVE(*str, al_string_length(*str)+len+1); + VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, from+len); + *VECTOR_ITER_END(*str) = 0; + } +} + +void al_string_append_range(al_string *str, const al_string_char_type *from, const al_string_char_type *to) +{ + if(to != from) + { + VECTOR_RESERVE(*str, al_string_length(*str)+(to-from)+1); + VECTOR_INSERT(*str, VECTOR_ITER_END(*str), from, to); + *VECTOR_ITER_END(*str) = 0; + } +} + +#ifdef _WIN32 +void al_string_copy_wcstr(al_string *str, const wchar_t *from) +{ + int len; + if((len=WideCharToMultiByte(CP_UTF8, 0, from, -1, NULL, 0, NULL, NULL)) > 0) + { + VECTOR_RESERVE(*str, len); + VECTOR_RESIZE(*str, len-1); + WideCharToMultiByte(CP_UTF8, 0, from, -1, &VECTOR_FRONT(*str), len, NULL, NULL); + *VECTOR_ITER_END(*str) = 0; + } +} +#endif diff --git a/jni/openal-soft-android/Alc/hrtf.c b/jni/openal-soft-1.16.0/Alc/hrtf.c similarity index 71% rename from jni/openal-soft-android/Alc/hrtf.c rename to jni/openal-soft-1.16.0/Alc/hrtf.c index 49bb97a3..707655a0 100644 --- a/jni/openal-soft-android/Alc/hrtf.c +++ b/jni/openal-soft-1.16.0/Alc/hrtf.c @@ -28,11 +28,7 @@ #include "alMain.h" #include "alSource.h" #include "alu.h" - - -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif +#include "hrtf.h" /* Current data set limits defined by the makehrtf utility. */ @@ -62,39 +58,33 @@ struct Hrtf { static const ALchar magicMarker00[8] = "MinPHR00"; static const ALchar magicMarker01[8] = "MinPHR01"; -/* Define the default HRTF: - * ALubyte defaultAzCount [DefaultHrtf.evCount] - * ALushort defaultEvOffset [DefaultHrtf.evCount] - * ALshort defaultCoeffs [DefaultHrtf.irCount * defaultHrtf.irSize] - * ALubyte defaultDelays [DefaultHrtf.irCount] - * - * struct Hrtf DefaultHrtf - */ -#include "hrtf_tables.inc" +/* First value for pass-through coefficients (remaining are 0), used for omni- + * directional sounds. */ +static const ALfloat PassthruCoeff = 32767.0f * 0.707106781187f/*sqrt(0.5)*/; static struct Hrtf *LoadedHrtfs = NULL; /* Calculate the elevation indices given the polar elevation in radians. - * This will return two indices between 0 and (Hrtf->evCount - 1) and an + * This will return two indices between 0 and (evcount - 1) and an * interpolation factor between 0.0 and 1.0. */ -static void CalcEvIndices(const struct Hrtf *Hrtf, ALfloat ev, ALuint *evidx, ALfloat *evmu) +static void CalcEvIndices(ALuint evcount, ALfloat ev, ALuint *evidx, ALfloat *evmu) { - ev = (F_PI_2 + ev) * (Hrtf->evCount-1) / F_PI; + ev = (F_PI_2 + ev) * (evcount-1) / F_PI; evidx[0] = fastf2u(ev); - evidx[1] = minu(evidx[0] + 1, Hrtf->evCount-1); + evidx[1] = minu(evidx[0] + 1, evcount-1); *evmu = ev - evidx[0]; } /* Calculate the azimuth indices given the polar azimuth in radians. This - * will return two indices between 0 and (Hrtf->azCount[ei] - 1) and an - * interpolation factor between 0.0 and 1.0. + * will return two indices between 0 and (azcount - 1) and an interpolation + * factor between 0.0 and 1.0. */ -static void CalcAzIndices(const struct Hrtf *Hrtf, ALuint evidx, ALfloat az, ALuint *azidx, ALfloat *azmu) +static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *azmu) { - az = (F_2PI + az) * Hrtf->azCount[evidx] / (F_2PI); - azidx[0] = fastf2u(az) % Hrtf->azCount[evidx]; - azidx[1] = (azidx[0] + 1) % Hrtf->azCount[evidx]; + az = (F_2PI + az) * azcount / (F_2PI); + azidx[0] = fastf2u(az) % azcount; + azidx[1] = (azidx[0] + 1) % azcount; *azmu = az - floorf(az); } @@ -112,18 +102,17 @@ ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], oldGain = maxf(oldGain, 0.0001f); gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f)); - // Calculate the normalized listener to source angle change when there is - // enough gain to notice it. + // Calculate the angle change only when there is enough gain to notice it. angleChange = 0.0f; if(gainChange > 0.0001f || newGain > 0.0001f) { // No angle change when the directions are equal or degenerate (when // both have zero length). - if(newdir[0]-olddir[0] || newdir[1]-olddir[1] || newdir[2]-olddir[2]) - angleChange = acosf(olddir[0]*newdir[0] + - olddir[1]*newdir[1] + - olddir[2]*newdir[2]) / F_PI; - + if(newdir[0] != olddir[0] || newdir[1] != olddir[1] || newdir[2] != olddir[2]) + { + ALfloat dotp = olddir[0]*newdir[0] + olddir[1]*newdir[1] + olddir[2]*newdir[2]; + angleChange = acosf(clampf(dotp, -1.0f, 1.0f)) / F_PI; + } } // Use the largest of the two changes for the delta factor, and apply a @@ -137,37 +126,30 @@ ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], * increase the apparent resolution of the HRIR data set. The coefficients * are also normalized and attenuated by the specified gain. */ -void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays) +void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays) { - ALuint evidx[2], azidx[2]; - ALuint lidx[4], ridx[4]; + ALuint evidx[2], lidx[4], ridx[4]; ALfloat mu[3], blend[4]; ALuint i; - // Claculate elevation indices and interpolation factor. - CalcEvIndices(Hrtf, elevation, evidx, &mu[2]); + /* Claculate elevation indices and interpolation factor. */ + CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]); - // Calculate azimuth indices and interpolation factor for the first - // elevation. - CalcAzIndices(Hrtf, evidx[0], azimuth, azidx, &mu[0]); + for(i = 0;i < 2;i++) + { + ALuint azcount = Hrtf->azCount[evidx[i]]; + ALuint evoffset = Hrtf->evOffset[evidx[i]]; + ALuint azidx[2]; - // Calculate the first set of linear HRIR indices for left and right - // channels. - lidx[0] = Hrtf->evOffset[evidx[0]] + azidx[0]; - lidx[1] = Hrtf->evOffset[evidx[0]] + azidx[1]; - ridx[0] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[0]) % Hrtf->azCount[evidx[0]]); - ridx[1] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[1]) % Hrtf->azCount[evidx[0]]); + /* Calculate azimuth indices and interpolation factor for this elevation. */ + CalcAzIndices(azcount, azimuth, azidx, &mu[i]); - // Calculate azimuth indices and interpolation factor for the second - // elevation. - CalcAzIndices(Hrtf, evidx[1], azimuth, azidx, &mu[1]); - - // Calculate the second set of linear HRIR indices for left and right - // channels. - lidx[2] = Hrtf->evOffset[evidx[1]] + azidx[0]; - lidx[3] = Hrtf->evOffset[evidx[1]] + azidx[1]; - ridx[2] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[0]) % Hrtf->azCount[evidx[1]]); - ridx[3] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[1]) % Hrtf->azCount[evidx[1]]); + /* Calculate a set of linear HRIR indices for left and right channels. */ + lidx[i*2 + 0] = evoffset + azidx[0]; + lidx[i*2 + 1] = evoffset + azidx[1]; + ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount); + ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount); + } /* Calculate 4 blending weights for 2D bilinear interpolation. */ blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]); @@ -176,12 +158,12 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi blend[3] = ( mu[1]) * ( mu[2]); /* Calculate the HRIR delays using linear interpolation. */ - delays[0] = fastf2u(Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] + - Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3] + - 0.5f) << HRTFDELAY_BITS; - delays[1] = fastf2u(Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] + - Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3] + - 0.5f) << HRTFDELAY_BITS; + delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] + + Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) * + dirfact + 0.5f) << HRTFDELAY_BITS; + delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] + + Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) * + dirfact + 0.5f) << HRTFDELAY_BITS; /* Calculate the sample offsets for the HRIR indices. */ lidx[0] *= Hrtf->irSize; @@ -199,17 +181,26 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi */ if(gain > 0.0001f) { + ALfloat c; + gain *= 1.0f/32767.0f; - for(i = 0;i < Hrtf->irSize;i++) + + i = 0; + c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] + + Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]); + coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain; + c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] + + Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]); + coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain; + + for(i = 1;i < Hrtf->irSize;i++) { - coeffs[i][0] = (Hrtf->coeffs[lidx[0]+i]*blend[0] + - Hrtf->coeffs[lidx[1]+i]*blend[1] + - Hrtf->coeffs[lidx[2]+i]*blend[2] + - Hrtf->coeffs[lidx[3]+i]*blend[3]) * gain; - coeffs[i][1] = (Hrtf->coeffs[ridx[0]+i]*blend[0] + - Hrtf->coeffs[ridx[1]+i]*blend[1] + - Hrtf->coeffs[ridx[2]+i]*blend[2] + - Hrtf->coeffs[ridx[3]+i]*blend[3]) * gain; + c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] + + Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]); + coeffs[i][0] = lerp(0.0f, c, dirfact) * gain; + c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] + + Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]); + coeffs[i][1] = lerp(0.0f, c, dirfact) * gain; } } else @@ -229,39 +220,32 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi * specified gain. Stepping resolution and count is determined using the * given delta factor between 0.0 and 1.0. */ -ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep) +ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep) { - ALuint evidx[2], azidx[2]; - ALuint lidx[4], ridx[4]; + ALuint evidx[2], lidx[4], ridx[4]; ALfloat mu[3], blend[4]; ALfloat left, right; ALfloat step; ALuint i; - // Claculate elevation indices and interpolation factor. - CalcEvIndices(Hrtf, elevation, evidx, &mu[2]); + /* Claculate elevation indices and interpolation factor. */ + CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]); - // Calculate azimuth indices and interpolation factor for the first - // elevation. - CalcAzIndices(Hrtf, evidx[0], azimuth, azidx, &mu[0]); + for(i = 0;i < 2;i++) + { + ALuint azcount = Hrtf->azCount[evidx[i]]; + ALuint evoffset = Hrtf->evOffset[evidx[i]]; + ALuint azidx[2]; - // Calculate the first set of linear HRIR indices for left and right - // channels. - lidx[0] = Hrtf->evOffset[evidx[0]] + azidx[0]; - lidx[1] = Hrtf->evOffset[evidx[0]] + azidx[1]; - ridx[0] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[0]) % Hrtf->azCount[evidx[0]]); - ridx[1] = Hrtf->evOffset[evidx[0]] + ((Hrtf->azCount[evidx[0]]-azidx[1]) % Hrtf->azCount[evidx[0]]); + /* Calculate azimuth indices and interpolation factor for this elevation. */ + CalcAzIndices(azcount, azimuth, azidx, &mu[i]); - // Calculate azimuth indices and interpolation factor for the second - // elevation. - CalcAzIndices(Hrtf, evidx[1], azimuth, azidx, &mu[1]); - - // Calculate the second set of linear HRIR indices for left and right - // channels. - lidx[2] = Hrtf->evOffset[evidx[1]] + azidx[0]; - lidx[3] = Hrtf->evOffset[evidx[1]] + azidx[1]; - ridx[2] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[0]) % Hrtf->azCount[evidx[1]]); - ridx[3] = Hrtf->evOffset[evidx[1]] + ((Hrtf->azCount[evidx[1]]-azidx[1]) % Hrtf->azCount[evidx[1]]); + /* Calculate a set of linear HRIR indices for left and right channels. */ + lidx[i*2 + 0] = evoffset + azidx[0]; + lidx[i*2 + 1] = evoffset + azidx[1]; + ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount); + ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount); + } // Calculate the stepping parameters. delta = maxf(floorf(delta*(Hrtf->sampleRate*0.015f) + 0.5f), 1.0f); @@ -280,12 +264,12 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a left = (ALfloat)(delays[0] - (delayStep[0] * counter)); right = (ALfloat)(delays[1] - (delayStep[1] * counter)); - delays[0] = fastf2u(Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] + - Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3] + - 0.5f) << HRTFDELAY_BITS; - delays[1] = fastf2u(Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] + - Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3] + - 0.5f) << HRTFDELAY_BITS; + delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] + + Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) * + dirfact + 0.5f) << HRTFDELAY_BITS; + delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] + + Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) * + dirfact + 0.5f) << HRTFDELAY_BITS; delayStep[0] = fastf2i(step * (delays[0] - left)); delayStep[1] = fastf2i(step * (delays[1] - right)); @@ -308,20 +292,35 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a */ if(gain > 0.0001f) { + ALfloat c; + gain *= 1.0f/32767.0f; - for(i = 0;i < HRIR_LENGTH;i++) + + i = 0; + left = coeffs[i][0] - (coeffStep[i][0] * counter); + right = coeffs[i][1] - (coeffStep[i][1] * counter); + + c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] + + Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]); + coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain; + c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] + + Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]); + coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain; + + coeffStep[i][0] = step * (coeffs[i][0] - left); + coeffStep[i][1] = step * (coeffs[i][1] - right); + + for(i = 1;i < Hrtf->irSize;i++) { left = coeffs[i][0] - (coeffStep[i][0] * counter); right = coeffs[i][1] - (coeffStep[i][1] * counter); - coeffs[i][0] = (Hrtf->coeffs[lidx[0]+i]*blend[0] + - Hrtf->coeffs[lidx[1]+i]*blend[1] + - Hrtf->coeffs[lidx[2]+i]*blend[2] + - Hrtf->coeffs[lidx[3]+i]*blend[3]) * gain; - coeffs[i][1] = (Hrtf->coeffs[ridx[0]+i]*blend[0] + - Hrtf->coeffs[ridx[1]+i]*blend[1] + - Hrtf->coeffs[ridx[2]+i]*blend[2] + - Hrtf->coeffs[ridx[3]+i]*blend[3]) * gain; + c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] + + Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]); + coeffs[i][0] = lerp(0.0f, c, dirfact) * gain; + c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] + + Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]); + coeffs[i][1] = lerp(0.0f, c, dirfact) * gain; coeffStep[i][0] = step * (coeffs[i][0] - left); coeffStep[i][1] = step * (coeffs[i][1] - right); @@ -329,7 +328,7 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a } else { - for(i = 0;i < HRIR_LENGTH;i++) + for(i = 0;i < Hrtf->irSize;i++) { left = coeffs[i][0] - (coeffStep[i][0] * counter); right = coeffs[i][1] - (coeffStep[i][1] * counter); @@ -664,24 +663,25 @@ static struct Hrtf *LoadHrtf01(FILE *f, ALuint deviceRate) static struct Hrtf *LoadHrtf(ALuint deviceRate) { - const char *fnamelist = NULL; + const char *fnamelist = "default-%r.mhr"; - if(!ConfigValueStr(NULL, "hrtf_tables", &fnamelist)) - return NULL; + ConfigValueStr(NULL, "hrtf_tables", &fnamelist); while(*fnamelist != '\0') { struct Hrtf *Hrtf = NULL; char fname[PATH_MAX]; + const char *next; ALchar magic[8]; ALuint i; FILE *f; + i = 0; while(isspace(*fnamelist) || *fnamelist == ',') fnamelist++; - i = 0; - while(*fnamelist != '\0' && *fnamelist != ',') + next = fnamelist; + while(*(fnamelist=next) != '\0' && *fnamelist != ',') { - const char *next = strpbrk(fnamelist, "%,"); + next = strpbrk(fnamelist, "%,"); while(fnamelist != next && *fnamelist && i < sizeof(fname)) fname[i++] = *(fnamelist++); @@ -704,7 +704,6 @@ static struct Hrtf *LoadHrtf(ALuint deviceRate) } else ERR("Invalid marker '%%%c'\n", *next); - fnamelist = next; } i = minu(i, sizeof(fname)-1); fname[i] = '\0'; @@ -716,7 +715,7 @@ static struct Hrtf *LoadHrtf(ALuint deviceRate) continue; TRACE("Loading %s...\n", fname); - f = fopen(fname, "rb"); + f = OpenDataFile(fname, "openal/hrtf"); if(f == NULL) { ERR("Could not open %s\n", fname); @@ -759,52 +758,45 @@ static struct Hrtf *LoadHrtf(ALuint deviceRate) return NULL; } -const struct Hrtf *GetHrtf(ALCdevice *device) +const struct Hrtf *GetHrtf(enum DevFmtChannels chans, ALCuint srate) { - if(device->FmtChans == DevFmtStereo) + if(chans == DevFmtStereo) { struct Hrtf *Hrtf = LoadedHrtfs; while(Hrtf != NULL) { - if(device->Frequency == Hrtf->sampleRate) + if(srate == Hrtf->sampleRate) return Hrtf; Hrtf = Hrtf->next; } - Hrtf = LoadHrtf(device->Frequency); + Hrtf = LoadHrtf(srate); if(Hrtf != NULL) return Hrtf; - - if(device->Frequency == DefaultHrtf.sampleRate) - return &DefaultHrtf; } - ERR("Incompatible format: %s %uhz\n", - DevFmtChannelsString(device->FmtChans), device->Frequency); + ERR("Incompatible format: %s %uhz\n", DevFmtChannelsString(chans), srate); return NULL; } -void FindHrtfFormat(const ALCdevice *device, enum DevFmtChannels *chans, ALCuint *srate) +ALCboolean FindHrtfFormat(enum DevFmtChannels *chans, ALCuint *srate) { - const struct Hrtf *hrtf = &DefaultHrtf; - - if(device->Frequency != DefaultHrtf.sampleRate) + const struct Hrtf *hrtf = LoadedHrtfs; + while(hrtf != NULL) { - hrtf = LoadedHrtfs; - while(hrtf != NULL) - { - if(device->Frequency == hrtf->sampleRate) - break; - hrtf = hrtf->next; - } + if(*srate == hrtf->sampleRate) + break; + hrtf = hrtf->next; + } - if(hrtf == NULL) - hrtf = LoadHrtf(device->Frequency); - if(hrtf == NULL) - hrtf = &DefaultHrtf; + if(hrtf == NULL) + { + hrtf = LoadHrtf(*srate); + if(hrtf == NULL) return ALC_FALSE; } *chans = DevFmtStereo; *srate = hrtf->sampleRate; + return ALC_TRUE; } void FreeHrtfs(void) diff --git a/jni/openal-soft-1.16.0/Alc/hrtf.h b/jni/openal-soft-1.16.0/Alc/hrtf.h new file mode 100644 index 00000000..938bf552 --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/hrtf.h @@ -0,0 +1,28 @@ +#ifndef ALC_HRTF_H +#define ALC_HRTF_H + +#include "AL/al.h" +#include "AL/alc.h" + +enum DevFmtChannels; + +struct Hrtf; + +#define HRIR_BITS (7) +#define HRIR_LENGTH (1<Gain = 1.0f; self->State = AL_INITIAL; - self->LastEvtTime = 0; - self->NextEvtTime = UINT64_MAX; - self->SamplesSinceLast = 0.0; - self->SamplesToNext = 0.0; - - self->SamplesPerTick = (ALdouble)device->Frequency / TICKS_PER_SECOND; + self->ClockBase = 0; + self->SamplesDone = 0; + self->SampleRate = device->Frequency; } void MidiSynth_Destruct(MidiSynth *self) @@ -195,29 +194,22 @@ void MidiSynth_stop(MidiSynth *self) { ResetEvtQueue(&self->EventQueue); - self->LastEvtTime = 0; - self->NextEvtTime = UINT64_MAX; - self->SamplesSinceLast = 0.0; - self->SamplesToNext = 0.0; + self->ClockBase = 0; + self->SamplesDone = 0; } extern inline void MidiSynth_reset(MidiSynth *self); - -ALuint64 MidiSynth_getTime(const MidiSynth *self) -{ - ALuint64 time = self->LastEvtTime + (self->SamplesSinceLast/self->SamplesPerTick); - return clampu64(time, self->LastEvtTime, self->NextEvtTime); -} - +extern inline ALuint64 MidiSynth_getTime(const MidiSynth *self); extern inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self); -void MidiSynth_setSampleRate(MidiSynth *self, ALdouble srate) +void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate) { - ALdouble sampletickrate = srate / TICKS_PER_SECOND; - - self->SamplesSinceLast = self->SamplesSinceLast * sampletickrate / self->SamplesPerTick; - self->SamplesToNext = self->SamplesToNext * sampletickrate / self->SamplesPerTick; - self->SamplesPerTick = sampletickrate; + if(self->SampleRate != srate) + { + self->ClockBase += self->SamplesDone * MIDI_CLOCK_RES / self->SampleRate; + self->SamplesDone = 0; + self->SampleRate = srate; + } } extern inline void MidiSynth_update(MidiSynth *self, ALCdevice *device); @@ -225,25 +217,11 @@ extern inline void MidiSynth_update(MidiSynth *self, ALCdevice *device); ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2) { MidiEvent entry; - ALenum err; - entry.time = time; entry.event = event; entry.param.val[0] = param1; entry.param.val[1] = param2; - - err = InsertEvtQueue(&self->EventQueue, &entry); - if(err != AL_NO_ERROR) return err; - - if(entry.time < self->NextEvtTime) - { - self->NextEvtTime = entry.time; - - self->SamplesToNext = (self->NextEvtTime - self->LastEvtTime) * self->SamplesPerTick; - self->SamplesToNext -= self->SamplesSinceLast; - } - - return AL_NO_ERROR; + return InsertEvtQueue(&self->EventQueue, &entry); } ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte *data, ALsizei size) @@ -261,18 +239,6 @@ ALenum MidiSynth_insertSysExEvent(MidiSynth *self, ALuint64 time, const ALbyte * err = InsertEvtQueue(&self->EventQueue, &entry); if(err != AL_NO_ERROR) - { free(entry.param.sysex.data); - return err; - } - - if(entry.time < self->NextEvtTime) - { - self->NextEvtTime = entry.time; - - self->SamplesToNext = (self->NextEvtTime - self->LastEvtTime) * self->SamplesPerTick; - self->SamplesToNext -= self->SamplesSinceLast; - } - - return AL_NO_ERROR; + return err; } diff --git a/jni/openal-soft-android/Alc/midi/base.h b/jni/openal-soft-1.16.0/Alc/midi/base.h similarity index 85% rename from jni/openal-soft-android/Alc/midi/base.h rename to jni/openal-soft-1.16.0/Alc/midi/base.h index f900c941..157f2399 100644 --- a/jni/openal-soft-android/Alc/midi/base.h +++ b/jni/openal-soft-1.16.0/Alc/midi/base.h @@ -17,23 +17,28 @@ typedef struct Reader { void *ptr; int error; } Reader; -#define READ(x_, buf_, len_) ((x_)->cb((buf_), (len_), (x_)->ptr)) -#define READERR(x_) ((x_)->error) +inline size_t Reader_read(Reader *self, void *buf, size_t len) +{ + size_t got = (!self->error) ? self->cb(buf, len, self->ptr) : 0; + if(got < len) self->error = 1; + return got; +} +#define READERR(x_) ((x_)->error) ALboolean loadSf2(Reader *stream, struct ALsoundfont *sfont, ALCcontext *context); +#define MIDI_CLOCK_RES U64(1000000000) + + struct MidiSynthVtable; typedef struct MidiSynth { EvtQueue EventQueue; - ALuint64 LastEvtTime; - ALuint64 NextEvtTime; - ALdouble SamplesSinceLast; - ALdouble SamplesToNext; - - ALdouble SamplesPerTick; + ALuint64 ClockBase; + ALuint SamplesDone; + ALuint SampleRate; /* NOTE: This rwlock is for the state and soundfont. The EventQueue and * related must instead use the device lock as they're used in the mixer @@ -59,14 +64,15 @@ inline void MidiSynth_setState(MidiSynth *self, ALenum state) { ExchangeInt(&sel inline ALenum MidiSynth_getState(const MidiSynth *self) { return self->State; } void MidiSynth_stop(MidiSynth *self); inline void MidiSynth_reset(MidiSynth *self) { MidiSynth_stop(self); } -ALuint64 MidiSynth_getTime(const MidiSynth *self); +inline ALuint64 MidiSynth_getTime(const MidiSynth *self) +{ return self->ClockBase + (self->SamplesDone*MIDI_CLOCK_RES/self->SampleRate); } inline ALuint64 MidiSynth_getNextEvtTime(const MidiSynth *self) { if(self->EventQueue.pos == self->EventQueue.size) return UINT64_MAX; return self->EventQueue.events[self->EventQueue.pos].time; } -void MidiSynth_setSampleRate(MidiSynth *self, ALdouble srate); +void MidiSynth_setSampleRate(MidiSynth *self, ALuint srate); inline void MidiSynth_update(MidiSynth *self, ALCdevice *device) { MidiSynth_setSampleRate(self, device->Frequency); } ALenum MidiSynth_insertEvent(MidiSynth *self, ALuint64 time, ALuint event, ALsizei param1, ALsizei param2); @@ -79,7 +85,6 @@ struct MidiSynthVtable { ALenum (*const selectSoundfonts)(MidiSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids); void (*const setGain)(MidiSynth *self, ALfloat gain); - void (*const setState)(MidiSynth *self, ALenum state); void (*const stop)(MidiSynth *self); void (*const reset)(MidiSynth *self); @@ -87,26 +92,25 @@ struct MidiSynthVtable { void (*const update)(MidiSynth *self, ALCdevice *device); void (*const process)(MidiSynth *self, ALuint samples, ALfloat (*restrict DryBuffer)[BUFFERSIZE]); - void (*const Delete)(MidiSynth *self); + void (*const Delete)(void *ptr); }; #define DEFINE_MIDISYNTH_VTABLE(T) \ DECLARE_THUNK(T, MidiSynth, void, Destruct) \ DECLARE_THUNK3(T, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*) \ DECLARE_THUNK1(T, MidiSynth, void, setGain, ALfloat) \ -DECLARE_THUNK1(T, MidiSynth, void, setState, ALenum) \ DECLARE_THUNK(T, MidiSynth, void, stop) \ DECLARE_THUNK(T, MidiSynth, void, reset) \ DECLARE_THUNK1(T, MidiSynth, void, update, ALCdevice*) \ DECLARE_THUNK2(T, MidiSynth, void, process, ALuint, ALfloatBUFFERSIZE*restrict) \ -DECLARE_THUNK(T, MidiSynth, void, Delete) \ +static void T##_MidiSynth_Delete(void *ptr) \ +{ T##_Delete(STATIC_UPCAST(T, MidiSynth, (MidiSynth*)ptr)); } \ \ static const struct MidiSynthVtable T##_MidiSynth_vtable = { \ T##_MidiSynth_Destruct, \ \ T##_MidiSynth_selectSoundfonts, \ T##_MidiSynth_setGain, \ - T##_MidiSynth_setState, \ T##_MidiSynth_stop, \ T##_MidiSynth_reset, \ T##_MidiSynth_update, \ @@ -116,6 +120,7 @@ static const struct MidiSynthVtable T##_MidiSynth_vtable = { \ } +MidiSynth *SSynth_create(ALCdevice *device); MidiSynth *FSynth_create(ALCdevice *device); MidiSynth *DSynth_create(ALCdevice *device); diff --git a/jni/openal-soft-android/Alc/midi/dummy.c b/jni/openal-soft-1.16.0/Alc/midi/dummy.c similarity index 64% rename from jni/openal-soft-android/Alc/midi/dummy.c rename to jni/openal-soft-1.16.0/Alc/midi/dummy.c index 71c03efb..d50b8fef 100644 --- a/jni/openal-soft-android/Alc/midi/dummy.c +++ b/jni/openal-soft-1.16.0/Alc/midi/dummy.c @@ -22,12 +22,11 @@ static void DSynth_Construct(DSynth *self, ALCdevice *device); static DECLARE_FORWARD(DSynth, MidiSynth, void, Destruct) static DECLARE_FORWARD3(DSynth, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*) static DECLARE_FORWARD1(DSynth, MidiSynth, void, setGain, ALfloat) -static DECLARE_FORWARD1(DSynth, MidiSynth, void, setState, ALenum) static DECLARE_FORWARD(DSynth, MidiSynth, void, stop) static DECLARE_FORWARD(DSynth, MidiSynth, void, reset) static DECLARE_FORWARD1(DSynth, MidiSynth, void, update, ALCdevice*) static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]); -static void DSynth_Delete(DSynth *self); +DECLARE_DEFAULT_ALLOCATORS(DSynth) DEFINE_MIDISYNTH_VTABLE(DSynth); @@ -49,47 +48,29 @@ static void DSynth_processQueue(DSynth *self, ALuint64 time) static void DSynth_process(DSynth *self, ALuint SamplesToDo, ALfloatBUFFERSIZE*restrict UNUSED(DryBuffer)) { MidiSynth *synth = STATIC_CAST(MidiSynth, self); + ALuint64 curtime; if(synth->State != AL_PLAYING) return; - synth->SamplesSinceLast += SamplesToDo; - synth->SamplesToNext -= SamplesToDo; - while(synth->SamplesToNext < 1.0f) - { - ALuint64 time = synth->NextEvtTime; - if(time == UINT64_MAX) - { - synth->SamplesToNext = 0.0; - break; - } + synth->SamplesDone += SamplesToDo; + synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES; + synth->SamplesDone %= synth->SampleRate; - synth->SamplesSinceLast -= (time - synth->LastEvtTime) * synth->SamplesPerTick; - synth->SamplesSinceLast = maxd(synth->SamplesSinceLast, 0.0); - synth->LastEvtTime = time; - DSynth_processQueue(self, time); - - synth->NextEvtTime = MidiSynth_getNextEvtTime(synth); - if(synth->NextEvtTime != UINT64_MAX) - synth->SamplesToNext += (synth->NextEvtTime - synth->LastEvtTime) * synth->SamplesPerTick; - } -} - - -static void DSynth_Delete(DSynth *self) -{ - free(self); + curtime = MidiSynth_getTime(synth); + DSynth_processQueue(self, maxi64(curtime-1, 0)); } MidiSynth *DSynth_create(ALCdevice *device) { - DSynth *synth = calloc(1, sizeof(*synth)); + DSynth *synth = DSynth_New(sizeof(*synth)); if(!synth) { ERR("Failed to allocate DSynth\n"); return NULL; } + memset(synth, 0, sizeof(*synth)); DSynth_Construct(synth, device); return STATIC_CAST(MidiSynth, synth); } diff --git a/jni/openal-soft-android/Alc/midi/fluidsynth.c b/jni/openal-soft-1.16.0/Alc/midi/fluidsynth.c similarity index 76% rename from jni/openal-soft-android/Alc/midi/fluidsynth.c rename to jni/openal-soft-1.16.0/Alc/midi/fluidsynth.c index 9d58f87b..82159127 100644 --- a/jni/openal-soft-android/Alc/midi/fluidsynth.c +++ b/jni/openal-soft-1.16.0/Alc/midi/fluidsynth.c @@ -10,15 +10,115 @@ #include "alMain.h" #include "alError.h" #include "alMidi.h" +#include "alu.h" +#include "compat.h" #include "evtqueue.h" #include "rwlock.h" -#include "alu.h" #ifdef HAVE_FLUIDSYNTH #include +#ifdef HAVE_DYNLOAD +#define FLUID_FUNCS(MAGIC) \ + MAGIC(new_fluid_synth); \ + MAGIC(delete_fluid_synth); \ + MAGIC(new_fluid_settings); \ + MAGIC(delete_fluid_settings); \ + MAGIC(fluid_settings_setint); \ + MAGIC(fluid_settings_setnum); \ + MAGIC(fluid_synth_noteon); \ + MAGIC(fluid_synth_noteoff); \ + MAGIC(fluid_synth_program_change); \ + MAGIC(fluid_synth_pitch_bend); \ + MAGIC(fluid_synth_channel_pressure); \ + MAGIC(fluid_synth_cc); \ + MAGIC(fluid_synth_sysex); \ + MAGIC(fluid_synth_bank_select); \ + MAGIC(fluid_synth_set_channel_type); \ + MAGIC(fluid_synth_all_sounds_off); \ + MAGIC(fluid_synth_system_reset); \ + MAGIC(fluid_synth_set_gain); \ + MAGIC(fluid_synth_set_sample_rate); \ + MAGIC(fluid_synth_write_float); \ + MAGIC(fluid_synth_add_sfloader); \ + MAGIC(fluid_synth_sfload); \ + MAGIC(fluid_synth_sfunload); \ + MAGIC(fluid_synth_alloc_voice); \ + MAGIC(fluid_synth_start_voice); \ + MAGIC(fluid_voice_gen_set); \ + MAGIC(fluid_voice_add_mod); \ + MAGIC(fluid_mod_set_source1); \ + MAGIC(fluid_mod_set_source2); \ + MAGIC(fluid_mod_set_amount); \ + MAGIC(fluid_mod_set_dest); + +void *fsynth_handle = NULL; +#define DECL_FUNC(x) __typeof(x) *p##x +FLUID_FUNCS(DECL_FUNC) +#undef DECL_FUNC + +#define new_fluid_synth pnew_fluid_synth +#define delete_fluid_synth pdelete_fluid_synth +#define new_fluid_settings pnew_fluid_settings +#define delete_fluid_settings pdelete_fluid_settings +#define fluid_settings_setint pfluid_settings_setint +#define fluid_settings_setnum pfluid_settings_setnum +#define fluid_synth_noteon pfluid_synth_noteon +#define fluid_synth_noteoff pfluid_synth_noteoff +#define fluid_synth_program_change pfluid_synth_program_change +#define fluid_synth_pitch_bend pfluid_synth_pitch_bend +#define fluid_synth_channel_pressure pfluid_synth_channel_pressure +#define fluid_synth_cc pfluid_synth_cc +#define fluid_synth_sysex pfluid_synth_sysex +#define fluid_synth_bank_select pfluid_synth_bank_select +#define fluid_synth_set_channel_type pfluid_synth_set_channel_type +#define fluid_synth_all_sounds_off pfluid_synth_all_sounds_off +#define fluid_synth_system_reset pfluid_synth_system_reset +#define fluid_synth_set_gain pfluid_synth_set_gain +#define fluid_synth_set_sample_rate pfluid_synth_set_sample_rate +#define fluid_synth_write_float pfluid_synth_write_float +#define fluid_synth_add_sfloader pfluid_synth_add_sfloader +#define fluid_synth_sfload pfluid_synth_sfload +#define fluid_synth_sfunload pfluid_synth_sfunload +#define fluid_synth_alloc_voice pfluid_synth_alloc_voice +#define fluid_synth_start_voice pfluid_synth_start_voice +#define fluid_voice_gen_set pfluid_voice_gen_set +#define fluid_voice_add_mod pfluid_voice_add_mod +#define fluid_mod_set_source1 pfluid_mod_set_source1 +#define fluid_mod_set_source2 pfluid_mod_set_source2 +#define fluid_mod_set_amount pfluid_mod_set_amount +#define fluid_mod_set_dest pfluid_mod_set_dest + +static ALboolean LoadFSynth(void) +{ + ALboolean ret = AL_TRUE; + if(!fsynth_handle) + { + fsynth_handle = LoadLib("libfluidsynth.so.1"); + if(!fsynth_handle) return AL_FALSE; + +#define LOAD_FUNC(x) do { \ + p##x = GetSymbol(fsynth_handle, #x); \ + if(!p##x) ret = AL_FALSE; \ +} while(0) + FLUID_FUNCS(LOAD_FUNC) +#undef LOAD_FUNC + + if(ret == AL_FALSE) + { + CloseLib(fsynth_handle); + fsynth_handle = NULL; + } + } + return ret; +} +#else +static inline ALboolean LoadFSynth(void) { return AL_TRUE; } +#endif + + /* MIDI events */ #define SYSEX_EVENT (0xF0) @@ -28,7 +128,7 @@ #define CTRL_ALLNOTESOFF (123) -static int getGenInput(ALenum input) +static int getModInput(ALenum input) { switch(input) { @@ -43,7 +143,7 @@ static int getGenInput(ALenum input) return input&0x7F; } -static int getGenFlags(ALenum input, ALenum type, ALenum form) +static int getModFlags(ALenum input, ALenum type, ALenum form) { int ret = 0; @@ -69,7 +169,7 @@ static int getGenFlags(ALenum input, ALenum type, ALenum form) return ret; } -static enum fluid_gen_type getSf2Gen(ALenum gen) +static enum fluid_gen_type getModDest(ALenum gen) { switch(gen) { @@ -144,7 +244,7 @@ typedef struct FSample { ALsizei NumMods; } FSample; -static void FSample_Construct(FSample *self, ALfontsound *sound, ALsoundfont *sfont) +static void FSample_Construct(FSample *self, ALfontsound *sound) { fluid_sample_t *sample = STATIC_CAST(fluid_sample_t, self); memset(sample->name, 0, sizeof(sample->name)); @@ -156,8 +256,8 @@ static void FSample_Construct(FSample *self, ALfontsound *sound, ALsoundfont *sf sample->origpitch = sound->PitchKey; sample->pitchadj = sound->PitchCorrection; sample->sampletype = getSampleType(sound->SampleType); - sample->valid = 1; - sample->data = sfont->Samples; + sample->valid = !!sound->Buffer; + sample->data = sound->Buffer ? sound->Buffer->data : NULL; sample->amplitude_that_reaches_noise_floor_is_valid = 0; sample->amplitude_that_reaches_noise_floor = 0.0; @@ -171,25 +271,30 @@ static void FSample_Construct(FSample *self, ALfontsound *sound, ALsoundfont *sf self->Sound = sound; self->NumMods = 0; - self->Mods = calloc(sound->ModulatorMap.size, sizeof(self->Mods[0])); + self->Mods = calloc(sound->ModulatorMap.size*4, sizeof(fluid_mod_t[4])); if(self->Mods) { - ALsizei i; + ALsizei i, j, k; - self->NumMods = sound->ModulatorMap.size; - for(i = 0;i < self->NumMods;i++) + for(i = j = 0;i < sound->ModulatorMap.size;i++) { ALsfmodulator *mod = sound->ModulatorMap.array[i].value; - fluid_mod_set_source1(&self->Mods[i], getGenInput(mod->Source[0].Input), - getGenFlags(mod->Source[0].Input, mod->Source[0].Type, - mod->Source[0].Form)); - fluid_mod_set_source2(&self->Mods[i], getGenInput(mod->Source[1].Input), - getGenFlags(mod->Source[1].Input, mod->Source[1].Type, - mod->Source[1].Form)); - fluid_mod_set_amount(&self->Mods[i], mod->Amount); - fluid_mod_set_dest(&self->Mods[i], getSf2Gen(mod->Dest)); - self->Mods[i].next = NULL; + for(k = 0;k < 4;k++,mod++) + { + if(mod->Dest == AL_NONE) + continue; + fluid_mod_set_source1(&self->Mods[j], getModInput(mod->Source[0].Input), + getModFlags(mod->Source[0].Input, mod->Source[0].Type, + mod->Source[0].Form)); + fluid_mod_set_source2(&self->Mods[j], getModInput(mod->Source[1].Input), + getModFlags(mod->Source[1].Input, mod->Source[1].Type, + mod->Source[1].Form)); + fluid_mod_set_amount(&self->Mods[j], mod->Amount); + fluid_mod_set_dest(&self->Mods[j], getModDest(mod->Dest)); + self->Mods[j++].next = NULL; + } } + self->NumMods = j; } } @@ -218,7 +323,7 @@ static int FPreset_getPreset(fluid_preset_t *preset); static int FPreset_getBank(fluid_preset_t *preset); static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int channel, int key, int velocity); -static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t *parent, ALsoundfont *sfont) +static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t *parent) { STATIC_CAST(fluid_preset_t, self)->data = self; STATIC_CAST(fluid_preset_t, self)->sfont = parent; @@ -240,7 +345,7 @@ static void FPreset_Construct(FPreset *self, ALsfpreset *preset, fluid_sfont_t * ALsizei i; self->NumSamples = preset->NumSounds; for(i = 0;i < self->NumSamples;i++) - FSample_Construct(&self->Samples[i], preset->Sounds[i], sfont); + FSample_Construct(&self->Samples[i], preset->Sounds[i]); } } @@ -258,7 +363,6 @@ static void FPreset_Destruct(FPreset *self) static ALboolean FPreset_canDelete(FPreset *self) { ALsizei i; - for(i = 0;i < self->NumSamples;i++) { if(fluid_sample_refcount(STATIC_CAST(fluid_sample_t, &self->Samples[i])) != 0) @@ -298,8 +402,7 @@ static int FPreset_noteOn(fluid_preset_t *preset, fluid_synth_t *synth, int chan continue; voice = fluid_synth_alloc_voice(synth, STATIC_CAST(fluid_sample_t, sample), channel, key, vel); - if(voice == NULL) - return FLUID_FAILED; + if(voice == NULL) return FLUID_FAILED; fluid_voice_gen_set(voice, GEN_MODLFOTOPITCH, sound->ModLfoToPitch); fluid_voice_gen_set(voice, GEN_VIBLFOTOPITCH, sound->VibratoLfoToPitch); @@ -384,7 +487,7 @@ static void FSfont_Construct(FSfont *self, ALsoundfont *sfont) ALsizei i; self->NumPresets = sfont->NumPresets; for(i = 0;i < self->NumPresets;i++) - FPreset_Construct(&self->Presets[i], sfont->Presets[i], STATIC_CAST(fluid_sfont_t, self), sfont); + FPreset_Construct(&self->Presets[i], sfont->Presets[i], STATIC_CAST(fluid_sfont_t, self)); } } @@ -470,13 +573,12 @@ static void FSynth_Destruct(FSynth *self); static ALboolean FSynth_init(FSynth *self, ALCdevice *device); static ALenum FSynth_selectSoundfonts(FSynth *self, ALCcontext *context, ALsizei count, const ALuint *ids); static void FSynth_setGain(FSynth *self, ALfloat gain); -static void FSynth_setState(FSynth *self, ALenum state); static void FSynth_stop(FSynth *self); static void FSynth_reset(FSynth *self); static void FSynth_update(FSynth *self, ALCdevice *device); static void FSynth_processQueue(FSynth *self, ALuint64 time); static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]); -static void FSynth_Delete(FSynth *self); +DECLARE_DEFAULT_ALLOCATORS(FSynth) DEFINE_MIDISYNTH_VTABLE(FSynth); static fluid_sfont_t *FSynth_loadSfont(fluid_sfloader_t *loader, const char *filename); @@ -632,32 +734,15 @@ static void FSynth_setGain(FSynth *self, ALfloat gain) } -static void FSynth_setState(FSynth *self, ALenum state) -{ - MidiSynth_setState(STATIC_CAST(MidiSynth, self), state); -} - static void FSynth_stop(FSynth *self) { MidiSynth *synth = STATIC_CAST(MidiSynth, self); + ALuint64 curtime; ALsizei chan; /* Make sure all pending events are processed. */ - while(!(synth->SamplesToNext >= 1.0)) - { - ALuint64 time = synth->NextEvtTime; - if(time == UINT64_MAX) - break; - - synth->SamplesSinceLast -= (time - synth->LastEvtTime) * synth->SamplesPerTick; - synth->SamplesSinceLast = maxd(synth->SamplesSinceLast, 0.0); - synth->LastEvtTime = time; - FSynth_processQueue(self, time); - - synth->NextEvtTime = MidiSynth_getNextEvtTime(synth); - if(synth->NextEvtTime != UINT64_MAX) - synth->SamplesToNext += (synth->NextEvtTime - synth->LastEvtTime) * synth->SamplesPerTick; - } + curtime = MidiSynth_getTime(synth); + FSynth_processQueue(self, curtime); /* All notes off */ for(chan = 0;chan < 16;chan++) @@ -759,6 +844,7 @@ static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict { MidiSynth *synth = STATIC_CAST(MidiSynth, self); ALenum state = synth->State; + ALuint64 curtime; ALuint total = 0; if(state == AL_INITIAL) @@ -770,58 +856,59 @@ static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict return; } + curtime = MidiSynth_getTime(synth); while(total < SamplesToDo) { - if(synth->SamplesToNext >= 1.0) - { - ALuint todo = minu(SamplesToDo - total, fastf2u(synth->SamplesToNext)); + ALuint64 time, diff; + ALint tonext; - fluid_synth_write_float(self->Synth, todo, - &DryBuffer[FrontLeft][total], 0, 1, - &DryBuffer[FrontRight][total], 0, 1); - total += todo; - synth->SamplesSinceLast += todo; - synth->SamplesToNext -= todo; + time = MidiSynth_getNextEvtTime(synth); + diff = maxu64(time, curtime) - curtime; + if(diff >= MIDI_CLOCK_RES || time == UINT64_MAX) + { + /* If there's no pending event, or if it's more than 1 second + * away, do as many samples as we can. */ + tonext = INT_MAX; } else { - ALuint64 time = synth->NextEvtTime; - if(time == UINT64_MAX) - { - synth->SamplesSinceLast += SamplesToDo-total; - fluid_synth_write_float(self->Synth, SamplesToDo-total, - &DryBuffer[FrontLeft][total], 0, 1, - &DryBuffer[FrontRight][total], 0, 1); - break; - } - - synth->SamplesSinceLast -= (time - synth->LastEvtTime) * synth->SamplesPerTick; - synth->SamplesSinceLast = maxd(synth->SamplesSinceLast, 0.0); - synth->LastEvtTime = time; - FSynth_processQueue(self, time); - - synth->NextEvtTime = MidiSynth_getNextEvtTime(synth); - if(synth->NextEvtTime != UINT64_MAX) - synth->SamplesToNext += (synth->NextEvtTime - synth->LastEvtTime) * synth->SamplesPerTick; + /* Figure out how many samples until the next event. */ + tonext = (ALint)((diff*synth->SampleRate + (MIDI_CLOCK_RES-1)) / MIDI_CLOCK_RES); + tonext -= total; } + + if(tonext > 0) + { + ALuint todo = minu(tonext, SamplesToDo-total); + fluid_synth_write_float(self->Synth, todo, DryBuffer[FrontLeft], total, 1, + DryBuffer[FrontRight], total, 1); + total += todo; + tonext -= todo; + } + if(total < SamplesToDo && tonext <= 0) + FSynth_processQueue(self, time); } -} - -static void FSynth_Delete(FSynth *self) -{ - free(self); + synth->SamplesDone += SamplesToDo; + synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES; + synth->SamplesDone %= synth->SampleRate; } MidiSynth *FSynth_create(ALCdevice *device) { - FSynth *synth = calloc(1, sizeof(*synth)); + FSynth *synth; + + if(!LoadFSynth()) + return NULL; + + synth = FSynth_New(sizeof(*synth)); if(!synth) { ERR("Failed to allocate FSynth\n"); return NULL; } + memset(synth, 0, sizeof(*synth)); FSynth_Construct(synth, device); if(FSynth_init(synth, device) == AL_FALSE) diff --git a/jni/openal-soft-android/Alc/midi/sf2load.c b/jni/openal-soft-1.16.0/Alc/midi/sf2load.c similarity index 73% rename from jni/openal-soft-android/Alc/midi/sf2load.c rename to jni/openal-soft-1.16.0/Alc/midi/sf2load.c index 5bba345f..233f7983 100644 --- a/jni/openal-soft-android/Alc/midi/sf2load.c +++ b/jni/openal-soft-1.16.0/Alc/midi/sf2load.c @@ -15,31 +15,22 @@ static ALuint read_le32(Reader *stream) { ALubyte buf[4]; - if(READ(stream, buf, 4) != 4) - { - READERR(stream) = 1; + if(Reader_read(stream, buf, 4) != 4) return 0; - } return (buf[3]<<24) | (buf[2]<<16) | (buf[1]<<8) | buf[0]; } static ALushort read_le16(Reader *stream) { ALubyte buf[2]; - if(READ(stream, buf, 2) != 2) - { - READERR(stream) = 1; + if(Reader_read(stream, buf, 2) != 2) return 0; - } return (buf[1]<<8) | buf[0]; } static ALubyte read_8(Reader *stream) { ALubyte buf[1]; - if(READ(stream, buf, 1) != 1) - { - READERR(stream) = 1; + if(Reader_read(stream, buf, 1) != 1) return 0; - } return buf[0]; } static void skip(Reader *stream, ALuint amt) @@ -47,12 +38,7 @@ static void skip(Reader *stream, ALuint amt) while(amt > 0 && !READERR(stream)) { char buf[4096]; - size_t got; - - got = READ(stream, buf, minu(sizeof(buf), amt)); - if(got == 0) READERR(stream) = 1; - - amt -= got; + amt -= Reader_read(stream, buf, minu(sizeof(buf), amt)); } } @@ -166,8 +152,7 @@ typedef struct PresetHeader { } PresetHeader; static void PresetHeader_read(PresetHeader *self, Reader *stream) { - if(READ(stream, self->mName, sizeof(self->mName)) != sizeof(self->mName)) - READERR(stream) = 1; + Reader_read(stream, self->mName, sizeof(self->mName)); self->mPreset = read_le16(stream); self->mBank = read_le16(stream); self->mZoneIdx = read_le16(stream); @@ -182,13 +167,12 @@ typedef struct InstrumentHeader { } InstrumentHeader; static void InstrumentHeader_read(InstrumentHeader *self, Reader *stream) { - if(READ(stream, self->mName, sizeof(self->mName)) != sizeof(self->mName)) - READERR(stream) = 1; + Reader_read(stream, self->mName, sizeof(self->mName)); self->mZoneIdx = read_le16(stream); } typedef struct SampleHeader { - ALchar mName[20]; // 20 bytes + ALchar mName[20]; ALuint mStart; ALuint mEnd; ALuint mStartloop; @@ -201,8 +185,7 @@ typedef struct SampleHeader { } SampleHeader; static void SampleHeader_read(SampleHeader *self, Reader *stream) { - if(READ(stream, self->mName, sizeof(self->mName)) != sizeof(self->mName)) - READERR(stream) = 1; + Reader_read(stream, self->mName, sizeof(self->mName)); self->mStart = read_le32(stream); self->mEnd = read_le32(stream); self->mStartloop = read_le32(stream); @@ -311,7 +294,8 @@ static void Soundfont_Destruct(Soundfont *self) } -#define FOURCC(a,b,c,d) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a)) +#define FOURCC(a,b,c,d) ((a) | ((b)<<8) | ((c)<<16) | ((d)<<24)) +#define FOURCCFMT "%c%c%c%c" #define FOURCCARGS(x) (char)((x)&0xff), (char)(((x)>>8)&0xff), (char)(((x)>>16)&0xff), (char)(((x)>>24)&0xff) typedef struct RiffHdr { ALuint mCode; @@ -325,60 +309,42 @@ static void RiffHdr_read(RiffHdr *self, Reader *stream) typedef struct GenModList { - Generator *gens; - ALsizei gens_size; - ALsizei gens_max; - - Modulator *mods; - ALsizei mods_size; - ALsizei mods_max; + VECTOR(Generator) gens; + VECTOR(Modulator) mods; } GenModList; static void GenModList_Construct(GenModList *self) { - self->gens = NULL; - self->gens_size = 0; - self->gens_max = 0; - - self->mods = NULL; - self->mods_size = 0; - self->mods_max = 0; + VECTOR_INIT(self->gens); + VECTOR_INIT(self->mods); } static void GenModList_Destruct(GenModList *self) { - free(self->gens); - self->gens = NULL; - self->gens_size = 0; - self->gens_max = 0; - - free(self->mods); - self->mods = NULL; - self->mods_size = 0; - self->mods_max = 0; + VECTOR_DEINIT(self->mods); + VECTOR_DEINIT(self->gens); } static GenModList GenModList_clone(const GenModList *self) { GenModList ret; - ret.gens = malloc(self->gens_max * sizeof(ret.gens[0])); - memcpy(ret.gens, self->gens, self->gens_size * sizeof(ret.gens[0])); - ret.gens_size = self->gens_size; - ret.gens_max = self->gens_max; + GenModList_Construct(&ret); - ret.mods = malloc(self->mods_max * sizeof(ret.mods[0])); - memcpy(ret.mods, self->mods, self->mods_size * sizeof(ret.mods[0])); - ret.mods_size = self->mods_size; - ret.mods_max = self->mods_max; + VECTOR_INSERT(ret.gens, VECTOR_ITER_END(ret.gens), + VECTOR_ITER_BEGIN(self->gens), VECTOR_ITER_END(self->gens) + ); + VECTOR_INSERT(ret.mods, VECTOR_ITER_END(ret.mods), + VECTOR_ITER_BEGIN(self->mods), VECTOR_ITER_END(self->mods) + ); return ret; } static void GenModList_insertGen(GenModList *self, const Generator *gen, ALboolean ispreset) { - Generator *i = self->gens; - Generator *end = i + self->gens_size; + Generator *i = VECTOR_ITER_BEGIN(self->gens); + Generator *end = VECTOR_ITER_END(self->gens); for(;i != end;i++) { if(i->mGenerator == gen->mGenerator) @@ -396,32 +362,16 @@ static void GenModList_insertGen(GenModList *self, const Generator *gen, ALboole gen->mGenerator == 58)) return; - if(self->gens_size == self->gens_max) + if(VECTOR_PUSH_BACK(self->gens, *gen) == AL_FALSE) { - void *temp = NULL; - ALsizei newsize; - - newsize = (self->gens_max ? self->gens_max<<1 : 1); - if(newsize > self->gens_max) - temp = realloc(self->gens, newsize * sizeof(self->gens[0])); - if(!temp) - { - ERR("Failed to increase generator storage to %d elements (from %d)\n", - newsize, self->gens_max); - return; - } - - self->gens = temp; - self->gens_max = newsize; + ERR("Failed to insert generator (from %d elements)\n", VECTOR_SIZE(self->gens)); + return; } - - self->gens[self->gens_size] = *gen; - self->gens_size++; } static void GenModList_accumGen(GenModList *self, const Generator *gen) { - Generator *i = self->gens; - Generator *end = i + self->gens_size; + Generator *i = VECTOR_ITER_BEGIN(self->gens); + Generator *end = VECTOR_ITER_END(self->gens); for(;i != end;i++) { if(i->mGenerator == gen->mGenerator) @@ -441,35 +391,19 @@ static void GenModList_accumGen(GenModList *self, const Generator *gen) } } - if(self->gens_size == self->gens_max) + if(VECTOR_PUSH_BACK(self->gens, *gen) == AL_FALSE) { - void *temp = NULL; - ALsizei newsize; - - newsize = (self->gens_max ? self->gens_max<<1 : 1); - if(newsize > self->gens_max) - temp = realloc(self->gens, newsize * sizeof(self->gens[0])); - if(!temp) - { - ERR("Failed to increase generator storage to %d elements (from %d)\n", - newsize, self->gens_max); - return; - } - - self->gens = temp; - self->gens_max = newsize; + ERR("Failed to insert generator (from %d elements)\n", VECTOR_SIZE(self->gens)); + return; } - - self->gens[self->gens_size] = *gen; if(gen->mGenerator < 60) - self->gens[self->gens_size].mAmount += DefaultGenValue[gen->mGenerator]; - self->gens_size++; + VECTOR_BACK(self->gens).mAmount += DefaultGenValue[gen->mGenerator]; } static void GenModList_insertMod(GenModList *self, const Modulator *mod) { - Modulator *i = self->mods; - Modulator *end = i + self->mods_size; + Modulator *i = VECTOR_ITER_BEGIN(self->mods); + Modulator *end = VECTOR_ITER_END(self->mods); for(;i != end;i++) { if(i->mDstOp == mod->mDstOp && i->mSrcOp == mod->mSrcOp && @@ -480,32 +414,16 @@ static void GenModList_insertMod(GenModList *self, const Modulator *mod) } } - if(self->mods_size == self->mods_max) + if(VECTOR_PUSH_BACK(self->mods, *mod) == AL_FALSE) { - void *temp = NULL; - ALsizei newsize; - - newsize = (self->mods_max ? self->mods_max<<1 : 1); - if(newsize > self->mods_max) - temp = realloc(self->mods, newsize * sizeof(self->mods[0])); - if(!temp) - { - ERR("Failed to increase modulator storage to %d elements (from %d)\n", - newsize, self->mods_max); - return; - } - - self->mods = temp; - self->mods_max = newsize; + ERR("Failed to insert modulator (from %d elements)\n", VECTOR_SIZE(self->mods)); + return; } - - self->mods[self->mods_size] = *mod; - self->mods_size++; } static void GenModList_accumMod(GenModList *self, const Modulator *mod) { - Modulator *i = self->mods; - Modulator *end = i + self->mods_size; + Modulator *i = VECTOR_ITER_BEGIN(self->mods); + Modulator *end = VECTOR_ITER_END(self->mods); for(;i != end;i++) { if(i->mDstOp == mod->mDstOp && i->mSrcOp == mod->mSrcOp && @@ -516,47 +434,32 @@ static void GenModList_accumMod(GenModList *self, const Modulator *mod) } } - if(self->mods_size == self->mods_max) + if(VECTOR_PUSH_BACK(self->mods, *mod) == AL_FALSE) { - void *temp = NULL; - ALsizei newsize; - - newsize = (self->mods_max ? self->mods_max<<1 : 1); - if(newsize > self->mods_max) - temp = realloc(self->mods, newsize * sizeof(self->mods[0])); - if(!temp) - { - ERR("Failed to increase modulator storage to %d elements (from %d)\n", - newsize, self->mods_max); - return; - } - - self->mods = temp; - self->mods_max = newsize; + ERR("Failed to insert modulator (from %d elements)\n", VECTOR_SIZE(self->mods)); + return; } - self->mods[self->mods_size] = *mod; if(mod->mSrcOp == 0x0502 && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 960; + VECTOR_BACK(self->mods).mAmount += 960; else if(mod->mSrcOp == 0x0102 && mod->mDstOp == 8 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += -2400; + VECTOR_BACK(self->mods).mAmount += -2400; else if(mod->mSrcOp == 0x000D && mod->mDstOp == 6 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 50; + VECTOR_BACK(self->mods).mAmount += 50; else if(mod->mSrcOp == 0x0081 && mod->mDstOp == 6 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 50; + VECTOR_BACK(self->mods).mAmount += 50; else if(mod->mSrcOp == 0x0582 && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 960; + VECTOR_BACK(self->mods).mAmount += 960; else if(mod->mSrcOp == 0x028A && mod->mDstOp == 17 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 1000; + VECTOR_BACK(self->mods).mAmount += 1000; else if(mod->mSrcOp == 0x058B && mod->mDstOp == 48 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 960; + VECTOR_BACK(self->mods).mAmount += 960; else if(mod->mSrcOp == 0x00DB && mod->mDstOp == 16 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 200; + VECTOR_BACK(self->mods).mAmount += 200; else if(mod->mSrcOp == 0x00DD && mod->mDstOp == 15 && mod->mAmtSrcOp == 0 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 200; + VECTOR_BACK(self->mods).mAmount += 200; /*else if(mod->mSrcOp == 0x020E && mod->mDstOp == ?initialpitch? && mod->mAmtSrcOp == 0x0010 && mod->mTransOp == 0) - self->mods[self->mods_size].mAmount += 12700;*/ - self->mods_size++; + VECTOR_BACK(self->mods).mAmount += 12700;*/ } @@ -569,7 +472,7 @@ static ALboolean ensureFontSanity(const Soundfont *sfont) { ALsizei i; - for(i = 0;i < sfont->phdr_size-1;i++) + for(i = 0;i < sfont->phdr_size;i++) { if(sfont->phdr[i].mZoneIdx >= sfont->pbag_size) { @@ -577,21 +480,15 @@ static ALboolean ensureFontSanity(const Soundfont *sfont) sfont->phdr[i].mZoneIdx, sfont->pbag_size); return AL_FALSE; } - if(sfont->phdr[i+1].mZoneIdx < sfont->phdr[i].mZoneIdx) + if(i+1 < sfont->phdr_size && sfont->phdr[i+1].mZoneIdx < sfont->phdr[i].mZoneIdx) { WARN("Preset %d has invalid zone index (%d does not follow %d)\n", i+1, sfont->phdr[i+1].mZoneIdx, sfont->phdr[i].mZoneIdx); return AL_FALSE; } } - if(sfont->phdr[i].mZoneIdx >= sfont->pbag_size) - { - WARN("Preset %d has invalid zone index %d (max: %d)\n", i, - sfont->phdr[i].mZoneIdx, sfont->pbag_size); - return AL_FALSE; - } - for(i = 0;i < sfont->pbag_size-1;i++) + for(i = 0;i < sfont->pbag_size;i++) { if(sfont->pbag[i].mGenIdx >= sfont->pgen_size) { @@ -599,7 +496,7 @@ static ALboolean ensureFontSanity(const Soundfont *sfont) sfont->pbag[i].mGenIdx, sfont->pgen_size); return AL_FALSE; } - if(sfont->pbag[i+1].mGenIdx < sfont->pbag[i].mGenIdx) + if(i+1 < sfont->pbag_size && sfont->pbag[i+1].mGenIdx < sfont->pbag[i].mGenIdx) { WARN("Preset zone %d has invalid generator index (%d does not follow %d)\n", i+1, sfont->pbag[i+1].mGenIdx, sfont->pbag[i].mGenIdx); @@ -611,28 +508,16 @@ static ALboolean ensureFontSanity(const Soundfont *sfont) sfont->pbag[i].mModIdx, sfont->pmod_size); return AL_FALSE; } - if(sfont->pbag[i+1].mModIdx < sfont->pbag[i].mModIdx) + if(i+1 < sfont->pbag_size && sfont->pbag[i+1].mModIdx < sfont->pbag[i].mModIdx) { WARN("Preset zone %d has invalid modulator index (%d does not follow %d)\n", i+1, sfont->pbag[i+1].mModIdx, sfont->pbag[i].mModIdx); return AL_FALSE; } } - if(sfont->pbag[i].mGenIdx >= sfont->pgen_size) - { - WARN("Preset zone %d has invalid generator index %d (max: %d)\n", i, - sfont->pbag[i].mGenIdx, sfont->pgen_size); - return AL_FALSE; - } - if(sfont->pbag[i].mModIdx >= sfont->pmod_size) - { - WARN("Preset zone %d has invalid modulator index %d (max: %d)\n", i, - sfont->pbag[i].mModIdx, sfont->pmod_size); - return AL_FALSE; - } - for(i = 0;i < sfont->inst_size-1;i++) + for(i = 0;i < sfont->inst_size;i++) { if(sfont->inst[i].mZoneIdx >= sfont->ibag_size) { @@ -640,21 +525,15 @@ static ALboolean ensureFontSanity(const Soundfont *sfont) sfont->inst[i].mZoneIdx, sfont->ibag_size); return AL_FALSE; } - if(sfont->inst[i+1].mZoneIdx < sfont->inst[i].mZoneIdx) + if(i+1 < sfont->inst_size && sfont->inst[i+1].mZoneIdx < sfont->inst[i].mZoneIdx) { WARN("Instrument %d has invalid zone index (%d does not follow %d)\n", i+1, sfont->inst[i+1].mZoneIdx, sfont->inst[i].mZoneIdx); return AL_FALSE; } } - if(sfont->inst[i].mZoneIdx >= sfont->ibag_size) - { - WARN("Instrument %d has invalid zone index %d (max: %d)\n", i, - sfont->inst[i].mZoneIdx, sfont->ibag_size); - return AL_FALSE; - } - for(i = 0;i < sfont->ibag_size-1;i++) + for(i = 0;i < sfont->ibag_size;i++) { if(sfont->ibag[i].mGenIdx >= sfont->igen_size) { @@ -662,7 +541,7 @@ static ALboolean ensureFontSanity(const Soundfont *sfont) sfont->ibag[i].mGenIdx, sfont->igen_size); return AL_FALSE; } - if(sfont->ibag[i+1].mGenIdx < sfont->ibag[i].mGenIdx) + if(i+1 < sfont->ibag_size && sfont->ibag[i+1].mGenIdx < sfont->ibag[i].mGenIdx) { WARN("Instrument zone %d has invalid generator index (%d does not follow %d)\n", i+1, sfont->ibag[i+1].mGenIdx, sfont->ibag[i].mGenIdx); @@ -674,25 +553,13 @@ static ALboolean ensureFontSanity(const Soundfont *sfont) sfont->ibag[i].mModIdx, sfont->imod_size); return AL_FALSE; } - if(sfont->ibag[i+1].mModIdx < sfont->ibag[i].mModIdx) + if(i+1 < sfont->ibag_size && sfont->ibag[i+1].mModIdx < sfont->ibag[i].mModIdx) { WARN("Instrument zone %d has invalid modulator index (%d does not follow %d)\n", i+1, sfont->ibag[i+1].mModIdx, sfont->ibag[i].mModIdx); return AL_FALSE; } } - if(sfont->ibag[i].mGenIdx >= sfont->igen_size) - { - WARN("Instrument zone %d has invalid generator index %d (max: %d)\n", i, - sfont->ibag[i].mGenIdx, sfont->igen_size); - return AL_FALSE; - } - if(sfont->ibag[i].mModIdx >= sfont->imod_size) - { - WARN("Instrument zone %d has invalid modulator index %d (max: %d)\n", i, - sfont->ibag[i].mModIdx, sfont->imod_size); - return AL_FALSE; - } for(i = 0;i < sfont->shdr_size-1;i++) @@ -710,21 +577,21 @@ static ALboolean ensureFontSanity(const Soundfont *sfont) static ALboolean checkZone(const GenModList *zone, const PresetHeader *preset, const InstrumentHeader *inst, const SampleHeader *samp) { - ALsizei i; - - for(i = 0;i < zone->gens_size;i++) + Generator *gen = VECTOR_ITER_BEGIN(zone->gens); + Generator *gen_end = VECTOR_ITER_END(zone->gens); + for(;gen != gen_end;gen++) { - if(zone->gens[i].mGenerator == 43 || zone->gens[i].mGenerator == 44) + if(gen->mGenerator == 43 || gen->mGenerator == 44) { - int high = zone->gens[i].mAmount>>8; - int low = zone->gens[i].mAmount&0xff; + int high = gen->mAmount>>8; + int low = gen->mAmount&0xff; if(!(low >= 0 && high <= 127 && high >= low)) { TRACE("Preset \"%s\", inst \"%s\", sample \"%s\": invalid %s range %d...%d\n", preset->mName, inst->mName, samp->mName, - (zone->gens[i].mGenerator == 43) ? "key" : - (zone->gens[i].mGenerator == 44) ? "velocity" : "(unknown)", + (gen->mGenerator == 43) ? "key" : + (gen->mGenerator == 44) ? "velocity" : "(unknown)", low, high); return AL_FALSE; } @@ -745,11 +612,8 @@ static ALenum getModSrcInput(int input) if(input == 16) return AL_PITCHBEND_SENSITIVITY_SOFT; if((input&0x80)) { - input ^= 0x80; - if(input > 0 && input < 120 && !(input == 6 || (input >= 32 && input <= 63) || - (input >= 98 && input <= 101))) - return input; - input ^= 0x80; + if(IsValidCtrlInput(input^0x80)) + return input^0x80; } ERR("Unhandled modulator source input: 0x%02x\n", input); return AL_INVALID; @@ -871,43 +735,43 @@ static void fillZone(ALfontsound *sound, ALCcontext *context, const GenModList * 0, /* 59 - */ }; const Generator *gen, *gen_end; + const Modulator *mod, *mod_end; - if(zone->mods) + mod = VECTOR_ITER_BEGIN(zone->mods); + mod_end = VECTOR_ITER_END(zone->mods); + for(;mod != mod_end;mod++) { - ALsizei i; - for(i = 0;i < zone->mods_size;i++) + ALenum src0in = getModSrcInput(mod->mSrcOp&0xFF); + ALenum src0type = getModSrcType(mod->mSrcOp&0x0300); + ALenum src0form = getModSrcForm(mod->mSrcOp&0xFC00); + ALenum src1in = getModSrcInput(mod->mAmtSrcOp&0xFF); + ALenum src1type = getModSrcType(mod->mAmtSrcOp&0x0300); + ALenum src1form = getModSrcForm(mod->mAmtSrcOp&0xFC00); + ALenum trans = getModTransOp(mod->mTransOp); + ALenum dst = (mod->mDstOp < 60) ? Gen2Param[mod->mDstOp] : 0; + if(!dst || dst == AL_KEY_RANGE_SOFT || dst == AL_VELOCITY_RANGE_SOFT || + dst == AL_LOOP_MODE_SOFT || dst == AL_EXCLUSIVE_CLASS_SOFT || + dst == AL_BASE_KEY_SOFT) + ERR("Unhandled modulator destination: %d\n", mod->mDstOp); + else if(src0in != AL_INVALID && src0form != AL_INVALID && src0type != AL_INVALID && + src1in != AL_INVALID && src1form != AL_INVALID && src0type != AL_INVALID && + trans != AL_INVALID) { - ALenum src0in = getModSrcInput(zone->mods[i].mSrcOp&0xFF); - ALenum src0type = getModSrcType(zone->mods[i].mSrcOp&0x0300); - ALenum src0form = getModSrcForm(zone->mods[i].mSrcOp&0xFC00); - ALenum src1in = getModSrcInput(zone->mods[i].mAmtSrcOp&0xFF); - ALenum src1type = getModSrcType(zone->mods[i].mAmtSrcOp&0x0300); - ALenum src1form = getModSrcForm(zone->mods[i].mAmtSrcOp&0xFC00); - ALenum trans = getModTransOp(zone->mods[i].mTransOp); - ALenum dst = (zone->mods[i].mDstOp < 60) ? Gen2Param[zone->mods[i].mDstOp] : 0; - if(!dst || dst == AL_KEY_RANGE_SOFT || dst == AL_VELOCITY_RANGE_SOFT || - dst == AL_LOOP_MODE_SOFT || dst == AL_EXCLUSIVE_CLASS_SOFT || - dst == AL_BASE_KEY_SOFT) - ERR("Unhandled modulator destination: %d\n", zone->mods[i].mDstOp); - else if(src0in != AL_INVALID && src0form != AL_INVALID && src0type != AL_INVALID && - src1in != AL_INVALID && src1form != AL_INVALID && src0type != AL_INVALID && - trans != AL_INVALID) - { - ALfontsound_setModStagei(sound, context, i, AL_SOURCE0_INPUT_SOFT, src0in); - ALfontsound_setModStagei(sound, context, i, AL_SOURCE0_TYPE_SOFT, src0type); - ALfontsound_setModStagei(sound, context, i, AL_SOURCE0_FORM_SOFT, src0form); - ALfontsound_setModStagei(sound, context, i, AL_SOURCE1_INPUT_SOFT, src1in); - ALfontsound_setModStagei(sound, context, i, AL_SOURCE1_TYPE_SOFT, src1type); - ALfontsound_setModStagei(sound, context, i, AL_SOURCE1_FORM_SOFT, src1form); - ALfontsound_setModStagei(sound, context, i, AL_AMOUNT_SOFT, zone->mods[i].mAmount); - ALfontsound_setModStagei(sound, context, i, AL_TRANSFORM_OP_SOFT, trans); - ALfontsound_setModStagei(sound, context, i, AL_DESTINATION_SOFT, dst); - } + ALsizei idx = (ALsizei)(mod - VECTOR_ITER_BEGIN(zone->mods)); + ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_INPUT_SOFT, src0in); + ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_TYPE_SOFT, src0type); + ALfontsound_setModStagei(sound, context, idx, AL_SOURCE0_FORM_SOFT, src0form); + ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_INPUT_SOFT, src1in); + ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_TYPE_SOFT, src1type); + ALfontsound_setModStagei(sound, context, idx, AL_SOURCE1_FORM_SOFT, src1form); + ALfontsound_setModStagei(sound, context, idx, AL_AMOUNT_SOFT, mod->mAmount); + ALfontsound_setModStagei(sound, context, idx, AL_TRANSFORM_OP_SOFT, trans); + ALfontsound_setModStagei(sound, context, idx, AL_DESTINATION_SOFT, dst); } } - gen = zone->gens; - gen_end = gen + zone->gens_size; + gen = VECTOR_ITER_BEGIN(zone->gens); + gen_end = VECTOR_ITER_END(zone->gens); for(;gen != gen_end;gen++) { ALint value = (ALshort)gen->mAmount; @@ -961,12 +825,12 @@ static void fillZone(ALfontsound *sound, ALCcontext *context, const GenModList * value = getLoopMode(value); ALfontsound_setPropi(sound, context, param, value); } - else if(gen->mGenerator < 256) + else { - static ALboolean warned[256]; - if(!warned[gen->mGenerator]) + static ALuint warned[65536/32]; + if(!(warned[gen->mGenerator/32]&(1<<(gen->mGenerator&31)))) { - warned[gen->mGenerator] = AL_TRUE; + warned[gen->mGenerator/32] |= 1<<(gen->mGenerator&31); ERR("Unhandled generator %d\n", gen->mGenerator); } } @@ -974,7 +838,7 @@ static void fillZone(ALfontsound *sound, ALCcontext *context, const GenModList * } } -static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCcontext *context, InstrumentHeader *inst, const PresetHeader *preset, const Soundfont *sfont, const GenModList *pzone) +static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCcontext *context, ALbuffer *buffer, InstrumentHeader *inst, const PresetHeader *preset, const Soundfont *sfont, const GenModList *pzone) { const Generator *gen, *gen_end; const Modulator *mod, *mod_end; @@ -1019,8 +883,8 @@ static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCco temp = realloc(*sounds, (zone_end-zone + *sounds_size)*sizeof((*sounds)[0])); if(!temp) { - ERR("Failed reallocating fontsound storage to %ld elements (from %d)\n", - (zone_end-zone + *sounds_size), *sounds_size); + ERR("Failed reallocating fontsound storage to %d elements (from %d)\n", + (ALsizei)(zone_end-zone) + *sounds_size, *sounds_size); return; } *sounds = temp; @@ -1049,13 +913,13 @@ static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCco } samp = &sfont->shdr[gen->mAmount]; - gen = pzone->gens; - gen_end = gen + pzone->gens_size; + gen = VECTOR_ITER_BEGIN(pzone->gens); + gen_end = VECTOR_ITER_END(pzone->gens); for(;gen != gen_end;gen++) GenModList_accumGen(&lzone, gen); - mod = pzone->mods; - mod_end = mod + pzone->mods_size; + mod = VECTOR_ITER_BEGIN(pzone->mods); + mod_end = VECTOR_ITER_END(pzone->mods); for(;mod != mod_end;mod++) GenModList_accumMod(&lzone, mod); @@ -1067,6 +931,7 @@ static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCco sound = NewFontsound(context); (*sounds)[(*sounds_size)++] = sound; + ALfontsound_setPropi(sound, context, AL_BUFFER, buffer->id); ALfontsound_setPropi(sound, context, AL_SAMPLE_START_SOFT, samp->mStart); ALfontsound_setPropi(sound, context, AL_SAMPLE_END_SOFT, samp->mEnd); ALfontsound_setPropi(sound, context, AL_SAMPLE_LOOP_START_SOFT, samp->mStartloop); @@ -1088,10 +953,27 @@ static void processInstrument(ALfontsound ***sounds, ALsizei *sounds_size, ALCco GenModList_Destruct(&gzone); } +static size_t printStringChunk(Reader *stream, const RiffHdr *chnk, const char *title) +{ + size_t len = 0; + if(chnk->mSize == 0 || (chnk->mSize&1)) + ERR("Invalid "FOURCCFMT" size: %d\n", FOURCCARGS(chnk->mCode), chnk->mSize); + else + { + char *str = calloc(1, chnk->mSize+1); + len = Reader_read(stream, str, chnk->mSize); + + TRACE("%s: %s\n", title, str); + free(str); + } + return len; +} + ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) { ALsfpreset **presets = NULL; ALsizei presets_size = 0; + ALbuffer *buffer = NULL; ALuint ltype; Soundfont sfont; RiffHdr riff; @@ -1102,36 +984,52 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&riff, stream); if(riff.mCode != FOURCC('R','I','F','F')) - ERROR_GOTO(error, "Invalid Format, expected RIFF got '%c%c%c%c'\n", FOURCCARGS(riff.mCode)); + ERROR_GOTO(error, "Invalid Format, expected RIFF got '"FOURCCFMT"'\n", FOURCCARGS(riff.mCode)); if((ltype=read_le32(stream)) != FOURCC('s','f','b','k')) - ERROR_GOTO(error, "Invalid Format, expected sfbk got '%c%c%c%c'\n", FOURCCARGS(ltype)); + ERROR_GOTO(error, "Invalid Format, expected sfbk got '"FOURCCFMT"'\n", FOURCCARGS(ltype)); if(READERR(stream) != 0) ERROR_GOTO(error, "Error reading file header\n"); RiffHdr_read(&list, stream); if(list.mCode != FOURCC('L','I','S','T')) - ERROR_GOTO(error, "Invalid Format, expected LIST (INFO) got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected LIST (INFO) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((ltype=read_le32(stream)) != FOURCC('I','N','F','O')) - ERROR_GOTO(error, "Invalid Format, expected INFO got '%c%c%c%c'\n", FOURCCARGS(ltype)); + ERROR_GOTO(error, "Invalid Format, expected INFO got '"FOURCCFMT"'\n", FOURCCARGS(ltype)); list.mSize -= 4; while(list.mSize > 0 && !READERR(stream)) { - RiffHdr info; + RiffHdr chnk; - RiffHdr_read(&info, stream); - list.mSize -= 8; - if(info.mCode == FOURCC('i','f','i','l')) + if(list.mSize < 8) { - if(info.mSize != 4) - ERR("Invalid ifil chunk size: %d\n", info.mSize); + WARN("Unexpected end of INFO list (%u extra bytes)\n", list.mSize); + skip(stream, list.mSize); + list.mSize = 0; + break; + } + + RiffHdr_read(&chnk, stream); + list.mSize -= 8; + if(list.mSize < chnk.mSize) + { + WARN("INFO sub-chunk '"FOURCCFMT"' has %u bytes, but only %u bytes remain\n", + FOURCCARGS(chnk.mCode), chnk.mSize, list.mSize); + skip(stream, list.mSize); + list.mSize = 0; + break; + } + list.mSize -= chnk.mSize; + + if(chnk.mCode == FOURCC('i','f','i','l')) + { + if(chnk.mSize != 4) + ERR("Invalid ifil chunk size: %d\n", chnk.mSize); else { ALushort major = read_le16(stream); ALushort minor = read_le16(stream); - - list.mSize -= 4; - info.mSize -= 4; + chnk.mSize -= 4; if(major != 2) ERROR_GOTO(error, "Unsupported SF2 format version: %d.%02d\n", major, minor); @@ -1140,24 +1038,48 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) sfont.ifil = (major<<16) | minor; } } - else if(info.mCode == FOURCC('i','r','o','m')) + else if(chnk.mCode == FOURCC('i','r','o','m')) { - if(info.mSize == 0 || (info.mSize&1)) - ERR("Invalid irom size: %d\n", info.mSize); + if(chnk.mSize == 0 || (chnk.mSize&1)) + ERR("Invalid irom size: %d\n", chnk.mSize); else { free(sfont.irom); - sfont.irom = calloc(1, info.mSize+1); - READ(stream, sfont.irom, info.mSize); - - list.mSize -= info.mSize; - info.mSize -= info.mSize; + sfont.irom = calloc(1, chnk.mSize+1); + chnk.mSize -= Reader_read(stream, sfont.irom, chnk.mSize); TRACE("SF2 ROM ID: %s\n", sfont.irom); } } - list.mSize -= info.mSize; - skip(stream, info.mSize); + else + { + static const struct { + ALuint code; + char title[16]; + } listinfos[] = { + { FOURCC('i','s','n','g'), "Engine ID" }, + { FOURCC('I','N','A','M'), "Name" }, + { FOURCC('I','C','R','D'), "Creation Date" }, + { FOURCC('I','E','N','G'), "Creator" }, + { FOURCC('I','P','R','D'), "Product ID" }, + { FOURCC('I','C','O','P'), "Copyright" }, + { FOURCC('I','C','M','T'), "Comment" }, + { FOURCC('I','S','F','T'), "Created With" }, + { 0, "" }, + }; + + for(i = 0;listinfos[i].code;i++) + { + if(listinfos[i].code == chnk.mCode) + { + chnk.mSize -= printStringChunk(stream, &chnk, listinfos[i].title); + break; + } + } + if(!listinfos[i].code) + TRACE("Skipping INFO sub-chunk '"FOURCCFMT"' (%u bytes)\n", FOURCCARGS(chnk.mCode), chnk.mSize); + } + skip(stream, chnk.mSize); } if(READERR(stream) != 0) @@ -1167,43 +1089,50 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&list, stream); if(list.mCode != FOURCC('L','I','S','T')) - ERROR_GOTO(error, "Invalid Format, expected LIST (sdta) got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected LIST (sdta) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((ltype=read_le32(stream)) != FOURCC('s','d','t','a')) - ERROR_GOTO(error, "Invalid Format, expected sdta got '%c%c%c%c'\n", FOURCCARGS(ltype)); + ERROR_GOTO(error, "Invalid Format, expected sdta got '"FOURCCFMT"'\n", FOURCCARGS(ltype)); list.mSize -= 4; { ALbyte *ptr; RiffHdr smpl; + ALenum err; RiffHdr_read(&smpl, stream); if(smpl.mCode != FOURCC('s','m','p','l')) - ERROR_GOTO(error, "Invalid Format, expected smpl got '%c%c%c%c'\n", FOURCCARGS(smpl.mCode)); + ERROR_GOTO(error, "Invalid Format, expected smpl got '"FOURCCFMT"'\n", FOURCCARGS(smpl.mCode)); list.mSize -= 8; if(smpl.mSize > list.mSize) ERROR_GOTO(error, "Invalid Format, sample chunk size mismatch\n"); + list.mSize -= smpl.mSize; - if(!(ptr=realloc(soundfont->Samples, smpl.mSize))) + buffer = NewBuffer(context); + if(!buffer) SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, error); - soundfont->Samples = (ALshort*)ptr; - soundfont->NumSamples = smpl.mSize/2; + /* Sample rate is unimportant, the individual fontsounds will specify it. */ + if((err=LoadData(buffer, 22050, AL_MONO16_SOFT, smpl.mSize/2, UserFmtMono, UserFmtShort, NULL, 1, AL_FALSE)) != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, error); + ptr = buffer->data; if(IS_LITTLE_ENDIAN) - READ(stream, ptr, smpl.mSize); + smpl.mSize -= Reader_read(stream, ptr, smpl.mSize); else { - while(smpl.mSize > 0) + ALuint total = 0; + while(total < smpl.mSize && !READERR(stream)) { ALbyte buf[4096]; - ALuint todo = minu(smpl.mSize, sizeof(buf)); + ALuint todo = minu(smpl.mSize-total, sizeof(buf)); ALuint i; - READ(stream, buf, todo); + smpl.mSize -= Reader_read(stream, buf, todo); for(i = 0;i < todo;i++) - ptr[i] = buf[i^1]; + ptr[total+i] = buf[i^1]; + + total += todo; } } - list.mSize -= smpl.mSize; skip(stream, list.mSize); } @@ -1213,14 +1142,14 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&list, stream); if(list.mCode != FOURCC('L','I','S','T')) - ERROR_GOTO(error, "Invalid Format, expected LIST (pdta) got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected LIST (pdta) got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((ltype=read_le32(stream)) != FOURCC('p','d','t','a')) - ERROR_GOTO(error, "Invalid Format, expected pdta got '%c%c%c%c'\n", FOURCCARGS(ltype)); + ERROR_GOTO(error, "Invalid Format, expected pdta got '"FOURCCFMT"'\n", FOURCCARGS(ltype)); // RiffHdr_read(&list, stream); if(list.mCode != FOURCC('p','h','d','r')) - ERROR_GOTO(error, "Invalid Format, expected phdr got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected phdr got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%38) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad phdr size: %u\n", list.mSize); sfont.phdr_size = list.mSize/38; @@ -1230,7 +1159,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&list, stream); if(list.mCode != FOURCC('p','b','a','g')) - ERROR_GOTO(error, "Invalid Format, expected pbag got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected pbag got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%4) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad pbag size: %u\n", list.mSize); sfont.pbag_size = list.mSize/4; @@ -1240,7 +1169,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&list, stream); if(list.mCode != FOURCC('p','m','o','d')) - ERROR_GOTO(error, "Invalid Format, expected pmod got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected pmod got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%10) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad pmod size: %u\n", list.mSize); sfont.pmod_size = list.mSize/10; @@ -1250,7 +1179,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&list, stream); if(list.mCode != FOURCC('p','g','e','n')) - ERROR_GOTO(error, "Invalid Format, expected pgen got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected pgen got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%4) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad pgen size: %u\n", list.mSize); sfont.pgen_size = list.mSize/4; @@ -1261,7 +1190,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) // RiffHdr_read(&list, stream); if(list.mCode != FOURCC('i','n','s','t')) - ERROR_GOTO(error, "Invalid Format, expected inst got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected inst got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%22) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad inst size: %u\n", list.mSize); sfont.inst_size = list.mSize/22; @@ -1271,7 +1200,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&list, stream); if(list.mCode != FOURCC('i','b','a','g')) - ERROR_GOTO(error, "Invalid Format, expected ibag got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected ibag got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%4) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad ibag size: %u\n", list.mSize); sfont.ibag_size = list.mSize/4; @@ -1281,7 +1210,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&list, stream); if(list.mCode != FOURCC('i','m','o','d')) - ERROR_GOTO(error, "Invalid Format, expected imod got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected imod got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%10) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad imod size: %u\n", list.mSize); sfont.imod_size = list.mSize/10; @@ -1291,7 +1220,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) RiffHdr_read(&list, stream); if(list.mCode != FOURCC('i','g','e','n')) - ERROR_GOTO(error, "Invalid Format, expected igen got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected igen got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%4) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad igen size: %u\n", list.mSize); sfont.igen_size = list.mSize/4; @@ -1302,7 +1231,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) // RiffHdr_read(&list, stream); if(list.mCode != FOURCC('s','h','d','r')) - ERROR_GOTO(error, "Invalid Format, expected shdr got '%c%c%c%c'\n", FOURCCARGS(list.mCode)); + ERROR_GOTO(error, "Invalid Format, expected shdr got '"FOURCCFMT"'\n", FOURCCARGS(list.mCode)); if((list.mSize%46) != 0 || list.mSize == 0) ERROR_GOTO(error, "Invalid Format, bad shdr size: %u\n", list.mSize); sfont.shdr_size = list.mSize/46; @@ -1316,9 +1245,11 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) if(!ensureFontSanity(&sfont)) goto error; - presets = calloc(1, (sfont.phdr_size-1)*sizeof(presets[0])); + presets = calloc(1, (soundfont->NumPresets+sfont.phdr_size-1)*sizeof(presets[0])); if(!presets) ERROR_GOTO(error, "Error allocating presets\n"); + memcpy(presets, soundfont->Presets, soundfont->NumPresets*sizeof(presets[0])); + presets_size = soundfont->NumPresets; for(i = 0;i < sfont.phdr_size-1;i++) { @@ -1382,8 +1313,10 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) ERR("Generator %ld has invalid instrument ID (%d of %d)\n", (long)(gen-sfont.pgen), gen->mAmount, sfont.inst_size-1); else - processInstrument(&sounds, &sounds_size, context, - &sfont.inst[gen->mAmount], &sfont.phdr[i], &sfont, &lzone); + processInstrument( + &sounds, &sounds_size, context, buffer, &sfont.inst[gen->mAmount], + &sfont.phdr[i], &sfont, &lzone + ); break; } GenModList_insertGen(&lzone, gen, AL_TRUE); @@ -1410,7 +1343,7 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) GenModList_Destruct(&gzone); } - for(i = 0;i < presets_size;i++) + for(i = soundfont->NumPresets;i < presets_size;i++) IncrementRef(&presets[i]->ref); presets = ExchangePtr((XchgPtr*)&soundfont->Presets, presets); ExchangeInt(&soundfont->NumPresets, presets_size); @@ -1418,6 +1351,12 @@ ALboolean loadSf2(Reader *stream, ALsoundfont *soundfont, ALCcontext *context) free(presets); Soundfont_Destruct(&sfont); + /* If the buffer ends up unused, delete it. */ + if(ReadRef(&buffer->ref) == 0) + { + TRACE("Deleting unused buffer...\n"); + DeleteBuffer(context->Device, buffer); + } return AL_TRUE; @@ -1425,12 +1364,14 @@ error: if(presets) { ALCdevice *device = context->Device; - for(i = 0;i < presets_size;i++) - DeletePreset(presets[i], device); + for(i = soundfont->NumPresets;i < presets_size;i++) + DeletePreset(device, presets[i]); free(presets); } Soundfont_Destruct(&sfont); + if(buffer) + DeleteBuffer(context->Device, buffer); return AL_FALSE; } diff --git a/jni/openal-soft-1.16.0/Alc/midi/soft.c b/jni/openal-soft-1.16.0/Alc/midi/soft.c new file mode 100644 index 00000000..6566b411 --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/midi/soft.c @@ -0,0 +1,140 @@ + +#include "config.h" + +#include +#include +#include +#include + +#include "alMain.h" +#include "alError.h" +#include "evtqueue.h" +#include "alu.h" + +#include "midi/base.h" + + +typedef struct SSynth { + DERIVE_FROM_TYPE(MidiSynth); +} SSynth; + +static void SSynth_mixSamples(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]); + +static void SSynth_Construct(SSynth *self, ALCdevice *device); +static void SSynth_Destruct(SSynth *self); +static DECLARE_FORWARD3(SSynth, MidiSynth, ALenum, selectSoundfonts, ALCcontext*, ALsizei, const ALuint*) +static DECLARE_FORWARD1(SSynth, MidiSynth, void, setGain, ALfloat) +static DECLARE_FORWARD(SSynth, MidiSynth, void, stop) +static DECLARE_FORWARD(SSynth, MidiSynth, void, reset) +static void SSynth_update(SSynth *self, ALCdevice *device); +static void SSynth_process(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]); +DECLARE_DEFAULT_ALLOCATORS(SSynth) +DEFINE_MIDISYNTH_VTABLE(SSynth); + + +static void SSynth_Construct(SSynth *self, ALCdevice *device) +{ + MidiSynth_Construct(STATIC_CAST(MidiSynth, self), device); + SET_VTABLE2(SSynth, MidiSynth, self); +} + +static void SSynth_Destruct(SSynth* UNUSED(self)) +{ +} + + +static void SSynth_update(SSynth* UNUSED(self), ALCdevice* UNUSED(device)) +{ +} + + +static void SSynth_mixSamples(SSynth* UNUSED(self), ALuint UNUSED(SamplesToDo), ALfloatBUFFERSIZE *restrict UNUSED(DryBuffer)) +{ +} + + +static void SSynth_processQueue(SSynth *self, ALuint64 time) +{ + EvtQueue *queue = &STATIC_CAST(MidiSynth, self)->EventQueue; + + while(queue->pos < queue->size && queue->events[queue->pos].time <= time) + queue->pos++; +} + +static void SSynth_process(SSynth *self, ALuint SamplesToDo, ALfloat (*restrict DryBuffer)[BUFFERSIZE]) +{ + MidiSynth *synth = STATIC_CAST(MidiSynth, self); + ALenum state = synth->State; + ALuint64 curtime; + ALuint total = 0; + + if(state == AL_INITIAL) + return; + if(state != AL_PLAYING) + { + SSynth_mixSamples(self, SamplesToDo, DryBuffer); + return; + } + + curtime = MidiSynth_getTime(synth); + while(total < SamplesToDo) + { + ALuint64 time, diff; + ALint tonext; + + time = MidiSynth_getNextEvtTime(synth); + diff = maxu64(time, curtime) - curtime; + if(diff >= MIDI_CLOCK_RES || time == UINT64_MAX) + { + /* If there's no pending event, or if it's more than 1 second + * away, do as many samples as we can. */ + tonext = INT_MAX; + } + else + { + /* Figure out how many samples until the next event. */ + tonext = (ALint)((diff*synth->SampleRate + (MIDI_CLOCK_RES-1)) / MIDI_CLOCK_RES); + tonext -= total; + /* For efficiency reasons, try to mix a multiple of 64 samples + * (~1ms @ 44.1khz) before processing the next event. */ + tonext = (tonext+63) & ~63; + } + + if(tonext > 0) + { + ALuint todo = mini(tonext, SamplesToDo-total); + SSynth_mixSamples(self, todo, DryBuffer); + total += todo; + tonext -= todo; + } + if(total < SamplesToDo && tonext <= 0) + SSynth_processQueue(self, time); + } + + synth->SamplesDone += SamplesToDo; + synth->ClockBase += (synth->SamplesDone/synth->SampleRate) * MIDI_CLOCK_RES; + synth->SamplesDone %= synth->SampleRate; +} + + +MidiSynth *SSynth_create(ALCdevice *device) +{ + SSynth *synth; + + /* This option is temporary. Once this synth is in a more usable state, a + * more generic selector should be used. */ + if(!GetConfigValueBool("midi", "internal-synth", 0)) + { + TRACE("Not using internal MIDI synth\n"); + return NULL; + } + + synth = SSynth_New(sizeof(*synth)); + if(!synth) + { + ERR("Failed to allocate SSynth\n"); + return NULL; + } + SSynth_Construct(synth, device); + return STATIC_CAST(MidiSynth, synth); +} diff --git a/jni/openal-soft-android/Alc/mixer.c b/jni/openal-soft-1.16.0/Alc/mixer.c similarity index 59% rename from jni/openal-soft-android/Alc/mixer.c rename to jni/openal-soft-1.16.0/Alc/mixer.c index acd6c610..f3b8f599 100644 --- a/jni/openal-soft-android/Alc/mixer.c +++ b/jni/openal-soft-1.16.0/Alc/mixer.c @@ -34,7 +34,68 @@ #include "alListener.h" #include "alAuxEffectSlot.h" #include "alu.h" -#include "bs2b.h" + +#include "mixer_defs.h" + + +extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size); + + +static inline HrtfMixerFunc SelectHrtfMixer(void) +{ +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return MixHrtf_SSE; +#endif +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return MixHrtf_Neon; +#endif + + return MixHrtf_C; +} + +static inline MixerFunc SelectMixer(void) +{ +#ifdef HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + return Mix_SSE; +#endif +#ifdef HAVE_NEON + if((CPUCapFlags&CPU_CAP_NEON)) + return Mix_Neon; +#endif + + return Mix_C; +} + +static inline ResamplerFunc SelectResampler(enum Resampler Resampler, ALuint increment) +{ + if(increment == FRACTIONONE) + return Resample_copy32_C; + switch(Resampler) + { + case PointResampler: + return Resample_point32_C; + case LinearResampler: +#ifdef HAVE_SSE4_1 + if((CPUCapFlags&CPU_CAP_SSE4_1)) + return Resample_lerp32_SSE41; +#endif +#ifdef HAVE_SSE2 + if((CPUCapFlags&CPU_CAP_SSE2)) + return Resample_lerp32_SSE2; +#endif + return Resample_lerp32_C; + case CubicResampler: + return Resample_cubic32_C; + case ResamplerMax: + /* Shouldn't happen */ + break; + } + + return Resample_point32_C; +} static inline ALfloat Sample_ALbyte(ALbyte val) @@ -60,7 +121,7 @@ DECL_TEMPLATE(ALfloat) #undef DECL_TEMPLATE -static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples) +static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples) { switch(srctype) { @@ -76,7 +137,7 @@ static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtTy } } -static void SilenceData(ALfloat *dst, ALuint samples) +static void SilenceSamples(ALfloat *dst, ALuint samples) { ALuint i; for(i = 0;i < samples;i++) @@ -84,21 +145,47 @@ static void SilenceData(ALfloat *dst, ALuint samples) } -static void DoFilter(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *restrict src, - ALuint numsamples) +static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter, + ALfloat *restrict dst, const ALfloat *restrict src, + ALuint numsamples, enum ActiveFilters type) { ALuint i; - for(i = 0;i < numsamples;i++) - dst[i] = ALfilterState_processSingle(filter, src[i]); - dst[i] = ALfilterState_processSingleC(filter, src[i]); + switch(type) + { + case AF_None: + break; + + case AF_LowPass: + ALfilterState_process(lpfilter, dst, src, numsamples); + return dst; + case AF_HighPass: + ALfilterState_process(hpfilter, dst, src, numsamples); + return dst; + + case AF_BandPass: + for(i = 0;i < numsamples;) + { + ALfloat temp[64]; + ALuint todo = minu(64, numsamples-i); + + ALfilterState_process(lpfilter, temp, src+i, todo); + ALfilterState_process(hpfilter, dst+i, temp, todo); + i += todo; + } + return dst; + } + return src; } -ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) +ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo) { + MixerFunc Mix; + HrtfMixerFunc HrtfMix; + ResamplerFunc Resample; + ALsource *Source = src->Source; ALbufferlistitem *BufferListItem; ALuint DataPosInt, DataPosFrac; - ALuint BuffersPlayed; ALboolean Looping; ALuint increment; enum Resampler Resampler; @@ -110,20 +197,19 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) ALuint chan, j; /* Get source info */ - State = Source->state; - BuffersPlayed = Source->BuffersPlayed; - DataPosInt = Source->position; - DataPosFrac = Source->position_fraction; - Looping = Source->Looping; - increment = Source->Params.Step; - Resampler = (increment==FRACTIONONE) ? PointResampler : Source->Resampler; - NumChannels = Source->NumChannels; - SampleSize = Source->SampleSize; + State = Source->state; + BufferListItem = ATOMIC_LOAD(&Source->current_buffer); + DataPosInt = Source->position; + DataPosFrac = Source->position_fraction; + Looping = Source->Looping; + increment = src->Step; + Resampler = (increment==FRACTIONONE) ? PointResampler : Source->Resampler; + NumChannels = Source->NumChannels; + SampleSize = Source->SampleSize; - /* Get current buffer queue item */ - BufferListItem = Source->queue; - for(j = 0;j < BuffersPlayed;j++) - BufferListItem = BufferListItem->next; + Mix = SelectMixer(); + HrtfMix = SelectHrtfMixer(); + Resample = SelectResampler(Resampler, increment); OutPos = 0; do { @@ -132,7 +218,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) ALuint SrcBufferSize, DstBufferSize; /* Figure out how many buffer samples will be needed */ - DataSize64 = SamplesToDo-OutPos+1; + DataSize64 = SamplesToDo-OutPos; DataSize64 *= increment; DataSize64 += DataPosFrac+FRACTIONMASK; DataSize64 >>= FRACTIONBITS; @@ -144,7 +230,6 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) DataSize64 = SrcBufferSize; DataSize64 -= BufferPadding+BufferPrePadding; DataSize64 <<= FRACTIONBITS; - DataSize64 -= increment; DataSize64 -= DataPosFrac; DstBufferSize = (ALuint)((DataSize64+(increment-1)) / increment); @@ -157,13 +242,13 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) for(chan = 0;chan < NumChannels;chan++) { - ALfloat *SrcData = Device->SampleData1; - ALfloat *ResampledData = Device->SampleData2; + const ALfloat *ResampledData; + ALfloat *SrcData = Device->SourceData; ALuint SrcDataSize = 0; if(Source->SourceType == AL_STATIC) { - const ALbuffer *ALBuffer = Source->queue->buffer; + const ALbuffer *ALBuffer = BufferListItem->buffer; const ALubyte *Data = ALBuffer->data; ALuint DataSize; ALuint pos; @@ -180,7 +265,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) DataSize = BufferPrePadding - DataPosInt; DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); - SilenceData(&SrcData[SrcDataSize], DataSize); + SilenceSamples(&SrcData[SrcDataSize], DataSize); SrcDataSize += DataSize; pos = 0; @@ -190,11 +275,11 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) * rest of the temp buffer */ DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos); - LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize], - NumChannels, ALBuffer->FmtType, DataSize); + LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); SrcDataSize += DataSize; - SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize); + SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize); SrcDataSize += SrcBufferSize - SrcDataSize; } else @@ -217,7 +302,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) DataSize = BufferPrePadding - DataPosInt; DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); - SilenceData(&SrcData[SrcDataSize], DataSize); + SilenceSamples(&SrcData[SrcDataSize], DataSize); SrcDataSize += DataSize; pos = 0; @@ -228,8 +313,8 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) DataSize = LoopEnd - pos; DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); - LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize], - NumChannels, ALBuffer->FmtType, DataSize); + LoadSamples(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); SrcDataSize += DataSize; DataSize = LoopEnd-LoopStart; @@ -237,8 +322,8 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) { DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); - LoadData(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize], - NumChannels, ALBuffer->FmtType, DataSize); + LoadSamples(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize], + NumChannels, ALBuffer->FmtType, DataSize); SrcDataSize += DataSize; } } @@ -256,25 +341,25 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) pos = BufferPrePadding - DataPosInt; while(pos > 0) { - if(!tmpiter->prev && !Looping) + ALbufferlistitem *prev; + if((prev=tmpiter->prev) != NULL) + tmpiter = prev; + else if(Looping) + { + while(tmpiter->next) + tmpiter = tmpiter->next; + } + else { ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos); - SilenceData(&SrcData[SrcDataSize], DataSize); + SilenceSamples(&SrcData[SrcDataSize], DataSize); SrcDataSize += DataSize; pos = 0; break; } - if(tmpiter->prev) - tmpiter = tmpiter->prev; - else - { - while(tmpiter->next) - tmpiter = tmpiter->next; - } - if(tmpiter->buffer) { if((ALuint)tmpiter->buffer->SampleLen > pos) @@ -305,55 +390,72 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) pos -= pos; DataSize = minu(SrcBufferSize - SrcDataSize, DataSize); - LoadData(&SrcData[SrcDataSize], Data, NumChannels, - ALBuffer->FmtType, DataSize); + LoadSamples(&SrcData[SrcDataSize], Data, NumChannels, + ALBuffer->FmtType, DataSize); SrcDataSize += DataSize; } } tmpiter = tmpiter->next; if(!tmpiter && Looping) - tmpiter = Source->queue; + tmpiter = ATOMIC_LOAD(&Source->queue); else if(!tmpiter) { - SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize); + SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize); SrcDataSize += SrcBufferSize - SrcDataSize; } } } /* Now resample, then filter and mix to the appropriate outputs. */ - Source->Params.Resample(&SrcData[BufferPrePadding], DataPosFrac, - increment, ResampledData, DstBufferSize); - + ResampledData = Resample( + &SrcData[BufferPrePadding], DataPosFrac, increment, + Device->ResampledData, DstBufferSize + ); { - DirectParams *directparms = &Source->Params.Direct; + DirectParams *parms = &src->Direct; + const ALfloat *samples; - DoFilter(&directparms->LpFilter[chan], SrcData, ResampledData, - DstBufferSize); - Source->Params.DryMix(directparms, SrcData, chan, OutPos, - SamplesToDo, DstBufferSize); + samples = DoFilters( + &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass, + Device->FilteredData, ResampledData, DstBufferSize, + parms->Filters[chan].ActiveType + ); + if(!src->IsHrtf) + Mix(samples, MaxChannels, parms->OutBuffer, parms->Mix.Gains[chan], + parms->Counter, OutPos, DstBufferSize); + else + HrtfMix(parms->OutBuffer, samples, parms->Counter, src->Offset, + OutPos, parms->Mix.Hrtf.IrSize, &parms->Mix.Hrtf.Params[chan], + &parms->Mix.Hrtf.State[chan], DstBufferSize); } for(j = 0;j < Device->NumAuxSends;j++) { - SendParams *sendparms = &Source->Params.Send[j]; - if(!sendparms->OutBuffer) + SendParams *parms = &src->Send[j]; + const ALfloat *samples; + + if(!parms->OutBuffer) continue; - DoFilter(&sendparms->LpFilter[chan], SrcData, ResampledData, - DstBufferSize); - Source->Params.WetMix(sendparms, SrcData, OutPos, - SamplesToDo, DstBufferSize); + samples = DoFilters( + &parms->Filters[chan].LowPass, &parms->Filters[chan].HighPass, + Device->FilteredData, ResampledData, DstBufferSize, + parms->Filters[chan].ActiveType + ); + Mix(samples, 1, parms->OutBuffer, &parms->Gain, + parms->Counter, OutPos, DstBufferSize); } } /* Update positions */ - for(j = 0;j < DstBufferSize;j++) - { - DataPosFrac += increment; - DataPosInt += DataPosFrac>>FRACTIONBITS; - DataPosFrac &= FRACTIONMASK; - } + DataPosFrac += increment*DstBufferSize; + DataPosInt += DataPosFrac>>FRACTIONBITS; + DataPosFrac &= FRACTIONMASK; + OutPos += DstBufferSize; + src->Offset += DstBufferSize; + src->Direct.Counter = maxu(src->Direct.Counter, DstBufferSize) - DstBufferSize; + for(j = 0;j < Device->NumAuxSends;j++) + src->Send[j].Counter = maxu(src->Send[j].Counter, DstBufferSize) - DstBufferSize; /* Handle looping sources */ while(1) @@ -374,6 +476,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) if(Looping && Source->SourceType == AL_STATIC) { + assert(LoopEnd > LoopStart); DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart; break; } @@ -381,24 +484,18 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) if(DataSize > DataPosInt) break; - if(BufferListItem->next) + if(!(BufferListItem=BufferListItem->next)) { - BufferListItem = BufferListItem->next; - BuffersPlayed++; - } - else if(Looping) - { - BufferListItem = Source->queue; - BuffersPlayed = 0; - } - else - { - State = AL_STOPPED; - BufferListItem = Source->queue; - BuffersPlayed = Source->BuffersInQueue; - DataPosInt = 0; - DataPosFrac = 0; - break; + if(Looping) + BufferListItem = ATOMIC_LOAD(&Source->queue); + else + { + State = AL_STOPPED; + BufferListItem = NULL; + DataPosInt = 0; + DataPosFrac = 0; + break; + } } DataPosInt -= DataSize; @@ -407,15 +504,7 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) /* Update source info */ Source->state = State; - Source->BuffersPlayed = BuffersPlayed; + ATOMIC_STORE(&Source->current_buffer, BufferListItem); Source->position = DataPosInt; Source->position_fraction = DataPosFrac; - Source->Hrtf.Offset += OutPos; - if(State == AL_PLAYING) - Source->Hrtf.Counter = maxu(Source->Hrtf.Counter, OutPos) - OutPos; - else - { - Source->Hrtf.Counter = 0; - Source->Hrtf.Moving = AL_FALSE; - } } diff --git a/jni/openal-soft-android/Alc/mixer_c.c b/jni/openal-soft-1.16.0/Alc/mixer_c.c similarity index 50% rename from jni/openal-soft-android/Alc/mixer_c.c rename to jni/openal-soft-1.16.0/Alc/mixer_c.c index 36d8bf5a..f3a229e5 100644 --- a/jni/openal-soft-android/Alc/mixer_c.c +++ b/jni/openal-soft-1.16.0/Alc/mixer_c.c @@ -15,28 +15,33 @@ static inline ALfloat lerp32(const ALfloat *vals, ALuint frac) static inline ALfloat cubic32(const ALfloat *vals, ALuint frac) { return cubic(vals[-1], vals[0], vals[1], vals[2], frac * (1.0f/FRACTIONONE)); } -void Resample_copy32_C(const ALfloat *data, ALuint UNUSED(frac), - ALuint increment, ALfloat *restrict OutBuffer, ALuint BufferSize) +const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint UNUSED(frac), + ALuint increment, ALfloat *restrict dst, ALuint numsamples) { assert(increment==FRACTIONONE); - memcpy(OutBuffer, data, (BufferSize+1)*sizeof(ALfloat)); +#if defined(HAVE_SSE) || defined(HAVE_NEON) + /* Avoid copying the source data if it's aligned like the destination. */ + if((((intptr_t)src)&15) == (((intptr_t)dst)&15)) + return src; +#endif + memcpy(dst, src, numsamples*sizeof(ALfloat)); + return dst; } #define DECL_TEMPLATE(Sampler) \ -void Resample_##Sampler##_C(const ALfloat *data, ALuint frac, \ - ALuint increment, ALfloat *restrict OutBuffer, ALuint BufferSize) \ +const ALfloat *Resample_##Sampler##_C(const ALfloat *src, ALuint frac, \ + ALuint increment, ALfloat *restrict dst, ALuint numsamples) \ { \ - ALuint pos = 0; \ ALuint i; \ - \ - for(i = 0;i < BufferSize+1;i++) \ + for(i = 0;i < numsamples;i++) \ { \ - OutBuffer[i] = Sampler(data + pos, frac); \ + dst[i] = Sampler(src, frac); \ \ frac += increment; \ - pos += frac>>FRACTIONBITS; \ + src += frac>>FRACTIONBITS; \ frac &= FRACTIONMASK; \ } \ + return dst; \ } DECL_TEMPLATE(point32) @@ -46,13 +51,26 @@ DECL_TEMPLATE(cubic32) #undef DECL_TEMPLATE -static inline void ApplyCoeffsStep(const ALuint IrSize, +void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples) +{ + ALuint i; + for(i = 0;i < numsamples;i++) + *(dst++) = ALfilterState_processSingle(filter, *(src++)); +} + + +static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2], + const ALuint IrSize, ALfloat (*restrict Coeffs)[2], - const ALfloat (*restrict CoeffStep)[2]) + const ALfloat (*restrict CoeffStep)[2], + ALfloat left, ALfloat right) { ALuint c; for(c = 0;c < IrSize;c++) { + const ALuint off = (Offset+c)&HRIR_MASK; + Values[off][0] += Coeffs[c][0] * left; + Values[off][1] += Coeffs[c][1] * right; Coeffs[c][0] += CoeffStep[c][0]; Coeffs[c][1] += CoeffStep[c][1]; } @@ -77,49 +95,32 @@ static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2], #undef SUFFIX -void MixDirect_C(const DirectParams *params, const ALfloat *restrict data, ALuint srcchan, - ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) +void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize) { - ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer; - ALfloat *restrict ClickRemoval = params->ClickRemoval; - ALfloat *restrict PendingClicks = params->PendingClicks; - ALfloat DrySend; - ALuint pos; + ALfloat gain, step; ALuint c; - for(c = 0;c < MaxChannels;c++) + for(c = 0;c < OutChans;c++) { - DrySend = params->Gains[srcchan][c]; - if(!(DrySend > GAIN_SILENCE_THRESHOLD)) - continue; + ALuint pos = 0; + gain = Gains[c].Current; + step = Gains[c].Step; + if(step != 1.0f && Counter > 0) + { + for(;pos < BufferSize && pos < Counter;pos++) + { + OutBuffer[c][OutPos+pos] += data[pos]*gain; + gain *= step; + } + if(pos == Counter) + gain = Gains[c].Target; + Gains[c].Current = gain; + } - if(OutPos == 0) - ClickRemoval[c] -= data[0]*DrySend; - for(pos = 0;pos < BufferSize;pos++) - OutBuffer[c][OutPos+pos] += data[pos]*DrySend; - if(OutPos+pos == SamplesToDo) - PendingClicks[c] += data[pos]*DrySend; + if(!(gain > GAIN_SILENCE_THRESHOLD)) + continue; + for(;pos < BufferSize;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; } } - - -void MixSend_C(const SendParams *params, const ALfloat *restrict data, - ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) -{ - ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer; - ALfloat *restrict ClickRemoval = params->ClickRemoval; - ALfloat *restrict PendingClicks = params->PendingClicks; - ALfloat WetSend; - ALuint pos; - - WetSend = params->Gain; - if(!(WetSend > GAIN_SILENCE_THRESHOLD)) - return; - - if(OutPos == 0) - ClickRemoval[0] -= data[0] * WetSend; - for(pos = 0;pos < BufferSize;pos++) - OutBuffer[0][OutPos+pos] += data[pos] * WetSend; - if(OutPos+pos == SamplesToDo) - PendingClicks[0] += data[pos] * WetSend; -} diff --git a/jni/openal-soft-1.16.0/Alc/mixer_defs.h b/jni/openal-soft-1.16.0/Alc/mixer_defs.h new file mode 100644 index 00000000..c1500ed2 --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/mixer_defs.h @@ -0,0 +1,65 @@ +#ifndef MIXER_DEFS_H +#define MIXER_DEFS_H + +#include "AL/alc.h" +#include "AL/al.h" +#include "alMain.h" +#include "alu.h" + +struct MixGains; + +struct HrtfParams; +struct HrtfState; + +/* C resamplers */ +const ALfloat *Resample_copy32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); +const ALfloat *Resample_point32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); +const ALfloat *Resample_lerp32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); +const ALfloat *Resample_cubic32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); + + +/* C mixers */ +void MixHrtf_C(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data, + ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize, + const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate, + ALuint BufferSize); +void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize); + +/* SSE mixers */ +void MixHrtf_SSE(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data, + ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize, + const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate, + ALuint BufferSize); +void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize); + +/* SSE resamplers */ +inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size) +{ + ALuint i; + + pos_arr[0] = 0; + frac_arr[0] = frac; + for(i = 1;i < size;i++) + { + ALuint frac_tmp = frac_arr[i-1] + increment; + pos_arr[i] = pos_arr[i-1] + (frac_tmp>>FRACTIONBITS); + frac_arr[i] = frac_tmp&FRACTIONMASK; + } +} + +const ALfloat *Resample_lerp32_SSE2(const ALfloat *src, ALuint frac, ALuint increment, + ALfloat *restrict dst, ALuint numsamples); +const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint increment, + ALfloat *restrict dst, ALuint numsamples); + +/* Neon mixers */ +void MixHrtf_Neon(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data, + ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize, + const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate, + ALuint BufferSize); +void Mix_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize); + +#endif /* MIXER_DEFS_H */ diff --git a/jni/openal-soft-1.16.0/Alc/mixer_inc.c b/jni/openal-soft-1.16.0/Alc/mixer_inc.c new file mode 100644 index 00000000..ab6f32c5 --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/mixer_inc.c @@ -0,0 +1,93 @@ +#include "config.h" + +#include "alMain.h" +#include "alSource.h" + +#include "hrtf.h" +#include "mixer_defs.h" +#include "align.h" + + +#define REAL_MERGE(a,b) a##b +#define MERGE(a,b) REAL_MERGE(a,b) + +#define MixHrtf MERGE(MixHrtf_,SUFFIX) + + +static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2], + const ALuint irSize, + ALfloat (*restrict Coeffs)[2], + const ALfloat (*restrict CoeffStep)[2], + ALfloat left, ALfloat right); +static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2], + const ALuint irSize, + ALfloat (*restrict Coeffs)[2], + ALfloat left, ALfloat right); + + +void MixHrtf(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data, + ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize, + const HrtfParams *hrtfparams, HrtfState *hrtfstate, ALuint BufferSize) +{ + alignas(16) ALfloat Coeffs[HRIR_LENGTH][2]; + ALuint Delay[2]; + ALfloat left, right; + ALuint pos; + ALuint c; + + for(c = 0;c < IrSize;c++) + { + Coeffs[c][0] = hrtfparams->Coeffs[c][0] - (hrtfparams->CoeffStep[c][0]*Counter); + Coeffs[c][1] = hrtfparams->Coeffs[c][1] - (hrtfparams->CoeffStep[c][1]*Counter); + } + Delay[0] = hrtfparams->Delay[0] - (hrtfparams->DelayStep[0]*Counter); + Delay[1] = hrtfparams->Delay[1] - (hrtfparams->DelayStep[1]*Counter); + + for(pos = 0;pos < BufferSize && pos < Counter;pos++) + { + hrtfstate->History[Offset&SRC_HISTORY_MASK] = data[pos]; + left = lerp(hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK], + hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK], + (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE)); + right = lerp(hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK], + hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK], + (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE)); + + Delay[0] += hrtfparams->DelayStep[0]; + Delay[1] += hrtfparams->DelayStep[1]; + + hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f; + hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f; + Offset++; + + ApplyCoeffsStep(Offset, hrtfstate->Values, IrSize, Coeffs, hrtfparams->CoeffStep, left, right); + OutBuffer[FrontLeft][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][0]; + OutBuffer[FrontRight][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][1]; + OutPos++; + } + + Delay[0] >>= HRTFDELAY_BITS; + Delay[1] >>= HRTFDELAY_BITS; + for(;pos < BufferSize;pos++) + { + hrtfstate->History[Offset&SRC_HISTORY_MASK] = data[pos]; + left = hrtfstate->History[(Offset-Delay[0])&SRC_HISTORY_MASK]; + right = hrtfstate->History[(Offset-Delay[1])&SRC_HISTORY_MASK]; + + hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f; + hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f; + Offset++; + + ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right); + OutBuffer[FrontLeft][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][0]; + OutBuffer[FrontRight][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][1]; + + OutPos++; + } +} + + +#undef MixHrtf + +#undef MERGE +#undef REAL_MERGE diff --git a/jni/openal-soft-1.16.0/Alc/mixer_neon.c b/jni/openal-soft-1.16.0/Alc/mixer_neon.c new file mode 100644 index 00000000..7b6da2b9 --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/mixer_neon.c @@ -0,0 +1,118 @@ +#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 SUFFIX Neon +#include "mixer_inc.c" +#undef SUFFIX + + +void MixDirect_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize) +{ + ALfloat gain, step; + float32x4_t gain4; + ALuint c; + + for(c = 0;c < OutChans;c++) + { + ALuint pos = 0; + gain = Gains[c].Current; + step = Gains[c].Step; + if(step != 1.0f && Counter > 0) + { + for(;pos < BufferSize && pos < Counter;pos++) + { + OutBuffer[c][OutPos+pos] += data[pos]*gain; + gain *= step; + } + if(pos == Counter) + gain = Gains[c].Target; + Gains[c].Current = gain; + /* Mix until pos is aligned with 4 or the mix is done. */ + for(;pos < BufferSize && (pos&3) != 0;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; + } + + if(!(gain > GAIN_SILENCE_THRESHOLD)) + continue; + gain4 = vdupq_n_f32(gain); + for(;BufferSize-pos > 3;pos += 4) + { + const float32x4_t val4 = vld1q_f32(&data[pos]); + float32x4_t dry4 = vld1q_f32(&OutBuffer[c][OutPos+pos]); + dry4 = vaddq_f32(dry4, vmulq_f32(val4, gain4)); + vst1q_f32(&OutBuffer[c][OutPos+pos], dry4); + } + for(;pos < BufferSize;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; + } +} diff --git a/jni/openal-soft-1.16.0/Alc/mixer_sse.c b/jni/openal-soft-1.16.0/Alc/mixer_sse.c new file mode 100644 index 00000000..970619ec --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/mixer_sse.c @@ -0,0 +1,202 @@ +#include "config.h" + +#ifdef IN_IDE_PARSER +/* KDevelop's parser won't recognize these defines that get added by the -msse + * switch used to compile this source. Without them, xmmintrin.h fails to + * declare anything. */ +#define __MMX__ +#define __SSE__ +#endif +#include + +#include "AL/al.h" +#include "AL/alc.h" +#include "alMain.h" +#include "alu.h" + +#include "alSource.h" +#include "alAuxEffectSlot.h" +#include "mixer_defs.h" + + +static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2], + const ALuint IrSize, + ALfloat (*restrict Coeffs)[2], + const ALfloat (*restrict CoeffStep)[2], + ALfloat left, ALfloat right) +{ + const __m128 lrlr = _mm_setr_ps(left, right, left, right); + __m128 coeffs, deltas, imp0, imp1; + __m128 vals = _mm_setzero_ps(); + ALuint i; + + if((Offset&1)) + { + const ALuint o0 = Offset&HRIR_MASK; + const ALuint o1 = (Offset+IrSize-1)&HRIR_MASK; + + coeffs = _mm_load_ps(&Coeffs[0][0]); + deltas = _mm_load_ps(&CoeffStep[0][0]); + vals = _mm_loadl_pi(vals, (__m64*)&Values[o0][0]); + imp0 = _mm_mul_ps(lrlr, coeffs); + coeffs = _mm_add_ps(coeffs, deltas); + vals = _mm_add_ps(imp0, vals); + _mm_store_ps(&Coeffs[0][0], coeffs); + _mm_storel_pi((__m64*)&Values[o0][0], vals); + for(i = 1;i < IrSize-1;i += 2) + { + const ALuint o2 = (Offset+i)&HRIR_MASK; + + coeffs = _mm_load_ps(&Coeffs[i+1][0]); + deltas = _mm_load_ps(&CoeffStep[i+1][0]); + vals = _mm_load_ps(&Values[o2][0]); + imp1 = _mm_mul_ps(lrlr, coeffs); + coeffs = _mm_add_ps(coeffs, deltas); + imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2)); + vals = _mm_add_ps(imp0, vals); + _mm_store_ps(&Coeffs[i+1][0], coeffs); + _mm_store_ps(&Values[o2][0], vals); + imp0 = imp1; + } + vals = _mm_loadl_pi(vals, (__m64*)&Values[o1][0]); + imp0 = _mm_movehl_ps(imp0, imp0); + vals = _mm_add_ps(imp0, vals); + _mm_storel_pi((__m64*)&Values[o1][0], vals); + } + else + { + for(i = 0;i < IrSize;i += 2) + { + const ALuint o = (Offset + i)&HRIR_MASK; + + coeffs = _mm_load_ps(&Coeffs[i][0]); + deltas = _mm_load_ps(&CoeffStep[i][0]); + vals = _mm_load_ps(&Values[o][0]); + imp0 = _mm_mul_ps(lrlr, coeffs); + coeffs = _mm_add_ps(coeffs, deltas); + vals = _mm_add_ps(imp0, vals); + _mm_store_ps(&Coeffs[i][0], coeffs); + _mm_store_ps(&Values[o][0], vals); + } + } +} + +static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2], + const ALuint IrSize, + ALfloat (*restrict Coeffs)[2], + ALfloat left, ALfloat right) +{ + const __m128 lrlr = _mm_setr_ps(left, right, left, right); + __m128 vals = _mm_setzero_ps(); + __m128 coeffs; + ALuint i; + + if((Offset&1)) + { + const ALuint o0 = Offset&HRIR_MASK; + const ALuint o1 = (Offset+IrSize-1)&HRIR_MASK; + __m128 imp0, imp1; + + coeffs = _mm_load_ps(&Coeffs[0][0]); + vals = _mm_loadl_pi(vals, (__m64*)&Values[o0][0]); + imp0 = _mm_mul_ps(lrlr, coeffs); + vals = _mm_add_ps(imp0, vals); + _mm_storel_pi((__m64*)&Values[o0][0], vals); + for(i = 1;i < IrSize-1;i += 2) + { + const ALuint o2 = (Offset+i)&HRIR_MASK; + + coeffs = _mm_load_ps(&Coeffs[i+1][0]); + vals = _mm_load_ps(&Values[o2][0]); + imp1 = _mm_mul_ps(lrlr, coeffs); + imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2)); + vals = _mm_add_ps(imp0, vals); + _mm_store_ps(&Values[o2][0], vals); + imp0 = imp1; + } + vals = _mm_loadl_pi(vals, (__m64*)&Values[o1][0]); + imp0 = _mm_movehl_ps(imp0, imp0); + vals = _mm_add_ps(imp0, vals); + _mm_storel_pi((__m64*)&Values[o1][0], vals); + } + else + { + for(i = 0;i < IrSize;i += 2) + { + const ALuint o = (Offset + i)&HRIR_MASK; + + coeffs = _mm_load_ps(&Coeffs[i][0]); + vals = _mm_load_ps(&Values[o][0]); + vals = _mm_add_ps(vals, _mm_mul_ps(lrlr, coeffs)); + _mm_store_ps(&Values[o][0], vals); + } + } +} + +#define SUFFIX SSE +#include "mixer_inc.c" +#undef SUFFIX + + +void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE], + MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize) +{ + ALfloat gain, step; + __m128 gain4, step4; + ALuint c; + + for(c = 0;c < OutChans;c++) + { + ALuint pos = 0; + gain = Gains[c].Current; + step = Gains[c].Step; + if(step != 1.0f && Counter > 0) + { + /* Mix with applying gain steps in aligned multiples of 4. */ + if(BufferSize-pos > 3 && Counter-pos > 3) + { + gain4 = _mm_setr_ps( + gain, + gain * step, + gain * step * step, + gain * step * step * step + ); + step4 = _mm_set1_ps(step * step * step * step); + do { + const __m128 val4 = _mm_load_ps(&data[pos]); + __m128 dry4 = _mm_load_ps(&OutBuffer[c][OutPos+pos]); + dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4)); + gain4 = _mm_mul_ps(gain4, step4); + _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4); + pos += 4; + } while(BufferSize-pos > 3 && Counter-pos > 3); + gain = _mm_cvtss_f32(gain4); + } + /* Mix with applying left over gain steps that aren't aligned multiples of 4. */ + for(;pos < BufferSize && pos < Counter;pos++) + { + OutBuffer[c][OutPos+pos] += data[pos]*gain; + gain *= step; + } + if(pos == Counter) + gain = Gains[c].Target; + Gains[c].Current = gain; + /* Mix until pos is aligned with 4 or the mix is done. */ + for(;pos < BufferSize && (pos&3) != 0;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; + } + + if(!(gain > GAIN_SILENCE_THRESHOLD)) + continue; + gain4 = _mm_set1_ps(gain); + for(;BufferSize-pos > 3;pos += 4) + { + const __m128 val4 = _mm_load_ps(&data[pos]); + __m128 dry4 = _mm_load_ps(&OutBuffer[c][OutPos+pos]); + dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4)); + _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4); + } + for(;pos < BufferSize;pos++) + OutBuffer[c][OutPos+pos] += data[pos]*gain; + } +} diff --git a/jni/openal-soft-1.16.0/Alc/mixer_sse2.c b/jni/openal-soft-1.16.0/Alc/mixer_sse2.c new file mode 100644 index 00000000..7670add3 --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/mixer_sse2.c @@ -0,0 +1,78 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2014 by Timothy Arceri . + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include + +#include "alu.h" +#include "mixer_defs.h" + + +const ALfloat *Resample_lerp32_SSE2(const ALfloat *src, ALuint frac, ALuint increment, + ALfloat *restrict dst, ALuint numsamples) +{ + const __m128i increment4 = _mm_set1_epi32(increment*4); + const __m128 fracOne4 = _mm_set1_ps(1.0f/FRACTIONONE); + const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK); + alignas(16) union { ALuint i[4]; float f[4]; } pos_; + alignas(16) union { ALuint i[4]; float f[4]; } frac_; + __m128i frac4, pos4; + ALuint pos; + ALuint i; + + InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4); + + frac4 = _mm_castps_si128(_mm_load_ps(frac_.f)); + pos4 = _mm_castps_si128(_mm_load_ps(pos_.f)); + + for(i = 0;numsamples-i > 3;i += 4) + { + const __m128 val1 = _mm_setr_ps(src[pos_.i[0]], src[pos_.i[1]], src[pos_.i[2]], src[pos_.i[3]]); + const __m128 val2 = _mm_setr_ps(src[pos_.i[0]+1], src[pos_.i[1]+1], src[pos_.i[2]+1], src[pos_.i[3]+1]); + + /* val1 + (val2-val1)*mu */ + const __m128 r0 = _mm_sub_ps(val2, val1); + const __m128 mu = _mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4); + const __m128 out = _mm_add_ps(val1, _mm_mul_ps(mu, r0)); + + _mm_store_ps(&dst[i], out); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS)); + frac4 = _mm_and_si128(frac4, fracMask4); + + _mm_store_ps(pos_.f, _mm_castsi128_ps(pos4)); + } + + pos = pos_.i[0]; + frac = _mm_cvtsi128_si32(frac4); + + for(;i < numsamples;i++) + { + dst[i] = lerp(src[pos], src[pos+1], frac * (1.0f/FRACTIONONE)); + + frac += increment; + pos += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} diff --git a/jni/openal-soft-1.16.0/Alc/mixer_sse41.c b/jni/openal-soft-1.16.0/Alc/mixer_sse41.c new file mode 100644 index 00000000..8ce8cd90 --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/mixer_sse41.c @@ -0,0 +1,82 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2014 by Timothy Arceri . + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#include +#include + +#include "alu.h" +#include "mixer_defs.h" + + +const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint increment, + ALfloat *restrict dst, ALuint numsamples) +{ + const __m128i increment4 = _mm_set1_epi32(increment*4); + const __m128 fracOne4 = _mm_set1_ps(1.0f/FRACTIONONE); + const __m128i fracMask4 = _mm_set1_epi32(FRACTIONMASK); + alignas(16) union { ALuint i[4]; float f[4]; } pos_; + alignas(16) union { ALuint i[4]; float f[4]; } frac_; + __m128i frac4, pos4; + ALuint pos; + ALuint i; + + InitiatePositionArrays(frac, increment, frac_.i, pos_.i, 4); + + frac4 = _mm_castps_si128(_mm_load_ps(frac_.f)); + pos4 = _mm_castps_si128(_mm_load_ps(pos_.f)); + + for(i = 0;numsamples-i > 3;i += 4) + { + const __m128 val1 = _mm_setr_ps(src[pos_.i[0]], src[pos_.i[1]], src[pos_.i[2]], src[pos_.i[3]]); + const __m128 val2 = _mm_setr_ps(src[pos_.i[0]+1], src[pos_.i[1]+1], src[pos_.i[2]+1], src[pos_.i[3]+1]); + + /* val1 + (val2-val1)*mu */ + const __m128 r0 = _mm_sub_ps(val2, val1); + const __m128 mu = _mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4); + const __m128 out = _mm_add_ps(val1, _mm_mul_ps(mu, r0)); + + _mm_store_ps(&dst[i], out); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, FRACTIONBITS)); + frac4 = _mm_and_si128(frac4, fracMask4); + + pos_.i[0] = _mm_extract_epi32(pos4, 0); + pos_.i[1] = _mm_extract_epi32(pos4, 1); + pos_.i[2] = _mm_extract_epi32(pos4, 2); + pos_.i[3] = _mm_extract_epi32(pos4, 3); + } + + pos = pos_.i[0]; + frac = _mm_cvtsi128_si32(frac4); + + for(;i < numsamples;i++) + { + dst[i] = lerp(src[pos], src[pos+1], frac * (1.0f/FRACTIONONE)); + + frac += increment; + pos += frac>>FRACTIONBITS; + frac &= FRACTIONMASK; + } + return dst; +} diff --git a/jni/openal-soft-android/Alc/panning.c b/jni/openal-soft-1.16.0/Alc/panning.c similarity index 100% rename from jni/openal-soft-android/Alc/panning.c rename to jni/openal-soft-1.16.0/Alc/panning.c diff --git a/jni/openal-soft-1.16.0/Alc/vector.h b/jni/openal-soft-1.16.0/Alc/vector.h new file mode 100644 index 00000000..9f28d0db --- /dev/null +++ b/jni/openal-soft-1.16.0/Alc/vector.h @@ -0,0 +1,87 @@ +#ifndef AL_VECTOR_H +#define AL_VECTOR_H + +#include + +#include + +/* "Base" vector type, designed to alias with the actual vector types. */ +typedef struct vector__s { + ALsizei Capacity; + ALsizei Size; +} *vector_; + +#define TYPEDEF_VECTOR(T, N) typedef struct { \ + ALsizei Capacity; \ + ALsizei Size; \ + T Data[]; \ +} _##N; \ +typedef _##N* N; \ +typedef const _##N* const_##N; + +#define VECTOR(T) struct { \ + ALsizei Capacity; \ + ALsizei Size; \ + T Data[]; \ +}* + +#define VECTOR_INIT(_x) do { (_x) = NULL; } while(0) +#define VECTOR_INIT_STATIC() NULL +#define VECTOR_DEINIT(_x) do { free((_x)); (_x) = NULL; } while(0) + +/* Helper to increase a vector's reserve. Do not call directly. */ +ALboolean vector_reserve(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count, ALboolean exact); +#define VECTOR_RESERVE(_x, _c) (vector_reserve((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_c), AL_TRUE)) + +ALboolean vector_resize(char *ptr, size_t base_size, size_t obj_size, ALsizei obj_count); +#define VECTOR_RESIZE(_x, _c) (vector_resize((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_c))) + +#define VECTOR_CAPACITY(_x) ((_x) ? (_x)->Capacity : 0) +#define VECTOR_SIZE(_x) ((_x) ? (_x)->Size : 0) + +#define VECTOR_ITER_BEGIN(_x) ((_x) ? (_x)->Data + 0 : NULL) +#define VECTOR_ITER_END(_x) ((_x) ? (_x)->Data + (_x)->Size : NULL) + +ALboolean vector_insert(char *ptr, size_t base_size, size_t obj_size, void *ins_pos, const void *datstart, const void *datend); +#ifdef __GNUC__ +#define TYPE_CHECK(T1, T2) __builtin_types_compatible_p(T1, T2) +#define VECTOR_INSERT(_x, _i, _s, _e) __extension__({ \ + ALboolean _r; \ + static_assert(TYPE_CHECK(__typeof((_x)->Data[0]), __typeof(*(_i))), "Incompatible insertion iterator"); \ + static_assert(TYPE_CHECK(__typeof((_x)->Data[0]), __typeof(*(_s))), "Incompatible insertion source type"); \ + static_assert(TYPE_CHECK(__typeof(*(_s)), __typeof(*(_e))), "Incompatible iterator sources"); \ + _r = vector_insert((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_i), (_s), (_e)); \ + _r; \ +}) +#else +#define VECTOR_INSERT(_x, _i, _s, _e) (vector_insert((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), (_i), (_s), (_e))) +#endif + +#define VECTOR_PUSH_BACK(_x, _obj) (vector_reserve((char*)&(_x), sizeof(*(_x)), sizeof((_x)->Data[0]), VECTOR_SIZE(_x)+1, AL_FALSE) && \ + (((_x)->Data[(_x)->Size++] = (_obj)),AL_TRUE)) +#define VECTOR_POP_BACK(_x) ((void)((_x)->Size--)) + +#define VECTOR_BACK(_x) ((_x)->Data[(_x)->Size-1]) +#define VECTOR_FRONT(_x) ((_x)->Data[0]) + +#define VECTOR_ELEM(_x, _o) ((_x)->Data[(_o)]) + +#define VECTOR_FOR_EACH(_t, _x, _f) do { \ + _t *_iter = VECTOR_ITER_BEGIN((_x)); \ + _t *_end = VECTOR_ITER_END((_x)); \ + for(;_iter != _end;++_iter) \ + _f(_iter); \ +} while(0) + +#define VECTOR_FIND_IF(_i, _t, _x, _f) do { \ + _t *_iter = VECTOR_ITER_BEGIN((_x)); \ + _t *_end = VECTOR_ITER_END((_x)); \ + for(;_iter != _end;++_iter) \ + { \ + if(_f(_iter)) \ + break; \ + } \ + (_i) = _iter; \ +} while(0) + +#endif /* AL_VECTOR_H */ diff --git a/jni/openal-soft-android/Android.mk b/jni/openal-soft-1.16.0/Android.mk similarity index 76% rename from jni/openal-soft-android/Android.mk rename to jni/openal-soft-1.16.0/Android.mk index 9b2400a9..85750dd0 100644 --- a/jni/openal-soft-android/Android.mk +++ b/jni/openal-soft-1.16.0/Android.mk @@ -4,7 +4,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := libopenal -LOCAL_CFLAGS := -DAL_ALEXT_PROTOTYPES -DAL_BUILD_LIBRARY -DAL_LIBTYPE_STATIC -D_GNU_SOURCE=1 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -std=c99 -Drestrict=__restrict +LOCAL_CFLAGS := -DAL_ALEXT_PROTOTYPES -DAL_BUILD_LIBRARY -D_GNU_SOURCE=1 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -std=c99 -Drestrict=__restrict LOCAL_CPPFLAGS := ${LOCAL_CFLAGS} @@ -18,12 +18,15 @@ LOCAL_SRC_FILES := \ Alc/mixer_neon.c \ Alc/mixer_inc.c \ Alc/mixer_sse.c \ + Alc/mixer_sse2.c \ + Alc/mixer_sse41.c \ , $(subst $(LOCAL_PATH)/,,\ ${LOCAL_PATH}/Alc/backends/base.c \ ${LOCAL_PATH}/Alc/backends/loopback.c \ ${LOCAL_PATH}/Alc/backends/null.c \ ${LOCAL_PATH}/Alc/backends/opensl.c \ ${LOCAL_PATH}/Alc/backends/wave.c \ + $(wildcard ${LOCAL_PATH}/common/*.c) \ $(wildcard ${LOCAL_PATH}/Alc/midi/*.c) \ $(wildcard ${LOCAL_PATH}/Alc/effects/*.c) \ $(wildcard ${LOCAL_PATH}/Alc/*.c) \ diff --git a/jni/openal-soft-android/CMakeLists.txt b/jni/openal-soft-1.16.0/CMakeLists.txt similarity index 58% rename from jni/openal-soft-android/CMakeLists.txt rename to jni/openal-soft-1.16.0/CMakeLists.txt index ff746764..0087edb2 100644 --- a/jni/openal-soft-android/CMakeLists.txt +++ b/jni/openal-soft-1.16.0/CMakeLists.txt @@ -20,56 +20,12 @@ INCLUDE(CheckSymbolExists) INCLUDE(CheckCCompilerFlag) INCLUDE(CheckCSourceCompiles) INCLUDE(CheckTypeSize) +include(CheckFileOffsetBits) SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) -OPTION(ALSOFT_CPUEXT_SSE "Check for SSE/SSE2 support" ON) -OPTION(ALSOFT_CPUEXT_NEON "Check for ARM Neon support" ON) - -OPTION(ALSOFT_REQUIRE_SSE "Require SSE/SSE2 support" OFF) -OPTION(ALSOFT_REQUIRE_NEON "Require ARM Neon support" OFF) - -IF(WIN32) - # 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) -ENDIF() - - -OPTION(ALSOFT_BACKEND_ALSA "Check for ALSA backend" ON) -OPTION(ALSOFT_BACKEND_OSS "Check for OSS backend" ON) -OPTION(ALSOFT_BACKEND_SOLARIS "Check for Solaris backend" ON) -OPTION(ALSOFT_BACKEND_SNDIO "Check for SndIO backend" ON) -OPTION(ALSOFT_BACKEND_QSA "Check for QSA backend" ON) -OPTION(ALSOFT_BACKEND_MMDEVAPI "Check for MMDevApi backend" ON) -OPTION(ALSOFT_BACKEND_DSOUND "Check for DirectSound backend" ON) -OPTION(ALSOFT_BACKEND_WINMM "Check for Windows Multimedia backend" ON) -OPTION(ALSOFT_BACKEND_PORTAUDIO "Check for PortAudio backend" ON) -OPTION(ALSOFT_BACKEND_PULSEAUDIO "Check for PulseAudio backend" ON) -OPTION(ALSOFT_BACKEND_COREAUDIO "Check for CoreAudio backend" ON) -OPTION(ALSOFT_BACKEND_OPENSL "Check for OpenSL backend" ON) -OPTION(ALSOFT_BACKEND_WAVE "Enable Wave Writer backend" ON) - -OPTION(ALSOFT_MIDI_FLUIDSYNTH "Check for FluidSynth MIDI" ON) - -OPTION(ALSOFT_REQUIRE_ALSA "Require ALSA backend" OFF) -OPTION(ALSOFT_REQUIRE_OSS "Require OSS backend" OFF) -OPTION(ALSOFT_REQUIRE_SOLARIS "Require Solaris backend" OFF) -OPTION(ALSOFT_REQUIRE_SNDIO "Require SndIO backend" OFF) -OPTION(ALSOFT_REQUIRE_QSA "Require QSA backend" OFF) -OPTION(ALSOFT_REQUIRE_MMDEVAPI "Require MMDevApi" OFF) -OPTION(ALSOFT_REQUIRE_DSOUND "Require DirectSound backend" OFF) -OPTION(ALSOFT_REQUIRE_WINMM "Require Windows Multimedia backend" OFF) -OPTION(ALSOFT_REQUIRE_PORTAUDIO "Require PortAudio backend" OFF) -OPTION(ALSOFT_REQUIRE_PULSEAUDIO "Require PulseAudio backend" OFF) -OPTION(ALSOFT_REQUIRE_COREAUDIO "Require CoreAudio backend" OFF) -OPTION(ALSOFT_REQUIRE_OPENSL "Require OpenSL backend" OFF) - -OPTION(ALSOFT_REQUIRE_FLUIDSYNTH "Require FluidSynth MIDI" OFF) - OPTION(ALSOFT_DLOPEN "Check for the dlopen API for loading optional libs" ON) OPTION(ALSOFT_WERROR "Treat compile warnings as errors" OFF) @@ -80,15 +36,46 @@ OPTION(ALSOFT_NO_CONFIG_UTIL "Disable building the alsoft-config utility" OFF) OPTION(ALSOFT_EXAMPLES "Build and install example programs" ON) OPTION(ALSOFT_CONFIG "Install alsoft.conf sample configuration file" ON) +OPTION(ALSOFT_HRTF_DEFS "Install HRTF definition files" ON) IF(WIN32) SET(LIBNAME OpenAL32) - ADD_DEFINITIONS("-D_WIN32 -D_WIN32_WINNT=0x0501") + 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() ELSE() SET(LIBNAME openal) + + # These are needed on non-Windows systems for extra features + ADD_DEFINITIONS(-D_GNU_SOURCE=1 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700) + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_GNU_SOURCE=1 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700") 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") + + # 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") @@ -100,8 +87,8 @@ IF(NOT LIBTYPE) ENDIF() SET(LIB_MAJOR_VERSION "1") -SET(LIB_MINOR_VERSION "15") -SET(LIB_REVISION "1") +SET(LIB_MINOR_VERSION "16") +SET(LIB_REVISION "0") SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}") SET(EXPORT_DECL "") @@ -124,19 +111,8 @@ IF(MSVC) CHECK_C_SOURCE_COMPILES("int *restrict foo; int main() {return 0;}" HAVE_RESTRICT) IF(NOT HAVE_RESTRICT) - # Slightly convoluted way to do this, because MSVC may barf if restrict is - # defined to __restrict. - CHECK_C_SOURCE_COMPILES("#define restrict __restrict - #include - int *restrict foo; - int main() {return 0;}" HAVE___RESTRICT) - IF(HAVE___RESTRICT) - ADD_DEFINITIONS(-Drestrict=__restrict) - SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Drestrict=__restrict") - ELSE() - ADD_DEFINITIONS("-Drestrict=") - SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Drestrict=") - ENDIF() + ADD_DEFINITIONS("-Drestrict=") + SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -Drestrict=") ENDIF() CHECK_C_SOURCE_COMPILES("inline void foo(void) { } @@ -169,6 +145,54 @@ IF(CMAKE_COMPILER_IS_GNUCC) SET(CMAKE_REQUIRED_FLAGS "${OLD_REQUIRED_FLAGS}") ENDIF() +# 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 + int _Atomic foo; + int main() + { + 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") @@ -232,6 +256,15 @@ ELSE() ADD_DEFINITIONS(-Werror) ENDIF() + # Force enable PIC if available. The static common library will be linked + # into the dynamic openal library, which requires all its code to be + # position-independent, and CMake doesn't automatically enable PIC for + # static library targets (Windows code is always position-independent). + CHECK_C_COMPILER_FLAG(-fPIC HAVE_FPIC_SWITCH) + IF(HAVE_FPIC_SWITCH AND NOT WIN32) + ADD_DEFINITIONS(-fPIC) + ENDIF() + SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -D_DEBUG" CACHE STRING "Flags used by the compiler during Release with Debug Info builds." FORCE) @@ -275,14 +308,9 @@ ELSE() ENDIF() IF(HAVE_GCC_PROTECTED_VISIBILITY OR HAVE_GCC_DEFAULT_VISIBILITY) - CHECK_C_COMPILER_FLAG(-fvisibility=internal HAVE_VISIBILITY_INTERNAL_SWITCH) - IF(HAVE_VISIBILITY_INTERNAL_SWITCH) - ADD_DEFINITIONS(-fvisibility=internal) - ELSE() - CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN_SWITCH) - IF(HAVE_VISIBILITY_HIDDEN_SWITCH) - ADD_DEFINITIONS(-fvisibility=hidden) - ENDIF() + CHECK_C_COMPILER_FLAG(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN_SWITCH) + IF(HAVE_VISIBILITY_HIDDEN_SWITCH) + ADD_DEFINITIONS(-fvisibility=hidden) ENDIF() ENDIF() @@ -296,25 +324,34 @@ ELSE() ENDIF() SET(SSE_SWITCH "") -IF(MSVC) - CHECK_C_COMPILER_FLAG(/arch:SSE HAVE_ARCHSSE_SWITCH) - IF(HAVE_ARCHSSE_SWITCH) - SET(SSE_SWITCH "/arch:SSE") - ENDIF() -ENDIF() -IF(NOT SSE_SWITCH) +SET(SSE2_SWITCH "") +SET(SSE4_1_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(-msse4.1 HAVE_MSSE4_1_SWITCH) + IF(HAVE_MSSE4_1_SWITCH) + SET(SSE4_1_SWITCH "-msse4.1") + 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(ftw.h HAVE_FTW_H) +CHECK_INCLUDE_FILE(io.h HAVE_IO_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) @@ -324,6 +361,25 @@ IF(NOT HAVE_GUIDDEF_H) CHECK_INCLUDE_FILE(initguid.h HAVE_INITGUID_H) ENDIF() +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() + # Some systems need libm for some of the following math functions to work CHECK_LIBRARY_EXISTS(m pow "" HAVE_LIBM) IF(HAVE_LIBM) @@ -336,11 +392,23 @@ 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) +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() +IF(HAVE_FTW_H) + CHECK_SYMBOL_EXISTS(ftw ftw.h HAVE_FTW) +ENDIF() +IF(HAVE_IO_H) + CHECK_SYMBOL_EXISTS(_wfindfirst io.h HAVE__WFINDFIRST) +ENDIF() CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF) CHECK_FUNCTION_EXISTS(stat HAVE_STAT) @@ -411,12 +479,8 @@ IF(ALSOFT_DLOPEN) ENDIF() # Check if we have Windows headers -CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0501) +CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0502) IF(NOT HAVE_WINDOWS_H) - # These are needed on some systems for extra features - ADD_DEFINITIONS(-D_GNU_SOURCE=1 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700) - SET(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_GNU_SOURCE=1 -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700") - CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY) IF(NOT HAVE_GETTIMEOFDAY) MESSAGE(FATAL_ERROR "No timing function found!") @@ -453,6 +517,11 @@ IF(NOT HAVE_WINDOWS_H) IF(NOT HAVE_PTHREAD_SETNAME_NP) CHECK_SYMBOL_EXISTS(pthread_set_name_np pthread.h HAVE_PTHREAD_SET_NAME_NP) ENDIF() + IF(HAVE_PTHREAD_NP_H) + CHECK_SYMBOL_EXISTS(pthread_mutexattr_setkind_np "pthread.h;pthread_np.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) @@ -464,7 +533,7 @@ ENDIF() CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H) IF(NOT HAVE_STDINT_H) IF(HAVE_WINDOWS_H) - CHECK_C_SOURCE_COMPILES("#define _WIN32_WINNT 0x0501 + CHECK_C_SOURCE_COMPILES("#define _WIN32_WINNT 0x0502 #include __int64 foo; int main() {return 0;}" HAVE___INT64) @@ -478,14 +547,12 @@ IF(NOT HAVE_STDINT_H) ENDIF() ENDIF() -# Windows needs winmm for timeGetTime, even if the backend is disabled -CHECK_SHARED_FUNCTION_EXISTS(timeGetTime "windows.h;mmsystem.h" winmm "" HAVE_LIBWINMM) -IF(HAVE_LIBWINMM) - SET(EXTRA_LIBS winmm ${EXTRA_LIBS}) - SET(PKG_CONFIG_LIBS ${PKG_CONFIG_LIBS} -lwinmm) -ENDIF() - +SET(COMMON_OBJS common/atomic.c + common/rwlock.c + common/threads.c + common/uintmap.c +) SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c OpenAL32/alBuffer.c OpenAL32/alEffect.c @@ -500,6 +567,7 @@ SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c OpenAL32/alSource.c OpenAL32/alState.c OpenAL32/alThunk.c + OpenAL32/sample_cvt.c ) SET(ALC_OBJS Alc/ALc.c Alc/ALu.c @@ -520,80 +588,19 @@ SET(ALC_OBJS Alc/ALc.c Alc/helpers.c Alc/hrtf.c Alc/panning.c - Alc/threads.c Alc/mixer.c Alc/mixer_c.c ) SET(CPU_EXTS "Default") -SET(HAVE_SSE 0) -SET(HAVE_NEON 0) +SET(HAVE_SSE 0) +SET(HAVE_SSE2 0) +SET(HAVE_SSE4_1 0) +SET(HAVE_NEON 0) -# Check for SSE support -IF(ALSOFT_CPUEXT_SSE AND ALIGN_DECL) - CHECK_INCLUDE_FILE(xmmintrin.h HAVE_XMMINTRIN_H "${SSE_SWITCH}") - IF(HAVE_XMMINTRIN_H) - 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() -IF(ALSOFT_REQUIRE_SSE AND NOT HAVE_SSE) - MESSAGE(FATAL_ERROR "Failed to enabled required SSE CPU extensions") -ENDIF() +SET(HAVE_FLUIDSYNTH 0) -# Check for ARM Neon support -IF(ALSOFT_CPUEXT_NEON) - CHECK_INCLUDE_FILE(arm_neon.h HAVE_ARM_NEON_H) - IF(HAVE_ARM_NEON_H) - SET(HAVE_NEON 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/mixer_neon.c) - 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() - - -SET(ALC_OBJS ${ALC_OBJS} - Alc/midi/base.c - Alc/midi/sf2load.c - Alc/midi/dummy.c - Alc/midi/fluidsynth.c -) - -SET(HAVE_FLUIDSYNTH 0) - -# Check for FluidSynth support -IF(ALSOFT_MIDI_FLUIDSYNTH) - FIND_PACKAGE(FluidSynth) - IF(FLUIDSYNTH_FOUND) - SET(HAVE_FLUIDSYNTH 1) - IF(CMAKE_VERSION VERSION_LESS "2.8.8") - INCLUDE_DIRECTORIES(${FLUIDSYNTH_INCLUDE_DIR}) - ENDIF() - SET(EXTRA_LIBS ${FLUIDSYNTH_LIBRARIES} ${EXTRA_LIBS}) - ENDIF() -ENDIF() -IF(ALSOFT_REQUIRE_FLUIDSYNTH AND NOT HAVE_FLUIDSYNTH) - MESSAGE(FATAL_ERROR "Failed to enabled required FluidSynth support") -ENDIF() - - -SET(ALC_OBJS ${ALC_OBJS} - Alc/backends/base.c - # Default backends, always available - Alc/backends/loopback.c - Alc/backends/null.c -) - -SET(BACKENDS "") SET(HAVE_ALSA 0) SET(HAVE_OSS 0) SET(HAVE_SOLARIS 0) @@ -608,20 +615,140 @@ SET(HAVE_COREAUDIO 0) SET(HAVE_OPENSL 0) SET(HAVE_WAVE 0) -# Check ALSA backend -IF(ALSOFT_BACKEND_ALSA) - CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ALSA_ASOUNDLIB_H) - IF(HAVE_ALSA_ASOUNDLIB_H) - CHECK_SHARED_FUNCTION_EXISTS(snd_pcm_open "alsa/asoundlib.h" asound "" HAVE_LIBASOUND) - IF(HAVE_LIBASOUND OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_ALSA 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/alsa.c) - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} ALSA,") - ELSE() - SET(BACKENDS "${BACKENDS} ALSA \(linked\),") - SET(EXTRA_LIBS asound ${EXTRA_LIBS}) +# 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_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) + 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(ALC_OBJS ${ALC_OBJS} + Alc/midi/base.c + Alc/midi/sf2load.c + Alc/midi/dummy.c + Alc/midi/fluidsynth.c + Alc/midi/soft.c +) + +# Check for FluidSynth support +OPTION(ALSOFT_REQUIRE_FLUIDSYNTH "Require FluidSynth MIDI" OFF) +FIND_PACKAGE(FluidSynth) +IF(FLUIDSYNTH_FOUND) + OPTION(ALSOFT_MIDI_FLUIDSYNTH "Enable FluidSynth MIDI" ON) + IF(ALSOFT_MIDI_FLUIDSYNTH) + SET(HAVE_FLUIDSYNTH 1) + ADD_BACKEND_LIBS(${FLUIDSYNTH_LIBRARIES}) + IF(CMAKE_VERSION VERSION_LESS "2.8.8") + INCLUDE_DIRECTORIES(${FLUIDSYNTH_INCLUDE_DIR}) + ENDIF() + ENDIF() +ENDIF() +IF(ALSOFT_REQUIRE_FLUIDSYNTH AND NOT HAVE_FLUIDSYNTH) + MESSAGE(FATAL_ERROR "Failed to enabled required FluidSynth support") +ENDIF() + + +SET(BACKENDS "") +SET(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() @@ -630,12 +757,17 @@ IF(ALSOFT_REQUIRE_ALSA AND NOT HAVE_ALSA) ENDIF() # Check OSS backend -IF(ALSOFT_BACKEND_OSS) - CHECK_INCLUDE_FILE(sys/soundcard.h HAVE_SYS_SOUNDCARD_H) - IF(HAVE_SYS_SOUNDCARD_H) +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(ALC_OBJS ${ALC_OBJS} Alc/backends/oss.c) 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) @@ -643,12 +775,17 @@ IF(ALSOFT_REQUIRE_OSS AND NOT HAVE_OSS) ENDIF() # Check Solaris backend -IF(ALSOFT_BACKEND_SOLARIS) - CHECK_INCLUDE_FILE(sys/audioio.h HAVE_SYS_AUDIOIO_H) - IF(HAVE_SYS_AUDIOIO_H) +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(ALC_OBJS ${ALC_OBJS} Alc/backends/solaris.c) 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) @@ -656,15 +793,17 @@ IF(ALSOFT_REQUIRE_SOLARIS AND NOT HAVE_SOLARIS) ENDIF() # Check SndIO backend -IF(ALSOFT_BACKEND_SNDIO) - CHECK_INCLUDE_FILE(sndio.h HAVE_SNDIO_H) - IF(HAVE_SNDIO_H) - CHECK_SHARED_FUNCTION_EXISTS(sio_open "sndio.h" sndio "" HAVE_LIBSNDIO) - IF(HAVE_LIBSNDIO) - SET(HAVE_SNDIO 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/sndio.c) - SET(BACKENDS "${BACKENDS} SndIO \(linked\),") - SET(EXTRA_LIBS sndio ${EXTRA_LIBS}) +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() @@ -673,15 +812,17 @@ IF(ALSOFT_REQUIRE_SNDIO AND NOT HAVE_SNDIO) ENDIF() # Check QSA backend -IF (ALSOFT_BACKEND_QSA AND "${CMAKE_C_PLATFORM_ID}" STREQUAL "QNX") - CHECK_INCLUDE_FILE(sys/asoundlib.h HAVE_SYS_ASOUNDLIB_H) - IF(HAVE_SYS_ASOUNDLIB_H) - CHECK_SHARED_FUNCTION_EXISTS(snd_pcm_open "sys/asoundlib.h" asound "" HAVE_LIBASOUND) - IF(HAVE_LIBASOUND) - SET(HAVE_QSA 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/qsa.c) - SET(EXTRA_LIBS asound ${EXTRA_LIBS}) - SET(BACKENDS "${BACKENDS} QSA \(linked\),") +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() @@ -689,72 +830,74 @@ IF(ALSOFT_REQUIRE_QSA AND NOT HAVE_QSA) MESSAGE(FATAL_ERROR "Failed to enabled required QSA backend") ENDIF() -# Check for MMDevApi backend +# 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) - IF(ALSOFT_BACKEND_MMDEVAPI) - CHECK_INCLUDE_FILE(mmdeviceapi.h HAVE_MMDEVICEAPI_H) - IF(HAVE_MMDEVICEAPI_H) - SET(HAVE_MMDEVAPI 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/mmdevapi.c) - - SET(BACKENDS "${BACKENDS} MMDevApi,") - ENDIF() - ENDIF() -ENDIF() -IF(ALSOFT_REQUIRE_MMDEVAPI AND NOT HAVE_MMDEVAPI) - MESSAGE(FATAL_ERROR "Failed to enabled required MMDevApi backend") -ENDIF() - -# Check DSound/MMSystem backend -IF(ALSOFT_BACKEND_DSOUND) - CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H) - IF(HAVE_DSOUND_H) - CHECK_SHARED_FUNCTION_EXISTS(DirectSoundCreate "dsound.h" dsound "" HAVE_LIBDSOUND) - IF(HAVE_LIBDSOUND OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_DSOUND 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/dsound.c) - - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} DirectSound,") - ELSE() - SET(BACKENDS "${BACKENDS} DirectSound \(linked\),") - SET(EXTRA_LIBS dsound ${EXTRA_LIBS}) + # 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() -ENDIF() -IF(ALSOFT_REQUIRE_DSOUND AND NOT HAVE_DSOUND) - MESSAGE(FATAL_ERROR "Failed to enabled required DSound backend") -ENDIF() -IF(HAVE_WINDOWS_H) - IF(ALSOFT_BACKEND_WINMM) - CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0501) - IF(HAVE_MMSYSTEM_H AND HAVE_LIBWINMM) - SET(HAVE_WINMM 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/winmm.c) - SET(BACKENDS "${BACKENDS} WinMM,") + # 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 -IF(ALSOFT_BACKEND_PORTAUDIO) - CHECK_INCLUDE_FILE(portaudio.h HAVE_PORTAUDIO_H) - IF(HAVE_PORTAUDIO_H) - CHECK_SHARED_FUNCTION_EXISTS(Pa_Initialize "portaudio.h" portaudio "" HAVE_LIBPORTAUDIO) - IF(HAVE_LIBPORTAUDIO OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_PORTAUDIO 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/portaudio.c) - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} PortAudio,") - ELSE() - SET(BACKENDS "${BACKENDS} PortAudio \(linked\),") - SET(EXTRA_LIBS portaudio ${EXTRA_LIBS}) - ENDIF() +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() @@ -763,19 +906,17 @@ IF(ALSOFT_REQUIRE_PORTAUDIO AND NOT HAVE_PORTAUDIO) ENDIF() # Check PulseAudio backend -IF(ALSOFT_BACKEND_PULSEAUDIO) - CHECK_INCLUDE_FILE(pulse/pulseaudio.h HAVE_PULSE_PULSEAUDIO_H) - IF(HAVE_PULSE_PULSEAUDIO_H) - CHECK_SHARED_FUNCTION_EXISTS(pa_context_new "pulse/pulseaudio.h" pulse "" HAVE_LIBPULSE) - IF(HAVE_LIBPULSE OR HAVE_DLFCN_H OR WIN32) - SET(HAVE_PULSEAUDIO 1) - SET(ALC_OBJS ${ALC_OBJS} Alc/backends/pulseaudio.c) - IF(HAVE_DLFCN_H OR WIN32) - SET(BACKENDS "${BACKENDS} PulseAudio,") - ELSE() - SET(BACKENDS "${BACKENDS} PulseAudio \(linked\),") - SET(EXTRA_LIBS pulse ${EXTRA_LIBS}) - ENDIF() +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() @@ -784,13 +925,18 @@ IF(ALSOFT_REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO) ENDIF() # Check CoreAudio backend -IF(ALSOFT_BACKEND_COREAUDIO) - CHECK_INCLUDE_FILE(/System/Library/Frameworks/CoreAudio.framework/Headers/CoreAudio.h HAVE_COREAUDIO_FRAMEWORK) - IF(HAVE_COREAUDIO_FRAMEWORK) +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 /System/Library/Frameworks/CoreAudio.framework ${EXTRA_LIBS}) + 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}) @@ -812,11 +958,13 @@ IF(ALSOFT_REQUIRE_COREAUDIO AND NOT HAVE_COREAUDIO) ENDIF() # Check for OpenSL (Android) backend -IF(ALSOFT_BACKEND_OPENSL) - 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_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,") @@ -829,6 +977,7 @@ IF(ALSOFT_REQUIRE_OPENSL AND NOT HAVE_OPENSL) 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) @@ -842,11 +991,15 @@ IF(ALSOFT_UTILS AND NOT ALSOFT_NO_CONFIG_UTIL) add_subdirectory(utils/alsoft-config) ENDIF() IF(ALSOFT_EXAMPLES) - FIND_PACKAGE(SDL) - IF(SDL_FOUND) + FIND_PACKAGE(SDL2) + IF(SDL2_FOUND) FIND_PACKAGE(SDL_sound) IF(SDL_SOUND_FOUND AND CMAKE_VERSION VERSION_LESS "2.8.8") - INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR}) + 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() @@ -873,7 +1026,10 @@ CONFIGURE_FILE( "${OpenAL_BINARY_DIR}/openal.pc" @ONLY) -# Build a library +# Build a common library with reusable helpers +ADD_LIBRARY(common STATIC ${COMMON_OBJS}) + +# Build main library ADD_LIBRARY(${LIBNAME} ${LIBTYPE} ${OPENAL_OBJS} ${ALC_OBJS}) SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY COMPILE_DEFINITIONS AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES) IF(WIN32 AND ALSOFT_NO_UID_DEFS) @@ -883,13 +1039,59 @@ SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES "${OpenAL_SOU IF(FLUIDSYNTH_FOUND) SET_PROPERTY(TARGET ${LIBNAME} APPEND PROPERTY INCLUDE_DIRECTORIES ${FLUIDSYNTH_INCLUDE_DIR}) ENDIF() +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() 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} ${EXTRA_LIBS}) +TARGET_LINK_LIBRARIES(${LIBNAME} common ${EXTRA_LIBS}) # Add an install target here INSTALL(TARGETS ${LIBNAME} @@ -938,6 +1140,16 @@ IF(ALSOFT_CONFIG) MESSAGE(STATUS "") ENDIF() +# Install HRTF definitions +IF(ALSOFT_HRTF_DEFS) + INSTALL(FILES hrtf/default-44100.mhr + hrtf/default-48000.mhr + DESTINATION share/openal/hrtf + ) + MESSAGE(STATUS "Installing HRTF definitions") + MESSAGE(STATUS "") +ENDIF() + IF(ALSOFT_UTILS) ADD_EXECUTABLE(openal-info utils/openal-info.c) TARGET_LINK_LIBRARIES(openal-info ${LIBNAME}) @@ -961,26 +1173,30 @@ IF(ALSOFT_UTILS) ENDIF() IF(ALSOFT_EXAMPLES) - IF(SDL_FOUND AND SDL_SOUND_FOUND) + 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 INCLUDE_DIRECTORIES ${SDL_SOUND_INCLUDE_DIR}) + 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} ${LIBNAME}) - SET_PROPERTY(TARGET alstream APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL_SOUND_INCLUDE_DIR}) + TARGET_LINK_LIBRARIES(alstream ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} ${LIBNAME}) + 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} ${LIBNAME}) - SET_PROPERTY(TARGET alreverb APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL_SOUND_INCLUDE_DIR}) + TARGET_LINK_LIBRARIES(alreverb ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} ${LIBNAME}) + 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} ${LIBNAME}) - SET_PROPERTY(TARGET allatency APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL_SOUND_INCLUDE_DIR}) + TARGET_LINK_LIBRARIES(allatency ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} ${LIBNAME}) + 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} ${SDL_LIBRARY} ${LIBNAME}) - SET_PROPERTY(TARGET alloopback APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL_INCLUDE_DIR} + TARGET_LINK_LIBRARIES(alloopback ex-common ${SDL_SOUND_LIBRARIES} ${SDL2_LIBRARY} ${LIBNAME}) + SET_PROPERTY(TARGET alloopback APPEND PROPERTY INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR}) INSTALL(TARGETS alstream alreverb allatency alloopback @@ -989,7 +1205,45 @@ IF(ALSOFT_EXAMPLES) ARCHIVE DESTINATION "lib${LIB_SUFFIX}" ) - MESSAGE(STATUS "Building example programs") + 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 INCLUDE_DIRECTORIES ${SDL2_INCLUDE_DIR} + ${FFMPEG_INCLUDE_DIRS}) + + INSTALL(TARGETS alffplay + RUNTIME DESTINATION bin + LIBRARY DESTINATION "lib${LIB_SUFFIX}" + ARCHIVE DESTINATION "lib${LIB_SUFFIX}" + ) + MESSAGE(STATUS "Building SDL and FFmpeg example programs") + ELSE() + MESSAGE(STATUS "Building SDL example programs") + ENDIF() MESSAGE(STATUS "") ENDIF() ENDIF() diff --git a/jni/openal-soft-android/COPYING b/jni/openal-soft-1.16.0/COPYING similarity index 100% rename from jni/openal-soft-android/COPYING rename to jni/openal-soft-1.16.0/COPYING diff --git a/jni/openal-soft-android/OpenAL32/Include/alAuxEffectSlot.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alAuxEffectSlot.h similarity index 93% rename from jni/openal-soft-android/OpenAL32/Include/alAuxEffectSlot.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alAuxEffectSlot.h index c7182d9b..286aa95d 100644 --- a/jni/openal-soft-android/OpenAL32/Include/alAuxEffectSlot.h +++ b/jni/openal-soft-1.16.0/OpenAL32/Include/alAuxEffectSlot.h @@ -4,6 +4,8 @@ #include "alMain.h" #include "alEffect.h" +#include "align.h" + #ifdef __cplusplus extern "C" { #endif @@ -22,7 +24,7 @@ struct ALeffectStateVtable { void (*const update)(ALeffectState *state, ALCdevice *device, const struct ALeffectslot *slot); void (*const process)(ALeffectState *state, ALuint samplesToDo, const ALfloat *restrict samplesIn, ALfloat (*restrict samplesOut)[BUFFERSIZE]); - void (*const Delete)(struct ALeffectState *state); + void (*const Delete)(void *ptr); }; #define DEFINE_ALEFFECTSTATE_VTABLE(T) \ @@ -30,7 +32,8 @@ DECLARE_THUNK(T, ALeffectState, void, Destruct) \ DECLARE_THUNK1(T, ALeffectState, ALboolean, deviceUpdate, ALCdevice*) \ DECLARE_THUNK2(T, ALeffectState, void, update, ALCdevice*, const ALeffectslot*) \ DECLARE_THUNK3(T, ALeffectState, void, process, ALuint, const ALfloat*restrict, ALfloatBUFFERSIZE*restrict) \ -DECLARE_THUNK(T, ALeffectState, void, Delete) \ +static void T##_ALeffectState_Delete(void *ptr) \ +{ return T##_Delete(STATIC_UPCAST(T, ALeffectState, (ALeffectState*)ptr)); } \ \ static const struct ALeffectStateVtable T##_ALeffectState_vtable = { \ T##_ALeffectState_Destruct, \ @@ -68,13 +71,10 @@ typedef struct ALeffectslot { volatile ALfloat Gain; volatile ALboolean AuxSendAuto; - volatile ALenum NeedsUpdate; + ATOMIC(ALenum) NeedsUpdate; ALeffectState *EffectState; - ALIGN(16) ALfloat WetBuffer[1][BUFFERSIZE]; - - ALfloat ClickRemoval[1]; - ALfloat PendingClicks[1]; + alignas(16) ALfloat WetBuffer[1][BUFFERSIZE]; RefCount ref; diff --git a/jni/openal-soft-android/OpenAL32/Include/alBuffer.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alBuffer.h similarity index 79% rename from jni/openal-soft-android/OpenAL32/Include/alBuffer.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alBuffer.h index d22b3b9b..557f2282 100644 --- a/jni/openal-soft-android/OpenAL32/Include/alBuffer.h +++ b/jni/openal-soft-1.16.0/OpenAL32/Include/alBuffer.h @@ -22,6 +22,7 @@ enum UserFmtType { UserFmtMulaw, UserFmtAlaw, UserFmtIMA4, + UserFmtMSADPCM, }; enum UserFmtChannels { UserFmtMono = AL_MONO_SOFT, @@ -33,8 +34,8 @@ enum UserFmtChannels { UserFmtX71 = AL_7POINT1_SOFT, /* (WFX order) */ }; -ALuint BytesFromUserFmt(enum UserFmtType type); -ALuint ChannelsFromUserFmt(enum UserFmtChannels chans); +ALuint BytesFromUserFmt(enum UserFmtType type) DECL_CONST; +ALuint ChannelsFromUserFmt(enum UserFmtChannels chans) DECL_CONST; inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type) { return ChannelsFromUserFmt(chans) * BytesFromUserFmt(type); @@ -58,8 +59,8 @@ enum FmtChannels { }; #define MAX_INPUT_CHANNELS (8) -ALuint BytesFromFmt(enum FmtType type); -ALuint ChannelsFromFmt(enum FmtChannels chans); +ALuint BytesFromFmt(enum FmtType type) DECL_CONST; +ALuint ChannelsFromFmt(enum FmtChannels chans) DECL_CONST; inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type) { return ChannelsFromFmt(chans) * BytesFromFmt(type); @@ -79,10 +80,14 @@ typedef struct ALbuffer { enum UserFmtChannels OriginalChannels; enum UserFmtType OriginalType; ALsizei OriginalSize; + ALsizei OriginalAlign; ALsizei LoopStart; ALsizei LoopEnd; + ALsizei UnpackAlign; + ALsizei PackAlign; + /* Number of times buffer was attached to a source (deletion can only occur when 0) */ RefCount ref; @@ -92,6 +97,11 @@ typedef struct ALbuffer { ALuint id; } ALbuffer; +ALbuffer *NewBuffer(ALCcontext *context); +void DeleteBuffer(ALCdevice *device, ALbuffer *buffer); + +ALenum LoadData(ALbuffer *buffer, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc); + inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) { return (struct ALbuffer*)LookupUIntMapKey(&device->BufferMap, id); } inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id) diff --git a/jni/openal-soft-android/OpenAL32/Include/alEffect.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alEffect.h similarity index 100% rename from jni/openal-soft-android/OpenAL32/Include/alEffect.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alEffect.h diff --git a/jni/openal-soft-android/OpenAL32/Include/alError.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alError.h similarity index 100% rename from jni/openal-soft-android/OpenAL32/Include/alError.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alError.h diff --git a/jni/openal-soft-android/OpenAL32/Include/alFilter.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alFilter.h similarity index 77% rename from jni/openal-soft-android/OpenAL32/Include/alFilter.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alFilter.h index 5167c125..62b5fda8 100644 --- a/jni/openal-soft-android/OpenAL32/Include/alFilter.h +++ b/jni/openal-soft-1.16.0/OpenAL32/Include/alFilter.h @@ -7,7 +7,8 @@ extern "C" { #endif -#define LOWPASSFREQREF (5000) +#define LOWPASSFREQREF (5000.0f) +#define HIGHPASSFREQREF (250.0f) /* Filters implementation is based on the "Cookbook formulae for audio * @@ -15,12 +16,18 @@ extern "C" { * http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt */ typedef enum ALfilterType { + /** EFX-style low-pass filter, specifying a gain and reference frequency. */ ALfilterType_HighShelf, + /** EFX-style high-pass filter, specifying a gain and reference frequency. */ ALfilterType_LowShelf, + /** Peaking filter, specifying a gain, reference frequency, and bandwidth. */ ALfilterType_Peaking, + /** Low-pass cut-off filter, specifying a cut-off frequency and bandwidth. */ ALfilterType_LowPass, + /** High-pass cut-off filter, specifying a cut-off frequency and bandwidth. */ ALfilterType_HighPass, + /** Band-pass filter, specifying a center frequency and bandwidth. */ ALfilterType_BandPass, } ALfilterType; @@ -29,10 +36,13 @@ typedef struct ALfilterState { ALfloat y[2]; /* History of two last output samples */ ALfloat a[3]; /* Transfer function coefficients "a" */ ALfloat b[3]; /* Transfer function coefficients "b" */ + + void (*process)(struct ALfilterState *self, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples); } ALfilterState; +#define ALfilterState_process(a, ...) ((a)->process((a), __VA_ARGS__)) void ALfilterState_clear(ALfilterState *filter); -void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_scale, ALfloat bandwidth); +void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat bandwidth); inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample) { @@ -51,14 +61,7 @@ inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample return outsmp; } -inline ALfloat ALfilterState_processSingleC(const ALfilterState *filter, ALfloat sample) -{ - return filter->b[0] * sample + - filter->b[1] * filter->x[0] + - filter->b[2] * filter->x[1] - - filter->a[1] * filter->y[0] - - filter->a[2] * filter->y[1]; -} +void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const ALfloat *src, ALuint numsamples); typedef struct ALfilter { @@ -67,6 +70,9 @@ typedef struct ALfilter { ALfloat Gain; ALfloat GainHF; + ALfloat HFReference; + ALfloat GainLF; + ALfloat LFReference; void (*SetParami)(struct ALfilter *filter, ALCcontext *context, ALenum param, ALint val); void (*SetParamiv)(struct ALfilter *filter, ALCcontext *context, ALenum param, const ALint *vals); diff --git a/jni/openal-soft-android/OpenAL32/Include/alListener.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alListener.h similarity index 100% rename from jni/openal-soft-android/OpenAL32/Include/alListener.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alListener.h diff --git a/jni/openal-soft-android/OpenAL32/Include/alMain.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alMain.h similarity index 87% rename from jni/openal-soft-android/OpenAL32/Include/alMain.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alMain.h index b6a9f0ae..111dde95 100644 --- a/jni/openal-soft-android/OpenAL32/Include/alMain.h +++ b/jni/openal-soft-1.16.0/OpenAL32/Include/alMain.h @@ -6,6 +6,7 @@ #include #include #include +#include #ifdef HAVE_STRINGS_H #include @@ -19,8 +20,22 @@ #include "AL/alc.h" #include "AL/alext.h" + +#if defined(_WIN64) +#define SZFMT "%I64u" +#elif defined(_WIN32) +#define SZFMT "%u" +#else +#define SZFMT "%zu" +#endif + + +#include "static_assert.h" +#include "align.h" #include "atomic.h" #include "uintmap.h" +#include "vector.h" +#include "alstring.h" #ifndef ALC_SOFT_HRTF #define ALC_SOFT_HRTF 1 @@ -29,54 +44,25 @@ #ifndef ALC_SOFT_midi_interface #define ALC_SOFT_midi_interface 1 +/* Global properties */ #define AL_MIDI_CLOCK_SOFT 0x9999 #define AL_MIDI_STATE_SOFT 0x9986 #define AL_MIDI_GAIN_SOFT 0x9998 -#define AL_MIDI_PRESET_SOFT 0x9997 -#define AL_MIDI_BANK_SOFT 0x9996 #define AL_SOUNDFONTS_SIZE_SOFT 0x9995 #define AL_SOUNDFONTS_SOFT 0x9994 + +/* Soundfont properties */ #define AL_PRESETS_SIZE_SOFT 0x9993 #define AL_PRESETS_SOFT 0x9992 + +/* Preset properties */ +#define AL_MIDI_PRESET_SOFT 0x9997 +#define AL_MIDI_BANK_SOFT 0x9996 #define AL_FONTSOUNDS_SIZE_SOFT 0x9991 #define AL_FONTSOUNDS_SOFT 0x9990 -#define AL_SOURCE0_INPUT_SOFT 0x998F -#define AL_SOURCE0_TYPE_SOFT 0x998E -#define AL_SOURCE0_FORM_SOFT 0x998D -#define AL_SOURCE1_INPUT_SOFT 0x998C -#define AL_SOURCE1_TYPE_SOFT 0x998B -#define AL_SOURCE1_FORM_SOFT 0x998A -#define AL_AMOUNT_SOFT 0x9989 -#define AL_TRANSFORM_OP_SOFT 0x9988 -#define AL_DESTINATION_SOFT 0x9987 - -/* Sounce Input */ -#define AL_ONE_SOFT 0x0080 -#define AL_NOTEON_VELOCITY_SOFT 0x0082 -#define AL_NOTEON_KEY_SOFT 0x0083 -/* AL_KEYPRESSURE_SOFT */ -/* AL_CHANNELPRESSURE_SOFT */ -/* AL_PITCHBEND_SOFT */ -#define AL_PITCHBEND_SENSITIVITY_SOFT 0x0090 -/* CC 0...127 */ - -/* Source Type */ -#define AL_UNORM_SOFT 0x0000 -#define AL_UNORM_REV_SOFT 0x0100 -#define AL_SNORM_SOFT 0x0200 -#define AL_SNORM_REV_SOFT 0x0300 - -/* Source Form */ -#define AL_LINEAR_SOFT 0x0000 -#define AL_CONCAVE_SOFT 0x0400 -#define AL_CONVEX_SOFT 0x0800 -#define AL_SWITCH_SOFT 0x0C00 - -/* Transform op */ -/* AL_LINEAR_SOFT */ -#define AL_ABSOLUTE_SOFT 0x0002 - +/* Fontsound properties */ +/* AL_BUFFER */ #define AL_SAMPLE_START_SOFT 0x2000 #define AL_SAMPLE_END_SOFT 0x2001 #define AL_SAMPLE_LOOP_START_SOFT 0x2002 @@ -125,11 +111,55 @@ #define AL_LOOP_MODE_SOFT 0x0036 #define AL_TUNING_SCALE_SOFT 0x0038 #define AL_EXCLUSIVE_CLASS_SOFT 0x0039 -#define AL_LOOP_CONTINUOUS_SOFT 0x0001 -#define AL_LOOP_UNTIL_RELEASE_SOFT 0x0003 + +/* Sample Types */ +/* AL_MONO_SOFT */ #define AL_RIGHT_SOFT 0x0002 #define AL_LEFT_SOFT 0x0004 -#define AL_FORMAT_TYPE_SOFT 0x1991 + +/* Loop Modes */ +/* AL_NONE */ +#define AL_LOOP_CONTINUOUS_SOFT 0x0001 +#define AL_LOOP_UNTIL_RELEASE_SOFT 0x0003 + +/* Fontsound modulator stage properties */ +#define AL_SOURCE0_INPUT_SOFT 0x998F +#define AL_SOURCE0_TYPE_SOFT 0x998E +#define AL_SOURCE0_FORM_SOFT 0x998D +#define AL_SOURCE1_INPUT_SOFT 0x998C +#define AL_SOURCE1_TYPE_SOFT 0x998B +#define AL_SOURCE1_FORM_SOFT 0x998A +#define AL_AMOUNT_SOFT 0x9989 +#define AL_TRANSFORM_OP_SOFT 0x9988 +#define AL_DESTINATION_SOFT 0x9987 + +/* Sounce Inputs */ +#define AL_ONE_SOFT 0x0080 +#define AL_NOTEON_VELOCITY_SOFT 0x0082 +#define AL_NOTEON_KEY_SOFT 0x0083 +/* AL_KEYPRESSURE_SOFT */ +/* AL_CHANNELPRESSURE_SOFT */ +/* AL_PITCHBEND_SOFT */ +#define AL_PITCHBEND_SENSITIVITY_SOFT 0x0090 +/* CC 0...127 */ + +/* Source Types */ +#define AL_UNORM_SOFT 0x0000 +#define AL_UNORM_REV_SOFT 0x0100 +#define AL_SNORM_SOFT 0x0200 +#define AL_SNORM_REV_SOFT 0x0300 + +/* Source Forms */ +#define AL_LINEAR_SOFT 0x0000 +#define AL_CONCAVE_SOFT 0x0400 +#define AL_CONVEX_SOFT 0x0800 +#define AL_SWITCH_SOFT 0x0C00 + +/* Transform Ops */ +/* AL_LINEAR_SOFT */ +#define AL_ABSOLUTE_SOFT 0x0002 + +/* Events */ #define AL_NOTEOFF_SOFT 0x0080 #define AL_NOTEON_SOFT 0x0090 #define AL_KEYPRESSURE_SOFT 0x00A0 @@ -137,13 +167,10 @@ #define AL_PROGRAMCHANGE_SOFT 0x00C0 #define AL_CHANNELPRESSURE_SOFT 0x00D0 #define AL_PITCHBEND_SOFT 0x00E0 + typedef void (AL_APIENTRY*LPALGENSOUNDFONTSSOFT)(ALsizei n, ALuint *ids); typedef void (AL_APIENTRY*LPALDELETESOUNDFONTSSOFT)(ALsizei n, const ALuint *ids); typedef ALboolean (AL_APIENTRY*LPALISSOUNDFONTSOFT)(ALuint id); -typedef void (AL_APIENTRY*LPALSOUNDFONTSAMPLESSOFT)(ALuint sfid, ALenum type, ALsizei count, const ALvoid *samples); -typedef void (AL_APIENTRY*LPALGETSOUNDFONTSAMPLESSOFT)(ALuint id, ALsizei offset, ALsizei count, ALenum type, ALvoid *samples); -typedef ALvoid* (AL_APIENTRY*LPALSOUNDFONTMAPSAMPLESSOFT)(ALuint sfid, ALsizei offset, ALsizei length); -typedef void (AL_APIENTRY*LPALSOUNDFONTUNMAPSAMPLESSOFT)(ALuint sfid); typedef void (AL_APIENTRY*LPALGETSOUNDFONTIVSOFT)(ALuint id, ALenum param, ALint *values); typedef void (AL_APIENTRY*LPALSOUNDFONTPRESETSSOFT)(ALuint id, ALsizei count, const ALuint *pids); typedef void (AL_APIENTRY*LPALGENPRESETSSOFT)(ALsizei n, ALuint *ids); @@ -178,10 +205,6 @@ typedef void (AL_APIENTRY*LPALLOADSOUNDFONTSOFT)(ALuint id, size_t(*cb)(ALvoid*, AL_API void AL_APIENTRY alGenSoundfontsSOFT(ALsizei n, ALuint *ids); AL_API void AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids); AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(ALuint id); -AL_API void AL_APIENTRY alSoundfontSamplesSOFT(ALuint sfid, ALenum type, ALsizei count, const ALvoid *samples); -AL_API void AL_APIENTRY alGetSoundfontSamplesSOFT(ALuint id, ALsizei offset, ALsizei count, ALenum type, ALvoid *samples); -AL_API ALvoid* AL_APIENTRY alSoundfontMapSamplesSOFT(ALuint sfid, ALsizei offset, ALsizei length); -AL_API void AL_APIENTRY alSoundfontUnmapSamplesSOFT(ALuint sfid); AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *values); AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const ALuint *pids); @@ -218,13 +241,14 @@ AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_ #endif #endif -#ifndef ALC_SOFT_pause_device -#define ALC_SOFT_pause_device 1 -typedef void (ALC_APIENTRY*LPALCDEVICEPAUSESOFT)(ALCdevice *device); -typedef void (ALC_APIENTRY*LPALCDEVICERESUMESOFT)(ALCdevice *device); +#ifndef ALC_SOFT_device_clock +#define ALC_SOFT_device_clock 1 +typedef int64_t ALCint64SOFT; +typedef uint64_t ALCuint64SOFT; +#define ALC_DEVICE_CLOCK_SOFT 0x1600 +typedef void (ALC_APIENTRY*LPALCGETINTEGER64VSOFT)(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); #ifdef AL_ALEXT_PROTOTYPES -ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device); -ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); +ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, ALsizei size, ALCint64SOFT *values); #endif #endif @@ -233,11 +257,6 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device); /* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but * recent versions (at least 4.5.1) do recognize GCC's __restrict. */ #define restrict __restrict -/* KDevelop won't see the ALIGN macro from config.h when viewing files that - * don't include it directly (e.g. headers). */ -#ifndef ALIGN -#define ALIGN(x) -#endif #endif @@ -273,10 +292,12 @@ typedef ptrdiff_t ALsizeiptrEXT; #endif #endif -#ifdef HAVE_GCC_FORMAT -#define PRINTF_STYLE(x, y) __attribute__((format(printf, (x), (y)))) +#ifdef __GNUC__ +#define DECL_CONST __attribute__((const)) +#define DECL_FORMAT(x, y, z) __attribute__((format(x, (y), (z)))) #else -#define PRINTF_STYLE(x, y) +#define DECL_CONST +#define DECL_FORMAT(x, y, z) #endif #if defined(__GNUC__) && defined(__i386__) @@ -289,6 +310,20 @@ typedef ptrdiff_t ALsizeiptrEXT; #define FORCE_ALIGN #endif +#ifdef HAVE_C99_VLA +#define DECL_VLA(T, _name, _size) T _name[(_size)] +#else +#define DECL_VLA(T, _name, _size) T *_name = alloca((_size) * sizeof(T)) +#endif + +#ifndef PATH_MAX +#ifdef MAX_PATH +#define PATH_MAX MAX_PATH +#else +#define PATH_MAX 4096 +#endif +#endif + static const union { ALuint u; @@ -301,8 +336,15 @@ static const union { #define DERIVE_FROM_TYPE(t) t t##_parent #define STATIC_CAST(to, obj) (&(obj)->to##_parent) +#ifdef __GNUC__ +#define STATIC_UPCAST(to, from, obj) __extension__({ \ + static_assert(__builtin_types_compatible_p(from, __typeof(*(obj))), \ + "Invalid upcast object from type"); \ + (to*)((char*)(obj) - offsetof(to, from##_parent)); \ +}) +#else #define STATIC_UPCAST(to, from, obj) ((to*)((char*)(obj) - offsetof(to, from##_parent))) - +#endif #define DECLARE_FORWARD(T1, T2, rettype, func) \ rettype T1##_##func(T1 *obj) \ @@ -343,6 +385,9 @@ static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b) \ static rettype T1##_##T2##_##func(T2 *obj, argtype1 a, argtype2 b, argtype3 c) \ { return T1##_##func(STATIC_UPCAST(T1, T2, obj), a, b, c); } +#define DECLARE_DEFAULT_ALLOCATORS(T) \ +static void* T##_New(size_t size) { return malloc(size); } \ +static void T##_Delete(void *ptr) { free(ptr); } /* Helper to extract an argument list for VCALL. Not used directly. */ #define EXTRACT_VCALL_ARGS(...) __VA_ARGS__)) @@ -437,12 +482,6 @@ void alc_solaris_probe(enum DevProbe type); ALCboolean alc_sndio_init(BackendFuncs *func_list); void alc_sndio_deinit(void); void alc_sndio_probe(enum DevProbe type); -ALCboolean alcMMDevApiInit(BackendFuncs *func_list); -void alcMMDevApiDeinit(void); -void alcMMDevApiProbe(enum DevProbe type); -ALCboolean alcDSoundInit(BackendFuncs *func_list); -void alcDSoundDeinit(void); -void alcDSoundProbe(enum DevProbe type); ALCboolean alcWinMMInit(BackendFuncs *FuncList); void alcWinMMDeinit(void); void alcWinMMProbe(enum DevProbe type); @@ -526,8 +565,8 @@ enum DevFmtChannels { DevFmtChannelsDefault = DevFmtStereo }; -ALuint BytesFromDevFmt(enum DevFmtType type); -ALuint ChannelsFromDevFmt(enum DevFmtChannels chans); +ALuint BytesFromDevFmt(enum DevFmtType type) DECL_CONST; +ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) DECL_CONST; inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, enum DevFmtType type) { return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type); @@ -559,7 +598,7 @@ enum DeviceType { struct ALCdevice_struct { - volatile RefCount ref; + RefCount ref; ALCboolean Connected; enum DeviceType Type; @@ -570,9 +609,9 @@ struct ALCdevice_struct enum DevFmtChannels FmtChans; enum DevFmtType FmtType; - ALCchar *DeviceName; + al_string DeviceName; - volatile ALCenum LastError; + ATOMIC(ALCenum) LastError; // Maximum number of sources that can be created ALuint MaxNoOfSources; @@ -623,28 +662,38 @@ struct ALCdevice_struct ALfloat SpeakerAngle[MaxChannels]; ALuint NumChan; - /* Temp storage used for mixing. +1 for the predictive sample. */ - ALIGN(16) ALfloat SampleData1[BUFFERSIZE+1]; - ALIGN(16) ALfloat SampleData2[BUFFERSIZE+1]; + ALuint64 ClockBase; + ALuint SamplesDone; + + /* Temp storage used for each source when mixing. */ + alignas(16) ALfloat SourceData[BUFFERSIZE]; + alignas(16) ALfloat ResampledData[BUFFERSIZE]; + alignas(16) ALfloat FilteredData[BUFFERSIZE]; // Dry path buffer mix - ALIGN(16) ALfloat DryBuffer[MaxChannels][BUFFERSIZE]; + alignas(16) ALfloat DryBuffer[MaxChannels][BUFFERSIZE]; - ALIGN(16) ALfloat ClickRemoval[MaxChannels]; - ALIGN(16) ALfloat PendingClicks[MaxChannels]; + /* Running count of the mixer invocations, in 31.1 fixed point. This + * actually increments *twice* when mixing, first at the start and then at + * the end, so the bottom bit indicates if the device is currently mixing + * and the upper bits indicates how many mixes have been done. + */ + RefCount MixCount; /* Default effect slot */ struct ALeffectslot *DefaultSlot; // Contexts created on this device - ALCcontext *volatile ContextList; + ATOMIC(ALCcontext*) ContextList; struct ALCbackend *Backend; - BackendFuncs *Funcs; - void *ExtraData; // For the backend's use + void *ExtraData; // For the backend's use ALCdevice *volatile next; + + /* Memory space used by the default slot (Playback devices only) */ + alignas(16) ALCbyte _slot_mem[]; }; // Frequency was requested by the app or config file @@ -669,6 +718,10 @@ struct ALCdevice_struct #define INVALID_OFFSET (~0u) +/* Nanosecond resolution for the device clock time. */ +#define DEVICE_CLOCK_RES U64(1000000000) + + /* Must be less than 15 characters (16 including terminating null) for * compatibility with pthread_setname_np limitations. */ #define MIXER_THREAD_NAME "alsoft-mixer" @@ -676,16 +729,16 @@ struct ALCdevice_struct struct ALCcontext_struct { - volatile RefCount ref; + RefCount ref; struct ALlistener *Listener; UIntMap SourceMap; UIntMap EffectSlotMap; - volatile ALenum LastError; + ATOMIC(ALenum) LastError; - volatile ALenum UpdateSources; + ATOMIC(ALenum) UpdateSources; volatile enum DistanceModel DistanceModel; volatile ALboolean SourceDistanceModel; @@ -695,18 +748,19 @@ struct ALCcontext_struct volatile ALfloat SpeedOfSound; volatile ALenum DeferUpdates; - struct ALsource **ActiveSources; - ALsizei ActiveSourceCount; - ALsizei MaxActiveSources; + struct ALactivesource **ActiveSources; + ALsizei ActiveSourceCount; + ALsizei MaxActiveSources; - struct ALeffectslot **ActiveEffectSlots; - ALsizei ActiveEffectSlotCount; - ALsizei MaxActiveEffectSlots; + VECTOR(struct ALeffectslot*) ActiveAuxSlots; ALCdevice *Device; const ALCchar *ExtensionList; ALCcontext *volatile next; + + /* Memory space used by the listener */ + alignas(16) ALCbyte _listener_mem[]; }; ALCcontext *GetContextRef(void); @@ -771,31 +825,17 @@ void SetRTPriority(void); void SetDefaultChannelOrder(ALCdevice *device); void SetDefaultWFXChannelOrder(ALCdevice *device); -const ALCchar *DevFmtTypeString(enum DevFmtType type); -const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans); - -#define HRIR_BITS (7) -#define HRIR_LENGTH (1<FontsoundMap, id); } inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id) { return (struct ALfontsound*)RemoveUIntMapKey(&device->FontsoundMap, id); } -inline struct ALsfmodulator *LookupModulator(ALfontsound *sound, ALuint id) -{ return (struct ALsfmodulator*)LookupUIntMapKey(&sound->ModulatorMap, id); } -inline struct ALsfmodulator *RemoveModulator(ALfontsound *sound, ALuint id) -{ return (struct ALsfmodulator*)RemoveUIntMapKey(&sound->ModulatorMap, id); } - void ReleaseALFontsounds(ALCdevice *device); typedef struct ALsfpreset { - volatile RefCount ref; + RefCount ref; ALint Preset; /* a.k.a. MIDI program number */ ALint Bank; /* MIDI bank 0...127, or percussion (bank 128) */ @@ -122,7 +120,7 @@ typedef struct ALsfpreset { } ALsfpreset; ALsfpreset *NewPreset(ALCcontext *context); -void DeletePreset(ALsfpreset *preset, ALCdevice *device); +void DeletePreset(ALCdevice *device, ALsfpreset *preset); inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id) { return (struct ALsfpreset*)LookupUIntMapKey(&device->PresetMap, id); } @@ -133,22 +131,16 @@ void ReleaseALPresets(ALCdevice *device); typedef struct ALsoundfont { - volatile RefCount ref; + RefCount ref; ALsfpreset **Presets; ALsizei NumPresets; - ALshort *Samples; - ALint NumSamples; - RWLock Lock; - volatile ALenum Mapped; ALuint id; } ALsoundfont; -void ALsoundfont_Construct(ALsoundfont *self); -void ALsoundfont_Destruct(ALsoundfont *self); ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context); void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device); @@ -159,6 +151,20 @@ inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id) void ReleaseALSoundfonts(ALCdevice *device); + +inline ALboolean IsValidCtrlInput(int cc) +{ + /* These correspond to MIDI functions, not real controller values. */ + if(cc == 0 || cc == 6 || cc == 32 || cc == 38 || (cc >= 98 && cc <= 101) || cc >= 120) + return AL_FALSE; + /* These are the LSB components of CC0...CC31, which are automatically used when + * reading the MSB controller value. */ + if(cc >= 32 && cc <= 63) + return AL_FALSE; + /* All the rest are okay! */ + return AL_TRUE; +} + #ifdef __cplusplus } #endif diff --git a/jni/openal-soft-android/OpenAL32/Include/alSource.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alSource.h similarity index 56% rename from jni/openal-soft-android/OpenAL32/Include/alSource.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alSource.h index 31a0d229..8d74fc54 100644 --- a/jni/openal-soft-android/OpenAL32/Include/alSource.h +++ b/jni/openal-soft-1.16.0/OpenAL32/Include/alSource.h @@ -5,17 +5,12 @@ #include "alMain.h" #include "alu.h" -#include "alFilter.h" -#include "alBuffer.h" +#include "hrtf.h" #ifdef __cplusplus extern "C" { #endif -#define SRC_HISTORY_BITS (6) -#define SRC_HISTORY_LENGTH (1<Update(s,a)) inline struct ALsource *LookupSource(ALCcontext *context, ALuint id) { return (struct ALsource*)LookupUIntMapKey(&context->SourceMap, id); } diff --git a/jni/openal-soft-android/OpenAL32/Include/alThunk.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alThunk.h similarity index 100% rename from jni/openal-soft-android/OpenAL32/Include/alThunk.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alThunk.h diff --git a/jni/openal-soft-android/OpenAL32/Include/alu.h b/jni/openal-soft-1.16.0/OpenAL32/Include/alu.h similarity index 54% rename from jni/openal-soft-android/OpenAL32/Include/alu.h rename to jni/openal-soft-1.16.0/OpenAL32/Include/alu.h index d88e860c..7727c666 100644 --- a/jni/openal-soft-android/OpenAL32/Include/alu.h +++ b/jni/openal-soft-1.16.0/OpenAL32/Include/alu.h @@ -1,8 +1,6 @@ #ifndef _ALU_H_ #define _ALU_H_ -#include "alMain.h" - #include #include #ifdef HAVE_FLOAT_H @@ -12,6 +10,13 @@ #include #endif +#include "alMain.h" +#include "alBuffer.h" +#include "alFilter.h" + +#include "hrtf.h" +#include "align.h" + #define F_PI (3.14159265358979323846f) #define F_PI_2 (1.57079632679489661923f) @@ -25,29 +30,103 @@ #define RAD2DEG(x) ((ALfloat)(x) * (180.0f/F_PI)) +#define SRC_HISTORY_BITS (6) +#define SRC_HISTORY_LENGTH (1<a0_lo*(in) + bs2b->b1_lo*(out_1)) + +/* Highboost filter */ +#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1)) + + /* Lowpass filter */ + bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]); + bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]); + + /* Highboost filter */ + bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]); + bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]); + bs2b->last_sample.asis[0] = sample[0]; + bs2b->last_sample.asis[1] = sample[1]; + + /* Crossfeed */ + sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1]; + sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0]; +#undef hi_filter +#undef lo_filter +} /* bs2b_cross_feed */ #ifdef __cplusplus } /* extern "C" */ diff --git a/jni/openal-soft-1.16.0/OpenAL32/Include/sample_cvt.h b/jni/openal-soft-1.16.0/OpenAL32/Include/sample_cvt.h new file mode 100644 index 00000000..12bb1fa6 --- /dev/null +++ b/jni/openal-soft-1.16.0/OpenAL32/Include/sample_cvt.h @@ -0,0 +1,9 @@ +#ifndef SAMPLE_CVT_H +#define SAMPLE_CVT_H + +#include "AL/al.h" +#include "alBuffer.h" + +void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align); + +#endif /* SAMPLE_CVT_H */ diff --git a/jni/openal-soft-android/OpenAL32/alAuxEffectSlot.c b/jni/openal-soft-1.16.0/OpenAL32/alAuxEffectSlot.c similarity index 87% rename from jni/openal-soft-android/OpenAL32/alAuxEffectSlot.c rename to jni/openal-soft-1.16.0/OpenAL32/alAuxEffectSlot.c index aa071de2..ec8890b6 100644 --- a/jni/openal-soft-android/OpenAL32/alAuxEffectSlot.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alAuxEffectSlot.c @@ -35,8 +35,8 @@ extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id); extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id); -static ALenum AddEffectSlotArray(ALCcontext *Context, ALsizei count, const ALuint *slots); -static ALvoid RemoveEffectSlotArray(ALCcontext *Context, ALeffectslot *slot); +static ALenum AddEffectSlotArray(ALCcontext *Context, ALeffectslot **start, ALsizei count); +static void RemoveEffectSlotArray(ALCcontext *Context, const ALeffectslot *slot); static UIntMap EffectStateFactoryMap; @@ -52,14 +52,20 @@ static inline ALeffectStateFactory *getFactoryByType(ALenum type) AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) { ALCcontext *context; + VECTOR(ALeffectslot*) slotvec; ALsizei cur; ALenum err; context = GetContextRef(); if(!context) return; + VECTOR_INIT(slotvec); + if(!(n >= 0)) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(!VECTOR_RESERVE(slotvec, n)) + SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); + for(cur = 0;cur < n;cur++) { ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot)); @@ -84,9 +90,11 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo SET_ERROR_AND_GOTO(context, err, done); } + VECTOR_PUSH_BACK(slotvec, slot); + effectslots[cur] = slot->id; } - err = AddEffectSlotArray(context, n, effectslots); + err = AddEffectSlotArray(context, VECTOR_ITER_BEGIN(slotvec), n); if(err != AL_NO_ERROR) { alDeleteAuxiliaryEffectSlots(cur, effectslots); @@ -94,6 +102,8 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo } done: + VECTOR_DEINIT(slotvec); + ALCcontext_DecRef(context); } @@ -112,7 +122,7 @@ AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint * { if((slot=LookupEffectSlot(context, effectslots[i])) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(slot->ref != 0) + if(ReadRef(&slot->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); } @@ -173,7 +183,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param err = InitializeEffect(device, slot, effect); if(err != AL_NO_ERROR) SET_ERROR_AND_GOTO(context, err, done); - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: @@ -181,7 +191,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); slot->AuxSendAuto = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; default: @@ -236,7 +246,7 @@ AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); slot->Gain = value; - slot->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&slot->NeedsUpdate, AL_TRUE); break; default: @@ -375,56 +385,32 @@ done: } -static ALvoid RemoveEffectSlotArray(ALCcontext *context, ALeffectslot *slot) +static ALenum AddEffectSlotArray(ALCcontext *context, ALeffectslot **start, ALsizei count) { - ALeffectslot **slotlist, **slotlistend; + ALenum err = AL_NO_ERROR; LockContext(context); - slotlist = context->ActiveEffectSlots; - slotlistend = slotlist + context->ActiveEffectSlotCount; - while(slotlist != slotlistend) - { - if(*slotlist == slot) - { - *slotlist = *(--slotlistend); - context->ActiveEffectSlotCount--; - break; - } - slotlist++; - } + if(!VECTOR_INSERT(context->ActiveAuxSlots, VECTOR_ITER_END(context->ActiveAuxSlots), start, start+count)) + err = AL_OUT_OF_MEMORY; UnlockContext(context); + + return err; } -static ALenum AddEffectSlotArray(ALCcontext *context, ALsizei count, const ALuint *slots) +static void RemoveEffectSlotArray(ALCcontext *context, const ALeffectslot *slot) { - ALsizei i; + ALeffectslot **iter; LockContext(context); - if(count > context->MaxActiveEffectSlots-context->ActiveEffectSlotCount) +#define MATCH_SLOT(_i) (slot == *(_i)) + VECTOR_FIND_IF(iter, ALeffectslot*, context->ActiveAuxSlots, MATCH_SLOT); + if(iter != VECTOR_ITER_END(context->ActiveAuxSlots)) { - ALsizei newcount; - void *temp = NULL; - - newcount = context->MaxActiveEffectSlots ? (context->MaxActiveEffectSlots<<1) : 1; - if(newcount > context->MaxActiveEffectSlots) - temp = realloc(context->ActiveEffectSlots, - newcount * sizeof(*context->ActiveEffectSlots)); - if(!temp) - { - UnlockContext(context); - return AL_OUT_OF_MEMORY; - } - context->ActiveEffectSlots = temp; - context->MaxActiveEffectSlots = newcount; - } - for(i = 0;i < count;i++) - { - ALeffectslot *slot = LookupEffectSlot(context, slots[i]); - assert(slot != NULL); - context->ActiveEffectSlots[context->ActiveEffectSlotCount++] = slot; + *iter = VECTOR_BACK(context->ActiveAuxSlots); + VECTOR_POP_BACK(context->ActiveAuxSlots); } +#undef MATCH_SLOT UnlockContext(context); - return AL_NO_ERROR; } @@ -499,7 +485,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e /* FIXME: This should be done asynchronously, but since the EffectState * object was changed, it needs an update before its Process method can * be called. */ - EffectSlot->NeedsUpdate = AL_FALSE; + ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_FALSE); V(EffectSlot->EffectState,update)(Device, EffectSlot); ALCdevice_Unlock(Device); @@ -515,7 +501,7 @@ ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *e ALCdevice_Lock(Device); memcpy(&EffectSlot->EffectProps, &effect->Props, sizeof(effect->Props)); ALCdevice_Unlock(Device); - EffectSlot->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&EffectSlot->NeedsUpdate, AL_TRUE); } } @@ -536,15 +522,13 @@ ALenum InitEffectSlot(ALeffectslot *slot) slot->Gain = 1.0; slot->AuxSendAuto = AL_TRUE; - slot->NeedsUpdate = AL_FALSE; + ATOMIC_INIT(&slot->NeedsUpdate, AL_FALSE); for(c = 0;c < 1;c++) { for(i = 0;i < BUFFERSIZE;i++) slot->WetBuffer[c][i] = 0.0f; - slot->ClickRemoval[c] = 0.0f; - slot->PendingClicks[c] = 0.0f; } - slot->ref = 0; + InitRef(&slot->ref, 0); return AL_NO_ERROR; } diff --git a/jni/openal-soft-1.16.0/OpenAL32/alBuffer.c b/jni/openal-soft-1.16.0/OpenAL32/alBuffer.c new file mode 100644 index 00000000..d03f30a4 --- /dev/null +++ b/jni/openal-soft-1.16.0/OpenAL32/alBuffer.c @@ -0,0 +1,1329 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2007 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include +#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 struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id); +extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id); +extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type); +extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type); + +static ALboolean IsValidType(ALenum type) DECL_CONST; +static ALboolean IsValidChannels(ALenum channels) DECL_CONST; +static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, enum UserFmtType *type) DECL_CONST; +static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) DECL_CONST; +static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align); + + +AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) +{ + ALCcontext *context; + ALsizei cur = 0; + + context = GetContextRef(); + if(!context) return; + + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + for(cur = 0;cur < n;cur++) + { + ALbuffer *buffer = NewBuffer(context); + if(!buffer) + { + alDeleteBuffers(cur, buffers); + break; + } + + buffers[cur] = buffer->id; + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *ALBuf; + ALsizei i; + + context = GetContextRef(); + if(!context) return; + + if(!(n >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + device = context->Device; + for(i = 0;i < n;i++) + { + if(!buffers[i]) + continue; + + /* Check for valid Buffer ID */ + if((ALBuf=LookupBuffer(device, buffers[i])) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(ReadRef(&ALBuf->ref) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + } + + for(i = 0;i < n;i++) + { + if((ALBuf=LookupBuffer(device, buffers[i])) != NULL) + DeleteBuffer(device, ALBuf); + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer) +{ + ALCcontext *context; + ALboolean ret; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + ret = ((!buffer || LookupBuffer(context->Device, buffer)) ? + AL_TRUE : AL_FALSE); + + ALCcontext_DecRef(context); + + return ret; +} + + +AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) +{ + enum UserFmtChannels srcchannels; + enum UserFmtType srctype; + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALenum newformat = AL_NONE; + ALuint framesize; + ALsizei align; + ALenum err; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(size >= 0 && freq > 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + align = albuf->UnpackAlign; + if(SanitizeAlignment(srctype, &align) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(srctype) + { + case UserFmtByte: + case UserFmtUByte: + case UserFmtShort: + case UserFmtUShort: + case UserFmtFloat: + framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + err = LoadData(albuf, freq, format, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case UserFmtInt: + case UserFmtUInt: + case UserFmtByte3: + case UserFmtUByte3: + case UserFmtDouble: + framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + switch(srcchannels) + { + case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break; + case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break; + case UserFmtRear: newformat = AL_FORMAT_REAR32; break; + case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break; + case UserFmtX51: newformat = AL_FORMAT_51CHN32; break; + case UserFmtX61: newformat = AL_FORMAT_61CHN32; break; + case UserFmtX71: newformat = AL_FORMAT_71CHN32; break; + } + err = LoadData(albuf, freq, newformat, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case UserFmtMulaw: + case UserFmtAlaw: + framesize = FrameSizeFromUserFmt(srcchannels, srctype) * align; + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + switch(srcchannels) + { + case UserFmtMono: newformat = AL_FORMAT_MONO16; break; + case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; + case UserFmtRear: newformat = AL_FORMAT_REAR16; break; + case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; + case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; + case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; + case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; + } + err = LoadData(albuf, freq, newformat, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case UserFmtIMA4: + framesize = (align-1)/2 + 4; + framesize *= ChannelsFromUserFmt(srcchannels); + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + switch(srcchannels) + { + case UserFmtMono: newformat = AL_FORMAT_MONO16; break; + case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; + case UserFmtRear: newformat = AL_FORMAT_REAR16; break; + case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; + case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; + case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; + case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; + } + err = LoadData(albuf, freq, newformat, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + + case UserFmtMSADPCM: + framesize = (align-2)/2 + 7; + framesize *= ChannelsFromUserFmt(srcchannels); + if((size%framesize) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + switch(srcchannels) + { + case UserFmtMono: newformat = AL_FORMAT_MONO16; break; + case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; + case UserFmtRear: newformat = AL_FORMAT_REAR16; break; + case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; + case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; + case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; + case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; + } + err = LoadData(albuf, freq, newformat, size/framesize*align, + srcchannels, srctype, data, align, AL_TRUE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + break; + } + +done: + ALCcontext_DecRef(context); +} + +AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) +{ + enum UserFmtChannels srcchannels; + enum UserFmtType srctype; + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALuint byte_align; + ALuint channels; + ALuint bytes; + ALsizei align; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(length >= 0 && offset >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + WriteLock(&albuf->lock); + align = albuf->UnpackAlign; + if(SanitizeAlignment(srctype, &align) == AL_FALSE) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(align != albuf->OriginalAlign) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + + if(albuf->OriginalType == UserFmtIMA4) + { + byte_align = (albuf->OriginalAlign-1)/2 + 4; + byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels); + } + else if(albuf->OriginalType == UserFmtMSADPCM) + { + byte_align = (albuf->OriginalAlign-2)/2 + 7; + byte_align *= ChannelsFromUserFmt(albuf->OriginalChannels); + } + else + { + byte_align = albuf->OriginalAlign; + byte_align *= FrameSizeFromUserFmt(albuf->OriginalChannels, + albuf->OriginalType); + } + + if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset || + (offset%byte_align) != 0 || (length%byte_align) != 0) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + channels = ChannelsFromFmt(albuf->FmtChannels); + bytes = BytesFromFmt(albuf->FmtType); + /* offset -> byte offset, length -> sample count */ + offset = offset/byte_align * channels*bytes; + length = length/byte_align * albuf->OriginalAlign; + + ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, + data, srctype, channels, length, align); + WriteUnlock(&albuf->lock); + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, + ALuint samplerate, ALenum internalformat, ALsizei samples, + ALenum channels, ALenum type, const ALvoid *data) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALsizei align; + ALenum err; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(samples >= 0 && samplerate != 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + align = albuf->UnpackAlign; + if(SanitizeAlignment(type, &align) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if((samples%align) != 0) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + + err = LoadData(albuf, samplerate, internalformat, samples, + channels, type, data, align, AL_FALSE); + if(err != AL_NO_ERROR) + SET_ERROR_AND_GOTO(context, err, done); + +done: + ALCcontext_DecRef(context); +} + +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, + ALsizei offset, ALsizei samples, + ALenum channels, ALenum type, const ALvoid *data) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALsizei align; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(samples >= 0 && offset >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(IsValidType(type) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + WriteLock(&albuf->lock); + align = albuf->UnpackAlign; + if(SanitizeAlignment(type, &align) == AL_FALSE) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if(channels != (ALenum)albuf->FmtChannels) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if((samples%align) != 0) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + /* offset -> byte offset */ + offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType); + ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, + data, type, ChannelsFromFmt(albuf->FmtChannels), samples, align); + WriteUnlock(&albuf->lock); + +done: + ALCcontext_DecRef(context); +} + +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, + ALsizei offset, ALsizei samples, + ALenum channels, ALenum type, ALvoid *data) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + ALsizei align; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + if(!(samples >= 0 && offset >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + if(IsValidType(type) == AL_FALSE) + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + + ReadLock(&albuf->lock); + align = albuf->PackAlign; + if(SanitizeAlignment(type, &align) == AL_FALSE) + { + ReadUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if(channels != (ALenum)albuf->FmtChannels) + { + ReadUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset) + { + ReadUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + if((samples%align) != 0) + { + ReadUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + /* offset -> byte offset */ + offset *= FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType); + ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, + ChannelsFromFmt(albuf->FmtChannels), samples, align); + ReadUnlock(&albuf->lock); + +done: + ALCcontext_DecRef(context); +} + +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format) +{ + enum FmtChannels dstchannels; + enum FmtType dsttype; + ALCcontext *context; + ALboolean ret; + + context = GetContextRef(); + if(!context) return AL_FALSE; + + ret = DecomposeFormat(format, &dstchannels, &dsttype); + + ALCcontext_DecRef(context); + + return ret; +} + + +AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value)) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3)) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint value) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + switch(param) + { + case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: + if(!(value >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + ExchangeInt(&albuf->UnpackAlign, value); + break; + + case AL_PACK_BLOCK_ALIGNMENT_SOFT: + if(!(value >= 0)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + ExchangeInt(&albuf->PackAlign, value); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBuffer3i(ALuint buffer, ALenum param, ALint UNUSED(value1), ALint UNUSED(value2), ALint UNUSED(value3)) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum param, const ALint *values) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + if(values) + { + switch(param) + { + case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: + case AL_PACK_BLOCK_ALIGNMENT_SOFT: + alBufferi(buffer, param, values[0]); + return; + } + } + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_LOOP_POINTS_SOFT: + WriteLock(&albuf->lock); + if(ReadRef(&albuf->ref) != 0) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + } + if(values[0] >= values[1] || values[0] < 0 || + values[1] > albuf->SampleLen) + { + WriteUnlock(&albuf->lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + } + + albuf->LoopStart = values[0]; + albuf->LoopEnd = values[1]; + WriteUnlock(&albuf->lock); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(value)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_SEC_LENGTH_SOFT: + ReadLock(&albuf->lock); + if(albuf->SampleLen != 0) + *value = albuf->SampleLen / (ALfloat)albuf->Frequency; + else + *value = 0.0f; + ReadUnlock(&albuf->lock); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(value1 && value2 && value3)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values) +{ + ALCdevice *device; + ALCcontext *context; + + switch(param) + { + case AL_SEC_LENGTH_SOFT: + alGetBufferf(buffer, param, values); + return; + } + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(value)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_FREQUENCY: + *value = albuf->Frequency; + break; + + case AL_BITS: + *value = BytesFromFmt(albuf->FmtType) * 8; + break; + + case AL_CHANNELS: + *value = ChannelsFromFmt(albuf->FmtChannels); + break; + + case AL_SIZE: + ReadLock(&albuf->lock); + *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels, + albuf->FmtType); + ReadUnlock(&albuf->lock); + break; + + case AL_INTERNAL_FORMAT_SOFT: + *value = albuf->Format; + break; + + case AL_BYTE_LENGTH_SOFT: + *value = albuf->OriginalSize; + break; + + case AL_SAMPLE_LENGTH_SOFT: + *value = albuf->SampleLen; + break; + + case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: + *value = albuf->UnpackAlign; + break; + + case AL_PACK_BLOCK_ALIGNMENT_SOFT: + *value = albuf->PackAlign; + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) +{ + ALCdevice *device; + ALCcontext *context; + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if(LookupBuffer(device, buffer) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(value1 && value2 && value3)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values) +{ + ALCdevice *device; + ALCcontext *context; + ALbuffer *albuf; + + switch(param) + { + case AL_FREQUENCY: + case AL_BITS: + case AL_CHANNELS: + case AL_SIZE: + case AL_INTERNAL_FORMAT_SOFT: + case AL_BYTE_LENGTH_SOFT: + case AL_SAMPLE_LENGTH_SOFT: + case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: + case AL_PACK_BLOCK_ALIGNMENT_SOFT: + alGetBufferi(buffer, param, values); + return; + } + + context = GetContextRef(); + if(!context) return; + + device = context->Device; + if((albuf=LookupBuffer(device, buffer)) == NULL) + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + + if(!(values)) + SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); + switch(param) + { + case AL_LOOP_POINTS_SOFT: + ReadLock(&albuf->lock); + values[0] = albuf->LoopStart; + values[1] = albuf->LoopEnd; + ReadUnlock(&albuf->lock); + break; + + default: + SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); + } + +done: + ALCcontext_DecRef(context); +} + + +/* + * LoadData + * + * Loads the specified data into the buffer, using the specified formats. + * Currently, the new format must have the same channel configuration as the + * original format. + */ +ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALsizei align, ALboolean storesrc) +{ + ALuint NewChannels, NewBytes; + enum FmtChannels DstChannels; + enum FmtType DstType; + ALuint64 newsize; + ALvoid *temp; + + if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE || + (long)SrcChannels != (long)DstChannels) + return AL_INVALID_ENUM; + + NewChannels = ChannelsFromFmt(DstChannels); + NewBytes = BytesFromFmt(DstType); + + newsize = frames; + newsize *= NewBytes; + newsize *= NewChannels; + if(newsize > INT_MAX) + return AL_OUT_OF_MEMORY; + + WriteLock(&ALBuf->lock); + if(ReadRef(&ALBuf->ref) != 0) + { + WriteUnlock(&ALBuf->lock); + return AL_INVALID_OPERATION; + } + + temp = realloc(ALBuf->data, (size_t)newsize); + if(!temp && newsize) + { + WriteUnlock(&ALBuf->lock); + return AL_OUT_OF_MEMORY; + } + ALBuf->data = temp; + + if(data != NULL) + ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames, align); + + if(storesrc) + { + ALBuf->OriginalChannels = SrcChannels; + ALBuf->OriginalType = SrcType; + if(SrcType == UserFmtIMA4) + { + ALsizei byte_align = ((align-1)/2 + 4) * ChannelsFromUserFmt(SrcChannels); + ALBuf->OriginalSize = frames / align * byte_align; + ALBuf->OriginalAlign = align; + } + else if(SrcType == UserFmtMSADPCM) + { + ALsizei byte_align = ((align-2)/2 + 7) * ChannelsFromUserFmt(SrcChannels); + ALBuf->OriginalSize = frames / align * byte_align; + ALBuf->OriginalAlign = align; + } + else + { + ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType); + ALBuf->OriginalAlign = 1; + } + } + else + { + ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels; + ALBuf->OriginalType = (enum UserFmtType)DstType; + ALBuf->OriginalSize = frames * NewBytes * NewChannels; + ALBuf->OriginalAlign = 1; + } + + ALBuf->Frequency = freq; + ALBuf->FmtChannels = DstChannels; + ALBuf->FmtType = DstType; + ALBuf->Format = NewFormat; + + ALBuf->SampleLen = frames; + ALBuf->LoopStart = 0; + ALBuf->LoopEnd = ALBuf->SampleLen; + + WriteUnlock(&ALBuf->lock); + return AL_NO_ERROR; +} + + +ALuint BytesFromUserFmt(enum UserFmtType type) +{ + switch(type) + { + case UserFmtByte: return sizeof(ALbyte); + case UserFmtUByte: return sizeof(ALubyte); + case UserFmtShort: return sizeof(ALshort); + case UserFmtUShort: return sizeof(ALushort); + case UserFmtInt: return sizeof(ALint); + case UserFmtUInt: return sizeof(ALuint); + case UserFmtFloat: return sizeof(ALfloat); + case UserFmtDouble: return sizeof(ALdouble); + case UserFmtByte3: return sizeof(ALbyte[3]); + case UserFmtUByte3: return sizeof(ALubyte[3]); + case UserFmtMulaw: return sizeof(ALubyte); + case UserFmtAlaw: return sizeof(ALubyte); + case UserFmtIMA4: break; /* not handled here */ + case UserFmtMSADPCM: break; /* not handled here */ + } + return 0; +} +ALuint ChannelsFromUserFmt(enum UserFmtChannels chans) +{ + switch(chans) + { + case UserFmtMono: return 1; + case UserFmtStereo: return 2; + case UserFmtRear: return 2; + case UserFmtQuad: return 4; + case UserFmtX51: return 6; + case UserFmtX61: return 7; + case UserFmtX71: return 8; + } + return 0; +} +static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, + enum UserFmtType *type) +{ + static const struct { + ALenum format; + enum UserFmtChannels channels; + enum UserFmtType type; + } list[] = { + { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte }, + { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort }, + { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat }, + { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble }, + { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 }, + { AL_FORMAT_MONO_MSADPCM_SOFT, UserFmtMono, UserFmtMSADPCM }, + { AL_FORMAT_MONO_MULAW, UserFmtMono, UserFmtMulaw }, + { AL_FORMAT_MONO_ALAW_EXT, UserFmtMono, UserFmtAlaw }, + + { AL_FORMAT_STEREO8, UserFmtStereo, UserFmtUByte }, + { AL_FORMAT_STEREO16, UserFmtStereo, UserFmtShort }, + { AL_FORMAT_STEREO_FLOAT32, UserFmtStereo, UserFmtFloat }, + { AL_FORMAT_STEREO_DOUBLE_EXT, UserFmtStereo, UserFmtDouble }, + { AL_FORMAT_STEREO_IMA4, UserFmtStereo, UserFmtIMA4 }, + { AL_FORMAT_STEREO_MSADPCM_SOFT, UserFmtStereo, UserFmtMSADPCM }, + { AL_FORMAT_STEREO_MULAW, UserFmtStereo, UserFmtMulaw }, + { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw }, + + { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte }, + { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort }, + { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat }, + { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw }, + + { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte }, + { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort }, + + { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte }, + { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort }, + { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat }, + { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw }, + + { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte }, + { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort }, + { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat }, + { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw }, + + { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte }, + { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort }, + { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat }, + { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw }, + + { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte }, + { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort }, + { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat }, + { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw }, + }; + ALuint i; + + for(i = 0;i < COUNTOF(list);i++) + { + if(list[i].format == format) + { + *chans = list[i].channels; + *type = list[i].type; + return AL_TRUE; + } + } + + return AL_FALSE; +} + +ALuint BytesFromFmt(enum FmtType type) +{ + switch(type) + { + case FmtByte: return sizeof(ALbyte); + case FmtShort: return sizeof(ALshort); + case FmtFloat: return sizeof(ALfloat); + } + return 0; +} +ALuint ChannelsFromFmt(enum FmtChannels chans) +{ + switch(chans) + { + case FmtMono: return 1; + case FmtStereo: return 2; + case FmtRear: return 2; + case FmtQuad: return 4; + case FmtX51: return 6; + case FmtX61: return 7; + case FmtX71: return 8; + } + return 0; +} +static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) +{ + static const struct { + ALenum format; + enum FmtChannels channels; + enum FmtType type; + } list[] = { + { AL_MONO8_SOFT, FmtMono, FmtByte }, + { AL_MONO16_SOFT, FmtMono, FmtShort }, + { AL_MONO32F_SOFT, FmtMono, FmtFloat }, + + { AL_STEREO8_SOFT, FmtStereo, FmtByte }, + { AL_STEREO16_SOFT, FmtStereo, FmtShort }, + { AL_STEREO32F_SOFT, FmtStereo, FmtFloat }, + + { AL_REAR8_SOFT, FmtRear, FmtByte }, + { AL_REAR16_SOFT, FmtRear, FmtShort }, + { AL_REAR32F_SOFT, FmtRear, FmtFloat }, + + { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte }, + { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort }, + + { AL_QUAD8_SOFT, FmtQuad, FmtByte }, + { AL_QUAD16_SOFT, FmtQuad, FmtShort }, + { AL_QUAD32F_SOFT, FmtQuad, FmtFloat }, + + { AL_5POINT1_8_SOFT, FmtX51, FmtByte }, + { AL_5POINT1_16_SOFT, FmtX51, FmtShort }, + { AL_5POINT1_32F_SOFT, FmtX51, FmtFloat }, + + { AL_6POINT1_8_SOFT, FmtX61, FmtByte }, + { AL_6POINT1_16_SOFT, FmtX61, FmtShort }, + { AL_6POINT1_32F_SOFT, FmtX61, FmtFloat }, + + { AL_7POINT1_8_SOFT, FmtX71, FmtByte }, + { AL_7POINT1_16_SOFT, FmtX71, FmtShort }, + { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat }, + }; + ALuint i; + + for(i = 0;i < COUNTOF(list);i++) + { + if(list[i].format == format) + { + *chans = list[i].channels; + *type = list[i].type; + return AL_TRUE; + } + } + + return AL_FALSE; +} + +static ALboolean SanitizeAlignment(enum UserFmtType type, ALsizei *align) +{ + if(*align < 0) + return AL_FALSE; + + if(*align == 0) + { + if(type == UserFmtIMA4) + { + /* Here is where things vary: + * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel + * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel + */ + *align = 65; + } + else if(type == UserFmtMSADPCM) + *align = 64; + else + *align = 1; + return AL_TRUE; + } + + if(type == UserFmtIMA4) + { + /* IMA4 block alignment must be a multiple of 8, plus 1. */ + return ((*align)&7) == 1; + } + if(type == UserFmtMSADPCM) + { + /* MSADPCM block alignment must be a multiple of 2. */ + /* FIXME: Too strict? Might only require align*channels to be a + * multiple of 2. */ + return ((*align)&1) == 0; + } + + return AL_TRUE; +} + + +static ALboolean IsValidType(ALenum type) +{ + switch(type) + { + case AL_BYTE_SOFT: + case AL_UNSIGNED_BYTE_SOFT: + case AL_SHORT_SOFT: + case AL_UNSIGNED_SHORT_SOFT: + case AL_INT_SOFT: + case AL_UNSIGNED_INT_SOFT: + case AL_FLOAT_SOFT: + case AL_DOUBLE_SOFT: + case AL_BYTE3_SOFT: + case AL_UNSIGNED_BYTE3_SOFT: + return AL_TRUE; + } + return AL_FALSE; +} + +static ALboolean IsValidChannels(ALenum channels) +{ + switch(channels) + { + case AL_MONO_SOFT: + case AL_STEREO_SOFT: + case AL_REAR_SOFT: + case AL_QUAD_SOFT: + case AL_5POINT1_SOFT: + case AL_6POINT1_SOFT: + case AL_7POINT1_SOFT: + return AL_TRUE; + } + return AL_FALSE; +} + + +ALbuffer *NewBuffer(ALCcontext *context) +{ + ALCdevice *device = context->Device; + ALbuffer *buffer; + ALenum err; + + buffer = calloc(1, sizeof(ALbuffer)); + if(!buffer) + SET_ERROR_AND_RETURN_VALUE(context, AL_OUT_OF_MEMORY, NULL); + RWLockInit(&buffer->lock); + + err = NewThunkEntry(&buffer->id); + if(err == AL_NO_ERROR) + err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer); + if(err != AL_NO_ERROR) + { + FreeThunkEntry(buffer->id); + memset(buffer, 0, sizeof(ALbuffer)); + free(buffer); + + SET_ERROR_AND_RETURN_VALUE(context, err, NULL); + } + + return buffer; +} + +void DeleteBuffer(ALCdevice *device, ALbuffer *buffer) +{ + RemoveBuffer(device, buffer->id); + FreeThunkEntry(buffer->id); + + free(buffer->data); + + memset(buffer, 0, sizeof(*buffer)); + free(buffer); +} + + +/* + * ReleaseALBuffers() + * + * INTERNAL: Called to destroy any buffers that still exist on the device + */ +ALvoid ReleaseALBuffers(ALCdevice *device) +{ + ALsizei i; + for(i = 0;i < device->BufferMap.size;i++) + { + ALbuffer *temp = device->BufferMap.array[i].value; + device->BufferMap.array[i].value = NULL; + + free(temp->data); + + FreeThunkEntry(temp->id); + memset(temp, 0, sizeof(ALbuffer)); + free(temp); + } +} diff --git a/jni/openal-soft-android/OpenAL32/alEffect.c b/jni/openal-soft-1.16.0/OpenAL32/alEffect.c similarity index 100% rename from jni/openal-soft-android/OpenAL32/alEffect.c rename to jni/openal-soft-1.16.0/OpenAL32/alEffect.c diff --git a/jni/openal-soft-android/OpenAL32/alError.c b/jni/openal-soft-1.16.0/OpenAL32/alError.c similarity index 90% rename from jni/openal-soft-android/OpenAL32/alError.c rename to jni/openal-soft-1.16.0/OpenAL32/alError.c index b557532e..9369af56 100644 --- a/jni/openal-soft-android/OpenAL32/alError.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alError.c @@ -35,6 +35,7 @@ ALboolean TrapALError = AL_FALSE; ALvoid alSetError(ALCcontext *Context, ALenum errorCode) { + ALenum curerr = AL_NO_ERROR; if(TrapALError) { #ifdef _WIN32 @@ -45,7 +46,7 @@ ALvoid alSetError(ALCcontext *Context, ALenum errorCode) raise(SIGTRAP); #endif } - CompExchangeInt(&Context->LastError, AL_NO_ERROR, errorCode); + ATOMIC_COMPARE_EXCHANGE_STRONG(ALenum, &Context->LastError, &curerr, errorCode); } AL_API ALenum AL_APIENTRY alGetError(void) @@ -68,7 +69,7 @@ AL_API ALenum AL_APIENTRY alGetError(void) return AL_INVALID_OPERATION; } - errorCode = ExchangeInt(&Context->LastError, AL_NO_ERROR); + errorCode = ATOMIC_EXCHANGE(ALenum, &Context->LastError, AL_NO_ERROR); ALCcontext_DecRef(Context); diff --git a/jni/openal-soft-android/OpenAL32/alExtension.c b/jni/openal-soft-1.16.0/OpenAL32/alExtension.c similarity index 99% rename from jni/openal-soft-android/OpenAL32/alExtension.c rename to jni/openal-soft-1.16.0/OpenAL32/alExtension.c index fc23a932..29f21783 100644 --- a/jni/openal-soft-android/OpenAL32/alExtension.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alExtension.c @@ -38,7 +38,9 @@ const struct EffectList EffectList[] = { { "eaxreverb", EAXREVERB, "AL_EFFECT_EAXREVERB", AL_EFFECT_EAXREVERB }, { "reverb", REVERB, "AL_EFFECT_REVERB", AL_EFFECT_REVERB }, +#if 0 { "autowah", AUTOWAH, "AL_EFFECT_AUTOWAH", AL_EFFECT_AUTOWAH }, +#endif { "chorus", CHORUS, "AL_EFFECT_CHORUS", AL_EFFECT_CHORUS }, { "compressor", COMPRESSOR, "AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR }, { "distortion", DISTORTION, "AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION }, diff --git a/jni/openal-soft-android/OpenAL32/alFilter.c b/jni/openal-soft-1.16.0/OpenAL32/alFilter.c similarity index 67% rename from jni/openal-soft-android/OpenAL32/alFilter.c rename to jni/openal-soft-1.16.0/OpenAL32/alFilter.c index 692109f5..acfae8a6 100644 --- a/jni/openal-soft-android/OpenAL32/alFilter.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alFilter.c @@ -32,7 +32,6 @@ extern inline struct ALfilter *LookupFilter(ALCdevice *device, ALuint id); extern inline struct ALfilter *RemoveFilter(ALCdevice *device, ALuint id); extern inline ALfloat ALfilterState_processSingle(ALfilterState *filter, ALfloat sample); -extern inline ALfloat ALfilterState_processSingleC(const ALfilterState *filter, ALfloat sample); static void InitFilterParams(ALfilter *filter, ALenum type); @@ -146,7 +145,8 @@ AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint value) { if(param == AL_FILTER_TYPE) { - if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS) + if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS || + value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS) InitFilterParams(ALFilter, value); else alSetError(Context, AL_INVALID_VALUE); @@ -336,7 +336,7 @@ void ALfilterState_clear(ALfilterState *filter) filter->y[1] = 0.0f; } -void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_scale, ALfloat bandwidth) +void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat gain, ALfloat freq_mult, ALfloat bandwidth) { ALfloat alpha; ALfloat w0; @@ -344,50 +344,28 @@ void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat g // Limit gain to -100dB gain = maxf(gain, 0.00001f); - w0 = F_2PI * freq_scale; + w0 = F_2PI * freq_mult; /* Calculate filter coefficients depending on filter type */ switch(type) { case ALfilterType_HighShelf: - alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f/gain) * - (1.0f/0.75f - 1.0f) + 2.0f); - filter->b[0] = gain * ((gain + 1.0f) + - (gain - 1.0f) * cosf(w0) + - 2.0f * sqrtf(gain) * alpha); - filter->b[1] = -2.0f * gain * ((gain - 1.0f) + - (gain + 1.0f) * cosf(w0)); - filter->b[2] = gain * ((gain + 1.0f) + - (gain - 1.0f) * cosf(w0) - - 2.0f * sqrtf(gain) * alpha); - filter->a[0] = (gain + 1.0f) - - (gain - 1.0f) * cosf(w0) + - 2.0f * sqrtf(gain) * alpha; - filter->a[1] = 2.0f * ((gain - 1.0f) - - (gain + 1.0f) * cosf(w0)); - filter->a[2] = (gain + 1.0f) - - (gain - 1.0f) * cosf(w0) - - 2.0f * sqrtf(gain) * alpha; + alpha = sinf(w0)/2.0f*sqrtf((gain + 1.0f/gain)*(1.0f/0.75f - 1.0f) + 2.0f); + filter->b[0] = gain*((gain+1.0f) + (gain-1.0f)*cosf(w0) + 2.0f*sqrtf(gain)*alpha); + filter->b[1] = -2.0f*gain*((gain-1.0f) + (gain+1.0f)*cosf(w0) ); + filter->b[2] = gain*((gain+1.0f) + (gain-1.0f)*cosf(w0) - 2.0f*sqrtf(gain)*alpha); + filter->a[0] = (gain+1.0f) - (gain-1.0f)*cosf(w0) + 2.0f*sqrtf(gain)*alpha; + filter->a[1] = 2.0f* ((gain-1.0f) - (gain+1.0f)*cosf(w0) ); + filter->a[2] = (gain+1.0f) - (gain-1.0f)*cosf(w0) - 2.0f*sqrtf(gain)*alpha; break; case ALfilterType_LowShelf: - alpha = sinf(w0) / 2.0f * sqrtf((gain + 1.0f / gain) * - (1.0f / 0.75f - 1.0f) + 2.0f); - filter->b[0] = gain * ((gain + 1.0f) - - (gain - 1.0f) * cosf(w0) + - 2.0f * sqrtf(gain) * alpha); - filter->b[1] = 2.0f * gain * ((gain - 1.0f) - - (gain + 1.0f) * cosf(w0)); - filter->b[2] = gain * ((gain + 1.0f) - - (gain - 1.0f) * cosf(w0) - - 2.0f * sqrtf(gain) * alpha); - filter->a[0] = (gain + 1.0f) + - (gain - 1.0f) * cosf(w0) + - 2.0f * sqrtf(gain) * alpha; - filter->a[1] = -2.0f * ((gain - 1.0f) + - (gain + 1.0f) * cosf(w0)); - filter->a[2] = (gain + 1.0f) + - (gain - 1.0f) * cosf(w0) - - 2.0f * sqrtf(gain) * alpha; + alpha = sinf(w0)/2.0f*sqrtf((gain + 1.0f/gain)*(1.0f/0.75f - 1.0f) + 2.0f); + filter->b[0] = gain*((gain+1.0f) - (gain-1.0f)*cosf(w0) + 2.0f*sqrtf(gain)*alpha); + filter->b[1] = 2.0f*gain*((gain-1.0f) - (gain+1.0f)*cosf(w0) ); + filter->b[2] = gain*((gain+1.0f) - (gain-1.0f)*cosf(w0) - 2.0f*sqrtf(gain)*alpha); + filter->a[0] = (gain+1.0f) + (gain-1.0f)*cosf(w0) + 2.0f*sqrtf(gain)*alpha; + filter->a[1] = -2.0f* ((gain-1.0f) + (gain+1.0f)*cosf(w0) ); + filter->a[2] = (gain+1.0f) + (gain-1.0f)*cosf(w0) - 2.0f*sqrtf(gain)*alpha; break; case ALfilterType_Peaking: alpha = sinf(w0) * sinhf(logf(2.0f) / 2.0f * bandwidth * w0 / sinf(w0)); @@ -434,6 +412,8 @@ void ALfilterState_setParams(ALfilterState *filter, ALfilterType type, ALfloat g filter->a[2] /= filter->a[0]; filter->a[1] /= filter->a[0]; filter->a[0] /= filter->a[0]; + + filter->process = ALfilterState_processC; } @@ -492,6 +472,126 @@ static void lp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, A } +static void hp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void hp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void hp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) +{ + switch(param) + { + case AL_HIGHPASS_GAIN: + if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->Gain = val; + break; + + case AL_HIGHPASS_GAINLF: + if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->GainLF = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void hp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + hp_SetParamf(filter, context, param, vals[0]); +} + +static void hp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void hp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void hp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) +{ + switch(param) + { + case AL_HIGHPASS_GAIN: + *val = filter->Gain; + break; + + case AL_HIGHPASS_GAINLF: + *val = filter->GainLF; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void hp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +{ + hp_GetParamf(filter, context, param, vals); +} + + +static void bp_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void bp_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void bp_SetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat val) +{ + switch(param) + { + case AL_BANDPASS_GAIN: + if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->Gain = val; + break; + + case AL_BANDPASS_GAINHF: + if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->GainHF = val; + break; + + case AL_BANDPASS_GAINLF: + if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF)) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + filter->GainLF = val; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void bp_SetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, const ALfloat *vals) +{ + bp_SetParamf(filter, context, param, vals[0]); +} + +static void bp_GetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(val)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void bp_GetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint *UNUSED(vals)) +{ SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } +static void bp_GetParamf(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *val) +{ + switch(param) + { + case AL_BANDPASS_GAIN: + *val = filter->Gain; + break; + + case AL_BANDPASS_GAINHF: + *val = filter->GainHF; + break; + + case AL_BANDPASS_GAINLF: + *val = filter->GainLF; + break; + + default: + SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); + } +} +static void bp_GetParamfv(ALfilter *filter, ALCcontext *context, ALenum param, ALfloat *vals) +{ + bp_GetParamf(filter, context, param, vals); +} + + static void null_SetParami(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), ALint UNUSED(val)) { SET_ERROR_AND_RETURN(context, AL_INVALID_ENUM); } static void null_SetParamiv(ALfilter *UNUSED(filter), ALCcontext *context, ALenum UNUSED(param), const ALint *UNUSED(vals)) @@ -533,6 +633,9 @@ static void InitFilterParams(ALfilter *filter, ALenum type) { filter->Gain = AL_LOWPASS_DEFAULT_GAIN; filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF; + filter->HFReference = LOWPASSFREQREF; + filter->GainLF = 1.0f; + filter->LFReference = HIGHPASSFREQREF; filter->SetParami = lp_SetParami; filter->SetParamiv = lp_SetParamiv; @@ -543,8 +646,48 @@ static void InitFilterParams(ALfilter *filter, ALenum type) filter->GetParamf = lp_GetParamf; filter->GetParamfv = lp_GetParamfv; } + else if(type == AL_FILTER_HIGHPASS) + { + filter->Gain = AL_HIGHPASS_DEFAULT_GAIN; + filter->GainHF = 1.0f; + filter->HFReference = LOWPASSFREQREF; + filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF; + filter->LFReference = HIGHPASSFREQREF; + + filter->SetParami = hp_SetParami; + filter->SetParamiv = hp_SetParamiv; + filter->SetParamf = hp_SetParamf; + filter->SetParamfv = hp_SetParamfv; + filter->GetParami = hp_GetParami; + filter->GetParamiv = hp_GetParamiv; + filter->GetParamf = hp_GetParamf; + filter->GetParamfv = hp_GetParamfv; + } + else if(type == AL_FILTER_BANDPASS) + { + filter->Gain = AL_BANDPASS_DEFAULT_GAIN; + filter->GainHF = AL_BANDPASS_DEFAULT_GAINHF; + filter->HFReference = LOWPASSFREQREF; + filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF; + filter->LFReference = HIGHPASSFREQREF; + + filter->SetParami = bp_SetParami; + filter->SetParamiv = bp_SetParamiv; + filter->SetParamf = bp_SetParamf; + filter->SetParamfv = bp_SetParamfv; + filter->GetParami = bp_GetParami; + filter->GetParamiv = bp_GetParamiv; + filter->GetParamf = bp_GetParamf; + filter->GetParamfv = bp_GetParamfv; + } else { + filter->Gain = 1.0f; + filter->GainHF = 1.0f; + filter->HFReference = LOWPASSFREQREF; + filter->GainLF = 1.0f; + filter->LFReference = HIGHPASSFREQREF; + filter->SetParami = null_SetParami; filter->SetParamiv = null_SetParamiv; filter->SetParamf = null_SetParamf; diff --git a/jni/openal-soft-android/OpenAL32/alFontsound.c b/jni/openal-soft-1.16.0/OpenAL32/alFontsound.c similarity index 92% rename from jni/openal-soft-android/OpenAL32/alFontsound.c rename to jni/openal-soft-1.16.0/OpenAL32/alFontsound.c index 94cf3064..3a8f1460 100644 --- a/jni/openal-soft-android/OpenAL32/alFontsound.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alFontsound.c @@ -8,6 +8,7 @@ #include "alMidi.h" #include "alError.h" #include "alThunk.h" +#include "alBuffer.h" #include "midi/base.h" @@ -15,13 +16,21 @@ extern inline struct ALfontsound *LookupFontsound(ALCdevice *device, ALuint id); extern inline struct ALfontsound *RemoveFontsound(ALCdevice *device, ALuint id); + static void ALfontsound_Construct(ALfontsound *self); -void ALfontsound_Destruct(ALfontsound *self); +static void ALfontsound_Destruct(ALfontsound *self); void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value); static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage); void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint value); static void ALfontsound_getModStagei(ALfontsound *self, ALCcontext *context, ALsizei stage, ALenum param, ALint *values); +static inline struct ALsfmodulator *LookupModulator(ALfontsound *sound, ALuint id) +{ + ALsfmodulator *mod = LookupUIntMapKey(&sound->ModulatorMap, id>>2); + if(mod) mod += id&3; + return mod; +} + AL_API void AL_APIENTRY alGenFontsoundsSOFT(ALsizei n, ALuint *ids) { @@ -69,19 +78,14 @@ AL_API ALvoid AL_APIENTRY alDeleteFontsoundsSOFT(ALsizei n, const ALuint *ids) /* Check for valid ID */ if((inst=LookupFontsound(device, ids[i])) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(inst->ref != 0) + if(ReadRef(&inst->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); } for(i = 0;i < n;i++) { - if((inst=RemoveFontsound(device, ids[i])) == NULL) - continue; - - ALfontsound_Destruct(inst); - - memset(inst, 0, sizeof(*inst)); - free(inst); + if((inst=LookupFontsound(device, ids[i])) != NULL) + DeleteFontsound(device, inst); } done: @@ -115,7 +119,7 @@ AL_API void AL_APIENTRY alFontsoundiSOFT(ALuint id, ALenum param, ALint value) device = context->Device; if(!(sound=LookupFontsound(device, id))) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(sound->ref != 0) + if(ReadRef(&sound->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); ALfontsound_setPropi(sound, context, param, value); @@ -136,7 +140,7 @@ AL_API void AL_APIENTRY alFontsound2iSOFT(ALuint id, ALenum param, ALint value1, device = context->Device; if(!(sound=LookupFontsound(device, id))) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(sound->ref != 0) + if(ReadRef(&sound->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); switch(param) { @@ -231,7 +235,7 @@ AL_API void AL_APIENTRY alFontsoundivSOFT(ALuint id, ALenum param, const ALint * device = context->Device; if(!(sound=LookupFontsound(device, id))) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(sound->ref != 0) + if(ReadRef(&sound->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); switch(param) { @@ -257,6 +261,10 @@ AL_API void AL_APIENTRY alGetFontsoundivSOFT(ALuint id, ALenum param, ALint *val SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); switch(param) { + case AL_BUFFER: + values[0] = (sound->Buffer ? sound->Buffer->id : 0); + break; + case AL_MOD_LFO_TO_PITCH_SOFT: values[0] = sound->ModLfoToPitch; break; @@ -505,10 +513,22 @@ ALfontsound *NewFontsound(ALCcontext *context) return sound; } +void DeleteFontsound(ALCdevice *device, ALfontsound *sound) +{ + RemoveFontsound(device, sound->id); + + ALfontsound_Destruct(sound); + + memset(sound, 0, sizeof(*sound)); + free(sound); +} + static void ALfontsound_Construct(ALfontsound *self) { - self->ref = 0; + InitRef(&self->ref, 0); + + self->Buffer = NULL; self->MinKey = 0; self->MaxKey = 127; @@ -580,13 +600,16 @@ static void ALfontsound_Construct(ALfontsound *self) self->id = 0; } -void ALfontsound_Destruct(ALfontsound *self) +static void ALfontsound_Destruct(ALfontsound *self) { ALsizei i; FreeThunkEntry(self->id); self->id = 0; + if(self->Buffer) + DecrementRef(&self->Buffer->ref); + self->Buffer = NULL; if(self->Link) DecrementRef(&self->Link->ref); self->Link = NULL; @@ -602,9 +625,26 @@ void ALfontsound_Destruct(ALfontsound *self) void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, ALint value) { ALfontsound *link; + ALbuffer *buffer; switch(param) { + case AL_BUFFER: + buffer = value ? LookupBuffer(context->Device, value) : NULL; + if(value && !buffer) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + else if(buffer) + { + /* Buffer must have a non-0 length, and must be mono. */ + if(buffer->SampleLen <= 0 || buffer->FmtChannels != FmtMono) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + } + + if(buffer) IncrementRef(&buffer->ref); + if((buffer=ExchangePtr((XchgPtr*)&self->Buffer, buffer)) != NULL) + DecrementRef(&buffer->ref); + break; + case AL_MOD_LFO_TO_PITCH_SOFT: self->ModLfoToPitch = value; break; @@ -787,17 +827,13 @@ void ALfontsound_setPropi(ALfontsound *self, ALCcontext *context, ALenum param, break; case AL_FONTSOUND_LINK_SOFT: - if(!value) - link = NULL; - else - { - link = LookupFontsound(context->Device, value); - if(!link) - SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); - } + link = value ? LookupFontsound(context->Device, value) : NULL; + if(value && !link) + SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); + if(link) IncrementRef(&link->ref); - link = ExchangePtr((XchgPtr*)&self->Link, link); - if(link) DecrementRef(&link->ref); + if((link=ExchangePtr((XchgPtr*)&self->Link, link)) != NULL) + DecrementRef(&link->ref); break; default: @@ -812,15 +848,18 @@ static ALsfmodulator *ALfontsound_getModStage(ALfontsound *self, ALsizei stage) { static const ALsfmodulator moddef = { { { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT }, - { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT } - }, + { AL_ONE_SOFT, AL_UNORM_SOFT, AL_LINEAR_SOFT } }, 0, AL_LINEAR_SOFT, AL_NONE }; - ret = malloc(sizeof(*ret)); - *ret = moddef; - InsertUIntMapEntry(&self->ModulatorMap, stage, ret); + ret = malloc(sizeof(ALsfmodulator[4])); + ret[0] = moddef; + ret[1] = moddef; + ret[2] = moddef; + ret[3] = moddef; + InsertUIntMapEntry(&self->ModulatorMap, stage>>2, ret); + ret += stage&3; } return ret; } @@ -829,7 +868,7 @@ void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei st { ALint srcidx = 0; - if(self->ref != 0) + if(ReadRef(&self->ref) != 0) SET_ERROR_AND_RETURN(context, AL_INVALID_OPERATION); switch(param) { @@ -841,10 +880,7 @@ void ALfontsound_setModStagei(ALfontsound *self, ALCcontext *context, ALsizei st value == AL_NOTEON_KEY_SOFT || value == AL_KEYPRESSURE_SOFT || value == AL_CHANNELPRESSURE_SOFT || value == AL_PITCHBEND_SOFT || value == AL_PITCHBEND_SENSITIVITY_SOFT || - (value > 0 && value < 120 && !(value == 6 || (value >= 32 && value <= 63) || - (value >= 98 && value <= 101)) - ) - )) + IsValidCtrlInput(value))) SET_ERROR_AND_RETURN(context, AL_INVALID_VALUE); ALfontsound_getModStage(self, stage)->Source[srcidx].Input = value; break; diff --git a/jni/openal-soft-android/OpenAL32/alListener.c b/jni/openal-soft-1.16.0/OpenAL32/alListener.c similarity index 97% rename from jni/openal-soft-android/OpenAL32/alListener.c rename to jni/openal-soft-1.16.0/OpenAL32/alListener.c index 87cd3c61..0baae82e 100644 --- a/jni/openal-soft-android/OpenAL32/alListener.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alListener.c @@ -40,7 +40,7 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->Listener->Gain = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; case AL_METERS_PER_UNIT: @@ -48,7 +48,7 @@ AL_API ALvoid AL_APIENTRY alListenerf(ALenum param, ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->Listener->MetersPerUnit = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; default: @@ -77,7 +77,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val context->Listener->Position[0] = value1; context->Listener->Position[1] = value2; context->Listener->Position[2] = value3; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); UnlockContext(context); break; @@ -89,7 +89,7 @@ AL_API ALvoid AL_APIENTRY alListener3f(ALenum param, ALfloat value1, ALfloat val context->Listener->Velocity[0] = value1; context->Listener->Velocity[1] = value2; context->Listener->Velocity[2] = value3; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); UnlockContext(context); break; @@ -142,7 +142,7 @@ AL_API ALvoid AL_APIENTRY alListenerfv(ALenum param, const ALfloat *values) context->Listener->Up[0] = values[3]; context->Listener->Up[1] = values[4]; context->Listener->Up[2] = values[5]; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); UnlockContext(context); break; diff --git a/jni/openal-soft-android/OpenAL32/alMidi.c b/jni/openal-soft-1.16.0/OpenAL32/alMidi.c similarity index 93% rename from jni/openal-soft-android/OpenAL32/alMidi.c rename to jni/openal-soft-1.16.0/OpenAL32/alMidi.c index 0679b64c..015b1915 100644 --- a/jni/openal-soft-android/OpenAL32/alMidi.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alMidi.c @@ -19,7 +19,9 @@ MidiSynth *SynthCreate(ALCdevice *device) { - MidiSynth *synth = FSynth_create(device); + MidiSynth *synth = NULL; + if(!synth) synth = SSynth_create(device); + if(!synth) synth = FSynth_create(device); if(!synth) synth = DSynth_create(device); return synth; } @@ -99,18 +101,12 @@ AL_API void AL_APIENTRY alMidiSysExSOFT(ALuint64SOFT time, const ALbyte *data, A ALCdevice *device; ALCcontext *context; ALenum err; - ALsizei i; context = GetContextRef(); if(!context) return; if(!data || size < 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - for(i = 0;i < size;i++) - { - if((data[i]&0x80)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - } device = context->Device; ALCdevice_Lock(device); @@ -133,7 +129,7 @@ AL_API void AL_APIENTRY alMidiPlaySOFT(void) synth = context->Device->Synth; WriteLock(&synth->Lock); - V(synth,setState)(AL_PLAYING); + MidiSynth_setState(synth, AL_PLAYING); WriteUnlock(&synth->Lock); ALCcontext_DecRef(context); @@ -149,7 +145,7 @@ AL_API void AL_APIENTRY alMidiPauseSOFT(void) synth = context->Device->Synth; WriteLock(&synth->Lock); - V(synth,setState)(AL_PAUSED); + MidiSynth_setState(synth, AL_PAUSED); WriteUnlock(&synth->Lock); ALCcontext_DecRef(context); @@ -168,7 +164,7 @@ AL_API void AL_APIENTRY alMidiStopSOFT(void) synth = device->Synth; WriteLock(&synth->Lock); - V(synth,setState)(AL_STOPPED); + MidiSynth_setState(synth, AL_STOPPED); ALCdevice_Lock(device); V0(synth,stop)(); @@ -191,7 +187,7 @@ AL_API void AL_APIENTRY alMidiResetSOFT(void) synth = device->Synth; WriteLock(&synth->Lock); - V(synth,setState)(AL_INITIAL); + MidiSynth_setState(synth, AL_INITIAL); ALCdevice_Lock(device); V0(synth,reset)(); diff --git a/jni/openal-soft-android/OpenAL32/alPreset.c b/jni/openal-soft-1.16.0/OpenAL32/alPreset.c similarity index 94% rename from jni/openal-soft-android/OpenAL32/alPreset.c rename to jni/openal-soft-1.16.0/OpenAL32/alPreset.c index d34772a4..1934ba05 100644 --- a/jni/openal-soft-android/OpenAL32/alPreset.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alPreset.c @@ -16,7 +16,7 @@ extern inline struct ALsfpreset *LookupPreset(ALCdevice *device, ALuint id); extern inline struct ALsfpreset *RemovePreset(ALCdevice *device, ALuint id); static void ALsfpreset_Construct(ALsfpreset *self); -void ALsfpreset_Destruct(ALsfpreset *self); +static void ALsfpreset_Destruct(ALsfpreset *self); AL_API void AL_APIENTRY alGenPresetsSOFT(ALsizei n, ALuint *ids) @@ -65,15 +65,14 @@ AL_API ALvoid AL_APIENTRY alDeletePresetsSOFT(ALsizei n, const ALuint *ids) /* Check for valid ID */ if((preset=LookupPreset(device, ids[i])) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(preset->ref != 0) + if(ReadRef(&preset->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); } for(i = 0;i < n;i++) { - if((preset=LookupPreset(device, ids[i])) == NULL) - continue; - DeletePreset(preset, device); + if((preset=LookupPreset(device, ids[i])) != NULL) + DeletePreset(device, preset); } done: @@ -107,7 +106,7 @@ AL_API void AL_APIENTRY alPresetiSOFT(ALuint id, ALenum param, ALint value) device = context->Device; if((preset=LookupPreset(device, id)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(preset->ref != 0) + if(ReadRef(&preset->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); switch(param) { @@ -151,7 +150,7 @@ AL_API void AL_APIENTRY alPresetivSOFT(ALuint id, ALenum param, const ALint *val device = context->Device; if((preset=LookupPreset(device, id)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(preset->ref != 0) + if(ReadRef(&preset->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); switch(param) { @@ -220,7 +219,7 @@ AL_API void AL_APIENTRY alPresetFontsoundsSOFT(ALuint id, ALsizei count, const A if(count < 0) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - if(preset->ref != 0) + if(ReadRef(&preset->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); if(count == 0) @@ -282,7 +281,7 @@ ALsfpreset *NewPreset(ALCcontext *context) return preset; } -void DeletePreset(ALsfpreset *preset, ALCdevice *device) +void DeletePreset(ALCdevice *device, ALsfpreset *preset) { RemovePreset(device, preset->id); @@ -294,7 +293,7 @@ void DeletePreset(ALsfpreset *preset, ALCdevice *device) static void ALsfpreset_Construct(ALsfpreset *self) { - self->ref = 0; + InitRef(&self->ref, 0); self->Preset = 0; self->Bank = 0; @@ -305,7 +304,7 @@ static void ALsfpreset_Construct(ALsfpreset *self) self->id = 0; } -void ALsfpreset_Destruct(ALsfpreset *self) +static void ALsfpreset_Destruct(ALsfpreset *self) { ALsizei i; diff --git a/jni/openal-soft-android/OpenAL32/alSoundfont.c b/jni/openal-soft-1.16.0/OpenAL32/alSoundfont.c similarity index 64% rename from jni/openal-soft-android/OpenAL32/alSoundfont.c rename to jni/openal-soft-1.16.0/OpenAL32/alSoundfont.c index 355c5b41..30c97a3a 100644 --- a/jni/openal-soft-android/OpenAL32/alSoundfont.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alSoundfont.c @@ -4,11 +4,13 @@ #include #include #include +#include #include "alMain.h" #include "alMidi.h" #include "alThunk.h" #include "alError.h" +#include #include "midi/base.h" @@ -16,8 +18,8 @@ extern inline struct ALsoundfont *LookupSfont(ALCdevice *device, ALuint id); extern inline struct ALsoundfont *RemoveSfont(ALCdevice *device, ALuint id); -void ALsoundfont_Construct(ALsoundfont *self); -void ALsoundfont_Destruct(ALsoundfont *self); +static void ALsoundfont_Construct(ALsoundfont *self); +static void ALsoundfont_Destruct(ALsoundfont *self); void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device); ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context); static size_t ALsoundfont_read(ALvoid *buf, size_t bytes, ALvoid *ptr); @@ -91,7 +93,7 @@ AL_API ALvoid AL_APIENTRY alDeleteSoundfontsSOFT(ALsizei n, const ALuint *ids) } else if((sfont=LookupSfont(device, ids[i])) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(sfont->Mapped != AL_FALSE || sfont->ref != 0) + if(ReadRef(&sfont->ref) != 0) SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); } @@ -136,137 +138,6 @@ AL_API ALboolean AL_APIENTRY alIsSoundfontSOFT(ALuint id) return ret; } -AL_API ALvoid AL_APIENTRY alSoundfontSamplesSOFT(ALuint id, ALenum type, ALsizei count, const ALvoid *samples) -{ - ALCdevice *device; - ALCcontext *context; - ALsoundfont *sfont; - void *ptr; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(id == 0) - SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); - if(!(sfont=LookupSfont(device, id))) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(type != AL_SHORT_SOFT) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - if(count <= 0) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - WriteLock(&sfont->Lock); - if(sfont->ref != 0) - alSetError(context, AL_INVALID_OPERATION); - else if(sfont->Mapped) - alSetError(context, AL_INVALID_OPERATION); - else if(!(ptr=realloc(sfont->Samples, count * sizeof(ALshort)))) - alSetError(context, AL_OUT_OF_MEMORY); - else - { - sfont->Samples = ptr; - sfont->NumSamples = count; - if(samples != NULL) - memcpy(sfont->Samples, samples, count * sizeof(ALshort)); - } - WriteUnlock(&sfont->Lock); - -done: - ALCcontext_DecRef(context); -} - -AL_API void AL_APIENTRY alGetSoundfontSamplesSOFT(ALuint id, ALsizei offset, ALsizei count, ALenum type, ALvoid *samples) -{ - ALCdevice *device; - ALCcontext *context; - ALsoundfont *sfont; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(id == 0) - sfont = ALsoundfont_getDefSoundfont(context); - else if(!(sfont=LookupSfont(device, id))) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(type != AL_SHORT_SOFT) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - if(offset < 0 || count <= 0) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - ReadLock(&sfont->Lock); - if(offset >= sfont->NumSamples || count > (sfont->NumSamples-offset)) - alSetError(context, AL_INVALID_VALUE); - else if(sfont->Mapped) - alSetError(context, AL_INVALID_OPERATION); - else - { - /* TODO: Allow conversion. */ - memcpy(samples, sfont->Samples + offset*sizeof(ALshort), count * sizeof(ALshort)); - } - ReadUnlock(&sfont->Lock); - -done: - ALCcontext_DecRef(context); -} - -AL_API ALvoid* AL_APIENTRY alSoundfontMapSamplesSOFT(ALuint id, ALsizei offset, ALsizei length) -{ - ALCdevice *device; - ALCcontext *context; - ALsoundfont *sfont; - ALvoid *ptr = NULL; - - context = GetContextRef(); - if(!context) return NULL; - - device = context->Device; - if(id == 0) - SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); - if(!(sfont=LookupSfont(device, id))) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(offset < 0 || (ALuint)offset > sfont->NumSamples*sizeof(ALshort)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - if(length <= 0 || (ALuint)length > (sfont->NumSamples*sizeof(ALshort) - offset)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - ReadLock(&sfont->Lock); - if(sfont->ref != 0) - alSetError(context, AL_INVALID_OPERATION); - else if(ExchangeInt(&sfont->Mapped, AL_TRUE) == AL_TRUE) - alSetError(context, AL_INVALID_OPERATION); - else - ptr = (ALbyte*)sfont->Samples + offset; - ReadUnlock(&sfont->Lock); - -done: - ALCcontext_DecRef(context); - - return ptr; -} - -AL_API ALvoid AL_APIENTRY alSoundfontUnmapSamplesSOFT(ALuint id) -{ - ALCdevice *device; - ALCcontext *context; - ALsoundfont *sfont; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(id == 0) - SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); - if(!(sfont=LookupSfont(device, id))) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(ExchangeInt(&sfont->Mapped, AL_FALSE) == AL_FALSE) - SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); - -done: - ALCcontext_DecRef(context); -} - AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *values) { ALCdevice *device; @@ -293,14 +164,6 @@ AL_API void AL_APIENTRY alGetSoundfontivSOFT(ALuint id, ALenum param, ALint *val values[i] = sfont->Presets[i]->id; break; - case AL_SAMPLE_LENGTH_SOFT: - values[0] = sfont->NumSamples; - break; - - case AL_FORMAT_TYPE_SOFT: - values[0] = AL_SHORT_SOFT; - break; - default: SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); } @@ -329,7 +192,7 @@ AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const A SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); WriteLock(&sfont->Lock); - if(sfont->ref != 0) + if(ReadRef(&sfont->ref) != 0) { WriteUnlock(&sfont->Lock); SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); @@ -350,6 +213,7 @@ AL_API void AL_APIENTRY alSoundfontPresetsSOFT(ALuint id, ALsizei count, const A { if(!(presets[i]=LookupPreset(device, pids[i]))) { + free(presets); WriteUnlock(&sfont->Lock); SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); } @@ -389,12 +253,7 @@ AL_API void AL_APIENTRY alLoadSoundfontSOFT(ALuint id, size_t(*cb)(ALvoid*,size_ SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); WriteLock(&sfont->Lock); - if(sfont->ref != 0) - { - WriteUnlock(&sfont->Lock); - SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); - } - if(sfont->Mapped) + if(ReadRef(&sfont->ref) != 0) { WriteUnlock(&sfont->Lock); SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); @@ -416,23 +275,19 @@ done: } -void ALsoundfont_Construct(ALsoundfont *self) +static void ALsoundfont_Construct(ALsoundfont *self) { - self->ref = 0; + InitRef(&self->ref, 0); self->Presets = NULL; self->NumPresets = 0; - self->Samples = NULL; - self->NumSamples = 0; - RWLockInit(&self->Lock); - self->Mapped = AL_FALSE; self->id = 0; } -void ALsoundfont_Destruct(ALsoundfont *self) +static void ALsoundfont_Destruct(ALsoundfont *self) { ALsizei i; @@ -447,16 +302,13 @@ void ALsoundfont_Destruct(ALsoundfont *self) free(self->Presets); self->Presets = NULL; self->NumPresets = 0; - - free(self->Samples); - self->Samples = NULL; - self->NumSamples = 0; } ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context) { ALCdevice *device = context->Device; - const char *fname; + al_string fname = AL_STRING_INIT_STATIC(); + const char *namelist; if(device->DefaultSfont) return device->DefaultSfont; @@ -464,25 +316,44 @@ ALsoundfont *ALsoundfont_getDefSoundfont(ALCcontext *context) device->DefaultSfont = calloc(1, sizeof(device->DefaultSfont[0])); ALsoundfont_Construct(device->DefaultSfont); - fname = getenv("ALSOFT_SOUNDFONT"); - if((fname && fname[0]) || ConfigValueStr("midi", "soundfont", &fname)) + namelist = getenv("ALSOFT_SOUNDFONT"); + if(!namelist || !namelist[0]) + ConfigValueStr("midi", "soundfont", &namelist); + while(namelist && namelist[0]) { + const char *next, *end; FILE *f; - f = fopen(fname, "rb"); + while(*namelist && (isspace(*namelist) || *namelist == ',')) + namelist++; + if(!*namelist) + break; + next = strchr(namelist, ','); + end = next ? next++ : (namelist+strlen(namelist)); + while(--end != namelist && isspace(*end)) { + } + if(end == namelist) + continue; + al_string_append_range(&fname, namelist, end+1); + namelist = next; + + f = OpenDataFile(al_string_get_cstr(fname), "openal/soundfonts"); if(f == NULL) - ERR("Failed to open %s\n", fname); + ERR("Failed to open %s\n", al_string_get_cstr(fname)); else { Reader reader; reader.cb = ALsoundfont_read; reader.ptr = f; reader.error = 0; - TRACE("Loading %s\n", fname); + TRACE("Loading %s\n", al_string_get_cstr(fname)); loadSf2(&reader, device->DefaultSfont, context); fclose(f); } + + al_string_clear(&fname); } + AL_STRING_DEINIT(fname); return device->DefaultSfont; } @@ -491,8 +362,10 @@ void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device) { ALsfpreset **presets; ALsizei num_presets; + VECTOR(ALbuffer*) buffers; ALsizei i; + VECTOR_INIT(buffers); presets = ExchangePtr((XchgPtr*)&self->Presets, NULL); num_presets = ExchangeInt(&self->NumPresets, 0); @@ -506,7 +379,8 @@ void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device) sounds = ExchangePtr((XchgPtr*)&preset->Sounds, NULL); num_sounds = ExchangeInt(&preset->NumSounds, 0); - DeletePreset(preset, device); + + DeletePreset(device, preset); preset = NULL; for(j = 0;j < num_sounds;j++) @@ -519,12 +393,21 @@ void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device) deleting = AL_FALSE; for(j = 0;j < num_sounds;j++) { - if(sounds[j] && sounds[j]->ref == 0) + if(sounds[j] && ReadRef(&sounds[j]->ref) == 0) { deleting = AL_TRUE; - RemoveFontsound(device, sounds[j]->id); - ALfontsound_Destruct(sounds[j]); - free(sounds[j]); + if(sounds[j]->Buffer) + { + ALbuffer *buffer = sounds[j]->Buffer; + ALbuffer **iter; + +#define MATCH_BUFFER(_i) (buffer == *(_i)) + VECTOR_FIND_IF(iter, ALbuffer*, buffers, MATCH_BUFFER); + if(iter == VECTOR_ITER_END(buffers)) + VECTOR_PUSH_BACK(buffers, buffer); +#undef MATCH_BUFFER + } + DeleteFontsound(device, sounds[j]); sounds[j] = NULL; } } @@ -534,6 +417,14 @@ void ALsoundfont_deleteSoundfont(ALsoundfont *self, ALCdevice *device) ALsoundfont_Destruct(self); free(self); + +#define DELETE_BUFFER(iter) do { \ + assert(ReadRef(&(*(iter))->ref) == 0); \ + DeleteBuffer(device, *(iter)); \ +} while(0) + VECTOR_FOR_EACH(ALbuffer*, buffers, DELETE_BUFFER); + VECTOR_DEINIT(buffers); +#undef DELETE_BUFFER } diff --git a/jni/openal-soft-android/OpenAL32/alSource.c b/jni/openal-soft-1.16.0/OpenAL32/alSource.c similarity index 78% rename from jni/openal-soft-android/OpenAL32/alSource.c rename to jni/openal-soft-1.16.0/OpenAL32/alSource.c index 543910db..752e2e35 100644 --- a/jni/openal-soft-android/OpenAL32/alSource.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alSource.c @@ -33,6 +33,8 @@ #include "alThunk.h" #include "alAuxEffectSlot.h" +#include "threads.h" + enum Resampler DefaultResampler = LinearResampler; const ALsizei ResamplerPadding[ResamplerMax] = { @@ -98,6 +100,8 @@ typedef enum SrcFloatProp { /* AL_EXT_source_distance_model */ sfDistanceModel = AL_DISTANCE_MODEL, + sfSecLength = AL_SEC_LENGTH_SOFT, + /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */ sfSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT, sfByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT, @@ -140,6 +144,9 @@ typedef enum SrcIntProp { /* AL_EXT_source_distance_model */ siDistanceModel = AL_DISTANCE_MODEL, + siByteLength = AL_BYTE_LENGTH_SOFT, + siSampleLength = AL_SAMPLE_LENGTH_SOFT, + /* AL_SOFT_buffer_sub_data / AL_SOFT_buffer_samples */ siSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT, siByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT, @@ -152,9 +159,9 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint *values); static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, const ALint64SOFT *values); -static ALboolean GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values); -static ALboolean GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values); -static ALboolean GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values); +static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values); +static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values); +static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values); static ALint FloatValsByProp(ALenum prop) { @@ -191,6 +198,7 @@ static ALint FloatValsByProp(ALenum prop) case sfBuffersQueued: case sfBuffersProcessed: case sfSourceType: + case sfSecLength: return 1; case sfSampleRWOffsetsSOFT: @@ -242,6 +250,7 @@ static ALint DoubleValsByProp(ALenum prop) case sfBuffersQueued: case sfBuffersProcessed: case sfSourceType: + case sfSecLength: return 1; case sfSampleRWOffsetsSOFT: @@ -285,6 +294,8 @@ static ALint IntValsByProp(ALenum prop) case siDirectFilter: case siDirectChannelsSOFT: case siDistanceModel: + case siByteLength: + case siSampleLength: return 1; case siSampleRWOffsetsSOFT: @@ -330,6 +341,8 @@ static ALint Int64ValsByProp(ALenum prop) case siDirectFilter: case siDirectChannelsSOFT: case siDistanceModel: + case siByteLength: + case siSampleLength: return 1; case siSampleRWOffsetsSOFT: @@ -362,98 +375,98 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp CHECKVAL(*values >= 0.0f); Source->Pitch = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_INNER_ANGLE: CHECKVAL(*values >= 0.0f && *values <= 360.0f); Source->InnerAngle = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_ANGLE: CHECKVAL(*values >= 0.0f && *values <= 360.0f); Source->OuterAngle = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_GAIN: CHECKVAL(*values >= 0.0f); Source->Gain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MAX_DISTANCE: CHECKVAL(*values >= 0.0f); Source->MaxDistance = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_ROLLOFF_FACTOR: CHECKVAL(*values >= 0.0f); Source->RollOffFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_REFERENCE_DISTANCE: CHECKVAL(*values >= 0.0f); Source->RefDistance = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MIN_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->MinGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_MAX_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->MaxGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_GAIN: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->OuterGain = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_CONE_OUTER_GAINHF: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->OuterGainHF = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AIR_ABSORPTION_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 10.0f); Source->AirAbsorptionFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_ROOM_ROLLOFF_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 10.0f); Source->RoomRolloffFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DOPPLER_FACTOR: CHECKVAL(*values >= 0.0f && *values <= 1.0f); Source->DopplerFactor = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_SEC_OFFSET: @@ -478,6 +491,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp return AL_TRUE; + case sfSecLength: case AL_SEC_OFFSET_LATENCY_SOFT: /* Query only */ SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); @@ -491,7 +505,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp Source->Position[1] = values[1]; Source->Position[2] = values[2]; UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_VELOCITY: @@ -502,7 +516,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp Source->Velocity[1] = values[1]; Source->Velocity[2] = values[2]; UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECTION: @@ -513,7 +527,7 @@ static ALboolean SetSourcefv(ALsource *Source, ALCcontext *Context, SrcFloatProp Source->Orientation[1] = values[1]; Source->Orientation[2] = values[2]; UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; @@ -552,6 +566,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p ALfilter *filter = NULL; ALeffectslot *slot = NULL; ALbufferlistitem *oldlist; + ALbufferlistitem *newlist; ALfloat fvals[3]; switch(prop) @@ -560,7 +575,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->HeadRelative = (ALboolean)*values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_LOOPING: @@ -572,49 +587,39 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p case AL_BUFFER: CHECKVAL(*values == 0 || (buffer=LookupBuffer(device, *values)) != NULL); - LockContext(Context); + WriteLock(&Source->queue_lock); if(!(Source->state == AL_STOPPED || Source->state == AL_INITIAL)) { - UnlockContext(Context); + WriteUnlock(&Source->queue_lock); SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_OPERATION, AL_FALSE); } - Source->BuffersInQueue = 0; - Source->BuffersPlayed = 0; - if(buffer != NULL) { - ALbufferlistitem *BufferListItem; + /* Add the selected buffer to a one-item queue */ + newlist = malloc(sizeof(ALbufferlistitem)); + newlist->buffer = buffer; + newlist->next = NULL; + newlist->prev = NULL; + IncrementRef(&buffer->ref); /* Source is now Static */ Source->SourceType = AL_STATIC; - /* Add the selected buffer to a one-item queue */ - BufferListItem = malloc(sizeof(ALbufferlistitem)); - BufferListItem->buffer = buffer; - BufferListItem->next = NULL; - BufferListItem->prev = NULL; - IncrementRef(&buffer->ref); - - oldlist = ExchangePtr((XchgPtr*)&Source->queue, BufferListItem); - Source->BuffersInQueue = 1; - ReadLock(&buffer->lock); Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels); Source->SampleSize = BytesFromFmt(buffer->FmtType); ReadUnlock(&buffer->lock); - if(buffer->FmtChannels == FmtMono) - Source->Update = CalcSourceParams; - else - Source->Update = CalcNonAttnSourceParams; - Source->NeedsUpdate = AL_TRUE; } else { /* Source is now Undetermined */ Source->SourceType = AL_UNDETERMINED; - oldlist = ExchangePtr((XchgPtr*)&Source->queue, NULL); + newlist = NULL; } + oldlist = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, newlist); + ATOMIC_STORE(&Source->current_buffer, newlist); + WriteUnlock(&Source->queue_lock); /* Delete all elements in the previous queue */ while(oldlist != NULL) @@ -626,7 +631,6 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p DecrementRef(&temp->buffer->ref); free(temp); } - UnlockContext(Context); return AL_TRUE; case siSourceState: @@ -658,6 +662,8 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p return AL_TRUE; + case siByteLength: + case siSampleLength: case siSampleRWOffsetsSOFT: case siByteRWOffsetsSOFT: /* Query only */ @@ -670,44 +676,50 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p LockContext(Context); if(!filter) { - Source->DirectGain = 1.0f; - Source->DirectGainHF = 1.0f; + 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->DirectGain = filter->Gain; - Source->DirectGainHF = filter->GainHF; + Source->Direct.Gain = filter->Gain; + Source->Direct.GainHF = filter->GainHF; + Source->Direct.HFReference = filter->HFReference; + Source->Direct.GainLF = filter->GainLF; + Source->Direct.LFReference = filter->LFReference; } UnlockContext(Context); - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECT_FILTER_GAINHF_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->DryGainHFAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->WetGainAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->WetGainHFAuto = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DIRECT_CHANNELS_SOFT: CHECKVAL(*values == AL_FALSE || *values == AL_TRUE); Source->DirectChannels = *values; - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; case AL_DISTANCE_MODEL: @@ -721,7 +733,7 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p Source->DistanceModel = *values; if(Context->SourceDistanceModel) - Source->NeedsUpdate = AL_TRUE; + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; @@ -745,14 +757,20 @@ static ALboolean SetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp p /* 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; } - Source->NeedsUpdate = AL_TRUE; UnlockContext(Context); + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); return AL_TRUE; @@ -802,6 +820,8 @@ static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp case AL_SOURCE_STATE: case AL_BYTE_OFFSET: case AL_SAMPLE_OFFSET: + case siByteLength: + case siSampleLength: case siSourceType: case siBuffersQueued: case siBuffersProcessed: @@ -862,8 +882,9 @@ static ALboolean SetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp #undef CHECKVAL -static ALboolean GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values) +static ALboolean GetSourcedv(ALsource *Source, ALCcontext *Context, SrcFloatProp prop, ALdouble *values) { + ALbufferlistitem *BufferList; ALdouble offsets[2]; ALdouble updateLen; ALint ivals[3]; @@ -915,9 +936,9 @@ static ALboolean GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFlo case AL_SAMPLE_OFFSET: case AL_BYTE_OFFSET: LockContext(Context); - updateLen = (ALdouble)Context->Device->UpdateSize / - Context->Device->Frequency; - GetSourceOffsets(Source, prop, offsets, updateLen); + ReadLock(&Source->queue_lock); + GetSourceOffsets(Source, prop, offsets, 0.0); + ReadUnlock(&Source->queue_lock); UnlockContext(Context); *values = offsets[0]; return AL_TRUE; @@ -938,18 +959,43 @@ static ALboolean GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFlo *values = Source->DopplerFactor; return AL_TRUE; + case sfSecLength: + ReadLock(&Source->queue_lock); + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) + *values = 0; + else + { + ALint length = 0; + ALsizei freq = 1; + do { + ALbuffer *buffer = BufferList->buffer; + if(buffer && buffer->SampleLen > 0) + { + freq = buffer->Frequency; + length += buffer->SampleLen; + } + } while((BufferList=BufferList->next) != NULL); + *values = (ALdouble)length / (ALdouble)freq; + } + ReadUnlock(&Source->queue_lock); + return AL_TRUE; + case AL_SAMPLE_RW_OFFSETS_SOFT: case AL_BYTE_RW_OFFSETS_SOFT: LockContext(Context); + ReadLock(&Source->queue_lock); updateLen = (ALdouble)Context->Device->UpdateSize / Context->Device->Frequency; GetSourceOffsets(Source, prop, values, updateLen); + ReadUnlock(&Source->queue_lock); UnlockContext(Context); return AL_TRUE; case AL_SEC_OFFSET_LATENCY_SOFT: LockContext(Context); + ReadLock(&Source->queue_lock); values[0] = GetSourceSecOffset(Source); + ReadUnlock(&Source->queue_lock); values[1] = (ALdouble)ALCdevice_GetLatency(Context->Device) / 1000000000.0; UnlockContext(Context); @@ -1000,7 +1046,7 @@ static ALboolean GetSourcedv(const ALsource *Source, ALCcontext *Context, SrcFlo SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE); } -static ALboolean GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values) +static ALboolean GetSourceiv(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint *values) { ALbufferlistitem *BufferList; ALdouble dvals[3]; @@ -1017,32 +1063,89 @@ static ALboolean GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcInt return AL_TRUE; case AL_BUFFER: - LockContext(Context); - BufferList = Source->queue; - if(Source->SourceType != AL_STATIC) - { - ALuint i = Source->BuffersPlayed; - while(i > 0) - { - BufferList = BufferList->next; - i--; - } - } - *values = ((BufferList && BufferList->buffer) ? - BufferList->buffer->id : 0); - UnlockContext(Context); + ReadLock(&Source->queue_lock); + BufferList = (Source->SourceType == AL_STATIC) ? ATOMIC_LOAD(&Source->queue) : + ATOMIC_LOAD(&Source->current_buffer); + *values = (BufferList && BufferList->buffer) ? BufferList->buffer->id : 0; + ReadUnlock(&Source->queue_lock); return AL_TRUE; case AL_SOURCE_STATE: *values = Source->state; return AL_TRUE; + case siByteLength: + ReadLock(&Source->queue_lock); + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) + *values = 0; + else + { + ALint length = 0; + do { + ALbuffer *buffer = BufferList->buffer; + if(buffer && buffer->SampleLen > 0) + { + ALuint byte_align, sample_align; + if(buffer->OriginalType == UserFmtIMA4) + { + ALsizei align = (buffer->OriginalAlign-1)/2 + 4; + byte_align = align * ChannelsFromFmt(buffer->FmtChannels); + sample_align = buffer->OriginalAlign; + } + else if(buffer->OriginalType == UserFmtMSADPCM) + { + ALsizei align = (buffer->OriginalAlign-2)/2 + 7; + byte_align = align * ChannelsFromFmt(buffer->FmtChannels); + sample_align = buffer->OriginalAlign; + } + else + { + ALsizei align = buffer->OriginalAlign; + byte_align = align * ChannelsFromFmt(buffer->FmtChannels); + sample_align = buffer->OriginalAlign; + } + + length += buffer->SampleLen / sample_align * byte_align; + } + } while((BufferList=BufferList->next) != NULL); + *values = length; + } + ReadUnlock(&Source->queue_lock); + return AL_TRUE; + + case siSampleLength: + ReadLock(&Source->queue_lock); + if(!(BufferList=ATOMIC_LOAD(&Source->queue))) + *values = 0; + else + { + ALint length = 0; + do { + ALbuffer *buffer = BufferList->buffer; + if(buffer) length += buffer->SampleLen; + } while((BufferList=BufferList->next) != NULL); + *values = length; + } + ReadUnlock(&Source->queue_lock); + return AL_TRUE; + case AL_BUFFERS_QUEUED: - *values = Source->BuffersInQueue; + 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: - LockContext(Context); + ReadLock(&Source->queue_lock); if(Source->Looping || Source->SourceType != AL_STREAMING) { /* Buffers on a looping source are in a perpetual state of @@ -1050,8 +1153,18 @@ static ALboolean GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcInt *values = 0; } else - *values = Source->BuffersPlayed; - UnlockContext(Context); + { + 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: @@ -1125,7 +1238,7 @@ static ALboolean GetSourceiv(const ALsource *Source, ALCcontext *Context, SrcInt SET_ERROR_AND_RETURN_VALUE(Context, AL_INVALID_ENUM, AL_FALSE); } -static ALboolean GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values) +static ALboolean GetSourcei64v(ALsource *Source, ALCcontext *Context, SrcIntProp prop, ALint64 *values) { ALdouble dvals[3]; ALint ivals[3]; @@ -1135,7 +1248,9 @@ static ALboolean GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcI { case AL_SAMPLE_OFFSET_LATENCY_SOFT: LockContext(Context); + ReadLock(&Source->queue_lock); values[0] = GetSourceOffset(Source); + ReadUnlock(&Source->queue_lock); values[1] = ALCdevice_GetLatency(Context->Device); UnlockContext(Context); return AL_TRUE; @@ -1178,6 +1293,8 @@ static ALboolean GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcI case AL_SOURCE_STATE: case AL_BUFFERS_QUEUED: case AL_BUFFERS_PROCESSED: + case siByteLength: + case siSampleLength: case AL_SOURCE_TYPE: case AL_DIRECT_FILTER_GAINHF_AUTO: case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: @@ -1191,15 +1308,15 @@ static ALboolean GetSourcei64v(const ALsource *Source, ALCcontext *Context, SrcI case siBuffer: case siDirectFilter: if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE) - *values = ((ALuint*)ivals)[0]; + *values = (ALuint)ivals[0]; return err; case siAuxSendFilter: if((err=GetSourceiv(Source, Context, (int)prop, ivals)) != AL_FALSE) { - values[0] = ((ALuint*)ivals)[0]; - values[1] = ((ALuint*)ivals)[1]; - values[2] = ((ALuint*)ivals)[2]; + values[0] = (ALuint)ivals[0]; + values[1] = (ALuint)ivals[1]; + values[2] = (ALuint)ivals[2]; } return err; } @@ -1272,7 +1389,7 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) } for(i = 0;i < n;i++) { - ALsource **srclist, **srclistend; + ALactivesource **srclist, **srclistend; if((Source=RemoveSource(context, sources[i])) == NULL) continue; @@ -1283,24 +1400,26 @@ AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) srclistend = srclist + context->ActiveSourceCount; while(srclist != srclistend) { - if(*srclist == Source) + if((*srclist)->Source == Source) { - context->ActiveSourceCount--; - *srclist = *(--srclistend); + ALactivesource *temp = *(--srclistend); + *srclistend = *srclist; + *srclist = temp; + --(context->ActiveSourceCount); break; } srclist++; } UnlockContext(context); - while(Source->queue != NULL) + BufferList = ATOMIC_EXCHANGE(ALbufferlistitem*, &Source->queue, NULL); + while(BufferList != NULL) { - BufferList = Source->queue; - Source->queue = BufferList->next; - + ALbufferlistitem *next = BufferList->next; if(BufferList->buffer != NULL) DecrementRef(&BufferList->buffer->ref); free(BufferList); + BufferList = next; } for(j = 0;j < MAX_SENDS;++j) @@ -1903,18 +2022,20 @@ AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) LockContext(context); while(n > context->MaxActiveSources-context->ActiveSourceCount) { - void *temp = NULL; + ALactivesource **temp = NULL; ALsizei newcount; newcount = context->MaxActiveSources << 1; if(newcount > 0) temp = realloc(context->ActiveSources, - sizeof(*context->ActiveSources) * newcount); + newcount * sizeof(context->ActiveSources[0])); if(!temp) { UnlockContext(context); SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); } + for(i = context->MaxActiveSources;i < newcount;i++) + temp[i] = NULL; context->ActiveSources = temp; context->MaxActiveSources = newcount; @@ -2041,7 +2162,7 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu ALCcontext *context; ALsource *source; ALsizei i; - ALbufferlistitem *BufferListStart = NULL; + ALbufferlistitem *BufferListStart; ALbufferlistitem *BufferList; ALbuffer *BufferFmt = NULL; @@ -2058,16 +2179,16 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu if((source=LookupSource(context, src)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - LockContext(context); + WriteLock(&source->queue_lock); if(source->SourceType == AL_STATIC) { - UnlockContext(context); + 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 = source->queue; + BufferList = ATOMIC_LOAD(&source->queue); while(BufferList) { if(BufferList->buffer) @@ -2078,13 +2199,15 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu BufferList = BufferList->next; } + BufferListStart = NULL; + BufferList = NULL; for(i = 0;i < nb;i++) { ALbuffer *buffer = NULL; if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == NULL) { - UnlockContext(context); - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); + WriteUnlock(&source->queue_lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, buffer_error); } if(!BufferListStart) @@ -2104,65 +2227,70 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint src, ALsizei nb, const ALu BufferList = BufferList->next; } if(!buffer) continue; + + /* Hold a read lock on each buffer being queued while checking all + * provided buffers. This is done so other threads don't see an extra + * reference on some buffers if this operation ends up failing. */ + ReadLock(&buffer->lock); IncrementRef(&buffer->ref); - ReadLock(&buffer->lock); if(BufferFmt == NULL) { BufferFmt = buffer; source->NumChannels = ChannelsFromFmt(buffer->FmtChannels); source->SampleSize = BytesFromFmt(buffer->FmtType); - if(buffer->FmtChannels == FmtMono) - source->Update = CalcSourceParams; - else - source->Update = CalcNonAttnSourceParams; - - source->NeedsUpdate = AL_TRUE; } else if(BufferFmt->Frequency != buffer->Frequency || BufferFmt->OriginalChannels != buffer->OriginalChannels || BufferFmt->OriginalType != buffer->OriginalType) { - ReadUnlock(&buffer->lock); - UnlockContext(context); - SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); + WriteUnlock(&source->queue_lock); + SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, buffer_error); + + buffer_error: + /* A buffer failed (invalid ID or format), so unlock and release + * each buffer we had. */ + while(BufferList != NULL) + { + ALbufferlistitem *prev = BufferList->prev; + if((buffer=BufferList->buffer) != NULL) + { + DecrementRef(&buffer->ref); + ReadUnlock(&buffer->lock); + } + free(BufferList); + BufferList = prev; + } + goto done; } - ReadUnlock(&buffer->lock); + } + /* All buffers good, unlock them now. */ + while(BufferList != NULL) + { + ALbuffer *buffer = BufferList->buffer; + if(buffer) ReadUnlock(&buffer->lock); + BufferList = BufferList->prev; } /* Source is now streaming */ source->SourceType = AL_STREAMING; - if(source->queue == NULL) - source->queue = BufferListStart; - else + BufferList = NULL; + if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->queue, &BufferList, BufferListStart)) { - /* Append to the end of the queue */ - BufferList = source->queue; + /* Queue head is not NULL, append to the end of the queue */ while(BufferList->next != NULL) BufferList = BufferList->next; BufferListStart->prev = BufferList; BufferList->next = BufferListStart; } - BufferListStart = NULL; - - source->BuffersInQueue += nb; - - UnlockContext(context); + BufferList = NULL; + ATOMIC_COMPARE_EXCHANGE_STRONG(ALbufferlistitem*, &source->current_buffer, &BufferList, BufferListStart); + WriteUnlock(&source->queue_lock); done: - while(BufferListStart) - { - BufferList = BufferListStart; - BufferListStart = BufferList->next; - - if(BufferList->buffer) - DecrementRef(&BufferList->buffer->ref); - free(BufferList); - } - ALCcontext_DecRef(context); } @@ -2170,8 +2298,10 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint { ALCcontext *context; ALsource *source; + ALbufferlistitem *NewHead; + ALbufferlistitem *OldHead; + ALbufferlistitem *Current; ALsizei i; - ALbufferlistitem *BufferList; if(nb == 0) return; @@ -2185,35 +2315,61 @@ AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers(ALuint src, ALsizei nb, ALuint if((source=LookupSource(context, src)) == NULL) SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - LockContext(context); - if(source->Looping || source->SourceType != AL_STREAMING || - (ALuint)nb > source->BuffersPlayed) + WriteLock(&source->queue_lock); + /* Find the new buffer queue head */ + NewHead = ATOMIC_LOAD(&source->queue); + Current = ATOMIC_LOAD(&source->current_buffer); + for(i = 0;i < nb && NewHead;i++) { - UnlockContext(context); + if(NewHead == Current) + break; + NewHead = NewHead->next; + } + if(source->Looping || source->SourceType != AL_STREAMING || i != nb) + { + WriteUnlock(&source->queue_lock); /* Trying to unqueue pending buffers, or a buffer that wasn't queued. */ SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); } - for(i = 0;i < nb;i++) + /* Swap it, and cut the new head from the old. */ + OldHead = ATOMIC_EXCHANGE(ALbufferlistitem*, &source->queue, NewHead); + if(NewHead) { - BufferList = source->queue; - source->queue = BufferList->next; - source->BuffersInQueue--; - source->BuffersPlayed--; + ALCdevice *device = context->Device; + ALbufferlistitem *OldTail = NewHead->prev; + uint count; - if(BufferList->buffer) + /* Cut the new head's link back to the old body. The mixer is robust + * enough to handle the link back going away. Once the active mix (if + * any) is complete, it's safe to finish cutting the old tail from the + * new head. */ + NewHead->prev = NULL; + if(((count=ReadRef(&device->MixCount))&1) != 0) { - buffers[i] = BufferList->buffer->id; - DecrementRef(&BufferList->buffer->ref); + while(count == ReadRef(&device->MixCount)) + althrd_yield(); } - else - buffers[i] = 0; - - free(BufferList); + 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; } - if(source->queue) - source->queue->prev = NULL; - UnlockContext(context); done: ALCcontext_DecRef(context); @@ -2224,6 +2380,8 @@ static ALvoid InitSourceParams(ALsource *Source) { ALuint i; + RWLockInit(&Source->queue_lock); + Source->InnerAngle = 360.0f; Source->OuterAngle = 360.0f; Source->Pitch = 1.0f; @@ -2254,6 +2412,8 @@ static ALvoid InitSourceParams(ALsource *Source) Source->DopplerFactor = 1.0f; Source->DirectChannels = AL_FALSE; + Source->Radius = 0.0f; + Source->DistanceModel = DefaultDistanceModel; Source->Resampler = DefaultResampler; @@ -2263,18 +2423,24 @@ static ALvoid InitSourceParams(ALsource *Source) Source->SourceType = AL_UNDETERMINED; Source->Offset = -1.0; - Source->DirectGain = 1.0f; - Source->DirectGainHF = 1.0f; + ATOMIC_INIT(&Source->queue, NULL); + ATOMIC_INIT(&Source->current_buffer, NULL); + + Source->Direct.Gain = 1.0f; + Source->Direct.GainHF = 1.0f; + Source->Direct.HFReference = LOWPASSFREQREF; + Source->Direct.GainLF = 1.0f; + Source->Direct.LFReference = HIGHPASSFREQREF; for(i = 0;i < MAX_SENDS;i++) { Source->Send[i].Gain = 1.0f; Source->Send[i].GainHF = 1.0f; + Source->Send[i].HFReference = LOWPASSFREQREF; + Source->Send[i].GainLF = 1.0f; + Source->Send[i].LFReference = HIGHPASSFREQREF; } - Source->NeedsUpdate = AL_TRUE; - - Source->Hrtf.Moving = AL_FALSE; - Source->Hrtf.Counter = 0; + ATOMIC_INIT(&Source->NeedsUpdate, AL_TRUE); } @@ -2284,41 +2450,31 @@ static ALvoid InitSourceParams(ALsource *Source) */ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) { + ReadLock(&Source->queue_lock); if(state == AL_PLAYING) { + ALCdevice *device = Context->Device; ALbufferlistitem *BufferList; + ALactivesource *src = NULL; ALsizei j, k; /* Check that there is a queue containing at least one valid, non zero * length Buffer. */ - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); while(BufferList) { - if(BufferList->buffer != NULL && BufferList->buffer->SampleLen) + ALbuffer *buffer; + if((buffer=BufferList->buffer) != NULL && buffer->SampleLen > 0) break; BufferList = BufferList->next; } - if(Source->state != AL_PLAYING) - { - for(j = 0;j < MAX_INPUT_CHANNELS;j++) - { - for(k = 0;k < SRC_HISTORY_LENGTH;k++) - Source->Hrtf.History[j][k] = 0.0f; - for(k = 0;k < HRIR_LENGTH;k++) - { - Source->Hrtf.Values[j][k][0] = 0.0f; - Source->Hrtf.Values[j][k][1] = 0.0f; - } - } - } - if(Source->state != AL_PAUSED) { Source->state = AL_PLAYING; Source->position = 0; Source->position_fraction = 0; - Source->BuffersPlayed = 0; + ATOMIC_STORE(&Source->current_buffer, BufferList); } else Source->state = AL_PLAYING; @@ -2329,37 +2485,72 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) /* If there's nothing to play, or device is disconnected, go right to * stopped */ - if(!BufferList || !Context->Device->Connected) - { - SetSourceState(Source, Context, AL_STOPPED); - return; - } + if(!BufferList || !device->Connected) + goto do_stop; for(j = 0;j < Context->ActiveSourceCount;j++) { - if(Context->ActiveSources[j] == Source) + if(Context->ActiveSources[j]->Source == Source) + { + src = Context->ActiveSources[j]; break; + } } - if(j == Context->ActiveSourceCount) - Context->ActiveSources[Context->ActiveSourceCount++] = Source; + if(src == NULL) + { + src = Context->ActiveSources[Context->ActiveSourceCount]; + if(src == NULL) + { + src = al_malloc(16, sizeof(src[0])); + Context->ActiveSources[Context->ActiveSourceCount] = src; + } + memset(src, 0, sizeof(*src)); + Context->ActiveSourceCount++; + + src->Source = Source; + } + else + { + ALuint i; + + src->Direct.Moving = AL_FALSE; + src->Direct.Counter = 0; + for(j = 0;j < MAX_INPUT_CHANNELS;j++) + { + for(k = 0;k < SRC_HISTORY_LENGTH;k++) + src->Direct.Mix.Hrtf.State[j].History[k] = 0.0f; + for(k = 0;k < HRIR_LENGTH;k++) + { + src->Direct.Mix.Hrtf.State[j].Values[k][0] = 0.0f; + src->Direct.Mix.Hrtf.State[j].Values[k][1] = 0.0f; + } + } + for(i = 0;i < device->NumAuxSends;i++) + { + src->Send[i].Counter = 0; + src->Send[i].Moving = AL_FALSE; + } + } + + if(BufferList->buffer->FmtChannels == FmtMono) + src->Update = CalcSourceParams; + else + src->Update = CalcNonAttnSourceParams; + + ATOMIC_STORE(&Source->NeedsUpdate, AL_TRUE); } else if(state == AL_PAUSED) { if(Source->state == AL_PLAYING) - { Source->state = AL_PAUSED; - Source->Hrtf.Moving = AL_FALSE; - Source->Hrtf.Counter = 0; - } } else if(state == AL_STOPPED) { + do_stop: if(Source->state != AL_INITIAL) { Source->state = AL_STOPPED; - Source->BuffersPlayed = Source->BuffersInQueue; - Source->Hrtf.Moving = AL_FALSE; - Source->Hrtf.Counter = 0; + ATOMIC_STORE(&Source->current_buffer, NULL); } Source->Offset = -1.0; } @@ -2370,12 +2561,11 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) Source->state = AL_INITIAL; Source->position = 0; Source->position_fraction = 0; - Source->BuffersPlayed = 0; - Source->Hrtf.Moving = AL_FALSE; - Source->Hrtf.Counter = 0; + ATOMIC_STORE(&Source->current_buffer, ATOMIC_LOAD(&Source->queue)); } Source->Offset = -1.0; } + ReadUnlock(&Source->queue_lock); } /* GetSourceOffset @@ -2387,8 +2577,8 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) static ALint64 GetSourceOffset(const ALsource *Source) { const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; ALuint64 readPos; - ALuint i; if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) return 0; @@ -2397,8 +2587,9 @@ static ALint64 GetSourceOffset(const ALsource *Source) * any played buffers */ readPos = (ALuint64)Source->position << 32; readPos |= (ALuint64)Source->position_fraction << (32-FRACTIONBITS); - BufferList = Source->queue; - for(i = 0;i < Source->BuffersPlayed && BufferList;i++) + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); + while(BufferList && BufferList != Current) { if(BufferList->buffer) readPos += (ALuint64)BufferList->buffer->SampleLen << 32; @@ -2416,36 +2607,37 @@ static ALint64 GetSourceOffset(const ALsource *Source) static ALdouble GetSourceSecOffset(const ALsource *Source) { const ALbufferlistitem *BufferList; + const ALbufferlistitem *Current; const ALbuffer *Buffer = NULL; ALuint64 readPos; - ALuint i; - BufferList = Source->queue; - while(BufferList) - { - if(BufferList->buffer) - { - Buffer = BufferList->buffer; - break; - } - BufferList = BufferList->next; - } - - if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer) + if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) return 0.0; /* NOTE: This is the offset into the *current* buffer, so add the length of * any played buffers */ readPos = (ALuint64)Source->position << FRACTIONBITS; readPos |= (ALuint64)Source->position_fraction; - BufferList = Source->queue; - for(i = 0;i < Source->BuffersPlayed && BufferList;i++) + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); + while(BufferList && BufferList != Current) { - if(BufferList->buffer) - readPos += (ALuint64)BufferList->buffer->SampleLen << FRACTIONBITS; + const ALbuffer *buffer = BufferList->buffer; + if(buffer != NULL) + { + if(!Buffer) Buffer = buffer; + readPos += (ALuint64)buffer->SampleLen << FRACTIONBITS; + } BufferList = BufferList->next; } + while(BufferList && !Buffer) + { + Buffer = BufferList->buffer; + BufferList = BufferList->next; + } + assert(Buffer != NULL); + return (ALdouble)readPos / (ALdouble)FRACTIONONE / (ALdouble)Buffer->Frequency; } @@ -2458,24 +2650,13 @@ static ALdouble GetSourceSecOffset(const ALsource *Source) static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen) { const ALbufferlistitem *BufferList; - const ALbuffer *Buffer = NULL; + const ALbufferlistitem *Current; + const ALbuffer *Buffer = NULL; + ALboolean readFin = AL_FALSE; ALuint readPos, writePos; ALuint totalBufferLen; - ALuint i; - // Find the first valid Buffer in the Queue - BufferList = Source->queue; - while(BufferList) - { - if(BufferList->buffer) - { - Buffer = BufferList->buffer; - break; - } - BufferList = BufferList->next; - } - - if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer) + if(Source->state != AL_PLAYING && Source->state != AL_PAUSED) { offset[0] = 0.0; offset[1] = 0.0; @@ -2487,19 +2668,24 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of /* NOTE: This is the offset into the *current* buffer, so add the length of * any played buffers */ - readPos = Source->position; totalBufferLen = 0; - BufferList = Source->queue; - for(i = 0;BufferList;i++) + readPos = Source->position; + BufferList = ATOMIC_LOAD(&Source->queue); + Current = ATOMIC_LOAD(&Source->current_buffer); + while(BufferList != NULL) { - if(BufferList->buffer) + const ALbuffer *buffer; + readFin = readFin || (BufferList == Current); + if((buffer=BufferList->buffer) != NULL) { - if(i < Source->BuffersPlayed) - readPos += BufferList->buffer->SampleLen; - totalBufferLen += BufferList->buffer->SampleLen; + if(!Buffer) Buffer = buffer; + totalBufferLen += buffer->SampleLen; + if(!readFin) readPos += buffer->SampleLen; } BufferList = BufferList->next; } + assert(Buffer != NULL); + if(Source->state == AL_PLAYING) writePos = readPos + (ALuint)(updateLen*Buffer->Frequency); else @@ -2536,8 +2722,26 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of case AL_BYTE_RW_OFFSETS_SOFT: if(Buffer->OriginalType == UserFmtIMA4) { - ALuint BlockSize = 36 * ChannelsFromFmt(Buffer->FmtChannels); - ALuint FrameBlockSize = 65; + ALsizei align = (Buffer->OriginalAlign-1)/2 + 4; + ALuint BlockSize = align * ChannelsFromFmt(Buffer->FmtChannels); + ALuint FrameBlockSize = Buffer->OriginalAlign; + + /* Round down to nearest ADPCM block */ + offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize); + if(Source->state != AL_PLAYING) + offset[1] = offset[0]; + else + { + /* Round up to nearest ADPCM block */ + offset[1] = (ALdouble)((writePos+FrameBlockSize-1) / + FrameBlockSize * BlockSize); + } + } + else if(Buffer->OriginalType == UserFmtMSADPCM) + { + ALsizei align = (Buffer->OriginalAlign-2)/2 + 7; + ALuint BlockSize = align * ChannelsFromFmt(Buffer->FmtChannels); + ALuint FrameBlockSize = Buffer->OriginalAlign; /* Round down to nearest ADPCM block */ offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize); @@ -2568,10 +2772,9 @@ static ALvoid GetSourceOffsets(const ALsource *Source, ALenum name, ALdouble *of */ ALboolean ApplyOffset(ALsource *Source) { - const ALbufferlistitem *BufferList; - const ALbuffer *Buffer; + ALbufferlistitem *BufferList; + const ALbuffer *Buffer; ALint bufferLen, totalBufferLen; - ALint buffersPlayed; ALint offset; /* Get sample frame offset */ @@ -2579,24 +2782,17 @@ ALboolean ApplyOffset(ALsource *Source) if(offset == -1) return AL_FALSE; - buffersPlayed = 0; totalBufferLen = 0; - - BufferList = Source->queue; - while(BufferList) + BufferList = ATOMIC_LOAD(&Source->queue); + while(BufferList && totalBufferLen <= offset) { Buffer = BufferList->buffer; bufferLen = Buffer ? Buffer->SampleLen : 0; - if(bufferLen <= offset-totalBufferLen) - { - /* Offset is past this buffer so increment to the next buffer */ - buffersPlayed++; - } - else if(totalBufferLen <= offset) + if(bufferLen > offset-totalBufferLen) { /* Offset is in this buffer */ - Source->BuffersPlayed = buffersPlayed; + ATOMIC_STORE(&Source->current_buffer, BufferList); Source->position = offset - totalBufferLen; Source->position_fraction = 0; @@ -2626,7 +2822,7 @@ static ALint GetSampleOffset(ALsource *Source) ALint Offset = -1; /* Find the first valid Buffer in the Queue */ - BufferList = Source->queue; + BufferList = ATOMIC_LOAD(&Source->queue); while(BufferList) { if(BufferList->buffer) @@ -2650,8 +2846,15 @@ static ALint GetSampleOffset(ALsource *Source) Offset = (ALint)Source->Offset; if(Buffer->OriginalType == UserFmtIMA4) { - Offset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels); - Offset *= 65; + 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); @@ -2677,6 +2880,7 @@ static ALint GetSampleOffset(ALsource *Source) */ ALvoid ReleaseALSources(ALCcontext *Context) { + ALbufferlistitem *item; ALsizei pos; ALuint j; for(pos = 0;pos < Context->SourceMap.size;pos++) @@ -2684,14 +2888,14 @@ ALvoid ReleaseALSources(ALCcontext *Context) ALsource *temp = Context->SourceMap.array[pos].value; Context->SourceMap.array[pos].value = NULL; - while(temp->queue != NULL) + item = ATOMIC_EXCHANGE(ALbufferlistitem*, &temp->queue, NULL); + while(item != NULL) { - ALbufferlistitem *BufferList = temp->queue; - temp->queue = BufferList->next; - - if(BufferList->buffer != NULL) - DecrementRef(&BufferList->buffer->ref); - free(BufferList); + ALbufferlistitem *next = item->next; + if(item->buffer != NULL) + DecrementRef(&item->buffer->ref); + free(item); + item = next; } for(j = 0;j < MAX_SENDS;++j) diff --git a/jni/openal-soft-android/OpenAL32/alState.c b/jni/openal-soft-1.16.0/OpenAL32/alState.c similarity index 93% rename from jni/openal-soft-android/OpenAL32/alState.c rename to jni/openal-soft-1.16.0/OpenAL32/alState.c index 280dd896..d48c268b 100644 --- a/jni/openal-soft-android/OpenAL32/alState.c +++ b/jni/openal-soft-1.16.0/OpenAL32/alState.c @@ -56,7 +56,7 @@ AL_API ALvoid AL_APIENTRY alEnable(ALenum capability) { case AL_SOURCE_DISTANCE_MODEL: context->SourceDistanceModel = AL_TRUE; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; default: @@ -78,7 +78,7 @@ AL_API ALvoid AL_APIENTRY alDisable(ALenum capability) { case AL_SOURCE_DISTANCE_MODEL: context->SourceDistanceModel = AL_FALSE; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); break; default: @@ -643,7 +643,7 @@ AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->DopplerFactor = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); @@ -660,7 +660,7 @@ AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->DopplerVelocity = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); @@ -677,7 +677,7 @@ AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value) SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); context->SpeedOfSound = value; - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); @@ -698,7 +698,7 @@ AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value) context->DistanceModel = value; if(!context->SourceDistanceModel) - context->UpdateSources = AL_TRUE; + ATOMIC_STORE(&context->UpdateSources, AL_TRUE); done: ALCcontext_DecRef(context); @@ -715,7 +715,7 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void) if(!context->DeferUpdates) { ALboolean UpdateSources; - ALsource **src, **src_end; + ALactivesource **src, **src_end; ALeffectslot **slot, **slot_end; FPUCtl oldMode; @@ -725,30 +725,34 @@ AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void) context->DeferUpdates = AL_TRUE; /* Make sure all pending updates are performed */ - UpdateSources = ExchangeInt(&context->UpdateSources, AL_FALSE); + UpdateSources = ATOMIC_EXCHANGE(ALenum, &context->UpdateSources, AL_FALSE); src = context->ActiveSources; src_end = src + context->ActiveSourceCount; while(src != src_end) { - if((*src)->state != AL_PLAYING) + ALsource *source = (*src)->Source; + + if(source->state != AL_PLAYING && source->state != AL_PAUSED) { - context->ActiveSourceCount--; - *src = *(--src_end); + ALactivesource *temp = *(--src_end); + *src_end = *src; + *src = temp; + --(context->ActiveSourceCount); continue; } - if(ExchangeInt(&(*src)->NeedsUpdate, AL_FALSE) || UpdateSources) - ALsource_Update(*src, context); + if(ATOMIC_EXCHANGE(ALenum, &source->NeedsUpdate, AL_FALSE) || UpdateSources) + (*src)->Update(*src, context); src++; } - slot = context->ActiveEffectSlots; - slot_end = slot + context->ActiveEffectSlotCount; + slot = VECTOR_ITER_BEGIN(context->ActiveAuxSlots); + slot_end = VECTOR_ITER_END(context->ActiveAuxSlots); while(slot != slot_end) { - if(ExchangeInt(&(*slot)->NeedsUpdate, AL_FALSE)) + if(ATOMIC_EXCHANGE(ALenum, &(*slot)->NeedsUpdate, AL_FALSE)) V((*slot)->EffectState,update)(context->Device, *slot); slot++; } @@ -780,7 +784,11 @@ AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void) if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && Source->Offset >= 0.0) + { + ReadLock(&Source->queue_lock); ApplyOffset(Source); + ReadUnlock(&Source->queue_lock); + } new_state = ExchangeInt(&Source->new_state, AL_NONE); if(new_state) diff --git a/jni/openal-soft-android/OpenAL32/alThunk.c b/jni/openal-soft-1.16.0/OpenAL32/alThunk.c similarity index 100% rename from jni/openal-soft-android/OpenAL32/alThunk.c rename to jni/openal-soft-1.16.0/OpenAL32/alThunk.c diff --git a/jni/openal-soft-1.16.0/OpenAL32/sample_cvt.c b/jni/openal-soft-1.16.0/OpenAL32/sample_cvt.c new file mode 100644 index 00000000..a02b217e --- /dev/null +++ b/jni/openal-soft-1.16.0/OpenAL32/sample_cvt.c @@ -0,0 +1,1269 @@ + +#include "config.h" + +#include "sample_cvt.h" + +#ifdef HAVE_ALLOCA_H +#include +#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; + } +} + + +static inline ALbyte Conv_ALbyte_ALbyte(ALbyte val) +{ return val; } +static inline ALbyte Conv_ALbyte_ALubyte(ALubyte val) +{ return val-128; } +static inline ALbyte Conv_ALbyte_ALshort(ALshort val) +{ return val>>8; } +static inline ALbyte Conv_ALbyte_ALushort(ALushort val) +{ return (val>>8)-128; } +static inline ALbyte Conv_ALbyte_ALint(ALint val) +{ return val>>24; } +static inline ALbyte Conv_ALbyte_ALuint(ALuint val) +{ return (val>>24)-128; } +static inline ALbyte Conv_ALbyte_ALfloat(ALfloat val) +{ + if(val > 1.0f) return 127; + if(val < -1.0f) return -128; + return (ALint)(val * 127.0f); +} +static inline ALbyte Conv_ALbyte_ALdouble(ALdouble val) +{ + if(val > 1.0) return 127; + if(val < -1.0) return -128; + return (ALint)(val * 127.0); +} +static inline ALbyte Conv_ALbyte_ALmulaw(ALmulaw val) +{ return Conv_ALbyte_ALshort(DecodeMuLaw(val)); } +static inline ALbyte Conv_ALbyte_ALalaw(ALalaw val) +{ return Conv_ALbyte_ALshort(DecodeALaw(val)); } +static inline ALbyte Conv_ALbyte_ALbyte3(ALbyte3 val) +{ return DecodeByte3(val)>>16; } +static inline ALbyte Conv_ALbyte_ALubyte3(ALubyte3 val) +{ return (DecodeUByte3(val)>>16)-128; } + +static inline ALubyte Conv_ALubyte_ALbyte(ALbyte val) +{ return val+128; } +static inline ALubyte Conv_ALubyte_ALubyte(ALubyte val) +{ return val; } +static inline ALubyte Conv_ALubyte_ALshort(ALshort val) +{ return (val>>8)+128; } +static inline ALubyte Conv_ALubyte_ALushort(ALushort val) +{ return val>>8; } +static inline ALubyte Conv_ALubyte_ALint(ALint val) +{ return (val>>24)+128; } +static inline ALubyte Conv_ALubyte_ALuint(ALuint val) +{ return val>>24; } +static inline ALubyte Conv_ALubyte_ALfloat(ALfloat val) +{ + if(val > 1.0f) return 255; + if(val < -1.0f) return 0; + return (ALint)(val * 127.0f) + 128; +} +static inline ALubyte Conv_ALubyte_ALdouble(ALdouble val) +{ + if(val > 1.0) return 255; + if(val < -1.0) return 0; + return (ALint)(val * 127.0) + 128; +} +static inline ALubyte Conv_ALubyte_ALmulaw(ALmulaw val) +{ return Conv_ALubyte_ALshort(DecodeMuLaw(val)); } +static inline ALubyte Conv_ALubyte_ALalaw(ALalaw val) +{ return Conv_ALubyte_ALshort(DecodeALaw(val)); } +static inline ALubyte Conv_ALubyte_ALbyte3(ALbyte3 val) +{ return (DecodeByte3(val)>>16)+128; } +static inline ALubyte Conv_ALubyte_ALubyte3(ALubyte3 val) +{ return DecodeUByte3(val)>>16; } + +static inline ALshort Conv_ALshort_ALbyte(ALbyte val) +{ return val<<8; } +static inline ALshort Conv_ALshort_ALubyte(ALubyte val) +{ return (val-128)<<8; } +static inline ALshort Conv_ALshort_ALshort(ALshort val) +{ return val; } +static inline ALshort Conv_ALshort_ALushort(ALushort val) +{ return val-32768; } +static inline ALshort Conv_ALshort_ALint(ALint val) +{ return val>>16; } +static inline ALshort Conv_ALshort_ALuint(ALuint val) +{ return (val>>16)-32768; } +static inline ALshort Conv_ALshort_ALfloat(ALfloat val) +{ + if(val > 1.0f) return 32767; + if(val < -1.0f) return -32768; + return (ALint)(val * 32767.0f); +} +static inline ALshort Conv_ALshort_ALdouble(ALdouble val) +{ + if(val > 1.0) return 32767; + if(val < -1.0) return -32768; + return (ALint)(val * 32767.0); +} +static inline ALshort Conv_ALshort_ALmulaw(ALmulaw val) +{ return Conv_ALshort_ALshort(DecodeMuLaw(val)); } +static inline ALshort Conv_ALshort_ALalaw(ALalaw val) +{ return Conv_ALshort_ALshort(DecodeALaw(val)); } +static inline ALshort Conv_ALshort_ALbyte3(ALbyte3 val) +{ return DecodeByte3(val)>>8; } +static inline ALshort Conv_ALshort_ALubyte3(ALubyte3 val) +{ return (DecodeUByte3(val)>>8)-32768; } + +static inline ALushort Conv_ALushort_ALbyte(ALbyte val) +{ return (val+128)<<8; } +static inline ALushort Conv_ALushort_ALubyte(ALubyte val) +{ return val<<8; } +static inline ALushort Conv_ALushort_ALshort(ALshort val) +{ return val+32768; } +static inline ALushort Conv_ALushort_ALushort(ALushort val) +{ return val; } +static inline ALushort Conv_ALushort_ALint(ALint val) +{ return (val>>16)+32768; } +static inline ALushort Conv_ALushort_ALuint(ALuint val) +{ return val>>16; } +static inline ALushort Conv_ALushort_ALfloat(ALfloat val) +{ + if(val > 1.0f) return 65535; + if(val < -1.0f) return 0; + return (ALint)(val * 32767.0f) + 32768; +} +static inline ALushort Conv_ALushort_ALdouble(ALdouble val) +{ + if(val > 1.0) return 65535; + if(val < -1.0) return 0; + return (ALint)(val * 32767.0) + 32768; +} +static inline ALushort Conv_ALushort_ALmulaw(ALmulaw val) +{ return Conv_ALushort_ALshort(DecodeMuLaw(val)); } +static inline ALushort Conv_ALushort_ALalaw(ALalaw val) +{ return Conv_ALushort_ALshort(DecodeALaw(val)); } +static inline ALushort Conv_ALushort_ALbyte3(ALbyte3 val) +{ return (DecodeByte3(val)>>8)+32768; } +static inline ALushort Conv_ALushort_ALubyte3(ALubyte3 val) +{ return DecodeUByte3(val)>>8; } + +static inline ALint Conv_ALint_ALbyte(ALbyte val) +{ return val<<24; } +static inline ALint Conv_ALint_ALubyte(ALubyte val) +{ return (val-128)<<24; } +static inline ALint Conv_ALint_ALshort(ALshort val) +{ return val<<16; } +static inline ALint Conv_ALint_ALushort(ALushort val) +{ return (val-32768)<<16; } +static inline ALint Conv_ALint_ALint(ALint val) +{ return val; } +static inline ALint Conv_ALint_ALuint(ALuint val) +{ return val-2147483648u; } +static inline ALint Conv_ALint_ALfloat(ALfloat val) +{ + if(val > 1.0f) return 2147483647; + if(val < -1.0f) return -2147483647-1; + return (ALint)(val*16777215.0f) << 7; +} +static inline ALint Conv_ALint_ALdouble(ALdouble val) +{ + if(val > 1.0) return 2147483647; + if(val < -1.0) return -2147483647-1; + return (ALint)(val * 2147483647.0); +} +static inline ALint Conv_ALint_ALmulaw(ALmulaw val) +{ return Conv_ALint_ALshort(DecodeMuLaw(val)); } +static inline ALint Conv_ALint_ALalaw(ALalaw val) +{ return Conv_ALint_ALshort(DecodeALaw(val)); } +static inline ALint Conv_ALint_ALbyte3(ALbyte3 val) +{ return DecodeByte3(val)<<8; } +static inline ALint Conv_ALint_ALubyte3(ALubyte3 val) +{ return (DecodeUByte3(val)-8388608)<<8; } + +static inline ALuint Conv_ALuint_ALbyte(ALbyte val) +{ return (val+128)<<24; } +static inline ALuint Conv_ALuint_ALubyte(ALubyte val) +{ return val<<24; } +static inline ALuint Conv_ALuint_ALshort(ALshort val) +{ return (val+32768)<<16; } +static inline ALuint Conv_ALuint_ALushort(ALushort val) +{ return val<<16; } +static inline ALuint Conv_ALuint_ALint(ALint val) +{ return val+2147483648u; } +static inline ALuint Conv_ALuint_ALuint(ALuint val) +{ return val; } +static inline ALuint Conv_ALuint_ALfloat(ALfloat val) +{ + if(val > 1.0f) return 4294967295u; + if(val < -1.0f) return 0; + return ((ALint)(val*16777215.0f)<<7) + 2147483648u; +} +static inline ALuint Conv_ALuint_ALdouble(ALdouble val) +{ + if(val > 1.0) return 4294967295u; + if(val < -1.0) return 0; + return (ALint)(val * 2147483647.0) + 2147483648u; +} +static inline ALuint Conv_ALuint_ALmulaw(ALmulaw val) +{ return Conv_ALuint_ALshort(DecodeMuLaw(val)); } +static inline ALuint Conv_ALuint_ALalaw(ALalaw val) +{ return Conv_ALuint_ALshort(DecodeALaw(val)); } +static inline ALuint Conv_ALuint_ALbyte3(ALbyte3 val) +{ return (DecodeByte3(val)+8388608)<<8; } +static inline ALuint Conv_ALuint_ALubyte3(ALubyte3 val) +{ return DecodeUByte3(val)<<8; } + +static inline ALfloat Conv_ALfloat_ALbyte(ALbyte val) +{ return val * (1.0f/127.0f); } +static inline ALfloat Conv_ALfloat_ALubyte(ALubyte val) +{ return (val-128) * (1.0f/127.0f); } +static inline ALfloat Conv_ALfloat_ALshort(ALshort val) +{ return val * (1.0f/32767.0f); } +static inline ALfloat Conv_ALfloat_ALushort(ALushort val) +{ return (val-32768) * (1.0f/32767.0f); } +static inline ALfloat Conv_ALfloat_ALint(ALint val) +{ return (ALfloat)(val>>7) * (1.0f/16777215.0f); } +static inline ALfloat Conv_ALfloat_ALuint(ALuint val) +{ return (ALfloat)((ALint)(val>>7)-16777216) * (1.0f/16777215.0f); } +static inline ALfloat Conv_ALfloat_ALfloat(ALfloat val) +{ return (val==val) ? val : 0.0f; } +static inline ALfloat Conv_ALfloat_ALdouble(ALdouble val) +{ return (val==val) ? (ALfloat)val : 0.0f; } +static inline ALfloat Conv_ALfloat_ALmulaw(ALmulaw val) +{ return Conv_ALfloat_ALshort(DecodeMuLaw(val)); } +static inline ALfloat Conv_ALfloat_ALalaw(ALalaw val) +{ return Conv_ALfloat_ALshort(DecodeALaw(val)); } +static inline ALfloat Conv_ALfloat_ALbyte3(ALbyte3 val) +{ return (ALfloat)(DecodeByte3(val) * (1.0/8388607.0)); } +static inline ALfloat Conv_ALfloat_ALubyte3(ALubyte3 val) +{ return (ALfloat)((DecodeUByte3(val)-8388608) * (1.0/8388607.0)); } + +static inline ALdouble Conv_ALdouble_ALbyte(ALbyte val) +{ return val * (1.0/127.0); } +static inline ALdouble Conv_ALdouble_ALubyte(ALubyte val) +{ return (val-128) * (1.0/127.0); } +static inline ALdouble Conv_ALdouble_ALshort(ALshort val) +{ return val * (1.0/32767.0); } +static inline ALdouble Conv_ALdouble_ALushort(ALushort val) +{ return (val-32768) * (1.0/32767.0); } +static inline ALdouble Conv_ALdouble_ALint(ALint val) +{ return val * (1.0/2147483647.0); } +static inline ALdouble Conv_ALdouble_ALuint(ALuint val) +{ return (ALint)(val-2147483648u) * (1.0/2147483647.0); } +static inline ALdouble Conv_ALdouble_ALfloat(ALfloat val) +{ return (val==val) ? val : 0.0f; } +static inline ALdouble Conv_ALdouble_ALdouble(ALdouble val) +{ return (val==val) ? val : 0.0; } +static inline ALdouble Conv_ALdouble_ALmulaw(ALmulaw val) +{ return Conv_ALdouble_ALshort(DecodeMuLaw(val)); } +static inline ALdouble Conv_ALdouble_ALalaw(ALalaw val) +{ return Conv_ALdouble_ALshort(DecodeALaw(val)); } +static inline ALdouble Conv_ALdouble_ALbyte3(ALbyte3 val) +{ return DecodeByte3(val) * (1.0/8388607.0); } +static inline ALdouble Conv_ALdouble_ALubyte3(ALubyte3 val) +{ return (DecodeUByte3(val)-8388608) * (1.0/8388607.0); } + +#define DECL_TEMPLATE(T) \ +static inline ALmulaw Conv_ALmulaw_##T(T val) \ +{ return EncodeMuLaw(Conv_ALshort_##T(val)); } + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +DECL_TEMPLATE(ALshort) +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +static inline ALmulaw Conv_ALmulaw_ALmulaw(ALmulaw val) +{ return val; } +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static inline ALalaw Conv_ALalaw_##T(T val) \ +{ return EncodeALaw(Conv_ALshort_##T(val)); } + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +DECL_TEMPLATE(ALshort) +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +static inline ALalaw Conv_ALalaw_ALalaw(ALalaw val) +{ return val; } +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static inline ALbyte3 Conv_ALbyte3_##T(T val) \ +{ return EncodeByte3(Conv_ALint_##T(val)>>8); } + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +DECL_TEMPLATE(ALshort) +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +static inline ALbyte3 Conv_ALbyte3_ALbyte3(ALbyte3 val) +{ return val; } +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static inline ALubyte3 Conv_ALubyte3_##T(T val) \ +{ return EncodeUByte3(Conv_ALuint_##T(val)>>8); } + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +DECL_TEMPLATE(ALshort) +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +static inline ALubyte3 Conv_ALubyte3_ALubyte3(ALubyte3 val) +{ return val; } + +#undef DECL_TEMPLATE + + +#define DECL_TEMPLATE(T1, T2) \ +static void Convert_##T1##_##T2(T1 *dst, const T2 *src, ALuint numchans, \ + ALuint len, ALsizei UNUSED(align)) \ +{ \ + ALuint i, j; \ + for(i = 0;i < len;i++) \ + { \ + for(j = 0;j < numchans;j++) \ + *(dst++) = Conv_##T1##_##T2(*(src++)); \ + } \ +} + +#define DECL_TEMPLATE2(T) \ +DECL_TEMPLATE(T, ALbyte) \ +DECL_TEMPLATE(T, ALubyte) \ +DECL_TEMPLATE(T, ALshort) \ +DECL_TEMPLATE(T, ALushort) \ +DECL_TEMPLATE(T, ALint) \ +DECL_TEMPLATE(T, ALuint) \ +DECL_TEMPLATE(T, ALfloat) \ +DECL_TEMPLATE(T, ALdouble) \ +DECL_TEMPLATE(T, ALmulaw) \ +DECL_TEMPLATE(T, ALalaw) \ +DECL_TEMPLATE(T, ALbyte3) \ +DECL_TEMPLATE(T, ALubyte3) + +DECL_TEMPLATE2(ALbyte) +DECL_TEMPLATE2(ALubyte) +DECL_TEMPLATE2(ALshort) +DECL_TEMPLATE2(ALushort) +DECL_TEMPLATE2(ALint) +DECL_TEMPLATE2(ALuint) +DECL_TEMPLATE2(ALfloat) +DECL_TEMPLATE2(ALdouble) +DECL_TEMPLATE2(ALmulaw) +DECL_TEMPLATE2(ALalaw) +DECL_TEMPLATE2(ALbyte3) +DECL_TEMPLATE2(ALubyte3) + +#undef DECL_TEMPLATE2 +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \ + ALuint len, ALuint align) \ +{ \ + ALsizei byte_align = ((align-1)/2 + 4) * numchans; \ + DECL_VLA(ALshort, tmp, align*numchans); \ + ALuint i, j, k; \ + \ + assert(align > 0 && (len%align) == 0); \ + for(i = 0;i < len;i += align) \ + { \ + DecodeIMA4Block(tmp, src, numchans, align); \ + src += byte_align; \ + \ + for(j = 0;j < align;j++) \ + { \ + for(k = 0;k < numchans;k++) \ + *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]); \ + } \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +static void Convert_ALshort_ALima4(ALshort *dst, const ALima4 *src, ALuint numchans, + ALuint len, ALuint align) +{ + ALsizei byte_align = ((align-1)/2 + 4) * numchans; + ALuint i; + + assert(align > 0 && (len%align) == 0); + for(i = 0;i < len;i += align) + { + DecodeIMA4Block(dst, src, numchans, align); + src += byte_align; + dst += align*numchans; + } +} +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \ + ALuint len, ALuint align) \ +{ \ + ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; \ + ALint index[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; \ + ALsizei byte_align = ((align-1)/2 + 4) * numchans; \ + DECL_VLA(ALshort, tmp, align*numchans); \ + ALuint i, j, k; \ + \ + assert(align > 0 && (len%align) == 0); \ + for(i = 0;i < len;i += align) \ + { \ + for(j = 0;j < align;j++) \ + { \ + for(k = 0;k < numchans;k++) \ + tmp[j*numchans + k] = Conv_ALshort_##T(*(src++)); \ + } \ + EncodeIMA4Block(dst, tmp, sample, index, numchans, align); \ + dst += byte_align; \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +static void Convert_ALima4_ALshort(ALima4 *dst, const ALshort *src, + ALuint numchans, ALuint len, ALuint align) +{ + ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; + ALint index[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; + ALsizei byte_align = ((align-1)/2 + 4) * numchans; + ALuint i; + + assert(align > 0 && (len%align) == 0); + for(i = 0;i < len;i += align) + { + EncodeIMA4Block(dst, src, sample, index, numchans, align); + src += align*numchans; + dst += byte_align; + } +} +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + + +#define DECL_TEMPLATE(T) \ +static void Convert_##T##_ALmsadpcm(T *dst, const ALmsadpcm *src, \ + ALuint numchans, ALuint len, \ + ALuint align) \ +{ \ + ALsizei byte_align = ((align-2)/2 + 7) * numchans; \ + DECL_VLA(ALshort, tmp, align*numchans); \ + ALuint i, j, k; \ + \ + assert(align > 1 && (len%align) == 0); \ + for(i = 0;i < len;i += align) \ + { \ + DecodeMSADPCMBlock(tmp, src, numchans, align); \ + src += byte_align; \ + \ + for(j = 0;j < align;j++) \ + { \ + for(k = 0;k < numchans;k++) \ + *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]); \ + } \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +static void Convert_ALshort_ALmsadpcm(ALshort *dst, const ALmsadpcm *src, + ALuint numchans, ALuint len, + ALuint align) +{ + ALsizei byte_align = ((align-2)/2 + 7) * numchans; + ALuint i; + + assert(align > 1 && (len%align) == 0); + for(i = 0;i < len;i += align) + { + DecodeMSADPCMBlock(dst, src, numchans, align); + src += byte_align; + dst += align*numchans; + } +} +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +#define DECL_TEMPLATE(T) \ +static void Convert_ALmsadpcm_##T(ALmsadpcm *dst, const T *src, \ + ALuint numchans, ALuint len, ALuint align) \ +{ \ + ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; \ + ALsizei byte_align = ((align-2)/2 + 7) * numchans; \ + DECL_VLA(ALshort, tmp, align*numchans); \ + ALuint i, j, k; \ + \ + assert(align > 1 && (len%align) == 0); \ + for(i = 0;i < len;i += align) \ + { \ + for(j = 0;j < align;j++) \ + { \ + for(k = 0;k < numchans;k++) \ + tmp[j*numchans + k] = Conv_ALshort_##T(*(src++)); \ + } \ + EncodeMSADPCMBlock(dst, tmp, sample, numchans, align); \ + dst += byte_align; \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +static void Convert_ALmsadpcm_ALshort(ALmsadpcm *dst, const ALshort *src, + ALuint numchans, ALuint len, ALuint align) +{ + ALint sample[MAX_INPUT_CHANNELS] = {0,0,0,0,0,0,0,0}; + ALsizei byte_align = ((align-2)/2 + 7) * numchans; + ALuint i; + + assert(align > 1 && (len%align) == 0); + for(i = 0;i < len;i += align) + { + EncodeMSADPCMBlock(dst, src, sample, numchans, align); + src += align*numchans; + dst += byte_align; + } +} +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + +/* NOTE: We don't store compressed samples internally, so these conversions + * should never happen. */ +static void Convert_ALima4_ALima4(ALima4* UNUSED(dst), const ALima4* UNUSED(src), + ALuint UNUSED(numchans), ALuint UNUSED(len), + ALuint UNUSED(align)) +{ + ERR("Unexpected IMA4-to-IMA4 conversion!\n"); +} + +static void Convert_ALmsadpcm_ALmsadpcm(ALmsadpcm* UNUSED(dst), const ALmsadpcm* UNUSED(src), + ALuint UNUSED(numchans), ALuint UNUSED(len), + ALuint UNUSED(align)) +{ + ERR("Unexpected MSADPCM-to-MSADPCM conversion!\n"); +} + +static void Convert_ALmsadpcm_ALima4(ALmsadpcm* UNUSED(dst), const ALima4* UNUSED(src), + ALuint UNUSED(numchans), ALuint UNUSED(len), + ALuint UNUSED(align)) +{ + ERR("Unexpected IMA4-to-MSADPCM conversion!\n"); +} + +static void Convert_ALima4_ALmsadpcm(ALima4* UNUSED(dst), const ALmsadpcm* UNUSED(src), + ALuint UNUSED(numchans), ALuint UNUSED(len), + ALuint UNUSED(align)) +{ + ERR("Unexpected MSADPCM-to-IMA4 conversion!\n"); +} + + +#define DECL_TEMPLATE(T) \ +static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType, \ + ALsizei numchans, ALsizei len, ALsizei align) \ +{ \ + switch(srcType) \ + { \ + case UserFmtByte: \ + Convert_##T##_ALbyte(dst, src, numchans, len, align); \ + break; \ + case UserFmtUByte: \ + Convert_##T##_ALubyte(dst, src, numchans, len, align); \ + break; \ + case UserFmtShort: \ + Convert_##T##_ALshort(dst, src, numchans, len, align); \ + break; \ + case UserFmtUShort: \ + Convert_##T##_ALushort(dst, src, numchans, len, align); \ + break; \ + case UserFmtInt: \ + Convert_##T##_ALint(dst, src, numchans, len, align); \ + break; \ + case UserFmtUInt: \ + Convert_##T##_ALuint(dst, src, numchans, len, align); \ + break; \ + case UserFmtFloat: \ + Convert_##T##_ALfloat(dst, src, numchans, len, align); \ + break; \ + case UserFmtDouble: \ + Convert_##T##_ALdouble(dst, src, numchans, len, align); \ + break; \ + case UserFmtMulaw: \ + Convert_##T##_ALmulaw(dst, src, numchans, len, align); \ + break; \ + case UserFmtAlaw: \ + Convert_##T##_ALalaw(dst, src, numchans, len, align); \ + break; \ + case UserFmtIMA4: \ + Convert_##T##_ALima4(dst, src, numchans, len, align); \ + break; \ + case UserFmtMSADPCM: \ + Convert_##T##_ALmsadpcm(dst, src, numchans, len, align); \ + break; \ + case UserFmtByte3: \ + Convert_##T##_ALbyte3(dst, src, numchans, len, align); \ + break; \ + case UserFmtUByte3: \ + Convert_##T##_ALubyte3(dst, src, numchans, len, align); \ + break; \ + } \ +} + +DECL_TEMPLATE(ALbyte) +DECL_TEMPLATE(ALubyte) +DECL_TEMPLATE(ALshort) +DECL_TEMPLATE(ALushort) +DECL_TEMPLATE(ALint) +DECL_TEMPLATE(ALuint) +DECL_TEMPLATE(ALfloat) +DECL_TEMPLATE(ALdouble) +DECL_TEMPLATE(ALmulaw) +DECL_TEMPLATE(ALalaw) +DECL_TEMPLATE(ALima4) +DECL_TEMPLATE(ALmsadpcm) +DECL_TEMPLATE(ALbyte3) +DECL_TEMPLATE(ALubyte3) + +#undef DECL_TEMPLATE + + +void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len, ALsizei align) +{ + switch(dstType) + { + case UserFmtByte: + Convert_ALbyte(dst, src, srcType, numchans, len, align); + break; + case UserFmtUByte: + Convert_ALubyte(dst, src, srcType, numchans, len, align); + break; + case UserFmtShort: + Convert_ALshort(dst, src, srcType, numchans, len, align); + break; + case UserFmtUShort: + Convert_ALushort(dst, src, srcType, numchans, len, align); + break; + case UserFmtInt: + Convert_ALint(dst, src, srcType, numchans, len, align); + break; + case UserFmtUInt: + Convert_ALuint(dst, src, srcType, numchans, len, align); + break; + case UserFmtFloat: + Convert_ALfloat(dst, src, srcType, numchans, len, align); + break; + case UserFmtDouble: + Convert_ALdouble(dst, src, srcType, numchans, len, align); + break; + case UserFmtMulaw: + Convert_ALmulaw(dst, src, srcType, numchans, len, align); + break; + case UserFmtAlaw: + Convert_ALalaw(dst, src, srcType, numchans, len, align); + break; + case UserFmtIMA4: + Convert_ALima4(dst, src, srcType, numchans, len, align); + break; + case UserFmtMSADPCM: + Convert_ALmsadpcm(dst, src, srcType, numchans, len, align); + break; + case UserFmtByte3: + Convert_ALbyte3(dst, src, srcType, numchans, len, align); + break; + case UserFmtUByte3: + Convert_ALubyte3(dst, src, srcType, numchans, len, align); + break; + } +} diff --git a/jni/openal-soft-android/README b/jni/openal-soft-1.16.0/README similarity index 100% rename from jni/openal-soft-android/README rename to jni/openal-soft-1.16.0/README diff --git a/jni/openal-soft-android/XCompile.txt b/jni/openal-soft-1.16.0/XCompile.txt similarity index 100% rename from jni/openal-soft-android/XCompile.txt rename to jni/openal-soft-1.16.0/XCompile.txt diff --git a/jni/openal-soft-android/alsoftrc.sample b/jni/openal-soft-1.16.0/alsoftrc.sample similarity index 81% rename from jni/openal-soft-android/alsoftrc.sample rename to jni/openal-soft-1.16.0/alsoftrc.sample index 64590357..2e6dd92a 100644 --- a/jni/openal-soft-android/alsoftrc.sample +++ b/jni/openal-soft-1.16.0/alsoftrc.sample @@ -1,28 +1,40 @@ -# OpenAL config file. Options that are not under a block or are under the -# [general] block are for general, non-backend-specific options. Blocks may -# appear multiple times, and duplicated options will take the last value -# specified. +# OpenAL config file. +# +# Option blocks may appear multiple times, and duplicated options will take the +# last value specified. Environment variables may be specified within option +# values, and are automatically substituted when the config file is loaded. +# Environment variable names may only contain alpha-numeric characters (a-z, +# A-Z, 0-9) and underscores (_), and are prefixed with $. For example, +# specifying "$HOME/file.ext" would typically result in something like +# "/home/user/file.ext". To specify an actual "$" character, use "$$". +# # The system-wide settings can be put in /etc/openal/alsoft.conf and user- -# specific override settings in ~/.alsoftrc. -# For Windows, these settings should go into %AppData%\alsoft.ini - +# specific override settings in $HOME/.alsoftrc. +# For Windows, these settings should go into $AppData\alsoft.ini +# # Option and block names are case-insenstive. The supplied values are only # hints and may not be honored (though generally it'll try to get as close as # possible). Note: options that are left unset may default to app- or system- # specified values. These are the current available settings: +## +## General stuff +## +[general] + ## disable-cpu-exts: -# Disables use of the listed CPU extensions. Certain methods may utilize CPU -# extensions when detected, and this option is useful for preventing those -# extensions from being used. The available extensions are: sse, sse2, neon. -# Specifying 'all' disables use of all extensions. +# Disables use of specialized methods that use specific CPU intrinsics. +# Certain methods may utilize CPU extensions for improved performance, and +# this option is useful for preventing some or all of those methods from being +# used. The available extensions are: sse, sse2, sse4.1, and neon. Specifying +# 'all' disables use of all such specialized methods. #disable-cpu-exts = ## channels: # Sets the output channel configuration. If left unspecified, one will try to # be detected from the system, and defaulting to stereo. The available values # are: mono, stereo, quad, surround51, surround61, surround71 -#channels = stereo +#channels = ## sample-type: # Sets the output sample type. Currently, all mixing is done with 32-bit float @@ -45,15 +57,19 @@ ## hrtf_tables # Specifies a comma-separated list of files containing HRTF data sets. The -# listed data sets can be used in place of or in addiiton to the the built-in -# set. The format of the files are described in hrtf.txt. The filenames may -# contain these markers, which will be replaced as needed: +# format of the files are described in hrtf.txt. The filenames may contain +# these markers, which will be replaced as needed: # %r - Device sampling rate # %% - Percent sign (%) -# So if this is set to "kemar-%r-diffuse.mhr", it will try to open -# "kemar-44100-diffuse.mhr" if the device is using 44100hz output, or -# "kemar-48000-diffuse.mhr" if the device is using 48000hz output, etc. -#hrtf_tables = +# The listed files are relative to system-dependant data directories. On +# Windows this is: +# $AppData\openal\hrtf +# And on other systems, it's (in order): +# $XDG_DATA_HOME/openal/hrtf (defaults to $HOME/.local/share/openal/hrtf) +# $XDG_DATA_DIRS/openal/hrtf (defaults to /usr/local/share/openal/hrtf and +# /usr/share/openal/hrtf) +# An absolute path may also be specified, if the given file is elsewhere. +#hrtf_tables = default-%r.mhr ## cf_level: # Sets the crossfeed level for stereo output. Valid values are: @@ -77,8 +93,9 @@ #wide-stereo = false ## frequency: -# Sets the output frequency. -#frequency = 44100 +# Sets the output frequency. If left unspecified it will try to detect a +# default from the system, otherwise it will default to 44100. +#frequency = ## resampler: # Selects the resampler used when mixing sources. Valid values are: @@ -117,11 +134,11 @@ ## drivers: # Sets the backend driver list order, comma-seperated. Unknown backends and # duplicated names are ignored. Unlisted backends won't be considered for use -# unless the list is ended with a comma (eg. 'oss,' will list OSS first -# followed by all other available backends, while 'oss' will list OSS only). -# Backends prepended with - won't be available for use (eg. '-oss,' will allow -# all available backends except OSS). An empty list means the default. -#drivers = pulse,alsa,core,oss,solaris,sndio,qsa,mmdevapi,dsound,winmm,port,opensl,null,wave +# unless the list is ended with a comma (e.g. 'oss,' will try OSS first before +# other backends, while 'oss' will try OSS only). Backends prepended with - +# won't be considered for use (e.g. '-oss,' will try all available backends +# except OSS). An empty list means to try all backends. +#drivers = ## excludefx: # Sets which effects to exclude, preventing apps from using them. This can @@ -190,7 +207,13 @@ ## soundfont: # A default soundfont (sf2 format). Used when an app requests the system -# default. +# default. The listed file is relative to system-dependant data directories. +# On Windows this is: +# $AppData\openal\soundfonts +# And on other systems, it's (in order): +# $XDG_DATA_HOME/openal/soundfonts +# $XDG_DATA_DIRS/openal/soundfonts +# An absolute path may also be specified, if the given file is elsewhere. #soundfont = ## volume: diff --git a/jni/openal-soft-1.16.0/build/.empty b/jni/openal-soft-1.16.0/build/.empty new file mode 100644 index 00000000..e69de29b diff --git a/jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.c b/jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.c new file mode 100644 index 00000000..de98296e --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.cmake b/jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.cmake new file mode 100644 index 00000000..8b549b69 --- /dev/null +++ b/jni/openal-soft-1.16.0/cmake/CheckFileOffsetBits.cmake @@ -0,0 +1,39 @@ +# - Check if the _FILE_OFFSET_BITS macro is needed for large files +# CHECK_FILE_OFFSET_BITS() +# +# The following variables may be set before calling this macro to +# modify the way the check is run: +# +# CMAKE_REQUIRED_FLAGS = string of compile command line flags +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) +# CMAKE_REQUIRED_INCLUDES = list of include directories +# Copyright (c) 2009, Chris Robinson +# +# Redistribution and use is allowed according to the terms of the LGPL license. + + +MACRO(CHECK_FILE_OFFSET_BITS) + + IF(NOT DEFINED _FILE_OFFSET_BITS) + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files") + TRY_COMPILE(__WITHOUT_FILE_OFFSET_BITS_64 + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/cmake/CheckFileOffsetBits.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}) + IF(NOT __WITHOUT_FILE_OFFSET_BITS_64) + TRY_COMPILE(__WITH_FILE_OFFSET_BITS_64 + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/cmake/CheckFileOffsetBits.c + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_FILE_OFFSET_BITS=64) + ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64) + + IF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + SET(_FILE_OFFSET_BITS 64 CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files") + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - 64") + ELSE(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + SET(_FILE_OFFSET_BITS "" CACHE INTERNAL "_FILE_OFFSET_BITS macro needed for large files") + MESSAGE(STATUS "Checking _FILE_OFFSET_BITS for large files - not needed") + ENDIF(NOT __WITHOUT_FILE_OFFSET_BITS_64 AND __WITH_FILE_OFFSET_BITS_64) + ENDIF(NOT DEFINED _FILE_OFFSET_BITS) + +ENDMACRO(CHECK_FILE_OFFSET_BITS) \ No newline at end of file diff --git a/jni/openal-soft-android/cmake/CheckSharedFunctionExists.cmake b/jni/openal-soft-1.16.0/cmake/CheckSharedFunctionExists.cmake similarity index 100% rename from jni/openal-soft-android/cmake/CheckSharedFunctionExists.cmake rename to jni/openal-soft-1.16.0/cmake/CheckSharedFunctionExists.cmake diff --git a/jni/openal-soft-1.16.0/cmake/FindALSA.cmake b/jni/openal-soft-1.16.0/cmake/FindALSA.cmake new file mode 100644 index 00000000..519304d6 --- /dev/null +++ b/jni/openal-soft-1.16.0/cmake/FindALSA.cmake @@ -0,0 +1,73 @@ +# - Find alsa +# Find the alsa libraries (asound) +# +# This module defines the following variables: +# ALSA_FOUND - True if ALSA_INCLUDE_DIR & ALSA_LIBRARY are found +# ALSA_LIBRARIES - Set when ALSA_LIBRARY is found +# ALSA_INCLUDE_DIRS - Set when ALSA_INCLUDE_DIR is found +# +# ALSA_INCLUDE_DIR - where to find asoundlib.h, etc. +# ALSA_LIBRARY - the asound library +# ALSA_VERSION_STRING - the version of alsa found (since CMake 2.8.8) +# + +#============================================================================= +# Copyright 2009-2011 Kitware, Inc. +# Copyright 2009-2011 Philip Lowman +# +# 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/jni/openal-soft-1.16.0/cmake/FindAudioIO.cmake b/jni/openal-soft-1.16.0/cmake/FindAudioIO.cmake new file mode 100644 index 00000000..f0f8b2a5 --- /dev/null +++ b/jni/openal-soft-1.16.0/cmake/FindAudioIO.cmake @@ -0,0 +1,21 @@ +# - Find AudioIO includes and libraries +# +# AUDIOIO_FOUND - True if AUDIOIO_INCLUDE_DIR is found +# AUDIOIO_INCLUDE_DIRS - Set when AUDIOIO_INCLUDE_DIR is found +# +# AUDIOIO_INCLUDE_DIR - where to find sys/audioio.h, etc. +# + +find_path(AUDIOIO_INCLUDE_DIR + NAMES sys/audioio.h + DOC "The AudioIO include directory" +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(AudioIO REQUIRED_VARS AUDIOIO_INCLUDE_DIR) + +if(AUDIOIO_FOUND) + set(AUDIOIO_INCLUDE_DIRS ${AUDIOIO_INCLUDE_DIR}) +endif() + +mark_as_advanced(AUDIOIO_INCLUDE_DIR) diff --git a/jni/openal-soft-1.16.0/cmake/FindDSound.cmake b/jni/openal-soft-1.16.0/cmake/FindDSound.cmake new file mode 100644 index 00000000..36cdf4b5 --- /dev/null +++ b/jni/openal-soft-1.16.0/cmake/FindDSound.cmake @@ -0,0 +1,33 @@ +# - Find DirectSound includes and libraries +# +# DSOUND_FOUND - True if DSOUND_INCLUDE_DIR & DSOUND_LIBRARY are found +# DSOUND_LIBRARIES - Set when DSOUND_LIBRARY is found +# DSOUND_INCLUDE_DIRS - Set when DSOUND_INCLUDE_DIR is found +# +# DSOUND_INCLUDE_DIR - where to find dsound.h, etc. +# DSOUND_LIBRARY - the dsound library +# + +find_path(DSOUND_INCLUDE_DIR + PATHS "${DXSDK_DIR}/include" + NAMES dsound.h + DOC "The DirectSound include directory" +) + +find_library(DSOUND_LIBRARY + PATHS "${DXSDK_DIR}/lib" + NAMES dsound + DOC "The DirectSound library" +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(DSound + REQUIRED_VARS DSOUND_LIBRARY DSOUND_INCLUDE_DIR +) + +if(DSOUND_FOUND) + set(DSOUND_LIBRARIES ${DSOUND_LIBRARY}) + set(DSOUND_INCLUDE_DIRS ${DSOUND_INCLUDE_DIR}) +endif() + +mark_as_advanced(DSOUND_INCLUDE_DIR DSOUND_LIBRARY) diff --git a/jni/openal-soft-1.16.0/cmake/FindFFmpeg.cmake b/jni/openal-soft-1.16.0/cmake/FindFFmpeg.cmake new file mode 100644 index 00000000..96cbb6ed --- /dev/null +++ b/jni/openal-soft-1.16.0/cmake/FindFFmpeg.cmake @@ -0,0 +1,173 @@ +# vim: ts=2 sw=2 +# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC) +# +# Once done this will define +# FFMPEG_FOUND - System has the all required components. +# FFMPEG_INCLUDE_DIRS - Include directory necessary for using the required components headers. +# FFMPEG_LIBRARIES - Link these to use the required ffmpeg components. +# FFMPEG_DEFINITIONS - Compiler switches required for using the required ffmpeg components. +# +# For each of the components it will additionaly set. +# - AVCODEC +# - AVDEVICE +# - AVFORMAT +# - AVUTIL +# - POSTPROC +# - SWSCALE +# - SWRESAMPLE +# the following variables will be defined +# _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/jni/openal-soft-android/cmake/FindFluidSynth.cmake b/jni/openal-soft-1.16.0/cmake/FindFluidSynth.cmake similarity index 67% rename from jni/openal-soft-android/cmake/FindFluidSynth.cmake rename to jni/openal-soft-1.16.0/cmake/FindFluidSynth.cmake index 7d5cb6a8..fe96b225 100644 --- a/jni/openal-soft-android/cmake/FindFluidSynth.cmake +++ b/jni/openal-soft-1.16.0/cmake/FindFluidSynth.cmake @@ -6,11 +6,6 @@ # FLUIDSYNTH_FOUND - True if fluidsynth found. -IF (FLUIDSYNTH_INCLUDE_DIR AND FLUIDSYNTH_LIBRARIES) - # Already in cache, be silent - SET(FluidSynth_FIND_QUIETLY TRUE) -ENDIF (FLUIDSYNTH_INCLUDE_DIR AND FLUIDSYNTH_LIBRARIES) - FIND_PATH(FLUIDSYNTH_INCLUDE_DIR fluidsynth.h) FIND_LIBRARY(FLUIDSYNTH_LIBRARIES NAMES fluidsynth ) @@ -19,5 +14,6 @@ MARK_AS_ADVANCED( FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR ) # handle the QUIETLY and REQUIRED arguments and set FLUIDSYNTH_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(FluidSynth DEFAULT_MSG FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(FluidSynth + REQUIRED_VARS FLUIDSYNTH_LIBRARIES FLUIDSYNTH_INCLUDE_DIR) diff --git a/jni/openal-soft-1.16.0/cmake/FindOSS.cmake b/jni/openal-soft-1.16.0/cmake/FindOSS.cmake new file mode 100644 index 00000000..88ee66ad --- /dev/null +++ b/jni/openal-soft-1.16.0/cmake/FindOSS.cmake @@ -0,0 +1,21 @@ +# - Find OSS includes +# +# OSS_FOUND - True if OSS_INCLUDE_DIR is found +# OSS_INCLUDE_DIRS - Set when OSS_INCLUDE_DIR is found +# +# OSS_INCLUDE_DIR - where to find sys/soundcard.h, etc. +# + +find_path(OSS_INCLUDE_DIR + NAMES sys/soundcard.h + DOC "The OSS include directory" +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OSS REQUIRED_VARS OSS_INCLUDE_DIR) + +if(OSS_FOUND) + set(OSS_INCLUDE_DIRS ${OSS_INCLUDE_DIR}) +endif() + +mark_as_advanced(OSS_INCLUDE_DIR) diff --git a/jni/openal-soft-1.16.0/cmake/FindPortAudio.cmake b/jni/openal-soft-1.16.0/cmake/FindPortAudio.cmake new file mode 100644 index 00000000..fad2313d --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/cmake/FindPulseAudio.cmake b/jni/openal-soft-1.16.0/cmake/FindPulseAudio.cmake new file mode 100644 index 00000000..1f6f843a --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/cmake/FindQSA.cmake b/jni/openal-soft-1.16.0/cmake/FindQSA.cmake new file mode 100644 index 00000000..0ad1fd43 --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/cmake/FindSDL2.cmake b/jni/openal-soft-1.16.0/cmake/FindSDL2.cmake new file mode 100644 index 00000000..70e607a8 --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/cmake/FindSDL_sound.cmake b/jni/openal-soft-1.16.0/cmake/FindSDL_sound.cmake new file mode 100644 index 00000000..2dab1a1c --- /dev/null +++ b/jni/openal-soft-1.16.0/cmake/FindSDL_sound.cmake @@ -0,0 +1,380 @@ +# - Locates the SDL_sound library +# +# This module depends on SDL being found and +# must be called AFTER FindSDL.cmake or FindSDL2.cmake is called. +# +# This module defines +# SDL_SOUND_INCLUDE_DIR, where to find SDL_sound.h +# SDL_SOUND_FOUND, if false, do not try to link to SDL_sound +# SDL_SOUND_LIBRARIES, this contains the list of libraries that you need +# to link against. This is a read-only variable and is marked INTERNAL. +# SDL_SOUND_EXTRAS, this is an optional variable for you to add your own +# flags to SDL_SOUND_LIBRARIES. This is prepended to SDL_SOUND_LIBRARIES. +# This is available mostly for cases this module failed to anticipate for +# and you must add additional flags. This is marked as ADVANCED. +# SDL_SOUND_VERSION_STRING, human-readable string containing the version of SDL_sound +# +# This module also defines (but you shouldn't need to use directly) +# SDL_SOUND_LIBRARY, the name of just the SDL_sound library you would link +# against. Use SDL_SOUND_LIBRARIES for you link instructions and not this one. +# And might define the following as needed +# MIKMOD_LIBRARY +# MODPLUG_LIBRARY +# OGG_LIBRARY +# VORBIS_LIBRARY +# SMPEG_LIBRARY +# FLAC_LIBRARY +# SPEEX_LIBRARY +# +# Typically, you should not use these variables directly, and you should use +# SDL_SOUND_LIBRARIES which contains SDL_SOUND_LIBRARY and the other audio libraries +# (if needed) to successfully compile on your system. +# +# Created by Eric Wing. +# This module is a bit more complicated than the other FindSDL* family modules. +# The reason is that SDL_sound can be compiled in a large variety of different ways +# which are independent of platform. SDL_sound may dynamically link against other 3rd +# party libraries to get additional codec support, such as Ogg Vorbis, SMPEG, ModPlug, +# MikMod, FLAC, Speex, and potentially others. +# Under some circumstances which I don't fully understand, +# there seems to be a requirement +# that dependent libraries of libraries you use must also be explicitly +# linked against in order to successfully compile. SDL_sound does not currently +# have any system in place to know how it was compiled. +# So this CMake module does the hard work in trying to discover which 3rd party +# libraries are required for building (if any). +# This module uses a brute force approach to create a test program that uses SDL_sound, +# and then tries to build it. If the build fails, it parses the error output for +# known symbol names to figure out which libraries are needed. +# +# Responds to the $SDLDIR and $SDLSOUNDDIR environmental variable that would +# correspond to the ./configure --prefix=$SDLDIR used in building SDL. +# +# On OSX, this will prefer the Framework version (if found) over others. +# People will have to manually change the cache values of +# SDL_LIBRARY or SDL2_LIBRARY to override this selection or set the CMake +# environment CMAKE_INCLUDE_PATH to modify the search paths. + +#============================================================================= +# Copyright 2005-2009 Kitware, Inc. +# Copyright 2012 Benjamin Eikel +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +set(SDL_SOUND_EXTRAS "" CACHE STRING "SDL_sound extra flags") +mark_as_advanced(SDL_SOUND_EXTRAS) + +# Find SDL_sound.h +find_path(SDL_SOUND_INCLUDE_DIR SDL_sound.h + HINTS + ENV SDLSOUNDDIR + ENV SDLDIR + PATH_SUFFIXES SDL SDL12 SDL11 +) + +find_library(SDL_SOUND_LIBRARY + NAMES SDL_sound + HINTS + ENV SDLSOUNDDIR + ENV SDLDIR +) + +if(SDL2_FOUND OR SDL_FOUND) + if(SDL_SOUND_INCLUDE_DIR AND SDL_SOUND_LIBRARY) + # CMake is giving me problems using TRY_COMPILE with the CMAKE_FLAGS + # for the :STRING syntax if I have multiple values contained in a + # single variable. This is a problem for the SDL2_LIBRARY variable + # because it does just that. When I feed this variable to the command, + # only the first value gets the appropriate modifier (e.g. -I) and + # the rest get dropped. + # To get multiple single variables to work, I must separate them with a "\;" + # I could go back and modify the FindSDL2.cmake module, but that's kind of painful. + # The solution would be to try something like: + # set(SDL2_TRY_COMPILE_LIBRARY_LIST "${SDL2_TRY_COMPILE_LIBRARY_LIST}\;${CMAKE_THREAD_LIBS_INIT}") + # Instead, it was suggested on the mailing list to write a temporary CMakeLists.txt + # with a temporary test project and invoke that with TRY_COMPILE. + # See message thread "Figuring out dependencies for a library in order to build" + # 2005-07-16 + # try_compile( + # MY_RESULT + # ${CMAKE_BINARY_DIR} + # ${PROJECT_SOURCE_DIR}/DetermineSoundLibs.c + # CMAKE_FLAGS + # -DINCLUDE_DIRECTORIES:STRING=${SDL2_INCLUDE_DIR}\;${SDL_SOUND_INCLUDE_DIR} + # -DLINK_LIBRARIES:STRING=${SDL_SOUND_LIBRARY}\;${SDL2_LIBRARY} + # OUTPUT_VARIABLE MY_OUTPUT + # ) + + # To minimize external dependencies, create a sdlsound test program + # which will be used to figure out if additional link dependencies are + # required for the link phase. + file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/DetermineSoundLibs.c + "#include \"SDL_sound.h\" + #include \"SDL.h\" + int main(int argc, char* argv[]) + { + Sound_AudioInfo desired; + Sound_Sample* sample; + + SDL_Init(0); + Sound_Init(); + + /* This doesn't actually have to work, but Init() is a no-op + * for some of the decoders, so this should force more symbols + * to be pulled in. + */ + sample = Sound_NewSampleFromFile(argv[1], &desired, 4096); + + Sound_Quit(); + SDL_Quit(); + return 0; + }" + ) + + # Calling + # target_link_libraries(DetermineSoundLibs "${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY}) + # causes problems when SDL2_LIBRARY looks like + # /Library/Frameworks/SDL2.framework;-framework Cocoa + # The ;-framework Cocoa seems to be confusing CMake once the OS X + # framework support was added. I was told that breaking up the list + # would fix the problem. + set(TMP_TRY_LIBS) + if(SDL2_FOUND) + foreach(lib ${SDL_SOUND_LIBRARY} ${SDL2_LIBRARY}) + set(TMP_TRY_LIBS "${TMP_TRY_LIBS} \"${lib}\"") + endforeach() + set(TMP_INCLUDE_DIRS ${SDL2_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR}) + else() + foreach(lib ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY}) + set(TMP_TRY_LIBS "${TMP_TRY_LIBS} \"${lib}\"") + endforeach() + set(TMP_INCLUDE_DIRS ${SDL_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR}) + endif() + + # message("TMP_TRY_LIBS ${TMP_TRY_LIBS}") + + # Write the CMakeLists.txt and test project + # Weird, this is still sketchy. If I don't quote the variables + # in the TARGET_LINK_LIBRARIES, I seem to loose everything + # in the SDL2_LIBRARY string after the "-framework". + # But if I quote the stuff in INCLUDE_DIRECTORIES, it doesn't work. + file(WRITE ${PROJECT_BINARY_DIR}/CMakeTmp/CMakeLists.txt + "cmake_minimum_required(VERSION 2.8) + project(DetermineSoundLibs C) + include_directories(${TMP_INCLUDE_DIRS}) + add_executable(DetermineSoundLibs DetermineSoundLibs.c) + target_link_libraries(DetermineSoundLibs ${TMP_TRY_LIBS})" + ) + unset(TMP_INCLUDE_DIRS) + unset(TMP_TRY_LIBS) + + try_compile( + MY_RESULT + ${PROJECT_BINARY_DIR}/CMakeTmp + ${PROJECT_BINARY_DIR}/CMakeTmp + DetermineSoundLibs + OUTPUT_VARIABLE MY_OUTPUT + ) + # message("${MY_RESULT}") + # message(${MY_OUTPUT}) + + if(NOT MY_RESULT) + # I expect that MPGLIB, VOC, WAV, AIFF, and SHN are compiled in statically. + # I think Timidity is also compiled in statically. + # I've never had to explcitly link against Quicktime, so I'll skip that for now. + + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY}) + + # Find MikMod + if("${MY_OUTPUT}" MATCHES "MikMod_") + find_library(MIKMOD_LIBRARY + NAMES libmikmod-coreaudio mikmod + PATHS + ENV MIKMODDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(MIKMOD_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MIKMOD_LIBRARY}) + endif(MIKMOD_LIBRARY) + endif("${MY_OUTPUT}" MATCHES "MikMod_") + + # Find ModPlug + if("${MY_OUTPUT}" MATCHES "MODPLUG_") + find_library(MODPLUG_LIBRARY + NAMES modplug + PATHS + ENV MODPLUGDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(MODPLUG_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MODPLUG_LIBRARY}) + endif() + endif() + + # Find Ogg and Vorbis + if("${MY_OUTPUT}" MATCHES "ov_") + find_library(VORBIS_LIBRARY + NAMES vorbis Vorbis VORBIS + PATHS + ENV VORBISDIR + ENV OGGDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(VORBIS_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBIS_LIBRARY}) + endif() + find_library(OGG_LIBRARY + NAMES ogg Ogg OGG + PATHS + ENV OGGDIR + ENV VORBISDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(OGG_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY}) + endif() + endif() + + # Find SMPEG + if("${MY_OUTPUT}" MATCHES "SMPEG_") + find_library(SMPEG_LIBRARY + NAMES smpeg SMPEG Smpeg SMpeg + PATHS + ENV SMPEGDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(SMPEG_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SMPEG_LIBRARY}) + endif() + endif() + + + # Find FLAC + if("${MY_OUTPUT}" MATCHES "FLAC_") + find_library(FLAC_LIBRARY + NAMES flac FLAC + PATHS + ENV FLACDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(FLAC_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${FLAC_LIBRARY}) + endif() + endif() + + + # Hmmm...Speex seems to depend on Ogg. This might be a problem if + # the TRY_COMPILE attempt gets blocked at SPEEX before it can pull + # in the Ogg symbols. I'm not sure if I should duplicate the ogg stuff + # above for here or if two ogg entries will screw up things. + if("${MY_OUTPUT}" MATCHES "speex_") + find_library(SPEEX_LIBRARY + NAMES speex SPEEX + PATHS + ENV SPEEXDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(SPEEX_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SPEEX_LIBRARY}) + endif() + + # Find OGG (needed for Speex) + # We might have already found Ogg for Vorbis, so skip it if so. + if(NOT OGG_LIBRARY) + find_library(OGG_LIBRARY + NAMES ogg Ogg OGG + PATHS + ENV OGGDIR + ENV VORBISDIR + ENV SPEEXDIR + ENV SDLSOUNDDIR + ENV SDLDIR + /sw + /opt/local + /opt/csw + /opt + PATH_SUFFIXES lib + ) + if(OGG_LIBRARY) + set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY}) + endif() + endif() + endif() + + set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARIES_TMP} CACHE INTERNAL "SDL_sound and dependent libraries") + else() + set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARY} CACHE INTERNAL "SDL_sound and dependent libraries") + endif() + endif() +endif() + +if(SDL_SOUND_INCLUDE_DIR AND EXISTS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h") + file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_MAJOR_LINE REGEX "^#define[ \t]+SOUND_VER_MAJOR[ \t]+[0-9]+$") + file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_MINOR_LINE REGEX "^#define[ \t]+SOUND_VER_MINOR[ \t]+[0-9]+$") + file(STRINGS "${SDL_SOUND_INCLUDE_DIR}/SDL_sound.h" SDL_SOUND_VERSION_PATCH_LINE REGEX "^#define[ \t]+SOUND_VER_PATCH[ \t]+[0-9]+$") + string(REGEX REPLACE "^#define[ \t]+SOUND_VER_MAJOR[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_MAJOR "${SDL_SOUND_VERSION_MAJOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SOUND_VER_MINOR[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_MINOR "${SDL_SOUND_VERSION_MINOR_LINE}") + string(REGEX REPLACE "^#define[ \t]+SOUND_VER_PATCH[ \t]+([0-9]+)$" "\\1" SDL_SOUND_VERSION_PATCH "${SDL_SOUND_VERSION_PATCH_LINE}") + set(SDL_SOUND_VERSION_STRING ${SDL_SOUND_VERSION_MAJOR}.${SDL_SOUND_VERSION_MINOR}.${SDL_SOUND_VERSION_PATCH}) + unset(SDL_SOUND_VERSION_MAJOR_LINE) + unset(SDL_SOUND_VERSION_MINOR_LINE) + unset(SDL_SOUND_VERSION_PATCH_LINE) + unset(SDL_SOUND_VERSION_MAJOR) + unset(SDL_SOUND_VERSION_MINOR) + unset(SDL_SOUND_VERSION_PATCH) +endif() + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(SDL_sound + REQUIRED_VARS SDL_SOUND_LIBRARIES SDL_SOUND_INCLUDE_DIR + VERSION_VAR SDL_SOUND_VERSION_STRING) diff --git a/jni/openal-soft-1.16.0/cmake/FindSoundIO.cmake b/jni/openal-soft-1.16.0/cmake/FindSoundIO.cmake new file mode 100644 index 00000000..10450254 --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/common/atomic.c b/jni/openal-soft-1.16.0/common/atomic.c new file mode 100644 index 00000000..3cdb77f4 --- /dev/null +++ b/jni/openal-soft-1.16.0/common/atomic.c @@ -0,0 +1,13 @@ + +#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); + +extern inline int ExchangeInt(volatile int *ptr, int newval); +extern inline void *ExchangePtr(XchgPtr *ptr, void *newval); diff --git a/jni/openal-soft-1.16.0/common/rwlock.c b/jni/openal-soft-1.16.0/common/rwlock.c new file mode 100644 index 00000000..cfa3aee4 --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/common/threads.c b/jni/openal-soft-1.16.0/common/threads.c new file mode 100644 index 00000000..cd9f6755 --- /dev/null +++ b/jni/openal-soft-1.16.0/common/threads.c @@ -0,0 +1,744 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 1999-2007 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include "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 (1*1024*1024) /* 1MB */ + +#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|almtx_timed); + 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 *mtx, const struct timespec *ts) +{ + int ret; + + if(!mtx || !ts) + return althrd_error; + + while((ret=almtx_trylock(mtx)) == althrd_busy) + { + struct timespec now; + + if(ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000 || + altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) + return althrd_error; + if(now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec && now.tv_nsec >= ts->tv_nsec)) + return althrd_timedout; + + althrd_yield(); + } + + return ret; +} + +#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; + + 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] = CreateEvent(NULL, FALSE, FALSE, NULL); + icond->events[BROADCAST] = CreateEvent(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; + 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.array[i].key); + altss_dtor_t callback = (altss_dtor_t)TlsDestructors.array[i].value; + 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(__GNUC__) + pthread_setname_np(thr, name); +#elif defined(__APPLE__) + if(althrd_equal(thr, althrd_current()) + pthread_setname_np(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; + + cntr = malloc(sizeof(*cntr)); + if(!cntr) return althrd_nomem; + + if(pthread_attr_init(&attr) != 0) + { + free(cntr); + return althrd_error; + } + if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE) != 0) + { + pthread_attr_destroy(&attr); + free(cntr); + return althrd_error; + } + + cntr->func = func; + cntr->arg = arg; + if(pthread_create(thr, &attr, althrd_starter, cntr) != 0) + { + pthread_attr_destroy(&attr); + free(cntr); + return althrd_error; + } + pthread_attr_destroy(&attr); + + return althrd_success; +} + +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; + if((type&~(almtx_recursive|almtx_timed)) != 0) + return althrd_error; + + 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) +{ + int ret; + +#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK + ret = pthread_mutex_timedlock(mtx, ts); + switch(ret) + { + case 0: return althrd_success; + case ETIMEDOUT: return althrd_timedout; + case EBUSY: return althrd_busy; + } + return althrd_error; +#else + if(!mtx || !ts) + return althrd_error; + + while((ret=almtx_trylock(mtx)) == althrd_busy) + { + struct timespec now; + + if(ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000 || + altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) + return althrd_error; + if(now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec && now.tv_nsec >= ts->tv_nsec)) + return althrd_timedout; + + althrd_yield(); + } + + return ret; +#endif +} + +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(time_t sec, long nsec) +{ + struct timespec ts, rem; + ts.tv_sec = sec; + ts.tv_nsec = nsec; + + while(althrd_sleep(&ts, &rem) == -1) + ts = rem; +} diff --git a/jni/openal-soft-1.16.0/common/uintmap.c b/jni/openal-soft-1.16.0/common/uintmap.c new file mode 100644 index 00000000..b7a9a29c --- /dev/null +++ b/jni/openal-soft-1.16.0/common/uintmap.c @@ -0,0 +1,144 @@ + +#include "config.h" + +#include "uintmap.h" + +#include +#include + + +extern inline void LockUIntMapRead(UIntMap *map); +extern inline void UnlockUIntMapRead(UIntMap *map); +extern inline void LockUIntMapWrite(UIntMap *map); +extern inline void UnlockUIntMapWrite(UIntMap *map); + + +void InitUIntMap(UIntMap *map, ALsizei limit) +{ + map->array = NULL; + map->size = 0; + map->maxsize = 0; + map->limit = limit; + RWLockInit(&map->lock); +} + +void ResetUIntMap(UIntMap *map) +{ + WriteLock(&map->lock); + free(map->array); + map->array = NULL; + map->size = 0; + map->maxsize = 0; + WriteUnlock(&map->lock); +} + +ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value) +{ + ALsizei pos = 0; + + WriteLock(&map->lock); + if(map->size > 0) + { + ALsizei low = 0; + ALsizei high = map->size - 1; + while(low < high) + { + ALsizei mid = low + (high-low)/2; + if(map->array[mid].key < key) + low = mid + 1; + else + high = mid; + } + if(map->array[low].key < key) + low++; + pos = low; + } + + if(pos == map->size || map->array[pos].key != key) + { + if(map->size == map->limit) + { + WriteUnlock(&map->lock); + return AL_OUT_OF_MEMORY; + } + + if(map->size == map->maxsize) + { + ALvoid *temp = NULL; + ALsizei newsize; + + newsize = (map->maxsize ? (map->maxsize<<1) : 4); + if(newsize >= map->maxsize) + temp = realloc(map->array, newsize*sizeof(map->array[0])); + if(!temp) + { + WriteUnlock(&map->lock); + return AL_OUT_OF_MEMORY; + } + map->array = temp; + map->maxsize = newsize; + } + + if(pos < map->size) + memmove(&map->array[pos+1], &map->array[pos], + (map->size-pos)*sizeof(map->array[0])); + map->size++; + } + map->array[pos].key = key; + map->array[pos].value = value; + WriteUnlock(&map->lock); + + return AL_NO_ERROR; +} + +ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key) +{ + ALvoid *ptr = NULL; + WriteLock(&map->lock); + if(map->size > 0) + { + ALsizei low = 0; + ALsizei high = map->size - 1; + while(low < high) + { + ALsizei mid = low + (high-low)/2; + if(map->array[mid].key < key) + low = mid + 1; + else + high = mid; + } + if(map->array[low].key == key) + { + ptr = map->array[low].value; + if(low < map->size-1) + memmove(&map->array[low], &map->array[low+1], + (map->size-1-low)*sizeof(map->array[0])); + map->size--; + } + } + WriteUnlock(&map->lock); + return ptr; +} + +ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key) +{ + ALvoid *ptr = NULL; + ReadLock(&map->lock); + if(map->size > 0) + { + ALsizei low = 0; + ALsizei high = map->size - 1; + while(low < high) + { + ALsizei mid = low + (high-low)/2; + if(map->array[mid].key < key) + low = mid + 1; + else + high = mid; + } + if(map->array[low].key == key) + ptr = map->array[low].value; + } + ReadUnlock(&map->lock); + return ptr; +} diff --git a/jni/openal-soft-android/config.h b/jni/openal-soft-1.16.0/config.h similarity index 72% rename from jni/openal-soft-android/config.h rename to jni/openal-soft-1.16.0/config.h index cc3c005b..d67d7a41 100644 --- a/jni/openal-soft-android/config.h +++ b/jni/openal-soft-1.16.0/config.h @@ -3,7 +3,7 @@ #define ALC_API __attribute__((visibility("protected"))) /* Define to the library version */ -#define ALSOFT_VERSION "1.15.1" +#define ALSOFT_VERSION "1.16.0" #ifdef IN_IDE_PARSER /* KDevelop's parser doesn't recognize the C99-standard restrict keyword, but @@ -25,9 +25,11 @@ /* Define if we have SSE CPU extensions */ /* #undef HAVE_SSE */ +/* #undef HAVE_SSE2 */ +/* #undef HAVE_SSE4_1 */ /* Define if we have ARM Neon CPU extensions */ -#undef HAVE_NEON +/* #undef HAVE_NEON */ /* Define if we have FluidSynth support */ /* #undef HAVE_FLUIDSYNTH */ @@ -89,6 +91,21 @@ /* Define to the size of a long long int type */ #define SIZEOF_LONG_LONG 8 +/* Define if we have C99 variable-length array support */ +#define HAVE_C99_VLA + +/* Define if we have C99 _Bool support */ +#define HAVE_C99_BOOL + +/* Define if we have C11 _Static_assert support */ +#define HAVE_C11_STATIC_ASSERT + +/* Define if we have C11 _Alignas support */ +/* #undef HAVE_C11_ALIGNAS */ + +/* Define if we have C11 _Atomic support */ +/* #undef HAVE_C11_ATOMIC */ + /* Define if we have GCC's destructor attribute */ #define HAVE_GCC_DESTRUCTOR @@ -98,6 +115,12 @@ /* Define if we have stdint.h */ #define HAVE_STDINT_H +/* Define if we have stdbool.h */ +#define HAVE_STDBOOL_H + +/* Define if we have stdalign.h */ +/* #undef HAVE_STDALIGN_H */ + /* Define if we have windows.h */ /* #undef HAVE_WINDOWS_H */ @@ -107,21 +130,27 @@ /* Define if we have pthread_np.h */ /* #undef HAVE_PTHREAD_NP_H */ -/* Define if we have xmmintrin.h */ -/* #undef HAVE_XMMINTRIN_H */ - -/* Define if we have arm_neon.h */ -/* #undef HAVE_ARM_NEON_H */ +/* Define if we have alloca.h */ +/* #undef HAVE_ALLOCA_H */ /* Define if we have malloc.h */ #define HAVE_MALLOC_H +/* Define if we have ftw.h */ +/* #undef HAVE_FTW_H */ + +/* Define if we have io.h */ +/* #undef HAVE_IO_H */ + /* Define if we have strings.h */ #define HAVE_STRINGS_H /* Define if we have cpuid.h */ /* #undef HAVE_CPUID_H */ +/* Define if we have intrin.h */ +/* #undef HAVE_INTRIN_H */ + /* Define if we have sys/sysconf.h */ #define HAVE_SYS_SYSCONF_H @@ -140,17 +169,35 @@ /* Define if we have fenv.h */ #define HAVE_FENV_H +/* Define if we have GCC's __get_cpuid() */ +/* #undef HAVE_GCC_GET_CPUID */ + +/* Define if we have the __cpuid() intrinsic */ +/* #undef HAVE_CPUID_INTRINSIC */ + /* Define if we have _controlfp() */ /* #undef HAVE__CONTROLFP */ /* Define if we have __control87_2() */ /* #undef HAVE___CONTROL87_2 */ +/* Define if we have ftw() */ +/* #undef HAVE_FTW */ + +/* Define if we have _wfindfirst() */ +/* #undef HAVE__WFINDFIRST */ + /* Define if we have pthread_setschedparam() */ #define HAVE_PTHREAD_SETSCHEDPARAM /* Define if we have pthread_setname_np() */ -/* #undef HAVE_PTHREAD_SETNAME_NP */ +#define HAVE_PTHREAD_SETNAME_NP /* Define if we have pthread_set_name_np() */ /* #undef HAVE_PTHREAD_SET_NAME_NP */ + +/* Define if we have pthread_mutexattr_setkind_np() */ +/* #undef HAVE_PTHREAD_MUTEXATTR_SETKIND_NP */ + +/* Define if we have pthread_mutex_timedlock() */ +/* #undef HAVE_PTHREAD_MUTEX_TIMEDLOCK */ diff --git a/jni/openal-soft-android/config.h.in b/jni/openal-soft-1.16.0/config.h.in similarity index 74% rename from jni/openal-soft-android/config.h.in rename to jni/openal-soft-1.16.0/config.h.in index d9582e74..af0d8bfd 100644 --- a/jni/openal-soft-android/config.h.in +++ b/jni/openal-soft-1.16.0/config.h.in @@ -25,6 +25,8 @@ /* Define if we have SSE CPU extensions */ #cmakedefine HAVE_SSE +#cmakedefine HAVE_SSE2 +#cmakedefine HAVE_SSE4_1 /* Define if we have ARM Neon CPU extensions */ #cmakedefine HAVE_NEON @@ -89,6 +91,21 @@ /* 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 @@ -98,6 +115,12 @@ /* 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 @@ -107,21 +130,27 @@ /* Define if we have pthread_np.h */ #cmakedefine HAVE_PTHREAD_NP_H -/* Define if we have xmmintrin.h */ -#cmakedefine HAVE_XMMINTRIN_H - -/* Define if we have arm_neon.h */ -#cmakedefine HAVE_ARM_NEON_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 ftw.h */ +#cmakedefine HAVE_FTW_H + +/* Define if we have io.h */ +#cmakedefine HAVE_IO_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 @@ -140,12 +169,24 @@ /* 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 ftw() */ +#cmakedefine HAVE_FTW + +/* Define if we have _wfindfirst() */ +#cmakedefine HAVE__WFINDFIRST + /* Define if we have pthread_setschedparam() */ #cmakedefine HAVE_PTHREAD_SETSCHEDPARAM @@ -154,3 +195,9 @@ /* 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/jni/openal-soft-android/env-vars.txt b/jni/openal-soft-1.16.0/env-vars.txt similarity index 100% rename from jni/openal-soft-android/env-vars.txt rename to jni/openal-soft-1.16.0/env-vars.txt diff --git a/jni/openal-soft-1.16.0/examples/alffplay.c b/jni/openal-soft-1.16.0/examples/alffplay.c new file mode 100644 index 00000000..d8ef0e57 --- /dev/null +++ b/jni/openal-soft-1.16.0/examples/alffplay.c @@ -0,0 +1,1479 @@ +/* + * alffplay.c + * + * A pedagogical video player that really works! Now with seeking features. + * + * Code based on FFplay, Copyright (c) 2003 Fabrice Bellard, and a tutorial by + * Martin Bohme . + * + * Requires C99. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "threads.h" +#include "bool.h" + +#include "AL/al.h" +#include "AL/alc.h" +#include "AL/alext.h" + + +static bool has_latency_check = false; +static LPALGETSOURCEDVSOFT alGetSourcedvSOFT; + +#define AUDIO_BUFFER_TIME 100 /* In milliseconds, per-buffer */ +#define AUDIO_BUFFER_QUEUE_SIZE 8 /* Number of buffers to queue */ +#define MAX_AUDIOQ_SIZE (5 * 16 * 1024) /* Bytes of compressed audio data to keep queued */ +#define MAX_VIDEOQ_SIZE (5 * 256 * 1024) /* Bytes of compressed video data to keep queued */ +#define AV_SYNC_THRESHOLD 0.01 +#define AV_NOSYNC_THRESHOLD 10.0 +#define SAMPLE_CORRECTION_MAX_DIFF 0.1 +#define AUDIO_DIFF_AVG_NB 20 +#define VIDEO_PICTURE_QUEUE_SIZE 16 + +enum { + FF_UPDATE_EVENT = SDL_USEREVENT, + FF_REFRESH_EVENT, + FF_QUIT_EVENT +}; + + +typedef struct PacketQueue { + AVPacketList *first_pkt, *last_pkt; + volatile int nb_packets; + volatile int size; + volatile bool flushing; + almtx_t mutex; + alcnd_t cond; +} PacketQueue; + +typedef struct VideoPicture { + SDL_Texture *bmp; + int width, height; /* Logical image size (actual size may be larger) */ + volatile bool updated; + double pts; +} VideoPicture; + +typedef struct AudioState { + AVStream *st; + + PacketQueue q; + AVPacket pkt; + + /* Used for clock difference average computation */ + double diff_accum; + double diff_avg_coef; + double diff_threshold; + + /* Time (in seconds) of the next sample to be buffered */ + double current_pts; + + /* Decompressed sample frame, and swresample context for conversion */ + AVFrame *decoded_aframe; + struct SwrContext *swres_ctx; + + /* Conversion format, for what gets fed to OpenAL */ + int dst_ch_layout; + enum AVSampleFormat dst_sample_fmt; + + /* Storage of converted samples */ + uint8_t *samples; + ssize_t samples_len; /* In samples */ + ssize_t samples_pos; + int samples_max; + + /* OpenAL format */ + ALenum format; + ALint frame_size; + + ALuint source; + ALuint buffer[AUDIO_BUFFER_QUEUE_SIZE]; + ALuint buffer_idx; + almtx_t src_mutex; + + althrd_t thread; +} AudioState; + +typedef struct VideoState { + AVStream *st; + + PacketQueue q; + + double clock; + double frame_timer; + double frame_last_pts; + double frame_last_delay; + double current_pts; + /* time (av_gettime) at which we updated current_pts - used to have running video pts */ + int64_t current_pts_time; + + /* Decompressed video frame, and swscale context for conversion */ + AVFrame *decoded_vframe; + struct SwsContext *swscale_ctx; + + VideoPicture pictq[VIDEO_PICTURE_QUEUE_SIZE]; + int pictq_size, pictq_rindex, pictq_windex; + almtx_t pictq_mutex; + alcnd_t pictq_cond; + + althrd_t thread; +} VideoState; + +typedef struct MovieState { + AVFormatContext *pFormatCtx; + int videoStream, audioStream; + + volatile bool seek_req; + int64_t seek_pos; + + int av_sync_type; + + int64_t external_clock_base; + + AudioState audio; + VideoState video; + + althrd_t parse_thread; + + char filename[1024]; + + volatile bool quit; +} MovieState; + +enum { + AV_SYNC_AUDIO_MASTER, + AV_SYNC_VIDEO_MASTER, + AV_SYNC_EXTERNAL_MASTER, + + DEFAULT_AV_SYNC_TYPE = AV_SYNC_EXTERNAL_MASTER +}; + +static AVPacket flush_pkt = { .data = (uint8_t*)"FLUSH" }; + +static void packet_queue_init(PacketQueue *q) +{ + memset(q, 0, sizeof(PacketQueue)); + almtx_init(&q->mutex, almtx_plain); + alcnd_init(&q->cond); +} +static int packet_queue_put(PacketQueue *q, AVPacket *pkt) +{ + AVPacketList *pkt1; + if(pkt != &flush_pkt && !pkt->buf && av_dup_packet(pkt) < 0) + return -1; + + pkt1 = av_malloc(sizeof(AVPacketList)); + if(!pkt1) return -1; + pkt1->pkt = *pkt; + pkt1->next = NULL; + + almtx_lock(&q->mutex); + if(!q->last_pkt) + q->first_pkt = pkt1; + else + q->last_pkt->next = pkt1; + q->last_pkt = pkt1; + q->nb_packets++; + q->size += pkt1->pkt.size; + almtx_unlock(&q->mutex); + + alcnd_signal(&q->cond); + return 0; +} +static int packet_queue_get(PacketQueue *q, AVPacket *pkt, MovieState *state) +{ + AVPacketList *pkt1; + int ret = -1; + + almtx_lock(&q->mutex); + while(!state->quit) + { + pkt1 = q->first_pkt; + if(pkt1) + { + q->first_pkt = pkt1->next; + if(!q->first_pkt) + q->last_pkt = NULL; + q->nb_packets--; + q->size -= pkt1->pkt.size; + *pkt = pkt1->pkt; + av_free(pkt1); + ret = 1; + break; + } + + if(q->flushing) + { + ret = 0; + break; + } + alcnd_wait(&q->cond, &q->mutex); + } + almtx_unlock(&q->mutex); + return ret; +} +static void packet_queue_clear(PacketQueue *q) +{ + AVPacketList *pkt, *pkt1; + + almtx_lock(&q->mutex); + for(pkt = q->first_pkt;pkt != NULL;pkt = pkt1) + { + pkt1 = pkt->next; + if(pkt->pkt.data != flush_pkt.data) + av_free_packet(&pkt->pkt); + av_freep(&pkt); + } + q->last_pkt = NULL; + q->first_pkt = NULL; + q->nb_packets = 0; + q->size = 0; + almtx_unlock(&q->mutex); +} +static void packet_queue_flush(PacketQueue *q) +{ + almtx_lock(&q->mutex); + q->flushing = true; + almtx_unlock(&q->mutex); + alcnd_signal(&q->cond); +} +static void packet_queue_deinit(PacketQueue *q) +{ + packet_queue_clear(q); + alcnd_destroy(&q->cond); + almtx_destroy(&q->mutex); +} + + +static double get_audio_clock(AudioState *state) +{ + double pts; + + almtx_lock(&state->src_mutex); + /* The audio clock is the timestamp of the sample currently being heard. + * It's based on 4 components: + * 1 - The timestamp of the next sample to buffer (state->current_pts) + * 2 - The length of the source's buffer queue (AL_SEC_LENGTH_SOFT) + * 3 - The offset OpenAL is currently at in the source (the first value + * from AL_SEC_OFFSET_LATENCY_SOFT) + * 4 - The latency between OpenAL and the DAC (the second value from + * AL_SEC_OFFSET_LATENCY_SOFT) + * + * Subtracting the length of the source queue from the next sample's + * timestamp gives the timestamp of the sample at start of the source + * queue. Adding the source offset to that results in the timestamp for + * OpenAL's current position, and subtracting the source latency from that + * gives the timestamp of the sample currently at the DAC. + */ + pts = state->current_pts; + if(state->source) + { + ALdouble offset[2] = { 0.0, 0.0 }; + ALdouble queue_len = 0.0; + ALint status; + + /* NOTE: The source state must be checked last, in case an underrun + * occurs and the source stops between retrieving the offset+latency + * and getting the state. */ + if(has_latency_check) + { + alGetSourcedvSOFT(state->source, AL_SEC_OFFSET_LATENCY_SOFT, offset); + alGetSourcedvSOFT(state->source, AL_SEC_LENGTH_SOFT, &queue_len); + } + else + { + ALint ioffset, ilen; + alGetSourcei(state->source, AL_SAMPLE_OFFSET, &ioffset); + alGetSourcei(state->source, AL_SAMPLE_LENGTH_SOFT, &ilen); + offset[0] = (double)ioffset / state->st->codec->sample_rate; + queue_len = (double)ilen / state->st->codec->sample_rate; + } + alGetSourcei(state->source, AL_SOURCE_STATE, &status); + + /* If the source is AL_STOPPED, then there was an underrun and all + * buffers are processed, so ignore the source queue. The audio thread + * will put the source into an AL_INITIAL state and clear the queue + * when it starts recovery. */ + if(status != AL_STOPPED) + pts = pts - queue_len + offset[0]; + if(status == AL_PLAYING) + pts = pts - offset[1]; + } + almtx_unlock(&state->src_mutex); + + return (pts >= 0.0) ? pts : 0.0; +} +static double get_video_clock(VideoState *state) +{ + double delta = (av_gettime() - state->current_pts_time) / 1000000.0; + return state->current_pts + delta; +} +static double get_external_clock(MovieState *movState) +{ + return (av_gettime()-movState->external_clock_base) / 1000000.0; +} + +double get_master_clock(MovieState *movState) +{ + if(movState->av_sync_type == AV_SYNC_VIDEO_MASTER) + return get_video_clock(&movState->video); + if(movState->av_sync_type == AV_SYNC_AUDIO_MASTER) + return get_audio_clock(&movState->audio); + return get_external_clock(movState); +} + +/* Return how many samples to skip to maintain sync (negative means to + * duplicate samples). */ +static int synchronize_audio(MovieState *movState) +{ + double diff, avg_diff; + double ref_clock; + + if(movState->av_sync_type == AV_SYNC_AUDIO_MASTER) + return 0; + + ref_clock = get_master_clock(movState); + diff = ref_clock - get_audio_clock(&movState->audio); + + if(!(diff < AV_NOSYNC_THRESHOLD)) + { + /* Difference is TOO big; reset diff stuff */ + movState->audio.diff_accum = 0.0; + return 0; + } + + /* Accumulate the diffs */ + movState->audio.diff_accum = movState->audio.diff_accum*movState->audio.diff_avg_coef + diff; + avg_diff = movState->audio.diff_accum*(1.0 - movState->audio.diff_avg_coef); + if(fabs(avg_diff) < movState->audio.diff_threshold) + return 0; + + /* Constrain the per-update difference to avoid exceedingly large skips */ + if(!(diff <= SAMPLE_CORRECTION_MAX_DIFF)) + diff = SAMPLE_CORRECTION_MAX_DIFF; + else if(!(diff >= -SAMPLE_CORRECTION_MAX_DIFF)) + diff = -SAMPLE_CORRECTION_MAX_DIFF; + return (int)(diff*movState->audio.st->codec->sample_rate); +} + +static int audio_decode_frame(MovieState *movState) +{ + AVPacket *pkt = &movState->audio.pkt; + + while(!movState->quit) + { + while(!movState->quit && pkt->size == 0) + { + av_free_packet(pkt); + + /* Get the next packet */ + int err; + if((err=packet_queue_get(&movState->audio.q, pkt, movState)) <= 0) + { + if(err == 0) + break; + return err; + } + if(pkt->data == flush_pkt.data) + { + avcodec_flush_buffers(movState->audio.st->codec); + movState->audio.diff_accum = 0.0; + movState->audio.current_pts = av_q2d(movState->audio.st->time_base)*pkt->pts; + + alSourceRewind(movState->audio.source); + alSourcei(movState->audio.source, AL_BUFFER, 0); + + av_new_packet(pkt, 0); + + return -1; + } + + /* If provided, update w/ pts */ + if(pkt->pts != AV_NOPTS_VALUE) + movState->audio.current_pts = av_q2d(movState->audio.st->time_base)*pkt->pts; + } + + AVFrame *frame = movState->audio.decoded_aframe; + int got_frame = 0; + int len1 = avcodec_decode_audio4(movState->audio.st->codec, frame, + &got_frame, pkt); + if(len1 < 0) break; + + if(len1 <= pkt->size) + { + /* Move the unread data to the front and clear the end bits */ + int remaining = pkt->size - len1; + memmove(pkt->data, &pkt->data[len1], remaining); + av_shrink_packet(pkt, remaining); + } + + if(!got_frame || frame->nb_samples <= 0) + { + av_frame_unref(frame); + continue; + } + + if(frame->nb_samples > movState->audio.samples_max) + { + av_freep(&movState->audio.samples); + av_samples_alloc( + &movState->audio.samples, NULL, movState->audio.st->codec->channels, + frame->nb_samples, movState->audio.dst_sample_fmt, 0 + ); + movState->audio.samples_max = frame->nb_samples; + } + /* Return the amount of sample frames converted */ + int data_size = swr_convert(movState->audio.swres_ctx, + &movState->audio.samples, frame->nb_samples, + (const uint8_t**)frame->data, frame->nb_samples + ); + + av_frame_unref(frame); + return data_size; + } + + return -1; +} + +static int read_audio(MovieState *movState, uint8_t *samples, int length) +{ + int sample_skip = synchronize_audio(movState); + int audio_size = 0; + + /* Read the next chunk of data, refill the buffer, and queue it + * on the source */ + length /= movState->audio.frame_size; + while(audio_size < length) + { + if(movState->audio.samples_len <= 0 || movState->audio.samples_pos >= movState->audio.samples_len) + { + int frame_len = audio_decode_frame(movState); + if(frame_len < 0) return -1; + + movState->audio.samples_len = frame_len; + if(movState->audio.samples_len == 0) + break; + + movState->audio.samples_pos = (movState->audio.samples_len < sample_skip) ? + movState->audio.samples_len : sample_skip; + sample_skip -= movState->audio.samples_pos; + + movState->audio.current_pts += (double)movState->audio.samples_pos / + (double)movState->audio.st->codec->sample_rate; + continue; + } + + int rem = length - audio_size; + if(movState->audio.samples_pos >= 0) + { + int n = movState->audio.frame_size; + int len = movState->audio.samples_len - movState->audio.samples_pos; + if(rem > len) rem = len; + memcpy(samples + audio_size*n, + movState->audio.samples + movState->audio.samples_pos*n, + rem*n); + } + else + { + int n = movState->audio.frame_size; + int len = -movState->audio.samples_pos; + if(rem > len) rem = len; + + /* Add samples by copying the first sample */ + if(n == 1) + { + uint8_t sample = ((uint8_t*)movState->audio.samples)[0]; + uint8_t *q = (uint8_t*)samples + audio_size; + for(int i = 0;i < rem;i++) + *(q++) = sample; + } + else if(n == 2) + { + uint16_t sample = ((uint16_t*)movState->audio.samples)[0]; + uint16_t *q = (uint16_t*)samples + audio_size; + for(int i = 0;i < rem;i++) + *(q++) = sample; + } + else if(n == 4) + { + uint32_t sample = ((uint32_t*)movState->audio.samples)[0]; + uint32_t *q = (uint32_t*)samples + audio_size; + for(int i = 0;i < rem;i++) + *(q++) = sample; + } + else if(n == 8) + { + uint64_t sample = ((uint64_t*)movState->audio.samples)[0]; + uint64_t *q = (uint64_t*)samples + audio_size; + for(int i = 0;i < rem;i++) + *(q++) = sample; + } + else + { + uint8_t *sample = movState->audio.samples; + uint8_t *q = samples + audio_size*n; + for(int i = 0;i < rem;i++) + { + memcpy(q, sample, n); + q += n; + } + } + } + + movState->audio.samples_pos += rem; + movState->audio.current_pts += (double)rem / movState->audio.st->codec->sample_rate; + audio_size += rem; + } + + return audio_size * movState->audio.frame_size; +} + +static int audio_thread(void *userdata) +{ + MovieState *movState = (MovieState*)userdata; + uint8_t *samples = NULL; + ALsizei buffer_len; + + alGenBuffers(AUDIO_BUFFER_QUEUE_SIZE, movState->audio.buffer); + alGenSources(1, &movState->audio.source); + + alSourcei(movState->audio.source, AL_SOURCE_RELATIVE, AL_TRUE); + alSourcei(movState->audio.source, AL_ROLLOFF_FACTOR, 0); + + av_new_packet(&movState->audio.pkt, 0); + + /* Find a suitable format for OpenAL. Currently does not handle surround + * sound (everything non-mono becomes stereo). */ + if(movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_U8 || + movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_U8P) + { + movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_U8; + movState->audio.frame_size = 1; + if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO) + { + movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO; + movState->audio.frame_size *= 1; + movState->audio.format = AL_FORMAT_MONO8; + } + else + { + movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO; + movState->audio.frame_size *= 2; + movState->audio.format = AL_FORMAT_STEREO8; + } + } + else if((movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_FLT || + movState->audio.st->codec->sample_fmt == AV_SAMPLE_FMT_FLTP) && + alIsExtensionPresent("AL_EXT_FLOAT32")) + { + movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_FLT; + movState->audio.frame_size = 4; + if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO) + { + movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO; + movState->audio.frame_size *= 1; + movState->audio.format = AL_FORMAT_MONO_FLOAT32; + } + else + { + movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO; + movState->audio.frame_size *= 2; + movState->audio.format = AL_FORMAT_STEREO_FLOAT32; + } + } + else + { + movState->audio.dst_sample_fmt = AV_SAMPLE_FMT_S16; + movState->audio.frame_size = 2; + if(movState->audio.st->codec->channel_layout == AV_CH_LAYOUT_MONO) + { + movState->audio.dst_ch_layout = AV_CH_LAYOUT_MONO; + movState->audio.frame_size *= 1; + movState->audio.format = AL_FORMAT_MONO16; + } + else + { + movState->audio.dst_ch_layout = AV_CH_LAYOUT_STEREO; + movState->audio.frame_size *= 2; + movState->audio.format = AL_FORMAT_STEREO16; + } + } + buffer_len = AUDIO_BUFFER_TIME * movState->audio.st->codec->sample_rate / 1000 * + movState->audio.frame_size; + samples = av_malloc(buffer_len); + + movState->audio.samples = NULL; + movState->audio.samples_max = 0; + movState->audio.samples_pos = 0; + movState->audio.samples_len = 0; + + if(!(movState->audio.decoded_aframe=av_frame_alloc())) + { + fprintf(stderr, "Failed to allocate audio frame\n"); + goto finish; + } + + movState->audio.swres_ctx = swr_alloc_set_opts(NULL, + movState->audio.dst_ch_layout, + movState->audio.dst_sample_fmt, + movState->audio.st->codec->sample_rate, + movState->audio.st->codec->channel_layout, + movState->audio.st->codec->sample_fmt, + movState->audio.st->codec->sample_rate, + 0, NULL + ); + if(!movState->audio.swres_ctx || swr_init(movState->audio.swres_ctx) != 0) + { + fprintf(stderr, "Failed to initialize audio converter\n"); + goto finish; + } + + almtx_lock(&movState->audio.src_mutex); + while(alGetError() == AL_NO_ERROR && !movState->quit) + { + /* First remove any processed buffers. */ + ALint processed; + alGetSourcei(movState->audio.source, AL_BUFFERS_PROCESSED, &processed); + alSourceUnqueueBuffers(movState->audio.source, processed, (ALuint[AUDIO_BUFFER_QUEUE_SIZE]){}); + + /* Refill the buffer queue. */ + ALint queued; + alGetSourcei(movState->audio.source, AL_BUFFERS_QUEUED, &queued); + while(queued < AUDIO_BUFFER_QUEUE_SIZE) + { + int audio_size; + + /* Read the next chunk of data, fill the buffer, and queue it on + * the source */ + audio_size = read_audio(movState, samples, buffer_len); + if(audio_size < 0) break; + + ALuint bufid = movState->audio.buffer[movState->audio.buffer_idx++]; + movState->audio.buffer_idx %= AUDIO_BUFFER_QUEUE_SIZE; + + alBufferData(bufid, movState->audio.format, samples, audio_size, + movState->audio.st->codec->sample_rate); + alSourceQueueBuffers(movState->audio.source, 1, &bufid); + queued++; + } + + /* Check that the source is playing. */ + ALint state; + alGetSourcei(movState->audio.source, AL_SOURCE_STATE, &state); + if(state == AL_STOPPED) + { + /* AL_STOPPED means there was an underrun. Double-check that all + * processed buffers are removed, then rewind the source to get it + * back into an AL_INITIAL state. */ + alGetSourcei(movState->audio.source, AL_BUFFERS_PROCESSED, &processed); + alSourceUnqueueBuffers(movState->audio.source, processed, (ALuint[AUDIO_BUFFER_QUEUE_SIZE]){}); + alSourceRewind(movState->audio.source); + continue; + } + + almtx_unlock(&movState->audio.src_mutex); + + /* (re)start the source if needed, and wait for a buffer to finish */ + if(state != AL_PLAYING && state != AL_PAUSED) + { + alGetSourcei(movState->audio.source, AL_BUFFERS_QUEUED, &queued); + if(queued > 0) alSourcePlay(movState->audio.source); + } + SDL_Delay(AUDIO_BUFFER_TIME); + + almtx_lock(&movState->audio.src_mutex); + } + almtx_unlock(&movState->audio.src_mutex); + +finish: + av_frame_free(&movState->audio.decoded_aframe); + swr_free(&movState->audio.swres_ctx); + + av_freep(&samples); + av_freep(&movState->audio.samples); + + alDeleteSources(1, &movState->audio.source); + alDeleteBuffers(AUDIO_BUFFER_QUEUE_SIZE, movState->audio.buffer); + + return 0; +} + + +static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque) +{ + (void)interval; + + SDL_PushEvent(&(SDL_Event){ .user={.type=FF_REFRESH_EVENT, .data1=opaque} }); + return 0; /* 0 means stop timer */ +} + +/* Schedule a video refresh in 'delay' ms */ +static void schedule_refresh(MovieState *movState, int delay) +{ + SDL_AddTimer(delay, sdl_refresh_timer_cb, movState); +} + +static void video_display(MovieState *movState, SDL_Window *screen, SDL_Renderer *renderer) +{ + VideoPicture *vp = &movState->video.pictq[movState->video.pictq_rindex]; + + if(!vp->bmp) + return; + + float aspect_ratio; + int win_w, win_h; + int w, h, x, y; + + if(movState->video.st->codec->sample_aspect_ratio.num == 0) + aspect_ratio = 0.0f; + else + { + aspect_ratio = av_q2d(movState->video.st->codec->sample_aspect_ratio) * + movState->video.st->codec->width / + movState->video.st->codec->height; + } + if(aspect_ratio <= 0.0f) + { + aspect_ratio = (float)movState->video.st->codec->width / + (float)movState->video.st->codec->height; + } + + SDL_GetWindowSize(screen, &win_w, &win_h); + h = win_h; + w = ((int)rint(h * aspect_ratio) + 3) & ~3; + if(w > win_w) + { + w = win_w; + h = ((int)rint(w / aspect_ratio) + 3) & ~3; + } + x = (win_w - w) / 2; + y = (win_h - h) / 2; + + SDL_RenderCopy(renderer, vp->bmp, + &(SDL_Rect){ .x=0, .y=0, .w=vp->width, .h=vp->height }, + &(SDL_Rect){ .x=x, .y=y, .w=w, .h=h } + ); + SDL_RenderPresent(renderer); +} + +static void video_refresh_timer(MovieState *movState, SDL_Window *screen, SDL_Renderer *renderer) +{ + if(!movState->video.st) + { + schedule_refresh(movState, 100); + return; + } + + almtx_lock(&movState->video.pictq_mutex); +retry: + if(movState->video.pictq_size == 0) + schedule_refresh(movState, 1); + else + { + VideoPicture *vp = &movState->video.pictq[movState->video.pictq_rindex]; + double actual_delay, delay, sync_threshold, ref_clock, diff; + + movState->video.current_pts = vp->pts; + movState->video.current_pts_time = av_gettime(); + + delay = vp->pts - movState->video.frame_last_pts; /* the pts from last time */ + if(delay <= 0 || delay >= 1.0) + { + /* if incorrect delay, use previous one */ + delay = movState->video.frame_last_delay; + } + /* save for next time */ + movState->video.frame_last_delay = delay; + movState->video.frame_last_pts = vp->pts; + + /* Update delay to sync to clock if not master source. */ + if(movState->av_sync_type != AV_SYNC_VIDEO_MASTER) + { + ref_clock = get_master_clock(movState); + diff = vp->pts - ref_clock; + + /* Skip or repeat the frame. Take delay into account. */ + sync_threshold = (delay > AV_SYNC_THRESHOLD) ? delay : AV_SYNC_THRESHOLD; + if(fabs(diff) < AV_NOSYNC_THRESHOLD) + { + if(diff <= -sync_threshold) + delay = 0; + else if(diff >= sync_threshold) + delay = 2 * delay; + } + } + + movState->video.frame_timer += delay; + /* Compute the REAL delay. */ + actual_delay = movState->video.frame_timer - (av_gettime() / 1000000.0); + if(!(actual_delay >= 0.010)) + { + /* We don't have time to handle this picture, just skip to the next one. */ + movState->video.pictq_rindex = (movState->video.pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE; + movState->video.pictq_size--; + alcnd_signal(&movState->video.pictq_cond); + goto retry; + } + schedule_refresh(movState, (int)(actual_delay*1000.0 + 0.5)); + + /* Show the picture! */ + video_display(movState, screen, renderer); + + /* Update queue for next picture. */ + movState->video.pictq_rindex = (movState->video.pictq_rindex+1)%VIDEO_PICTURE_QUEUE_SIZE; + movState->video.pictq_size--; + alcnd_signal(&movState->video.pictq_cond); + } + almtx_unlock(&movState->video.pictq_mutex); +} + + +static void update_picture(MovieState *movState, bool *first_update, SDL_Window *screen, SDL_Renderer *renderer) +{ + VideoPicture *vp = &movState->video.pictq[movState->video.pictq_windex]; + + /* allocate or resize the buffer! */ + if(!vp->bmp || vp->width != movState->video.st->codec->width || + vp->height != movState->video.st->codec->height) + { + if(vp->bmp) + SDL_DestroyTexture(vp->bmp); + vp->bmp = SDL_CreateTexture( + renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, + movState->video.st->codec->coded_width, movState->video.st->codec->coded_height + ); + if(!vp->bmp) + fprintf(stderr, "Failed to create YV12 texture!\n"); + vp->width = movState->video.st->codec->width; + vp->height = movState->video.st->codec->height; + + if(*first_update && vp->width > 0 && vp->height > 0) + { + /* For the first update, set the window size to the video size. */ + *first_update = false; + + int w = vp->width; + int h = vp->height; + if(movState->video.st->codec->sample_aspect_ratio.num != 0 && + movState->video.st->codec->sample_aspect_ratio.den != 0) + { + double aspect_ratio = av_q2d(movState->video.st->codec->sample_aspect_ratio); + if(aspect_ratio >= 1.0) + w = (int)(w*aspect_ratio + 0.5); + else if(aspect_ratio > 0.0) + h = (int)(h/aspect_ratio + 0.5); + } + SDL_SetWindowSize(screen, w, h); + } + } + + if(vp->bmp) + { + AVFrame *frame = movState->video.decoded_vframe; + void *pixels = NULL; + int pitch = 0; + + if(movState->video.st->codec->pix_fmt == PIX_FMT_YUV420P) + SDL_UpdateYUVTexture(vp->bmp, NULL, + frame->data[0], frame->linesize[0], + frame->data[1], frame->linesize[1], + frame->data[2], frame->linesize[2] + ); + else if(SDL_LockTexture(vp->bmp, NULL, &pixels, &pitch) != 0) + fprintf(stderr, "Failed to lock texture\n"); + else + { + // Convert the image into YUV format that SDL uses + int coded_w = movState->video.st->codec->coded_width; + int coded_h = movState->video.st->codec->coded_height; + int w = movState->video.st->codec->width; + int h = movState->video.st->codec->height; + if(!movState->video.swscale_ctx) + movState->video.swscale_ctx = sws_getContext( + w, h, movState->video.st->codec->pix_fmt, + w, h, PIX_FMT_YUV420P, SWS_X, NULL, NULL, NULL + ); + + /* point pict at the queue */ + AVPicture pict; + pict.data[0] = pixels; + pict.data[2] = pict.data[0] + coded_w*coded_h; + pict.data[1] = pict.data[2] + coded_w*coded_h/4; + + pict.linesize[0] = pitch; + pict.linesize[2] = pitch / 2; + pict.linesize[1] = pitch / 2; + + sws_scale(movState->video.swscale_ctx, (const uint8_t**)frame->data, + frame->linesize, 0, h, pict.data, pict.linesize); + SDL_UnlockTexture(vp->bmp); + } + } + + almtx_lock(&movState->video.pictq_mutex); + vp->updated = true; + almtx_unlock(&movState->video.pictq_mutex); + alcnd_signal(&movState->video.pictq_cond); +} + +static int queue_picture(MovieState *movState, double pts) +{ + /* Wait until we have space for a new pic */ + almtx_lock(&movState->video.pictq_mutex); + while(movState->video.pictq_size >= VIDEO_PICTURE_QUEUE_SIZE && !movState->quit) + alcnd_wait(&movState->video.pictq_cond, &movState->video.pictq_mutex); + almtx_unlock(&movState->video.pictq_mutex); + + if(movState->quit) + return -1; + + VideoPicture *vp = &movState->video.pictq[movState->video.pictq_windex]; + + /* We have to create/update the picture in the main thread */ + vp->updated = false; + SDL_PushEvent(&(SDL_Event){ .user={.type=FF_UPDATE_EVENT, .data1=movState} }); + + /* Wait until the picture is updated. */ + almtx_lock(&movState->video.pictq_mutex); + while(!vp->updated && !movState->quit) + alcnd_wait(&movState->video.pictq_cond, &movState->video.pictq_mutex); + almtx_unlock(&movState->video.pictq_mutex); + if(movState->quit) + return -1; + vp->pts = pts; + + movState->video.pictq_windex = (movState->video.pictq_windex+1)%VIDEO_PICTURE_QUEUE_SIZE; + almtx_lock(&movState->video.pictq_mutex); + movState->video.pictq_size++; + almtx_unlock(&movState->video.pictq_mutex); + + return 0; +} + +static double synchronize_video(MovieState *movState, double pts) +{ + double frame_delay; + + if(pts == 0.0) /* if we aren't given a pts, set it to the clock */ + pts = movState->video.clock; + else /* if we have pts, set video clock to it */ + movState->video.clock = pts; + + /* update the video clock */ + frame_delay = av_q2d(movState->video.st->codec->time_base); + /* if we are repeating a frame, adjust clock accordingly */ + frame_delay += movState->video.decoded_vframe->repeat_pict * (frame_delay * 0.5); + movState->video.clock += frame_delay; + return pts; +} + +int video_thread(void *arg) +{ + MovieState *movState = (MovieState*)arg; + AVPacket *packet = (AVPacket[1]){}; + int64_t saved_pts, pkt_pts; + int frameFinished; + + movState->video.decoded_vframe = av_frame_alloc(); + while(packet_queue_get(&movState->video.q, packet, movState) >= 0) + { + if(packet->data == flush_pkt.data) + { + avcodec_flush_buffers(movState->video.st->codec); + + almtx_lock(&movState->video.pictq_mutex); + movState->video.pictq_size = 0; + movState->video.pictq_rindex = 0; + movState->video.pictq_windex = 0; + almtx_unlock(&movState->video.pictq_mutex); + + movState->video.clock = av_q2d(movState->video.st->time_base)*packet->pts; + movState->video.current_pts = movState->video.clock; + movState->video.current_pts_time = av_gettime(); + continue; + } + + pkt_pts = packet->pts; + + /* Decode video frame */ + avcodec_decode_video2(movState->video.st->codec, movState->video.decoded_vframe, + &frameFinished, packet); + if(pkt_pts != AV_NOPTS_VALUE && !movState->video.decoded_vframe->opaque) + { + /* Store the packet's original pts in the frame, in case the frame + * is not finished decoding yet. */ + saved_pts = pkt_pts; + movState->video.decoded_vframe->opaque = &saved_pts; + } + + av_free_packet(packet); + + if(frameFinished) + { + double pts = av_q2d(movState->video.st->time_base); + if(packet->dts != AV_NOPTS_VALUE) + pts *= packet->dts; + else if(movState->video.decoded_vframe->opaque) + pts *= *(int64_t*)movState->video.decoded_vframe->opaque; + else + pts *= 0.0; + movState->video.decoded_vframe->opaque = NULL; + + pts = synchronize_video(movState, pts); + if(queue_picture(movState, pts) < 0) + break; + } + } + + sws_freeContext(movState->video.swscale_ctx); + movState->video.swscale_ctx = NULL; + av_frame_free(&movState->video.decoded_vframe); + return 0; +} + + +static int stream_component_open(MovieState *movState, int stream_index) +{ + AVFormatContext *pFormatCtx = movState->pFormatCtx; + AVCodecContext *codecCtx; + AVCodec *codec; + + if(stream_index < 0 || (unsigned int)stream_index >= pFormatCtx->nb_streams) + return -1; + + /* Get a pointer to the codec context for the video stream, and open the + * associated codec */ + codecCtx = pFormatCtx->streams[stream_index]->codec; + + codec = avcodec_find_decoder(codecCtx->codec_id); + if(!codec || avcodec_open2(codecCtx, codec, NULL) < 0) + { + fprintf(stderr, "Unsupported codec!\n"); + return -1; + } + + /* Initialize and start the media type handler */ + switch(codecCtx->codec_type) + { + case AVMEDIA_TYPE_AUDIO: + movState->audioStream = stream_index; + movState->audio.st = pFormatCtx->streams[stream_index]; + + /* Averaging filter for audio sync */ + movState->audio.diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB); + /* Correct audio only if larger error than this */ + movState->audio.diff_threshold = 2.0 * 0.050/* 50 ms */; + + memset(&movState->audio.pkt, 0, sizeof(movState->audio.pkt)); + if(althrd_create(&movState->audio.thread, audio_thread, movState) != althrd_success) + { + movState->audioStream = -1; + movState->audio.st = NULL; + } + break; + + case AVMEDIA_TYPE_VIDEO: + movState->videoStream = stream_index; + movState->video.st = pFormatCtx->streams[stream_index]; + + movState->video.current_pts_time = av_gettime(); + movState->video.frame_timer = (double)movState->video.current_pts_time / + 1000000.0; + movState->video.frame_last_delay = 40e-3; + + if(althrd_create(&movState->video.thread, video_thread, movState) != althrd_success) + { + movState->videoStream = -1; + movState->video.st = NULL; + } + break; + + default: + break; + } + + return 0; +} + +static int decode_interrupt_cb(void *ctx) +{ + return ((MovieState*)ctx)->quit; +} + +int decode_thread(void *arg) +{ + MovieState *movState = (MovieState *)arg; + AVFormatContext *fmtCtx = movState->pFormatCtx; + AVPacket *packet = (AVPacket[1]){}; + int video_index = -1; + int audio_index = -1; + + movState->videoStream = -1; + movState->audioStream = -1; + + /* Dump information about file onto standard error */ + av_dump_format(fmtCtx, 0, movState->filename, 0); + + /* Find the first video and audio streams */ + for(unsigned int i = 0;i < fmtCtx->nb_streams;i++) + { + if(fmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO && video_index < 0) + video_index = i; + else if(fmtCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO && audio_index < 0) + audio_index = i; + } + movState->external_clock_base = av_gettime(); + if(audio_index >= 0) + stream_component_open(movState, audio_index); + if(video_index >= 0) + stream_component_open(movState, video_index); + + if(movState->videoStream < 0 && movState->audioStream < 0) + { + fprintf(stderr, "%s: could not open codecs\n", movState->filename); + goto fail; + } + + /* Main packet handling loop */ + while(!movState->quit) + { + if(movState->seek_req) + { + int64_t seek_target = movState->seek_pos; + int stream_index= -1; + + /* Prefer seeking on the video stream. */ + if(movState->videoStream >= 0) + stream_index = movState->videoStream; + else if(movState->audioStream >= 0) + stream_index = movState->audioStream; + + /* Get a seek timestamp for the appropriate stream. */ + int64_t timestamp = seek_target; + if(stream_index >= 0) + timestamp = av_rescale_q(seek_target, AV_TIME_BASE_Q, fmtCtx->streams[stream_index]->time_base); + + if(av_seek_frame(movState->pFormatCtx, stream_index, timestamp, 0) < 0) + fprintf(stderr, "%s: error while seeking\n", movState->pFormatCtx->filename); + else + { + /* Seek successful, clear the packet queues and send a special + * 'flush' packet with the new stream clock time. */ + if(movState->audioStream >= 0) + { + packet_queue_clear(&movState->audio.q); + flush_pkt.pts = av_rescale_q(seek_target, AV_TIME_BASE_Q, + fmtCtx->streams[movState->audioStream]->time_base + ); + packet_queue_put(&movState->audio.q, &flush_pkt); + } + if(movState->videoStream >= 0) + { + packet_queue_clear(&movState->video.q); + flush_pkt.pts = av_rescale_q(seek_target, AV_TIME_BASE_Q, + fmtCtx->streams[movState->videoStream]->time_base + ); + packet_queue_put(&movState->video.q, &flush_pkt); + } + movState->external_clock_base = av_gettime() - seek_target; + } + movState->seek_req = false; + } + + if(movState->audio.q.size >= MAX_AUDIOQ_SIZE || + movState->video.q.size >= MAX_VIDEOQ_SIZE) + { + SDL_Delay(10); + continue; + } + + if(av_read_frame(movState->pFormatCtx, packet) < 0) + { + packet_queue_flush(&movState->video.q); + packet_queue_flush(&movState->audio.q); + break; + } + + /* Place the packet in the queue it's meant for, or discard it. */ + if(packet->stream_index == movState->videoStream) + packet_queue_put(&movState->video.q, packet); + else if(packet->stream_index == movState->audioStream) + packet_queue_put(&movState->audio.q, packet); + else + av_free_packet(packet); + } + + /* all done - wait for it */ + while(!movState->quit) + { + if(movState->audio.q.nb_packets == 0 && movState->video.q.nb_packets == 0) + break; + SDL_Delay(100); + } + +fail: + movState->quit = true; + packet_queue_flush(&movState->video.q); + packet_queue_flush(&movState->audio.q); + + if(movState->videoStream >= 0) + althrd_join(movState->video.thread, NULL); + if(movState->audioStream >= 0) + althrd_join(movState->audio.thread, NULL); + + SDL_PushEvent(&(SDL_Event){ .user={.type=FF_QUIT_EVENT, .data1=movState} }); + + return 0; +} + + +static void stream_seek(MovieState *movState, double incr) +{ + if(!movState->seek_req) + { + double newtime = get_master_clock(movState)+incr; + if(newtime <= 0.0) movState->seek_pos = 0; + else movState->seek_pos = (int64_t)(newtime * AV_TIME_BASE); + movState->seek_req = true; + } +} + +int main(int argc, char *argv[]) +{ + SDL_Event event; + MovieState *movState; + bool first_update = true; + SDL_Window *screen; + SDL_Renderer *renderer; + ALCdevice *device; + ALCcontext *context; + + if(argc < 2) + { + fprintf(stderr, "Usage: %s \n", argv[0]); + return 1; + } + /* Register all formats and codecs */ + av_register_all(); + /* Initialize networking protocols */ + avformat_network_init(); + + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER)) + { + fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError()); + return 1; + } + + /* Make a window to put our video */ + screen = SDL_CreateWindow("alffplay", 0, 0, 640, 480, SDL_WINDOW_RESIZABLE); + if(!screen) + { + fprintf(stderr, "SDL: could not set video mode - exiting\n"); + return 1; + } + /* Make a renderer to handle the texture image surface and rendering. */ + renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED); + if(renderer) + { + SDL_RendererInfo rinf; + bool ok = false; + + /* Make sure the renderer supports YV12 textures. If not, fallback to a + * software renderer. */ + if(SDL_GetRendererInfo(renderer, &rinf) == 0) + { + for(Uint32 i = 0;!ok && i < rinf.num_texture_formats;i++) + ok = (rinf.texture_formats[i] == SDL_PIXELFORMAT_YV12); + } + if(!ok) + { + fprintf(stderr, "YV12 pixelformat textures not supported on renderer %s\n", rinf.name); + SDL_DestroyRenderer(renderer); + renderer = NULL; + } + } + if(!renderer) + renderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_SOFTWARE); + if(!renderer) + { + fprintf(stderr, "SDL: could not create renderer - exiting\n"); + return 1; + } + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderFillRect(renderer, NULL); + SDL_RenderPresent(renderer); + + /* Open an audio device */ + device = alcOpenDevice(NULL); + if(!device) + { + fprintf(stderr, "OpenAL: could not open device - exiting\n"); + return 1; + } + context = alcCreateContext(device, NULL); + if(!context) + { + fprintf(stderr, "OpenAL: could not create context - exiting\n"); + return 1; + } + if(alcMakeContextCurrent(context) == ALC_FALSE) + { + fprintf(stderr, "OpenAL: could not make context current - exiting\n"); + return 1; + } + + if(!alIsExtensionPresent("AL_SOFT_source_length")) + { + fprintf(stderr, "Required AL_SOFT_source_length not supported - exiting\n"); + return 1; + } + + if(!alIsExtensionPresent("AL_SOFT_source_latency")) + fprintf(stderr, "AL_SOFT_source_latency not supported, audio may be a bit laggy.\n"); + else + { + alGetSourcedvSOFT = alGetProcAddress("alGetSourcedvSOFT"); + has_latency_check = true; + } + + + movState = av_mallocz(sizeof(MovieState)); + + av_strlcpy(movState->filename, argv[1], sizeof(movState->filename)); + + packet_queue_init(&movState->audio.q); + packet_queue_init(&movState->video.q); + + almtx_init(&movState->video.pictq_mutex, almtx_plain); + alcnd_init(&movState->video.pictq_cond); + almtx_init(&movState->audio.src_mutex, almtx_recursive); + + movState->av_sync_type = DEFAULT_AV_SYNC_TYPE; + + movState->pFormatCtx = avformat_alloc_context(); + movState->pFormatCtx->interrupt_callback = (AVIOInterruptCB){.callback=decode_interrupt_cb, .opaque=movState}; + + if(avio_open2(&movState->pFormatCtx->pb, movState->filename, AVIO_FLAG_READ, + &movState->pFormatCtx->interrupt_callback, NULL)) + { + fprintf(stderr, "Failed to open %s\n", movState->filename); + return 1; + } + + /* Open movie file */ + if(avformat_open_input(&movState->pFormatCtx, movState->filename, NULL, NULL) != 0) + { + fprintf(stderr, "Failed to open %s\n", movState->filename); + return 1; + } + + /* Retrieve stream information */ + if(avformat_find_stream_info(movState->pFormatCtx, NULL) < 0) + { + fprintf(stderr, "%s: failed to find stream info\n", movState->filename); + return 1; + } + + schedule_refresh(movState, 40); + + + if(althrd_create(&movState->parse_thread, decode_thread, movState) != althrd_success) + { + fprintf(stderr, "Failed to create parse thread!\n"); + return 1; + } + while(SDL_WaitEvent(&event) == 1) + { + switch(event.type) + { + case SDL_KEYDOWN: + switch(event.key.keysym.sym) + { + case SDLK_ESCAPE: + movState->quit = true; + break; + + case SDLK_LEFT: + stream_seek(movState, -10.0); + break; + case SDLK_RIGHT: + stream_seek(movState, 10.0); + break; + case SDLK_UP: + stream_seek(movState, 30.0); + break; + case SDLK_DOWN: + stream_seek(movState, -30.0); + break; + + default: + break; + } + break; + + case SDL_WINDOWEVENT: + switch(event.window.event) + { + case SDL_WINDOWEVENT_RESIZED: + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderFillRect(renderer, NULL); + break; + + default: + break; + } + break; + + case SDL_QUIT: + movState->quit = true; + break; + + case FF_UPDATE_EVENT: + update_picture(event.user.data1, &first_update, screen, renderer); + break; + + case FF_REFRESH_EVENT: + video_refresh_timer(event.user.data1, screen, renderer); + break; + + case FF_QUIT_EVENT: + althrd_join(movState->parse_thread, NULL); + + avformat_close_input(&movState->pFormatCtx); + + almtx_destroy(&movState->audio.src_mutex); + almtx_destroy(&movState->video.pictq_mutex); + alcnd_destroy(&movState->video.pictq_cond); + packet_queue_deinit(&movState->video.q); + packet_queue_deinit(&movState->audio.q); + + alcMakeContextCurrent(NULL); + alcDestroyContext(context); + alcCloseDevice(device); + + SDL_Quit(); + exit(0); + + default: + break; + } + } + + fprintf(stderr, "SDL_WaitEvent error - %s\n", SDL_GetError()); + return 1; +} diff --git a/jni/openal-soft-android/examples/allatency.c b/jni/openal-soft-1.16.0/examples/allatency.c similarity index 100% rename from jni/openal-soft-android/examples/allatency.c rename to jni/openal-soft-1.16.0/examples/allatency.c diff --git a/jni/openal-soft-android/examples/alloopback.c b/jni/openal-soft-1.16.0/examples/alloopback.c similarity index 99% rename from jni/openal-soft-android/examples/alloopback.c rename to jni/openal-soft-1.16.0/examples/alloopback.c index 649ef6ef..2361ada1 100644 --- a/jni/openal-soft-android/examples/alloopback.c +++ b/jni/openal-soft-1.16.0/examples/alloopback.c @@ -92,13 +92,15 @@ static ALuint CreateSineWave(void) } -int main() +int main(int argc, char *argv[]) { PlaybackInfo playback = { NULL, NULL, 0 }; SDL_AudioSpec desired, obtained; ALuint source, buffer; ALCint attrs[16]; ALenum state; + (void)argc; + (void)argv; /* Print out error if extension is missing. */ if(!alcIsExtensionPresent(NULL, "ALC_SOFT_loopback")) @@ -167,6 +169,8 @@ int main() attrs[6] = 0; /* end of list */ + playback.FrameSize = FramesToBytes(1, attrs[1], attrs[3]); + /* Initialize OpenAL loopback device, using our format attributes. */ playback.Device = alcLoopbackOpenDeviceSOFT(NULL); if(!playback.Device) @@ -187,7 +191,6 @@ int main() fprintf(stderr, "Failed to set an OpenAL audio context\n"); goto error; } - playback.FrameSize = FramesToBytes(1, attrs[1], attrs[3]); /* Start SDL playing. Our callback (thus alcRenderSamplesSOFT) will now * start being called regularly to update the AL playback state. */ diff --git a/jni/openal-soft-android/examples/alreverb.c b/jni/openal-soft-1.16.0/examples/alreverb.c similarity index 100% rename from jni/openal-soft-android/examples/alreverb.c rename to jni/openal-soft-1.16.0/examples/alreverb.c diff --git a/jni/openal-soft-android/examples/alstream.c b/jni/openal-soft-1.16.0/examples/alstream.c similarity index 100% rename from jni/openal-soft-android/examples/alstream.c rename to jni/openal-soft-1.16.0/examples/alstream.c diff --git a/jni/openal-soft-android/examples/common/alhelpers.c b/jni/openal-soft-1.16.0/examples/common/alhelpers.c similarity index 100% rename from jni/openal-soft-android/examples/common/alhelpers.c rename to jni/openal-soft-1.16.0/examples/common/alhelpers.c diff --git a/jni/openal-soft-android/examples/common/alhelpers.h b/jni/openal-soft-1.16.0/examples/common/alhelpers.h similarity index 100% rename from jni/openal-soft-android/examples/common/alhelpers.h rename to jni/openal-soft-1.16.0/examples/common/alhelpers.h diff --git a/jni/openal-soft-android/examples/common/sdl_sound.c b/jni/openal-soft-1.16.0/examples/common/sdl_sound.c similarity index 100% rename from jni/openal-soft-android/examples/common/sdl_sound.c rename to jni/openal-soft-1.16.0/examples/common/sdl_sound.c diff --git a/jni/openal-soft-android/examples/common/sdl_sound.h b/jni/openal-soft-1.16.0/examples/common/sdl_sound.h similarity index 100% rename from jni/openal-soft-android/examples/common/sdl_sound.h rename to jni/openal-soft-1.16.0/examples/common/sdl_sound.h diff --git a/jni/openal-soft-android/hrtf.txt b/jni/openal-soft-1.16.0/hrtf.txt similarity index 91% rename from jni/openal-soft-android/hrtf.txt rename to jni/openal-soft-1.16.0/hrtf.txt index 59a8b4ee..e19fb0b8 100644 --- a/jni/openal-soft-android/hrtf.txt +++ b/jni/openal-soft-1.16.0/hrtf.txt @@ -12,16 +12,16 @@ placement of sounds, making it seem as though they are coming from all around, including above and below the listener, instead of just to the front, back, and sides. -The built-in data set is based on the KEMAR HRTF data provided by MIT, which -can be found at . It's only +The default data set is based on the KEMAR HRTF data provided by MIT, which can +be found at . It's only available when using 44100hz playback. -External HRTF Data Sets -======================= +Custom HRTF Data Sets +===================== OpenAL Soft also provides an option to use user-specified data sets, in -addition to or in place of the built-in set. This allows users to provide their +addition to or in place of the default set. This allows users to provide their own data sets, which could be better suited for their heads, or to work with stereo speakers instead of headphones, or to support more playback sample rates, for example. diff --git a/jni/openal-soft-1.16.0/hrtf/default-44100.mhr b/jni/openal-soft-1.16.0/hrtf/default-44100.mhr new file mode 100644 index 0000000000000000000000000000000000000000..e0d0bf4b6c42e1211af3ead111275fbdb118afa9 GIT binary patch literal 53853 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

dCu@tZqPa^Ns4*bMj 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 J&t|jX{{hDUFed;2 literal 0 HcmV?d00001 diff --git a/jni/openal-soft-android/include/AL/al.h b/jni/openal-soft-1.16.0/include/AL/al.h similarity index 100% rename from jni/openal-soft-android/include/AL/al.h rename to jni/openal-soft-1.16.0/include/AL/al.h diff --git a/jni/openal-soft-android/include/AL/alc.h b/jni/openal-soft-1.16.0/include/AL/alc.h similarity index 100% rename from jni/openal-soft-android/include/AL/alc.h rename to jni/openal-soft-1.16.0/include/AL/alc.h diff --git a/jni/openal-soft-android/include/AL/alext.h b/jni/openal-soft-1.16.0/include/AL/alext.h similarity index 94% rename from jni/openal-soft-android/include/AL/alext.h rename to jni/openal-soft-1.16.0/include/AL/alext.h index f15ba33f..7d2a9527 100644 --- a/jni/openal-soft-android/include/AL/alext.h +++ b/jni/openal-soft-1.16.0/include/AL/alext.h @@ -364,6 +364,35 @@ 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 + #ifdef __cplusplus } #endif diff --git a/jni/openal-soft-android/include/AL/efx-creative.h b/jni/openal-soft-1.16.0/include/AL/efx-creative.h similarity index 100% rename from jni/openal-soft-android/include/AL/efx-creative.h rename to jni/openal-soft-1.16.0/include/AL/efx-creative.h diff --git a/jni/openal-soft-android/include/AL/efx-presets.h b/jni/openal-soft-1.16.0/include/AL/efx-presets.h similarity index 100% rename from jni/openal-soft-android/include/AL/efx-presets.h rename to jni/openal-soft-1.16.0/include/AL/efx-presets.h diff --git a/jni/openal-soft-android/include/AL/efx.h b/jni/openal-soft-1.16.0/include/AL/efx.h similarity index 100% rename from jni/openal-soft-android/include/AL/efx.h rename to jni/openal-soft-1.16.0/include/AL/efx.h diff --git a/jni/openal-soft-1.16.0/include/align.h b/jni/openal-soft-1.16.0/include/align.h new file mode 100644 index 00000000..babd4106 --- /dev/null +++ b/jni/openal-soft-1.16.0/include/align.h @@ -0,0 +1,21 @@ +#ifndef AL_ALIGN_H +#define AL_ALIGN_H + +#ifdef HAVE_STDALIGN_H +#include +#endif + +#ifndef alignas +#ifdef HAVE_C11_ALIGNAS +#define alignas _Alignas +#elif defined(IN_IDE_PARSER) +/* KDevelop has problems with our align macro, so just use nothing for parsing. */ +#define alignas(x) +#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/jni/openal-soft-1.16.0/include/atomic.h b/jni/openal-soft-1.16.0/include/atomic.h new file mode 100644 index 00000000..d761890e --- /dev/null +++ b/jni/openal-soft-1.16.0/include/atomic.h @@ -0,0 +1,313 @@ +#ifndef AL_ATOMIC_H +#define AL_ATOMIC_H + +#include "static_assert.h" +#include "bool.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *volatile XchgPtr; + +/* Atomics using C11 */ +#ifdef HAVE_C11_ATOMIC + +#include + +inline int ExchangeInt(volatile int *ptr, int newval) +{ return atomic_exchange(ptr, newval); } +inline void *ExchangePtr(XchgPtr *ptr, void *newval) +{ return atomic_exchange(ptr, newval); } + + +#define ATOMIC(T) struct { T _Atomic value; } + +#define ATOMIC_INIT(_val, _newval) atomic_init(&(_val)->value, (_newval)) +#define ATOMIC_INIT_STATIC(_newval) {ATOMIC_VAR_INIT(_newval)} + +#define ATOMIC_LOAD(_val) atomic_load(&(_val)->value) +#define ATOMIC_STORE(_val, _newval) atomic_store(&(_val)->value, (_newval)) + +#define ATOMIC_ADD(T, _val, _incr) atomic_fetch_add(&(_val)->value, (_incr)) +#define ATOMIC_SUB(T, _val, _decr) atomic_fetch_sub(&(_val)->value, (_decr)) + +#define ATOMIC_EXCHANGE(T, _val, _newval) atomic_exchange(&(_val)->value, (_newval)) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) \ + atomic_compare_exchange_strong(&(_val)->value, (_oldval), (_newval)) +#define ATOMIC_COMPARE_EXCHANGE_WEAK(T, _val, _oldval, _newval) \ + atomic_compare_exchange_weak(&(_val)->value, (_oldval), (_newval)) + +/* Atomics using GCC intrinsics */ +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__QNXNTO__) + +inline int ExchangeInt(volatile int *ptr, int newval) +{ return __sync_lock_test_and_set(ptr, newval); } +inline void *ExchangePtr(XchgPtr *ptr, void *newval) +{ return __sync_lock_test_and_set(ptr, newval); } + + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_INIT(_val, _newval) do { (_val)->value = (_newval); } while(0) +#define ATOMIC_INIT_STATIC(_newval) {(_newval)} + +#define ATOMIC_LOAD(_val) __extension__({ \ + __typeof((_val)->value) _r = (_val)->value; \ + __asm__ __volatile__("" ::: "memory"); \ + _r; \ +}) +#define ATOMIC_STORE(_val, _newval) do { \ + __asm__ __volatile__("" ::: "memory"); \ + (_val)->value = (_newval); \ +} while(0) + +#define ATOMIC_ADD(T, _val, _incr) __extension__({ \ + static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + __sync_fetch_and_add(&(_val)->value, (_incr)); \ +}) +#define ATOMIC_SUB(T, _val, _decr) __extension__({ \ + static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + __sync_fetch_and_sub(&(_val)->value, (_decr)); \ +}) + +#define ATOMIC_EXCHANGE(T, _val, _newval) __extension__({ \ + static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + __sync_lock_test_and_set(&(_val)->value, (_newval)); \ +}) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) __extension__({ \ + static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + T _o = *(_oldval); \ + *(_oldval) = __sync_val_compare_and_swap(&(_val)->value, _o, (_newval)); \ + *(_oldval) == _o; \ +}) + +/* Atomics using x86/x86-64 GCC inline assembly */ +#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + +#define WRAP_ADD(ret, dest, incr) __asm__ __volatile__( \ + "lock; xaddl %0,(%1)" \ + : "=r" (ret) \ + : "r" (dest), "0" (incr) \ + : "memory" \ +) +#define WRAP_SUB(ret, dest, decr) __asm__ __volatile__( \ + "lock; xaddl %0,(%1)" \ + : "=r" (ret) \ + : "r" (dest), "0" (-(decr)) \ + : "memory" \ +) + +#define WRAP_XCHG(S, ret, dest, newval) __asm__ __volatile__( \ + "lock; xchg"S" %0,(%1)" \ + : "=r" (ret) \ + : "r" (dest), "0" (newval) \ + : "memory" \ +) +#define WRAP_CMPXCHG(S, ret, dest, oldval, newval) __asm__ __volatile__( \ + "lock; cmpxchg"S" %2,(%1)" \ + : "=a" (ret) \ + : "r" (dest), "r" (newval), "0" (oldval) \ + : "memory" \ +) + + +inline int ExchangeInt(volatile int *dest, int newval) +{ int ret; WRAP_XCHG("l", ret, dest, newval); return ret; } + +#ifdef __i386__ +inline void *ExchangePtr(XchgPtr *dest, void *newval) +{ void *ret; WRAP_XCHG("l", ret, dest, newval); return ret; } +#else +inline void *ExchangePtr(XchgPtr *dest, void *newval) +{ void *ret; WRAP_XCHG("q", ret, dest, newval); return ret; } +#endif + + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_INIT(_val, _newval) do { (_val)->value = (_newval); } while(0) +#define ATOMIC_INIT_STATIC(_newval) {(_newval)} + +#define ATOMIC_LOAD(_val) __extension__({ \ + __typeof((_val)->value) _r = (_val)->value; \ + __asm__ __volatile__("" ::: "memory"); \ + _r; \ +}) +#define ATOMIC_STORE(_val, _newval) do { \ + __asm__ __volatile__("" ::: "memory"); \ + (_val)->value = (_newval); \ +} while(0) + +#define ATOMIC_ADD(T, _val, _incr) __extension__({ \ + static_assert(sizeof(T)==4, "Type "#T" has incorrect size!"); \ + static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + T _r; \ + WRAP_ADD(_r, &(_val)->value, (T)(_incr)); \ + _r; \ +}) +#define ATOMIC_SUB(T, _val, _decr) __extension__({ \ + static_assert(sizeof(T)==4, "Type "#T" has incorrect size!"); \ + static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + T _r; \ + WRAP_SUB(_r, &(_val)->value, (T)(_decr)); \ + _r; \ +}) + +#define ATOMIC_EXCHANGE(T, _val, _newval) __extension__({ \ + static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \ + static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + T _r; \ + if(sizeof(T) == 4) WRAP_XCHG("l", _r, &(_val)->value, (T)(_newval)); \ + else if(sizeof(T) == 8) WRAP_XCHG("q", _r, &(_val)->value, (T)(_newval)); \ + _r; \ +}) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) __extension__({ \ + static_assert(sizeof(T)==4 || sizeof(T)==8, "Type "#T" has incorrect size!"); \ + static_assert(sizeof(T)==sizeof((_val)->value), "Type "#T" has incorrect size!"); \ + T _old = *(_oldval); \ + if(sizeof(T) == 4) WRAP_CMPXCHG("l", *(_oldval), &(_val)->value, _old, (T)(_newval)); \ + else if(sizeof(T) == 8) WRAP_CMPXCHG("q", *(_oldval), &(_val)->value, _old, (T)(_newval)); \ + *(_oldval) == _old; \ +}) + +/* Atomics using Windows methods */ +#elif defined(_WIN32) + +#define WIN32_LEAN_AND_MEAN +#include + +/* NOTE: This mess is *extremely* noisy, at least on GCC. It works by wrapping + * Windows' 32-bit and 64-bit atomic methods, which are then casted to use the + * given type based on its size (e.g. int and float use 32-bit atomics). This + * is fine for the swap and compare-and-swap methods, although the add and + * subtract methods only work properly for integer types. + * + * Despite how noisy it is, it's unfortunately the only way that doesn't rely + * on C99 (damn MSVC). + */ + +inline LONG AtomicAdd32(volatile LONG *dest, LONG incr) +{ + return InterlockedExchangeAdd(dest, incr); +} +inline LONG AtomicSub32(volatile LONG *dest, LONG decr) +{ + return InterlockedExchangeAdd(dest, -decr); +} + +inline LONG AtomicSwap32(volatile LONG *dest, LONG newval) +{ + return InterlockedExchange(dest, newval); +} +inline LONGLONG AtomicSwap64(volatile LONGLONG *dest, LONGLONG newval) +{ + return InterlockedExchange64(dest, newval); +} + +inline bool CompareAndSwap32(volatile LONG *dest, LONG newval, LONG *oldval) +{ + LONG old = *oldval; + *oldval = InterlockedCompareExchange(dest, newval, *oldval); + return old == *oldval; +} +inline bool CompareAndSwap64(volatile LONGLONG *dest, LONGLONG newval, LONGLONG *oldval) +{ + LONGLONG old = *oldval; + *oldval = InterlockedCompareExchange64(dest, newval, *oldval); + return old == *oldval; +} + +#define WRAP_ADDSUB(T, _func, _ptr, _amnt) ((T(*)(T volatile*,T))_func)((_ptr), (_amnt)) +#define WRAP_XCHG(T, _func, _ptr, _newval) ((T(*)(T volatile*,T))_func)((_ptr), (_newval)) +#define WRAP_CMPXCHG(T, _func, _ptr, _newval, _oldval) ((bool(*)(T volatile*,T,T*))_func)((_ptr), (_newval), (_oldval)) + +inline int ExchangeInt(volatile int *ptr, int newval) +{ return WRAP_XCHG(int,AtomicSwap32,ptr,newval); } + +#ifdef _WIN64 +inline void *ExchangePtr(XchgPtr *ptr, void *newval) +{ return WRAP_XCHG(void*,AtomicSwap64,ptr,newval); } +#else +inline void *ExchangePtr(XchgPtr *ptr, void *newval) +{ return WRAP_XCHG(void*,AtomicSwap32,ptr,newval); } +#endif + + +#define ATOMIC(T) struct { T volatile value; } + +#define ATOMIC_INIT(_val, _newval) do { (_val)->value = (_newval); } while(0) +#define ATOMIC_INIT_STATIC(_newval) {(_newval)} + +#define ATOMIC_LOAD(_val) ((_val)->value) +#define ATOMIC_STORE(_val, _newval) do { \ + (_val)->value = (_newval); \ +} while(0) + +int _al_invalid_atomic_size(); /* not defined */ + +#define ATOMIC_ADD(T, _val, _incr) \ + ((sizeof(T)==4) ? WRAP_ADDSUB(T, AtomicAdd32, &(_val)->value, (_incr)) : \ + (T)_al_invalid_atomic_size()) +#define ATOMIC_SUB(T, _val, _decr) \ + ((sizeof(T)==4) ? WRAP_ADDSUB(T, AtomicSub32, &(_val)->value, (_decr)) : \ + (T)_al_invalid_atomic_size()) + +#define ATOMIC_EXCHANGE(T, _val, _newval) \ + ((sizeof(T)==4) ? WRAP_XCHG(T, AtomicSwap32, &(_val)->value, (_newval)) : \ + (sizeof(T)==8) ? WRAP_XCHG(T, AtomicSwap64, &(_val)->value, (_newval)) : \ + (T)_al_invalid_atomic_size()) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) \ + ((sizeof(T)==4) ? WRAP_CMPXCHG(T, CompareAndSwap32, &(_val)->value, (_newval), (_oldval)) : \ + (sizeof(T)==8) ? WRAP_CMPXCHG(T, CompareAndSwap64, &(_val)->value, (_newval), (_oldval)) : \ + (bool)_al_invalid_atomic_size()) + +#else + +#error "No atomic functions available on this platform!" + +#define ATOMIC(T) T + +#define ATOMIC_INIT_STATIC(_newval) (0) + +#define ATOMIC_LOAD_UNSAFE(_val) (0) +#define ATOMIC_STORE_UNSAFE(_val, _newval) ((void)0) + +#define ATOMIC_LOAD(_val) (0) +#define ATOMIC_STORE(_val, _newval) ((void)0) + +#define ATOMIC_ADD(T, _val, _incr) (0) +#define ATOMIC_SUB(T, _val, _decr) (0) + +#define ATOMIC_EXCHANGE(T, _val, _newval) (0) +#define ATOMIC_COMPARE_EXCHANGE_STRONG(T, _val, _oldval, _newval) (0) +#endif + +/* If no weak cmpxchg is provided (not all systems will have one), substitute a + * strong cmpxchg. */ +#ifndef ATOMIC_COMPARE_EXCHANGE_WEAK +#define ATOMIC_COMPARE_EXCHANGE_WEAK(a, b, c, d) ATOMIC_COMPARE_EXCHANGE_STRONG(a, b, c, d) +#endif + +/* This is *NOT* atomic, but is a handy utility macro to compare-and-swap non- + * atomic variables. */ +#define COMPARE_EXCHANGE(_val, _oldval, _newval) ((*(_val) == *(_oldval)) ? ((*(_val)=(_newval)),true) : ((*(_oldval)=*(_val)),false)) + + +typedef unsigned int uint; +typedef ATOMIC(uint) RefCount; + +inline void InitRef(RefCount *ptr, uint value) +{ ATOMIC_INIT(ptr, value); } +inline uint ReadRef(RefCount *ptr) +{ return ATOMIC_LOAD(ptr); } +inline uint IncrementRef(RefCount *ptr) +{ return ATOMIC_ADD(uint, ptr, 1)+1; } +inline uint DecrementRef(RefCount *ptr) +{ return ATOMIC_SUB(uint, ptr, 1)-1; } + +#ifdef __cplusplus +} +#endif + +#endif /* AL_ATOMIC_H */ diff --git a/jni/openal-soft-1.16.0/include/bool.h b/jni/openal-soft-1.16.0/include/bool.h new file mode 100644 index 00000000..6f714d09 --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/include/rwlock.h b/jni/openal-soft-1.16.0/include/rwlock.h new file mode 100644 index 00000000..158a0670 --- /dev/null +++ b/jni/openal-soft-1.16.0/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/jni/openal-soft-1.16.0/include/static_assert.h b/jni/openal-soft-1.16.0/include/static_assert.h new file mode 100644 index 00000000..65283cf0 --- /dev/null +++ b/jni/openal-soft-1.16.0/include/static_assert.h @@ -0,0 +1,17 @@ +#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) +#define static_assert(_cond, _msg) typedef struct { int CTASTR(static_assert_failed_at_line_,__LINE__) : !!(_cond); } CTASTR(static_assertion_,__COUNTER__) +#endif +#endif + +#endif /* AL_STATIC_ASSERT_H */ diff --git a/jni/openal-soft-1.16.0/include/threads.h b/jni/openal-soft-1.16.0/include/threads.h new file mode 100644 index 00000000..25a75625 --- /dev/null +++ b/jni/openal-soft-1.16.0/include/threads.h @@ -0,0 +1,243 @@ +#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 _TIMESPEC_DEFINED +#define _TIMESPEC_DEFINED +struct timespec { + time_t tv_sec; + long tv_nsec; +}; + +struct itimerspec { + struct timespec it_interval; + struct timespec it_value; +}; +#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(time_t sec, long nsec); + +#ifdef __cplusplus +} +#endif + +#endif /* AL_THREADS_H */ diff --git a/jni/openal-soft-android/Alc/uintmap.h b/jni/openal-soft-1.16.0/include/uintmap.h similarity index 78% rename from jni/openal-soft-android/Alc/uintmap.h rename to jni/openal-soft-1.16.0/include/uintmap.h index 2c70f161..2c4c5e7a 100644 --- a/jni/openal-soft-android/Alc/uintmap.h +++ b/jni/openal-soft-1.16.0/include/uintmap.h @@ -4,6 +4,10 @@ #include "AL/al.h" #include "rwlock.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct UIntMap { struct { ALuint key; @@ -14,7 +18,8 @@ typedef struct UIntMap { ALsizei limit; RWLock lock; } UIntMap; -extern UIntMap TlsDestructor; +#define UINTMAP_STATIC_INITIALIZE_N(_n) { 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); @@ -31,4 +36,8 @@ inline void LockUIntMapWrite(UIntMap *map) inline void UnlockUIntMapWrite(UIntMap *map) { WriteUnlock(&map->lock); } +#ifdef __cplusplus +} +#endif + #endif /* AL_UINTMAP_H */ diff --git a/jni/openal-soft-android/openal.pc.in b/jni/openal-soft-1.16.0/openal.pc.in similarity index 100% rename from jni/openal-soft-android/openal.pc.in rename to jni/openal-soft-1.16.0/openal.pc.in diff --git a/jni/openal-soft-android/utils/CIAIR.def b/jni/openal-soft-1.16.0/utils/CIAIR.def similarity index 100% rename from jni/openal-soft-android/utils/CIAIR.def rename to jni/openal-soft-1.16.0/utils/CIAIR.def diff --git a/jni/openal-soft-android/utils/IRC_1005.def b/jni/openal-soft-1.16.0/utils/IRC_1005.def similarity index 100% rename from jni/openal-soft-android/utils/IRC_1005.def rename to jni/openal-soft-1.16.0/utils/IRC_1005.def diff --git a/jni/openal-soft-android/utils/MIT_KEMAR.def b/jni/openal-soft-1.16.0/utils/MIT_KEMAR.def similarity index 100% rename from jni/openal-soft-android/utils/MIT_KEMAR.def rename to jni/openal-soft-1.16.0/utils/MIT_KEMAR.def diff --git a/jni/openal-soft-android/utils/alsoft-config/CMakeLists.txt b/jni/openal-soft-1.16.0/utils/alsoft-config/CMakeLists.txt similarity index 100% rename from jni/openal-soft-android/utils/alsoft-config/CMakeLists.txt rename to jni/openal-soft-1.16.0/utils/alsoft-config/CMakeLists.txt diff --git a/jni/openal-soft-android/utils/alsoft-config/main.cpp b/jni/openal-soft-1.16.0/utils/alsoft-config/main.cpp similarity index 100% rename from jni/openal-soft-android/utils/alsoft-config/main.cpp rename to jni/openal-soft-1.16.0/utils/alsoft-config/main.cpp diff --git a/jni/openal-soft-android/utils/alsoft-config/mainwindow.cpp b/jni/openal-soft-1.16.0/utils/alsoft-config/mainwindow.cpp similarity index 84% rename from jni/openal-soft-android/utils/alsoft-config/mainwindow.cpp rename to jni/openal-soft-1.16.0/utils/alsoft-config/mainwindow.cpp index 0047233f..1d5a3dcd 100644 --- a/jni/openal-soft-android/utils/alsoft-config/mainwindow.cpp +++ b/jni/openal-soft-1.16.0/utils/alsoft-config/mainwindow.cpp @@ -52,6 +52,48 @@ static QString getDefaultConfigName() return base +'/'+ fname; return fname; } + +static QString getBaseDataPath() +{ +#ifdef Q_OS_WIN32 + QByteArray base = qgetenv("AppData"); +#else + QByteArray base = qgetenv("XDG_DATA_HOME"); + if(base.isEmpty()) + { + base = qgetenv("HOME"); + if(!base.isEmpty()) + base += "/.local/share"; + } +#endif + return base; +} + +static QStringList getAllDataPaths(QString append=QString()) +{ + QStringList list; + list.append(getBaseDataPath()); +#ifdef Q_OS_WIN32 + // TODO: Common AppData path +#else + QString paths = qgetenv("XDG_DATA_DIRS"); + if(paths.isEmpty()) + paths = "/usr/local/share/:/usr/share/"; + list += paths.split(QChar(':'), QString::SkipEmptyParts); +#endif + QStringList::iterator iter = list.begin(); + while(iter != list.end()) + { + if(iter->isEmpty()) + iter = list.erase(iter); + else + { + iter->append(append); + iter++; + } + } + return list; +} } MainWindow::MainWindow(QWidget *parent) : @@ -218,9 +260,10 @@ void MainWindow::loadConfig(const QString &fname) disabledCpuExts = disabledCpuExts[0].split(QChar(',')); std::transform(disabledCpuExts.begin(), disabledCpuExts.end(), disabledCpuExts.begin(), std::mem_fun_ref(&QString::trimmed)); - ui->disableSSECheckBox->setChecked(disabledCpuExts.contains("sse", Qt::CaseInsensitive)); - ui->disableSSE2CheckBox->setChecked(disabledCpuExts.contains("sse2", Qt::CaseInsensitive)); - ui->disableNeonCheckBox->setChecked(disabledCpuExts.contains("neon", Qt::CaseInsensitive)); + ui->enableSSECheckBox->setChecked(!disabledCpuExts.contains("sse", Qt::CaseInsensitive)); + ui->enableSSE2CheckBox->setChecked(!disabledCpuExts.contains("sse2", Qt::CaseInsensitive)); + ui->enableSSE41CheckBox->setChecked(!disabledCpuExts.contains("sse4.1", Qt::CaseInsensitive)); + ui->enableNeonCheckBox->setChecked(!disabledCpuExts.contains("neon", Qt::CaseInsensitive)); if(settings.value("hrtf").toString() == QString()) ui->hrtfEnableButton->setChecked(true); @@ -288,15 +331,16 @@ void MainWindow::loadConfig(const QString &fname) excludefx = excludefx[0].split(QChar(',')); std::transform(excludefx.begin(), excludefx.end(), excludefx.begin(), std::mem_fun_ref(&QString::trimmed)); - ui->disableEaxReverbCheck->setChecked(excludefx.contains("eaxreverb", Qt::CaseInsensitive)); - ui->disableStdReverbCheck->setChecked(excludefx.contains("reverb", Qt::CaseInsensitive)); - ui->disableChorusCheck->setChecked(excludefx.contains("chorus", Qt::CaseInsensitive)); - ui->disableDistortionCheck->setChecked(excludefx.contains("distortion", Qt::CaseInsensitive)); - ui->disableEchoCheck->setChecked(excludefx.contains("echo", Qt::CaseInsensitive)); - ui->disableEqualizerCheck->setChecked(excludefx.contains("equalizer", Qt::CaseInsensitive)); - ui->disableFlangerCheck->setChecked(excludefx.contains("flanger", Qt::CaseInsensitive)); - ui->disableModulatorCheck->setChecked(excludefx.contains("modulator", Qt::CaseInsensitive)); - ui->disableDedicatedCheck->setChecked(excludefx.contains("dedicated", Qt::CaseInsensitive)); + ui->enableEaxReverbCheck->setChecked(!excludefx.contains("eaxreverb", Qt::CaseInsensitive)); + ui->enableStdReverbCheck->setChecked(!excludefx.contains("reverb", Qt::CaseInsensitive)); + ui->enableChorusCheck->setChecked(!excludefx.contains("chorus", Qt::CaseInsensitive)); + ui->enableCompressorCheck->setChecked(!excludefx.contains("compressor", Qt::CaseInsensitive)); + ui->enableDistortionCheck->setChecked(!excludefx.contains("distortion", Qt::CaseInsensitive)); + ui->enableEchoCheck->setChecked(!excludefx.contains("echo", Qt::CaseInsensitive)); + ui->enableEqualizerCheck->setChecked(!excludefx.contains("equalizer", Qt::CaseInsensitive)); + ui->enableFlangerCheck->setChecked(!excludefx.contains("flanger", Qt::CaseInsensitive)); + ui->enableModulatorCheck->setChecked(!excludefx.contains("modulator", Qt::CaseInsensitive)); + ui->enableDedicatedCheck->setChecked(!excludefx.contains("dedicated", Qt::CaseInsensitive)); } void MainWindow::saveCurrentConfig() @@ -355,11 +399,13 @@ void MainWindow::saveConfig(const QString &fname) const } QStringList strlist; - if(ui->disableSSECheckBox->isChecked()) + if(!ui->enableSSECheckBox->isChecked()) strlist.append("sse"); - if(ui->disableSSE2CheckBox->isChecked()) + if(!ui->enableSSE2CheckBox->isChecked()) strlist.append("sse2"); - if(ui->disableNeonCheckBox->isChecked()) + if(!ui->enableSSE41CheckBox->isChecked()) + strlist.append("sse4.1"); + if(!ui->enableNeonCheckBox->isChecked()) strlist.append("neon"); settings.setValue("disable-cpu-exts", strlist.join(QChar(','))); @@ -410,23 +456,25 @@ void MainWindow::saveConfig(const QString &fname) const settings.setValue("reverb/boost", ui->reverbBoostEdit->text()); strlist.clear(); - if(ui->disableEaxReverbCheck->isChecked()) + if(!ui->enableEaxReverbCheck->isChecked()) strlist.append("eaxreverb"); - if(ui->disableStdReverbCheck->isChecked()) + if(!ui->enableStdReverbCheck->isChecked()) strlist.append("reverb"); - if(ui->disableChorusCheck->isChecked()) + if(!ui->enableChorusCheck->isChecked()) strlist.append("chorus"); - if(ui->disableDistortionCheck->isChecked()) + if(!ui->enableDistortionCheck->isChecked()) strlist.append("distortion"); - if(ui->disableEchoCheck->isChecked()) + if(!ui->enableCompressorCheck->isChecked()) + strlist.append("compressor"); + if(!ui->enableEchoCheck->isChecked()) strlist.append("echo"); - if(ui->disableEqualizerCheck->isChecked()) + if(!ui->enableEqualizerCheck->isChecked()) strlist.append("equalizer"); - if(ui->disableFlangerCheck->isChecked()) + if(!ui->enableFlangerCheck->isChecked()) strlist.append("flanger"); - if(ui->disableModulatorCheck->isChecked()) + if(!ui->enableModulatorCheck->isChecked()) strlist.append("modulator"); - if(ui->disableDedicatedCheck->isChecked()) + if(!ui->enableDedicatedCheck->isChecked()) strlist.append("dedicated"); settings.setValue("excludefx", strlist.join(QChar(','))); @@ -484,10 +532,36 @@ void MainWindow::updatePeriodCountSlider() void MainWindow::addHrtfFile() { - QStringList fnames = QFileDialog::getOpenFileNames(this, tr("Select Files"), QString(), + const QStringList datapaths = getAllDataPaths("/openal/hrtf"); + QStringList fnames = QFileDialog::getOpenFileNames(this, tr("Select Files"), + datapaths.empty() ? QString() : datapaths[0], "HRTF Datasets(*.mhr);;All Files(*.*)"); if(fnames.isEmpty() == false) - ui->hrtfFileList->addItems(fnames); + { + for(QStringList::iterator iter = fnames.begin();iter != fnames.end();iter++) + { + QStringList::const_iterator path = datapaths.constBegin(); + for(;path != datapaths.constEnd();path++) + { + QDir hrtfdir(*path); + if(!hrtfdir.isAbsolute()) + continue; + + const QString relname = hrtfdir.relativeFilePath(*iter); + if(!relname.startsWith("..")) + { + // If filename is within this path, use the relative pathname + ui->hrtfFileList->addItem(relname); + break; + } + } + if(path == datapaths.constEnd()) + { + // Filename is not within any data path, use the absolute pathname + ui->hrtfFileList->addItem(*iter); + } + } + } } void MainWindow::removeHrtfFile() diff --git a/jni/openal-soft-android/utils/alsoft-config/mainwindow.h b/jni/openal-soft-1.16.0/utils/alsoft-config/mainwindow.h similarity index 100% rename from jni/openal-soft-android/utils/alsoft-config/mainwindow.h rename to jni/openal-soft-1.16.0/utils/alsoft-config/mainwindow.h diff --git a/jni/openal-soft-android/utils/alsoft-config/mainwindow.ui b/jni/openal-soft-1.16.0/utils/alsoft-config/mainwindow.ui similarity index 90% rename from jni/openal-soft-android/utils/alsoft-config/mainwindow.ui rename to jni/openal-soft-1.16.0/utils/alsoft-config/mainwindow.ui index 4c7d0c69..3c92abf6 100644 --- a/jni/openal-soft-android/utils/alsoft-config/mainwindow.ui +++ b/jni/openal-soft-1.16.0/utils/alsoft-config/mainwindow.ui @@ -58,8 +58,8 @@ 120 20 - 206 - 23 + 188 + 22 @@ -147,8 +147,8 @@ float and converted to the output sample type as needed. 120 50 - 247 - 23 + 227 + 22 @@ -200,7 +200,7 @@ to stereo output. 120 80 - 123 + 111 22 @@ -348,15 +348,14 @@ sample rate. 110 30 - 361 + 301 121 A list of files containing HRTF data sets. The listed data sets -are used in place of or in addiiton to the the built-in set. The -filenames may contain these markers, which will be replaced -as needed: +are used in place of the default sets. The filenames may +contain these markers, which will be replaced as needed: %r - Device sampling rate %% - Percent sign (%) @@ -379,14 +378,14 @@ as needed: - 475 + 419 30 - 25 + 81 25 - + Add... @@ -400,14 +399,14 @@ as needed: - 475 + 419 60 - 25 + 81 25 - + Remove @@ -738,8 +737,8 @@ value currently possible is 4. 110 120 - 203 - 23 + 185 + 22 @@ -775,54 +774,79 @@ value currently possible is 4. 10 150 511 - 61 + 91 - Disables use of specific CPU extensions. Certain methods may -utilize CPU extensions when detected, and this is useful for -preventing those extensions from being used. + Enables use of specific CPU extensions. Certain methods may +utilize CPU extensions when detected, and disabling these can +be useful for preventing those extensions from being used. CPU Extensions - + - 10 + 180 20 - 101 + 71 31 - Disable SSE + SSE + + + true - + - 200 - 20 - 111 + 180 + 50 + 71 31 - Disable SSE2 + SSE2 + + + true - + - 380 - 20 - 111 + 260 + 50 + 71 31 - Disable Neon + Neon + + + true + + + + + + 260 + 20 + 71 + 31 + + + + SSE4.1 + + + true @@ -1011,21 +1035,21 @@ value of 0 means no change. - 9 + 10 170 511 - 181 + 191 - Disables effects, preventing apps from recognizing them. This -can help for apps that try to use effects which are too CPU -intensive for the system to handle. + Specifies which effects apps can recognize. Disabling effects +can help for apps that try to use ones that are too intensive +for the system to handle. - Disabled Effects + Enabled Effects - + 70 @@ -1037,8 +1061,11 @@ intensive for the system to handle. EAX Reverb + + true + - + 70 @@ -1050,8 +1077,11 @@ intensive for the system to handle. Standard Reverb + + true + - + 70 @@ -1063,21 +1093,11 @@ intensive for the system to handle. Chorus - - - - - 70 - 120 - 131 - 21 - - - - Distortion + + true - + 70 @@ -1087,10 +1107,13 @@ intensive for the system to handle. - Echo + Distortion + + + true - + 320 @@ -1100,10 +1123,13 @@ intensive for the system to handle. - Equalizer + Echo + + + true - + 320 @@ -1113,10 +1139,13 @@ intensive for the system to handle. - Flanger + Equalizer + + + true - + 320 @@ -1126,10 +1155,13 @@ intensive for the system to handle. - Ring Modulator + Flanger + + + true - + 320 @@ -1138,13 +1170,48 @@ intensive for the system to handle. 21 + + Ring Modulator + + + true + + + + + + 320 + 150 + 131 + 21 + + - Disables both the Dedicated Dialog and Dedicated LFE effects + Enables both the Dedicated Dialog and Dedicated LFE effects added by the ALC_EXT_DEDICATED extension. Dedicated ... + + true + + + + + + 70 + 120 + 111 + 21 + + + + Compressor + + + true + @@ -1168,8 +1235,8 @@ added by the ALC_EXT_DEDICATED extension. 160 20 - 142 - 23 + 131 + 22 @@ -1320,7 +1387,7 @@ added by the ALC_EXT_DEDICATED extension. 0 0 564 - 20 + 19 diff --git a/jni/openal-soft-android/utils/makehrtf.c b/jni/openal-soft-1.16.0/utils/makehrtf.c similarity index 98% rename from jni/openal-soft-android/utils/makehrtf.c rename to jni/openal-soft-1.16.0/utils/makehrtf.c index f9da9429..0a1bd043 100644 --- a/jni/openal-soft-android/utils/makehrtf.c +++ b/jni/openal-soft-1.16.0/utils/makehrtf.c @@ -58,7 +58,6 @@ * 1999 */ -// Needed for 64-bit unsigned integer. #include "config.h" #include @@ -67,9 +66,13 @@ #include #include #include +#ifdef HAVE_STRINGS_H +#include +#endif // Rely (if naively) on OpenAL's header for the types used for serialization. #include "AL/al.h" +#include "AL/alext.h" #ifndef M_PI #define M_PI (3.14159265358979323846) @@ -231,23 +234,12 @@ enum OutputFormatT { // Unsigned integer type. typedef unsigned int uint; -// Serialization types. The trailing digit indicates the number of bytes. -typedef ALubyte uint1; +// Serialization types. The trailing digit indicates the number of bits. +typedef ALubyte uint8; -typedef ALint int4; -typedef ALuint uint4; - -#if defined (HAVE_STDINT_H) -#include - -typedef uint64_t uint8; -#elif defined (HAVE___INT64) -typedef unsigned __int64 uint8; -#elif (SIZEOF_LONG == 8) -typedef unsigned long uint8; -#elif (SIZEOF_LONG_LONG == 8) -typedef unsigned long long uint8; -#endif +typedef ALint int32; +typedef ALuint uint32; +typedef ALuint64SOFT uint64; typedef enum ByteOrderT ByteOrderT; typedef enum SourceFormatT SourceFormatT; @@ -779,21 +771,23 @@ static int HpTpdfDither (const double in, int * hpHist) { } // Allocates an array of doubles. -static double * CreateArray (const size_t n) { - double * a = NULL; +static double *CreateArray(size_t n) +{ + double *a; - a = (double *) calloc (n, sizeof (double)); - if (a == NULL) { - fprintf (stderr, "Error: Out of memory.\n"); - exit (-1); - } - return (a); + if(n == 0) n = 1; + a = calloc(n, sizeof(double)); + if(a == NULL) + { + fprintf(stderr, "Error: Out of memory.\n"); + exit(-1); + } + return a; } // Frees an array of doubles. -static void DestroyArray (const double * a) { - free ((void *) a); -} +static void DestroyArray(double *a) +{ free(a); } // Complex number routines. All outputs must be non-NULL. @@ -1220,6 +1214,9 @@ static void ResamplerRun (ResamplerT * rs, const uint inN, const double * in, co double r; uint j_f, j_s; + if (outN == 0) + return; + // Handle in-place operation. if (in == out) work = CreateArray (outN); @@ -1252,9 +1249,9 @@ static void ResamplerRun (ResamplerT * rs, const uint inN, const double * in, co // Read a binary value of the specified byte order and byte size from a file, // storing it as a 32-bit unsigned integer. -static int ReadBin4 (FILE * fp, const char * filename, const ByteOrderT order, const uint bytes, uint4 * out) { - uint1 in [4]; - uint4 accum; +static int ReadBin4 (FILE * fp, const char * filename, const ByteOrderT order, const uint bytes, uint32 * out) { + uint8 in [4]; + uint32 accum; uint i; if (fread (in, 1, bytes, fp) != bytes) { @@ -1280,9 +1277,9 @@ static int ReadBin4 (FILE * fp, const char * filename, const ByteOrderT order, c // Read a binary value of the specified byte order from a file, storing it as // a 64-bit unsigned integer. -static int ReadBin8 (FILE * fp, const char * filename, const ByteOrderT order, uint8 * out) { - uint1 in [8]; - uint8 accum; +static int ReadBin8 (FILE * fp, const char * filename, const ByteOrderT order, uint64 * out) { + uint8 in [8]; + uint64 accum; uint i; if (fread (in, 1, 8, fp) != 8) { @@ -1321,8 +1318,8 @@ static int WriteAscii (const char * out, FILE * fp, const char * filename) { // Write a binary value of the given byte order and byte size to a file, // loading it from a 32-bit unsigned integer. -static int WriteBin4 (const ByteOrderT order, const uint bytes, const uint4 in, FILE * fp, const char * filename) { - uint1 out [4]; +static int WriteBin4 (const ByteOrderT order, const uint bytes, const uint32 in, FILE * fp, const char * filename) { + uint8 out [4]; uint i; switch (order) { @@ -1352,12 +1349,12 @@ static int WriteBin4 (const ByteOrderT order, const uint bytes, const uint4 in, */ static int ReadBinAsDouble (FILE * fp, const char * filename, const ByteOrderT order, const ElementTypeT type, const uint bytes, const int bits, double * out) { union { - uint4 ui; - int4 i; + uint32 ui; + int32 i; float f; } v4; union { - uint8 ui; + uint64 ui; double f; } v8; @@ -1419,8 +1416,8 @@ static int ReadAsciiAsDouble (TokenReaderT * tr, const char * filename, const El // Read the RIFF/RIFX WAVE format chunk from a file, validating it against // the source parameters and data set metrics. static int ReadWaveFormat (FILE * fp, const ByteOrderT order, const uint hrirRate, SourceRefT * src) { - uint4 fourCC, chunkSize; - uint4 format, channels, rate, dummy, block, size, bits; + uint32 fourCC, chunkSize; + uint32 format, channels, rate, dummy, block, size, bits; chunkSize = 0; do { @@ -1522,7 +1519,7 @@ static int ReadWaveData (FILE * fp, const SourceRefT * src, const ByteOrderT ord // Read the RIFF/RIFX WAVE list or data chunk, converting all elements to // doubles. static int ReadWaveList (FILE * fp, const SourceRefT * src, const ByteOrderT order, const uint n, double * hrir) { - uint4 fourCC, chunkSize, listSize, count; + uint32 fourCC, chunkSize, listSize, count; uint block, skip, offset, i; double lastSample; @@ -1608,7 +1605,7 @@ static int ReadWaveList (FILE * fp, const SourceRefT * src, const ByteOrderT ord // Load a source HRIR from a RIFF/RIFX WAVE file. static int LoadWaveSource (FILE * fp, SourceRefT * src, const uint hrirRate, const uint n, double * hrir) { - uint4 fourCC, dummy; + uint32 fourCC, dummy; ByteOrderT order; if ((! ReadBin4 (fp, src -> mPath, BO_LITTLE, 4, & fourCC)) || @@ -2061,14 +2058,14 @@ static int StoreMhr (const HrirDataT * hData, const char * filename) { } if (! WriteAscii (MHR_FORMAT, fp, filename)) return (0); - if (! WriteBin4 (BO_LITTLE, 4, (uint4) hData -> mIrRate, fp, filename)) + if (! WriteBin4 (BO_LITTLE, 4, (uint32) hData -> mIrRate, fp, filename)) return (0); - if (! WriteBin4 (BO_LITTLE, 1, (uint4) hData -> mIrPoints, fp, filename)) + if (! WriteBin4 (BO_LITTLE, 1, (uint32) hData -> mIrPoints, fp, filename)) return (0); - if (! WriteBin4 (BO_LITTLE, 1, (uint4) hData -> mEvCount, fp, filename)) + if (! WriteBin4 (BO_LITTLE, 1, (uint32) hData -> mEvCount, fp, filename)) return (0); for (e = 0; e < hData -> mEvCount; e ++) { - if (! WriteBin4 (BO_LITTLE, 1, (uint4) hData -> mAzCount [e], fp, filename)) + if (! WriteBin4 (BO_LITTLE, 1, (uint32) hData -> mAzCount [e], fp, filename)) return (0); } step = hData -> mIrSize; @@ -2079,13 +2076,13 @@ static int StoreMhr (const HrirDataT * hData, const char * filename) { hpHist = 0; for (i = 0; i < n; i ++) { v = HpTpdfDither (32767.0 * hData -> mHrirs [j + i], & hpHist); - if (! WriteBin4 (BO_LITTLE, 2, (uint4) v, fp, filename)) + if (! WriteBin4 (BO_LITTLE, 2, (uint32) v, fp, filename)) return (0); } } for (j = 0; j < hData -> mIrCount; j ++) { v = (int) fmin (round (hData -> mIrRate * hData -> mHrtds [j]), MAX_HRTD); - if (! WriteBin4 (BO_LITTLE, 1, (uint4) v, fp, filename)) + if (! WriteBin4 (BO_LITTLE, 1, (uint32) v, fp, filename)) return (0); } fclose (fp); @@ -2207,7 +2204,7 @@ static int ProcessMetrics (TokenReaderT * tr, const uint fftSize, const uint tru return (0); points = (uint) intVal; if ((fftSize > 0) && (points > fftSize)) { - TrErrorAt (tr, line, col, "Value exceeds the overriden FFT size.\n"); + TrErrorAt (tr, line, col, "Value exceeds the overridden FFT size.\n"); return (0); } if (points < truncSize) { diff --git a/jni/openal-soft-android/utils/openal-info.c b/jni/openal-soft-1.16.0/utils/openal-info.c similarity index 100% rename from jni/openal-soft-android/utils/openal-info.c rename to jni/openal-soft-1.16.0/utils/openal-info.c diff --git a/jni/openal-soft-android/.gitignore b/jni/openal-soft-android/.gitignore deleted file mode 100644 index b792eb2e..00000000 --- a/jni/openal-soft-android/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -build -winbuild -win64build -include/sndio.h -include/sys -openal-soft.kdev4 diff --git a/jni/openal-soft-android/Alc/atomic.h b/jni/openal-soft-android/Alc/atomic.h deleted file mode 100644 index 1dd8f9dc..00000000 --- a/jni/openal-soft-android/Alc/atomic.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef AL_ATOMIC_H -#define AL_ATOMIC_H - - -typedef void *volatile XchgPtr; - -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) && !defined(__QNXNTO__) -typedef unsigned int RefCount; -inline RefCount IncrementRef(volatile RefCount *ptr) -{ return __sync_add_and_fetch(ptr, 1); } -inline RefCount DecrementRef(volatile RefCount *ptr) -{ return __sync_sub_and_fetch(ptr, 1); } - -inline int ExchangeInt(volatile int *ptr, int newval) -{ - return __sync_lock_test_and_set(ptr, newval); -} -inline void *ExchangePtr(XchgPtr *ptr, void *newval) -{ - return __sync_lock_test_and_set(ptr, newval); -} -inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval) -{ - return __sync_bool_compare_and_swap(ptr, oldval, newval); -} -inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval) -{ - return __sync_bool_compare_and_swap(ptr, oldval, newval); -} - -#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) - -inline unsigned int xaddl(volatile unsigned int *dest, int incr) -{ - unsigned int ret; - __asm__ __volatile__("lock; xaddl %0,(%1)" - : "=r" (ret) - : "r" (dest), "0" (incr) - : "memory"); - return ret; -} - -typedef unsigned int RefCount; -inline RefCount IncrementRef(volatile RefCount *ptr) -{ return xaddl(ptr, 1)+1; } -inline RefCount DecrementRef(volatile RefCount *ptr) -{ return xaddl(ptr, -1)-1; } - -inline int ExchangeInt(volatile int *dest, int newval) -{ - int ret; - __asm__ __volatile__("lock; xchgl %0,(%1)" - : "=r" (ret) - : "r" (dest), "0" (newval) - : "memory"); - return ret; -} - -inline ALboolean CompExchangeInt(volatile int *dest, int oldval, int newval) -{ - int ret; - __asm__ __volatile__("lock; cmpxchgl %2,(%1)" - : "=a" (ret) - : "r" (dest), "r" (newval), "0" (oldval) - : "memory"); - return ret == oldval; -} - -inline void *ExchangePtr(XchgPtr *dest, void *newval) -{ - void *ret; - __asm__ __volatile__( -#ifdef __i386__ - "lock; xchgl %0,(%1)" -#else - "lock; xchgq %0,(%1)" -#endif - : "=r" (ret) - : "r" (dest), "0" (newval) - : "memory" - ); - return ret; -} - -inline ALboolean CompExchangePtr(XchgPtr *dest, void *oldval, void *newval) -{ - void *ret; - __asm__ __volatile__( -#ifdef __i386__ - "lock; cmpxchgl %2,(%1)" -#else - "lock; cmpxchgq %2,(%1)" -#endif - : "=a" (ret) - : "r" (dest), "r" (newval), "0" (oldval) - : "memory" - ); - return ret == oldval; -} - -#elif defined(_WIN32) - -#define WIN32_LEAN_AND_MEAN -#include - -typedef LONG RefCount; -inline RefCount IncrementRef(volatile RefCount *ptr) -{ return InterlockedIncrement(ptr); } -inline RefCount DecrementRef(volatile RefCount *ptr) -{ return InterlockedDecrement(ptr); } - -extern ALbyte LONG_size_does_not_match_int[(sizeof(LONG)==sizeof(int))?1:-1]; - -inline int ExchangeInt(volatile int *ptr, int newval) -{ - union { - volatile int *i; - volatile LONG *l; - } u = { ptr }; - return InterlockedExchange(u.l, newval); -} -inline void *ExchangePtr(XchgPtr *ptr, void *newval) -{ - return InterlockedExchangePointer(ptr, newval); -} -inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval) -{ - union { - volatile int *i; - volatile LONG *l; - } u = { ptr }; - return InterlockedCompareExchange(u.l, newval, oldval) == oldval; -} -inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval) -{ - return InterlockedCompareExchangePointer(ptr, newval, oldval) == oldval; -} - -#elif defined(__APPLE__) - -#include - -typedef int32_t RefCount; -inline RefCount IncrementRef(volatile RefCount *ptr) -{ return OSAtomicIncrement32Barrier(ptr); } -inline RefCount DecrementRef(volatile RefCount *ptr) -{ return OSAtomicDecrement32Barrier(ptr); } - -inline int ExchangeInt(volatile int *ptr, int newval) -{ - /* Really? No regular old atomic swap? */ - int oldval; - do { - oldval = *ptr; - } while(!OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr)); - return oldval; -} -inline void *ExchangePtr(XchgPtr *ptr, void *newval) -{ - void *oldval; - do { - oldval = *ptr; - } while(!OSAtomicCompareAndSwapPtrBarrier(oldval, newval, ptr)); - return oldval; -} -inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval) -{ - return OSAtomicCompareAndSwap32Barrier(oldval, newval, ptr); -} -inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval) -{ - return OSAtomicCompareAndSwapPtrBarrier(oldval, newval, ptr); -} - -#else -#error "No atomic functions available on this platform!" -typedef ALuint RefCount; -#endif - -#endif /* AL_ATOMIC_H */ diff --git a/jni/openal-soft-android/Alc/compat.h b/jni/openal-soft-android/Alc/compat.h deleted file mode 100644 index dbbcce28..00000000 --- a/jni/openal-soft-android/Alc/compat.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef AL_COMPAT_H -#define AL_COMPAT_H - -#include "AL/al.h" - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include - -typedef DWORD althread_key_t; -int althread_key_create(althread_key_t *key, void (*callback)(void*)); -int althread_key_delete(althread_key_t key); -void *althread_getspecific(althread_key_t key); -int althread_setspecific(althread_key_t key, void *val); - -typedef LONG althread_once_t; -#define ALTHREAD_ONCE_INIT 0 -void althread_once(althread_once_t *once, void (*callback)(void)); - -inline int alsched_yield(void) -{ SwitchToThread(); return 0; } - -WCHAR *strdupW(const WCHAR *str); - -#define HAVE_DYNLOAD 1 - -#else - -#include - -typedef pthread_mutex_t CRITICAL_SECTION; -void InitializeCriticalSection(CRITICAL_SECTION *cs); -void DeleteCriticalSection(CRITICAL_SECTION *cs); -void EnterCriticalSection(CRITICAL_SECTION *cs); -void LeaveCriticalSection(CRITICAL_SECTION *cs); - -ALuint timeGetTime(void); -void Sleep(ALuint t); - -#define althread_key_t pthread_key_t -#define althread_key_create pthread_key_create -#define althread_key_delete pthread_key_delete -#define althread_getspecific pthread_getspecific -#define althread_setspecific pthread_setspecific - -#define althread_once_t pthread_once_t -#define ALTHREAD_ONCE_INIT PTHREAD_ONCE_INIT -#define althread_once pthread_once - -#define alsched_yield sched_yield - -#if defined(HAVE_DLFCN_H) -#define HAVE_DYNLOAD 1 -#endif - -#endif - -#ifdef HAVE_DYNLOAD -void *LoadLib(const char *name); -void CloseLib(void *handle); -void *GetSymbol(void *handle, const char *name); -#endif - -#endif /* AL_COMPAT_H */ diff --git a/jni/openal-soft-android/Alc/helpers.c b/jni/openal-soft-android/Alc/helpers.c deleted file mode 100644 index f8a5f13b..00000000 --- a/jni/openal-soft-android/Alc/helpers.c +++ /dev/null @@ -1,708 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 2011 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include -#include -#ifdef HAVE_MALLOC_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); - -#ifdef HAVE_MMDEVAPI -#include -DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); -#endif -#endif -#endif /* AL_NO_UID_DEFS */ - -#ifdef HAVE_DLFCN_H -#include -#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 - -#include "alMain.h" -#include "atomic.h" -#include "uintmap.h" -#include "compat.h" - - -extern inline RefCount IncrementRef(volatile RefCount *ptr); -extern inline RefCount DecrementRef(volatile RefCount *ptr); -extern inline int ExchangeInt(volatile int *ptr, int newval); -extern inline void *ExchangePtr(XchgPtr *ptr, void *newval); -extern inline ALboolean CompExchangeInt(volatile int *ptr, int oldval, int newval); -extern inline ALboolean CompExchangePtr(XchgPtr *ptr, void *oldval, void *newval); - -extern inline void LockUIntMapRead(UIntMap *map); -extern inline void UnlockUIntMapRead(UIntMap *map); -extern inline void LockUIntMapWrite(UIntMap *map); -extern inline void UnlockUIntMapWrite(UIntMap *map); - -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_CPUID_H) && (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; - } - } - } -#elif defined(HAVE_WINDOWS_H) - HMODULE k32 = GetModuleHandleA("kernel32.dll"); - BOOL (WINAPI*IsProcessorFeaturePresent)(DWORD ProcessorFeature); - IsProcessorFeaturePresent = (BOOL(WINAPI*)(DWORD))GetProcAddress(k32, "IsProcessorFeaturePresent"); - if(!IsProcessorFeaturePresent) - ERR("IsProcessorFeaturePresent not available; CPU caps not detected\n"); - else - { - if(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE)) - { - caps |= CPU_CAP_SSE; - if(IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE)) - caps |= CPU_CAP_SSE2; - } - } -#endif -#ifdef HAVE_NEON - /* Assume Neon support if compiled with it */ - caps |= CPU_CAP_NEON; -#endif - - TRACE("Got caps:%s%s%s%s\n", ((caps&CPU_CAP_SSE)?((capfilter&CPU_CAP_SSE)?" SSE":" (SSE)"):""), - ((caps&CPU_CAP_SSE2)?((capfilter&CPU_CAP_SSE2)?" SSE2":" (SSE2)"):""), - ((caps&CPU_CAP_NEON)?((capfilter&CPU_CAP_NEON)?" Neon":" (Neon)"):""), - ((!caps)?" -none-":"")); - CPUCapFlags = caps & capfilter; -} - - -void *al_malloc(size_t alignment, size_t size) -{ -#if defined(HAVE_ALIGNED_ALLOC) - size = (size+(alignment-1))&~(alignment-1); - return aligned_alloc(alignment, size); -#elif defined(HAVE_POSIX_MEMALIGN) - void *ret; - if(posix_memalign(&ret, alignment, size) == 0) - return ret; - return NULL; -#elif defined(HAVE__ALIGNED_MALLOC) - return _aligned_malloc(size, alignment); -#else - char *ret = malloc(size+alignment); - if(ret != NULL) - { - *(ret++) = 0x00; - while(((ALintptrEXT)ret&(alignment-1)) != 0) - *(ret++) = 0x55; - } - return ret; -#endif -} - -void *al_calloc(size_t alignment, size_t size) -{ - void *ret = al_malloc(alignment, size); - if(ret) memset(ret, 0, size); - return ret; -} - -void al_free(void *ptr) -{ -#if defined(HAVE_ALIGNED_ALLOC) || defined(HAVE_POSIX_MEMALIGN) - free(ptr); -#elif defined(HAVE__ALIGNED_MALLOC) - _aligned_free(ptr); -#else - if(ptr != NULL) - { - char *finder = ptr; - do { - --finder; - } while(*finder == 0x55); - free(finder); - } -#endif -} - - -#if (defined(HAVE___CONTROL87_2) || defined(HAVE__CONTROLFP)) && (defined(__x86_64__) || defined(_M_X64)) -/* Win64 doesn't allow us to set the precision control. */ -#undef _MCW_PC -#define _MCW_PC 0 -#endif - -void SetMixerFPUMode(FPUCtl *ctl) -{ -#ifdef HAVE_FENV_H - fegetenv(STATIC_CAST(fenv_t, ctl)); -#if defined(__GNUC__) && defined(HAVE_SSE) - if((CPUCapFlags&CPU_CAP_SSE)) - __asm__ __volatile__("stmxcsr %0" : "=m" (*&ctl->sse_state)); -#endif - -#ifdef FE_TOWARDZERO - fesetround(FE_TOWARDZERO); -#endif -#if defined(__GNUC__) && defined(HAVE_SSE) - if((CPUCapFlags&CPU_CAP_SSE)) - { - int sseState = ctl->sse_state; - sseState |= 0x6000; /* set round-to-zero */ - sseState |= 0x8000; /* set flush-to-zero */ - if((CPUCapFlags&CPU_CAP_SSE2)) - sseState |= 0x0040; /* set denormals-are-zero */ - __asm__ __volatile__("ldmxcsr %0" : : "m" (*&sseState)); - } -#endif - -#elif defined(HAVE___CONTROL87_2) - - int mode; - __control87_2(0, 0, &ctl->state, NULL); - __control87_2(_RC_CHOP|_PC_24, _MCW_RC|_MCW_PC, &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|_PC_24, _MCW_RC|_MCW_PC); -#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|_MCW_PC, &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|_MCW_PC); -#endif -} - - -#ifdef _WIN32 -extern inline int alsched_yield(void); - -void althread_once(althread_once_t *once, void (*callback)(void)) -{ - LONG ret; - while((ret=InterlockedExchange(once, 1)) == 1) - alsched_yield(); - if(ret == 0) - callback(); - InterlockedExchange(once, 2); -} - - -int althread_key_create(althread_key_t *key, void (*callback)(void*)) -{ - *key = TlsAlloc(); - if(callback) - InsertUIntMapEntry(&TlsDestructor, *key, callback); - return 0; -} - -int althread_key_delete(althread_key_t key) -{ - InsertUIntMapEntry(&TlsDestructor, key, NULL); - TlsFree(key); - return 0; -} - -void *althread_getspecific(althread_key_t key) -{ return TlsGetValue(key); } - -int althread_setspecific(althread_key_t key, void *val) -{ - TlsSetValue(key, val); - return 0; -} - - -void *LoadLib(const char *name) -{ return LoadLibraryA(name); } -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; -} - -#else - -#include -#ifdef HAVE_PTHREAD_NP_H -#include -#endif -#include -#include -#include - -void InitializeCriticalSection(CRITICAL_SECTION *cs) -{ - pthread_mutexattr_t attrib; - int ret; - - ret = pthread_mutexattr_init(&attrib); - assert(ret == 0); - - ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE); -#ifdef HAVE_PTHREAD_NP_H - if(ret != 0) - ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE); -#endif - assert(ret == 0); - ret = pthread_mutex_init(cs, &attrib); - assert(ret == 0); - - pthread_mutexattr_destroy(&attrib); -} -void DeleteCriticalSection(CRITICAL_SECTION *cs) -{ - int ret; - ret = pthread_mutex_destroy(cs); - assert(ret == 0); -} -void EnterCriticalSection(CRITICAL_SECTION *cs) -{ - int ret; - ret = pthread_mutex_lock(cs); - assert(ret == 0); -} -void LeaveCriticalSection(CRITICAL_SECTION *cs) -{ - int ret; - ret = pthread_mutex_unlock(cs); - assert(ret == 0); -} - -/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed - * to the expected DWORD. Both are defined as unsigned 32-bit types, however. - * Additionally, Win32 is supposed to measure the time since Windows started, - * as opposed to the actual time. */ -ALuint timeGetTime(void) -{ -#if _POSIX_TIMERS > 0 - struct timespec ts; - int ret = -1; - -#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0) -#if _POSIX_MONOTONIC_CLOCK == 0 - static int hasmono = 0; - if(hasmono > 0 || (hasmono == 0 && - (hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0)) -#endif - ret = clock_gettime(CLOCK_MONOTONIC, &ts); -#endif - if(ret != 0) - ret = clock_gettime(CLOCK_REALTIME, &ts); - assert(ret == 0); - - return ts.tv_nsec/1000000 + ts.tv_sec*1000; -#else - struct timeval tv; - int ret; - - ret = gettimeofday(&tv, NULL); - assert(ret == 0); - - return tv.tv_usec/1000 + tv.tv_sec*1000; -#endif -} - -void Sleep(ALuint t) -{ - struct timespec tv, rem; - tv.tv_nsec = (t*1000000)%1000000000; - tv.tv_sec = t/1000; - - while(nanosleep(&tv, &rem) == -1 && errno == EINTR) - tv = rem; -} - -#ifdef HAVE_DLFCN_H - -void *LoadLib(const char *name) -{ - const char *err; - void *handle; - - dlerror(); - handle = dlopen(name, RTLD_NOW); - if((err=dlerror()) != NULL) - handle = NULL; - return handle; -} -void CloseLib(void *handle) -{ dlclose(handle); } -void *GetSymbol(void *handle, const char *name) -{ - const char *err; - void *sym; - - dlerror(); - sym = dlsym(handle, name); - if((err=dlerror()) != NULL) - { - WARN("Failed to load %s: %s\n", name, err); - sym = NULL; - } - return sym; -} - -#endif -#endif - - -void al_print(const char *type, const char *func, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - fprintf(LogFile, "AL lib: %s %s: ", type, func); - vfprintf(LogFile, fmt, ap); - va_end(ap); - - fflush(LogFile); -} - - -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"); -} - - -static void Lock(volatile ALenum *l) -{ - while(ExchangeInt(l, AL_TRUE) == AL_TRUE) - alsched_yield(); -} - -static void Unlock(volatile ALenum *l) -{ - ExchangeInt(l, AL_FALSE); -} - -void RWLockInit(RWLock *lock) -{ - lock->read_count = 0; - lock->write_count = 0; - lock->read_lock = AL_FALSE; - lock->read_entry_lock = AL_FALSE; - lock->write_lock = AL_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); -} - - -void InitUIntMap(UIntMap *map, ALsizei limit) -{ - map->array = NULL; - map->size = 0; - map->maxsize = 0; - map->limit = limit; - RWLockInit(&map->lock); -} - -void ResetUIntMap(UIntMap *map) -{ - WriteLock(&map->lock); - free(map->array); - map->array = NULL; - map->size = 0; - map->maxsize = 0; - WriteUnlock(&map->lock); -} - -ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value) -{ - ALsizei pos = 0; - - WriteLock(&map->lock); - if(map->size > 0) - { - ALsizei low = 0; - ALsizei high = map->size - 1; - while(low < high) - { - ALsizei mid = low + (high-low)/2; - if(map->array[mid].key < key) - low = mid + 1; - else - high = mid; - } - if(map->array[low].key < key) - low++; - pos = low; - } - - if(pos == map->size || map->array[pos].key != key) - { - if(map->size == map->limit) - { - WriteUnlock(&map->lock); - return AL_OUT_OF_MEMORY; - } - - if(map->size == map->maxsize) - { - ALvoid *temp = NULL; - ALsizei newsize; - - newsize = (map->maxsize ? (map->maxsize<<1) : 4); - if(newsize >= map->maxsize) - temp = realloc(map->array, newsize*sizeof(map->array[0])); - if(!temp) - { - WriteUnlock(&map->lock); - return AL_OUT_OF_MEMORY; - } - map->array = temp; - map->maxsize = newsize; - } - - if(pos < map->size) - memmove(&map->array[pos+1], &map->array[pos], - (map->size-pos)*sizeof(map->array[0])); - map->size++; - } - map->array[pos].key = key; - map->array[pos].value = value; - WriteUnlock(&map->lock); - - return AL_NO_ERROR; -} - -ALvoid *RemoveUIntMapKey(UIntMap *map, ALuint key) -{ - ALvoid *ptr = NULL; - WriteLock(&map->lock); - if(map->size > 0) - { - ALsizei low = 0; - ALsizei high = map->size - 1; - while(low < high) - { - ALsizei mid = low + (high-low)/2; - if(map->array[mid].key < key) - low = mid + 1; - else - high = mid; - } - if(map->array[low].key == key) - { - ptr = map->array[low].value; - if(low < map->size-1) - memmove(&map->array[low], &map->array[low+1], - (map->size-1-low)*sizeof(map->array[0])); - map->size--; - } - } - WriteUnlock(&map->lock); - return ptr; -} - -ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key) -{ - ALvoid *ptr = NULL; - ReadLock(&map->lock); - if(map->size > 0) - { - ALsizei low = 0; - ALsizei high = map->size - 1; - while(low < high) - { - ALsizei mid = low + (high-low)/2; - if(map->array[mid].key < key) - low = mid + 1; - else - high = mid; - } - if(map->array[low].key == key) - ptr = map->array[low].value; - } - ReadUnlock(&map->lock); - return ptr; -} diff --git a/jni/openal-soft-android/Alc/hrtf_tables.inc b/jni/openal-soft-android/Alc/hrtf_tables.inc deleted file mode 100644 index 9c6af6a1..00000000 --- a/jni/openal-soft-android/Alc/hrtf_tables.inc +++ /dev/null @@ -1,848 +0,0 @@ -/* Elevation metrics */ -static const ALubyte defaultAzCount[19] = { 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1, }; -static const ALushort defaultEvOffset[19] = { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827, }; - -/* HRIR Coefficients */ -static const ALshort defaultCoeffs[26496] = -{ - +6117, +8354, +3531, +2903, +1118, +342, +874, -822, -2447, -1309, +579, -133, -617, -1093, -998, -416, -244, -202, -84, -134, -375, -200, -416, -331, -408, -614, -489, -332, -207, -97, -7, -145, - +6958, +8678, +3013, +3274, +1145, +25, +847, -771, -2501, -1666, +534, +86, -597, -917, -967, -916, -367, -80, -198, -215, -475, -312, -442, -372, -399, -554, -517, -249, -103, -75, -5, -176, - +6349, +8083, +2935, +2854, +1109, +344, +851, -891, -2351, -1252, +506, -191, -559, -861, -745, -485, -327, -77, -17, -172, -405, -189, -402, -350, -459, -599, -449, -315, -184, -77, +13, -134, - +5910, +7494, +2698, +2625, +992, +373, +884, -825, -2197, -962, +698, -127, -425, -759, -697, -286, -213, -171, -64, -127, -336, -131, -355, -271, -368, -553, -428, -299, -179, -74, +4, -137, - +5808, +7380, +2660, +2585, +1001, +453, +998, -698, -2078, -854, +773, -100, -470, -857, -730, -241, -185, -179, -63, -114, -325, -112, -322, -220, -300, -507, -404, -297, -216, -122, -35, -168, - +5957, +7591, +2687, +2503, +871, +340, +913, -821, -2282, -1053, +775, -16, -459, -904, -784, -240, -114, -100, -12, -59, -285, -105, -334, -253, -340, -532, -400, -251, -127, -17, +33, -156, - +6515, +8209, +2752, +2639, +892, +326, +895, -1074, -2683, -1313, +854, -53, -682, -1135, -939, -316, -155, -153, -32, -64, -346, -124, -339, -249, -345, -543, -400, -232, -129, -39, +38, -120, - +6887, +8888, +3060, +2770, +926, +146, +833, -1245, -2800, -1317, +584, -231, -619, -1119, -983, -413, -244, -71, -9, -143, -405, -183, -399, -307, -420, -595, -439, -302, -153, -55, +34, -129, - +7340, +9090, +2964, +3130, +1162, +115, +612, -1577, -2702, -692, +458, -1019, -864, -943, -587, -190, -434, -226, +41, -162, -398, -144, -463, -353, -533, -708, -464, -374, -270, -103, +2, -187, - +8348, +9865, +2233, +2503, +594, +154, +1277, -1477, -3002, -433, +1280, -991, -1387, -1385, -643, +20, -514, -498, -16, -150, -545, -145, -486, -329, -539, -846, -509, -326, -250, -110, +9, -211, - +8668, +10241, +2446, +2335, +160, +133, +1408, -1244, -3403, -895, +1742, -269, -1341, -2123, -1100, +207, -94, -571, -238, -198, -607, -211, -581, -326, -492, -792, -539, -293, -202, -119, -28, -265, - +8261, +10052, +3261, +2775, +344, +65, +1000, -1138, -3661, -1615, +1337, +126, -290, -1970, -1899, -55, +143, -202, -175, -248, -492, -207, -591, -284, -495, -901, -578, -409, -197, -51, +38, -151, - +7749, +9628, +3084, +3049, +870, +16, +727, -1159, -2880, -1819, +969, +83, -717, -1031, -1759, -1055, -39, -9, -26, -31, -379, -324, -646, -479, -344, -651, -608, -341, -196, -48, +22, -160, - +7872, +8889, +2424, +3846, +1113, -405, +870, -636, -2562, -2175, +535, +438, -627, -691, -988, -1594, -378, +123, -383, -287, -574, -435, -436, -421, -370, -475, -575, -138, +9, -79, -10, -210, - +7007, +8290, +2692, +3507, +1037, -125, +838, -876, -2265, -1597, +225, -49, -510, -580, -573, -987, -677, +32, +42, -236, -535, -281, -374, -349, -433, -522, -408, -257, -182, -133, +15, -132, - +6475, +7694, +2419, +2913, +1152, +342, +794, -920, -2186, -1265, +352, -196, -457, -569, -494, -665, -413, +113, +33, -239, -428, -173, -379, -384, -517, -559, -408, -308, -159, -59, +31, -118, - +5981, +7105, +2165, +2692, +1134, +347, +767, -876, -2030, -957, +421, -294, -318, -441, -466, -416, -281, -39, -27, -194, -378, -156, -345, -274, -384, -498, -440, -344, -158, -51, +21, -134, - +5468, +6465, +2050, +2460, +952, +446, +858, -776, -1849, -646, +711, -106, -171, -377, -412, -225, -208, -139, -49, -122, -280, -59, -288, -217, -330, -482, -372, -276, -153, -54, +11, -123, - +5247, +6086, +1760, +2189, +842, +506, +1054, -433, -1470, -298, +965, +30, -189, -498, -477, -163, -126, -106, -24, -94, -283, -72, -247, -143, -266, -434, -302, -196, -110, -68, -52, -213, - +5232, +6232, +1996, +2383, +983, +625, +1098, -519, -1614, -432, +848, -66, -286, -585, -461, -110, -157, -165, -46, -92, -261, -20, -217, -109, -190, -394, -333, -281, -239, -151, -66, -182, - +5323, +6297, +1900, +2226, +867, +582, +1114, -514, -1700, -507, +886, -53, -362, -695, -545, -42, +42, -2, +24, -89, -290, -90, -302, -188, -238, -341, -202, -173, -185, -163, -115, -218, - +5574, +6674, +1997, +2183, +707, +407, +936, -776, -2047, -829, +914, +130, -285, -696, -573, -93, +9, -5, +50, +20, -186, -16, -247, -182, -271, -441, -315, -175, -47, +63, +58, -176, - +6045, +7217, +2109, +2333, +722, +394, +912, -1008, -2484, -1201, +940, +97, -533, -929, -717, -112, +69, +18, +107, +96, -204, -31, -262, -175, -230, -397, -254, -106, -72, -21, +17, -112, - +6856, +7935, +1962, +2469, +717, +365, +900, -1353, -2894, -1309, +1170, +26, -784, -1168, -861, -220, -61, -113, +16, +18, -323, -43, -253, -171, -282, -468, -311, -130, -56, +10, +78, -94, - +7514, +8789, +1982, +2483, +712, +262, +907, -1695, -3191, -1325, +1153, -23, -806, -1333, -975, -279, -115, -59, -35, -42, -373, -130, -392, -273, -384, -542, -334, -150, -38, +4, +93, -104, - +7708, +9393, +2471, +2673, +752, -59, +807, -1726, -3115, -1282, +555, -307, -586, -1146, -966, -429, -241, +103, +48, -175, -435, -160, -372, -287, -438, -565, -385, -281, -93, -15, +72, -115, - +7961, +9595, +2700, +3173, +1089, -199, +393, -2045, -2982, -748, +119, -1067, -577, -787, -541, -413, -602, -36, +144, -149, -336, -111, -417, -324, -553, -659, -425, -410, -226, -58, +56, -137, - +8750, +9725, +2189, +3527, +1193, -202, +307, -2424, -2793, +130, +87, -2091, -927, -659, -104, -33, -745, -205, +211, -231, -414, -73, -531, -374, -686, -789, -410, -438, -340, -94, +17, -238, - +9887, +10729, +1149, +2712, +812, -159, +1171, -2374, -3238, +573, +900, -2331, -1559, -881, +10, +282, -825, -483, +230, -178, -567, -74, -569, -393, -734, -962, -410, -384, -393, -161, +71, -197, - +11064, +11221, +279, +2282, +77, +57, +1829, -2384, -3518, +811, +1905, -2262, -2145, -1529, -99, +470, -985, -810, +158, -183, -755, -35, -580, -314, -703, -1105, -476, -311, -308, -116, +33, -294, - +11675, +11698, +209, +1859, -553, +242, +2236, -2105, -4055, +456, +2775, -1639, -2377, -2493, -525, +885, -700, -1033, -74, -269, -767, -30, -730, -335, -644, -1070, -436, -206, -262, -87, -13, -377, - +11801, +11992, +657, +1830, -875, +135, +2141, -1883, -4508, -144, +3105, -728, -2249, -3247, -939, +1040, -70, -1098, -336, -229, -882, -166, -780, -279, -597, -994, -559, -229, -208, -150, -49, -410, - +11441, +12041, +1632, +2283, -957, -39, +1816, -1840, -4880, -918, +2879, +121, -1146, -3647, -1711, +1051, +438, -745, -603, -262, -776, -209, -700, -151, -609, -1078, -625, -402, -194, -201, -9, -262, - +10865, +11676, +2584, +2613, -586, -83, +1224, -1524, -5125, -1724, +2382, +303, +58, -3199, -2831, +663, +561, -315, -300, -369, -601, -190, -808, -177, -617, -1246, -617, -484, -161, +7, +81, -166, - +10191, +11218, +2753, +3225, -135, -314, +1139, -1492, -4741, -2381, +2120, +202, +83, -1978, -3635, -327, +757, +52, -23, -340, -548, -69, -879, -641, -441, -1126, -641, -329, -170, +77, +67, -175, - +9689, +10846, +2307, +3298, +545, -344, +602, -1494, -3324, -2412, +1584, +308, -905, -920, -2772, -1685, +423, +196, -11, +88, -409, -493, -902, -608, -212, -710, -760, -321, -179, +12, +47, -183, - +8953, +9908, +2218, +3607, +920, -373, +599, -1197, -2905, -2314, +1261, +665, -1096, -819, -1580, -2014, -168, +187, -326, -97, -344, -334, -636, -572, -272, -489, -771, -288, -106, -59, +97, -199, - +8864, +8963, +1784, +4657, +969, -956, +982, -415, -2657, -2862, +633, +942, -750, -396, -1083, -2461, -216, +391, -668, -329, -673, -573, -389, -489, -318, -379, -677, +16, +122, -114, -18, -247, - +7756, +8469, +2432, +4304, +831, -834, +867, -757, -2207, -2102, -12, +321, -466, -174, -519, -1837, -871, +255, +23, -250, -677, -423, -326, -339, -330, -413, -490, -195, -73, -162, -2, -152, - +7061, +7757, +2298, +3660, +972, -50, +816, -871, -2023, -1762, +29, +39, -419, -270, -323, -1264, -738, +345, +74, -339, -535, -233, -317, -423, -530, -487, -350, -279, -220, -117, +68, -96, - +6469, +7209, +2035, +3061, +1233, +321, +690, -887, -1952, -1381, +126, -112, -325, -222, -261, -975, -473, +378, +46, -334, -435, -156, -344, -439, -577, -492, -370, -312, -132, -41, +48, -98, - +5924, +6587, +1791, +2840, +1306, +325, +630, -832, -1787, -1021, +168, -250, -169, -97, -250, -687, -289, +202, -37, -279, -361, -130, -348, -361, -448, -399, -386, -361, -133, -16, +50, -129, - +5282, +6011, +1719, +2545, +1130, +445, +720, -784, -1642, -749, +308, -187, +39, -21, -232, -423, -260, +27, -35, -215, -317, -45, -205, -222, -390, -439, -388, -320, -115, -45, +11, -94, - +4741, +5315, +1665, +2368, +986, +543, +781, -655, -1403, -392, +608, -36, +147, +49, -163, -239, -215, -100, -40, -117, -205, +8, -213, -171, -294, -397, -329, -264, -127, -36, +13, -103, - +4473, +4913, +1415, +2018, +802, +585, +981, -314, -1070, -10, +964, +194, +186, -38, -233, -201, -159, -68, +40, -54, -215, -5, -156, -100, -249, -363, -242, -160, -67, -14, -33, -215, - +4287, +4651, +1225, +2028, +1002, +772, +1151, -74, -767, +174, +960, +71, -57, -266, -220, -24, -57, -86, -63, -101, -197, +12, -123, -8, -137, -308, -225, -169, -123, -121, -128, -237, - +4337, +4965, +1624, +2246, +1058, +843, +1155, -266, -1056, -75, +799, +3, -60, -285, -202, -30, -153, -156, -30, -66, -178, +71, -100, -2, -76, -278, -279, -283, -274, -184, -98, -187, - +4443, +5025, +1531, +2119, +997, +856, +1205, -260, -1169, -213, +764, -10, -150, -366, -219, +89, +76, -16, -38, -108, -204, -23, -212, -56, -66, -154, -135, -246, -290, -240, -153, -192, - +4604, +5187, +1421, +1877, +708, +663, +1129, -291, -1278, -255, +968, +170, -109, -537, -478, +41, +175, +171, +207, -3, -219, -11, -242, -189, -190, -256, -119, -13, -31, -100, -174, -309, - +4923, +5652, +1529, +1902, +624, +528, +924, -671, -1743, -664, +996, +326, -100, -476, -372, +25, +128, +85, +100, +106, -73, +61, -152, -121, -199, -342, -237, -104, +32, +141, +70, -204, - +5421, +6220, +1615, +2041, +613, +476, +868, -945, -2209, -1062, +1028, +282, -361, -678, -462, +90, +247, +119, +166, +124, -141, +83, -164, -99, -131, -291, -197, -34, +4, +4, +72, -42, - +6190, +6818, +1507, +2236, +597, +518, +893, -1240, -2699, -1316, +1269, +222, -676, -957, -667, -54, +151, +26, +170, +185, -160, +80, -150, -125, -158, -266, -176, +4, -12, -12, +35, -111, - +7121, +7541, +1201, +2394, +583, +455, +869, -1653, -3075, -1304, +1541, +95, -937, -1178, -764, -132, +36, -84, +64, +109, -308, +44, -155, -103, -220, -385, -224, -28, +7, +54, +114, -67, - +7954, +8408, +983, +2438, +632, +359, +872, -2062, -3411, -1245, +1676, +31, -1048, -1363, -832, -150, -48, -120, +14, +94, -364, -58, -298, -170, -314, -457, -245, -56, +16, +70, +176, -53, - +8426, +9277, +1223, +2430, +532, +133, +944, -2316, -3533, -1292, +1244, -43, -818, -1449, -1029, -259, -53, +135, -32, -56, -402, -136, -404, -282, -407, -503, -267, -114, +46, +41, +136, -109, - +8583, +9860, +1762, +2634, +598, -282, +801, -2272, -3373, -1211, +481, -346, -524, -1183, -947, -470, -228, +324, +74, -228, -460, -132, -337, -273, -462, -518, -331, -270, -26, +19, +110, -100, - +8789, +10123, +2143, +3154, +907, -539, +350, -2551, -3191, -653, -134, -1144, -348, -706, -562, -559, -647, +213, +190, -170, -308, -125, -412, -293, -550, -593, -367, -441, -161, -3, +111, -113, - +9368, +10135, +1939, +3756, +1190, -650, -93, -2909, -2955, +75, -583, -2117, -371, -455, -4, -431, -1040, +118, +327, -275, -298, -31, -480, -340, -761, -730, -381, -524, -283, -44, +42, -215, - +10370, +10210, +1204, +4156, +1175, -623, -28, -3363, -2672, +1145, -623, -3309, -728, -270, +428, +27, -1178, -99, +420, -357, -415, +13, -626, -389, -869, -847, -326, -533, -414, -65, +33, -301, - +11635, +11075, -31, +3531, +952, -550, +724, -3443, -3032, +1791, +130, -3849, -1409, -370, +688, +391, -1323, -332, +504, -391, -598, +96, -680, -457, -950, -1002, -305, -479, -469, -136, +71, -286, - +13207, +11905, -1547, +2772, +301, -274, +1873, -3587, -3556, +2285, +1234, -3973, -2188, -835, +809, +672, -1631, -769, +602, -241, -847, +83, -674, -374, -941, -1208, -342, -448, -473, -101, +134, -318, - +14337, +12287, -2399, +2422, -469, +62, +2531, -3616, -3929, +2464, +2354, -3991, -2785, -1503, +623, +891, -1697, -1088, +457, -261, -1009, +151, -717, -276, -913, -1388, -372, -300, -384, -112, +67, -401, - +15087, +12820, -2744, +1910, -1184, +425, +3120, -3448, -4563, +2187, +3466, -3489, -3173, -2589, +266, +1446, -1532, -1382, +191, -327, -1016, +193, -847, -301, -888, -1367, -296, -177, -336, -114, +20, -474, - +15581, +13124, -2434, +1591, -1676, +521, +3195, -3036, -5227, +1724, +4250, -2658, -3404, -3573, -56, +1861, -986, -1649, +4, -355, -1041, +91, -1052, -239, -767, -1287, -362, -121, -296, -58, -65, -569, - +15601, +13452, -1914, +1563, -2007, +399, +3052, -2823, -5735, +1036, +4617, -1613, -3294, -4431, -451, +2051, -245, -1777, -331, -235, -1215, -48, -1032, -173, -736, -1221, -537, -142, -232, -189, -69, -580, - +15203, +13689, -870, +1955, -2244, +197, +2769, -2807, -6122, +172, +4587, -487, -2272, -5183, -1225, +2226, +446, -1489, -791, -175, -1171, -107, -880, -30, -790, -1309, -587, -320, -186, -316, -13, -442, - +14648, +13594, +409, +2248, -2137, -16, +2270, -2431, -6673, -665, +4167, +189, -766, -5403, -2316, +2230, +741, -1027, -813, -342, -840, -164, -978, +109, -745, -1474, -642, -547, -154, -159, +47, -247, - +13996, +13109, +1461, +2499, -1685, -37, +1524, -2013, -6863, -1546, +3712, +317, +445, -4840, -3714, +1807, +920, -566, -438, -485, -703, -148, -1075, +6, -791, -1647, -584, -567, -97, +72, +120, -190, - +13165, +12534, +1976, +3362, -1471, -314, +1381, -1961, -6484, -2520, +3399, +361, +831, -3679, -5026, +938, +1344, -192, -237, -452, -597, -58, -1183, -507, -582, -1548, -641, -480, -68, +246, +63, -219, - +12626, +12250, +1611, +3690, -681, -941, +1250, -1619, -5566, -2944, +3036, +177, +25, -1933, -5154, -665, +1470, +164, +107, -276, -664, -178, -1249, -762, -296, -1315, -631, -232, -234, +180, +66, -251, - +11980, +11934, +1167, +3735, +109, -727, +510, -1829, -3781, -3108, +2485, +496, -1203, -728, -4093, -2241, +1182, +347, -49, +233, -470, -711, -1173, -711, -7, -812, -944, -259, -161, +83, +61, -212, - +11247, +11010, +1120, +4114, +574, -764, +386, -1687, -3259, -2815, +2128, +825, -1544, -509, -2722, -2986, +467, +444, -350, +190, -276, -570, -1067, -700, +132, -512, -1156, -281, -35, -10, +123, -207, - +10116, +9947, +1402, +4469, +759, -942, +664, -954, -2962, -3136, +1495, +1323, -1375, -529, -1640, -2951, +60, +455, -723, -188, -423, -428, -490, -651, -326, -390, -839, -121, -11, -87, +128, -262, - +9934, +8876, +1128, +5737, +644, -1620, +1223, -109, -2816, -3751, +890, +1596, -1024, +3, -1280, -3531, +194, +690, -1086, -313, -780, -731, -285, -592, -233, -265, -834, +227, +227, -185, -20, -287, - +8502, +8500, +2204, +5212, +430, -1605, +1028, -561, -2155, -2773, -185, +874, -495, +321, -570, -2903, -846, +586, -74, -234, -828, -571, -225, -357, -205, -310, -640, -115, +58, -204, -18, -162, - +7584, +7772, +2171, +4547, +704, -725, +925, -716, -1861, -2401, -267, +505, -407, +183, -244, -2138, -927, +680, +60, -459, -671, -326, -222, -451, -469, -353, -358, -211, -203, -191, +84, -98, - +6877, +7100, +2027, +3726, +1015, +37, +675, -791, -1748, -2003, -196, +244, -318, +111, -88, -1694, -708, +748, +20, -457, -485, -226, -270, -512, -629, -427, -353, -293, -167, -97, +74, -60, - +6094, +6516, +1758, +3125, +1461, +313, +506, -750, -1620, -1508, -142, +48, -126, +224, -68, -1338, -382, +704, -7, -454, -398, -106, -300, -528, -626, -363, -337, -340, -80, +0, +68, -81, - +5474, +5821, +1573, +2970, +1494, +257, +449, -672, -1419, -1123, -157, -119, +81, +343, -71, -994, -247, +423, -94, -356, -314, -117, -307, -403, -455, -271, -389, -398, -91, +12, +63, -119, - +4706, +5219, +1556, +2650, +1342, +394, +527, -623, -1238, -816, -65, -106, +329, +424, -62, -677, -264, +193, -57, -276, -283, -47, -151, -234, -379, -329, -417, -360, -71, -27, +20, -78, - +3969, +4463, +1642, +2395, +1176, +599, +584, -518, -1032, -470, +216, +31, +488, +473, -5, -409, -215, +23, -78, -181, -137, +68, -136, -185, -309, -316, -333, -291, -98, -38, +10, -54, - +3424, +3827, +1536, +2086, +1002, +678, +738, -333, -681, +35, +605, +269, +533, +528, +71, -284, -241, -104, +39, -20, -139, +38, -65, -74, -225, -293, -257, -229, -78, +5, +12, -102, - +3209, +3445, +1231, +1747, +899, +784, +1000, +168, -305, +345, +880, +396, +496, +306, -68, -218, -102, -1, +55, -36, -135, +45, -28, -19, -180, -238, -160, -103, -27, -22, -94, -255, - +2989, +3191, +1074, +1836, +1186, +989, +1156, +381, -8, +502, +823, +223, +193, +66, +7, +5, -16, -56, -80, -81, -98, +68, +12, +88, -46, -191, -160, -138, -110, -149, -188, -250, - +3027, +3528, +1478, +2058, +1276, +1085, +1144, +149, -311, +281, +686, +149, +146, +19, +50, +25, -119, -132, -55, -57, -69, +143, +32, +105, +37, -167, -229, -266, -280, -209, -151, -192, - +3214, +3748, +1601, +2025, +1190, +1116, +1202, +89, -552, -87, +478, +220, +213, +9, +55, +81, -6, -61, -71, -93, -61, +81, -92, +76, +154, -10, -220, -365, -342, -251, -170, -159, - +3266, +3741, +1347, +1791, +1078, +1077, +1224, +91, -623, +51, +737, +114, -29, -162, -63, +235, +299, +125, +20, -78, -150, -17, -140, -29, -21, +31, +66, -141, -296, -306, -239, -221, - +3541, +4062, +1288, +1550, +718, +829, +1077, -44, -837, -142, +945, +448, +111, -311, -297, +101, +259, +279, +274, +70, -83, +51, -163, -131, -124, -170, -40, +66, +53, -44, -202, -351, - +3954, +4589, +1351, +1593, +636, +691, +854, -482, -1382, -587, +1032, +601, +79, -242, -184, +108, +254, +168, +138, +202, +51, +122, -43, -74, -123, -230, -173, -35, +112, +219, +65, -237, - +4535, +5212, +1390, +1740, +598, +607, +776, -814, -1908, -1025, +1099, +545, -214, -426, -239, +239, +413, +193, +207, +182, -47, +183, -57, -40, -30, -175, -148, +40, +73, +37, +118, +7, - +5318, +5785, +1269, +1968, +575, +658, +805, -1127, -2442, -1307, +1372, +466, -591, -725, -443, +119, +395, +164, +270, +354, -56, +110, -69, -55, -25, -139, -51, +109, +11, +15, +19, -56, - +6436, +6460, +882, +2236, +497, +666, +802, -1573, -2941, -1397, +1743, +286, -941, -976, -603, -18, +243, -4, +204, +282, -184, +170, -29, -57, -91, -187, -111, +112, +41, +27, +68, -96, - +7585, +7281, +373, +2458, +491, +542, +790, -2104, -3319, -1286, +2043, +126, -1200, -1227, -664, -50, +85, -70, +93, +172, -322, +133, -69, -86, -185, -297, -168, +53, +66, +96, +196, +7, - +8554, +8204, +13, +2518, +545, +433, +808, -2585, -3651, -1161, +2167, +23, -1301, -1412, -719, -73, +18, -111, +45, +202, -388, -7, -242, -122, -287, -383, -162, +38, +78, +115, +239, -27, - +9212, +9220, +103, +2448, +407, +223, +921, -2981, -3805, -1200, +1719, +26, -1055, -1626, -929, -188, +43, +226, -94, +18, -406, -89, -400, -275, -396, -440, -171, +13, +140, +43, +175, -97, - +9425, +9997, +611, +2554, +412, -263, +952, -2951, -3684, -1187, +857, -167, -621, -1410, -1053, -347, -65, +452, -3, -165, -453, -143, -340, -269, -451, -441, -242, -198, +101, +82, +181, -110, - +9602, +10483, +1219, +2947, +590, -759, +563, -2991, -3446, -797, -98, -815, -218, -921, -768, -633, -444, +563, +104, -246, -350, -155, -369, -240, -521, -488, -298, -401, -10, +50, +144, -115, - +9910, +10681, +1487, +3547, +923, -1024, +61, -3330, -3146, -137, -870, -1590, +8, -449, -298, -772, -939, +485, +312, -243, -240, -78, -399, -324, -669, -567, -332, -547, -156, +25, +160, -93, - +10699, +10561, +1144, +4345, +1148, -1198, -465, -3692, -2804, +756, -1507, -2809, +121, -169, +369, -651, -1433, +435, +473, -418, -220, +23, -526, -346, -932, -715, -318, -648, -289, -5, +58, -250, - +11865, +10458, +321, +5013, +1084, -1187, -415, -4235, -2391, +1999, -1758, -4266, -88, +147, +902, -193, -1705, +234, +619, -537, -297, +92, -743, -384, -1023, -815, -255, -684, -426, -12, +35, -330, - +13346, +11005, -1112, +4810, +949, -1079, +138, -4587, -2456, +3025, -1295, -5300, -712, +202, +1270, +293, -1889, -46, +762, -642, -552, +226, -817, -466, -1180, -995, -171, -630, -552, -62, +74, -399, - +14971, +12208, -3034, +3816, +594, -863, +1619, -4784, -3319, +3684, -109, -5706, -1550, +27, +1400, +652, -2108, -458, +869, -483, -776, +220, -858, -433, -1201, -1254, -117, -550, -640, -140, +204, -318, - +16995, +12596, -4875, +3443, -244, -334, +2668, -5173, -3649, +4366, +1153, -6044, -2514, -559, +1728, +927, -2652, -901, +1093, -410, -1143, +329, -841, -335, -1196, -1458, -195, -525, -564, -33, +194, -462, - +18241, +12894, -5826, +3138, -1130, +187, +3380, -5255, -4143, +4561, +2499, -6195, -3183, -1309, +1509, +1233, -2676, -1266, +894, -425, -1299, +432, -922, -204, -1176, -1686, -183, -313, -482, -86, +105, -535, - +19257, +13367, -6379, +2592, -1984, +792, +4070, -5179, -4919, +4384, +3882, -5784, -3709, -2594, +1250, +1947, -2577, -1645, +617, -476, -1302, +491, -1070, -197, -1169, -1676, -76, -162, -446, -100, +47, -614, - +19926, +13767, -6244, +2039, -2577, +1096, +4300, -4713, -5817, +3943, +5112, -5041, -4213, -3795, +981, +2627, -2147, -2070, +431, -519, -1281, +436, -1355, -148, -989, -1627, -104, -51, -433, -15, -50, -735, - +20240, +14125, -5799, +1784, -3007, +1064, +4265, -4313, -6590, +3386, +5836, -3972, -4474, -4840, +741, +2976, -1373, -2410, +167, -416, -1413, +247, -1435, -24, -966, -1480, -291, -55, -313, -65, -145, -781, - +20015, +14601, -5023, +1828, -3407, +908, +4058, -4144, -7140, +2450, +6274, -2630, -4153, -5964, +216, +3298, -453, -2534, -345, -178, -1641, +157, -1311, +64, -954, -1504, -457, -98, -260, -285, -55, -762, - +19554, +14863, -3770, +2150, -3733, +724, +3709, -4072, -7621, +1495, +6312, -1303, -3056, -6981, -603, +3594, +321, -2274, -920, -58, -1568, +72, -1120, +198, -1037, -1588, -525, -300, -179, -434, +24, -584, - +18917, +14814, -2183, +2351, -3715, +455, +3162, -3571, -8351, +569, +5938, -361, -1346, -7547, -1834, +3783, +700, -1769, -1070, -238, -1132, -62, -1211, +391, -1003, -1782, -585, -567, -111, -272, +77, -349, - +18106, +14727, -945, +2225, -3047, +302, +2302, -2969, -8873, -290, +5489, -62, +243, -7348, -3434, +3665, +911, -1246, -777, -513, -915, -51, -1324, +362, -1049, -1967, -506, -762, +16, -24, +82, -173, - +17254, +13805, +460, +2982, -2958, +154, +1644, -2479, -8779, -1643, +5145, +181, +1378, -6455, -5404, +3105, +1393, -741, -423, -612, -704, -72, -1484, +78, -955, -2125, -465, -626, +16, +278, +142, -257, - +16265, +13474, +690, +3849, -2566, -357, +1746, -2519, -8172, -2680, +5031, +100, +1311, -4691, -6912, +1980, +2040, -358, -216, -622, -649, +103, -1622, -626, -497, -1964, -571, -423, -30, +370, +49, -249, - +15646, +13159, +261, +4311, -1678, -1288, +1621, -1987, -7004, -3335, +4543, -14, +302, -2477, -7170, -48, +2406, +32, +137, -377, -773, -133, -1665, -841, -152, -1691, -589, -158, -270, +328, +50, -306, - +14914, +12999, -328, +4365, -702, -1133, +553, -2016, -4671, -4043, +4026, +360, -1378, -617, -6226, -2166, +2377, +298, -4, +327, -691, -899, -1434, -845, +201, -1106, -1032, -122, -210, +203, +45, -267, - +13958, +12124, -373, +4782, +21, -1129, +272, -2320, -3404, -3627, +3139, +1060, -2160, -3, -4519, -3752, +1820, +541, -476, +570, -311, -1038, -1434, -687, +457, -671, -1457, -167, -11, +62, +118, -218, - +12918, +10973, -67, +5240, +257, -1386, +443, -1503, -3392, -3835, +2924, +1581, -2328, -20, -2956, -4208, +1045, +694, -894, +202, -292, -645, -959, -841, +200, -409, -1380, -60, +24, -53, +228, -310, - +11453, +9857, +558, +5625, +370, -1608, +838, -661, -3107, -4122, +1928, +2028, -1762, -127, -1944, -4054, +595, +740, -1213, -166, -505, -568, -347, -773, -312, -278, -974, +83, +83, -136, +142, -319, - +11087, +8602, +495, +7107, +58, -2371, +1638, +267, -3072, -4860, +1382, +2390, -1510, +558, -1623, -4806, +939, +963, -1665, -194, -913, -908, -115, -747, -101, -144, -1056, +521, +304, -293, -8, -330, - +9334, +8472, +2057, +6324, -243, -2522, +1386, -290, -2159, -3680, -245, +1661, -676, +956, -788, -4263, -533, +965, -282, -154, -1031, -742, -56, -400, -21, -215, -885, +31, +223, -288, -38, -168, - +8202, +7850, +2127, +5711, +161, -1682, +1271, -489, -1744, -3323, -499, +1254, -540, +771, -297, -3344, -963, +1117, -26, -591, -845, -454, -64, -490, -350, -197, -438, -86, -170, -321, +106, -106, - +7291, +7027, +2168, +4730, +564, -540, +844, -580, -1481, -2901, -474, +853, -365, +616, -57, -2666, -805, +1195, -67, -613, -593, -252, -128, -623, -577, -254, -297, -288, -279, -138, +171, -54, - +6561, +6470, +2014, +3851, +1081, +55, +479, -597, -1428, -2456, -448, +615, -253, +562, +94, -2318, -595, +1226, -130, -587, -411, -244, -197, -635, -712, -320, -371, -307, -113, -95, +84, -14, - +5624, +5918, +1762, +3266, +1692, +206, +288, -499, -1267, -1883, -464, +389, +31, +706, +63, -1900, -243, +1098, -142, -584, -335, -87, -244, -648, -669, -209, -339, -372, -24, +17, +83, -55, - +4953, +5180, +1625, +3144, +1769, +106, +214, -394, -1053, -1453, -538, +193, +277, +807, +43, -1499, -93, +748, -239, -450, -232, -115, -285, -525, -481, -91, -398, -447, -39, +45, +83, -112, - +4115, +4607, +1619, +2888, +1682, +161, +244, -329, -812, -1141, -599, +67, +593, +924, +29, -1137, -210, +449, -129, -365, -249, -133, -121, -277, -340, -178, -530, -428, -2, -6, +39, -84, - +3177, +4024, +1786, +2341, +1485, +534, +375, -316, -681, -795, -329, +287, +817, +880, +57, -781, -190, +258, -112, -286, -153, +95, +56, -236, -403, -237, -370, -335, -19, -47, -2, +10, - +2412, +3137, +2012, +2211, +1367, +699, +342, -131, -395, -414, -56, +329, +935, +975, +138, -528, -171, +55, -126, -152, +41, +119, -74, -171, -229, -182, -327, -290, -76, -28, +10, -11, - +1837, +2561, +1897, +1806, +1200, +798, +563, +60, +7, +156, +349, +604, +923, +1022, +216, -431, -239, -64, +75, +24, -47, +67, +76, -40, -176, -179, -231, -224, -40, +27, +0, -75, - +1620, +2181, +1603, +1392, +1074, +916, +849, +620, +322, +470, +694, +763, +907, +764, +43, -376, -76, +71, +101, -3, -39, +86, +110, +0, -148, -121, -113, -69, +18, +9, -117, -268, - +1298, +1691, +1267, +1399, +1307, +1124, +1131, +1104, +891, +667, +567, +575, +628, +507, +105, -108, +52, +24, -45, -25, -34, +55, +160, +131, -29, -57, -79, -54, -16, -156, -247, -286, - +1179, +1848, +1466, +1730, +1760, +1293, +1046, +857, +729, +698, +565, +381, +236, +320, +318, +91, +9, -97, -187, -79, +91, +171, +186, +225, +142, -75, -156, -189, -210, -232, -263, -201, - +1352, +2405, +2052, +1820, +1528, +1334, +1064, +583, +298, +292, +336, +420, +473, +384, +247, -41, -172, -129, -4, +7, +46, +224, +188, +178, +173, -32, -241, -326, -370, -251, -162, -160, - +1579, +2518, +2005, +1719, +1482, +1383, +1139, +573, +88, -86, +163, +548, +481, +335, +281, +88, +49, -30, -101, -73, +80, +110, +12, +172, +343, +170, -228, -430, -393, -298, -216, -120, - +1583, +2450, +1680, +1499, +1447, +1389, +1184, +570, +27, +164, +464, +283, +128, +199, +220, +325, +423, +123, -72, -74, -43, -22, -19, +72, +115, +277, +185, -229, -439, -410, -283, -162, - +1893, +2685, +1508, +1157, +986, +1135, +1120, +583, -124, +57, +765, +643, +287, -137, -232, +275, +511, +407, +350, +8, -96, +73, -79, -165, +36, +100, +98, +172, -6, -229, -385, -374, - +2209, +3190, +1517, +1044, +774, +938, +848, +161, -496, -290, +950, +973, +315, -37, -73, +18, +254, +388, +315, +238, +180, +91, -63, -33, -110, -192, -12, +129, +232, +155, -164, -407, - +2814, +3765, +1508, +1224, +774, +836, +645, -346, -1219, -800, +1084, +985, +184, +33, +8, +229, +466, +169, +87, +354, +189, +192, +160, -56, +4, -65, -184, -15, +177, +366, +142, -203, - +3495, +4412, +1460, +1383, +688, +753, +615, -665, -1708, -1197, +1222, +875, -213, -223, -72, +363, +610, +259, +273, +267, +37, +270, +44, +9, +100, -45, -90, +149, +122, +13, +149, +90, - +4347, +4935, +1271, +1660, +643, +828, +646, -1007, -2278, -1449, +1567, +759, -633, -516, -277, +238, +622, +239, +355, +523, +20, +141, +46, -6, +111, -2, +46, +213, +21, +33, +1, +6, - +5621, +5545, +799, +2031, +504, +892, +652, -1492, -2860, -1584, +2032, +530, -1030, -782, -469, +89, +432, +59, +340, +429, -61, +279, +83, -74, +47, +39, -51, +241, +56, -19, +59, -78, - +6893, +6162, +149, +2382, +396, +828, +623, -2048, -3200, -1408, +2392, +211, -1344, -961, -526, -16, +350, -90, +203, +396, -312, +253, +114, +45, -53, -188, -37, +217, +87, +120, +108, -66, - +8235, +7080, -573, +2693, +417, +618, +659, -2697, -3569, -1230, +2683, +76, -1575, -1280, -539, +24, +87, -57, +104, +215, -351, +233, +5, -119, -156, -194, -147, +124, +129, +137, +322, +117, - +9244, +7992, -1030, +2743, +479, +517, +696, -3209, -3857, -1043, +2739, -57, -1623, -1427, -588, -20, +90, -120, +74, +343, -449, +31, -200, -78, -273, -310, -78, +136, +134, +157, +303, -20, - +10028, +9088, -1078, +2631, +294, +324, +855, -3729, -3984, -1086, +2220, +48, -1346, -1774, -793, -139, +148, +326, -185, +119, -427, -45, -395, -273, -382, -360, -77, +135, +222, +28, +223, -85, - +10294, +10035, -677, +2629, +250, -196, +1099, -3767, -3909, -1145, +1327, -1, -804, -1656, -1142, -169, +106, +562, -120, -57, -462, -169, -331, -270, -431, -351, -156, -128, +239, +131, +252, -134, - +10483, +10682, -44, +2812, +332, -824, +879, -3596, -3635, -1021, +145, -213, -350, -1319, -899, -635, -133, +919, -37, -375, -472, -69, -227, -286, -527, -354, -246, -281, +155, +54, +190, -76, - +10698, +11090, +572, +3361, +554, -1371, +356, -3757, -3360, -322, -956, -1204, +285, -664, -624, -896, -670, +916, +86, -272, -203, -223, -395, -193, -602, -435, -271, -578, +42, +87, +178, -136, - +11106, +11176, +704, +4050, +883, -1630, -180, -4140, -2927, +390, -1871, -1878, +528, -231, -70, -1098, -1213, +889, +383, -352, -139, -56, -382, -365, -792, -502, -300, -681, -116, +59, +212, -78, - +12036, +10896, +310, +5032, +1033, -1870, -823, -4447, -2503, +1349, -2741, -3214, +855, +29, +682, -1055, -1808, +920, +555, -599, -93, +53, -545, -351, -1135, -651, -258, -802, -256, +44, +72, -285, - +13249, +10533, -420, +6055, +876, -1900, -821, -5027, -1957, +2680, -3299, -4856, +928, +484, +1323, -695, -2251, +831, +740, -767, -47, +126, -881, -350, -1161, -698, -223, -889, -359, +46, +17, -320, - +14864, +10460, -1804, +6568, +665, -1731, -635, -5767, -1405, +4093, -3512, -6402, +622, +675, +1688, -26, -2440, +393, +956, -897, -408, +254, -945, -393, -1446, -932, -12, -855, -629, +79, +67, -544, - +16627, +11397, -3842, +5964, +612, -1624, +440, -5965, -2042, +5011, -2485, -7307, -214, +766, +2141, +296, -2808, +260, +1140, -1052, -587, +505, -1093, -517, -1488, -1064, +12, -788, -651, -39, +118, -479, - +18518, +12633, -6334, +4990, +229, -1244, +2367, -6506, -3133, +5859, -1129, -7799, -1129, +600, +2173, +719, -3075, -318, +1316, -740, -910, +425, -1093, -394, -1508, -1432, +145, -700, -804, -94, +327, -401, - +20973, +12619, -8500, +4951, -770, -461, +3392, -7134, -3315, +6719, +196, -8369, -2213, +3, +2743, +961, -3843, -722, +1691, -730, -1369, +644, -1082, -293, -1519, -1634, +52, -689, -686, +59, +271, -608, - +22297, +12836, -9690, +4807, -1655, +104, +4092, -7312, -3771, +7038, +1693, -8910, -3012, -482, +2558, +1188, -3919, -1129, +1548, -693, -1611, +794, -1184, -115, -1465, -1976, +34, -436, -598, -24, +171, -683, - +23980, +12855, -10608, +4407, -2867, +1228, +4914, -7539, -4560, +7253, +3208, -8777, -3558, -1999, +2512, +1964, -3980, -1552, +1290, -765, -1611, +896, -1300, -1, -1603, -2008, +250, -237, -601, -60, +99, -743, - +24531, +13684, -11034, +3704, -3405, +1665, +5463, -7291, -5568, +6806, +4893, -8341, -4325, -3233, +2310, +2880, -3885, -2013, +1022, -727, -1606, +925, -1552, -68, -1433, -1949, +261, -130, -552, -62, +43, -848, - +25399, +13806, -10659, +3086, -4032, +2086, +5508, -6663, -6694, +6473, +6232, -7551, -4944, -4555, +2202, +3628, -3339, -2592, +933, -785, -1566, +810, -1901, +111, -1220, -1934, +196, +16, -580, +86, -113, -983, - +25699, +14205, -10203, +2771, -4453, +2044, +5466, -6220, -7611, +5940, +7067, -6399, -5381, -5665, +2085, +3997, -2469, -3078, +674, -608, -1758, +594, -1930, +265, -1252, -1733, -62, +13, -409, -15, -218, -1005, - +25576, +14678, -9511, +2627, -4889, +1979, +5231, -5940, -8313, +5036, +7731, -5018, -5437, -6902, +1757, +4371, -1482, -3465, +202, -277, -2109, +514, -1803, +302, -1201, -1716, -327, +65, -365, -277, -95, -1022, - +24917, +15555, -8325, +2832, -5406, +1692, +5071, -5894, -8820, +3797, +8250, -3317, -4558, -8452, +986, +4981, -445, -3381, -624, +98, -2239, +474, -1567, +517, -1341, -1880, -275, -194, -234, -524, +73, -946, - +24560, +15279, -6686, +3008, -5680, +1683, +4433, -5659, -9447, +3055, +7994, -2069, -3264, -9450, +188, +5223, +139, -3059, -1138, +123, -1936, +284, -1347, +532, -1421, -1864, -486, -372, -126, -624, +111, -613, - +23630, +15485, -4781, +2918, -5523, +1209, +3879, -4787, -10506, +1989, +7668, -1020, -1165, -10262, -1408, +5686, +432, -2423, -1223, -173, -1294, +57, -1598, +885, -1360, -2222, -434, -735, -7, -301, +148, -390, - +22705, +15510, -3489, +2520, -4580, +974, +2845, -3997, -11138, +1148, +7254, -749, +544, -10123, -3273, +5720, +656, -1873, -901, -539, -1078, +82, -1698, +797, -1433, -2392, -307, -961, +186, -54, +102, -179, - +21833, +14435, -1480, +2989, -4502, +876, +1865, -3114, -11297, -386, +7023, -399, +2038, -9446, -5658, +5465, +1168, -1290, -470, -782, -783, -20, -1877, +659, -1411, -2696, -156, -783, +130, +317, +217, -316, - +20537, +13992, -708, +4279, -4744, +442, +1972, -3237, -10625, -1985, +6923, -199, +2505, -7991, -7936, +4778, +2128, -1048, -448, -664, -657, +84, -2053, -179, -858, -2526, -357, -737, +238, +571, -51, -298, - +19638, +14025, -1030, +4778, -3659, -452, +2274, -3224, -9891, -2808, +7103, -662, +1734, -5223, -9487, +3226, +2912, -583, -44, -906, -673, +388, -2239, -882, -152, -2483, -417, -219, -101, +496, +27, -274, - +19049, +13570, -1555, +5415, -2800, -1809, +2085, -2243, -8328, -3763, +6265, -489, +380, -2622, -9535, +545, +3560, -254, +273, -392, -940, -193, -2156, -847, +103, -2093, -472, -40, -391, +519, -11, -393, - +18168, +13590, -2249, +5443, -1644, -1455, +603, -2301, -5416, -4970, +5891, +62, -1742, -291, -8568, -1959, +3759, +29, -30, +506, -899, -1149, -1711, -913, +543, -1423, -1173, +54, -259, +333, +11, -312, - +17035, +12827, -2281, +5894, -726, -1489, +185, -2933, -3444, -4639, +4541, +1190, -2977, +751, -6689, -4331, +3534, +367, -666, +1029, -430, -1560, -1739, -617, +856, -909, -1806, +43, +2, +135, +104, -229, - +16109, +11603, -1857, +6452, -517, -1810, +245, -2043, -3755, -4481, +4547, +1368, -3096, +727, -4933, -5160, +2492, +733, -1012, +720, -307, -1028, -1535, -868, +957, -652, -2015, +138, +117, -22, +249, -321, - +14557, +10522, -1242, +6803, -315, -2135, +723, -1118, -3548, -5279, +4014, +2629, -3572, +779, -3115, -5769, +2018, +890, -1739, +290, -311, -714, -642, -1091, +163, -204, -1599, +276, +13, -124, +387, -488, - +12812, +9467, -224, +7139, -314, -2365, +1207, -230, -3341, -5355, +2557, +2879, -2315, +419, -2362, -5322, +1454, +982, -1883, -47, -628, -728, -93, -958, -294, -130, -1142, +362, +163, -228, +155, -376, - +13067, +8369, -144, +8730, -2405, -3459, +1450, -1502, -5332, -4279, +6473, +1714, -1900, +3709, -1903, -4707, +1918, +120, -2550, -1093, -1848, -621, -724, -1598, -147, -744, -877, +540, -151, -509, +318, -28, - +10904, +8241, +866, +7747, -891, -4073, +130, -1350, -3923, -2891, +4427, +2115, -885, +2373, -1299, -4343, +153, +77, -1658, -317, -1588, -605, +53, -1825, -85, -335, -1528, -11, -42, -273, +59, -76, - +9279, +7452, +1520, +7064, -405, -3081, +178, -1385, -2926, -2332, +3123, +1898, -776, +1781, -925, -3718, -102, -120, -1233, -82, -1199, -290, +2, -1550, -49, -380, -1428, -264, -245, -270, +11, -162, - +7668, +6712, +2160, +6267, +54, -2125, +134, -1110, -2049, -2036, +2189, +1460, -699, +1339, -688, -3011, -497, -119, -970, -142, -497, +186, +37, -1292, -184, -526, -1267, -503, -546, -437, +10, -9, - +6368, +6134, +2492, +5439, +623, -1515, +73, -449, -1505, -1848, +1544, +1044, -644, +955, -348, -2562, -737, -6, -786, +148, +175, +380, -63, -1068, -366, -637, -1119, -714, -616, -443, -44, +1, - +5309, +5691, +2463, +4700, +1132, -1190, +301, +59, -1194, -1566, +901, +654, -559, +719, -197, -2168, -766, +93, -248, +496, +263, +194, -53, -903, -530, -692, -1037, -585, -576, -463, -126, -99, - +4671, +5240, +2273, +4089, +1224, -820, +599, +183, -902, -1333, +289, +350, -412, +640, -190, -1832, -504, +307, +145, +562, +47, +10, -140, -891, -579, -467, -751, -658, -629, -412, -121, -71, - +4304, +4612, +2145, +3630, +1141, -235, +799, +247, -609, -1181, -104, +233, -152, +634, +32, -1399, -325, +524, +389, +368, -139, -41, -258, -648, -199, -313, -764, -659, -480, -282, -35, +38, - +3883, +4121, +1999, +3085, +1218, +245, +812, +308, -391, -1122, -309, +165, +293, +913, +46, -1198, -224, +714, +439, +55, -298, +56, +12, -400, -192, -282, -674, -589, -276, -72, +113, +77, - +3262, +3880, +1810, +2399, +1483, +674, +763, +273, -288, -1047, -181, +700, +489, +675, +71, -953, -158, +742, +296, -120, -45, +156, +92, -270, -319, -271, -421, -326, -57, +99, -64, -314, - +2385, +3308, +1933, +2191, +1681, +725, +640, +373, +136, -286, -143, +637, +683, +410, +103, -565, -257, +619, +421, -40, +28, +179, +55, -233, -135, -54, -204, -72, -29, -217, -320, -330, - +1874, +3072, +1941, +1419, +1419, +1279, +891, +484, +398, +297, +230, +463, +469, +136, +85, -228, -107, +538, +410, +40, -27, +98, +145, +77, +20, +54, +21, -272, -370, -309, -248, -206, - +1591, +2376, +1629, +1368, +1569, +1437, +1231, +1006, +583, +432, +297, +204, +299, +145, -140, +13, +312, +339, +220, +17, +14, +285, +382, +203, +101, -101, -334, -332, -302, -287, -184, -195, - +1470, +1787, +1502, +1987, +1911, +1545, +1043, +878, +865, +431, +197, +86, +12, +101, +92, +101, +251, +178, +190, +346, +300, +250, +251, +133, -107, -287, -400, -336, -238, -260, -239, -257, - +1914, +2455, +1662, +1958, +1844, +1522, +942, +380, +248, +262, +332, +128, +22, +126, +219, +6, -12, +304, +516, +586, +402, +88, -170, -256, -295, -306, -261, -267, -279, -273, -326, -327, - +1650, +2454, +1992, +2081, +1838, +1445, +722, +274, +244, +203, +344, +372, +259, +83, -81, -61, +209, +336, +515, +666, +466, +145, -229, -453, -374, -308, -238, -216, -280, -231, -312, -373, - +1972, +2726, +1615, +1875, +1444, +1065, +882, +237, +52, +429, +512, +299, +333, -155, -232, +94, +178, +234, +473, +659, +391, +136, -262, -514, -398, -381, -424, -222, -224, -324, -266, -374, - +1944, +2569, +1405, +1599, +1309, +1157, +866, +373, +250, +451, +528, +453, +471, +1, +55, +191, +129, +155, +283, +436, +597, +713, +68, -320, -396, -509, -294, -216, -242, -220, -186, -273, - +2213, +2847, +1259, +1256, +996, +980, +849, +260, -32, +445, +818, +478, +247, +265, +193, +76, +464, +202, +102, +347, +222, +450, +618, +397, -308, -565, -442, -327, -186, -168, -163, -249, - +2697, +3456, +1227, +1213, +572, +517, +850, +102, -387, +192, +924, +490, +415, +251, -28, +334, +487, +237, +455, +306, -44, +361, +407, +349, +369, -96, -484, -382, -224, -207, -148, -176, - +3120, +3716, +1221, +1448, +755, +624, +603, -564, -1136, +136, +1257, +246, +285, +171, -38, +383, +232, +372, +711, +324, +99, +204, -9, +285, +321, +68, +177, -36, -413, -443, -150, -173, - +3790, +4330, +1096, +1569, +784, +588, +463, -1059, -1653, +106, +1501, +73, -126, -239, -105, +460, +435, +368, +402, +389, +91, +309, +250, +37, -30, -24, +199, +248, +66, -210, -381, -373, - +4622, +5180, +929, +1541, +623, +502, +584, -1498, -2233, +215, +1742, -187, -310, -505, -413, +362, +388, +344, +575, +292, -268, +436, +270, +95, +161, -323, -90, +279, +151, -2, +128, -96, - +5681, +5925, +575, +1587, +609, +492, +477, -2071, -2626, +569, +1878, -446, -437, -854, -523, +332, +170, +294, +523, +68, -219, +380, -38, +251, +114, -335, +23, -101, -23, +248, +375, +75, - +6767, +6666, +205, +1705, +662, +498, +302, -2825, -2958, +1150, +2042, -710, -533, -1232, -642, +377, +122, +237, +348, -95, -351, +388, -30, +5, -60, -377, -119, +125, +76, -40, +330, +247, - +7914, +7510, -124, +1761, +488, +420, +174, -3558, -3104, +1640, +2028, -832, -567, -1607, -766, +361, +95, +311, +212, -352, -461, +375, -113, -24, -351, -633, -128, +128, +9, -5, +457, +80, - +8830, +8494, -246, +1750, +304, +130, +113, -4143, -3165, +1945, +1825, -857, -549, -1777, -958, +191, +133, +387, +88, -480, -608, +386, -265, -246, -302, -723, -280, -84, -50, +74, +350, +96, - +9314, +9665, +71, +1635, +346, -372, -34, -4328, -3176, +2030, +1536, -817, -547, -1732, -1016, -133, +66, +591, +24, -506, -733, +116, -40, -327, -495, -730, -460, +25, -137, -166, +374, -5, - +9168, +10764, +1097, +1383, +468, -796, -470, -4274, -3169, +1769, +1273, -725, -691, -1625, -1027, -452, -36, +630, +83, -652, -832, +127, -43, -349, -695, -737, -514, -168, -181, -314, +338, +138, - +8846, +11350, +2560, +1552, +433, -953, -869, -4243, -3192, +1361, +998, -476, -837, -1626, -886, -800, -125, +635, -124, -228, -816, -255, -7, -394, -552, -761, -755, -414, -246, -133, +444, +75, - +8964, +11306, +3527, +2438, +253, -982, -961, -4230, -3082, +755, +442, -71, -869, -1742, -700, -1038, -454, +793, +25, -389, -604, -243, +7, -464, -738, -765, -951, -330, -59, -171, +251, +95, - +9403, +11033, +3733, +3695, +308, -1271, -992, -4163, -2722, +92, -735, +217, -696, -1699, -422, -1673, -402, +984, -229, -198, -530, -373, +28, -463, -956, -681, -906, -518, -289, -162, +497, +102, - +10184, +10713, +3388, +4822, +577, -1450, -980, -3974, -2096, -266, -2455, +170, -229, -2033, +139, -1657, -867, +1176, -218, -154, -435, -585, +36, -392, -1039, -506, -950, -753, -269, -164, +336, -63, - +11469, +10305, +2546, +5881, +499, -1455, -857, -3843, -1101, -509, -4401, -50, +59, -2342, +782, -1732, -924, +1406, -569, -258, -144, -530, -49, -395, -1238, -446, -756, -782, -536, -315, +337, -105, - +12812, +9997, +1333, +7068, +255, -1649, -308, -3676, +7, -196, -6478, -1003, +993, -2770, +1003, -1205, -1230, +1463, -713, -345, +195, -392, -236, -389, -1244, -431, -777, -964, -608, -183, +371, -471, - +14298, +10024, -465, +8212, +114, -2512, +382, -3674, +1378, +663, -8685, -2459, +1859, -2562, +871, -988, -1367, +1466, -684, -580, +254, -110, -241, -347, -1398, -758, -715, -816, -729, -361, +154, -579, - +15791, +10811, -2667, +8435, +624, -3271, +1069, -3748, +2502, +2079, -10027, -4329, +2301, -1901, +666, -578, -1480, +1296, -627, -770, +123, +401, -53, -652, -1473, -822, -551, -788, -1234, -414, +540, -655, - +17964, +11856, -5206, +7310, +1001, -3366, +1912, -4139, +2658, +3650, -10394, -6002, +1938, -1051, +777, -287, -1664, +896, -566, -1001, +87, +651, -41, -918, -1419, -920, -813, -755, -1256, -323, +672, -811, - +20009, +12521, -7253, +6282, +961, -3398, +2583, -4837, +2731, +5771, -10940, -7407, +1508, -472, +1186, -388, -1734, +332, -519, -1043, -71, +553, -29, -952, -1661, -1165, -989, -425, -1171, -377, +657, -839, - +22177, +13864, -9457, +4361, +273, -2050, +3806, -6178, +2512, +7329, -10722, -7725, +990, -611, +1552, -139, -1889, -63, -466, -1163, -297, +596, -38, -1172, -1902, -1306, -955, -76, -1070, -458, +771, -742, - +24345, +14808, -11064, +2917, -761, -281, +4365, -7368, +2909, +8263, -9604, -7789, +243, -1094, +2044, +574, -2131, -536, -396, -1094, -498, +632, -243, -1137, -1962, -1496, -848, +190, -940, -375, +1054, -832, - +26147, +15550, -12303, +1685, -1810, +967, +4288, -7960, +2974, +9042, -8220, -8190, -317, -1893, +2641, +1163, -2716, -789, -273, -1142, -847, +531, -446, -868, -2137, -1852, -734, +364, -774, -243, +1065, -1025, - +27659, +16152, -13062, +755, -2711, +1616, +4052, -7901, +2526, +9678, -6491, -8602, -661, -2830, +3049, +1720, -3198, -833, -91, -1450, -1161, +618, -586, -618, -2344, -2144, -611, +510, -566, -204, +872, -1008, - +28303, +17220, -13451, +40, -3448, +1563, +3863, -7612, +1462, +10219, -4267, -9081, -1078, -3763, +2992, +2435, -3478, -882, -13, -1844, -1413, +823, -875, -471, -2328, -2410, -559, +601, -471, -315, +732, -991, - +29181, +17405, -13114, -304, -4240, +1458, +3452, -7492, +539, +10765, -2404, -8991, -1702, -4595, +2982, +2817, -3292, -1057, +74, -2172, -1478, +872, -1165, -289, -2195, -2469, -548, +634, -663, -287, +578, -1042, - +29321, +17827, -12348, -557, -5122, +1071, +3363, -7877, -467, +11248, -887, -8472, -2373, -5291, +2598, +3058, -2743, -1532, +107, -2142, -1752, +699, -1290, -111, -1997, -2388, -740, +468, -816, -385, +487, -985, - +28805, +18575, -11075, -519, -6256, +621, +3883, -8757, -1416, +11447, +404, -7310, -2751, -5966, +1821, +3238, -1902, -1967, -52, -1838, -2084, +568, -1247, +63, -1562, -2577, -1051, +401, -1056, -280, +613, -1053, - +27710, +19425, -9278, -279, -7398, +89, +4632, -9740, -2488, +11491, +1418, -5692, -2452, -7072, +956, +3436, -1270, -1977, -465, -1644, -2124, +549, -1018, +267, -1537, -2600, -1365, +17, -689, -160, +642, -1022, - +26524, +19729, -7061, +31, -8340, -267, +5003, -10177, -3987, +11429, +2435, -4362, -1321, -8478, +66, +3718, -1132, -1735, -895, -1806, -1690, +886, -1190, +400, -1479, -2883, -1377, -121, -394, -59, +689, -900, - +24731, +20271, -4631, +239, -8724, -1229, +4844, -9185, -6220, +10730, +4243, -3815, +672, -9539, -1506, +4100, -1430, -1335, -947, -2166, -1162, +1047, -1494, +767, -1758, -3042, -837, -474, -154, +165, +571, -941, - +23477, +19815, -2244, +479, -9027, -1898, +3618, -7399, -7878, +9201, +6108, -3552, +2583, -9590, -3747, +4198, -1760, -1193, -323, -2539, -1400, +1397, -1635, +542, -1400, -3228, -438, -316, -265, +162, +498, -845, - +22603, +18971, -668, +1272, -8642, -2638, +2333, -6179, -8347, +7433, +7800, -2940, +3459, -8248, -6239, +4034, -1687, -1398, +219, -2550, -1401, +1181, -1707, +569, -817, -3297, +15, -296, -506, +401, +364, -924, - +21958, +18536, -765, +2387, -7488, -4223, +1716, -5274, -8935, +6110, +9409, -2450, +3540, -6393, -8448, +3758, -1179, -2277, +576, -2418, -1529, +1177, -1880, +420, +14, -3051, -213, -188, -381, +229, +231, -793, - +22176, +17185, -1463, +4151, -7417, -5322, +1894, -4670, -9301, +4733, +10404, -1838, +3744, -5092, -9471, +2688, -467, -2307, -46, -2508, -1717, +1645, -1714, +18, +585, -2841, -290, -132, -583, +271, +215, -863, - +21283, +15947, -1061, +5846, -8289, -5644, +2856, -4640, -8855, +2098, +10641, -385, +3529, -2820, -10460, +1131, +531, -2119, -590, -2947, -2184, +2054, -1090, -387, +1198, -3026, -869, +546, -650, +116, +60, -894, - +19683, +14620, -396, +7001, -7790, -5818, +2880, -3841, -8800, -338, +10153, +959, +3167, -585, -10098, -824, +1447, -2278, -872, -2755, -2996, +1653, -697, +272, +1462, -3849, -1195, +1382, -669, -246, -11, -701, - +19043, +12870, -2025, +8715, -5341, -5810, +2282, -4136, -8408, -1971, +10181, +1931, +1229, +1395, -8274, -2327, +1832, -1907, -1520, -2677, -3203, +831, -255, +370, +1503, -3747, -1696, +1786, -499, -464, -64, -480, - +17772, +11494, -1905, +9490, -4457, -5781, +2323, -3030, -7953, -3525, +9683, +2138, -957, +3838, -5603, -4565, +2549, -1532, -2419, -1808, -2980, +12, -610, -213, +1746, -2508, -2211, +1172, +20, -342, -24, -448, - +16172, +10332, -1197, +9288, -3999, -4949, +1874, -2282, -7098, -4475, +8985, +1667, -1887, +4717, -3907, -5051, +2520, -1200, -2844, -1330, -2611, -280, -1072, -1112, +1423, -1375, -1811, +550, -258, -177, +416, -403, - +14861, +9191, -894, +9322, -3451, -4203, +1793, -2119, -6076, -4508, +7671, +1778, -2043, +4285, -2907, -4648, +2360, -879, -2603, -1241, -2298, -406, -1008, -1513, +521, -984, -1055, +584, -582, -325, +664, -263, - +15154, +9134, -4908, +9650, +694, -5568, -98, -860, -5127, -4048, +7837, -470, -3638, +3508, -972, -2437, +3394, +805, -1417, +31, -1653, -577, -2362, -2979, -580, -1077, -1684, -192, -259, +22, +565, -429, - +12672, +9048, -2546, +8370, +349, -5006, +73, -1080, -4272, -3672, +5900, +444, -2326, +2893, -1066, -2332, +2479, +666, -949, -82, -1657, -457, -1794, -2452, -454, -1165, -1497, -205, -372, -240, +406, -163, - +10640, +8312, -1031, +7498, +500, -3857, +463, -1057, -3977, -3222, +4691, +603, -1571, +2325, -824, -2114, +1780, +754, -897, -192, -1342, -620, -1307, -1779, -405, -857, -1348, -343, -250, -417, +44, -237, - +8848, +7462, +273, +6812, +521, -2799, +1008, -1064, -3777, -2718, +3754, +821, -1252, +1806, -375, -2145, +1225, +906, -817, -265, -1155, -585, -1036, -1174, -21, -762, -1257, -311, -233, -510, -203, -397, - +7576, +6767, +783, +6094, +949, -1930, +961, -934, -3200, -2533, +3115, +1137, -1365, +1382, -102, -2040, +908, +789, -690, -334, -1018, -480, -555, -707, -43, -640, -1047, -255, -386, -684, -317, -445, - +6758, +6214, +818, +5337, +1627, -1135, +432, -710, -2305, -2322, +2540, +1251, -1296, +892, -62, -1566, +663, +551, -577, -337, -682, -77, -179, -659, -184, -409, -797, -413, -574, -679, -216, -506, - +5676, +5613, +1210, +4774, +1859, -559, +347, -565, -1759, -1969, +1960, +1004, -1099, +525, -53, -1205, +350, +369, -435, -6, -319, -23, -94, -656, -285, -373, -741, -563, -562, -531, -260, -514, - +4838, +5040, +1571, +4251, +1972, -105, +267, -310, -1227, -1573, +1267, +789, -798, +205, +14, -944, +147, +508, -9, +9, -221, +150, -128, -742, -391, -376, -652, -447, -470, -469, -201, -405, - +3971, +4513, +1934, +3945, +1836, +92, +581, -63, -938, -1357, +811, +579, -793, +202, +181, -781, +327, +624, -92, +15, +0, +147, -352, -881, -357, -191, -505, -444, -412, -282, -88, -284, - +3487, +4143, +1924, +3589, +1775, +195, +713, +196, -635, -1287, +387, +393, -687, +361, +568, -535, +98, +502, -1, +100, +31, -150, -611, -593, -111, -190, -456, -382, -216, -81, -181, -553, - +3301, +3728, +1795, +3379, +1523, +332, +960, +396, -543, -1253, +191, +235, -129, +880, +351, -652, +117, +445, +130, +39, -216, -238, -343, -293, -61, -146, -363, -182, -162, -325, -424, -636, - +3158, +3429, +1574, +3069, +1415, +510, +1197, +428, -494, -1109, +222, +719, +168, +681, +275, -640, +81, +477, +19, -67, -36, -85, -122, -162, +45, -5, -361, -356, -380, -419, -409, -428, - +2927, +3070, +1345, +2819, +1417, +712, +1293, +444, -262, -476, +280, +510, +400, +568, +118, -618, -112, +442, +241, +165, -34, -72, +77, +111, +94, -334, -675, -432, -303, -274, -306, -497, - +2770, +2981, +1085, +2080, +1492, +1281, +1415, +707, +136, -480, +296, +711, +259, +268, -123, -614, +243, +742, +216, +47, +81, +319, +285, -194, -408, -500, -506, -280, -185, -330, -423, -456, - +2145, +2721, +1165, +1872, +1627, +1355, +2019, +1188, +250, -296, -84, +490, +282, +67, -115, -178, +405, +756, +354, +121, +267, +315, -30, -468, -422, -383, -385, -212, -269, -357, -406, -427, - +1842, +2681, +1515, +1848, +2108, +1608, +1340, +1172, +512, -174, -238, -168, -13, +491, +474, +113, +382, +613, +415, +165, +91, -47, -298, -384, -349, -382, -402, -278, -199, -319, -431, -344, - +1494, +2675, +2068, +1863, +2114, +2048, +1472, +644, +14, -248, -149, +107, +179, +299, +556, +612, +502, +443, +238, -13, -145, -180, -250, -339, -297, -336, -446, -377, -225, -244, -239, -265, - +1925, +2822, +1707, +2248, +2162, +1532, +1572, +666, -432, -363, +210, +212, +263, +498, +470, +699, +813, +253, -219, -217, -141, -158, -176, -306, -384, -385, -364, -200, -281, -326, -188, -200, - +1895, +2793, +1934, +2045, +1846, +1354, +1196, +799, +59, -3, +248, +165, +197, +407, +651, +831, +698, +67, -242, -221, -251, -169, -144, -186, -354, -464, -369, -235, -233, -217, -227, -253, - +2070, +3085, +1525, +1328, +1530, +1219, +1048, +1205, +562, -2, +387, +198, +130, +544, +658, +484, +722, +457, -348, -457, -175, -78, -253, -223, -258, -370, -406, -378, -222, -139, -199, -290, - +2157, +2952, +1156, +902, +1034, +1185, +1499, +1126, +501, +624, +479, -49, +331, +597, +587, +621, +629, +548, +175, -291, -470, -235, -85, -52, -278, -368, -303, -369, -323, -238, -97, -173, - +2202, +2907, +1140, +947, +996, +914, +968, +769, +506, +769, +808, +471, +171, +297, +838, +683, +510, +567, +580, +137, -151, -326, -508, -27, -10, -284, -285, -236, -358, -292, -161, -179, - +2228, +3053, +1096, +862, +1274, +1155, +755, +13, -357, +880, +1376, +402, +198, +406, +514, +671, +748, +486, +514, +663, +288, -200, -289, -329, -436, -55, -28, -272, -239, -283, -290, -193, - +2611, +3293, +974, +955, +1269, +1230, +755, -497, -748, +618, +1056, +494, +365, +41, +465, +810, +420, +494, +736, +416, +453, +551, -173, -405, -427, -456, -169, -36, -153, -282, -273, -363, - +3071, +3880, +1049, +902, +1063, +1099, +721, -721, -1094, +709, +1109, -47, +104, +119, +412, +545, +413, +580, +520, +543, +532, +362, +329, +140, -499, -431, -240, -372, -190, -30, -169, -356, - +3643, +4399, +965, +972, +1042, +1109, +628, -1277, -1336, +964, +1149, -203, -182, -383, +345, +664, +317, +410, +437, +373, +394, +662, +276, +180, +133, -200, -383, -376, -281, -286, -117, -162, - +4308, +4895, +774, +1151, +1170, +1121, +455, -1795, -1513, +1267, +1131, -396, -245, -566, +93, +375, +376, +540, +286, +94, +297, +541, +252, +439, +34, +129, +201, -368, -356, -264, -280, -354, - +5087, +5494, +565, +1262, +1166, +1002, +246, -2296, -1418, +1649, +899, -695, -391, -688, +139, +229, +44, +521, +312, -3, +101, +250, +192, +280, +43, +280, +150, +88, +29, -357, -310, -372, - +5947, +6051, +327, +1497, +1239, +800, -127, -2807, -1134, +2147, +640, -918, -589, -888, +220, +107, +62, +477, +59, -49, +73, +198, -35, +79, -132, +175, +309, +137, +146, +162, -75, -593, - +6826, +6642, +77, +1786, +1321, +527, -620, -3298, -663, +2560, +320, -1067, -693, -1064, +226, -95, -6, +673, -51, -262, -29, +141, -44, -11, -506, +62, +205, +6, +401, +111, +23, -56, - +7619, +7443, -127, +1929, +1356, +155, -1099, -3708, -137, +2846, -83, -1160, -806, -1101, +269, -385, -138, +769, -105, -266, -156, -64, -45, -101, -607, -105, -82, +19, +101, +44, +338, -87, - +8308, +8291, -181, +1996, +1443, -217, -1606, -4093, +424, +3041, -446, -1225, -972, -1051, +348, -589, -310, +757, -179, -230, -151, -213, -150, -169, -724, -105, -113, -531, +38, +251, +144, +14, - +8643, +9273, +110, +1817, +1665, -587, -2048, -4412, +705, +3223, -686, -1244, -1233, -1013, +428, -696, -381, +630, -323, -238, -129, -251, -193, -373, -663, -295, -481, -278, -3, -42, +123, -69, - +8492, +10281, +986, +1409, +1924, -770, -2443, -4558, +552, +3340, -711, -1234, -1461, -1100, +472, -719, -429, +587, -437, -400, -100, -332, -135, -347, -1076, -422, -280, -435, -79, -23, +2, -146, - +8125, +10926, +2345, +1150, +1899, -669, -2844, -4563, +156, +3228, -595, -1223, -1573, -1303, +463, -750, -482, +579, -448, -544, -287, -237, -139, -775, -987, -370, -466, -463, -189, -20, +78, -37, - +7991, +11060, +3529, +1603, +1541, -533, -3046, -4622, -35, +2877, -564, -1180, -1626, -1431, +402, -852, -505, +583, -405, -609, -263, -542, -401, -426, -1162, -560, -503, -504, -197, +50, +140, -226, - +8113, +10987, +4130, +2562, +1381, -747, -2977, -4641, -186, +2488, -599, -1166, -1769, -1438, +351, -1006, -539, +563, -351, -314, -744, -723, -154, -612, -1117, -726, -662, -455, -57, +40, -92, -256, - +8541, +10760, +4178, +3497, +1698, -1029, -2982, -4222, -351, +1963, -668, -970, -2110, -1515, +400, -1246, -614, +645, -262, -603, -476, -696, -449, -571, -1094, -668, -849, -390, -123, -169, +68, -29, - +9463, +10347, +3864, +4361, +1905, -1015, -3375, -3543, -178, +968, -787, -513, -2341, -1829, +501, -1686, -325, +497, -681, +38, -559, -871, -367, -691, -1137, -482, -872, -677, -284, +7, +225, -241, - +10674, +9874, +3106, +5362, +1727, -766, -3609, -3015, +543, -431, -1222, +153, -2336, -2209, +365, -1836, -554, +242, -426, +197, -633, -802, -399, -696, -1174, -325, -1145, -803, -31, -108, -43, -199, - +11979, +9620, +1869, +6561, +1461, -835, -3245, -2641, +1610, -1691, -2279, +974, -2010, -2575, +505, -2638, -686, +670, -1065, +774, -478, -978, -319, -585, -1119, -498, -1130, -708, -19, -296, -40, -290, - +13201, +9744, +157, +7624, +1518, -1581, -2587, -2110, +2716, -2532, -3960, +1424, -1264, -2535, -109, -3054, -615, +404, -1230, +1095, -263, -1158, -337, -435, -1109, -466, -1189, -812, +84, -300, -171, -443, - +14767, +10074, -1860, +8018, +1956, -2430, -2103, -1372, +3819, -2797, -5967, +1234, +173, -2924, -421, -3162, -1160, +752, -1619, +1210, +95, -1349, -306, -444, -1114, -283, -1142, -1053, +276, -314, -302, -597, - +16745, +11407, -4630, +6674, +3018, -2190, -1545, -1323, +4470, -2021, -7769, +629, +1347, -2958, -574, -3466, -1241, +900, -1709, +1083, +268, -1132, -420, -544, -1164, -33, -940, -1138, +189, -205, -362, -753, - +18725, +12859, -7380, +4619, +4068, -1417, -1079, -1554, +4711, -1055, -8876, -550, +1948, -2355, -915, -3587, -1380, +839, -1610, +894, +413, -1080, -618, -661, -1073, +37, -840, -1169, +44, -15, -345, -1019, - +20617, +14278, -9830, +2481, +4741, -181, -623, -1858, +4753, +25, -9421, -1889, +2095, -1425, -1076, -3758, -1263, +565, -1542, +933, +391, -1113, -672, -722, -1015, -8, -886, -996, +4, +105, -420, -1228, - +22971, +14648, -11936, +1010, +4670, +1158, -431, -2361, +5156, +1040, -10169, -3060, +2153, -790, -797, -4032, -1000, +16, -1618, +1257, +163, -1228, -657, -703, -1282, -23, -913, -801, -89, +33, -392, -1315, - +25010, +15029, -13660, +283, +4193, +2237, -295, -3037, +6357, +2181, -11344, -3815, +2283, -582, +157, -4078, -1205, -374, -1568, +1582, -149, -1216, -484, -731, -1677, +102, -841, -808, -116, +31, -256, -1422, - +26769, +15204, -15115, +212, +3256, +2746, -305, -3981, +8274, +2753, -12585, -4021, +1747, -336, +1272, -4084, -1750, -584, -1463, +1491, -429, -1113, -280, -912, -2029, +54, -759, -856, -175, +86, -304, -1461, - +28266, +15342, -16203, +581, +2138, +2848, -458, -4840, +10385, +2925, -13189, -4103, +831, +88, +2199, -3878, -2349, -502, -1510, +1038, -429, -929, -129, -1132, -2297, -63, -611, -925, -177, +40, -335, -1317, - +29815, +15252, -16897, +1083, +956, +2943, -891, -5377, +12108, +2999, -12962, -4416, +24, +360, +3011, -3485, -2819, -229, -1736, +410, -242, -574, -195, -1310, -2449, -114, -453, -1000, -245, +121, -272, -1376, - +30704, +15809, -17499, +1266, -67, +2973, -1441, -5841, +12884, +3441, -12109, -5095, -636, +265, +3716, -2998, -3240, +129, -2153, -287, -24, -180, -492, -1366, -2616, -99, -271, -1307, -188, +298, -393, -1578, - +31618, +16165, -17687, +1138, -966, +3162, -2242, -6103, +13031, +3994, -10855, -5814, -1132, -114, +4440, -2576, -3472, +441, -2571, -925, +179, +66, -731, -1305, -2901, +118, -240, -1556, +32, +256, -573, -1665, - +32352, +16428, -17457, +790, -1672, +3290, -2962, -6399, +12571, +4836, -9536, -6362, -1498, -662, +5052, -2203, -3513, +550, -2849, -1412, +253, +166, -883, -1139, -3109, +166, -209, -1529, +21, +58, -646, -1719, - +32443, +17279, -16999, +233, -2175, +3032, -2969, -7266, +11609, +6215, -8405, -6559, -1896, -1197, +5401, -1763, -3376, +385, -2990, -1689, +180, +133, -974, -846, -3214, -83, +9, -1520, -177, -60, -770, -1566, - +31892, +18478, -16118, -275, -2655, +2351, -2206, -8781, +10331, +8020, -7513, -6312, -2325, -1753, +5424, -1170, -3047, -34, -3062, -1782, +143, -158, -877, -571, -3280, -291, -54, -1441, -346, -233, -674, -1187, - +30789, +19780, -14759, -548, -3198, +1460, -1025, -10799, +8894, +10055, -6732, -5809, -2497, -2429, +5133, -346, -2659, -573, -3168, -1582, +53, -566, -705, -356, -3272, -629, -135, -1412, -494, -112, -434, -955, - +29203, +20906, -12769, -646, -3914, +632, +128, -12834, +7097, +11981, -5813, -5212, -2227, -3391, +4539, +673, -2372, -1121, -3072, -1520, +50, -953, -749, -83, -3467, -767, -412, -1439, -216, +10, -266, -671, - +27369, +21887, -10304, -719, -4689, +134, +1044, -14260, +4701, +13487, -4266, -4865, -1191, -4653, +3796, +1775, -2279, -1199, -3034, -1527, +71, -1028, -1358, +221, -3301, -1300, -376, -1263, +67, +149, +70, -544, - +25668, +22491, -8130, -702, -4924, -592, +1193, -14383, +1825, +13879, -1753, -4990, +70, -5585, +2485, +3061, -2364, -1028, -2910, -1941, +216, -1133, -2116, +371, -3234, -1474, -105, -1358, +438, +510, +66, -745, - +24445, +22594, -6916, -408, -4078, -1908, +266, -13241, -891, +13193, +1079, -5162, +987, -5936, +931, +4120, -2150, -1025, -2529, -2729, -156, -699, -2958, -77, -2635, -1480, +97, -1388, +718, +673, -84, -802, - +24036, +21606, -6204, +627, -3020, -3027, -1363, -11604, -2945, +12413, +3083, -5038, +1938, -6484, +131, +4636, -1658, -795, -2484, -3507, -351, -682, -3613, +80, -2402, -1272, +354, -1476, +898, +717, -205, -856, - +23746, +20456, -5957, +1984, -1938, -4319, -2729, -9544, -5054, +11531, +5123, -5779, +3222, -6434, -1058, +5531, -1261, -866, -2359, -3656, -1163, -839, -3784, +272, -1846, -1591, +565, -1292, +952, +517, -310, -562, - +23960, +19174, -6448, +3094, -1039, -5368, -3542, -7116, -6317, +9363, +7378, -6843, +3456, -4600, -3042, +6646, -852, -1642, -1443, -3885, -1943, -945, -3873, +318, -958, -2243, +620, -863, +528, +698, -367, -469, - +23567, +18274, -6810, +4250, -385, -6084, -3975, -5591, -6825, +6911, +9455, -6771, +1918, -2142, -4373, +6456, +835, -2708, -1024, -3507, -2457, -992, -4100, +133, -369, -2407, +311, -628, +321, +831, -178, -597, - +23143, +16836, -6902, +5727, -531, -6291, -3459, -5161, -7193, +5338, +10494, -6386, +648, -1274, -4124, +6012, +1743, -2864, -1093, -2840, -2832, -626, -4269, -880, -83, -2116, +209, -691, +146, +839, -37, -502, - +22711, +15714, -7208, +6876, -1112, -6813, -1895, -4170, -8096, +3464, +11809, -6438, -833, +596, -4557, +5103, +2952, -2724, -1144, -2460, -2916, -73, -4033, -2509, -346, -1558, +340, -324, -568, +509, +520, -161, - +21883, +15259, -8430, +8064, -235, -8167, -638, -2887, -8285, +800, +12561, -5050, -2930, +2356, -4439, +2991, +4720, -2205, -1490, -1642, -3457, +613, -3421, -4138, -736, -1237, +241, +437, -924, -343, +1118, +203, - +21336, +14054, -8898, +8815, +778, -8299, -1119, -1073, -7651, -2227, +13016, -3460, -4273, +3243, -3776, +1237, +5044, -803, -1471, -1297, -3268, +457, -2964, -4426, -1137, -1555, +51, +1032, -730, -630, +878, +351, - +20364, +12658, -8776, +9749, +928, -8029, -658, -913, -7055, -3196, +11978, -2563, -4312, +3779, -3422, -39, +4857, -93, -856, -1070, -2919, +46, -2987, -3874, -1261, -1841, -597, +1113, -366, -282, +474, -132, - +19013, +11105, -7802, +10307, +543, -7199, -275, -1181, -6482, -3416, +10634, -2108, -4042, +4151, -2777, -1409, +4761, +291, -1107, -73, -2791, -368, -2750, -3871, -721, -1726, -1380, +656, -107, +32, +532, -418, - +17238, +9876, -6359, +10305, +398, -6315, -102, -1089, -5867, -3730, +9349, -1363, -3939, +4046, -1704, -2280, +4126, +804, -1450, +148, -1982, -710, -2585, -3457, -636, -1203, -1796, +107, -115, +106, +736, -435, - +16850, +7680, -7300, +12520, +2285, -8479, -1087, +427, -4800, -1828, +6635, -3369, -2358, +3423, -1655, -892, +2571, -327, -160, +642, -662, +1201, -1048, -1605, +229, -1235, -1428, -365, -1650, -1331, -434, -718, - +14445, +7248, -5479, +10890, +2224, -6676, -847, +20, -3992, -1849, +5544, -2552, -2301, +2914, -1338, -1107, +2267, -66, -274, +451, -432, +1011, -1109, -1445, +210, -1200, -1152, -150, -1229, -1064, -619, -638, - +12262, +7034, -3826, +9064, +2556, -4912, -1000, -85, -3259, -1912, +4712, -1765, -2260, +2378, -779, -1142, +1866, +240, -211, +297, -362, +843, -852, -1395, +26, -936, -987, +115, -841, -918, -540, -612, - +10302, +6772, -2608, +7425, +3047, -3580, -1144, +38, -2705, -1968, +3948, -1167, -2245, +1845, -376, -1032, +1522, +265, -101, +261, -453, +682, -692, -1289, -83, -615, -752, -59, -567, -670, -472, -618, - +8655, +6443, -1690, +6216, +3422, -2584, -975, +289, -2316, -1951, +3369, -755, -2184, +1494, -28, -828, +1147, +375, +103, +99, -381, +549, -584, -1004, +111, -444, -718, -65, -432, -490, -423, -480, - +7221, +6029, -1043, +5350, +3704, -1861, -720, +491, -2015, -1932, +2857, -505, -2070, +1231, +249, -749, +916, +588, -26, +2, -231, +492, -373, -773, +146, -331, -639, -153, -420, -446, -268, -366, - +6149, +5337, -522, +4890, +3705, -1298, -409, +653, -1896, -1811, +2394, -329, -1930, +1021, +457, -665, +862, +483, -128, +133, -8, +453, -352, -564, +224, -355, -685, -251, -418, -327, -123, -232, - +5347, +4865, -12, +4345, +3331, -784, +8, +681, -1713, -1654, +1950, -310, -1698, +1128, +488, -580, +778, +296, +168, +368, -71, +403, -167, -481, +0, -380, -642, -237, -238, -203, -161, -399, - +4513, +4458, +327, +3862, +3291, -212, +50, +538, -1286, -1648, +1413, -6, -1274, +809, +432, -246, +709, +464, +342, +239, -48, +380, -170, -546, -158, -340, -484, -110, -208, -423, -383, -436, - +3737, +4010, +796, +3404, +3194, +416, -10, +338, -902, -1429, +1024, +156, -1024, +609, +727, +264, +595, +355, +422, +205, -29, +258, -264, -566, -23, -135, -442, -273, -489, -465, -296, -300, - +3244, +3768, +1128, +2910, +3135, +692, -253, +385, -416, -1327, +523, +399, -524, +860, +1068, +205, +374, +460, +341, +111, -88, +108, -72, -266, -80, -420, -614, -364, -338, -321, -247, -281, - +2573, +3501, +1542, +2422, +3009, +997, -86, +399, -529, -1166, +615, +927, +3, +728, +933, +166, +369, +430, +133, +29, +88, +270, -37, -461, -485, -479, -438, -286, -266, -299, -341, -359, - +2231, +3444, +1513, +2040, +3101, +1062, -319, +337, -154, -486, +938, +903, +105, +773, +781, +97, +163, +295, +372, +236, +56, -55, -435, -564, -350, -311, -370, -314, -370, -380, -309, -324, - +2099, +3103, +1628, +2260, +2332, +675, +355, +998, +218, -292, +974, +821, +239, +834, +457, -122, +408, +649, +268, -133, -357, -207, -248, -398, -297, -330, -451, -420, -307, -346, -285, -262, - +2122, +2791, +1338, +2074, +2185, +1299, +1098, +1022, +96, -224, +1143, +1002, +34, +360, +626, +337, +351, +217, -313, -387, -92, +1, -292, -456, -393, -443, -464, -373, -291, -249, -256, -321, - +1707, +2474, +1550, +2358, +2684, +1380, +926, +1182, +372, +34, +972, +722, +127, +725, +656, -121, -188, -80, -126, -77, -58, -130, -419, -521, -423, -415, -422, -288, -194, -281, -292, -289, - +2009, +3271, +2261, +2063, +1937, +1369, +1101, +993, +457, +278, +709, +981, +479, -169, -163, -155, -17, +78, -53, -120, -289, -340, -416, -495, -424, -327, -303, -303, -181, -220, -289, -318, - +2008, +3310, +2283, +1883, +1850, +1562, +1336, +1209, +776, +362, +614, +893, +94, -536, -228, +27, +139, +104, -127, -295, -281, -260, -428, -460, -357, -327, -324, -261, -177, -196, -244, -322, - +1917, +2862, +1700, +1658, +1732, +1613, +1699, +1958, +1364, +660, +516, +154, +109, -111, -309, -59, +186, +33, -209, -177, -238, -291, -369, -419, -336, -324, -384, -275, -151, -205, -230, -271, - +2083, +2983, +1506, +1369, +1260, +1246, +1868, +2065, +1340, +757, +550, +543, +648, -21, -250, -120, -176, +2, -56, -272, -389, -249, -240, -367, -275, -212, -264, -298, -255, -207, -278, -316, - +2198, +2902, +1108, +1182, +1319, +951, +937, +1441, +1654, +1337, +1100, +824, +681, +876, +211, -700, -323, -124, -65, -79, -310, -308, -251, -253, -245, -200, -273, -191, -287, -316, -203, -334, - +2056, +2797, +1106, +1111, +1388, +1207, +805, +382, +604, +1281, +1542, +1132, +810, +896, +1118, +443, -493, -486, -254, -141, -40, -152, -378, -280, -153, -282, -256, -141, -244, -319, -313, -273, - +2227, +2815, +713, +806, +1269, +1147, +860, +283, +11, +688, +1122, +928, +1193, +1393, +1389, +1011, +515, +126, -365, -592, -318, -110, -213, -289, -293, -274, -243, -88, -185, -280, -240, -271, - +2487, +3077, +731, +1027, +1384, +982, +654, -128, +18, +996, +561, +73, +591, +932, +1479, +1270, +870, +925, +448, -201, -501, -563, -415, -115, -143, -320, -310, -120, -171, -247, -175, -287, - +2775, +3186, +631, +1392, +1798, +1197, +294, -934, -91, +1380, +530, -194, +56, +369, +981, +652, +864, +1272, +870, +557, +177, -277, -677, -549, -265, -205, -167, -195, -284, -238, -143, -268, - +3354, +3952, +622, +1159, +1616, +1212, +384, -1193, -171, +1340, +276, -317, +73, +202, +505, +358, +412, +812, +941, +759, +457, +303, +14, -361, -589, -473, -252, -41, -106, -338, -312, -210, - +3851, +4360, +508, +1396, +1995, +1083, -118, -1646, +204, +1680, -168, -602, -109, +183, +637, +36, +22, +528, +357, +402, +649, +527, +382, +246, -154, -411, -536, -224, -139, -252, -213, -373, - +4411, +4791, +385, +1660, +2324, +1023, -690, -2047, +660, +1766, -479, -607, -315, +44, +662, -70, -18, +284, +30, +175, +102, +352, +562, +305, +304, +207, -224, -238, -340, -387, -265, -275, - +5196, +5589, +252, +1519, +2294, +877, -1040, -2105, +1073, +1563, -889, -523, -328, -3, +615, -267, -54, +275, -150, -65, -69, +83, +148, +190, +385, +349, +230, +269, -184, -470, -345, -462, - +5718, +5975, +175, +2056, +2782, +433, -1979, -2126, +1813, +1397, -1262, -508, -449, +38, +582, -483, -40, +268, -347, -79, -259, -144, +146, -223, +11, +368, +235, +504, +304, -118, -274, -506, - +6315, +6714, +139, +2135, +3020, +109, -2674, -1982, +2425, +978, -1604, -368, -505, +111, +586, -693, -117, +249, -464, -85, -325, -245, +4, -438, -62, +108, +23, +446, +291, +123, +139, -256, - +6745, +7502, +262, +2112, +3265, -191, -3399, -1845, +3011, +575, -2029, -233, -551, +131, +609, -828, -184, +190, -609, -176, -413, -318, +53, -619, -305, +55, -89, +207, +130, -29, +147, +100, - +7135, +8455, +528, +1753, +3383, -342, -3912, -1715, +3302, +347, -2377, -280, -478, +73, +666, -864, -309, +173, -675, -305, -523, -417, -31, -619, -370, -108, -188, +168, -8, -183, -48, -243, - +7313, +9335, +990, +1537, +3442, -503, -4294, -1670, +3510, +231, -2617, -467, -433, +51, +676, -780, -520, +145, -610, -381, -642, -599, -117, -669, -413, -163, -232, +54, +96, -400, -473, -157, - +7366, +10104, +1617, +1432, +3413, -641, -4433, -1789, +3563, +295, -2857, -581, -471, -47, +733, -715, -694, +95, -548, -428, -666, -773, -215, -762, -547, -237, -183, +203, -336, -503, -328, -397, - +7627, +10884, +2189, +1075, +3085, -556, -4178, -2011, +3118, +500, -2883, -799, -373, -262, +585, -455, -843, -134, -419, -461, -781, -795, -264, -872, -798, -151, -218, -232, -138, -459, -588, -350, - +7805, +11222, +3062, +1025, +2511, +140, -3881, -2575, +2792, +742, -2671, -862, -572, -376, +526, -340, -707, -443, -595, -287, -600, -934, -448, -730, -617, -528, -615, +39, -258, -504, -448, -459, - +8363, +10906, +3309, +2010, +2235, +305, -3931, -2743, +2509, +616, -2212, -1029, -818, -300, +441, -402, -584, -720, -757, -88, -693, -1025, -498, -478, -772, -805, -578, -256, -196, -436, -534, -482, - +9029, +10207, +3227, +3604, +2126, +318, -3990, -2699, +2282, -66, -1506, -870, -1243, -147, +313, -594, -347, -843, -960, -75, -980, -749, -429, -936, -470, -770, -924, -178, -239, -505, -518, -435, - +9921, +9094, +2287, +6032, +2825, -665, -3976, -1942, +1634, -1240, -452, -499, -1858, -63, +175, -661, -141, -1007, -1221, -134, -966, -783, -874, -746, -300, -913, -822, -399, -257, -376, -363, -634, - +11207, +8923, +714, +7384, +3504, -1787, -3331, -478, +667, -3182, +480, +632, -2340, -174, -41, -734, +254, -1209, -1563, +237, -1495, -1119, -374, -1179, -176, -742, -854, -326, -296, -187, -407, -889, - +12500, +9128, -1225, +8120, +4706, -2957, -3096, +1429, +224, -5655, +633, +2334, -2476, -521, -246, -1021, +659, -1250, -1598, -102, -1942, -946, -536, -1243, -56, -809, -795, -9, -245, -516, -388, -591, - +13676, +9715, -3224, +8146, +6300, -3786, -3252, +3385, +497, -7984, -273, +4084, -1795, -1036, -439, -1428, +900, -738, -2169, -270, -1884, -1560, -244, -1157, -225, -702, -726, +327, -337, -781, -147, -433, - +15154, +10710, -5567, +6975, +8141, -3612, -4028, +4575, +1224, -9451, -1863, +5048, -504, -1304, -849, -1887, +1317, -802, -2679, +65, -2243, -1967, -192, -1025, -170, -751, -680, +394, -331, -789, -111, -452, - +16751, +11590, -7670, +5697, +9423, -3002, -4671, +5673, +1938, -10472, -3508, +5316, +1125, -1098, -1562, -2113, +1531, -1067, -2689, -22, -2225, -2260, -408, -719, -88, -730, -829, +416, -248, -657, -207, -430, - +19048, +11932, -9850, +4534, +10090, -1984, -5054, +6461, +2293, -11027, -4690, +4999, +2637, -594, -2197, -2457, +1788, -1314, -2837, +89, -2336, -2296, -497, -623, +34, -680, -1066, +461, -55, -678, -251, -446, - +21615, +12285, -12393, +3218, +10447, -513, -5263, +6448, +2499, -11072, -5490, +4213, +3638, +192, -2622, -3085, +2128, -1593, -3108, +258, -2535, -2078, -721, -584, +167, -802, -1230, +548, +77, -824, -300, -503, - +23814, +13115, -14900, +2298, +10402, +898, -5101, +6133, +3297, -10978, -6160, +3330, +4213, +1402, -2845, -3633, +2406, -1782, -3197, +506, -2620, -1975, -705, -585, +213, -896, -1169, +725, -33, -930, -208, -501, - +26386, +12827, -16969, +2278, +9703, +1341, -4735, +5967, +4345, -11169, -7039, +2751, +4328, +2440, -3053, -3808, +2333, -2300, -2829, +717, -2947, -2030, -466, -759, +120, -952, -975, +828, -420, -898, -159, -497, - +27944, +13492, -18792, +2616, +8679, +1183, -4343, +5611, +6445, -11341, -8610, +2448, +4449, +2910, -2638, -3722, +1665, -2447, -2294, +737, -3191, -2075, -286, -1008, +16, -802, -857, +864, -755, -842, -70, -604, - +29685, +13246, -19821, +3525, +7289, +438, -4363, +5714, +8745, -11618, -10243, +2318, +4494, +2830, -1737, -3623, +798, -2252, -1923, +676, -3494, -1846, -281, -1396, -10, -574, -760, +810, -964, -876, +89, -884, - +30876, +13227, -20231, +4464, +5889, -395, -4997, +6035, +11190, -11731, -11571, +2002, +4359, +2564, -389, -3809, +115, -1644, -2030, +671, -3672, -1473, -429, -1750, -81, -276, -628, +609, -946, -950, +127, -1298, - +31278, +13828, -20217, +5005, +4867, -1003, -6198, +6112, +13378, -11330, -12204, +1134, +4093, +2243, +984, -3911, -507, -785, -2404, +550, -3517, -1127, -734, -1985, -167, -11, -527, +311, -626, -1201, -142, -1426, - +31763, +14606, -20213, +4922, +4300, -1334, -7821, +5934, +15019, -10488, -12296, -244, +3894, +2145, +1899, -3668, -996, -217, -2645, +278, -3186, -960, -1050, -2098, -246, +125, -509, +271, -479, -1663, -297, -1411, - +32059, +15063, -19624, +4534, +3996, -1550, -9300, +5401, +15706, -8935, -11963, -1825, +3576, +2337, +2148, -3207, -1061, -200, -2557, +23, -2815, -964, -1297, -2112, -372, +106, -371, +213, -866, -1642, -555, -1453, - +31594, +16148, -18709, +3873, +3953, -1965, -10020, +3854, +16002, -6585, -11621, -3362, +3109, +2803, +1915, -2572, -712, -591, -2348, +118, -2607, -1103, -1413, -2224, -397, +185, -559, -36, -1026, -1584, -771, -1168, - +30561, +17638, -17451, +3091, +3826, -2310, -9959, +1289, +16030, -3803, -11272, -4403, +2328, +3336, +1431, -1843, -11, -1291, -1874, +345, -2491, -1351, -1564, -2198, -272, -81, -1106, +216, -1299, -1439, -527, -1224, - +29054, +19377, -15810, +1898, +3337, -2040, -9228, -2236, +15567, -882, -10760, -4753, +1128, +3442, +1193, -1335, +949, -1929, -1501, +721, -2539, -1679, -1649, -1976, -762, -420, -1351, +363, -1271, -1184, -487, -1395, - +27602, +19984, -13330, +1384, +2220, -1553, -8967, -5440, +14956, +1794, -10257, -4554, -131, +2570, +2016, -1408, +1844, -1852, -1851, +1473, -2793, -1890, -1630, -2378, -1270, -515, -1540, +663, -952, -1427, -261, -1350, - +25630, +20290, -10249, +1324, +1107, -1114, -8918, -8485, +14115, +4665, -9857, -4277, -756, +606, +3451, -1301, +1865, -565, -2709, +1877, -2367, -2459, -1746, -2677, -1920, -340, -1413, +665, -508, -1675, -66, -1466, - +23903, +20683, -7286, +510, -377, -53, -7840, -11202, +11907, +7374, -9146, -4087, -105, -1982, +4052, -56, +1078, +860, -2851, +1241, -1622, -2794, -2100, -2674, -2293, -321, -1039, +386, -96, -1780, -277, -1191, - +22823, +20723, -6390, +1262, +38, -1708, -6903, -11540, +8654, +9407, -7731, -4726, +1287, -3835, +3356, +1929, +303, +1232, -2157, +96, -909, -2590, -2708, -1999, -2763, -486, -647, +74, -134, -1612, -437, -1074, - +23286, +19705, -6984, +2708, +768, -3874, -6807, -9892, +5577, +9767, -5818, -5461, +2601, -4494, +2384, +2776, +168, +931, -1602, -159, -1262, -1698, -2885, -1466, -2698, -1301, -450, -206, -5, -1620, -620, -969, - +23121, +19255, -7571, +3875, +1563, -5614, -6214, -8564, +2641, +9601, -3111, -6567, +3743, -4320, +945, +3692, -1043, +1590, -1282, -840, -479, -978, -2698, -1087, -2537, -2252, -520, -532, +376, -1513, -1259, -735, - +23895, +17231, -7926, +5603, +1022, -6360, -5559, -7729, +248, +9659, -1110, -7381, +4032, -2981, -753, +3497, -675, +212, -226, -663, -11, -138, -2841, -1009, -2052, -2616, -1508, -419, +202, -1307, -1387, -864, - +24342, +16471, -9991, +7124, +2357, -8386, -5329, -5315, -1440, +7468, +1850, -7622, +3025, -1191, -1868, +2925, -544, -837, +462, +724, -295, +355, -2494, -1379, -1397, -2680, -2066, -975, -223, -1077, -799, -950, - +24670, +15431, -12280, +9290, +3619, -10800, -4710, -2736, -2869, +4919, +4375, -7414, +1744, +298, -2787, +2517, -329, -1185, +786, +1117, +234, +534, -2350, -1334, -1274, -2503, -2002, -1594, -1255, -755, -99, -851, - +25053, +13472, -13783, +11903, +3737, -12350, -3755, -973, -3561, +2410, +5792, -6487, +903, +639, -3500, +2947, +120, -1823, +1427, +635, +328, +1654, -2795, -1081, -1079, -2818, -1321, -1807, -2368, -781, +236, -570, - +25116, +10992, -14060, +14345, +2919, -12891, -2578, +298, -4831, +849, +7344, -6355, -113, +1687, -3785, +2243, +1525, -1852, +673, +891, +28, +1939, -1939, -1636, -642, -2710, -1531, -1027, -2946, -1438, +260, -246, - +23985, +9052, -12782, +15373, +1674, -11878, -1468, -66, -5434, +491, +7676, -6469, -622, +2840, -3942, +1270, +2660, -1561, +29, +815, -200, +1925, -1493, -1644, -301, -2510, -1767, -674, -2584, -1874, -316, -165, - +21931, +7984, -10773, +14942, +1323, -10330, -1496, -41, -5153, -560, +7563, -5510, -1367, +3202, -3067, +472, +2598, -1083, +280, +328, -550, +2171, -1750, -1359, +265, -2505, -1617, -565, -2257, -1696, -689, -545, - +19430, +7714, -9051, +13883, +1898, -9550, -1479, +550, -5119, -1546, +7412, -4342, -2191, +3447, -2123, -382, +2504, -635, +149, +475, -754, +1639, -1244, -1582, +373, -1789, -1679, -351, -2065, -1520, -554, -754, - +15748, +5880, -5425, +14058, +1054, -9150, +6, +395, -3696, +26, +2379, -3599, +1707, +2155, -2493, -381, +1177, -628, -908, +221, -185, +13, -490, +744, +822, +168, +287, -448, -1045, -444, -892, -1472, - +13423, +5793, -3949, +12100, +1504, -7414, -200, +63, -3202, +36, +2192, -2942, +1203, +1913, -1964, -650, +802, -427, -791, -12, -102, +329, -386, +362, +832, +203, -6, -415, -837, -549, -728, -965, - +11547, +5785, -2873, +10302, +2118, -6063, -463, +55, -2706, -44, +2080, -2250, +641, +1766, -1389, -907, +655, -241, -693, -30, +34, +406, -343, +364, +574, +40, +171, -246, -795, -541, -534, -664, - +9992, +5645, -2205, +8952, +2516, -5038, -463, +97, -2247, -98, +1995, -1860, +247, +1695, -1144, -964, +569, -79, -605, +22, +220, +235, -242, +317, +304, +54, +320, -69, -720, -432, -411, -602, - +8782, +5267, -1688, +7925, +2586, -4032, -444, +186, -1797, -191, +1866, -1605, +27, +1498, -942, -933, +555, +32, -524, +199, +141, +118, -129, +149, +324, +142, +325, +78, -560, -385, -344, -545, - +7729, +4882, -1177, +6873, +2650, -3039, -407, +340, -1509, -165, +1693, -1465, -61, +1352, -781, -864, +627, +111, -305, +152, +24, +234, -129, +182, +391, +215, +338, +94, -398, -277, -266, -463, - +6682, +4405, -731, +6123, +2845, -2298, -387, +459, -1188, -176, +1393, -1251, -73, +1145, -660, -560, +620, +101, -161, +95, +165, +308, -117, +224, +453, +233, +340, +124, -276, -83, -284, -652, - +5690, +4114, -370, +5337, +2959, -1597, -302, +540, -969, -272, +1211, -1020, -123, +962, -388, -419, +496, +293, -68, +198, +277, +243, -1, +258, +446, +244, +316, +224, -197, -287, -538, -753, - +4886, +3783, -77, +4739, +3009, -1004, -171, +567, -808, -296, +1071, -732, -150, +762, -143, -243, +583, +495, +70, +295, +285, +282, +109, +300, +419, +303, +318, -41, -410, -429, -543, -696, - +4226, +3500, +214, +4230, +2888, -619, +78, +571, -807, -209, +1096, -674, -362, +872, +202, -45, +765, +519, +142, +420, +299, +326, +177, +298, +271, +19, +43, -216, -432, -470, -647, -770, - +3932, +3487, +332, +3583, +2646, -337, +285, +627, -784, -249, +992, -484, -225, +1185, +515, -8, +833, +683, +354, +372, +256, +357, +26, -114, -52, -13, -48, -275, -631, -669, -560, -678, - +3417, +3033, +572, +3583, +2497, -132, +512, +448, -821, -41, +1094, -215, +63, +1208, +613, +421, +1026, +661, +269, +268, +157, -77, -316, -230, -50, -15, -270, -450, -631, -506, -489, -682, - +3181, +2995, +715, +3281, +2345, -67, +347, +573, -324, +109, +1136, +26, +360, +1541, +983, +492, +841, +521, -21, -138, -249, -144, -314, -277, -62, -239, -335, -379, -509, -456, -497, -624, - +2727, +2772, +1072, +2985, +1995, +392, +618, +698, +14, +104, +1230, +616, +773, +1489, +881, +385, +451, -79, -396, -153, -251, -293, -476, -335, -58, -202, -314, -426, -485, -422, -544, -580, - +2494, +2557, +1043, +2809, +2364, +870, +612, +794, +496, +543, +1308, +960, +905, +1098, +463, -159, -22, -97, -245, -365, -543, -373, -259, -109, -161, -351, -340, -303, -434, -540, -495, -424, - +2244, +2930, +1654, +2496, +2296, +1063, +990, +1335, +682, +721, +1328, +513, +346, +642, +45, -321, -153, -280, -469, -425, -401, -290, -203, -148, -250, -401, -344, -391, -436, -433, -426, -380, - +2037, +3030, +1906, +2584, +3062, +1893, +990, +1134, +771, +385, +555, +134, +140, +441, -13, -448, -353, -397, -487, -345, -327, -238, -229, -306, -339, -347, -307, -358, -440, -470, -365, -304, - +2260, +3620, +2531, +2997, +2841, +1693, +1371, +1050, +54, -313, +437, +310, -186, +172, -15, -693, -347, -145, -477, -380, -271, -292, -232, -289, -368, -327, -359, -335, -337, -420, -362, -300, - +2676, +4646, +3139, +2421, +2169, +1461, +1102, +750, +196, +85, +103, -264, -85, +79, -270, -444, -278, -319, -366, -267, -356, -287, -310, -325, -320, -352, -353, -348, -336, -368, -283, -304, - +2949, +4690, +2841, +1992, +1689, +1410, +1437, +860, +277, +660, +273, -352, -345, -179, +121, -193, -595, -313, -69, -302, -301, -297, -388, -283, -359, -329, -293, -304, -317, -316, -248, -264, - +2663, +4197, +2446, +1659, +1599, +1195, +1150, +1390, +834, +702, +922, +74, -262, -12, -178, -353, -146, -141, -372, -189, -146, -406, -452, -309, -320, -299, -251, -248, -234, -286, -278, -279, - +2398, +3447, +2003, +1730, +1358, +984, +1031, +668, +683, +1466, +1326, +833, +547, +62, +124, -145, -512, -263, -44, -260, -496, -309, -241, -380, -321, -210, -197, -195, -288, -327, -348, -283, - +1987, +2518, +1256, +1700, +1770, +1374, +486, -161, +666, +1239, +1117, +1441, +1412, +1138, +952, +102, -154, -108, -471, -390, -130, -296, -423, -224, -149, -219, -273, -144, -187, -306, -316, -312, - +2277, +2839, +857, +1089, +1531, +1252, +447, -170, +485, +946, +625, +786, +1274, +1596, +1572, +803, +425, +213, -154, -308, -514, -316, -104, -287, -376, -112, -81, -229, -298, -346, -243, -269, - +2475, +3091, +1057, +1202, +1523, +1181, +155, -419, +779, +1083, +35, +243, +607, +800, +1330, +1039, +902, +962, +366, -99, -203, -378, -433, -305, -177, -196, -314, -134, -130, -427, -342, -186, - +2867, +3436, +954, +1406, +1896, +1116, -228, -668, +1005, +1052, -200, +160, +322, +441, +627, +249, +723, +1109, +691, +570, +250, -239, -146, -317, -437, -152, -136, -255, -367, -288, -235, -306, - +3223, +4037, +1059, +1327, +1971, +1123, -496, -724, +1262, +822, -504, +196, +267, +346, +542, -168, +79, +604, +516, +608, +511, +379, +188, -138, -157, -106, -291, -239, -240, -438, -390, -237, - +3604, +4513, +1093, +1460, +2232, +986, -1011, -692, +1601, +582, -689, +154, +137, +264, +549, -231, -112, +308, -5, +126, +288, +386, +454, +334, +190, +65, -9, -169, -440, -448, -309, -360, - +4214, +5204, +1001, +1333, +2363, +811, -1317, -468, +1657, +218, -774, +195, +54, +193, +477, -310, -143, +220, -205, -91, -167, -47, +273, +245, +485, +588, +199, -41, -178, -454, -469, -319, - +4699, +5772, +1037, +1391, +2580, +571, -1811, -137, +1930, -248, -876, +278, -102, +158, +529, -367, -232, +173, -250, -176, -332, -250, -145, -125, +369, +578, +501, +334, -24, -230, -185, -365, - +5288, +6343, +926, +1516, +2837, +116, -2274, +403, +2022, -767, -921, +321, -140, +29, +469, -385, -290, +151, -299, -257, -451, -381, -272, -339, +52, +314, +302, +289, +305, +49, -70, -194, - +5726, +6820, +1096, +1667, +3026, -179, -2850, +907, +2339, -1355, -1017, +450, -163, -66, +415, -378, -412, +166, -245, -345, -541, -415, -353, -452, -62, +81, +100, +97, +117, +54, +153, +24, - +6153, +7423, +1241, +1705, +3192, -342, -3363, +1287, +2593, -1875, -1019, +557, -240, -122, +319, -290, -434, +2, -201, -386, -582, -375, -458, -561, -160, +6, +81, -90, -141, -171, +10, +136, - +6828, +8181, +890, +1848, +3361, -805, -3382, +1527, +2488, -2165, -973, +617, -316, -246, +308, -188, -549, -125, -176, -412, -641, -381, -560, -633, -100, -94, -15, -180, -313, -244, -131, -157, - +7339, +8745, +841, +2086, +3460, -1152, -3508, +1614, +2597, -2420, -1103, +713, -354, -350, +308, -133, -681, -241, -127, -375, -784, -526, -527, -641, -141, -117, -177, -223, -325, -365, -249, -300, - +7574, +9152, +1067, +2490, +3582, -1504, -3603, +1572, +2713, -2475, -1389, +742, -241, -424, +146, -29, -689, -412, -49, -482, -922, -508, -528, -656, -326, -236, +0, -242, -494, -465, -250, -363, - +7771, +9477, +1527, +2680, +3445, -1316, -3581, +1119, +2776, -2355, -1714, +883, -172, -648, +99, -15, -445, -536, -388, -395, -960, -596, -496, -760, -479, -221, +19, -221, -514, -524, -422, -579, - +8021, +9527, +2130, +2911, +3042, -704, -3474, +429, +2652, -2057, -1809, +694, -37, -769, -100, +184, -247, -761, -609, -325, -1000, -680, -746, -736, -332, -408, -31, -128, -468, -729, -608, -586, - +8404, +9096, +2503, +3785, +2807, -578, -3480, +263, +2211, -1959, -1522, +174, -65, -508, -392, +128, +9, -898, -776, -193, -1245, -945, -832, -687, -337, -524, -93, -26, -595, -926, -547, -887, - +8807, +8295, +2417, +5558, +3298, -1393, -3611, +1274, +1418, -2498, -541, -286, -448, +137, -733, -107, +472, -919, -800, -132, -1516, -1020, -876, -819, -258, -573, -75, -222, -470, -870, -816, -827, - +9721, +7750, +1320, +7320, +3992, -2723, -3178, +2422, -20, -3129, +726, -465, -1243, +477, -680, -418, +820, -960, -919, -87, -1553, -1159, -1230, -839, -90, -743, -335, -154, -533, -893, -664, -1012, - +10870, +7707, -280, +8285, +5199, -3799, -2870, +3710, -1420, -4018, +2054, -220, -2214, +514, -188, -855, +1016, -762, -1123, +24, -1500, -1380, -1443, -763, -169, -955, -493, -100, -557, -806, -616, -1159, - +11833, +8327, -2134, +8341, +6953, -4401, -2931, +5077, -2393, -5396, +3185, +626, -3054, -50, +496, -988, +898, -338, -1369, +122, -1461, -1366, -1542, -1049, -218, -1029, -640, -181, -361, -866, -501, -1048, - +12829, +9031, -3811, +7670, +8588, -4509, -3175, +6408, -3118, -7036, +3841, +1817, -3527, -1043, +839, -699, +618, +2, -1465, -51, -1246, -1421, -1712, -1253, -467, -1107, -577, -354, -342, -807, -350, -891, - +14193, +9389, -5197, +6872, +9549, -4273, -3139, +7727, -3898, -8441, +3999, +3031, -3444, -2122, +727, -197, +556, +113, -1327, -318, -1040, -1564, -1813, -1380, -747, -1085, -601, -339, -469, -645, -199, -888, - +15661, +9657, -6466, +6233, +9751, -3871, -2723, +8959, -4623, -9557, +3687, +4006, -2825, -3063, +218, +188, +872, +40, -1085, -476, -1213, -1459, -1966, -1538, -758, -1196, -697, -106, -518, -710, -84, -846, - +17612, +9338, -7642, +6082, +9245, -3958, -1634, +10145, -5734, -10179, +3233, +4461, -2053, -3596, -499, +236, +1471, -53, -824, -783, -1511, -1205, -2322, -1376, -936, -1374, -531, +50, -558, -860, -125, -756, - +19463, +9219, -8893, +6261, +8413, -4281, -363, +11374, -6530, -10787, +2801, +4644, -1342, -3682, -1194, -39, +2157, +139, -767, -1072, -1682, -1101, -2364, -1296, -1186, -1329, -395, +235, -591, -1146, -127, -554, - +21650, +9391, -10922, +6081, +8229, -4220, +202, +11812, -6628, -11097, +2478, +4559, -1182, -3433, -1549, -554, +2784, +461, -1205, -1027, -1704, -1258, -2251, -1431, -1146, -1205, -447, +400, -669, -1391, -60, -370, - +23618, +9863, -13021, +6004, +8047, -4224, +416, +12157, -6101, -11654, +2261, +4560, -1406, -3057, -1488, -1343, +3208, +953, -1820, -705, -1697, -1485, -2065, -1531, -1035, -1118, -452, +413, -760, -1496, +104, -350, - +25507, +10091, -14633, +6037, +7728, -4437, +358, +12536, -5172, -12313, +2012, +4630, -1785, -2622, -1212, -2223, +3337, +1463, -2227, -360, -1728, -1658, -1788, -1625, -1024, -963, -484, +363, -873, -1530, +387, -597, - +26627, +10861, -15853, +5976, +7293, -4687, -371, +13070, -3740, -13126, +1550, +4641, -1970, -2334, -931, -3002, +3015, +1972, -2297, -262, -1622, -1706, -1631, -1718, -1043, -847, -523, +200, -913, -1491, +419, -863, - +27529, +11441, -16338, +5805, +6853, -5062, -1537, +13789, -2342, -13609, +1025, +4352, -1778, -2113, -836, -3461, +2445, +2244, -1905, -447, -1343, -1486, -1806, -1634, -1063, -761, -595, -38, -809, -1509, +121, -852, - +28224, +11700, -16026, +5571, +6480, -5603, -2945, +14554, -1154, -13550, +445, +3703, -1208, -1832, -1081, -3648, +1918, +2132, -1094, -755, -1071, -949, -2221, -1385, -1073, -728, -775, -144, -846, -1640, -17, -888, - +28214, +12317, -15132, +5336, +6093, -6385, -4398, +15063, +169, -13141, -349, +2865, -289, -1493, -1675, -3631, +1627, +1567, -67, -871, -1083, -137, -2567, -1204, -1005, -901, -818, -487, -1098, -1321, -264, -1047, - +27674, +13198, -13952, +5049, +5725, -7019, -5818, +14656, +1734, -12326, -1241, +1915, +642, -1155, -2395, -3373, +1425, +664, +785, -409, -1488, +642, -2474, -1372, -798, -1009, -1376, -899, -968, -1199, -318, -1143, - +26652, +14012, -12267, +5200, +5059, -7687, -7096, +13622, +3659, -11441, -2232, +1136, +1363, -745, -2920, -3117, +1275, -215, +1173, +578, -1926, +1018, -1813, -1727, -552, -1508, -1936, -882, -1218, -880, -117, -1274, - +25476, +14976, -10645, +5041, +4465, -7268, -8563, +11373, +5951, -10470, -2967, +695, +1268, -121, -2916, -3040, +1232, -1049, +1136, +1691, -1847, +783, -939, -1782, -1189, -1393, -2259, -1210, -1263, -527, +246, -1345, - +24418, +15887, -9483, +5106, +3650, -6572, -9308, +8066, +7947, -9122, -3698, +546, +799, +234, -2298, -3040, +979, -1401, +660, +2460, -1414, +581, -594, -1924, -1571, -1185, -2342, -1526, -1293, -276, +512, -1388, - +23795, +16122, -8471, +5677, +2738, -6335, -9272, +4879, +8930, -7283, -4533, +587, +584, -12, -1140, -3045, +596, -1168, -297, +2828, -664, +171, -697, -1636, -1755, -862, -2122, -1839, -1085, -590, +469, -1065, - +23181, +16390, -7741, +6442, +2203, -6740, -8434, +1898, +8933, -4752, -5617, +579, +1155, -849, +75, -2508, -62, -548, -1446, +2589, +243, -427, -620, -1078, -1599, -627, -1538, -1798, -1522, -1117, +586, -608, - +22030, +16813, -6552, +6365, +1905, -6491, -7923, -1054, +8742, -2377, -6611, +561, +1892, -1729, +1053, -1623, -1078, +90, -2143, +1121, +1073, -290, -801, -281, -1302, -213, -1096, -1925, -1798, -1686, +156, -224, - +21251, +16564, -5227, +6101, +1298, -5618, -7958, -3289, +8275, -752, -6864, +468, +2279, -1970, +1851, -1720, -1502, +720, -2997, -87, +1066, +346, -609, +374, -840, -207, -612, -1924, -1832, -2459, -669, -2, - +21059, +15707, -4300, +6487, +399, -4731, -7511, -5182, +7533, +993, -7053, +282, +3472, -2462, +1927, -1518, -1924, +1110, -3285, -499, +296, +615, +989, +279, -802, +498, -387, -1895, -1824, -2715, -1623, -344, - +21308, +14470, -4242, +7387, -252, -4583, -6956, -6093, +6238, +2376, -6555, -258, +4580, -2860, +1045, -858, -2358, +1013, -2617, -1140, +487, +118, +1239, +1477, -1144, +905, +15, -2196, -1670, -2549, -2403, -914, - +21749, +13551, -6010, +9423, +237, -6449, -5831, -5696, +4659, +3069, -5379, -988, +5203, -3101, -229, +148, -2474, +413, -1565, -777, +245, -263, +270, +2911, -521, +46, +1169, -2577, -2021, -1583, -2762, -1790, - +22949, +11670, -8631, +12918, +409, -9740, -4092, -3756, +2385, +3036, -3324, -2593, +5421, -2472, -2044, +991, -1723, -438, -884, +258, -444, -546, -80, +2348, +873, +112, +640, -1839, -2303, -1429, -2266, -2374, - +23912, +9195, -9740, +15651, -753, -10898, -2348, -2548, +736, +2645, -1865, -3420, +5193, -2092, -2914, +1332, -608, -827, -805, +690, -265, -735, -758, +2026, +1239, +685, +402, -1265, -2108, -2026, -1548, -2057, - +24116, +7253, -10354, +17453, -1244, -12053, -838, -452, -1755, +1608, +585, -4398, +4021, -759, -3062, +841, +208, -518, -792, +316, -185, -122, -1534, +1707, +1529, +201, +1161, -889, -2381, -1596, -1536, -1868, - +22899, +6009, -9723, +18156, -1387, -12297, +387, +197, -3319, +1403, +1627, -5089, +3452, +505, -3305, +713, +563, -709, -310, -26, -425, +286, -1418, +1157, +1256, +363, +1114, -493, -2226, -1184, -1308, -2261, - +20564, +5546, -8226, +17550, -828, -11490, +294, +435, -3523, +690, +1926, -4747, +2908, +1152, -2973, +467, +625, -707, -390, +101, -449, +40, -906, +959, +763, +546, +863, -551, -1476, -956, -1217, -2071, - +18013, +5812, -6919, +15896, +403, -10591, +67, +717, -3782, +91, +2336, -4162, +2130, +1919, -2779, -103, +1086, -691, -833, +297, -250, -202, -650, +1014, +731, +166, +703, -484, -1293, -477, -1156, -1837, - +15954, +7279, -4696, +11257, -415, -7760, +15, -732, -924, +300, -779, -1111, +2316, +31, -1667, -359, +362, -476, -1406, +77, +201, +160, +31, +184, +33, +618, +402, -142, -19, -131, -351, -177, - +13494, +6705, -2870, +10505, -334, -6612, +28, -1001, -670, +405, -783, -1035, +2308, +178, -1639, -390, +219, -411, -1192, +78, +48, +72, +135, +215, +200, +619, +296, -179, +63, -49, -474, -174, - +11237, +6344, -1097, +9098, -68, -4982, -506, -1321, -184, +563, -966, -831, +2204, +226, -1398, -487, +210, -400, -1067, +109, +7, -13, +137, +290, +364, +506, +81, -34, +85, -87, -211, -95, - +9435, +6226, -171, +7621, +609, -3889, -842, -1290, +79, +593, -877, -638, +1778, +372, -1115, -612, +133, -304, -919, +84, +28, -9, +49, +403, +518, +117, +63, +315, +9, -189, +148, +127, - +8281, +6134, -52, +6557, +1253, -3449, -792, -804, +3, +410, -398, -491, +1170, +585, -801, -816, +97, -92, -760, -8, +125, +10, +14, +591, +350, +20, +334, +355, -11, +73, +387, +50, - +7625, +5926, -212, +5732, +1440, -2973, -409, -538, -153, +402, +53, -528, +814, +714, -773, -751, +187, -25, -685, +71, +194, -126, +301, +656, +141, +177, +495, +460, +123, +277, +255, -206, - +6929, +5539, -213, +5156, +1489, -2470, -128, -421, -216, +512, +263, -626, +604, +666, -598, -609, +135, +2, -569, +170, +101, +124, +603, +290, +211, +558, +624, +396, +73, +189, -68, -300, - +6185, +4980, +12, +4844, +1476, -2007, +5, -218, -48, +475, +186, -579, +652, +583, -532, -454, +163, -44, -351, +323, +185, +454, +519, +323, +554, +596, +513, +149, -59, +27, -156, -301, - +5578, +4710, +139, +4160, +1511, -1429, +247, -167, -134, +535, +301, -478, +484, +512, -357, -355, +143, +139, +9, +323, +460, +774, +454, +456, +460, +265, +311, +29, -141, -56, -157, -425, - +4834, +4247, +381, +3890, +1667, -1077, +239, -52, +64, +515, +186, -374, +470, +446, -204, -178, +260, +402, +264, +582, +786, +717, +277, +144, +133, +174, +219, +36, -212, -220, -241, -491, - +4111, +3866, +739, +3569, +1573, -633, +462, -99, +98, +570, +132, -353, +509, +570, +1, -45, +535, +857, +514, +702, +653, +127, -67, +94, +33, +142, +132, -176, -297, -218, -361, -612, - +3730, +3751, +749, +2995, +1740, -73, +398, -128, +157, +562, +322, -106, +526, +653, +398, +535, +911, +896, +331, +268, +196, +17, -50, +13, -44, +14, +4, -239, -323, -300, -491, -605, - +2892, +3209, +1362, +3059, +1608, +182, +476, -76, +432, +661, +242, +160, +1034, +1084, +626, +638, +748, +381, -9, +164, +81, +56, -148, -220, -132, -95, -61, -252, -388, -412, -527, -492, - +2752, +3422, +1354, +2301, +1710, +560, +500, +0, +522, +1109, +816, +680, +1165, +1033, +440, -19, +152, +356, +205, +72, -219, -249, -230, -203, -210, -180, -256, -370, -297, -417, -460, -470, - +2213, +3015, +1710, +2495, +1858, +590, +641, +619, +1215, +1482, +1045, +756, +541, +266, +10, +87, +388, +325, -149, -273, -65, -313, -465, -315, -243, -222, -297, -239, -314, -374, -410, -472, - +2378, +3632, +1949, +1796, +1538, +1419, +1931, +1407, +1042, +906, +324, -55, +57, +281, +416, +73, -141, +104, -125, -338, -346, -567, -456, -178, -236, -293, -193, -168, -347, -459, -409, -412, - +2533, +3615, +2312, +2871, +2388, +1873, +1924, +743, -6, +118, +67, +58, +149, +131, +262, -115, -211, -1, -357, -465, -469, -597, -378, -114, -162, -284, -237, -201, -345, -426, -423, -455, - +2942, +4615, +3780, +3595, +1951, +1001, +577, -3, -9, +178, +100, -150, -79, +35, +232, -191, -343, -241, -527, -515, -469, -366, -285, -260, -253, -164, -168, -307, -405, -445, -401, -430, - +3532, +6354, +4764, +2112, +192, +502, +1060, +740, -280, -481, -6, +64, -3, -232, +35, -123, -425, -424, -500, -331, -403, -411, -380, -233, -195, -219, -156, -328, -390, -471, -421, -332, - +3754, +6378, +3302, +1176, +770, +1524, +1808, +405, -520, -9, +89, -401, +38, -134, -211, -179, -439, -279, -348, -439, -354, -411, -499, -252, -186, -273, -220, -306, -347, -364, -422, -391, - +2291, +3472, +1957, +1996, +2277, +2297, +2104, +987, +507, +706, +356, -152, -298, -91, -5, -385, -390, -196, -226, -195, -416, -447, -287, -389, -410, -244, -292, -350, -178, -230, -400, -417, - +1819, +2518, +1138, +1323, +2016, +2067, +1584, +1227, +1540, +1527, +1077, +599, +319, +222, -133, -344, -224, -354, -392, -98, -287, -313, -172, -348, -336, -273, -365, -452, -322, -244, -281, -244, - +1991, +2736, +1265, +1355, +1696, +1270, +711, +599, +1244, +1618, +1273, +1004, +935, +768, +344, -110, -219, -251, -264, -319, -400, -274, -131, -258, -317, -231, -396, -403, -299, -400, -335, -208, - +2251, +2968, +994, +1270, +1801, +1182, +278, +85, +960, +1169, +719, +996, +1351, +1194, +875, +354, +176, -35, -282, -178, -385, -406, -153, -263, -175, -84, -340, -346, -297, -435, -353, -295, - +2479, +3474, +1165, +1200, +1738, +845, +57, +328, +1004, +611, +199, +546, +759, +1002, +1149, +732, +519, +336, +110, +42, -306, -317, -221, -391, -190, -72, -254, -255, -285, -409, -356, -289, - +2648, +3711, +1310, +1382, +2036, +687, -508, +326, +1209, +455, +69, +381, +353, +462, +570, +467, +723, +755, +406, +258, +135, -71, -226, -267, -244, -225, -239, -248, -226, -295, -370, -333, - +2964, +4131, +1490, +1331, +2035, +615, -807, +460, +1251, +53, -30, +484, +328, +176, +292, +67, +31, +459, +630, +520, +346, +231, +64, -123, -179, -163, -253, -368, -325, -244, -286, -364, - +3240, +4589, +1670, +1277, +2158, +577, -1140, +581, +1323, -227, -122, +553, +290, +100, +235, -70, -152, +21, +69, +287, +434, +552, +333, +96, +114, -5, -177, -258, -330, -382, -258, -309, - +3730, +5196, +1638, +1123, +2168, +499, -1274, +755, +1209, -628, -139, +668, +292, -40, +122, -92, -234, -100, -101, -83, -135, +285, +479, +374, +279, +151, +85, -119, -293, -348, -282, -381, - +4119, +5684, +1732, +1126, +2228, +300, -1467, +1077, +1204, -1061, -263, +742, +305, -24, +37, -204, -274, -137, -131, -189, -340, -114, +44, +178, +404, +348, +234, +110, -83, -267, -257, -291, - +4622, +6186, +1693, +1242, +2320, -46, -1538, +1517, +1127, -1483, -304, +841, +294, -67, +5, -203, -308, -200, -102, -217, -386, -222, -141, -99, +23, +201, +346, +265, +65, -52, -11, -200, - +5193, +6638, +1553, +1499, +2388, -594, -1569, +2013, +985, -1862, -401, +847, +342, -127, -49, -265, -391, -279, -24, -258, -446, -237, -373, -107, -35, -174, -57, +100, +163, +130, +55, -58, - +5824, +7125, +1374, +1701, +2443, -1077, -1576, +2426, +806, -2127, -438, +769, +324, -176, +41, -326, -603, -328, -5, -213, -487, -284, -470, -142, -47, -263, -242, -262, -124, +12, +120, +33, - +6335, +7628, +1408, +1800, +2526, -1396, -1736, +2894, +798, -2493, -400, +738, +274, -165, +15, -222, -694, -482, +72, -261, -572, -116, -475, -277, -17, -291, -261, -317, -412, -297, -56, +28, - +6761, +8075, +1459, +2066, +2609, -1964, -1828, +3359, +727, -2782, -456, +715, +208, -232, -18, -148, -747, -627, +81, -302, -698, -121, -406, -325, -107, -219, -294, -466, -521, -391, -176, -288, - +7157, +8606, +1581, +2068, +2784, -2202, -2039, +3602, +767, -2899, -542, +707, +104, -260, -9, -128, -676, -844, +64, -130, -840, -253, -381, -284, -107, -233, -282, -564, -568, -421, -261, -447, - +7410, +9322, +1838, +1630, +3033, -1959, -2478, +3478, +916, -2764, -738, +578, +126, -372, +30, -107, -667, -935, -60, -32, -777, -452, -481, -148, -144, -362, -257, -530, -598, -498, -436, -437, - +7600, +9757, +2318, +1422, +3068, -1530, -2951, +3205, +1134, -2618, -848, +362, +153, -421, -49, -52, -609, -1028, -173, +13, -822, -437, -527, -269, -108, -428, -361, -411, -698, -654, -354, -475, - +8104, +9762, +2543, +1907, +2993, -1492, -3123, +3108, +1007, -2376, -799, +85, +225, -462, -207, +76, -422, -1156, -330, +104, -791, -492, -526, -345, -141, -393, -383, -537, -744, -705, -190, -505, - +8909, +9413, +2318, +2985, +3009, -1948, -3050, +3168, +425, -2046, -543, -270, +167, -483, -337, +79, -154, -1299, -550, +186, -643, -695, -585, -287, -262, -358, -406, -740, -843, -531, -265, -573, - +9426, +9025, +2181, +4009, +3640, -2472, -3407, +3777, -384, -2061, +272, -562, -296, -282, -348, -201, +397, -1463, -821, +375, -577, -753, -723, -199, -322, -387, -483, -747, -845, -590, -326, -571, - +10108, +8385, +1400, +6014, +4224, -3846, -2895, +4634, -1924, -2185, +1409, -691, -736, -445, -160, -496, +690, -1211, -1255, +419, -429, -745, -766, -201, -456, -411, -561, -544, -937, -907, -160, -739, - +10943, +8373, +46, +7110, +5244, -4697, -2467, +5334, -3432, -2574, +2681, -670, -1220, -664, +155, -796, +596, -633, -1639, +276, -169, -751, -786, -162, -512, -556, -561, -560, -872, -1006, -393, -823, - +12145, +8720, -1664, +7093, +6723, -4974, -2355, +5841, -4655, -3092, +3716, -397, -1752, -903, +493, -914, +75, -59, -1625, -196, +169, -746, -800, +30, -700, -607, -584, -846, -650, -980, -876, -718, - +13449, +9173, -3433, +6797, +7856, -4807, -2042, +6051, -5634, -3740, +4384, +233, -2242, -1265, +790, -884, -471, +114, -1201, -709, +233, -517, -817, +265, -855, -714, -702, -983, -688, -985, -936, -805, - +14554, +9843, -4692, +5589, +8876, -3969, -1993, +6452, -6471, -4465, +4658, +1064, -2464, -1808, +1040, -734, -892, -140, -587, -969, -47, -87, -824, +496, -902, -929, -759, -1132, -899, -928, -701, -988, - +15499, +10690, -5588, +4019, +9370, -2825, -1817, +6925, -7237, -5143, +4618, +1819, -2391, -2377, +1112, -527, -1082, -687, -144, -864, -451, +270, -610, +501, -919, -981, -876, -1386, -1039, -897, -490, -928, - +17184, +10743, -6654, +3458, +8941, -2496, -296, +6958, -8428, -5131, +4435, +2201, -2279, -2678, +1041, -465, -1059, -1191, -112, -563, -633, +396, -146, +255, -999, -772, -1178, -1541, -1165, -955, -285, -586, - +18439, +11433, -7884, +3086, +8223, -2330, +1154, +7363, -9381, -5433, +4476, +2299, -2058, -2772, +772, -429, -922, -1487, -412, -319, -459, +489, +179, +4, -920, -666, -1378, -1593, -1381, -989, -70, -199, - +20043, +11571, -8926, +2927, +7480, -2933, +2814, +7900, -10432, -5634, +4629, +2163, -2083, -2501, +322, -605, -660, -1666, -795, -420, +2, +773, +28, -86, -714, -788, -1426, -1661, -1631, -934, -18, +154, - +21100, +12438, -9991, +2658, +6924, -3598, +3640, +9112, -11048, -6263, +4923, +1936, -2083, -2127, -90, -1004, -241, -1755, -1109, -655, +353, +1477, -496, -26, -322, -1103, -1235, -1773, -1804, -950, -17, +340, - +22220, +13016, -10684, +2238, +6616, -4544, +3961, +10464, -11476, -6710, +4989, +1692, -2097, -1740, -471, -1509, +171, -1891, -1172, -1008, +446, +2361, -1007, -80, +206, -1448, -1059, -1719, -2148, -946, -187, +379, - +23160, +13514, -10970, +1648, +6564, -5582, +3717, +11856, -11585, -6851, +4668, +1415, -1888, -1527, -831, -1885, +423, -2020, -993, -1361, +246, +3145, -1090, -388, +815, -1543, -1101, -1488, -2586, -1060, -470, +329, - +23984, +13865, -11140, +1506, +6153, -6455, +3221, +12728, -11274, -6683, +4149, +879, -1350, -1515, -1321, -1966, +480, -2107, -735, -1620, -134, +3538, -695, -707, +1213, -1214, -1434, -1269, -3012, -1293, -736, +72, - +24782, +14120, -11236, +1961, +5253, -7111, +2788, +12880, -10420, -6360, +3471, +290, -601, -1551, -1881, -1800, +635, -2271, -409, -1692, -623, +3484, +102, -645, +1121, -484, -1860, -1402, -3095, -1550, -1113, -154, - +24478, +15178, -10478, +1270, +5126, -7637, +1416, +13108, -9038, -6194, +2475, -43, +4, -1635, -2240, -1773, +998, -2517, -301, -1320, -1403, +2910, +1377, -319, +543, +368, -2377, -1572, -2886, -2071, -1188, -610, - +23336, +16618, -8704, -223, +5298, -7565, -968, +13263, -6982, -6465, +1742, -449, +352, -1376, -2596, -1623, +1240, -2651, -286, -899, -1898, +1936, +2438, +528, -375, +750, -2161, -1941, -2664, -2274, -1304, -958, - +22712, +17229, -7217, -356, +4386, -7099, -2807, +12389, -4621, -6839, +1425, -975, +424, -777, -2826, -1526, +1422, -2734, -246, -516, -2068, +1271, +2387, +1470, -861, +696, -1581, -2206, -2447, -2243, -1214, -1282, - +22892, +17053, -6909, +1550, +2504, -7309, -2981, +10387, -2761, -6478, +847, -1462, +747, -527, -2541, -1653, +1330, -2326, -581, +131, -2018, +687, +1356, +2090, -263, +54, -772, -2199, -2423, -1678, -1280, -1950, - +22958, +16963, -6994, +3862, +804, -8094, -2421, +7964, -1267, -5599, -222, -1546, +1312, -701, -1892, -1941, +925, -1306, -1223, +805, -1822, -507, +577, +2232, +644, +10, -622, -1590, -2129, -1759, -1313, -2053, - +22795, +16811, -6665, +5414, -231, -8963, -2057, +5715, -140, -4502, -1495, -1224, +1967, -1203, -1238, -1944, +128, +141, -1762, +375, -1151, -1442, -293, +2236, +1381, +482, -421, -1050, -2081, -1865, -1013, -2075, - +22156, +16822, -5737, +5914, -531, -9248, -2574, +3914, +921, -3656, -2319, -843, +2476, -1480, -1050, -1438, -455, +614, -1691, -640, -770, -1051, -1218, +1623, +1962, +1863, -702, -1229, -1009, -2137, -1191, -1810, - +21420, +16785, -4799, +6154, -663, -9035, -3372, +2102, +2124, -2833, -3110, -133, +2641, -1601, -638, -1248, -923, +605, -1675, -1249, -658, -53, -1902, +1335, +2038, +2064, +272, -1486, -537, -2097, -1156, -1644, - +21361, +15629, -3750, +6528, -1323, -8215, -4323, +464, +3132, -1840, -3943, +437, +3186, -1861, -582, -1384, -980, +77, -1818, -753, -1149, +490, -779, +520, +1069, +2103, +1599, -1602, -997, -1118, -1205, -1803, - +20330, +15116, -2198, +6125, -1778, -6323, -6028, -1388, +5002, -1330, -4769, +1469, +3125, -2056, -350, -2178, -854, +367, -2722, -22, -540, -99, +456, +351, -11, +1824, +1553, -531, -893, -1195, -631, -1855, - +20062, +13940, -1073, +5901, -2918, -4148, -6485, -3763, +6395, -76, -5571, +1976, +3170, -2469, -500, -2482, -418, +183, -3077, +751, +150, -824, +890, +1089, -685, +923, +962, +419, -69, -1542, -261, -1391, - +21165, +12566, -2644, +7196, -3419, -4374, -5591, -3941, +6004, +491, -4989, +1625, +3132, -2899, -840, -2060, -308, +352, -2926, +725, +461, -401, +854, +946, -597, +286, +687, +245, +522, -714, -834, -655, - +22181, +10753, -4743, +9694, -3820, -6164, -3751, -3237, +4762, +962, -4786, +856, +3566, -3082, -1668, -1292, +74, +282, -2679, +317, +654, +206, +432, +672, -272, -199, +427, +115, +322, +278, -897, -731, - +21833, +9209, -6007, +12315, -3453, -8356, -2210, -1380, +3074, +222, -3684, +199, +3572, -2831, -2010, -495, +19, -33, -2094, +470, +147, +334, +628, +538, -358, +45, -17, -272, +825, +112, -396, -410, - +21222, +7854, -6428, +13904, -3314, -9841, -311, -717, +1107, +600, -2989, -732, +3598, -2074, -2105, -29, +34, -558, -1422, +552, -367, +238, +799, +488, -473, +119, +72, -314, +618, +130, -262, -1, - +19959, +7458, -6254, +13163, -2749, -8575, +168, -1541, +524, +795, -2410, -1167, +3370, -1359, -1981, +131, -37, -600, -1272, +322, -134, +241, +366, +572, -360, -40, +508, -76, -11, +77, -84, -39, - +18263, +7315, -5697, +12058, -1512, -7911, -155, -1097, -277, +440, -1476, -1163, +2794, -682, -1653, -226, +195, -447, -1525, +167, +243, +191, +5, +420, -166, +267, +536, -17, -141, -216, +13, -120, - +14574, +8295, -838, +5767, -2715, -2520, -1691, -1773, +1779, -38, -2463, +993, +2121, -1350, -803, -1187, +196, -325, -1656, +367, -300, -397, +308, +424, +622, +1154, -257, -779, -260, -661, -212, +363, - +12640, +8177, -514, +5232, -1427, -2829, -1332, -1356, +968, +94, -1951, +761, +1867, -950, -840, -1080, +224, -469, -1525, +376, -426, -453, +483, +403, +530, +830, -326, -345, -235, -760, -56, +349, - +11044, +7881, -148, +5139, -839, -2943, -771, -1231, +563, +131, -1472, +726, +1552, -637, -706, -854, +77, -516, -1176, +229, -479, -289, +444, +438, +558, +439, -291, +63, -149, -710, +13, +439, - +9448, +7315, +777, +4791, -766, -2291, -640, -1240, +566, +79, -1184, +670, +1401, -496, -584, -601, -102, -472, -972, +95, -341, -227, +329, +485, +481, +177, -40, +272, -35, -470, -18, +555, - +7784, +6813, +1919, +4053, -580, -1299, -807, -1308, +740, +180, -1143, +616, +1306, -404, -321, -523, -263, -345, -754, -11, -288, -134, +224, +482, +339, +206, +285, +426, +140, -377, +51, +463, - +6153, +6246, +2936, +3514, -265, -522, -963, -1330, +954, +278, -1137, +468, +1183, -27, -199, -727, -188, -39, -737, -145, -161, -167, +296, +467, +191, +475, +664, +574, +50, -370, +118, +236, - +5216, +5838, +3133, +3059, +1, -157, -756, -1165, +778, +326, -848, +372, +928, +178, -109, -801, -20, +104, -796, -199, -47, -58, +362, +449, +343, +811, +845, +385, -220, -311, +33, +113, - +4597, +5368, +3150, +2849, +47, +176, -392, -1164, +650, +523, -570, +155, +748, +467, -67, -777, +130, +87, -748, -20, -18, +143, +685, +510, +516, +926, +646, +76, -295, -314, +101, +201, - +4160, +4800, +2975, +2878, +215, +185, -346, -879, +720, +434, -577, +142, +805, +500, -153, -718, +261, +104, -689, +154, +246, +528, +763, +288, +509, +781, +225, -155, -161, -171, -27, -42, - +4047, +4610, +2554, +2523, +343, +309, -161, -677, +639, +395, -412, +331, +729, +219, -6, -351, +190, +142, -205, +534, +514, +540, +360, +158, +449, +446, +134, -82, -194, -248, -36, -79, - +3681, +4202, +2459, +2522, +468, +335, -124, -483, +720, +451, -371, +292, +718, +292, +137, -143, +474, +547, +124, +441, +403, +249, +3, +182, +383, +387, +48, -193, -191, -244, -51, -202, - +3418, +3958, +2332, +2406, +561, +275, -16, -147, +764, +316, -330, +555, +677, +300, +712, +391, +554, +506, -31, +195, +200, -92, +90, +358, +160, +198, -1, -186, -221, -248, -146, -268, - +3294, +3885, +2237, +2055, +440, +495, +330, -195, +594, +558, -92, +562, +1070, +915, +915, +255, +158, +177, -224, +85, +144, -90, +60, +179, +169, +71, -152, -244, -264, -222, -259, -374, - +3036, +3530, +2299, +2284, +540, +283, +250, +363, +785, +420, +481, +1288, +1245, +678, +546, -172, -123, +52, -133, +151, -76, -120, +87, +168, +37, -127, -184, -303, -217, -273, -383, -412, - +2951, +3684, +2445, +1884, +210, +635, +675, +547, +1250, +1227, +765, +965, +798, +86, +80, -228, +0, +39, -228, +30, -27, -42, +25, +53, -221, -186, -201, -304, -216, -403, -409, -382, - +2948, +3672, +2453, +1863, +191, +765, +1578, +1710, +1229, +774, +415, +256, +396, -103, +36, -65, -268, -80, -64, -3, -34, -116, -164, -71, -281, -296, -229, -301, -271, -378, -434, -341, - +2843, +3566, +2452, +2150, +1119, +1466, +1682, +1795, +928, -254, -261, +372, +403, -274, -165, -161, -184, -111, -88, -48, -200, -201, -180, -289, -413, -275, -295, -256, -268, -441, -348, -288, - +2564, +4101, +3460, +2647, +1410, +1412, +1574, +983, +11, +28, -27, +71, +225, -244, +4, -163, -265, +10, -151, -168, -99, -187, -352, -372, -357, -210, -195, -232, -258, -356, -289, -290, - +3244, +5969, +3950, +1503, +762, +1387, +767, +390, +603, -90, -364, -54, +452, -41, -367, -79, -184, -274, -111, -48, -196, -322, -399, -360, -258, -194, -183, -224, -289, -330, -316, -345, - +3784, +6054, +3526, +1790, +389, +352, +1278, +1092, -88, -197, +260, -59, +139, +65, -157, -256, -333, -279, -121, -80, -211, -244, -442, -312, -216, -247, -254, -250, -268, -326, -359, -335, - +2822, +5085, +3846, +2069, +435, +648, +1401, +1023, +236, -6, +341, +350, +172, -40, +34, -202, -361, -272, -304, -204, -29, -187, -395, -181, -217, -302, -314, -303, -311, -325, -288, -335, - +2707, +4855, +2989, +1364, +947, +1039, +1087, +968, +768, +256, +227, +682, +564, +111, +39, -39, -213, -415, -274, -193, -240, -136, -135, -139, -171, -174, -321, -402, -386, -337, -287, -323, - +2574, +4549, +2481, +1104, +1330, +907, +475, +1038, +988, +424, +619, +680, +540, +614, +433, -71, -59, -64, -397, -356, -134, -141, -286, +11, +52, -193, -195, -312, -434, -438, -356, -279, - +2422, +4172, +2328, +1283, +1472, +647, +125, +1006, +879, +224, +547, +905, +832, +557, +435, +418, +214, -78, -116, -201, -318, -253, -140, -84, -96, +29, -87, -310, -305, -394, -495, -381, - +2457, +4168, +2312, +1258, +1473, +568, -47, +1024, +903, -67, +189, +852, +771, +615, +723, +347, +177, +387, +190, -226, -97, -8, -307, -173, +62, -42, -182, -125, -211, -363, -347, -400, - +2479, +4135, +2339, +1562, +1610, +192, -248, +1300, +909, -337, +81, +690, +508, +388, +636, +433, +219, +291, +303, +164, +7, +21, +31, -36, -110, -67, -84, -238, -296, -215, -282, -331, - +2624, +4417, +2420, +1461, +1611, +190, -334, +1254, +921, -411, -37, +569, +431, +277, +366, +238, +20, +196, +411, +163, +23, +266, +197, +88, +161, +35, -197, -291, -298, -316, -320, -247, - +2857, +4661, +2448, +1599, +1644, -52, -369, +1426, +846, -542, -64, +578, +333, +106, +438, +207, -300, -149, +268, +191, +20, +247, +302, +342, +299, +211, +96, -235, -456, -375, -272, -328, - +3188, +5067, +2423, +1526, +1665, -114, -379, +1420, +746, -615, -22, +514, +244, +36, +349, +284, -291, -398, -114, +35, -95, +71, +386, +395, +370, +407, +245, -45, -298, -398, -392, -348, - +3392, +5464, +2575, +1426, +1705, -141, -510, +1546, +697, -819, -14, +541, +205, -81, +197, +362, -172, -517, -262, -166, -340, -129, +171, +384, +434, +397, +374, +107, -152, -237, -310, -366, - +3778, +5985, +2547, +1224, +1789, -132, -599, +1611, +647, -931, +4, +483, +130, -67, +79, +336, -105, -481, -339, -274, -374, -355, -90, +280, +364, +297, +401, +185, -84, -89, -184, -264, - +4238, +6510, +2468, +1077, +1860, -270, -600, +1756, +466, -1066, +75, +520, -27, -200, +61, +302, -74, -470, -390, -308, -412, -437, -214, +90, +251, +154, +227, +157, -56, -78, -125, -116, - +4791, +7085, +2292, +969, +1933, -473, -530, +1936, +231, -1156, +164, +537, -117, -309, +2, +238, -84, -390, -352, -407, -462, -398, -204, -73, +172, +87, +45, +57, -238, -129, -20, -64, - +5298, +7657, +2183, +875, +2016, -753, -494, +2218, -13, -1312, +267, +578, -182, -441, -93, +196, -122, -393, -302, -435, -513, -440, -113, -135, -14, +190, -70, -156, -337, -293, -128, -66, - +5772, +8287, +2120, +701, +2131, -1043, -540, +2502, -218, -1459, +344, +564, -207, -513, -279, +141, -129, -411, -314, -481, -509, -495, -83, -55, -189, +147, -1, -322, -411, -420, -358, -159, - +6156, +8940, +2162, +466, +2269, -1223, -655, +2753, -350, -1564, +441, +587, -308, -513, -366, -30, -129, -409, -289, -486, -560, -558, -73, +140, -206, -105, +70, -261, -507, -464, -575, -293, - +6742, +9493, +2028, +426, +2287, -1512, -626, +2857, -609, -1493, +499, +542, -410, -555, -338, -271, -242, -367, -235, -522, -637, -614, -88, +199, -77, -219, -130, -145, -572, -543, -605, -493, - +7455, +9892, +1817, +673, +2165, -1782, -526, +2877, -874, -1369, +613, +482, -471, -664, -187, -495, -430, -293, -210, -463, -712, -671, -39, +162, -43, -26, -317, -285, -509, -579, -619, -592, - +8019, +10193, +1826, +947, +2060, -1895, -616, +2838, -973, -1270, +603, +513, -417, -884, -78, -555, -646, -328, -167, -385, -659, -776, -74, +250, -111, +117, -295, -476, -508, -590, -658, -581, - +8488, +10358, +1977, +1265, +2015, -1887, -920, +2788, -1005, -1210, +617, +441, -268, -1020, -166, -487, -785, -574, -79, -286, -605, -796, -270, +464, -155, +23, -164, -502, -600, -692, -661, -560, - +9032, +10338, +2002, +1761, +2191, -2067, -1283, +2872, -1174, -1205, +746, +309, -249, -938, -329, -531, -744, -897, -123, -86, -627, -738, -388, +469, +0, -188, -125, -361, -727, -819, -607, -613, - +9864, +10088, +1523, +2776, +2578, -2733, -1373, +3075, -1563, -1189, +922, +251, -375, -786, -321, -773, -647, -1025, -380, +85, -536, -746, -274, +305, +98, -159, -216, -318, -746, -852, -593, -682, - +10598, +9701, +940, +4274, +3058, -3831, -1125, +3536, -2290, -1265, +1285, +276, -567, -754, -134, -923, -659, -1033, -713, +96, -164, -899, -154, +299, +14, +105, -391, -378, -574, -830, -773, -577, - +10878, +9347, +643, +5807, +3528, -5043, -576, +4279, -3492, -1535, +1951, +350, -873, -858, +153, -941, -755, -1006, -1030, -132, +274, -915, -234, +450, -136, +336, -408, -493, -454, -795, -947, -437, - +11510, +9866, -517, +5809, +4860, -5267, -967, +4693, -4147, -1854, +2440, +298, -1178, -888, +429, -1109, -918, -824, -1173, -606, +385, -531, -456, +537, -109, +345, -322, -566, -435, -822, -1034, -491, - +12635, +10354, -1762, +5073, +6221, -4898, -1391, +4717, -4535, -2049, +2756, +364, -1594, -867, +721, -1229, -1148, -678, -1099, -989, +154, -84, -438, +418, +119, +303, -273, -468, -478, -915, -1048, -631, - +13739, +10931, -3039, +4229, +7036, -3993, -1627, +4425, -4683, -2247, +2950, +515, -2020, -897, +930, -1302, -1368, -646, -958, -1207, -291, +233, -188, +154, +374, +357, -256, -270, -569, -1081, -1002, -747, - +14744, +11698, -4040, +3065, +7514, -2833, -1645, +3985, -4805, -2328, +2928, +769, -2368, -998, +1104, -1337, -1464, -742, -746, -1258, -738, +270, +219, -28, +461, +565, -183, -98, -674, -1208, -1015, -822, - +15661, +12563, -4797, +1712, +7684, -1798, -1303, +3560, -5128, -2181, +2756, +928, -2517, -1206, +1167, -1348, -1484, -913, -576, -1200, -996, -13, +556, +59, +345, +829, -12, -35, -778, -1229, -1099, -956, - +16364, +13610, -5417, +358, +7606, -1081, -694, +3363, -5713, -1853, +2574, +824, -2410, -1460, +1029, -1325, -1426, -1134, -452, -1081, -1063, -425, +647, +304, +234, +1059, +210, -50, -832, -1188, -1210, -1113, - +17301, +14490, -6249, -381, +7171, -884, +239, +3371, -6504, -1381, +2548, +400, -2128, -1591, +701, -1356, -1209, -1399, -313, -902, -1081, -684, +503, +524, +231, +1359, +398, -161, -776, -1179, -1300, -1239, - +19090, +14422, -7537, +119, +6088, -1186, +1568, +3110, -7218, -739, +2538, -295, -1756, -1656, +234, -1424, -1032, -1537, -233, -694, -1129, -779, +292, +571, +268, +1771, +559, -457, -623, -1262, -1420, -1267, - +20805, +14336, -8736, +920, +4704, -1494, +2649, +2925, -7561, -328, +2504, -973, -1224, -1901, -205, -1369, -1023, -1413, -248, -538, -1010, -940, +175, +531, +207, +2290, +770, -842, -494, -1328, -1610, -1150, - +22109, +14485, -9555, +1595, +3405, -1875, +3399, +2878, -7467, -159, +2320, -1375, -756, -2191, -602, -1235, -972, -1286, -262, -418, -788, -1088, +82, +594, -8, +2708, +1095, -1168, -535, -1285, -1751, -974, - +22911, +14859, -9889, +1889, +2263, -2415, +3753, +2933, -7127, -227, +1986, -1630, -415, -2450, -1051, -1037, -827, -1434, -165, -366, -647, -1068, -154, +882, -368, +2616, +1524, -1241, -905, -1145, -1703, -979, - +23245, +15363, -9604, +1856, +1322, -3040, +3776, +3098, -6633, -350, +1568, -1819, -103, -2618, -1435, -794, -655, -1757, +41, -318, -654, -746, -459, +1267, -738, +1911, +2006, -928, -1339, -994, -1484, -1026, - +23048, +16128, -8809, +1596, +486, -3594, +3405, +3364, -5994, -577, +1227, -2110, +338, -2650, -1697, -633, -515, -2058, +200, -158, -867, -14, -786, +1297, -792, +869, +2115, -163, -1403, -1180, -994, -927, - +22809, +16473, -7468, +1279, -304, -4094, +2691, +3769, -5530, -656, +858, -2440, +917, -2540, -1937, -596, -384, -2335, +377, -58, -950, +797, -1345, +1069, -434, -289, +1797, +898, -1234, -1327, -340, -1167, - +22287, +16759, -6019, +907, -957, -4847, +1807, +4137, -5333, -671, +434, -2757, +1592, -2484, -2177, -772, -331, -2403, +180, +397, -1148, +952, -1488, +457, +9, -900, +941, +1571, -432, -1370, -331, -1254, - +21687, +17120, -4653, +1201, -1531, -5605, +1233, +4224, -4907, -618, +334, -2824, +2339, -2255, -2444, -777, -345, -2119, +138, +690, -1476, +1035, -1282, -255, +720, -854, -197, +2118, +560, -1484, -235, -840, - +20812, +17571, -3517, +1604, -1925, -6559, +655, +3983, -4426, -559, +260, -2689, +2858, -2122, -2599, -1007, -244, -1381, -668, +771, -1403, +492, -756, -404, +502, +93, -695, +1167, +1322, -839, -247, -943, - +20139, +17539, -2371, +1932, -2101, -7422, -134, +3611, -3812, -412, +185, -2382, +3168, -1970, -3046, -567, -229, -1405, -1029, +419, -1307, +375, -467, -375, +380, +1214, -1001, -411, +2033, -274, -430, -799, - +19753, +17050, -1457, +2572, -2382, -8049, -965, +2983, -2716, -235, -326, -1321, +2916, -2171, -2296, -826, -571, -1104, -1712, +62, -637, +159, -684, +668, +232, +865, +69, -1322, +1025, +254, +67, -588, - +19313, +16611, -863, +3251, -2596, -8557, -2035, +2815, -1745, -84, -572, -839, +2943, -1918, -2229, -1014, -802, -1378, -1915, +318, -814, +322, -33, +499, +177, +995, +794, -1733, -313, +324, +698, -311, - +19432, +15373, -280, +4094, -3296, -8664, -2599, +2170, -225, -30, -1542, +594, +2691, -2281, -1544, -1686, -1307, -903, -1915, -153, -126, +698, -360, +340, +825, +1064, +273, -993, -998, -689, +1129, +142, - +19161, +14270, +164, +4902, -4023, -8420, -3080, +1712, +839, +173, -2097, +1066, +2771, -2396, -1584, -2406, -841, -783, -2457, +724, +24, +6, +115, +460, +603, +1331, -24, -638, -844, -1849, +898, +543, - +18185, +13294, +1396, +5056, -4975, -6537, -4217, +256, +3477, -142, -3597, +2330, +2565, -2744, -1485, -2544, -786, -568, -2073, +767, -278, -87, +712, +47, +286, +1855, +49, -975, -401, -2019, -110, +720, - +18313, +12559, +1145, +3915, -4788, -4611, -4800, -248, +4385, -385, -3737, +2444, +2059, -2542, -1236, -3085, -90, -60, -2227, +677, -342, +170, +590, -167, +444, +1928, +89, -943, -588, -1828, -345, +588, - +19047, +11703, -955, +4365, -4893, -3853, -3267, -1533, +4299, +134, -4009, +2112, +2030, -2635, -1305, -2227, -55, -224, -2038, +767, -148, -368, +345, +393, +586, +1413, +142, -763, -846, -1547, -218, +199, - +19014, +10464, -2335, +5732, -4481, -4151, -2526, -849, +3281, -472, -3208, +1847, +1902, -2824, -779, -1622, -183, -396, -1924, +1079, -378, -665, +394, +566, +672, +1279, -35, -701, -812, -1354, +31, +44, - +18162, +9492, -3044, +7090, -3964, -4906, -1033, -851, +1796, -66, -2783, +1424, +1900, -2369, -665, -1270, -198, -516, -1532, +747, -522, -404, +331, +314, +897, +1359, -338, -718, -601, -1136, +5, +342, - +16598, +8667, -2195, +6902, -3696, -3649, -980, -1771, +1921, -11, -2768, +1203, +2093, -1882, -722, -1121, -151, -296, -1570, +398, -363, -287, +171, +326, +918, +1214, -295, -849, -425, -762, -169, +362, - +14574, +8452, +258, +4430, -4365, -2407, +102, -220, -223, -832, -1852, +1615, +1202, -2022, +253, -1216, -444, -63, -1455, +368, -312, -727, +373, +217, -412, +849, +339, -186, +129, -916, -296, -195, - +12278, +8141, +1428, +3486, -3243, -1249, -493, -560, +165, -592, -1924, +1327, +1447, -1595, +92, -1011, -282, -108, -1214, +238, -313, -593, +289, +150, -236, +853, +317, -36, -85, -842, +19, -3, - +9818, +8134, +2487, +2440, -2082, -590, -823, -829, +309, -432, -1752, +1141, +1209, -1118, +27, -830, -297, -203, -900, +148, -415, -552, +316, +48, -77, +666, +249, +139, -158, -658, +206, +196, - +8218, +7700, +2637, +2474, -1307, -764, -546, -580, +192, -485, -1350, +993, +1042, -888, +8, -569, -372, -127, -680, -31, -355, -306, +131, -53, +119, +550, +383, +249, -130, -272, +357, +9, - +7260, +6952, +2528, +2729, -947, -957, -177, -207, -119, -455, -915, +762, +893, -798, +106, -330, -495, -95, -429, -94, -346, -203, -44, +24, +289, +567, +633, +250, -96, -40, +210, -228, - +6314, +6251, +2666, +2794, -629, -891, -34, +102, -183, -316, -716, +491, +887, -525, +110, -285, -414, +113, -262, -316, -185, -38, -118, +319, +459, +666, +731, +112, -104, -55, +52, -322, - +5417, +5613, +2827, +2816, -327, -838, +28, +455, -189, -286, -591, +343, +896, -378, +146, -174, -275, +223, -276, -286, +110, +144, +58, +429, +461, +747, +496, -173, -50, +14, -42, -390, - +4737, +5252, +2774, +2553, +28, -656, +97, +596, -174, -128, -477, +136, +904, -37, +86, -133, -68, +253, -71, +76, +414, +107, +44, +523, +339, +397, +292, -77, +23, -24, -184, -339, - +3981, +4689, +2974, +2705, +128, -673, +191, +862, -76, -188, -396, +170, +926, +95, +102, -7, +257, +567, +232, +227, +237, +46, +2, +205, +229, +329, +244, -63, +38, -31, -270, -262, - +3639, +4461, +2924, +2330, +166, -438, +386, +823, -29, -56, -316, +227, +932, +175, +339, +566, +570, +436, +183, +186, -95, -222, +17, +187, +153, +207, +145, +26, +72, -187, -282, -293, - +3259, +4171, +2982, +2255, +67, -366, +661, +923, -74, +111, -202, +162, +1330, +741, +513, +485, +402, +353, -62, -283, -157, +6, -120, +24, +146, +186, +148, -35, -33, -267, -322, -309, - +3122, +4118, +2900, +1944, +0, -98, +882, +1021, -181, +159, +515, +745, +1264, +473, +425, +351, -23, -30, -118, -265, -166, -97, -186, +192, +98, -114, +91, +11, -210, -322, -297, -412, - +3235, +4303, +2623, +1571, +77, +285, +881, +1185, +547, +613, +652, +402, +925, +370, -45, -8, +19, -59, -264, -364, +11, +81, -230, -1, -128, -117, +119, -34, -321, -411, -265, -385, - +3389, +4725, +2245, +1203, +58, +908, +2020, +1399, +334, +357, +538, +113, +387, +96, +39, -34, -209, -107, -173, -4, +62, -200, -339, -98, -124, -103, +123, -133, -427, -315, -196, -296, - +3432, +4882, +1947, +1109, +1266, +1747, +1687, +1007, +236, +86, +163, -84, +293, +0, -42, -68, -271, +122, +155, -210, -251, -156, -291, -288, -163, +38, -58, -180, -248, -250, -248, -317, - +3101, +4702, +2964, +1975, +929, +1541, +1764, +744, -57, -59, +188, -44, +87, -46, -2, +54, +100, +125, -120, -181, -166, -232, -402, -239, -149, -71, +43, -36, -164, -289, -356, -319, - +3896, +5904, +2447, +896, +1159, +1573, +1310, +595, -175, -62, +179, +2, +162, -166, +142, +495, +86, -291, -23, -10, -305, -361, -351, -199, -209, +43, +163, +6, -270, -382, -312, -377, - +4111, +6381, +2053, +273, +1154, +1396, +1209, +828, +5, -261, +331, +111, +75, +99, +333, +466, -15, -97, -25, -78, -294, -279, -352, -332, -105, +81, +175, -17, -195, -388, -359, -345, - +3095, +5772, +3360, +570, +281, +922, +1379, +1273, +83, -225, +436, +376, -8, +55, +499, +520, +210, -84, -45, +41, -164, -351, -289, -251, -244, +17, +144, +52, -153, -277, -319, -362, - +2581, +5083, +3747, +1205, +166, +554, +1050, +1250, +302, -212, +397, +598, +127, +67, +436, +383, +436, +172, +39, +53, -182, -180, -149, -287, -291, -5, +118, -12, -207, -177, -214, -333, - +2552, +4951, +3531, +1372, +349, +359, +972, +1271, +183, -443, +321, +679, +210, +58, +442, +429, +340, +218, +211, +180, -63, -124, -120, -161, -112, -103, +24, +72, -222, -300, -275, -209, - +2665, +4956, +3357, +1460, +482, +248, +879, +1296, +212, -508, +150, +505, +100, +12, +412, +341, +306, +406, +139, +62, +128, -3, -44, -39, -12, -31, +66, +41, -175, -338, -364, -294, - +2910, +5172, +3202, +1418, +526, +219, +908, +1323, +135, -544, +153, +494, +74, -268, +195, +282, +179, +422, +266, +64, +20, -95, +137, +155, -18, +190, +178, +50, -99, -282, -367, -378, - +3106, +5510, +3157, +1272, +654, +172, +826, +1393, +101, -594, +108, +460, +164, -335, -22, +133, -125, +219, +461, +52, -105, -110, +31, +176, +54, +285, +298, +145, +61, -223, -389, -316, - +3368, +5932, +3118, +1145, +758, +78, +765, +1468, +37, -717, +138, +457, +120, -290, -144, +62, -257, -129, +404, +63, -206, -153, -100, +152, +60, +155, +386, +264, +71, -31, -197, -377, - +3733, +6456, +3058, +942, +889, +25, +681, +1552, -15, -820, +148, +459, +69, -211, -190, -47, -265, -323, +274, +169, -372, -347, -72, +87, +21, +34, +374, +281, +11, +98, -68, -219, - +4188, +7066, +2967, +691, +995, -34, +635, +1651, -188, -887, +235, +437, -43, -227, -100, -139, -354, -381, +96, +266, -304, -584, -157, +39, -36, +7, +204, +218, +59, +6, -48, -108, - +4746, +7725, +2804, +457, +1072, -163, +664, +1759, -458, -963, +395, +430, -203, -287, -43, -200, -465, -426, -10, +200, -148, -659, -283, +63, -164, -51, +108, +49, +5, -21, -57, -176, - +5293, +8424, +2691, +200, +1075, -352, +722, +1883, -811, -1091, +593, +430, -407, -391, +9, -266, -633, -524, -73, +107, -103, -596, -428, +55, -134, -199, +69, -190, -167, +13, -143, -226, - +5863, +9141, +2667, +40, +1052, -543, +868, +2094, -1172, -1177, +878, +497, -546, -487, +104, -257, -732, -597, -153, +94, -40, -473, -388, -65, +22, -141, -52, -184, -372, -50, -90, -264, - +6256, +9830, +2894, -163, +970, -781, +879, +2372, -1514, -1408, +1131, +611, -714, -628, +124, -250, -817, -728, -318, +48, +3, -481, -237, -140, -63, +59, -165, -299, -349, -283, -158, -207, - +6594, +10538, +3188, -331, +878, -910, +803, +2530, -1667, -1658, +1306, +784, -813, -792, +152, -249, -880, -762, -546, -74, +192, -563, -200, +88, -247, +128, -7, -470, -416, -264, -343, -125, - +6837, +11211, +3624, -582, +873, -887, +585, +2486, -1630, -1804, +1272, +974, -837, -900, +104, -254, -971, -753, -648, -416, +302, -345, -395, +287, -167, -70, +229, -446, -659, -259, -391, -167, - +7304, +11778, +3694, -565, +932, -974, +429, +2281, -1610, -1825, +1167, +1061, -833, -962, +48, -273, -1134, -738, -667, -706, +131, -22, -389, +150, +154, -245, +198, -184, -827, -453, -344, -269, - +8235, +12147, +3165, -179, +1250, -1280, +244, +2247, -1802, -1646, +1035, +1095, -763, -1091, +127, -372, -1161, -866, -623, -801, -185, +121, -30, -44, +248, -32, -42, -16, -686, -726, -403, -227, - +9297, +12266, +2226, +787, +1787, -2113, +102, +2510, -2139, -1611, +994, +1052, -665, -1269, +199, -511, -1125, -991, -710, -778, -421, -49, +341, +106, +24, +220, -125, -69, -467, -801, -641, -218, - +10147, +12083, +1353, +2463, +2227, -3535, +293, +3115, -2724, -1863, +1270, +952, -736, -1330, +259, -696, -1131, -995, -849, -797, -533, -301, +461, +439, -103, +301, -72, -178, -379, -650, -774, -450, - +10811, +11594, +849, +4553, +2308, -5080, +959, +3783, -3596, -2129, +1832, +791, -1018, -1161, +326, -938, -1147, -869, -944, -907, -502, -461, +355, +652, +38, +401, -29, -244, -390, -373, -749, -645, - +12468, +11803, -955, +4782, +3329, -5109, +523, +3592, -3808, -2001, +2054, +456, -1328, -944, +309, -1271, -1148, -913, -864, -1037, -475, -486, +86, +849, +201, +318, +27, -164, -495, -300, -684, -554, - +14105, +12174, -2678, +4502, +4313, -4564, -152, +3309, -3818, -1885, +2202, +220, -1631, -822, +354, -1654, -1062, -1037, -689, -1076, -553, -275, -262, +847, +479, +306, -29, -31, -462, -290, -612, -344, - +15495, +12899, -4263, +3779, +5080, -3531, -900, +2885, -3629, -1828, +2258, +22, -1763, -951, +442, -1975, -1049, -1113, -557, -940, -769, +0, -446, +597, +677, +483, -199, +94, -302, -403, -398, -267, - +17119, +13318, -5617, +3044, +5263, -2373, -1299, +2236, -3473, -1545, +2114, -220, -1690, -1270, +432, -2146, -1156, -1068, -496, -761, -890, +68, -296, +183, +744, +728, -384, +229, -162, -523, -141, -307, - +18484, +13996, -6861, +2361, +5043, -1327, -1316, +1482, -3224, -1275, +1889, -488, -1425, -1754, +345, -2172, -1331, -893, -513, -608, -886, +7, -57, -56, +527, +1062, -513, +203, +21, -599, -22, -277, - +19664, +14808, -7930, +1852, +4472, -629, -944, +743, -2898, -1130, +1684, -714, -1190, -2160, +165, -2109, -1400, -723, -585, -442, -817, -87, +159, -22, +135, +1403, -577, -74, +264, -623, -30, -70, - +21117, +15043, -8651, +1665, +3562, -302, -433, +306, -2732, -998, +1479, -897, -1082, -2373, -85, -2001, -1270, -757, -612, -253, -784, -73, +231, +244, -130, +1411, -530, -488, +338, -544, +88, +69, - +22154, +15465, -8959, +1402, +2531, -346, +86, +155, -2719, -964, +1298, -1197, -837, -2538, -368, -1715, -1223, -911, -611, -54, -781, -33, +268, +653, -384, +1073, -318, -957, +90, -192, +241, +104, - +22859, +15907, -8818, +1234, +1297, -584, +637, +95, -2746, -892, +980, -1473, -344, -2665, -593, -1404, -1232, -1113, -586, +219, -920, +190, +386, +763, -501, +647, -217, -1200, -157, -60, +514, +428, - +23324, +16162, -8220, +1233, -271, -830, +1044, +4, -2761, -848, +545, -1644, +393, -2819, -805, -1116, -1381, -1232, -481, +245, -798, +446, +127, +832, -496, +109, -143, -1012, -512, -218, +1023, +636, - +23496, +16326, -7279, +1262, -1985, -1155, +1282, -135, -2863, -819, +135, -1617, +1191, -3031, -953, -1076, -1474, -1177, -641, +567, -852, +321, -9, +770, -595, -103, +21, -1077, -316, -427, +637, +1058, - +23095, +16685, -5961, +1382, -3468, -1694, +1418, -258, -2996, -670, +47, -1596, +2016, -3064, -1350, -839, -1582, -979, -545, +371, -989, +403, -350, +690, -257, -300, +78, -651, -207, -824, +183, +1360, - +23064, +16194, -4345, +1405, -4772, -2458, +1309, -309, -3246, -87, -265, -1329, +2641, -3203, -1669, -828, -1062, -1045, -1017, +329, -1074, +156, -379, +809, -266, -110, +348, -721, -327, -460, -318, +476, - +22166, +16307, -2720, +1513, -5503, -3602, +868, +57, -3167, +189, -262, -1102, +3165, -3419, -1892, +19, -1444, -1300, -1087, -50, -1052, +281, -440, +743, +297, +10, -121, -326, +62, -941, -205, -296, - +21370, +16040, -1198, +1538, -5866, -4987, +180, +1090, -3147, +120, +48, -770, +2709, -2688, -1726, -511, -1299, -1588, -1418, -44, -787, -13, -172, +1224, -173, +86, +190, -419, +152, -1134, +61, -580, - +20588, +15763, -447, +2263, -6362, -6502, +294, +1839, -3312, +732, -314, -780, +3610, -2936, -1826, -471, -1919, -1347, -1286, -339, -634, +489, -63, +635, +27, +550, -117, -722, +816, -1169, -430, +0, - +20517, +14351, +399, +2893, -7361, -6720, +201, +2186, -2610, +382, -514, +112, +3193, -2866, -1734, -1281, -1564, -810, -1919, -87, +325, -151, -301, +1086, -74, +249, +48, -598, +812, -904, -810, +141, - +19676, +13347, +1269, +2990, -7493, -6742, +83, +2235, -1954, +838, -1855, +980, +3383, -3609, -1607, -1296, -1241, -963, -1499, +306, -188, -169, +134, +680, -311, +474, +114, -498, +603, -657, -632, -512, - +18294, +12994, +1651, +2477, -6776, -5594, -1193, +2361, -74, -729, -2110, +2060, +2280, -3521, -925, -1755, -1040, +4, -1831, -24, +217, -146, -194, +523, -89, +412, +148, -368, +547, -585, -520, -748, - +18558, +12123, -346, +2881, -6362, -4645, -59, +1181, -164, -263, -2409, +2048, +1834, -3453, -616, -1525, -435, -206, -2101, +563, +264, -775, -79, +639, -65, +370, -42, -65, +678, -907, -609, -386, - +17685, +10480, -40, +3473, -6519, -2739, -508, +476, +794, -1230, -2572, +2593, +1476, -3576, +141, -1207, -497, -277, -1926, +798, -90, -892, +128, +624, -265, +467, +194, -122, +569, -901, -567, -322, - +16309, +9199, +186, +4082, -5385, -2804, -279, +710, -5, -1375, -2021, +2397, +953, -2773, +531, -1321, -456, -212, -1629, +612, -269, -841, +361, +372, -412, +797, +264, -230, +451, -838, -585, -226, - +15571, +11264, +2379, +478, -10208, -3446, +2999, +3275, -500, -1930, -3348, +266, +1652, -1984, +1186, -362, -580, +611, -665, +483, -71, -639, -236, -683, -414, +551, -551, -99, +973, -315, +229, -109, - +13108, +11000, +3186, +1280, -8696, -4695, +2112, +2705, +415, -824, -3163, -516, +1162, -1069, +990, -408, -449, +725, -557, +276, +252, -440, -211, -595, -598, +266, -697, +52, +1118, -108, +414, -97, - +11346, +10103, +3442, +1763, -7242, -4319, +1504, +1898, +542, -443, -2642, -793, +1114, -726, +553, -274, -403, +642, -397, +111, +268, -218, -281, -579, -486, +53, -591, +203, +993, +104, +363, -159, - +9333, +9181, +4026, +1891, -5737, -3665, +628, +1442, +686, -179, -2080, -924, +1011, -560, +271, -128, -344, +546, -210, +21, +313, -35, -349, -508, -402, +17, -265, +291, +786, +199, +233, -195, - +7824, +8565, +4450, +1794, -4594, -3174, +140, +1252, +671, +30, -1593, -927, +798, -461, +248, -40, -339, +534, -12, -10, +342, +33, -332, -281, -185, +20, -144, +273, +558, +171, +139, -239, - +6337, +7830, +4715, +1908, -3553, -2897, -163, +1081, +702, +211, -1249, -839, +616, -437, +196, +111, -267, +479, +135, +12, +326, +212, -47, -34, -177, -218, -105, +167, +266, +120, +84, -158, - +5342, +7158, +4878, +2188, -2903, -2714, -263, +1026, +804, +276, -973, -621, +425, -432, +323, +229, -177, +523, +156, +236, +666, +314, -37, +11, -270, -439, -68, +145, +155, +196, +77, -226, - +4764, +6717, +4705, +2043, -2555, -2349, -213, +866, +792, +353, -756, -574, +302, -362, +407, +259, -158, +679, +475, +400, +570, +170, -131, -157, -526, -408, +47, -28, +159, +57, -96, +32, - +4181, +6120, +4609, +2151, -2225, -2162, -181, +900, +848, +365, -518, -436, +242, -269, +393, +570, +370, +732, +393, +271, +373, -75, -324, -138, -536, -326, +93, -221, -12, +223, +50, -24, - +4015, +5982, +4273, +1823, -2038, -1791, +35, +933, +871, +389, -235, -337, +148, +75, +824, +806, +274, +455, +265, +150, +178, -130, -231, -188, -435, -270, -151, -8, +202, +32, -30, +38, - +3935, +5782, +3945, +1507, -1917, -1335, +323, +927, +964, +503, -86, -55, +602, +326, +626, +524, +61, +238, +130, +138, +142, -108, -297, -233, -424, -97, +144, -211, +2, +11, +59, +102, - +3902, +5745, +3557, +1311, -1656, -1075, +626, +1068, +893, +711, +517, +29, +271, +228, +356, +317, +28, +184, +167, +138, +52, -157, -344, -161, +13, -100, -239, -186, +14, +16, +22, +148, - +3628, +5656, +3399, +1258, -1213, -703, +858, +1220, +1301, +913, +184, -182, +3, -30, +266, +240, +91, +140, +96, +72, +8, -109, -120, +190, -242, -389, -174, -137, -134, -75, +225, -41, - +3635, +5627, +3156, +1153, -667, -305, +1152, +1542, +949, +463, +84, -274, -67, -129, +266, +232, +17, +66, +88, +199, -87, +174, +189, -310, -329, -218, -244, -286, -93, -9, -62, +33, - +3750, +5696, +2978, +1126, -254, +215, +1221, +1141, +606, +286, +8, -220, -48, -224, +233, +223, -143, +120, +323, +31, +156, +458, -282, -324, -203, -336, -370, -173, -80, -307, +26, +219, - +3708, +6007, +3252, +1084, -197, +131, +973, +976, +487, +259, +136, -370, -69, -106, +43, +210, -33, +247, +171, +273, +554, -86, -293, -37, -371, -530, -251, -143, -337, -184, +155, +321, - +3943, +6405, +3364, +855, -445, -300, +746, +1177, +555, +245, +158, -422, -186, -48, +127, +143, +129, +192, +83, +689, +384, -278, -109, -102, -392, -521, -225, -363, -322, +86, +221, +118, - +3963, +6788, +3553, +597, -677, -627, +588, +1136, +500, +391, +206, -514, -153, +22, +70, +197, +285, -39, +123, +985, +227, -286, +1, -155, -441, -352, -267, -542, -311, +209, +364, -112, - +3772, +6899, +3947, +501, -937, -727, +636, +1168, +340, +109, +160, -312, -140, -4, +244, +180, +122, +45, +73, +884, +451, -250, -58, -111, -413, -290, -294, -523, -289, +122, +331, -74, - +3462, +6882, +4502, +695, -1202, -904, +656, +1374, +518, -169, -142, -383, -288, +151, +492, +188, +134, +104, -153, +774, +761, -195, -124, +19, -277, -262, -247, -438, -285, +127, +319, -81, - +3402, +6922, +4775, +801, -1378, -1083, +663, +1537, +602, -245, -249, -453, -540, -124, +493, +404, +124, +134, -71, +426, +838, +18, -287, -73, -153, -110, -193, -451, -296, +175, +269, -23, - +3560, +7157, +4846, +842, -1601, -1246, +801, +1630, +679, -335, -317, -376, -611, -299, +272, +320, +96, +184, +134, +295, +750, +284, -376, -324, -110, -14, -46, -352, -273, +168, +253, +68, - +3781, +7518, +5064, +780, -1878, -1426, +861, +1887, +678, -490, -323, -360, -585, -337, +124, +225, -92, -87, +272, +304, +648, +580, -207, -590, -353, -33, +88, -214, -276, +256, +259, +93, - +4023, +8013, +5260, +520, -2126, -1537, +904, +2110, +621, -684, -367, -338, -545, -334, +31, +151, -90, -326, +98, +316, +484, +602, +136, -551, -624, -186, +88, -177, -281, +258, +226, +119, - +4437, +8672, +5470, +189, -2426, -1777, +1004, +2534, +471, -984, -417, -281, -536, -313, +40, +69, -119, -424, -33, +239, +301, +445, +325, -371, -639, -347, -13, -119, -335, +161, +141, +68, - +4952, +9349, +5539, -179, -2758, -2011, +1219, +2888, +279, -1276, -463, -211, -592, -300, +102, -4, -169, -480, -76, +194, +168, +301, +339, -242, -691, -395, -6, -107, -357, +112, +26, -204, - +5239, +10282, +5947, -647, -3196, -2226, +1311, +3315, +161, -1681, -491, -173, -597, -373, +170, -45, -294, -440, -175, +126, +127, +78, +331, -124, -648, -478, -149, -83, -176, +24, -84, -362, - +5839, +11149, +6005, -1123, -3665, -2327, +1613, +3627, -71, -2065, -429, -99, -639, -410, +251, -61, -421, -436, -166, +117, +55, -75, +317, -59, -558, -473, -198, -174, -157, +173, -146, -406, - +6264, +12031, +6260, -1503, -4165, -2511, +1902, +3881, -220, -2443, -428, +51, -706, -495, +320, -9, -559, -492, -144, +113, +44, -260, +228, +46, -480, -381, -268, -203, -217, +218, -114, -429, - +6813, +12945, +6569, -1945, -4848, -2783, +2188, +4127, -523, -2951, -443, +204, -809, -654, +274, +56, -695, -599, -243, +84, +37, -469, +12, +64, -398, -293, -252, -328, -254, +98, -55, -527, - +7209, +13717, +6921, -1967, -5316, -3090, +2544, +4308, -606, -3304, -485, +501, -832, -729, +300, +116, -725, -556, -280, +71, +96, -513, -156, +86, -225, -237, -54, -372, -184, +51, -70, -428, - +7996, +14426, +6885, -1822, -5825, -3511, +3030, +4353, -912, -3620, -593, +764, -830, -921, +358, +119, -837, -534, -312, +44, +63, -481, -430, -53, +49, -227, +88, -308, -219, +114, -168, -425, - +8882, +15071, +6412, -1835, -5966, -3673, +3408, +4119, -1227, -3662, -763, +899, -746, -1111, +359, +151, -942, -516, -330, +17, -16, -403, -535, -393, +280, -94, +75, -119, -291, +140, -109, -538, - +10567, +15752, +4909, -1935, -5684, -3567, +3668, +3636, -1744, -3453, -930, +847, -522, -1336, +279, +135, -969, -534, -297, -7, -169, -364, -497, -748, +299, +223, -60, +142, -209, -44, +74, -643, - +11943, +15859, +3693, -1168, -5342, -4152, +3859, +3672, -2239, -3456, -946, +824, -414, -1484, +211, +82, -987, -499, -174, -100, -272, -362, -415, -898, +70, +599, -127, +237, +12, -204, +166, -634, - +13286, +15772, +2438, -128, -4984, -4823, +4009, +3750, -2786, -3502, -799, +696, -411, -1556, +156, -56, -1055, -395, +29, -275, -377, -305, -450, -921, -205, +832, -22, +179, +243, -241, +88, -561, - +15203, +16245, +66, +61, -3930, -4645, +3668, +3392, -3154, -3516, -581, +453, -338, -1692, +34, -193, -1068, -347, +256, -295, -574, -274, -592, -759, -402, +757, +277, +182, +289, -131, -87, -538, - +17246, +16423, -2122, -11, -3063, -3961, +3236, +2949, -3315, -3590, -360, +310, -300, -1854, +21, -379, -1001, -238, +408, -257, -762, -185, -742, -584, -408, +586, +464, +330, +189, -58, -105, -673, - +19117, +17194, -4525, -594, -2040, -2928, +2541, +2436, -3174, -3955, -153, +154, -238, -2084, -35, -538, -893, -103, +477, -124, -1066, -60, -862, -458, -281, +408, +389, +584, +66, -198, +49, -844, - +20721, +17777, -6299, -1368, -1442, -1849, +1965, +2056, -2976, -4357, -43, +20, -202, -2215, -94, -626, -745, -20, +462, +11, -1311, +50, -912, -421, -24, +317, +54, +773, +39, -439, +197, -803, - +22510, +18390, -7885, -2507, -1141, -610, +1490, +1800, -2821, -4825, -36, -196, -92, -2264, -98, -656, -568, +0, +406, +174, -1496, +186, -1014, -271, +276, +136, -341, +713, +119, -602, +263, -543, - +23764, +19077, -8920, -3523, -1276, +188, +1429, +1689, -2771, -5201, -193, -427, +128, -2191, -88, -582, -532, -60, +345, +366, -1555, +193, -996, -85, +266, +23, -631, +431, +299, -553, +232, -344, - +24818, +19733, -9528, -4328, -1918, +770, +1688, +1610, -2757, -5522, -511, -645, +585, -2065, -55, -440, -631, -162, +378, +612, -1616, +251, -901, -119, +151, -32, -905, +195, +543, -403, +171, -190, - +25942, +20257, -9828, -5006, -3337, +1229, +2251, +1491, -2816, -5884, -1016, -737, +1357, -2026, +75, -408, -894, -120, +477, +717, -1428, +314, -1223, -176, -2, -219, -932, +91, +634, -169, +260, -194, - +26806, +20370, -9612, -5429, -4920, +1516, +2696, +1428, -3018, -6052, -1361, -633, +1984, -1981, +130, -617, -894, -5, +427, +963, -1258, -100, -1423, -216, -233, -165, -732, -55, +587, +188, +254, -445, - +27209, +20584, -8793, -5848, -6861, +1389, +3245, +1326, -3300, -5756, -1708, -571, +2761, -2008, -124, -572, -811, +83, +640, +854, -1485, -319, -1727, -286, -130, -52, -610, -82, +598, +192, +317, -394, - +26893, +21151, -7832, -5916, -8592, +716, +3831, +1043, -3056, -5275, -2081, -436, +3209, -2095, -313, -337, -686, +446, +148, +578, -1361, -677, -1772, -79, -85, -62, -326, -96, +288, +256, +729, -628, - +26953, +20650, -6193, -5839, -10706, -128, +4025, +1350, -2673, -4655, -2334, -397, +3476, -2270, -280, +333, -640, -63, -135, +292, -1261, -713, -1609, +24, -62, +134, -367, -195, +342, +253, +839, -600, - +26223, +20702, -4716, -5564, -12304, -1451, +4411, +2099, -2421, -4083, -2432, -598, +3439, -2035, +238, +317, -1138, -105, -496, +286, -908, -750, -1436, +173, -78, -80, -177, -33, +173, +164, +1062, -575, - +25928, +19969, -3485, -5141, -13936, -2549, +5094, +2717, -2372, -3260, -2726, -1115, +3984, -1704, +8, +193, -1565, -173, -413, +254, -689, -651, -1111, -74, -302, +129, -24, -206, +176, +212, +1048, -582, - +25176, +19122, -2331, -4479, -15530, -3096, +5493, +3261, -1783, -2862, -3340, -611, +4094, -2064, +150, -498, -1520, +306, -690, +346, -212, -559, -1329, -185, -92, +42, -36, -161, +240, +170, +921, -542, - +24482, +17970, -1385, -4296, -15673, -3520, +5482, +4107, -1928, -2384, -3245, -840, +4078, -2209, -307, -382, -1158, +232, -617, +670, -229, -809, -1085, -111, -314, +49, +102, -188, +256, +76, +933, -522, - +23018, +16730, -558, -3503, -15157, -4048, +5380, +4222, -1077, -2064, -4052, -288, +3518, -2565, -42, -296, -1035, +526, -341, +255, -181, -591, -933, -333, -446, +264, +149, -398, +317, +312, +625, -550, - +21612, +15388, -80, -2338, -14307, -4401, +4806, +4911, -877, -2366, -3925, -404, +3244, -2585, +155, -320, -674, +881, -905, +291, +164, -706, -883, -428, -426, +443, -108, -467, +714, +169, +330, -367, - +19859, +13489, +594, -510, -13595, -4524, +5021, +4279, -755, -2023, -4414, +179, +2843, -2732, +498, -73, -330, +471, -963, +610, +149, -898, -638, -432, -427, +380, -223, -282, +814, +29, +168, -248, - +17742, +12321, +1537, +213, -12421, -3676, +4012, +3612, -294, -2291, -3920, +331, +2249, -2515, +892, +37, -643, +510, -767, +581, +11, -855, -358, -539, -531, +491, -270, -331, +960, -123, +115, -173, - +16821, +11926, +463, -1706, -11380, -169, +5057, +1524, -1492, -1439, -2644, -359, +2193, -2391, +635, +125, -644, +317, -422, +472, -172, -610, -637, -211, -252, -7, -26, -80, -218, -217, +829, -147, - +13656, +11995, +3238, -883, -11164, -2746, +3338, +2611, +688, -1041, -2888, -1083, +1213, -1539, +1161, +189, -818, +634, -355, +123, +274, -342, -515, +152, -873, -436, -4, -321, +327, +309, +783, -46, - +11207, +10925, +3942, -83, -8816, -2936, +2399, +2271, +597, -709, -2174, -1110, +823, -992, +937, +143, -694, +584, -237, +52, +375, -217, -303, +162, -792, -361, +105, -252, +214, +381, +632, -19, - +9243, +9941, +4245, +657, -6939, -2976, +1760, +1792, +578, -304, -1653, -1098, +643, -655, +689, +159, -542, +528, -131, +56, +430, -13, -221, +210, -469, -319, +52, -319, +110, +335, +494, +43, - +7775, +9004, +4364, +1074, -5566, -2771, +1288, +1356, +632, -19, -1266, -996, +487, -456, +486, +214, -418, +456, -8, +91, +463, +193, -8, +266, -378, -438, -88, -360, -112, +272, +544, +30, - +6749, +8329, +4226, +1199, -4454, -2378, +954, +1109, +723, +141, -897, -819, +428, -339, +428, +308, -281, +463, +96, +331, +672, +327, +10, +166, -357, -510, -211, -393, -151, +319, +576, +31, - +5988, +7653, +4116, +1168, -3765, -2038, +743, +915, +737, +259, -623, -668, +285, -262, +442, +295, -206, +564, +342, +402, +543, +169, -105, +70, -443, -594, -251, -433, -272, +334, +502, -77, - +5467, +7250, +3847, +1019, -3110, -1692, +669, +871, +822, +369, -365, -484, +245, -133, +474, +473, +20, +567, +337, +288, +369, +117, -150, +13, -324, -594, -356, -414, -226, +271, +602, +138, - +5122, +6973, +3542, +803, -2565, -1389, +713, +947, +893, +463, -170, -291, +235, +82, +633, +446, -49, +345, +308, +240, +201, +133, -77, -9, -324, -573, -352, -476, -45, +494, +363, +16, - +4855, +6836, +3247, +531, -2098, -1103, +840, +1094, +882, +577, -75, -121, +401, +26, +454, +321, -151, +130, +276, +269, +118, +152, -61, -115, -199, -507, -538, -83, +76, +24, +184, +126, - +4686, +6807, +3020, +381, -1698, -797, +985, +1300, +880, +654, +193, -260, +327, -18, +295, +312, -217, +5, +244, +427, +89, +60, +69, +22, -305, -328, -97, -385, -172, +69, +91, +154, - +4632, +6769, +2880, +360, -1379, -630, +1032, +1346, +1008, +601, +155, -416, +54, +91, +208, +254, -266, -94, +300, +314, +94, +118, +154, -112, -59, +83, -557, -570, -137, +42, +28, +65, - +4540, +6825, +2991, +442, -1145, -666, +903, +1315, +922, +656, +103, -490, -32, -70, +234, +239, -193, -130, +219, +288, +5, +292, +9, +89, +428, -439, -684, -356, -314, -42, +168, -24, - +4565, +7043, +3133, +398, -1092, -628, +698, +1105, +781, +505, +302, -393, -208, -57, +80, +210, -27, -27, +131, +97, +164, +95, +10, +715, +96, -727, -439, -390, -341, +7, +168, -278, - +4628, +7376, +3330, +175, -1131, -632, +658, +1096, +468, +306, +276, -396, -10, -64, +41, +226, -104, +83, +212, +65, +61, -40, +256, +815, -181, -624, -368, -423, -196, +109, -11, -411, - +4617, +7799, +3588, -63, -1282, -806, +761, +1267, +342, +103, +9, -566, -109, +89, +288, +207, -102, +37, +103, +149, +142, -173, +222, +878, -329, -612, -244, -446, -47, +197, -164, -416, - +4660, +8175, +3965, -277, -1581, -952, +885, +1487, +358, +16, -136, -742, -411, +6, +351, +359, +99, +41, +67, +54, +185, -145, +158, +875, -393, -637, -194, -414, +89, +273, -162, -421, - +4721, +8663, +4296, -438, -1910, -1208, +1075, +1666, +396, -64, -205, -776, -575, -199, +234, +288, +60, +190, +260, +39, +105, -43, -107, +796, -78, -840, -343, -310, +149, +286, -89, -348, - +4872, +9194, +4729, -774, -2386, -1225, +1197, +1899, +429, -345, -152, -738, -728, -229, +85, +167, -114, +11, +383, +94, +153, +194, -391, +530, +269, -869, -518, -280, +55, +314, -13, -367, - +5066, +9823, +5271, -1107, -2955, -1313, +1335, +2152, +396, -624, -133, -598, -828, -241, +24, +42, -162, -203, +299, +184, -39, +336, -145, +68, +454, -442, -819, -503, +69, +300, -63, -319, - +5153, +10511, +6095, -1484, -3588, -1456, +1423, +2504, +356, -975, -219, -396, -876, -284, +78, -92, -239, -325, +171, +296, -163, +80, +60, -117, +343, +144, -711, -771, -136, +164, +7, -305, - +5279, +11273, +7005, -1898, -4346, -1576, +1570, +2874, +319, -1413, -325, -192, -896, -360, +145, -111, -363, -399, +61, +261, +19, -193, -117, -56, -9, +423, -34, -872, -482, +162, -138, -388, - +6056, +12428, +7017, -2743, -5015, -1595, +2092, +3133, -74, -1835, -369, -82, -887, -433, +159, -124, -505, -444, +1, +176, +57, -207, -371, -191, -116, +297, +399, -455, -738, -65, -85, -546, - +6550, +13417, +7566, -3351, -5854, -1576, +2466, +3359, -262, -2321, -480, +199, -992, -483, +233, -211, -561, -459, -82, +172, +17, -196, -387, -532, -129, +223, +460, +107, -612, -458, -73, -511, - +7012, +14309, +8271, -3829, -6828, -1561, +2860, +3523, -456, -2805, -697, +575, -1040, -702, +326, -213, -692, -488, -58, +49, +67, -318, -318, -681, -441, +323, +421, +317, -109, -624, -463, -340, - +8016, +15374, +8120, -4423, -7514, -1497, +3500, +3557, -967, -3143, -754, +778, -1014, -873, +371, -263, -697, -565, +8, +40, -65, -294, -389, -676, -607, +208, +557, +311, +173, -239, -863, -535, - +8871, +16239, +8063, -4588, -8132, -1638, +4115, +3491, -1344, -3391, -963, +994, -922, -1121, +393, -248, -762, -536, +34, +55, -184, -324, -431, -662, -593, -42, +629, +427, +134, +214, -755, -1041, - +9741, +17020, +7674, -4576, -8426, -2000, +4611, +3393, -1757, -3551, -1213, +1115, -851, -1378, +299, -217, -824, -499, +46, +51, -282, -489, -415, -741, -447, -171, +355, +641, +79, +272, -284, -1349, - +11312, +17790, +6362, -4799, -8173, -2096, +4973, +3237, -2301, -3658, -1190, +1112, -886, -1482, +185, -250, -754, -451, +117, +102, -439, -579, -427, -793, -304, +10, -28, +635, +235, +100, +114, -1241, - +13177, +18485, +4498, -4942, -7590, -1947, +5032, +3048, -2673, -3843, -991, +968, -867, -1596, +107, -286, -639, -361, +165, +232, -672, -529, -499, -772, -195, +286, -298, +389, +407, -34, +287, -927, - +15061, +19221, +2298, -5197, -6823, -1696, +4782, +2846, -2873, -4171, -778, +660, -800, -1706, -5, -268, -588, -254, +120, +358, -929, -400, -614, -747, -72, +413, -441, -8, +458, -76, +301, -594, - +17417, +19661, -218, -5533, -6027, -1097, +4358, +2666, -3090, -4449, -601, +308, -686, -1718, -14, -284, -463, -238, +124, +408, -1064, -243, -713, -651, +62, +367, -575, -268, +316, -31, +381, -321, - +19867, +19942, -2698, -5917, -5419, -356, +3943, +2529, -3315, -4768, -533, -59, -432, -1576, -30, -272, -359, -356, +203, +452, -1089, -118, -778, -495, +49, +184, -640, -440, +103, +121, +489, -151, - +22000, +20274, -4928, -6244, -5183, +422, +3657, +2387, -3535, -5191, -499, -408, +124, -1486, -39, -209, -489, -410, +327, +558, -1091, -6, -842, -510, -62, +53, -686, -527, +27, +247, +412, +120, - +23867, +20630, -6764, -6611, -5435, +1219, +3584, +2132, -3790, -5664, -426, -579, +849, -1544, +115, -346, -693, -253, +402, +737, -1086, +70, -1208, -570, -77, -89, -681, -321, -84, +142, +497, +304, - +25427, +20921, -8048, -7062, -6069, +1884, +3693, +1754, -4141, -5893, -210, -678, +1594, -1604, +126, -548, -678, -23, +392, +982, -1152, -266, -1531, -447, -207, -3, -478, -227, -288, +201, +484, +187, - +26670, +20956, -8821, -7361, -6968, +2286, +3959, +1161, -4414, -5482, -257, -597, +2261, -1827, +18, -485, -493, +96, +432, +895, -1493, -446, -1665, -450, +33, +175, -509, -150, -228, -15, +349, +351, - +27247, +21029, -9279, -7221, -8186, +2443, +4316, +433, -4111, -5058, -277, -461, +2624, -2135, +8, -68, -470, +172, -50, +659, -1495, -578, -1725, -94, +295, -26, -297, -74, -411, -173, +430, +303, - +27900, +20315, -8903, -7184, -9921, +2431, +4704, +385, -3980, -4367, -496, -493, +2857, -2265, +375, +207, -681, -337, -225, +556, -1409, -535, -1534, +66, +228, +14, -233, -136, -400, -267, +410, +268, - +27607, +19995, -8273, -6960, -11863, +2111, +5727, +206, -3669, -3625, -950, -750, +3372, -2159, +511, +126, -1428, -249, -334, +460, -1027, -385, -1566, +110, +211, -88, -105, -186, -370, -401, +501, +177, - +27622, +18453, -7307, -6733, -13561, +2585, +6218, +129, -3285, -2980, -1630, -393, +3761, -2468, +529, -441, -1518, +13, -480, +602, -588, -563, -1536, +165, +105, -89, -91, -163, -357, -425, +580, -7, - +26712, +17271, -6277, -6285, -14362, +2609, +6500, +415, -3110, -2459, -1751, -325, +3747, -2769, +192, -404, -1346, +67, -259, +700, -500, -685, -1381, +215, -122, -46, -21, -142, -291, -476, +628, -31, - +24769, +16230, -5111, -5257, -14397, +2104, +6670, +474, -2600, -1910, -2144, -355, +3491, -3153, +319, -229, -1416, +584, -304, +502, -383, -651, -1149, -88, -115, +8, -18, -89, -321, -449, +713, -173, - +22531, +14663, -3328, -4140, -13801, +1449, +6057, +1180, -2109, -1891, -2239, -499, +2901, -2827, +365, -277, -887, +650, -524, +392, -96, -669, -1178, -67, -149, -9, +23, -125, -229, -396, +626, -144, - +19895, +13154, -1419, -2898, -12707, +438, +5719, +1680, -2070, -1480, -2520, -641, +2754, -2677, +403, +34, -653, +479, -618, +548, -55, -828, -839, -119, -236, +37, -10, -61, -202, -414, +734, -50, - +15813, +10164, -3306, -1259, -4293, +3357, +1973, -2111, -1944, +200, +219, -308, +1352, -2193, +64, -117, -1126, +153, -436, +60, -137, -521, -663, +805, -86, +19, +120, -674, -64, -483, -254, +28, - +13540, +9962, -1922, -1329, -4062, +2676, +2356, -1429, -1777, +3, -53, -302, +1192, -1816, -26, +30, -863, +65, -256, +68, -137, -483, -700, +634, +28, +18, +255, -495, -126, -392, -252, -65, - +11634, +9561, -699, -1265, -3629, +2134, +2474, -898, -1471, -172, -210, -167, +1001, -1414, -33, +173, -616, +55, -78, +97, -92, -391, -629, +503, +182, +60, +264, -359, -148, -296, -278, -94, - +10116, +9195, +85, -1190, -3168, +1756, +2451, -457, -1159, -296, -215, -72, +824, -1068, +57, +267, -418, +80, +67, +164, -62, -236, -495, +399, +241, +62, +228, -255, -153, -255, -222, -97, - +8972, +8865, +505, -1212, -2723, +1474, +2315, -138, -916, -335, -184, -65, +679, -767, +131, +280, -267, +100, +140, +232, -22, -124, -428, +222, +224, +45, +106, -204, -143, -199, -220, -223, - +8143, +8550, +717, -1226, -2288, +1267, +2150, +132, -720, -286, -144, -49, +640, -554, +197, +300, -154, +119, +220, +280, -45, -61, -392, +43, +178, +16, +16, -111, -123, -218, -232, -196, - +7519, +8353, +812, -1237, -1913, +1117, +2025, +376, -587, -178, -1, -84, +685, -393, +217, +358, -60, +126, +213, +332, -84, -72, -329, -119, +124, +96, -34, -68, -117, -163, -197, -307, - +7138, +8193, +814, -1279, -1576, +1064, +1902, +541, -519, -85, +237, -175, +678, -205, +145, +407, -22, +33, +193, +347, -106, -168, -290, -132, +40, +147, -63, -81, -15, -226, -137, +56, - +6765, +8188, +868, -1293, -1277, +1051, +1806, +584, -405, -124, +486, -108, +449, +28, +127, +224, +67, +7, +73, +339, -51, -243, -320, +0, -67, +74, +55, -80, -93, +50, +86, -210, - +6619, +8107, +942, -1282, -1022, +1117, +1715, +528, -435, -63, +479, +47, +396, -99, +275, +103, -92, +116, +36, +186, -20, -104, -395, -86, -10, +55, +1, -128, +248, +155, -185, -146, - +6506, +8197, +996, -1294, -821, +1178, +1651, +459, -560, -146, +509, -44, +460, -45, +85, +200, -171, -75, +154, +145, -147, -20, -290, -290, -60, +165, -210, +91, +457, -145, -98, -174, - +6582, +8378, +972, -1387, -629, +1360, +1678, +371, -630, -289, +430, -31, +347, +59, +235, +84, -170, +9, -19, +188, -18, -105, -290, -206, -28, -83, -58, +442, +120, -133, +100, -328, - +6729, +8662, +933, -1675, -529, +1529, +1750, +352, -860, -415, +386, -244, +217, +58, +206, +210, -193, -125, +73, +64, -149, +23, -388, -231, +36, -212, +36, +433, -79, -64, +4, -312, - +6891, +9095, +950, -1986, -500, +1682, +1851, +373, -983, -585, +394, -308, -13, -44, +240, +173, -175, +14, +14, +51, -151, -125, -432, -103, +46, -279, +169, +405, -280, -72, +3, -309, - +7140, +9633, +936, -2394, -433, +1844, +1940, +403, -1165, -606, +441, -410, -140, -123, +140, +125, -224, -22, +162, +113, -243, -123, -493, -210, +171, -184, +103, +464, -305, -188, -101, -278, - +7579, +10153, +808, -2790, -377, +2061, +1958, +319, -1378, -620, +599, -484, -299, -248, +140, +31, -407, -65, +163, +117, -205, -114, -553, -215, +158, -225, +53, +587, -241, -398, -127, -310, - +8098, +10746, +572, -3255, -297, +2282, +1951, +145, -1630, -671, +779, -545, -492, -334, +56, -74, -517, -231, +85, +61, -318, -68, -487, -259, +155, -163, -275, +532, +118, -570, -295, -288, - +8856, +11416, +228, -3688, -131, +2625, +1937, -65, -1888, -582, +1023, -544, -642, -393, +130, -159, -647, -205, +40, -68, -349, -125, -337, -110, +114, -18, -391, +244, +381, -387, -478, -229, - +9699, +12034, -166, -4109, -4, +2965, +1853, -341, -2231, -485, +1256, -561, -825, -509, +157, -201, -806, -277, +86, -284, -419, -202, -354, +141, +75, -8, -343, -105, +372, -52, -654, -293, - +10543, +12775, -545, -4510, +87, +3328, +1796, -636, -2510, -451, +1566, -593, -960, -599, +156, -239, -879, -366, +153, -404, -550, -174, -435, +353, +148, -50, -279, -255, +87, +310, -515, -582, - +11200, +13601, -758, -4805, +51, +3618, +1817, -936, -2667, -529, +1865, -619, -1077, -658, +152, -290, -948, -411, +137, -381, -707, -102, -513, +487, +276, -91, -256, -301, -183, +365, -56, -808, - +11970, +14337, -1048, -4982, -71, +3819, +1800, -1224, -2823, -587, +2067, -657, -1227, -698, +129, -342, -1036, -477, +85, -363, -801, -49, -525, +479, +403, -110, -295, -362, -353, +170, +366, -705, - +12952, +14790, -1411, -4961, -192, +3874, +1746, -1433, -2954, -613, +2172, -717, -1346, -744, +115, -409, -1087, -567, +16, -356, -787, -59, -428, +439, +419, -85, -317, -480, -441, -15, +471, -306, - +13912, +15283, -1898, -4796, -288, +3733, +1713, -1566, -3031, -703, +2247, -785, -1394, -782, +55, -432, -1125, -661, -51, -311, -721, -96, -300, +422, +338, -39, -314, -612, -519, -71, +296, +100, - +14855, +15823, -2738, -4516, -305, +3389, +1721, -1674, -3103, -885, +2277, -894, -1325, -878, -28, -456, -1189, -726, -166, -184, -719, -109, -219, +375, +189, +34, -370, -698, -563, -131, +49, +307, - +16338, +16003, -4097, -3971, -183, +3015, +1641, -1812, -3218, -959, +2300, -1062, -1053, -1052, -10, -553, -1252, -711, -213, -61, -766, +9, -305, +359, +93, +64, -446, -677, -520, -329, -54, +380, - +18251, +15738, -5808, -3185, -135, +2789, +1385, -1959, -3407, -901, +2346, -1243, -701, -1229, +42, -723, -1269, -588, -226, -66, -699, +25, -533, +532, -57, +38, -378, -632, -576, -478, +14, +227, - +20108, +15232, -7463, -2359, -182, +2680, +993, -2135, -3628, -757, +2465, -1466, -282, -1397, +30, -889, -1150, -413, -456, +70, -740, -222, -483, +617, -261, +207, -289, -809, -541, -427, -149, +45, - +21818, +14565, -8920, -1528, -323, +2633, +590, -2360, -3741, -408, +2485, -1626, +257, -1681, +37, -834, -979, -443, -529, +77, -986, -154, -547, +693, -157, +334, -410, -839, -327, -606, -328, +75, - +23103, +13939, -10069, -743, -746, +2659, +301, -2677, -3587, -100, +2394, -1612, +709, -2069, +297, -672, -1108, -278, -883, +30, -908, -351, -497, +1045, -177, +252, -316, -804, -379, -726, -359, +57, - +23945, +13086, -10548, -173, -1474, +2865, +166, -2907, -3401, +227, +2202, -1525, +1022, -2203, +552, -677, -1107, -549, -996, +157, -1089, -304, -261, +1165, -310, +418, -308, -941, -344, -785, -396, +51, - +24255, +12118, -10245, -13, -2426, +3265, +310, -3204, -3183, +647, +1733, -1352, +1565, -2480, +734, -599, -1582, -399, -1019, +24, -846, -257, -242, +1202, -199, +374, -346, -1003, -311, -777, -466, +127, - +23709, +11520, -9531, -151, -3388, +3855, +550, -3483, -2789, +731, +1250, -841, +1752, -2633, +801, -862, -1583, -318, -1087, +206, -657, -373, -274, +1353, -271, +302, -334, -1032, -204, -865, -432, +235, - +22428, +11143, -8405, -496, -4041, +4230, +889, -3448, -2615, +728, +1070, -660, +1947, -2748, +486, -621, -1697, -171, -896, +282, -583, -459, -269, +1324, -316, +161, -148, -1048, -191, -833, -297, +216, - +20761, +10556, -6721, -940, -4366, +4259, +1328, -3270, -2442, +888, +519, -254, +1808, -2851, +481, -564, -1534, -32, -625, +157, -458, -456, -349, +1175, -358, +206, -68, -1025, -144, -651, -305, +204, - +18483, +10322, -5051, -1232, -4488, +3998, +1699, -2851, -2083, +521, +346, -174, +1484, -2533, +230, -316, -1365, +115, -496, +12, -245, -474, -558, +987, -219, +124, +13, -912, -46, -573, -264, +159, - +15151, +10407, -3905, -1083, -1883, +2118, +367, -2185, -1952, +542, +790, -175, +1158, -1491, +303, +11, -942, -141, -277, +14, -417, -305, -403, +619, -260, -27, +128, -617, -289, -452, -406, -109, - +12885, +10154, -2446, -1435, -1886, +1994, +819, -1625, -1685, +115, +676, -116, +950, -1122, +70, +152, -656, +7, -100, +33, -249, -339, -518, +467, -154, -64, +221, -437, -240, -376, -360, -167, - +11026, +9815, -1373, -1604, -1732, +1727, +1082, -1042, -1489, -153, +594, -120, +851, -783, -35, +259, -348, +25, +24, +163, -205, -275, -535, +286, -60, -104, +181, -299, -203, -314, -276, -258, - +9638, +9479, -718, -1704, -1525, +1463, +1205, -627, -1291, -289, +532, -105, +728, -476, -29, +265, -147, +9, +102, +238, -168, -228, -548, +99, -70, -181, +55, -160, -166, -274, -267, -318, - +8752, +9179, -333, -1745, -1266, +1296, +1255, -331, -1103, -308, +517, +6, +654, -256, +108, +218, -57, +66, +139, +248, -132, -162, -550, -73, -107, -216, +35, -13, -164, -279, -126, -282, - +8140, +9001, -85, -1784, -995, +1204, +1247, -134, -1072, -291, +536, +70, +685, -204, +206, +280, -165, +40, +195, +187, -211, -72, -529, -292, -102, -127, -36, -76, -58, -138, -270, -89, - +7821, +8936, +29, -1810, -714, +1265, +1138, -40, -1096, -420, +649, +5, +642, -11, +138, +306, -111, -183, +147, +285, -330, -213, -387, -248, -250, -102, -97, -86, +22, -265, +130, +187, - +7807, +9028, -50, -1866, -441, +1451, +1138, -195, -1118, -490, +518, +2, +517, +35, +307, +254, -153, -103, +7, +126, -244, -245, -496, -140, -99, -332, -144, +49, -205, +61, +387, -266, - +7883, +9354, -84, -2058, -175, +1671, +1191, -268, -1313, -554, +542, -204, +353, +81, +268, +401, -95, -139, +119, +41, -495, -190, -362, -215, -155, -154, -74, -308, -29, +393, -17, -331, - +8309, +9731, -294, -2293, +42, +1934, +1203, -363, -1445, -664, +574, -270, +131, -85, +298, +391, -163, +29, +228, -28, -529, -302, -516, -77, -71, -224, -65, -236, +37, +234, -157, -305, - +8910, +10272, -662, -2606, +320, +2118, +1145, -521, -1640, -652, +647, -370, -95, -197, +260, +249, -276, +1, +311, +7, -540, -340, -597, -115, -162, -109, -41, -330, +23, +288, -224, -561, - +9705, +10883, -1159, -2876, +618, +2308, +939, -735, -1827, -569, +847, -551, -252, -350, +282, +190, -540, -53, +297, -89, -533, -247, -636, +1, -229, -304, +0, -239, -164, +169, +30, -627, - +10729, +11542, -1791, -3053, +931, +2475, +682, -1055, -1976, -419, +1145, -742, -457, -399, +293, +130, -657, -195, +215, -136, -668, -129, -569, +112, -117, -431, -109, -273, -261, +33, +231, -480, - +11880, +12255, -2434, -3089, +1163, +2572, +450, -1357, -2085, -232, +1467, -892, -621, -438, +381, +30, -732, -214, +65, -162, -709, -100, -437, +212, -28, -368, -165, -380, -411, -90, +291, -64, - +13138, +12910, -3157, -3037, +1198, +2492, +221, -1627, -2212, -103, +1693, -1094, -727, -513, +408, -69, -857, -306, -36, -187, -773, -78, -367, +223, -33, -259, -244, -476, -574, -270, +164, +260, - +14397, +13579, -3910, -2827, +1090, +2265, +96, -1784, -2287, -52, +1872, -1249, -736, -567, +401, -118, -956, -410, -92, -132, -795, +4, -347, +213, -84, -122, -283, -544, -622, -487, +74, +387, - +15830, +13982, -4898, -2472, +856, +1874, -58, -1916, -2412, -69, +1931, -1394, -672, -679, +358, -219, -1064, -512, -131, -146, -801, +55, -460, +223, -217, -78, -273, -623, -663, -737, +48, +327, - +17467, +14082, -6145, -1897, +641, +1483, -284, -1985, -2544, -62, +2082, -1574, -443, -758, +315, -348, -1052, -474, -316, -34, -792, -77, -456, +264, -381, +42, -169, -787, -651, -765, -87, +204, - +19204, +13692, -7428, -1120, +469, +1144, -634, -1991, -2737, +205, +2197, -1785, +24, -916, +275, -357, -852, -637, -399, +114, -1061, -13, -468, +245, -296, +208, -219, -909, -451, -819, -365, +209, - +20434, +13223, -8548, -342, +182, +828, -924, -2160, -2725, +468, +2161, -1789, +445, -1242, +435, -205, -999, -575, -649, -4, -1029, -158, -482, +542, -293, +181, -169, -874, -514, -927, -442, +127, - +21071, +12403, -8865, +245, -318, +823, -1130, -2243, -2635, +724, +2101, -1684, +725, -1293, +626, -269, -883, -830, -829, +105, -1203, -105, -238, +653, -371, +371, -143, -1016, -532, -886, -493, +33, - +20789, +11662, -8363, +332, -911, +1138, -984, -2430, -2493, +1026, +1715, -1379, +1228, -1581, +803, -170, -1256, -633, -926, +9, -905, -125, -208, +782, -256, +313, -208, -993, -501, -825, -526, -5, - +19596, +11016, -7150, -54, -1442, +1677, -696, -2554, -2277, +940, +1405, -817, +1246, -1536, +683, -288, -1142, -645, -762, +96, -739, -256, -171, +923, -379, +209, -146, -915, -439, -791, -471, +64, - +17572, +10705, -5607, -659, -1779, +2017, -199, -2475, -2231, +834, +1110, -554, +1413, -1693, +462, -69, -1229, -319, -565, +61, -598, -344, -187, +729, -361, +89, -38, -790, -417, -617, -384, -60, - +13984, +10256, -4374, -387, +520, +1170, -465, -1651, -1737, +620, +1299, -598, +593, -692, +507, -106, -759, -500, -601, +13, -482, -134, -166, +603, -169, +64, -79, -688, -462, -543, -415, -231, - +12758, +10312, -3687, -1357, +269, +1735, +98, -1444, -1892, +26, +1171, -327, +678, -523, +452, +210, -645, -277, -231, -18, -408, -233, -377, +567, -155, -104, +72, -516, -401, -434, -355, -174, - +11716, +10426, -3021, -2050, -38, +1840, +528, -1068, -1835, -336, +989, -214, +710, -348, +420, +365, -440, -231, -16, +39, -429, -185, -574, +332, -35, -237, +26, -307, -370, -373, -221, -235, - +11134, +10529, -2662, -2372, -80, +1872, +687, -929, -1758, -466, +868, -263, +670, -278, +447, +463, -382, -147, +37, -28, -515, -135, -648, +44, +50, -206, -64, -271, -287, -346, -196, -161, - +11076, +10636, -2726, -2397, +319, +2006, +654, -1075, -1802, -427, +898, -371, +393, -170, +406, +444, -274, -100, +119, -97, -686, -259, -554, +17, -61, -105, -68, -278, -240, -444, -157, +31, - +11612, +10554, -3129, -2035, +925, +2135, +343, -1322, -1834, -253, +981, -508, +127, -339, +524, +263, -428, +146, +113, -216, -691, -403, -615, +161, -3, -171, -98, -195, -334, -500, -145, +70, - +12375, +10683, -3543, -1496, +1375, +1878, -63, -1524, -1717, +100, +1163, -755, -161, -335, +443, +21, -544, +0, +88, -275, -693, -316, -565, +159, -85, -8, -150, -333, -390, -555, -137, +51, - +13451, +11029, -4018, -1046, +1272, +1286, -363, -1499, -1496, +592, +1316, -1108, -273, -352, +296, -275, -635, -344, -118, -175, -740, -127, -424, +105, -164, +113, -179, -568, -399, -627, -271, +78, - +14734, +11620, -4801, -879, +695, +632, -389, -1350, -1318, +1007, +1424, -1500, -74, -505, -4, -282, -945, -711, -166, -124, -792, +39, -391, +77, -83, +118, -326, -662, -381, -867, -393, +164, - +15985, +11630, -5516, -532, +203, +208, -354, -1214, -1189, +1341, +1442, -1615, +268, -744, -62, -254, -1183, -868, -259, -11, -770, +72, -261, +154, +24, +109, -377, -617, -514, -967, -389, +157, - +16167, +11377, -5735, -169, +103, +84, -542, -1299, -1254, +1362, +1544, -1556, +422, -670, -103, -248, -1015, -1157, -377, +88, -926, +197, -106, +201, +13, +190, -354, -777, -517, -923, -458, +58, - +15468, +10670, -5248, +0, +346, +442, -693, -1493, -1502, +1200, +1468, -1209, +625, -745, +218, -158, -964, -895, -623, +11, -688, +93, -44, +335, -4, +183, -327, -757, -508, -710, -494, -108, - +11864, +10338, -3078, -621, +1333, +599, -268, -1143, -1003, +1077, +1244, -764, -17, -195, +147, -60, -510, -758, -332, -70, -719, -16, -15, +316, +287, +250, -355, -886, -747, -549, -54, +215, -}; - -/* HRIR Delays */ -static const ALubyte defaultDelays[828] = -{ - 12, 12, 13, 14, 14, 14, 13, 12, 11, 10, 10, 10, 11, 12, 13, 14, 15, 15, 16, 16, 16, 15, 15, 14, 13, 12, 11, 10, 9, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 17, 18, 18, 18, 18, 18, 17, 16, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 20, 20, 20, 20, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 5, 5, 5, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 21, 22, 22, 22, 22, 22, 21, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 24, 24, 24, 24, 23, 22, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 24, 25, 26, 26, 26, 26, 26, 25, 24, 24, 23, 22, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 28, 28, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 26, 27, 28, 28, 28, 27, 26, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 24, 25, 26, 26, 26, 26, 26, 25, 24, 24, 23, 22, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 3, 3, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 24, 24, 24, 24, 23, 22, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 4, 3, 3, 2, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 21, 22, 22, 22, 22, 22, 21, 21, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 6, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 4, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 18, 19, 20, 20, 20, 20, 20, 19, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 8, 7, 6, 5, 5, 5, 4, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 17, 18, 18, 18, 18, 18, 17, 16, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 7, 6, 6, 6, 6, 6, 7, 7, 8, 9, 10, 11, 12, 13, 14, 15, 15, 16, 16, 16, 15, 15, 14, 13, 12, 11, 10, 9, 8, 8, 8, 8, 8, 9, 10, 11, 12, 13, 14, 14, 14, 13, 12, 11, 10, 10, 10, 11, 12, -}; - -/* Default HRTF Definition */ -static const struct Hrtf DefaultHrtf = { - 44100, 32, 19, defaultAzCount, defaultEvOffset, - defaultCoeffs, defaultDelays, NULL -}; diff --git a/jni/openal-soft-android/Alc/mixer_defs.h b/jni/openal-soft-android/Alc/mixer_defs.h deleted file mode 100644 index f8968a0a..00000000 --- a/jni/openal-soft-android/Alc/mixer_defs.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef MIXER_DEFS_H -#define MIXER_DEFS_H - -#include "AL/alc.h" -#include "AL/al.h" -#include "alMain.h" - -struct DirectParams; -struct SendParams; - -/* C resamplers */ -void Resample_copy32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); -void Resample_point32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); -void Resample_lerp32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); -void Resample_cubic32_C(const ALfloat *src, ALuint frac, ALuint increment, ALfloat *restrict dst, ALuint dstlen); - - -/* C mixers */ -void MixDirect_Hrtf_C(const struct DirectParams*,const ALfloat*restrict,ALuint,ALuint,ALuint,ALuint); -void MixDirect_C(const struct DirectParams*,const ALfloat*restrict,ALuint,ALuint,ALuint,ALuint); -void MixSend_C(const struct SendParams*,const ALfloat*restrict,ALuint,ALuint,ALuint); - -/* SSE mixers */ -void MixDirect_Hrtf_SSE(const struct DirectParams*,const ALfloat*restrict,ALuint,ALuint,ALuint,ALuint); -void MixDirect_SSE(const struct DirectParams*,const ALfloat*restrict,ALuint,ALuint,ALuint,ALuint); -void MixSend_SSE(const struct SendParams*,const ALfloat*restrict,ALuint,ALuint,ALuint); - -/* Neon mixers */ -void MixDirect_Hrtf_Neon(const struct DirectParams*,const ALfloat*restrict,ALuint,ALuint,ALuint,ALuint); -void MixDirect_Neon(const struct DirectParams*,const ALfloat*restrict,ALuint,ALuint,ALuint,ALuint); -void MixSend_Neon(const struct SendParams*,const ALfloat*restrict,ALuint,ALuint,ALuint); - -#endif /* MIXER_DEFS_H */ diff --git a/jni/openal-soft-android/Alc/mixer_inc.c b/jni/openal-soft-android/Alc/mixer_inc.c deleted file mode 100644 index 17be5cde..00000000 --- a/jni/openal-soft-android/Alc/mixer_inc.c +++ /dev/null @@ -1,140 +0,0 @@ -#include "config.h" - -#include "alMain.h" -#include "alSource.h" -#include "mixer_defs.h" - -#ifdef __GNUC__ -#define LIKELY(x) __builtin_expect(!!(x), 1) -#define UNLIKELY(x) __builtin_expect(!!(x), 0) -#else -#define LIKELY(x) (x) -#define UNLIKELY(x) (x) -#endif - -#define REAL_MERGE2(a,b) a##b -#define MERGE2(a,b) REAL_MERGE2(a,b) - -#define MixDirect_Hrtf MERGE2(MixDirect_Hrtf_,SUFFIX) - - -static inline void ApplyCoeffsStep(const ALuint irSize, - ALfloat (*restrict Coeffs)[2], - const ALfloat (*restrict CoeffStep)[2]); -static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2], - const ALuint irSize, - ALfloat (*restrict Coeffs)[2], - ALfloat left, ALfloat right); - - -void MixDirect_Hrtf(const DirectParams *params, const ALfloat *restrict data, ALuint srcchan, - ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) -{ - ALfloat (*restrict DryBuffer)[BUFFERSIZE] = params->OutBuffer; - ALfloat *restrict ClickRemoval = params->ClickRemoval; - ALfloat *restrict PendingClicks = params->PendingClicks; - const ALuint IrSize = params->Hrtf.Params.IrSize; - const ALint *restrict DelayStep = params->Hrtf.Params.DelayStep; - const ALfloat (*restrict CoeffStep)[2] = params->Hrtf.Params.CoeffStep; - const ALfloat (*restrict TargetCoeffs)[2] = params->Hrtf.Params.Coeffs[srcchan]; - const ALuint *restrict TargetDelay = params->Hrtf.Params.Delay[srcchan]; - ALfloat *restrict History = params->Hrtf.State->History[srcchan]; - ALfloat (*restrict Values)[2] = params->Hrtf.State->Values[srcchan]; - ALint Counter = maxu(params->Hrtf.State->Counter, OutPos) - OutPos; - ALuint Offset = params->Hrtf.State->Offset + OutPos; - ALIGN(16) ALfloat Coeffs[HRIR_LENGTH][2]; - ALuint Delay[2]; - ALfloat left, right; - ALuint pos; - ALuint c; - - pos = 0; - for(c = 0;c < IrSize;c++) - { - Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter); - Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter); - } - - Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter); - Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter); - - if(LIKELY(OutPos == 0)) - { - History[Offset&SRC_HISTORY_MASK] = data[pos]; - left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK], - History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK], - (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE)); - right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK], - History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK], - (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE)); - - ClickRemoval[FrontLeft] -= Values[(Offset+1)&HRIR_MASK][0] + - Coeffs[0][0] * left; - ClickRemoval[FrontRight] -= Values[(Offset+1)&HRIR_MASK][1] + - Coeffs[0][1] * right; - } - for(pos = 0;pos < BufferSize && Counter > 0;pos++) - { - History[Offset&SRC_HISTORY_MASK] = data[pos]; - left = lerp(History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK], - History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK], - (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE)); - right = lerp(History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK], - History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK], - (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE)); - - Delay[0] += DelayStep[0]; - Delay[1] += DelayStep[1]; - - Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f; - Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f; - Offset++; - - ApplyCoeffs(Offset, Values, IrSize, Coeffs, left, right); - DryBuffer[FrontLeft][OutPos] += Values[Offset&HRIR_MASK][0]; - DryBuffer[FrontRight][OutPos] += Values[Offset&HRIR_MASK][1]; - ApplyCoeffsStep(IrSize, Coeffs, CoeffStep); - - OutPos++; - Counter--; - } - - Delay[0] >>= HRTFDELAY_BITS; - Delay[1] >>= HRTFDELAY_BITS; - for(;pos < BufferSize;pos++) - { - History[Offset&SRC_HISTORY_MASK] = data[pos]; - left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; - right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; - - Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f; - Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f; - Offset++; - - ApplyCoeffs(Offset, Values, IrSize, Coeffs, left, right); - DryBuffer[FrontLeft][OutPos] += Values[Offset&HRIR_MASK][0]; - DryBuffer[FrontRight][OutPos] += Values[Offset&HRIR_MASK][1]; - - OutPos++; - } - if(LIKELY(OutPos == SamplesToDo)) - { - History[Offset&SRC_HISTORY_MASK] = data[pos]; - left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; - right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; - - PendingClicks[FrontLeft] += Values[(Offset+1)&HRIR_MASK][0] + - Coeffs[0][0] * left; - PendingClicks[FrontRight] += Values[(Offset+1)&HRIR_MASK][1] + - Coeffs[0][1] * right; - } -} - - -#undef MixDirect_Hrtf - -#undef MERGE2 -#undef REAL_MERGE2 - -#undef UNLIKELY -#undef LIKELY diff --git a/jni/openal-soft-android/Alc/mixer_neon.c b/jni/openal-soft-android/Alc/mixer_neon.c deleted file mode 100644 index 0aa450ad..00000000 --- a/jni/openal-soft-android/Alc/mixer_neon.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "config.h" - -#ifdef HAVE_ARM_NEON_H -#include -#endif - -#include "AL/al.h" -#include "AL/alc.h" -#include "alMain.h" -#include "alu.h" - - -static inline void ApplyCoeffsStep(const ALuint IrSize, - ALfloat (*restrict Coeffs)[2], - const ALfloat (*restrict CoeffStep)[2]) -{ - float32x4_t coeffs, deltas; - ALuint c; - - for(c = 0;c < IrSize;c += 2) - { - coeffs = vld1q_f32(&Coeffs[c][0]); - deltas = vld1q_f32(&CoeffStep[c][0]); - coeffs = vaddq_f32(coeffs, deltas); - vst1q_f32(&Coeffs[c][0], coeffs); - } -} - -static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2], - const ALuint IrSize, - ALfloat (*restrict Coeffs)[2], - ALfloat left, ALfloat right) -{ - ALuint c; - float32x4_t leftright4; - { - float32x2_t leftright2 = vdup_n_f32(0.0); - leftright2 = vset_lane_f32(left, leftright2, 0); - leftright2 = vset_lane_f32(right, leftright2, 1); - leftright4 = vcombine_f32(leftright2, leftright2); - } - for(c = 0;c < IrSize;c += 2) - { - const ALuint o0 = (Offset+c)&HRIR_MASK; - const ALuint o1 = (o0+1)&HRIR_MASK; - float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]), - vld1_f32((float32_t*)&Values[o1][0])); - float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]); - - vals = vmlaq_f32(vals, coefs, leftright4); - - vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals)); - vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals)); - } -} - - -#define SUFFIX Neon -#include "mixer_inc.c" -#undef SUFFIX - - -void MixDirect_Neon(const DirectParams *params, const ALfloat *restrict data, ALuint srcchan, - ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) -{ - ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer; - ALfloat *restrict ClickRemoval = params->ClickRemoval; - ALfloat *restrict PendingClicks = params->PendingClicks; - ALfloat DrySend; - float32x4_t gain; - ALuint pos; - ALuint c; - - for(c = 0;c < MaxChannels;c++) - { - DrySend = params->Gains[srcchan][c]; - if(!(DrySend > GAIN_SILENCE_THRESHOLD)) - continue; - - if(OutPos == 0) - ClickRemoval[c] -= data[0]*DrySend; - - gain = vdupq_n_f32(DrySend); - for(pos = 0;BufferSize-pos > 3;pos += 4) - { - const float32x4_t val4 = vld1q_f32(&data[pos]); - float32x4_t dry4 = vld1q_f32(&OutBuffer[c][OutPos+pos]); - dry4 = vaddq_f32(dry4, vmulq_f32(val4, gain)); - vst1q_f32(&OutBuffer[c][OutPos+pos], dry4); - } - for(;pos < BufferSize;pos++) - OutBuffer[c][OutPos+pos] += data[pos]*DrySend; - - if(OutPos+pos == SamplesToDo) - PendingClicks[c] += data[pos]*DrySend; - } -} - - -void MixSend_Neon(const SendParams *params, const ALfloat *restrict data, - ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) -{ - ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer; - ALfloat *restrict ClickRemoval = params->ClickRemoval; - ALfloat *restrict PendingClicks = params->PendingClicks; - ALfloat WetGain; - float32x4_t gain; - ALuint pos; - - WetGain = params->Gain; - if(!(WetGain > GAIN_SILENCE_THRESHOLD)) - return; - - if(OutPos == 0) - ClickRemoval[0] -= data[0] * WetGain; - - gain = vdupq_n_f32(WetGain); - for(pos = 0;BufferSize-pos > 3;pos += 4) - { - const float32x4_t val4 = vld1q_f32(&data[pos]); - float32x4_t wet4 = vld1q_f32(&OutBuffer[0][OutPos+pos]); - wet4 = vaddq_f32(wet4, vmulq_f32(val4, gain)); - vst1q_f32(&OutBuffer[0][OutPos+pos], wet4); - } - for(;pos < BufferSize;pos++) - OutBuffer[0][OutPos+pos] += data[pos] * WetGain; - - if(OutPos+pos == SamplesToDo) - PendingClicks[0] += data[pos] * WetGain; -} diff --git a/jni/openal-soft-android/Alc/mixer_sse.c b/jni/openal-soft-android/Alc/mixer_sse.c deleted file mode 100644 index 719ebd23..00000000 --- a/jni/openal-soft-android/Alc/mixer_sse.c +++ /dev/null @@ -1,164 +0,0 @@ -#include "config.h" - -#ifdef HAVE_XMMINTRIN_H -#ifdef IN_IDE_PARSER -/* KDevelop's parser won't recognize these defines that get added by the -msse - * switch used to compile this source. Without them, xmmintrin.h fails to - * declare anything. */ -#define __MMX__ -#define __SSE__ -#endif -#include -#endif - -#include "AL/al.h" -#include "AL/alc.h" -#include "alMain.h" -#include "alu.h" - -#include "alSource.h" -#include "alAuxEffectSlot.h" -#include "mixer_defs.h" - - -static inline void ApplyCoeffsStep(const ALuint IrSize, - ALfloat (*restrict Coeffs)[2], - const ALfloat (*restrict CoeffStep)[2]) -{ - __m128 coeffs, deltas; - ALuint i; - - for(i = 0;i < IrSize;i += 2) - { - coeffs = _mm_load_ps(&Coeffs[i][0]); - deltas = _mm_load_ps(&CoeffStep[i][0]); - coeffs = _mm_add_ps(coeffs, deltas); - _mm_store_ps(&Coeffs[i][0], coeffs); - } -} - -static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2], - const ALuint IrSize, - ALfloat (*restrict Coeffs)[2], - ALfloat left, ALfloat right) -{ - const __m128 lrlr = { left, right, left, right }; - __m128 vals = _mm_setzero_ps(); - __m128 coeffs; - ALuint i; - - if((Offset&1)) - { - const ALuint o0 = Offset&HRIR_MASK; - const ALuint o1 = (Offset+IrSize-1)&HRIR_MASK; - __m128 imp0, imp1; - - coeffs = _mm_load_ps(&Coeffs[0][0]); - vals = _mm_loadl_pi(vals, (__m64*)&Values[o0][0]); - imp0 = _mm_mul_ps(lrlr, coeffs); - vals = _mm_add_ps(imp0, vals); - _mm_storel_pi((__m64*)&Values[o0][0], vals); - for(i = 1;i < IrSize-1;i += 2) - { - const ALuint o2 = (Offset+i)&HRIR_MASK; - - coeffs = _mm_load_ps(&Coeffs[i+1][0]); - vals = _mm_load_ps(&Values[o2][0]); - imp1 = _mm_mul_ps(lrlr, coeffs); - imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2)); - vals = _mm_add_ps(imp0, vals); - _mm_store_ps(&Values[o2][0], vals); - imp0 = imp1; - } - vals = _mm_loadl_pi(vals, (__m64*)&Values[o1][0]); - imp0 = _mm_movehl_ps(imp0, imp0); - vals = _mm_add_ps(imp0, vals); - _mm_storel_pi((__m64*)&Values[o1][0], vals); - } - else - { - for(i = 0;i < IrSize;i += 2) - { - const ALuint o = (Offset + i)&HRIR_MASK; - - coeffs = _mm_load_ps(&Coeffs[i][0]); - vals = _mm_load_ps(&Values[o][0]); - vals = _mm_add_ps(vals, _mm_mul_ps(lrlr, coeffs)); - _mm_store_ps(&Values[o][0], vals); - } - } -} - -#define SUFFIX SSE -#include "mixer_inc.c" -#undef SUFFIX - - -void MixDirect_SSE(const DirectParams *params, const ALfloat *restrict data, ALuint srcchan, - ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) -{ - ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer; - ALfloat *restrict ClickRemoval = params->ClickRemoval; - ALfloat *restrict PendingClicks = params->PendingClicks; - ALfloat DrySend; - __m128 gain; - ALuint pos; - ALuint c; - - for(c = 0;c < MaxChannels;c++) - { - DrySend = params->Gains[srcchan][c]; - if(!(DrySend > GAIN_SILENCE_THRESHOLD)) - continue; - - if(OutPos == 0) - ClickRemoval[c] -= data[0]*DrySend; - - gain = _mm_set1_ps(DrySend); - for(pos = 0;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, gain)); - _mm_store_ps(&OutBuffer[c][OutPos+pos], dry4); - } - for(;pos < BufferSize;pos++) - OutBuffer[c][OutPos+pos] += data[pos]*DrySend; - - if(OutPos+pos == SamplesToDo) - PendingClicks[c] += data[pos]*DrySend; - } -} - - -void MixSend_SSE(const SendParams *params, const ALfloat *restrict data, - ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) -{ - ALfloat (*restrict OutBuffer)[BUFFERSIZE] = params->OutBuffer; - ALfloat *restrict ClickRemoval = params->ClickRemoval; - ALfloat *restrict PendingClicks = params->PendingClicks; - ALfloat WetGain; - __m128 gain; - ALuint pos; - - WetGain = params->Gain; - if(!(WetGain > GAIN_SILENCE_THRESHOLD)) - return; - - if(OutPos == 0) - ClickRemoval[0] -= data[0] * WetGain; - - gain = _mm_set1_ps(WetGain); - for(pos = 0;BufferSize-pos > 3;pos += 4) - { - const __m128 val4 = _mm_load_ps(&data[pos]); - __m128 wet4 = _mm_load_ps(&OutBuffer[0][OutPos+pos]); - wet4 = _mm_add_ps(wet4, _mm_mul_ps(val4, gain)); - _mm_store_ps(&OutBuffer[0][OutPos+pos], wet4); - } - for(;pos < BufferSize;pos++) - OutBuffer[0][OutPos+pos] += data[pos] * WetGain; - - if(OutPos+pos == SamplesToDo) - PendingClicks[0] += data[pos] * WetGain; -} diff --git a/jni/openal-soft-android/Alc/rwlock.h b/jni/openal-soft-android/Alc/rwlock.h deleted file mode 100644 index efbab4e8..00000000 --- a/jni/openal-soft-android/Alc/rwlock.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef AL_RWLOCK_H -#define AL_RWLOCK_H - -#include "AL/al.h" -#include "atomic.h" - -typedef struct { - volatile RefCount read_count; - volatile RefCount write_count; - volatile ALenum read_lock; - volatile ALenum read_entry_lock; - volatile ALenum write_lock; -} RWLock; - -void RWLockInit(RWLock *lock); -void ReadLock(RWLock *lock); -void ReadUnlock(RWLock *lock); -void WriteLock(RWLock *lock); -void WriteUnlock(RWLock *lock); - -#endif /* AL_RWLOCK_H */ diff --git a/jni/openal-soft-android/Alc/threads.c b/jni/openal-soft-android/Alc/threads.c deleted file mode 100644 index 64586ae9..00000000 --- a/jni/openal-soft-android/Alc/threads.c +++ /dev/null @@ -1,200 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include "threads.h" - -#include -#include - -#include "alMain.h" -#include "alThunk.h" - -#define THREAD_STACK_SIZE (1*1024*1024) /* 1MB */ - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include - -typedef struct althread_info { - ALuint (*func)(ALvoid*); - ALvoid *ptr; - HANDLE hdl; -} althread_info; - -static DWORD CALLBACK StarterFunc(void *ptr) -{ - althread_info *inf = (althread_info*)ptr; - ALuint ret; - - ret = inf->func(inf->ptr); - ExitThread((DWORD)ret); - - return (DWORD)ret; -} - - -ALboolean StartThread(althread_t *thread, ALuint (*func)(ALvoid*), ALvoid *ptr) -{ - althread_info *info; - DWORD dummy; - - info = malloc(sizeof(*info)); - if(!info) return AL_FALSE; - - info->func = func; - info->ptr = ptr; - - info->hdl = CreateThread(NULL, THREAD_STACK_SIZE, StarterFunc, info, 0, &dummy); - if(!info->hdl) - { - free(info); - return AL_FALSE; - } - - *thread = info; - return AL_TRUE; -} - -ALuint StopThread(althread_t thread) -{ - DWORD ret = 0; - - WaitForSingleObject(thread->hdl, INFINITE); - GetExitCodeThread(thread->hdl, &ret); - CloseHandle(thread->hdl); - - free(thread); - - return (ALuint)ret; -} - - -void SetThreadName(const char *name) -{ -#if defined(_MSC_VER) -#define MS_VC_EXCEPTION 0x406D1388 - 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; - info.dwType = 0x1000; - info.szName = name; - info.dwThreadID = -1; - info.dwFlags = 0; - - __try { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(DWORD), (ULONG_PTR*)&info); - } - __except(EXCEPTION_CONTINUE_EXECUTION) { - } -#undef MS_VC_EXCEPTION -#else - TRACE("Can't set thread %04lx name to \"%s\"\n", GetCurrentThreadId(), name); -#endif -} - -#else - -#include - -typedef struct althread_info { - ALuint (*func)(ALvoid*); - ALvoid *ptr; - ALuint ret; - pthread_t hdl; -} althread_info; - -static void *StarterFunc(void *ptr) -{ - althread_info *inf = (althread_info*)ptr; - inf->ret = inf->func(inf->ptr); - return NULL; -} - - -ALboolean StartThread(althread_t *thread, ALuint (*func)(ALvoid*), ALvoid *ptr) -{ - pthread_attr_t attr; - althread_info *info; - - info = malloc(sizeof(*info)); - if(!info) return AL_FALSE; - - if(pthread_attr_init(&attr) != 0) - { - free(info); - return AL_FALSE; - } - if(pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE) != 0) - { - pthread_attr_destroy(&attr); - free(info); - return AL_FALSE; - } - - info->func = func; - info->ptr = ptr; - if(pthread_create(&info->hdl, &attr, StarterFunc, info) != 0) - { - pthread_attr_destroy(&attr); - free(info); - return AL_FALSE; - } - pthread_attr_destroy(&attr); - - *thread = info; - return AL_TRUE; -} - -ALuint StopThread(althread_t thread) -{ - ALuint ret; - - pthread_join(thread->hdl, NULL); - ret = thread->ret; - - free(thread); - - return ret; -} - - -void SetThreadName(const char *name) -{ -#if defined(HAVE_PTHREAD_SETNAME_NP) -#if defined(__GNUC__) - if(pthread_setname_np(pthread_self(), name) != 0) -#elif defined(__APPLE__) - if(pthread_setname_np(name) != 0) -#endif - WARN("Failed to set thread name to \"%s\": %s\n", name, strerror(errno)); -#elif defined(HAVE_PTHREAD_SET_NAME_NP) - pthread_set_name_np(pthread_self(), name); -#else - TRACE("Can't set thread name to \"%s\"\n", name); -#endif -} - -#endif diff --git a/jni/openal-soft-android/OpenAL32/Include/threads.h b/jni/openal-soft-android/OpenAL32/Include/threads.h deleted file mode 100644 index 26493101..00000000 --- a/jni/openal-soft-android/OpenAL32/Include/threads.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef AL_THREADS_H -#define AL_THREADS_H - -#include "alMain.h" - -struct althread_info; -typedef struct althread_info* althread_t; - -ALboolean StartThread(althread_t *out, ALuint (*func)(ALvoid*), ALvoid *ptr); -ALuint StopThread(althread_t thread); - -void SetThreadName(const char *name); - -#endif /* AL_THREADS_H */ diff --git a/jni/openal-soft-android/OpenAL32/alBuffer.c b/jni/openal-soft-android/OpenAL32/alBuffer.c deleted file mode 100644 index d9c91c2f..00000000 --- a/jni/openal-soft-android/OpenAL32/alBuffer.c +++ /dev/null @@ -1,2212 +0,0 @@ -/** - * OpenAL cross platform audio library - * Copyright (C) 1999-2007 by authors. - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * Or go to http://www.gnu.org/copyleft/lgpl.html - */ - -#include "config.h" - -#include -#include -#include -#include - -#include "alMain.h" -#include "alu.h" -#include "alError.h" -#include "alBuffer.h" -#include "alThunk.h" - - -extern inline struct ALbuffer *LookupBuffer(ALCdevice *device, ALuint id); -extern inline struct ALbuffer *RemoveBuffer(ALCdevice *device, ALuint id); -extern inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, enum UserFmtType type); -extern inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type); - -static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels chans, enum UserFmtType type, const ALvoid *data, ALboolean storesrc); -static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len); -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); - - -/* - * Global Variables - */ - -/* 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 -}; - -/* 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 -}; - - -AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) -{ - 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++) - { - ALbuffer *buffer = calloc(1, sizeof(ALbuffer)); - if(!buffer) - { - alDeleteBuffers(cur, buffers); - SET_ERROR_AND_GOTO(context, AL_OUT_OF_MEMORY, done); - } - RWLockInit(&buffer->lock); - - err = NewThunkEntry(&buffer->id); - if(err == AL_NO_ERROR) - err = InsertUIntMapEntry(&device->BufferMap, buffer->id, buffer); - if(err != AL_NO_ERROR) - { - FreeThunkEntry(buffer->id); - memset(buffer, 0, sizeof(ALbuffer)); - free(buffer); - - alDeleteBuffers(cur, buffers); - SET_ERROR_AND_GOTO(context, err, done); - } - - buffers[cur] = buffer->id; - } - -done: - ALCcontext_DecRef(context); -} - -AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers) -{ - ALCdevice *device; - ALCcontext *context; - ALbuffer *ALBuf; - ALsizei i; - - context = GetContextRef(); - if(!context) return; - - if(!(n >= 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - device = context->Device; - for(i = 0;i < n;i++) - { - if(!buffers[i]) - continue; - - /* Check for valid Buffer ID */ - if((ALBuf=LookupBuffer(device, buffers[i])) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(ALBuf->ref != 0) - SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); - } - - for(i = 0;i < n;i++) - { - if((ALBuf=RemoveBuffer(device, buffers[i])) == NULL) - continue; - FreeThunkEntry(ALBuf->id); - - free(ALBuf->data); - - memset(ALBuf, 0, sizeof(*ALBuf)); - free(ALBuf); - } - -done: - ALCcontext_DecRef(context); -} - -AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer) -{ - ALCcontext *context; - ALboolean ret; - - context = GetContextRef(); - if(!context) return AL_FALSE; - - ret = ((!buffer || LookupBuffer(context->Device, buffer)) ? - AL_TRUE : AL_FALSE); - - ALCcontext_DecRef(context); - - return ret; -} - - -AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) -{ - enum UserFmtChannels srcchannels; - enum UserFmtType srctype; - ALCdevice *device; - ALCcontext *context; - ALuint framesize; - ALenum newformat; - ALbuffer *albuf; - ALenum err; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(!(size >= 0 && freq > 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - switch(srctype) - { - case UserFmtByte: - case UserFmtUByte: - case UserFmtShort: - case UserFmtUShort: - case UserFmtFloat: - framesize = FrameSizeFromUserFmt(srcchannels, srctype); - if(!((size%framesize) == 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - err = LoadData(albuf, freq, format, size/framesize, - srcchannels, srctype, data, 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); - if(!((size%framesize) == 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - newformat = AL_FORMAT_MONO_FLOAT32; - switch(srcchannels) - { - case UserFmtMono: newformat = AL_FORMAT_MONO_FLOAT32; break; - case UserFmtStereo: newformat = AL_FORMAT_STEREO_FLOAT32; break; - case UserFmtRear: newformat = AL_FORMAT_REAR32; break; - case UserFmtQuad: newformat = AL_FORMAT_QUAD32; break; - case UserFmtX51: newformat = AL_FORMAT_51CHN32; break; - case UserFmtX61: newformat = AL_FORMAT_61CHN32; break; - case UserFmtX71: newformat = AL_FORMAT_71CHN32; break; - } - err = LoadData(albuf, freq, newformat, size/framesize, - srcchannels, srctype, data, AL_TRUE); - if(err != AL_NO_ERROR) - SET_ERROR_AND_GOTO(context, err, done); - break; - - case UserFmtMulaw: - case UserFmtAlaw: - framesize = FrameSizeFromUserFmt(srcchannels, srctype); - if(!((size%framesize) == 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - newformat = AL_FORMAT_MONO16; - switch(srcchannels) - { - case UserFmtMono: newformat = AL_FORMAT_MONO16; break; - case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; - case UserFmtRear: newformat = AL_FORMAT_REAR16; break; - case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; - case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; - case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; - case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; - } - err = LoadData(albuf, freq, newformat, size/framesize, - srcchannels, srctype, data, AL_TRUE); - if(err != AL_NO_ERROR) - SET_ERROR_AND_GOTO(context, err, done); - break; - - case 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 - */ - framesize = ChannelsFromUserFmt(srcchannels) * 36; - if(!((size%framesize) == 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - - newformat = AL_FORMAT_MONO16; - switch(srcchannels) - { - case UserFmtMono: newformat = AL_FORMAT_MONO16; break; - case UserFmtStereo: newformat = AL_FORMAT_STEREO16; break; - case UserFmtRear: newformat = AL_FORMAT_REAR16; break; - case UserFmtQuad: newformat = AL_FORMAT_QUAD16; break; - case UserFmtX51: newformat = AL_FORMAT_51CHN16; break; - case UserFmtX61: newformat = AL_FORMAT_61CHN16; break; - case UserFmtX71: newformat = AL_FORMAT_71CHN16; break; - } - err = LoadData(albuf, freq, newformat, size/framesize*65, - srcchannels, srctype, data, AL_TRUE); - if(err != AL_NO_ERROR) - SET_ERROR_AND_GOTO(context, err, done); - break; - } - -done: - ALCcontext_DecRef(context); -} - -AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) -{ - enum UserFmtChannels srcchannels; - enum UserFmtType srctype; - ALCdevice *device; - ALCcontext *context; - ALbuffer *albuf; - ALuint original_align; - ALuint channels; - ALuint bytes; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(!(length >= 0 && offset >= 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - if(DecomposeUserFormat(format, &srcchannels, &srctype) == AL_FALSE) - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - - WriteLock(&albuf->lock); - original_align = ((albuf->OriginalType == UserFmtIMA4) ? - (ChannelsFromUserFmt(albuf->OriginalChannels)*36) : - FrameSizeFromUserFmt(albuf->OriginalChannels, - albuf->OriginalType)); - - if(srcchannels != albuf->OriginalChannels || srctype != albuf->OriginalType) - { - WriteUnlock(&albuf->lock); - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - if(offset > albuf->OriginalSize || length > albuf->OriginalSize-offset || - (offset%original_align) != 0 || (length%original_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 */ - if(srctype == UserFmtIMA4) - { - offset = offset/36*65 * bytes; - length = length/original_align * 65; - } - else - { - ALuint OldBytes = BytesFromUserFmt(srctype); - offset = offset/OldBytes * bytes; - length = length/OldBytes/channels; - } - ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, - data, srctype, channels, length); - WriteUnlock(&albuf->lock); - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, - ALuint samplerate, ALenum internalformat, ALsizei samples, - ALenum channels, ALenum type, const ALvoid *data) -{ - ALCdevice *device; - ALCcontext *context; - ALbuffer *albuf; - ALenum err; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(!(samples >= 0 && samplerate != 0)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE) - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - - err = LoadData(albuf, samplerate, internalformat, samples, - channels, type, data, AL_FALSE); - if(err != AL_NO_ERROR) - SET_ERROR_AND_GOTO(context, err, done); - -done: - ALCcontext_DecRef(context); -} - -AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, - ALsizei offset, ALsizei samples, - ALenum channels, ALenum type, const ALvoid *data) -{ - ALCdevice *device; - ALCcontext *context; - ALuint framesize; - ALbuffer *albuf; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(!(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); - framesize = FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType); - if(channels != (ALenum)albuf->FmtChannels) - { - WriteUnlock(&albuf->lock); - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - else if(offset > albuf->SampleLen || samples > albuf->SampleLen-offset) - { - WriteUnlock(&albuf->lock); - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - } - - /* offset -> byte offset */ - offset *= framesize; - ConvertData((char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, - data, type, ChannelsFromFmt(albuf->FmtChannels), samples); - WriteUnlock(&albuf->lock); - -done: - ALCcontext_DecRef(context); -} - -AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, - ALsizei offset, ALsizei samples, - ALenum channels, ALenum type, ALvoid *data) -{ - ALCdevice *device; - ALCcontext *context; - ALuint framesize; - ALbuffer *albuf; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - if(!(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); - framesize = FrameSizeFromFmt(albuf->FmtChannels, albuf->FmtType); - 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(type == UserFmtIMA4 && (samples%65) != 0) - { - ReadUnlock(&albuf->lock); - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - } - - /* offset -> byte offset */ - offset *= framesize; - ConvertData(data, type, (char*)albuf->data+offset, (enum UserFmtType)albuf->FmtType, - ChannelsFromFmt(albuf->FmtChannels), samples); - ReadUnlock(&albuf->lock); - -done: - ALCcontext_DecRef(context); -} - -AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format) -{ - enum FmtChannels dstchannels; - enum FmtType dsttype; - ALCcontext *context; - ALboolean ret; - - context = GetContextRef(); - if(!context) return AL_FALSE; - - ret = DecomposeFormat(format, &dstchannels, &dsttype); - - ALCcontext_DecRef(context); - - return ret; -} - - -AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum param, ALfloat UNUSED(value)) -{ - ALCdevice *device; - ALCcontext *context; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(LookupBuffer(device, buffer) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - switch(param) - { - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum param, ALfloat UNUSED(value1), ALfloat UNUSED(value2), ALfloat UNUSED(value3)) -{ - ALCdevice *device; - ALCcontext *context; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(LookupBuffer(device, buffer) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - switch(param) - { - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum param, const ALfloat *values) -{ - ALCdevice *device; - ALCcontext *context; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(LookupBuffer(device, buffer) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - if(!(values)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - switch(param) - { - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum param, ALint UNUSED(value)) -{ - ALCdevice *device; - ALCcontext *context; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(LookupBuffer(device, buffer) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - switch(param) - { - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY 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; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - if(!(values)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - switch(param) - { - case AL_LOOP_POINTS_SOFT: - WriteLock(&albuf->lock); - if(albuf->ref != 0) - { - WriteUnlock(&albuf->lock); - SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done); - } - if(values[0] >= values[1] || values[0] < 0 || - values[1] > albuf->SampleLen) - { - WriteUnlock(&albuf->lock); - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - } - - albuf->LoopStart = values[0]; - albuf->LoopEnd = values[1]; - WriteUnlock(&albuf->lock); - break; - - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum param, ALfloat *value) -{ - ALCdevice *device; - ALCcontext *context; - ALbuffer *albuf; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - if(!(value)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - switch(param) - { - case AL_SEC_LENGTH_SOFT: - ReadLock(&albuf->lock); - if(albuf->SampleLen != 0) - *value = albuf->SampleLen / (ALfloat)albuf->Frequency; - else - *value = 0.0f; - ReadUnlock(&albuf->lock); - break; - - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) -{ - ALCdevice *device; - ALCcontext *context; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(LookupBuffer(device, buffer) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - if(!(value1 && value2 && value3)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - switch(param) - { - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum param, ALfloat *values) -{ - ALCdevice *device; - ALCcontext *context; - - switch(param) - { - case AL_SEC_LENGTH_SOFT: - alGetBufferf(buffer, param, values); - return; - } - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(LookupBuffer(device, buffer) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - if(!(values)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - switch(param) - { - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum param, ALint *value) -{ - ALCdevice *device; - ALCcontext *context; - ALbuffer *albuf; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - if(!(value)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - switch(param) - { - case AL_FREQUENCY: - *value = albuf->Frequency; - break; - - case AL_BITS: - *value = BytesFromFmt(albuf->FmtType) * 8; - break; - - case AL_CHANNELS: - *value = ChannelsFromFmt(albuf->FmtChannels); - break; - - case AL_SIZE: - ReadLock(&albuf->lock); - *value = albuf->SampleLen * FrameSizeFromFmt(albuf->FmtChannels, - albuf->FmtType); - ReadUnlock(&albuf->lock); - break; - - case AL_INTERNAL_FORMAT_SOFT: - *value = albuf->Format; - break; - - case AL_BYTE_LENGTH_SOFT: - *value = albuf->OriginalSize; - break; - - case AL_SAMPLE_LENGTH_SOFT: - *value = albuf->SampleLen; - break; - - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) -{ - ALCdevice *device; - ALCcontext *context; - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if(LookupBuffer(device, buffer) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - if(!(value1 && value2 && value3)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - switch(param) - { - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum param, ALint *values) -{ - ALCdevice *device; - ALCcontext *context; - ALbuffer *albuf; - - switch(param) - { - case AL_FREQUENCY: - case AL_BITS: - case AL_CHANNELS: - case AL_SIZE: - case AL_INTERNAL_FORMAT_SOFT: - case AL_BYTE_LENGTH_SOFT: - case AL_SAMPLE_LENGTH_SOFT: - alGetBufferi(buffer, param, values); - return; - } - - context = GetContextRef(); - if(!context) return; - - device = context->Device; - if((albuf=LookupBuffer(device, buffer)) == NULL) - SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done); - - if(!(values)) - SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done); - switch(param) - { - case AL_LOOP_POINTS_SOFT: - ReadLock(&albuf->lock); - values[0] = albuf->LoopStart; - values[1] = albuf->LoopEnd; - ReadUnlock(&albuf->lock); - break; - - default: - SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done); - } - -done: - ALCcontext_DecRef(context); -} - - -typedef ALubyte ALmulaw; -typedef ALubyte ALalaw; -typedef ALubyte ALima4; -typedef struct { - ALbyte b[3]; -} ALbyte3; -extern ALbyte ALbyte3_size_is_not_3[(sizeof(ALbyte3)==sizeof(ALbyte[3]))?1:-1]; -typedef struct { - ALubyte b[3]; -} ALubyte3; -extern ALbyte ALubyte3_size_is_not_3[(sizeof(ALubyte3)==sizeof(ALubyte[3]))?1:-1]; - -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) -{ - 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]; - } - - j = 1; - while(j < 65) - { - 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++,j++) - { - 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*numchans + c] = sample[c]; - } - } - } -} - -static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALint *index, ALint numchans) -{ - 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; - } - - j = 1; - while(j < 65) - { - 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; - } - } - j += 8; - } -} - - -static inline ALint DecodeByte3(ALbyte3 val) -{ - if(IS_LITTLE_ENDIAN) - return (val.b[2]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[0]); - return (val.b[0]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[2]); -} - -static inline ALbyte3 EncodeByte3(ALint val) -{ - if(IS_LITTLE_ENDIAN) - { - ALbyte3 ret = {{ val, val>>8, val>>16 }}; - return ret; - } - else - { - ALbyte3 ret = {{ val>>16, val>>8, val }}; - return ret; - } -} - -static inline ALint DecodeUByte3(ALubyte3 val) -{ - if(IS_LITTLE_ENDIAN) - return (val.b[2]<<16) | (val.b[1]<<8) | (val.b[0]); - return (val.b[0]<<16) | (val.b[1]<<8) | val.b[2]; -} - -static inline ALubyte3 EncodeUByte3(ALint val) -{ - if(IS_LITTLE_ENDIAN) - { - ALubyte3 ret = {{ val, val>>8, val>>16 }}; - return ret; - } - else - { - ALubyte3 ret = {{ val>>16, val>>8, val }}; - return ret; - } -} - - -static inline ALbyte Conv_ALbyte_ALbyte(ALbyte val) -{ return val; } -static inline ALbyte Conv_ALbyte_ALubyte(ALubyte val) -{ return val-128; } -static inline ALbyte Conv_ALbyte_ALshort(ALshort val) -{ return val>>8; } -static inline ALbyte Conv_ALbyte_ALushort(ALushort val) -{ return (val>>8)-128; } -static inline ALbyte Conv_ALbyte_ALint(ALint val) -{ return val>>24; } -static inline ALbyte Conv_ALbyte_ALuint(ALuint val) -{ return (val>>24)-128; } -static inline ALbyte Conv_ALbyte_ALfloat(ALfloat val) -{ - if(val > 1.0f) return 127; - if(val < -1.0f) return -128; - return (ALint)(val * 127.0f); -} -static inline ALbyte Conv_ALbyte_ALdouble(ALdouble val) -{ - if(val > 1.0) return 127; - if(val < -1.0) return -128; - return (ALint)(val * 127.0); -} -static inline ALbyte Conv_ALbyte_ALmulaw(ALmulaw val) -{ return Conv_ALbyte_ALshort(DecodeMuLaw(val)); } -static inline ALbyte Conv_ALbyte_ALalaw(ALalaw val) -{ return Conv_ALbyte_ALshort(DecodeALaw(val)); } -static inline ALbyte Conv_ALbyte_ALbyte3(ALbyte3 val) -{ return DecodeByte3(val)>>16; } -static inline ALbyte Conv_ALbyte_ALubyte3(ALubyte3 val) -{ return (DecodeUByte3(val)>>16)-128; } - -static inline ALubyte Conv_ALubyte_ALbyte(ALbyte val) -{ return val+128; } -static inline ALubyte Conv_ALubyte_ALubyte(ALubyte val) -{ return val; } -static inline ALubyte Conv_ALubyte_ALshort(ALshort val) -{ return (val>>8)+128; } -static inline ALubyte Conv_ALubyte_ALushort(ALushort val) -{ return val>>8; } -static inline ALubyte Conv_ALubyte_ALint(ALint val) -{ return (val>>24)+128; } -static inline ALubyte Conv_ALubyte_ALuint(ALuint val) -{ return val>>24; } -static inline ALubyte Conv_ALubyte_ALfloat(ALfloat val) -{ - if(val > 1.0f) return 255; - if(val < -1.0f) return 0; - return (ALint)(val * 127.0f) + 128; -} -static inline ALubyte Conv_ALubyte_ALdouble(ALdouble val) -{ - if(val > 1.0) return 255; - if(val < -1.0) return 0; - return (ALint)(val * 127.0) + 128; -} -static inline ALubyte Conv_ALubyte_ALmulaw(ALmulaw val) -{ return Conv_ALubyte_ALshort(DecodeMuLaw(val)); } -static inline ALubyte Conv_ALubyte_ALalaw(ALalaw val) -{ return Conv_ALubyte_ALshort(DecodeALaw(val)); } -static inline ALubyte Conv_ALubyte_ALbyte3(ALbyte3 val) -{ return (DecodeByte3(val)>>16)+128; } -static inline ALubyte Conv_ALubyte_ALubyte3(ALubyte3 val) -{ return DecodeUByte3(val)>>16; } - -static inline ALshort Conv_ALshort_ALbyte(ALbyte val) -{ return val<<8; } -static inline ALshort Conv_ALshort_ALubyte(ALubyte val) -{ return (val-128)<<8; } -static inline ALshort Conv_ALshort_ALshort(ALshort val) -{ return val; } -static inline ALshort Conv_ALshort_ALushort(ALushort val) -{ return val-32768; } -static inline ALshort Conv_ALshort_ALint(ALint val) -{ return val>>16; } -static inline ALshort Conv_ALshort_ALuint(ALuint val) -{ return (val>>16)-32768; } -static inline ALshort Conv_ALshort_ALfloat(ALfloat val) -{ - if(val > 1.0f) return 32767; - if(val < -1.0f) return -32768; - return (ALint)(val * 32767.0f); -} -static inline ALshort Conv_ALshort_ALdouble(ALdouble val) -{ - if(val > 1.0) return 32767; - if(val < -1.0) return -32768; - return (ALint)(val * 32767.0); -} -static inline ALshort Conv_ALshort_ALmulaw(ALmulaw val) -{ return Conv_ALshort_ALshort(DecodeMuLaw(val)); } -static inline ALshort Conv_ALshort_ALalaw(ALalaw val) -{ return Conv_ALshort_ALshort(DecodeALaw(val)); } -static inline ALshort Conv_ALshort_ALbyte3(ALbyte3 val) -{ return DecodeByte3(val)>>8; } -static inline ALshort Conv_ALshort_ALubyte3(ALubyte3 val) -{ return (DecodeUByte3(val)>>8)-32768; } - -static inline ALushort Conv_ALushort_ALbyte(ALbyte val) -{ return (val+128)<<8; } -static inline ALushort Conv_ALushort_ALubyte(ALubyte val) -{ return val<<8; } -static inline ALushort Conv_ALushort_ALshort(ALshort val) -{ return val+32768; } -static inline ALushort Conv_ALushort_ALushort(ALushort val) -{ return val; } -static inline ALushort Conv_ALushort_ALint(ALint val) -{ return (val>>16)+32768; } -static inline ALushort Conv_ALushort_ALuint(ALuint val) -{ return val>>16; } -static inline ALushort Conv_ALushort_ALfloat(ALfloat val) -{ - if(val > 1.0f) return 65535; - if(val < -1.0f) return 0; - return (ALint)(val * 32767.0f) + 32768; -} -static inline ALushort Conv_ALushort_ALdouble(ALdouble val) -{ - if(val > 1.0) return 65535; - if(val < -1.0) return 0; - return (ALint)(val * 32767.0) + 32768; -} -static inline ALushort Conv_ALushort_ALmulaw(ALmulaw val) -{ return Conv_ALushort_ALshort(DecodeMuLaw(val)); } -static inline ALushort Conv_ALushort_ALalaw(ALalaw val) -{ return Conv_ALushort_ALshort(DecodeALaw(val)); } -static inline ALushort Conv_ALushort_ALbyte3(ALbyte3 val) -{ return (DecodeByte3(val)>>8)+32768; } -static inline ALushort Conv_ALushort_ALubyte3(ALubyte3 val) -{ return DecodeUByte3(val)>>8; } - -static inline ALint Conv_ALint_ALbyte(ALbyte val) -{ return val<<24; } -static inline ALint Conv_ALint_ALubyte(ALubyte val) -{ return (val-128)<<24; } -static inline ALint Conv_ALint_ALshort(ALshort val) -{ return val<<16; } -static inline ALint Conv_ALint_ALushort(ALushort val) -{ return (val-32768)<<16; } -static inline ALint Conv_ALint_ALint(ALint val) -{ return val; } -static inline ALint Conv_ALint_ALuint(ALuint val) -{ return val-2147483648u; } -static inline ALint Conv_ALint_ALfloat(ALfloat val) -{ - if(val > 1.0f) return 2147483647; - if(val < -1.0f) return -2147483647-1; - return (ALint)(val*16777215.0f) << 7; -} -static inline ALint Conv_ALint_ALdouble(ALdouble val) -{ - if(val > 1.0) return 2147483647; - if(val < -1.0) return -2147483647-1; - return (ALint)(val * 2147483647.0); -} -static inline ALint Conv_ALint_ALmulaw(ALmulaw val) -{ return Conv_ALint_ALshort(DecodeMuLaw(val)); } -static inline ALint Conv_ALint_ALalaw(ALalaw val) -{ return Conv_ALint_ALshort(DecodeALaw(val)); } -static inline ALint Conv_ALint_ALbyte3(ALbyte3 val) -{ return DecodeByte3(val)<<8; } -static inline ALint Conv_ALint_ALubyte3(ALubyte3 val) -{ return (DecodeUByte3(val)-8388608)<<8; } - -static inline ALuint Conv_ALuint_ALbyte(ALbyte val) -{ return (val+128)<<24; } -static inline ALuint Conv_ALuint_ALubyte(ALubyte val) -{ return val<<24; } -static inline ALuint Conv_ALuint_ALshort(ALshort val) -{ return (val+32768)<<16; } -static inline ALuint Conv_ALuint_ALushort(ALushort val) -{ return val<<16; } -static inline ALuint Conv_ALuint_ALint(ALint val) -{ return val+2147483648u; } -static inline ALuint Conv_ALuint_ALuint(ALuint val) -{ return val; } -static inline ALuint Conv_ALuint_ALfloat(ALfloat val) -{ - if(val > 1.0f) return 4294967295u; - if(val < -1.0f) return 0; - return ((ALint)(val*16777215.0f)<<7) + 2147483648u; -} -static inline ALuint Conv_ALuint_ALdouble(ALdouble val) -{ - if(val > 1.0) return 4294967295u; - if(val < -1.0) return 0; - return (ALint)(val * 2147483647.0) + 2147483648u; -} -static inline ALuint Conv_ALuint_ALmulaw(ALmulaw val) -{ return Conv_ALuint_ALshort(DecodeMuLaw(val)); } -static inline ALuint Conv_ALuint_ALalaw(ALalaw val) -{ return Conv_ALuint_ALshort(DecodeALaw(val)); } -static inline ALuint Conv_ALuint_ALbyte3(ALbyte3 val) -{ return (DecodeByte3(val)+8388608)<<8; } -static inline ALuint Conv_ALuint_ALubyte3(ALubyte3 val) -{ return DecodeUByte3(val)<<8; } - -static inline ALfloat Conv_ALfloat_ALbyte(ALbyte val) -{ return val * (1.0f/127.0f); } -static inline ALfloat Conv_ALfloat_ALubyte(ALubyte val) -{ return (val-128) * (1.0f/127.0f); } -static inline ALfloat Conv_ALfloat_ALshort(ALshort val) -{ return val * (1.0f/32767.0f); } -static inline ALfloat Conv_ALfloat_ALushort(ALushort val) -{ return (val-32768) * (1.0f/32767.0f); } -static inline ALfloat Conv_ALfloat_ALint(ALint val) -{ return (ALfloat)(val * (1.0/2147483647.0)); } -static inline ALfloat Conv_ALfloat_ALuint(ALuint val) -{ return (ALfloat)((ALint)(val-2147483648u) * (1.0/2147483647.0)); } -static inline ALfloat Conv_ALfloat_ALfloat(ALfloat val) -{ return (val==val) ? val : 0.0f; } -static inline ALfloat Conv_ALfloat_ALdouble(ALdouble val) -{ return (val==val) ? (ALfloat)val : 0.0f; } -static inline ALfloat Conv_ALfloat_ALmulaw(ALmulaw val) -{ return Conv_ALfloat_ALshort(DecodeMuLaw(val)); } -static inline ALfloat Conv_ALfloat_ALalaw(ALalaw val) -{ return Conv_ALfloat_ALshort(DecodeALaw(val)); } -static inline ALfloat Conv_ALfloat_ALbyte3(ALbyte3 val) -{ return (ALfloat)(DecodeByte3(val) * (1.0/8388607.0)); } -static inline ALfloat Conv_ALfloat_ALubyte3(ALubyte3 val) -{ return (ALfloat)((DecodeUByte3(val)-8388608) * (1.0/8388607.0)); } - -static inline ALdouble Conv_ALdouble_ALbyte(ALbyte val) -{ return val * (1.0/127.0); } -static inline ALdouble Conv_ALdouble_ALubyte(ALubyte val) -{ return (val-128) * (1.0/127.0); } -static inline ALdouble Conv_ALdouble_ALshort(ALshort val) -{ return val * (1.0/32767.0); } -static inline ALdouble Conv_ALdouble_ALushort(ALushort val) -{ return (val-32768) * (1.0/32767.0); } -static inline ALdouble Conv_ALdouble_ALint(ALint val) -{ return val * (1.0/2147483647.0); } -static inline ALdouble Conv_ALdouble_ALuint(ALuint val) -{ return (ALint)(val-2147483648u) * (1.0/2147483647.0); } -static inline ALdouble Conv_ALdouble_ALfloat(ALfloat val) -{ return (val==val) ? val : 0.0f; } -static inline ALdouble Conv_ALdouble_ALdouble(ALdouble val) -{ return (val==val) ? val : 0.0; } -static inline ALdouble Conv_ALdouble_ALmulaw(ALmulaw val) -{ return Conv_ALdouble_ALshort(DecodeMuLaw(val)); } -static inline ALdouble Conv_ALdouble_ALalaw(ALalaw val) -{ return Conv_ALdouble_ALshort(DecodeALaw(val)); } -static inline ALdouble Conv_ALdouble_ALbyte3(ALbyte3 val) -{ return DecodeByte3(val) * (1.0/8388607.0); } -static inline ALdouble Conv_ALdouble_ALubyte3(ALubyte3 val) -{ return (DecodeUByte3(val)-8388608) * (1.0/8388607.0); } - -#define DECL_TEMPLATE(T) \ -static inline ALmulaw Conv_ALmulaw_##T(T val) \ -{ return EncodeMuLaw(Conv_ALshort_##T(val)); } - -DECL_TEMPLATE(ALbyte) -DECL_TEMPLATE(ALubyte) -DECL_TEMPLATE(ALshort) -DECL_TEMPLATE(ALushort) -DECL_TEMPLATE(ALint) -DECL_TEMPLATE(ALuint) -DECL_TEMPLATE(ALfloat) -DECL_TEMPLATE(ALdouble) -static inline ALmulaw Conv_ALmulaw_ALmulaw(ALmulaw val) -{ return val; } -DECL_TEMPLATE(ALalaw) -DECL_TEMPLATE(ALbyte3) -DECL_TEMPLATE(ALubyte3) - -#undef DECL_TEMPLATE - -#define DECL_TEMPLATE(T) \ -static inline ALalaw Conv_ALalaw_##T(T val) \ -{ return EncodeALaw(Conv_ALshort_##T(val)); } - -DECL_TEMPLATE(ALbyte) -DECL_TEMPLATE(ALubyte) -DECL_TEMPLATE(ALshort) -DECL_TEMPLATE(ALushort) -DECL_TEMPLATE(ALint) -DECL_TEMPLATE(ALuint) -DECL_TEMPLATE(ALfloat) -DECL_TEMPLATE(ALdouble) -DECL_TEMPLATE(ALmulaw) -static inline ALalaw Conv_ALalaw_ALalaw(ALalaw val) -{ return val; } -DECL_TEMPLATE(ALbyte3) -DECL_TEMPLATE(ALubyte3) - -#undef DECL_TEMPLATE - -#define DECL_TEMPLATE(T) \ -static inline ALbyte3 Conv_ALbyte3_##T(T val) \ -{ return EncodeByte3(Conv_ALint_##T(val)>>8); } - -DECL_TEMPLATE(ALbyte) -DECL_TEMPLATE(ALubyte) -DECL_TEMPLATE(ALshort) -DECL_TEMPLATE(ALushort) -DECL_TEMPLATE(ALint) -DECL_TEMPLATE(ALuint) -DECL_TEMPLATE(ALfloat) -DECL_TEMPLATE(ALdouble) -DECL_TEMPLATE(ALmulaw) -DECL_TEMPLATE(ALalaw) -static inline ALbyte3 Conv_ALbyte3_ALbyte3(ALbyte3 val) -{ return val; } -DECL_TEMPLATE(ALubyte3) - -#undef DECL_TEMPLATE - -#define DECL_TEMPLATE(T) \ -static inline ALubyte3 Conv_ALubyte3_##T(T val) \ -{ return EncodeUByte3(Conv_ALuint_##T(val)>>8); } - -DECL_TEMPLATE(ALbyte) -DECL_TEMPLATE(ALubyte) -DECL_TEMPLATE(ALshort) -DECL_TEMPLATE(ALushort) -DECL_TEMPLATE(ALint) -DECL_TEMPLATE(ALuint) -DECL_TEMPLATE(ALfloat) -DECL_TEMPLATE(ALdouble) -DECL_TEMPLATE(ALmulaw) -DECL_TEMPLATE(ALalaw) -DECL_TEMPLATE(ALbyte3) -static inline ALubyte3 Conv_ALubyte3_ALubyte3(ALubyte3 val) -{ return val; } - -#undef DECL_TEMPLATE - - -#define DECL_TEMPLATE(T1, T2) \ -static void Convert_##T1##_##T2(T1 *dst, const T2 *src, ALuint numchans, \ - ALuint len) \ -{ \ - ALuint i, j; \ - for(i = 0;i < len;i++) \ - { \ - for(j = 0;j < numchans;j++) \ - *(dst++) = Conv_##T1##_##T2(*(src++)); \ - } \ -} - -DECL_TEMPLATE(ALbyte, ALbyte) -DECL_TEMPLATE(ALbyte, ALubyte) -DECL_TEMPLATE(ALbyte, ALshort) -DECL_TEMPLATE(ALbyte, ALushort) -DECL_TEMPLATE(ALbyte, ALint) -DECL_TEMPLATE(ALbyte, ALuint) -DECL_TEMPLATE(ALbyte, ALfloat) -DECL_TEMPLATE(ALbyte, ALdouble) -DECL_TEMPLATE(ALbyte, ALmulaw) -DECL_TEMPLATE(ALbyte, ALalaw) -DECL_TEMPLATE(ALbyte, ALbyte3) -DECL_TEMPLATE(ALbyte, ALubyte3) - -DECL_TEMPLATE(ALubyte, ALbyte) -DECL_TEMPLATE(ALubyte, ALubyte) -DECL_TEMPLATE(ALubyte, ALshort) -DECL_TEMPLATE(ALubyte, ALushort) -DECL_TEMPLATE(ALubyte, ALint) -DECL_TEMPLATE(ALubyte, ALuint) -DECL_TEMPLATE(ALubyte, ALfloat) -DECL_TEMPLATE(ALubyte, ALdouble) -DECL_TEMPLATE(ALubyte, ALmulaw) -DECL_TEMPLATE(ALubyte, ALalaw) -DECL_TEMPLATE(ALubyte, ALbyte3) -DECL_TEMPLATE(ALubyte, ALubyte3) - -DECL_TEMPLATE(ALshort, ALbyte) -DECL_TEMPLATE(ALshort, ALubyte) -DECL_TEMPLATE(ALshort, ALshort) -DECL_TEMPLATE(ALshort, ALushort) -DECL_TEMPLATE(ALshort, ALint) -DECL_TEMPLATE(ALshort, ALuint) -DECL_TEMPLATE(ALshort, ALfloat) -DECL_TEMPLATE(ALshort, ALdouble) -DECL_TEMPLATE(ALshort, ALmulaw) -DECL_TEMPLATE(ALshort, ALalaw) -DECL_TEMPLATE(ALshort, ALbyte3) -DECL_TEMPLATE(ALshort, ALubyte3) - -DECL_TEMPLATE(ALushort, ALbyte) -DECL_TEMPLATE(ALushort, ALubyte) -DECL_TEMPLATE(ALushort, ALshort) -DECL_TEMPLATE(ALushort, ALushort) -DECL_TEMPLATE(ALushort, ALint) -DECL_TEMPLATE(ALushort, ALuint) -DECL_TEMPLATE(ALushort, ALfloat) -DECL_TEMPLATE(ALushort, ALdouble) -DECL_TEMPLATE(ALushort, ALmulaw) -DECL_TEMPLATE(ALushort, ALalaw) -DECL_TEMPLATE(ALushort, ALbyte3) -DECL_TEMPLATE(ALushort, ALubyte3) - -DECL_TEMPLATE(ALint, ALbyte) -DECL_TEMPLATE(ALint, ALubyte) -DECL_TEMPLATE(ALint, ALshort) -DECL_TEMPLATE(ALint, ALushort) -DECL_TEMPLATE(ALint, ALint) -DECL_TEMPLATE(ALint, ALuint) -DECL_TEMPLATE(ALint, ALfloat) -DECL_TEMPLATE(ALint, ALdouble) -DECL_TEMPLATE(ALint, ALmulaw) -DECL_TEMPLATE(ALint, ALalaw) -DECL_TEMPLATE(ALint, ALbyte3) -DECL_TEMPLATE(ALint, ALubyte3) - -DECL_TEMPLATE(ALuint, ALbyte) -DECL_TEMPLATE(ALuint, ALubyte) -DECL_TEMPLATE(ALuint, ALshort) -DECL_TEMPLATE(ALuint, ALushort) -DECL_TEMPLATE(ALuint, ALint) -DECL_TEMPLATE(ALuint, ALuint) -DECL_TEMPLATE(ALuint, ALfloat) -DECL_TEMPLATE(ALuint, ALdouble) -DECL_TEMPLATE(ALuint, ALmulaw) -DECL_TEMPLATE(ALuint, ALalaw) -DECL_TEMPLATE(ALuint, ALbyte3) -DECL_TEMPLATE(ALuint, ALubyte3) - -DECL_TEMPLATE(ALfloat, ALbyte) -DECL_TEMPLATE(ALfloat, ALubyte) -DECL_TEMPLATE(ALfloat, ALshort) -DECL_TEMPLATE(ALfloat, ALushort) -DECL_TEMPLATE(ALfloat, ALint) -DECL_TEMPLATE(ALfloat, ALuint) -DECL_TEMPLATE(ALfloat, ALfloat) -DECL_TEMPLATE(ALfloat, ALdouble) -DECL_TEMPLATE(ALfloat, ALmulaw) -DECL_TEMPLATE(ALfloat, ALalaw) -DECL_TEMPLATE(ALfloat, ALbyte3) -DECL_TEMPLATE(ALfloat, ALubyte3) - -DECL_TEMPLATE(ALdouble, ALbyte) -DECL_TEMPLATE(ALdouble, ALubyte) -DECL_TEMPLATE(ALdouble, ALshort) -DECL_TEMPLATE(ALdouble, ALushort) -DECL_TEMPLATE(ALdouble, ALint) -DECL_TEMPLATE(ALdouble, ALuint) -DECL_TEMPLATE(ALdouble, ALfloat) -DECL_TEMPLATE(ALdouble, ALdouble) -DECL_TEMPLATE(ALdouble, ALmulaw) -DECL_TEMPLATE(ALdouble, ALalaw) -DECL_TEMPLATE(ALdouble, ALbyte3) -DECL_TEMPLATE(ALdouble, ALubyte3) - -DECL_TEMPLATE(ALmulaw, ALbyte) -DECL_TEMPLATE(ALmulaw, ALubyte) -DECL_TEMPLATE(ALmulaw, ALshort) -DECL_TEMPLATE(ALmulaw, ALushort) -DECL_TEMPLATE(ALmulaw, ALint) -DECL_TEMPLATE(ALmulaw, ALuint) -DECL_TEMPLATE(ALmulaw, ALfloat) -DECL_TEMPLATE(ALmulaw, ALdouble) -DECL_TEMPLATE(ALmulaw, ALmulaw) -DECL_TEMPLATE(ALmulaw, ALalaw) -DECL_TEMPLATE(ALmulaw, ALbyte3) -DECL_TEMPLATE(ALmulaw, ALubyte3) - -DECL_TEMPLATE(ALalaw, ALbyte) -DECL_TEMPLATE(ALalaw, ALubyte) -DECL_TEMPLATE(ALalaw, ALshort) -DECL_TEMPLATE(ALalaw, ALushort) -DECL_TEMPLATE(ALalaw, ALint) -DECL_TEMPLATE(ALalaw, ALuint) -DECL_TEMPLATE(ALalaw, ALfloat) -DECL_TEMPLATE(ALalaw, ALdouble) -DECL_TEMPLATE(ALalaw, ALmulaw) -DECL_TEMPLATE(ALalaw, ALalaw) -DECL_TEMPLATE(ALalaw, ALbyte3) -DECL_TEMPLATE(ALalaw, ALubyte3) - -DECL_TEMPLATE(ALbyte3, ALbyte) -DECL_TEMPLATE(ALbyte3, ALubyte) -DECL_TEMPLATE(ALbyte3, ALshort) -DECL_TEMPLATE(ALbyte3, ALushort) -DECL_TEMPLATE(ALbyte3, ALint) -DECL_TEMPLATE(ALbyte3, ALuint) -DECL_TEMPLATE(ALbyte3, ALfloat) -DECL_TEMPLATE(ALbyte3, ALdouble) -DECL_TEMPLATE(ALbyte3, ALmulaw) -DECL_TEMPLATE(ALbyte3, ALalaw) -DECL_TEMPLATE(ALbyte3, ALbyte3) -DECL_TEMPLATE(ALbyte3, ALubyte3) - -DECL_TEMPLATE(ALubyte3, ALbyte) -DECL_TEMPLATE(ALubyte3, ALubyte) -DECL_TEMPLATE(ALubyte3, ALshort) -DECL_TEMPLATE(ALubyte3, ALushort) -DECL_TEMPLATE(ALubyte3, ALint) -DECL_TEMPLATE(ALubyte3, ALuint) -DECL_TEMPLATE(ALubyte3, ALfloat) -DECL_TEMPLATE(ALubyte3, ALdouble) -DECL_TEMPLATE(ALubyte3, ALmulaw) -DECL_TEMPLATE(ALubyte3, ALalaw) -DECL_TEMPLATE(ALubyte3, ALbyte3) -DECL_TEMPLATE(ALubyte3, ALubyte3) - -#undef DECL_TEMPLATE - -#define DECL_TEMPLATE(T) \ -static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \ - ALuint len) \ -{ \ - ALshort tmp[65*MAX_INPUT_CHANNELS]; /* Max samples an IMA4 frame can be */\ - ALuint i, j, k; \ - \ - i = 0; \ - while(i < len) \ - { \ - DecodeIMA4Block(tmp, src, numchans); \ - src += 36*numchans; \ - \ - for(j = 0;j < 65 && i < len;j++,i++) \ - { \ - for(k = 0;k < numchans;k++) \ - *(dst++) = Conv_##T##_ALshort(tmp[j*numchans + k]); \ - } \ - } \ -} - -DECL_TEMPLATE(ALbyte) -DECL_TEMPLATE(ALubyte) -DECL_TEMPLATE(ALshort) -DECL_TEMPLATE(ALushort) -DECL_TEMPLATE(ALint) -DECL_TEMPLATE(ALuint) -DECL_TEMPLATE(ALfloat) -DECL_TEMPLATE(ALdouble) -DECL_TEMPLATE(ALmulaw) -DECL_TEMPLATE(ALalaw) -DECL_TEMPLATE(ALbyte3) -DECL_TEMPLATE(ALubyte3) - -#undef DECL_TEMPLATE - -#define DECL_TEMPLATE(T) \ -static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \ - ALuint len) \ -{ \ - ALshort tmp[65*MAX_INPUT_CHANNELS]; /* Max samples an IMA4 frame can be */\ - ALint sample[MaxChannels] = {0,0,0,0,0,0,0,0}; \ - ALint index[MaxChannels] = {0,0,0,0,0,0,0,0}; \ - ALuint i, j; \ - \ - for(i = 0;i < len;i += 65) \ - { \ - for(j = 0;j < 65*numchans;j++) \ - tmp[j] = Conv_ALshort_##T(*(src++)); \ - EncodeIMA4Block(dst, tmp, sample, index, numchans); \ - dst += 36*numchans; \ - } \ -} - -DECL_TEMPLATE(ALbyte) -DECL_TEMPLATE(ALubyte) -DECL_TEMPLATE(ALshort) -DECL_TEMPLATE(ALushort) -DECL_TEMPLATE(ALint) -DECL_TEMPLATE(ALuint) -DECL_TEMPLATE(ALfloat) -DECL_TEMPLATE(ALdouble) -DECL_TEMPLATE(ALmulaw) -DECL_TEMPLATE(ALalaw) -static void Convert_ALima4_ALima4(ALima4 *dst, const ALima4 *src, - ALuint numchans, ALuint numblocks) -{ memcpy(dst, src, numblocks*36*numchans); } -DECL_TEMPLATE(ALbyte3) -DECL_TEMPLATE(ALubyte3) - -#undef DECL_TEMPLATE - -#define DECL_TEMPLATE(T) \ -static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType, \ - ALsizei numchans, ALsizei len) \ -{ \ - switch(srcType) \ - { \ - case UserFmtByte: \ - Convert_##T##_ALbyte(dst, src, numchans, len); \ - break; \ - case UserFmtUByte: \ - Convert_##T##_ALubyte(dst, src, numchans, len); \ - break; \ - case UserFmtShort: \ - Convert_##T##_ALshort(dst, src, numchans, len); \ - break; \ - case UserFmtUShort: \ - Convert_##T##_ALushort(dst, src, numchans, len); \ - break; \ - case UserFmtInt: \ - Convert_##T##_ALint(dst, src, numchans, len); \ - break; \ - case UserFmtUInt: \ - Convert_##T##_ALuint(dst, src, numchans, len); \ - break; \ - case UserFmtFloat: \ - Convert_##T##_ALfloat(dst, src, numchans, len); \ - break; \ - case UserFmtDouble: \ - Convert_##T##_ALdouble(dst, src, numchans, len); \ - break; \ - case UserFmtMulaw: \ - Convert_##T##_ALmulaw(dst, src, numchans, len); \ - break; \ - case UserFmtAlaw: \ - Convert_##T##_ALalaw(dst, src, numchans, len); \ - break; \ - case UserFmtIMA4: \ - Convert_##T##_ALima4(dst, src, numchans, len); \ - break; \ - case UserFmtByte3: \ - Convert_##T##_ALbyte3(dst, src, numchans, len); \ - break; \ - case UserFmtUByte3: \ - Convert_##T##_ALubyte3(dst, src, numchans, len); \ - 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(ALbyte3) -DECL_TEMPLATE(ALubyte3) - -#undef DECL_TEMPLATE - - -static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len) -{ - switch(dstType) - { - case UserFmtByte: - Convert_ALbyte(dst, src, srcType, numchans, len); - break; - case UserFmtUByte: - Convert_ALubyte(dst, src, srcType, numchans, len); - break; - case UserFmtShort: - Convert_ALshort(dst, src, srcType, numchans, len); - break; - case UserFmtUShort: - Convert_ALushort(dst, src, srcType, numchans, len); - break; - case UserFmtInt: - Convert_ALint(dst, src, srcType, numchans, len); - break; - case UserFmtUInt: - Convert_ALuint(dst, src, srcType, numchans, len); - break; - case UserFmtFloat: - Convert_ALfloat(dst, src, srcType, numchans, len); - break; - case UserFmtDouble: - Convert_ALdouble(dst, src, srcType, numchans, len); - break; - case UserFmtMulaw: - Convert_ALmulaw(dst, src, srcType, numchans, len); - break; - case UserFmtAlaw: - Convert_ALalaw(dst, src, srcType, numchans, len); - break; - case UserFmtIMA4: - Convert_ALima4(dst, src, srcType, numchans, len); - break; - case UserFmtByte3: - Convert_ALbyte3(dst, src, srcType, numchans, len); - break; - case UserFmtUByte3: - Convert_ALubyte3(dst, src, srcType, numchans, len); - break; - } -} - - -/* - * 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. - */ -static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALboolean storesrc) -{ - ALuint NewChannels, NewBytes; - enum FmtChannels DstChannels; - enum FmtType DstType; - ALuint64 newsize; - ALvoid *temp; - - if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE || - (long)SrcChannels != (long)DstChannels) - return AL_INVALID_ENUM; - - NewChannels = ChannelsFromFmt(DstChannels); - NewBytes = BytesFromFmt(DstType); - - newsize = frames; - newsize *= NewBytes; - newsize *= NewChannels; - if(newsize > INT_MAX) - return AL_OUT_OF_MEMORY; - - WriteLock(&ALBuf->lock); - if(ALBuf->ref != 0) - { - WriteUnlock(&ALBuf->lock); - return AL_INVALID_OPERATION; - } - - temp = realloc(ALBuf->data, (size_t)newsize); - if(!temp && newsize) - { - WriteUnlock(&ALBuf->lock); - return AL_OUT_OF_MEMORY; - } - ALBuf->data = temp; - - if(data != NULL) - ConvertData(ALBuf->data, (enum UserFmtType)DstType, data, SrcType, NewChannels, frames); - - if(storesrc) - { - ALBuf->OriginalChannels = SrcChannels; - ALBuf->OriginalType = SrcType; - if(SrcType == UserFmtIMA4) - ALBuf->OriginalSize = frames / 65 * 36 * ChannelsFromUserFmt(SrcChannels); - else - ALBuf->OriginalSize = frames * FrameSizeFromUserFmt(SrcChannels, SrcType); - } - else - { - ALBuf->OriginalChannels = (enum UserFmtChannels)DstChannels; - ALBuf->OriginalType = (enum UserFmtType)DstType; - ALBuf->OriginalSize = frames * NewBytes * NewChannels; - } - - 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(ALbyte3); - case UserFmtUByte3: return sizeof(ALubyte3); - case UserFmtMulaw: return sizeof(ALubyte); - case UserFmtAlaw: return sizeof(ALubyte); - case UserFmtIMA4: break; /* not handled here */ - } - return 0; -} -ALuint ChannelsFromUserFmt(enum UserFmtChannels chans) -{ - switch(chans) - { - case UserFmtMono: return 1; - case UserFmtStereo: return 2; - case UserFmtRear: return 2; - case UserFmtQuad: return 4; - case UserFmtX51: return 6; - case UserFmtX61: return 7; - case UserFmtX71: return 8; - } - return 0; -} -static ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, - enum UserFmtType *type) -{ - static const struct { - ALenum format; - enum UserFmtChannels channels; - enum UserFmtType type; - } list[] = { - { AL_FORMAT_MONO8, UserFmtMono, UserFmtUByte }, - { AL_FORMAT_MONO16, UserFmtMono, UserFmtShort }, - { AL_FORMAT_MONO_FLOAT32, UserFmtMono, UserFmtFloat }, - { AL_FORMAT_MONO_DOUBLE_EXT, UserFmtMono, UserFmtDouble }, - { AL_FORMAT_MONO_IMA4, UserFmtMono, UserFmtIMA4 }, - { AL_FORMAT_MONO_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_MULAW, UserFmtStereo, UserFmtMulaw }, - { AL_FORMAT_STEREO_ALAW_EXT, UserFmtStereo, UserFmtAlaw }, - - { AL_FORMAT_REAR8, UserFmtRear, UserFmtUByte }, - { AL_FORMAT_REAR16, UserFmtRear, UserFmtShort }, - { AL_FORMAT_REAR32, UserFmtRear, UserFmtFloat }, - { AL_FORMAT_REAR_MULAW, UserFmtRear, UserFmtMulaw }, - - { AL_FORMAT_QUAD8_LOKI, UserFmtQuad, UserFmtUByte }, - { AL_FORMAT_QUAD16_LOKI, UserFmtQuad, UserFmtShort }, - - { AL_FORMAT_QUAD8, UserFmtQuad, UserFmtUByte }, - { AL_FORMAT_QUAD16, UserFmtQuad, UserFmtShort }, - { AL_FORMAT_QUAD32, UserFmtQuad, UserFmtFloat }, - { AL_FORMAT_QUAD_MULAW, UserFmtQuad, UserFmtMulaw }, - - { AL_FORMAT_51CHN8, UserFmtX51, UserFmtUByte }, - { AL_FORMAT_51CHN16, UserFmtX51, UserFmtShort }, - { AL_FORMAT_51CHN32, UserFmtX51, UserFmtFloat }, - { AL_FORMAT_51CHN_MULAW, UserFmtX51, UserFmtMulaw }, - - { AL_FORMAT_61CHN8, UserFmtX61, UserFmtUByte }, - { AL_FORMAT_61CHN16, UserFmtX61, UserFmtShort }, - { AL_FORMAT_61CHN32, UserFmtX61, UserFmtFloat }, - { AL_FORMAT_61CHN_MULAW, UserFmtX61, UserFmtMulaw }, - - { AL_FORMAT_71CHN8, UserFmtX71, UserFmtUByte }, - { AL_FORMAT_71CHN16, UserFmtX71, UserFmtShort }, - { AL_FORMAT_71CHN32, UserFmtX71, UserFmtFloat }, - { AL_FORMAT_71CHN_MULAW, UserFmtX71, UserFmtMulaw }, - }; - ALuint i; - - for(i = 0;i < COUNTOF(list);i++) - { - if(list[i].format == format) - { - *chans = list[i].channels; - *type = list[i].type; - return AL_TRUE; - } - } - - return AL_FALSE; -} - -ALuint BytesFromFmt(enum FmtType type) -{ - switch(type) - { - case FmtByte: return sizeof(ALbyte); - case FmtShort: return sizeof(ALshort); - case FmtFloat: return sizeof(ALfloat); - } - return 0; -} -ALuint ChannelsFromFmt(enum FmtChannels chans) -{ - switch(chans) - { - case FmtMono: return 1; - case FmtStereo: return 2; - case FmtRear: return 2; - case FmtQuad: return 4; - case FmtX51: return 6; - case FmtX61: return 7; - case FmtX71: return 8; - } - return 0; -} -static ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) -{ - static const struct { - ALenum format; - enum FmtChannels channels; - enum FmtType type; - } list[] = { - { AL_MONO8_SOFT, FmtMono, FmtByte }, - { AL_MONO16_SOFT, FmtMono, FmtShort }, - { AL_MONO32F_SOFT, FmtMono, FmtFloat }, - - { AL_STEREO8_SOFT, FmtStereo, FmtByte }, - { AL_STEREO16_SOFT, FmtStereo, FmtShort }, - { AL_STEREO32F_SOFT, FmtStereo, FmtFloat }, - - { AL_REAR8_SOFT, FmtRear, FmtByte }, - { AL_REAR16_SOFT, FmtRear, FmtShort }, - { AL_REAR32F_SOFT, FmtRear, FmtFloat }, - - { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtByte }, - { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort }, - - { AL_QUAD8_SOFT, FmtQuad, FmtByte }, - { AL_QUAD16_SOFT, FmtQuad, FmtShort }, - { AL_QUAD32F_SOFT, FmtQuad, FmtFloat }, - - { AL_5POINT1_8_SOFT, FmtX51, FmtByte }, - { AL_5POINT1_16_SOFT, FmtX51, FmtShort }, - { AL_5POINT1_32F_SOFT, FmtX51, FmtFloat }, - - { AL_6POINT1_8_SOFT, FmtX61, FmtByte }, - { AL_6POINT1_16_SOFT, FmtX61, FmtShort }, - { AL_6POINT1_32F_SOFT, FmtX61, FmtFloat }, - - { AL_7POINT1_8_SOFT, FmtX71, FmtByte }, - { AL_7POINT1_16_SOFT, FmtX71, FmtShort }, - { AL_7POINT1_32F_SOFT, FmtX71, FmtFloat }, - }; - ALuint i; - - for(i = 0;i < COUNTOF(list);i++) - { - if(list[i].format == format) - { - *chans = list[i].channels; - *type = list[i].type; - return AL_TRUE; - } - } - - return AL_FALSE; -} - - -static ALboolean IsValidType(ALenum type) -{ - switch(type) - { - case AL_BYTE_SOFT: - case AL_UNSIGNED_BYTE_SOFT: - case AL_SHORT_SOFT: - case AL_UNSIGNED_SHORT_SOFT: - case AL_INT_SOFT: - case AL_UNSIGNED_INT_SOFT: - case AL_FLOAT_SOFT: - case AL_DOUBLE_SOFT: - case AL_BYTE3_SOFT: - case AL_UNSIGNED_BYTE3_SOFT: - return AL_TRUE; - } - return AL_FALSE; -} - -static ALboolean IsValidChannels(ALenum channels) -{ - switch(channels) - { - case AL_MONO_SOFT: - case AL_STEREO_SOFT: - case AL_REAR_SOFT: - case AL_QUAD_SOFT: - case AL_5POINT1_SOFT: - case AL_6POINT1_SOFT: - case AL_7POINT1_SOFT: - return AL_TRUE; - } - return AL_FALSE; -} - - -/* - * ReleaseALBuffers() - * - * INTERNAL: Called to destroy any buffers that still exist on the device - */ -ALvoid ReleaseALBuffers(ALCdevice *device) -{ - ALsizei i; - for(i = 0;i < device->BufferMap.size;i++) - { - ALbuffer *temp = device->BufferMap.array[i].value; - device->BufferMap.array[i].value = NULL; - - free(temp->data); - - FreeThunkEntry(temp->id); - memset(temp, 0, sizeof(ALbuffer)); - free(temp); - } -} diff --git a/jni/openal-soft-android/cmake/FindSDL_sound.cmake b/jni/openal-soft-android/cmake/FindSDL_sound.cmake deleted file mode 100644 index 97d2a84c..00000000 --- a/jni/openal-soft-android/cmake/FindSDL_sound.cmake +++ /dev/null @@ -1,382 +0,0 @@ -# - Locates the SDL_sound library -# -# This module depends on SDL being found and -# must be called AFTER FindSDL.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 to override this selectionor 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(SDL_FOUND AND 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 SDL_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 FindSDL.cmake module, but that's kind of painful. - # The solution would be to try something like: - # set(SDL_TRY_COMPILE_LIBRARY_LIST "${SDL_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=${SDL_INCLUDE_DIR}\;${SDL_SOUND_INCLUDE_DIR} - # -DLINK_LIBRARIES:STRING=${SDL_SOUND_LIBRARY}\;${SDL_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} ${SDL_LIBRARY}) - # causes problems when SDL_LIBRARY looks like - # /Library/Frameworks/SDL.framework;-framework Cocoa - # The ;-framework Cocoa seems to be confusing CMake once the OS X - # framework support was added. I was told that breaking up the list - # would fix the problem. - set(TMP_TRY_LIBS) - foreach(lib ${SDL_SOUND_LIBRARY} ${SDL_LIBRARY}) - set(TMP_TRY_LIBS "${TMP_TRY_LIBS} \"${lib}\"") - endforeach() - - # 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 SDL_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(${SDL_INCLUDE_DIR} ${SDL_SOUND_INCLUDE_DIR}) - add_executable(DetermineSoundLibs DetermineSoundLibs.c) - target_link_libraries(DetermineSoundLibs ${TMP_TRY_LIBS})" - ) - - try_compile( - MY_RESULT - ${PROJECT_BINARY_DIR}/CMakeTmp - ${PROJECT_BINARY_DIR}/CMakeTmp - DetermineSoundLibs - OUTPUT_VARIABLE MY_OUTPUT - ) - - # message("${MY_RESULT}") - # message(${MY_OUTPUT}) - - if(NOT MY_RESULT) - - # I expect that MPGLIB, VOC, WAV, AIFF, and SHN are compiled in statically. - # I think Timidity is also compiled in statically. - # I've never had to explcitly link against Quicktime, so I'll skip that for now. - - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARY}) - - # Find MikMod - if("${MY_OUTPUT}" MATCHES "MikMod_") - find_library(MIKMOD_LIBRARY - NAMES libmikmod-coreaudio mikmod - PATHS - ENV MIKMODDIR - ENV SDLSOUNDDIR - ENV SDLDIR - /sw - /opt/local - /opt/csw - /opt - PATH_SUFFIXES - lib - ) - if(MIKMOD_LIBRARY) - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MIKMOD_LIBRARY}) - endif(MIKMOD_LIBRARY) - endif("${MY_OUTPUT}" MATCHES "MikMod_") - - # Find ModPlug - if("${MY_OUTPUT}" MATCHES "MODPLUG_") - find_library(MODPLUG_LIBRARY - NAMES modplug - PATHS - ENV MODPLUGDIR - ENV SDLSOUNDDIR - ENV SDLDIR - /sw - /opt/local - /opt/csw - /opt - PATH_SUFFIXES - lib - ) - if(MODPLUG_LIBRARY) - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${MODPLUG_LIBRARY}) - endif() - endif() - - - # Find Ogg and Vorbis - if("${MY_OUTPUT}" MATCHES "ov_") - find_library(VORBIS_LIBRARY - NAMES vorbis Vorbis VORBIS - PATHS - ENV VORBISDIR - ENV OGGDIR - ENV SDLSOUNDDIR - ENV SDLDIR - /sw - /opt/local - /opt/csw - /opt - PATH_SUFFIXES - lib - ) - if(VORBIS_LIBRARY) - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${VORBIS_LIBRARY}) - endif() - - find_library(OGG_LIBRARY - NAMES ogg Ogg OGG - PATHS - ENV OGGDIR - ENV VORBISDIR - ENV SDLSOUNDDIR - ENV SDLDIR - /sw - /opt/local - /opt/csw - /opt - PATH_SUFFIXES - lib - ) - if(OGG_LIBRARY) - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY}) - endif() - endif() - - - # Find SMPEG - if("${MY_OUTPUT}" MATCHES "SMPEG_") - find_library(SMPEG_LIBRARY - NAMES smpeg SMPEG Smpeg SMpeg - PATHS - ENV SMPEGDIR - ENV SDLSOUNDDIR - ENV SDLDIR - /sw - /opt/local - /opt/csw - /opt - PATH_SUFFIXES - lib - ) - if(SMPEG_LIBRARY) - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SMPEG_LIBRARY}) - endif() - endif() - - - # Find FLAC - if("${MY_OUTPUT}" MATCHES "FLAC_") - find_library(FLAC_LIBRARY - NAMES flac FLAC - PATHS - ENV FLACDIR - ENV SDLSOUNDDIR - ENV SDLDIR - /sw - /opt/local - /opt/csw - /opt - PATH_SUFFIXES - lib - ) - if(FLAC_LIBRARY) - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${FLAC_LIBRARY}) - endif() - endif() - - - # Hmmm...Speex seems to depend on Ogg. This might be a problem if - # the TRY_COMPILE attempt gets blocked at SPEEX before it can pull - # in the Ogg symbols. I'm not sure if I should duplicate the ogg stuff - # above for here or if two ogg entries will screw up things. - if("${MY_OUTPUT}" MATCHES "speex_") - find_library(SPEEX_LIBRARY - NAMES speex SPEEX - PATHS - ENV SPEEXDIR - ENV SDLSOUNDDIR - ENV SDLDIR - /sw - /opt/local - /opt/csw - /opt - PATH_SUFFIXES - lib - ) - if(SPEEX_LIBRARY) - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${SPEEX_LIBRARY}) - endif() - - # Find OGG (needed for Speex) - # We might have already found Ogg for Vorbis, so skip it if so. - if(NOT OGG_LIBRARY) - find_library(OGG_LIBRARY - NAMES ogg Ogg OGG - PATHS - ENV OGGDIR - ENV VORBISDIR - ENV SPEEXDIR - ENV SDLSOUNDDIR - ENV SDLDIR - /sw - /opt/local - /opt/csw - /opt - PATH_SUFFIXES lib - ) - if(OGG_LIBRARY) - set(SDL_SOUND_LIBRARIES_TMP ${SDL_SOUND_LIBRARIES_TMP} ${OGG_LIBRARY}) - endif() - endif() - endif() - - set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARIES_TMP} CACHE INTERNAL "SDL_sound and dependent libraries") - else() - set(SDL_SOUND_LIBRARIES ${SDL_SOUND_EXTRAS} ${SDL_SOUND_LIBRARY} CACHE INTERNAL "SDL_sound and dependent libraries") - endif() -endif() - -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_LIBRARY SDL_SOUND_INCLUDE_DIR - VERSION_VAR SDL_SOUND_VERSION_STRING) diff --git a/jni/openal-soft-android/cmake/toolchain.android.cmake b/jni/openal-soft-android/cmake/toolchain.android.cmake deleted file mode 100644 index 1751e1bf..00000000 --- a/jni/openal-soft-android/cmake/toolchain.android.cmake +++ /dev/null @@ -1,171 +0,0 @@ -# Adapted from http://code.google.com/p/android-cmake/ - -set(CMAKE_SYSTEM_NAME Linux) -set(CMAKE_SYSTEM_VERSION 1) - -if(APPLE) - set(HOST_APPLE true) -elseif(UNIX) - set(HOST_UNIX true) -endif() - -set(APPLE false) -set(UNIX true) - -set(ANDROID_NDK_DEFAULT_SEARCH_PATH /opt/android-ndk) -set(ANDROID_NDK_SUPPORTED_VERSIONS -r8d -r8 -r7 -r6 -r5c -r5b -r5 "") -set(ANDROID_NDK_TOOLCHAIN_DEFAULT_SEARCH_PATH /opt/android-toolchain) -set(TOOL_OS_SUFFIX "") - -if(NOT DEFINED ANDROID_NDK) - set(ANDROID_NDK "$ENV{ANDROID_NDK}") -endif() - -if(NOT DEFINED ANDROID_NDK_TOOLCHAIN_ROOT) - set(ANDROID_NDK_TOOLCHAIN_ROOT $ENV{ANDROID_NDK_TOOLCHAIN_ROOT}) -endif() - -if(NOT EXISTS "${ANDROID_NDK}") - foreach(ndk_version ${ANDROID_NDK_SUPPORTED_VERSIONS}) - if(EXISTS ${ANDROID_NDK_DEFAULT_SEARCH_PATH}${ndk_version}) - set(ANDROID_NDK "${ANDROID_NDK_DEFAULT_SEARCH_PATH}${ndk_version}") - message(STATUS "Using default path for android NDK ${ANDROID_NDK}") - message(STATUS " If you prefer to use a different location, please define the variable: ANDROID_NDK") - break() - endif() - endforeach() -endif() - -if(EXISTS "${ANDROID_NDK}") - if(APPLE) - set(ANDROID_TOOLCHAIN_SYSTEM "darwin-x86") - elseif(WIN32) - set(ANDROID_TOOLCHAIN_SYSTEM "windows") - set(TOOL_OS_SUFFIX ".exe") - elseif(UNIX) - set(ANDROID_TOOLCHAIN_SYSTEM "linux-x86_64") - else() - message(FATAL_ERROR "Your platform is not supported") - endif() - - if(NOT ANDROID_API_LEVEL GREATER 2) - if(NDK_CPU_X86) - set(ANDROID_API_LEVEL 9) - else() - set(ANDROID_API_LEVEL 5) - endif() - message(STATUS "Using default android API level android-${ANDROID_API_LEVEL}") - message(STATUS " If you prefer to use a different API level, please define the variable: ANDROID_API_LEVEL") - endif() - - if (NDK_CPU_X86) - set(ANDROID_TOOLCHAIN_PREFIX "i686-android-linux") - set(ANDROID_TOOLCHAIN_NAME "x86") - set(ANDROID_TOOLCHAIN_PLATFORM_NAME "x86") - else() - set(ANDROID_TOOLCHAIN_PREFIX "arm-linux-androideabi") - set(ANDROID_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_PREFIX}") - set(ANDROID_TOOLCHAIN_PLATFORM_NAME "arm") - endif() - - if (NOT DEFINED ANDROID_TOOLCHAIN_VERSION) - set(SUPPORTED_TOOLCHAIN_VERSIONS 4.4.0 4.4.3 4.6.0 4.6.1 4.6.2 4.6.3 4.7) - foreach(gcc_version ${SUPPORTED_TOOLCHAIN_VERSIONS}) - if (EXISTS "${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}-${gcc_version}") - set(ANDROID_TOOLCHAIN_VERSION ${gcc_version}) - endif() - endforeach() - if(NOT DEFINED ANDROID_TOOLCHAIN_VERSION) - message(FATAL_ERROR "Unable to find toolchain") - else() - message(STATUS "Using auto-detected toolchain ${ANDROID_TOOLCHAIN_NAME}-${ANDROID_TOOLCHAIN_VERSION}") - endif() - endif() - if (EXISTS "${ANDROID_NDK}/toolchains/clang-android-${ANDROID_TOOLCHAIN_VERSION}") - set (ANDROID_TOOLCHAIN_NAME "clang-android") - message(STATUS "Found clang toolchain ${ANDROID_TOOLCHAIN_NAME}-${ANDROID_TOOLCHAIN_VERSION}") - endif() - - set(ANDROID_NDK_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_API_LEVEL}/arch-${ANDROID_TOOLCHAIN_PLATFORM_NAME}") - set(ANDROID_NDK_TOOLCHAIN_ROOT "${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_NAME}-${ANDROID_TOOLCHAIN_VERSION}/prebuilt/${ANDROID_TOOLCHAIN_SYSTEM}") -endif() - -set(CMAKE_C_COMPILER "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "gcc" FORCE) -set(CMAKE_CXX_COMPILER "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-g++${TOOL_OS_SUFFIX}" CACHE PATH "g++" FORCE) -set(CMAKE_AR "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-ar${TOOL_OS_SUFFIX}" CACHE PATH "archive" FORCE) -set(CMAKE_LINKER "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-ld${TOOL_OS_SUFFIX}" CACHE PATH "linker" FORCE) -set(CMAKE_NM "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-nm${TOOL_OS_SUFFIX}" CACHE PATH "nm" FORCE) -set(CMAKE_OBJCOPY "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" FORCE) -set(CMAKE_OBJDUMP "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" FORCE) -set(CMAKE_STRIP "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-strip${TOOL_OS_SUFFIX}" CACHE PATH "strip" FORCE) -set(CMAKE_RANLIB "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_PREFIX}-ranlib${TOOL_OS_SUFFIX}" CACHE PATH "ranlib" FORCE) - -if(NDK_CPU_X86) - set(ANDROID_NDK_CPU_NAME "x86") - set(CMAKE_SYSTEM_PROCESSOR "x86") -elseif(NDK_CPU_ARM_V7A) - set(NDK_CPU_ARM_NEON false) - set(NDK_CPU_ARM_VFPV3 false) - set(NDK_CPU_ARM true) - set(ANDROID_NDK_CPU_NAME "armeabi-v7a") - set(CMAKE_SYSTEM_PROCESSOR "armv7-a") -else() - set(NDK_CPU_ARM true) - set(ANDROID_NDK_CPU_NAME "armeabi") - set(NDK_CPU_ARM_NEON false) - set(CMAKE_SYSTEM_PROCESSOR "armv5te") -endif() - -set(CMAKE_FIND_ROOT_PATH "${ANDROID_NDK_TOOLCHAIN_ROOT}/bin" "${ANDROID_NDK_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_PREFIX}" "${ANDROID_NDK_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share") - -set(STL_PATH "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++") -set(STL_LIBRARIES_PATH "${STL_PATH}/libs/${ANDROID_NDK_CPU_NAME}") -include_directories(SYSTEM "${STL_PATH}/include" "${STL_LIBRARIES_PATH}/include") -link_directories("${ANDROID_NDK_SYSROOT}/usr/lib") - -set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH) -set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) -set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) - -set(CMAKE_C_FLAGS "-fPIC -DANDROID -Wno-psabi -fsigned-char") - -set(FORCE_ARM OFF CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1") -if(NDK_CPU_X86) -elseif(NOT FORCE_ARM) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb") -else() - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm") -endif() - -set(CMAKE_C_FLAGS "--sysroot=${ANDROID_NDK_SYSROOT} ${CMAKE_C_FLAGS}") - -include(CMakeForceCompiler) -CMAKE_FORCE_C_COMPILER("${CMAKE_C_COMPILER}" GNU) -CMAKE_FORCE_CXX_COMPILER("${CMAKE_CXX_COMPILER}" GNU) - -if(NDK_CPU_ARM_V7A) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv7-a -mfloat-abi=softfp") - if(NDK_CPU_ARM_NEON) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon") - elseif(NDK_CPU_ARM_VFPV3) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=vfpv3") - endif() -endif() - -set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c++ flags") -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "c flags") - -set(LINKER_FLAGS "-L\"${STL_LIBRARIES_PATH}\" -L\"${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_CPU_NAME}\"") -if(NDK_CPU_ARM OR NDK_CPU_ARM_V7A) - set(LINKER_FLAGS "-Wl,--fix-cortex-a8 ${LINKER_FLAGS}") -endif() - -set(CMAKE_SHARED_LINKER_FLAGS "${LINKER_FLAGS}" CACHE STRING "linker flags" FORCE) -set(CMAKE_MODULE_LINKER_FLAGS "${LINKER_FLAGS}" CACHE STRING "linker flags" FORCE) -set(CMAKE_EXE_LINKER_FLAGS "${LINKER_FLAGS}" CACHE STRING "linker flags" FORCE) - -set(ANDROID true) -set(BUILD_ANDROID true) - -MARK_AS_ADVANCED(FORCE_ARM NO_UNDEFINED) -